Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"POT-Creation-Date: 2022-01-10T08:43:46.954Z\n"
"PO-Revision-Date: 2022-01-10T08:43:46.954Z\n"
"POT-Creation-Date: 2022-08-23T08:55:03.041Z\n"
"PO-Revision-Date: 2022-08-23T08:55:03.041Z\n"

msgid "<No value>"
msgstr ""
Expand Down Expand Up @@ -77,10 +77,10 @@ msgstr ""
msgid "NHWA Data Approval Status Report"
msgstr ""

msgid "Data set"
msgid "Period"
msgstr ""

msgid "Period"
msgid "Data set"
msgstr ""

msgid "Attribute"
Expand Down Expand Up @@ -128,6 +128,12 @@ msgstr ""
msgid "NHWA Comments Report"
msgstr ""

msgid "Download CSV"
msgstr ""

msgid "Switch Periods"
msgstr ""

msgid "Section"
msgstr ""

Expand Down
12 changes: 9 additions & 3 deletions i18n/es.po
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: i18next-conv\n"
"POT-Creation-Date: 2022-01-10T08:43:46.954Z\n"
"POT-Creation-Date: 2022-08-23T08:55:03.041Z\n"
"PO-Revision-Date: 2018-10-25T09:02:35.143Z\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
Expand Down Expand Up @@ -77,10 +77,10 @@ msgstr ""
msgid "NHWA Data Approval Status Report"
msgstr ""

msgid "Data set"
msgid "Period"
msgstr ""

msgid "Period"
msgid "Data set"
msgstr ""

msgid "Attribute"
Expand Down Expand Up @@ -128,6 +128,12 @@ msgstr ""
msgid "NHWA Comments Report"
msgstr ""

msgid "Download CSV"
msgstr ""

msgid "Switch Periods"
msgstr ""

msgid "Section"
msgstr ""

Expand Down
46 changes: 30 additions & 16 deletions src/data/NHWADataCommentsDefaultRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,27 +63,41 @@ export class NHWADataCommentsDefaultRepository implements NHWADataCommentsReposi
.join("-") || "-";

const sqlViews = new Dhis2SqlViews(this.api);
const { pager, rows } = await sqlViews
.query<Variables, SqlField>(
config.dataCommentsSqlView.id,
{
orgUnitIds: sqlViewJoinIds(orgUnitIds),
periods: sqlViewJoinIds(_.isEmpty(periods) ? config.years : periods),
dataSetIds: sqlViewJoinIds(dataSetIds2),
sectionIds: sqlViewJoinIds(sectionIds),
orderByColumn: fieldMapping[sorting.field],
orderByDirection: sorting.direction,
commentPairs,
},
paging
)
.getData();
const { pager, rows } = _.merge(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the idea of that merge with a single object?

await sqlViews
.query<Variables, SqlField>(
config.dataCommentsSqlView.id,
{
orgUnitIds: sqlViewJoinIds(orgUnitIds),
periods: sqlViewJoinIds(periods),
dataSetIds: sqlViewJoinIds(dataSetIds2),
sectionIds: sqlViewJoinIds(sectionIds),
orderByColumn: fieldMapping[sorting.field],
orderByDirection: sorting.direction,
commentPairs,
},
paging
)
.getData()
);

// A data value is not associated to a specific data set, but we can still map it
// through the data element (1 data value -> 1 data element -> N data sets).

