@cdc/dashboard 4.22.10 → 4.22.11
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/README.md +36 -36
- package/dist/cdcdashboard.js +6 -6
- package/examples/default-data.json +367 -367
- package/examples/default-filter-control.json +176 -174
- package/examples/default-multi-dataset.json +505 -497
- package/examples/default.json +161 -155
- package/examples/private/chart-issue.json +3462 -3466
- package/examples/private/no-issue.json +3462 -3466
- package/examples/private/totals-two.json +103 -103
- package/examples/private/totals.json +102 -102
- package/examples/temp-example-data.json +1 -1
- package/examples/test-example.json +163 -1
- package/package.json +7 -7
- package/src/CdcDashboard.js +200 -124
- package/src/CdcDashboard.jsx +271 -277
- package/src/ConfigContext.js +3 -3
- package/src/components/Column.jsx +10 -9
- package/src/components/DataTable.tsx +91 -111
- package/src/components/EditorPanel.js +184 -246
- package/src/components/Grid.jsx +8 -4
- package/src/components/Header.jsx +209 -118
- package/src/components/Row.js +30 -29
- package/src/components/Row.jsx +36 -52
- package/src/components/Widget.js +68 -61
- package/src/components/Widget.jsx +85 -62
- package/src/data/initial-state.js +3 -9
- package/src/index.html +24 -26
- package/src/index.js +12 -12
- package/src/scss/editor-panel.scss +494 -489
- package/src/scss/grid.scss +20 -19
- package/src/scss/main.scss +16 -15
- package/src/scss/variables.scss +1 -1
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
import React, { useState, useEffect, memo, useContext } from 'react'
|
|
2
2
|
import ReactTooltip from 'react-tooltip'
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import { useDebounce } from 'use-debounce';
|
|
12
|
-
|
|
13
|
-
import Context from '../context';
|
|
14
|
-
|
|
15
|
-
import ErrorBoundary from '@cdc/core/components/ErrorBoundary';
|
|
16
|
-
import QuestionIcon from '@cdc/core/assets/question-circle.svg';
|
|
4
|
+
import { Accordion, AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
|
|
5
|
+
import { useDebounce } from 'use-debounce'
|
|
6
|
+
|
|
7
|
+
import Context from '../context'
|
|
8
|
+
|
|
9
|
+
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
10
|
+
import QuestionIcon from '@cdc/core/assets/question-circle.svg'
|
|
17
11
|
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
18
12
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
19
13
|
|
|
20
|
-
const Helper = ({text}) => {
|
|
14
|
+
const Helper = ({ text }) => {
|
|
21
15
|
return (
|
|
22
16
|
<span className='tooltip helper' data-tip={text}>
|
|
23
17
|
<QuestionIcon />
|
|
@@ -26,84 +20,108 @@ const Helper = ({text}) => {
|
|
|
26
20
|
}
|
|
27
21
|
|
|
28
22
|
// IE11 Custom Event polyfill
|
|
29
|
-
(function () {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
evt
|
|
37
|
-
|
|
38
|
-
}
|
|
23
|
+
;(function () {
|
|
24
|
+
if (typeof window.CustomEvent === 'function') return false
|
|
25
|
+
|
|
26
|
+
function CustomEvent(event, params) {
|
|
27
|
+
params = params || { bubbles: false, cancelable: false, detail: null }
|
|
28
|
+
var evt = document.createEvent('CustomEvent')
|
|
29
|
+
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)
|
|
30
|
+
return evt
|
|
31
|
+
}
|
|
39
32
|
|
|
40
|
-
window.CustomEvent = CustomEvent
|
|
41
|
-
})()
|
|
33
|
+
window.CustomEvent = CustomEvent
|
|
34
|
+
})()
|
|
42
35
|
|
|
43
|
-
const TextField = memo(({label, section = null, subsection = null, fieldName, updateField, value: stateValue, tooltip, type =
|
|
44
|
-
const [
|
|
36
|
+
const TextField = memo(({ label, section = null, subsection = null, fieldName, updateField, value: stateValue, tooltip, type = 'input', i = null, min = null, ...attributes }) => {
|
|
37
|
+
const [value, setValue] = useState(stateValue)
|
|
45
38
|
|
|
46
|
-
const [
|
|
39
|
+
const [debouncedValue] = useDebounce(value, 500)
|
|
47
40
|
|
|
48
41
|
useEffect(() => {
|
|
49
|
-
if('string' === typeof debouncedValue && stateValue !== debouncedValue
|
|
42
|
+
if ('string' === typeof debouncedValue && stateValue !== debouncedValue) {
|
|
50
43
|
updateField(section, subsection, fieldName, debouncedValue, i)
|
|
51
44
|
}
|
|
52
45
|
}, [debouncedValue])
|
|
53
46
|
|
|
54
|
-
let name = subsection ? `${section}-${subsection}-${fieldName}` : `${section}-${subsection}-${fieldName}
|
|
47
|
+
let name = subsection ? `${section}-${subsection}-${fieldName}` : `${section}-${subsection}-${fieldName}`
|
|
55
48
|
|
|
56
|
-
const onChange =
|
|
57
|
-
if('number' !== type || min === null){
|
|
58
|
-
setValue(e.target.value)
|
|
49
|
+
const onChange = e => {
|
|
50
|
+
if ('number' !== type || min === null) {
|
|
51
|
+
setValue(e.target.value)
|
|
59
52
|
} else {
|
|
60
|
-
if(!e.target.value || min <= parseFloat(e.target.value)){
|
|
61
|
-
setValue(e.target.value)
|
|
53
|
+
if (!e.target.value || min <= parseFloat(e.target.value)) {
|
|
54
|
+
setValue(e.target.value)
|
|
62
55
|
} else {
|
|
63
|
-
setValue(min.toString())
|
|
56
|
+
setValue(min.toString())
|
|
64
57
|
}
|
|
65
58
|
}
|
|
66
|
-
}
|
|
59
|
+
}
|
|
67
60
|
|
|
68
|
-
let formElement = <input type=
|
|
61
|
+
let formElement = <input type='text' name={name} onChange={onChange} {...attributes} value={value} />
|
|
69
62
|
|
|
70
|
-
if('textarea' === type) {
|
|
71
|
-
formElement =
|
|
72
|
-
<textarea name={name} onChange={onChange} {...attributes} value={value}></textarea>
|
|
73
|
-
)
|
|
63
|
+
if ('textarea' === type) {
|
|
64
|
+
formElement = <textarea name={name} onChange={onChange} {...attributes} value={value}></textarea>
|
|
74
65
|
}
|
|
75
66
|
|
|
76
|
-
if('number' === type) {
|
|
77
|
-
formElement = <input type=
|
|
67
|
+
if ('number' === type) {
|
|
68
|
+
formElement = <input type='number' name={name} onChange={onChange} {...attributes} value={value} />
|
|
78
69
|
}
|
|
79
70
|
|
|
80
71
|
return (
|
|
81
72
|
<label>
|
|
82
|
-
<span className=
|
|
73
|
+
<span className='edit-label column-heading'>
|
|
74
|
+
{label}
|
|
75
|
+
{tooltip}
|
|
76
|
+
</span>
|
|
83
77
|
{formElement}
|
|
84
78
|
</label>
|
|
85
79
|
)
|
|
86
80
|
})
|
|
87
81
|
|
|
88
|
-
const CheckBox = memo(({label, value, fieldName, section = null, subsection = null, updateField, ...attributes}) => (
|
|
89
|
-
<label className=
|
|
90
|
-
<input
|
|
91
|
-
|
|
92
|
-
|
|
82
|
+
const CheckBox = memo(({ label, value, fieldName, section = null, subsection = null, updateField, ...attributes }) => (
|
|
83
|
+
<label className='checkbox'>
|
|
84
|
+
<input
|
|
85
|
+
type='checkbox'
|
|
86
|
+
name={fieldName}
|
|
87
|
+
checked={value}
|
|
88
|
+
onChange={() => {
|
|
89
|
+
updateField(section, subsection, fieldName, !value)
|
|
90
|
+
}}
|
|
91
|
+
{...attributes}
|
|
92
|
+
/>
|
|
93
|
+
<span className='edit-label'>{label}</span>
|
|
94
|
+
{section === 'table' && fieldName === 'show' && <Helper text=' Hiding the data table may affect accessibility. An alternate form of accessing visualization data is a 508 requirement.' />}
|
|
93
95
|
</label>
|
|
94
96
|
))
|
|
95
97
|
|
|
96
|
-
const Select = memo(({label, value, options, fieldName, section = null, subsection = null, required = false, updateField, initial: initialValue, ...attributes}) => {
|
|
97
|
-
let optionsJsx = options.map(optionName =>
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
const Select = memo(({ label, value, options, fieldName, section = null, subsection = null, required = false, updateField, initial: initialValue, ...attributes }) => {
|
|
99
|
+
let optionsJsx = options.map(optionName => (
|
|
100
|
+
<option value={optionName} key={optionName}>
|
|
101
|
+
{optionName}
|
|
102
|
+
</option>
|
|
103
|
+
))
|
|
104
|
+
|
|
105
|
+
if (initialValue) {
|
|
106
|
+
optionsJsx.unshift(
|
|
107
|
+
<option value='' key='initial'>
|
|
108
|
+
{initialValue}
|
|
109
|
+
</option>
|
|
110
|
+
)
|
|
101
111
|
}
|
|
102
112
|
|
|
103
113
|
return (
|
|
104
114
|
<label>
|
|
105
|
-
<span className=
|
|
106
|
-
<select
|
|
115
|
+
<span className='edit-label'>{label}</span>
|
|
116
|
+
<select
|
|
117
|
+
className={required && !value ? 'warning' : ''}
|
|
118
|
+
name={fieldName}
|
|
119
|
+
value={value}
|
|
120
|
+
onChange={event => {
|
|
121
|
+
updateField(section, subsection, fieldName, event.target.value)
|
|
122
|
+
}}
|
|
123
|
+
{...attributes}
|
|
124
|
+
>
|
|
107
125
|
{optionsJsx}
|
|
108
126
|
</select>
|
|
109
127
|
</label>
|
|
@@ -111,52 +129,45 @@ const Select = memo(({label, value, options, fieldName, section = null, subsecti
|
|
|
111
129
|
})
|
|
112
130
|
|
|
113
131
|
const EditorPanel = memo(() => {
|
|
114
|
-
const {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
loading,
|
|
118
|
-
rawData,
|
|
119
|
-
setParentConfig,
|
|
120
|
-
setEditing
|
|
121
|
-
} = useContext(Context);
|
|
122
|
-
|
|
123
|
-
const enforceRestrictions = (updatedConfig) => {
|
|
132
|
+
const { config, updateConfig, loading, rawData, setParentConfig, setEditing } = useContext(Context)
|
|
133
|
+
|
|
134
|
+
const enforceRestrictions = updatedConfig => {
|
|
124
135
|
// TODO
|
|
125
|
-
}
|
|
136
|
+
}
|
|
126
137
|
|
|
127
138
|
const updateField = (section, subsection, fieldName, newValue) => {
|
|
128
139
|
// Top level
|
|
129
|
-
if(
|
|
130
|
-
let dashboardConfig = config.dashboard
|
|
140
|
+
if (null === section && null === subsection) {
|
|
141
|
+
let dashboardConfig = config.dashboard
|
|
131
142
|
|
|
132
|
-
dashboardConfig[fieldName] = newValue
|
|
143
|
+
dashboardConfig[fieldName] = newValue
|
|
133
144
|
|
|
134
|
-
let updatedConfig = {...config, dashboard: dashboardConfig}
|
|
145
|
+
let updatedConfig = { ...config, dashboard: dashboardConfig }
|
|
135
146
|
|
|
136
|
-
enforceRestrictions(updatedConfig)
|
|
147
|
+
enforceRestrictions(updatedConfig)
|
|
137
148
|
|
|
138
|
-
updateConfig(updatedConfig)
|
|
149
|
+
updateConfig(updatedConfig)
|
|
139
150
|
return
|
|
140
151
|
}
|
|
141
152
|
|
|
142
|
-
const isArray = Array.isArray(config[section])
|
|
153
|
+
const isArray = Array.isArray(config[section])
|
|
143
154
|
|
|
144
|
-
let sectionValue = isArray ? [...config[section], newValue] : {...config[section], [fieldName]: newValue}
|
|
155
|
+
let sectionValue = isArray ? [...config[section], newValue] : { ...config[section], [fieldName]: newValue }
|
|
145
156
|
|
|
146
|
-
if(null !== subsection) {
|
|
147
|
-
if(isArray) {
|
|
157
|
+
if (null !== subsection) {
|
|
158
|
+
if (isArray) {
|
|
148
159
|
sectionValue = [...config[section]]
|
|
149
|
-
sectionValue[subsection] = {...sectionValue[subsection], [fieldName]: newValue}
|
|
150
|
-
} else if(typeof newValue ===
|
|
160
|
+
sectionValue[subsection] = { ...sectionValue[subsection], [fieldName]: newValue }
|
|
161
|
+
} else if (typeof newValue === 'string') {
|
|
151
162
|
sectionValue[subsection] = newValue
|
|
152
163
|
} else {
|
|
153
|
-
sectionValue = {...config[section], [subsection]: { ...config[section][subsection], [fieldName]: newValue}}
|
|
164
|
+
sectionValue = { ...config[section], [subsection]: { ...config[section][subsection], [fieldName]: newValue } }
|
|
154
165
|
}
|
|
155
166
|
}
|
|
156
167
|
|
|
157
|
-
let updatedConfig = {...config, [section]: sectionValue}
|
|
168
|
+
let updatedConfig = { ...config, [section]: sectionValue }
|
|
158
169
|
|
|
159
|
-
enforceRestrictions(updatedConfig)
|
|
170
|
+
enforceRestrictions(updatedConfig)
|
|
160
171
|
|
|
161
172
|
updateConfig(updatedConfig)
|
|
162
173
|
}
|
|
@@ -164,15 +175,15 @@ const EditorPanel = memo(() => {
|
|
|
164
175
|
const missingRequiredSections = () => {
|
|
165
176
|
//TODO
|
|
166
177
|
|
|
167
|
-
return false
|
|
168
|
-
}
|
|
178
|
+
return false
|
|
179
|
+
}
|
|
169
180
|
|
|
170
|
-
const [
|
|
181
|
+
const [displayPanel, setDisplayPanel] = useState(true)
|
|
171
182
|
|
|
172
183
|
// Used to pipe a JSON version of the config you are creating out
|
|
173
|
-
const [
|
|
184
|
+
const [configData, setConfigData] = useState({})
|
|
174
185
|
|
|
175
|
-
if(loading) {
|
|
186
|
+
if (loading) {
|
|
176
187
|
return null
|
|
177
188
|
}
|
|
178
189
|
|
|
@@ -180,12 +191,12 @@ const EditorPanel = memo(() => {
|
|
|
180
191
|
let columns = {}
|
|
181
192
|
|
|
182
193
|
rawData.map(row => {
|
|
183
|
-
Object.keys(row).forEach(columnName => columns[columnName] = true)
|
|
194
|
+
Object.keys(row).forEach(columnName => (columns[columnName] = true))
|
|
184
195
|
})
|
|
185
196
|
|
|
186
|
-
if(filter) {
|
|
197
|
+
if (filter) {
|
|
187
198
|
Object.keys(columns).forEach(key => {
|
|
188
|
-
if((config.series && config.series.filter(series => series.dataKey === key).length > 0) || (config.confidenceKeys && Object.keys(config.confidenceKeys).includes(key))
|
|
199
|
+
if ((config.series && config.series.filter(series => series.dataKey === key).length > 0) || (config.confidenceKeys && Object.keys(config.confidenceKeys).includes(key))) {
|
|
189
200
|
delete columns[key]
|
|
190
201
|
}
|
|
191
202
|
})
|
|
@@ -196,24 +207,24 @@ const EditorPanel = memo(() => {
|
|
|
196
207
|
|
|
197
208
|
const Error = () => {
|
|
198
209
|
return (
|
|
199
|
-
<section className=
|
|
200
|
-
<section className=
|
|
210
|
+
<section className='waiting'>
|
|
211
|
+
<section className='waiting-container'>
|
|
201
212
|
<h3>Error With Configuration</h3>
|
|
202
213
|
<p>{config.runtime.editorErrorMessage}</p>
|
|
203
214
|
</section>
|
|
204
215
|
</section>
|
|
205
|
-
)
|
|
216
|
+
)
|
|
206
217
|
}
|
|
207
218
|
|
|
208
|
-
const convertStateToConfig = (type =
|
|
219
|
+
const convertStateToConfig = (type = 'JSON') => {
|
|
209
220
|
let strippedState = JSON.parse(JSON.stringify(config))
|
|
210
|
-
if(false === missingRequiredSections()) {
|
|
221
|
+
if (false === missingRequiredSections()) {
|
|
211
222
|
delete strippedState.newViz
|
|
212
223
|
}
|
|
213
224
|
delete strippedState.runtime
|
|
214
225
|
|
|
215
|
-
if(type ===
|
|
216
|
-
return JSON.stringify(
|
|
226
|
+
if (type === 'JSON') {
|
|
227
|
+
return JSON.stringify(strippedState)
|
|
217
228
|
}
|
|
218
229
|
|
|
219
230
|
return strippedState
|
|
@@ -222,96 +233,79 @@ const EditorPanel = memo(() => {
|
|
|
222
233
|
useEffect(() => {
|
|
223
234
|
const parsedData = convertStateToConfig()
|
|
224
235
|
|
|
225
|
-
const formattedData = JSON.stringify(JSON.parse(parsedData), undefined, 2)
|
|
236
|
+
const formattedData = JSON.stringify(JSON.parse(parsedData), undefined, 2)
|
|
226
237
|
|
|
227
238
|
setConfigData(formattedData)
|
|
228
239
|
|
|
229
240
|
// Emit the data in a regular JS event so it can be consumed by anything.
|
|
230
|
-
const event = new CustomEvent('updateVizConfig', { detail: parsedData})
|
|
241
|
+
const event = new CustomEvent('updateVizConfig', { detail: parsedData })
|
|
231
242
|
|
|
232
243
|
window.dispatchEvent(event)
|
|
233
244
|
|
|
234
245
|
// Pass up to Editor if needed
|
|
235
|
-
if(setParentConfig) {
|
|
236
|
-
const newConfig = convertStateToConfig(
|
|
246
|
+
if (setParentConfig) {
|
|
247
|
+
const newConfig = convertStateToConfig('object')
|
|
237
248
|
setParentConfig(newConfig)
|
|
238
249
|
}
|
|
239
250
|
|
|
240
|
-
|
|
241
|
-
}, [config])
|
|
251
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
252
|
+
}, [config])
|
|
242
253
|
|
|
243
|
-
const removeFilter =
|
|
244
|
-
let dashboardConfig = config.dashboard
|
|
254
|
+
const removeFilter = index => {
|
|
255
|
+
let dashboardConfig = config.dashboard
|
|
245
256
|
|
|
246
|
-
dashboardConfig.filters.splice(index, 1)
|
|
257
|
+
dashboardConfig.filters.splice(index, 1)
|
|
247
258
|
|
|
248
|
-
updateConfig({...config, dashboard: dashboardConfig})
|
|
259
|
+
updateConfig({ ...config, dashboard: dashboardConfig })
|
|
249
260
|
}
|
|
250
261
|
|
|
251
262
|
const updateFilterProp = (name, index, value) => {
|
|
252
|
-
let dashboardConfig = config.dashboard
|
|
263
|
+
let dashboardConfig = config.dashboard
|
|
253
264
|
|
|
254
|
-
dashboardConfig.filters[index][name] = value
|
|
265
|
+
dashboardConfig.filters[index][name] = value
|
|
255
266
|
|
|
256
|
-
updateConfig({...config, dashboard: dashboardConfig})
|
|
267
|
+
updateConfig({ ...config, dashboard: dashboardConfig })
|
|
257
268
|
}
|
|
258
269
|
|
|
259
270
|
const addNewFilter = () => {
|
|
260
|
-
let dashboardConfig = config.dashboard
|
|
271
|
+
let dashboardConfig = config.dashboard
|
|
261
272
|
|
|
262
|
-
dashboardConfig.filters = dashboardConfig.filters || []
|
|
273
|
+
dashboardConfig.filters = dashboardConfig.filters || []
|
|
263
274
|
|
|
264
|
-
dashboardConfig.filters.push({values: []})
|
|
275
|
+
dashboardConfig.filters.push({ values: [] })
|
|
265
276
|
|
|
266
|
-
updateConfig({...config, dashboard: dashboardConfig})
|
|
277
|
+
updateConfig({ ...config, dashboard: dashboardConfig })
|
|
267
278
|
}
|
|
268
279
|
|
|
269
280
|
return (
|
|
270
|
-
<ErrorBoundary component=
|
|
281
|
+
<ErrorBoundary component='EditorPanel'>
|
|
271
282
|
{config.runtime && config.runtime.editorErrorMessage && <Error />}
|
|
272
|
-
<button
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
></button>
|
|
277
|
-
<section
|
|
278
|
-
className={
|
|
279
|
-
displayPanel ? "editor-panel cove" : "hidden editor-panel cove"
|
|
280
|
-
}
|
|
281
|
-
>
|
|
282
|
-
<div className="heading-2">Configure</div>
|
|
283
|
-
<section className="form-container">
|
|
283
|
+
<button className={displayPanel ? `editor-toggle` : `editor-toggle collapsed`} title={displayPanel ? `Collapse Editor` : `Expand Editor`} onClick={() => setDisplayPanel(!displayPanel)}></button>
|
|
284
|
+
<section className={displayPanel ? 'editor-panel cove' : 'hidden editor-panel cove'}>
|
|
285
|
+
<div className='heading-2'>Configure</div>
|
|
286
|
+
<section className='form-container'>
|
|
284
287
|
<form>
|
|
285
288
|
<Accordion allowZeroExpanded={true}>
|
|
286
289
|
<AccordionItem>
|
|
287
|
-
{
|
|
290
|
+
{' '}
|
|
288
291
|
{/* General */}
|
|
289
292
|
<AccordionItemHeading>
|
|
290
293
|
<AccordionItemButton>General</AccordionItemButton>
|
|
291
294
|
</AccordionItemHeading>
|
|
292
295
|
<AccordionItemPanel>
|
|
293
|
-
<TextField
|
|
294
|
-
value={config.dashboard.title}
|
|
295
|
-
section="dashboard"
|
|
296
|
-
fieldName="title"
|
|
297
|
-
label="Title"
|
|
298
|
-
updateField={updateField}
|
|
299
|
-
/>
|
|
296
|
+
<TextField value={config.dashboard.title} section='dashboard' fieldName='title' label='Title' updateField={updateField} />
|
|
300
297
|
|
|
301
298
|
<TextField
|
|
302
|
-
value={
|
|
299
|
+
value={'Super Title'}
|
|
303
300
|
updateField={updateField}
|
|
304
|
-
section=
|
|
305
|
-
fieldName=
|
|
306
|
-
label=
|
|
307
|
-
placeholder=
|
|
301
|
+
section='general'
|
|
302
|
+
fieldName='superTitle'
|
|
303
|
+
label='Super Title'
|
|
304
|
+
placeholder='Super Title'
|
|
308
305
|
tooltip={
|
|
309
|
-
<Tooltip style={{ textTransform:
|
|
306
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
310
307
|
<Tooltip.Target>
|
|
311
|
-
<Icon
|
|
312
|
-
display="question"
|
|
313
|
-
style={{ marginLeft: "0.5rem" }}
|
|
314
|
-
/>
|
|
308
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
315
309
|
</Tooltip.Target>
|
|
316
310
|
<Tooltip.Content>
|
|
317
311
|
<p>Super Title</p>
|
|
@@ -321,19 +315,16 @@ const EditorPanel = memo(() => {
|
|
|
321
315
|
/>
|
|
322
316
|
|
|
323
317
|
<TextField
|
|
324
|
-
type=
|
|
325
|
-
value={
|
|
318
|
+
type='textarea'
|
|
319
|
+
value={'Intro Text'}
|
|
326
320
|
updateField={updateField}
|
|
327
|
-
section=
|
|
328
|
-
fieldName=
|
|
329
|
-
label=
|
|
321
|
+
section='general'
|
|
322
|
+
fieldName='introText'
|
|
323
|
+
label='Intro Text'
|
|
330
324
|
tooltip={
|
|
331
|
-
<Tooltip style={{ textTransform:
|
|
325
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
332
326
|
<Tooltip.Target>
|
|
333
|
-
<Icon
|
|
334
|
-
display="question"
|
|
335
|
-
style={{ marginLeft: "0.5rem" }}
|
|
336
|
-
/>
|
|
327
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
337
328
|
</Tooltip.Target>
|
|
338
329
|
<Tooltip.Content>
|
|
339
330
|
<p>Intro Text</p>
|
|
@@ -343,45 +334,35 @@ const EditorPanel = memo(() => {
|
|
|
343
334
|
/>
|
|
344
335
|
|
|
345
336
|
<TextField
|
|
346
|
-
type=
|
|
337
|
+
type='textarea'
|
|
347
338
|
value={config.dashboard.description}
|
|
348
|
-
section=
|
|
349
|
-
fieldName=
|
|
350
|
-
label=
|
|
339
|
+
section='dashboard'
|
|
340
|
+
fieldName='description'
|
|
341
|
+
label='Description'
|
|
351
342
|
updateField={updateField}
|
|
352
343
|
tooltip={
|
|
353
|
-
<Tooltip style={{ textTransform:
|
|
344
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
354
345
|
<Tooltip.Target>
|
|
355
|
-
<Icon
|
|
356
|
-
display="question"
|
|
357
|
-
style={{ marginLeft: "0.5rem" }}
|
|
358
|
-
/>
|
|
346
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
359
347
|
</Tooltip.Target>
|
|
360
348
|
<Tooltip.Content>
|
|
361
|
-
<p>
|
|
362
|
-
Enter supporting text to display below the data
|
|
363
|
-
visualization, if applicable. The following HTML
|
|
364
|
-
tags are supported: strong, em, sup, and sub.
|
|
365
|
-
</p>
|
|
349
|
+
<p>Enter supporting text to display below the data visualization, if applicable. The following HTML tags are supported: strong, em, sup, and sub.</p>
|
|
366
350
|
</Tooltip.Content>
|
|
367
351
|
</Tooltip>
|
|
368
352
|
}
|
|
369
353
|
/>
|
|
370
354
|
|
|
371
355
|
<TextField
|
|
372
|
-
type=
|
|
373
|
-
value={
|
|
356
|
+
type='textarea'
|
|
357
|
+
value={'Foootnotes'}
|
|
374
358
|
updateField={updateField}
|
|
375
|
-
section=
|
|
376
|
-
fieldName=
|
|
377
|
-
label=
|
|
359
|
+
section='general'
|
|
360
|
+
fieldName='footnotes'
|
|
361
|
+
label='Footnotes'
|
|
378
362
|
tooltip={
|
|
379
|
-
<Tooltip style={{ textTransform:
|
|
363
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
380
364
|
<Tooltip.Target>
|
|
381
|
-
<Icon
|
|
382
|
-
display="question"
|
|
383
|
-
style={{ marginLeft: "0.5rem" }}
|
|
384
|
-
/>
|
|
365
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
385
366
|
</Tooltip.Target>
|
|
386
367
|
<Tooltip.Content>
|
|
387
368
|
<p>Footnotes</p>
|
|
@@ -396,38 +377,29 @@ const EditorPanel = memo(() => {
|
|
|
396
377
|
<AccordionItemButton>Filters</AccordionItemButton>
|
|
397
378
|
</AccordionItemHeading>
|
|
398
379
|
<AccordionItemPanel>
|
|
399
|
-
<ul className=
|
|
380
|
+
<ul className='filters-list'>
|
|
400
381
|
{config.dashboard.filters &&
|
|
401
382
|
config.dashboard.filters.map((filter, index) => (
|
|
402
|
-
<fieldset
|
|
403
|
-
className="edit-block"
|
|
404
|
-
key={filter.columnName + index}
|
|
405
|
-
>
|
|
383
|
+
<fieldset className='edit-block' key={filter.columnName + index}>
|
|
406
384
|
<button
|
|
407
|
-
type=
|
|
408
|
-
className=
|
|
385
|
+
type='button'
|
|
386
|
+
className='remove-column'
|
|
409
387
|
onClick={() => {
|
|
410
|
-
removeFilter(index)
|
|
388
|
+
removeFilter(index)
|
|
411
389
|
}}
|
|
412
390
|
>
|
|
413
391
|
Remove
|
|
414
392
|
</button>
|
|
415
393
|
<label>
|
|
416
|
-
<span className=
|
|
417
|
-
Filter
|
|
418
|
-
</span>
|
|
394
|
+
<span className='edit-label column-heading'>Filter</span>
|
|
419
395
|
<select
|
|
420
396
|
value={filter.columnName}
|
|
421
|
-
onChange={
|
|
422
|
-
updateFilterProp(
|
|
423
|
-
"columnName",
|
|
424
|
-
index,
|
|
425
|
-
e.target.value
|
|
426
|
-
);
|
|
397
|
+
onChange={e => {
|
|
398
|
+
updateFilterProp('columnName', index, e.target.value)
|
|
427
399
|
}}
|
|
428
400
|
>
|
|
429
|
-
<option value=
|
|
430
|
-
{getColumns().map(
|
|
401
|
+
<option value=''>- Select Option -</option>
|
|
402
|
+
{getColumns().map(dataKey => (
|
|
431
403
|
<option value={dataKey} key={dataKey}>
|
|
432
404
|
{dataKey}
|
|
433
405
|
</option>
|
|
@@ -435,18 +407,12 @@ const EditorPanel = memo(() => {
|
|
|
435
407
|
</select>
|
|
436
408
|
</label>
|
|
437
409
|
<label>
|
|
438
|
-
<span className=
|
|
439
|
-
Label
|
|
440
|
-
</span>
|
|
410
|
+
<span className='edit-label column-heading'>Label</span>
|
|
441
411
|
<input
|
|
442
|
-
type=
|
|
412
|
+
type='text'
|
|
443
413
|
value={filter.label}
|
|
444
|
-
onChange={
|
|
445
|
-
updateFilterProp(
|
|
446
|
-
"label",
|
|
447
|
-
index,
|
|
448
|
-
e.target.value
|
|
449
|
-
);
|
|
414
|
+
onChange={e => {
|
|
415
|
+
updateFilterProp('label', index, e.target.value)
|
|
450
416
|
}}
|
|
451
417
|
/>
|
|
452
418
|
</label>
|
|
@@ -454,11 +420,7 @@ const EditorPanel = memo(() => {
|
|
|
454
420
|
))}
|
|
455
421
|
</ul>
|
|
456
422
|
|
|
457
|
-
<button
|
|
458
|
-
type="button"
|
|
459
|
-
onClick={addNewFilter}
|
|
460
|
-
className="btn btn-primary"
|
|
461
|
-
>
|
|
423
|
+
<button type='button' onClick={addNewFilter} className='btn btn-primary'>
|
|
462
424
|
Add Filter
|
|
463
425
|
</button>
|
|
464
426
|
</AccordionItemPanel>
|
|
@@ -468,43 +430,19 @@ const EditorPanel = memo(() => {
|
|
|
468
430
|
<AccordionItemButton>Data Table</AccordionItemButton>
|
|
469
431
|
</AccordionItemHeading>
|
|
470
432
|
<AccordionItemPanel>
|
|
471
|
-
<CheckBox
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
label="Show Table"
|
|
476
|
-
updateField={updateField}
|
|
477
|
-
/>
|
|
478
|
-
<CheckBox
|
|
479
|
-
value={config.table.expanded}
|
|
480
|
-
section="table"
|
|
481
|
-
fieldName="expanded"
|
|
482
|
-
label="Expanded by Default"
|
|
483
|
-
updateField={updateField}
|
|
484
|
-
/>
|
|
485
|
-
<CheckBox
|
|
486
|
-
value={config.table.download}
|
|
487
|
-
section="table"
|
|
488
|
-
fieldName="download"
|
|
489
|
-
label="Display Download Button"
|
|
490
|
-
updateField={updateField}
|
|
491
|
-
/>
|
|
492
|
-
<TextField
|
|
493
|
-
value={config.table.label}
|
|
494
|
-
section="table"
|
|
495
|
-
fieldName="label"
|
|
496
|
-
label="Label"
|
|
497
|
-
updateField={updateField}
|
|
498
|
-
/>
|
|
433
|
+
<CheckBox value={config.table.show} section='table' fieldName='show' label='Show Table' updateField={updateField} />
|
|
434
|
+
<CheckBox value={config.table.expanded} section='table' fieldName='expanded' label='Expanded by Default' updateField={updateField} />
|
|
435
|
+
<CheckBox value={config.table.download} section='table' fieldName='download' label='Display Download Button' updateField={updateField} />
|
|
436
|
+
<TextField value={config.table.label} section='table' fieldName='label' label='Label' updateField={updateField} />
|
|
499
437
|
</AccordionItemPanel>
|
|
500
438
|
</AccordionItem>
|
|
501
439
|
</Accordion>
|
|
502
440
|
</form>
|
|
503
441
|
</section>
|
|
504
|
-
<ReactTooltip html={true} multiline={true} className=
|
|
442
|
+
<ReactTooltip html={true} multiline={true} className='helper-tooltip' />
|
|
505
443
|
</section>
|
|
506
444
|
</ErrorBoundary>
|
|
507
|
-
)
|
|
445
|
+
)
|
|
508
446
|
})
|
|
509
447
|
|
|
510
|
-
export default EditorPanel
|
|
448
|
+
export default EditorPanel
|