From 5f03005443b90f71d5d056c1a702d5333e6e1726 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jan 2024 13:28:32 +0100 Subject: [PATCH 1/5] chore(deps): bump @dhis2/app-runtime from 3.9.4 to 3.10.2 (#3103) * chore(release): cut 100.3.0 [skip release] # [100.3.0](https://github.com/dhis2/maps-app/compare/v100.2.3...v100.3.0) (2024-01-12) ### Features * add support for hash routing in line with other analytics apps [DHIS2-15762] ([#3009](https://github.com/dhis2/maps-app/issues/3009)) ([b25267d](https://github.com/dhis2/maps-app/commit/b25267d33a8ab5a136f34516ba1bc802ae9e51b3)) * chore(deps): bump @dhis2/app-runtime from 3.9.4 to 3.10.2 Bumps [@dhis2/app-runtime](https://github.com/dhis2/app-runtime/tree/HEAD/runtime) from 3.9.4 to 3.10.2. - [Release notes](https://github.com/dhis2/app-runtime/releases) - [Changelog](https://github.com/dhis2/app-runtime/blob/master/CHANGELOG.md) - [Commits](https://github.com/dhis2/app-runtime/commits/v3.10.2/runtime) --- updated-dependencies: - dependency-name: "@dhis2/app-runtime" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --------- Signed-off-by: dependabot[bot] Co-authored-by: @dhis2-bot Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jen Jones Arnesen --- package.json | 2 +- yarn.lock | 108 ++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 81 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 1098e202c..5c86e8291 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ }, "dependencies": { "@dhis2/analytics": "^26.2.0", - "@dhis2/app-runtime": "^3.9.4", + "@dhis2/app-runtime": "^3.10.2", "@dhis2/app-runtime-adapter-d2": "^1.1.0", "@dhis2/app-service-alerts": "^3.9.4", "@dhis2/app-service-datastore": "^1.0.0-beta.3", diff --git a/yarn.lock b/yarn.lock index ee30f8a69..66cf96595 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2145,30 +2145,31 @@ dependencies: prop-types "^15.7.2" -"@dhis2/app-runtime@^3.9.0", "@dhis2/app-runtime@^3.9.4": - version "3.9.4" - resolved "https://registry.yarnpkg.com/@dhis2/app-runtime/-/app-runtime-3.9.4.tgz#88243dbb9a4a805be744a61cffd13a4c3d2d031d" - integrity sha512-CBwMXer5/Kcxf6MgfwPgpEaUSXbDXzwItCkH3i0nsjmkD0KIaEOZ6Y1pQL+/5RYnziZ5glYCFWsCKn0eCJrdJg== - dependencies: - "@dhis2/app-service-alerts" "3.9.4" - "@dhis2/app-service-config" "3.9.4" - "@dhis2/app-service-data" "3.9.4" - "@dhis2/app-service-offline" "3.9.4" - -"@dhis2/app-service-alerts@3.9.4", "@dhis2/app-service-alerts@^3.9.4": - version "3.9.4" - resolved "https://registry.yarnpkg.com/@dhis2/app-service-alerts/-/app-service-alerts-3.9.4.tgz#5aed2b191bb98bbf5eb14babb495b70f28b69aff" - integrity sha512-Oq2PZMcYyB+uXNwmifclv8oVobuKLTfN9ia7Gwa5G63c7Zjl4HldOxrM3TGDnsGYWfuGxtm8LNuzKfFX91HWmg== - -"@dhis2/app-service-config@3.9.4": - version "3.9.4" - resolved "https://registry.yarnpkg.com/@dhis2/app-service-config/-/app-service-config-3.9.4.tgz#4cab3a4ba090e53235f01c6a6913467171052d89" - integrity sha512-hiJr33zNWjUWJDx8l7tFMDfzX11euE+t6+ph2x9LnQ9KHDXFhh3GZhyQnX+8IATtlS4Fx9fjz2scQhGsg2dt0g== - -"@dhis2/app-service-data@3.9.4": - version "3.9.4" - resolved "https://registry.yarnpkg.com/@dhis2/app-service-data/-/app-service-data-3.9.4.tgz#03cd4cc40a316670d5ae328488cc8ef2a8a9b377" - integrity sha512-3AFwBkR1H8M6b+T5N3vcRsx9iiJm5LjltXYkbA9fmxcjJ02VoHa2B3a529pp8w9qSp7mpAF4Kmr3gZPvFpBRDA== +"@dhis2/app-runtime@^3.10.2", "@dhis2/app-runtime@^3.9.0": + version "3.10.2" + resolved "https://registry.yarnpkg.com/@dhis2/app-runtime/-/app-runtime-3.10.2.tgz#e82639bd68234bdeaf2f6d3c256dcdfcdd267da2" + integrity sha512-GiftKk8ZTXlPElXAgVJn41Vj6E1vEGTPGrjrqU7j41ZTYsg+tUcCkISNt1woe5l7E+8+y+9Fy4bgqSsBOAEUvg== + dependencies: + "@dhis2/app-service-alerts" "3.10.2" + "@dhis2/app-service-config" "3.10.2" + "@dhis2/app-service-data" "3.10.2" + "@dhis2/app-service-offline" "3.10.2" + "@dhis2/app-service-plugin" "3.10.2" + +"@dhis2/app-service-alerts@3.10.2", "@dhis2/app-service-alerts@^3.9.4": + version "3.10.2" + resolved "https://registry.yarnpkg.com/@dhis2/app-service-alerts/-/app-service-alerts-3.10.2.tgz#0e07c3530606f81ab998a20f2c478600b6027a77" + integrity sha512-2IqaawnlOzYVJLBF2AKVQJ4cuxJNZD7FK0XE0XOv1WwFs70h6bp23MQueIJ/QHxLo7lamE0FC22m4diM4P0CuA== + +"@dhis2/app-service-config@3.10.2": + version "3.10.2" + resolved "https://registry.yarnpkg.com/@dhis2/app-service-config/-/app-service-config-3.10.2.tgz#be52676068e31cdb1fe3f8ddabb8153e1cd6e3e6" + integrity sha512-Crw7Tx4yg4qWw3qYxNCIye77IaY2HUYyDmDKPVVWzgmrcSGxpunv/NtsUg12pxrVfVLnqlH9L6AF9A6hO0afmw== + +"@dhis2/app-service-data@3.10.2": + version "3.10.2" + resolved "https://registry.yarnpkg.com/@dhis2/app-service-data/-/app-service-data-3.10.2.tgz#e94d45d87cab5e156decfe9e92e3153e5df68ba0" + integrity sha512-+ESLrVEDQKXBaQmpaCq78RonkqJM2BliykaO4QBeOc4ilWohaqYajue1Ntg4uV2KrdkCylBdMDwGYjsak0G7hg== dependencies: react-query "^3.13.11" @@ -2185,13 +2186,20 @@ "@dhis2/app-service-data" "^2.1.1" uuid "^8.1.0" -"@dhis2/app-service-offline@3.9.4": - version "3.9.4" - resolved "https://registry.yarnpkg.com/@dhis2/app-service-offline/-/app-service-offline-3.9.4.tgz#ba4f3a916ca9a4c714fdedac51c66daa4f2c6bd7" - integrity sha512-vtv9V3Za/ukujPpqBRGkKZTloM2Cu29J+zHziyrTKC+hVsw8p3d4dHgXvpOGLcjq3ePAvEX4aEZK9+VCHnNFRQ== +"@dhis2/app-service-offline@3.10.2": + version "3.10.2" + resolved "https://registry.yarnpkg.com/@dhis2/app-service-offline/-/app-service-offline-3.10.2.tgz#082279b7045e702c2eecda751d762225313156b0" + integrity sha512-bTp+CCRbyKt/0QADj0O6wLNWhi+6QDkjt2+sfpv3M8oKcftjaQDqedVoypZRA0nqvSdVL2ehtTzqMrrxu6jtZQ== dependencies: lodash "^4.17.21" +"@dhis2/app-service-plugin@3.10.2": + version "3.10.2" + resolved "https://registry.yarnpkg.com/@dhis2/app-service-plugin/-/app-service-plugin-3.10.2.tgz#09de64ee59017c86c8dab96a0d2ca0d915ae9d31" + integrity sha512-FqR6ILmvAXT2n1SzCZknT+5jJRdajg1dBegWAu3xqZXAntsM4wvFLCx6EtjS5LO2Kga9VZ+TJmVr2UFX1330CQ== + dependencies: + post-robot "^10.0.46" + "@dhis2/app-shell@10.3.11": version "10.3.11" resolved "https://registry.yarnpkg.com/@dhis2/app-shell/-/app-shell-10.3.11.tgz#461a19159ae6938e705ab793005403327b1ad95b" @@ -4937,6 +4945,15 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +belter@^1.0.41: + version "1.0.190" + resolved "https://registry.yarnpkg.com/belter/-/belter-1.0.190.tgz#491857550ef240d9c66b56fc637991f5c3089966" + integrity sha512-jz05FHrO+bwitdI6JxV5ESyRdVhTcwMWQ7L4o+q/R4LNJFQrG58sp9EiwsSjhbihhiyYFcmmCMRRagxte6igtw== + dependencies: + cross-domain-safe-weakmap "^1" + cross-domain-utils "^2" + zalgo-promise "^1" + bfj@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/bfj/-/bfj-7.0.2.tgz#1988ce76f3add9ac2913fd8ba47aad9e651bfbb2" @@ -6155,6 +6172,20 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" +cross-domain-safe-weakmap@^1, cross-domain-safe-weakmap@^1.0.1: + version "1.0.29" + resolved "https://registry.yarnpkg.com/cross-domain-safe-weakmap/-/cross-domain-safe-weakmap-1.0.29.tgz#0847975c27d9e1cc840f24c1745311958df98022" + integrity sha512-VLoUgf2SXnf3+na8NfeUFV59TRZkIJqCIATaMdbhccgtnTlSnHXkyTRwokngEGYdQXx8JbHT9GDYitgR2sdjuA== + dependencies: + cross-domain-utils "^2.0.0" + +cross-domain-utils@^2, cross-domain-utils@^2.0.0: + version "2.0.38" + resolved "https://registry.yarnpkg.com/cross-domain-utils/-/cross-domain-utils-2.0.38.tgz#2eaf321c4dfdb61596805ca4233fde4400cb6377" + integrity sha512-zZfi3+2EIR9l4chrEiXI2xFleyacsJf8YMLR1eJ0Veb5FTMXeJ3DpxDjZkto2FhL/g717WSELqbptNSo85UJDw== + dependencies: + zalgo-promise "^1.0.11" + cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -12403,6 +12434,17 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== +post-robot@^10.0.46: + version "10.0.46" + resolved "https://registry.yarnpkg.com/post-robot/-/post-robot-10.0.46.tgz#39cea5b51033729390fc7c90be3285cd285f0377" + integrity sha512-EgVJiuvI4iRWDZvzObWes0X/n8olWBEJWxlSw79zmhpgkigX8UsVL4VOBhVtoJKwf0Y9qP9g2zOONw1rv80QbA== + dependencies: + belter "^1.0.41" + cross-domain-safe-weakmap "^1.0.1" + cross-domain-utils "^2.0.0" + universal-serialize "^1.0.4" + zalgo-promise "^1.0.3" + postcss-attribute-case-insensitive@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz#03d761b24afc04c09e757e92ff53716ae8ea2741" @@ -15734,6 +15776,11 @@ unique-string@^2.0.0: dependencies: crypto-random-string "^2.0.0" +universal-serialize@^1.0.4: + version "1.0.10" + resolved "https://registry.yarnpkg.com/universal-serialize/-/universal-serialize-1.0.10.tgz#3279bb30f47290ea479f45135620f98fa9d3f3a6" + integrity sha512-FdouA4xSFa0fudk1+z5vLWtxZCoC0Q9lKYV3uUdFl7DttNfolmiw2ASr5ddY+/Yz6Isr68u3IqC9XMSwMP+Pow== + universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -16689,6 +16736,11 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +zalgo-promise@^1, zalgo-promise@^1.0.11, zalgo-promise@^1.0.3: + version "1.0.48" + resolved "https://registry.yarnpkg.com/zalgo-promise/-/zalgo-promise-1.0.48.tgz#9e33eef502d5ed9f5a09fc5728c833c3e87afa2e" + integrity sha512-LLHANmdm53+MucY9aOFIggzYtUdkSBFxUsy4glTTQYNyK6B3uCPWTbfiGvSrEvLojw0mSzyFJ1/RRLv+QMNdzQ== + zip-stream@^2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-2.1.3.tgz#26cc4bdb93641a8590dd07112e1f77af1758865b" From 7c8455742ad9d231027be1175557469a02c40164 Mon Sep 17 00:00:00 2001 From: Jen Jones Arnesen Date: Wed, 24 Jan 2024 16:51:44 +0100 Subject: [PATCH 2/5] chore: add data table cypress test and enable orgunitinfo test (#3114) --- cypress/integration/dataTable.cy.js | 47 +++++++++++++++++++++++++ cypress/integration/mapDownload.cy.js | 12 +++++++ cypress/integration/orgUnitInfo.cy.js | 24 +++++++------ cypress/integration/routes.cy.js | 10 ++++++ src/components/core/Checkbox.js | 4 ++- src/components/datatable/BottomPanel.js | 1 + src/components/download/NorthArrow.js | 1 + 7 files changed, 87 insertions(+), 12 deletions(-) create mode 100644 cypress/integration/dataTable.cy.js diff --git a/cypress/integration/dataTable.cy.js b/cypress/integration/dataTable.cy.js new file mode 100644 index 000000000..ecfff1d48 --- /dev/null +++ b/cypress/integration/dataTable.cy.js @@ -0,0 +1,47 @@ +import { EXTENDED_TIMEOUT } from '../support/util.js' + +const map = { + id: 'eDlFx0jTtV9', + name: 'ANC: LLITN Cov Chiefdom this year', + downloadFileNamePrefix: 'ANC LLITN Cov Chiefdom this year', + cardTitle: 'ANC LLITN coverage', +} + +describe('data table', () => { + it('opens data table', () => { + cy.visit(`/#/${map.id}`, EXTENDED_TIMEOUT) + cy.get('canvas', EXTENDED_TIMEOUT).should('be.visible') + + cy.getByDataTest('moremenubutton').first().click() + + cy.getByDataTest('more-menu') + .find('li') + .not('.disabled') + .should('have.length', 6) + + cy.getByDataTest('more-menu') + .find('li') + .contains('Show data table') + .click() + + //check that the bottom panel is present + cy.getByDataTest('bottom-panel').should('be.visible') + + // check number of columns + cy.getByDataTest('bottom-panel') + .find('[role="columnheader"]') + .should('have.length', 10) + + // try the filtering + cy.getByDataTest('bottom-panel') + .find('[role="columnheader"]') + .containsExact('Name') + .siblings('input') + .type('Kakua') + + // check that the filter worked + cy.getByDataTest('bottom-panel') + .find('.ReactVirtualized__Table__row') + .should('have.length', 1) + }) +}) diff --git a/cypress/integration/mapDownload.cy.js b/cypress/integration/mapDownload.cy.js index ad7367475..93b23ed4a 100644 --- a/cypress/integration/mapDownload.cy.js +++ b/cypress/integration/mapDownload.cy.js @@ -70,6 +70,18 @@ describe('Map Download', () => { clickDownloadSetting('Show map name') cy.getByDataTest('download-map-info').find('h1').should('not.exist') + clickDownloadSetting('Show north arrow') + cy.getByDataTest('north-arrow').should('not.exist') + + clickDownloadSetting('Show overview map') + cy.getByDataTest('download-map-info') + .findByDataTest('overview-map') + .should('not.exist') + + clickDownloadSetting('Show legend') + cy.getByDataTest('download-map-info').should('not.exist') + + // and download the map cy.getByDataTest('download-settings') .find('button') .contains('Download') diff --git a/cypress/integration/orgUnitInfo.cy.js b/cypress/integration/orgUnitInfo.cy.js index 2c69f29e1..cc7439f09 100644 --- a/cypress/integration/orgUnitInfo.cy.js +++ b/cypress/integration/orgUnitInfo.cy.js @@ -1,23 +1,25 @@ -// import { ThematicLayer } from '../elements/thematic_layer.js' -import { EXTENDED_TIMEOUT } from '../support/util.js' +import { CURRENT_YEAR, EXTENDED_TIMEOUT } from '../support/util.js' -context('OrgUnitInfo', () => { - it.skip('opens the panel for an OrgUnit', () => { - cy.visit('/?id=ZBjCfSaLSqD', EXTENDED_TIMEOUT) - cy.wait(5000) // eslint-disable-line cypress/no-unnecessary-waiting +describe('OrgUnitInfo', () => { + it('opens the panel for an OrgUnit', () => { + cy.visit('/#/ZBjCfSaLSqD', EXTENDED_TIMEOUT) cy.get('canvas').should('be.visible') + cy.wait(5000) // eslint-disable-line cypress/no-unnecessary-waiting - cy.getByDataTest('dhis2-map-container') + cy.get('#dhis2-map-container') .findByDataTest('dhis2-uicore-componentcover', EXTENDED_TIMEOUT) .should('not.exist') - cy.get('.dhis2-map').click(300, 100) //Bombali - cy.contains('View profile').click() + cy.get('.dhis2-map').click(350, 350) //Click somewhere on the map + + cy.get('.maplibregl-popup').contains('View profile').click() // check the Org Unit Profile panel cy.getByDataTest('org-unit-profile').contains( 'Organisation unit profile' ) - cy.getByDataTest('org-unit-info').find('h3').contains('Bombali') + + // // TODO - find a way to ensure that "Bombali" is the orgunit that was clicked on + // // cy.getByDataTest('org-unit-info').find('h3').contains('Bombali') cy.getByDataTest('org-unit-data') .findByDataTest('button-previous-year') @@ -27,7 +29,7 @@ context('OrgUnitInfo', () => { .findByDataTest('dhis2-uicore-circularloader') .should('not.exist') - cy.getByDataTest('year-select').contains('2022') + cy.getByDataTest('year-select').contains(CURRENT_YEAR - 1) cy.getByDataTest('org-unit-data-table').contains('Expected pregnancies') }) diff --git a/cypress/integration/routes.cy.js b/cypress/integration/routes.cy.js index 0e12826e4..0153b3054 100644 --- a/cypress/integration/routes.cy.js +++ b/cypress/integration/routes.cy.js @@ -82,6 +82,16 @@ context('Routes', () => { 'Viewing interpretation: ANC: LLITN coverage district and facility' ) .should('be.visible') + + cy.getByDataTest('interpretation-modal') + .find('canvas') + .should('be.visible') + + cy.getByDataTest('interpretation-modal') + .contains( + 'Koinadugu has a very high LLITN coverage despite low density of facilities providing nets.' + ) + .should('be.visible') }) it('loads with map id (legacy) and interpretationId uppercase', () => { diff --git a/src/components/core/Checkbox.js b/src/components/core/Checkbox.js index e32ea0bfe..71cdeebad 100644 --- a/src/components/core/Checkbox.js +++ b/src/components/core/Checkbox.js @@ -13,8 +13,9 @@ const Checkbox = ({ tooltip, onChange, className, + dataTest, }) => ( -
+
{ ref={panelRef} className={styles.bottomPanel} style={{ height: tableHeight }} + data-test="bottom-panel" > Date: Thu, 25 Jan 2024 10:07:46 +0100 Subject: [PATCH 3/5] chore(dependencies): upgrade ui to v9 (#3115) set resolution to ^9 since cli-app-scripts hasn't been upgraded to ui^9 yet. --- package.json | 7 +- yarn.lock | 895 ++++++++++++++++++++++++++------------------------- 2 files changed, 453 insertions(+), 449 deletions(-) diff --git a/package.json b/package.json index 5c86e8291..0678986a0 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "postinstall": "patch-package" }, "devDependencies": { - "@dhis2/cli-app-scripts": "^10.3.11", + "@dhis2/cli-app-scripts": "^10.4.0", "@dhis2/cli-style": "^10.5.1", "@dhis2/cypress-commands": "^10.0.3", "@dhis2/cypress-plugins": "^10.0.3", @@ -46,7 +46,7 @@ "@dhis2/app-service-datastore": "^1.0.0-beta.3", "@dhis2/d2-i18n": "^1.1.3", "@dhis2/maps-gl": "^3.8.6", - "@dhis2/ui": "^8.16.0", + "@dhis2/ui": "^9.2.0", "@krakenjs/post-robot": "^11.0.0", "@reportportal/agent-js-cypress": "git+https://github.com/dhis2/agent-js-cypress.git#develop", "@reportportal/agent-js-jest": "^5.0.7", @@ -80,5 +80,8 @@ "redux-thunk": "^2.4.2", "styled-jsx": "^4.0.1", "url-polyfill": "^1.1.12" + }, + "resolutions": { + "@dhis2/ui": "^9.2.0" } } diff --git a/yarn.lock b/yarn.lock index 66cf96595..7add303b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1529,583 +1529,583 @@ debug "^3.1.0" lodash.once "^4.1.1" -"@dhis2-ui/alert@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/alert/-/alert-8.16.0.tgz#589b8243b3d6133d1f2b226ac9dc9df0803f5872" - integrity sha512-PfuSxm5K+xxbPVZU82L0U26KMbOdNx+sFFLMEWHukDhCSuja7zp64EzkX0iT/KfDBHBdbxF9G9fwyATA84Dnlg== +"@dhis2-ui/alert@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/alert/-/alert-9.2.0.tgz#3b30e90a88a96c617219c60ad8bc16a5969e85d1" + integrity sha512-9uh6vIKlj9vm9wOr/7UvSvxrEgl0p99+FdfFtvCeiOywR2+CCPvd9fRsL/vWKcCraopOriCmTm5PzBUWPuatvg== dependencies: - "@dhis2-ui/portal" "8.16.0" + "@dhis2-ui/portal" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/box@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/box/-/box-8.16.0.tgz#23741e67254e1b48dd9bebfe726e8a2f1b407e3e" - integrity sha512-vrKNXC03ZUAUL0YaAa43XhHpCSMNTn4Fu4GUmzQg0Jb+3ALp4+D+WBQzVWaZYMSqesDiOPS1ZB4z65QUMAAawQ== +"@dhis2-ui/box@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/box/-/box-9.2.0.tgz#0f8fd79059d724c075180ea442c860ebff88c802" + integrity sha512-ERNEd8lDAQIGDmTYknWClPGbmWuOpFAnE8XurB6wrkydn0M2+wsIa00q2on6RgY2YaAjVtYZEXr9CfjBtwh04w== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/button@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/button/-/button-8.16.0.tgz#f78b7dffcb3414fa8210db1b9d62c9414d6544ba" - integrity sha512-YCsNgRzCoazZ1RjmJUckACqy4iL76wOJoFMRnP+7AzOFU8myEFZakPnihR6dxsjxSCTsQTBebRMmmGRNp259wg== +"@dhis2-ui/button@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/button/-/button-9.2.0.tgz#8d465f471ca629e1cb0ded01fc68143eb4960c1c" + integrity sha512-YBdIpaOqEgpI0JhHm8XBlpFGDF7O6eiFQ4Noxu131KEyDOf7a+AkIyECVZw6Jsj3n2zrbyzBDw6IndSFSlBqRQ== dependencies: - "@dhis2-ui/layer" "8.16.0" - "@dhis2-ui/loader" "8.16.0" - "@dhis2-ui/popper" "8.16.0" + "@dhis2-ui/layer" "9.2.0" + "@dhis2-ui/loader" "9.2.0" + "@dhis2-ui/popper" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/calendar@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/calendar/-/calendar-8.16.0.tgz#3c64736ddb87195699c9db3219b2b2e56345b3fc" - integrity sha512-B+EI/t9r1Ed8XQ3dNmnZl/NSXiee4IV9DpNcCIwOV6K9OZ23/zt1L4QaRjI7u3/F5JeguxRg5EtUX4oZBdUFDw== +"@dhis2-ui/calendar@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/calendar/-/calendar-9.2.0.tgz#c3fbcdc622a13dd112de163719cfdcd0f960cfe2" + integrity sha512-6xxkCx66tjfGffGoPnDB6pe9Pvx+UybAGCqof7/0xfHP2vnfdss716imM02HfJRZwp5dNUrXqBO9uuQ1qkp/HA== dependencies: - "@dhis2-ui/button" "8.16.0" - "@dhis2-ui/card" "8.16.0" - "@dhis2-ui/input" "8.16.0" - "@dhis2-ui/layer" "8.16.0" - "@dhis2-ui/popper" "8.16.0" + "@dhis2-ui/button" "9.2.0" + "@dhis2-ui/card" "9.2.0" + "@dhis2-ui/input" "9.2.0" + "@dhis2-ui/layer" "9.2.0" + "@dhis2-ui/popper" "9.2.0" "@dhis2/multi-calendar-dates" "1.0.2" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/card@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/card/-/card-8.16.0.tgz#86dbd4d1e219de1d08a15d132fb7b402609006ad" - integrity sha512-7Y2xmyUL6omqwhsj3j9OzMfw7c/jWOXb2mWO0YYHroxreViHDadi6jbROp2iJbS38FfA6Svn5R+rWaVs6IJ9xQ== +"@dhis2-ui/card@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/card/-/card-9.2.0.tgz#1a2d8f2f9becfd9fd43e7e315fda511418698fd1" + integrity sha512-++eLieBc4WsNXD1iQEQaqijnQ7hpKu0HH9cjkwTa46jjI9SoJGdYInvCzZPafB1XuCZ42f08kTcdND2qZWbssQ== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/center@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/center/-/center-8.16.0.tgz#eff8d9a5e663d1a541a23d6d0b715351738f116b" - integrity sha512-ELfUaNaayaX6CFFijGJV3phNIj6pNFv32yS14Pmu7K9SbpnhIFqIB/Zepg6KkCxClqKXX1ALqwBXhaEWROVAXQ== +"@dhis2-ui/center@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/center/-/center-9.2.0.tgz#f7fbcbd00696d718286f269a64a5bad327160449" + integrity sha512-IBwLld/SQEtT5acjBr3nJnpkXNzypxm9f+QfdGYRq2ZSQmkIv9IUjIvlC25CU72Ksq+N0nWvA8AYp2Qx/l04fg== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/checkbox@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/checkbox/-/checkbox-8.16.0.tgz#55c7d95bfab6d70c3dd30f85e9b60debce00edad" - integrity sha512-yAP//QBULxaq7c2KjwY6YwIEkqP77AoMh6sSmh1yfQaYtiGO79c+T4Na8Acqt847ERhylKWtkoFyOu6S4ol6QA== +"@dhis2-ui/checkbox@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/checkbox/-/checkbox-9.2.0.tgz#7f27c645bb9d31df4898c9c96cfdabf9ddd01ab3" + integrity sha512-EIGbkdnCLOyW3s7Mh31LdPgghHPaTAt0MJe5ieF/1NycUCfx99NGoR7wXlAlI6wNvjkuTYnYBknERGHUEzY9rA== dependencies: - "@dhis2-ui/field" "8.16.0" - "@dhis2-ui/required" "8.16.0" + "@dhis2-ui/field" "9.2.0" + "@dhis2-ui/required" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/chip@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/chip/-/chip-8.16.0.tgz#976c1c4b0ab067ce24df37b1293126b12753a455" - integrity sha512-AglEijghZT6LTAIMy0aID1vp22hjxBN5GYF1chLFEujBm1Pt10ld35URU6CpHlEgreWUCjKMllNa4IpCJO1IUw== +"@dhis2-ui/chip@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/chip/-/chip-9.2.0.tgz#45b5e55e6d11318bb6917f1bcdee9bf9b67bd620" + integrity sha512-PesbKz0MrXegDAFcGHq34Ast0kM/mJrmExiLua262egYYaRiQXDYeaNuS2TT+qPsPsDva2Pp7kqjdrFRDL2Few== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/cover@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/cover/-/cover-8.16.0.tgz#88b63ffb99c209b3327a3e7d50d519074ce06bab" - integrity sha512-4xKMzt4cOb3MFQMoK42gmhJXJKW5BiRloToC7PnLCZnnXNzuLIXrQ5rxz0C8vJ/+rh7g8XLjOhLCXCEJjMAp4w== +"@dhis2-ui/cover@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/cover/-/cover-9.2.0.tgz#0288dad0ba9caf8c0b77c86868fc4bae3388f6c7" + integrity sha512-ZxcOOuyy/dB4pgjdVzBlgwtVue0HEct2XOiuIKM66F5G0DPBqz6UtLDD+8VRofQwTKcTYQh9kPZPmx/9q65Zcg== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/css@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/css/-/css-8.16.0.tgz#fee49707a209c62da05e9cb221372874f12401e9" - integrity sha512-O5YVBv8EFnw30xMgPopcAmkpcsVc99XuARv+3rxpMxfOuVtH0Y6BjWh/RJhvZLYc4OrfsrQDRoIlhvZUKGRv/A== +"@dhis2-ui/css@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/css/-/css-9.2.0.tgz#ad881b90371c7506690ee2a2b2151c09f793e368" + integrity sha512-dBe9S75+Nj1c9SNRkxU0VWTVwFZJ+vLFKxD1UYaPdbJ2DHD6AD4UJ1YtXgvBvgiJ0wbT1vesh3tKfEUXbnTmkw== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/divider@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/divider/-/divider-8.16.0.tgz#afc0d8104e433372bbdee63ff508ffef88d12800" - integrity sha512-Zomxz5Z87G4UP1VmTlLrpc19gQmlCtABDxVyirIMv7ZnUXUozj0KFzhO6VJAF7qPo5Q4cKV/6ZkprPwYAN4I9A== +"@dhis2-ui/divider@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/divider/-/divider-9.2.0.tgz#2f9ea2f3a1f89853963bcffdeef27e5ebc390021" + integrity sha512-z87v4XKIO1IXhWmHYhCQgR7MTiuU+zLMg9Py2OIDxMchVXrdyGSeKCpL9UgOzl/jtHxwoMdnVDzy8sLLzITgsw== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/field@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/field/-/field-8.16.0.tgz#d985198ada6f857f88a9b7023b095dfcc1f7c649" - integrity sha512-aaEwfxenl1MU7Kv2r5r7nwjVtIUH4zSZFSSBXBYQQlirsTTjsJWlbo4urnY5y649OpqJnSoiaZTndhKMGk/MHg== +"@dhis2-ui/field@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/field/-/field-9.2.0.tgz#d16b443ff168e352b6f5168d2179975377902dd1" + integrity sha512-pZr1LkzOm4TOPdPAen9e3RHQE8Y1uCbdFhP1oc5vg44etmudX7stJuEXP6/DrPm6sHCJRojf90laqPai1vfrHg== dependencies: - "@dhis2-ui/box" "8.16.0" - "@dhis2-ui/help" "8.16.0" - "@dhis2-ui/label" "8.16.0" + "@dhis2-ui/box" "9.2.0" + "@dhis2-ui/help" "9.2.0" + "@dhis2-ui/label" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/file-input@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/file-input/-/file-input-8.16.0.tgz#2bae2a4312aa8848c91413d21bb081058705898c" - integrity sha512-C6DnqUidG8+GIan0+b7dvQQnJilBvd98DlKC2FrrnSq0gtkf5TI0nY7U8GMjaupRVy3kJ0M4dIYIGvWatJgXAg== +"@dhis2-ui/file-input@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/file-input/-/file-input-9.2.0.tgz#d48e9d290aea798640b251d915b9a8f51abcf363" + integrity sha512-x+lKilo6aQN320fIAPZMAq13PxKuTb/jhZb7m7pMS0HKsPqfT5rWm1VfmBlN/02BkKsmhsvo/tTe9vxpAic71A== dependencies: - "@dhis2-ui/button" "8.16.0" - "@dhis2-ui/field" "8.16.0" - "@dhis2-ui/label" "8.16.0" - "@dhis2-ui/loader" "8.16.0" - "@dhis2-ui/status-icon" "8.16.0" + "@dhis2-ui/button" "9.2.0" + "@dhis2-ui/field" "9.2.0" + "@dhis2-ui/label" "9.2.0" + "@dhis2-ui/loader" "9.2.0" + "@dhis2-ui/status-icon" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/header-bar@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/header-bar/-/header-bar-8.16.0.tgz#43b94c1e3ce337d2e3d39026ba43fc2e637d9408" - integrity sha512-UwyhAU3MUYfmfKVp7IE0A0CSwxwGQveuxNFRpZh+LpWO2pC7/gkb7Tv2ISfrIdf8R+a/FU6SUkmKp7iWFyz3Eg== - dependencies: - "@dhis2-ui/box" "8.16.0" - "@dhis2-ui/button" "8.16.0" - "@dhis2-ui/card" "8.16.0" - "@dhis2-ui/center" "8.16.0" - "@dhis2-ui/divider" "8.16.0" - "@dhis2-ui/input" "8.16.0" - "@dhis2-ui/layer" "8.16.0" - "@dhis2-ui/loader" "8.16.0" - "@dhis2-ui/logo" "8.16.0" - "@dhis2-ui/menu" "8.16.0" - "@dhis2-ui/modal" "8.16.0" - "@dhis2-ui/user-avatar" "8.16.0" +"@dhis2-ui/header-bar@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/header-bar/-/header-bar-9.2.0.tgz#83efe93821318decca3bd1a28d30fd3089435b6d" + integrity sha512-7iNKOllQNeYfa9nJjXVqiohcuKEk+RMhuu/7BY8g2oPmwbvS0uc49KiL53cFfAWBST/v5fU1XOpWS/N7PmJr2g== + dependencies: + "@dhis2-ui/box" "9.2.0" + "@dhis2-ui/button" "9.2.0" + "@dhis2-ui/card" "9.2.0" + "@dhis2-ui/center" "9.2.0" + "@dhis2-ui/divider" "9.2.0" + "@dhis2-ui/input" "9.2.0" + "@dhis2-ui/layer" "9.2.0" + "@dhis2-ui/loader" "9.2.0" + "@dhis2-ui/logo" "9.2.0" + "@dhis2-ui/menu" "9.2.0" + "@dhis2-ui/modal" "9.2.0" + "@dhis2-ui/user-avatar" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" moment "^2.29.1" prop-types "^15.7.2" -"@dhis2-ui/help@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/help/-/help-8.16.0.tgz#d1d3abc06aace2f753d0e89300bbd15ca03be343" - integrity sha512-5Ag6d92iFpB2gJfIXx0bodHnuv0J9FWMnMkVscfOS2LiIFHzJNrR/iEnXmbFSzLBaPvE4gFjmAZ0WskDXdPt+g== +"@dhis2-ui/help@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/help/-/help-9.2.0.tgz#76556c0d581fb0f7611fe5c5bb0d9adf35ad0c8e" + integrity sha512-qD3oNEwEb+pT7jsD4ciHtu16KrxMySPWoqco5nJwoGbcZFLw/caEfkBo2IroImD0MxtI0mKt5emD7V2yXRWm7A== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/input@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/input/-/input-8.16.0.tgz#ac14629d11a492f658b992937f8ee3edc4f14857" - integrity sha512-Zn+Jo+NkVJSHdKwWz9WMPYmnKRDM/metSjnDdAZ2guIS820dNCPgsbC1+DOgMKVxtl+DSb0e+05niIVwsAIELA== +"@dhis2-ui/input@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/input/-/input-9.2.0.tgz#bdf7c72e11b818ed86e1e6335cd373ae037f4ef3" + integrity sha512-0bzF/8pZSMqe5ZN2v0t0/rMTvKWd9kl5MDOy9fRXpX6yoFgfH+j+iIU06eVyqJl3DMqCdInfapJvpJR7MHvd+g== dependencies: - "@dhis2-ui/box" "8.16.0" - "@dhis2-ui/field" "8.16.0" - "@dhis2-ui/input" "8.16.0" - "@dhis2-ui/loader" "8.16.0" - "@dhis2-ui/status-icon" "8.16.0" + "@dhis2-ui/box" "9.2.0" + "@dhis2-ui/field" "9.2.0" + "@dhis2-ui/input" "9.2.0" + "@dhis2-ui/loader" "9.2.0" + "@dhis2-ui/status-icon" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/intersection-detector@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/intersection-detector/-/intersection-detector-8.16.0.tgz#c525b9a7bc2268e0cc063e4a1f30c37c79be6262" - integrity sha512-z8b9RjRBG5PgRgB85ltUC+toN2IgXCHmMXpxyAfEL3tE4asej4y75cWLafY1sO8QkwwHJBAlEq0IrPUS8ggKzw== +"@dhis2-ui/intersection-detector@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/intersection-detector/-/intersection-detector-9.2.0.tgz#31f19bfb8645ebda7d7af6f6e641b40fa1e57888" + integrity sha512-erBoDMhOPmua8eP8bKJNl4WIUUm+Fw3Jj9M0OxC+xia3/Fi8scLUyk0Yek1Y0lGdb4YHJEXqx475dLNjpmiLRQ== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/label@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/label/-/label-8.16.0.tgz#c6558ed1076c6d0955898135917cc3bf64d3a5e8" - integrity sha512-OrtE4ZfDH3lBApL1mR/eZ1Ndr14V/FwgUoER9Xw9Zmt8vNGhtYHkWzLzwnzsSiV0gkJ0rHF/SU7nctVOWdQQjQ== +"@dhis2-ui/label@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/label/-/label-9.2.0.tgz#81ec2de2ea1b9bc7cf25eb8bb036d451d5b61748" + integrity sha512-k9Q4XyIbaNRvCn1+rLcEb/iDi479S3fOEJ2MCT6wsGxr1+Hys7yVw7Ggq0OQ9SLCEwElNQcvj+vWB4dZltXl5Q== dependencies: - "@dhis2-ui/required" "8.16.0" + "@dhis2-ui/required" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/layer@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/layer/-/layer-8.16.0.tgz#f2b9b1de1770c8584e5b3cdc217b1ba11039a8b1" - integrity sha512-GHIud7bFoXPSBGkkiJXCQqnYuEh0eXllF62eJTnFu3iMzoroepylxiDLDXzQMhxc1bCmkQBEgX5aNzT3riHH5A== +"@dhis2-ui/layer@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/layer/-/layer-9.2.0.tgz#7afcb2ef8571eb9c839fc522eb76ead70e395dbc" + integrity sha512-95aFgQYxgJ7GmWY6AOSoAH4BH7wkIyUAioAIRUDwp0mmSJhJxG6P9b1PFqw4koX1zV4/RLoz+NiQ7Twv+03CLQ== dependencies: - "@dhis2-ui/portal" "8.16.0" + "@dhis2-ui/portal" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/legend@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/legend/-/legend-8.16.0.tgz#0c89f557b1feb3b229d9f63772f1d3c54af559a9" - integrity sha512-0RNCMh6KAo/wIsbvi0cAvTNCbDd517iF/IJ7pugSCHflACrN0i+p/ZqL/bXcXlI7pM6dssn1tjto4qvcyncuUQ== +"@dhis2-ui/legend@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/legend/-/legend-9.2.0.tgz#a051822fd67c1442b6986a86097aca94f3960dd2" + integrity sha512-IfJhu48eu//O9AlHt7IUdsv5E92XG7v/95laFfyQOaGhf1C4BQf11s6yXc3nTFoil/p55oAsZnWp5e7UXcgrhg== dependencies: - "@dhis2-ui/required" "8.16.0" + "@dhis2-ui/required" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/loader@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/loader/-/loader-8.16.0.tgz#cd3a7736e65c7096175ccfca68ede041ce441129" - integrity sha512-AyHID3Wftk6j4n6hoHpjx4OZF3ENtDBcOIrSVCbLpv+y14m06RZk0T6wekSnplW/1zCFruS5vLZNR7aYJEKIyA== +"@dhis2-ui/loader@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/loader/-/loader-9.2.0.tgz#f45fdb19a37182351932cd3e11980d43b4895d40" + integrity sha512-M8tuLE5kgm7oHmIN6par8GfRDpmt+DXFU3cCSZdiYIUM6SQSD8G5LmA8AaIHR5h7l430d93vcw7RQL3eeE/svw== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/logo@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/logo/-/logo-8.16.0.tgz#b600ad9db431a7e478cc53b9b0ba09a0cc9a51af" - integrity sha512-5NXPKRKEZN99DXP2TOHTximelZZh43qYUWgcVmB7RkiM7EBKaNQkz1LtP6cV5yv2Jr4RQtW3Myg690Wtgg+VNg== +"@dhis2-ui/logo@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/logo/-/logo-9.2.0.tgz#0452aadd8e92afc1c558869a08c8e5d1f14ff55f" + integrity sha512-OEFrSpDijeCIhLjJ8vipDGRdihTgj8+iLcPLDrOeRAurlgJZJZiicxBKSuY6uc6p1/9QPccqX2huJjM1uNqo2g== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/menu@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/menu/-/menu-8.16.0.tgz#31fa42d534cf34cfa07c1ecfe16877226e3f7d5e" - integrity sha512-oT7UVlMAM3xl5WDpdVjAgcHG5d9ACza+bUsMAXNURT0ceW1kD6OKLfmNNJOixpudwmZ45G6b1gBUqVQ3REXNTg== +"@dhis2-ui/menu@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/menu/-/menu-9.2.0.tgz#996729545b29def9366a099005a17c781bdca8f6" + integrity sha512-8k15qmoqBWKo1Afj+QXFnDAIoDyAqosvq3j8M/+xM+cSn0H+6e3Q7UOp0ByVQlumoY5DyrT9Z7NojULIjFUifQ== dependencies: - "@dhis2-ui/card" "8.16.0" - "@dhis2-ui/divider" "8.16.0" - "@dhis2-ui/layer" "8.16.0" - "@dhis2-ui/popper" "8.16.0" - "@dhis2-ui/portal" "8.16.0" + "@dhis2-ui/card" "9.2.0" + "@dhis2-ui/divider" "9.2.0" + "@dhis2-ui/layer" "9.2.0" + "@dhis2-ui/popper" "9.2.0" + "@dhis2-ui/portal" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/modal@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/modal/-/modal-8.16.0.tgz#7c5b193533e00070fbb9e0699180853463dbc6fd" - integrity sha512-RJb6UTMoU1juuc4V5hIJj59YokZ4WoqbQoyjGfWMSf5zFfXAWT36HlOTnew322dekZA5CGt0hcxlcuqpbRaJjQ== +"@dhis2-ui/modal@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/modal/-/modal-9.2.0.tgz#7815efe62be4f482b2e2224ffe92981068b1bae9" + integrity sha512-gp+gCTmtoiLVAhigo1i6msE598qIGnkW6To+dTkUecvxyvni+DZTAulTmL62UtTzzjPjYO0yOqNTWQztbpj1KQ== dependencies: - "@dhis2-ui/card" "8.16.0" - "@dhis2-ui/center" "8.16.0" - "@dhis2-ui/layer" "8.16.0" - "@dhis2-ui/portal" "8.16.0" + "@dhis2-ui/card" "9.2.0" + "@dhis2-ui/center" "9.2.0" + "@dhis2-ui/layer" "9.2.0" + "@dhis2-ui/portal" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/node@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/node/-/node-8.16.0.tgz#9dd9e8c99d036297eb6f2da38c07e50739ce6585" - integrity sha512-QpwwKuIK8Z+DlYB9LhXe8NWQNJdZBotjl0qU8faltVIsRGC76YzT1jbcIMvxKcVRaQOdNQtMt1uOYd4KCnA04Q== +"@dhis2-ui/node@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/node/-/node-9.2.0.tgz#3560b3e7394d275c1bce3e800b2654cddcd2adb2" + integrity sha512-xx7P/6V7vq3JLXUUATKGGUCORHqQL74fsGYUd9a0izyUyq4h3pEHL9ZT6Cel+A0d5ODYn/j/Q6fHICZzg55FBQ== dependencies: - "@dhis2-ui/loader" "8.16.0" + "@dhis2-ui/loader" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/notice-box@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/notice-box/-/notice-box-8.16.0.tgz#a1878418e0591cfa0382b6f947559a25d5ca351c" - integrity sha512-TulrAmzU3MXs1l1xqwikOtSRivkQKC2RLBta+ZRAXGEqH0VFUoDkk9OtTZ0QsNJRAXs/NHQZ2REhZfRCaiWI7w== +"@dhis2-ui/notice-box@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/notice-box/-/notice-box-9.2.0.tgz#8c1fb4a2a780fea0fde4b8f9eaf8f73957187c99" + integrity sha512-DY3WYXj1hsOsiBHGaNrOeZ8h7SPaXox6iMCTzL/jLvnfmTrH7wy6SHRLQYWg0BMrDflhMJu9qhn0jtzhEXZNMQ== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/organisation-unit-tree@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/organisation-unit-tree/-/organisation-unit-tree-8.16.0.tgz#b491f6f7f76f5d68b0be597e241553d1f150c4ed" - integrity sha512-VkqwNz2bqiOuP3bsnKeuReraQzhKe+R4dtPIjPUZpe+vA78uQfcsOB1OUK3JqI/9qL8eL0RYepoACHQwb+1MNw== +"@dhis2-ui/organisation-unit-tree@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/organisation-unit-tree/-/organisation-unit-tree-9.2.0.tgz#ce33d91361145d6574ddbef3866b56be06cee6cb" + integrity sha512-PHm908gNGPhq5D655BI4lrB+hMqfISKASjoFCWxG2f9FU64/pvQ+snZQQwQFMAJYMd6FKw4GOP1isKz0jTGNuA== dependencies: - "@dhis2-ui/checkbox" "8.16.0" - "@dhis2-ui/loader" "8.16.0" - "@dhis2-ui/node" "8.16.0" + "@dhis2-ui/checkbox" "9.2.0" + "@dhis2-ui/loader" "9.2.0" + "@dhis2-ui/node" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/pagination@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/pagination/-/pagination-8.16.0.tgz#f50b7408f48e77134c9c1457a77fde07cb166aa8" - integrity sha512-oytevq4Bb0fGXeL3hVBz7P5dGBxSpenV0AOhNA3W7m7/UNSmFJXJjWRB+nvHS6jcq0/gxNJvEZctGF/zlViyVQ== +"@dhis2-ui/pagination@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/pagination/-/pagination-9.2.0.tgz#f38d1ada2bc9f9795dae8f86c52d54f29889dd17" + integrity sha512-jXJNQ8JOPweeMFCsPXgAb8dAx8J/rNTnExL8WA6rfRDWujOojLp8Gu2MrH5jlHRpCBWIl+aJO1I/ZKHekQOeDg== dependencies: - "@dhis2-ui/button" "8.16.0" - "@dhis2-ui/select" "8.16.0" + "@dhis2-ui/button" "9.2.0" + "@dhis2-ui/select" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/popover@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/popover/-/popover-8.16.0.tgz#e01dfa4d9ceb50b94d4a28f824427d1fe14cd892" - integrity sha512-UPZ+9JTD4j4kVUge97zzXVknnlWIabO3YZFL/2O2tjHo23OUR4bl3AnUYiWYXVVIB7B28cadKHBa8ybnNn+gSA== +"@dhis2-ui/popover@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/popover/-/popover-9.2.0.tgz#3eccd6abde1da72089aa5feda5669ce4d1aa6f7e" + integrity sha512-7g8AHPrzUuMuv2MXpX5HdwiyO+peSGoq7hg6rHN/VDasIUvGS7vbaV4Xbxfd32fNmpHceBV7gMga31hRNaKtgw== dependencies: - "@dhis2-ui/layer" "8.16.0" - "@dhis2-ui/popper" "8.16.0" + "@dhis2-ui/layer" "9.2.0" + "@dhis2-ui/popper" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/popper@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/popper/-/popper-8.16.0.tgz#0f574233b55d259c416c7841a4bcbd618a06f06f" - integrity sha512-O0zztHX63rHYVV2YoexQjmzKwSjAJxZBFqN6f5glaZHstfgFr43/XDTJo91JT5yZKX5gkhFRC7TlhzC5UUzpQw== +"@dhis2-ui/popper@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/popper/-/popper-9.2.0.tgz#6d17ca49d7f0496289e11315d414095d93d179b5" + integrity sha512-6xWNvUQaDu8VE4rCa+uYOheb/4BD/52Cs23w2yt4lLAVrym4kV+0cnpHtlEG1ZuuVrK/yHelMjrmYxn6yJE41Q== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" "@popperjs/core" "^2.10.1" classnames "^2.3.1" prop-types "^15.7.2" react-popper "^2.2.5" resize-observer-polyfill "^1.5.1" -"@dhis2-ui/portal@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/portal/-/portal-8.16.0.tgz#57fb8f3bd91e5ec3e9116fd9208f3aa3034c4dfc" - integrity sha512-I5+lc2QLEu7foKOJJnv4I4XcKlgwGzvmFF0AhJsyY5rmsFpZ+xZRSReOpdZdCWeL8tHboVddRJ9laLHfHx5BkQ== +"@dhis2-ui/portal@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/portal/-/portal-9.2.0.tgz#12435f3a8886de685fc9ee4540639810eabf0191" + integrity sha512-a5DqmTG+pn4y1aXZWr8wEGlK4xRqdvnOWJVqO/6aebEn4ZtcPJT6yyXouviAM2yoW7+fDj6TZhKrZo3vgMLHlA== dependencies: classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/radio@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/radio/-/radio-8.16.0.tgz#35c87c4a047509b455f0deef72f13d1525f6ae90" - integrity sha512-dNPIJa2PdZR9pHLbLPxcT7ppaV3GQPUjwXPYB2QA2KLilNmb2aQWFKKnuNaOZTA4qwS/H5SGHuM0k3NvY4tRtA== +"@dhis2-ui/radio@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/radio/-/radio-9.2.0.tgz#9223ada90fe2d0eae375e85e0d99e6eb81d5269a" + integrity sha512-rjcz05spFlvRL8fnkO/7/ckznY4agQLl5P7UKSFL3Kz0KxvnocmounTX1BDsm6iQhKKt2HqJCYShpzPhTXavSA== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/required@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/required/-/required-8.16.0.tgz#3c7c65d1f462910620056b64873ccfd491752a2c" - integrity sha512-LjyvfCQZ+muxl1L1HW3KvhN1xfvpBisHcP0lA4MpEDC2ca/wnGqILxnPWC6RzMnnXA7OovMnmm+a80V/JCuEmw== +"@dhis2-ui/required@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/required/-/required-9.2.0.tgz#8d76c914c3eb483958284c8ddf52ef7095cc2f42" + integrity sha512-cNoQct7gVbrAdzGDDFLnfBktmwmxAhD48oEZ6z4TE7IrPi2N+idqOiQCTEVKEWmuY7VGv9TV0I/1OLX6oiuSvA== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/segmented-control@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/segmented-control/-/segmented-control-8.16.0.tgz#7120f68be62f6718ea9ca9cc1527dc856c4f8be3" - integrity sha512-JAmHEkiXF/qBVTOykjkE8s36E4ZTq48NJE9ON4Z2Umrh9EHqm8vZEbBZ9EJaSIzT7NROIDG6mbgb9ZWNQHevfA== +"@dhis2-ui/segmented-control@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/segmented-control/-/segmented-control-9.2.0.tgz#2b230eea17e35194072544ebbfc68e2c896fb951" + integrity sha512-x4eDqGu4JFfFPQk06mg8YdUCjYeYyXCLmZ0gbGj1Zx03gxpMwb4/nVyGoAxZg31/IVkhBOeAwXlvt+ckNXovgw== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/select@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/select/-/select-8.16.0.tgz#6446be9c0fe853e7071dabb2d0b48905cfc2ee1e" - integrity sha512-J0AQA3Sgu4T0/0rbiC0gkcD+HA2C7PmOyW4PTvDk7PWLLROh40leWqfLVAJT1JmTic0sBE6pMDk/B8ilODlfhw== - dependencies: - "@dhis2-ui/box" "8.16.0" - "@dhis2-ui/button" "8.16.0" - "@dhis2-ui/card" "8.16.0" - "@dhis2-ui/checkbox" "8.16.0" - "@dhis2-ui/chip" "8.16.0" - "@dhis2-ui/field" "8.16.0" - "@dhis2-ui/input" "8.16.0" - "@dhis2-ui/layer" "8.16.0" - "@dhis2-ui/loader" "8.16.0" - "@dhis2-ui/popper" "8.16.0" - "@dhis2-ui/status-icon" "8.16.0" +"@dhis2-ui/select@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/select/-/select-9.2.0.tgz#e854ecf6fd2580f9fb904301d1985923c1ade9cf" + integrity sha512-Hv0mRbpJNHJUa2lVivrWBt67iJ+4xTb7KxZkThISkmpQpzbWmhmJWlDbe0L+PdqOsaB2A70/N9HH4dhQyVP8vA== + dependencies: + "@dhis2-ui/box" "9.2.0" + "@dhis2-ui/button" "9.2.0" + "@dhis2-ui/card" "9.2.0" + "@dhis2-ui/checkbox" "9.2.0" + "@dhis2-ui/chip" "9.2.0" + "@dhis2-ui/field" "9.2.0" + "@dhis2-ui/input" "9.2.0" + "@dhis2-ui/layer" "9.2.0" + "@dhis2-ui/loader" "9.2.0" + "@dhis2-ui/popper" "9.2.0" + "@dhis2-ui/status-icon" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/selector-bar@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/selector-bar/-/selector-bar-8.16.0.tgz#2622d4fa3a2e08d29f09fbc508862636a3a3060b" - integrity sha512-f6iEHXIglHZTmc1ljmosrUSZjbBcdY7pWZYDQp/ybpuVyi5T4rV1/bPliZXZRydnp0WkBM+nDuKD/tJRtUAKlg== - dependencies: - "@dhis2-ui/button" "8.16.0" - "@dhis2-ui/card" "8.16.0" - "@dhis2-ui/layer" "8.16.0" - "@dhis2-ui/popper" "8.16.0" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" +"@dhis2-ui/selector-bar@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/selector-bar/-/selector-bar-9.2.0.tgz#23790f850bee1142e7bdffd711a2dea27dc78112" + integrity sha512-HDb/XKuUdD82vDh5mgz+OWIwpKjyiZEqek74y8g2r/AsMIl5Fe2rOyncOUPpGctxYeVp9u3gAlkFbIHd/qpv/w== + dependencies: + "@dhis2-ui/button" "9.2.0" + "@dhis2-ui/card" "9.2.0" + "@dhis2-ui/layer" "9.2.0" + "@dhis2-ui/popper" "9.2.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" "@testing-library/react" "^12.1.2" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/sharing-dialog@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/sharing-dialog/-/sharing-dialog-8.16.0.tgz#49f45b9b0d488c4bc4e51c46f6bd0cce7ee39204" - integrity sha512-1YuiKlghl7PbZxK7vbLFgknrMoX7ld2AnYMWwiJmJPPwAvyHjq+MeWTYCaNjZJV2bBslO41CONyhN8eE/4cF2w== - dependencies: - "@dhis2-ui/box" "8.16.0" - "@dhis2-ui/button" "8.16.0" - "@dhis2-ui/card" "8.16.0" - "@dhis2-ui/divider" "8.16.0" - "@dhis2-ui/input" "8.16.0" - "@dhis2-ui/layer" "8.16.0" - "@dhis2-ui/menu" "8.16.0" - "@dhis2-ui/modal" "8.16.0" - "@dhis2-ui/notice-box" "8.16.0" - "@dhis2-ui/popper" "8.16.0" - "@dhis2-ui/select" "8.16.0" - "@dhis2-ui/tab" "8.16.0" - "@dhis2-ui/tooltip" "8.16.0" - "@dhis2-ui/user-avatar" "8.16.0" +"@dhis2-ui/sharing-dialog@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/sharing-dialog/-/sharing-dialog-9.2.0.tgz#8818e5119c2113b3a54add3bd56dfe55ad2fc52a" + integrity sha512-h7chsY8XM2kw06r52pGRjS8ZknuwiEkRxuBTXD77G1Loni5TMm6xr0OFr9nSQHSsbcbxydbo2WPRPAu6WjVyfg== + dependencies: + "@dhis2-ui/box" "9.2.0" + "@dhis2-ui/button" "9.2.0" + "@dhis2-ui/card" "9.2.0" + "@dhis2-ui/divider" "9.2.0" + "@dhis2-ui/input" "9.2.0" + "@dhis2-ui/layer" "9.2.0" + "@dhis2-ui/menu" "9.2.0" + "@dhis2-ui/modal" "9.2.0" + "@dhis2-ui/notice-box" "9.2.0" + "@dhis2-ui/popper" "9.2.0" + "@dhis2-ui/select" "9.2.0" + "@dhis2-ui/tab" "9.2.0" + "@dhis2-ui/tooltip" "9.2.0" + "@dhis2-ui/user-avatar" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" "@react-hook/size" "^2.1.2" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/status-icon@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/status-icon/-/status-icon-8.16.0.tgz#0f2e041d1e971768c7be99a663ad571f165c307a" - integrity sha512-SsCUdi1U0a7dm3ZCxVpjGi6zyK0+lh/wSDLn+tlzdIlDYTlyjgBdUiqJiBoqv53Ob9PSyyCcxxEqt0nQlMQLbQ== +"@dhis2-ui/status-icon@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/status-icon/-/status-icon-9.2.0.tgz#5686721ef7dc1b1cd1cca315b11136e0809e568f" + integrity sha512-oILHs38xICDU27C7CXgFAEttU4QJzg0wImKlX4XVJ5z1aGeq6qOW0RUVibF6JtyAppEi9XsYZ+AB1KLEGnDFJw== dependencies: - "@dhis2-ui/loader" "8.16.0" + "@dhis2-ui/loader" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/switch@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/switch/-/switch-8.16.0.tgz#37dffc57dd76899014e43167d0076e8017253d2a" - integrity sha512-Gi3UcoIkarTEZW54c5LY2+JSQ2413HytTzc5iA5eeNKwX1Y7PV7xrbeIsC0hLOgK9pZaVe4pHJlpKpO26v/2vg== +"@dhis2-ui/switch@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/switch/-/switch-9.2.0.tgz#1fc9ed88546906da11aa19348b8ba8ff2e7c8414" + integrity sha512-IwVUiqxMKZmx7VtEJkyHqGzy4tvRNh4qbhmrFodaH6d9YrbycaFNECbphrT1OywrUBuci0Q2LovZhYKInkeIFg== dependencies: - "@dhis2-ui/field" "8.16.0" - "@dhis2-ui/required" "8.16.0" + "@dhis2-ui/field" "9.2.0" + "@dhis2-ui/required" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/tab@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/tab/-/tab-8.16.0.tgz#218864494102c52f44df221c231f9f1b9e052082" - integrity sha512-03B6o7gFmc9LK25/npLmZ8pT5+ax+ELLd3c0wYwdNYLYRk0c0MQEag7LChCRfz8M8P0LCd4kPceVFeTXOUZc6g== +"@dhis2-ui/tab@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/tab/-/tab-9.2.0.tgz#910223a907f8c007921924138306b53c2014f0fd" + integrity sha512-zVxwQ7WgjcrCGd+qWzLx+OtTWlGOIuC+AuSknHz0wpGgW3vawr1rMDA6j129l4O+ezzPs5bw8vN3xUQORbj0Bg== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/table@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/table/-/table-8.16.0.tgz#869c04df7fd72e3ae590d252f7417d2a809cd1f9" - integrity sha512-a7r8WfAP2MmrtvaqhmozTiOXu14wIUhu9zQkNIKlepQEQafTfDRqM5+oaapAfAOWvR5tlxlaZaF/IdOmS4vZew== +"@dhis2-ui/table@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/table/-/table-9.2.0.tgz#83d535e6c60ff9c9c3f436e592489a131caef772" + integrity sha512-wep8wPQKRg5vYPGg3HLAvsAEo+lUk3L7wO7axHyzx/XuHR40QXRirpv4tsFVn8VPpSFVq0w/BFGp8ijp3Y6RtA== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/tag@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/tag/-/tag-8.16.0.tgz#1cf5d89303c5d8342bfa1987cd9801980c7e1283" - integrity sha512-k9y6ZAbV5uh7swHB/s4lLbMkbQ26SxJBCFTQ64YbqYmuUGi7GTZM6gGLJznQND/xNJvydkVX51yI44/GPx9vBg== +"@dhis2-ui/tag@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/tag/-/tag-9.2.0.tgz#c6a11fbdfc20151cc75c323e6a6b1470ef064e58" + integrity sha512-qt/FUIFPZkghfF/fhhLHr4oOl54d1Zwy4CKf4cZmO2DSd09h7E7cfIUxXaX/shRHsSmeUhrFP2Nv5LAvu8XVUg== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/text-area@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/text-area/-/text-area-8.16.0.tgz#13e7e351b982d21a693db2e405aa9671e493c187" - integrity sha512-UMhOaNigxYp4K8VQtlaSdFuC6FErSbB7RCN22ii7Ic12XBsVoWKjGCkhdol3w7+rHefPbp+9SmJExyj+9E2y5g== +"@dhis2-ui/text-area@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/text-area/-/text-area-9.2.0.tgz#75f279281f1513801148f11c2693537a5e9beed7" + integrity sha512-KLBlerlO3OvBvzTVKKolfghaAMjDPUZkxFsyRvWEIPh1RRxS9ZprunXpBWRkNO2I6U6uwqN0DiBLTNbh/zrafg== dependencies: - "@dhis2-ui/box" "8.16.0" - "@dhis2-ui/field" "8.16.0" - "@dhis2-ui/loader" "8.16.0" - "@dhis2-ui/status-icon" "8.16.0" + "@dhis2-ui/box" "9.2.0" + "@dhis2-ui/field" "9.2.0" + "@dhis2-ui/loader" "9.2.0" + "@dhis2-ui/status-icon" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-icons" "8.16.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-icons" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/tooltip@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/tooltip/-/tooltip-8.16.0.tgz#6b52906b45ce9d048a1c39f960750c1aa906c527" - integrity sha512-h4BveS+DKwq8Tb9ThqvGynhPwRe0eerU73jdii3orh9tnf/skNYYQrc388t1t1Ti7PHw40eWVOWXs1xfBLtLoA== +"@dhis2-ui/tooltip@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/tooltip/-/tooltip-9.2.0.tgz#e7a0827d9ca6b30b69073916f7801d01fb7c9793" + integrity sha512-7Gb/Occ5/Bju95dnxUGzt/Q4129zqGWrxu1+S2uhc0YPRSx83JcG0MivPsVsr0BeU+p+8xwTVdGBOhMmqLpL9Q== dependencies: - "@dhis2-ui/popper" "8.16.0" - "@dhis2-ui/portal" "8.16.0" + "@dhis2-ui/popper" "9.2.0" + "@dhis2-ui/portal" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/transfer@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/transfer/-/transfer-8.16.0.tgz#4de6686b83dcc8cb41e186a04b7ec22cc1f2b15e" - integrity sha512-uds51dhlqRFsnaNL1cKedWy9/R4abmx5H/BAWzvNRhnTJaY33KplXlxcfTta/9TaN530uZt1fCE5NwC+dPBZqQ== +"@dhis2-ui/transfer@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/transfer/-/transfer-9.2.0.tgz#3624d08100b72143da5639ce231b53d57706ffdc" + integrity sha512-1+SdfeCBr+iOLaXf4gkpNLlysaBsWLOmlVzBdGVqFt4I4SMJrhFrCMUTz4A1Nsw7GpKGds35vGClQUe5LcuVSw== dependencies: - "@dhis2-ui/button" "8.16.0" - "@dhis2-ui/field" "8.16.0" - "@dhis2-ui/input" "8.16.0" - "@dhis2-ui/intersection-detector" "8.16.0" - "@dhis2-ui/loader" "8.16.0" + "@dhis2-ui/button" "9.2.0" + "@dhis2-ui/field" "9.2.0" + "@dhis2-ui/input" "9.2.0" + "@dhis2-ui/intersection-detector" "9.2.0" + "@dhis2-ui/loader" "9.2.0" "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" -"@dhis2-ui/user-avatar@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2-ui/user-avatar/-/user-avatar-8.16.0.tgz#c5b8ebbf5c486c8bb79b2ce20360d8f07eb2d3d2" - integrity sha512-4dhKcVoQ07UBGIjWmyk6UbzLhXnmpmSg0zbkorvwdYi34NrhQeskRrGbJCEr/SWUbhxeA085LajmJL/2YH8GVg== +"@dhis2-ui/user-avatar@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2-ui/user-avatar/-/user-avatar-9.2.0.tgz#722b4bad239aff8eb2b639ca51bd6528a08da1e4" + integrity sha512-XRop5Mmc5q1GnrM3YgIEdjw0OX7/KA9ZdxRNS4AU7ifYMEjUNutYmq8a2bJ1M6eZfq2DrhRQui9/1E7MvK+Evw== dependencies: "@dhis2/prop-types" "^3.1.2" - "@dhis2/ui-constants" "8.16.0" + "@dhis2/ui-constants" "9.2.0" classnames "^2.3.1" prop-types "^15.7.2" @@ -2130,12 +2130,12 @@ react-beautiful-dnd "^10.1.1" resize-observer-polyfill "^1.5.1" -"@dhis2/app-adapter@10.3.11": - version "10.3.11" - resolved "https://registry.yarnpkg.com/@dhis2/app-adapter/-/app-adapter-10.3.11.tgz#a5322deba404fb405f80925684d7a5d9cdc48c81" - integrity sha512-H36P1tqSuzMyu4/uxSVFsEIXrWXzqVG1NPtANY+xEJcmrOoXH7YuiKvJu/Dl4rINDkERuUM+GwWMMgfBuMmrUw== +"@dhis2/app-adapter@10.4.0": + version "10.4.0" + resolved "https://registry.yarnpkg.com/@dhis2/app-adapter/-/app-adapter-10.4.0.tgz#befb3e9ee09a4f2d064a6dc0c590bffaf5a7ca7c" + integrity sha512-dqjrK8FtshofMp4LzMV6J1Oj3c2/pyl6m+gOYx65Ynr7FPk20QybMNPEWnpmeWQbhI1iMf/OV/O6MzTiezfUfQ== dependencies: - "@dhis2/pwa" "10.3.11" + "@dhis2/pwa" "10.4.0" moment "^2.24.0" "@dhis2/app-runtime-adapter-d2@^1.1.0": @@ -2145,7 +2145,7 @@ dependencies: prop-types "^15.7.2" -"@dhis2/app-runtime@^3.10.2", "@dhis2/app-runtime@^3.9.0": +"@dhis2/app-runtime@^3.10.0-alpha.2", "@dhis2/app-runtime@^3.10.2": version "3.10.2" resolved "https://registry.yarnpkg.com/@dhis2/app-runtime/-/app-runtime-3.10.2.tgz#e82639bd68234bdeaf2f6d3c256dcdfcdd267da2" integrity sha512-GiftKk8ZTXlPElXAgVJn41Vj6E1vEGTPGrjrqU7j41ZTYsg+tUcCkISNt1woe5l7E+8+y+9Fy4bgqSsBOAEUvg== @@ -2200,18 +2200,19 @@ dependencies: post-robot "^10.0.46" -"@dhis2/app-shell@10.3.11": - version "10.3.11" - resolved "https://registry.yarnpkg.com/@dhis2/app-shell/-/app-shell-10.3.11.tgz#461a19159ae6938e705ab793005403327b1ad95b" - integrity sha512-DCEOFK5i2/oNOOz33SqQ/7J3LJN0zUYMukdS/arEQCR9zP4bs+1yHGNRXtv8XoQRiYzdlIXsimlZzOm1ZDsxTw== +"@dhis2/app-shell@10.4.0": + version "10.4.0" + resolved "https://registry.yarnpkg.com/@dhis2/app-shell/-/app-shell-10.4.0.tgz#66cf2148bc2e92f741f7ef0dd08ef955f2c40707" + integrity sha512-XROGP/co8IZJF//xHUY/m6EZhIh+6g4Wk/ItTgrkYnBbz69JWXB2Zo/M/b2nx3TKOKbz9FeVXVeH7liWHKkaug== dependencies: - "@dhis2/app-adapter" "10.3.11" - "@dhis2/app-runtime" "^3.9.0" + "@dhis2/app-adapter" "10.4.0" + "@dhis2/app-runtime" "^3.10.0-alpha.2" "@dhis2/d2-i18n" "^1.1.1" - "@dhis2/pwa" "10.3.11" + "@dhis2/pwa" "10.4.0" "@dhis2/ui" "^8.12.3" classnames "^2.2.6" moment "^2.29.1" + post-robot "^10.0.46" prop-types "^15.7.2" react "^16.8.6" react-dom "^16.8.6" @@ -2221,10 +2222,10 @@ typeface-roboto "^0.0.75" typescript "^3.6.3" -"@dhis2/cli-app-scripts@^10.3.11": - version "10.3.11" - resolved "https://registry.yarnpkg.com/@dhis2/cli-app-scripts/-/cli-app-scripts-10.3.11.tgz#024920726eb9a9057fa1f73d745b9a75b5d55b7e" - integrity sha512-j7fetbmlSSHdGz9YlGJMaKyLzfEGWnOoaKvi53UfI0e3k7EIBbc9YTLH6qoYJX4KvvXNjB9ICNjvTFEjWHeIZw== +"@dhis2/cli-app-scripts@^10.4.0": + version "10.4.0" + resolved "https://registry.yarnpkg.com/@dhis2/cli-app-scripts/-/cli-app-scripts-10.4.0.tgz#3a80ccc7c10b0804e8d76f7df40ece48d30d5f17" + integrity sha512-QMx+5UEEEb0AELzeZ5oZcxb8dv0hpzHS3/ily67oRchVdGB1K1stl0MwQF7CdbCS4ejGtU+2c5ODWFoBD0cWFA== dependencies: "@babel/core" "^7.6.2" "@babel/plugin-proposal-class-properties" "^7.8.3" @@ -2233,7 +2234,7 @@ "@babel/preset-env" "^7.14.7" "@babel/preset-react" "^7.0.0" "@babel/preset-typescript" "^7.6.0" - "@dhis2/app-shell" "10.3.11" + "@dhis2/app-shell" "10.4.0" "@dhis2/cli-helpers-engine" "^3.2.0" "@jest/core" "^27.0.6" "@pmmmwh/react-refresh-webpack-plugin" "^0.5.4" @@ -2385,10 +2386,10 @@ resolved "https://registry.yarnpkg.com/@dhis2/prop-types/-/prop-types-3.1.2.tgz#65b8ad2da8cd2f72bc8b951049a6c9d1b97af3e9" integrity sha512-eM0jjLOWvtXWqSFp5YC4DHFpkP8Y1D2eUwGV7MBWjni+o27oesVan+oT7WHeOeLdlAd4acRJrnaaAyB4Ck1wGQ== -"@dhis2/pwa@10.3.11": - version "10.3.11" - resolved "https://registry.yarnpkg.com/@dhis2/pwa/-/pwa-10.3.11.tgz#6eb5a692fe92a56bd6ffa56f06322617c15968dc" - integrity sha512-nHQhNDe0MTEG3/YcdBDcGD6NwcDoDKUyJWbtC8xErEKbHIns0HWjhIC+NPMrVu3NxEv1HZiHupK9lnfzPVJC4Q== +"@dhis2/pwa@10.4.0": + version "10.4.0" + resolved "https://registry.yarnpkg.com/@dhis2/pwa/-/pwa-10.4.0.tgz#1b21b79b1a8c85aed9c73e4655e1bb1f4d3d3d95" + integrity sha512-iNq4imbSBnIv2YBkrtljsAHV/Q934ZxZVfUiffGWAAiS9gqhrD1iQ9dhCRl4nq/X71sIRR28aK7CDlwql31OrQ== dependencies: idb "^6.0.0" workbox-core "^6.1.5" @@ -2396,91 +2397,91 @@ workbox-routing "^6.1.5" workbox-strategies "^6.1.5" -"@dhis2/ui-constants@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2/ui-constants/-/ui-constants-8.16.0.tgz#ab37fbe34ba074fd303ea405b13ea8ba93bfcafe" - integrity sha512-IXYyLmVRCfY7JBZUrRdOCqhYP5B5uvH/6SZL54apHgnl5JpblTdK9YxSYjr38m0MgiRmL07NLjK0nW7xVTzV0g== +"@dhis2/ui-constants@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2/ui-constants/-/ui-constants-9.2.0.tgz#47506acaec5e4ce28630519a630a05657d2d29f6" + integrity sha512-gMbnVJQJmCPoGJHnY09BoDe6Z1vukzFdUcm0HPYyijs8ZWnclLs+69iVamxhskOnNWgj8hEt/FVs4mfhMcW3Cg== dependencies: prop-types "^15.7.2" -"@dhis2/ui-forms@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2/ui-forms/-/ui-forms-8.16.0.tgz#6d896ebd6a0de89c4e9fd63f919c084464db3036" - integrity sha512-tOS+0sQxh36H4IeoAnlXr0C1nKx+Ckq/9W9r3I0+8OidMzlZD7u+43IcpWI02r9AEZC6LlNRwdM2wOjXnJXN9w== - dependencies: - "@dhis2-ui/button" "8.16.0" - "@dhis2-ui/checkbox" "8.16.0" - "@dhis2-ui/field" "8.16.0" - "@dhis2-ui/file-input" "8.16.0" - "@dhis2-ui/input" "8.16.0" - "@dhis2-ui/radio" "8.16.0" - "@dhis2-ui/select" "8.16.0" - "@dhis2-ui/switch" "8.16.0" - "@dhis2-ui/text-area" "8.16.0" +"@dhis2/ui-forms@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2/ui-forms/-/ui-forms-9.2.0.tgz#a5651dc5010a495c8a52ef5484e7d44b2583b715" + integrity sha512-eodiPW+ahR5wVsgrl/bFvj2zyeJD+DR9woqys4ZyoaHlKjOdeLqDNbJDnrS+AmHfte5uorF/aWzmEZr825LBVg== + dependencies: + "@dhis2-ui/button" "9.2.0" + "@dhis2-ui/checkbox" "9.2.0" + "@dhis2-ui/field" "9.2.0" + "@dhis2-ui/file-input" "9.2.0" + "@dhis2-ui/input" "9.2.0" + "@dhis2-ui/radio" "9.2.0" + "@dhis2-ui/select" "9.2.0" + "@dhis2-ui/switch" "9.2.0" + "@dhis2-ui/text-area" "9.2.0" "@dhis2/prop-types" "^3.1.2" classnames "^2.3.1" final-form "^4.20.2" prop-types "^15.7.2" react-final-form "^6.5.3" -"@dhis2/ui-icons@8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2/ui-icons/-/ui-icons-8.16.0.tgz#eda8efc060740b17c1821c89a14435b938ef8c27" - integrity sha512-RaYCrFuqN6/l0mF+71CyxvRKwXCfaUfMQudTgdCpZw0OwwoRmfg4wJdB75u+jl4RUj/E447zl439YGyHEbStHw== - -"@dhis2/ui@^8.12.3", "@dhis2/ui@^8.16.0": - version "8.16.0" - resolved "https://registry.yarnpkg.com/@dhis2/ui/-/ui-8.16.0.tgz#b427cb3d35b0e8c8d2e8c3abfeec333dd54ef7b2" - integrity sha512-qWUd0dBRXT+dkuCbs7XlPl3YpXRJuouTM2Uf5Wa7z5VHsFVPBrHRBGmgYqmJpTrrQBFTnRmrKHVjSqfnm14D5g== - dependencies: - "@dhis2-ui/alert" "8.16.0" - "@dhis2-ui/box" "8.16.0" - "@dhis2-ui/button" "8.16.0" - "@dhis2-ui/calendar" "8.16.0" - "@dhis2-ui/card" "8.16.0" - "@dhis2-ui/center" "8.16.0" - "@dhis2-ui/checkbox" "8.16.0" - "@dhis2-ui/chip" "8.16.0" - "@dhis2-ui/cover" "8.16.0" - "@dhis2-ui/css" "8.16.0" - "@dhis2-ui/divider" "8.16.0" - "@dhis2-ui/field" "8.16.0" - "@dhis2-ui/file-input" "8.16.0" - "@dhis2-ui/header-bar" "8.16.0" - "@dhis2-ui/help" "8.16.0" - "@dhis2-ui/input" "8.16.0" - "@dhis2-ui/intersection-detector" "8.16.0" - "@dhis2-ui/label" "8.16.0" - "@dhis2-ui/layer" "8.16.0" - "@dhis2-ui/legend" "8.16.0" - "@dhis2-ui/loader" "8.16.0" - "@dhis2-ui/logo" "8.16.0" - "@dhis2-ui/menu" "8.16.0" - "@dhis2-ui/modal" "8.16.0" - "@dhis2-ui/node" "8.16.0" - "@dhis2-ui/notice-box" "8.16.0" - "@dhis2-ui/organisation-unit-tree" "8.16.0" - "@dhis2-ui/pagination" "8.16.0" - "@dhis2-ui/popover" "8.16.0" - "@dhis2-ui/popper" "8.16.0" - "@dhis2-ui/portal" "8.16.0" - "@dhis2-ui/radio" "8.16.0" - "@dhis2-ui/required" "8.16.0" - "@dhis2-ui/segmented-control" "8.16.0" - "@dhis2-ui/select" "8.16.0" - "@dhis2-ui/selector-bar" "8.16.0" - "@dhis2-ui/sharing-dialog" "8.16.0" - "@dhis2-ui/switch" "8.16.0" - "@dhis2-ui/tab" "8.16.0" - "@dhis2-ui/table" "8.16.0" - "@dhis2-ui/tag" "8.16.0" - "@dhis2-ui/text-area" "8.16.0" - "@dhis2-ui/tooltip" "8.16.0" - "@dhis2-ui/transfer" "8.16.0" - "@dhis2-ui/user-avatar" "8.16.0" - "@dhis2/ui-constants" "8.16.0" - "@dhis2/ui-forms" "8.16.0" - "@dhis2/ui-icons" "8.16.0" +"@dhis2/ui-icons@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2/ui-icons/-/ui-icons-9.2.0.tgz#bddf5223cabec93c9499281b2181eb165346b639" + integrity sha512-g9993UGWVLwDcbV+wp3HqrK8AXFu49aped0GpZsQUlGbHIzEl1EgmjiII44N40VbXwVUnqIDmu99wBxpH5Gd+g== + +"@dhis2/ui@^8.12.3", "@dhis2/ui@^9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@dhis2/ui/-/ui-9.2.0.tgz#33d474cbc7cd95f8a714e019d6c69e144f77f86b" + integrity sha512-nhKwW5bmIfQvt3L16PffFO2NsDk9BgYb91vHx06fPgM56UdwGYSejpax8eU29vE9urmHSkijSpnBqY4buZy6Ow== + dependencies: + "@dhis2-ui/alert" "9.2.0" + "@dhis2-ui/box" "9.2.0" + "@dhis2-ui/button" "9.2.0" + "@dhis2-ui/calendar" "9.2.0" + "@dhis2-ui/card" "9.2.0" + "@dhis2-ui/center" "9.2.0" + "@dhis2-ui/checkbox" "9.2.0" + "@dhis2-ui/chip" "9.2.0" + "@dhis2-ui/cover" "9.2.0" + "@dhis2-ui/css" "9.2.0" + "@dhis2-ui/divider" "9.2.0" + "@dhis2-ui/field" "9.2.0" + "@dhis2-ui/file-input" "9.2.0" + "@dhis2-ui/header-bar" "9.2.0" + "@dhis2-ui/help" "9.2.0" + "@dhis2-ui/input" "9.2.0" + "@dhis2-ui/intersection-detector" "9.2.0" + "@dhis2-ui/label" "9.2.0" + "@dhis2-ui/layer" "9.2.0" + "@dhis2-ui/legend" "9.2.0" + "@dhis2-ui/loader" "9.2.0" + "@dhis2-ui/logo" "9.2.0" + "@dhis2-ui/menu" "9.2.0" + "@dhis2-ui/modal" "9.2.0" + "@dhis2-ui/node" "9.2.0" + "@dhis2-ui/notice-box" "9.2.0" + "@dhis2-ui/organisation-unit-tree" "9.2.0" + "@dhis2-ui/pagination" "9.2.0" + "@dhis2-ui/popover" "9.2.0" + "@dhis2-ui/popper" "9.2.0" + "@dhis2-ui/portal" "9.2.0" + "@dhis2-ui/radio" "9.2.0" + "@dhis2-ui/required" "9.2.0" + "@dhis2-ui/segmented-control" "9.2.0" + "@dhis2-ui/select" "9.2.0" + "@dhis2-ui/selector-bar" "9.2.0" + "@dhis2-ui/sharing-dialog" "9.2.0" + "@dhis2-ui/switch" "9.2.0" + "@dhis2-ui/tab" "9.2.0" + "@dhis2-ui/table" "9.2.0" + "@dhis2-ui/tag" "9.2.0" + "@dhis2-ui/text-area" "9.2.0" + "@dhis2-ui/tooltip" "9.2.0" + "@dhis2-ui/transfer" "9.2.0" + "@dhis2-ui/user-avatar" "9.2.0" + "@dhis2/ui-constants" "9.2.0" + "@dhis2/ui-forms" "9.2.0" + "@dhis2/ui-icons" "9.2.0" prop-types "^15.7.2" "@dnd-kit/accessibility@^3.0.0": From c3f60fe77ca179f0f9a2d5f906f42622f61b799c Mon Sep 17 00:00:00 2001 From: Jen Jones Arnesen Date: Mon, 12 Feb 2024 14:14:37 +0100 Subject: [PATCH 4/5] feat: replace data table with UI data table (#3015) Implements https://dhis2.atlassian.net/browse/DHIS2-15795 Features: * horizontal scrolling * styling in line with our style guide * virtualization (performance matches old implementation) --- cypress.config.js | 2 +- cypress/elements/event_layer.js | 8 + cypress/integration/dataTable.cy.js | 240 ++++++- cypress/support/commands.js | 2 +- i18n/en.pot | 46 +- package.json | 2 + src/components/datatable/BottomPanel.js | 36 +- src/components/datatable/DataTable.js | 636 ++++++++---------- src/components/datatable/ErrorBoundary.js | 40 ++ src/components/datatable/FilterInput.js | 75 +-- .../datatable/__tests__/useTableData.spec.js | 539 +++++++++++++++ .../datatable/styles/BottomPanel.module.css | 27 +- .../datatable/styles/DataTable.module.css | 90 ++- .../datatable/styles/FilterInput.module.css | 14 - .../datatable/styles/ResizeHandle.module.css | 17 +- src/components/datatable/useTableData.js | 282 ++++++++ .../layers/toolbar/LayerToolbarMoreMenu.js | 5 +- src/components/loaders/EventLoader.js | 6 +- src/components/loaders/LayersLoader.js | 51 +- .../loaders/__tests__/LayersLoader.spec.js | 32 +- .../__snapshots__/LayersLoader.spec.js.snap | 12 +- src/loaders/eventLoader.js | 31 +- yarn.lock | 162 +---- 23 files changed, 1656 insertions(+), 699 deletions(-) create mode 100644 src/components/datatable/ErrorBoundary.js create mode 100644 src/components/datatable/__tests__/useTableData.spec.js delete mode 100644 src/components/datatable/styles/FilterInput.module.css create mode 100644 src/components/datatable/useTableData.js diff --git a/cypress.config.js b/cypress.config.js index 43a62ced8..0717507a8 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -67,7 +67,7 @@ module.exports = defineConfig({ // Enabled to reduce the risk of out-of-memory issues experimentalMemoryManagement: true, // Set to a low number to reduce the risk of out-of-memory issues - numTestsKeptInMemory: 5, + numTestsKeptInMemory: 4, /* When allowing 1 retry on CI, the test suite will pass if * it's flaky. And/but we also get to identify flaky tests on the * Cypress Dashboard. */ diff --git a/cypress/elements/event_layer.js b/cypress/elements/event_layer.js index f3a0fc47f..6f7db422c 100644 --- a/cypress/elements/event_layer.js +++ b/cypress/elements/event_layer.js @@ -3,6 +3,7 @@ import { Layer } from './layer.js' export class EventLayer extends Layer { selectProgram(program) { cy.get('[data-test="programselect"]').click() + cy.contains(program).scrollIntoView() cy.contains(program).click() return this @@ -22,4 +23,11 @@ export class EventLayer extends Layer { return this } + + selectPeriodType(periodType) { + cy.getByDataTest('relative-period-select-content').click() + cy.contains(periodType).click() + + return this + } } diff --git a/cypress/integration/dataTable.cy.js b/cypress/integration/dataTable.cy.js index ecfff1d48..7f5717f49 100644 --- a/cypress/integration/dataTable.cy.js +++ b/cypress/integration/dataTable.cy.js @@ -1,4 +1,15 @@ -import { EXTENDED_TIMEOUT } from '../support/util.js' +import { EventLayer } from '../elements/event_layer.js' +import { CURRENT_YEAR, EXTENDED_TIMEOUT } from '../support/util.js' + +Cypress.on('uncaught:exception', (err) => { + if ( + err.message.includes( + 'ResizeObserver loop completed with undelivered notifications.' + ) + ) { + return false + } +}) const map = { id: 'eDlFx0jTtV9', @@ -8,7 +19,7 @@ const map = { } describe('data table', () => { - it('opens data table', () => { + it('opens data table and filters and sorts', () => { cy.visit(`/#/${map.id}`, EXTENDED_TIMEOUT) cy.get('canvas', EXTENDED_TIMEOUT).should('be.visible') @@ -29,19 +40,226 @@ describe('data table', () => { // check number of columns cy.getByDataTest('bottom-panel') - .find('[role="columnheader"]') + .findByDataTest('dhis2-uicore-datatablecellhead') .should('have.length', 10) - // try the filtering + // Filter by name + cy.getByDataTest('data-table-column-filter-input-Name') + .find('input') + .type('bar') + + // check that the filter returned the correct number of rows + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .findByDataTest('dhis2-uicore-datatablerow') + .should('have.length', 7) + + // confirm that the sort order is initially ascending by Name + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .find('tr') + .first() + .find('td') + .eq(1) + .should('contain', 'Bargbe') + + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .find('tr') + .last() + .find('td') + .eq(1) + .should('contain', 'Upper Bambara') + + // Sort by name + cy.get('button[title="Sort by Name"]').click() + + // confirm that the rows are sorted by Name descending + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .find('tr') + .first() + .find('td') + .eq(1) + .should('contain', 'Upper Bambara') + + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .find('tr') + .last() + .find('td') + .eq(1) + .should('contain', 'Bargbe') + + // filter by Value (numeric) + cy.getByDataTest('data-table-column-filter-input-Value') + .find('input') + .type('>26') + + // check that the (combined) filter returned the correct number of rows + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .findByDataTest('dhis2-uicore-datatablerow') + .should('have.length', 5) + + // Sort by value + cy.get('button[title="Sort by Value"]').click() + + // check that the rows are sorted by Value ascending + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .find('tr') + .first() + .find('td') + .eq(3) + .should('contain', '35') + + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .find('tr') + .last() + .find('td') + .eq(3) + .should('contain', '76') + + // click on a row + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .findByDataTest('dhis2-uicore-datatablerow') + .first() + .click() + + // check that the org unit profile drawer is opened + cy.getByDataTest('org-unit-profile').should('be.visible') + }) + + it('opens the data table for an Event layer', () => { + cy.visit('/', EXTENDED_TIMEOUT) + + const Layer = new EventLayer() + + Layer.openDialog('Events') + .selectProgram('Malaria case registration') + .validateStage('Malaria case registration') + .selectTab('Period') + .selectPeriodType('Start/end dates') + .typeStartDate(`${CURRENT_YEAR - 1}-01-01`) + .typeEndDate(`${CURRENT_YEAR - 1}-01-15`) + .selectTab('Org Units') + .selectOu('Bo') + .addToMap() + + Layer.validateDialogClosed(true) + + Layer.validateCardTitle('Malaria case registration') + + cy.getByDataTest('moremenubutton').first().click() + + cy.getByDataTest('more-menu') + .find('li') + .contains('Show data table') + .not('disabled') + .click() + + cy.getByDataTest('bottom-panel').should('be.visible') + + // check number of columns + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-datatablecellhead') + .should('have.length', 9) + + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-datatablecellhead') + .contains('Age in years', { matchCase: false }) + .should('be.visible') + + // filter by Org unit + const ouName = 'Benduma' + cy.getByDataTest('data-table-column-filter-input-Org unit') + .find('input') + .type(ouName) + + // check that all the rows have Org unit Yakaji + + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .find('tr') + .first() + .find('td') + .eq(1) + .should('contain', ouName) + + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .find('tr') + .last() + .find('td') + .eq(1) + .should('contain', ouName) + cy.getByDataTest('bottom-panel') - .find('[role="columnheader"]') - .containsExact('Name') - .siblings('input') - .type('Kakua') + .findByDataTest('dhis2-uicore-tablebody') + .findByDataTest('dhis2-uicore-datatablerow') + .should('have.length', 5) + + // filter by Gender + cy.getByDataTest('data-table-column-filter-input-Gender') + .find('input') + .type('Female') + + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .findByDataTest('dhis2-uicore-datatablerow') + .should('have.length', 4) + + cy.getByDataTest('data-table-column-filter-input-Gender') + .find('input') + .clear() - // check that the filter worked cy.getByDataTest('bottom-panel') - .find('.ReactVirtualized__Table__row') - .should('have.length', 1) + .findByDataTest('dhis2-uicore-tablebody') + .findByDataTest('dhis2-uicore-datatablerow') + .should('have.length', 5) + + // filter by Age in years (numeric) + cy.getByDataTest('data-table-column-filter-input-Age in years') + .find('input') + .type('<51') + + // check that the filter returned the correct number of rows + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .findByDataTest('dhis2-uicore-datatablerow') + .should('have.length', 3) + + // Sort by Age in years + cy.get('button[title="Sort by Age in years"]').click() + + // confirm that the rows are sorted by Age in years descending + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .find('tr') + .first() + .find('td') + .eq(7) + .should('contain', '44') + + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .find('tr') + .last() + .find('td') + .eq(7) + .should('contain', '6') + + // click on a row + cy.getByDataTest('bottom-panel') + .findByDataTest('dhis2-uicore-tablebody') + .findByDataTest('dhis2-uicore-datatablerow') + .first() + .click() + + // check that the org unit profile drawer is NOT opened + cy.getByDataTest('org-unit-profile').should('not.exist') }) }) diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 50b4f5a19..1243879df 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -2,7 +2,7 @@ import '@dhis2/cypress-commands' import 'cypress-wait-until' Cypress.Commands.add('getByDataTest', (selector, ...args) => - cy.get(`[data-test=${selector}]`, ...args) + cy.get(`[data-test="${selector}"]`, ...args) ) Cypress.Commands.add( 'findByDataTest', diff --git a/i18n/en.pot b/i18n/en.pot index 4ae87b4de..71c7fd25c 100644 --- a/i18n/en.pot +++ b/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-01-11T09:20:59.829Z\n" -"PO-Revision-Date: 2024-01-11T09:20:59.829Z\n" +"POT-Creation-Date: 2024-02-12T09:30:18.362Z\n" +"PO-Revision-Date: 2024-02-12T09:30:18.362Z\n" msgid "Untitled map, {{date}}" msgstr "Untitled map, {{date}}" @@ -131,23 +131,23 @@ msgstr "Date" msgid "Data set" msgstr "Data set" -msgid "Index" -msgstr "Index" +msgid "No results found" +msgstr "No results found" -msgid "Org unit" -msgstr "Org unit" +msgid "Sort by {{column}}" +msgstr "Sort by {{column}}" -msgid "Id" -msgstr "Id" +msgid "Something went wrong" +msgstr "Something went wrong" -msgid "Event time" -msgstr "Event time" +msgid "Search" +msgstr "Search" -msgid "Legend" -msgstr "Legend" +msgid "Index" +msgstr "Index" -msgid "Range" -msgstr "Range" +msgid "Id" +msgstr "Id" msgid "Level" msgstr "Level" @@ -158,9 +158,27 @@ msgstr "Parent" msgid "Type" msgstr "Type" +msgid "Legend" +msgstr "Legend" + +msgid "Range" +msgstr "Range" + +msgid "Org unit" +msgstr "Org unit" + +msgid "Event time" +msgstr "Event time" + msgid "Data table is not supported when events are grouped on the server." msgstr "Data table is not supported when events are grouped on the server." +msgid "No valid data was found for the current layer configuration." +msgstr "No valid data was found for the current layer configuration." + +msgid "Data table is not supported for this layer type." +msgstr "Data table is not supported for this layer type." + msgid "Items" msgstr "Items" diff --git a/package.json b/package.json index 0678986a0..438188f05 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "@krakenjs/post-robot": "^11.0.0", "@reportportal/agent-js-cypress": "git+https://github.com/dhis2/agent-js-cypress.git#develop", "@reportportal/agent-js-jest": "^5.0.7", + "@testing-library/react-hooks": "^8.0.1", "abortcontroller-polyfill": "^1.7.5", "array-move": "^4.0.0", "classnames": "^2.3.2", @@ -75,6 +76,7 @@ "react-redux": "^8.1.2", "react-sortable-hoc": "^1.11.0", "react-virtualized": "^9.22.5", + "react-virtuoso": "^4.6.2", "redux": "^4.2.1", "redux-logger": "^3.0.6", "redux-thunk": "^2.4.2", diff --git a/src/components/datatable/BottomPanel.js b/src/components/datatable/BottomPanel.js index 62160bcbf..31b2be27c 100644 --- a/src/components/datatable/BottomPanel.js +++ b/src/components/datatable/BottomPanel.js @@ -8,8 +8,9 @@ import { LAYERS_PANEL_WIDTH, RIGHT_PANEL_WIDTH, } from '../../constants/layout.js' -import DataTable from '../datatable/DataTable.js' import { useWindowDimensions } from '../WindowDimensionsProvider.js' +import DataTable from './DataTable.js' +import ErrorBoundary from './ErrorBoundary.js' import ResizeHandle from './ResizeHandle.js' import styles from './styles/BottomPanel.module.css' @@ -39,21 +40,28 @@ const BottomPanel = () => {
- dispatch(closeDataTable())} - > - - - dispatch(resizeDataTable(height))} - /> - +
+ dispatch(resizeDataTable(height))} + /> + +
+ + +
) } diff --git a/src/components/datatable/DataTable.js b/src/components/datatable/DataTable.js index 27c8f7a99..cf661531a 100644 --- a/src/components/datatable/DataTable.js +++ b/src/components/datatable/DataTable.js @@ -1,384 +1,296 @@ import i18n from '@dhis2/d2-i18n' -import { CenteredContent, CircularLoader } from '@dhis2/ui' -import { isValidUid } from 'd2/uid' -import { debounce } from 'lodash/fp' +import { + DataTable, + DataTableRow, + DataTableCell, + DataTableColumnHeader, + DataTableHead, + DataTableBody, + ComponentCover, + CenteredContent, + CircularLoader, +} from '@dhis2/ui' +import cx from 'classnames' import PropTypes from 'prop-types' -import React, { Component } from 'react' -import { connect } from 'react-redux' -import { Table, Column } from 'react-virtualized' -import { closeDataTable } from '../../actions/dataTable.js' +import React, { + useReducer, + useCallback, + useMemo, + useEffect, + useRef, + useState, +} from 'react' +import { useSelector, useDispatch } from 'react-redux' +import { TableVirtuoso } from 'react-virtuoso' import { highlightFeature } from '../../actions/feature.js' -import { updateLayer } from '../../actions/layers.js' import { setOrgUnitProfile } from '../../actions/orgUnits.js' -import { - EVENT_LAYER, - THEMATIC_LAYER, - ORG_UNIT_LAYER, - EARTH_ENGINE_LAYER, -} from '../../constants/layers.js' -import { numberValueTypes } from '../../constants/valueTypes.js' -import { filterData } from '../../util/filter.js' -import { formatTime } from '../../util/helpers.js' -import ColorCell from './ColorCell.js' -import ColumnHeader from './ColumnHeader.js' -import EarthEngineColumns from './EarthEngineColumns.js' +import { EVENT_LAYER } from '../../constants/layers.js' +import { isDarkColor } from '../../util/colors.js' +import FilterInput from './FilterInput.js' import styles from './styles/DataTable.module.css' -import 'react-virtualized/styles.css' - -// Using react component to keep sorting state, which is only used within the data table. -class DataTable extends Component { - static propTypes = { - closeDataTable: PropTypes.func.isRequired, - height: PropTypes.number.isRequired, - highlightFeature: PropTypes.func.isRequired, - layer: PropTypes.object.isRequired, - setOrgUnitProfile: PropTypes.func.isRequired, - updateLayer: PropTypes.func.isRequired, - width: PropTypes.number.isRequired, - aggregations: PropTypes.object, - feature: PropTypes.object, - } - - static defaultProps = { - data: [], - } - - state = {} - - constructor(props, context) { - super(props, context) - - // Default sort - const sortBy = 'index' - const sortDirection = 'ASC' - - const data = this.sort(this.filter(), sortBy, sortDirection) - - this.state = { - sortBy, - sortDirection, - data, - } - } - - componentDidMount() { - this.loadExtendedData() - } +import { useTableData } from './useTableData.js' + +const ASCENDING = 'asc' +const DESCENDING = 'desc' + +const DataTableWithVirtuosoContext = ({ context, ...props }) => ( + +) + +DataTableWithVirtuosoContext.propTypes = { + context: PropTypes.shape({ + layout: PropTypes.string, + }), +} - componentDidUpdate(prevProps) { - const { layer, aggregations, closeDataTable } = this.props - const { data, dataFilters } = layer - const prev = prevProps.layer +const DataTableRowWithVirtuosoContext = ({ context, item, ...props }) => ( + context.onClick(item)} + onMouseEnter={() => context.onMouseEnter(item)} + onMouseLeave={context.onMouseLeave} + {...props} + /> +) + +DataTableRowWithVirtuosoContext.propTypes = { + context: PropTypes.shape({ + onClick: PropTypes.func, + onMouseEnter: PropTypes.func, + onMouseLeave: PropTypes.func, + }), + item: PropTypes.arrayOf( + PropTypes.shape({ + dataKey: PropTypes.string, + value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + }) + ), +} - if (!data) { - closeDataTable() - } else if ( - data !== prev.data || - dataFilters !== prev.dataFilters || - aggregations !== prevProps.aggregations - ) { - const { sortBy, sortDirection } = this.state +const TableComponents = { + Table: DataTableWithVirtuosoContext, + TableBody: DataTableBody, + TableHead: DataTableHead, + TableRow: DataTableRowWithVirtuosoContext, + EmptyPlaceholder: () => ( + + +
+ {i18n.t('No results found')} +
+ + + ), +} - this.setState({ - data: this.sort(this.filter(), sortBy, sortDirection), - }) +const Table = ({ availableHeight, availableWidth }) => { + const headerRowRef = useRef(null) + const [columnWidths, setColumnWidths] = useState([]) + const { mapViews } = useSelector((state) => state.map) + const activeLayerId = useSelector((state) => state.dataTable) + + const dispatch = useDispatch() + const feature = useSelector((state) => state.feature) + const [{ sortField, sortDirection }, setSorting] = useReducer( + (sorting, newSorting) => ({ ...sorting, ...newSorting }), + { + sortField: 'name', + sortDirection: ASCENDING, } - } + ) - loadExtendedData() { - const { layer, updateLayer } = this.props - const { layer: layerType, isExtended, serverCluster } = layer + const layer = mapViews.find((l) => l.id === activeLayerId) - if (layerType === EVENT_LAYER && !isExtended && !serverCluster) { - updateLayer({ - ...layer, - showDataTable: true, + const sortData = useCallback( + ({ name }) => { + setSorting({ + sortField: name, + sortDirection: + sortDirection === ASCENDING ? DESCENDING : ASCENDING, }) - } - } - - filter() { - const { layer, aggregations = {} } = this.props - const { dataFilters } = layer - const data = layer.data.filter( - (d) => !d.properties.hasAdditionalGeometry - ) - - return filterData( - data.map((d, index) => ({ - ...(d.properties || d), - ...aggregations[d.id], - index, - })), - dataFilters - ) - } - - // TODO: Make sure sorting works across different locales - use lib method - sort(data, sortBy, sortDirection) { - return data.sort((a, b) => { - a = a[sortBy] - b = b[sortBy] - - if (typeof a === 'number') { - return sortDirection === 'ASC' ? a - b : b - a + }, + [sortDirection] + ) + + const showOrgUnitProfile = useCallback( + (row) => { + const id = row.find((r) => r.dataKey === 'id')?.value + id && dispatch(setOrgUnitProfile(id)) + }, + [dispatch] + ) + + const setFeatureHighlight = useCallback( + (row) => { + const id = row.find((r) => r.dataKey === 'id')?.value + if (!id || !feature || id !== feature.id) { + dispatch( + highlightFeature( + id + ? { + id, + layerId: layer.id, + origin: 'table', + } + : null + ) + ) } - - if (a !== undefined) { - return sortDirection === 'ASC' - ? a.localeCompare(b) - : b.localeCompare(a) + }, + [feature, dispatch, layer.id] + ) + const clearFeatureHighlight = useCallback( + (event) => { + const nextElement = event.toElement ?? event.relatedTarget + // When hovering to the next row the next element is a `TD` + // If this is the case `setFeatureHighlight` will + // fire and the highlight does not need to be cleared + if (nextElement.tagName !== 'TD') { + dispatch(highlightFeature(null)) } - - return 0 - }) - } - - onSort(sortBy, sortDirection) { - const { data } = this.state - - this.setState({ - sortBy, - sortDirection, - data: this.sort(data, sortBy, sortDirection), - }) - } - - // Return event data items used for styling, filters or "display in reports" - getEventDataItems() { - const { headers = [] } = this.props.layer - - return headers - .filter(({ name }) => isValidUid(name)) - .map(({ name, column, valueType }) => ({ - key: name, - label: column, - type: numberValueTypes.includes(valueType) - ? 'number' - : 'string', - })) - } - - // Debounce needed as event is triggered multiple times for the same row - highlightFeature = debounce(50, (id) => { - const { feature, layer } = this.props - - // If not the same feature as already highlighted - if (!id || !feature || id !== feature.id) { - this.props.highlightFeature( - id - ? { - id, - layerId: layer.id, - origin: 'table', - } - : null - ) - } + }, + [dispatch] + ) + + const tableContext = useMemo( + () => ({ + onClick: + layer.layer !== EVENT_LAYER + ? showOrgUnitProfile + : Function.prototype, + onMouseEnter: setFeatureHighlight, + onMouseLeave: clearFeatureHighlight, + layout: columnWidths.length > 0 ? 'fixed' : 'auto', + }), + [ + layer.layer, + showOrgUnitProfile, + setFeatureHighlight, + clearFeatureHighlight, + columnWidths, + ] + ) + + const { headers, rows, isLoading, error } = useTableData({ + layer, + sortField, + sortDirection, }) - onRowClick = (evt) => this.props.setOrgUnitProfile(evt.rowData.id) - onRowMouseOver = (evt) => this.highlightFeature(evt.rowData.id) - onRowMouseOut = () => this.highlightFeature() - - render() { - const { data, sortBy, sortDirection } = this.state - const { width, height, layer, aggregations } = this.props - - const { - layer: layerType, - styleDataItem, - serverCluster, - aggregationType, - legend, - } = layer - - const isThematic = layerType === THEMATIC_LAYER - const isOrgUnit = layerType === ORG_UNIT_LAYER - const isEvent = layerType === EVENT_LAYER - const isEarthEngine = layerType === EARTH_ENGINE_LAYER - const isLoading = - isEarthEngine && aggregationType?.length && !aggregations + useEffect(() => { + /* The combination of automtic table layout and virtual scrolling + * causes a content shift when scrolling and filtering because the + * cells in the DOM have a different content length which causes the + * columns to have a different width. To avoid that we measure the + * initial column widths and switch to a fixed layout based on these + * measured widths */ + if (columnWidths.length === 0) { + requestAnimationFrame(() => { + const measuredColumnWidths = [] + + for (const cell of headerRowRef.current.cells) { + const rect = cell.getBoundingClientRect() + measuredColumnWidths.push(Math.floor(rect.width)) + } + + setColumnWidths(measuredColumnWidths) + }) + } + }, [columnWidths]) + + useEffect(() => { + /* When the window is resized, the sidebar opens, or the table + * headers change, the table needs to switch back to its + * automatic layout so that the cells can subsequently can be + * measured again in the useEffect hook above */ + setColumnWidths([]) + }, [availableWidth, headers]) + + if (error) { + return
{error}
+ } - return !serverCluster ? ( - <> - data[index]} - sort={({ sortBy, sortDirection }) => - this.onSort(sortBy, sortDirection) - } - sortBy={sortBy} - sortDirection={sortDirection} - useDynamicRowHeight={false} - hideIndexRow={false} - onRowClick={!isEvent ? this.onRowClick : undefined} - onRowMouseOver={this.onRowMouseOver} - onRowMouseOut={this.onRowMouseOut} - > - rowData.index} - dataKey="index" - label={i18n.t('Index')} - width={72} - className="right" - /> - ( - - )} - /> - ( - - )} - /> - {isEvent && ( - ( - - )} - cellRenderer={({ cellData }) => - cellData ? formatTime(cellData) : '' - } - /> - )} - {isEvent && - this.getEventDataItems().map(({ key, label, type }) => ( - ( - - )} - /> + return ( + <> + ( + + {headers.map(({ name, dataKey, type }, index) => ( + + ) + } + width={ + columnWidths.length > 0 + ? `${columnWidths[index]}px` + : 'auto' + } + > + {name} + ))} - {isThematic && ( - ( - - )} - /> - )} - {isThematic && ( - ( - - )} - /> - )} - {isThematic && ( - ( - - )} - /> - )} - {(isThematic || isOrgUnit) && ( - ( - - )} - /> - )} - {(isThematic || isOrgUnit) && ( - ( - - )} - /> - )} - ( - - )} - /> - {(isThematic || styleDataItem) && ( - ( - - )} - cellRenderer={ColorCell} - /> - )} - - {isEarthEngine && - EarthEngineColumns({ aggregationType, legend, data })} -
- {isLoading === true && ( -
- - - -
- )} - - ) : ( -
- {i18n.t( - 'Data table is not supported when events are grouped on the server.' + )} -
- ) - } + itemContent={(_, row) => + row.map(({ dataKey, value, align }) => ( + + {dataKey === 'color' ? value?.toLowerCase() : value} + + )) + } + /> + {isLoading && ( + + + + + + )} + + ) } -export default connect( - ({ dataTable, map, aggregations = {}, feature }) => { - const layer = map.mapViews.find((l) => l.id === dataTable) +Table.propTypes = { + availableHeight: PropTypes.number, + availableWidth: PropTypes.number, +} - return layer - ? { - layer, - feature, - aggregations: aggregations[layer.id], - } - : {} - }, - { - closeDataTable, - updateLayer, - setOrgUnitProfile, - highlightFeature, - } -)(DataTable) +export default Table diff --git a/src/components/datatable/ErrorBoundary.js b/src/components/datatable/ErrorBoundary.js new file mode 100644 index 000000000..d9032eab8 --- /dev/null +++ b/src/components/datatable/ErrorBoundary.js @@ -0,0 +1,40 @@ +import i18n from '@dhis2/d2-i18n' +import { CenteredContent } from '@dhis2/ui' +import PropTypes from 'prop-types' +import React, { Component } from 'react' + +class ErrorBoundary extends Component { + constructor(props) { + super(props) + this.state = { + error: null, + errorInfo: null, + } + } + + componentDidCatch(error, errorInfo) { + this.setState({ + error, + errorInfo, + }) + } + + render() { + const { children } = this.props + if (this.state.error) { + return ( + +

{i18n.t('Something went wrong')}

+
+ ) + } + + return children + } +} + +ErrorBoundary.propTypes = { + children: PropTypes.node.isRequired, +} + +export default ErrorBoundary diff --git a/src/components/datatable/FilterInput.js b/src/components/datatable/FilterInput.js index 109745bc0..16bab4a9c 100644 --- a/src/components/datatable/FilterInput.js +++ b/src/components/datatable/FilterInput.js @@ -1,68 +1,47 @@ +import i18n from '@dhis2/d2-i18n' +import { Input } from '@dhis2/ui' import PropTypes from 'prop-types' import React from 'react' -import { connect } from 'react-redux' +import { useDispatch, useSelector } from 'react-redux' import { setDataFilter, clearDataFilter } from '../../actions/dataFilters.js' -import styles from './styles/FilterInput.module.css' -// http://adazzle.github.io/react-data-grid/examples.html#/custom-filters -// https://github.com/adazzle/react-data-grid/tree/master/packages/react-data-grid-addons/src/cells/headerCells/filters -const FilterInput = ({ - layerId, - type, - dataKey, - filters, - setDataFilter, - clearDataFilter, -}) => { - const filterValue = filters[dataKey] || '' +const FilterInput = ({ type, dataKey, name }) => { + const dispatch = useDispatch() + const dataTable = useSelector((state) => state.dataTable) + const map = useSelector((state) => state.map) - // https://stackoverflow.com/questions/36683770/react-how-to-get-the-value-of-an-input-field - const onChange = (evt) => { - const value = evt.target.value + const overlay = + dataTable && map.mapViews.filter((layer) => layer.id === dataTable)[0] - if (value !== '') { - setDataFilter(layerId, dataKey, value) - } else { - clearDataFilter(layerId, dataKey, value) - } + let layerId + let filters + if (overlay) { + layerId = overlay.id + filters = overlay.dataFilters || {} } + const filterValue = filters[dataKey] || '' + + const onChange = ({ value }) => + value !== '' + ? dispatch(setDataFilter(layerId, dataKey, value)) + : dispatch(clearDataFilter(layerId, dataKey, value)) + return ( - 3&<8' : 'Search'} // TODO: Support more field types + 3&<8' : i18n.t('Search')} value={filterValue} - onClick={(evt) => evt.stopPropagation()} onChange={onChange} /> ) } FilterInput.propTypes = { - clearDataFilter: PropTypes.func.isRequired, dataKey: PropTypes.string.isRequired, - filters: PropTypes.object.isRequired, - layerId: PropTypes.string.isRequired, - setDataFilter: PropTypes.func.isRequired, + name: PropTypes.string.isRequired, type: PropTypes.string.isRequired, } -// Avoid needing to pass filter and actions to every input field -const mapStateToProps = ({ dataTable, map }) => { - const overlay = dataTable - ? map.mapViews.filter((layer) => layer.id === dataTable)[0] - : null - - if (overlay) { - return { - layerId: overlay.id, - filters: overlay.dataFilters || {}, - } - } - - return null -} - -export default connect(mapStateToProps, { setDataFilter, clearDataFilter })( - FilterInput -) +export default FilterInput diff --git a/src/components/datatable/__tests__/useTableData.spec.js b/src/components/datatable/__tests__/useTableData.spec.js new file mode 100644 index 000000000..9976daadb --- /dev/null +++ b/src/components/datatable/__tests__/useTableData.spec.js @@ -0,0 +1,539 @@ +import { renderHook } from '@testing-library/react-hooks' +import React from 'react' +import { Provider } from 'react-redux' +import configureMockStore from 'redux-mock-store' +import { useTableData } from '../useTableData.js' + +jest.mock('../../map/MapApi.js', () => ({ + loadEarthEngineWorker: jest.fn(), +})) + +const mockStore = configureMockStore() + +describe('useTableData', () => { + test('gets headers and rows for facility layer', () => { + const store = { + aggregations: {}, + } + const layer = { + layer: 'facility', + dataFilters: null, + data: [ + { + properties: { + id: 'facility-1', + name: 'Facility 1', + type: 'Point', + }, + }, + ], + } + + const { result } = renderHook( + () => + useTableData({ + layer, + sortField: 'name', + sortDirection: 'asc', + }), + { + wrapper: ({ children }) => ( + {children} + ), + } + ) + + const { headers, rows, isLoading } = result.current + expect(headers).toHaveLength(4) + expect(headers).toMatchObject([ + { name: 'Index', dataKey: 'index', type: 'number' }, + { name: 'Name', dataKey: 'name', type: 'string' }, + { name: 'Id', dataKey: 'id', type: 'string' }, + { name: 'Type', dataKey: 'type', type: 'string' }, + ]) + expect(rows).toHaveLength(1) + expect(rows[0]).toHaveLength(4) + expect(rows[0]).toMatchObject([ + { value: 0, dataKey: 'index' }, + { value: 'Facility 1', dataKey: 'name' }, + { value: 'facility-1', dataKey: 'id' }, + { value: 'Point', dataKey: 'type' }, + ]) + expect(isLoading).toBe(false) + }) + + test('gets headers and rows for orgUnit layer', () => { + const store = { + aggregations: {}, + } + const layer = { + layer: 'orgUnit', + dataFilters: null, + data: [ + { + properties: { + id: 'orgunit-id-1', + name: 'OrgUnitName 1', + type: 'MultiPolygon', + level: 3, + parentName: 'Bo', + }, + }, + ], + } + + const { result } = renderHook( + () => + useTableData({ + layer, + sortField: 'name', + sortDirection: 'asc', + }), + { + wrapper: ({ children }) => ( + {children} + ), + } + ) + const { headers, rows, isLoading } = result.current + expect(headers).toHaveLength(6) + expect(headers).toMatchObject([ + { name: 'Index', dataKey: 'index', type: 'number' }, + { name: 'Name', dataKey: 'name', type: 'string' }, + { name: 'Id', dataKey: 'id', type: 'string' }, + { name: 'Level', dataKey: 'level', type: 'number' }, + { name: 'Parent', dataKey: 'parentName', type: 'string' }, + { name: 'Type', dataKey: 'type', type: 'string' }, + ]) + expect(rows).toHaveLength(1) + expect(rows[0]).toHaveLength(6) + expect(rows[0]).toMatchObject([ + { value: 0, dataKey: 'index' }, + { value: 'OrgUnitName 1', dataKey: 'name' }, + { value: 'orgunit-id-1', dataKey: 'id' }, + { value: 3, dataKey: 'level' }, + { value: 'Bo', dataKey: 'parentName' }, + { value: 'MultiPolygon', dataKey: 'type' }, + ]) + expect(isLoading).toBe(false) + }) + + test('gets headers and rows for thematic layer', () => { + const store = { + aggregations: {}, + } + const layer = { + layer: 'thematic', + dataFilters: null, + data: [ + { + properties: { + type: 'Point', + id: 'thematicId-1', + name: 'Ngelehun CHC', + level: 4, + parentName: 'Badjia', + color: '#FFFFB2', + legend: 'Great', + range: '90 - 120', + value: 106.3, + }, + }, + ], + } + const { result } = renderHook( + () => + useTableData({ + layer, + sortField: 'name', + sortDirection: 'asc', + }), + { + wrapper: ({ children }) => ( + {children} + ), + } + ) + const { headers, rows, isLoading } = result.current + expect(headers).toHaveLength(10) + expect(headers).toMatchObject([ + { name: 'Index', dataKey: 'index', type: 'number' }, + { name: 'Name', dataKey: 'name', type: 'string' }, + { name: 'Id', dataKey: 'id', type: 'string' }, + { name: 'Value', dataKey: 'value', type: 'number' }, + { name: 'Legend', dataKey: 'legend', type: 'string' }, + { name: 'Range', dataKey: 'range', type: 'string' }, + { name: 'Level', dataKey: 'level', type: 'number' }, + { name: 'Parent', dataKey: 'parentName', type: 'string' }, + { name: 'Type', dataKey: 'type', type: 'string' }, + { + name: 'Color', + dataKey: 'color', + type: 'string', + renderer: 'rendercolor', + }, + ]) + expect(rows).toHaveLength(1) + expect(rows[0]).toHaveLength(10) + expect(rows[0]).toMatchObject([ + { value: 0, dataKey: 'index' }, + { value: 'Ngelehun CHC', dataKey: 'name' }, + { value: 'thematicId-1', dataKey: 'id' }, + { value: 106.3, dataKey: 'value' }, + { value: 'Great', dataKey: 'legend' }, + { value: '90 - 120', dataKey: 'range' }, + { value: 4, dataKey: 'level' }, + { value: 'Badjia', dataKey: 'parentName' }, + { value: 'Point', dataKey: 'type' }, + { value: '#FFFFB2', dataKey: 'color' }, + ]) + expect(isLoading).toBe(false) + }) + + test('gets headers and rows for event layer', () => { + const store = { + aggregations: {}, + } + const layer = { + layer: 'event', + dataFilters: null, + isExtended: true, + headers: [ + { + name: 'ps', + column: 'Program stage', + valueType: 'TEXT', + }, + { + name: 'eventdate', + column: 'Report date', + valueType: 'DATE', + }, + { + name: 'lastupdated', + column: 'Last updated on', + valueType: 'DATE', + }, + { + name: 'eventstatus', + column: 'Event status', + valueType: 'TEXT', + }, + { + name: 'oZg33kd9taw', + column: 'Gender', + valueType: 'TEXT', + }, + ], + + data: [ + { + properties: { + id: 'a9712323629', + type: 'Point', + ps: 'pTo4uMt3xur', + eventdate: '2023-05-15 00:00:00.0', + lastupdated: '2018-04-12 20:58:51.31', + ouname: 'Lumley Hospital', + eventstatus: 'ACTIVE', + oZg33kd9taw: 'Female', + value: 'Female', + color: '#ff7f00', + }, + }, + ], + } + const { result } = renderHook( + () => + useTableData({ + layer, + sortField: 'name', + sortDirection: 'asc', + }), + { + wrapper: ({ children }) => ( + {children} + ), + } + ) + const { headers, rows, isLoading } = result.current + expect(headers).toHaveLength(8) + expect(headers).toMatchObject([ + { name: 'Index', dataKey: 'index', type: 'number' }, + { name: 'Org unit', dataKey: 'ouname', type: 'string' }, + { name: 'Id', dataKey: 'id', type: 'string' }, + { + name: 'Event time', + dataKey: 'eventdate', + type: 'date', + renderer: 'formatTime...', + }, + { name: 'Last updated on', dataKey: 'lastupdated', type: 'string' }, + { name: 'Event status', dataKey: 'eventstatus', type: 'string' }, + { name: 'Gender', dataKey: 'oZg33kd9taw', type: 'string' }, + { name: 'Type', dataKey: 'type', type: 'string' }, + ]) + expect(rows).toHaveLength(1) + expect(rows[0]).toHaveLength(8) + expect(rows[0]).toMatchObject([ + { value: 0, dataKey: 'index' }, + { value: 'Lumley Hospital', dataKey: 'ouname' }, + { value: 'a9712323629', dataKey: 'id' }, + { value: '2023-05-15 00:00:00.0', dataKey: 'eventdate' }, + { value: '2018-04-12 20:58:51.31', dataKey: 'lastupdated' }, + { value: 'ACTIVE', dataKey: 'eventstatus' }, + { value: 'Female', dataKey: 'oZg33kd9taw' }, + { value: 'Point', dataKey: 'type' }, + ]) + expect(isLoading).toBe(false) + }) + + test('gets headers and rows for EE population layer', () => { + const store = { + aggregations: { + eelayerid: { + boOU: { + mean: 47.34593724212383, + sum: 851090.567864418, + }, + bombaliOU: { + mean: 27.347820392739166, + sum: 585872.3562736511, + }, + }, + }, + } + + const layer = { + layer: 'earthEngine', + aggregationType: ['sum', 'mean'], + legend: { + title: 'Population', + }, + id: 'eelayerid', + dataFilters: null, + data: [ + { + id: 'boOU', + properties: { + type: 'Polygon', + id: 'boOu', + name: 'Bo', + }, + }, + { + id: 'bombaliOU', + properties: { + type: 'Polygon', + id: 'bombaliOU', + name: 'Bombali', + }, + }, + ], + } + const { result } = renderHook( + () => + useTableData({ + layer, + sortField: 'name', + sortDirection: 'asc', + }), + { + wrapper: ({ children }) => ( + {children} + ), + } + ) + const { headers, rows, isLoading } = result.current + + expect(headers).toHaveLength(6) + expect(headers).toMatchObject([ + { name: 'Index', dataKey: 'index', type: 'number' }, + { name: 'Name', dataKey: 'name', type: 'string' }, + { name: 'Id', dataKey: 'id', type: 'string' }, + { name: 'Type', dataKey: 'type', type: 'string' }, + { + name: 'Sum Population', + dataKey: 'sum', + // roundFn: Function.prototype, + type: 'number', + }, + { + name: 'Mean Population', + dataKey: 'mean', + // roundFn: Function.prototype, + type: 'number', + }, + ]) + expect(headers[4].roundFn).toBeInstanceOf(Function) + expect(headers[5].roundFn).toBeInstanceOf(Function) + expect(rows).toHaveLength(2) + expect(rows[0]).toHaveLength(6) + expect(rows[0]).toMatchObject([ + { value: 0, dataKey: 'index' }, + { value: 'Bo', dataKey: 'name' }, + { value: 'boOu', dataKey: 'id' }, + { value: 'Polygon', dataKey: 'type' }, + { value: 851091, dataKey: 'sum' }, + { value: 47.35, dataKey: 'mean' }, + ]) + expect(isLoading).toBe(false) + }) + + test('gets headers and rows for EE population age groups layer', () => { + const store = { + aggregations: { + eelayerid: { + badijaOU: { + M_0_mean: 0.4416957503717281, + M_0_sum: 279.5934099853039, + M_1_mean: 1.667343524395007, + M_1_sum: 1055.4284509420395, + M_5_mean: 1.8668244672235907, + M_5_sum: 1181.699887752533, + mean: 3.975863741990326, + sum: 2516.7217486798763, + }, + baomaOU: { + M_0_mean: 0.6669754306043404, + M_0_sum: 1012.4687036573887, + M_1_mean: 2.517744771694477, + M_1_sum: 3821.9365634322166, + M_5_mean: 2.818359887764859, + M_5_sum: 4278.270309627056, + mean: 6.003080090063677, + sum: 9112.675576716661, + }, + }, + }, + } + + const layer = { + layer: 'earthEngine', + name: 'Population age groups', + aggregationType: ['sum', 'mean'], + id: 'eelayerid', + legend: { + title: 'Population age groups', + groups: [ + { + id: 'M_0', + name: 'Male 0 - 1 years', + }, + { + id: 'M_1', + name: 'Male 1 - 4 years', + }, + { + id: 'M_5', + name: 'Male 5 - 9 years', + }, + ], + items: [ + { + color: '#fee5d9', + from: 0, + to: 10, + name: '0 - 10', + }, + { + color: '#fcbba1', + from: 10, + to: 20, + name: '10 - 20', + }, + { + color: '#fc9272', + from: 20, + to: 30, + name: '20 - 30', + }, + { + color: '#fb6a4a', + from: 30, + to: 40, + name: '30 - 40', + }, + { + color: '#de2d26', + from: 40, + to: 50, + name: '40 - 50', + }, + { + color: '#a50f15', + from: 50, + name: '> 50', + }, + ], + }, + data: [ + { + id: 'badijaOU', + properties: { + type: 'Polygon', + id: 'boOU', + name: 'Badija', + }, + }, + { + type: 'Feature', + id: 'baomaOU', + properties: { + type: 'Polygon', + id: 'baomaOU', + name: 'Baoma', + }, + }, + ], + } + + const { result } = renderHook( + () => + useTableData({ + layer, + sortField: 'name', + sortDirection: 'asc', + }), + { + wrapper: ({ children }) => ( + {children} + ), + } + ) + const { headers, rows, isLoading } = result.current + + expect(headers).toHaveLength(6) + expect(headers).toMatchObject([ + { name: 'Index', dataKey: 'index', type: 'number' }, + { name: 'Name', dataKey: 'name', type: 'string' }, + { name: 'Id', dataKey: 'id', type: 'string' }, + { name: 'Type', dataKey: 'type', type: 'string' }, + { + name: 'Sum Population Age Groups', + dataKey: 'sum', + // roundFn: Function.prototype, + type: 'number', + }, + { + name: 'Mean Population Age Groups', + dataKey: 'mean', + // roundFn: Function.prototype, + type: 'number', + }, + ]) + expect(headers[4].roundFn).toBeInstanceOf(Function) + expect(headers[5].roundFn).toBeInstanceOf(Function) + expect(rows).toHaveLength(2) + expect(rows[0]).toHaveLength(6) + expect(rows[0]).toMatchObject([ + { value: 0, dataKey: 'index' }, + { value: 'Badija', dataKey: 'name' }, + { value: 'boOU', dataKey: 'id' }, + { value: 'Polygon', dataKey: 'type' }, + { value: 2517, dataKey: 'sum' }, + { value: 3.976, dataKey: 'mean' }, + ]) + expect(isLoading).toBe(false) + }) +}) diff --git a/src/components/datatable/styles/BottomPanel.module.css b/src/components/datatable/styles/BottomPanel.module.css index cd3dff206..85fc33e4f 100644 --- a/src/components/datatable/styles/BottomPanel.module.css +++ b/src/components/datatable/styles/BottomPanel.module.css @@ -4,13 +4,36 @@ bottom: 0; z-index: 1040; background: #fff; - box-shadow: 0 -2px 3px rgba(0, 0, 0, 0.1); +} + +.dataTableControls { + width: 100%; + height: 20px; + background-color: var(--colors-grey100); + position: relative; } .closeIcon { position: absolute; - right: 3px; + top: 0; + right: 2px; z-index: 100; cursor: pointer; color: var(--colors-grey800); + background-color: var(--colors-grey100); + width: 20px; + height: 20px; + border: none; +} + +.closeIcon:hover { + color: var(--colors-grey900); + background-color: var(--colors-grey300); +} + +.closeIcon svg { + position:absolute; + top: 50%; + left: 50%; + margin: -8px 0 0 -8px; } diff --git a/src/components/datatable/styles/DataTable.module.css b/src/components/datatable/styles/DataTable.module.css index b624f85ce..b5a3e6e4c 100644 --- a/src/components/datatable/styles/DataTable.module.css +++ b/src/components/datatable/styles/DataTable.module.css @@ -1,74 +1,60 @@ .dataTable { - font-size: 11px; - font-family: Roboto, sans-serif; - overflow: hidden; + height: 1px; } -.noSupport { - position: absolute; - top: 50%; - left: 50%; - transform: translateX(-50%) translateY(-50%); - color: #333; - font-style: italic; - line-height: 30px; -} - -.loader { - position: absolute; - width: 100%; - height: 100%; - top: 0; +.dataTable > :global(thead) { + user-select: none; } -:global(.ReactVirtualized__Table__headerRow) { - position: relative; - background-color: #eee; - box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 6px, rgba(0, 0, 0, 0.12) 0px 1px 2px; - z-index: 10; +td.dataCell { + padding-top: var(--spacers-dp8); + padding-bottom: var(--spacers-dp8); + font-size: 11px; } -:global(.ReactVirtualized__Table__headerRow .ColumnHeader-label) { - white-space: nowrap; +td.dataCell:hover { + cursor: default; } -:global(.ReactVirtualized__Table__headerTruncatedText) { - display: inline-block; - position: absolute; - top: 7px; - left: 10px; - right: 15px; - user-select: none; - overflow: hidden; +td.lightText { + color: var(--colors-white); } -:global(.ReactVirtualized__Table__sortableHeaderIcon) { - position: absolute; - top: 5px; - right: 0; +.columnHeader > :global(span.container) { + justify-content: space-between; } -:global(.ReactVirtualized__Table__headerColumn) { - height: 48px; - margin-bottom: 2px; - position: relative; +.columnHeader :global(input.dense) { + padding: 4px 6px; } -:global(.ReactVirtualized__Table__headerColumn:focus) { - outline: none; +.columnHeader :global(input::placeholder) { + color: var(--colors-grey400); } -:global(.ReactVirtualized__Table__row) { - position: relative; - border-bottom: 1px solid #e0e0e0; - z-index: 9; +/* Hide the filter icon */ +.columnHeader + > :global(span.container) + > :global(span.top) + > button:last-of-type { + visibility: hidden; } -:global(.ReactVirtualized__Table__row:hover) { - background-color: #fafafa; - cursor: pointer; +.noResults { + display: flex; + color: var(--colors-grey600); + align-items: center; + justify-content: center; + font-style: italic; + min-height: 40px; } -:global(.ReactVirtualized__Table__rowColumn.right) { - text-align: right; +.noSupport { + position: absolute; + top: 50%; + left: 50%; + transform: translateX(-50%) translateY(-50%); + color: #333; + font-style: italic; + line-height: 30px; } diff --git a/src/components/datatable/styles/FilterInput.module.css b/src/components/datatable/styles/FilterInput.module.css deleted file mode 100644 index 91807f2e2..000000000 --- a/src/components/datatable/styles/FilterInput.module.css +++ /dev/null @@ -1,14 +0,0 @@ -.filterInput { - position: absolute; - left: 0; - top: 22px; - box-sizing: border-box; - width: 100%; - height: 24px; - font-weight: normal; - padding-left: 5px; -} - -.filterInput::placeholder { - color: #ddd; -} diff --git a/src/components/datatable/styles/ResizeHandle.module.css b/src/components/datatable/styles/ResizeHandle.module.css index e3f5952ee..27c0465ab 100644 --- a/src/components/datatable/styles/ResizeHandle.module.css +++ b/src/components/datatable/styles/ResizeHandle.module.css @@ -2,27 +2,18 @@ display: flex; justify-content: center; align-items: center; - position: absolute; - left: 50%; - top: -8px; - box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.2); - width: 40px; - height: 12px; - background: #fff; + width: 100%; + height: 100%; z-index: 1500; cursor: grab; - cursor: -moz-grab; - cursor: -webkit-grab; } .resizeHandle:hover, .resizeHandle:active { - transform: scale(1.03); - box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.2); + background-color: var(--colors-grey300); + color: var(--colors-grey900); } .resizeHandle:active { cursor: grabbing; - cursor: -moz-grabbing; - cursor: -webkit-grabbing; } diff --git a/src/components/datatable/useTableData.js b/src/components/datatable/useTableData.js new file mode 100644 index 000000000..42e61bf0c --- /dev/null +++ b/src/components/datatable/useTableData.js @@ -0,0 +1,282 @@ +import i18n from '@dhis2/d2-i18n' +import { useMemo } from 'react' +import { useSelector } from 'react-redux' +import { + EVENT_LAYER, + THEMATIC_LAYER, + ORG_UNIT_LAYER, + EARTH_ENGINE_LAYER, + FACILITY_LAYER, +} from '../../constants/layers.js' +import { numberValueTypes } from '../../constants/valueTypes.js' +import { hasClasses, getPrecision } from '../../util/earthEngine.js' +import { filterData } from '../../util/filter.js' +import { isValidUid } from '../../util/helpers.js' +import { numberPrecision } from '../../util/numbers.js' + +const ASCENDING = 'asc' + +const TYPE_NUMBER = 'number' +const TYPE_STRING = 'string' +const TYPE_DATE = 'date' + +const INDEX = 'index' +const NAME = 'name' +const ID = 'id' +const VALUE = 'value' +const LEGEND = 'legend' +const RANGE = 'range' +const LEVEL = 'level' +const PARENT_NAME = 'parentName' +const TYPE = 'type' +const COLOR = 'color' +const OUNAME = 'ouname' +const EVENTDATE = 'eventdate' + +const defaultFieldsMap = () => ({ + [INDEX]: { name: i18n.t('Index'), dataKey: INDEX, type: TYPE_NUMBER }, + [NAME]: { name: i18n.t('Name'), dataKey: NAME, type: TYPE_STRING }, + [ID]: { name: i18n.t('Id'), dataKey: ID, type: TYPE_STRING }, + [LEVEL]: { name: i18n.t('Level'), dataKey: LEVEL, type: TYPE_NUMBER }, + [PARENT_NAME]: { + name: i18n.t('Parent'), + dataKey: PARENT_NAME, + type: TYPE_STRING, + }, + [TYPE]: { name: i18n.t('Type'), dataKey: TYPE, type: TYPE_STRING }, + [VALUE]: { name: i18n.t('Value'), dataKey: VALUE, type: TYPE_NUMBER }, + [LEGEND]: { name: i18n.t('Legend'), dataKey: LEGEND, type: TYPE_STRING }, + [RANGE]: { name: i18n.t('Range'), dataKey: RANGE, type: TYPE_STRING }, + [OUNAME]: { name: i18n.t('Org unit'), dataKey: OUNAME, type: TYPE_STRING }, + [EVENTDATE]: { + name: i18n.t('Event time'), + dataKey: EVENTDATE, + type: TYPE_DATE, + renderer: 'formatTime...', + }, + [COLOR]: { + name: i18n.t('Color'), + dataKey: COLOR, + type: TYPE_STRING, + renderer: 'rendercolor', + }, +}) + +const getThematicHeaders = () => + [ + INDEX, + NAME, + ID, + VALUE, + LEGEND, + RANGE, + LEVEL, + PARENT_NAME, + TYPE, + COLOR, + ].map((field) => defaultFieldsMap()[field]) + +const getEventHeaders = ({ layerHeaders = [], styleDataItem }) => { + const fields = [INDEX, OUNAME, ID, EVENTDATE].map( + (field) => defaultFieldsMap()[field] + ) + + const customFields = layerHeaders + .filter(({ name }) => isValidUid(name)) + .map(({ name: dataKey, column: name, valueType }) => ({ + name, + dataKey, + type: numberValueTypes.includes(valueType) + ? TYPE_NUMBER + : TYPE_STRING, + })) + + customFields.push(defaultFieldsMap()[TYPE]) + + if (styleDataItem) { + customFields.push(defaultFieldsMap()[COLOR]) + } + + return fields.concat(customFields) +} + +const getOrgUnitHeaders = () => + [INDEX, NAME, ID, LEVEL, PARENT_NAME, TYPE].map( + (field) => defaultFieldsMap()[field] + ) + +const getFacilityHeaders = () => + [INDEX, NAME, ID, TYPE].map((field) => defaultFieldsMap()[field]) + +const toTitleCase = (str) => + str.replace( + /\w\S*/g, + (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase() + ) + +const getEarthEngineHeaders = ({ aggregationType, legend, data }) => { + const { title, items } = legend + + let customFields = [] + + if (hasClasses(aggregationType) && items) { + customFields = items.map(({ id, name }) => ({ + name, + dataKey: String(id), + roundFn: numberPrecision(2), + type: TYPE_NUMBER, + })) + } else if (Array.isArray(aggregationType) && aggregationType.length) { + customFields = aggregationType.map((type) => { + let roundFn = null + if (data?.length) { + const precision = getPrecision(data.map((d) => d[type])) + roundFn = numberPrecision(precision) + } + return { + name: toTitleCase(`${type} ${title}`), + dataKey: type, + roundFn, + type: TYPE_NUMBER, + } + }) + } + + return [INDEX, NAME, ID, TYPE] + .map((field) => defaultFieldsMap()[field]) + .concat(customFields) +} + +const EMPTY_AGGREGATIONS = {} +const EMPTY_LAYER = {} + +export const useTableData = ({ layer, sortField, sortDirection }) => { + const allAggregations = useSelector((state) => state.aggregations) + const aggregations = allAggregations[layer.id] || EMPTY_AGGREGATIONS + + const { + layer: layerType, + aggregationType, + legend, + styleDataItem, + data, + dataFilters, + headers: layerHeaders, + serverCluster, + } = layer || EMPTY_LAYER + + const dataWithAggregations = useMemo(() => { + if (!data || serverCluster) { + return null + } + return data + .map((d, i) => ({ + index: i, + ...d, + })) + .filter((d) => !d.properties.hasAdditionalGeometry) + .map((d, i) => ({ + ...(d.properties || d), + ...aggregations[d.id], + index: d.index, + i, + })) + }, [data, aggregations, serverCluster]) + + const headers = useMemo(() => { + if (dataWithAggregations === null) { + return null + } + + switch (layerType) { + case THEMATIC_LAYER: + return getThematicHeaders() + case EVENT_LAYER: + return getEventHeaders({ layerHeaders, styleDataItem }) + case ORG_UNIT_LAYER: + return getOrgUnitHeaders() + case EARTH_ENGINE_LAYER: + return getEarthEngineHeaders({ + aggregationType, + legend, + data: dataWithAggregations, + }) + case FACILITY_LAYER: + return getFacilityHeaders() + default: { + return null + } + } + }, [ + layerType, + aggregationType, + legend, + styleDataItem, + dataWithAggregations, + layerHeaders, + ]) + + const rows = useMemo(() => { + if (dataWithAggregations === null || headers === null) { + return null + } + + if (!dataWithAggregations.length || !headers?.length) { + return [] + } + + const filteredData = filterData(dataWithAggregations, dataFilters) + + //sort + filteredData.sort((a, b) => { + a = a[sortField] + b = b[sortField] + + if (typeof a === TYPE_NUMBER) { + return sortDirection === ASCENDING ? a - b : b - a + } + // TODO: Make sure sorting works across different locales - use lib method + if (a !== undefined) { + return sortDirection === ASCENDING + ? a.localeCompare(b) + : b.localeCompare(a) + } + + return 0 + }) + + return filteredData.map((item) => + headers.map(({ dataKey, roundFn, type }) => { + const value = roundFn ? roundFn(item[dataKey]) : item[dataKey] + + return { + dataKey, + value: type === TYPE_NUMBER && isNaN(value) ? null : value, + align: type === TYPE_NUMBER ? 'right' : 'left', + } + }) + ) + }, [headers, dataWithAggregations, dataFilters, sortField, sortDirection]) + + // EE layers and event layers may be loading additional data + const isLoading = + (layerType === EARTH_ENGINE_LAYER && + aggregationType?.length && + (!aggregations || aggregations === EMPTY_AGGREGATIONS)) || + (layerType === EVENT_LAYER && !layer.isExtended && !serverCluster) + + let error = null + if (serverCluster) { + error = i18n.t( + 'Data table is not supported when events are grouped on the server.' + ) + } else if (dataWithAggregations === null) { + error = i18n.t( + 'No valid data was found for the current layer configuration.' + ) + } else if (headers === null) { + error = i18n.t('Data table is not supported for this layer type.') + } + + return { headers, rows, isLoading, error } +} diff --git a/src/components/layers/toolbar/LayerToolbarMoreMenu.js b/src/components/layers/toolbar/LayerToolbarMoreMenu.js index 619598f76..b2b3846bf 100644 --- a/src/components/layers/toolbar/LayerToolbarMoreMenu.js +++ b/src/components/layers/toolbar/LayerToolbarMoreMenu.js @@ -40,6 +40,9 @@ const LayerToolbarMoreMenu = ({ return null } + const showDataTableDisabled = + !hasOrgUnitData && (!dataTableOpen || dataTableOpen !== layer.id) + return ( <>
)} {openAs && ( diff --git a/src/components/loaders/EventLoader.js b/src/components/loaders/EventLoader.js index 2230658da..df45f6be2 100644 --- a/src/components/loaders/EventLoader.js +++ b/src/components/loaders/EventLoader.js @@ -1,11 +1,13 @@ import PropTypes from 'prop-types' import { useEffect } from 'react' +import { useSelector } from 'react-redux' import eventLoader from '../../loaders/eventLoader.js' const EventLoader = ({ config, onLoad }) => { + const dataTableOpen = useSelector((state) => !!state.dataTable) useEffect(() => { - eventLoader(config).then(onLoad) - }, [config, onLoad]) + eventLoader(config, dataTableOpen).then(onLoad) + }, [config, onLoad, dataTableOpen]) return null } diff --git a/src/components/loaders/LayersLoader.js b/src/components/loaders/LayersLoader.js index b703672a1..36396215c 100644 --- a/src/components/loaders/LayersLoader.js +++ b/src/components/loaders/LayersLoader.js @@ -1,29 +1,44 @@ import React, { useEffect } from 'react' import { useSelector, useDispatch } from 'react-redux' import { setLayerLoading, updateLayer } from '../../actions/layers.js' +import { EVENT_LAYER } from '../../constants/layers.js' import LayerLoader from './LayerLoader.js' const LayersLoader = () => { - const layers = useSelector((state) => - state.map.mapViews.filter((layer) => { - // The layer is currently being loaded - don't load again - if (layer.isLoading) { - return false - } else { - // The layer is not loaded - load it - if (!layer.isLoaded) { - return true + const layers = useSelector(({ map, dataTable }) => + map.mapViews.filter( + ({ + id, + isLoading, + isLoaded, + isExtended, + layer: layerType, + serverCluster, + }) => { + // The layer is currently being loaded - don't load again + if (isLoading) { + return false + } else { + // The layer is not loaded - load it + if (!isLoaded) { + return true + } + + // The layer is loaded but the data table is now displayed and + // event extended data hasn't been loaded yet - so load it + if ( + layerType === EVENT_LAYER && + id === dataTable && + !isExtended && + !serverCluster + ) { + return true + } + + return false } - - // The layer is loaded but the data table is now displayed and - // event extended data hasn't been loaded yet - so load it - if (layer.showDataTable && !layer.isExtended) { - return true - } - - return false } - }) + ) ) const dispatch = useDispatch() diff --git a/src/components/loaders/__tests__/LayersLoader.spec.js b/src/components/loaders/__tests__/LayersLoader.spec.js index f9d933a89..f8a9fc4b9 100644 --- a/src/components/loaders/__tests__/LayersLoader.spec.js +++ b/src/components/loaders/__tests__/LayersLoader.spec.js @@ -2,10 +2,13 @@ import { render } from '@testing-library/react' import React from 'react' import { Provider } from 'react-redux' import configureMockStore from 'redux-mock-store' +import { EVENT_LAYER } from '../../../constants/layers.js' import LayersLoader from '../LayersLoader.js' const mockStore = configureMockStore() +const id = 'thelayerid' + jest.mock( '../LayerLoader.js', () => @@ -16,24 +19,26 @@ jest.mock( const testCases = [ { - testTitle: 'renders 0 layers if no layers', + testTitle: 'renders 0 layerloaders if no layers', store: { map: { mapViews: [], }, + dataTable: null, }, }, { - testTitle: 'renders 0 layers if currently loading the layer', + testTitle: 'renders 0 layerloaders if currently loading the layer', store: { map: { mapViews: [{ isLoading: true, isLoaded: false }], }, + dataTable: null, }, }, { testTitle: - 'renders 0 layers if currently loading regardless of whether loaded already', + 'renders 0 layerloaders if currently loading regardless of whether loaded already', store: { map: { mapViews: [ @@ -43,10 +48,12 @@ const testCases = [ }, ], }, + dataTable: null, }, }, { - testTitle: 'renders 1 layer if not currently loading and not loaded', + testTitle: + 'renders 1 layerloader if not currently loading and not loaded', store: { map: { mapViews: [ @@ -56,45 +63,52 @@ const testCases = [ }, ], }, + dataTable: null, }, }, { testTitle: - 'renders 1 layer if not currently loading and is loaded but need extended data', + 'renders 1 layerloader if not currently loading and is loaded but need extended data', store: { map: { mapViews: [ { + id, + layer: EVENT_LAYER, isLoading: false, isLoaded: true, - showDataTable: true, isExtended: false, + serverCluster: false, }, ], }, + dataTable: id, }, }, { testTitle: - 'renders 0 layers if not currently loading and loaded and extended data also loaded', + 'renders 0 layerloaders if not currently loading and loaded and extended data also loaded', store: { map: { mapViews: [ { + id, + layer: EVENT_LAYER, isLoading: false, isLoaded: true, - showDataTable: true, isExtended: true, + serverCluster: false, }, ], }, + dataTable: id, }, }, ] describe('LayersLoader', () => { testCases.forEach(({ testTitle, store }) => { - test(testTitle, () => { + it(testTitle, () => { const { container } = render( diff --git a/src/components/loaders/__tests__/__snapshots__/LayersLoader.spec.js.snap b/src/components/loaders/__tests__/__snapshots__/LayersLoader.spec.js.snap index 90197f2b9..e8c7db59e 100644 --- a/src/components/loaders/__tests__/__snapshots__/LayersLoader.spec.js.snap +++ b/src/components/loaders/__tests__/__snapshots__/LayersLoader.spec.js.snap @@ -1,14 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`LayersLoader renders 0 layers if currently loading regardless of whether loaded already 1`] = `
`; +exports[`LayersLoader renders 0 layerloaders if currently loading regardless of whether loaded already 1`] = `
`; -exports[`LayersLoader renders 0 layers if currently loading the layer 1`] = `
`; +exports[`LayersLoader renders 0 layerloaders if currently loading the layer 1`] = `
`; -exports[`LayersLoader renders 0 layers if no layers 1`] = `
`; +exports[`LayersLoader renders 0 layerloaders if no layers 1`] = `
`; -exports[`LayersLoader renders 0 layers if not currently loading and loaded and extended data also loaded 1`] = `
`; +exports[`LayersLoader renders 0 layerloaders if not currently loading and loaded and extended data also loaded 1`] = `
`; -exports[`LayersLoader renders 1 layer if not currently loading and is loaded but need extended data 1`] = ` +exports[`LayersLoader renders 1 layerloader if not currently loading and is loaded but need extended data 1`] = `
LayerLoader @@ -16,7 +16,7 @@ exports[`LayersLoader renders 1 layer if not currently loading and is loaded but
`; -exports[`LayersLoader renders 1 layer if not currently loading and not loaded 1`] = ` +exports[`LayersLoader renders 1 layerloader if not currently loading and not loaded 1`] = `
LayerLoader diff --git a/src/loaders/eventLoader.js b/src/loaders/eventLoader.js index c53eeb80c..1761728b7 100644 --- a/src/loaders/eventLoader.js +++ b/src/loaders/eventLoader.js @@ -7,6 +7,7 @@ import { EVENT_COLOR, EVENT_RADIUS, } from '../constants/layers.js' +import { numberValueTypes } from '../constants/valueTypes.js' import { getFiltersFromColumns, getFiltersAsText, @@ -16,6 +17,7 @@ import { import { cssColor, getContrastColor } from '../util/colors.js' import { getAnalyticsRequest, loadData } from '../util/event.js' import { getBounds } from '../util/geojson.js' +import { isValidUid } from '../util/helpers.js' import { styleByDataItem } from '../util/styleByDataItem.js' import { formatStartEndDate, getDateArray } from '../util/time.js' @@ -37,10 +39,10 @@ const unknownErrorAlert = { // TODO: Refactor to share code with other loaders // Returns a promise -const eventLoader = async (layerConfig) => { +const eventLoader = async (layerConfig, loadExtended) => { const config = { ...layerConfig } try { - await loadEventLayer(config) + await loadEventLayer(config, loadExtended) } catch (e) { if (e.httpStatusCode === 403 || e.httpStatusCode === 409) { config.alerts = [ @@ -61,7 +63,7 @@ const eventLoader = async (layerConfig) => { return config } -const loadEventLayer = async (config) => { +const loadEventLayer = async (config, loadExtended) => { const { columns, endDate, @@ -74,14 +76,13 @@ const loadEventLayer = async (config) => { startDate, styleDataItem, areaRadius, - showDataTable, } = config const period = getPeriodFromFilters(filters) const dataFilters = getFiltersFromColumns(columns) const d2 = await getD2() - config.isExtended = showDataTable + config.isExtended = loadExtended const analyticsRequest = await getAnalyticsRequest(config, { d2, @@ -160,6 +161,26 @@ const loadEventLayer = async (config) => { }) config.headers = response.headers + + const numericDataItemHeaders = config.headers.filter( + (header) => + isValidUid(header.name) && + numberValueTypes.includes(header.valueType) + ) + + if (numericDataItemHeaders.length) { + config.data = config.data.map((d) => { + const newD = { ...d } + + numericDataItemHeaders.forEach((header) => { + newD.properties[header.name] = parseFloat( + d.properties[header.name] + ) + }) + + return newD + }) + } } if (!styleDataItem) { diff --git a/yarn.lock b/yarn.lock index 7add303b8..452847445 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26,14 +26,7 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.8.3": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== - dependencies: - "@babel/highlight" "^7.18.6" - -"@babel/code-frame@^7.22.13": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.8.3": version "7.22.13" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== @@ -76,17 +69,7 @@ eslint-visitor-keys "^2.1.0" semver "^6.3.0" -"@babel/generator@^7.21.0", "@babel/generator@^7.7.2": - version "7.21.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd" - integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA== - dependencies: - "@babel/types" "^7.21.0" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/generator@^7.23.0": +"@babel/generator@^7.21.0", "@babel/generator@^7.23.0", "@babel/generator@^7.7.2": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g== @@ -156,12 +139,7 @@ resolve "^1.14.2" semver "^6.1.2" -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== - -"@babel/helper-environment-visitor@^7.22.20": +"@babel/helper-environment-visitor@^7.18.9", "@babel/helper-environment-visitor@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== @@ -173,15 +151,7 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0", "@babel/helper-function-name@^7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4" - integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg== - dependencies: - "@babel/template" "^7.20.7" - "@babel/types" "^7.21.0" - -"@babel/helper-function-name@^7.23.0": +"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0", "@babel/helper-function-name@^7.21.0", "@babel/helper-function-name@^7.23.0": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== @@ -189,14 +159,7 @@ "@babel/template" "^7.22.15" "@babel/types" "^7.23.0" -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-hoist-variables@^7.22.5": +"@babel/helper-hoist-variables@^7.18.6", "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== @@ -279,36 +242,19 @@ dependencies: "@babel/types" "^7.20.0" -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-split-export-declaration@^7.22.6": +"@babel/helper-split-export-declaration@^7.18.6", "@babel/helper-split-export-declaration@^7.22.6": version "7.22.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== dependencies: "@babel/types" "^7.22.5" -"@babel/helper-string-parser@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" - integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== - "@babel/helper-string-parser@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== -"@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== - -"@babel/helper-validator-identifier@^7.22.20": +"@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.19.1", "@babel/helper-validator-identifier@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== @@ -337,16 +283,7 @@ "@babel/traverse" "^7.21.0" "@babel/types" "^7.21.0" -"@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.22.13": +"@babel/highlight@^7.10.4", "@babel/highlight@^7.22.13": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== @@ -355,12 +292,7 @@ chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.0", "@babel/parser@^7.7.0": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3" - integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ== - -"@babel/parser@^7.22.15", "@babel/parser@^7.23.0": +"@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.0", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0", "@babel/parser@^7.7.0": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== @@ -1141,30 +1073,14 @@ core-js "^2.6.12" regenerator-runtime "^0.13.11" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.0", "@babel/runtime@^7.16.3", "@babel/runtime@^7.2.0", "@babel/runtime@^7.20.6", "@babel/runtime@^7.20.7", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" - integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== - dependencies: - regenerator-runtime "^0.13.11" - -"@babel/runtime@^7.7.6": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.0", "@babel/runtime@^7.16.3", "@babel/runtime@^7.2.0", "@babel/runtime@^7.20.6", "@babel/runtime@^7.20.7", "@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.8.7", "@babel/runtime@^7.9.2": version "7.22.10" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.10.tgz#ae3e9631fd947cb7e3610d3e9d8fef5f76696682" integrity sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ== dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.3.3": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" - integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - -"@babel/template@^7.22.15": +"@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.22.15", "@babel/template@^7.3.3": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== @@ -1197,16 +1113,7 @@ "@babel/helper-validator-identifier" "^7.14.9" to-fast-properties "^2.0.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.21.4", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": - version "7.21.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.4.tgz#2d5d6bb7908699b3b416409ffd3b5daa25b030d4" - integrity sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA== - dependencies: - "@babel/helper-string-parser" "^7.19.4" - "@babel/helper-validator-identifier" "^7.19.1" - to-fast-properties "^2.0.0" - -"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0": +"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.21.4", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== @@ -3308,6 +3215,14 @@ lz-string "^1.4.4" pretty-format "^27.0.2" +"@testing-library/react-hooks@^8.0.1": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz#0924bbd5b55e0c0c0502d1754657ada66947ca12" + integrity sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g== + dependencies: + "@babel/runtime" "^7.12.5" + react-error-boundary "^3.1.0" + "@testing-library/react@^12.1.2", "@testing-library/react@^12.1.5": version "12.1.5" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.5.tgz#bb248f72f02a5ac9d949dea07279095fa577963b" @@ -5507,7 +5422,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -8308,12 +8223,7 @@ flush-write-stream@^1.0.2: inherits "^2.0.3" readable-stream "^2.3.6" -follow-redirects@^1.0.0, follow-redirects@^1.14.7, follow-redirects@^1.14.9: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== - -follow-redirects@^1.15.0: +follow-redirects@^1.0.0, follow-redirects@^1.14.7, follow-redirects@^1.14.9, follow-redirects@^1.15.0: version "1.15.3" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== @@ -13410,6 +13320,13 @@ react-dom@^16.14.0, react-dom@^16.8.6: prop-types "^15.6.2" scheduler "^0.19.1" +react-error-boundary@^3.1.0: + version "3.1.4" + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.4.tgz#255db92b23197108757a888b01e5b729919abde0" + integrity sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA== + dependencies: + "@babel/runtime" "^7.12.5" + react-error-overlay@^6.0.11: version "6.0.11" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb" @@ -13580,6 +13497,11 @@ react-virtualized@^9.22.5: prop-types "^15.7.2" react-lifecycles-compat "^3.0.4" +react-virtuoso@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-4.6.2.tgz#74b59ebe3260e1f73e92340ffec84a6853285a12" + integrity sha512-vvlqvzPif+MvBrJ09+hJJrVY0xJK9yran+A+/1iwY78k0YCVKsyoNPqoLxOxzYPggspNBNXqUXEcvckN29OxyQ== + react@^16.14.0, react@^16.8.6: version "16.14.0" resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" @@ -14125,14 +14047,7 @@ rxjs@^6.6.0: dependencies: tslib "^1.9.0" -rxjs@^7.5.1: - version "7.8.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4" - integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg== - dependencies: - tslib "^2.1.0" - -rxjs@^7.8.1: +rxjs@^7.5.1, rxjs@^7.8.1: version "7.8.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== @@ -15539,16 +15454,11 @@ tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0: +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1: version "2.6.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410" integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig== -tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" - integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== - tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" From 0696fbaab1c54021f857eb7ce5f82842389b02cf Mon Sep 17 00:00:00 2001 From: Jen Jones Arnesen Date: Tue, 13 Feb 2024 10:52:22 +0100 Subject: [PATCH 5/5] chore: include release notes in slack bot message (#3123) --- .github/workflows/dhis2-verify-app.yml | 34 +++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dhis2-verify-app.yml b/.github/workflows/dhis2-verify-app.yml index d802dab9a..12e9c2d65 100644 --- a/.github/workflows/dhis2-verify-app.yml +++ b/.github/workflows/dhis2-verify-app.yml @@ -187,13 +187,41 @@ jobs: channel-id: ${{ secrets.SLACK_CHANNEL_ID }} payload: | { - "text": ":large_green_circle: :maps-app: :tada: Maps app release succeeded for version: ${{ steps.extract_version.outputs.version }}", + "text": "Maps app release ${{ steps.extract_version.outputs.version }} succeeded", "blocks": [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": ":large_green_circle: :maps-app: Maps version ${{ steps.extract_version.outputs.version }} released :tada:", + "emoji": true + } + }, + { + "type": "divider" + }, { "type": "section", "text": { - "type": "mrkdwn", - "text": ":large_green_circle: :maps-app: :tada: Maps version ${{ steps.extract_version.outputs.version }} released " + "type": "mrkdwn", + "text": "*Release Notes*" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ${{ toJSON(github.event.head_commit.message) }} + } + }, + { + "type": "divider" + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Link to " } } ]