const dataValues: Array<DataCommentsItem> = rows.map(
(dv): DataCommentsItem => ({
(dv: {
period: string;
orgunit: any;
datasetname: any;
dataelementid: any;
dataelementname: any;
section: any;
cocname: any;
value: any;
comment: any;
lastupdated: string | number | Date;
storedby: any;
}): DataCommentsItem => ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why type dv? It should be already typed.

period: dv.period.split("-")[0] ?? "",
orgUnit: { name: dv.orgunit },
dataSet: { name: dv.datasetname },
Expand Down
2 changes: 1 addition & 1 deletion src/domain/nhwa-comments/usecases/GetDataValuesUseCase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
import { DataCommentsItem } from "../entities/DataCommentsItem";
import { PaginatedObjects } from "../../common/entities/PaginatedObjects";

type GetDataValuesUseCaseOptions = NHWADataCommentsRepositoryGetOptions;
export type GetDataValuesUseCaseOptions = NHWADataCommentsRepositoryGetOptions;

export class GetDataValuesUseCase {
constructor(private dataValueRepository: NHWADataCommentsRepository) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
TableSorting,
} from "@eyeseetea/d2-ui-components";
import StorageIcon from "@material-ui/icons/Storage";
import RestartAltIcon from "@material-ui/icons/Storage";
import _ from "lodash";
import React from "react";
import { sortByName } from "../../../../domain/common/entities/Base";
Expand All @@ -21,80 +22,93 @@ import { useSnackbarOnError } from "../../../utils/snackbar";
import { DataCommentsViewModel, getDataCommentsViews } from "../DataCommentsViewModel";
import { DataValuesFilter } from "./Filters";
import { FiltersBox } from "./FiltersBox";

export const DataCommentsList: React.FC = React.memo(() => {
export const DataCommentsList: React.FC = () => {
const [oldYears, setOldYears] = React.useState(false);
const { compositionRoot, config } = useAppContext();

const selectablePeriods = React.useMemo(() => {
const currentYear = new Date().getFullYear();
return oldYears
? _.range(currentYear - 40, currentYear - 10).map(n => n.toString())
: _.range(currentYear - 10, currentYear + 1).map(n => n.toString());
}, [oldYears]);

const [filters, setFilters] = React.useState(() => getEmptyDataValuesFilter(config));
const baseConfig = React.useMemo(getBaseListConfig, []);
const [sorting, setSorting] = React.useState<TableSorting<DataCommentsViewModel>>();

const getRows = React.useMemo(
() => async (paging: TablePagination, sorting: TableSorting<DataCommentsViewModel>) => {
const { pager, objects } = await compositionRoot.dataComments.get({
config,
paging: { page: paging.page, pageSize: paging.pageSize },
sorting: getSortingFromTableSorting(sorting),
...getUseCaseOptions(filters),
...getUseCaseOptions(filters, selectablePeriods),
});
setFilters(filters);
setSorting(sorting);
return { pager, objects: getDataCommentsViews(config, objects) };
},
[config, compositionRoot, filters]
[config, compositionRoot, filters, selectablePeriods]
);

const getRowsWithSnackbarOrError = useSnackbarOnError(getRows);
const tableProps = useObjectsTable(baseConfig, getRowsWithSnackbarOrError);
const filterOptions = React.useMemo(() => getFilterOptions(config, filters), [config, filters]);

const filterOptions = React.useMemo(
() => getFilterOptions(config, filters, selectablePeriods),
[config, filters, selectablePeriods]
);
const downloadCsv: TableGlobalAction = {
name: "downloadCsv",
text: "Download CSV",
text: i18n.t("Download CSV"),
icon: <StorageIcon />,
onClick: async () => {
if (!sorting) return;
// FUTURE: create a single use case that performs the get+saveCSV
const { objects: dataValues } = await compositionRoot.dataComments.get({
config,
paging: { page: 1, pageSize: 100000 },
sorting: getSortingFromTableSorting(sorting),
...getUseCaseOptions(filters),
...getUseCaseOptions(filters, selectablePeriods),
});
compositionRoot.dataComments.save("data-values.csv", dataValues);
},
};

const periodsToggle: TableGlobalAction = {
name: "switchPeriods",
text: i18n.t("Switch Periods"),
icon: <RestartAltIcon />,
onClick: async () => {
setOldYears(oldYears => !oldYears);
setFilters(currentFilters => ({ ...currentFilters, periods: [] }));
},
};
return (
<ObjectsList<DataCommentsViewModel> {...tableProps} globalActions={[downloadCsv]}>
<ObjectsList<DataCommentsViewModel> {...tableProps} globalActions={[downloadCsv, periodsToggle]}>
<FiltersBox showToggleButton={false} values={filters} options={filterOptions} onChange={setFilters} />
</ObjectsList>
);
});
};

function getUseCaseOptions(filter: DataValuesFilter) {
function getUseCaseOptions(filter: DataValuesFilter, selectablePeriods: string[]) {
return {
...filter,
periods: _.isEmpty(filter.periods) ? selectablePeriods : filter.periods,
orgUnitIds: getOrgUnitIdsFromPaths(filter.orgUnitPaths),
};
}

function getSortingFromTableSorting(sorting: TableSorting<DataCommentsViewModel>): Sorting<DataCommentsItem> {
return {
field: sorting.field === "id" ? "period" : sorting.field,
direction: sorting.order,
};
}

function getBaseListConfig(): TableConfig<DataCommentsViewModel> {
const paginationOptions: PaginationOptions = {
pageSizeOptions: [10, 20, 50],
pageSizeInitialValue: 10,
};

const initialSorting: TableSorting<DataCommentsViewModel> = {
field: "dataSet" as const,
order: "asc" as const,
};

const columns: TableColumn<DataCommentsViewModel>[] = [
{ name: "dataSet", text: i18n.t("Data set"), sortable: true },
{ name: "period", text: i18n.t("Period"), sortable: true },
Expand All @@ -107,26 +121,22 @@ function getBaseListConfig(): TableConfig<DataCommentsViewModel> {
{ name: "lastUpdated", text: i18n.t("Last updated"), sortable: true, hidden: true },
{ name: "storedBy", text: i18n.t("Stored by"), sortable: true, hidden: true },
];

return { columns, initialSorting, paginationOptions };
}

function getFilterOptions(config: Config, filters: DataValuesFilter) {
function getFilterOptions(config: Config, filters: DataValuesFilter, selectablePeriods: string[]) {
const { dataSetIds } = filters;
const sections = _(config.sectionsByDataSet)
.at(_.isEmpty(dataSetIds) ? _.keys(config.sectionsByDataSet) : dataSetIds)
.flatten()
.compact()
.uniqBy(section => section.id)
.value();

return {
periods: config.years,
periods: selectablePeriods,
dataSets: sortByName(_.values(config.dataSets)),
sections: sortByName(sections),
};
}

function getEmptyDataValuesFilter(config: Config): DataValuesFilter {
return {
orgUnitPaths: getMainUserPaths(config),
Expand Down