@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.
@@ -41,6 +41,8 @@
41
41
  "horizontal": false,
42
42
  "series": false
43
43
  },
44
+ "filters": [],
45
+ "filterBehavior": "Filter Change",
44
46
  "formattedData": [
45
47
  {
46
48
  "Race": "Hispanic or Latino",
@@ -17,6 +17,8 @@
17
17
  "newViz": true,
18
18
  "openModal": false,
19
19
  "uid": "table1707840146431",
20
+ "filters": [],
21
+ "filterBehavior": "Filter Change",
20
22
  "table": {
21
23
  "label": "Data Table",
22
24
  "show": true,
@@ -369,6 +369,7 @@ const FilterModal: React.FC<ModalProps> = ({ config, filterState, index, removeF
369
369
  value={filter.pivot}
370
370
  onChange={e => {
371
371
  updateFilterProp('pivot', e.target.value)
372
+ updateFilterProp('showDropdown', true)
372
373
  }}
373
374
  >
374
375
  <option value=''>- Select Option -</option>
@@ -391,16 +392,19 @@ const FilterModal: React.FC<ModalProps> = ({ config, filterState, index, removeF
391
392
  }}
392
393
  />
393
394
  </label>
394
- <label>
395
- <span className='edit-label column-heading'>Show Dropdown</span>
396
- <input
397
- type='checkbox'
398
- defaultChecked={filter.showDropdown === true}
399
- onChange={e => {
400
- updateFilterProp('showDropdown', !filter.showDropdown)
401
- }}
402
- />
403
- </label>
395
+ {!filter.pivot && (
396
+ <label>
397
+ <span className='edit-label column-heading'>Show Dropdown</span>
398
+ <input
399
+ type='checkbox'
400
+ defaultChecked={filter.showDropdown === true}
401
+ onChange={e => {
402
+ updateFilterProp('showDropdown', !filter.showDropdown)
403
+ }}
404
+ />
405
+ </label>
406
+ )}
407
+
404
408
  <label>
405
409
  <span className='edit-label column-heading'>Set By: </span>
406
410
  <select value={filter.setBy} onChange={e => updateFilterProp('setBy', e.target.value)}>
@@ -9,7 +9,8 @@ const MultiTabs = () => {
9
9
  const tabs = useMemo<string[]>(() => (config.multiDashboards || []).map(({ label }) => label), [config.multiDashboards])
10
10
  const activeTab = useMemo<number>(() => config.activeDashboard, [config.activeDashboard])
11
11
 
12
- const load = (indexToSwitchTo: number) => {
12
+ const load = (indexToSwitchTo: number, e) => {
13
+ e.preventDefault() // some form wrapper is causing this to act as a submit button
13
14
  dispatch({ type: 'SWITCH_CONFIG', payload: indexToSwitchTo })
14
15
  }
15
16
 
@@ -18,7 +19,7 @@ const MultiTabs = () => {
18
19
  <ul className='nav nav-tabs multi-config-tabs'>
19
20
  {tabs.map((tab, index) => (
20
21
  <li className='nav-item'>
21
- <a className={`nav-link${activeTab === index ? ' active' : ''}`} aria-current={activeTab === index ? 'page' : null} href='#' onClick={() => load(index)}>
22
+ <a className={`nav-link${activeTab === index ? ' active' : ''}`} aria-current={activeTab === index ? 'page' : null} href='#' onClick={e => load(index, e)}>
22
23
  {tab}
23
24
  </a>
24
25
  </li>
@@ -2,9 +2,7 @@ import DataTableStandAlone from '@cdc/core/components/DataTable/DataTableStandAl
2
2
  import React, { MouseEventHandler, useContext, useMemo } from 'react'
3
3
  import Toggle from './Toggle'
4
4
  import _ from 'lodash'
5
- import { DashboardConfig } from '../types/DashboardConfig'
6
5
  import { ConfigRow } from '../types/ConfigRow'
7
- import DataTransform from '@cdc/core/helpers/DataTransform'
8
6
  import CdcMap from '@cdc/map'
9
7
  import CdcChart from '@cdc/chart'
10
8
  import CdcDataBite from '@cdc/data-bite'
@@ -16,6 +14,7 @@ import { FilterBehavior } from './Header/Header'
16
14
  import { DashboardContext } from '../DashboardContext'
17
15
  import { ViewPort } from '@cdc/core/types/ViewPort'
18
16
  import { getVizConfig } from '../helpers/getVizConfig'
17
+ import { TableConfig } from '@cdc/core/components/DataTable/types/TableConfig'
19
18
 
20
19
  type VizRowProps = {
21
20
  filteredDataOverride?: Object[]
@@ -134,12 +133,12 @@ const VisualizationRow: React.FC<VizRowProps> = ({ filteredDataOverride, row, ro
134
133
  <CdcMarkupInclude
135
134
  key={col.widget}
136
135
  config={visualizationConfig}
136
+ configUrl={undefined}
137
+ isDashboard={true}
137
138
  isEditor={false}
138
139
  setConfig={newConfig => {
139
140
  updateChildConfig(col.widget, newConfig)
140
141
  }}
141
- isDashboard={true}
142
- configUrl={undefined}
143
142
  />
144
143
  )}
145
144
  {visualizationConfig.type === 'filtered-text' && (
@@ -160,7 +159,17 @@ const VisualizationRow: React.FC<VizRowProps> = ({ filteredDataOverride, row, ro
160
159
  <GoButton autoLoad={visualizationConfig.autoLoad} />
161
160
  </React.Fragment>
162
161
  )}
163
- {visualizationConfig.type === 'table' && <DataTableStandAlone key={col.widget} visualizationKey={col.widget} config={visualizationConfig} viewport={currentViewport} />}
162
+ {visualizationConfig.type === 'table' && (
163
+ <DataTableStandAlone
164
+ key={col.widget}
165
+ updateConfig={newConfig => {
166
+ updateChildConfig(col.widget, newConfig)
167
+ }}
168
+ visualizationKey={col.widget}
169
+ config={visualizationConfig as TableConfig}
170
+ viewport={currentViewport}
171
+ />
172
+ )}
164
173
  </div>
165
174
  </React.Fragment>
166
175
  )
@@ -7,6 +7,8 @@ import { Table } from '@cdc/core/types/Table'
7
7
  const addVisualization = (type, subType) => {
8
8
  const modalWillOpen = type !== 'markup-include'
9
9
  const newVisualizationConfig: Partial<Visualization> = {
10
+ filters: [],
11
+ filterBehavior: 'Filter Change',
10
12
  newViz: type !== 'table',
11
13
  openModal: modalWillOpen,
12
14
  uid: type + Date.now(),
@@ -21,15 +23,36 @@ const addVisualization = (type, subType) => {
21
23
  newVisualizationConfig.general = {}
22
24
  newVisualizationConfig.general.geoType = subType
23
25
  break
24
- case 'data-bite' || 'waffle-chart' || 'markup-include' || 'filtered-text':
26
+ case 'data-bite' || 'waffle-chart' || 'filtered-text':
25
27
  newVisualizationConfig.visualizationType = type
26
28
  break
27
29
  case 'table':
28
- const tableConfig: Table = { label: 'Data Table', show: true, showDownloadUrl: false, showVertical: true, expanded: true }
30
+ const tableConfig: Table = { label: 'Data Table', show: true, showDownloadUrl: false, showVertical: true, expanded: true, collapsible: true }
29
31
  newVisualizationConfig.table = tableConfig
30
32
  newVisualizationConfig.columns = {}
31
33
  newVisualizationConfig.dataFormat = {}
32
34
  newVisualizationConfig.visualizationType = type
35
+ break
36
+ case 'markup-include':
37
+ newVisualizationConfig.contentEditor = {
38
+ inlineHTML: '<h2>Inline HTML</h2>',
39
+ markupVariables: [],
40
+ showHeader: true,
41
+ srcUrl: '#example',
42
+ title: 'Markup Include',
43
+ useInlineHTML: true
44
+ }
45
+ newVisualizationConfig.theme = 'theme-blue'
46
+ newVisualizationConfig.visual = {
47
+ border: false,
48
+ accent: false,
49
+ background: false,
50
+ hideBackgroundColor: false,
51
+ borderColorTheme: false
52
+ }
53
+ newVisualizationConfig.showEditorPanel = true
54
+ newVisualizationConfig.visualizationType = type
55
+
33
56
  break
34
57
  default:
35
58
  newVisualizationConfig.visualizationType = type
@@ -65,7 +88,7 @@ const VisualizationsPanel = ({ loadConfig, config }) => (
65
88
  <Widget addVisualization={() => addVisualization('table', '')} type='table' />
66
89
  </div>
67
90
  <span className='subheading-3'>Advanced</span>
68
- <AdvancedEditor loadConfig={loadConfig} state={config} convertStateToConfig={undefined} />
91
+ <AdvancedEditor loadConfig={loadConfig} state={config} convertStateToConfig={() => undefined} />
69
92
  </div>
70
93
  )
71
94
 
@@ -168,7 +168,7 @@ const Widget = ({ data, addVisualization, type }: WidgetProps) => {
168
168
 
169
169
  let isConfigurationReady = false
170
170
  const dataConfiguredForRow = !!rows[data?.rowIdx]?.dataKey
171
- if (dataConfiguredForRow || ['markup-include', 'filter-dropdowns'].includes(type)) {
171
+ if (dataConfiguredForRow || ['filter-dropdowns', 'markup-include'].includes(type)) {
172
172
  isConfigurationReady = true
173
173
  } else {
174
174
  if (data?.formattedData) {
@@ -182,7 +182,7 @@ const Widget = ({ data, addVisualization, type }: WidgetProps) => {
182
182
  }
183
183
  }
184
184
 
185
- const needsDataConfiguration = !dataConfiguredForRow && type !== 'markup-include'
185
+ const needsDataConfiguration = !dataConfiguredForRow
186
186
 
187
187
  return (
188
188
  <>
@@ -23,21 +23,19 @@ function getMaxTierAndSetFilterTiers(filters: SharedFilter[]): number {
23
23
  }
24
24
 
25
25
  function filter(data, filters, condition) {
26
- return data
27
- ? data.filter(row => {
28
- const found = filters.find(filter => {
29
- if (filter.pivot) return false
30
- const currentValue = row[filter.columnName]
31
- const selectedValue = filter.queuedActive || filter.active
32
- const isNotTheSelectedValue = selectedValue && currentValue != selectedValue
33
- const isFirstOccurrenceOfTier = filter.tier === condition
34
- if (filter.type !== 'urlfilter' && isFirstOccurrenceOfTier && isNotTheSelectedValue) {
35
- return true
36
- }
37
- })
38
- return !found
39
- })
40
- : []
26
+ return data ? data.filter(row => {
27
+ const found = filters.find(filter => {
28
+ if (filter.pivot) return false
29
+ const currentValue = row[filter.columnName]
30
+ const selectedValue = filter.queuedActive || filter.active
31
+ const isNotTheSelectedValue = selectedValue && currentValue != selectedValue
32
+ const isFirstOccurrenceOfTier = filter.tier === condition
33
+ if (filter.type !== 'urlfilter' && isFirstOccurrenceOfTier && isNotTheSelectedValue) {
34
+ return true
35
+ }
36
+ })
37
+ return !found
38
+ }) : []
41
39
  }
42
40
 
43
41
  function setFilterValuesAndActiveFilter(filters: SharedFilter[], filteredData: Object[], i: number) {
@@ -68,7 +66,7 @@ const pivotData = (data, pivotFilter: SharedFilter) => {
68
66
  const row = newData[index] || {}
69
67
  if (!inactive.includes(key)) row[key] = val[valueColumn]
70
68
  const toAdd = _.omit(val, [pivotColumn, valueColumn, ...inactive])
71
- newData[index] = { ...row, ...toAdd }
69
+ newData[index] = { ...toAdd, ...row }
72
70
  })
73
71
  }
74
72
  return newData
@@ -84,7 +82,7 @@ export const filterData = (filters: SharedFilter[], _data: Object[]): Object[] =
84
82
 
85
83
  const filteredData = filter(_data, filters, i + 1)
86
84
 
87
- setFilterValuesAndActiveFilter(_.cloneDeep(filters), filteredData, i)
85
+ setFilterValuesAndActiveFilter(filters, filteredData, i)
88
86
 
89
87
  if (lastIteration) {
90
88
  const pivotFilter = filters.find(filter => filter.pivot)
@@ -1,14 +1,10 @@
1
1
  import type { DashboardConfig as Config } from '../types/DashboardConfig'
2
2
  import { type Action } from '@cdc/core/types/Action'
3
3
  import { Tab } from '../types/Tab'
4
- <<<<<<< HEAD
5
4
  import { ConfigureData } from '@cdc/core/types/ConfigureData'
6
5
  import { ConfigRow } from '../types/ConfigRow'
7
- =======
8
- import { SharedFilter } from '../types/SharedFilter'
9
- >>>>>>> 35436844 (fixed api dropdowns)
10
6
 
11
- type SET_CONFIG = Action<'SET_CONFIG', Partial<Config>>
7
+ type SET_CONFIG = Action<'SET_CONFIG', Config>
12
8
  type UPDATE_CONFIG = Action<'UPDATE_CONFIG', [Config, Object?]>
13
9
  type SET_DATA = Action<'SET_DATA', Object>
14
10
  type SET_LOADING = Action<'SET_LOADING', boolean>
@@ -23,12 +19,8 @@ type ADD_NEW_DASHBOARD = Action<'ADD_NEW_DASHBOARD', undefined>
23
19
  type SAVE_CURRENT_CHANGES = Action<'SAVE_CURRENT_CHANGES', undefined>
24
20
  type SWITCH_CONFIG = Action<'SWITCH_CONFIG', number>
25
21
  type TOGGLE_ROW = Action<'TOGGLE_ROW', { rowIndex: number; colIndex: number }>
26
- <<<<<<< HEAD
27
22
  type UPDATE_VISUALIZATION = Action<'UPDATE_VISUALIZATION', { vizKey: string; configureData: Partial<ConfigureData> }>
28
23
  type UPDATE_ROW = Action<'UPDATE_ROW', { rowIndex: number; rowData: Partial<ConfigRow> }>
29
- =======
30
- type SET_SHARED_FILTERS = Action<'SET_SHARED_FILTERS', SharedFilter[]>
31
- >>>>>>> 35436844 (fixed api dropdowns)
32
24
 
33
25
  type DashboardActions =
34
26
  | ADD_NEW_DASHBOARD
@@ -42,7 +34,6 @@ type DashboardActions =
42
34
  | SET_LOADING
43
35
  | SET_PREVIEW
44
36
  | SET_FILTERED_DATA
45
- | SET_SHARED_FILTERS
46
37
  | SET_TAB_SELECTED
47
38
  | SWITCH_CONFIG
48
39
  | INITIALIZE_MULTIDASHBOARDS
@@ -1,19 +1,26 @@
1
1
  import _ from 'lodash'
2
2
  import { getUpdateConfig } from '../helpers/getUpdateConfig'
3
- import { MultiDashboardConfig } from '../types/MultiDashboard'
3
+ import { MultiDashboard, MultiDashboardConfig } from '../types/MultiDashboard'
4
4
  import DashboardActions from './dashboard.actions'
5
5
  import { devToolsWrapper } from '@cdc/core/helpers/withDevTools'
6
6
  import { Tab } from '../types/Tab'
7
+ import { DashboardConfig } from '../types/DashboardConfig'
8
+ import { ConfigRow } from '../types/ConfigRow'
7
9
 
8
- const createBlankDashboard = () => ({
9
- dashboard: {
10
- theme: 'theme-blue'
11
- },
12
- rows: [[{ width: 12 }, {}, {}]],
10
+ type BlankMultiConfig = {
11
+ dashboard: Partial<DashboardConfig>
12
+ rows: Partial<ConfigRow>[]
13
+ visualizations: Record<string, Object>
14
+ table: Object
15
+ }
16
+
17
+ const createBlankDashboard: () => BlankMultiConfig = () => ({
18
+ dashboard: {},
19
+ rows: [{ columns: [{ width: 12 }] }],
13
20
  visualizations: {},
14
21
  table: {
15
22
  label: 'Data Table',
16
- show: true,
23
+ show: false,
17
24
  showDownloadUrl: false,
18
25
  showVertical: true
19
26
  }
@@ -41,7 +48,7 @@ const reducer = (state: DashboardState, action: DashboardActions): DashboardStat
41
48
  return { ...state, config, filteredData }
42
49
  }
43
50
  case 'SET_CONFIG': {
44
- return { ...state, config: { ...state.config, ...action.payload } }
51
+ return { ...state, config: action.payload }
45
52
  }
46
53
  case 'SET_DATA': {
47
54
  return { ...state, data: action.payload }
@@ -92,11 +99,6 @@ const reducer = (state: DashboardState, action: DashboardActions): DashboardStat
92
99
  newMultiDashboards[saveSlot] = { ...toSave, label }
93
100
  return applyMultiDashboards(state, newMultiDashboards)
94
101
  }
95
- case 'SET_SHARED_FILTERS': {
96
- const newSharedFilters = action.payload
97
- const newDashboardConfig = { ...state.config.dashboard, sharedFilters: newSharedFilters }
98
- return { ...state, config: { ...state.config, dashboard: newDashboardConfig } }
99
- }
100
102
  case 'INITIALIZE_MULTIDASHBOARDS': {
101
103
  const label = 'New Dashboard 1'
102
104
  const toSave = _.pick(state.config, ['dashboard', 'visualizations', 'rows'])
@@ -1,4 +1,5 @@
1
- export type APIFilter = Record<'apiEndpoint' | 'valueSelector' | 'textSelector', string> & {
2
- autoLoad?: boolean
3
- defaultValue?: string
4
- }
1
+ export type APIFilter = Record<'apiEndpoint'|'valueSelector'|'textSelector', string> & {
2
+ heirarchyLookup?: string
3
+ autoLoad?: boolean
4
+ defaultValue?: string
5
+ }
@@ -1,52 +0,0 @@
1
- import React from 'react'
2
- import { Accordion } from 'react-accessible-accordion'
3
- import Header from '../Header'
4
- import { Visualization } from '@cdc/core/types/Visualization'
5
- import { ViewPort } from '@cdc/core/types/ViewPort'
6
- import './editor-wrapper.style.css'
7
-
8
- type StandAloneComponentProps = {
9
- visualizationKey: string
10
- config: Visualization
11
- isEditor: boolean
12
- setConfig: Function
13
- isDashboard: boolean
14
- configUrl: string
15
- setEditing: Function
16
- hostname: string
17
- viewport?: ViewPort
18
- }
19
-
20
- type EditorProps = {
21
- component: React.JSXElementConstructor<StandAloneComponentProps>
22
- type: string
23
- visualizationKey: string
24
- visualizationConfig: Visualization
25
- updateConfig: Function
26
- viewport?: ViewPort
27
- }
28
-
29
- const EditorWrapper: React.FC<React.PropsWithChildren<EditorProps>> = ({ children, visualizationKey, visualizationConfig, type, component: Component, updateConfig, viewport }) => {
30
- const [displayPanel, setDisplayPanel] = React.useState(true)
31
- return (
32
- <>
33
- <Header visualizationKey={visualizationKey} subEditor={type} />
34
- <div className='editor-wrapper'>
35
- <button className={`editor-toggle ${displayPanel ? '' : 'collapsed'}`} title={displayPanel ? `Collapse Editor` : `Expand Editor`} onClick={() => setDisplayPanel(!displayPanel)} />
36
- <section className={`${displayPanel ? '' : 'hidden'} editor-panel cove`}>
37
- <div aria-level={2} role='heading' className='heading-2'>
38
- Configure {type}
39
- </div>
40
- <form>
41
- <Accordion allowZeroExpanded={true}>{children}</Accordion>
42
- </form>
43
- </section>
44
- <div className='preview-wrapper'>
45
- <Component visualizationKey={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true} configUrl={undefined} setEditing={undefined} hostname={undefined} viewport={viewport} />
46
- </div>
47
- </div>
48
- </>
49
- )
50
- }
51
-
52
- export default EditorWrapper
@@ -1,13 +0,0 @@
1
- .editor-wrapper {
2
- --editorPanelWidth: 350px;
3
- position: relative;
4
- .editor-panel {
5
- :is(form) {
6
- border-right: var(--lightGray) 1px solid;
7
- flex-grow: 1;
8
- }
9
- }
10
- .preview-wrapper {
11
- padding-left: var(--editorPanelWidth);
12
- }
13
- }