diff --git a/collections/forms/i18n/en.pot b/collections/forms/i18n/en.pot index dd42956f40..b977b9a031 100644 --- a/collections/forms/i18n/en.pot +++ b/collections/forms/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-09T12:09:30.724Z\n" -"PO-Revision-Date: 2024-09-09T12:09:30.724Z\n" +"POT-Creation-Date: 2024-11-13T11:27:44.715Z\n" +"PO-Revision-Date: 2024-11-13T11:27:44.725Z\n" msgid "Upload file" msgstr "Upload file" diff --git a/components/organisation-unit-tree/src/__e2e__/get-organisation-unit-data.js b/components/organisation-unit-tree/src/__e2e__/get-organisation-unit-data.js index 6c07473f8c..49e302713e 100644 --- a/components/organisation-unit-tree/src/__e2e__/get-organisation-unit-data.js +++ b/components/organisation-unit-tree/src/__e2e__/get-organisation-unit-data.js @@ -1,119 +1,127 @@ const createResponse = ({ fields, id, path, displayName, children }) => ({ ...(fields.includes('id') ? { id } : {}), - ...(fields.includes('path') ? { path } : {}), + ...(fields.includes('path') ? { path, level: path.split('/').length } : {}), ...(fields.includes('displayName') ? { displayName } : {}), ...(fields.includes('children::size') ? { children: children.length } : {}), ...(fields.includes('children[id,path,displayName]') ? { children } : {}), }) export const getOrganisationUnitData = (id, { fields }) => { - let data - - if (id === 'A0000000000') { - data = createResponse({ - fields, - id: 'A0000000000', - path: '/A0000000000', - displayName: 'Org Unit 1', - children: [ - { - id: 'A0000000001', - path: '/A0000000000/A0000000001', - displayName: 'Org Unit 2', - }, - { - id: 'A0000000002', - path: '/A0000000000/A0000000002', - displayName: 'Org Unit 3', - }, - { - id: 'A0000000006', - path: '/A0000000000/A0000000006', - displayName: 'Org Unit 7', - }, - ], - }) + const allData = { + ...createHierarchyResponses({ rootPrefix: 'A', fields }), + ...createHierarchyResponses({ rootPrefix: 'B', fields, nameGenerator: (num) => `Org unit B ${num}` }), } + // return null + console.log({ id}) + console.log({allData}) + return allData[id] +} - if (id === 'A0000000001') { - data = createResponse({ - fields, - id: 'A0000000001', - path: '/A0000000000/A0000000001', - displayName: 'Org Unit 2', - children: [ - { - id: 'A0000000003', - path: '/A0000000000/A0000000001/A0000000003', - children: [], - displayName: 'Org Unit 4', - }, - { - id: 'A0000000004', - path: '/A0000000000/A0000000001/A0000000004', - children: [], - displayName: 'Org Unit 5', - }, - ], - }) - } +const createHierarchyResponses = ({ rootPrefix, nameGenerator, fields }) => { + nameGenerator = + typeof nameGenerator === 'function' + ? nameGenerator + : (num) => `Org Unit ${num}` + const data = {} + const generateId = (num) => `${rootPrefix}000000000${num}` - if (id === 'A0000000002') { - data = createResponse({ - fields, - displayName: 'Org Unit 3', - id: 'A0000000002', - path: '/A0000000000/A0000000002', - children: [], - }) - } + data[generateId(0)] = createResponse({ + fields, + id: generateId(0), + path: `/${rootPrefix}0000000000`, + displayName: nameGenerator(1), + children: [ + { + id: generateId(1), + path: [generateId(0), generateId(1)].join('/'), + displayName: nameGenerator(2), //'Org Unit 2', + }, + { + id: generateId(2), + path: [generateId(0), generateId(2)].join('/'), + displayName: nameGenerator(3), + }, + { + id: generateId(6), + path: [generateId(0), generateId(6)].join('/'), + displayName: nameGenerator(7), + }, + ], + }) - if (id === 'A0000000003') { - data = createResponse({ - fields, - displayName: 'Org Unit 4', - id: 'A0000000003', - path: '/A0000000000/A0000000001/A0000000003', - children: [ - { - id: 'A0000000007', - path: '/A0000000000/A0000000001/A0000000003/A0000000007', - children: [], - displayName: 'Org Unit 8', - }, - ], - }) - } + data[generateId(1)] = createResponse({ + fields, + id: generateId(1), + path: [generateId(0), generateId(1)].join('/'), + displayName: nameGenerator(2), + children: [ + { + id: generateId(3), + path: [generateId(0), generateId(1), generateId(3)].join('/'), + children: [], + displayName: nameGenerator(4), + }, + { + id: generateId(4), + path: [generateId(0), generateId(1), generateId(4)].join('/'), + children: [], + displayName: nameGenerator(5), + }, + ], + }) - if (id === 'A0000000004') { - data = createResponse({ - fields, - displayName: 'Org Unit 5', - id: 'A0000000004', - path: '/A0000000000/A0000000001/A0000000004', - children: [], - }) - } + data[generateId(2)] = createResponse({ + fields, + displayName: nameGenerator(3), + id: generateId(2), + path: [generateId(0), generateId(2)].join('/'), + children: [], + }) - if (id === 'A0000000006') { - data = createResponse({ - fields, - displayName: 'Org Unit 7', - id: 'A0000000006', - path: '/A0000000000/A0000000006', - children: [], - }) - } + data[generateId(3)] = createResponse({ + fields, + displayName: nameGenerator(4), + id: generateId(3), + path: [generateId(0), generateId(1), generateId(3)].join('/'), + children: [ + { + id: generateId(7), + path: [ + generateId(0), + generateId(1), + generateId(3), + generateId(7), + ].join('/'), + displayName: nameGenerator(8), + }, + ], + }) - if (id === 'A0000000007') { - data = createResponse({ - fields, - displayName: 'Org Unit 8', - id: 'A0000000007', - path: '/A0000000000/A0000000001/A0000000003/A0000000007', - children: [], - }) - } + data[generateId(4)] = createResponse({ + fields, + displayName: nameGenerator(5), + id: generateId(4), + path: [generateId(0), generateId(1), generateId(4)].join('/'), + children: [], + }) + + data[generateId(6)] = createResponse({ + fields, + displayName: nameGenerator(7), + id: generateId(6), + path: [generateId(0), generateId(6)].join('/'), + children: [], + }) + + data[generateId(7)] = createResponse({ + fields, + displayName: nameGenerator(8), + id: generateId(7), + path: [generateId(0), generateId(1), generateId(3), generateId(7)].join( + '/' + ), + children: [], + }) return data } diff --git a/components/organisation-unit-tree/src/__e2e__/sub_unit_as_root.js b/components/organisation-unit-tree/src/__e2e__/sub_unit_as_root.js index d7fc4c7061..01df2e2a69 100644 --- a/components/organisation-unit-tree/src/__e2e__/sub_unit_as_root.js +++ b/components/organisation-unit-tree/src/__e2e__/sub_unit_as_root.js @@ -16,7 +16,7 @@ export const MultipleRootSubAndOneMainOrgUnit = (_, { selected, onChange }) => { filter={filter ? filter.split(',') : []} onChange={onChange} selected={selected} - roots={['A0000000000', 'A0000000001', 'A0000000002']} + roots={['A0000000001', 'A0000000002']} /> ) diff --git a/components/organisation-unit-tree/src/__stories__/multiple-roots.js b/components/organisation-unit-tree/src/__stories__/multiple-roots.js index 1e51d42ae2..e2682babff 100644 --- a/components/organisation-unit-tree/src/__stories__/multiple-roots.js +++ b/components/organisation-unit-tree/src/__stories__/multiple-roots.js @@ -9,7 +9,7 @@ export const MultipleRoots = (_, { onChange, selected }) => ( ) diff --git a/components/organisation-unit-tree/src/__stories__/shared.js b/components/organisation-unit-tree/src/__stories__/shared.js index 9ae83966c4..87f223fdad 100644 --- a/components/organisation-unit-tree/src/__stories__/shared.js +++ b/components/organisation-unit-tree/src/__stories__/shared.js @@ -16,8 +16,11 @@ const createResponse = ({ fields, id, path, displayName, children }) => ({ ...(fields.includes('children::size') ? { children: children.length } : {}), ...(fields.includes('children[id,path,displayName]') ? { children } : {}), }) +import { getOrganisationUnitData as goud } from '../__e2e__/get-organisation-unit-data' -export const getOrganisationUnitData = (id, { fields }) => { +export const getOrganisationUnitData = goud + +const t = (id, { fields }) => { let data if (id === 'A0000000000') { diff --git a/components/organisation-unit-tree/src/features/expanded.feature b/components/organisation-unit-tree/src/features/expanded.feature index e2a7e6d848..b76adfc888 100644 --- a/components/organisation-unit-tree/src/features/expanded.feature +++ b/components/organisation-unit-tree/src/features/expanded.feature @@ -10,18 +10,8 @@ Feature: Nodes can be expanded Given a OrganisationUnitTree with children and the path of the first unit on the second level in the initiallyExpanded prop is rendered Then the root unit is opened - # For info what a "sub", "main" and "root" unit is, see - # "sub_unit_as_root.feature" - Scenario: A sub org unit gets expanded within the main org unit tree - Given both a sub org unit with children and a main org unit are root org units - And the root main org unit is expanded - When the user expands the sub org unit within the main org unit tree - Then the root sub org unit should not expand - - # For info what a "sub", "main" and "root" unit is, see - # "sub_unit_as_root.feature" - Scenario: A root sub org unit gets expanded which is also in the main org unit tree - Given both a sub org unit with children and a main org unit are root org units - And the root main org unit is expanded - When the user expands the root sub org unit - Then the sub org unit within the main org unit tree should not expand + Scenario: A sub org unit and its parents are both root org units + Given both a sub org unit and its parent are root org units + Then only the parent unit is first rendered + When the root main org unit is expanded + Then the sub org unit is rendered diff --git a/components/organisation-unit-tree/src/features/expanded/index.js b/components/organisation-unit-tree/src/features/expanded/index.js index 8b70f45eec..854cf5789a 100644 --- a/components/organisation-unit-tree/src/features/expanded/index.js +++ b/components/organisation-unit-tree/src/features/expanded/index.js @@ -1,4 +1,4 @@ -import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor' +import { Given, Then } from '@badeball/cypress-cucumber-preprocessor' const getRootOrgUnitByLabel = (label) => { const rootOrgUnitLabelSelector = ` @@ -28,38 +28,17 @@ Given( } ) -Given( - 'both a sub org unit with children and a main org unit are root org units', - () => { - cy.visitStory( - 'OrganisationUnitTree', - 'with root main and root sub org unit' - ) - } -) - -Given('the root main org unit is expanded', () => { - getRootOrgUnitByLabel('Org Unit 1') - .find('> [data-test="dhis2-uiwidgets-orgunittree-node-toggle"]') - .click() +Given('both a sub org unit and its parent are root org units', () => { + cy.visitStory( + 'OrganisationUnitTree', + 'with root main and root sub org unit' + ) }) -When('the user expands the sub org unit within the main org unit tree', () => { +Given('the root main org unit is expanded', () => { getRootOrgUnitByLabel('Org Unit 1') - .contains( - '[data-test="dhis2-uiwidgets-orgunittree-node"]', - 'Org Unit 2' - ) - .find('> [data-test="dhis2-uiwidgets-orgunittree-node-toggle"]') - .click() - .should('have.class', 'open') -}) - -When('the user expands the root sub org unit', () => { - getRootOrgUnitByLabel('Org Unit 2') .find('> [data-test="dhis2-uiwidgets-orgunittree-node-toggle"]') .click() - .should('have.class', 'open') }) Then('the root unit is closed', () => { @@ -70,18 +49,21 @@ Then('the root unit is opened', () => { cy.getOrgUnitByLabel('Org Unit 1').shouldBeAnOrgUnitNode() }) -Then('the root sub org unit should not expand', () => { - getRootOrgUnitByLabel('Org Unit 2') - .find('> [data-test="dhis2-uiwidgets-orgunittree-node-toggle"]') - .should('not.have.class', 'open') +Then('only the parent unit is first rendered', () => { + cy.contains( + '[data-test="dhis2-uiwidgets-orgunittree-node-label"]', + 'Org Unit 1' + ).should('exist') + + cy.contains( + '[data-test="dhis2-uiwidgets-orgunittree-node-label"]', + 'Org Unit 2' + ).should('not.exist') }) -Then('the sub org unit within the main org unit tree should not expand', () => { - getRootOrgUnitByLabel('Org Unit 1') - .contains( - '[data-test="dhis2-uiwidgets-orgunittree-node"]', - 'Org Unit 2' - ) - .find('> [data-test="dhis2-uiwidgets-orgunittree-node-toggle"]') - .should('not.have.class', 'open') +Then('the sub org unit is rendered', () => { + cy.contains( + '[data-test="dhis2-uiwidgets-orgunittree-node-label"]', + 'Org Unit 2' + ).should('exist') }) diff --git a/components/organisation-unit-tree/src/features/sub_unit_as_root.feature b/components/organisation-unit-tree/src/features/sub_unit_as_root.feature index 11caed3428..768ce24775 100644 --- a/components/organisation-unit-tree/src/features/sub_unit_as_root.feature +++ b/components/organisation-unit-tree/src/features/sub_unit_as_root.feature @@ -11,18 +11,6 @@ Feature: Sub-org units can be a root org unit When the user selects the root sub org unit Then the root sub org unit should be selected - Scenario: The user selects the root sub org unit which is included in the tree of a root main org unit - Given both a sub org unit and a main org unit are root org units - And the root sub org unit is a child of the root main org unit - When the user selects the root sub org unit - Then the root main org unit should be marked as indeterminate - - Scenario: The user selects the a child in the root main org unit which is also a root sub org unit - Given both a sub org unit and a main org unit are root org units - And the root sub org unit is a child of the root main org unit - When the user selects sub org unit in the main org unit tree - Then the root sub org unit should be selected - Scenario: The user filtered the tree by a root sub unit path Given multiple sub org units is a root org unit And the user provided one root sub org unit to the filter @@ -32,3 +20,5 @@ Feature: Sub-org units can be a root org unit Given multiple sub org units is a root org unit And the user provided one non-root sub org unit to the filter Then only the root main org units should be visible + When the user expands the root sub org unit + Then only the matching children should be visible diff --git a/components/organisation-unit-tree/src/features/sub_unit_as_root/index.js b/components/organisation-unit-tree/src/features/sub_unit_as_root/index.js index e821ef2164..ae57401129 100644 --- a/components/organisation-unit-tree/src/features/sub_unit_as_root/index.js +++ b/components/organisation-unit-tree/src/features/sub_unit_as_root/index.js @@ -15,13 +15,6 @@ Given('a sub org unit is a root org unit', () => { ) }) -Given('both a sub org unit and a main org unit are root org units', () => { - cy.visitStory( - 'OrganisationUnitTree', - 'multiple root sub and one main org unit' - ) -}) - Given('multiple sub org units is a root org unit', () => { cy.visitStory( 'OrganisationUnitTree', @@ -29,47 +22,33 @@ Given('multiple sub org units is a root org unit', () => { ) }) -Given('the root sub org unit is a child of the root main org unit', () => { - cy.visitStory( - 'OrganisationUnitTree', - 'multiple root sub and one main org unit' - ) -}) - Given('the user provided one root sub org unit to the filter', () => { cy.get('input[type="input"]').clear().type('/A0000000001') }) Given('the user provided one non-root sub org unit to the filter', () => { - cy.get('input[type="input"]').clear().type('/A0000000000/A0000000006') -}) - -When('the user selects sub org unit in the main org unit tree', () => { - cy.contains('label', 'Org Unit 1').click() - cy.get('[data-test="dhis2-uiwidgets-orgunittree-node-content"]') - .contains('label', 'Org Unit 2') - .click() + cy.get('input[type="input"]').clear().type('/A0000000001/A0000000003') }) When('the user selects the root sub org unit', () => { cy.contains(rootOrgUnitLabelSelector, 'Org Unit 2').click() }) +When('the user expands the root sub org unit', () => { + cy.contains(rootOrgUnitLabelSelector, 'Org Unit 2') + .parents('[data-test="dhis2-uiwidgets-orgunittree-node"]') + .find('> [data-test="dhis2-uiwidgets-orgunittree-node-toggle"]') + .click() +}) + Then( 'all root sub org units but the filtered sub org unit should be hidden', () => { cy.contains(rootOrgUnitLabelSelector, 'Org Unit 2').should('exist') - cy.contains(rootOrgUnitLabelSelector, 'Org Unit 1').should('not.exist') cy.contains(rootOrgUnitLabelSelector, 'Org Unit 3').should('not.exist') } ) -Then('the root main org unit should be marked as indeterminate', () => { - cy.contains(rootOrgUnitLabelSelector, 'Org Unit 1') - .find('> .icon svg') - .should('have.class', 'indeterminate') -}) - Then('the root sub org unit should be selected', () => { cy.contains(rootOrgUnitLabelSelector, 'Org Unit 2') .find('> .icon svg') @@ -77,7 +56,18 @@ Then('the root sub org unit should be selected', () => { }) Then('only the root main org units should be visible', () => { - cy.contains(rootOrgUnitLabelSelector, 'Org Unit 1').should('exist') - cy.contains(rootOrgUnitLabelSelector, 'Org Unit 2').should('not.exist') + cy.contains(rootOrgUnitLabelSelector, 'Org Unit 2').should('exist') cy.contains(rootOrgUnitLabelSelector, 'Org Unit 3').should('not.exist') }) + +Then('only the matching children should be visible', () => { + cy.contains(rootOrgUnitLabelSelector, 'Org Unit 2').should('exist') + cy.contains( + '[data-test="dhis2-uiwidgets-orgunittree-node-label"]', + 'Org Unit 4' + ).should('exist') + cy.contains( + '[data-test="dhis2-uiwidgets-orgunittree-node-label"]', + 'Org Unit 5' + ).should('not.exist') +}) diff --git a/components/organisation-unit-tree/src/organisation-unit-tree/find-common-orgunit-roots.js b/components/organisation-unit-tree/src/organisation-unit-tree/find-common-orgunit-roots.js new file mode 100644 index 0000000000..9754d349d0 --- /dev/null +++ b/components/organisation-unit-tree/src/organisation-unit-tree/find-common-orgunit-roots.js @@ -0,0 +1,29 @@ +/** + * Find the minimum/common root units from a list of orgunits. + * This is used to "deduplicate" a list of units, where some unit in the list + * may be a parent of another, and thus only the parent should be included as a root. + * + * This is mainly because of the /me API returning the verbatim selected units, + * where the user is able to select children deep in a tree, even if an ancestor above is selected + * @param {Array} unitsWithLevel - List of orgunits with their level + * @param {Array} rootIds - List of root orgunits ids + * @returns {Array} - A filtered list of the minimum root units + */ +export const findCommonOrgUnitRoots = (unitsWithLevel, rootIds) => { + const filteredUnitsWithLevel = unitsWithLevel.filter((orgUnit) => + rootIds.includes(orgUnit.id) + ) + + const sorted = filteredUnitsWithLevel.sort((a, b) => a.level - b.level) + + const minimumRoots = sorted.filter((ou, index, array) => { + // since the array is sorted by level we can just check the previous units, + // because we want to get the "minimum" level + const previousUnits = array.slice(0, index) + // if a previous unit has a path that is a prefix of the current path, + // then the current path is a child and should not be included + return !previousUnits.some((pu) => ou.path.startsWith(pu.path)) + }) + + return minimumRoots +} diff --git a/components/organisation-unit-tree/src/organisation-unit-tree/find-common-orgunit-roots.test.js b/components/organisation-unit-tree/src/organisation-unit-tree/find-common-orgunit-roots.test.js new file mode 100644 index 0000000000..cef4b81542 --- /dev/null +++ b/components/organisation-unit-tree/src/organisation-unit-tree/find-common-orgunit-roots.test.js @@ -0,0 +1,152 @@ +import { findCommonOrgUnitRoots } from './find-common-orgunit-roots.js' + +const unitToPath = { + sierra: '/ImspTQPwCqd', + tanzania: '/N5hLlID8ihI', + ethiopia: '/LK1v9z1Jt3k', + 'sierra/bo': '/ImspTQPwCqd/O6uvpzGd5pu', + 'sierra/bo/bargbe': '/ImspTQPwCqd/O6uvpzGd5pu/dGheVylzol6', + 'sierra/bo/bargbe/barlie': + '/ImspTQPwCqd/O6uvpzGd5pu/dGheVylzol6/y5hLlID8ihI', + 'sierra/bargbe/barlie': '/ImspTQPwCqd/dGheVylzol6/y5hLlID8ihI', + 'sierra/bargbe/barlie/ngalu': + '/ImspTQPwCqd/dGheVylzol6/y5hLlID8ihI/Aj5v9z1Jt3k', + 'sierra/bo/baoma': '/ImspTQPwCqd/O6uvpzGd5pu/vWbkYPRmKyS', + 'sierra/bo/baoma/faabu': '/ImspTQPwCqd/O6uvpzGd5pu/vWbkYPRmKyS/ZpE2POxvl9P', + 'sierra/bo/badjia': '/ImspTQPwCqd/O6uvpzGd5pu/YuQRtpLP10I', + 'sierra/bo/badjia/ngelehun': + '/ImspTQPwCqd/O6uvpzGd5pu/YuQRtpLP10I/DiszpKrYNg8', + 'sierra/bombali': '/ImspTQPwCqd/fdc6uOvgoji', +} + +describe('findCommonOrgUnitRoots', () => { + it('should return a single root unit when there is only one unit', () => { + const units = [{ id: '1', path: unitToPath.sierra, level: 1 }] + const result = findCommonOrgUnitRoots(units, ['1']) + expect(result).toEqual([{ id: '1', path: unitToPath.sierra, level: 1 }]) + // should not mutate the input + expect(units).toStrictEqual(units) + }) + + it('should return two root units when there are two sibling units', () => { + const units = [ + { id: '1', path: unitToPath['sierra/bo'], level: 2 }, + { id: '2', path: unitToPath['sierra/bombali'], level: 2 }, + ] + + const result = findCommonOrgUnitRoots(units, ['1', '2']) + expect(result).toEqual([ + { id: '1', path: unitToPath['sierra/bo'], level: 2 }, + { id: '2', path: unitToPath['sierra/bombali'], level: 2 }, + ]) + expect(units).toStrictEqual(units) + }) + + it('should return only the root unit when one unit is a child of another', () => { + const units = [ + { id: '1', path: unitToPath['sierra'], level: 1 }, + { id: '2', path: unitToPath['sierra/bo'], level: 2 }, + ] + const result = findCommonOrgUnitRoots(units, ['1', '2']) + expect(result).toEqual([ + { id: '1', path: unitToPath['sierra'], level: 1 }, + ]) + expect(units).toStrictEqual(units) + }) + + it('should return only the root unit when one unit is a deep child of another', () => { + const units = [ + { id: '1', path: unitToPath['sierra'], level: 1 }, + { + id: '2', + path: unitToPath['sierra/bo/badjia/ngelehun'], + level: 4, + }, + ] + const result = findCommonOrgUnitRoots(units, ['1', '2']) + expect(result).toEqual([ + { id: '1', path: unitToPath['sierra'], level: 1 }, + ]) + expect(units).toStrictEqual(units) + }) + + it('should return multiple root units when paths do not overlap', () => { + const units = [ + { id: '1', path: unitToPath['sierra'], level: 1 }, + { id: '2', path: unitToPath['tanzania'], level: 1 }, + { id: '3', path: unitToPath['ethiopia'], level: 1 }, + ] + const result = findCommonOrgUnitRoots(units, ['1', '2', '3']) + expect(result).toEqual([ + { id: '1', path: unitToPath['sierra'], level: 1 }, + { id: '2', path: unitToPath['tanzania'], level: 1 }, + { id: '3', path: unitToPath['ethiopia'], level: 1 }, + ]) + expect(units).toStrictEqual(units) + }) + + it('should filter org units where is in not part of the roots ids', () => { + const units = [ + { id: '1', path: unitToPath['sierra'], level: 1 }, + { id: '2', path: unitToPath['tanzania'], level: 1 }, + { id: '3', path: unitToPath['ethiopia'], level: 1 }, + ] + const result = findCommonOrgUnitRoots(units, ['1', '3']) + expect(result).toEqual([ + { id: '1', path: unitToPath['sierra'], level: 1 }, + { id: '3', path: unitToPath['ethiopia'], level: 1 }, + ]) + expect(units).toStrictEqual(units) + }) + + it('should return the correct root units when there is a mix of roots and children', () => { + const units = [ + { + id: '1', + path: unitToPath['sierra/bo/badjia/ngelehun'], + level: 4, + }, + { id: '2', path: unitToPath['sierra/bo/baoma/faabu'], level: 4 }, + { id: '3', path: unitToPath['sierra/bo/baoma'], level: 3 }, + { id: '4', path: unitToPath['sierra/bo/bargbe'], level: 3 }, + ] + const result = findCommonOrgUnitRoots(units, ['1', '2', '3', '4']) + expect(result).toEqual([ + { id: '3', path: unitToPath['sierra/bo/baoma'], level: 3 }, + { id: '4', path: unitToPath['sierra/bo/bargbe'], level: 3 }, + { + id: '1', + path: unitToPath['sierra/bo/badjia/ngelehun'], + level: 4, + }, + ]) + expect(units).toStrictEqual(units) + }) + + it('should return the root units when multiple nested children exist', () => { + const units = [ + { id: '1', path: unitToPath['sierra/bo'], level: 2 }, + { id: '2', path: unitToPath['sierra/bo/badjia'], level: 3 }, + { id: '3', path: unitToPath['sierra/bo/baoma'], level: 3 }, + { id: '4', path: unitToPath['sierra/bargbe/barlie'], level: 3 }, + { + id: '5', + path: unitToPath['sierra/bargbe/barlie/ngalu'], + level: 4, + }, + ] + const result = findCommonOrgUnitRoots(units, ['1', '2', '3', '4', '5']) + expect(result).toEqual([ + { id: '1', path: unitToPath['sierra/bo'], level: 2 }, + { id: '4', path: unitToPath['sierra/bargbe/barlie'], level: 3 }, + ]) + expect(units).toStrictEqual(units) + }) + + it('should handle empty input and return an empty array', () => { + const units = [] + const result = findCommonOrgUnitRoots(units) + expect(result).toEqual([]) + expect(units).toStrictEqual(units) + }) +}) diff --git a/components/organisation-unit-tree/src/organisation-unit-tree/organisation-unit-tree.js b/components/organisation-unit-tree/src/organisation-unit-tree/organisation-unit-tree.js index c9df120ddb..1877230608 100644 --- a/components/organisation-unit-tree/src/organisation-unit-tree/organisation-unit-tree.js +++ b/components/organisation-unit-tree/src/organisation-unit-tree/organisation-unit-tree.js @@ -1,10 +1,11 @@ import { requiredIf } from '@dhis2/prop-types' import PropTypes from 'prop-types' -import React, { useEffect, useState } from 'react' +import React, { useEffect, useMemo, useState } from 'react' import { OrganisationUnitNode } from '../organisation-unit-node/index.js' import { orgUnitPathPropType } from '../prop-types.js' import { defaultRenderNodeLabel } from './default-render-node-label/index.js' import { filterRootIds } from './filter-root-ids.js' +import { findCommonOrgUnitRoots } from './find-common-orgunit-roots.js' import { OrganisationUnitTreeRootError } from './organisation-unit-tree-root-error.js' import { OrganisationUnitTreeRootLoading } from './organisation-unit-tree-root-loading.js' import { useExpanded } from './use-expanded/index.js' @@ -49,6 +50,13 @@ const OrganisationUnitTree = ({ suppressAlphabeticalSorting, }) + const rootNodes = useMemo(() => { + if (!data) { + return [] + } + return findCommonOrgUnitRoots(Object.values(data), rootIds) + }, [data, rootIds]) + const { expanded, handleExpand, handleCollapse } = useExpanded({ initiallyExpanded, onExpand, @@ -79,36 +87,32 @@ const OrganisationUnitTree = ({ {error && } {!error && !isLoading && - rootIds.map((rootId) => { - const rootNode = data[rootId] - - return ( - - ) - })} + rootNodes.map((rootNode) => ( + + ))} ) } diff --git a/components/organisation-unit-tree/src/organisation-unit-tree/use-root-org-data/use-root-org-data.js b/components/organisation-unit-tree/src/organisation-unit-tree/use-root-org-data/use-root-org-data.js index c075f62ad6..1e2df21019 100644 --- a/components/organisation-unit-tree/src/organisation-unit-tree/use-root-org-data/use-root-org-data.js +++ b/components/organisation-unit-tree/src/organisation-unit-tree/use-root-org-data/use-root-org-data.js @@ -11,7 +11,7 @@ export const createRootQuery = (ids) => resource: `organisationUnits`, params: ({ isUserDataViewFallback }) => ({ isUserDataViewFallback, - fields: ['displayName', 'path', 'id'], + fields: ['displayName', 'path', 'id', 'level'], }), }, }), diff --git a/yarn.lock b/yarn.lock index d8cefb525b..576e9005a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1363,7 +1363,7 @@ core-js-pure "^3.30.2" regenerator-runtime "^0.14.0" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.3", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.6", "@babel/runtime@^7.20.13", "@babel/runtime@^7.21.0", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.8", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.3", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.6", "@babel/runtime@^7.20.13", "@babel/runtime@^7.21.0", "@babel/runtime@^7.23.8", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": version "7.25.0" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz" integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== @@ -2590,11 +2590,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== -"@esbuild/aix-ppc64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz#51299374de171dbd80bb7d838e1cfce9af36f353" - integrity sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ== - "@esbuild/android-arm64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz#7ad65a36cfdb7e0d429c353e00f680d737c2aed4" @@ -2605,11 +2600,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== -"@esbuild/android-arm64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz#58565291a1fe548638adb9c584237449e5e14018" - integrity sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw== - "@esbuild/android-arm@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.12.tgz#b0c26536f37776162ca8bde25e42040c203f2824" @@ -2620,11 +2610,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== -"@esbuild/android-arm@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.23.1.tgz#5eb8c652d4c82a2421e3395b808e6d9c42c862ee" - integrity sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ== - "@esbuild/android-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.12.tgz#cb13e2211282012194d89bf3bfe7721273473b3d" @@ -2635,11 +2620,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== -"@esbuild/android-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.23.1.tgz#ae19d665d2f06f0f48a6ac9a224b3f672e65d517" - integrity sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg== - "@esbuild/darwin-arm64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz#cbee41e988020d4b516e9d9e44dd29200996275e" @@ -2650,11 +2630,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== -"@esbuild/darwin-arm64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz#05b17f91a87e557b468a9c75e9d85ab10c121b16" - integrity sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q== - "@esbuild/darwin-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz#e37d9633246d52aecf491ee916ece709f9d5f4cd" @@ -2665,11 +2640,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== -"@esbuild/darwin-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz#c58353b982f4e04f0d022284b8ba2733f5ff0931" - integrity sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw== - "@esbuild/freebsd-arm64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz#1ee4d8b682ed363b08af74d1ea2b2b4dbba76487" @@ -2680,11 +2650,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== -"@esbuild/freebsd-arm64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz#f9220dc65f80f03635e1ef96cfad5da1f446f3bc" - integrity sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA== - "@esbuild/freebsd-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz#37a693553d42ff77cd7126764b535fb6cc28a11c" @@ -2695,11 +2660,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== -"@esbuild/freebsd-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz#69bd8511fa013b59f0226d1609ac43f7ce489730" - integrity sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g== - "@esbuild/linux-arm64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz#be9b145985ec6c57470e0e051d887b09dddb2d4b" @@ -2710,11 +2670,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== -"@esbuild/linux-arm64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz#8050af6d51ddb388c75653ef9871f5ccd8f12383" - integrity sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g== - "@esbuild/linux-arm@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz#207ecd982a8db95f7b5279207d0ff2331acf5eef" @@ -2725,11 +2680,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== -"@esbuild/linux-arm@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz#ecaabd1c23b701070484990db9a82f382f99e771" - integrity sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ== - "@esbuild/linux-ia32@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz#d0d86b5ca1562523dc284a6723293a52d5860601" @@ -2740,11 +2690,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== -"@esbuild/linux-ia32@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz#3ed2273214178109741c09bd0687098a0243b333" - integrity sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ== - "@esbuild/linux-loong64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz#9a37f87fec4b8408e682b528391fa22afd952299" @@ -2755,11 +2700,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== -"@esbuild/linux-loong64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz#a0fdf440b5485c81b0fbb316b08933d217f5d3ac" - integrity sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw== - "@esbuild/linux-mips64el@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz#4ddebd4e6eeba20b509d8e74c8e30d8ace0b89ec" @@ -2770,11 +2710,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== -"@esbuild/linux-mips64el@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz#e11a2806346db8375b18f5e104c5a9d4e81807f6" - integrity sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q== - "@esbuild/linux-ppc64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz#adb67dadb73656849f63cd522f5ecb351dd8dee8" @@ -2785,11 +2720,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== -"@esbuild/linux-ppc64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz#06a2744c5eaf562b1a90937855b4d6cf7c75ec96" - integrity sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw== - "@esbuild/linux-riscv64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz#11bc0698bf0a2abf8727f1c7ace2112612c15adf" @@ -2800,11 +2730,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== -"@esbuild/linux-riscv64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz#65b46a2892fc0d1af4ba342af3fe0fa4a8fe08e7" - integrity sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA== - "@esbuild/linux-s390x@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz#e86fb8ffba7c5c92ba91fc3b27ed5a70196c3cc8" @@ -2815,11 +2740,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== -"@esbuild/linux-s390x@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz#e71ea18c70c3f604e241d16e4e5ab193a9785d6f" - integrity sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw== - "@esbuild/linux-x64@0.19.12": version "0.19.12" resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz" @@ -2830,11 +2750,6 @@ resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz" integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== -"@esbuild/linux-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz#d47f97391e80690d4dfe811a2e7d6927ad9eed24" - integrity sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ== - "@esbuild/netbsd-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz#29da566a75324e0d0dd7e47519ba2f7ef168657b" @@ -2845,16 +2760,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== -"@esbuild/netbsd-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz#44e743c9778d57a8ace4b72f3c6b839a3b74a653" - integrity sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA== - -"@esbuild/openbsd-arm64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz#05c5a1faf67b9881834758c69f3e51b7dee015d7" - integrity sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q== - "@esbuild/openbsd-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz#306c0acbdb5a99c95be98bdd1d47c916e7dc3ff0" @@ -2865,11 +2770,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== -"@esbuild/openbsd-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz#2e58ae511bacf67d19f9f2dcd9e8c5a93f00c273" - integrity sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA== - "@esbuild/sunos-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz#0933eaab9af8b9b2c930236f62aae3fc593faf30" @@ -2880,11 +2780,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== -"@esbuild/sunos-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz#adb022b959d18d3389ac70769cef5a03d3abd403" - integrity sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA== - "@esbuild/win32-arm64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz#773bdbaa1971b36db2f6560088639ccd1e6773ae" @@ -2895,11 +2790,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== -"@esbuild/win32-arm64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz#84906f50c212b72ec360f48461d43202f4c8b9a2" - integrity sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A== - "@esbuild/win32-ia32@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz#000516cad06354cc84a73f0943a4aa690ef6fd67" @@ -2910,11 +2800,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== -"@esbuild/win32-ia32@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz#5e3eacc515820ff729e90d0cb463183128e82fac" - integrity sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ== - "@esbuild/win32-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz#c57c8afbb4054a3ab8317591a0b7320360b444ae" @@ -2925,11 +2810,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== -"@esbuild/win32-x64@0.23.1": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz#81fd50d11e2c32b2d6241470e3185b70c7b30699" - integrity sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg== - "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" @@ -8063,7 +7943,7 @@ depd@~1.1.2: resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== -dequal@^2.0.2, dequal@^2.0.3: +dequal@^2.0.2: version "2.0.3" resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== @@ -13463,7 +13343,7 @@ minimatch@3.0.4, minimatch@~3.0.2: dependencies: brace-expansion "^1.1.7" -minimatch@3.1.2, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@3.1.2, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -15635,7 +15515,7 @@ react-error-overlay@^6.0.11, react-error-overlay@^6.0.7: resolved "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz" integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg== -react-fast-compare@^3.0.1, react-fast-compare@^3.2.0, react-fast-compare@^3.2.2: +react-fast-compare@^3.0.1, react-fast-compare@^3.2.0: version "3.2.2" resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz" integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== @@ -15879,7 +15759,7 @@ read-yaml-file@^1.1.0: pify "^4.0.1" strip-bom "^3.0.0" -readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.2.0, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: +readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.2.0, readable-stream@^3.4.0, readable-stream@^3.5.0: version "3.6.2" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -16558,7 +16438,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -16617,13 +16497,6 @@ scheduler@^0.19.1: loose-envify "^1.1.0" object-assign "^4.1.1" -scheduler@^0.23.2: - version "0.23.2" - resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz" - integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== - dependencies: - loose-envify "^1.1.0" - schema-utils@2.7.0, schema-utils@^2.6.5: version "2.7.0" resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz" @@ -18452,11 +18325,6 @@ underscore@~1.13.2: resolved "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz" integrity sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g== -undici-types@~6.13.0: - version "6.13.0" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz" - integrity sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg== - undici-types@~6.19.2: version "6.19.8" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"