@cdc/dashboard 4.24.4 → 4.24.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.html CHANGED
@@ -21,12 +21,12 @@
21
21
  </head>
22
22
 
23
23
  <body>
24
- <!-- <div class="react-container" data-config="/examples/full-dashboard.json"></div> -->
24
+ <div class="react-container" data-config="/examples/full-dashboard.json"></div>
25
25
  <!-- <div class="react-container" data-config="/examples/dashboard-gallery.json"></div> -->
26
- <div class="react-container" data-config="/examples/filtered-dash.json"></div>
26
+ <!-- <div class="react-container" data-config="/examples/filtered-dash.json"></div> -->
27
27
  <!-- <div class="react-container" data-config="/examples/all-components.json"></div> -->
28
28
  <!-- <div class="react-container" data-config="/examples/sankey.json"></div> -->
29
- <div class="react-container" data-config="/examples/DEV-6574.json"></div>
29
+ <!-- <div class="react-container" data-config="/examples/DEV-6574.json"></div> -->
30
30
  <!-- <div class="react-container" data-config="/examples/default-multi-dataset-2.json"></div> -->
31
31
  <!-- <div class="react-container" data-config="/examples/default-multi-dataset.json"></div> -->
32
32
  <!-- <div class="react-container" data-config="/examples/default-filter-control.json"></div> -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cdc/dashboard",
3
- "version": "4.24.4",
3
+ "version": "4.24.5",
4
4
  "description": "React component for combining multiple visualizations into a single dashboard",
5
5
  "moduleName": "CdcDashboard",
6
6
  "main": "dist/cdcdashboard",
@@ -26,13 +26,13 @@
26
26
  },
27
27
  "license": "Apache-2.0",
28
28
  "dependencies": {
29
- "@cdc/chart": "^4.24.4",
30
- "@cdc/core": "^4.24.4",
31
- "@cdc/data-bite": "^4.24.4",
32
- "@cdc/filtered-text": "^4.24.4",
33
- "@cdc/map": "^4.24.4",
34
- "@cdc/markup-include": "^4.24.4",
35
- "@cdc/waffle-chart": "^4.24.4",
29
+ "@cdc/chart": "^4.24.5",
30
+ "@cdc/core": "^4.24.5",
31
+ "@cdc/data-bite": "^4.24.5",
32
+ "@cdc/filtered-text": "^4.24.5",
33
+ "@cdc/map": "^4.24.5",
34
+ "@cdc/markup-include": "^4.24.5",
35
+ "@cdc/waffle-chart": "^4.24.5",
36
36
  "html-react-parser": "^3.0.8",
37
37
  "js-base64": "^2.5.2",
38
38
  "papaparse": "^5.3.0",
@@ -48,5 +48,5 @@
48
48
  "react": "^18.2.0",
49
49
  "react-dom": "^18.2.0"
50
50
  },
51
- "gitHead": "1843b4632140d582af6a87606374cbd4fe25ad5c"
51
+ "gitHead": "def85aaf4cd9dc1983e80f2900199f35de82af95"
52
52
  }
@@ -40,7 +40,6 @@ import { capitalizeSplitAndJoin } from '@cdc/core/helpers/cove/string'
40
40
  import VisualizationsPanel from './components/VisualizationsPanel'
41
41
  import dashboardReducer from './store/dashboard.reducer'
42
42
  import { filterData } from './helpers/filterData'
43
- import { getFormattedData } from './helpers/getFormattedData'
44
43
  import { getVizKeys } from './helpers/getVizKeys'
45
44
  import Title from '@cdc/core/components/ui/Title'
46
45
  import { type TableConfig } from '@cdc/core/components/DataTable/types/TableConfig'
@@ -56,13 +55,11 @@ import _ from 'lodash'
56
55
  import EditorContext from '../../editor/src/ConfigContext'
57
56
  import { getApiFilterKey } from './helpers/getApiFilterKey'
58
57
  import Filters, { APIFilterDropdowns, DropdownOptions } from './components/Filters'
59
- import EditorWrapper from './components/EditorWrapper/EditorWrapper'
60
- import DataTableEditorPanel from '@cdc/core/components/DataTable/components/DataTableEditorPanel'
61
58
  import DataTableStandAlone from '@cdc/core/components/DataTable/DataTableStandAlone'
