From 00ab05d22a6a1ff0378887e460283345934d03f1 Mon Sep 17 00:00:00 2001 From: Jen Jones Arnesen Date: Thu, 14 Sep 2023 12:11:10 +0200 Subject: [PATCH] fix: ou group filter crashes in custom widgets [v38] (#2693) Fixes DHIS2-14544 If path exists, then parse it, otherwise use id (which will be the case for groups, levels and USER_ORGUNITS) --- .d2styleignore | 1 + src/components/Item/AppItem/Item.js | 22 +--- .../AppItem/__tests__/getIframeSrc.spec.js | 106 ++++++++++++++++++ src/components/Item/AppItem/getIframeSrc.js | 15 +++ 4 files changed, 126 insertions(+), 18 deletions(-) create mode 100644 src/components/Item/AppItem/__tests__/getIframeSrc.spec.js create mode 100644 src/components/Item/AppItem/getIframeSrc.js diff --git a/.d2styleignore b/.d2styleignore index cc9010b2a..83af254cc 100644 --- a/.d2styleignore +++ b/.d2styleignore @@ -4,3 +4,4 @@ /src/locales/* /cypress/assets /cypress/fixtures +cypress.env.json diff --git a/src/components/Item/AppItem/Item.js b/src/components/Item/AppItem/Item.js index c6e50d71f..5c6bc9fa6 100644 --- a/src/components/Item/AppItem/Item.js +++ b/src/components/Item/AppItem/Item.js @@ -3,27 +3,13 @@ import { Divider, colors, spacers, IconQuestion24 } from '@dhis2/ui' import PropTypes from 'prop-types' import React from 'react' import { connect } from 'react-redux' -import { FILTER_ORG_UNIT } from '../../../actions/itemFilters' -import { EDIT, isEditMode } from '../../../modules/dashboardModes' +import { EDIT, isEditMode } from '../../../modules/dashboardModes.js' import { sGetItemFiltersRoot, DEFAULT_STATE_ITEM_FILTERS, -} from '../../../reducers/itemFilters' -import ItemHeader from '../ItemHeader/ItemHeader' - -const getIframeSrc = (appDetails, item, itemFilters) => { - let iframeSrc = `${appDetails.launchUrl}?dashboardItemId=${item.id}` - - if (itemFilters[FILTER_ORG_UNIT] && itemFilters[FILTER_ORG_UNIT].length) { - const ouIds = itemFilters[FILTER_ORG_UNIT].map( - ouFilter => ouFilter.path.split('/').slice(-1)[0] - ) - - iframeSrc += `&userOrgUnit=${ouIds.join(',')}` - } - - return iframeSrc -} +} from '../../../reducers/itemFilters.js' +import ItemHeader from '../ItemHeader/ItemHeader.js' +import { getIframeSrc } from './getIframeSrc.js' const AppItem = ({ dashboardMode, item, itemFilters }) => { const { d2 } = useD2() diff --git a/src/components/Item/AppItem/__tests__/getIframeSrc.spec.js b/src/components/Item/AppItem/__tests__/getIframeSrc.spec.js new file mode 100644 index 000000000..c6ce9d1e3 --- /dev/null +++ b/src/components/Item/AppItem/__tests__/getIframeSrc.spec.js @@ -0,0 +1,106 @@ +import { getIframeSrc } from '../getIframeSrc.js' + +const appDetails = { launchUrl: 'debug/dev' } +const dashboardItem = { id: 'rainbowdashitem' } +const expectedSrc = `${appDetails.launchUrl}?dashboardItemId=${dashboardItem.id}` + +describe('getIframeSrc', () => { + it('no ou filter', () => { + const ouFilter = [] + + const src = getIframeSrc(appDetails, dashboardItem, { ou: ouFilter }) + expect(src).toEqual(expectedSrc) + }) + + it('should return the correct iframe src', () => { + const ouFilter = [ + { + id: 'fdc6uOvgoji', + path: '/ImspTQPwCqd/fdc6uOvgoji', + name: 'Bombali', + }, + { + id: 'lc3eMKXaEfw', + path: '/ImspTQPwCqd/lc3eMKXaEfw', + name: 'Bonthe', + }, + ] + + const src = getIframeSrc(appDetails, dashboardItem, { ou: ouFilter }) + expect(src).toEqual( + `${expectedSrc}&userOrgUnit=fdc6uOvgoji,lc3eMKXaEfw` + ) + }) + + it('org unit group in filter', () => { + const ouFilter = [ + { + id: 'OU_GROUP-b0EsAxm8Nge', + name: 'Western Area', + }, + { + id: 'lc3eMKXaEfw', + path: '/ImspTQPwCqd/lc3eMKXaEfw', + name: 'Bonthe', + }, + ] + + const src = getIframeSrc(appDetails, dashboardItem, { ou: ouFilter }) + expect(src).toEqual( + `${expectedSrc}&userOrgUnit=OU_GROUP-b0EsAxm8Nge,lc3eMKXaEfw` + ) + }) + + it('org unit level in filter', () => { + const ouFilter = [ + { + id: 'LEVEL-m9lBJogzE95', + name: 'Facility', + }, + { + id: 'fdc6uOvgoji', + path: '/ImspTQPwCqd/fdc6uOvgoji', + name: 'Bombali', + }, + ] + + const src = getIframeSrc(appDetails, dashboardItem, { ou: ouFilter }) + expect(src).toEqual( + `${expectedSrc}&userOrgUnit=LEVEL-m9lBJogzE95,fdc6uOvgoji` + ) + }) + + it('user org unit in filter', () => { + const ouFilter = [ + { + id: 'USER_ORGUNIT', + displayName: 'User organisation unit', + }, + ] + + const src = getIframeSrc(appDetails, dashboardItem, { ou: ouFilter }) + expect(src).toEqual(`${expectedSrc}&userOrgUnit=USER_ORGUNIT`) + }) + + it('all user org units in filter', () => { + const ouFilter = [ + { + id: 'USER_ORGUNIT_CHILDREN', + displayName: 'User sub-units', + }, + { + id: 'USER_ORGUNIT_GRANDCHILDREN', + displayName: 'User sub-x2-units', + }, + { + id: 'USER_ORGUNIT', + displayName: 'User organisation unit', + }, + ] + + const src = getIframeSrc(appDetails, dashboardItem, { ou: ouFilter }) + expect(src).toEqual( + `${expectedSrc}&userOrgUnit=USER_ORGUNIT_CHILDREN,USER_ORGUNIT_GRANDCHILDREN,USER_ORGUNIT` + ) + }) +}) diff --git a/src/components/Item/AppItem/getIframeSrc.js b/src/components/Item/AppItem/getIframeSrc.js new file mode 100644 index 000000000..ae2b1c2c8 --- /dev/null +++ b/src/components/Item/AppItem/getIframeSrc.js @@ -0,0 +1,15 @@ +import { FILTER_ORG_UNIT } from '../../../actions/itemFilters.js' + +export const getIframeSrc = (appDetails, item, itemFilters) => { + let iframeSrc = `${appDetails.launchUrl}?dashboardItemId=${item.id}` + + if (itemFilters[FILTER_ORG_UNIT] && itemFilters[FILTER_ORG_UNIT].length) { + const ouIds = itemFilters[FILTER_ORG_UNIT].map(({ id, path }) => + path ? path.split('/').slice(-1)[0] : id + ) + + iframeSrc += `&userOrgUnit=${ouIds.join(',')}` + } + + return iframeSrc +}