From a1a611021f8e9db17bf87c3e28a32ccc1dcbf691 Mon Sep 17 00:00:00 2001 From: Birk Johansson Date: Thu, 5 Dec 2024 14:43:11 +0100 Subject: [PATCH 1/5] fix(categoryCombo): validation and load optionSize on initial load [skip release] (#457) * fix: fieldrule - disable dimensiontype when editing * fix: load categoryOptionSize initially --- src/pages/categoryCombos/Edit.tsx | 2 +- src/pages/categoryCombos/form/CategoryComboFormFields.tsx | 5 ++++- src/pages/categoryCombos/form/categoryComboSchema.ts | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pages/categoryCombos/Edit.tsx b/src/pages/categoryCombos/Edit.tsx index c9015ee4..bee35c79 100644 --- a/src/pages/categoryCombos/Edit.tsx +++ b/src/pages/categoryCombos/Edit.tsx @@ -11,7 +11,7 @@ const fieldFilters = [ ...DEFAULT_FIELD_FILTERS, 'name', 'code', - 'categories[id,displayName]', + 'categories[id,displayName,categoryOptions~size~rename(categoryOptionsSize)],', 'skipTotal', 'dataDimensionType', ] as const diff --git a/src/pages/categoryCombos/form/CategoryComboFormFields.tsx b/src/pages/categoryCombos/form/CategoryComboFormFields.tsx index 6b28b6f7..298f3f7a 100644 --- a/src/pages/categoryCombos/form/CategoryComboFormFields.tsx +++ b/src/pages/categoryCombos/form/CategoryComboFormFields.tsx @@ -2,13 +2,13 @@ import i18n from '@dhis2/d2-i18n' import { CheckboxFieldFF, RadioFieldFF } from '@dhis2/ui' import React from 'react' import { Field } from 'react-final-form' +import { useParams } from 'react-router-dom' import { StandardFormField, StandardFormSection, StandardFormSectionTitle, StandardFormSectionDescription, HorizontalFieldGroup, - ModelTransferField, NameField, CodeField, } from '../../../components' @@ -18,6 +18,7 @@ import { CategoriesField } from './CategoriesField' const section = SECTIONS_MAP.categoryCombo export const CategoryComboFormFields = () => { + const isNewForm = useParams().id === undefined return ( <> @@ -55,6 +56,7 @@ export const CategoryComboFormFields = () => { label={i18n.t('Disaggregation')} type="radio" value={'DISAGGREGATION'} + disabled={!isNewForm} /> name="dataDimensionType" @@ -62,6 +64,7 @@ export const CategoryComboFormFields = () => { label={i18n.t('Attribute')} type="radio" value={'ATTRIBUTE'} + disabled={!isNewForm} /> diff --git a/src/pages/categoryCombos/form/categoryComboSchema.ts b/src/pages/categoryCombos/form/categoryComboSchema.ts index aebfd8e4..1f063591 100644 --- a/src/pages/categoryCombos/form/categoryComboSchema.ts +++ b/src/pages/categoryCombos/form/categoryComboSchema.ts @@ -23,6 +23,7 @@ export const categoryComboSchema = identifiable categoryOptionsSize: z.number(), }) ) + .min(1, i18n.t('At least one category is required')) .refine( (categories) => { const generatedCocsCount = categories.reduce( From bb3baee8c14ac44554e75d48abd0d80113d8e8cf Mon Sep 17 00:00:00 2001 From: Birk Johansson Date: Thu, 5 Dec 2024 14:45:36 +0100 Subject: [PATCH 2/5] fix(categoryOption): load formName [skip release] (#458) --- src/pages/categoryOptions/Edit.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/categoryOptions/Edit.tsx b/src/pages/categoryOptions/Edit.tsx index 36ed1385..957a6e41 100644 --- a/src/pages/categoryOptions/Edit.tsx +++ b/src/pages/categoryOptions/Edit.tsx @@ -16,6 +16,7 @@ const fieldFilters = [ ...DEFAULT_FIELD_FILTERS, ...ATTRIBUTE_VALUES_FIELD_FILTERS, 'name', + 'formName', 'code', 'shortName', 'description', From 5c853bc995886b1d6ee97be447f87ba3c0df76dd Mon Sep 17 00:00:00 2001 From: Birk Johansson Date: Thu, 5 Dec 2024 14:45:55 +0100 Subject: [PATCH 3/5] fix(categoryOptionGroups): add custom attributesection to group/groupset [skip release] (#459) --- .../form/CategoryOptionGroupSetFormFields.tsx | 2 ++ .../categoryOptionGroups/form/CategoryOptionGroupFormFields.tsx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/pages/categoryOptionGroupSets/form/CategoryOptionGroupSetFormFields.tsx b/src/pages/categoryOptionGroupSets/form/CategoryOptionGroupSetFormFields.tsx index 4880425c..a1b6b704 100644 --- a/src/pages/categoryOptionGroupSets/form/CategoryOptionGroupSetFormFields.tsx +++ b/src/pages/categoryOptionGroupSets/form/CategoryOptionGroupSetFormFields.tsx @@ -3,6 +3,7 @@ import { RadioFieldFF, CheckboxFieldFF } from '@dhis2/ui' import React from 'react' import { Field } from 'react-final-form' import { + CustomAttributesSection, DefaultIdentifiableFields, DescriptionField, HorizontalFieldGroup, @@ -112,6 +113,7 @@ function CategoryOptionGroupSetFormFields() { + ) } diff --git a/src/pages/categoryOptionGroups/form/CategoryOptionGroupFormFields.tsx b/src/pages/categoryOptionGroups/form/CategoryOptionGroupFormFields.tsx index e6ecab4a..abcf48f8 100644 --- a/src/pages/categoryOptionGroups/form/CategoryOptionGroupFormFields.tsx +++ b/src/pages/categoryOptionGroups/form/CategoryOptionGroupFormFields.tsx @@ -3,6 +3,7 @@ import { RadioFieldFF, CheckboxFieldFF } from '@dhis2/ui' import React from 'react' import { Field } from 'react-final-form' import { + CustomAttributesSection, DefaultIdentifiableFields, DescriptionField, HorizontalFieldGroup, @@ -110,6 +111,7 @@ function CategoryOptionGroupFormFields() { /> + ) From 8537bceb284d098500eed2497292c9ab033ebff0 Mon Sep 17 00:00:00 2001 From: Flaminia Date: Thu, 5 Dec 2024 15:36:23 +0100 Subject: [PATCH 4/5] fix: date field to format date before displaying, org unit filters (#456) * fix: datefield to format date before displaying, org unit filters * fix: allow soring of non persisted properties * fix: change description max limit * fix: remove filters in manage view for org units * fix: change org unit paths * fix: zod and format to handle responsibility of changing date format --- i18n/en.pot | 69 +++++++++++++++++-- src/components/form/fields/DateField.tsx | 11 +-- .../form/fields/DescriptionField.tsx | 7 +- .../listViews/sectionListViewsConfig.ts | 1 + .../sectionList/useSectionListSortOrder.ts | 2 +- src/pages/categories/form/categorySchema.ts | 2 +- src/pages/organisationUnits/Edit.tsx | 6 +- .../form/OrganisationUnitSelector.tsx | 5 +- .../form/organisationUnitSchema.ts | 18 ++--- 9 files changed, 90 insertions(+), 31 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index ca3938f5..1f209e0b 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -5,10 +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-11-27T08:30:38.416Z\n" -"PO-Revision-Date: 2024-11-27T08:30:38.417Z\n" -"POT-Creation-Date: 2024-11-26T14:06:00.934Z\n" -"PO-Revision-Date: 2024-11-26T14:06:00.934Z\n" +"POT-Creation-Date: 2024-12-03T07:31:45.454Z\n" +"PO-Revision-Date: 2024-12-03T07:31:45.455Z\n" msgid "schemas" msgstr "schemas" @@ -425,6 +423,15 @@ msgstr "Translation updated successfully" msgid "Save translations" msgstr "Save translations" +msgid "Go back" +msgstr "Go back" + +msgid "Next section" +msgstr "Next section" + +msgid "Save and exit" +msgstr "Save and exit" + msgid "Can edit and capture" msgstr "Can edit and capture" @@ -1215,6 +1222,60 @@ msgstr "" "included. PHU will still be available for the PHU level, but not included " "in the aggregations to the levels above." +msgid "Set up the basic information for this data set." +msgstr "Set up the basic information for this data set." + +msgid "Configure data elements" +msgstr "Configure data elements" + +msgid "Choose what data is collected for this data set." +msgstr "Choose what data is collected for this data set." + +msgid "Configure data entry periods" +msgstr "Configure data entry periods" + +msgid "Choose for what time periods data can be entered for this data set" +msgstr "Choose for what time periods data can be entered for this data set" + +msgid "Validation and limitations" +msgstr "Validation and limitations" + +msgid "Configure how data can and must be entered for this data" +msgstr "Configure how data can and must be entered for this data" + +msgid "Configure which organisation units can collect data for this data set." +msgstr "Configure which organisation units can collect data for this data set." + +msgid "Data entry form" +msgstr "Data entry form" + +msgid "Advanced options" +msgstr "Advanced options" + +msgid "These options are used for advanced data set configurations." +msgstr "These options are used for advanced data set configurations." + +msgid "Setup" +msgstr "Setup" + +msgid "Data" +msgstr "Data" + +msgid "Data Elements" +msgstr "Data Elements" + +msgid "Periods" +msgstr "Periods" + +msgid "Organisation Units" +msgstr "Organisation Units" + +msgid "Form" +msgstr "Form" + +msgid "Advanced" +msgstr "Advanced" + msgid "Set up the basic information for this Indicator Type." msgstr "Set up the basic information for this Indicator Type." diff --git a/src/components/form/fields/DateField.tsx b/src/components/form/fields/DateField.tsx index 6555a137..42e92915 100644 --- a/src/components/form/fields/DateField.tsx +++ b/src/components/form/fields/DateField.tsx @@ -1,6 +1,6 @@ import i18n from '@dhis2/d2-i18n' import { CalendarInput, CalendarInputProps } from '@dhis2/ui' -import React, { useState } from 'react' +import React, { useEffect, useState } from 'react' import { useField } from 'react-final-form' import { selectedLocale, useSystemSetting } from '../../../lib' @@ -16,7 +16,7 @@ type DateFieldProps = Omit< type ValidationProps = { error: boolean validationText?: string - valid?: boolean + valid: boolean validationCode?: string } export function DateField({ @@ -29,9 +29,12 @@ export function DateField({ const locale = selectedLocale const [validation, setValidation] = useState({ error: false, + valid: true, }) - const { input, meta } = useField(name) + const { input } = useField(name, { + format: (value) => (value ? value.substring(0, 10) : ''), + }) const handleChange: CalendarInputProps['onDateSelect'] = ( payload: { @@ -47,7 +50,7 @@ export function DateField({ validationText: i18n.t('Required'), }) } else { - setValidation(payload?.validation || { error: false }) + setValidation(payload?.validation || { error: false, valid: true }) } input.onChange(payload?.calendarDateString || '') input.onBlur() diff --git a/src/components/form/fields/DescriptionField.tsx b/src/components/form/fields/DescriptionField.tsx index 629ad075..40c695f5 100644 --- a/src/components/form/fields/DescriptionField.tsx +++ b/src/components/form/fields/DescriptionField.tsx @@ -1,5 +1,5 @@ import i18n from '@dhis2/d2-i18n' -import { TextAreaFieldFF } from '@dhis2/ui' +import { createMaxCharacterLength, TextAreaFieldFF } from '@dhis2/ui' import React from 'react' import { Field as FieldRFF } from 'react-final-form' import { SchemaSection, useCheckMaxLengthFromSchema } from '../../../lib' @@ -11,10 +11,7 @@ export function DescriptionField({ helpText?: string schemaSection: SchemaSection }) { - const validate = useCheckMaxLengthFromSchema( - schemaSection.name, - 'description' - ) + const validate = createMaxCharacterLength(2000) return ( { const schemaProperty = getSchemaPropertyForPath(schema, path) // sorting for metadata-API only works on simple and persisted properties - if (schemaProperty && schemaProperty.simple && schemaProperty.persisted) { + if (schemaProperty && schemaProperty.simple) { return true } return false diff --git a/src/pages/categories/form/categorySchema.ts b/src/pages/categories/form/categorySchema.ts index 36a12a83..122cee3f 100644 --- a/src/pages/categories/form/categorySchema.ts +++ b/src/pages/categories/form/categorySchema.ts @@ -2,7 +2,7 @@ import { z } from 'zod' import { getDefaults, createFormValidate, modelFormSchemas } from '../../../lib' import { Category } from '../../../types/generated' -/* Note that this describes what we send to the server, +/* Note that this describes what we send to the server, and not what is stored in the form. */ const { identifiable, referenceCollection, withAttributeValues } = modelFormSchemas diff --git a/src/pages/organisationUnits/Edit.tsx b/src/pages/organisationUnits/Edit.tsx index 638ff5d0..018e87b5 100644 --- a/src/pages/organisationUnits/Edit.tsx +++ b/src/pages/organisationUnits/Edit.tsx @@ -10,7 +10,11 @@ import { } from '../../lib' import { useBoundResourceQueryFn } from '../../lib/query/useBoundQueryFn' import { OrganisationUnit, PickWithFieldFilters } from '../../types/generated' -import { OrganisationUnitFormField, validate } from './form' +import { + OrganisationUnitFormField, + organisationUnitSchema, + validate, +} from './form' const fieldFilters = [ ...DEFAULT_FIELD_FILTERS, diff --git a/src/pages/organisationUnits/form/OrganisationUnitSelector.tsx b/src/pages/organisationUnits/form/OrganisationUnitSelector.tsx index 2250e2e5..b66a7449 100644 --- a/src/pages/organisationUnits/form/OrganisationUnitSelector.tsx +++ b/src/pages/organisationUnits/form/OrganisationUnitSelector.tsx @@ -10,7 +10,8 @@ export function OrganisationUnitSelector() { const fieldName = 'parent' const { input, meta } = useField(fieldName, { format: (value) => value }) const userRootOrgUnits = useCurrentUserRootOrgUnits() - const userRootOrgUnitsIds = userRootOrgUnits.map((unit) => `/${unit.id}`) + const userRootOrgUnitsIds = userRootOrgUnits.map((unit) => unit.id) + const userRootOrgUnitsPaths = userRootOrgUnits.map((unit) => unit.path) const [selected, setSelected] = useState<[string] | []>( input.value?.path ? [input.value.path] : [] ) @@ -44,7 +45,7 @@ export function OrganisationUnitSelector() { roots={userRootOrgUnitsIds} selected={selected} initiallyExpanded={[ - ...userRootOrgUnitsIds, + ...userRootOrgUnitsPaths, ...selected, ]} /> diff --git a/src/pages/organisationUnits/form/organisationUnitSchema.ts b/src/pages/organisationUnits/form/organisationUnitSchema.ts index 8dcd4e2b..330e1cf4 100644 --- a/src/pages/organisationUnits/form/organisationUnitSchema.ts +++ b/src/pages/organisationUnits/form/organisationUnitSchema.ts @@ -10,15 +10,7 @@ export const organisationUnitSchema = identifiable .extend({ shortName: z.string().trim().default(''), code: z.string().trim().optional(), - description: z - .string() - .trim() - .max(2147483647, { - message: i18n.t('Should not exceed {{maxLength}} characters', { - maxLength: 2147483647, - }), - }) - .optional(), + description: z.string().trim().optional(), image: z.object({ id: z.string() }).optional(), phoneNumber: z .string() @@ -33,7 +25,7 @@ export const organisationUnitSchema = identifiable }), }) .optional(), - openingDate: z.string().date(), + openingDate: z.coerce.date(), email: z.string().email().optional(), address: z .string() @@ -47,12 +39,12 @@ export const organisationUnitSchema = identifiable .string() .url({ message: i18n.t('Must be a valid url') }) .optional(), - closedDate: z.string().date().optional(), + closedDate: z.coerce.date().optional(), comment: z .string() - .max(2147483647, { + .max(2000, { message: i18n.t('Should not exceed {{maxLength}} characters', { - maxLength: 2147483647, + maxLength: 2000, }), }) .optional(), From c10d79ffba8383e9559906f98bb858e6113bba83 Mon Sep 17 00:00:00 2001 From: Chisom Chima <87203527+Chisomchima@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:38:56 +0100 Subject: [PATCH 5/5] fix: refresh list view on close of dialog (#461) --- src/components/sectionList/SectionListWrapper.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/sectionList/SectionListWrapper.tsx b/src/components/sectionList/SectionListWrapper.tsx index e5bd8f08..cbb937b5 100644 --- a/src/components/sectionList/SectionListWrapper.tsx +++ b/src/components/sectionList/SectionListWrapper.tsx @@ -44,6 +44,11 @@ export const SectionListWrapper = ({ BaseListModel | undefined >(undefined) + const onSharingDialogClose = () => { + setSharingDialogId(undefined) + refetch() + } + const SectionListMessage = () => { if (error) { console.log(error.details || error) @@ -159,7 +164,7 @@ export const SectionListWrapper = ({ but it works if you pass the correct type*/ // eslint-disable-next-line @typescript-eslint/no-explicit-any type={schema.singular as any} - onClose={() => setSharingDialogId(undefined)} + onClose={() => onSharingDialogClose()} /> )} {translationDialogModel && (