From ff9ad1b59cea9124b7e92e200f97ee0793bf5c69 Mon Sep 17 00:00:00 2001 From: idelcano Date: Tue, 22 Mar 2022 15:36:17 +0100 Subject: [PATCH 01/24] empty validation custom forms --- src/webapp/components/select/Select.tsx | 79 +++++++++++++++++++ src/webapp/reports/Reports.tsx | 4 + .../CustomFormErrorsList.tsx | 10 +++ .../ValidateCustomFormsReport.tsx | 64 +++++++++++++++ 4 files changed, 157 insertions(+) create mode 100644 src/webapp/components/select/Select.tsx create mode 100644 src/webapp/reports/validate-custom-forms/CustomFormErrorsList.tsx create mode 100644 src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx diff --git a/src/webapp/components/select/Select.tsx b/src/webapp/components/select/Select.tsx new file mode 100644 index 00000000..11814dd4 --- /dev/null +++ b/src/webapp/components/select/Select.tsx @@ -0,0 +1,79 @@ +import { + FormControl, + InputLabel, + MenuItem, + Select as MuiSelect, + SelectProps as MuiSelectProps, +} from "@material-ui/core"; +import { createStyles, makeStyles } from "@material-ui/core/styles"; +import _ from "lodash"; +import React, { useMemo, useState } from "react"; + +export type SelectOption = { value: string; label: string }; + +export interface SelectProps extends Omit { + placeholder?: string; + options: Array; + onChange: (option: SelectOption) => void; + defaultValue?: SelectOption; + value?: string; + allowEmpty?: boolean; + emptyLabel?: string; +} + +export const Select: React.FC = ({ + placeholder, + options, + onChange, + defaultValue, + value, + allowEmpty = false, + emptyLabel = "", + ...rest +}) => { + const classes = useStyles(); + const [stateValue, setValue] = useState(defaultValue ? defaultValue.value : ""); + const optionsByValue = useMemo(() => _.keyBy(options, option => option.value), [options]); + const defaultOption = allowEmpty ? { label: "", value: "" } : undefined; + + const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => { + const newValue = event.target.value as string; + const option = _(optionsByValue).get(newValue, defaultOption); + setValue(newValue); + if (option) onChange(option); + }; + + const defaultLabel = allowEmpty ? emptyLabel : placeholder; + + return ( +
+ + {!!placeholder && {placeholder}} + + {!!defaultLabel && ( + + {defaultLabel} + + )} + {options.map(option => ( + + {option.label} + + ))} + + +
+ ); +}; + +const useStyles = makeStyles(() => + createStyles({ + formControl: { + margin: 0, + display: "flex", + }, + menuItem: { + minHeight: 35, + }, + }) +); diff --git a/src/webapp/reports/Reports.tsx b/src/webapp/reports/Reports.tsx index 15f4cf3c..33714b3e 100644 --- a/src/webapp/reports/Reports.tsx +++ b/src/webapp/reports/Reports.tsx @@ -2,6 +2,7 @@ import React from "react"; import AdminReport from "./admin/AdminReport"; import NHWACommentsReport from "./nhwa-comments/NHWACommentsReport"; import NHWADataApprovalStatusReport from "./nhwa-approval-status/NHWADataApprovalStatusReport"; +import ValidateCustomFormsReport from "./validate-custom-forms/ValidateCustomFormsReport"; const widget = process.env.REACT_APP_REPORT_VARIANT || ""; @@ -16,6 +17,9 @@ const Component: React.FC = () => { case "admin": { return ; } + case "validatecustomforms": { + return ; + } default: { return

{`Please provide a valid REACT_APP_REPORT_VARIANT`}

; } diff --git a/src/webapp/reports/validate-custom-forms/CustomFormErrorsList.tsx b/src/webapp/reports/validate-custom-forms/CustomFormErrorsList.tsx new file mode 100644 index 00000000..3e5d6145 --- /dev/null +++ b/src/webapp/reports/validate-custom-forms/CustomFormErrorsList.tsx @@ -0,0 +1,10 @@ +import React from "react"; + +export const CustomFormErrorsList: React.FC = React.memo(() => { + //await compositionRoot.dataComments.get({}) + return ( +
+ {

{ "ERROR: UID xxx does not exist in dataset xxxx" }

}{

{ "ERROR: DataElement xxx is not associated to dataset xxxx" }

} +
+ ); +}); diff --git a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx new file mode 100644 index 00000000..700609be --- /dev/null +++ b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx @@ -0,0 +1,64 @@ +import { Typography, makeStyles } from "@material-ui/core"; +import React from "react"; +import { useState } from "react"; +import i18n from "../../../locales"; +import { Select, SelectOption } from "../../components/select/Select"; +import { CustomFormErrorsList } from "./CustomFormErrorsList"; + + +const onModuleChange = ({ value }: SelectOption) => { + //execute use case to get the CustomFormErrorsList from a given dataset + return value + +}; +const AdminReport: React.FC = () => { + const classes = useStyles(); + //hardcoded list of modules + const [modules] = useState<{ value: string; label: string }[]>([]); + return ( + +

{i18n.t("Custom Form Validation")}

+ +
+
- - {} -
- - {i18n.t("Result:")} - -
-
- -
+ {} + +
+ {i18n.t("Result:")} +
+
+ {list.forEach(item => { + return

{item}

; + })} +

{_.values(list)}

+
); }; @@ -57,19 +67,20 @@ const useStyles = makeStyles({ flexFlow: "row nowrap", justifyContent: "space-around", marginRight: "1em", - marginLeft: "1%" + marginLeft: "1%", + }, + title: { marginBottom: 0, marginLeft: "1%" }, + select: { + flexBasis: "100%", + margin: "0.5em", + marginTop: "1em", + flexFlow: "row nowrap", + justifyContent: "space-around", + marginRight: "75%", + marginLeft: "1%", }, - title: { marginBottom: 0, - marginLeft: "1%" }, - select: { flexBasis: "100%", margin: "0.5em", marginTop: "1em", - flexFlow: "row nowrap", - justifyContent: "space-around", - marginRight: "75%", - marginLeft: "1%" }, checkbox: { marginTop: "1em" }, fullWidth: { width: "25%" }, }); - export default AdminReport; - From cdd073d1d674681add994edbe8949912ac676345 Mon Sep 17 00:00:00 2001 From: idelcano Date: Tue, 29 Mar 2022 19:34:24 +0200 Subject: [PATCH 04/24] create validation logic --- i18n/en.pot | 14 ++-- i18n/es.po | 12 +++- src/data/CustomFormErrorsDefaultRepository.ts | 70 +++++++++++++------ .../ValidateCustomFormsReport.tsx | 21 ++---- yarn.lock | 13 ++-- 5 files changed, 80 insertions(+), 50 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index 73d40913..9787ce54 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -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-03-28T16:58:13.797Z\n" +"PO-Revision-Date: 2022-03-28T16:58:13.797Z\n" msgid "" msgstr "" @@ -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" @@ -154,3 +154,9 @@ msgstr "" msgid "Toggle filters" msgstr "" + +msgid "Custom Form Validation" +msgstr "" + +msgid "Select custom form to validate..." +msgstr "" diff --git a/i18n/es.po b/i18n/es.po index a81ba594..db654015 100644 --- a/i18n/es.po +++ b/i18n/es.po @@ -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-03-28T16:58:13.797Z\n" "PO-Revision-Date: 2018-10-25T09:02:35.143Z\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -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" @@ -155,6 +155,12 @@ msgstr "" msgid "Toggle filters" msgstr "" +msgid "Custom Form Validation" +msgstr "" + +msgid "Select custom form to validate..." +msgstr "" + #~ msgid "Add" #~ msgstr "AƱadir" diff --git a/src/data/CustomFormErrorsDefaultRepository.ts b/src/data/CustomFormErrorsDefaultRepository.ts index 4596f516..006d892b 100644 --- a/src/data/CustomFormErrorsDefaultRepository.ts +++ b/src/data/CustomFormErrorsDefaultRepository.ts @@ -1,39 +1,69 @@ - import _ from "lodash"; import { CustomFormErrorsRepository } from "../domain/validatecustomforms/repositories/CustomFormErrorsRepository"; import { D2Api } from "../types/d2-api"; export class CustomFormErrorsDefaultRepository implements CustomFormErrorsRepository { constructor(private api: D2Api) {} - async get(id:string): Promise { + async get(id: string): Promise { //http://localhost:8080/api/metadata.json?dataSets:fields=id,name,dataSetElements[dataElement[id,categoryCombo[id]&categoryCombos:fields=id,categoryOptionCombos&filter=id:eq:Tu81BTLUuCT - // eslint-disable-next-line - debugger; const dataSetMetadata: any = await this.api.metadata.d2Api .get( "/metadata.json?dataSets:fields=id,name,dataEntryForm[htmlCode],dataSetElements[dataElement[id,categoryCombo[id]&categoryCombos:fields=id,categoryOptionCombos" ) .getData(); - // eslint-disable-next-line - const dataSets = dataSetMetadata["dataSets"] - // eslint-disable-next-line - debugger - // eslint-disable-next-line + const dataSets = dataSetMetadata["dataSets"]; const filtered = _.filter(dataSets, dataset => dataset.id === id); + const htmlCode = filtered[0]["dataEntryForm"]["htmlCode"]; + const newRegExp = new RegExp(/((([a-zA-Z0-9]){11})-(([a-zA-Z0-9]){11})-val)/g); - // eslint-disable-next-line - debugger - // eslint-disable-next-line - const htmlCode = filtered[0]["dataEntryForm"]["htmlCode"] - const newRegExp = new RegExp('((([a-zA-Z0-9]){11})-(([a-zA-Z0-9]){11})-val)') - // eslint-disable-next-line - const result = newRegExp.exec(htmlCode) + const matches = htmlCode.match(newRegExp); - const result_2 = [...htmlCode.matchAll(newRegExp)] + const result = _.map(matches, match => { + const groups = newRegExp.exec(match); + if (groups != null) { + return { dataElementId: groups[2], categoryOptionComboId: groups[4] }; + } + }); // eslint-disable-next-line - debugger + const errors = _.map(result, input => { + if (input != null) { + const categoryComboInDatasetElement = _.map(filtered[0]["dataSetElements"], dataelement => { + if (input != null && input["dataElementId"] === dataelement["dataElement"]["id"]) { + return dataelement["dataElement"]["categoryCombo"]["id"]; + } + }); + const categoryComboInDataElement = _.compact(categoryComboInDatasetElement); + if (categoryComboInDataElement.length === 0) { + return "ERROR dataelement " + input["dataElementId"] + " not exist in given dataset"; + } else { + const categoryOptionComboInCategoryCombo = _.map( + dataSetMetadata["categoryCombos"], + categoryCombo => { + if (categoryComboInDataElement[0] === categoryCombo["id"]) { + const exist = _.map(categoryCombo["categoryOptionCombos"], categoryOptionCombo => { + return (categoryOptionCombo["id"] === input["categoryOptionComboId"]) + }) + return _.compact(exist); + }else{ + return undefined; + } + } + ) + const categoryComboOptionErrors = _.compact(categoryOptionComboInCategoryCombo); + if (categoryComboOptionErrors.length !== 1) { + return ( + "ERROR CategoryOptionCombo " + + input["categoryOptionComboId"] + + " not exist in given dataelement " + + input["dataElementId"] + ); + } + } + } + }); + const newerror = _.compact(errors); //return this.mapMetadataObjects(Object.assign(publicAccessResult, userGroupAccessesResult), options); - return ["Error example"] + return newerror } -} \ No newline at end of file +} diff --git a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx index e00099ec..021f5269 100644 --- a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx +++ b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx @@ -7,29 +7,22 @@ import { useAppContext } from "../../contexts/app-context"; const list = ["Error ex"]; -const AdminReport: React.FC = () => { +const ValidateCustomFormsReport: React.FC = () => { const { compositionRoot, config } = useAppContext(); const OnModuleChange = async ({ value }: SelectOption) => { //execute use case to get the CustomFormErrorsList from a given dataset - // eslint-disable-next-line - debugger; const result = await compositionRoot.validateCustomForm.get(value); - // eslint-disable-next-line - // eslint-disable-next-line - debugger; + _.remove(list); result.map(item => { - list.push(item); + return list.push(item); }); - //list.push(result) - // setIsRunning(false) - //} - // eslint-disable-next-line - debugger; return value; }; const classes = useStyles(); const [modules] = React.useState<{ value: string; label: string }[]>( - _.values(config.dataSets).map(ds => { + _.values(config.dataSets).filter(ds =>{ + return (ds.name.indexOf("Maturity") === -1) + }).map(ds => { return { value: ds.id, label: ds.name }; }) ); @@ -83,4 +76,4 @@ const useStyles = makeStyles({ fullWidth: { width: "25%" }, }); -export default AdminReport; +export default ValidateCustomFormsReport; diff --git a/yarn.lock b/yarn.lock index da94d7bc..828c2083 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6027,15 +6027,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001254: - version "1.0.30001258" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001258.tgz#b604eed80cc54a578e4bf5a02ae3ed49f869d252" - integrity sha512-RBByOG6xWXUp0CR2/WU2amXz3stjKpSl5J1xU49F1n2OxD//uBZO4wCKUiG+QMGf7CHGfDDcqoKriomoGVxTeA== - -caniuse-lite@^1.0.30001280: - version "1.0.30001282" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001282.tgz#38c781ee0a90ccfe1fe7fefd00e43f5ffdcb96fd" - integrity sha512-YhF/hG6nqBEllymSIjLtR2iWDDnChvhnVJqp+vloyt2tEHFG1yBR+ac2B/rOw0qOK0m0lEXU2dv4E/sMk5P9Kg== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001254, caniuse-lite@^1.0.30001280: + version "1.0.30001320" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz" + integrity sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA== capture-exit@^2.0.0: version "2.0.0" From 3a87d03685d9360da42a811da6296f6a8294b9c6 Mon Sep 17 00:00:00 2001 From: idelcano Date: Tue, 29 Mar 2022 20:00:32 +0200 Subject: [PATCH 05/24] Added progress bar when validation is running --- .../ValidateCustomFormsReport.tsx | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx index 021f5269..793c9623 100644 --- a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx +++ b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx @@ -1,30 +1,41 @@ -import { Typography, makeStyles, CircularProgress } from "@material-ui/core"; +import { Typography, makeStyles } from "@material-ui/core"; import _ from "lodash"; -import React from "react"; +import React, { useState } from "react"; import i18n from "../../../locales"; +import { Spinner } from "../../components/objects-list/Spinner"; import { Select, SelectOption } from "../../components/select/Select"; import { useAppContext } from "../../contexts/app-context"; -const list = ["Error ex"]; +const list = [""]; const ValidateCustomFormsReport: React.FC = () => { + const [isLoading, setLoading] = useState(false); + const { compositionRoot, config } = useAppContext(); const OnModuleChange = async ({ value }: SelectOption) => { - //execute use case to get the CustomFormErrorsList from a given dataset + setLoading(true); const result = await compositionRoot.validateCustomForm.get(value); _.remove(list); + if (result.length == 0) { + list.push("No errors detected"); + } result.map(item => { return list.push(item); }); + setLoading(false); return value; }; + const classes = useStyles(); + const [modules] = React.useState<{ value: string; label: string }[]>( - _.values(config.dataSets).filter(ds =>{ - return (ds.name.indexOf("Maturity") === -1) - }).map(ds => { - return { value: ds.id, label: ds.name }; - }) + _.values(config.dataSets) + .filter(ds => { + return ds.name.indexOf("Maturity") === -1; + }) + .map(ds => { + return { value: ds.id, label: ds.name }; + }) ); return ( @@ -39,15 +50,16 @@ const ValidateCustomFormsReport: React.FC = () => { /> - {} +
+

+ +

+
{i18n.t("Result:")}
- {list.forEach(item => { - return

{item}

; - })}

{_.values(list)}

From 3278e9936d14625ffb876ee02c3b60d01ffe9660 Mon Sep 17 00:00:00 2001 From: idelcano Date: Tue, 29 Mar 2022 20:16:33 +0200 Subject: [PATCH 06/24] updated isnull check methods and strings --- src/data/CustomFormErrorsDefaultRepository.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/data/CustomFormErrorsDefaultRepository.ts b/src/data/CustomFormErrorsDefaultRepository.ts index 006d892b..7d7b0194 100644 --- a/src/data/CustomFormErrorsDefaultRepository.ts +++ b/src/data/CustomFormErrorsDefaultRepository.ts @@ -21,21 +21,21 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi const result = _.map(matches, match => { const groups = newRegExp.exec(match); - if (groups != null) { + if (!_.isNil(groups)) { return { dataElementId: groups[2], categoryOptionComboId: groups[4] }; } }); // eslint-disable-next-line const errors = _.map(result, input => { - if (input != null) { + if (!_.isNil(input)) { const categoryComboInDatasetElement = _.map(filtered[0]["dataSetElements"], dataelement => { - if (input != null && input["dataElementId"] === dataelement["dataElement"]["id"]) { + if (!_.isNil(input) && input["dataElementId"] === dataelement["dataElement"]["id"]) { return dataelement["dataElement"]["categoryCombo"]["id"]; } }); const categoryComboInDataElement = _.compact(categoryComboInDatasetElement); if (categoryComboInDataElement.length === 0) { - return "ERROR dataelement " + input["dataElementId"] + " not exist in given dataset"; + return "ERROR dataelement with UID: " + input["dataElementId"] + " not exist in dataset with UID: "+id; } else { const categoryOptionComboInCategoryCombo = _.map( dataSetMetadata["categoryCombos"], @@ -53,10 +53,10 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi const categoryComboOptionErrors = _.compact(categoryOptionComboInCategoryCombo); if (categoryComboOptionErrors.length !== 1) { return ( - "ERROR CategoryOptionCombo " + - input["categoryOptionComboId"] + - " not exist in given dataelement " + - input["dataElementId"] + "ERROR Dataelement with UID: " + + input["dataElementId"] + + " is not associated with CategoryOptionComboID: "+ + input["categoryOptionComboId"] ); } } From 550eda60e304b96dcd414578f57fe7b127102409 Mon Sep 17 00:00:00 2001 From: idelcano Date: Mon, 4 Apr 2022 09:58:25 +0200 Subject: [PATCH 07/24] clean code and draw items with \n --- src/data/CustomFormErrorsDefaultRepository.ts | 8 ++----- .../ValidateCustomFormsReport.tsx | 22 +++++++++++++------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/data/CustomFormErrorsDefaultRepository.ts b/src/data/CustomFormErrorsDefaultRepository.ts index 7d7b0194..e93d06a1 100644 --- a/src/data/CustomFormErrorsDefaultRepository.ts +++ b/src/data/CustomFormErrorsDefaultRepository.ts @@ -5,8 +5,6 @@ import { D2Api } from "../types/d2-api"; export class CustomFormErrorsDefaultRepository implements CustomFormErrorsRepository { constructor(private api: D2Api) {} async get(id: string): Promise { - //http://localhost:8080/api/metadata.json?dataSets:fields=id,name,dataSetElements[dataElement[id,categoryCombo[id]&categoryCombos:fields=id,categoryOptionCombos&filter=id:eq:Tu81BTLUuCT - const dataSetMetadata: any = await this.api.metadata.d2Api .get( "/metadata.json?dataSets:fields=id,name,dataEntryForm[htmlCode],dataSetElements[dataElement[id,categoryCombo[id]&categoryCombos:fields=id,categoryOptionCombos" @@ -25,7 +23,6 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi return { dataElementId: groups[2], categoryOptionComboId: groups[4] }; } }); - // eslint-disable-next-line const errors = _.map(result, input => { if (!_.isNil(input)) { const categoryComboInDatasetElement = _.map(filtered[0]["dataSetElements"], dataelement => { @@ -50,8 +47,8 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi } } ) - const categoryComboOptionErrors = _.compact(categoryOptionComboInCategoryCombo); - if (categoryComboOptionErrors.length !== 1) { + const categoryComboOptionErrors = _.compact(categoryOptionComboInCategoryCombo)[0]; + if (categoryComboOptionErrors?.length !== 1) { return ( "ERROR Dataelement with UID: " + input["dataElementId"] + @@ -63,7 +60,6 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi } }); const newerror = _.compact(errors); - //return this.mapMetadataObjects(Object.assign(publicAccessResult, userGroupAccessesResult), options); return newerror } } diff --git a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx index 793c9623..6412b3f3 100644 --- a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx +++ b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx @@ -6,7 +6,7 @@ import { Spinner } from "../../components/objects-list/Spinner"; import { Select, SelectOption } from "../../components/select/Select"; import { useAppContext } from "../../contexts/app-context"; -const list = [""]; +const list = [{ text: "" }]; const ValidateCustomFormsReport: React.FC = () => { const [isLoading, setLoading] = useState(false); @@ -16,11 +16,11 @@ const ValidateCustomFormsReport: React.FC = () => { setLoading(true); const result = await compositionRoot.validateCustomForm.get(value); _.remove(list); - if (result.length == 0) { - list.push("No errors detected"); + if (result.length === 0) { + list.push({ text: "No errors detected" }); } result.map(item => { - return list.push(item); + return list.push({ text: item }); }); setLoading(false); return value; @@ -59,9 +59,11 @@ const ValidateCustomFormsReport: React.FC = () => {
{i18n.t("Result:")}
-
-

{_.values(list)}

-
+ + {_.map(list, item => { + return
{item.text}
; + })} + ); }; @@ -74,6 +76,12 @@ const useStyles = makeStyles({ marginRight: "1em", marginLeft: "1%", }, + items: { + display: "flex", + flexFlow: "row nowrap", + marginRight: "1em", + marginLeft: "1%", + }, title: { marginBottom: 0, marginLeft: "1%" }, select: { flexBasis: "100%", From 6d0b91a85c25a924deab21f87c6410b43649390d Mon Sep 17 00:00:00 2001 From: idelcano Date: Tue, 5 Apr 2022 21:07:09 +0200 Subject: [PATCH 08/24] remove unused file --- .../validate-custom-forms/CustomFormErrorsList.tsx | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 src/webapp/reports/validate-custom-forms/CustomFormErrorsList.tsx diff --git a/src/webapp/reports/validate-custom-forms/CustomFormErrorsList.tsx b/src/webapp/reports/validate-custom-forms/CustomFormErrorsList.tsx deleted file mode 100644 index 3e5d6145..00000000 --- a/src/webapp/reports/validate-custom-forms/CustomFormErrorsList.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; - -export const CustomFormErrorsList: React.FC = React.memo(() => { - //await compositionRoot.dataComments.get({}) - return ( -
- {

{ "ERROR: UID xxx does not exist in dataset xxxx" }

}{

{ "ERROR: DataElement xxx is not associated to dataset xxxx" }

} -
- ); -}); From 6a74c108a6e9ea062e94043ed44ddd859f10864c Mon Sep 17 00:00:00 2001 From: idelcano Date: Tue, 5 Apr 2022 21:07:47 +0200 Subject: [PATCH 09/24] Added translations --- .../ValidateCustomFormsReport.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx index 6412b3f3..34455ab2 100644 --- a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx +++ b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx @@ -17,7 +17,7 @@ const ValidateCustomFormsReport: React.FC = () => { const result = await compositionRoot.validateCustomForm.get(value); _.remove(list); if (result.length === 0) { - list.push({ text: "No errors detected" }); + list.push({ text: i18n.t("No errors detected" )}); } result.map(item => { return list.push({ text: item }); @@ -59,11 +59,10 @@ const ValidateCustomFormsReport: React.FC = () => {
{i18n.t("Result:")}
- - {_.map(list, item => { - return
{item.text}
; - })} - + + {_.map(list, item => { + return
{item.text}
; + })} ); }; From 40148bab52a2db618531144b0f296cdfcf849181 Mon Sep 17 00:00:00 2001 From: idelcano Date: Tue, 5 Apr 2022 21:08:34 +0200 Subject: [PATCH 10/24] fixed most of reviews --- src/data/CustomFormErrorsDefaultRepository.ts | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/data/CustomFormErrorsDefaultRepository.ts b/src/data/CustomFormErrorsDefaultRepository.ts index e93d06a1..bcd3b7ab 100644 --- a/src/data/CustomFormErrorsDefaultRepository.ts +++ b/src/data/CustomFormErrorsDefaultRepository.ts @@ -1,65 +1,74 @@ import _ from "lodash"; import { CustomFormErrorsRepository } from "../domain/validatecustomforms/repositories/CustomFormErrorsRepository"; +import i18n from "../locales"; import { D2Api } from "../types/d2-api"; export class CustomFormErrorsDefaultRepository implements CustomFormErrorsRepository { + constructor(private api: D2Api) {} + async get(id: string): Promise { - const dataSetMetadata: any = await this.api.metadata.d2Api + const dataSetMetadata : any = await this.api.metadata.d2Api .get( "/metadata.json?dataSets:fields=id,name,dataEntryForm[htmlCode],dataSetElements[dataElement[id,categoryCombo[id]&categoryCombos:fields=id,categoryOptionCombos" ) .getData(); const dataSets = dataSetMetadata["dataSets"]; - const filtered = _.filter(dataSets, dataset => dataset.id === id); - const htmlCode = filtered[0]["dataEntryForm"]["htmlCode"]; + const dataSet = _.filter(dataSets, dataset => dataset.id === id)[0] + const htmlCode = dataSet["dataEntryForm"]["htmlCode"]; const newRegExp = new RegExp(/((([a-zA-Z0-9]){11})-(([a-zA-Z0-9]){11})-val)/g); const matches = htmlCode.match(newRegExp); const result = _.map(matches, match => { const groups = newRegExp.exec(match); - if (!_.isNil(groups)) { + if (groups) { return { dataElementId: groups[2], categoryOptionComboId: groups[4] }; } }); const errors = _.map(result, input => { - if (!_.isNil(input)) { - const categoryComboInDatasetElement = _.map(filtered[0]["dataSetElements"], dataelement => { - if (!_.isNil(input) && input["dataElementId"] === dataelement["dataElement"]["id"]) { + if (input) { + const categoryComboInDatasetElement = _.map(dataSet["dataSetElements"], dataelement => { + if (input && input["dataElementId"] === dataelement["dataElement"]["id"]) { return dataelement["dataElement"]["categoryCombo"]["id"]; } }); const categoryComboInDataElement = _.compact(categoryComboInDatasetElement); if (categoryComboInDataElement.length === 0) { - return "ERROR dataelement with UID: " + input["dataElementId"] + " not exist in dataset with UID: "+id; + return ( + i18n.t("ERROR dataelement with UID: ") + + input["dataElementId"] + + i18n.t(" does not exist in dataset with UID: ") + + id + ); } else { const categoryOptionComboInCategoryCombo = _.map( dataSetMetadata["categoryCombos"], categoryCombo => { if (categoryComboInDataElement[0] === categoryCombo["id"]) { const exist = _.map(categoryCombo["categoryOptionCombos"], categoryOptionCombo => { - return (categoryOptionCombo["id"] === input["categoryOptionComboId"]) - }) + return categoryOptionCombo["id"] === input["categoryOptionComboId"]; + }); return _.compact(exist); - }else{ + } else { return undefined; } } - ) + ); const categoryComboOptionErrors = _.compact(categoryOptionComboInCategoryCombo)[0]; if (categoryComboOptionErrors?.length !== 1) { return ( - "ERROR Dataelement with UID: " + + i18n.t("ERROR Dataelement with UID: ") + input["dataElementId"] + - " is not associated with CategoryOptionComboID: "+ - input["categoryOptionComboId"] + i18n.t(" is not associated with CategoryOptionComboID: ") + + input["categoryOptionComboId"] ); } } } }); const newerror = _.compact(errors); - return newerror + + return _.uniq(newerror); } } From b5decf654c259c9ff85835e30ef20fa9bad65868 Mon Sep 17 00:00:00 2001 From: idelcano Date: Tue, 5 Apr 2022 21:48:31 +0200 Subject: [PATCH 11/24] Added trnslations and some function --- i18n/en.pot | 7 +++++-- i18n/es.po | 5 ++++- src/compositionRoot.ts | 1 - src/data/CustomFormErrorsDefaultRepository.ts | 21 +++++++++---------- .../CustomFormErrorsRepository.ts | 2 +- .../ValidateCustomFormsReport.tsx | 4 +++- 6 files changed, 23 insertions(+), 17 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index 9787ce54..3b95829f 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -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-03-28T16:58:13.797Z\n" -"PO-Revision-Date: 2022-03-28T16:58:13.797Z\n" +"POT-Creation-Date: 2022-04-05T19:14:43.245Z\n" +"PO-Revision-Date: 2022-04-05T19:14:43.245Z\n" msgid "" msgstr "" @@ -155,6 +155,9 @@ msgstr "" msgid "Toggle filters" msgstr "" +msgid "No errors detected" +msgstr "" + msgid "Custom Form Validation" msgstr "" diff --git a/i18n/es.po b/i18n/es.po index db654015..42ebb45c 100644 --- a/i18n/es.po +++ b/i18n/es.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2022-03-28T16:58:13.797Z\n" +"POT-Creation-Date: 2022-04-05T19:14:43.245Z\n" "PO-Revision-Date: 2018-10-25T09:02:35.143Z\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -155,6 +155,9 @@ msgstr "" msgid "Toggle filters" msgstr "" +msgid "No errors detected" +msgstr "" + msgid "Custom Form Validation" msgstr "" diff --git a/src/compositionRoot.ts b/src/compositionRoot.ts index 5a037677..bcddee7e 100644 --- a/src/compositionRoot.ts +++ b/src/compositionRoot.ts @@ -25,7 +25,6 @@ export function getCompositionRoot(api: D2Api) { const widpAdminDefaultRepository = new WIDPAdminDefaultRepository(api); const orgUnitsRepository = new Dhis2OrgUnitsRepository(api); const customFormErrorsDefaultRepository = new CustomFormErrorsDefaultRepository(api); - return { admin: getExecute({ diff --git a/src/data/CustomFormErrorsDefaultRepository.ts b/src/data/CustomFormErrorsDefaultRepository.ts index bcd3b7ab..7b536e99 100644 --- a/src/data/CustomFormErrorsDefaultRepository.ts +++ b/src/data/CustomFormErrorsDefaultRepository.ts @@ -4,17 +4,16 @@ import i18n from "../locales"; import { D2Api } from "../types/d2-api"; export class CustomFormErrorsDefaultRepository implements CustomFormErrorsRepository { - constructor(private api: D2Api) {} async get(id: string): Promise { - const dataSetMetadata : any = await this.api.metadata.d2Api + const dataSetMetadata: any = await this.api.metadata.d2Api .get( "/metadata.json?dataSets:fields=id,name,dataEntryForm[htmlCode],dataSetElements[dataElement[id,categoryCombo[id]&categoryCombos:fields=id,categoryOptionCombos" ) .getData(); const dataSets = dataSetMetadata["dataSets"]; - const dataSet = _.filter(dataSets, dataset => dataset.id === id)[0] + const dataSet = _.filter(dataSets, dataset => dataset.id === id)[0]; const htmlCode = dataSet["dataEntryForm"]["htmlCode"]; const newRegExp = new RegExp(/((([a-zA-Z0-9]){11})-(([a-zA-Z0-9]){11})-val)/g); @@ -34,11 +33,11 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi } }); const categoryComboInDataElement = _.compact(categoryComboInDatasetElement); - if (categoryComboInDataElement.length === 0) { + if (!_.some(categoryComboInDataElement, 0)) { return ( - i18n.t("ERROR dataelement with UID: ") + - input["dataElementId"] + - i18n.t(" does not exist in dataset with UID: ") + + i18n.t("ERROR Dataelement with UID:") +" "+ + input["dataElementId"] +" "+ + i18n.t("does not exist in dataset with UID:") +" "+ id ); } else { @@ -56,11 +55,11 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi } ); const categoryComboOptionErrors = _.compact(categoryOptionComboInCategoryCombo)[0]; - if (categoryComboOptionErrors?.length !== 1) { + if (_.every(categoryComboOptionErrors, false)) { return ( - i18n.t("ERROR Dataelement with UID: ") + - input["dataElementId"] + - i18n.t(" is not associated with CategoryOptionComboID: ") + + i18n.t("ERROR Dataelement with UID:") +" "+ + input["dataElementId"] +" "+ + i18n.t("is not associated with CategoryOptionComboID:") +" "+ input["categoryOptionComboId"] ); } diff --git a/src/domain/validatecustomforms/repositories/CustomFormErrorsRepository.ts b/src/domain/validatecustomforms/repositories/CustomFormErrorsRepository.ts index 8698e44f..55249667 100644 --- a/src/domain/validatecustomforms/repositories/CustomFormErrorsRepository.ts +++ b/src/domain/validatecustomforms/repositories/CustomFormErrorsRepository.ts @@ -1,3 +1,3 @@ export interface CustomFormErrorsRepository { get(id: string): Promise; -} \ No newline at end of file +} diff --git a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx index 34455ab2..04797003 100644 --- a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx +++ b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx @@ -17,7 +17,7 @@ const ValidateCustomFormsReport: React.FC = () => { const result = await compositionRoot.validateCustomForm.get(value); _.remove(list); if (result.length === 0) { - list.push({ text: i18n.t("No errors detected" )}); + list.push({ text: i18n.t("No errors detected") }); } result.map(item => { return list.push({ text: item }); @@ -60,9 +60,11 @@ const ValidateCustomFormsReport: React.FC = () => { {i18n.t("Result:")} + {_.map(list, item => { return
{item.text}
; })} + ); }; From 6285f02f1fb1fbf697baa8767d8786f51264bb06 Mon Sep 17 00:00:00 2001 From: idelcano Date: Tue, 5 Apr 2022 21:51:32 +0200 Subject: [PATCH 12/24] wip --- src/data/CustomFormErrorsDefaultRepository.ts | 18 ++++++++++++------ .../ValidateCustomFormsReport.tsx | 13 ++++++------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/data/CustomFormErrorsDefaultRepository.ts b/src/data/CustomFormErrorsDefaultRepository.ts index 7b536e99..fcaec96f 100644 --- a/src/data/CustomFormErrorsDefaultRepository.ts +++ b/src/data/CustomFormErrorsDefaultRepository.ts @@ -35,9 +35,12 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi const categoryComboInDataElement = _.compact(categoryComboInDatasetElement); if (!_.some(categoryComboInDataElement, 0)) { return ( - i18n.t("ERROR Dataelement with UID:") +" "+ - input["dataElementId"] +" "+ - i18n.t("does not exist in dataset with UID:") +" "+ + i18n.t("ERROR Dataelement with UID:") + + " " + + input["dataElementId"] + + " " + + i18n.t("does not exist in dataset with UID:") + + " " + id ); } else { @@ -57,9 +60,12 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi const categoryComboOptionErrors = _.compact(categoryOptionComboInCategoryCombo)[0]; if (_.every(categoryComboOptionErrors, false)) { return ( - i18n.t("ERROR Dataelement with UID:") +" "+ - input["dataElementId"] +" "+ - i18n.t("is not associated with CategoryOptionComboID:") +" "+ + i18n.t("ERROR Dataelement with UID:") + + " " + + input["dataElementId"] + + " " + + i18n.t("is not associated with CategoryOptionComboID:") + + " " + input["categoryOptionComboId"] ); } diff --git a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx index 04797003..47b0a147 100644 --- a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx +++ b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx @@ -6,7 +6,8 @@ import { Spinner } from "../../components/objects-list/Spinner"; import { Select, SelectOption } from "../../components/select/Select"; import { useAppContext } from "../../contexts/app-context"; -const list = [{ text: "" }]; +const errors = [{ text: "" }]; +const [errros, setErrors] = React.useState>([{ text: "" }]); const ValidateCustomFormsReport: React.FC = () => { const [isLoading, setLoading] = useState(false); @@ -15,12 +16,12 @@ const ValidateCustomFormsReport: React.FC = () => { const OnModuleChange = async ({ value }: SelectOption) => { setLoading(true); const result = await compositionRoot.validateCustomForm.get(value); - _.remove(list); + _.remove(errors); if (result.length === 0) { - list.push({ text: i18n.t("No errors detected") }); + errors.push({ text: i18n.t("No errors detected") }); } result.map(item => { - return list.push({ text: item }); + return errors.push({ text: item }); }); setLoading(false); return value; @@ -60,11 +61,9 @@ const ValidateCustomFormsReport: React.FC = () => { {i18n.t("Result:")} - - {_.map(list, item => { + {_.map(errors, item => { return
{item.text}
; })} - ); }; From a52fa2620782bb365661a76c9421ac0cefcd35c3 Mon Sep 17 00:00:00 2001 From: idelcano Date: Tue, 5 Apr 2022 21:54:05 +0200 Subject: [PATCH 13/24] change report variant name --- src/webapp/reports/Reports.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webapp/reports/Reports.tsx b/src/webapp/reports/Reports.tsx index 33714b3e..78fd01de 100644 --- a/src/webapp/reports/Reports.tsx +++ b/src/webapp/reports/Reports.tsx @@ -17,7 +17,7 @@ const Component: React.FC = () => { case "admin": { return ; } - case "validatecustomforms": { + case "validate-custom-forms": { return ; } default: { From 6de8ef7c2b81c15b789218554e57aecf2f1eb4e7 Mon Sep 17 00:00:00 2001 From: idelcano Date: Thu, 7 Apr 2022 22:13:08 +0200 Subject: [PATCH 14/24] refactor --- src/data/CustomFormErrorsDefaultRepository.ts | 11 ++++------- .../ValidateCustomFormsReport.tsx | 11 +++++------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/data/CustomFormErrorsDefaultRepository.ts b/src/data/CustomFormErrorsDefaultRepository.ts index fcaec96f..12a3117d 100644 --- a/src/data/CustomFormErrorsDefaultRepository.ts +++ b/src/data/CustomFormErrorsDefaultRepository.ts @@ -33,7 +33,7 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi } }); const categoryComboInDataElement = _.compact(categoryComboInDatasetElement); - if (!_.some(categoryComboInDataElement, 0)) { + if (categoryComboInDataElement.length === 0) { return ( i18n.t("ERROR Dataelement with UID:") + " " + @@ -48,17 +48,14 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi dataSetMetadata["categoryCombos"], categoryCombo => { if (categoryComboInDataElement[0] === categoryCombo["id"]) { - const exist = _.map(categoryCombo["categoryOptionCombos"], categoryOptionCombo => { + return _.map(categoryCombo["categoryOptionCombos"], categoryOptionCombo => { return categoryOptionCombo["id"] === input["categoryOptionComboId"]; }); - return _.compact(exist); - } else { - return undefined; } } ); - const categoryComboOptionErrors = _.compact(categoryOptionComboInCategoryCombo)[0]; - if (_.every(categoryComboOptionErrors, false)) { + const categoryComboOptionErrors = _.compact(_.compact(categoryOptionComboInCategoryCombo)[0]); + if (categoryComboOptionErrors?.length !== 1) { return ( i18n.t("ERROR Dataelement with UID:") + " " + diff --git a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx index 47b0a147..e244a13a 100644 --- a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx +++ b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx @@ -6,23 +6,22 @@ import { Spinner } from "../../components/objects-list/Spinner"; import { Select, SelectOption } from "../../components/select/Select"; import { useAppContext } from "../../contexts/app-context"; -const errors = [{ text: "" }]; -const [errros, setErrors] = React.useState>([{ text: "" }]); +//const errors = [{ text: "" }]; const ValidateCustomFormsReport: React.FC = () => { const [isLoading, setLoading] = useState(false); + const [errors, setErrors] = React.useState>([{ text: "" }]); const { compositionRoot, config } = useAppContext(); const OnModuleChange = async ({ value }: SelectOption) => { setLoading(true); const result = await compositionRoot.validateCustomForm.get(value); _.remove(errors); if (result.length === 0) { - errors.push({ text: i18n.t("No errors detected") }); + setErrors([{ text: i18n.t("No errors detected") }]); + } else { + setErrors(_.map(result, item =>{ return {text: item}} )) } - result.map(item => { - return errors.push({ text: item }); - }); setLoading(false); return value; }; From b123ce26fb40c1bf832f88ea1867bf9127a1605c Mon Sep 17 00:00:00 2001 From: idelcano Date: Fri, 8 Apr 2022 22:26:19 +0200 Subject: [PATCH 15/24] remove warning --- .../validate-custom-forms/ValidateCustomFormsReport.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx index e244a13a..ea02bfc8 100644 --- a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx +++ b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx @@ -50,10 +50,8 @@ const ValidateCustomFormsReport: React.FC = () => { /> -
-

+

-

@@ -75,6 +73,10 @@ const useStyles = makeStyles({ marginRight: "1em", marginLeft: "1%", }, + spinner: { + position: 'absolute', left: '50%', top: '50%', + transform: 'translate(-50%, -50%)' + }, items: { display: "flex", flexFlow: "row nowrap", From acfe448ca3ad95016b32bda7630cfb946fcb8f9b Mon Sep 17 00:00:00 2001 From: idelcano Date: Fri, 8 Apr 2022 22:26:33 +0200 Subject: [PATCH 16/24] use d2 interface --- src/data/CustomFormErrorsDefaultRepository.ts | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/data/CustomFormErrorsDefaultRepository.ts b/src/data/CustomFormErrorsDefaultRepository.ts index 12a3117d..9400b192 100644 --- a/src/data/CustomFormErrorsDefaultRepository.ts +++ b/src/data/CustomFormErrorsDefaultRepository.ts @@ -7,17 +7,28 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi constructor(private api: D2Api) {} async get(id: string): Promise { - const dataSetMetadata: any = await this.api.metadata.d2Api - .get( - "/metadata.json?dataSets:fields=id,name,dataEntryForm[htmlCode],dataSetElements[dataElement[id,categoryCombo[id]&categoryCombos:fields=id,categoryOptionCombos" - ) - .getData(); - const dataSets = dataSetMetadata["dataSets"]; + const metadata$ = this.api.metadata.get({ + dataSets: { + fields: { + id: true, + displayName: true, + dataEntryForm: { htmlCode: true }, + dataSetElements: { + dataElement: { id: true, categoryCombo: { id: true } }, + }, + }, + }, + categoryCombos: { fields: { id: true, categoryOptionCombos: { id: true } } }, + }); + + const data = await metadata$.getData(); + + const dataSets = data.dataSets; const dataSet = _.filter(dataSets, dataset => dataset.id === id)[0]; - const htmlCode = dataSet["dataEntryForm"]["htmlCode"]; + const htmlCode = dataSet?.dataEntryForm.htmlCode; const newRegExp = new RegExp(/((([a-zA-Z0-9]){11})-(([a-zA-Z0-9]){11})-val)/g); - const matches = htmlCode.match(newRegExp); + const matches = htmlCode?.match(newRegExp); const result = _.map(matches, match => { const groups = newRegExp.exec(match); @@ -27,9 +38,9 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi }); const errors = _.map(result, input => { if (input) { - const categoryComboInDatasetElement = _.map(dataSet["dataSetElements"], dataelement => { - if (input && input["dataElementId"] === dataelement["dataElement"]["id"]) { - return dataelement["dataElement"]["categoryCombo"]["id"]; + const categoryComboInDatasetElement = _.map(dataSet?.dataSetElements, dataelement => { + if (input && input["dataElementId"] === dataelement.dataElement.id) { + return dataelement.dataElement.categoryCombo.id; } }); const categoryComboInDataElement = _.compact(categoryComboInDatasetElement); @@ -44,16 +55,13 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi id ); } else { - const categoryOptionComboInCategoryCombo = _.map( - dataSetMetadata["categoryCombos"], - categoryCombo => { - if (categoryComboInDataElement[0] === categoryCombo["id"]) { - return _.map(categoryCombo["categoryOptionCombos"], categoryOptionCombo => { - return categoryOptionCombo["id"] === input["categoryOptionComboId"]; - }); - } + const categoryOptionComboInCategoryCombo = _.map(data.categoryCombos, categoryCombo => { + if (categoryComboInDataElement[0] === categoryCombo.id) { + return _.map(categoryCombo.categoryOptionCombos, categoryOptionCombo => { + return categoryOptionCombo.id === input["categoryOptionComboId"]; + }); } - ); + }); const categoryComboOptionErrors = _.compact(_.compact(categoryOptionComboInCategoryCombo)[0]); if (categoryComboOptionErrors?.length !== 1) { return ( From 22b538759417a84e1e77cafa942fd02d7b067920 Mon Sep 17 00:00:00 2001 From: idelcano Date: Fri, 8 Apr 2022 22:33:17 +0200 Subject: [PATCH 17/24] rename repository --- src/compositionRoot.ts | 8 ++++---- ...faultRepository.ts => DataSetsDefaultRepository.ts} | 9 +++++---- .../repositories/CustomFormErrorsRepository.ts | 3 --- .../repositories/DataSetsRepository.ts | 3 +++ .../usecases/GetCustomFormErrorsUseCase.ts | 10 ---------- .../usecases/GetValidatedDataSetsUseCase.ts | 10 ++++++++++ 6 files changed, 22 insertions(+), 21 deletions(-) rename src/data/{CustomFormErrorsDefaultRepository.ts => DataSetsDefaultRepository.ts} (89%) delete mode 100644 src/domain/validatecustomforms/repositories/CustomFormErrorsRepository.ts create mode 100644 src/domain/validatecustomforms/repositories/DataSetsRepository.ts delete mode 100644 src/domain/validatecustomforms/usecases/GetCustomFormErrorsUseCase.ts create mode 100644 src/domain/validatecustomforms/usecases/GetValidatedDataSetsUseCase.ts diff --git a/src/compositionRoot.ts b/src/compositionRoot.ts index bcddee7e..17705c6a 100644 --- a/src/compositionRoot.ts +++ b/src/compositionRoot.ts @@ -1,6 +1,6 @@ import { Dhis2ConfigRepository } from "./data/Dhis2ConfigRepository"; import { Dhis2OrgUnitsRepository } from "./data/Dhis2OrgUnitsRepository"; -import { CustomFormErrorsDefaultRepository } from "./data/CustomFormErrorsDefaultRepository"; +import { DataSetsDefaultRepository } from "./data/DataSetsDefaultRepository"; import { NHWADataApprovalDefaultRepository } from "./data/NHWADataApprovalDefaultRepository"; import { NHWADataCommentsDefaultRepository } from "./data/NHWADataCommentsDefaultRepository"; import { WIDPAdminDefaultRepository } from "./data/WIDPAdminDefaultRepository"; @@ -16,7 +16,7 @@ import { SaveDataSetsUseCase } from "./domain/nhwa-approval-status/usecases/Save import { GetDataValuesUseCase } from "./domain/nhwa-comments/usecases/GetDataValuesUseCase"; import { SaveDataValuesUseCase } from "./domain/nhwa-comments/usecases/SaveDataValuesCsvUseCase"; import { D2Api } from "./types/d2-api"; -import { GetCustomFormErrorsUseCase } from "./domain/validatecustomforms/usecases/GetCustomFormErrorsUseCase"; +import { GetValidatedDataSetsUseCase } from "./domain/validatecustomforms/usecases/GetValidatedDataSetsUseCase"; export function getCompositionRoot(api: D2Api) { const configRepository = new Dhis2ConfigRepository(api); @@ -24,7 +24,7 @@ export function getCompositionRoot(api: D2Api) { const dataApprovalRepository = new NHWADataApprovalDefaultRepository(api); const widpAdminDefaultRepository = new WIDPAdminDefaultRepository(api); const orgUnitsRepository = new Dhis2OrgUnitsRepository(api); - const customFormErrorsDefaultRepository = new CustomFormErrorsDefaultRepository(api); + const dataSetsRepositoryDefaultRepository = new DataSetsDefaultRepository(api); return { admin: getExecute({ @@ -46,7 +46,7 @@ export function getCompositionRoot(api: D2Api) { get: new GetOrgUnitsUseCase(orgUnitsRepository), }), validateCustomForm: getExecute({ - get: new GetCustomFormErrorsUseCase(customFormErrorsDefaultRepository), + get: new GetValidatedDataSetsUseCase(dataSetsRepositoryDefaultRepository), }), config: getExecute({ get: new GetConfig(configRepository), diff --git a/src/data/CustomFormErrorsDefaultRepository.ts b/src/data/DataSetsDefaultRepository.ts similarity index 89% rename from src/data/CustomFormErrorsDefaultRepository.ts rename to src/data/DataSetsDefaultRepository.ts index 9400b192..3bdcc1ed 100644 --- a/src/data/CustomFormErrorsDefaultRepository.ts +++ b/src/data/DataSetsDefaultRepository.ts @@ -1,12 +1,12 @@ import _ from "lodash"; -import { CustomFormErrorsRepository } from "../domain/validatecustomforms/repositories/CustomFormErrorsRepository"; +import { DataSetsRepository } from "../domain/validatecustomforms/repositories/DataSetsRepository"; import i18n from "../locales"; import { D2Api } from "../types/d2-api"; -export class CustomFormErrorsDefaultRepository implements CustomFormErrorsRepository { +export class DataSetsDefaultRepository implements DataSetsRepository { constructor(private api: D2Api) {} - async get(id: string): Promise { + async validate(id: string): Promise { const metadata$ = this.api.metadata.get({ dataSets: { fields: { @@ -24,7 +24,8 @@ export class CustomFormErrorsDefaultRepository implements CustomFormErrorsReposi const data = await metadata$.getData(); const dataSets = data.dataSets; - const dataSet = _.filter(dataSets, dataset => dataset.id === id)[0]; + //const dataSet = _.filter(dataSets, dataset => dataset.id === id)[0]; + const dataSet = dataSets.find(dataset => dataset.id === id) const htmlCode = dataSet?.dataEntryForm.htmlCode; const newRegExp = new RegExp(/((([a-zA-Z0-9]){11})-(([a-zA-Z0-9]){11})-val)/g); diff --git a/src/domain/validatecustomforms/repositories/CustomFormErrorsRepository.ts b/src/domain/validatecustomforms/repositories/CustomFormErrorsRepository.ts deleted file mode 100644 index 55249667..00000000 --- a/src/domain/validatecustomforms/repositories/CustomFormErrorsRepository.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface CustomFormErrorsRepository { - get(id: string): Promise; -} diff --git a/src/domain/validatecustomforms/repositories/DataSetsRepository.ts b/src/domain/validatecustomforms/repositories/DataSetsRepository.ts new file mode 100644 index 00000000..31a41cef --- /dev/null +++ b/src/domain/validatecustomforms/repositories/DataSetsRepository.ts @@ -0,0 +1,3 @@ +export interface DataSetsRepository { + validate(id: string): Promise; +} diff --git a/src/domain/validatecustomforms/usecases/GetCustomFormErrorsUseCase.ts b/src/domain/validatecustomforms/usecases/GetCustomFormErrorsUseCase.ts deleted file mode 100644 index f935ef8f..00000000 --- a/src/domain/validatecustomforms/usecases/GetCustomFormErrorsUseCase.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { CustomFormErrorsRepository } from "../repositories/CustomFormErrorsRepository"; - -export class GetCustomFormErrorsUseCase { - constructor(private customFormErrorsRepository: CustomFormErrorsRepository) {} - - execute(id: string): Promise { - // FUTURE: Return a Future-like instead, to allow better error handling and cancellation. - return this.customFormErrorsRepository.get(id); - } -} diff --git a/src/domain/validatecustomforms/usecases/GetValidatedDataSetsUseCase.ts b/src/domain/validatecustomforms/usecases/GetValidatedDataSetsUseCase.ts new file mode 100644 index 00000000..1de66d73 --- /dev/null +++ b/src/domain/validatecustomforms/usecases/GetValidatedDataSetsUseCase.ts @@ -0,0 +1,10 @@ +import { DataSetsRepository } from "../repositories/DataSetsRepository"; + +export class GetValidatedDataSetsUseCase { + constructor(private dataSetsRepository: DataSetsRepository) {} + + execute(id: string): Promise { + // FUTURE: Return a Future-like instead, to allow better error handling and cancellation. + return this.dataSetsRepository.validate(id); + } +} From 5ee628c623c92d63a9a34e058b0d7613bdbcb0bd Mon Sep 17 00:00:00 2001 From: idelcano Date: Fri, 8 Apr 2022 22:40:49 +0200 Subject: [PATCH 18/24] prettify --- src/data/DataSetsDefaultRepository.ts | 2 +- .../ValidateCustomFormsReport.tsx | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/data/DataSetsDefaultRepository.ts b/src/data/DataSetsDefaultRepository.ts index 3bdcc1ed..355140aa 100644 --- a/src/data/DataSetsDefaultRepository.ts +++ b/src/data/DataSetsDefaultRepository.ts @@ -25,7 +25,7 @@ export class DataSetsDefaultRepository implements DataSetsRepository { const dataSets = data.dataSets; //const dataSet = _.filter(dataSets, dataset => dataset.id === id)[0]; - const dataSet = dataSets.find(dataset => dataset.id === id) + const dataSet = dataSets.find(dataset => dataset.id === id); const htmlCode = dataSet?.dataEntryForm.htmlCode; const newRegExp = new RegExp(/((([a-zA-Z0-9]){11})-(([a-zA-Z0-9]){11})-val)/g); diff --git a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx index ea02bfc8..828aed20 100644 --- a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx +++ b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx @@ -20,7 +20,11 @@ const ValidateCustomFormsReport: React.FC = () => { if (result.length === 0) { setErrors([{ text: i18n.t("No errors detected") }]); } else { - setErrors(_.map(result, item =>{ return {text: item}} )) + setErrors( + _.map(result, item => { + return { text: item }; + }) + ); } setLoading(false); return value; @@ -51,7 +55,7 @@ const ValidateCustomFormsReport: React.FC = () => {
- +
@@ -74,8 +78,10 @@ const useStyles = makeStyles({ marginLeft: "1%", }, spinner: { - position: 'absolute', left: '50%', top: '50%', - transform: 'translate(-50%, -50%)' + position: "absolute", + left: "50%", + top: "50%", + transform: "translate(-50%, -50%)", }, items: { display: "flex", From b60d18b9fb2f4b0d1747e8fe6ce7c796cbbb2388 Mon Sep 17 00:00:00 2001 From: Arnau Sanchez Date: Wed, 27 Apr 2022 10:29:29 +0200 Subject: [PATCH 19/24] Testing code --- i18n/en.pot | 9 +- i18n/es.po | 7 +- src/data/DataSetsDefaultRepository.ts | 85 ++++++++++--------- .../ValidateCustomFormsReport.tsx | 8 +- 4 files changed, 66 insertions(+), 43 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index 3b95829f..cf561559 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -5,8 +5,13 @@ 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-04-05T19:14:43.245Z\n" -"PO-Revision-Date: 2022-04-05T19:14:43.245Z\n" +"POT-Creation-Date: 2022-04-27T08:03:22.361Z\n" +"PO-Revision-Date: 2022-04-27T08:03:22.361Z\n" + +msgid "" +"ERROR Dataelement with UID: {{dataElementId}} does not exist in dataset " +"with UID: {{dataSetId}}" +msgstr "" msgid "" msgstr "" diff --git a/i18n/es.po b/i18n/es.po index 42ebb45c..12c29a8d 100644 --- a/i18n/es.po +++ b/i18n/es.po @@ -1,13 +1,18 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2022-04-05T19:14:43.245Z\n" +"POT-Creation-Date: 2022-04-27T08:03:22.361Z\n" "PO-Revision-Date: 2018-10-25T09:02:35.143Z\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +msgid "" +"ERROR Dataelement with UID: {{dataElementId}} does not exist in dataset with " +"UID: {{dataSetId}}" +msgstr "" + msgid "" msgstr "" diff --git a/src/data/DataSetsDefaultRepository.ts b/src/data/DataSetsDefaultRepository.ts index 355140aa..dc2f47e8 100644 --- a/src/data/DataSetsDefaultRepository.ts +++ b/src/data/DataSetsDefaultRepository.ts @@ -18,63 +18,72 @@ export class DataSetsDefaultRepository implements DataSetsRepository { }, }, }, - categoryCombos: { fields: { id: true, categoryOptionCombos: { id: true } } }, + dataElements: { + fields: { id: true, categoryCombo: { id: true } }, + }, + categoryCombos: { + fields: { id: true, categoryOptionCombos: { id: true } }, + }, }); - const data = await metadata$.getData(); + const { dataSets, categoryCombos } = await metadata$.getData(); - const dataSets = data.dataSets; + //map/find/filter //const dataSet = _.filter(dataSets, dataset => dataset.id === id)[0]; + //const dataSet = _.find(dataSets, dataset => dataset.id === id); const dataSet = dataSets.find(dataset => dataset.id === id); const htmlCode = dataSet?.dataEntryForm.htmlCode; const newRegExp = new RegExp(/((([a-zA-Z0-9]){11})-(([a-zA-Z0-9]){11})-val)/g); const matches = htmlCode?.match(newRegExp); - const result = _.map(matches, match => { - const groups = newRegExp.exec(match); - if (groups) { - return { dataElementId: groups[2], categoryOptionComboId: groups[4] }; - } - }); - const errors = _.map(result, input => { - if (input) { - const categoryComboInDatasetElement = _.map(dataSet?.dataSetElements, dataelement => { - if (input && input["dataElementId"] === dataelement.dataElement.id) { - return dataelement.dataElement.categoryCombo.id; + const customFormIds = _(matches) + .map(match => { + const groups = newRegExp.exec(match); + return groups ? { dataElementId: groups[2], categoryOptionComboId: groups[4] } : undefined; + }) + .compact() + .value(); + + const categoryCombosById = _.keyBy(categoryCombos, cc => cc.id); + + // const objs: Record + + const errors = _.map(customFormIds, input => { + // const dataElement = dataElementsById[input.dataElementId]; + // const categoryCombo = categoryCombosById[dataElement.categoryCombo.id] + // const isValid = categoryCombo.categoryOptionCombos.includes(input.categoryOptionComboId); + + const categoryComboInDatasetElement = _.map(dataSet?.dataSetElements, dataElement => { + if (input.dataElementId === dataElement.dataElement.id) { + return dataElement.dataElement.categoryCombo.id; + } + }); + const categoryComboInDataElement = _.compact(categoryComboInDatasetElement); + if (categoryComboInDataElement.length === 0) { + return i18n.t( + "ERROR Dataelement with UID '{{dataElementId}}' does not exist in dataset with UID '{{dataSetId}}'", + { dataElementId: input.dataElementId, dataSetId: id, nsSeparator: false } + ); + } else { + const categoryOptionComboInCategoryCombo = _.map(categoryCombos, categoryCombo => { + if (categoryComboInDataElement[0] === categoryCombo.id) { + return _.map(categoryCombo.categoryOptionCombos, categoryOptionCombo => { + return categoryOptionCombo.id === input["categoryOptionComboId"]; + }); } }); - const categoryComboInDataElement = _.compact(categoryComboInDatasetElement); - if (categoryComboInDataElement.length === 0) { + const categoryComboOptionErrors = _.compact(_.compact(categoryOptionComboInCategoryCombo)[0]); + if (categoryComboOptionErrors?.length !== 1) { return ( i18n.t("ERROR Dataelement with UID:") + " " + input["dataElementId"] + " " + - i18n.t("does not exist in dataset with UID:") + + i18n.t("is not associated with CategoryOptionComboID:") + " " + - id + input["categoryOptionComboId"] ); - } else { - const categoryOptionComboInCategoryCombo = _.map(data.categoryCombos, categoryCombo => { - if (categoryComboInDataElement[0] === categoryCombo.id) { - return _.map(categoryCombo.categoryOptionCombos, categoryOptionCombo => { - return categoryOptionCombo.id === input["categoryOptionComboId"]; - }); - } - }); - const categoryComboOptionErrors = _.compact(_.compact(categoryOptionComboInCategoryCombo)[0]); - if (categoryComboOptionErrors?.length !== 1) { - return ( - i18n.t("ERROR Dataelement with UID:") + - " " + - input["dataElementId"] + - " " + - i18n.t("is not associated with CategoryOptionComboID:") + - " " + - input["categoryOptionComboId"] - ); - } } } }); diff --git a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx index 828aed20..558283ce 100644 --- a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx +++ b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx @@ -62,8 +62,12 @@ const ValidateCustomFormsReport: React.FC = () => { {i18n.t("Result:")}
- {_.map(errors, item => { - return
{item.text}
; + {_.map(errors, (item, index) => { + return ( +
+ {item.text} +
+ ); })} ); From 49277b1da14258dfd2ad993ac4b3fb128eaf452b Mon Sep 17 00:00:00 2001 From: idelcano Date: Tue, 3 May 2022 13:46:45 +0200 Subject: [PATCH 20/24] clean code but found regexp bug, wip --- src/data/DataSetsDefaultRepository.ts | 58 +++++++++++---------------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/src/data/DataSetsDefaultRepository.ts b/src/data/DataSetsDefaultRepository.ts index dc2f47e8..0f30b9c7 100644 --- a/src/data/DataSetsDefaultRepository.ts +++ b/src/data/DataSetsDefaultRepository.ts @@ -26,65 +26,55 @@ export class DataSetsDefaultRepository implements DataSetsRepository { }, }); - const { dataSets, categoryCombos } = await metadata$.getData(); + const { dataSets, categoryCombos, dataElements } = await metadata$.getData(); - //map/find/filter - //const dataSet = _.filter(dataSets, dataset => dataset.id === id)[0]; - //const dataSet = _.find(dataSets, dataset => dataset.id === id); const dataSet = dataSets.find(dataset => dataset.id === id); const htmlCode = dataSet?.dataEntryForm.htmlCode; - const newRegExp = new RegExp(/((([a-zA-Z0-9]){11})-(([a-zA-Z0-9]){11})-val)/g); + const newRegExp = new RegExp(/(([a-zA-Z0-9]){11})-(([A-Za-zA-Z0-9]){11})-(val)/g); + const finalRegExp = new RegExp(/^((.){11})-((.){11})-val$/g) const matches = htmlCode?.match(newRegExp); const customFormIds = _(matches) .map(match => { - const groups = newRegExp.exec(match); - return groups ? { dataElementId: groups[2], categoryOptionComboId: groups[4] } : undefined; + const groups = finalRegExp.exec(match); + return groups ? { dataElementId: groups[1] ?? "", categoryOptionComboId: groups[3] ?? "" } : undefined; }) .compact() .value(); const categoryCombosById = _.keyBy(categoryCombos, cc => cc.id); + const dataElementsDataSetById = _.keyBy(dataSet?.dataSetElements, cc => cc.dataElement.id); + const dataElementsById = _.keyBy(dataElements, cc => cc.id); // const objs: Record - const errors = _.map(customFormIds, input => { - // const dataElement = dataElementsById[input.dataElementId]; - // const categoryCombo = categoryCombosById[dataElement.categoryCombo.id] - // const isValid = categoryCombo.categoryOptionCombos.includes(input.categoryOptionComboId); - - const categoryComboInDatasetElement = _.map(dataSet?.dataSetElements, dataElement => { - if (input.dataElementId === dataElement.dataElement.id) { - return dataElement.dataElement.categoryCombo.id; + const errors = _.map(customFormIds, dataElementFromCustomForm => { + const dataElement = dataElementsDataSetById[dataElementFromCustomForm.dataElementId]?.dataElement; + if (dataElement) { + if (dataElement.id === "aEDrisPWh6i"){ + console.log("test"); } - }); - const categoryComboInDataElement = _.compact(categoryComboInDatasetElement); - if (categoryComboInDataElement.length === 0) { - return i18n.t( - "ERROR Dataelement with UID '{{dataElementId}}' does not exist in dataset with UID '{{dataSetId}}'", - { dataElementId: input.dataElementId, dataSetId: id, nsSeparator: false } - ); - } else { - const categoryOptionComboInCategoryCombo = _.map(categoryCombos, categoryCombo => { - if (categoryComboInDataElement[0] === categoryCombo.id) { - return _.map(categoryCombo.categoryOptionCombos, categoryOptionCombo => { - return categoryOptionCombo.id === input["categoryOptionComboId"]; - }); - } - }); - const categoryComboOptionErrors = _.compact(_.compact(categoryOptionComboInCategoryCombo)[0]); - if (categoryComboOptionErrors?.length !== 1) { + const categoryCombo = + dataElement.categoryCombo.id ?? + dataElementsById[dataElementFromCustomForm.dataElementId]?.categoryCombo.id; + const isValid = categoryCombosById[categoryCombo ?? ""]?.categoryOptionCombos.find( coc => coc.id === dataElementFromCustomForm.categoryOptionComboId); + if (!isValid) { return ( i18n.t("ERROR Dataelement with UID:") + " " + - input["dataElementId"] + + dataElementFromCustomForm["dataElementId"] + " " + i18n.t("is not associated with CategoryOptionComboID:") + " " + - input["categoryOptionComboId"] + dataElementFromCustomForm["categoryOptionComboId"] ); } + } else { + return i18n.t( + "ERROR Dataelement with UID '{{dataElementId}}' does not exist in dataset with UID '{{dataSetId}}'", + { dataElementId: dataElementFromCustomForm.dataElementId, dataSetId: id, nsSeparator: false } + ); } }); const newerror = _.compact(errors); From d7b7ef2d1f1a9bd076a703f393675064adbe19e5 Mon Sep 17 00:00:00 2001 From: idelcano Date: Thu, 5 May 2022 21:49:26 +0200 Subject: [PATCH 21/24] change match metod by split --- src/data/DataSetsDefaultRepository.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/data/DataSetsDefaultRepository.ts b/src/data/DataSetsDefaultRepository.ts index 0f30b9c7..0400732b 100644 --- a/src/data/DataSetsDefaultRepository.ts +++ b/src/data/DataSetsDefaultRepository.ts @@ -31,17 +31,17 @@ export class DataSetsDefaultRepository implements DataSetsRepository { const dataSet = dataSets.find(dataset => dataset.id === id); const htmlCode = dataSet?.dataEntryForm.htmlCode; const newRegExp = new RegExp(/(([a-zA-Z0-9]){11})-(([A-Za-zA-Z0-9]){11})-(val)/g); - const finalRegExp = new RegExp(/^((.){11})-((.){11})-val$/g) const matches = htmlCode?.match(newRegExp); - - const customFormIds = _(matches) + const customFormIds =_.compact(matches).map(item =>{ + return {dataElementId: item.split("-")[0] ?? "-", categoryOptionComboId: item.split("-")[1] ?? "-"}}) + /* const customFormIds = _(matches) .map(match => { const groups = finalRegExp.exec(match); return groups ? { dataElementId: groups[1] ?? "", categoryOptionComboId: groups[3] ?? "" } : undefined; }) .compact() - .value(); + .value(); */ const categoryCombosById = _.keyBy(categoryCombos, cc => cc.id); const dataElementsDataSetById = _.keyBy(dataSet?.dataSetElements, cc => cc.dataElement.id); From 775d0dd69b56d6bc4bfe82012be49aa6d7313472 Mon Sep 17 00:00:00 2001 From: idelcano Date: Fri, 6 May 2022 08:15:52 +0200 Subject: [PATCH 22/24] refactor: pretiffy and remove unnecesary code --- i18n/en.pot | 8 +++---- i18n/es.po | 6 +++--- src/data/DataSetsDefaultRepository.ts | 21 ++++++------------- .../ValidateCustomFormsReport.tsx | 9 ++++---- 4 files changed, 17 insertions(+), 27 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index cf561559..2d11f7b9 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -5,12 +5,12 @@ 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-04-27T08:03:22.361Z\n" -"PO-Revision-Date: 2022-04-27T08:03:22.361Z\n" +"POT-Creation-Date: 2022-05-06T05:50:16.003Z\n" +"PO-Revision-Date: 2022-05-06T05:50:16.003Z\n" msgid "" -"ERROR Dataelement with UID: {{dataElementId}} does not exist in dataset " -"with UID: {{dataSetId}}" +"ERROR Dataelement with UID '{{dataElementId}}' does not exist in dataset " +"with UID '{{dataSetId}}'" msgstr "" msgid "" diff --git a/i18n/es.po b/i18n/es.po index 12c29a8d..ef9ff87f 100644 --- a/i18n/es.po +++ b/i18n/es.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: i18next-conv\n" -"POT-Creation-Date: 2022-04-27T08:03:22.361Z\n" +"POT-Creation-Date: 2022-05-06T05:50:16.003Z\n" "PO-Revision-Date: 2018-10-25T09:02:35.143Z\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -9,8 +9,8 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1)\n" msgid "" -"ERROR Dataelement with UID: {{dataElementId}} does not exist in dataset with " -"UID: {{dataSetId}}" +"ERROR Dataelement with UID '{{dataElementId}}' does not exist in dataset " +"with UID '{{dataSetId}}'" msgstr "" msgid "" diff --git a/src/data/DataSetsDefaultRepository.ts b/src/data/DataSetsDefaultRepository.ts index 0400732b..744eb407 100644 --- a/src/data/DataSetsDefaultRepository.ts +++ b/src/data/DataSetsDefaultRepository.ts @@ -33,32 +33,23 @@ export class DataSetsDefaultRepository implements DataSetsRepository { const newRegExp = new RegExp(/(([a-zA-Z0-9]){11})-(([A-Za-zA-Z0-9]){11})-(val)/g); const matches = htmlCode?.match(newRegExp); - const customFormIds =_.compact(matches).map(item =>{ - return {dataElementId: item.split("-")[0] ?? "-", categoryOptionComboId: item.split("-")[1] ?? "-"}}) - /* const customFormIds = _(matches) - .map(match => { - const groups = finalRegExp.exec(match); - return groups ? { dataElementId: groups[1] ?? "", categoryOptionComboId: groups[3] ?? "" } : undefined; - }) - .compact() - .value(); */ + const customFormIds = _(matches).map(item => { + return { dataElementId: item.split("-")[0] ?? "-", categoryOptionComboId: item.split("-")[1] ?? "-" }; + }).commit().value(); const categoryCombosById = _.keyBy(categoryCombos, cc => cc.id); const dataElementsDataSetById = _.keyBy(dataSet?.dataSetElements, cc => cc.dataElement.id); const dataElementsById = _.keyBy(dataElements, cc => cc.id); - // const objs: Record - const errors = _.map(customFormIds, dataElementFromCustomForm => { const dataElement = dataElementsDataSetById[dataElementFromCustomForm.dataElementId]?.dataElement; if (dataElement) { - if (dataElement.id === "aEDrisPWh6i"){ - console.log("test"); - } const categoryCombo = dataElement.categoryCombo.id ?? dataElementsById[dataElementFromCustomForm.dataElementId]?.categoryCombo.id; - const isValid = categoryCombosById[categoryCombo ?? ""]?.categoryOptionCombos.find( coc => coc.id === dataElementFromCustomForm.categoryOptionComboId); + const isValid = categoryCombosById[categoryCombo ?? ""]?.categoryOptionCombos.find( + coc => coc.id === dataElementFromCustomForm.categoryOptionComboId + ); if (!isValid) { return ( i18n.t("ERROR Dataelement with UID:") + diff --git a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx index 558283ce..a6dc65b0 100644 --- a/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx +++ b/src/webapp/reports/validate-custom-forms/ValidateCustomFormsReport.tsx @@ -13,10 +13,9 @@ const ValidateCustomFormsReport: React.FC = () => { const [errors, setErrors] = React.useState>([{ text: "" }]); const { compositionRoot, config } = useAppContext(); - const OnModuleChange = async ({ value }: SelectOption) => { + const validationErrors = async ({ value }: SelectOption) => { setLoading(true); const result = await compositionRoot.validateCustomForm.get(value); - _.remove(errors); if (result.length === 0) { setErrors([{ text: i18n.t("No errors detected") }]); } else { @@ -32,7 +31,7 @@ const ValidateCustomFormsReport: React.FC = () => { const classes = useStyles(); - const [modules] = React.useState<{ value: string; label: string }[]>( + const [dataSets] = React.useState<{ value: string; label: string }[]>( _.values(config.dataSets) .filter(ds => { return ds.name.indexOf("Maturity") === -1; @@ -49,8 +48,8 @@ const ValidateCustomFormsReport: React.FC = () => {
@@ -61,13 +56,11 @@ const ValidateCustomFormsReport: React.FC = () => { {i18n.t("Result:")}
- {_.map(errors, (item, index) => { - return ( -
- {item.text} -
- ); - })} + {_.map(errors, (item, index) => ( +
+ {item.text} +
+ ))} ); }; @@ -106,4 +99,4 @@ const useStyles = makeStyles({ fullWidth: { width: "25%" }, }); -export default ValidateCustomFormsReport; +export default React.memo(ValidateCustomFormsReport);