diff --git a/cypress/fixtures/externalMapLayersWithGeojson.json b/cypress/fixtures/externalMapLayersWithGeojson.json index 03e6e3fed..b33a5e0a9 100644 --- a/cypress/fixtures/externalMapLayersWithGeojson.json +++ b/cypress/fixtures/externalMapLayersWithGeojson.json @@ -67,4 +67,4 @@ "name": "Polygon only geojson" } ] -} \ No newline at end of file +} diff --git a/cypress/integration/dataTable.cy.js b/cypress/integration/dataTable.cy.js index 8649e6b18..744ee310f 100644 --- a/cypress/integration/dataTable.cy.js +++ b/cypress/integration/dataTable.cy.js @@ -133,25 +133,23 @@ describe('data table', () => { cy.getByDataTest('org-unit-profile').should('be.visible') }) - it.skip('opens the data table for an Event layer', () => { + 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') + .selectProgram('Inpatient morbidity and mortality') + .validateStage('Inpatient morbidity and mortality') .selectTab('Period') .selectPeriodType('Start/end dates') .typeStartDate(`${CURRENT_YEAR - 1}-01-01`) - .typeEndDate(`${CURRENT_YEAR - 1}-01-15`) - .selectTab('Org Units') - .selectOu('Bo') + .typeEndDate(`${CURRENT_YEAR - 1}-01-03`) .addToMap() Layer.validateDialogClosed(true) - Layer.validateCardTitle('Malaria case registration') + Layer.validateCardTitle('Inpatient morbidity and mortality') cy.getByDataTest('moremenubutton').first().click() @@ -166,7 +164,7 @@ describe('data table', () => { // check number of columns cy.getByDataTest('bottom-panel') .findByDataTest('dhis2-uicore-datatablecellhead') - .should('have.length', 9) + .should('have.length', 10) cy.getByDataTest('bottom-panel') .findByDataTest('dhis2-uicore-datatablecellhead') @@ -174,12 +172,12 @@ describe('data table', () => { .should('be.visible') // filter by Org unit - const ouName = 'Benduma' + const ouName = 'Moyowa' cy.getByDataTest('data-table-column-filter-input-Org unit') .find('input') .type(ouName) - // check that all the rows have Org unit Yakaji + // check that all the rows have Org unit Moyowa cy.getByDataTest('bottom-panel') .findByDataTest('dhis2-uicore-tablebody') @@ -200,26 +198,26 @@ describe('data table', () => { cy.getByDataTest('bottom-panel') .findByDataTest('dhis2-uicore-tablebody') .findByDataTest('dhis2-uicore-datatablerow') - .should('have.length', 5) + .should('have.length', 3) - // filter by Gender - cy.getByDataTest('data-table-column-filter-input-Gender') + // filter by Mode of Discharge + cy.getByDataTest('data-table-column-filter-input-Mode of Discharge') .find('input') - .type('Female') + .type('Absconded') cy.getByDataTest('bottom-panel') .findByDataTest('dhis2-uicore-tablebody') .findByDataTest('dhis2-uicore-datatablerow') - .should('have.length', 4) + .should('have.length', 1) - cy.getByDataTest('data-table-column-filter-input-Gender') + cy.getByDataTest('data-table-column-filter-input-Mode of Discharge') .find('input') .clear() cy.getByDataTest('bottom-panel') .findByDataTest('dhis2-uicore-tablebody') .findByDataTest('dhis2-uicore-datatablerow') - .should('have.length', 5) + .should('have.length', 3) // filter by Age in years (numeric) cy.getByDataTest('data-table-column-filter-input-Age in years') @@ -230,7 +228,7 @@ describe('data table', () => { cy.getByDataTest('bottom-panel') .findByDataTest('dhis2-uicore-tablebody') .findByDataTest('dhis2-uicore-datatablerow') - .should('have.length', 3) + .should('have.length', 2) // Sort by Age in years cy.get('button[title="Sort by Age in years"]').click() @@ -242,7 +240,7 @@ describe('data table', () => { .first() .find('td') .eq(7) - .should('contain', '44') + .should('contain', '32') cy.getByDataTest('bottom-panel') .findByDataTest('dhis2-uicore-tablebody') diff --git a/cypress/integration/layers/eventlayer.cy.js b/cypress/integration/layers/eventlayer.cy.js index c407fd618..0a3df6beb 100644 --- a/cypress/integration/layers/eventlayer.cy.js +++ b/cypress/integration/layers/eventlayer.cy.js @@ -30,4 +30,26 @@ context('Event Layers', () => { Layer.validateCardTitle('Inpatient morbidity and mortality') Layer.validateCardItems(['Event']) }) + + it('adds an event layer and applies style for boolean data element', () => { + Layer.openDialog('Events') + .selectProgram('E2E program') + .validateStage('Stage 1 - Repeatable') + .selectTab('Style') + + cy.getByDataTest('style-by-data-element-select').click() + + cy.getByDataTest('dhis2-uicore-singleselectoption') + .contains('E2E - Yes/no') + .click() + + cy.getByDataTest('dhis2-uicore-modalactions') + .contains('Add layer') + .click() + + Layer.validateDialogClosed(true) + + Layer.validateCardTitle('Stage 1 - Repeatable') + Layer.validateCardItems(['Yes', 'No', 'Not set']) + }) }) diff --git a/cypress/integration/layers/facilitylayer.cy.js b/cypress/integration/layers/facilitylayer.cy.js index 3c90ddbe6..62f8709e0 100644 --- a/cypress/integration/layers/facilitylayer.cy.js +++ b/cypress/integration/layers/facilitylayer.cy.js @@ -25,10 +25,30 @@ context('Facility Layers', () => { .addToMap() Layer.validateDialogClosed(true) + Layer.validateCardTitle('Facilities') + Layer.validateCardItems(['Facility']) + }) - // TODO: use visual snapshot testing to check the rendering of the map + it('adds a facilities layer and changes the style', () => { + Layer.openDialog('Facilities') + .selectTab('Organisation Units') + .selectOu('Bo') + .selectOuLevel('Facility') + .selectTab('Style') + + cy.getByDataTest('orgunitgroupsetselect-content').click() + cy.getByDataTest('dhis2-uicore-select-menu-menuwrapper') + .contains('Facility Type') + .click() + + cy.getByDataTest('group-set-style').should('be.visible') + cy.getByDataTest('group-set-style').children().should('have.length', 5) + + cy.getByDataTest('dhis2-uicore-modalactions') + .contains('Add layer') + .click() Layer.validateCardTitle('Facilities') - Layer.validateCardItems(['Facility']) + Layer.validateCardItems(['CHC', 'CHP', 'Clinic', 'Hospital', 'MCHP']) }) }) diff --git a/cypress/integration/layers/orgunitlayer.cy.js b/cypress/integration/layers/orgunitlayer.cy.js index c6d0b2dcb..da53061e3 100644 --- a/cypress/integration/layers/orgunitlayer.cy.js +++ b/cypress/integration/layers/orgunitlayer.cy.js @@ -17,7 +17,7 @@ context('Org Unit Layers', () => { cy.contains('No organisation units are selected').should('be.visible') }) - it('adds a org unit layer', () => { + it('adds an org unit layer', () => { Layer.openDialog('Org units') .selectOu('Sierra Leone') .selectOuLevel('District') @@ -30,4 +30,26 @@ context('Org Unit Layers', () => { Layer.validateCardTitle('Organisation units') Layer.validateCardItems(['District']) }) + + it('adds an org unit layer and changes the style', () => { + Layer.openDialog('Org units') + .selectOu('Sierra Leone') + .selectOuLevel('District') + .selectTab('Style') + + cy.getByDataTest('orgunitgroupsetselect-content').click() + cy.getByDataTest('dhis2-uicore-select-menu-menuwrapper') + .contains('Facility Type') + .click() + + cy.getByDataTest('group-set-style').should('be.visible') + cy.getByDataTest('group-set-style').children().should('have.length', 5) + + cy.getByDataTest('dhis2-uicore-modalactions') + .contains('Add layer') + .click() + + Layer.validateCardTitle('Organisation units') + Layer.validateCardItems(['CHC', 'CHP', 'Clinic', 'Hospital', 'MCHP']) + }) }) diff --git a/cypress/integration/layers/thematiclayer.cy.js b/cypress/integration/layers/thematiclayer.cy.js index 3d9038392..1640db979 100644 --- a/cypress/integration/layers/thematiclayer.cy.js +++ b/cypress/integration/layers/thematiclayer.cy.js @@ -71,15 +71,6 @@ context('Thematic Layers', () => { Layer.validateDialogClosed(true) Layer.validateCardTitle(INDICATOR_NAME) - // TODO: test this in a way that is not dependent on the date - // Layer.validateCardItems([ - // '80.9 - 83.04 (1)', - // '83.04 - 85.18 (0)', - // '85.18 - 87.32 (0)', - // '87.32 - 89.46 (0)', - // '89.46 - 91.6 (1)', - // ]); - getMaps().should('have.length', 1) }) @@ -138,4 +129,22 @@ context('Thematic Layers', () => { { name: VIEW_PROFILE }, ]) }) + + it('adds a thematic layer for data element', () => { + const DE_NAME = 'ANC 1st visit' + Layer.openDialog('Thematic') + .selectItemType('Data element') + .selectDataElementGroup('ANC') + .selectDataElement(DE_NAME) + .addToMap() + + Layer.validateDialogClosed(true) + + Layer.validateCardTitle(DE_NAME) + cy.getByDataTest(`card-ANC1stvisit`) + .findByDataTest('layerlegend-item') + .should('have.length', 5) + + getMaps().should('have.length', 1) + }) }) diff --git a/cypress/integration/routes.cy.js b/cypress/integration/routes.cy.js index 6df2c8212..e168e95c3 100644 --- a/cypress/integration/routes.cy.js +++ b/cypress/integration/routes.cy.js @@ -76,6 +76,15 @@ describe('Routes', () => { const Layer = new ThematicLayer() Layer.validateCardTitle('ANC 1 Coverage') cy.get('canvas.maplibregl-canvas').should('be.visible') + + cy.getByDataTest(`card-ANC1Coverage`) + .findByDataTest('layerlegend-item') + .should('have.length', 7) + + cy.getByDataTest(`card-ANC1Coverage`) + .findByDataTest('layerlegend-item') + .first() + .contains('Low 0 - 30') }) it('loads with map id (legacy) and interpretationid lowercase', () => { diff --git a/src/AppWrapper.js b/src/AppWrapper.js index 3c74bbff4..b2a581178 100644 --- a/src/AppWrapper.js +++ b/src/AppWrapper.js @@ -20,24 +20,7 @@ log.setLevel( ) const d2Config = { - schemas: [ - 'dataElement', - 'dataElementGroup', - 'dataSet', - 'externalMapLayer', - 'indicator', - 'indicatorGroup', - 'legendSet', - 'map', - 'optionSet', - 'organisationUnit', - 'organisationUnitGroup', - 'organisationUnitGroupSet', - 'organisationUnitLevel', - 'program', - 'programStage', - 'userGroup', - ], + schemas: [], } const replaceLegacyUrl = () => { diff --git a/src/components/OrgUnitsProvider.js b/src/components/OrgUnitsProvider.js index 22d3646a9..5eb97cf23 100644 --- a/src/components/OrgUnitsProvider.js +++ b/src/components/OrgUnitsProvider.js @@ -7,7 +7,7 @@ const ORG_UNITS_QUERY = { roots: { resource: 'organisationUnits', params: () => ({ - fields: ['id', 'displayName~rename(name)', 'path'], + fields: ['id', 'displayName~rename(name)', 'path'], // TODO organisationUnits has shortName userDataViewFallback: true, }), }, diff --git a/src/components/dataItem/StyleByDataItem.js b/src/components/dataItem/StyleByDataItem.js index 957c104a9..1931ddaaf 100644 --- a/src/components/dataItem/StyleByDataItem.js +++ b/src/components/dataItem/StyleByDataItem.js @@ -59,6 +59,7 @@ const StyleByDataItem = ({ program, programStage, error }) => { value={styleDataItem ? styleDataItem.id : null} items={dataItems} onChange={onChange} + dataTest="style-by-data-element-select" /> {styleDataItem && ( diff --git a/src/components/groupSet/GroupSetSelect.js b/src/components/groupSet/GroupSetSelect.js index 30bde0337..08fe8efd1 100644 --- a/src/components/groupSet/GroupSetSelect.js +++ b/src/components/groupSet/GroupSetSelect.js @@ -53,7 +53,7 @@ const GroupSetSelect = ({ error?.message || (!value && errorText ? errorText : null) } className={className} - data-test="orgunitgroupsetselect" + dataTest="orgunitgroupsetselect" /> ) } diff --git a/src/components/groupSet/GroupSetStyle.js b/src/components/groupSet/GroupSetStyle.js index bcb923f56..9e03307a4 100644 --- a/src/components/groupSet/GroupSetStyle.js +++ b/src/components/groupSet/GroupSetStyle.js @@ -4,23 +4,16 @@ import { Help } from '@dhis2/ui' import PropTypes from 'prop-types' import React, { useState, useEffect } from 'react' import { STYLE_TYPE_COLOR } from '../../constants/layers.js' -import { parseGroupSet } from '../../util/orgUnits.js' +import { + ORG_UNITS_GROUP_SET_QUERY, + parseGroupSet, +} from '../../util/orgUnits.js' import GroupStyle from './GroupStyle.js' import styles from './styles/GroupSetStyle.module.css' -const GROUP_SETS_QUERY = { - groupSets: { - resource: 'organisationUnitGroupSets', - id: ({ id }) => id, - params: { - fields: ['organisationUnitGroups[id,name,color,symbol]'], - }, - }, -} - const GroupSetStyle = ({ defaultStyleType = STYLE_TYPE_COLOR, groupSet }) => { const [groups, setGroups] = useState([]) - const { error: err, refetch } = useDataQuery(GROUP_SETS_QUERY, { + const { error: err, refetch } = useDataQuery(ORG_UNITS_GROUP_SET_QUERY, { lazy: true, onComplete: ({ groupSets }) => { const groupsWithColors = parseGroupSet({ @@ -45,7 +38,7 @@ const GroupSetStyle = ({ defaultStyleType = STYLE_TYPE_COLOR, groupSet }) => { } return ( -
+
{groups?.map((group) => ( { - const [imagePath, setImagePath] = useState() + const { baseUrl } = useConfig() + const imagePath = `${baseUrl}/images/orgunitgroup/` const useColor = styleType !== 'SYMBOL' - useEffect(() => { - getD2().then((d2) => - setImagePath( - `${d2.system.systemInfo.contextPath}/images/orgunitgroup/` - ) - ) - }, []) - return (
{useColor ? ( diff --git a/src/components/layers/download/DataDownloadDialog.js b/src/components/layers/download/DataDownloadDialog.js index af9c320ab..a28e8355a 100644 --- a/src/components/layers/download/DataDownloadDialog.js +++ b/src/components/layers/download/DataDownloadDialog.js @@ -1,4 +1,5 @@ import { useCachedDataQuery } from '@dhis2/analytics' +import { useDataEngine } from '@dhis2/app-runtime' import { useD2 } from '@dhis2/app-runtime-adapter-d2' import i18n from '@dhis2/d2-i18n' import { @@ -18,6 +19,7 @@ import DataDownloadDialogActions from './DataDownloadDialogActions.js' import styles from './styles/DataDownloadDialog.module.css' const DataDownloadDialog = ({ layer, onCloseDialog }) => { + const engine = useDataEngine() const { nameProperty } = useCachedDataQuery() const formatOptions = getFormatOptions() const { d2 } = useD2() @@ -46,6 +48,7 @@ const DataDownloadDialog = ({ layer, onCloseDialog }) => { const onStartDownload = async () => { setIsDownloading(true) setError(null) + console.log('onStartDownload', { nameProperty, layer }) try { await downloadData({ layer, @@ -54,6 +57,7 @@ const DataDownloadDialog = ({ layer, onCloseDialog }) => { humanReadableKeys: humanReadable, d2, nameProperty, + engine, }) setIsDownloading(false) onClose() diff --git a/src/components/loaders/EarthEngineLoader.js b/src/components/loaders/EarthEngineLoader.js index ee23746ca..13a7799dd 100644 --- a/src/components/loaders/EarthEngineLoader.js +++ b/src/components/loaders/EarthEngineLoader.js @@ -1,3 +1,4 @@ +import { useCachedDataQuery } from '@dhis2/analytics' import PropTypes from 'prop-types' import { useEffect } from 'react' import earthEngineLoader from '../../loaders/earthEngineLoader.js' @@ -5,15 +6,17 @@ import useLoaderAlerts from './useLoaderAlerts.js' const EarthEngineLoader = ({ config, onLoad, loaderAlertAction }) => { const { showAlerts } = useLoaderAlerts(loaderAlertAction) + const { currentUser } = useCachedDataQuery() + const nameProperty = currentUser.keyAnalysisDisplayProperty.toUpperCase() useEffect(() => { - earthEngineLoader(config).then((result) => { + earthEngineLoader({ config, nameProperty }).then((result) => { if (result.alerts?.length && loaderAlertAction) { showAlerts(result.alerts) } onLoad(result) }) - }, [config, onLoad, showAlerts, loaderAlertAction]) + }, [config, onLoad, showAlerts, loaderAlertAction, nameProperty]) return null } diff --git a/src/components/loaders/EventLoader.js b/src/components/loaders/EventLoader.js index d0de3d284..9a82c3b05 100644 --- a/src/components/loaders/EventLoader.js +++ b/src/components/loaders/EventLoader.js @@ -1,3 +1,5 @@ +import { useCachedDataQuery } from '@dhis2/analytics' +import { useDataEngine } from '@dhis2/app-runtime' import PropTypes from 'prop-types' import { useEffect } from 'react' import eventLoader from '../../loaders/eventLoader.js' @@ -5,15 +7,32 @@ import useLoaderAlerts from './useLoaderAlerts.js' const EventLoader = ({ config, dataTableOpen, onLoad, loaderAlertAction }) => { const { showAlerts } = useLoaderAlerts(loaderAlertAction) + const { currentUser } = useCachedDataQuery() + const engine = useDataEngine() + + const nameProperty = currentUser.keyAnalysisDisplayProperty useEffect(() => { - eventLoader(config, dataTableOpen).then((result) => { + eventLoader({ + layerConfig: config, + loadExtended: dataTableOpen, + engine, + nameProperty, + }).then((result) => { if (result.alerts?.length && loaderAlertAction) { showAlerts(result.alerts) } onLoad(result) }) - }, [config, dataTableOpen, onLoad, showAlerts, loaderAlertAction]) + }, [ + config, + onLoad, + dataTableOpen, + engine, + nameProperty, + showAlerts, + loaderAlertAction, + ]) return null } diff --git a/src/components/loaders/ExternalLoader.js b/src/components/loaders/ExternalLoader.js index b1b8364ed..242324db2 100644 --- a/src/components/loaders/ExternalLoader.js +++ b/src/components/loaders/ExternalLoader.js @@ -1,11 +1,14 @@ +import { useDataEngine } from '@dhis2/app-runtime' import PropTypes from 'prop-types' import { useEffect } from 'react' import externalLoader from '../../loaders/externalLoader.js' const ExternalLoader = ({ config, onLoad }) => { + const engine = useDataEngine() + useEffect(() => { - externalLoader(config).then(onLoad) - }, [config, onLoad]) + externalLoader({ config, engine }).then(onLoad) + }, [config, onLoad, engine]) return null } diff --git a/src/components/loaders/FacilityLoader.js b/src/components/loaders/FacilityLoader.js index b475976a0..bdc098ec1 100644 --- a/src/components/loaders/FacilityLoader.js +++ b/src/components/loaders/FacilityLoader.js @@ -1,3 +1,5 @@ +import { useCachedDataQuery } from '@dhis2/analytics' +import { useDataEngine, useConfig } from '@dhis2/app-runtime' import PropTypes from 'prop-types' import { useEffect } from 'react' import facilityLoader from '../../loaders/facilityLoader.js' @@ -5,14 +7,29 @@ import useLoaderAlerts from './useLoaderAlerts.js' const FacilityLoader = ({ config, onLoad, loaderAlertAction }) => { const { showAlerts } = useLoaderAlerts(loaderAlertAction) + const { currentUser } = useCachedDataQuery() + const { baseUrl } = useConfig() + const nameProperty = currentUser.keyAnalysisDisplayProperty.toUpperCase() + const engine = useDataEngine() + useEffect(() => { - facilityLoader(config).then((result) => { - if (result.alerts?.length && loaderAlertAction) { - showAlerts(result.alerts) + facilityLoader({ config, engine, nameProperty, baseUrl }).then( + (result) => { + if (result.alerts?.length && loaderAlertAction) { + showAlerts(result.alerts) + } + onLoad(result) } - onLoad(result) - }) - }, [config, onLoad, showAlerts, loaderAlertAction]) + ) + }, [ + config, + onLoad, + engine, + nameProperty, + baseUrl, + showAlerts, + loaderAlertAction, + ]) return null } diff --git a/src/components/loaders/OrgUnitLoader.js b/src/components/loaders/OrgUnitLoader.js index 8c8ba75d2..aa2904e35 100644 --- a/src/components/loaders/OrgUnitLoader.js +++ b/src/components/loaders/OrgUnitLoader.js @@ -1,3 +1,5 @@ +import { useCachedDataQuery } from '@dhis2/analytics' +import { useDataEngine, useConfig } from '@dhis2/app-runtime' import PropTypes from 'prop-types' import { useEffect } from 'react' import orgUnitLoader from '../../loaders/orgUnitLoader.js' @@ -5,15 +7,29 @@ import useLoaderAlerts from './useLoaderAlerts.js' const OrgUnitLoader = ({ config, onLoad, loaderAlertAction }) => { const { showAlerts } = useLoaderAlerts(loaderAlertAction) + const { currentUser } = useCachedDataQuery() + const { baseUrl } = useConfig() + const nameProperty = currentUser.keyAnalysisDisplayProperty.toUpperCase() + const engine = useDataEngine() useEffect(() => { - orgUnitLoader(config).then((result) => { - if (result.alerts?.length && loaderAlertAction) { - showAlerts(result.alerts) + orgUnitLoader({ config, engine, nameProperty, baseUrl }).then( + (result) => { + if (result.alerts?.length && loaderAlertAction) { + showAlerts(result.alerts) + } + onLoad(result) } - onLoad(result) - }) - }, [config, onLoad, showAlerts, loaderAlertAction]) + ) + }, [ + config, + onLoad, + engine, + nameProperty, + baseUrl, + showAlerts, + loaderAlertAction, + ]) return null } diff --git a/src/components/loaders/ThematicLoader.js b/src/components/loaders/ThematicLoader.js index 9558faaa6..6ef08a6ab 100644 --- a/src/components/loaders/ThematicLoader.js +++ b/src/components/loaders/ThematicLoader.js @@ -1,3 +1,5 @@ +import { useCachedDataQuery } from '@dhis2/analytics' +import { useDataEngine } from '@dhis2/app-runtime' import PropTypes from 'prop-types' import { useEffect } from 'react' import thematicLoader from '../../loaders/thematicLoader.js' @@ -5,15 +7,18 @@ import useLoaderAlerts from './useLoaderAlerts.js' const ThematicLoader = ({ config, onLoad, loaderAlertAction }) => { const { showAlerts } = useLoaderAlerts(loaderAlertAction) + const { currentUser } = useCachedDataQuery() + const engine = useDataEngine() + const nameProperty = currentUser.keyAnalysisDisplayProperty.toUpperCase() useEffect(() => { - thematicLoader(config).then((result) => { + thematicLoader({ config, engine, nameProperty }).then((result) => { if (result.alerts?.length && loaderAlertAction) { showAlerts(result.alerts) } onLoad(result) }) - }, [config, onLoad, showAlerts, loaderAlertAction]) + }, [config, engine, onLoad, nameProperty, showAlerts, loaderAlertAction]) return null } diff --git a/src/components/map/Map.js b/src/components/map/Map.js index 4af6e4f5e..c999fd46e 100644 --- a/src/components/map/Map.js +++ b/src/components/map/Map.js @@ -36,12 +36,14 @@ class Map extends Component { closeCoordinatePopup: PropTypes.func, controls: PropTypes.array, coordinatePopup: PropTypes.array, + engine: PropTypes.object, feature: PropTypes.object, isFullscreen: PropTypes.bool, isPlugin: PropTypes.bool, latitude: PropTypes.number, layers: PropTypes.array, longitude: PropTypes.number, + nameProperty: PropTypes.string, resizeCount: PropTypes.number, setAggregations: PropTypes.func, setFeatureProfile: PropTypes.func, @@ -142,6 +144,8 @@ class Map extends Component { render() { const { basemap, + engine, + nameProperty, layers, feature, coordinatePopup: coordinates, @@ -173,6 +177,8 @@ class Map extends Component { openContextMenu={openContextMenu} setAggregations={setAggregations} setFeatureProfile={setFeatureProfile} + engine={engine} + nameProperty={nameProperty} {...config} /> ) diff --git a/src/components/map/MapView.js b/src/components/map/MapView.js index 77f993eb6..0d6c5bab4 100644 --- a/src/components/map/MapView.js +++ b/src/components/map/MapView.js @@ -1,4 +1,5 @@ -import { useConfig } from '@dhis2/app-runtime' +import { useCachedDataQuery } from '@dhis2/analytics' +import { useDataEngine, useConfig } from '@dhis2/app-runtime' import { ComponentCover, CenteredContent, CircularLoader } from '@dhis2/ui' import PropTypes from 'prop-types' import React, { useMemo } from 'react' @@ -26,6 +27,9 @@ const MapView = (props) => { } = props const { baseUrl } = useConfig() + const engine = useDataEngine() + const { currentUser } = useCachedDataQuery() + const nameProperty = currentUser.keyAnalysisDisplayProperty const splitViewLayer = getSplitViewLayer(layers) const isSplitView = !!splitViewLayer @@ -71,6 +75,8 @@ const MapView = (props) => { resizeCount={resizeCount} setMapObject={setMapObject} baseUrl={baseUrl} + engine={engine} + nameProperty={nameProperty} {...layerDispatchActions} /> )} diff --git a/src/components/map/layers/EventLayer.js b/src/components/map/layers/EventLayer.js index 64bb4a8ab..7f518fd93 100644 --- a/src/components/map/layers/EventLayer.js +++ b/src/components/map/layers/EventLayer.js @@ -2,10 +2,13 @@ import { getInstance as getD2 } from 'd2' import React from 'react' import { EVENT_COLOR, EVENT_RADIUS } from '../../../constants/layers.js' import { getContrastColor } from '../../../util/colors.js' -import { getAnalyticsRequest } from '../../../util/event.js' +import { + getAnalyticsRequest, + PROGRAM_STAGE_QUERY, +} from '../../../util/event.js' import { filterData } from '../../../util/filter.js' -import { getDisplayPropertyUrl } from '../../../util/helpers.js' import { formatCount } from '../../../util/numbers.js' +import { OPTION_SET_QUERY } from '../../../util/requests.js' import EventPopup from './EventPopup.js' import Layer from './Layer.js' @@ -26,9 +29,11 @@ class EventLayer extends Layer { isVisible, bounds, data, + engine, eventClustering, eventPointColor, eventPointRadius, + nameProperty, program, programStage, serverCluster, @@ -87,9 +92,8 @@ class EventLayer extends Layer { eventRequest || (await getAnalyticsRequest(this.props, { d2, - nameProperty: - d2.currentUser.settings - .keyAnalysisDisplayProperty, + nameProperty, + engine, })) eventRequest = eventRequest @@ -124,7 +128,7 @@ class EventLayer extends Layer { } if (program && programStage) { - this.loadDisplayElements() + this.loadDisplayElements(engine, nameProperty) } // Create and add event layer based on config object @@ -196,16 +200,16 @@ class EventLayer extends Layer { } // Loads the data elements for a program stage to display in popup - async loadDisplayElements() { + async loadDisplayElements(engine, nameProperty) { const { programStage, eventCoordinateField } = this.props - const d2 = await getD2() - const data = await d2.models.programStage.get(programStage.id, { - fields: `programStageDataElements[displayInReports,dataElement[id,${getDisplayPropertyUrl( - d2 - )},optionSet,valueType]]`, - paging: false, + const displayNameProp = + nameProperty === 'name' ? 'displayName' : 'displayShortName' + + const { programStage: data } = await engine.query(PROGRAM_STAGE_QUERY, { + variables: { id: programStage.id, nameProperty: displayNameProp }, }) + const { programStageDataElements } = data let displayElements = [] let eventCoordinateFieldName @@ -216,7 +220,7 @@ class EventLayer extends Layer { .map((d) => d.dataElement) for (const d of displayElements) { - await this.loadOptionSet(d) + await this.loadOptionSet(d, engine) } if (eventCoordinateField) { @@ -234,20 +238,20 @@ class EventLayer extends Layer { } // Loads an option set for an data element to get option names - async loadOptionSet(dataElement) { + async loadOptionSet(dataElement, engine) { const { optionSet } = dataElement if (!optionSet || !optionSet.id) { return dataElement } - const d2 = await getD2() - if (optionSet && optionSet.id) { - const fullOptionSet = await d2.models.optionSets.get(optionSet.id, { - fields: 'id,displayName~rename(name),options[code,displayName~rename(name)]', - paging: false, - }) + const { optionSet: fullOptionSet } = await engine.query( + OPTION_SET_QUERY, + { + variables: { id: optionSet.id }, + } + ) if (fullOptionSet && fullOptionSet.options) { dataElement.options = fullOptionSet.options.reduce( diff --git a/src/components/openAs/OpenAsMapDialog.js b/src/components/openAs/OpenAsMapDialog.js index e293e96fa..0e5f1304f 100644 --- a/src/components/openAs/OpenAsMapDialog.js +++ b/src/components/openAs/OpenAsMapDialog.js @@ -1,3 +1,4 @@ +import { useDataEngine } from '@dhis2/app-runtime' import { useSetting } from '@dhis2/app-service-datastore' import i18n from '@dhis2/d2-i18n' import { @@ -24,6 +25,7 @@ import styles from './styles/OpenAsMapDialog.module.css' const OpenAsMapDialog = () => { const dispatch = useDispatch() const [currentAO] = useSetting(CURRENT_AO_KEY) + const engine = useDataEngine() const allDataDimensions = getDataDimensionsFromAnalyticalObject(currentAO) const firstDimensionId = allDataDimensions[0]?.id @@ -35,11 +37,12 @@ const OpenAsMapDialog = () => { // Call in sequence for (const dataId of selectedDimensions) { - const layer = await getThematicLayerFromAnalyticalObject( - currentAO, + const layer = await getThematicLayerFromAnalyticalObject({ + ao: currentAO, dataId, - dataId === lastDataId - ) + isVisible: dataId === lastDataId, + engine, + }) if (layer) { dispatch(addLayer(layer)) diff --git a/src/components/plugin/MapContainer.js b/src/components/plugin/MapContainer.js index 677370b30..bc1c87948 100644 --- a/src/components/plugin/MapContainer.js +++ b/src/components/plugin/MapContainer.js @@ -33,7 +33,8 @@ const MapContainer = ({ visualization }) => { } else if (!mapViews) { initialConfig = await getConfigFromNonMapConfig( otherMapProps, - keyDefaultBaseMap + keyDefaultBaseMap, + engine ) } else { initialConfig = getMigratedMapConfig( diff --git a/src/components/plugin/Plugin.js b/src/components/plugin/Plugin.js index f760eeac2..453368740 100644 --- a/src/components/plugin/Plugin.js +++ b/src/components/plugin/Plugin.js @@ -11,19 +11,7 @@ import LoadingMask from './LoadingMask.js' import MapContainer from './MapContainer.js' const d2Config = { - schemas: [ - 'dataElement', - 'dataSet', - 'externalMapLayer', - 'indicator', - 'legendSet', - 'map', - 'optionSet', - 'organisationUnitGroup', - 'organisationUnitGroupSet', - 'organisationUnitLevel', - 'programStage', - ], + schemas: [], } const query = { @@ -33,9 +21,15 @@ const query = { key: SYSTEM_SETTINGS, }, }, + currentUser: { + resource: 'me', + params: { + fields: 'id,username,displayName~rename(name),authorities,settings[keyAnalysisDisplayProperty]', + }, + }, } -const providerDataTransformation = ({ systemSettings }) => { +const providerDataTransformation = ({ systemSettings, currentUser }) => { return { systemSettings: Object.assign( {}, @@ -45,6 +39,18 @@ const providerDataTransformation = ({ systemSettings }) => { hiddenPeriods: getHiddenPeriods(systemSettings), } ), + currentUser: { + id: currentUser.id, + name: currentUser.name, + username: currentUser.username, + authorities: new Set(currentUser.authorities), + keyAnalysisDisplayProperty: + currentUser.settings.keyAnalysisDisplayProperty, + }, + nameProperty: + currentUser.settings.keyAnalysisDisplayProperty === 'name' + ? 'displayName' + : 'displayShortName', } } diff --git a/src/components/plugin/getBasemapConfig.js b/src/components/plugin/getBasemapConfig.js index 12ebe44f1..01b24a316 100644 --- a/src/components/plugin/getBasemapConfig.js +++ b/src/components/plugin/getBasemapConfig.js @@ -4,7 +4,7 @@ import { } from '../../constants/basemaps.js' import { MAP_LAYER_POSITION_BASEMAP } from '../../constants/layers.js' import { createExternalBasemapLayer } from '../../util/external.js' -import { fetchExternalLayersQuery } from '../../util/requests.js' +import { EXTERNAL_MAP_LAYERS_QUERY } from '../../util/requests.js' import { isValidUid } from '../../util/uid.js' async function getBasemaps(basemapId, defaultBasemapId, engine) { @@ -12,7 +12,7 @@ async function getBasemaps(basemapId, defaultBasemapId, engine) { let externalBasemaps = [] if (isValidUid(basemapId) || isValidUid(defaultBasemapId)) { const { externalLayers } = await engine.query({ - externalLayers: fetchExternalLayersQuery, + externalLayers: EXTERNAL_MAP_LAYERS_QUERY, }) externalBasemaps = externalLayers.externalMapLayers .filter( diff --git a/src/constants/colorbrewer.js b/src/constants/colorbrewer.js index 762b3c909..093e9c83f 100644 --- a/src/constants/colorbrewer.js +++ b/src/constants/colorbrewer.js @@ -1,418 +1,1847 @@ // This product includes color specifications and designs developed by Cynthia Brewer (http://colorbrewer.org/). // Please see license at http://colorbrewer.org/export/LICENSE.txt -export default { YlGn: { - 3: ['#f7fcb9', '#addd8e', '#31a354'], - 4: ['#ffffcc', '#c2e699', '#78c679', '#238443'], - 5: ['#ffffcc', '#c2e699', '#78c679', '#31a354', '#006837'], - 6: ['#ffffcc', '#d9f0a3', '#addd8e', '#78c679', '#31a354', '#006837'], - 7: ['#ffffcc', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#005a32'], - 8: ['#ffffe5', '#f7fcb9', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#005a32'], - 9: ['#ffffe5', '#f7fcb9', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#006837', '#004529'], -}, -YlGnBu: { - 3: ['#edf8b1', '#7fcdbb', '#2c7fb8'], - 4: ['#ffffcc', '#a1dab4', '#41b6c4', '#225ea8'], - 5: ['#ffffcc', '#a1dab4', '#41b6c4', '#2c7fb8', '#253494'], - 6: ['#ffffcc', '#c7e9b4', '#7fcdbb', '#41b6c4', '#2c7fb8', '#253494'], - 7: ['#ffffcc', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#0c2c84'], - 8: ['#ffffd9', '#edf8b1', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#0c2c84'], - 9: ['#ffffd9', '#edf8b1', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#253494', '#081d58'], -}, -GnBu: { - 3: ['#e0f3db', '#a8ddb5', '#43a2ca'], - 4: ['#f0f9e8', '#bae4bc', '#7bccc4', '#2b8cbe'], - 5: ['#f0f9e8', '#bae4bc', '#7bccc4', '#43a2ca', '#0868ac'], - 6: ['#f0f9e8', '#ccebc5', '#a8ddb5', '#7bccc4', '#43a2ca', '#0868ac'], - 7: ['#f0f9e8', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#2b8cbe', '#08589e'], - 8: ['#f7fcf0', '#e0f3db', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#2b8cbe', '#08589e'], - 9: ['#f7fcf0', '#e0f3db', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#2b8cbe', '#0868ac', '#084081'], -}, -BuGn: { - 3: ['#e5f5f9', '#99d8c9', '#2ca25f'], - 4: ['#edf8fb', '#b2e2e2', '#66c2a4', '#238b45'], - 5: ['#edf8fb', '#b2e2e2', '#66c2a4', '#2ca25f', '#006d2c'], - 6: ['#edf8fb', '#ccece6', '#99d8c9', '#66c2a4', '#2ca25f', '#006d2c'], - 7: ['#edf8fb', '#ccece6', '#99d8c9', '#66c2a4', '#41ae76', '#238b45', '#005824'], - 8: ['#f7fcfd', '#e5f5f9', '#ccece6', '#99d8c9', '#66c2a4', '#41ae76', '#238b45', '#005824'], - 9: ['#f7fcfd', '#e5f5f9', '#ccece6', '#99d8c9', '#66c2a4', '#41ae76', '#238b45', '#006d2c', '#00441b'], -}, -PuBuGn: { - 3: ['#ece2f0', '#a6bddb', '#1c9099'], - 4: ['#f6eff7', '#bdc9e1', '#67a9cf', '#02818a'], - 5: ['#f6eff7', '#bdc9e1', '#67a9cf', '#1c9099', '#016c59'], - 6: ['#f6eff7', '#d0d1e6', '#a6bddb', '#67a9cf', '#1c9099', '#016c59'], - 7: ['#f6eff7', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016450'], - 8: ['#fff7fb', '#ece2f0', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016450'], - 9: ['#fff7fb', '#ece2f0', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016c59', '#014636'], -}, -PuBu: { - 3: ['#ece7f2', '#a6bddb', '#2b8cbe'], - 4: ['#f1eef6', '#bdc9e1', '#74a9cf', '#0570b0'], - 5: ['#f1eef6', '#bdc9e1', '#74a9cf', '#2b8cbe', '#045a8d'], - 6: ['#f1eef6', '#d0d1e6', '#a6bddb', '#74a9cf', '#2b8cbe', '#045a8d'], - 7: ['#f1eef6', '#d0d1e6', '#a6bddb', '#74a9cf', '#3690c0', '#0570b0', '#034e7b'], - 8: ['#fff7fb', '#ece7f2', '#d0d1e6', '#a6bddb', '#74a9cf', '#3690c0', '#0570b0', '#034e7b'], - 9: ['#fff7fb', '#ece7f2', '#d0d1e6', '#a6bddb', '#74a9cf', '#3690c0', '#0570b0', '#045a8d', '#023858'], -}, -BuPu: { - 3: ['#e0ecf4', '#9ebcda', '#8856a7'], - 4: ['#edf8fb', '#b3cde3', '#8c96c6', '#88419d'], - 5: ['#edf8fb', '#b3cde3', '#8c96c6', '#8856a7', '#810f7c'], - 6: ['#edf8fb', '#bfd3e6', '#9ebcda', '#8c96c6', '#8856a7', '#810f7c'], - 7: ['#edf8fb', '#bfd3e6', '#9ebcda', '#8c96c6', '#8c6bb1', '#88419d', '#6e016b'], - 8: ['#f7fcfd', '#e0ecf4', '#bfd3e6', '#9ebcda', '#8c96c6', '#8c6bb1', '#88419d', '#6e016b'], - 9: ['#f7fcfd', '#e0ecf4', '#bfd3e6', '#9ebcda', '#8c96c6', '#8c6bb1', '#88419d', '#810f7c', '#4d004b'], -}, -RdPu: { - 3: ['#fde0dd', '#fa9fb5', '#c51b8a'], - 4: ['#feebe2', '#fbb4b9', '#f768a1', '#ae017e'], - 5: ['#feebe2', '#fbb4b9', '#f768a1', '#c51b8a', '#7a0177'], - 6: ['#feebe2', '#fcc5c0', '#fa9fb5', '#f768a1', '#c51b8a', '#7a0177'], - 7: ['#feebe2', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177'], - 8: ['#fff7f3', '#fde0dd', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177'], - 9: ['#fff7f3', '#fde0dd', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177', '#49006a'], -}, -PuRd: { - 3: ['#e7e1ef', '#c994c7', '#dd1c77'], - 4: ['#f1eef6', '#d7b5d8', '#df65b0', '#ce1256'], - 5: ['#f1eef6', '#d7b5d8', '#df65b0', '#dd1c77', '#980043'], - 6: ['#f1eef6', '#d4b9da', '#c994c7', '#df65b0', '#dd1c77', '#980043'], - 7: ['#f1eef6', '#d4b9da', '#c994c7', '#df65b0', '#e7298a', '#ce1256', '#91003f'], - 8: ['#f7f4f9', '#e7e1ef', '#d4b9da', '#c994c7', '#df65b0', '#e7298a', '#ce1256', '#91003f'], - 9: ['#f7f4f9', '#e7e1ef', '#d4b9da', '#c994c7', '#df65b0', '#e7298a', '#ce1256', '#980043', '#67001f'], -}, -OrRd: { - 3: ['#fee8c8', '#fdbb84', '#e34a33'], - 4: ['#fef0d9', '#fdcc8a', '#fc8d59', '#d7301f'], - 5: ['#fef0d9', '#fdcc8a', '#fc8d59', '#e34a33', '#b30000'], - 6: ['#fef0d9', '#fdd49e', '#fdbb84', '#fc8d59', '#e34a33', '#b30000'], - 7: ['#fef0d9', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#990000'], - 8: ['#fff7ec', '#fee8c8', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#990000'], - 9: ['#fff7ec', '#fee8c8', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#b30000', '#7f0000'], -}, -YlOrRd: { - 3: ['#ffeda0', '#feb24c', '#f03b20'], - 4: ['#ffffb2', '#fecc5c', '#fd8d3c', '#e31a1c'], - 5: ['#ffffb2', '#fecc5c', '#fd8d3c', '#f03b20', '#bd0026'], - 6: ['#ffffb2', '#fed976', '#feb24c', '#fd8d3c', '#f03b20', '#bd0026'], - 7: ['#ffffb2', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#b10026'], - 8: ['#ffffcc', '#ffeda0', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#b10026'], - 9: ['#ffffcc', '#ffeda0', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#bd0026', '#800026'], -}, -YlOrBr: { - 3: ['#fff7bc', '#fec44f', '#d95f0e'], - 4: ['#ffffd4', '#fed98e', '#fe9929', '#cc4c02'], - 5: ['#ffffd4', '#fed98e', '#fe9929', '#d95f0e', '#993404'], - 6: ['#ffffd4', '#fee391', '#fec44f', '#fe9929', '#d95f0e', '#993404'], - 7: ['#ffffd4', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#8c2d04'], - 8: ['#ffffe5', '#fff7bc', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#8c2d04'], - 9: ['#ffffe5', '#fff7bc', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#993404', '#662506'], -}, -Purples: { - 3: ['#efedf5', '#bcbddc', '#756bb1'], - 4: ['#f2f0f7', '#cbc9e2', '#9e9ac8', '#6a51a3'], - 5: ['#f2f0f7', '#cbc9e2', '#9e9ac8', '#756bb1', '#54278f'], - 6: ['#f2f0f7', '#dadaeb', '#bcbddc', '#9e9ac8', '#756bb1', '#54278f'], - 7: ['#f2f0f7', '#dadaeb', '#bcbddc', '#9e9ac8', '#807dba', '#6a51a3', '#4a1486'], - 8: ['#fcfbfd', '#efedf5', '#dadaeb', '#bcbddc', '#9e9ac8', '#807dba', '#6a51a3', '#4a1486'], - 9: ['#fcfbfd', '#efedf5', '#dadaeb', '#bcbddc', '#9e9ac8', '#807dba', '#6a51a3', '#54278f', '#3f007d'], -}, -Blues: { - 3: ['#deebf7', '#9ecae1', '#3182bd'], - 4: ['#eff3ff', '#bdd7e7', '#6baed6', '#2171b5'], - 5: ['#eff3ff', '#bdd7e7', '#6baed6', '#3182bd', '#08519c'], - 6: ['#eff3ff', '#c6dbef', '#9ecae1', '#6baed6', '#3182bd', '#08519c'], - 7: ['#eff3ff', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#084594'], - 8: ['#f7fbff', '#deebf7', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#084594'], - 9: ['#f7fbff', '#deebf7', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#08519c', '#08306b'], -}, -Greens: { - 3: ['#e5f5e0', '#a1d99b', '#31a354'], - 4: ['#edf8e9', '#bae4b3', '#74c476', '#238b45'], - 5: ['#edf8e9', '#bae4b3', '#74c476', '#31a354', '#006d2c'], - 6: ['#edf8e9', '#c7e9c0', '#a1d99b', '#74c476', '#31a354', '#006d2c'], - 7: ['#edf8e9', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#005a32'], - 8: ['#f7fcf5', '#e5f5e0', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#005a32'], - 9: ['#f7fcf5', '#e5f5e0', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#006d2c', '#00441b'], -}, -Oranges: { - 3: ['#fee6ce', '#fdae6b', '#e6550d'], - 4: ['#feedde', '#fdbe85', '#fd8d3c', '#d94701'], - 5: ['#feedde', '#fdbe85', '#fd8d3c', '#e6550d', '#a63603'], - 6: ['#feedde', '#fdd0a2', '#fdae6b', '#fd8d3c', '#e6550d', '#a63603'], - 7: ['#feedde', '#fdd0a2', '#fdae6b', '#fd8d3c', '#f16913', '#d94801', '#8c2d04'], - 8: ['#fff5eb', '#fee6ce', '#fdd0a2', '#fdae6b', '#fd8d3c', '#f16913', '#d94801', '#8c2d04'], - 9: ['#fff5eb', '#fee6ce', '#fdd0a2', '#fdae6b', '#fd8d3c', '#f16913', '#d94801', '#a63603', '#7f2704'], -}, -Reds: { - 3: ['#fee0d2', '#fc9272', '#de2d26'], - 4: ['#fee5d9', '#fcae91', '#fb6a4a', '#cb181d'], - 5: ['#fee5d9', '#fcae91', '#fb6a4a', '#de2d26', '#a50f15'], - 6: ['#fee5d9', '#fcbba1', '#fc9272', '#fb6a4a', '#de2d26', '#a50f15'], - 7: ['#fee5d9', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#99000d'], - 8: ['#fff5f0', '#fee0d2', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#99000d'], - 9: ['#fff5f0', '#fee0d2', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#a50f15', '#67000d'], -}, -Greys: { - 3: ['#f0f0f0', '#bdbdbd', '#636363'], - 4: ['#f7f7f7', '#cccccc', '#969696', '#525252'], - 5: ['#f7f7f7', '#cccccc', '#969696', '#636363', '#252525'], - 6: ['#f7f7f7', '#d9d9d9', '#bdbdbd', '#969696', '#636363', '#252525'], - 7: ['#f7f7f7', '#d9d9d9', '#bdbdbd', '#969696', '#737373', '#525252', '#252525'], - 8: ['#ffffff', '#f0f0f0', '#d9d9d9', '#bdbdbd', '#969696', '#737373', '#525252', '#252525'], - 9: ['#ffffff', '#f0f0f0', '#d9d9d9', '#bdbdbd', '#969696', '#737373', '#525252', '#252525', '#000000'], -}, -PuOr: { - 3: ['#f1a340', '#f7f7f7', '#998ec3'], - 4: ['#e66101', '#fdb863', '#b2abd2', '#5e3c99'], - 5: ['#e66101', '#fdb863', '#f7f7f7', '#b2abd2', '#5e3c99'], - 6: ['#b35806', '#f1a340', '#fee0b6', '#d8daeb', '#998ec3', '#542788'], - 7: ['#b35806', '#f1a340', '#fee0b6', '#f7f7f7', '#d8daeb', '#998ec3', '#542788'], - 8: ['#b35806', '#e08214', '#fdb863', '#fee0b6', '#d8daeb', '#b2abd2', '#8073ac', '#542788'], - 9: ['#b35806', '#e08214', '#fdb863', '#fee0b6', '#f7f7f7', '#d8daeb', '#b2abd2', '#8073ac', '#542788'], - 10: ['#7f3b08', '#b35806', '#e08214', '#fdb863', '#fee0b6', '#d8daeb', '#b2abd2', '#8073ac', '#542788', '#2d004b'], - 11: ['#7f3b08', '#b35806', '#e08214', '#fdb863', '#fee0b6', '#f7f7f7', '#d8daeb', '#b2abd2', '#8073ac', '#542788', '#2d004b'], -}, -BrBG: { - 3: ['#d8b365', '#f5f5f5', '#5ab4ac'], - 4: ['#a6611a', '#dfc27d', '#80cdc1', '#018571'], - 5: ['#a6611a', '#dfc27d', '#f5f5f5', '#80cdc1', '#018571'], - 6: ['#8c510a', '#d8b365', '#f6e8c3', '#c7eae5', '#5ab4ac', '#01665e'], - 7: ['#8c510a', '#d8b365', '#f6e8c3', '#f5f5f5', '#c7eae5', '#5ab4ac', '#01665e'], - 8: ['#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#c7eae5', '#80cdc1', '#35978f', '#01665e'], - 9: ['#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#f5f5f5', '#c7eae5', '#80cdc1', '#35978f', '#01665e'], - 10: ['#543005', '#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#c7eae5', '#80cdc1', '#35978f', '#01665e', '#003c30'], - 11: ['#543005', '#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#f5f5f5', '#c7eae5', '#80cdc1', '#35978f', '#01665e', '#003c30'], -}, -PRGn: { - 3: ['#af8dc3', '#f7f7f7', '#7fbf7b'], - 4: ['#7b3294', '#c2a5cf', '#a6dba0', '#008837'], - 5: ['#7b3294', '#c2a5cf', '#f7f7f7', '#a6dba0', '#008837'], - 6: ['#762a83', '#af8dc3', '#e7d4e8', '#d9f0d3', '#7fbf7b', '#1b7837'], - 7: ['#762a83', '#af8dc3', '#e7d4e8', '#f7f7f7', '#d9f0d3', '#7fbf7b', '#1b7837'], - 8: ['#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837'], - 9: ['#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#f7f7f7', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837'], - 10: ['#40004b', '#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837', '#00441b'], - 11: ['#40004b', '#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#f7f7f7', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837', '#00441b'], -}, -PiYG: { - 3: ['#e9a3c9', '#f7f7f7', '#a1d76a'], - 4: ['#d01c8b', '#f1b6da', '#b8e186', '#4dac26'], - 5: ['#d01c8b', '#f1b6da', '#f7f7f7', '#b8e186', '#4dac26'], - 6: ['#c51b7d', '#e9a3c9', '#fde0ef', '#e6f5d0', '#a1d76a', '#4d9221'], - 7: ['#c51b7d', '#e9a3c9', '#fde0ef', '#f7f7f7', '#e6f5d0', '#a1d76a', '#4d9221'], - 8: ['#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221'], - 9: ['#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#f7f7f7', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221'], - 10: ['#8e0152', '#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221', '#276419'], - 11: ['#8e0152', '#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#f7f7f7', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221', '#276419'], -}, -RdBu: { - 3: ['#ef8a62', '#f7f7f7', '#67a9cf'], - 4: ['#ca0020', '#f4a582', '#92c5de', '#0571b0'], - 5: ['#ca0020', '#f4a582', '#f7f7f7', '#92c5de', '#0571b0'], - 6: ['#b2182b', '#ef8a62', '#fddbc7', '#d1e5f0', '#67a9cf', '#2166ac'], - 7: ['#b2182b', '#ef8a62', '#fddbc7', '#f7f7f7', '#d1e5f0', '#67a9cf', '#2166ac'], - 8: ['#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac'], - 9: ['#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#f7f7f7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac'], - 10: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac', '#053061'], - 11: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#f7f7f7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac', '#053061'], -}, -RdGy: { - 3: ['#ef8a62', '#ffffff', '#999999'], - 4: ['#ca0020', '#f4a582', '#bababa', '#404040'], - 5: ['#ca0020', '#f4a582', '#ffffff', '#bababa', '#404040'], - 6: ['#b2182b', '#ef8a62', '#fddbc7', '#e0e0e0', '#999999', '#4d4d4d'], - 7: ['#b2182b', '#ef8a62', '#fddbc7', '#ffffff', '#e0e0e0', '#999999', '#4d4d4d'], - 8: ['#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#e0e0e0', '#bababa', '#878787', '#4d4d4d'], - 9: ['#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#ffffff', '#e0e0e0', '#bababa', '#878787', '#4d4d4d'], - 10: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#e0e0e0', '#bababa', '#878787', '#4d4d4d', '#1a1a1a'], - 11: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#ffffff', '#e0e0e0', '#bababa', '#878787', '#4d4d4d', '#1a1a1a'], -}, -RdYlBu: { - 3: ['#fc8d59', '#ffffbf', '#91bfdb'], - 4: ['#d7191c', '#fdae61', '#abd9e9', '#2c7bb6'], - 5: ['#d7191c', '#fdae61', '#ffffbf', '#abd9e9', '#2c7bb6'], - 6: ['#d73027', '#fc8d59', '#fee090', '#e0f3f8', '#91bfdb', '#4575b4'], - 7: ['#d73027', '#fc8d59', '#fee090', '#ffffbf', '#e0f3f8', '#91bfdb', '#4575b4'], - 8: ['#d73027', '#f46d43', '#fdae61', '#fee090', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4'], - 9: ['#d73027', '#f46d43', '#fdae61', '#fee090', '#ffffbf', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4'], - 10: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee090', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695'], - 11: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee090', '#ffffbf', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695'], -}, -Spectral: { - 3: ['#fc8d59', '#ffffbf', '#99d594'], - 4: ['#d7191c', '#fdae61', '#abdda4', '#2b83ba'], - 5: ['#d7191c', '#fdae61', '#ffffbf', '#abdda4', '#2b83ba'], - 6: ['#d53e4f', '#fc8d59', '#fee08b', '#e6f598', '#99d594', '#3288bd'], - 7: ['#d53e4f', '#fc8d59', '#fee08b', '#ffffbf', '#e6f598', '#99d594', '#3288bd'], - 8: ['#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#e6f598', '#abdda4', '#66c2a5', '#3288bd'], - 9: ['#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#e6f598', '#abdda4', '#66c2a5', '#3288bd'], - 10: ['#9e0142', '#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#e6f598', '#abdda4', '#66c2a5', '#3288bd', '#5e4fa2'], - 11: ['#9e0142', '#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#e6f598', '#abdda4', '#66c2a5', '#3288bd', '#5e4fa2'], -}, -RdYlGn: { - 3: ['#fc8d59', '#ffffbf', '#91cf60'], - 4: ['#d7191c', '#fdae61', '#a6d96a', '#1a9641'], - 5: ['#d7191c', '#fdae61', '#ffffbf', '#a6d96a', '#1a9641'], - 6: ['#d73027', '#fc8d59', '#fee08b', '#d9ef8b', '#91cf60', '#1a9850'], - 7: ['#d73027', '#fc8d59', '#fee08b', '#ffffbf', '#d9ef8b', '#91cf60', '#1a9850'], - 8: ['#d73027', '#f46d43', '#fdae61', '#fee08b', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850'], - 9: ['#d73027', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850'], - 10: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee08b', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', '#006837'], - 11: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', '#006837'], -}, -Accent: { - 3: ['#7fc97f', '#beaed4', '#fdc086'], - 4: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99'], - 5: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0'], - 6: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f'], - 7: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f', '#bf5b17'], - 8: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f', '#bf5b17', '#666666'], -}, -Dark2: { - 3: ['#1b9e77', '#d95f02', '#7570b3'], - 4: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a'], - 5: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e'], - 6: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02'], - 7: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02', '#a6761d'], - 8: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02', '#a6761d', '#666666'], -}, -Paired: { - 3: ['#a6cee3', '#1f78b4', '#b2df8a'], - 4: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c'], - 5: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99'], - 6: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c'], - 7: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f'], - 8: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00'], - 9: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6'], - 10: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a'], - 11: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', '#ffff99'], - 12: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', '#ffff99', '#b15928'], -}, -Pastel1: { - 3: ['#fbb4ae', '#b3cde3', '#ccebc5'], - 4: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4'], - 5: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6'], - 6: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc'], - 7: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd'], - 8: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd', '#fddaec'], - 9: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd', '#fddaec', '#f2f2f2'], -}, -Pastel2: { - 3: ['#b3e2cd', '#fdcdac', '#cbd5e8'], - 4: ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4'], - 5: ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9'], - 6: ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae'], - 7: ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae', '#f1e2cc'], - 8: ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae', '#f1e2cc', '#cccccc'], -}, -Set1: { - 3: ['#e41a1c', '#377eb8', '#4daf4a'], - 4: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3'], - 5: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00'], - 6: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33'], - 7: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628'], - 8: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628', '#f781bf'], - 9: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628', '#f781bf', '#999999'], -}, -Set2: { - 3: ['#66c2a5', '#fc8d62', '#8da0cb'], - 4: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3'], - 5: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854'], - 6: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f'], - 7: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', '#e5c494'], - 8: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', '#e5c494', '#b3b3b3'], -}, -Set3: { - 3: ['#8dd3c7', '#ffffb3', '#bebada'], - 4: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072'], - 5: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3'], - 6: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462'], - 7: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69'], - 8: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5'], - 9: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9'], - 10: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd'], - 11: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5'], - 12: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5', '#ffed6f'], -}, -YlOrBr_reverse: { - 3: ['#d95f0e', '#fec44f', '#fff7bc'], - 4: ['#cc4c02', '#fe9929', '#fed98e', '#ffffd4'], - 5: ['#993404', '#d95f0e', '#fe9929', '#fed98e', '#ffffd4'], - 6: ['#993404', '#d95f0e', '#fe9929', '#fec44f', '#fee391', '#ffffd4'], - 7: ['#8c2d04', '#cc4c02', '#ec7014', '#fe9929', '#fec44f', '#fee391', '#ffffd4'], - 8: ['#8c2d04', '#cc4c02', '#ec7014', '#fe9929', '#fec44f', '#fee391', '#fff7bc', '#ffffe5'], - 9: ['#662506', '#993404', '#cc4c02', '#ec7014', '#fe9929', '#fec44f', '#fee391', '#fff7bc', '#ffffe5'], -}, -Reds_reverse: { - 3: ['#de2d26', '#fc9272', '#fee0d2'], - 4: ['#cb181d', '#fb6a4a', '#fcae91', '#fee5d9'], - 5: ['#a50f15', '#de2d26', '#fb6a4a', '#fcae91', '#fee5d9'], - 6: ['#a50f15', '#de2d26', '#fb6a4a', '#fc9272', '#fcbba1', '#fee5d9'], - 7: ['#99000d', '#cb181d', '#ef3b2c', '#fb6a4a', '#fc9272', '#fcbba1', '#fee5d9'], - 8: ['#99000d', '#cb181d', '#ef3b2c', '#fb6a4a', '#fc9272', '#fcbba1', '#fee0d2', '#fff5f0'], - 9: ['#67000d', '#a50f15', '#cb181d', '#ef3b2c', '#fb6a4a', '#fc9272', '#fcbba1', '#fee0d2', '#fff5f0'], -}, -YlGn_reverse: { - 3: ['#31a354', '#addd8e', '#f7fcb9'], - 4: ['#238443', '#78c679', '#c2e699', '#ffffcc'], - 5: ['#006837', '#31a354', '#78c679', '#c2e699', '#ffffcc'], - 6: ['#006837', '#31a354', '#78c679', '#addd8e', '#d9f0a3', '#ffffcc'], - 7: ['#005a32', '#238443', '#41ab5d', '#78c679', '#addd8e', '#d9f0a3', '#ffffcc'], - 8: ['#005a32', '#238443', '#41ab5d', '#78c679', '#addd8e', '#d9f0a3', '#f7fcb9', '#ffffe5'], - 9: ['#004529', '#006837', '#238443', '#41ab5d', '#78c679', '#addd8e', '#d9f0a3', '#f7fcb9', '#ffffe5'], -}, -Greens_reverse: { - 3: ['#31a354', '#a1d99b', '#e5f5e0'], - 4: ['#238b45', '#74c476', '#bae4b3', '#edf8e9'], - 5: ['#006d2c', '#31a354', '#74c476', '#bae4b3', '#edf8e9'], - 6: ['#006d2c', '#31a354', '#74c476', '#a1d99b', '#c7e9c0', '#edf8e9'], - 7: ['#005a32', '#238b45', '#41ab5d', '#74c476', '#a1d99b', '#c7e9c0', '#edf8e9'], - 8: ['#005a32', '#238b45', '#41ab5d', '#74c476', '#a1d99b', '#c7e9c0', '#e5f5e0', '#f7fcf5'], - 9: ['#00441b', '#006d2c', '#238b45', '#41ab5d', '#74c476', '#a1d99b', '#c7e9c0', '#e5f5e0', '#f7fcf5'], -}, -Blues_reverse: { - 3: ['#3182bd', '#9ecae1', '#deebf7'], - 4: ['#2171b5', '#6baed6', '#bdd7e7', '#eff3ff'], - 5: ['#08519c', '#3182bd', '#6baed6', '#bdd7e7', '#eff3ff'], - 6: ['#08519c', '#3182bd', '#6baed6', '#9ecae1', '#c6dbef', '#eff3ff'], - 7: ['#084594', '#2171b5', '#4292c6', '#6baed6', '#9ecae1', '#c6dbef', '#eff3ff'], - 8: ['#084594', '#2171b5', '#4292c6', '#6baed6', '#9ecae1', '#c6dbef', '#deebf7', '#f7fbff'], - 9: ['#08306b', '#08519c', '#2171b5', '#4292c6', '#6baed6', '#9ecae1', '#c6dbef', '#deebf7', '#f7fbff'], -}, -BuPu_reverse: { - 3: ['#8856a7', '#9ebcda', '#e0ecf4'], - 4: ['#88419d', '#8c96c6', '#b3cde3', '#edf8fb'], - 5: ['#810f7c', '#8856a7', '#8c96c6', '#b3cde3', '#edf8fb'], - 6: ['#810f7c', '#8856a7', '#8c96c6', '#9ebcda', '#bfd3e6', '#edf8fb'], - 7: ['#6e016b', '#88419d', '#8c6bb1', '#8c96c6', '#9ebcda', '#bfd3e6', '#edf8fb'], - 8: ['#6e016b', '#88419d', '#8c6bb1', '#8c96c6', '#9ebcda', '#bfd3e6', '#e0ecf4', '#f7fcfd'], - 9: ['#4d004b', '#810f7c', '#88419d', '#8c6bb1', '#8c96c6', '#9ebcda', '#bfd3e6', '#e0ecf4', '#f7fcfd'], -}, -RdPu_reverse: { - 3: ['#c51b8a', '#fa9fb5', '#fde0dd'], - 4: ['#ae017e', '#f768a1', '#fbb4b9', '#feebe2'], - 5: ['#7a0177', '#c51b8a', '#f768a1', '#fbb4b9', '#feebe2'], - 6: ['#7a0177', '#c51b8a', '#f768a1', '#fa9fb5', '#fcc5c0', '#feebe2'], - 7: ['#7a0177', '#ae017e', '#dd3497', '#f768a1', '#fa9fb5', '#fcc5c0', '#feebe2'], - 8: ['#7a0177', '#ae017e', '#dd3497', '#f768a1', '#fa9fb5', '#fcc5c0', '#fde0dd', '#fff7f3'], - 9: ['#49006a', '#7a0177', '#ae017e', '#dd3497', '#f768a1', '#fa9fb5', '#fcc5c0', '#fde0dd', '#fff7f3'], -}, -PuRd_reverse: { - 3: ['#dd1c77', '#c994c7', '#e7e1ef'], - 4: ['#ce1256', '#df65b0', '#d7b5d8', '#f1eef6'], - 5: ['#980043', '#dd1c77', '#df65b0', '#d7b5d8', '#f1eef6'], - 6: ['#980043', '#dd1c77', '#df65b0', '#c994c7', '#d4b9da', '#f1eef6'], - 7: ['#91003f', '#ce1256', '#e7298a', '#df65b0', '#c994c7', '#d4b9da', '#f1eef6'], - 8: ['#91003f', '#ce1256', '#e7298a', '#df65b0', '#c994c7', '#d4b9da', '#e7e1ef', '#f7f4f9'], - 9: ['#67001f', '#980043', '#ce1256', '#e7298a', '#df65b0', '#c994c7', '#d4b9da', '#e7e1ef', '#f7f4f9'], -}, -Greys_reverse: { - 3: ['#636363', '#bdbdbd', '#f0f0f0'], - 4: ['#525252', '#969696', '#cccccc', '#f7f7f7'], - 5: ['#252525', '#636363', '#969696', '#cccccc', '#f7f7f7'], - 6: ['#252525', '#636363', '#969696', '#bdbdbd', '#d9d9d9', '#f7f7f7'], - 7: ['#252525', '#525252', '#737373', '#969696', '#bdbdbd', '#d9d9d9', '#f7f7f7'], - 8: ['#252525', '#525252', '#737373', '#969696', '#bdbdbd', '#d9d9d9', '#f0f0f0', '#ffffff'], - 9: ['#000000', '#252525', '#525252', '#737373', '#969696', '#bdbdbd', '#d9d9d9', '#f0f0f0', '#ffffff'], -} }; \ No newline at end of file +export default { + YlGn: { + 3: ['#f7fcb9', '#addd8e', '#31a354'], + 4: ['#ffffcc', '#c2e699', '#78c679', '#238443'], + 5: ['#ffffcc', '#c2e699', '#78c679', '#31a354', '#006837'], + 6: ['#ffffcc', '#d9f0a3', '#addd8e', '#78c679', '#31a354', '#006837'], + 7: [ + '#ffffcc', + '#d9f0a3', + '#addd8e', + '#78c679', + '#41ab5d', + '#238443', + '#005a32', + ], + 8: [ + '#ffffe5', + '#f7fcb9', + '#d9f0a3', + '#addd8e', + '#78c679', + '#41ab5d', + '#238443', + '#005a32', + ], + 9: [ + '#ffffe5', + '#f7fcb9', + '#d9f0a3', + '#addd8e', + '#78c679', + '#41ab5d', + '#238443', + '#006837', + '#004529', + ], + }, + YlGnBu: { + 3: ['#edf8b1', '#7fcdbb', '#2c7fb8'], + 4: ['#ffffcc', '#a1dab4', '#41b6c4', '#225ea8'], + 5: ['#ffffcc', '#a1dab4', '#41b6c4', '#2c7fb8', '#253494'], + 6: ['#ffffcc', '#c7e9b4', '#7fcdbb', '#41b6c4', '#2c7fb8', '#253494'], + 7: [ + '#ffffcc', + '#c7e9b4', + '#7fcdbb', + '#41b6c4', + '#1d91c0', + '#225ea8', + '#0c2c84', + ], + 8: [ + '#ffffd9', + '#edf8b1', + '#c7e9b4', + '#7fcdbb', + '#41b6c4', + '#1d91c0', + '#225ea8', + '#0c2c84', + ], + 9: [ + '#ffffd9', + '#edf8b1', + '#c7e9b4', + '#7fcdbb', + '#41b6c4', + '#1d91c0', + '#225ea8', + '#253494', + '#081d58', + ], + }, + GnBu: { + 3: ['#e0f3db', '#a8ddb5', '#43a2ca'], + 4: ['#f0f9e8', '#bae4bc', '#7bccc4', '#2b8cbe'], + 5: ['#f0f9e8', '#bae4bc', '#7bccc4', '#43a2ca', '#0868ac'], + 6: ['#f0f9e8', '#ccebc5', '#a8ddb5', '#7bccc4', '#43a2ca', '#0868ac'], + 7: [ + '#f0f9e8', + '#ccebc5', + '#a8ddb5', + '#7bccc4', + '#4eb3d3', + '#2b8cbe', + '#08589e', + ], + 8: [ + '#f7fcf0', + '#e0f3db', + '#ccebc5', + '#a8ddb5', + '#7bccc4', + '#4eb3d3', + '#2b8cbe', + '#08589e', + ], + 9: [ + '#f7fcf0', + '#e0f3db', + '#ccebc5', + '#a8ddb5', + '#7bccc4', + '#4eb3d3', + '#2b8cbe', + '#0868ac', + '#084081', + ], + }, + BuGn: { + 3: ['#e5f5f9', '#99d8c9', '#2ca25f'], + 4: ['#edf8fb', '#b2e2e2', '#66c2a4', '#238b45'], + 5: ['#edf8fb', '#b2e2e2', '#66c2a4', '#2ca25f', '#006d2c'], + 6: ['#edf8fb', '#ccece6', '#99d8c9', '#66c2a4', '#2ca25f', '#006d2c'], + 7: [ + '#edf8fb', + '#ccece6', + '#99d8c9', + '#66c2a4', + '#41ae76', + '#238b45', + '#005824', + ], + 8: [ + '#f7fcfd', + '#e5f5f9', + '#ccece6', + '#99d8c9', + '#66c2a4', + '#41ae76', + '#238b45', + '#005824', + ], + 9: [ + '#f7fcfd', + '#e5f5f9', + '#ccece6', + '#99d8c9', + '#66c2a4', + '#41ae76', + '#238b45', + '#006d2c', + '#00441b', + ], + }, + PuBuGn: { + 3: ['#ece2f0', '#a6bddb', '#1c9099'], + 4: ['#f6eff7', '#bdc9e1', '#67a9cf', '#02818a'], + 5: ['#f6eff7', '#bdc9e1', '#67a9cf', '#1c9099', '#016c59'], + 6: ['#f6eff7', '#d0d1e6', '#a6bddb', '#67a9cf', '#1c9099', '#016c59'], + 7: [ + '#f6eff7', + '#d0d1e6', + '#a6bddb', + '#67a9cf', + '#3690c0', + '#02818a', + '#016450', + ], + 8: [ + '#fff7fb', + '#ece2f0', + '#d0d1e6', + '#a6bddb', + '#67a9cf', + '#3690c0', + '#02818a', + '#016450', + ], + 9: [ + '#fff7fb', + '#ece2f0', + '#d0d1e6', + '#a6bddb', + '#67a9cf', + '#3690c0', + '#02818a', + '#016c59', + '#014636', + ], + }, + PuBu: { + 3: ['#ece7f2', '#a6bddb', '#2b8cbe'], + 4: ['#f1eef6', '#bdc9e1', '#74a9cf', '#0570b0'], + 5: ['#f1eef6', '#bdc9e1', '#74a9cf', '#2b8cbe', '#045a8d'], + 6: ['#f1eef6', '#d0d1e6', '#a6bddb', '#74a9cf', '#2b8cbe', '#045a8d'], + 7: [ + '#f1eef6', + '#d0d1e6', + '#a6bddb', + '#74a9cf', + '#3690c0', + '#0570b0', + '#034e7b', + ], + 8: [ + '#fff7fb', + '#ece7f2', + '#d0d1e6', + '#a6bddb', + '#74a9cf', + '#3690c0', + '#0570b0', + '#034e7b', + ], + 9: [ + '#fff7fb', + '#ece7f2', + '#d0d1e6', + '#a6bddb', + '#74a9cf', + '#3690c0', + '#0570b0', + '#045a8d', + '#023858', + ], + }, + BuPu: { + 3: ['#e0ecf4', '#9ebcda', '#8856a7'], + 4: ['#edf8fb', '#b3cde3', '#8c96c6', '#88419d'], + 5: ['#edf8fb', '#b3cde3', '#8c96c6', '#8856a7', '#810f7c'], + 6: ['#edf8fb', '#bfd3e6', '#9ebcda', '#8c96c6', '#8856a7', '#810f7c'], + 7: [ + '#edf8fb', + '#bfd3e6', + '#9ebcda', + '#8c96c6', + '#8c6bb1', + '#88419d', + '#6e016b', + ], + 8: [ + '#f7fcfd', + '#e0ecf4', + '#bfd3e6', + '#9ebcda', + '#8c96c6', + '#8c6bb1', + '#88419d', + '#6e016b', + ], + 9: [ + '#f7fcfd', + '#e0ecf4', + '#bfd3e6', + '#9ebcda', + '#8c96c6', + '#8c6bb1', + '#88419d', + '#810f7c', + '#4d004b', + ], + }, + RdPu: { + 3: ['#fde0dd', '#fa9fb5', '#c51b8a'], + 4: ['#feebe2', '#fbb4b9', '#f768a1', '#ae017e'], + 5: ['#feebe2', '#fbb4b9', '#f768a1', '#c51b8a', '#7a0177'], + 6: ['#feebe2', '#fcc5c0', '#fa9fb5', '#f768a1', '#c51b8a', '#7a0177'], + 7: [ + '#feebe2', + '#fcc5c0', + '#fa9fb5', + '#f768a1', + '#dd3497', + '#ae017e', + '#7a0177', + ], + 8: [ + '#fff7f3', + '#fde0dd', + '#fcc5c0', + '#fa9fb5', + '#f768a1', + '#dd3497', + '#ae017e', + '#7a0177', + ], + 9: [ + '#fff7f3', + '#fde0dd', + '#fcc5c0', + '#fa9fb5', + '#f768a1', + '#dd3497', + '#ae017e', + '#7a0177', + '#49006a', + ], + }, + PuRd: { + 3: ['#e7e1ef', '#c994c7', '#dd1c77'], + 4: ['#f1eef6', '#d7b5d8', '#df65b0', '#ce1256'], + 5: ['#f1eef6', '#d7b5d8', '#df65b0', '#dd1c77', '#980043'], + 6: ['#f1eef6', '#d4b9da', '#c994c7', '#df65b0', '#dd1c77', '#980043'], + 7: [ + '#f1eef6', + '#d4b9da', + '#c994c7', + '#df65b0', + '#e7298a', + '#ce1256', + '#91003f', + ], + 8: [ + '#f7f4f9', + '#e7e1ef', + '#d4b9da', + '#c994c7', + '#df65b0', + '#e7298a', + '#ce1256', + '#91003f', + ], + 9: [ + '#f7f4f9', + '#e7e1ef', + '#d4b9da', + '#c994c7', + '#df65b0', + '#e7298a', + '#ce1256', + '#980043', + '#67001f', + ], + }, + OrRd: { + 3: ['#fee8c8', '#fdbb84', '#e34a33'], + 4: ['#fef0d9', '#fdcc8a', '#fc8d59', '#d7301f'], + 5: ['#fef0d9', '#fdcc8a', '#fc8d59', '#e34a33', '#b30000'], + 6: ['#fef0d9', '#fdd49e', '#fdbb84', '#fc8d59', '#e34a33', '#b30000'], + 7: [ + '#fef0d9', + '#fdd49e', + '#fdbb84', + '#fc8d59', + '#ef6548', + '#d7301f', + '#990000', + ], + 8: [ + '#fff7ec', + '#fee8c8', + '#fdd49e', + '#fdbb84', + '#fc8d59', + '#ef6548', + '#d7301f', + '#990000', + ], + 9: [ + '#fff7ec', + '#fee8c8', + '#fdd49e', + '#fdbb84', + '#fc8d59', + '#ef6548', + '#d7301f', + '#b30000', + '#7f0000', + ], + }, + YlOrRd: { + 3: ['#ffeda0', '#feb24c', '#f03b20'], + 4: ['#ffffb2', '#fecc5c', '#fd8d3c', '#e31a1c'], + 5: ['#ffffb2', '#fecc5c', '#fd8d3c', '#f03b20', '#bd0026'], + 6: ['#ffffb2', '#fed976', '#feb24c', '#fd8d3c', '#f03b20', '#bd0026'], + 7: [ + '#ffffb2', + '#fed976', + '#feb24c', + '#fd8d3c', + '#fc4e2a', + '#e31a1c', + '#b10026', + ], + 8: [ + '#ffffcc', + '#ffeda0', + '#fed976', + '#feb24c', + '#fd8d3c', + '#fc4e2a', + '#e31a1c', + '#b10026', + ], + 9: [ + '#ffffcc', + '#ffeda0', + '#fed976', + '#feb24c', + '#fd8d3c', + '#fc4e2a', + '#e31a1c', + '#bd0026', + '#800026', + ], + }, + YlOrBr: { + 3: ['#fff7bc', '#fec44f', '#d95f0e'], + 4: ['#ffffd4', '#fed98e', '#fe9929', '#cc4c02'], + 5: ['#ffffd4', '#fed98e', '#fe9929', '#d95f0e', '#993404'], + 6: ['#ffffd4', '#fee391', '#fec44f', '#fe9929', '#d95f0e', '#993404'], + 7: [ + '#ffffd4', + '#fee391', + '#fec44f', + '#fe9929', + '#ec7014', + '#cc4c02', + '#8c2d04', + ], + 8: [ + '#ffffe5', + '#fff7bc', + '#fee391', + '#fec44f', + '#fe9929', + '#ec7014', + '#cc4c02', + '#8c2d04', + ], + 9: [ + '#ffffe5', + '#fff7bc', + '#fee391', + '#fec44f', + '#fe9929', + '#ec7014', + '#cc4c02', + '#993404', + '#662506', + ], + }, + Purples: { + 3: ['#efedf5', '#bcbddc', '#756bb1'], + 4: ['#f2f0f7', '#cbc9e2', '#9e9ac8', '#6a51a3'], + 5: ['#f2f0f7', '#cbc9e2', '#9e9ac8', '#756bb1', '#54278f'], + 6: ['#f2f0f7', '#dadaeb', '#bcbddc', '#9e9ac8', '#756bb1', '#54278f'], + 7: [ + '#f2f0f7', + '#dadaeb', + '#bcbddc', + '#9e9ac8', + '#807dba', + '#6a51a3', + '#4a1486', + ], + 8: [ + '#fcfbfd', + '#efedf5', + '#dadaeb', + '#bcbddc', + '#9e9ac8', + '#807dba', + '#6a51a3', + '#4a1486', + ], + 9: [ + '#fcfbfd', + '#efedf5', + '#dadaeb', + '#bcbddc', + '#9e9ac8', + '#807dba', + '#6a51a3', + '#54278f', + '#3f007d', + ], + }, + Blues: { + 3: ['#deebf7', '#9ecae1', '#3182bd'], + 4: ['#eff3ff', '#bdd7e7', '#6baed6', '#2171b5'], + 5: ['#eff3ff', '#bdd7e7', '#6baed6', '#3182bd', '#08519c'], + 6: ['#eff3ff', '#c6dbef', '#9ecae1', '#6baed6', '#3182bd', '#08519c'], + 7: [ + '#eff3ff', + '#c6dbef', + '#9ecae1', + '#6baed6', + '#4292c6', + '#2171b5', + '#084594', + ], + 8: [ + '#f7fbff', + '#deebf7', + '#c6dbef', + '#9ecae1', + '#6baed6', + '#4292c6', + '#2171b5', + '#084594', + ], + 9: [ + '#f7fbff', + '#deebf7', + '#c6dbef', + '#9ecae1', + '#6baed6', + '#4292c6', + '#2171b5', + '#08519c', + '#08306b', + ], + }, + Greens: { + 3: ['#e5f5e0', '#a1d99b', '#31a354'], + 4: ['#edf8e9', '#bae4b3', '#74c476', '#238b45'], + 5: ['#edf8e9', '#bae4b3', '#74c476', '#31a354', '#006d2c'], + 6: ['#edf8e9', '#c7e9c0', '#a1d99b', '#74c476', '#31a354', '#006d2c'], + 7: [ + '#edf8e9', + '#c7e9c0', + '#a1d99b', + '#74c476', + '#41ab5d', + '#238b45', + '#005a32', + ], + 8: [ + '#f7fcf5', + '#e5f5e0', + '#c7e9c0', + '#a1d99b', + '#74c476', + '#41ab5d', + '#238b45', + '#005a32', + ], + 9: [ + '#f7fcf5', + '#e5f5e0', + '#c7e9c0', + '#a1d99b', + '#74c476', + '#41ab5d', + '#238b45', + '#006d2c', + '#00441b', + ], + }, + Oranges: { + 3: ['#fee6ce', '#fdae6b', '#e6550d'], + 4: ['#feedde', '#fdbe85', '#fd8d3c', '#d94701'], + 5: ['#feedde', '#fdbe85', '#fd8d3c', '#e6550d', '#a63603'], + 6: ['#feedde', '#fdd0a2', '#fdae6b', '#fd8d3c', '#e6550d', '#a63603'], + 7: [ + '#feedde', + '#fdd0a2', + '#fdae6b', + '#fd8d3c', + '#f16913', + '#d94801', + '#8c2d04', + ], + 8: [ + '#fff5eb', + '#fee6ce', + '#fdd0a2', + '#fdae6b', + '#fd8d3c', + '#f16913', + '#d94801', + '#8c2d04', + ], + 9: [ + '#fff5eb', + '#fee6ce', + '#fdd0a2', + '#fdae6b', + '#fd8d3c', + '#f16913', + '#d94801', + '#a63603', + '#7f2704', + ], + }, + Reds: { + 3: ['#fee0d2', '#fc9272', '#de2d26'], + 4: ['#fee5d9', '#fcae91', '#fb6a4a', '#cb181d'], + 5: ['#fee5d9', '#fcae91', '#fb6a4a', '#de2d26', '#a50f15'], + 6: ['#fee5d9', '#fcbba1', '#fc9272', '#fb6a4a', '#de2d26', '#a50f15'], + 7: [ + '#fee5d9', + '#fcbba1', + '#fc9272', + '#fb6a4a', + '#ef3b2c', + '#cb181d', + '#99000d', + ], + 8: [ + '#fff5f0', + '#fee0d2', + '#fcbba1', + '#fc9272', + '#fb6a4a', + '#ef3b2c', + '#cb181d', + '#99000d', + ], + 9: [ + '#fff5f0', + '#fee0d2', + '#fcbba1', + '#fc9272', + '#fb6a4a', + '#ef3b2c', + '#cb181d', + '#a50f15', + '#67000d', + ], + }, + Greys: { + 3: ['#f0f0f0', '#bdbdbd', '#636363'], + 4: ['#f7f7f7', '#cccccc', '#969696', '#525252'], + 5: ['#f7f7f7', '#cccccc', '#969696', '#636363', '#252525'], + 6: ['#f7f7f7', '#d9d9d9', '#bdbdbd', '#969696', '#636363', '#252525'], + 7: [ + '#f7f7f7', + '#d9d9d9', + '#bdbdbd', + '#969696', + '#737373', + '#525252', + '#252525', + ], + 8: [ + '#ffffff', + '#f0f0f0', + '#d9d9d9', + '#bdbdbd', + '#969696', + '#737373', + '#525252', + '#252525', + ], + 9: [ + '#ffffff', + '#f0f0f0', + '#d9d9d9', + '#bdbdbd', + '#969696', + '#737373', + '#525252', + '#252525', + '#000000', + ], + }, + PuOr: { + 3: ['#f1a340', '#f7f7f7', '#998ec3'], + 4: ['#e66101', '#fdb863', '#b2abd2', '#5e3c99'], + 5: ['#e66101', '#fdb863', '#f7f7f7', '#b2abd2', '#5e3c99'], + 6: ['#b35806', '#f1a340', '#fee0b6', '#d8daeb', '#998ec3', '#542788'], + 7: [ + '#b35806', + '#f1a340', + '#fee0b6', + '#f7f7f7', + '#d8daeb', + '#998ec3', + '#542788', + ], + 8: [ + '#b35806', + '#e08214', + '#fdb863', + '#fee0b6', + '#d8daeb', + '#b2abd2', + '#8073ac', + '#542788', + ], + 9: [ + '#b35806', + '#e08214', + '#fdb863', + '#fee0b6', + '#f7f7f7', + '#d8daeb', + '#b2abd2', + '#8073ac', + '#542788', + ], + 10: [ + '#7f3b08', + '#b35806', + '#e08214', + '#fdb863', + '#fee0b6', + '#d8daeb', + '#b2abd2', + '#8073ac', + '#542788', + '#2d004b', + ], + 11: [ + '#7f3b08', + '#b35806', + '#e08214', + '#fdb863', + '#fee0b6', + '#f7f7f7', + '#d8daeb', + '#b2abd2', + '#8073ac', + '#542788', + '#2d004b', + ], + }, + BrBG: { + 3: ['#d8b365', '#f5f5f5', '#5ab4ac'], + 4: ['#a6611a', '#dfc27d', '#80cdc1', '#018571'], + 5: ['#a6611a', '#dfc27d', '#f5f5f5', '#80cdc1', '#018571'], + 6: ['#8c510a', '#d8b365', '#f6e8c3', '#c7eae5', '#5ab4ac', '#01665e'], + 7: [ + '#8c510a', + '#d8b365', + '#f6e8c3', + '#f5f5f5', + '#c7eae5', + '#5ab4ac', + '#01665e', + ], + 8: [ + '#8c510a', + '#bf812d', + '#dfc27d', + '#f6e8c3', + '#c7eae5', + '#80cdc1', + '#35978f', + '#01665e', + ], + 9: [ + '#8c510a', + '#bf812d', + '#dfc27d', + '#f6e8c3', + '#f5f5f5', + '#c7eae5', + '#80cdc1', + '#35978f', + '#01665e', + ], + 10: [ + '#543005', + '#8c510a', + '#bf812d', + '#dfc27d', + '#f6e8c3', + '#c7eae5', + '#80cdc1', + '#35978f', + '#01665e', + '#003c30', + ], + 11: [ + '#543005', + '#8c510a', + '#bf812d', + '#dfc27d', + '#f6e8c3', + '#f5f5f5', + '#c7eae5', + '#80cdc1', + '#35978f', + '#01665e', + '#003c30', + ], + }, + PRGn: { + 3: ['#af8dc3', '#f7f7f7', '#7fbf7b'], + 4: ['#7b3294', '#c2a5cf', '#a6dba0', '#008837'], + 5: ['#7b3294', '#c2a5cf', '#f7f7f7', '#a6dba0', '#008837'], + 6: ['#762a83', '#af8dc3', '#e7d4e8', '#d9f0d3', '#7fbf7b', '#1b7837'], + 7: [ + '#762a83', + '#af8dc3', + '#e7d4e8', + '#f7f7f7', + '#d9f0d3', + '#7fbf7b', + '#1b7837', + ], + 8: [ + '#762a83', + '#9970ab', + '#c2a5cf', + '#e7d4e8', + '#d9f0d3', + '#a6dba0', + '#5aae61', + '#1b7837', + ], + 9: [ + '#762a83', + '#9970ab', + '#c2a5cf', + '#e7d4e8', + '#f7f7f7', + '#d9f0d3', + '#a6dba0', + '#5aae61', + '#1b7837', + ], + 10: [ + '#40004b', + '#762a83', + '#9970ab', + '#c2a5cf', + '#e7d4e8', + '#d9f0d3', + '#a6dba0', + '#5aae61', + '#1b7837', + '#00441b', + ], + 11: [ + '#40004b', + '#762a83', + '#9970ab', + '#c2a5cf', + '#e7d4e8', + '#f7f7f7', + '#d9f0d3', + '#a6dba0', + '#5aae61', + '#1b7837', + '#00441b', + ], + }, + PiYG: { + 3: ['#e9a3c9', '#f7f7f7', '#a1d76a'], + 4: ['#d01c8b', '#f1b6da', '#b8e186', '#4dac26'], + 5: ['#d01c8b', '#f1b6da', '#f7f7f7', '#b8e186', '#4dac26'], + 6: ['#c51b7d', '#e9a3c9', '#fde0ef', '#e6f5d0', '#a1d76a', '#4d9221'], + 7: [ + '#c51b7d', + '#e9a3c9', + '#fde0ef', + '#f7f7f7', + '#e6f5d0', + '#a1d76a', + '#4d9221', + ], + 8: [ + '#c51b7d', + '#de77ae', + '#f1b6da', + '#fde0ef', + '#e6f5d0', + '#b8e186', + '#7fbc41', + '#4d9221', + ], + 9: [ + '#c51b7d', + '#de77ae', + '#f1b6da', + '#fde0ef', + '#f7f7f7', + '#e6f5d0', + '#b8e186', + '#7fbc41', + '#4d9221', + ], + 10: [ + '#8e0152', + '#c51b7d', + '#de77ae', + '#f1b6da', + '#fde0ef', + '#e6f5d0', + '#b8e186', + '#7fbc41', + '#4d9221', + '#276419', + ], + 11: [ + '#8e0152', + '#c51b7d', + '#de77ae', + '#f1b6da', + '#fde0ef', + '#f7f7f7', + '#e6f5d0', + '#b8e186', + '#7fbc41', + '#4d9221', + '#276419', + ], + }, + RdBu: { + 3: ['#ef8a62', '#f7f7f7', '#67a9cf'], + 4: ['#ca0020', '#f4a582', '#92c5de', '#0571b0'], + 5: ['#ca0020', '#f4a582', '#f7f7f7', '#92c5de', '#0571b0'], + 6: ['#b2182b', '#ef8a62', '#fddbc7', '#d1e5f0', '#67a9cf', '#2166ac'], + 7: [ + '#b2182b', + '#ef8a62', + '#fddbc7', + '#f7f7f7', + '#d1e5f0', + '#67a9cf', + '#2166ac', + ], + 8: [ + '#b2182b', + '#d6604d', + '#f4a582', + '#fddbc7', + '#d1e5f0', + '#92c5de', + '#4393c3', + '#2166ac', + ], + 9: [ + '#b2182b', + '#d6604d', + '#f4a582', + '#fddbc7', + '#f7f7f7', + '#d1e5f0', + '#92c5de', + '#4393c3', + '#2166ac', + ], + 10: [ + '#67001f', + '#b2182b', + '#d6604d', + '#f4a582', + '#fddbc7', + '#d1e5f0', + '#92c5de', + '#4393c3', + '#2166ac', + '#053061', + ], + 11: [ + '#67001f', + '#b2182b', + '#d6604d', + '#f4a582', + '#fddbc7', + '#f7f7f7', + '#d1e5f0', + '#92c5de', + '#4393c3', + '#2166ac', + '#053061', + ], + }, + RdGy: { + 3: ['#ef8a62', '#ffffff', '#999999'], + 4: ['#ca0020', '#f4a582', '#bababa', '#404040'], + 5: ['#ca0020', '#f4a582', '#ffffff', '#bababa', '#404040'], + 6: ['#b2182b', '#ef8a62', '#fddbc7', '#e0e0e0', '#999999', '#4d4d4d'], + 7: [ + '#b2182b', + '#ef8a62', + '#fddbc7', + '#ffffff', + '#e0e0e0', + '#999999', + '#4d4d4d', + ], + 8: [ + '#b2182b', + '#d6604d', + '#f4a582', + '#fddbc7', + '#e0e0e0', + '#bababa', + '#878787', + '#4d4d4d', + ], + 9: [ + '#b2182b', + '#d6604d', + '#f4a582', + '#fddbc7', + '#ffffff', + '#e0e0e0', + '#bababa', + '#878787', + '#4d4d4d', + ], + 10: [ + '#67001f', + '#b2182b', + '#d6604d', + '#f4a582', + '#fddbc7', + '#e0e0e0', + '#bababa', + '#878787', + '#4d4d4d', + '#1a1a1a', + ], + 11: [ + '#67001f', + '#b2182b', + '#d6604d', + '#f4a582', + '#fddbc7', + '#ffffff', + '#e0e0e0', + '#bababa', + '#878787', + '#4d4d4d', + '#1a1a1a', + ], + }, + RdYlBu: { + 3: ['#fc8d59', '#ffffbf', '#91bfdb'], + 4: ['#d7191c', '#fdae61', '#abd9e9', '#2c7bb6'], + 5: ['#d7191c', '#fdae61', '#ffffbf', '#abd9e9', '#2c7bb6'], + 6: ['#d73027', '#fc8d59', '#fee090', '#e0f3f8', '#91bfdb', '#4575b4'], + 7: [ + '#d73027', + '#fc8d59', + '#fee090', + '#ffffbf', + '#e0f3f8', + '#91bfdb', + '#4575b4', + ], + 8: [ + '#d73027', + '#f46d43', + '#fdae61', + '#fee090', + '#e0f3f8', + '#abd9e9', + '#74add1', + '#4575b4', + ], + 9: [ + '#d73027', + '#f46d43', + '#fdae61', + '#fee090', + '#ffffbf', + '#e0f3f8', + '#abd9e9', + '#74add1', + '#4575b4', + ], + 10: [ + '#a50026', + '#d73027', + '#f46d43', + '#fdae61', + '#fee090', + '#e0f3f8', + '#abd9e9', + '#74add1', + '#4575b4', + '#313695', + ], + 11: [ + '#a50026', + '#d73027', + '#f46d43', + '#fdae61', + '#fee090', + '#ffffbf', + '#e0f3f8', + '#abd9e9', + '#74add1', + '#4575b4', + '#313695', + ], + }, + Spectral: { + 3: ['#fc8d59', '#ffffbf', '#99d594'], + 4: ['#d7191c', '#fdae61', '#abdda4', '#2b83ba'], + 5: ['#d7191c', '#fdae61', '#ffffbf', '#abdda4', '#2b83ba'], + 6: ['#d53e4f', '#fc8d59', '#fee08b', '#e6f598', '#99d594', '#3288bd'], + 7: [ + '#d53e4f', + '#fc8d59', + '#fee08b', + '#ffffbf', + '#e6f598', + '#99d594', + '#3288bd', + ], + 8: [ + '#d53e4f', + '#f46d43', + '#fdae61', + '#fee08b', + '#e6f598', + '#abdda4', + '#66c2a5', + '#3288bd', + ], + 9: [ + '#d53e4f', + '#f46d43', + '#fdae61', + '#fee08b', + '#ffffbf', + '#e6f598', + '#abdda4', + '#66c2a5', + '#3288bd', + ], + 10: [ + '#9e0142', + '#d53e4f', + '#f46d43', + '#fdae61', + '#fee08b', + '#e6f598', + '#abdda4', + '#66c2a5', + '#3288bd', + '#5e4fa2', + ], + 11: [ + '#9e0142', + '#d53e4f', + '#f46d43', + '#fdae61', + '#fee08b', + '#ffffbf', + '#e6f598', + '#abdda4', + '#66c2a5', + '#3288bd', + '#5e4fa2', + ], + }, + RdYlGn: { + 3: ['#fc8d59', '#ffffbf', '#91cf60'], + 4: ['#d7191c', '#fdae61', '#a6d96a', '#1a9641'], + 5: ['#d7191c', '#fdae61', '#ffffbf', '#a6d96a', '#1a9641'], + 6: ['#d73027', '#fc8d59', '#fee08b', '#d9ef8b', '#91cf60', '#1a9850'], + 7: [ + '#d73027', + '#fc8d59', + '#fee08b', + '#ffffbf', + '#d9ef8b', + '#91cf60', + '#1a9850', + ], + 8: [ + '#d73027', + '#f46d43', + '#fdae61', + '#fee08b', + '#d9ef8b', + '#a6d96a', + '#66bd63', + '#1a9850', + ], + 9: [ + '#d73027', + '#f46d43', + '#fdae61', + '#fee08b', + '#ffffbf', + '#d9ef8b', + '#a6d96a', + '#66bd63', + '#1a9850', + ], + 10: [ + '#a50026', + '#d73027', + '#f46d43', + '#fdae61', + '#fee08b', + '#d9ef8b', + '#a6d96a', + '#66bd63', + '#1a9850', + '#006837', + ], + 11: [ + '#a50026', + '#d73027', + '#f46d43', + '#fdae61', + '#fee08b', + '#ffffbf', + '#d9ef8b', + '#a6d96a', + '#66bd63', + '#1a9850', + '#006837', + ], + }, + Accent: { + 3: ['#7fc97f', '#beaed4', '#fdc086'], + 4: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99'], + 5: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0'], + 6: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f'], + 7: [ + '#7fc97f', + '#beaed4', + '#fdc086', + '#ffff99', + '#386cb0', + '#f0027f', + '#bf5b17', + ], + 8: [ + '#7fc97f', + '#beaed4', + '#fdc086', + '#ffff99', + '#386cb0', + '#f0027f', + '#bf5b17', + '#666666', + ], + }, + Dark2: { + 3: ['#1b9e77', '#d95f02', '#7570b3'], + 4: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a'], + 5: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e'], + 6: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02'], + 7: [ + '#1b9e77', + '#d95f02', + '#7570b3', + '#e7298a', + '#66a61e', + '#e6ab02', + '#a6761d', + ], + 8: [ + '#1b9e77', + '#d95f02', + '#7570b3', + '#e7298a', + '#66a61e', + '#e6ab02', + '#a6761d', + '#666666', + ], + }, + Paired: { + 3: ['#a6cee3', '#1f78b4', '#b2df8a'], + 4: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c'], + 5: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99'], + 6: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c'], + 7: [ + '#a6cee3', + '#1f78b4', + '#b2df8a', + '#33a02c', + '#fb9a99', + '#e31a1c', + '#fdbf6f', + ], + 8: [ + '#a6cee3', + '#1f78b4', + '#b2df8a', + '#33a02c', + '#fb9a99', + '#e31a1c', + '#fdbf6f', + '#ff7f00', + ], + 9: [ + '#a6cee3', + '#1f78b4', + '#b2df8a', + '#33a02c', + '#fb9a99', + '#e31a1c', + '#fdbf6f', + '#ff7f00', + '#cab2d6', + ], + 10: [ + '#a6cee3', + '#1f78b4', + '#b2df8a', + '#33a02c', + '#fb9a99', + '#e31a1c', + '#fdbf6f', + '#ff7f00', + '#cab2d6', + '#6a3d9a', + ], + 11: [ + '#a6cee3', + '#1f78b4', + '#b2df8a', + '#33a02c', + '#fb9a99', + '#e31a1c', + '#fdbf6f', + '#ff7f00', + '#cab2d6', + '#6a3d9a', + '#ffff99', + ], + 12: [ + '#a6cee3', + '#1f78b4', + '#b2df8a', + '#33a02c', + '#fb9a99', + '#e31a1c', + '#fdbf6f', + '#ff7f00', + '#cab2d6', + '#6a3d9a', + '#ffff99', + '#b15928', + ], + }, + Pastel1: { + 3: ['#fbb4ae', '#b3cde3', '#ccebc5'], + 4: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4'], + 5: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6'], + 6: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc'], + 7: [ + '#fbb4ae', + '#b3cde3', + '#ccebc5', + '#decbe4', + '#fed9a6', + '#ffffcc', + '#e5d8bd', + ], + 8: [ + '#fbb4ae', + '#b3cde3', + '#ccebc5', + '#decbe4', + '#fed9a6', + '#ffffcc', + '#e5d8bd', + '#fddaec', + ], + 9: [ + '#fbb4ae', + '#b3cde3', + '#ccebc5', + '#decbe4', + '#fed9a6', + '#ffffcc', + '#e5d8bd', + '#fddaec', + '#f2f2f2', + ], + }, + Pastel2: { + 3: ['#b3e2cd', '#fdcdac', '#cbd5e8'], + 4: ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4'], + 5: ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9'], + 6: ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae'], + 7: [ + '#b3e2cd', + '#fdcdac', + '#cbd5e8', + '#f4cae4', + '#e6f5c9', + '#fff2ae', + '#f1e2cc', + ], + 8: [ + '#b3e2cd', + '#fdcdac', + '#cbd5e8', + '#f4cae4', + '#e6f5c9', + '#fff2ae', + '#f1e2cc', + '#cccccc', + ], + }, + Set1: { + 3: ['#e41a1c', '#377eb8', '#4daf4a'], + 4: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3'], + 5: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00'], + 6: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33'], + 7: [ + '#e41a1c', + '#377eb8', + '#4daf4a', + '#984ea3', + '#ff7f00', + '#ffff33', + '#a65628', + ], + 8: [ + '#e41a1c', + '#377eb8', + '#4daf4a', + '#984ea3', + '#ff7f00', + '#ffff33', + '#a65628', + '#f781bf', + ], + 9: [ + '#e41a1c', + '#377eb8', + '#4daf4a', + '#984ea3', + '#ff7f00', + '#ffff33', + '#a65628', + '#f781bf', + '#999999', + ], + }, + Set2: { + 3: ['#66c2a5', '#fc8d62', '#8da0cb'], + 4: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3'], + 5: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854'], + 6: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f'], + 7: [ + '#66c2a5', + '#fc8d62', + '#8da0cb', + '#e78ac3', + '#a6d854', + '#ffd92f', + '#e5c494', + ], + 8: [ + '#66c2a5', + '#fc8d62', + '#8da0cb', + '#e78ac3', + '#a6d854', + '#ffd92f', + '#e5c494', + '#b3b3b3', + ], + }, + Set3: { + 3: ['#8dd3c7', '#ffffb3', '#bebada'], + 4: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072'], + 5: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3'], + 6: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462'], + 7: [ + '#8dd3c7', + '#ffffb3', + '#bebada', + '#fb8072', + '#80b1d3', + '#fdb462', + '#b3de69', + ], + 8: [ + '#8dd3c7', + '#ffffb3', + '#bebada', + '#fb8072', + '#80b1d3', + '#fdb462', + '#b3de69', + '#fccde5', + ], + 9: [ + '#8dd3c7', + '#ffffb3', + '#bebada', + '#fb8072', + '#80b1d3', + '#fdb462', + '#b3de69', + '#fccde5', + '#d9d9d9', + ], + 10: [ + '#8dd3c7', + '#ffffb3', + '#bebada', + '#fb8072', + '#80b1d3', + '#fdb462', + '#b3de69', + '#fccde5', + '#d9d9d9', + '#bc80bd', + ], + 11: [ + '#8dd3c7', + '#ffffb3', + '#bebada', + '#fb8072', + '#80b1d3', + '#fdb462', + '#b3de69', + '#fccde5', + '#d9d9d9', + '#bc80bd', + '#ccebc5', + ], + 12: [ + '#8dd3c7', + '#ffffb3', + '#bebada', + '#fb8072', + '#80b1d3', + '#fdb462', + '#b3de69', + '#fccde5', + '#d9d9d9', + '#bc80bd', + '#ccebc5', + '#ffed6f', + ], + }, + YlOrBr_reverse: { + 3: ['#d95f0e', '#fec44f', '#fff7bc'], + 4: ['#cc4c02', '#fe9929', '#fed98e', '#ffffd4'], + 5: ['#993404', '#d95f0e', '#fe9929', '#fed98e', '#ffffd4'], + 6: ['#993404', '#d95f0e', '#fe9929', '#fec44f', '#fee391', '#ffffd4'], + 7: [ + '#8c2d04', + '#cc4c02', + '#ec7014', + '#fe9929', + '#fec44f', + '#fee391', + '#ffffd4', + ], + 8: [ + '#8c2d04', + '#cc4c02', + '#ec7014', + '#fe9929', + '#fec44f', + '#fee391', + '#fff7bc', + '#ffffe5', + ], + 9: [ + '#662506', + '#993404', + '#cc4c02', + '#ec7014', + '#fe9929', + '#fec44f', + '#fee391', + '#fff7bc', + '#ffffe5', + ], + }, + Reds_reverse: { + 3: ['#de2d26', '#fc9272', '#fee0d2'], + 4: ['#cb181d', '#fb6a4a', '#fcae91', '#fee5d9'], + 5: ['#a50f15', '#de2d26', '#fb6a4a', '#fcae91', '#fee5d9'], + 6: ['#a50f15', '#de2d26', '#fb6a4a', '#fc9272', '#fcbba1', '#fee5d9'], + 7: [ + '#99000d', + '#cb181d', + '#ef3b2c', + '#fb6a4a', + '#fc9272', + '#fcbba1', + '#fee5d9', + ], + 8: [ + '#99000d', + '#cb181d', + '#ef3b2c', + '#fb6a4a', + '#fc9272', + '#fcbba1', + '#fee0d2', + '#fff5f0', + ], + 9: [ + '#67000d', + '#a50f15', + '#cb181d', + '#ef3b2c', + '#fb6a4a', + '#fc9272', + '#fcbba1', + '#fee0d2', + '#fff5f0', + ], + }, + YlGn_reverse: { + 3: ['#31a354', '#addd8e', '#f7fcb9'], + 4: ['#238443', '#78c679', '#c2e699', '#ffffcc'], + 5: ['#006837', '#31a354', '#78c679', '#c2e699', '#ffffcc'], + 6: ['#006837', '#31a354', '#78c679', '#addd8e', '#d9f0a3', '#ffffcc'], + 7: [ + '#005a32', + '#238443', + '#41ab5d', + '#78c679', + '#addd8e', + '#d9f0a3', + '#ffffcc', + ], + 8: [ + '#005a32', + '#238443', + '#41ab5d', + '#78c679', + '#addd8e', + '#d9f0a3', + '#f7fcb9', + '#ffffe5', + ], + 9: [ + '#004529', + '#006837', + '#238443', + '#41ab5d', + '#78c679', + '#addd8e', + '#d9f0a3', + '#f7fcb9', + '#ffffe5', + ], + }, + Greens_reverse: { + 3: ['#31a354', '#a1d99b', '#e5f5e0'], + 4: ['#238b45', '#74c476', '#bae4b3', '#edf8e9'], + 5: ['#006d2c', '#31a354', '#74c476', '#bae4b3', '#edf8e9'], + 6: ['#006d2c', '#31a354', '#74c476', '#a1d99b', '#c7e9c0', '#edf8e9'], + 7: [ + '#005a32', + '#238b45', + '#41ab5d', + '#74c476', + '#a1d99b', + '#c7e9c0', + '#edf8e9', + ], + 8: [ + '#005a32', + '#238b45', + '#41ab5d', + '#74c476', + '#a1d99b', + '#c7e9c0', + '#e5f5e0', + '#f7fcf5', + ], + 9: [ + '#00441b', + '#006d2c', + '#238b45', + '#41ab5d', + '#74c476', + '#a1d99b', + '#c7e9c0', + '#e5f5e0', + '#f7fcf5', + ], + }, + Blues_reverse: { + 3: ['#3182bd', '#9ecae1', '#deebf7'], + 4: ['#2171b5', '#6baed6', '#bdd7e7', '#eff3ff'], + 5: ['#08519c', '#3182bd', '#6baed6', '#bdd7e7', '#eff3ff'], + 6: ['#08519c', '#3182bd', '#6baed6', '#9ecae1', '#c6dbef', '#eff3ff'], + 7: [ + '#084594', + '#2171b5', + '#4292c6', + '#6baed6', + '#9ecae1', + '#c6dbef', + '#eff3ff', + ], + 8: [ + '#084594', + '#2171b5', + '#4292c6', + '#6baed6', + '#9ecae1', + '#c6dbef', + '#deebf7', + '#f7fbff', + ], + 9: [ + '#08306b', + '#08519c', + '#2171b5', + '#4292c6', + '#6baed6', + '#9ecae1', + '#c6dbef', + '#deebf7', + '#f7fbff', + ], + }, + BuPu_reverse: { + 3: ['#8856a7', '#9ebcda', '#e0ecf4'], + 4: ['#88419d', '#8c96c6', '#b3cde3', '#edf8fb'], + 5: ['#810f7c', '#8856a7', '#8c96c6', '#b3cde3', '#edf8fb'], + 6: ['#810f7c', '#8856a7', '#8c96c6', '#9ebcda', '#bfd3e6', '#edf8fb'], + 7: [ + '#6e016b', + '#88419d', + '#8c6bb1', + '#8c96c6', + '#9ebcda', + '#bfd3e6', + '#edf8fb', + ], + 8: [ + '#6e016b', + '#88419d', + '#8c6bb1', + '#8c96c6', + '#9ebcda', + '#bfd3e6', + '#e0ecf4', + '#f7fcfd', + ], + 9: [ + '#4d004b', + '#810f7c', + '#88419d', + '#8c6bb1', + '#8c96c6', + '#9ebcda', + '#bfd3e6', + '#e0ecf4', + '#f7fcfd', + ], + }, + RdPu_reverse: { + 3: ['#c51b8a', '#fa9fb5', '#fde0dd'], + 4: ['#ae017e', '#f768a1', '#fbb4b9', '#feebe2'], + 5: ['#7a0177', '#c51b8a', '#f768a1', '#fbb4b9', '#feebe2'], + 6: ['#7a0177', '#c51b8a', '#f768a1', '#fa9fb5', '#fcc5c0', '#feebe2'], + 7: [ + '#7a0177', + '#ae017e', + '#dd3497', + '#f768a1', + '#fa9fb5', + '#fcc5c0', + '#feebe2', + ], + 8: [ + '#7a0177', + '#ae017e', + '#dd3497', + '#f768a1', + '#fa9fb5', + '#fcc5c0', + '#fde0dd', + '#fff7f3', + ], + 9: [ + '#49006a', + '#7a0177', + '#ae017e', + '#dd3497', + '#f768a1', + '#fa9fb5', + '#fcc5c0', + '#fde0dd', + '#fff7f3', + ], + }, + PuRd_reverse: { + 3: ['#dd1c77', '#c994c7', '#e7e1ef'], + 4: ['#ce1256', '#df65b0', '#d7b5d8', '#f1eef6'], + 5: ['#980043', '#dd1c77', '#df65b0', '#d7b5d8', '#f1eef6'], + 6: ['#980043', '#dd1c77', '#df65b0', '#c994c7', '#d4b9da', '#f1eef6'], + 7: [ + '#91003f', + '#ce1256', + '#e7298a', + '#df65b0', + '#c994c7', + '#d4b9da', + '#f1eef6', + ], + 8: [ + '#91003f', + '#ce1256', + '#e7298a', + '#df65b0', + '#c994c7', + '#d4b9da', + '#e7e1ef', + '#f7f4f9', + ], + 9: [ + '#67001f', + '#980043', + '#ce1256', + '#e7298a', + '#df65b0', + '#c994c7', + '#d4b9da', + '#e7e1ef', + '#f7f4f9', + ], + }, + Greys_reverse: { + 3: ['#636363', '#bdbdbd', '#f0f0f0'], + 4: ['#525252', '#969696', '#cccccc', '#f7f7f7'], + 5: ['#252525', '#636363', '#969696', '#cccccc', '#f7f7f7'], + 6: ['#252525', '#636363', '#969696', '#bdbdbd', '#d9d9d9', '#f7f7f7'], + 7: [ + '#252525', + '#525252', + '#737373', + '#969696', + '#bdbdbd', + '#d9d9d9', + '#f7f7f7', + ], + 8: [ + '#252525', + '#525252', + '#737373', + '#969696', + '#bdbdbd', + '#d9d9d9', + '#f0f0f0', + '#ffffff', + ], + 9: [ + '#000000', + '#252525', + '#525252', + '#737373', + '#969696', + '#bdbdbd', + '#d9d9d9', + '#f0f0f0', + '#ffffff', + ], + }, +} diff --git a/src/loaders/earthEngineLoader.js b/src/loaders/earthEngineLoader.js index d41410e37..1a2c18213 100644 --- a/src/loaders/earthEngineLoader.js +++ b/src/loaders/earthEngineLoader.js @@ -13,7 +13,6 @@ import { getStaticFilterFromPeriod, getPeriodFromFilter, } from '../util/earthEngine.js' -import { getDisplayProperty } from '../util/helpers.js' import { toGeoJson } from '../util/map.js' import { getRoundToPrecisionFn } from '../util/numbers.js' import { @@ -22,7 +21,7 @@ import { } from '../util/orgUnits.js' // Returns a promise -const earthEngineLoader = async (config) => { +const earthEngineLoader = async ({ config, nameProperty }) => { const { format, rows, aggregationType } = config const orgUnits = getOrgUnitsFromRows(rows) const coordinateField = getCoordinateField(config) @@ -34,14 +33,13 @@ const earthEngineLoader = async (config) => { if (orgUnits && orgUnits.length) { const d2 = await getD2() - const displayProperty = getDisplayProperty(d2).toUpperCase() const orgUnitParams = orgUnits.map((item) => item.id) let mainFeatures let associatedGeometries const featuresRequest = d2.geoFeatures .byOrgUnit(orgUnitParams) - .displayProperty(displayProperty) + .displayProperty(nameProperty) try { mainFeatures = await featuresRequest.getAll().then(toGeoJson) diff --git a/src/loaders/eventLoader.js b/src/loaders/eventLoader.js index 0b8f20e3d..6b34f92c0 100644 --- a/src/loaders/eventLoader.js +++ b/src/loaders/eventLoader.js @@ -18,6 +18,7 @@ import { import { cssColor, getContrastColor } from '../util/colors.js' import { getAnalyticsRequest, loadData } from '../util/event.js' import { getBounds } from '../util/geojson.js' +import { OPTION_SET_QUERY } from '../util/requests.js' import { styleByDataItem } from '../util/styleByDataItem.js' import { formatStartEndDate, getDateArray } from '../util/time.js' import { isValidUid } from '../util/uid.js' @@ -42,10 +43,15 @@ const unknownErrorAlert = { } // Returns a promise -const eventLoader = async (layerConfig, loadExtended) => { +const eventLoader = async ({ + layerConfig, + loadExtended, + engine, + nameProperty, +}) => { const config = { ...layerConfig } try { - await loadEventLayer(config, loadExtended) + await loadEventLayer({ config, loadExtended, engine, nameProperty }) } catch (e) { if (e.httpStatusCode === 403 || e.httpStatusCode === 409) { config.alerts = [ @@ -66,7 +72,12 @@ const eventLoader = async (layerConfig, loadExtended) => { return config } -const loadEventLayer = async (config, loadExtended) => { +const loadEventLayer = async ({ + config, + loadExtended, + engine, + nameProperty, +}) => { const { columns, endDate, @@ -89,7 +100,8 @@ const loadEventLayer = async (config, loadExtended) => { const analyticsRequest = await getAnalyticsRequest(config, { d2, - nameProperty: d2.currentUser.settings.keyAnalysisDisplayProperty, + nameProperty, + engine, }) let alert @@ -132,7 +144,7 @@ const loadEventLayer = async (config, loadExtended) => { if (Array.isArray(config.data) && config.data.length) { if (styleDataItem) { - await styleByDataItem(config) + await styleByDataItem(config, engine) } if (total > EVENT_CLIENT_PAGE_SIZE) { @@ -161,7 +173,11 @@ const loadEventLayer = async (config, loadExtended) => { dataFilters && getFiltersAsText(dataFilters, { ...names, - ...(await getFilterOptionNames(dataFilters, response.headers)), + ...(await getFilterOptionNames( + dataFilters, + response.headers, + engine + )), }) config.headers = response.headers @@ -231,9 +247,7 @@ export const getCount = async (request) => { // If the layer included filters using option sets, this function return an object // mapping option codes to named used to translate codes in the legend -const getFilterOptionNames = async (filters, headers) => { - const d2 = await getD2() - +const getFilterOptionNames = async (filters, headers, engine) => { if (!filters) { return null } @@ -250,30 +264,29 @@ const getFilterOptionNames = async (filters, headers) => { return } - const mappedOptionSets = await Promise.all( + const allOptionSets = await Promise.all( optionSets.map((id) => - d2.models.optionSets - .get(id, { - fields: 'options[code,displayName~rename(name)]', - }) - .then((model) => model.options) - .then((options) => - options.reduce((obj, { code, name }) => { - obj[code] = name - return obj - }, {}) - ) + engine.query(OPTION_SET_QUERY, { + variables: { id }, + }) ) ) // Returns one object with all option codes mapped to names - return mappedOptionSets.reduce( - (obj, set) => ({ - ...obj, - ...set, - }), - {} - ) + return allOptionSets + .map(({ optionSet }) => + optionSet.options.reduce((obj, { code, name }) => { + obj[code] = name + return obj + }, {}) + ) + .reduce( + (obj, set) => ({ + ...obj, + ...set, + }), + {} + ) } export default eventLoader diff --git a/src/loaders/externalLoader.js b/src/loaders/externalLoader.js index d529da207..678fbb83e 100644 --- a/src/loaders/externalLoader.js +++ b/src/loaders/externalLoader.js @@ -1,12 +1,13 @@ import { EXTERNAL_LAYER } from '../constants/layers.js' import { parseLayerConfig } from '../util/external.js' -import { loadLegendSet, getPredefinedLegendItems } from '../util/legend.js' +import { getPredefinedLegendItems } from '../util/legend.js' +import { LEGEND_SET_QUERY } from '../util/requests.js' -const externalLoader = async (layer) => { +const externalLoader = async ({ config: layer, engine }) => { let config if (typeof layer.config === 'string') { // External layer is loaded in analytical object - config = await parseLayerConfig(layer.config) + config = await parseLayerConfig(layer.config, engine) } else { config = { ...layer.config } } @@ -14,7 +15,12 @@ const externalLoader = async (layer) => { const legend = { title: config.name } if (config.legendSet) { - const legendItems = await loadLegendSet(config.legendSet) + const { legendSet: legendItems } = await engine.query( + LEGEND_SET_QUERY, + { + variables: { id: config.legendSet.id }, + } + ) legend.items = getPredefinedLegendItems(legendItems) } diff --git a/src/loaders/facilityLoader.js b/src/loaders/facilityLoader.js index fc56d445f..a950fe6b3 100644 --- a/src/loaders/facilityLoader.js +++ b/src/loaders/facilityLoader.js @@ -6,17 +6,17 @@ import { CUSTOM_ALERT, } from '../constants/alerts.js' import { getOrgUnitsFromRows } from '../util/analytics.js' -import { getDisplayProperty } from '../util/helpers.js' import { toGeoJson } from '../util/map.js' import { - fetchOrgUnitGroupSet, + ORG_UNITS_GROUP_SET_QUERY, getPointItems, getPolygonItems, getStyledOrgUnits, getCoordinateField, + parseGroupSet, } from '../util/orgUnits.js' -const facilityLoader = async (config) => { +const facilityLoader = async ({ config, engine, nameProperty, baseUrl }) => { const { rows, organisationUnitGroupSet: groupSet, areaRadius } = config const orgUnits = getOrgUnitsFromRows(rows) const includeGroupSets = !!groupSet @@ -26,13 +26,11 @@ const facilityLoader = async (config) => { let associatedGeometries const d2 = await getD2() - const displayProperty = getDisplayProperty(d2).toUpperCase() - const { contextPath } = d2.system.systemInfo const name = i18n.t('Facilities') const featuresRequest = d2.geoFeatures .byOrgUnit(orgUnitParams) - .displayProperty(displayProperty) + .displayProperty(nameProperty) const requests = [ featuresRequest @@ -53,20 +51,26 @@ const facilityLoader = async (config) => { // Load organisationUnitGroups if not passed if (includeGroupSets && !groupSet.organisationUnitGroups) { - requests.push(fetchOrgUnitGroupSet(groupSet.id)) + const orgUnitGroupsRequest = engine.query(ORG_UNITS_GROUP_SET_QUERY, { + variables: { id: groupSet.id }, + }) + requests.push(orgUnitGroupsRequest) } - const [features, organisationUnitGroups] = await Promise.all(requests) + const [features, orgUnitGroups] = await Promise.all(requests) - if (organisationUnitGroups) { - groupSet.organisationUnitGroups = organisationUnitGroups + if (orgUnitGroups) { + const { groupSets } = orgUnitGroups + groupSet.organisationUnitGroups = parseGroupSet({ + organisationUnitGroups: groupSets.organisationUnitGroups, + }) } const { styledFeatures, legend } = getStyledOrgUnits( features, groupSet, config, - contextPath + baseUrl ) legend.title = name diff --git a/src/loaders/geoJsonUrlLoader.js b/src/loaders/geoJsonUrlLoader.js index 7c82d7126..b5a921492 100644 --- a/src/loaders/geoJsonUrlLoader.js +++ b/src/loaders/geoJsonUrlLoader.js @@ -53,7 +53,7 @@ const geoJsonUrlLoader = async (layer, engine, instanceBaseUrl) => { // keep featureStyle property outside of config while in app if (typeof config === 'string') { // External layer is loaded in analytical object - newConfig = await parseLayerConfig(config) + newConfig = await parseLayerConfig(config, engine) featureStyle = { ...newConfig.featureStyle } || EMPTY_FEATURE_STYLE delete newConfig.featureStyle } else { diff --git a/src/loaders/orgUnitLoader.js b/src/loaders/orgUnitLoader.js index e389a8c87..4feb0d80c 100644 --- a/src/loaders/orgUnitLoader.js +++ b/src/loaders/orgUnitLoader.js @@ -6,17 +6,27 @@ import { ERROR_CRITICAL, } from '../constants/alerts.js' import { getOrgUnitsFromRows } from '../util/analytics.js' -import { getDisplayProperty } from '../util/helpers.js' import { toGeoJson } from '../util/map.js' import { - fetchOrgUnitGroupSet, + ORG_UNITS_GROUP_SET_QUERY, addAssociatedGeometries, - getOrgUnitLevels, getStyledOrgUnits, getCoordinateField, + parseGroupSet, } from '../util/orgUnits.js' -const orgUnitLoader = async (config) => { +// orgUnitLevels do not have shortName property +const ORG_UNIT_LEVELS_QUERY = { + orgUnitLevels: { + resource: 'organisationUnitLevels', + params: { + fields: 'id,level,displayName~rename(name)', + paging: false, + }, + }, +} + +const orgUnitLoader = async ({ config, engine, nameProperty, baseUrl }) => { const { rows, organisationUnitGroupSet: groupSet } = config const orgUnits = getOrgUnitsFromRows(rows) const orgUnitParams = orgUnits.map((item) => item.id) @@ -24,14 +34,12 @@ const orgUnitLoader = async (config) => { const coordinateField = getCoordinateField(config) const d2 = await getD2() - const displayProperty = getDisplayProperty(d2).toUpperCase() - const { contextPath } = d2.system.systemInfo const name = i18n.t('Organisation units') const alerts = [] const featuresRequest = d2.geoFeatures .byOrgUnit(orgUnitParams) - .displayProperty(displayProperty) + .displayProperty(nameProperty) let associatedGeometries @@ -47,15 +55,20 @@ const orgUnitLoader = async (config) => { }) } }), - getOrgUnitLevels(d2), ] + const levelsRequest = engine.query(ORG_UNIT_LEVELS_QUERY) + requests.push(levelsRequest) + // Load organisationUnitGroups if not passed if (includeGroupSets && !groupSet.organisationUnitGroups) { - requests.push(fetchOrgUnitGroupSet(groupSet.id)) + const orgUnitGroupsRequest = engine.query(ORG_UNITS_GROUP_SET_QUERY, { + variables: { id: groupSet.id }, + }) + requests.push(orgUnitGroupsRequest) } - const [mainFeatures = [], orgUnitLevels, organisationUnitGroups] = + const [mainFeatures = [], { orgUnitLevels }, orgUnitGroups] = await Promise.all(requests) if (!mainFeatures.length && !alerts.length) { @@ -65,8 +78,11 @@ const orgUnitLoader = async (config) => { }) } - if (organisationUnitGroups) { - groupSet.organisationUnitGroups = organisationUnitGroups + if (orgUnitGroups) { + const { groupSets } = orgUnitGroups + groupSet.organisationUnitGroups = parseGroupSet({ + organisationUnitGroups: groupSets.organisationUnitGroups, + }) } if (coordinateField) { @@ -91,8 +107,14 @@ const orgUnitLoader = async (config) => { features, groupSet, config, - contextPath, - orgUnitLevels + baseUrl, + orgUnitLevels.organisationUnitLevels.reduce( + (obj, item) => ({ + ...obj, + [item.level]: item.name, + }), + {} + ) ) legend.title = name diff --git a/src/loaders/thematicLoader.js b/src/loaders/thematicLoader.js index d131abaff..22f70ffdd 100644 --- a/src/loaders/thematicLoader.js +++ b/src/loaders/thematicLoader.js @@ -29,9 +29,7 @@ import { getApiResponseNames, } from '../util/analytics.js' import { getLegendItemForValue } from '../util/classify.js' -import { getDisplayProperty } from '../util/helpers.js' import { - loadLegendSet, getPredefinedLegendItems, getAutomaticLegendItems, } from '../util/legend.js' @@ -40,9 +38,10 @@ import { getCoordinateField, addAssociatedGeometries, } from '../util/orgUnits.js' +import { LEGEND_SET_QUERY } from '../util/requests.js' import { formatStartEndDate, getDateArray } from '../util/time.js' -const thematicLoader = async (config) => { +const thematicLoader = async ({ config, engine, nameProperty }) => { const { columns, radiusLow = THEMATIC_RADIUS_LOW, @@ -59,7 +58,7 @@ const thematicLoader = async (config) => { let error - const response = await loadData(config).catch((err) => { + const response = await loadData(config, nameProperty).catch((err) => { error = err }) @@ -121,7 +120,10 @@ const thematicLoader = async (config) => { const method = legendSet ? CLASSIFICATION_PREDEFINED : config.method if (legendSet) { - legendSet = await loadLegendSet(legendSet) + const result = await engine.query(LEGEND_SET_QUERY, { + variables: { id: config.legendSet.id }, + }) + legendSet = result.legendSet } let legendItems = [] @@ -323,12 +325,11 @@ const getOrderedValues = (data) => { } // Load features and data values from api -const loadData = async (config) => { +const loadData = async (config, nameProperty) => { const { rows, columns, filters, - displayProperty, startDate, endDate, userOrgUnit, @@ -346,10 +347,7 @@ const loadData = async (config) => { const isOperand = columns[0].dimension === dimConf.operand.objectName const isSingleMap = renderingStrategy === RENDERING_STRATEGY_SINGLE const d2 = await getD2() - const displayPropertyUpper = getDisplayProperty( - d2, - displayProperty - ).toUpperCase() + const geoFeaturesParams = {} const orgUnitParams = orgUnits.map((item) => item.id) let dataDimension = isOperand ? dataItem.id.split('.')[0] : dataItem.id @@ -361,7 +359,7 @@ const loadData = async (config) => { let analyticsRequest = new d2.analytics.request() .addOrgUnitDimension(orgUnits.map((ou) => ou.id)) .addDataDimension(dataDimension) - .withDisplayProperty(displayPropertyUpper) + .withDisplayProperty(nameProperty) if (!isSingleMap) { analyticsRequest = analyticsRequest.addPeriodDimension(period.id) @@ -407,7 +405,7 @@ const loadData = async (config) => { const featuresRequest = d2.geoFeatures .byOrgUnit(orgUnitParams) - .displayProperty(displayPropertyUpper) + .displayProperty(nameProperty) // Features request const orgUnitReq = featuresRequest.getAll(geoFeaturesParams).then(toGeoJson) diff --git a/src/reducers/map.js b/src/reducers/map.js index d53b58335..a3ce501b1 100644 --- a/src/reducers/map.js +++ b/src/reducers/map.js @@ -1,6 +1,6 @@ import { arrayMoveImmutable } from 'array-move' -import { generateUid } from 'd2/uid' import * as types from '../constants/actionTypes.js' +import { generateUid } from '../util/uid.js' export const defaultBasemapState = { isVisible: true, diff --git a/src/util/__tests__/analyticalObject.spec.js b/src/util/__tests__/analyticalObject.spec.js index 69b7378a6..8313bc5d5 100644 --- a/src/util/__tests__/analyticalObject.spec.js +++ b/src/util/__tests__/analyticalObject.spec.js @@ -62,24 +62,30 @@ describe('analytical object utils', () => { it('returns undefined if no org unit dimension is passed', async () => { const result = await getThematicLayerFromAnalyticalObject({ - columns, + ao: { + columns, + }, }) expect(result).toBeUndefined() }) it('returns undefined if no period dimension is passed', async () => { const result = await getThematicLayerFromAnalyticalObject({ - columns, - rows, + ao: { + columns, + rows, + }, }) expect(result).toBeUndefined() }) it('returns layer object if data, org unit and period dimensions are passed', async () => { const result = await getThematicLayerFromAnalyticalObject({ - columns, - rows, - filters, + ao: { + columns, + rows, + filters, + }, }) expect(result).toBeInstanceOf(Object) diff --git a/src/util/__tests__/getConfigFromNonMapConfig.spec.js b/src/util/__tests__/getConfigFromNonMapConfig.spec.js index 5cfc27476..0b5a256e1 100644 --- a/src/util/__tests__/getConfigFromNonMapConfig.spec.js +++ b/src/util/__tests__/getConfigFromNonMapConfig.spec.js @@ -1,7 +1,7 @@ -import * as getuid from 'd2/uid' import { getConfigFromNonMapConfig } from '../getConfigFromNonMapConfig.js' // import * as analyticalObject from '../analyticalObject'; import * as legend from '../legend.js' +import * as getuid from '../uid.js' const mockLegendSet = { id: 'fqs276KXCXi', name: 'ANC Coverage' } const chartConfig = { diff --git a/src/util/__tests__/orgUnits.spec.js b/src/util/__tests__/orgUnits.spec.js new file mode 100644 index 000000000..b3d72c0b6 --- /dev/null +++ b/src/util/__tests__/orgUnits.spec.js @@ -0,0 +1,79 @@ +import { getStyledOrgUnits } from '../orgUnits.js' + +describe('getStyledOrgUnits', () => { + it('should return styled features and legend for facility layer', () => { + const features = [ + { + geometry: { type: 'Point' }, + properties: { + hasAdditionalGeometry: false, + dimensions: {}, + iconUrl: 'http://iconurl.com', + }, + }, + ] + const groupSet = { + id: '1', + name: 'GroupSet1', + organisationUnitGroups: [], + } + const styleParams = { organisationUnitColor: 'red', radiusLow: 10 } + const contextPath = '/contextPath' + const result = getStyledOrgUnits( + features, + groupSet, + styleParams, + contextPath + ) + + expect(result.styledFeatures).toHaveLength(1) + expect(result.styledFeatures[0]).toMatchObject({ + geometry: { type: 'Point' }, + properties: { + hasAdditionalGeometry: false, + dimensions: {}, + iconUrl: 'http://iconurl.com', + radius: 10, + }, + }) + expect(result.styledFeatures[0].properties.radius).toEqual(10) + expect(result.legend.unit).toEqual('GroupSet1') + }) + + it('should return styled features and legend for orgUnit layer', () => { + const features = [ + { + geometry: { type: 'Polygon' }, + properties: { level: 1, dimensions: {} }, + }, + ] + const groupSet = { name: 'GroupSet1', organisationUnitGroups: [] } + + const styleParams = { organisationUnitColor: 'red', radiusLow: 10 } + + const orgUnitLevels = { + 1: 'Level1', + 2: 'Level2', + 3: 'Level3', + 4: 'Level4', + } + + const result = getStyledOrgUnits( + features, + groupSet, + styleParams, + '/contextPath', + orgUnitLevels + ) + + expect(result.styledFeatures).toHaveLength(1) + expect(result.styledFeatures[0]).toMatchObject({ + geometry: { type: 'Polygon' }, + properties: { level: 1, dimensions: {}, weight: 1 }, + }) + expect(result.legend).toMatchObject({ + unit: 'GroupSet1', + items: [{ name: 'Level1' }], + }) + }) +}) diff --git a/src/util/analyticalObject.js b/src/util/analyticalObject.js index f04097949..309938741 100644 --- a/src/util/analyticalObject.js +++ b/src/util/analyticalObject.js @@ -27,11 +27,12 @@ export const getDataDimensionsFromAnalyticalObject = (ao) => { } // Returns a thematic layer config from an analytical object -export const getThematicLayerFromAnalyticalObject = async ( +export const getThematicLayerFromAnalyticalObject = async ({ ao = {}, dataId, - isVisible = true -) => { + isVisible = true, + engine, +}) => { const { yearlySeries, aggregationType = 'DEFAULT' } = ao const dataDims = getDataDimensionsFromAnalyticalObject(ao) const dims = getDimensionsFromAnalyticalObject(ao) @@ -49,7 +50,7 @@ export const getThematicLayerFromAnalyticalObject = async ( } // Load default legend set for selected data dimension - const legendSet = await loadDataItemLegendSet(dataDim) + const legendSet = await loadDataItemLegendSet(dataDim, engine) // Currently we only support one period in map filters so we select the first if (yearlySeries && yearlySeries.length) { diff --git a/src/util/app.js b/src/util/app.js index 80c1c7007..0d7c77121 100644 --- a/src/util/app.js +++ b/src/util/app.js @@ -12,7 +12,7 @@ import { } from './external.js' import { getDefaultLayerTypes } from './getDefaultLayerTypes.js' import { getHiddenPeriods } from './periods.js' -import { fetchExternalLayersQuery } from './requests.js' +import { EXTERNAL_MAP_LAYERS_QUERY } from './requests.js' export const appQueries = { currentUser: { @@ -27,6 +27,7 @@ export const appQueries = { key: SYSTEM_SETTINGS, }, }, + externalMapLayers: EXTERNAL_MAP_LAYERS_QUERY, systemInfo: { resource: 'system/info', params: { @@ -39,7 +40,6 @@ export const appQueries = { key: ['keyUiLocale'], }, }, - externalMapLayers: fetchExternalLayersQuery, } const getBasemapList = (externalMapLayers, systemSettings) => { @@ -91,6 +91,8 @@ export const providerDataTransformation = ({ name: currentUser.name, username: currentUser.username, authorities: new Set(currentUser.authorities), + keyAnalysisDisplayProperty: + currentUser.settings.keyAnalysisDisplayProperty, }, nameProperty: currentUser.settings.keyAnalysisDisplayProperty === 'name' diff --git a/src/util/dataDownload.js b/src/util/dataDownload.js index 326e6812c..f141c2e7c 100644 --- a/src/util/dataDownload.js +++ b/src/util/dataDownload.js @@ -89,6 +89,7 @@ export const downloadData = async ({ humanReadableKeys, d2, nameProperty, + engine, }) => { const { name, layer: layerType } = layer let layerData = layer.data @@ -97,7 +98,7 @@ export const downloadData = async ({ const columns = await getEventColumns(layer, { format, nameProperty, - d2, + engine, }) const config = { ...layer, @@ -110,7 +111,7 @@ export const downloadData = async ({ } const result = await loadData( - await getAnalyticsRequest(config, { d2, nameProperty }), + await getAnalyticsRequest(config, { d2, nameProperty, engine }), config, d2 ) diff --git a/src/util/event.js b/src/util/event.js index 3704f777b..f4711ce78 100644 --- a/src/util/event.js +++ b/src/util/event.js @@ -6,6 +6,17 @@ import { import { getOrgUnitsFromRows, getPeriodFromFilters } from './analytics.js' import { addStyleDataItem, createEventFeatures } from './geojson.js' +export const PROGRAM_STAGE_QUERY = { + programStage: { + resource: 'programStages', + id: ({ id }) => id, + params: ({ nameProperty }) => ({ + fields: `programStageDataElements[displayInReports,dataElement[id,code,${nameProperty}~rename(name),optionSet,valueType]]`, + paging: false, + }), + }, +} + // Empty filter sometimes returned for saved maps // Dimension without filter and empty items array returns false const isValidDimension = ({ dimension, filter, items }) => @@ -15,11 +26,10 @@ const METADATA_FORMAT_NAME = 'name' export const getEventColumns = async ( layer, - { format = METADATA_FORMAT_NAME, nameProperty, d2 } + { format = METADATA_FORMAT_NAME, nameProperty, engine } ) => { - const result = await d2.models.programStage.get(layer.programStage.id, { - fields: `programStageDataElements[displayInReports,dataElement[id,code,${nameProperty}~rename(name),optionSet]]`, - paging: false, + const { programStage: result } = await engine.query(PROGRAM_STAGE_QUERY, { + variables: { id: layer.programStage.id, nameProperty }, }) return result.programStageDataElements @@ -48,7 +58,7 @@ export const getAnalyticsRequest = async ( relativePeriodDate, isExtended, }, - { d2, nameProperty } + { d2, nameProperty, engine } ) => { const orgUnits = getOrgUnitsFromRows(rows) const period = getPeriodFromFilters(filters) @@ -61,7 +71,7 @@ export const getAnalyticsRequest = async ( if (isExtended) { const displayColumns = await getEventColumns( { programStage }, - { d2, nameProperty } + { engine, nameProperty } ) displayColumns.forEach((col) => { diff --git a/src/util/external.js b/src/util/external.js index a2dd50564..8d4e96746 100644 --- a/src/util/external.js +++ b/src/util/external.js @@ -6,7 +6,7 @@ import { GEOJSON_URL_LAYER, GEOJSON_LAYER, } from '../constants/layers.js' -import { getExternalLayer } from './requests.js' +import { EXTERNAL_MAP_LAYER_QUERY } from './requests.js' const MAP_SERVICE_WMS = 'WMS' const MAP_SERVICE_TMS = 'TMS' @@ -76,7 +76,7 @@ const createExternalLayerConfig = (model) => { } // Parse external layer config returned as a string in ao -export const parseLayerConfig = async (layerConfig) => { +export const parseLayerConfig = async (layerConfig, engine) => { let config try { @@ -89,8 +89,15 @@ export const parseLayerConfig = async (layerConfig) => { // use a fresh layer config from the API if (config.id) { try { - const layer = await getExternalLayer(config.id) - const newConfig = createExternalLayerConfig(layer) + const { externalLayer } = await engine.query( + { externalLayer: EXTERNAL_MAP_LAYER_QUERY }, + { + variables: { + id: config.id, + }, + } + ) + const newConfig = createExternalLayerConfig(externalLayer) newConfig.featureStyle = { ...config.featureStyle } } catch (evt) { return config diff --git a/src/util/getConfigFromNonMapConfig.js b/src/util/getConfigFromNonMapConfig.js index 8a49a1b65..3db96a98d 100644 --- a/src/util/getConfigFromNonMapConfig.js +++ b/src/util/getConfigFromNonMapConfig.js @@ -1,17 +1,19 @@ -import { generateUid } from 'd2/uid' import { getThematicLayerFromAnalyticalObject } from './analyticalObject.js' +import { generateUid } from './uid.js' -export const getConfigFromNonMapConfig = (config, defaultBasemapId) => { +export const getConfigFromNonMapConfig = (config, defaultBasemapId, engine) => { const { name } = config - return getThematicLayerFromAnalyticalObject(config).then((mapView) => ({ - name, - basemap: { id: defaultBasemapId }, - mapViews: [ - { - id: generateUid(), - ...mapView, - }, - ], - })) + return getThematicLayerFromAnalyticalObject({ ao: config, engine }).then( + (mapView) => ({ + name, + basemap: { id: defaultBasemapId }, + mapViews: [ + { + id: generateUid(), + ...mapView, + }, + ], + }) + ) } diff --git a/src/util/helpers.js b/src/util/helpers.js index b2e7ccf16..cbb9e7251 100644 --- a/src/util/helpers.js +++ b/src/util/helpers.js @@ -1,31 +1,6 @@ import { isObject } from 'lodash/fp' import { RENDERING_STRATEGY_SPLIT_BY_PERIOD } from '../constants/layers.js' -const propertyMap = { - name: 'name', - displayName: 'name', - shortName: 'shortName', - displayShortName: 'shortName', -} - -export const getDisplayProperty = (d2, displayProperty) => { - const keyAnalysisDisplayProperty = - d2.currentUser.settings.keyAnalysisDisplayProperty - return ( - propertyMap[keyAnalysisDisplayProperty] || - propertyMap[displayProperty] || - 'name' - ) // TODO: check -} - -/* -export const getDisplayPropertyUrl = d2 => { - return `${getDisplayProperty(d2)}~rename(name)`; // TODO -}; -*/ - -export const getDisplayPropertyUrl = () => `displayName~rename(name)` - const baseFields = [ 'id', 'user', @@ -46,15 +21,15 @@ const baseFields = [ ] const analysisFields = () => { - const namePropertyUrl = getDisplayPropertyUrl() + const nameProperty = `displayName~rename(name)` return [ '*', - `columns[dimension,filter,items[dimensionItem~rename(id),dimensionItemType,${namePropertyUrl}]]`, - `rows[dimension,filter,items[dimensionItem~rename(id),dimensionItemType,${namePropertyUrl}]]`, - `filters[dimension,filter,items[dimensionItem~rename(id),dimensionItemType,${namePropertyUrl}]]`, + `columns[dimension,filter,items[dimensionItem~rename(id),dimensionItemType,${nameProperty}]]`, + `rows[dimension,filter,items[dimensionItem~rename(id),dimensionItemType,${nameProperty}]]`, + `filters[dimension,filter,items[dimensionItem~rename(id),dimensionItemType,${nameProperty}]]`, 'organisationUnits[id,path]', // Added to retrieve org unit paths 'dataDimensionItems', - `program[id,${namePropertyUrl}]`, + `program[id,${nameProperty}]`, 'programStage[id,displayName~rename(name)]', 'legendSet[id,displayName~rename(name)]', 'trackedEntityType[id,displayName~rename(name)]', @@ -102,10 +77,6 @@ export const legendFields = [ '!userGroupAccesses', ] -export const legendSetFields = [ - 'id,displayName~rename(name),legends[' + legendFields.join(',') + ']', -] - // Add path to org unit dimension - https://jira.dhis2.org/browse/DHIS2-4212 export const addOrgUnitPaths = (mapViews) => mapViews.map((view) => diff --git a/src/util/legend.js b/src/util/legend.js index fd1e49c33..8d44da32e 100644 --- a/src/util/legend.js +++ b/src/util/legend.js @@ -1,27 +1,76 @@ -import { getInstance as getD2 } from 'd2' +import { + DIMENSION_TYPE_INDICATOR, + DIMENSION_TYPE_DATA_ELEMENT, + DIMENSION_TYPE_DATA_SET, +} from '@dhis2/analytics' import { sortBy, pick } from 'lodash/fp' import { CLASSIFICATION_EQUAL_INTERVALS } from '../constants/layers.js' import { getLegendItems } from '../util/classify.js' import { defaultClasses, defaultColorScale } from '../util/colors.js' -export const loadLegendSet = async (legendSet) => { - const d2 = await getD2() - return d2.models.legendSet.get(legendSet.id) // TODO: Restrict loading fields +const INDICATOR_QUERY = { + dimension: { + resource: 'indicators', + id: ({ id }) => id, + params: { + fields: 'legendSet[id,displayName~rename(name)]', + }, + }, } -export const loadDataItemLegendSet = async (dataItem) => { - const type = (dataItem.dimensionItemType || '').toLowerCase() - const d2 = await getD2() +const DATA_ELEMENT_QUERY = { + dimension: { + resource: 'dataElements', + id: ({ id }) => id, + params: { + fields: 'legendSet[id,displayName~rename(name)]', + }, + }, +} - if (!type || !d2.models[type]) { - return +const DATA_SET_QUERY = { + dimension: { + resource: 'dataSets', + id: ({ id }) => id, + params: { + fields: 'legendSet[id,displayName~rename(name)]', + }, + }, +} + +export const loadDataItemLegendSet = async (dataItem, engine) => { + if (!dataItem) { + return null } - return d2.models[type] - .get(dataItem.id, { - fields: 'legendSet[id,displayName~rename(name)]', - }) - .then((model) => model.legendSet) + let result = null + switch (dataItem.dimensionItemType) { + case DIMENSION_TYPE_INDICATOR: + { + result = await engine.query(INDICATOR_QUERY, { + variables: { id: dataItem.id }, + }) + } + break + case DIMENSION_TYPE_DATA_ELEMENT: + { + result = await engine.query(DATA_ELEMENT_QUERY, { + variables: { id: dataItem.id }, + }) + } + break + case DIMENSION_TYPE_DATA_SET: + { + result = await engine.query(DATA_SET_QUERY, { + variables: { id: dataItem.id }, + }) + } + break + default: + return null + } + + return result.dimension.legendSet } export const formatLegendItems = (legendItems) => { diff --git a/src/util/orgUnits.js b/src/util/orgUnits.js index 531a6c82f..1ace80c4c 100644 --- a/src/util/orgUnits.js +++ b/src/util/orgUnits.js @@ -9,9 +9,7 @@ import { STYLE_TYPE_SYMBOL, NONE, } from '../constants/layers.js' -import { apiFetch } from './api.js' import { getUniqueColor } from './colors.js' -import { getDisplayPropertyUrl } from './helpers.js' const getGroupColor = (groups) => { const groupsWithoutColors = groups.filter((g) => !g.color) @@ -44,10 +42,15 @@ export const parseGroupSet = ({ organisationUnitGroups: groups }) => { })) } -export const fetchOrgUnitGroupSet = (id) => - apiFetch( - `/organisationUnitGroupSets/${id}?fields=organisationUnitGroups[id,name,color,symbol]` - ).then(parseGroupSet) +export const ORG_UNITS_GROUP_SET_QUERY = { + groupSets: { + resource: 'organisationUnitGroupSets', + id: ({ id }) => id, + params: { + fields: ['organisationUnitGroups[id,name,color,symbol]'], + }, + }, +} export const getPointItems = (data) => data.filter((d) => d.ty === 1) @@ -182,24 +185,6 @@ export const getStyledOrgUnits = ( } /* eslint-enable max-params */ -// This function returns the org unit level names used in the legend -export const getOrgUnitLevels = async (d2) => { - const orgUnitLevels = await d2.models.organisationUnitLevels.list({ - fields: `id,${getDisplayPropertyUrl(d2)},level`, - paging: false, - }) - - return orgUnitLevels - ? orgUnitLevels.toArray().reduce( - (obj, item) => ({ - ...obj, - [item.level]: item.name, - }), - {} - ) - : {} -} - // Converts "LEVEL-x" to newer "LEVEL-uid" format export const translateOrgUnitLevels = (orgUnits, orgUnitLevels = []) => { const items = orgUnits?.items || [] diff --git a/src/util/requests.js b/src/util/requests.js index 7e5a2cbd5..248b61fec 100644 --- a/src/util/requests.js +++ b/src/util/requests.js @@ -1,6 +1,6 @@ -import { getInstance as getD2 } from 'd2' import { getMigratedMapConfig } from './getMigratedMapConfig.js' import { mapFields } from './helpers.js' + // API requests const fetchMapQuery = { @@ -26,7 +26,7 @@ export const fetchMap = async (id, engine, keyDefaultBaseMap) => throw new Error(`Could not load map with id "${id}"`) }) -export const fetchExternalLayersQuery = { +export const EXTERNAL_MAP_LAYERS_QUERY = { resource: 'externalMapLayers', params: { fields: 'id,displayName~rename(name),service,url,attribution,mapService,layers,imageFormat,mapLayerPosition,legendSet,legendSetUrl', @@ -35,7 +35,41 @@ export const fetchExternalLayersQuery = { } // Fetch a single externalLayer -export const getExternalLayer = async (id) => { - const d2 = await getD2() - return d2.models.externalMapLayers.get(id) +export const EXTERNAL_MAP_LAYER_QUERY = { + resource: 'externalMapLayers', + id: ({ id }) => id, + params: { + fields: 'id,displayName~rename(name),service,url,attribution,mapService,layers,imageFormat,mapLayerPosition,legendSet,legendSetUrl', + }, +} + +export const OPTION_SET_QUERY = { + optionSet: { + resource: 'optionSets', + id: ({ id }) => id, + params: { + fields: [ + 'id', + 'displayName~rename(name)', + 'options[id,code,displayName~rename(name)]', + ], + paging: false, + }, + }, +} + +// Load a single legend set +export const LEGEND_SET_QUERY = { + legendSet: { + resource: 'legendSets', + id: ({ id }) => id, + params: { + fields: [ + 'id', + 'displayName~rename(name)', + 'legends[id,displayName~rename(name),startValue,endValue,color]', + ], + paging: false, + }, + }, } diff --git a/src/util/styleByDataItem.js b/src/util/styleByDataItem.js index dc7ebb681..79eb12396 100644 --- a/src/util/styleByDataItem.js +++ b/src/util/styleByDataItem.js @@ -1,5 +1,4 @@ import i18n from '@dhis2/d2-i18n' -import { getInstance as getD2 } from 'd2' import { curry } from 'lodash/fp' import { EVENT_COLOR, @@ -8,25 +7,22 @@ import { } from '../constants/layers.js' import { numberValueTypes } from '../constants/valueTypes.js' import { cssColor } from '../util/colors.js' +import { OPTION_SET_QUERY, LEGEND_SET_QUERY } from '../util/requests.js' import { getLegendItemForValue } from './classify.js' -import { - loadLegendSet, - getAutomaticLegendItems, - getPredefinedLegendItems, -} from './legend.js' +import { getAutomaticLegendItems, getPredefinedLegendItems } from './legend.js' // "Style by data item" handling for event layer // Can be reused for TEI layer when the Web API is improved // This function is modifiyng the config object before it's added to the redux store -export const styleByDataItem = async (config) => { +export const styleByDataItem = async (config, engine) => { const { styleDataItem } = config if (styleDataItem.optionSet) { - await styleByOptionSet(config) + await styleByOptionSet(config, engine) } else if (numberValueTypes.includes(styleDataItem.valueType)) { - await styleByNumeric(config) + await styleByNumeric(config, engine) } else if (styleDataItem.valueType === 'BOOLEAN') { - await styleByBoolean(config) + await styleByBoolean(config, engine) } config.legend.items.push({ @@ -38,7 +34,7 @@ export const styleByDataItem = async (config) => { return config } -export const styleByBoolean = async (config) => { +const styleByBoolean = async (config, engine) => { const { styleDataItem, data, legend, eventPointRadius } = config const { id, name, values } = styleDataItem @@ -59,7 +55,13 @@ export const styleByBoolean = async (config) => { } }) - legend.unit = name || (await getDataElementName(id)) + legend.unit = + name || + (await engine + .query(DATA_ELEMENT_NAME_QUERY, { + variables: { id }, + }) + .then(({ dataElement }) => dataElement.name)) legend.items = [ { @@ -80,7 +82,7 @@ export const styleByBoolean = async (config) => { return config } -export const styleByNumeric = async (config) => { +const styleByNumeric = async (config, engine) => { const { styleDataItem, method, @@ -93,7 +95,9 @@ export const styleByNumeric = async (config) => { // If legend set if (method === CLASSIFICATION_PREDEFINED) { // Load legend set from server - const legendSet = await loadLegendSet(config.legendSet) + const { legendSet } = await engine.query(LEGEND_SET_QUERY, { + variables: { id: config.legendSet.id }, + }) // Use legend set name and legend unit config.legend.unit = legendSet.name @@ -108,7 +112,12 @@ export const styleByNumeric = async (config) => { // Use data item name as legend unit (load from server if needed) config.legend.unit = - styleDataItem.name || (await getDataElementName(styleDataItem.id)) + styleDataItem.name || + (await engine + .query(DATA_ELEMENT_NAME_QUERY, { + variables: { id: styleDataItem.id }, + }) + .then(({ dataElement }) => dataElement.name)) // Generate legend items based on layer config config.legend.items = getAutomaticLegendItems( @@ -150,9 +159,9 @@ export const styleByNumeric = async (config) => { return config } -export const styleByOptionSet = async (config) => { +const styleByOptionSet = async (config, engine) => { const { styleDataItem } = config - const optionSet = await getOptionSet(styleDataItem.optionSet) + const optionSet = await getOptionSet(styleDataItem.optionSet, engine) const id = styleDataItem.id // Replace styleDataItem with a version with names @@ -205,16 +214,15 @@ export const styleByOptionSet = async (config) => { // The style option set included in a favorite is stripped for names // and this function add the names if needed -const getOptionSet = async (optionSet) => { +const getOptionSet = async (optionSet, engine) => { // Return unmodified option set if names are included if (optionSet.name) { return optionSet } // Load option set from server - const d2 = await getD2() - const optSet = await d2.models.optionSet.get(optionSet.id, { - fields: 'displayName~rename(name),options[id,code,displayName~rename(name)]', + const { optionSet: optSet } = await engine.query(OPTION_SET_QUERY, { + variables: { id: optionSet.id }, }) // Return modified option set with names and codes @@ -228,11 +236,12 @@ const getOptionSet = async (optionSet) => { } } -const getDataElementName = async (id) => { - const d2 = await getD2() - return d2.models.dataElement - .get(id, { +const DATA_ELEMENT_NAME_QUERY = { + dataElement: { + resource: 'dataElements', + id: ({ id }) => id, + params: { fields: 'displayName~rename(name)', - }) - .then((model) => model.name) + }, + }, }