Skip to content

Commit

Permalink
EES-5541 added onChange to Form and simplified boundary form implemen…
Browse files Browse the repository at this point in the history
…tation
  • Loading branch information
bennettstuart committed Oct 16, 2024
1 parent 1b744fc commit 6fead8c
Show file tree
Hide file tree
Showing 7 changed files with 342 additions and 231 deletions.
Original file line number Diff line number Diff line change
@@ -1,34 +1,22 @@
import ChartBuilderSaveActions from '@admin/pages/release/datablocks/components/chart/ChartBuilderSaveActions';
import { useChartBuilderFormsContext } from '@admin/pages/release/datablocks/components/chart/contexts/ChartBuilderFormsContext';
import { ChartOptions } from '@admin/pages/release/datablocks/components/chart/reducers/chartBuilderReducer';
import Effect from '@common/components/Effect';
import Form from '@common/components/form/Form';
import FormFieldSelect from '@common/components/form/FormFieldSelect';
import FormProvider from '@common/components/form/FormProvider';
import {
AxisConfiguration,
MapConfig,
MapDataSetConfig,
} from '@common/modules/charts/types/chart';
import { LegendConfiguration } from '@common/modules/charts/types/legend';
import createDataSetCategories from '@common/modules/charts/util/createDataSetCategories';
import expandDataSet from '@common/modules/charts/util/expandDataSet';
import generateDataSetKey from '@common/modules/charts/util/generateDataSetKey';
import getDataSetCategoryConfigs from '@common/modules/charts/util/getDataSetCategoryConfigs';
import { FullTableMeta } from '@common/modules/table-tool/types/fullTable';
import { TableDataResult } from '@common/services/tableBuilderService';
import parseNumber from '@common/utils/number/parseNumber';
import Yup from '@common/validation/yup';
import { isEqual } from 'lodash';
import merge from 'lodash/merge';
import React, { ReactNode, useCallback, useMemo } from 'react';
import { AnyObject, NumberSchema, ObjectSchema } from 'yup';
import ChartBoundaryLevelsDataSetConfiguration from './ChartBoundaryLevelsDataSetConfiguration';

const formId = 'chartBoundaryLevelsConfigurationForm';

export interface ChartBoundaryLevelsFormValues {
boundaryLevel?: number;
dataSetConfigs: Omit<MapDataSetConfig, 'dataGrouping'>[];
}
import ChartBoundaryLevelsForm, {
ChartBoundaryLevelsFormValues,
} from './ChartBoundaryLevelsForm';
import generateDataSetLabel from './utils/generateDataSetLabel';

