@cdc/core 4.24.5 → 4.24.9-1

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.
Files changed (109) hide show
  1. package/assets/icon-gear-multi.svg +23 -0
  2. package/components/AdvancedEditor/AdvancedEditor.tsx +93 -0
  3. package/components/AdvancedEditor/advanced-editor-styles.css +3 -0
  4. package/components/AdvancedEditor/index.ts +1 -0
  5. package/components/Alert/components/Alert.styles.css +15 -0
  6. package/components/Alert/components/Alert.tsx +39 -0
  7. package/components/Alert/index.tsx +3 -0
  8. package/components/DataTable/DataTable.tsx +127 -32
  9. package/components/DataTable/DataTableStandAlone.tsx +4 -25
  10. package/components/DataTable/components/DataTableEditorPanel.tsx +4 -4
  11. package/components/DataTable/components/ExpandCollapse.tsx +1 -1
  12. package/components/DataTable/helpers/chartCellMatrix.tsx +6 -12
  13. package/components/DataTable/helpers/getChartCellValue.ts +9 -5
  14. package/components/DataTable/helpers/getDataSeriesColumns.ts +10 -7
  15. package/components/DataTable/helpers/getRowType.ts +6 -0
  16. package/components/DataTable/helpers/mapCellMatrix.tsx +3 -3
  17. package/components/DataTable/types/TableConfig.ts +2 -1
  18. package/components/EditorPanel/ColumnsEditor.tsx +3 -30
  19. package/components/EditorPanel/DataTableEditor.tsx +66 -22
  20. package/components/EditorPanel/FieldSetWrapper.tsx +51 -0
  21. package/components/EditorPanel/FootnotesEditor.tsx +77 -0
  22. package/components/EditorPanel/Inputs.tsx +13 -4
  23. package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +268 -0
  24. package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +306 -0
  25. package/components/EditorPanel/VizFilterEditor/components/FilterOrder.tsx +40 -0
  26. package/components/EditorPanel/VizFilterEditor/index.ts +1 -0
  27. package/components/EditorWrapper/EditorWrapper.tsx +3 -4
  28. package/components/EditorWrapper/index.ts +1 -0
  29. package/components/Filters.tsx +520 -0
  30. package/components/Footnotes/Footnotes.tsx +25 -0
  31. package/components/Footnotes/FootnotesStandAlone.tsx +45 -0
  32. package/components/Footnotes/footnotes.css +5 -0
  33. package/components/Footnotes/index.ts +1 -0
  34. package/components/Layout/components/Responsive.tsx +14 -4
  35. package/components/Layout/components/Sidebar/components/Sidebar.tsx +14 -5
  36. package/components/Layout/components/Sidebar/components/sidebar.styles.scss +23 -20
  37. package/components/Layout/components/Visualization/index.tsx +19 -6
  38. package/components/Layout/components/Visualization/visualizations.scss +32 -26
  39. package/components/Layout/styles/editor.scss +0 -8
  40. package/components/Legend/Legend.Gradient.tsx +133 -0
  41. package/components/LegendShape.tsx +28 -0
  42. package/components/MultiSelect/MultiSelect.tsx +41 -11
  43. package/components/MultiSelect/multiselect.styles.css +0 -3
  44. package/components/NestedDropdown/NestedDropdown.tsx +47 -52
  45. package/components/NestedDropdown/nesteddropdown.styles.css +19 -25
  46. package/components/Table/Table.tsx +8 -5
  47. package/components/Table/components/Cell.tsx +2 -2
  48. package/components/Table/components/Row.tsx +25 -7
  49. package/components/_stories/Footnotes.stories.tsx +17 -0
  50. package/components/_stories/Layout.Debug.stories.tsx +91 -0
  51. package/components/_stories/_mocks/bar-chart-suppressed.json +474 -0
  52. package/components/_stories/styles.scss +14 -1
  53. package/components/createBarElement.jsx +4 -4
  54. package/components/inputs/InputSelect.tsx +17 -6
  55. package/components/ui/Icon.tsx +22 -16
  56. package/components/ui/Title/Title.scss +0 -8
  57. package/helpers/DataTransform.ts +2 -2
  58. package/helpers/addValuesToFilters.ts +135 -0
  59. package/helpers/cove/accessibility.ts +17 -4
  60. package/helpers/cove/fontSettings.ts +2 -0
  61. package/helpers/coveUpdateWorker.ts +30 -9
  62. package/helpers/filterVizData.ts +49 -0
  63. package/helpers/formatConfigBeforeSave.ts +110 -0
  64. package/helpers/gatherQueryParams.ts +24 -7
  65. package/helpers/getGradientLegendWidth.ts +15 -0
  66. package/helpers/getTextWidth.ts +18 -0
  67. package/helpers/lineChartHelpers.js +2 -1
  68. package/helpers/pivotData.ts +18 -0
  69. package/helpers/queryStringUtils.ts +29 -0
  70. package/helpers/scaling.ts +7 -0
  71. package/helpers/tests/addValuesToFilters.test.ts +55 -0
  72. package/helpers/tests/filterVizData.test.ts +31 -0
  73. package/helpers/tests/gatherQueryParams.test.ts +22 -0
  74. package/helpers/tests/invertValue.test.ts +35 -0
  75. package/helpers/tests/updateFieldFactory.test.ts +1 -0
  76. package/helpers/updateFieldFactory.ts +1 -1
  77. package/helpers/updatePaletteNames.ts +19 -0
  78. package/helpers/{useDataVizClasses.js → useDataVizClasses.ts} +3 -2
  79. package/helpers/ver/4.24.5.ts +3 -3
  80. package/helpers/ver/4.24.7.ts +123 -0
  81. package/helpers/ver/4.24.9.ts +63 -0
  82. package/helpers/ver/tests/4.24.9.test.ts +22 -0
  83. package/helpers/ver/versionNeedsUpdate.ts +9 -0
  84. package/package.json +6 -4
  85. package/styles/_button-section.scss +7 -2
  86. package/styles/_data-table.scss +0 -1
  87. package/styles/_global.scss +6 -2
  88. package/styles/base.scss +4 -0
  89. package/styles/filters.scss +4 -0
  90. package/styles/v2/themes/_color-definitions.scss +1 -0
  91. package/types/Annotation.ts +46 -0
  92. package/types/Axis.ts +3 -2
  93. package/types/ConfigureData.ts +1 -1
  94. package/types/Dimensions.ts +1 -0
  95. package/types/Footnotes.ts +17 -0
  96. package/types/General.ts +5 -0
  97. package/types/Runtime.ts +2 -7
  98. package/types/Table.ts +6 -0
  99. package/types/Visualization.ts +31 -9
  100. package/types/VizFilter.ts +39 -7
  101. package/components/AdvancedEditor.jsx +0 -74
  102. package/components/EditorPanel/VizFilterEditor.tsx +0 -234
  103. package/components/Filters.jsx +0 -461
  104. package/components/LegendCircle.jsx +0 -17
  105. package/helpers/queryStringUtils.js +0 -26
  106. package/helpers/updatePaletteNames.js +0 -16
  107. package/types/BaseVisualizationType.ts +0 -1
  108. /package/components/{Waiting.jsx → Waiting.tsx} +0 -0
  109. /package/helpers/ver/{4.23.4.ts → 4.24.4.ts} +0 -0
