diff --git a/i18n/en.pot b/i18n/en.pot index 86fa648c..97eccf17 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -7,6 +7,8 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "POT-Creation-Date: 2024-12-05T06:06:51.471Z\n" "PO-Revision-Date: 2024-12-05T06:06:51.471Z\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" 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 ( (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 && ( diff --git a/src/lib/sectionList/listViews/sectionListViewsConfig.ts b/src/lib/sectionList/listViews/sectionListViewsConfig.ts index ca6a2f8e..6c6403b7 100644 --- a/src/lib/sectionList/listViews/sectionListViewsConfig.ts +++ b/src/lib/sectionList/listViews/sectionListViewsConfig.ts @@ -145,6 +145,7 @@ export const modelListViewsConfig = { }, filters: { default: [], + overrideDefaultAvailable: true, }, }, categoryOption: { diff --git a/src/lib/sectionList/useSectionListSortOrder.ts b/src/lib/sectionList/useSectionListSortOrder.ts index 4d9c4427..ea114dfe 100644 --- a/src/lib/sectionList/useSectionListSortOrder.ts +++ b/src/lib/sectionList/useSectionListSortOrder.ts @@ -41,7 +41,7 @@ export const isValidSortPathForSchema = (schema: Schema, path: string) => { 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/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( 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 b3e4954e..2c5ca915 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, @@ -99,6 +100,7 @@ function CategoryOptionGroupFormFields() { /> + ) 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', 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(),