diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7f4..4c6280eb4 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,5 +1,11 @@ + + + + + + diff --git a/packages/app/i18n/en.pot b/packages/app/i18n/en.pot index bebe0fa66..0914271cf 100644 --- a/packages/app/i18n/en.pot +++ b/packages/app/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: 2024-09-12T05:03:56.135Z\n" -"PO-Revision-Date: 2024-09-12T05:03:56.135Z\n" +"POT-Creation-Date: 2024-09-16T09:21:02.849Z\n" +"PO-Revision-Date: 2024-09-16T09:21:02.849Z\n" msgid "Could not determine scorecard's access" msgstr "Could not determine scorecard's access" @@ -71,9 +71,6 @@ msgstr "grid" msgid "Add New Scorecard" msgstr "Add New Scorecard" -msgid "Please select at least one organisation unit" -msgstr "Please select at least one organisation unit" - msgid "Organisation Unit" msgstr "Organisation Unit" @@ -411,6 +408,9 @@ msgstr "A data group must have at least one data item" msgid "A scorecard needs at least one data group" msgstr "A scorecard needs at least one data group" +msgid "You must select at least one organisation unit" +msgstr "You must select at least one organisation unit" + msgid "Preparing migration..." msgstr "Preparing migration..." diff --git a/packages/app/package.json b/packages/app/package.json index 0b826f05b..63ad57d46 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -52,7 +52,7 @@ "@dhis2/multi-calendar-dates": "^1.2.4", "@dhis2/ui": "^9.11.0", "@hisptz/dhis2-analytics": "^2.0.24", - "@hisptz/dhis2-ui": "^2.0.19", + "@hisptz/dhis2-ui": "^2.0.20", "@hisptz/dhis2-utils": "^2.0.5", "@hookform/resolvers": "^3.9.0", "@iapps/function-analytics": "^1.0.0-beta.23", diff --git a/packages/app/src/locales/en/translations.json b/packages/app/src/locales/en/translations.json index ae2061de8..731858831 100644 --- a/packages/app/src/locales/en/translations.json +++ b/packages/app/src/locales/en/translations.json @@ -20,7 +20,6 @@ "list": "list", "grid": "grid", "Add New Scorecard": "Add New Scorecard", - "Please select at least one organisation unit": "Please select at least one organisation unit", "Organisation Unit": "Organisation Unit", "Select Access": "Select Access", "Add": "Add", @@ -126,6 +125,7 @@ "A scorecard with the title '{{value}}' already exists. Please select another title": "A scorecard with the title '{{value}}' already exists. Please select another title", "A data group must have at least one data item": "A data group must have at least one data item", "A scorecard needs at least one data group": "A scorecard needs at least one data group", + "You must select at least one organisation unit": "You must select at least one organisation unit", "Preparing migration...": "Preparing migration...", "Migrating scorecards": "Migrating scorecards", "of": "of", diff --git a/packages/app/src/modules/ScorecardManagement/components/Access/Components/OrgUnitFilter/index.tsx b/packages/app/src/modules/ScorecardManagement/components/Access/Components/OrgUnitFilter/index.tsx deleted file mode 100644 index e7d0c4e96..000000000 --- a/packages/app/src/modules/ScorecardManagement/components/Access/Components/OrgUnitFilter/index.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import i18n from "@dhis2/d2-i18n"; -import { colors, IconError24 } from "@dhis2/ui"; -import { OrgUnitSelector } from "@hisptz/dhis2-ui"; -import { ContainerLoader, OrgUnitSelection } from "@scorecard/shared"; -import { get } from "lodash"; -import React, { Suspense, useCallback } from "react"; -import { useFormContext } from "react-hook-form"; - -function anyOrgUnitSelected({ - groups, - levels, - orgUnits, - userOrgUnit, - userSubUnit, - userSubX2Unit, -}: any) { - return ( - userSubX2Unit || - userSubUnit || - userOrgUnit || - groups.length > 0 || - levels.length > 0 || - orgUnits.length > 0 - ); -} - -export default function OrgUnit() { - const { setValue, watch, register, formState } = useFormContext(); - register("orgUnitSelection", { - validate: { - atLeastOneOrgUnit: (value) => { - if (anyOrgUnitSelected(value)) { - return true; - } - return i18n.t("Please select at least one organisation unit"); - }, - }, - }); - const organisationUnit = watch("orgUnitSelection"); - - const setOrganisationUnit = useCallback( - (updatedOrgUnitSelection: any) => { - setValue("orgUnitSelection", updatedOrgUnitSelection); - }, - [setValue], - ); - - const onSetOrgUnit = (values: any) => { - setOrganisationUnit( - OrgUnitSelection.setObject(organisationUnit, values), - ); - }; - - const error: any = get(formState.errors, "orgUnitSelection"); - - return ( -
-
-

