From 252fb8e2f47e22112ba37638e1c9e075ccfe5dab Mon Sep 17 00:00:00 2001 From: Chisomchima Date: Wed, 16 Oct 2024 11:03:46 +0100 Subject: [PATCH 1/2] feat: add category option combo list --- i18n/en.pot | 28 +++++++------------------ src/pages/categoryOptionGroups/List.tsx | 3 +++ 2 files changed, 11 insertions(+), 20 deletions(-) create mode 100644 src/pages/categoryOptionGroups/List.tsx diff --git a/i18n/en.pot b/i18n/en.pot index 8e3d64b6..f86a8248 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: 2024-09-30T15:09:50.864Z\n" -"PO-Revision-Date: 2024-09-30T15:09:50.864Z\n" +"POT-Creation-Date: 2024-10-16T10:01:50.562Z\n" +"PO-Revision-Date: 2024-10-16T10:01:50.563Z\n" msgid "schemas" msgstr "schemas" @@ -120,21 +120,6 @@ msgstr "Failed to load {{label}}" msgid "Failed to load" msgstr "Failed to load" -msgid "Download" -msgstr "Download" - -msgid "Merge" -msgstr "Merge" - -msgid "Delete source data element values" -msgstr "Delete source data element values" - -msgid "Last updated" -msgstr "Last updated" - -msgid "Discard" -msgstr "Discard" - msgid "Aggregation level(s)" msgstr "Aggregation level(s)" @@ -234,6 +219,9 @@ msgstr "Created" msgid "Last updated by" msgstr "Last updated by" +msgid "Last updated" +msgstr "Last updated" + msgid "Id" msgstr "Id" @@ -255,6 +243,9 @@ msgstr "Details" msgid "Failed to load details" msgstr "Failed to load details" +msgid "Download" +msgstr "Download" + msgid "Download {{section}}" msgstr "Download {{section}}" @@ -855,9 +846,6 @@ msgstr "Data dimension type" msgid "This field requires a unique value, please choose another one" msgstr "This field requires a unique value, please choose another one" -msgid "{{label}} (required)" -msgstr "{{label}} (required)" - msgid "No changes to be saved" msgstr "No changes to be saved" diff --git a/src/pages/categoryOptionGroups/List.tsx b/src/pages/categoryOptionGroups/List.tsx new file mode 100644 index 00000000..e03292f8 --- /dev/null +++ b/src/pages/categoryOptionGroups/List.tsx @@ -0,0 +1,3 @@ +import { DefaultSectionList } from '../DefaultSectionList' + +export const Component = DefaultSectionList From 6033dfd644ad48fca942ddce8dcfd4528f26af23 Mon Sep 17 00:00:00 2001 From: Chisomchima Date: Wed, 16 Oct 2024 16:04:42 +0100 Subject: [PATCH 2/2] feat: implement new and edit forms --- src/pages/categoryOptionGroups/Edit.tsx | 57 +++++++++ src/pages/categoryOptionGroups/New.tsx | 23 ++++ .../form/CategoryOptionGroupFormFields.tsx | 114 ++++++++++++++++++ .../form/categoryOptionGroupSchema.ts | 27 +++++ 4 files changed, 221 insertions(+) create mode 100644 src/pages/categoryOptionGroups/Edit.tsx create mode 100644 src/pages/categoryOptionGroups/New.tsx create mode 100644 src/pages/categoryOptionGroups/form/CategoryOptionGroupFormFields.tsx create mode 100644 src/pages/categoryOptionGroups/form/categoryOptionGroupSchema.ts diff --git a/src/pages/categoryOptionGroups/Edit.tsx b/src/pages/categoryOptionGroups/Edit.tsx new file mode 100644 index 00000000..052bde1a --- /dev/null +++ b/src/pages/categoryOptionGroups/Edit.tsx @@ -0,0 +1,57 @@ +import React from 'react' +import { useQuery } from 'react-query' +import { useParams } from 'react-router-dom' +import { DefaultEditFormContents, FormBase } from '../../components' +import { DEFAULT_FIELD_FILTERS, SECTIONS_MAP, useOnSubmitEdit } from '../../lib' +import { useBoundResourceQueryFn } from '../../lib/query/useBoundQueryFn' +import { PickWithFieldFilters } from '../../types/generated' +import { Category } from '../../types/models' +import CategoryOptionGroupFormFields from './form/CategoryOptionGroupFormFields' +import { validate } from './form/categoryOptionGroupSchema' + +const fieldFilters = [ + ...DEFAULT_FIELD_FILTERS, + 'name', + 'shortName', + 'code', + 'description', + 'categoryOptions[id,displayName]', + 'dataDimension', + 'dataDimensionType', + 'attributeValues[value,attribute[id]]', +] as const + +export type CategoryFormValues = PickWithFieldFilters< + Category, + typeof fieldFilters +> + +export const Component = () => { + const section = SECTIONS_MAP.categoryOptionGroup + const queryFn = useBoundResourceQueryFn() + const modelId = useParams().id as string + const query = { + resource: 'categoryOptionGroups', + id: modelId, + params: { + fields: fieldFilters.concat(), + }, + } + const categoryQuery = useQuery({ + queryKey: [query], + queryFn: queryFn, + }) + + return ( + + + + + + ) +} diff --git a/src/pages/categoryOptionGroups/New.tsx b/src/pages/categoryOptionGroups/New.tsx new file mode 100644 index 00000000..83355bac --- /dev/null +++ b/src/pages/categoryOptionGroups/New.tsx @@ -0,0 +1,23 @@ +import React from 'react' +import { FormBase } from '../../components' +import { DefaultNewFormContents } from '../../components/form/DefaultFormContents' +import { SECTIONS_MAP, useOnSubmitNew } from '../../lib' +import CategoryOptionGroupFormFields from './form/CategoryOptionGroupFormFields' +import { initialValues, validate } from './form/categoryOptionGroupSchema' + +const section = SECTIONS_MAP.categoryOptionGroup + +export const Component = () => { + return ( + + + + + + ) +} diff --git a/src/pages/categoryOptionGroups/form/CategoryOptionGroupFormFields.tsx b/src/pages/categoryOptionGroups/form/CategoryOptionGroupFormFields.tsx new file mode 100644 index 00000000..0c25be03 --- /dev/null +++ b/src/pages/categoryOptionGroups/form/CategoryOptionGroupFormFields.tsx @@ -0,0 +1,114 @@ +import i18n from '@dhis2/d2-i18n' +import { RadioFieldFF, CheckboxFieldFF } from '@dhis2/ui' +import React from 'react' +import { Field } from 'react-final-form' +import { + DefaultIdentifiableFields, + DescriptionField, + HorizontalFieldGroup, + ModelTransferField, + StandardFormField, + StandardFormSection, + StandardFormSectionDescription, + StandardFormSectionTitle, +} from '../../../components' +import { SECTIONS_MAP } from '../../../lib' + +function CategoryOptionGroupFormFields() { + const section = SECTIONS_MAP.categoryOptionGroup + return ( + <> + + + {i18n.t('Basic information')} + + + {i18n.t('Set up the basic information for this category.')} + + + + + + + + {i18n.t('Data configuration')} + + + {i18n.t( + 'Choose how this category will be used to capture and analyze' + )} + + + + + name="dataDimensionType" + component={RadioFieldFF} + label={i18n.t('Disaggregation')} + type="radio" + value={'DISAGGREGATION'} + /> + + name="dataDimensionType" + component={RadioFieldFF} + label={i18n.t('Attribute')} + type="radio" + value={'ATTRIBUTE'} + /> + + + + + + + + + + + + + {i18n.t( + 'Choose the category options to include in this category.' + )} + + + + + + + + + ) +} + +export default CategoryOptionGroupFormFields diff --git a/src/pages/categoryOptionGroups/form/categoryOptionGroupSchema.ts b/src/pages/categoryOptionGroups/form/categoryOptionGroupSchema.ts new file mode 100644 index 00000000..e086768d --- /dev/null +++ b/src/pages/categoryOptionGroups/form/categoryOptionGroupSchema.ts @@ -0,0 +1,27 @@ +import { z } from 'zod' +import { getDefaults, createFormValidate, modelFormSchemas } from '../../../lib' +import { CategoryOptionGroup } from '../../../types/generated' + +/* Note that this describes what we send to the server, + and not what is stored in the form. */ +const { identifiable, referenceCollection, withAttributeValues } = + modelFormSchemas + +export const categoryOptionGroupSchema = identifiable + .merge(withAttributeValues) + .extend({ + shortName: z.string().trim(), + code: z.string().trim().optional(), + description: z.string().trim().optional(), + dataDimensionType: z + .nativeEnum(CategoryOptionGroup.dataDimensionType) + .default(CategoryOptionGroup.dataDimensionType.DISAGGREGATION), + dataDimension: z.boolean().default(true), + categoryOptions: referenceCollection + .min(1, 'At least one category option is required') + .default([]), + }) + +export const initialValues = getDefaults(categoryOptionGroupSchema) + +export const validate = createFormValidate(categoryOptionGroupSchema)