interface Props {
buttons?: ReactNode;
Expand All @@ -38,7 +26,7 @@ interface Props {
map?: MapConfig;
meta: FullTableMeta;
options: ChartOptions;
onChange: (values: ChartBoundaryLevelsFormValues) => void;
onChange: (values: Partial<ChartBoundaryLevelsFormValues>) => void;
onSubmit: (values: ChartBoundaryLevelsFormValues) => void;
}

Expand All @@ -53,145 +41,93 @@ export default function ChartBoundaryLevelsConfiguration({
onChange,
onSubmit,
}: Props) {
const { updateForm, submitForms } = useChartBuilderFormsContext();

const normalizeValues = useCallback(
(values: ChartBoundaryLevelsFormValues): ChartBoundaryLevelsFormValues => {
(
values: Partial<ChartBoundaryLevelsFormValues>,
): ChartBoundaryLevelsFormValues => {
// Use `merge` as we want to avoid potential undefined
// values from overwriting existing values
return {
boundaryLevel: values.boundaryLevel
? parseNumber(values.boundaryLevel)
: undefined,
dataSetConfigs: values.dataSetConfigs.map(
({ boundaryLevel, dataSet }) => ({
dataSetConfigs:
values.dataSetConfigs?.map(({ boundaryLevel, dataSet }) => ({
boundaryLevel: parseNumber(boundaryLevel),
dataSet,
}),
),
})) ?? [],
};
},
[],
);

const handleChange = useCallback(
const handleSubmit = useCallback(
(values: ChartBoundaryLevelsFormValues) => {
onSubmit(normalizeValues(values));
},
[onSubmit, normalizeValues],
);
const handleChange = useCallback(
(values: Partial<ChartBoundaryLevelsFormValues>) => {
onChange(normalizeValues(values));
},
[normalizeValues, onChange],
[onChange, normalizeValues],
);

const validationSchema = useMemo<
ObjectSchema<ChartBoundaryLevelsFormValues>
>(() => {
return Yup.object({
boundaryLevel: Yup.number()
.transform(value => (Number.isNaN(value) ? undefined : value))
.nullable()
.oneOf(meta.boundaryLevels.map(level => level.id))
.required('Choose a boundary level'),
dataSetConfigs: Yup.array()
.of(
Yup.object({
boundaryLevel: Yup.mixed<number | ''>().test(
'dataset-boundary-is-number-or-empty',
'Must be a number or an empty string',
value => !Number.isNaN(value) || value === '',
) as NumberSchema<number, AnyObject, undefined, ''>,
dataSet: Yup.object({
filters: Yup.array().required(),
}).required(),
}),
)
.required(),
});
}, [meta.boundaryLevels]);
const { dataSetConfigs, boundaryLevel } =
useMemo<ChartBoundaryLevelsFormValues>(() => {
const dataSetCategories = createDataSetCategories({
axisConfiguration: {
...axisMajor,
groupBy: 'locations',
},
data,
meta,
});

const initialValues = useMemo<ChartBoundaryLevelsFormValues>(() => {
const dataSetCategories = createDataSetCategories({
axisConfiguration: {
...axisMajor,
groupBy: 'locations',
},
data,
meta,
});
const dataSetCategoryConfigs = getDataSetCategoryConfigs({
dataSetCategories,
legendItems: legend.items,
meta,
deprecatedDataClassification: options.dataClassification,
deprecatedDataGroups: options.dataGroups,
});

const dataSetCategoryConfigs = getDataSetCategoryConfigs({
dataSetCategories,
legendItems: legend.items,
meta,
deprecatedDataClassification: options.dataClassification,
deprecatedDataGroups: options.dataGroups,
});

return {
boundaryLevel: options.boundaryLevel,
dataSetConfigs: dataSetCategoryConfigs.map(({ rawDataSet }) => ({
dataSet: rawDataSet,
boundaryLevel: map?.dataSetConfigs.find(config =>
isEqual(config.dataSet, rawDataSet),
)?.boundaryLevel,
})),
};
}, [axisMajor, data, meta, legend.items, map, options]);
return {
boundaryLevel: options.boundaryLevel,
dataSetConfigs: dataSetCategoryConfigs.map(({ rawDataSet }) => ({
dataSet: rawDataSet,
boundaryLevel: map?.dataSetConfigs.find(config =>
isEqual(config.dataSet, rawDataSet),
)?.boundaryLevel,
})),
};
}, [axisMajor, data, meta, legend.items, map, options]);

return (
<FormProvider<ChartBoundaryLevelsFormValues>
enableReinitialize
initialValues={initialValues}
validationSchema={validationSchema}
>
{({ formState, watch }) => {
const values = watch();
return (
<Form id={formId} onSubmit={onSubmit}>
<Effect value={values} onChange={handleChange} />
<Effect
value={{
formKey: 'boundaryLevels',
isValid: formState.isValid,
submitCount: 0,
}}
onChange={updateForm}
onMount={updateForm}
/>
<FormFieldSelect<ChartBoundaryLevelsFormValues>
label="Default Boundary level"
hint="Select a version of geographical data to use across any data sets that don't have a specific one set"
name="boundaryLevel"
order={[]}
options={[
{
label: 'Please select',
value: '',
},
...meta.boundaryLevels.map(({ id, label }) => ({
value: id,
label,
})),
]}
/>
const mappedDataSetConfigs = useMemo(() => {
return Object.values(dataSetConfigs).map(dataSetConfig => {
const expandedDataSet = expandDataSet(dataSetConfig.dataSet, meta);
const label = generateDataSetLabel(expandedDataSet);
const key = generateDataSetKey(dataSetConfig.dataSet);

<ChartBoundaryLevelsDataSetConfiguration
dataSetConfigs={values.dataSetConfigs}
meta={meta}
/>
return {
label,
key,
};
});
}, [meta, dataSetConfigs]);

<ChartBuilderSaveActions
formId={formId}
formKey="boundaryLevels"
disabled={formState.isSubmitting}
onClick={async () => {
onSubmit(values);
await submitForms();
}}
>
{buttons}
</ChartBuilderSaveActions>
</Form>
);
}}
</FormProvider>
return (
<ChartBoundaryLevelsForm
buttons={buttons}
boundaryLevelOptions={meta.boundaryLevels.map(({ id, label }) => ({
label,
value: id,
}))}
dataSetRows={mappedDataSetConfigs}
initialValues={{ boundaryLevel, dataSetConfigs }}
onChange={handleChange}
onSubmit={handleSubmit}
/>
);
}

This file was deleted.

Loading

0 comments on commit 6fead8c

Please sign in to comment.