@@ -1,13 +1,45 @@
1
- export type VizFilter = {
2
- active: string
1
+ export type OrderBy = 'asc' | 'desc' | 'cust'
2
+
3
+ export type FilterBase = {
3
4
  columnName: string
4
- filterStyle: 'tab' | 'pill' | 'tab bar' | 'dropdown'
5
+ values: string[]
6
+ showDropdown: boolean
7
+ id: number
8
+ parents: number[]
9
+ }
10
+
11
+ export type VizFilterStyle =
12
+ | 'tab'
13
+ | 'pill'
14
+ | 'tab bar'
15
+ | 'dropdown'
16
+ | 'dropdown bar'
17
+ | 'multi-select'
18
+ | 'nested-dropdown'
19
+ export type GeneralFilter = FilterBase & {
20
+ active: string
21
+ queuedActive: string
22
+ filterStyle: VizFilterStyle
5
23
  label: string
6
- order: 'asc' | 'desc' | 'cust'
7
- orderedValues?: string[]
24
+ order: OrderBy
25
+ orderedValues?: string[] // should only exist if the order is 'cust'
8
26
  queryParameter: string
9
27
  setByQueryParameter: string
10
- showDropdown: boolean
28
+ subGrouping: SubGrouping
11
29
  type: 'url'
12
- values: string[]
13
30
  }
31
+
32
+ export type MultiSelectFilter = {
33
+ active: string[]
34
+ selectLimit: number
35
+ } & Omit<GeneralFilter, 'active'>
36
+
37
+ export type SubGrouping = {
38
+ active: string
39
+ columnName: string
40
+ setByQueryParameter: string
41
+ order?: OrderBy
42
+ valuesLookup: Record<string, { orderedValues?: string[]; values: string[] }>
43
+ }
44
+
45
+ export type VizFilter = GeneralFilter | MultiSelectFilter
@@ -1,74 +0,0 @@
1
- import React, { useState, useEffect } from 'react'
2
- import MapIcon from '../assets/map-folded.svg'
3
- import ChartIcon from '../assets/icon-chart-bar.svg'
4
- import MarkupIncludeIcon from '../assets/icon-code.svg'
5
-
6
- export const AdvancedEditor = ({ loadConfig, state, convertStateToConfig }) => {
7
- const [advancedToggle, setAdvancedToggle] = useState(false)
8
- const [configTextboxValue, setConfigTextbox] = useState({})
9
-
10
- useEffect(() => {
11
- let parsedData = state
12
- if (state.type !== 'dashboard') {
13
- parsedData = convertStateToConfig()
14
- } else {
15
- parsedData = JSON.parse(JSON.stringify(parsedData))
16
- }
17
- const formattedData = JSON.stringify(parsedData, undefined, 2)
18
-
19
- setConfigTextbox(formattedData)
20
- }, [state])
21
-
22
- const typeLookup = {
23
- chart: ['Charts', 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/bar-chart.html', <ChartIcon />],
24
- dashboard: ['Dashboard', 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/bar-chart.html', <ChartIcon />],
25
- map: ['Maps', 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/data-map.html', <MapIcon />],
26
- 'markup-include': ['Markup Include', 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/Markup-Include.html', <MarkupIncludeIcon />]
27
- }
28
-
29
- if (!state.type) return <></>
30
- return (
31
- <>
32
- <a href={typeLookup[state.type][1]} target='_blank' rel='noopener noreferrer' className='guidance-link'>
33
- {typeLookup[state.type][2]}
34
- <div>
35
- <span className='heading-3'>Get Help with {typeLookup[state.type][0]}</span>
36
- <p>Examples and documentation</p>
37
- </div>
38
- </a>
39
- <div className='advanced'>
40
- <span className='advanced-toggle-link' onClick={() => setAdvancedToggle(!advancedToggle)}>
41
- <span>{advancedToggle ? `— ` : `+ `}</span>Advanced Options
42
- </span>
43
- {advancedToggle && (
44
- <React.Fragment>
45
- <section className='error-box py-2 px-3 my-2'>
46
- <div>
47
- <strong className='pt-1'>Warning</strong>
48
- <p>This can cause serious errors in your visualization.</p>
49
- </div>
50
- </section>
51
- <p className='pb-2'>
52
- This tool displays the actual <acronym title='JavaScript Object Notation'>JSON</acronym> configuration that is generated by this editor and allows you to edit properties directly and apply them.
53
- </p>
54
- <button
55
- className='btn'
56
- onClick={() => {
57
- navigator.clipboard.writeText(configTextboxValue)
58
- alert('Copied!')
59
- }}
60
- >
61
- Copy to Clipboard
62
- </button>
63
- <textarea value={configTextboxValue} onChange={event => setConfigTextbox(event.target.value)} />
64
- <button className='btn full-width' onClick={() => loadConfig(JSON.parse(configTextboxValue))}>
65
- Apply
66
- </button>
67
- </React.Fragment>
68
- )}
69
- </div>
70
- </>
71
- )
72
- }
73
-
74
- export default AdvancedEditor
@@ -1,234 +0,0 @@
1
- import { AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
2
- import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd'
3
- import { Select } from './Inputs'
4
- import Tooltip from '../ui/Tooltip'
5
- import Icon from '../ui/Icon'
6
- import { Visualization } from '../../types/Visualization'
7
- import { UpdateFieldFunc } from '../../types/UpdateFieldFunc'
8
- import _ from 'lodash'
9
- import { VizFilter } from '../../types/VizFilter'
10
- import { filterStyleOptions, filterOrderOptions, handleSorting } from '../Filters'
11
-
12
- type VizFilterProps = {
13
- config: Visualization
14
- updateField: UpdateFieldFunc<string | VizFilter[] | VizFilter>
15
- rawData: Object[]
16
- }
17
-
18
- const VizFilterEditor: React.FC<VizFilterProps> = ({ config, updateField, rawData }) => {
19
- const getFilters = () => {
20
- return _.uniq(_.flatten(rawData.map(row => Object.keys(row))))
21
- }
22
- const removeFilter = index => {
23
- let filters = _.cloneDeep(config.filters)
24
-
25
- filters.splice(index, 1)
26
-
27
- updateField(null, null, 'filters', filters)
28
- }
29
-
30
- const updateFilterProp = (prop, index, value) => {
31
- updateField('filters', index, prop, value)
32
- }
33
-
34
- const handleNameChange = (filterIndex, columnName) => {
35
- const values = _.uniq(rawData.map(row => row[columnName]))
36
- const copiedFilter = { ..._.cloneDeep(config.filters[filterIndex]), columnName, values }
37
- handleSorting(copiedFilter) // sorts dropdown values in place
38
- copiedFilter.active = copiedFilter.values[0]
39
- const newFilters = config.filters.map((filter, index) => {
40
- if (index === filterIndex) return copiedFilter
41
- return filter
42
- })
43
- updateField(null, null, 'filters', newFilters)
44
- }
45
-
46
- const addNewFilter = () => {
47
- const filters = config.filters ? [...config.filters] : []
48
- const newVizFilter: VizFilter = { values: [], filterStyle: 'dropdown' } as VizFilter
49
- filters.push(newVizFilter)
50
- updateField(null, null, 'filters', filters)
51
- }
52
-
53
- const handleFilterOrder = (idx1, idx2, filterIndex, filter) => {
54
- // Create a shallow copy of the filter values array & update position of the values
55
- const updatedValues = [...filter.values]
56
- const [movedItem] = updatedValues.splice(idx1, 1)
57
- updatedValues.splice(idx2, 0, movedItem)
58
-
59
- const filtersCopy = _.cloneDeep(config.filters)
60
- const filterItem = { ...filtersCopy[filterIndex] }
61
-
62
- // Overwrite filterItem.values since thats what we map through in the editor panel
63
- filterItem.values = updatedValues
64
- filterItem.orderedValues = updatedValues
65
- filterItem.active = updatedValues[0]
66
- filterItem.order = 'cust'
67
-
68
- // Update the filters
69
- filtersCopy[filterIndex] = filterItem
70
-
71
- updateField(null, null, 'filters', filtersCopy)
72
- }
73
-
74
- return (
75
- <>
76
- {config.filters && (
77
- <>
78
- <Select
79
- value={config.filterBehavior}
80
- fieldName='filterBehavior'
81
- label='Filter Behavior'
82
- updateField={updateField}
83
- options={['Apply Button', 'Filter Change']}
84
- tooltip={
85
- <Tooltip style={{ textTransform: 'none' }}>
86
- <Tooltip.Target>
87
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
88
- </Tooltip.Target>
89
- <Tooltip.Content>
90
- <p>The Apply Button option changes the visualization when the user clicks "apply". The Filter Change option immediately changes the visualization when the selection is changed.</p>
91
- </Tooltip.Content>
92
- </Tooltip>
93
- }
94
- />
95
- <br />
96
- </>
97
- )}
98
- {config.filters && (
99
- <ul className='filters-list'>
100
- {/* Whether filters should apply onChange or Apply Button */}
101
-
102
- {config.filters.map((filter, index) => {
103
- if (filter.type === 'url') return <></>
104
-
105
- return (
106
- <fieldset className='edit-block' key={index}>
107
- <button
108
- type='button'
109
- className='remove-column'
110
- onClick={() => {
111
- removeFilter(index)
112
- }}
113
- >
114
- Remove
115
- </button>
116
- <label>
117
- <span className='edit-label column-heading'>Filter</span>
118
- <select
119
- value={filter.columnName}
120
- onChange={e => {
121
- handleNameChange(index, e.target.value)
122
- }}
123
- >
124
- <option value=''>- Select Option -</option>
125
- {getFilters().map((dataKey, index) => (
126
- <option value={dataKey} key={index}>
127
- {dataKey}
128
- </option>
129
- ))}
130
- </select>
131
- </label>
132
-
133
- <label>
134
- <span className='edit-showDropdown column-heading'>Show Filter Input</span>
135
- <input
136
- type='checkbox'
137
- checked={filter.showDropdown === undefined ? true : filter.showDropdown}
138
- onChange={e => {
139
- updateFilterProp('showDropdown', index, e.target.checked)
140
- }}
141
- />
142
- </label>
143
-
144
- <label>
145
- <span className='edit-label column-heading'>Filter Style</span>
146
-
147
- <select
148
- value={filter.filterStyle}
149
- onChange={e => {
150
- updateFilterProp('filterStyle', index, e.target.value)
151
- }}
152
- >
153
- {filterStyleOptions.map((item, index) => {
154
- return (
155
- <option key={`filter-style-${index}`} value={item}>
156
- {item}
157
- </option>
158
- )
159
- })}
160
- </select>
161
- </label>
162
- <label>
163
- <span className='edit-label column-heading'>Label</span>
164
- <input
165
- type='text'
166
- value={filter.label}
167
- onChange={e => {
168
- updateFilterProp('label', index, e.target.value)
169
- }}
170
- />
171
- </label>
172
-
173
- <label>
174
- <span className='edit-label column-heading'>Default Value Set By Query String Parameter</span>
175
- <input
176
- type='text'
177
- value={filter.setByQueryParameter}
178
- onChange={e => {
179
- updateFilterProp('setByQueryParameter', index, e.target.value)
180
- }}
181
- />
182
- </label>
183
-
184
- <label>
185
- <span className='edit-filterOrder column-heading'>Filter Order</span>
186
- <select value={filter.order ? filter.order : 'asc'} onChange={e => updateFilterProp('order', index, e.target.value)}>
187
- {filterOrderOptions.map((option, index) => {
188
- return (
189
- <option value={option.value} key={`filter-${index}`}>
190
- {option.label}
191
- </option>
192
- )
193
- })}
194
- </select>
195
-
196
- {filter.order === 'cust' && (
197
- <DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, config.filters[index])}>
198
- <Droppable droppableId='filter_order'>
199
- {provided => (
200
- <ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
201
- {config.filters[index]?.values.map((value, index) => {
202
- return (
203
- <Draggable key={value} draggableId={`draggableFilter-${value}`} index={index}>
204
- {(provided, snapshot) => (
205
- <li>
206
- <div className={snapshot.isDragging ? 'currently-dragging' : ''} style={provided.draggableProps.style} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
207
- {value}
208
- </div>
209
- </li>
210
- )}
211
- </Draggable>
212
- )
213
- })}
214
- {provided.placeholder}
215
- </ul>
216
- )}
217
- </Droppable>
218
- </DragDropContext>
219
- )}
220
- </label>
221
- </fieldset>
222
- )
223
- })}
224
- </ul>
225
- )}
226
- {!config.filters && <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
227
- <button type='button' onClick={addNewFilter} className='btn btn-primary full-width'>
228
- Add Filter
229
- </button>
230
- </>
231
- )
232
- }
233
-
234
- export default VizFilterEditor