From 07bd69939f4c551dd0cb8d6cb788dba16155b0df Mon Sep 17 00:00:00 2001 From: Chris Hellen Date: Thu, 23 May 2024 14:31:21 -0500 Subject: [PATCH] Implemented dynamic accessability labels for select elements. Refactored tests/translations to accommodate. --- .../Criteria/AggregateCriteriaCard.test.tsx | 8 +- .../Criteria/AggregateCriteriaCard.tsx | 133 +++++++++--------- .../Criteria/CriteriaCardSelect.tsx | 13 +- .../Criteria/CriteriaFeeFineOwner.test.tsx | 2 +- .../Criteria/CriteriaFeeFineOwner.tsx | 18 ++- .../Criteria/CriteriaFeeFineType.test.tsx | 8 +- .../Criteria/CriteriaFeeFineType.tsx | 23 ++- .../Criteria/CriteriaLocation.test.tsx | 4 +- src/components/Criteria/CriteriaLocation.tsx | 33 ++++- .../Criteria/CriteriaPatronGroup.test.tsx | 2 +- .../Criteria/CriteriaPatronGroup.tsx | 19 ++- .../Criteria/CriteriaServicePoint.tsx | 19 ++- src/components/Criteria/OperatorSelect.tsx | 95 +++++++------ .../FormSection/SchedulingSection.tsx | 12 +- .../FormSection/TransferInfoSection.test.tsx | 4 +- src/hooks/useCriteriaCardOptions.ts | 24 ++-- translations/ui-plugin-bursar-export/en.json | 45 +++--- 17 files changed, 274 insertions(+), 188 deletions(-) diff --git a/src/components/Criteria/AggregateCriteriaCard.test.tsx b/src/components/Criteria/AggregateCriteriaCard.test.tsx index e454702..a3fe3d1 100644 --- a/src/components/Criteria/AggregateCriteriaCard.test.tsx +++ b/src/components/Criteria/AggregateCriteriaCard.test.tsx @@ -25,7 +25,7 @@ describe('Aggregate criteria card', () => { }); it('Treats pass as default', async () => { - expect(screen.getByRole('combobox', { name: 'Filter type' })).toHaveValue(CriteriaAggregateType.PASS); + expect(screen.getByRole('combobox', { name: 'None (include all patrons)' })).toHaveValue(CriteriaAggregateType.PASS); await userEvent.click(screen.getByRole('button', { name: 'Submit' })); @@ -37,7 +37,7 @@ describe('Aggregate criteria card', () => { }); it('Pass has no extra boxes/options', async () => { - await userEvent.selectOptions(screen.getByRole('combobox', { name: 'Filter type' }), CriteriaAggregateType.PASS); + await userEvent.selectOptions(screen.getByRole('combobox', { name: 'None (include all patrons)' }), CriteriaAggregateType.PASS); expect(screen.queryByRole('combobox', { name: 'Comparison operator' })).toBeNull(); expect(screen.queryByRole('spinbutton')).toBeNull(); @@ -46,7 +46,7 @@ describe('Aggregate criteria card', () => { it('Quantity has operator and dollar amount', async () => { await userEvent.selectOptions( - screen.getByRole('combobox', { name: 'Filter type' }), + screen.getByRole('combobox', { name: 'None (include all patrons)' }), CriteriaAggregateType.NUM_ROWS, ); @@ -73,7 +73,7 @@ describe('Aggregate criteria card', () => { it('Amount has operator and dollar amount', async () => { await userEvent.selectOptions( - screen.getByRole('combobox', { name: 'Filter type' }), + screen.getByRole('combobox', { name: 'None (include all patrons)' }), CriteriaAggregateType.TOTAL_AMOUNT, ); diff --git a/src/components/Criteria/AggregateCriteriaCard.tsx b/src/components/Criteria/AggregateCriteriaCard.tsx index f29772d..c4cd329 100644 --- a/src/components/Criteria/AggregateCriteriaCard.tsx +++ b/src/components/Criteria/AggregateCriteriaCard.tsx @@ -1,4 +1,4 @@ -import { Card, Col, Row, Select, TextField } from '@folio/stripes/components'; +import { Card, Col, Row, Select, TextField, Label } from '@folio/stripes/components'; import React, { useMemo } from 'react'; import { Field, useField } from 'react-final-form'; import { FormattedMessage, useIntl } from 'react-intl'; @@ -18,20 +18,20 @@ export default function AggregateCriteriaCard() { () => [ { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.none', + id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.Pass', }), value: CriteriaAggregateType.PASS, }, ...[ { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.numAccounts', + id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.NumRows', }), value: CriteriaAggregateType.NUM_ROWS, }, { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.totalAmount', + id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.TotalAmount', }), value: CriteriaAggregateType.TOTAL_AMOUNT, }, @@ -41,77 +41,82 @@ export default function AggregateCriteriaCard() { ); return ( - }> - - - - {(fieldProps) => ( - - {...fieldProps} - fullWidth - marginBottom0 - required - label={} - dataOptions={criteriaOptions} - /> - )} - - - - {selectedType !== CriteriaAggregateType.PASS && ( - - - - )} - - {selectedType === CriteriaAggregateType.NUM_ROWS && ( + <> + }> + - + + {(fieldProps) => ( - + {...fieldProps} fullWidth marginBottom0 required - type="number" - label={ - - } - min={1} - step={1} + aria-label={intl.formatMessage({ id: `ui-plugin-bursar-export.bursarExports.aggregate.filter.${selectedType}` })} + dataOptions={criteriaOptions} /> )} - )} - {selectedType === CriteriaAggregateType.TOTAL_AMOUNT && ( - - - {(fieldProps) => ( - - {...fieldProps} - fullWidth - marginBottom0 - required - type="number" - label={ - - } - min={0} - step={0.01} - /> - )} - - - )} - + {selectedType !== CriteriaAggregateType.PASS && ( + + + + )} + + {selectedType === CriteriaAggregateType.NUM_ROWS && ( + + + {(fieldProps) => ( + + {...fieldProps} + fullWidth + marginBottom0 + required + type="number" + label={ + + } + min={1} + step={1} + /> + )} + + + )} + + {selectedType === CriteriaAggregateType.TOTAL_AMOUNT && ( + + + {(fieldProps) => ( + + {...fieldProps} + fullWidth + marginBottom0 + required + type="number" + label={ + + } + min={0} + step={0.01} + /> + )} + + + )} + -

- - - -

-
+

+ + + +

+ + ); } diff --git a/src/components/Criteria/CriteriaCardSelect.tsx b/src/components/Criteria/CriteriaCardSelect.tsx index 04ec5ba..1163b71 100644 --- a/src/components/Criteria/CriteriaCardSelect.tsx +++ b/src/components/Criteria/CriteriaCardSelect.tsx @@ -1,6 +1,6 @@ import { Select } from '@folio/stripes/components'; import React, { useMemo } from 'react'; -import { Field } from 'react-final-form'; +import { Field, useField } from 'react-final-form'; import { useIntl } from 'react-intl'; import { CriteriaGroupType, CriteriaTerminalType } from '../../types'; import useCriteriaCardOptions from '../../hooks/useCriteriaCardOptions'; @@ -26,19 +26,24 @@ export default function CriteriaCardSelect({ const selectOptions = useCriteriaCardOptions(root, patronOnly); + const selectValue = useField(name, { + subscription: { value: true }, + }).input.value; + return ( {(fieldProps) => ( {...fieldProps} required marginBottom0 + aria-label={selectValue.length === 0 ? + intl.formatMessage({ id: 'ui-plugin-bursar-export.bursarExports.criteria.accordion' }) : + intl.formatMessage({ id: `ui-plugin-bursar-export.bursarExports.criteria.select.${selectValue}` }) + } dataOptions={selectOptions} /> )} diff --git a/src/components/Criteria/CriteriaFeeFineOwner.test.tsx b/src/components/Criteria/CriteriaFeeFineOwner.test.tsx index 55af1be..24502b1 100644 --- a/src/components/Criteria/CriteriaFeeFineOwner.test.tsx +++ b/src/components/Criteria/CriteriaFeeFineOwner.test.tsx @@ -59,7 +59,7 @@ describe('Fee/fine owner criteria displays appropriate form', () => { }); it('Selecting an owner works as expected', async () => { - await userEvent.selectOptions(screen.getByRole('combobox', { name: 'Fee/fine owner' }), 'Owner 1'); + await userEvent.selectOptions(screen.getAllByRole('combobox', { name: 'Fee/fine owner' })[1], 'Owner 1'); await userEvent.click(screen.getByRole('button', { name: 'Submit' })); expect(submitter).toHaveBeenLastCalledWith({ diff --git a/src/components/Criteria/CriteriaFeeFineOwner.tsx b/src/components/Criteria/CriteriaFeeFineOwner.tsx index b6baed1..6f9ffdd 100644 --- a/src/components/Criteria/CriteriaFeeFineOwner.tsx +++ b/src/components/Criteria/CriteriaFeeFineOwner.tsx @@ -1,11 +1,16 @@ -import { Col, Select } from '@folio/stripes/components'; +import { Col, Select, Label } from '@folio/stripes/components'; import React, { useMemo } from 'react'; -import { Field } from 'react-final-form'; -import { FormattedMessage } from 'react-intl'; +import { Field, useField } from 'react-final-form'; +import { useIntl } from 'react-intl'; import { useFeeFineOwners } from '../../api/queries'; export default function CriteriaFeeFineOwner({ prefix }: Readonly<{ prefix: string }>) { const feeFineOwners = useFeeFineOwners(); + const intl = useIntl(); + + const selectedOwner = useField(`${prefix}feeFineOwnerId`, { + subscription: { value: true }, + }).input.value; const ownersSelectOptions = useMemo(() => { if (!feeFineOwners.isSuccess) { @@ -23,8 +28,13 @@ export default function CriteriaFeeFineOwner({ prefix }: Readonly<{ prefix: stri ]; }, [feeFineOwners]); + const ownerName = ownersSelectOptions.find((owner) => owner.value === selectedOwner)?.label; + return ( + {(fieldProps) => ( @@ -32,7 +42,7 @@ export default function CriteriaFeeFineOwner({ prefix }: Readonly<{ prefix: stri fullWidth marginBottom0 required - label={} + aria-label={ownerName?.length === 0 ? 'Fee/fine owner' : ownerName} dataOptions={ownersSelectOptions} /> )} diff --git a/src/components/Criteria/CriteriaFeeFineType.test.tsx b/src/components/Criteria/CriteriaFeeFineType.test.tsx index e0b4037..297540b 100644 --- a/src/components/Criteria/CriteriaFeeFineType.test.tsx +++ b/src/components/Criteria/CriteriaFeeFineType.test.tsx @@ -93,7 +93,7 @@ describe('Fee/fine type criteria displays appropriate form', () => { it('Automatic works as expected', async () => { // check default fill in - expect(screen.getByRole('combobox', { name: 'Fee/fine owner' })).toHaveDisplayValue('Automatic'); + expect(screen.getByRole('combobox', { name: 'Automatic' })).toHaveDisplayValue('Automatic'); expect(screen.getByRole('option', { name: 'Overdue fine' })).toBeVisible(); expect(screen.getByRole('option', { name: 'Lost item fee' })).toBeVisible(); @@ -101,7 +101,7 @@ describe('Fee/fine type criteria displays appropriate form', () => { expect(screen.queryByRole('option', { name: 'Type 2' })).toBeNull(); expect(screen.queryByRole('option', { name: 'Type 3' })).toBeNull(); - await userEvent.selectOptions(screen.getByRole('combobox', { name: 'Fee/fine type' }), 'Lost item fee'); + await userEvent.selectOptions(screen.getAllByRole('combobox', { name: 'Fee/fine type' })[1], 'Lost item fee'); await userEvent.click(screen.getByRole('button', { name: 'Submit' })); expect(submitter).toHaveBeenLastCalledWith({ @@ -114,14 +114,14 @@ describe('Fee/fine type criteria displays appropriate form', () => { }); it('Selecting an owner works as expected', async () => { - await userEvent.selectOptions(screen.getByRole('combobox', { name: 'Fee/fine owner' }), 'Owner 1'); + await userEvent.selectOptions(screen.getByRole('combobox', { name: 'Automatic' }), 'Owner 1'); expect(screen.getByRole('option', { name: 'Type 1' })).toBeVisible(); expect(screen.getByRole('option', { name: 'Type 2' })).toBeVisible(); expect(screen.queryByRole('option', { name: 'Type 3' })).toBeNull(); expect(screen.queryByRole('option', { name: 'Overdue fine' })).toBeNull(); - await userEvent.selectOptions(screen.getByRole('combobox', { name: 'Fee/fine type' }), 'Type 2'); + await userEvent.selectOptions(screen.getAllByRole('combobox', { name: 'Fee/fine type' })[1], 'Type 2'); await userEvent.click(screen.getByRole('button', { name: 'Submit' })); expect(submitter).toHaveBeenLastCalledWith({ diff --git a/src/components/Criteria/CriteriaFeeFineType.tsx b/src/components/Criteria/CriteriaFeeFineType.tsx index ff38508..8f38a55 100644 --- a/src/components/Criteria/CriteriaFeeFineType.tsx +++ b/src/components/Criteria/CriteriaFeeFineType.tsx @@ -1,7 +1,7 @@ -import { Col, Select } from '@folio/stripes/components'; +import { Col, Select, Label } from '@folio/stripes/components'; import React, { useMemo } from 'react'; import { Field, useField } from 'react-final-form'; -import { FormattedMessage, useIntl } from 'react-intl'; +import { useIntl } from 'react-intl'; import { useFeeFineOwners, useFeeFineTypes } from '../../api/queries'; export default function CriteriaFeeFineType({ prefix }: Readonly<{ prefix: string }>) { @@ -15,6 +15,10 @@ export default function CriteriaFeeFineType({ prefix }: Readonly<{ prefix: strin format: (value) => value ?? 'automatic', }).input.value; + const selectedType = useField(`${prefix}feeFineTypeId`, { + subscription: { value: true }, + }).input.value; + const ownersSelectOptions = useMemo(() => { const defaultOption = { label: intl.formatMessage({ @@ -65,31 +69,38 @@ export default function CriteriaFeeFineType({ prefix }: Readonly<{ prefix: strin [typeSelectOptions], ); + const ownerName = ownersSelectOptions.find((owner) => owner.value === selectedOwner)?.label; + const typeName = typeSelectOptions.find((type) => type.value === selectedType)?.label; + return ( <> + {(fieldProps) => ( {...fieldProps} fullWidth marginBottom0 - required - label={} + aria-label={ownerName} dataOptions={ownersSelectOptions} /> )} + {(fieldProps) => ( {...fieldProps} fullWidth marginBottom0 - required - label={} + aria-label={typeName === undefined ? 'Fee/fine type' : typeName} dataOptions={typeSelectOptionsForDisplay} /> )} diff --git a/src/components/Criteria/CriteriaLocation.test.tsx b/src/components/Criteria/CriteriaLocation.test.tsx index ff759ef..e6b9248 100644 --- a/src/components/Criteria/CriteriaLocation.test.tsx +++ b/src/components/Criteria/CriteriaLocation.test.tsx @@ -143,7 +143,7 @@ it('Location criteria displays appropriate form', async () => { expectOptionNotInDocument('Matching location 2'); expectOptionNotInDocument('Non-matching location'); - await userEvent.selectOptions(screen.getByRole('combobox', { name: 'Campus' }), 'Matching campus 2'); + await userEvent.selectOptions(screen.getByRole('combobox', { name: 'Matching campus 1' }), 'Matching campus 2'); expectOptionNotInDocument('Matching library'); expectOptionNotInDocument('Non-matching library'); @@ -151,7 +151,7 @@ it('Location criteria displays appropriate form', async () => { expectOptionNotInDocument('Matching location 2'); expectOptionNotInDocument('Non-matching location'); - await userEvent.selectOptions(screen.getByRole('combobox', { name: 'Campus' }), 'Matching campus 1'); + await userEvent.selectOptions(screen.getByRole('combobox', { name: 'Matching campus 2' }), 'Matching campus 1'); expectOptionInDocument('Matching library'); expectOptionNotInDocument('Non-matching library'); diff --git a/src/components/Criteria/CriteriaLocation.tsx b/src/components/Criteria/CriteriaLocation.tsx index 7a13aff..e229471 100644 --- a/src/components/Criteria/CriteriaLocation.tsx +++ b/src/components/Criteria/CriteriaLocation.tsx @@ -1,7 +1,7 @@ -import { Col, Select } from '@folio/stripes/components'; +import { Col, Select, Label } from '@folio/stripes/components'; import React, { useMemo } from 'react'; import { Field, useField } from 'react-final-form'; -import { FormattedMessage } from 'react-intl'; +import { useIntl } from 'react-intl'; import { useCampuses, useInstitutions, useLibraries, useLocations } from '../../api/queries'; export default function CriteriaLocation({ prefix }: Readonly<{ prefix: string }>) { @@ -9,6 +9,7 @@ export default function CriteriaLocation({ prefix }: Readonly<{ prefix: string } const campuses = useCampuses(); const libraries = useLibraries(); const locations = useLocations(); + const intl = useIntl(); const selectedInstitution = useField(`${prefix}institutionId`, { subscription: { value: true }, @@ -19,6 +20,9 @@ export default function CriteriaLocation({ prefix }: Readonly<{ prefix: string } const selectedLibrary = useField(`${prefix}libraryId`, { subscription: { value: true }, }).input.value; + const selectedLocation = useField(`${prefix}locationId`, { + subscription: { value: true }, + }).input.value; const institutionSelectOptions = useMemo(() => { if (!institutions.isSuccess) { @@ -87,9 +91,17 @@ export default function CriteriaLocation({ prefix }: Readonly<{ prefix: string } ]; }, [selectedLibrary, locations]); + const institutionName = institutionSelectOptions.find((inst) => inst.value === selectedInstitution)?.label; + const campusName = campusSelectOptions.find((camp) => camp.value === selectedCampus)?.label; + const libraryName = librarySelectOptions.find((lib) => lib.value === selectedLibrary)?.label; + const locationName = locationSelectOptions.find((loc) => loc.value === selectedLocation)?.label; + return ( <> + {(fieldProps) => ( @@ -97,13 +109,16 @@ export default function CriteriaLocation({ prefix }: Readonly<{ prefix: string } fullWidth marginBottom0 required - label={} + aria-label={institutionName === undefined ? 'Institution' : institutionName} dataOptions={institutionSelectOptions} /> )} + {(fieldProps) => ( @@ -111,13 +126,16 @@ export default function CriteriaLocation({ prefix }: Readonly<{ prefix: string } fullWidth marginBottom0 required - label={} + aria-label={campusName === undefined ? 'Campus' : campusName} dataOptions={campusSelectOptions} /> )} + {(fieldProps) => ( @@ -125,13 +143,16 @@ export default function CriteriaLocation({ prefix }: Readonly<{ prefix: string } fullWidth marginBottom0 required - label={} + aria-label={libraryName === undefined ? 'Library' : libraryName} dataOptions={librarySelectOptions} /> )} + {(fieldProps) => ( @@ -139,7 +160,7 @@ export default function CriteriaLocation({ prefix }: Readonly<{ prefix: string } fullWidth marginBottom0 required - label={} + aria-label={locationName === undefined ? 'Location' : locationName} dataOptions={locationSelectOptions} /> )} diff --git a/src/components/Criteria/CriteriaPatronGroup.test.tsx b/src/components/Criteria/CriteriaPatronGroup.test.tsx index 8937d3c..2714c56 100644 --- a/src/components/Criteria/CriteriaPatronGroup.test.tsx +++ b/src/components/Criteria/CriteriaPatronGroup.test.tsx @@ -71,7 +71,7 @@ it('Patron group type criteria displays appropriate form', async () => { expect(screen.getByRole('option', { name: 'faculty' })).toBeVisible(); expect(screen.getByRole('option', { name: 'undergrad' })).toBeVisible(); - await userEvent.selectOptions(screen.getByRole('combobox', { name: 'Patron group' }), 'staff'); + await userEvent.selectOptions(screen.getAllByRole('combobox', { name: 'Patron group' })[1], 'staff'); await userEvent.click(screen.getByRole('button', { name: 'Submit' })); diff --git a/src/components/Criteria/CriteriaPatronGroup.tsx b/src/components/Criteria/CriteriaPatronGroup.tsx index c83b2a5..d48c6fa 100644 --- a/src/components/Criteria/CriteriaPatronGroup.tsx +++ b/src/components/Criteria/CriteriaPatronGroup.tsx @@ -1,12 +1,18 @@ -import { Col, Select } from '@folio/stripes/components'; +import { Col, Select, Label } from '@folio/stripes/components'; import React, { useMemo } from 'react'; -import { Field } from 'react-final-form'; -import { FormattedMessage } from 'react-intl'; +import { Field, useField } from 'react-final-form'; +import { useIntl } from 'react-intl'; import { usePatronGroups } from '../../api/queries'; export default function CriteriaPatronGroup({ prefix }: Readonly<{ prefix: string }>) { const patronGroups = usePatronGroups(); + const intl = useIntl(); + + const selectedPatron = useField(`${prefix}patronGroupId`, { + subscription: { value: true }, + }).input.value; + const selectOptions = useMemo(() => { if (!patronGroups.isSuccess) { return [{ label: '', value: undefined }]; @@ -23,8 +29,13 @@ export default function CriteriaPatronGroup({ prefix }: Readonly<{ prefix: strin ]; }, [patronGroups]); + const patronName = selectOptions.find((patron) => patron.value === selectedPatron)?.label; + return ( + {(fieldProps) => ( @@ -32,7 +43,7 @@ export default function CriteriaPatronGroup({ prefix }: Readonly<{ prefix: strin fullWidth marginBottom0 required - label={} + aria-label={patronName === undefined ? 'Patron group' : patronName} dataOptions={selectOptions} /> )} diff --git a/src/components/Criteria/CriteriaServicePoint.tsx b/src/components/Criteria/CriteriaServicePoint.tsx index 5f006b6..c784859 100644 --- a/src/components/Criteria/CriteriaServicePoint.tsx +++ b/src/components/Criteria/CriteriaServicePoint.tsx @@ -1,11 +1,16 @@ -import { Col, Select } from '@folio/stripes/components'; +import { Col, Select, Label } from '@folio/stripes/components'; import React, { useMemo } from 'react'; -import { Field } from 'react-final-form'; -import { FormattedMessage } from 'react-intl'; +import { Field, useField } from 'react-final-form'; +import { useIntl } from 'react-intl'; import { useServicePoints } from '../../api/queries'; export default function CriteriaServicePoint({ prefix }: Readonly<{ prefix: string }>) { const servicePoints = useServicePoints(); + const intl = useIntl(); + + const selectedServicePoint = useField(`${prefix}servicePointId`, { + subscription: { value: true }, + }).input.value; const selectOptions = useMemo(() => { if (!servicePoints.isSuccess) { @@ -23,16 +28,20 @@ export default function CriteriaServicePoint({ prefix }: Readonly<{ prefix: stri ]; }, [servicePoints]); + const servicePointName = selectOptions.find((sp) => sp.value === selectedServicePoint)?.label; + return ( + {(fieldProps) => ( {...fieldProps} fullWidth marginBottom0 - required - label={} + aria-label={servicePointName === undefined ? 'Service point' : servicePointName} dataOptions={selectOptions} /> )} diff --git a/src/components/Criteria/OperatorSelect.tsx b/src/components/Criteria/OperatorSelect.tsx index 25d1277..1197374 100644 --- a/src/components/Criteria/OperatorSelect.tsx +++ b/src/components/Criteria/OperatorSelect.tsx @@ -1,49 +1,62 @@ -import { Select } from '@folio/stripes/components'; +import { Label, Select } from '@folio/stripes/components'; import React from 'react'; -import { Field } from 'react-final-form'; -import { FormattedMessage, useIntl } from 'react-intl'; +import { Field, useField } from 'react-final-form'; +import { useIntl } from 'react-intl'; import { ComparisonOperator } from '../../types'; export default function OperatorSelect({ name }: Readonly<{ name: string }>) { const intl = useIntl(); + + + const operatorValue = useField(name, { + subscription: { value: true }, + }).input.value; + return ( - - {(fieldProps) => ( - - {...fieldProps} - fullWidth - marginBottom0 - required - label={} - dataOptions={[ - { label: '', value: undefined }, - { - label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.operator.less', - }), - value: ComparisonOperator.LESS_THAN, - }, - { - label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.operator.lessEqual', - }), - value: ComparisonOperator.LESS_THAN_EQUAL, - }, - { - label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.operator.greater', - }), - value: ComparisonOperator.GREATER_THAN, - }, - { - label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.operator.greaterEqual', - }), - value: ComparisonOperator.GREATER_THAN_EQUAL, - }, - ]} - /> - )} - + <> + + + {(fieldProps) => ( + + {...fieldProps} + fullWidth + marginBottom0 + required + aria-label={operatorValue?.length === 0 ? + intl.formatMessage({ id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.operator' }) : + intl.formatMessage({ id: `ui-plugin-bursar-export.bursarExports.aggregate.filter.operator.${operatorValue}` })} + dataOptions={[ + { label: '', value: undefined }, + { + label: intl.formatMessage({ + id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.operator.LESS_THAN', + }), + value: ComparisonOperator.LESS_THAN, + }, + { + label: intl.formatMessage({ + id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.operator.LESS_THAN_EQUAL', + }), + value: ComparisonOperator.LESS_THAN_EQUAL, + }, + { + label: intl.formatMessage({ + id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.operator.GREATER_THAN', + }), + value: ComparisonOperator.GREATER_THAN, + }, + { + label: intl.formatMessage({ + id: 'ui-plugin-bursar-export.bursarExports.aggregate.filter.operator.GREATER_THAN_EQUAL', + }), + value: ComparisonOperator.GREATER_THAN_EQUAL, + }, + ]} + /> + )} + + ); } diff --git a/src/components/FormSection/SchedulingSection.tsx b/src/components/FormSection/SchedulingSection.tsx index 8dd09bd..f325338 100644 --- a/src/components/FormSection/SchedulingSection.tsx +++ b/src/components/FormSection/SchedulingSection.tsx @@ -30,29 +30,31 @@ export default function SchedulingSection() { {...fieldProps} fullWidth required - label={} + aria-label={frequencyValue.length === 0 ? + intl.formatMessage({ id: 'ui-plugin-bursar-export.bursarExports.scheduling.frequency' }) : + intl.formatMessage({ id: `ui-plugin-bursar-export.bursarExports.scheduling.frequency.${frequencyValue}` })} dataOptions={[ { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.scheduling.frequency.manual', + id: 'ui-plugin-bursar-export.bursarExports.scheduling.frequency.NONE', }), value: SchedulingFrequency.Manual, }, { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.scheduling.frequency.hours', + id: 'ui-plugin-bursar-export.bursarExports.scheduling.frequency.HOUR', }), value: SchedulingFrequency.Hours, }, { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.scheduling.frequency.days', + id: 'ui-plugin-bursar-export.bursarExports.scheduling.frequency.DAY', }), value: SchedulingFrequency.Days, }, { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.scheduling.frequency.weeks', + id: 'ui-plugin-bursar-export.bursarExports.scheduling.frequency.WEEK', }), value: SchedulingFrequency.Weeks, }, diff --git a/src/components/FormSection/TransferInfoSection.test.tsx b/src/components/FormSection/TransferInfoSection.test.tsx index c735c03..9d0fe15 100644 --- a/src/components/FormSection/TransferInfoSection.test.tsx +++ b/src/components/FormSection/TransferInfoSection.test.tsx @@ -149,11 +149,11 @@ describe('Transfer criteria section', () => { await act(() => userEvent.click(screen.getByRole('button', { name: 'Add condition' }))); await act(async () => { await userEvent.selectOptions( - screen.getAllByRole('combobox', { name: 'Criteria' })[2], + screen.getAllByRole('combobox', { name: 'Patron group' })[0], 'Patron group', ); await userEvent.selectOptions( - screen.getByRole('combobox', { name: 'Patron group' }), + screen.getAllByRole('combobox', { name: 'Patron group' })[1], 'staff', ); await userEvent.selectOptions( diff --git a/src/hooks/useCriteriaCardOptions.ts b/src/hooks/useCriteriaCardOptions.ts index 4d6f43d..e7d7d95 100644 --- a/src/hooks/useCriteriaCardOptions.ts +++ b/src/hooks/useCriteriaCardOptions.ts @@ -10,19 +10,19 @@ export default function useCriteriaCardOptions(root: boolean, patronOnly: boolea const options: SelectOptionType[] = [ { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.criteria.select.allOf', + id: 'ui-plugin-bursar-export.bursarExports.criteria.select.Condition-AND', }), value: CriteriaGroupType.ALL_OF, }, { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.criteria.select.anyOf', + id: 'ui-plugin-bursar-export.bursarExports.criteria.select.Condition-OR', }), value: CriteriaGroupType.ANY_OF, }, { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.criteria.select.noneOf', + id: 'ui-plugin-bursar-export.bursarExports.criteria.select.Condition-NOR', }), value: CriteriaGroupType.NONE_OF, }, @@ -37,50 +37,50 @@ export default function useCriteriaCardOptions(root: boolean, patronOnly: boolea ? [ { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.criteria.select.patronGroup', + id: 'ui-plugin-bursar-export.bursarExports.criteria.select.PatronGroup', }), value: CriteriaTerminalType.PATRON_GROUP, }, ] : [ { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.criteria.select.age', + id: 'ui-plugin-bursar-export.bursarExports.criteria.select.Age', }), value: CriteriaTerminalType.AGE, }, { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.criteria.select.amount', + id: 'ui-plugin-bursar-export.bursarExports.criteria.select.Amount', }), value: CriteriaTerminalType.AMOUNT, }, { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.criteria.select.owner', + id: 'ui-plugin-bursar-export.bursarExports.criteria.select.FeeFineOwner', }), value: CriteriaTerminalType.FEE_FINE_OWNER, }, { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.criteria.select.type', + id: 'ui-plugin-bursar-export.bursarExports.criteria.select.FeeType', }), value: CriteriaTerminalType.FEE_FINE_TYPE, }, { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.criteria.select.location', + id: 'ui-plugin-bursar-export.bursarExports.criteria.select.Location', }), value: CriteriaTerminalType.LOCATION, }, { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.criteria.select.servicePoint', + id: 'ui-plugin-bursar-export.bursarExports.criteria.select.ServicePoint', }), value: CriteriaTerminalType.SERVICE_POINT, }, { label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.criteria.select.patronGroup', + id: 'ui-plugin-bursar-export.bursarExports.criteria.select.PatronGroup', }), value: CriteriaTerminalType.PATRON_GROUP, }, @@ -91,7 +91,7 @@ export default function useCriteriaCardOptions(root: boolean, patronOnly: boolea if (root) { options.unshift({ label: intl.formatMessage({ - id: 'ui-plugin-bursar-export.bursarExports.criteria.select.none', + id: 'ui-plugin-bursar-export.bursarExports.criteria.select.Pass', }), value: CriteriaTerminalType.PASS, }); diff --git a/translations/ui-plugin-bursar-export/en.json b/translations/ui-plugin-bursar-export/en.json index e004eea..e9716d6 100644 --- a/translations/ui-plugin-bursar-export/en.json +++ b/translations/ui-plugin-bursar-export/en.json @@ -12,10 +12,10 @@ "bursarExports.scheduling.accordion": "Scheduling", "bursarExports.scheduling.frequency": "Frequency", - "bursarExports.scheduling.frequency.manual": "Never (run manually)", - "bursarExports.scheduling.frequency.hours": "Hours", - "bursarExports.scheduling.frequency.days": "Days", - "bursarExports.scheduling.frequency.weeks": "Weeks", + "bursarExports.scheduling.frequency.NONE": "Never (run manually)", + "bursarExports.scheduling.frequency.HOUR": "Hours", + "bursarExports.scheduling.frequency.DAY": "Days", + "bursarExports.scheduling.frequency.WEEK": "Weeks", "bursarExports.scheduling.interval.HOUR": "Hours between runs", "bursarExports.scheduling.interval.DAY": "Days between runs", "bursarExports.scheduling.interval.WEEK": "Weeks between runs", @@ -28,18 +28,17 @@ "bursarExports.scheduler.mutation.manual.error": "Failed to start job", "bursarExports.criteria.accordion": "Criteria", - "bursarExports.criteria.select.allOf": "All of:", - "bursarExports.criteria.select.anyOf": "Any of:", - "bursarExports.criteria.select.noneOf": "None of:", - "bursarExports.criteria.select.age": "Age", - "bursarExports.criteria.select.amount": "Amount", - "bursarExports.criteria.select.owner": "Fee/fine owner", - "bursarExports.criteria.select.type": "Fee/fine type", - "bursarExports.criteria.select.location": "Item location", - "bursarExports.criteria.select.servicePoint": "Item service point", - "bursarExports.criteria.select.patronGroup": "Patron group", - "bursarExports.criteria.select.none": "No criteria (always run)", - "bursarExports.criteria.select.label": "Criteria", + "bursarExports.criteria.select.Condition-AND": "All of:", + "bursarExports.criteria.select.Condition-OR": "Any of:", + "bursarExports.criteria.select.Condition-NOR": "None of:", + "bursarExports.criteria.select.Age": "Age", + "bursarExports.criteria.select.Amount": "Amount", + "bursarExports.criteria.select.FeeFineOwner": "Fee/fine owner", + "bursarExports.criteria.select.FeeType": "Fee/fine type", + "bursarExports.criteria.select.Location": "Item location", + "bursarExports.criteria.select.ServicePoint": "Item service point", + "bursarExports.criteria.select.PatronGroup": "Patron group", + "bursarExports.criteria.select.Pass": "No criteria (always run)", "bursarExports.criteria.age.value": "Number of days old", "bursarExports.criteria.type.automatic": "Automatic", @@ -56,16 +55,16 @@ "bursarExports.aggregate.description": "If enabled, each output row will correspond to a single patron with all of their accounts, rather than just a single account.", "bursarExports.aggregate.filter": "Filter type", "bursarExports.aggregate.filter.header": "Only include patrons with:", - "bursarExports.aggregate.filter.none": "None (include all patrons)", - "bursarExports.aggregate.filter.numAccounts": "Number of accounts", + "bursarExports.aggregate.filter.Pass": "None (include all patrons)", + "bursarExports.aggregate.filter.NumRows": "Number of accounts", "bursarExports.aggregate.filter.numAccounts.amount": "Number of accounts", - "bursarExports.aggregate.filter.totalAmount": "Total amount", + "bursarExports.aggregate.filter.TotalAmount": "Total amount", "bursarExports.aggregate.filter.totalAmount.amount": "Amount", "bursarExports.aggregate.filter.operator": "Comparison operator", - "bursarExports.aggregate.filter.operator.less": "Less than but not equal to", - "bursarExports.aggregate.filter.operator.lessEqual": "Less than or equal to", - "bursarExports.aggregate.filter.operator.greater": "Greater than but not equal to", - "bursarExports.aggregate.filter.operator.greaterEqual": "Greater than or equal to", + "bursarExports.aggregate.filter.operator.LESS_THAN": "Less than but not equal to", + "bursarExports.aggregate.filter.operator.LESS_THAN_EQUAL": "Less than or equal to", + "bursarExports.aggregate.filter.operator.GREATER_THAN": "Greater than but not equal to", + "bursarExports.aggregate.filter.operator.GREATER_THAN_EQUAL": "Greater than or equal to", "bursarExports.aggregate.filter.description": "This will be applied after accounts are evaluated per the \u201cCriteria\u201d specified above.", "bursarExports.header.accordion": "Header format",