{i18n.t("Organisation Unit")}

-
- {error && ( -
- - {error?.message} -
- )} -
- }> - - -
-
- ); -} diff --git a/packages/app/src/modules/ScorecardManagement/components/Access/components/OrgUnitFilter/index.tsx b/packages/app/src/modules/ScorecardManagement/components/Access/components/OrgUnitFilter/index.tsx new file mode 100644 index 000000000..28d6f8c89 --- /dev/null +++ b/packages/app/src/modules/ScorecardManagement/components/Access/components/OrgUnitFilter/index.tsx @@ -0,0 +1,50 @@ +import i18n from "@dhis2/d2-i18n"; +import { colors, IconError24 } from "@dhis2/ui"; +import { OrgUnitSelector } from "@hisptz/dhis2-ui"; +import { ContainerLoader } from "@scorecard/shared"; +import React, { Suspense } from "react"; +import { useController } from "react-hook-form"; +import { ScorecardConfig } from "@hisptz/dhis2-analytics"; + + +export default function OrgUnit() { + const { field, fieldState } = useController({ + name: "orgUnitSelection" + }); + + return ( +
+
+

{i18n.t("Organisation Unit")}

+
+ {fieldState.error && ( +
+ + {fieldState.error?.message} +
+ )} +
+ }> + + +
+
+ ); +} diff --git a/packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/Components/SharingList/Components/AddSharingAccess.tsx b/packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/components/SharingList/components/AddSharingAccess.tsx similarity index 100% rename from packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/Components/SharingList/Components/AddSharingAccess.tsx rename to packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/components/SharingList/components/AddSharingAccess.tsx diff --git a/packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/Components/SharingList/Components/SharingMenu.tsx b/packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/components/SharingList/components/SharingMenu.tsx similarity index 100% rename from packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/Components/SharingList/Components/SharingMenu.tsx rename to packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/components/SharingList/components/SharingMenu.tsx diff --git a/packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/Components/SharingList/Components/SingleSharingComponent.tsx b/packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/components/SharingList/components/SingleSharingComponent.tsx similarity index 100% rename from packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/Components/SharingList/Components/SingleSharingComponent.tsx rename to packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/components/SharingList/components/SingleSharingComponent.tsx diff --git a/packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/Components/SharingList/index.tsx b/packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/components/SharingList/index.tsx similarity index 92% rename from packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/Components/SharingList/index.tsx rename to packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/components/SharingList/index.tsx index 7d4f2daf1..22c6dfd3b 100644 --- a/packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/Components/SharingList/index.tsx +++ b/packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/components/SharingList/index.tsx @@ -1,7 +1,7 @@ import { Menu, MenuDivider } from "@dhis2/ui"; import React, { Fragment } from "react"; import useAccessManage from "../../../../hooks/useAccessManage"; -import SingleSharingComponent from "./Components/SingleSharingComponent"; +import SingleSharingComponent from "./components/SingleSharingComponent"; export default function SharingList() { const { diff --git a/packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/Components/UserAndUserGroupSelector/hooks/useSearch.ts b/packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/components/UserAndUserGroupSelector/hooks/useSearch.ts similarity index 100% rename from packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/Components/UserAndUserGroupSelector/hooks/useSearch.ts rename to packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/components/UserAndUserGroupSelector/hooks/useSearch.ts diff --git a/packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/Components/UserAndUserGroupSelector/index.tsx b/packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/components/UserAndUserGroupSelector/index.tsx similarity index 100% rename from packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/Components/UserAndUserGroupSelector/index.tsx rename to packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/components/UserAndUserGroupSelector/index.tsx diff --git a/packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/index.tsx b/packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/index.tsx similarity index 81% rename from packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/index.tsx rename to packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/index.tsx index e6f3df0d0..e660af3cd 100644 --- a/packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/index.tsx +++ b/packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/index.tsx @@ -1,7 +1,8 @@ import i18n from "@dhis2/d2-i18n"; import React from "react"; -import SharingList from "./Components/SharingList"; -import AddSharingAccess from "./Components/SharingList/Components/AddSharingAccess"; +import SharingList from "./components/SharingList"; +import AddSharingAccess from "./components/SharingList/components/AddSharingAccess"; + export default function Sharing() { return ( diff --git a/packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/utils.tsx b/packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/utils.tsx similarity index 100% rename from packages/app/src/modules/ScorecardManagement/components/Access/Components/Sharing/utils.tsx rename to packages/app/src/modules/ScorecardManagement/components/Access/components/Sharing/utils.tsx diff --git a/packages/app/src/modules/ScorecardManagement/components/Access/index.tsx b/packages/app/src/modules/ScorecardManagement/components/Access/index.tsx index 0fd03f5a0..5ebd5b075 100644 --- a/packages/app/src/modules/ScorecardManagement/components/Access/index.tsx +++ b/packages/app/src/modules/ScorecardManagement/components/Access/index.tsx @@ -1,12 +1,12 @@ import { ACCESS_HELP_STEPS, Help } from "@scorecard/shared"; import React from "react"; -import OrgUnit from "./Components/OrgUnitFilter"; -import Sharing from "./Components/Sharing"; +import OrgUnit from "./components/OrgUnitFilter"; +import Sharing from "./components/Sharing"; export default function AccessScorecardForm() { return (
diff --git a/packages/app/src/modules/ScorecardManagement/components/DataConfiguration/components/DataSourceConfigurationForm/index.tsx b/packages/app/src/modules/ScorecardManagement/components/DataConfiguration/components/DataSourceConfigurationForm/index.tsx index 8a988e199..20595f377 100644 --- a/packages/app/src/modules/ScorecardManagement/components/DataConfiguration/components/DataSourceConfigurationForm/index.tsx +++ b/packages/app/src/modules/ScorecardManagement/components/DataConfiguration/components/DataSourceConfigurationForm/index.tsx @@ -28,6 +28,7 @@ export default function DataSourceConfigurationForm({ path }: { path: string }) /> diff --git a/packages/app/src/modules/ScorecardManagement/components/HighlightedIndicators/Table/index.tsx b/packages/app/src/modules/ScorecardManagement/components/HighlightedIndicators/Table/index.tsx index ecb832bf3..8b48f1bb6 100644 --- a/packages/app/src/modules/ScorecardManagement/components/HighlightedIndicators/Table/index.tsx +++ b/packages/app/src/modules/ScorecardManagement/components/HighlightedIndicators/Table/index.tsx @@ -1,10 +1,9 @@ import i18n from "@dhis2/d2-i18n"; -import { Button, ButtonStrip, IconEdit16, Table, TableBody, TableCell, TableCellHead, TableHead, TableRow, TableRowHead } from "@dhis2/ui"; +import { Button, ButtonStrip, colors, IconEdit16, IconError16, Table, TableBody, TableCell, TableCellHead, TableHead, TableRow, TableRowHead, Tooltip } from "@dhis2/ui"; import { Help, HIGHLIGHTED_TABLE_HELP_STEPS } from "@scorecard/shared"; import { IconDelete16 } from "@dhis2/ui-icons"; -import { get, isEmpty } from "lodash"; -import React, { Fragment } from "react"; -import { useController } from "react-hook-form"; +import { capitalize, get, isEmpty } from "lodash"; +import { FieldError, useController } from "react-hook-form"; import { ScorecardConfig } from "@hisptz/dhis2-analytics"; import { useBoolean } from "usehooks-ts"; import HighlightedDataSourceConfigurationForm from "../HighlightedDataSourceConfigurationForm"; @@ -30,15 +29,21 @@ function HighlightedTableRow({ index, onRemove }: { index: number; onRemove: (in name: `highlightedIndicators.${index}` }); + const errorObject = fieldState.error as unknown as Record ?? {}; + + const errorMessage = Object.keys(errorObject).map((key: string) => `${capitalize(key)}: ${errorObject[key]?.message as string}`); return ( - {columns?.map(({ path }) => ( + {columns?.map(({ path }, index) => ( - {get(field.value, path)} +
+ {index === 0 && fieldState.error ? : null} + {get(field.value, path)} +
))} diff --git a/packages/app/src/modules/ScorecardManagement/hooks/schema.ts b/packages/app/src/modules/ScorecardManagement/hooks/schema.ts index c2d0adfa1..158b9519f 100644 --- a/packages/app/src/modules/ScorecardManagement/hooks/schema.ts +++ b/packages/app/src/modules/ScorecardManagement/hooks/schema.ts @@ -4,7 +4,26 @@ import i18n from "@dhis2/d2-i18n"; import { titleDoesNotExist } from "../components/General/utils/utils"; import { useParams } from "react-router-dom"; import { useDataEngine } from "@dhis2/app-runtime"; -import { dataGroupSchema, dataHolderSchema } from "@hisptz/dhis2-analytics"; +import { dataGroupSchema, dataHolderSchema, organisationUnitSelectionSchema } from "@hisptz/dhis2-analytics"; + + +function anyOrgUnitSelected({ + groups, + levels, + orgUnits, + userOrgUnit, + userSubUnit, + userSubX2Unit + }: any) { + return ( + userSubX2Unit || + userSubUnit || + userOrgUnit || + groups.length > 0 || + levels.length > 0 || + orgUnits.length > 0 + ); +} export function useFormSchema() { @@ -23,6 +42,11 @@ export function useFormSchema() { dataHolders: z.array(dataHolderSchema).min(1, i18n.t("A data group must have at least one data item")) })).min(1, i18n.t("A scorecard needs at least one data group")) }), + orgUnitSelection: organisationUnitSelectionSchema.refine((value) => { + return anyOrgUnitSelected(value); + }, { + message: i18n.t("You must select at least one organisation unit") + }), additionalLabels: z.array(z.string()).optional(), subtitle: z.string().optional(), customHeader: z.string().optional(), diff --git a/yarn.lock b/yarn.lock index d15391ee9..538082d7b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2963,7 +2963,7 @@ zod "^3.23.8" "@hisptz/dhis2-analytics@file:../dhis2-utils-v2/packages/analytics": - version "2.0.24" + version "2.0.25" dependencies: "@dnd-kit/core" "^6.1.0" "@dnd-kit/utilities" "^3.2.2" @@ -2989,10 +2989,12 @@ screenfull "^6.0.2" zod "^3.23.8" -"@hisptz/dhis2-ui@2.0.19", "@hisptz/dhis2-ui@file:../dhis2-utils-v2/packages/ui": +"@hisptz/dhis2-ui@2.0.19": version "2.0.19" + resolved "https://registry.yarnpkg.com/@hisptz/dhis2-ui/-/dhis2-ui-2.0.19.tgz#48723c73330b88029ccb151811c69de2a297b060" + integrity sha512-fbyLshZrK4I2HQjPxANT+TriCthbhtNV4LpUTrXzSA38njcKH8PV50JKLDUqHQJyGgkhvsLqV7E9BKaV4feMiQ== dependencies: - "@hisptz/dhis2-utils" "workspace:*" + "@hisptz/dhis2-utils" "2.0.7" classnames "^2.5.1" dexie "^3.2.3" jodit-react "^1.3.39" @@ -3006,10 +3008,10 @@ styled-components "^6.1.8" usehooks-ts "^2.9.2" -"@hisptz/dhis2-ui@^2.0.19": - version "2.0.19" - resolved "https://registry.yarnpkg.com/@hisptz/dhis2-ui/-/dhis2-ui-2.0.19.tgz#48723c73330b88029ccb151811c69de2a297b060" - integrity sha512-fbyLshZrK4I2HQjPxANT+TriCthbhtNV4LpUTrXzSA38njcKH8PV50JKLDUqHQJyGgkhvsLqV7E9BKaV4feMiQ== +"@hisptz/dhis2-ui@^2.0.20": + version "2.0.20" + resolved "https://registry.yarnpkg.com/@hisptz/dhis2-ui/-/dhis2-ui-2.0.20.tgz#8de46a996da429d1231f457df8da1f253bcd2911" + integrity sha512-oIleodTExiSKjs6LyByoIgYDwtPGpLrNAi6oGNnfS7vhkF+TPMxPznHWaH4nnwegs4/u+4oyAaJPp3qW/jBqwA== dependencies: "@hisptz/dhis2-utils" "2.0.7" classnames "^2.5.1" @@ -3025,6 +3027,23 @@ styled-components "^6.1.8" usehooks-ts "^2.9.2" +"@hisptz/dhis2-ui@file:../dhis2-utils-v2/packages/ui": + version "2.0.20" + dependencies: + "@hisptz/dhis2-utils" "workspace:*" + classnames "^2.5.1" + dexie "^3.2.3" + jodit-react "^1.3.39" + lodash "^4.17.21" + luxon "^3.4.4" + react-circular-progressbar "^2.1.0" + react-collapsible "^2.10.0" + react-color "^2.19.3" + react-hook-form "^7.53.0" + recoil "^0.7.7" + styled-components "^6.1.8" + usehooks-ts "^2.9.2" + "@hisptz/dhis2-ui@workspace:*": version "2.0.14" resolved "https://registry.yarnpkg.com/@hisptz/dhis2-ui/-/dhis2-ui-2.0.14.tgz#acf1f0af8383c0d3a6fdfa555a97d23dc6e17cb3"