62
59
  import { ViewPort } from '@cdc/core/types/ViewPort'
63
60
  import VisualizationRow from './components/VisualizationRow'
64
61
  import { getVizConfig } from './helpers/getVizConfig'
65
- import { getApplicableFilters, getFilteredData } from './helpers/getFilteredData'
62
+ import { getFilteredData } from './helpers/getFilteredData'
66
63
  import { getVizRowColumnLocator } from './helpers/getVizRowColumnLocator'
67
64
  import Layout from '@cdc/core/components/Layout'
68
65
 
@@ -103,7 +100,7 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
103
100
 
104
101
  const transform = new DataTransform()
105
102
 
106
- const setAutoLoadDefaultValue = (sharedFilterIndex: number, filterDropdowns: DropdownOptions, dashboardConfigOverride) => {
103
+ const setAutoLoadDefaultValue = (sharedFilterIndex: number, filterDropdowns: DropdownOptions) => {
107
104
  const autoLoadViz = getAutoLoadVisualization()
108
105
  if (!autoLoadViz) return // no autoLoading happening
109
106
  const notIncludedInAutoLoad = autoLoadViz.hide
@@ -111,22 +108,20 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
111
108
  // we don't want to auto load it
112
109
  return
113
110
  } else {
114
- const sharedFilters = dashboardConfigOverride.sharedFilters
115
- const sharedFilter = sharedFilters[sharedFilterIndex]
111
+ const sharedFilter = state.config.dashboard.sharedFilters[sharedFilterIndex]
116
112
  if (sharedFilter.active) return // a value has already been selected.
117
- const filterParents = sharedFilters.filter(f => sharedFilter.parents?.includes(f.key))
118
- const notAllParentFiltersSelected = filterParents.some(p => !p.active && !p.queuedActive)
113
+ const filterParents = state.config.dashboard.sharedFilters.filter(f => sharedFilter.parents?.includes(f.key))
114
+ const notAllParentFiltersSelected = filterParents.some(p => !p.active)
119
115
  if (filterParents && notAllParentFiltersSelected) return
120
116
  const defaultFilterDropdown = filterDropdowns.find(({ value }) => value === sharedFilter.apiFilter!.defaultValue)
121
- const defaultValue = defaultFilterDropdown?.value || filterDropdowns[0].value
122
- sharedFilter.active = defaultValue
117
+ let defaultValue = defaultFilterDropdown?.value || filterDropdowns[0].value
118
+ changeFilterActive(sharedFilterIndex, defaultValue)
123
119
  }
124
120
  }
125
121
 
