diff --git a/src/pages/organisationUnits/Edit.tsx b/src/pages/organisationUnits/Edit.tsx index 81b22b2b..638ff5d0 100644 --- a/src/pages/organisationUnits/Edit.tsx +++ b/src/pages/organisationUnits/Edit.tsx @@ -7,11 +7,10 @@ import { DEFAULT_FIELD_FILTERS, SECTIONS_MAP, useOnSubmitEdit, - validate, } from '../../lib' import { useBoundResourceQueryFn } from '../../lib/query/useBoundQueryFn' import { OrganisationUnit, PickWithFieldFilters } from '../../types/generated' -import { OrganisationUnitFormField, organisationUnitSchema } from './form' +import { OrganisationUnitFormField, validate } from './form' const fieldFilters = [ ...DEFAULT_FIELD_FILTERS, @@ -68,9 +67,7 @@ export const Component = () => { })} section={section} initialValues={orgUnit.data} - validate={(values: OrgUnitFormValues) => { - return validate(organisationUnitSchema, values) - }} + validate={validate} > diff --git a/src/pages/organisationUnits/New.tsx b/src/pages/organisationUnits/New.tsx index f61de6f9..1bc689f5 100644 --- a/src/pages/organisationUnits/New.tsx +++ b/src/pages/organisationUnits/New.tsx @@ -1,13 +1,8 @@ import React from 'react' import { FormBase } from '../../components' import { DefaultNewFormContents } from '../../components/form/DefaultFormContents' -import { SECTIONS_MAP, useOnSubmitNew, validate } from '../../lib' -import { - FormValues, - initialValues, - OrganisationUnitFormField, - organisationUnitSchema, -} from './form' +import { SECTIONS_MAP, useOnSubmitNew } from '../../lib' +import { initialValues, OrganisationUnitFormField, validate } from './form' const section = SECTIONS_MAP.organisationUnit export const Component = () => { @@ -16,10 +11,8 @@ export const Component = () => { onSubmit={useOnSubmitNew({ section, })} - initialValues={initialValues as FormValues} - validate={(values: FormValues) => { - return validate(organisationUnitSchema, values) - }} + initialValues={initialValues} + validate={validate} > diff --git a/src/pages/organisationUnits/form/OrganisationUnitFormFields.tsx b/src/pages/organisationUnits/form/OrganisationUnitFormFields.tsx index d9bdec6f..8fb8e4dc 100644 --- a/src/pages/organisationUnits/form/OrganisationUnitFormFields.tsx +++ b/src/pages/organisationUnits/form/OrganisationUnitFormFields.tsx @@ -1,5 +1,5 @@ import i18n from '@dhis2/d2-i18n' -import { Field, InputFieldFF, TextAreaFieldFF } from '@dhis2/ui' +import { InputFieldFF, TextAreaFieldFF } from '@dhis2/ui' import React from 'react' import { Field as FieldRFF } from 'react-final-form' import { @@ -31,7 +31,9 @@ export function OrganisationUnitFormField() { <> - {i18n.t('Placement in hierarchy')} + {i18n.t( diff --git a/src/pages/organisationUnits/form/OrganisationUnitSelector.tsx b/src/pages/organisationUnits/form/OrganisationUnitSelector.tsx index 0d0172af..2250e2e5 100644 --- a/src/pages/organisationUnits/form/OrganisationUnitSelector.tsx +++ b/src/pages/organisationUnits/form/OrganisationUnitSelector.tsx @@ -1,7 +1,7 @@ import i18n from '@dhis2/d2-i18n' import { Field, NoticeBox, OrganisationUnitTree } from '@dhis2/ui' import { IconInfo16 } from '@dhis2/ui-icons' -import React, { useEffect, useState } from 'react' +import React, { useState } from 'react' import { useField } from 'react-final-form' import { useCurrentUserRootOrgUnits } from '../../../lib/user/currentUserStore' import classes from './OrganisationUnitSelector.module.css' @@ -31,6 +31,7 @@ export function OrganisationUnitSelector() { return ( diff --git a/src/pages/organisationUnits/form/index.ts b/src/pages/organisationUnits/form/index.ts index c5bde466..d839a7a8 100644 --- a/src/pages/organisationUnits/form/index.ts +++ b/src/pages/organisationUnits/form/index.ts @@ -1,5 +1,9 @@ export { OrganisationUnitFormField } from './OrganisationUnitFormFields' export { ImageField } from './ImageField' export { OrganisationUnitSelector } from './OrganisationUnitSelector' -export { organisationUnitSchema, initialValues } from './organisationUnitSchema' +export { + organisationUnitSchema, + initialValues, + validate, +} from './organisationUnitSchema' export type { FormValues } from './types' diff --git a/src/pages/organisationUnits/form/organisationUnitSchema.ts b/src/pages/organisationUnits/form/organisationUnitSchema.ts index 23d61535..57727b88 100644 --- a/src/pages/organisationUnits/form/organisationUnitSchema.ts +++ b/src/pages/organisationUnits/form/organisationUnitSchema.ts @@ -1,6 +1,6 @@ import i18n from '@dhis2/d2-i18n' import { z } from 'zod' -import { getDefaults, modelFormSchemas } from '../../../lib' +import { createFormValidate, getDefaults, modelFormSchemas } from '../../../lib' const { withAttributeValues, identifiable, referenceCollection } = modelFormSchemas @@ -56,7 +56,7 @@ export const organisationUnitSchema = identifiable }), }) .optional(), - parent: z.object({ id: z.string() }).optional(), + parent: z.object({ id: z.string(), path: z.string() }).optional(), geometry: z .object({ type: z.literal('Point'), @@ -92,7 +92,22 @@ export const organisationUnitSchema = identifiable programs: referenceCollection.optional().default([]), dataSets: referenceCollection.optional().default([]), }) + .refine( + (orgUnit) => { + if (!orgUnit.id) { + return true + } + const isDescendantOfSelf = orgUnit.parent?.path.includes(orgUnit.id) + return !isDescendantOfSelf + }, + { + message: i18n.t( + 'Parent organisation unit cannot be itself or a descendant of itself.' + ), + path: ['parent'], + } + ) -export const initialValues = getDefaults( - organisationUnitSchema as z.AnyZodObject -) +export const initialValues = getDefaults(organisationUnitSchema) + +export const validate = createFormValidate(organisationUnitSchema)