Skip to content

Commit

Permalink
UISER-184: Implement separation of chronology and enumeration (#353)
Browse files Browse the repository at this point in the history
* refactor: Chronology labels field array

Added chronlogy labels field array to ruleset form

* refactor: Token info

Refactored rendering of token info by moving to child component, also renamed props on chronology field component

* refactor: Enumeration field array

Refactored label field array into another seperate enumeration field array component

* feat: Template string field

Added template string field to ruleset form, taken from now deprecated labelfieldarray component

* refactor: Removed LabelFieldArray

Removed now deprecated label field array

* refactor: Ruleset view conditionals

Updated conditionals within the ruleset views to use seperated enumeration/chronology rules

* refactor: Handler refactors

Refactored more places in which templateConfig.rules was used, should be all of them now, additional testing and tidy up required

* refactor: Chronology/enumeration field arrays

Implemented some performance refactors discussed previously

* refactor: Chronology options

Seperated out selectification (?) of chronology refdata values

* test: Updated resources

Updated centralised test resources

* test: Updated tests

Everything should be passing now (Yipee)

* refactor: Slight pieces preview modal refactor

Very very slight refactor done to pieces preview modal, its out of the scope of this ticket to refactor this, would prefer to add this to tech debt

* test: ChronologyField test tweaks

First run at refactoring chronology field test

* test: Chronology field test

Tweaked chronology field test to use .each functions along with stripes-erm-testing helpers

* refactor: Updated getRulesetFormValues

getRulesetFormValues was affected by uiser-182

* test: Chronology labels test

Added test for ChronlogyLabels component

* test: Enumeration labels test

Added tests for enumeration labels component

* test: Enumeration field array

Added test for enumeration field array component

* test: Chronology field array

Added test for chronology fioeld array component

* chore: Sonarcloud issue

Fixed sonar cloud issue in PiecesPreviewModalForm

* fix: Format starting values

Fixed issue with syntax and incorrect implementation of return array

* fix: Starting values mapping fix

User configured metadata index mapping was weird due to seperation, now filtering so the sv array is just enumeration rules

* test: RulesetView test

Added test for RulesetView test
  • Loading branch information
Jack-Golding authored Feb 5, 2025
1 parent 597b5ac commit 1315a44
Show file tree
Hide file tree
Showing 38 changed files with 1,576 additions and 1,365 deletions.
45 changes: 26 additions & 19 deletions src/components/PiecesPreviewModal/PiecesPreviewModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,29 +82,40 @@ const PiecesPreviewModal = ({
.then((res) => history.push(urls.pieceSetView(res?.id)))
);

// Slightly annoying implementation here, for future work we expect to refactor the UserConfiguredMetadata on the backend
// At which point this should be refactored aswell
const formatStartingValues = (values) => {
return ruleset?.templateConfig?.rules?.map((rule, ruleIndex) => {
const tmrt =
rule?.templateMetadataRuleType?.value ?? rule?.templateMetadataRuleType;
const startingValuesArray = [];

ruleset?.templateConfig?.chronologyRules?.forEach((rule, ruleIndex) => {
startingValuesArray.push({
userConfiguredTemplateMetadataType: 'chronology',
index: ruleIndex,
metadataType: {},
});
});

ruleset?.templateConfig?.enumerationRules?.forEach((rule, ruleIndex) => {
const tmrf =
rule?.ruleType?.templateMetadataRuleFormat?.value ??
rule?.ruleType?.templateMetadataRuleFormat;
return {
userConfiguredTemplateMetadataType: tmrt,
rule?.templateMetadataRuleFormat?.value ??
rule?.templateMetadataRuleFormat;
startingValuesArray.push({
userConfiguredTemplateMetadataType: 'enumeration',
index: ruleIndex,
metadataType: {
...(tmrf === 'enumeration_numeric' && {
levels:
rule?.ruleType?.ruleFormat?.levels?.map((_level, levelIndex) => {
rule?.ruleFormat?.levels?.map((_level, levelIndex) => {
return {
...values?.startingValues[ruleIndex]?.levels[levelIndex],
index: levelIndex,
};
}) || {},
}),
},
};
});
});
return startingValuesArray;
};

// istanbul ignore next
Expand Down Expand Up @@ -135,6 +146,7 @@ const PiecesPreviewModal = ({
const dateExists = existingPieceSets?.some(
(ps) => ps?.startDate === values?.startDate
);

return (
<>
{allowCreation && (
Expand Down Expand Up @@ -163,7 +175,7 @@ const PiecesPreviewModal = ({
key="preview-predicated-pieces-button"
buttonStyle={allowCreation ? 'default' : 'primary'}
disabled={submitting || invalid || pristine}
id="rulset-preview-button"
id="ruleset-preview-button"
marginBottom0
onClick={() => handleGeneration(values)}
type="submit"
Expand All @@ -184,7 +196,7 @@ const PiecesPreviewModal = ({
);
};

// TODO what is the point of this
// Added to prevent SonarCloud smells
const renderPublicationDate = (piece) => {
return <PiecePublicationDate piece={piece} />;
};
Expand Down Expand Up @@ -220,14 +232,9 @@ const PiecesPreviewModal = ({
columnWidths={{
publicationDate: { min: 100, max: 165 },
}}
// DEPRECATED - This handles the older case in which generatePieces responded with an array of pieces
// Now supports newer response of the predicted piece set object, containing an array of pieces
// TODO Remove this once interface version has been increased
contentData={
Array.isArray(generatedPieceSet)
? generatedPieceSet
: generatedPieceSet?.pieces
}
// We have removed the Array handling of this as of MODSER-42 which is an interface version bump
// Should be 2.0 I believe, or 1.3, eitherway as of sunflower release this frontend no longer supports older backend interfaces
contentData={generatedPieceSet?.pieces}
formatter={formatter}
id="pieces-preview-multi-columns"
interactive={false}
Expand Down
23 changes: 11 additions & 12 deletions src/components/PiecesPreviewModal/PiecesPreviewModal.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ describe('PiecesPreviewModal', () => {
translationsProperties
);
});

test('renders the expected modal header', async () => {
const { getByText } = renderComponent;
expect(getByText('Generate predicted pieces')).toBeInTheDocument();
Expand Down Expand Up @@ -105,7 +104,7 @@ describe('PiecesPreviewModal', () => {

test('renders the expected label 1 label', async () => {
const { getByText } = renderComponent;
expect(getByText('Label 2')).toBeInTheDocument();
expect(getByText('Label 1')).toBeInTheDocument();
});

test('renders the expected level 1 label', async () => {
Expand All @@ -129,7 +128,7 @@ describe('PiecesPreviewModal', () => {
});

test('renders the preview button', async () => {
await Button({ id: 'rulset-preview-button' }).has({ disabled: true });
await Button({ id: 'ruleset-preview-button' }).has({ disabled: true });
});

test('renders the close button', async () => {
Expand All @@ -143,10 +142,10 @@ describe('PiecesPreviewModal', () => {
mockMutateAsync.mockClear();
await waitFor(async () => {
await Datepicker({ id: 'ruleset-start-date' }).fillIn('01/01/2026');
await TextField({ name: 'startingValues[1].levels[0].rawValue' }).fillIn(
await TextField({ name: 'startingValues[0].levels[0].rawValue' }).fillIn(
'1'
);
await TextField({ name: 'startingValues[1].levels[1].rawValue' }).fillIn(
await TextField({ name: 'startingValues[0].levels[1].rawValue' }).fillIn(
'1'
);
});
Expand Down Expand Up @@ -185,10 +184,10 @@ describe('PiecesPreviewModal', () => {
mockMutateAsync.mockClear();
await waitFor(async () => {
await Datepicker({ id: 'ruleset-start-date' }).fillIn('02/01/2024');
await TextField({ name: 'startingValues[1].levels[0].rawValue' }).fillIn(
await TextField({ name: 'startingValues[0].levels[0].rawValue' }).fillIn(
'1'
);
await TextField({ name: 'startingValues[1].levels[1].rawValue' }).fillIn(
await TextField({ name: 'startingValues[0].levels[1].rawValue' }).fillIn(
'1'
);
});
Expand Down Expand Up @@ -269,18 +268,18 @@ describe('PiecesPreviewModal w/o allowCreation', () => {
});

test('renders the preview button', async () => {
await Button({ id: 'rulset-preview-button' }).has({ disabled: true });
await Button({ id: 'ruleset-preview-button' }).has({ disabled: true });
});

// TODO better name for this
describe('typing dates into fields', () => {
beforeEach(async () => {
await waitFor(async () => {
await Datepicker({ id: 'ruleset-start-date' }).fillIn('01/01/2025');
await TextField({ name: 'startingValues[1].levels[0].rawValue' }).fillIn(
await TextField({ name: 'startingValues[0].levels[0].rawValue' }).fillIn(
'1'
);
await TextField({ name: 'startingValues[1].levels[1].rawValue' }).fillIn(
await TextField({ name: 'startingValues[0].levels[1].rawValue' }).fillIn(
'1'
);
});
Expand All @@ -293,13 +292,13 @@ describe('PiecesPreviewModal w/o allowCreation', () => {
});

test('preview button is not disabled', async () => {
await Button({ id: 'rulset-preview-button' }).has({ disabled: false });
await Button({ id: 'ruleset-preview-button' }).has({ disabled: false });
});

describe('clicking preview button', () => {
beforeEach(async () => {
await waitFor(async () => {
await Button({ id: 'rulset-preview-button' }).click();
await Button({ id: 'ruleset-preview-button' }).click();
});
});

Expand Down
107 changes: 58 additions & 49 deletions src/components/PiecesPreviewModal/PiecesPreviewModalForm.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMemo } from 'react';
import { useCallback, useMemo } from 'react';
import PropTypes from 'prop-types';
import { Field, useForm, useFormState } from 'react-final-form';
import { FormattedMessage, useIntl } from 'react-intl';
Expand Down Expand Up @@ -83,13 +83,16 @@ const PiecesPreviewModalForm = ({
);
}, [ruleset?.recurrence?.period, ruleset?.recurrence?.timeUnit?.value]);

const getAdjustedStartDate = (date, numberOfCycles = 1) => {
const adjustedStartDate = new Date(date);
adjustedStartDate.setFullYear(
adjustedStartDate.getFullYear() + minimumNumberOfYears * numberOfCycles
);
return adjustedStartDate;
};
const getAdjustedStartDate = useCallback(
(date, numberOfCycles = 1) => {
const adjustedStartDate = new Date(date);
adjustedStartDate.setFullYear(
adjustedStartDate.getFullYear() + minimumNumberOfYears * numberOfCycles
);
return adjustedStartDate;
},
[minimumNumberOfYears]
);

const startingValueDataOptions = existingPieceSets
?.filter((ps) => ps?.ruleset?.id === ruleset?.id)
Expand All @@ -103,39 +106,47 @@ const PiecesPreviewModalForm = ({
};
});

const handleStartingValuesChange = (e) => {
const selectedPieceSet = existingPieceSets?.find(
(ps) => ps.id === e?.target?.value || ''
);
batch(() => {
change(
'startDate',
selectedPieceSet?.startDate
? getAdjustedStartDate(
selectedPieceSet?.startDate,
selectedPieceSet?.numberOfCycles ?? 1
)
: null
);
change('numberOfCycles', selectedPieceSet?.numberOfCycles ?? 1);
change(
'startingValues',
selectedPieceSet?.continuationPieceRecurrenceMetadata?.userConfigured?.map(
(uc) => {
if (uc?.metadataType?.levels?.length) {
return {
levels: uc?.metadataType?.levels?.map((ucl) => {
return { rawValue: ucl?.rawValue };
}),
};
}
return null;
}
)
);
});
// Seperated out due to sonarcloud code smells
const formatUserConfiguredMetadata = (userConfiguredMetadata = []) => {
return userConfiguredMetadata
.filter((uc) => uc?.metadataType?.levels?.length)
.map((uc) => {
return {
levels: uc?.metadataType?.levels?.map((ucl) => {
return { rawValue: ucl?.rawValue };
}),
};
});
};

const handleStartingValuesChange = useCallback(
(e) => {
const selectedPieceSet = existingPieceSets?.find(
(ps) => ps.id === e?.target?.value || ''
);
batch(() => {
change(
'startDate',
selectedPieceSet?.startDate
? getAdjustedStartDate(
selectedPieceSet?.startDate,
selectedPieceSet?.numberOfCycles ?? 1
)
: null
);
change('numberOfCycles', selectedPieceSet?.numberOfCycles ?? 1);
change(
'startingValues',
formatUserConfiguredMetadata(
selectedPieceSet?.continuationPieceRecurrenceMetadata
?.userConfigured
)
);
});
},
[batch, change, existingPieceSets, getAdjustedStartDate]
);

const renderEnumerationNumericField = (formatValues, index) => {
return (
<Row key={`enumeration-numeric-field-${index}`}>
Expand All @@ -149,7 +160,7 @@ const PiecesPreviewModalForm = ({
</strong>
</Layout>
</Col>
{formatValues?.ruleType?.ruleFormat?.levels?.map((e, i) => {
{formatValues?.ruleFormat?.levels?.map((e, i) => {
return (
<Col key={`${index}-${i}`} xs={2}>
<Field
Expand Down Expand Up @@ -190,11 +201,10 @@ const PiecesPreviewModalForm = ({
</Col>
</Row>
<br />
{ruleset?.templateConfig?.rules?.map((e, i) => {
{ruleset?.templateConfig?.enumerationRules?.map((e, i) => {
if (
e?.ruleType?.templateMetadataRuleFormat?.value ===
'enumeration_numeric' ||
e?.ruleType?.templateMetadataRuleFormat === 'enumeration_numeric'
e?.templateMetadataRuleFormat?.value === 'enumeration_numeric' ||
e?.templateMetadataRuleFormat === 'enumeration_numeric'
) {
// Required so that sonarcloud doesnt flag use of index within key prop
const indexCounter = i;
Expand All @@ -213,7 +223,7 @@ const PiecesPreviewModalForm = ({

return (
<>
{!!startingValueDataOptions?.length && (
{startingValueDataOptions?.length > 0 && (
<Row>
<Col xs={12}>
<Select
Expand Down Expand Up @@ -288,10 +298,9 @@ const PiecesPreviewModalForm = ({
</Col>
)}
</Row>
{!!ruleset?.templateConfig?.rules?.some(
(e) => e?.ruleType?.templateMetadataRuleFormat?.value ===
'enumeration_numeric' ||
e?.ruleType?.templateMetadataRuleFormat === 'enumeration_numeric'
{ruleset?.templateConfig?.enumerationRules?.some(
(e) => e?.templateMetadataRuleFormat?.value === 'enumeration_numeric' ||
e?.templateMetadataRuleFormat === 'enumeration_numeric'
) && renderTemplateStartingValues()}
{existingPieceSets?.some((ps) => ps?.startDate === values?.startDate) && (
<MessageBanner type="warning">
Expand Down
Loading

0 comments on commit 1315a44

Please sign in to comment.