126
- const loadAPIFilters = (dashboardConfigOverride = undefined) => {
127
- const sharedFilters = (dashboardConfigOverride || state.config.dashboard).sharedFilters
128
- if (sharedFilters) {
129
- const sharedAPIFilters = sharedFilters.filter(f => f.apiFilter)
122
+ const loadAPIFilters = async () => {
123
+ if (state.config.dashboard.sharedFilters) {
124
+ const sharedAPIFilters = state.config.dashboard.sharedFilters.filter(f => f.apiFilter)
130
125
  const loadingFilterMemo: APIFilterDropdowns = sharedAPIFilters.reduce((acc, curr) => {
131
126
  const _key = getApiFilterKey(curr.apiFilter!)
132
127
  if (apiFilterDropdowns[_key] != null) return acc // don't overwrite fetched data.
@@ -138,69 +133,58 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
138
133
  const getParentParams = (childFilter: SharedFilter): Record<'key' | 'value', string>[] | null => {
139
134
  const _parents = sharedAPIFilters.filter(parentFilter => childFilter.parents?.includes(parentFilter.key))
140
135
  if (!_parents.length) return null
141
- return _parents.map(({ queryParameter, active, queuedActive }) => ({ key: queryParameter || '', value: active || queuedActive || '' }))
136
+ return _parents.map(({ queryParameter, queuedActive }) => ({ key: queryParameter || '', value: queuedActive || '' }))
142
137
  }
143
- const getFilterValues = (data: Array<Object>, apiFilter: APIFilter): DropdownOptions => {
144
- const { textSelector, valueSelector } = apiFilter
138
+ const getFilterValues = (data: Object | Array<Object>, apiFilter: APIFilter): DropdownOptions => {
139
+ const { textSelector, valueSelector, heirarchyLookup } = apiFilter
140
+ if (heirarchyLookup) {
141
+ const heirarchy = heirarchyLookup!.split('.')
142
+ const selector = heirarchy.shift() // pop first element
143
+ return getFilterValues(selector ? data[selector] : data, { ...apiFilter, heirarchyLookup: heirarchy.join('.') })
144
+ }
145
+ if (!Array.isArray(data)) throw new Error('the filter data has requires a heirarchy path to access the filter values, This should be in the format key.subkey.subsubkey')
145
146
  return data.map(v => ({ text: v[textSelector], value: v[valueSelector] }))
146
147
  }
147
- const toFetch = {}
148
- sharedAPIFilters.forEach((filter, index) => {
148
+ state.config.dashboard.sharedFilters.forEach(async (filter, index) => {
149
+ if (!filter.apiFilter) return
149
150
  const baseEndpoint = filter.apiFilter.apiEndpoint
150
151
  const _key = getApiFilterKey(filter.apiFilter)
151
152
  const params = getParentParams(filter)
152
153
  const notAllParentsSelected = params?.some(({ value }) => value === '')
153
-
154
154
  if (notAllParentsSelected) return // don't send request for dependent children filter options
155
- if (apiFilterDropdowns[_key] && !params) return // don't reload filter unless it's a child
156
- const topLevelDataAlreadyLoaded = apiFilterDropdowns[_key] && !filter.parents
157
- if (topLevelDataAlreadyLoaded) return // don't reload top level filters
158
-
155
+ if (apiFilterDropdowns[_key] && !params && filter.filterBy === 'Query String') return // don't reload filter unless it's a child
159
156
  const endpoint = baseEndpoint + (params ? gatherQueryParams(params) : '')
160
- toFetch[endpoint] = [_key, index]
157
+
158
+ fetch(endpoint)
159
+ .then(resp => resp.json())
160
+ .then(data => {
161
+ const apiFilter = filterLookup.get(_key) as APIFilter
162
+ const _filterValues = getFilterValues(data, apiFilter)
163
+ setAPIFilterDropdowns(dropdowns => ({ ...dropdowns, [_key]: _filterValues }))
164
+ setAutoLoadDefaultValue(index, _filterValues)
165
+ })
161
166
  })
162
- return Promise.all(
163
- Object.keys(toFetch).map(
164
- endpoint =>
165
- new Promise<void>(resolve => {
166
- fetch(endpoint)
167
- .then(resp => resp.json())
168
- .then(data => {
169
- const [_key, index] = toFetch[endpoint]
170
- if (!Array.isArray(data)) throw new Error('COVE only supports response data in the shape Array<Object>')
171
- const apiFilter = filterLookup.get(_key) as APIFilter
172
- const _filterValues = getFilterValues(data, apiFilter)
173
- setAPIFilterDropdowns(dropdowns => ({ ...dropdowns, [_key]: _filterValues }))
174
- setAutoLoadDefaultValue(index, _filterValues, dashboardConfigOverride)
175
- })
176
- .catch(console.error)
177
- .finally(() => {
178
- resolve()
179
- })
180
- })
181
- )
182
- )
183
167
  }
184
168
  }
185
169
 
186
- const reloadURLData = async (dashboardConfigOverride = undefined) => {
187
- const config = _.cloneDeep(state.config)
170
+ const reloadURLData = async () => {
171
+ const { config } = state
188
172
  if (!config.datasets) return
189
173
  let newData = { ...state.data }
190
174
  let newDatasets = { ...config.datasets }
191
175
  let datasetsNeedsUpdate = false
192
176
  let datasetKeys = Object.keys(config.datasets)
193
177
  let newFileName = ''
194
- const filters = (dashboardConfigOverride || config.dashboard)?.sharedFilters
178
+
195
179
  for (let i = 0; i < datasetKeys.length; i++) {
196
180
  const datasetKey = datasetKeys[i]
197
181
  const dataset = config.datasets[datasetKey]
198
-
182
+ const filters = config.dashboard?.sharedFilters
199
183
  if (dataset.dataUrl && filters) {
200
184
  const dataUrl = new URL(dataset.runtimeDataUrl || dataset.dataUrl, window.location.origin)
201
185
  let currentQSParams = Object.fromEntries(new URLSearchParams(dataUrl.search))
202
186
  let updatedQSParams = {}
203
- let isUpdateNeeded = !!dashboardConfigOverride
187
+ let isUpdateNeeded = false
204
188
 
205
189
  filters.forEach(filter => {
206
190
  // filter.active is always a string when filter.type is 'urlfilter'
@@ -272,10 +256,10 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
272
256
  }
273
257
 
274
258
  if (datasetsNeedsUpdate) {
275
- const dashboardConfig = dashboardConfigOverride || config.dashboard
276
259
  dispatch({ type: 'SET_DATA', payload: newData })
277
260
 
278
261
  const newFilteredData = getFilteredData(state, {}, newData)
262
+
279
263
  const visualizations = Object.keys(config.visualizations).reduce((acc, vizKey) => {
280
264
  const dataKey = config.visualizations[vizKey].dataKey
281
265
  if (newData[dataKey]) {
@@ -285,7 +269,7 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
285
269
  }, _.cloneDeep(config.visualizations))
286
270
 
287
271
  dispatch({ type: 'SET_FILTERED_DATA', payload: newFilteredData })
288
- dispatch({ type: 'SET_CONFIG', payload: { dashboard: dashboardConfig, datasets: newDatasets, visualizations } })
272
+ dispatch({ type: 'SET_CONFIG', payload: { ...config, datasets: newDatasets, visualizations } })
289
273
  }
290
274
  }
291
275
 
@@ -300,7 +284,8 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
300
284
  }
301
285
 
302
286
  const setSharedFilter = (key, datum) => {
303
- const { config: newConfig, filteredData } = _.cloneDeep(state)
287
+ const { config } = state
288
+ let newConfig = { ...config }
304
289
 
305
290
  for (let i = 0; i < newConfig.dashboard.sharedFilters.length; i++) {
306
291
  const filter = newConfig.dashboard.sharedFilters[i]
@@ -312,13 +297,14 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
312
297
  }
313
298
  }
314
299
 
315
- const newFilteredData = getFilteredData({ ...state, config: newConfig }, filteredData)
300
+ const newFilteredData = getFilteredData(state, _.cloneDeep(state.filteredData))
316
301
 
317
302
  dispatch({ type: 'SET_FILTERED_DATA', payload: newFilteredData })
318
- dispatch({ type: 'SET_SHARED_FILTERS', payload: newConfig.dashboard.sharedFilters })
303
+ dispatch({ type: 'SET_CONFIG', payload: newConfig })
319
304
  }
320
305
 
321
306
  useEffect(() => {
307
+ if (state.tabSelected && state.tabSelected !== 'Dashboard Preview') return
322
308
  const { config } = state
323
309
  if (config.filterBehavior !== FilterBehavior.Apply) {
324
310
  reloadURLData()
@@ -327,16 +313,16 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
327
313
  }, [])
328
314
 
329
315
  const updateChildConfig = (visualizationKey, newConfig) => {
330
- const config = _.cloneDeep(state.config)
331
- const updatedConfig = _.pick(config, ['visualizations', 'multiDashboards'])
316
+ const { config } = state
317
+ let updatedConfig = { ...config }
332
318
  updatedConfig.visualizations[visualizationKey] = newConfig
333
319
  updatedConfig.visualizations[visualizationKey].formattedData = config.visualizations[visualizationKey].formattedData
334
320
  if (config.multiDashboards) {
335
321
  const activeDashboard = config.activeDashboard
336
322
  const multiDashboards = [...config.multiDashboards]
337
323
  const label = multiDashboards[activeDashboard].label
338
- const toSave = { label, visualizations: updatedConfig.visualizations, ..._.pick(config, ['dashboard', 'rows']) }
339
- multiDashboards[activeDashboard] = toSave
324
+ const toSave = _.pick(updatedConfig, ['dashboard', 'visualizations', 'rows'])
325
+ multiDashboards[activeDashboard] = { ...toSave, label }
340
326
  updatedConfig.multiDashboards = multiDashboards
341
327
  }
342
328
 
@@ -348,22 +334,13 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
348
334
  }
349
335
 
350
336
  const applyFilters = () => {
351
- const dashboardConfig = _.cloneDeep(state.config.dashboard)
352
- const autoLoadViz = getAutoLoadVisualization()
353
- const nonAutoLoadFilterIndexes = autoLoadViz?.hide || []
354
- const allRequiredFiltersSelected = !dashboardConfig.sharedFilters.some((filter, filterIndex) => {
355
- if (nonAutoLoadFilterIndexes.includes(filterIndex)) {
356
- !filter.active && !filter.queuedActive
357
- } else {
358
- // autoload filters don't need to be selected to apply filters
359
- return false
360
- }
361
- })
362
- if (allRequiredFiltersSelected) {
337
+ let dashboardConfig = state.config.dashboard
338
+ const allFiltersSelected = !state.config.dashboard.sharedFilters.some(filter => !filter.active && !filter.queuedActive)
339
+ if (allFiltersSelected) {
363
340
  if (state.config.filterBehavior === FilterBehavior.Apply) {
364
341
  const queryParams = getQueryParams()
365
342
  let needsQueryUpdate = false
366
- dashboardConfig.sharedFilters.forEach((sharedFilter, index) => {
343
+ state.config.dashboard.sharedFilters.forEach((sharedFilter, index) => {
367
344
  if (sharedFilter.queuedActive) {
368
345
  dashboardConfig.sharedFilters[index].active = sharedFilter.queuedActive
369
346
  delete dashboardConfig.sharedFilters[index].queuedActive
@@ -380,28 +357,21 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
380
357
  }
381
358
  }
382
359
 
383
- dispatch({ type: 'SET_SHARED_FILTERS', payload: dashboardConfig.sharedFilters })
384
- updateDataFilters()
385
- loadAPIFilters(dashboardConfig)
386
- .then(() => {
387
- reloadURLData(dashboardConfig)
388
- })
389
- .catch(e => {
390
- console.error(e)
391
- })
360
+ dispatch({ type: 'SET_CONFIG', payload: { ...state.config, dashboard: dashboardConfig } })
361
+ dispatch({ type: 'SET_FILTERED_DATA', payload: getFilteredData(state) })
362
+ reloadURLData()
392
363
  } else {
393
364
  // TODO noftify of required fields
394
365
  }
395
366
  }
396
367
 
397
368
  const changeFilterActive = (index: number, value: string | string[]) => {
398
- const sharedFilters = _.cloneDeep(state.config.dashboard.sharedFilters)
399
- const filterActive = sharedFilters[index]
400
- const nonAutoLoadFilterIndexes = getAutoLoadVisualization()?.hide
401
- const isAutoLoad = nonAutoLoadFilterIndexes && !nonAutoLoadFilterIndexes.includes(index)
369
+ const { config } = state
370
+ let dashboardConfig = { ...config.dashboard }
371
+ let filterActive = dashboardConfig.sharedFilters[index]
402
372
 
403
- if (state.config.filterBehavior !== FilterBehavior.Apply || isAutoLoad) {
404
- sharedFilters[index].active = value
373
+ if (config.filterBehavior !== FilterBehavior.Apply) {
374
+ dashboardConfig.sharedFilters[index].active = value
405
375
 
406
376
  const queryParams = getQueryParams()
407
377
  if (filterActive.setByQueryParameter && queryParams[filterActive.setByQueryParameter] !== filterActive.active) {
@@ -410,35 +380,28 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
410
380
  }
411
381
  } else {
412
382
  if (Array.isArray(value)) throw Error(`Cannot set active values on urlfilters. expected: ${JSON.stringify(value)} to be a single value.`)
413
- sharedFilters[index].queuedActive = value
383
+ dashboardConfig.sharedFilters[index].queuedActive = value
414
384
  }
415
385
 
416
- dispatch({ type: 'SET_SHARED_FILTERS', payload: sharedFilters })
417
- if (state.config.filterBehavior !== FilterBehavior.Apply) {
418
- updateDataFilters(sharedFilters)
386
+ dispatch({ type: 'SET_CONFIG', payload: { ...config, dashboard: dashboardConfig } })
387
+ if (config.filterBehavior !== FilterBehavior.Apply) {
388
+ dispatch({ type: 'SET_FILTERED_DATA', payload: getFilteredData(state) })
419
389
  reloadURLData()
420
390
  }
421
- return sharedFilters
422
- }
423
-
424
- const updateDataFilters = (sharedFilters = undefined) => {
425
- const clonedState = _.cloneDeep(state)
426
- if (sharedFilters) clonedState.config.dashboard.sharedFilters = sharedFilters
427
- const newFilteredData = getFilteredData(clonedState)
428
- dispatch({ type: 'SET_FILTERED_DATA', payload: newFilteredData })
429
391
  }
430
392
 
431
393
  const handleOnChange = (index: number, value: string | string[]) => {
432
- const config = _.cloneDeep(state.config)
433
- const newSharedFilters = changeFilterActive(index, value)
394
+ const { config } = state
395
+ changeFilterActive(index, value)
434
396
  if (config.filterBehavior === FilterBehavior.Apply) {
435
397
  const autoLoadViz = getAutoLoadVisualization()
436
- const isAutoSelectFilter = !autoLoadViz?.hide.includes(index)
398
+ if (!autoLoadViz) return // nothing left to do for regular filter behavior.
399
+ const isAutoSelectFilter = !autoLoadViz.hide.includes(index)
437
400
  const missingFilterSelections = config.dashboard.sharedFilters.some(f => !f.active)
438
401
  if (isAutoSelectFilter && !missingFilterSelections) {
439
402
  // a dropdown has been selected that doesn't
440
403
  // require the Go Button
441
- reloadURLData({ sharedFilters: newSharedFilters })
404
+ reloadURLData()
442
405
  } else {
443
406
  // A parent filter was selected, reset filters by:
444
407
  // set auto select filter dropdowns to null
@@ -460,12 +423,11 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
460
423
  if (_isAutoSelectFilter) filter.active = ''
461
424
  return filter
462
425
  })
463
- const _newConfig = { dashboard: { ...config.dashboard, sharedFilters: newSharedFilters } }
426
+ const _newConfig = { ...config, dashboard: { ...config.dashboard, sharedFilters: newSharedFilters } }
464
427
  dispatch({ type: 'SET_CONFIG', payload: _newConfig })
465
428
  // setData to empty object because we no longer have a data state.
466
429
  dispatch({ type: 'SET_DATA', payload: {} })
467
430
  dispatch({ type: 'SET_FILTERED_DATA', payload: {} })
468
- loadAPIFilters(_newConfig.dashboard)
469
431
  }
470
432
  }
471
433
  }
@@ -604,9 +566,10 @@ export default function CdcDashboard({ initialState, isEditor = false, isDebug =
604
566
  break
605
567
  case 'table':
606
568
  body = (
607
- <EditorWrapper component={DataTableStandAlone} visualizationKey={visualizationKey} visualizationConfig={visualizationConfig} updateConfig={_updateConfig} type={'Table'} viewport={currentViewport}>
608
- <DataTableEditorPanel key={visualizationKey} config={visualizationConfig} updateConfig={_updateConfig} />
609
- </EditorWrapper>
569
+ <>
570
+ <Header visualizationKey={visualizationKey} subEditor='Table' />
571
+ <DataTableStandAlone visualizationKey={visualizationKey} config={visualizationConfig} isEditor={true} updateConfig={_updateConfig} />
572
+ </>
610
573
  )
611
574
  break
612
575
  default:
@@ -7,6 +7,7 @@ import ExampleConfig_2 from './_mock/dashboard-2.json'
7
7
  import ExampleConfig_3 from './_mock/dashboard_no_filter.json'
8
8
  import Dashboard_Filter from './_mock/dashboard-filter.json'
9
9
  import MultiVizConfig from './_mock/multi-viz.json'
10
+ import MultiDashboardConfig from './_mock/multi-dashboards.json'
10
11
  import Dashboard from '../CdcDashboard'
11
12
  import StandaloneTable from './_mock/standalone-table.json'
12
13
  import PivotFitlerConfig from './_mock/pivot-filter.json'
@@ -99,6 +100,13 @@ export const MultiVisualization: Story = {
99
100
  }
100
101
  }
101
102
 
103
+ export const MultiDashboard: Story = {
104
+ args: {
105
+ config: MultiDashboardConfig,
106
+ isEditor: false
107
+ }
108
+ }
109
+
102
110
  const sleep = ms => {
103
111
  return new Promise(r => setTimeout(r, ms))
104
112
  }
@@ -125,18 +133,35 @@ const fetchMock = {
125
133
  body: [{ IndicatorID: 'indicatorID', Indicator: 'Some Indicator' }]
126
134
  }
127
135
  },
128
- ...['Year', 'DataValueType', 'StratificationCategory', 'Stratification'].map(filter => {
129
- return {
130
- matcher: {
131
- name: 'filters' + filter,
132
- url: 'path:/api/POC/Filters/' + filter
133
- },
134
- response: {
135
- status: 200,
136
- body: _.times(5, i => ({ [filter]: `Some ${filter} ${i}` }))
136
+ {
137
+ matcher: {
138
+ name: 'filters',
139
+ url: 'path:/api/POC/Filters'
140
+ },
141
+ response: {
142
+ status: 200,
143
+ body: {
144
+ Years: [{ Year: 1999 }],
145
+ DataValueTypes: [{ DataValueType: 'Some Data Value Type', DataValueTypeId: 'dataValueTypeId' }],
146
+ StratificationCategories: [{ StratificationCategoryId: 'stratCategoryId', StratificationCategory: 'Some Strat Category' }]
137
147
  }
138
148
  }
139
- }),
149
+ },
150
+ {
151
+ matcher: {
152
+ name: 'stratifications',
153
+ url: 'path:/api/POC/stratifications'
154
+ },
155
+ response: {
156
+ status: 200,
157
+ body: [
158
+ {
159
+ StratificationId: 'stratId',
160
+ Stratification: 'Some Strat'
161
+ }
162
+ ]
163
+ }
164
+ },
140
165
  {
141
166
  matcher: {
142
167
  name: 'locations',
@@ -205,11 +230,11 @@ export const APIFiltersMap: Story = {
205
230
  const indicatorsFilter = canvas.getByLabelText('Indicator', { selector: 'select' })
206
231
  await user.selectOptions(indicatorsFilter, ['indicatorID'])
207
232
  const yearsFilter = canvas.getByLabelText('Year', { selector: 'select' })
208
- await user.selectOptions(yearsFilter, ['Some Year 0'])
233
+ await user.selectOptions(yearsFilter, ['1999'])
209
234
  const stratCategoryFilter = canvas.getByLabelText('View By', { selector: 'select' })
210
- await user.selectOptions(stratCategoryFilter, ['Some StratificationCategory 0'])
235
+ await user.selectOptions(stratCategoryFilter, ['stratCategoryId'])
211
236
  const stratFilter = canvas.getByLabelText('Stratification', { selector: 'select' })
212
- await user.selectOptions(stratFilter, ['Some Stratification 0'])
237
+ await user.selectOptions(stratFilter, ['stratId'])
213
238
  await user.click(canvas.getByText('GO!'))
214
239
  }
215
240
  }
@@ -235,9 +260,8 @@ export const APIFiltersChart: Story = {
235
260
  const indicatorsFilter = canvas.getByLabelText('Indicator', { selector: 'select' })
236
261
  await user.selectOptions(indicatorsFilter, ['indicatorID'])
237
262
  await user.click(canvas.getByText('GO!'))
238
- await sleep(1000)
239
263
  const yearFilter = canvas.getByLabelText('Year', { selector: 'select' })
240
- await user.selectOptions(yearFilter, ['Some Year 1'])
264
+ await user.selectOptions(yearFilter, ['1999'])
241
265
  }
242
266
  }
243
267
 
@@ -4,6 +4,9 @@
4
4
  "sharedFilters": [
5
5
  {
6
6
  "key": "Location",
7
+ "usedBy": [
8
+ "chart1"
9
+ ],
7
10
  "type": "urlfilter",
8
11
  "apiFilter": {
9
12
  "apiEndpoint": "http://test.gov/api/poc/locations",
@@ -16,6 +19,9 @@
16
19
  },
17
20
  {
18
21
  "key": "Category",
22
+ "usedBy": [
23
+ "chart1"
24
+ ],
19
25
  "type": "urlfilter",
20
26
  "apiFilter": {
21
27
  "apiEndpoint": "http://test.gov/api/poc/topics",
@@ -28,6 +34,9 @@
28
34
  },
29
35
  {
30
36
  "key": "Indicator",
37
+ "usedBy": [
38
+ "chart1"
39
+ ],
31
40
  "type": "urlfilter",
32
41
  "apiFilter": {
33
42
  "apiEndpoint": "http://test.gov/api/poc/indicators",
@@ -41,11 +50,15 @@
41
50
  },
42
51
  {
43
52
  "key": "Year",
53
+ "usedBy": [
54
+ "chart1"
55
+ ],
44
56
  "type": "urlfilter",
45
57
  "apiFilter": {
46
- "apiEndpoint": "http://test.gov/api/POC/Filters/Year",
58
+ "apiEndpoint": "http://test.gov/api/POC/Filters",
47
59
  "valueSelector": "Year",
48
- "textSelector": "Year"
60
+ "textSelector": "Year",
61
+ "heirarchyLookup": "Years"
49
62
  },
50
63
  "queryParameter": "year",
51
64
  "showDropdown": true,
@@ -53,11 +66,15 @@
53
66
  },
54
67
  {
55
68
  "key": "View By",
69
+ "usedBy": [
70
+ "chart1"
71
+ ],
56
72
  "type": "urlfilter",
57
73
  "apiFilter": {
58
- "apiEndpoint": "http://test.gov/api/POC/Filters/StratificationCategory",
59
- "valueSelector": "StratificationCategory",
74
+ "apiEndpoint": "http://test.gov/api/POC/Filters",
75
+ "valueSelector": "StratificationCategoryId",
60
76
  "textSelector": "StratificationCategory",
77
+ "heirarchyLookup": "StratificationCategories",
61
78
  "defaultValue": "AGE"
62
79
  },
63
80
  "queryParameter": "stratificationcategoryid",
@@ -66,11 +83,16 @@
66
83
  },
67
84
  {
68
85
  "key": "Data Type",
86
+ "usedBy": [
87
+ "chart1"
88
+ ],
69
89
  "type": "urlfilter",
70
90
  "apiFilter": {
71
- "apiEndpoint": "http://test.gov/api/POC/Filters/DataValueType",
72
- "valueSelector": "DataValueType",
73
- "textSelector": "DataValueType"
91
+ "apiEndpoint": "http://test.gov/api/POC/Filters",
92
+ "valueSelector": "DataValueTypeId",
93
+ "textSelector": "DataValueType",
94
+ "heirarchyLookup": "DataValueTypes"
95
+
74
96
  },
75
97
  "queryParameter": "datavaluetypeid",
76
98
  "showDropdown": true,
@@ -108,7 +130,7 @@
108
130
  "filters": {
109
131
  "type": "filter-dropdowns",
110
132
  "visualizationType": "filter-dropdowns",
111
- "hide": [3, 4, 5]
133
+ "hide": [ 3, 4, 5 ]
112
134
  },
113
135
  "header": {
114
136
  "type": "markup-include",
@@ -119,7 +141,7 @@
119
141
  "subfilters": {
120
142
  "type": "filter-dropdowns",
121
143
  "visualizationType": "filter-dropdowns",
122
- "hide": [0, 1, 2],
144
+ "hide": [ 0, 1, 2 ],
123
145
  "autoLoad": true
124
146
  },
125
147
  "chart1": {
@@ -319,7 +341,9 @@
319
341
  },
320
342
  "validated": 4.23,
321
343
  "dynamicMarginTop": 0,
322
- "regions": [{}]
344
+ "regions": [
345
+ {}
346
+ ]
323
347
  }
324
348
  },
325
349
  "type": "dashboard",
@@ -331,4 +355,4 @@
331
355
  "filterBehavior": "Apply Button",
332
356
  "runtime": {},
333
357
  "uuid": 1684783370106
334
- }
358
+ }