@cdc/filtered-text 4.25.11 → 4.26.2
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/dist/cdcfilteredtext.js +8882 -8596
- package/examples/default.json +7 -0
- package/index.html +1 -36
- package/package.json +27 -31
- package/src/CdcFilteredText.jsx +20 -14
- package/src/components/EditorPanel/EditorPanel.tsx +160 -0
- package/src/components/EditorPanel/index.tsx +3 -0
- package/src/data/initial-state.js +1 -0
- package/src/scss/main.scss +11 -1
- package/src/test/CdcFilteredText.test.jsx +1 -1
- package/LICENSE +0 -201
- package/src/components/EditorPanel.jsx +0 -302
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
import React, { memo, useState, useEffect, useContext } from 'react'
|
|
2
|
-
import cloneConfig from '@cdc/core/helpers/cloneConfig'
|
|
3
|
-
import _ from 'lodash'
|
|
4
|
-
import ConfigContext from '../ConfigContext'
|
|
5
|
-
|
|
6
|
-
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
7
|
-
import Accordion from '@cdc/core/components/ui/Accordion'
|
|
8
|
-
import { TextField, Select, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
|
|
9
|
-
import Button from '@cdc/core/components/elements/Button'
|
|
10
|
-
import Icon from '@cdc/core/components/ui/Icon'
|
|
11
|
-
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
12
|
-
import Layout from '@cdc/core/components/Layout'
|
|
13
|
-
import { HeaderThemeSelector } from '@cdc/core/components/HeaderThemeSelector'
|
|
14
|
-
import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
|
|
15
|
-
|
|
16
|
-
import '@cdc/core/styles/v2/components/editor.scss'
|
|
17
|
-
|
|
18
|
-
const EditorPanel = memo(props => {
|
|
19
|
-
const { config, updateConfig, loading, stateData: data, setParentConfig, isDashboard } = useContext(ConfigContext)
|
|
20
|
-
|
|
21
|
-
const [displayPanel, setDisplayPanel] = useState(true)
|
|
22
|
-
const [showConfigConfirm, setShowConfigConfirm] = useState(false)
|
|
23
|
-
|
|
24
|
-
const updateField = updateFieldFactory(config, updateConfig, true)
|
|
25
|
-
|
|
26
|
-
const missingRequiredSections = () => {
|
|
27
|
-
return false
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Filters -------------------------
|
|
31
|
-
const removeFilter = index => {
|
|
32
|
-
let filters = [...config.filters]
|
|
33
|
-
|
|
34
|
-
filters.splice(index, 1)
|
|
35
|
-
|
|
36
|
-
updateConfig({ ...config, filters })
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const updateFilterProp = (name, index, value) => {
|
|
40
|
-
let filters = [...config.filters]
|
|
41
|
-
|
|
42
|
-
filters[index][name] = value
|
|
43
|
-
|
|
44
|
-
updateConfig({ ...config, filters })
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const addNewFilter = () => {
|
|
48
|
-
let filters = config.filters ? [...config.filters] : []
|
|
49
|
-
|
|
50
|
-
filters.push({ values: [] })
|
|
51
|
-
|
|
52
|
-
updateConfig({ ...config, filters })
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const getColumns = (filter = true) => {
|
|
56
|
-
let columns = {}
|
|
57
|
-
if (data.length) {
|
|
58
|
-
data.map(row => {
|
|
59
|
-
return Object.keys(row).forEach(columnName => (columns[columnName] = true))
|
|
60
|
-
})
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return Object.keys(columns)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const getFilterColumnValues = index => {
|
|
67
|
-
let filterDataOptions = []
|
|
68
|
-
const filterColumnName = config.filters[index].columnName
|
|
69
|
-
if (data && filterColumnName) {
|
|
70
|
-
data.forEach(function (row) {
|
|
71
|
-
if (undefined !== row[filterColumnName] && -1 === filterDataOptions.indexOf(row[filterColumnName])) {
|
|
72
|
-
filterDataOptions.push(row[filterColumnName])
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
|
-
filterDataOptions.sort()
|
|
76
|
-
}
|
|
77
|
-
return filterDataOptions
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
useEffect(() => {
|
|
81
|
-
// Pass up to Editor if needed
|
|
82
|
-
if (setParentConfig) {
|
|
83
|
-
const newConfig = convertStateToConfig()
|
|
84
|
-
setParentConfig(newConfig)
|
|
85
|
-
}
|
|
86
|
-
}, [config])
|
|
87
|
-
|
|
88
|
-
useEffect(() => {
|
|
89
|
-
if (!showConfigConfirm) {
|
|
90
|
-
let newConfig = { ...config }
|
|
91
|
-
delete newConfig.newViz
|
|
92
|
-
updateConfig(newConfig)
|
|
93
|
-
}
|
|
94
|
-
}, [])
|
|
95
|
-
|
|
96
|
-
const onBackClick = () => {
|
|
97
|
-
setDisplayPanel(!displayPanel)
|
|
98
|
-
updateConfig({
|
|
99
|
-
...config,
|
|
100
|
-
showEditorPanel: !displayPanel
|
|
101
|
-
})
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const Error = () => {
|
|
105
|
-
return (
|
|
106
|
-
<section className='waiting'>
|
|
107
|
-
<section className='waiting-container'>
|
|
108
|
-
<h3>Error With Configuration</h3>
|
|
109
|
-
<p>{config.runtime.editorErrorMessage}</p>
|
|
110
|
-
</section>
|
|
111
|
-
</section>
|
|
112
|
-
)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const Confirm = () => {
|
|
116
|
-
const confirmDone = e => {
|
|
117
|
-
e.preventDefault()
|
|
118
|
-
let newConfig = { ...config }
|
|
119
|
-
delete newConfig.newViz
|
|
120
|
-
updateConfig(newConfig)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return (
|
|
124
|
-
<section className='waiting'>
|
|
125
|
-
<section className='waiting-container'>
|
|
126
|
-
<h3>Finish Configuring</h3>
|
|
127
|
-
<p>Set all required options to the left and confirm below to display a preview of the markup.</p>
|
|
128
|
-
<button className='btn btn-primary' style={{ margin: '1em auto' }} onClick={confirmDone}>
|
|
129
|
-
I'm Done
|
|
130
|
-
</button>
|
|
131
|
-
</section>
|
|
132
|
-
</section>
|
|
133
|
-
)
|
|
134
|
-
}
|
|
135
|
-
const convertStateToConfig = () => {
|
|
136
|
-
let strippedState = cloneConfig(config)
|
|
137
|
-
delete strippedState.newViz
|
|
138
|
-
delete strippedState.runtime
|
|
139
|
-
|
|
140
|
-
return strippedState
|
|
141
|
-
}
|
|
142
|
-
const editorContent = (
|
|
143
|
-
<Accordion>
|
|
144
|
-
<Accordion.Section title='General'>
|
|
145
|
-
<TextField
|
|
146
|
-
value={config.title}
|
|
147
|
-
fieldName='title'
|
|
148
|
-
label='Title'
|
|
149
|
-
placeholder='Filterable Text Title'
|
|
150
|
-
updateField={updateField}
|
|
151
|
-
/>
|
|
152
|
-
</Accordion.Section>
|
|
153
|
-
<Accordion.Section title='Data'>
|
|
154
|
-
<Select
|
|
155
|
-
value={config.textColumn || ''}
|
|
156
|
-
fieldName='textColumn'
|
|
157
|
-
label='Text Column'
|
|
158
|
-
updateField={updateField}
|
|
159
|
-
initial='Select'
|
|
160
|
-
options={getColumns()}
|
|
161
|
-
/>
|
|
162
|
-
|
|
163
|
-
<label style={{ marginBottom: '1rem' }}>
|
|
164
|
-
<span className='edit-label'>
|
|
165
|
-
Data Point Filters
|
|
166
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
167
|
-
<Tooltip.Target>
|
|
168
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
169
|
-
</Tooltip.Target>
|
|
170
|
-
<Tooltip.Content>
|
|
171
|
-
<p>
|
|
172
|
-
To refine the highlighted data point, specify one or more filters (e.g., "Male" and "Female" for a
|
|
173
|
-
column called "Sex").
|
|
174
|
-
</p>
|
|
175
|
-
</Tooltip.Content>
|
|
176
|
-
</Tooltip>
|
|
177
|
-
</span>
|
|
178
|
-
</label>
|
|
179
|
-
{config.filters && (
|
|
180
|
-
<ul className='filters-list' style={{ paddingLeft: 0, marginBottom: '1rem' }}>
|
|
181
|
-
{config.filters.map((filter, index) => (
|
|
182
|
-
<fieldset className='edit-block' key={index}>
|
|
183
|
-
<button
|
|
184
|
-
type='button'
|
|
185
|
-
className='remove-column'
|
|
186
|
-
onClick={() => {
|
|
187
|
-
removeFilter(index)
|
|
188
|
-
}}
|
|
189
|
-
>
|
|
190
|
-
Remove
|
|
191
|
-
</button>
|
|
192
|
-
<Select
|
|
193
|
-
label='Column'
|
|
194
|
-
value={filter.columnName || ''}
|
|
195
|
-
options={[
|
|
196
|
-
{ value: '', label: '- Select Option -' },
|
|
197
|
-
...getColumns().map(col => ({ value: col, label: col }))
|
|
198
|
-
]}
|
|
199
|
-
onChange={e => {
|
|
200
|
-
updateFilterProp('columnName', index, e.target.value)
|
|
201
|
-
}}
|
|
202
|
-
/>
|
|
203
|
-
<Select
|
|
204
|
-
label='Column Value'
|
|
205
|
-
value={filter.columnValue || ''}
|
|
206
|
-
options={[
|
|
207
|
-
{ value: '', label: '- Select Option -' },
|
|
208
|
-
...getFilterColumnValues(index).map(val => ({ value: val, label: val }))
|
|
209
|
-
]}
|
|
210
|
-
onChange={e => {
|
|
211
|
-
updateFilterProp('columnValue', index, e.target.value)
|
|
212
|
-
}}
|
|
213
|
-
/>
|
|
214
|
-
</fieldset>
|
|
215
|
-
))}
|
|
216
|
-
</ul>
|
|
217
|
-
)}
|
|
218
|
-
<Button onClick={addNewFilter} fluid>
|
|
219
|
-
Add Filter
|
|
220
|
-
</Button>
|
|
221
|
-
</Accordion.Section>
|
|
222
|
-
<Accordion.Section title='Visual'>
|
|
223
|
-
<Select
|
|
224
|
-
value={config.fontSize}
|
|
225
|
-
fieldName='fontSize'
|
|
226
|
-
label='Font Size'
|
|
227
|
-
updateField={updateField}
|
|
228
|
-
options={['small', 'medium', 'large']}
|
|
229
|
-
/>
|
|
230
|
-
<HeaderThemeSelector
|
|
231
|
-
selectedTheme={config.theme}
|
|
232
|
-
onThemeSelect={theme => updateConfig({ ...config, theme })}
|
|
233
|
-
label='Theme'
|
|
234
|
-
/>
|
|
235
|
-
|
|
236
|
-
<div className='cove-accordion__panel-section checkbox-group'>
|
|
237
|
-
<CheckBox
|
|
238
|
-
inline
|
|
239
|
-
size='small'
|
|
240
|
-
value={config.visual.border}
|
|
241
|
-
section='visual'
|
|
242
|
-
fieldName='border'
|
|
243
|
-
label='Display Border'
|
|
244
|
-
updateField={updateField}
|
|
245
|
-
/>
|
|
246
|
-
<CheckBox
|
|
247
|
-
inline
|
|
248
|
-
size='small'
|
|
249
|
-
value={config.visual.borderColorTheme}
|
|
250
|
-
section='visual'
|
|
251
|
-
fieldName='borderColorTheme'
|
|
252
|
-
label='Use theme border color'
|
|
253
|
-
updateField={updateField}
|
|
254
|
-
/>
|
|
255
|
-
<CheckBox
|
|
256
|
-
size='small'
|
|
257
|
-
value={config.visual.accent}
|
|
258
|
-
section='visual'
|
|
259
|
-
fieldName='accent'
|
|
260
|
-
label='Use Accent Style'
|
|
261
|
-
updateField={updateField}
|
|
262
|
-
/>
|
|
263
|
-
<CheckBox
|
|
264
|
-
size='small'
|
|
265
|
-
value={config.visual.background}
|
|
266
|
-
section='visual'
|
|
267
|
-
fieldName='background'
|
|
268
|
-
label='Use Theme Background Color'
|
|
269
|
-
updateField={updateField}
|
|
270
|
-
/>
|
|
271
|
-
<CheckBox
|
|
272
|
-
size='small'
|
|
273
|
-
value={config.visual.hideBackgroundColor}
|
|
274
|
-
section='visual'
|
|
275
|
-
fieldName='hideBackgroundColor'
|
|
276
|
-
label='Hide Background Color'
|
|
277
|
-
updateField={updateField}
|
|
278
|
-
/>
|
|
279
|
-
</div>
|
|
280
|
-
</Accordion.Section>
|
|
281
|
-
</Accordion>
|
|
282
|
-
)
|
|
283
|
-
|
|
284
|
-
if (loading) return null
|
|
285
|
-
|
|
286
|
-
return (
|
|
287
|
-
<ErrorBoundary component='EditorPanel'>
|
|
288
|
-
<Layout.Sidebar
|
|
289
|
-
displayPanel={displayPanel}
|
|
290
|
-
isDashboard={isDashboard}
|
|
291
|
-
title={'Configure Filtered Text'}
|
|
292
|
-
onBackClick={onBackClick}
|
|
293
|
-
>
|
|
294
|
-
{!config.newViz && config.runtime && config.runtime.editorErrorMessage && <Error />}
|
|
295
|
-
{config.newViz && showConfigConfirm && <Confirm />}
|
|
296
|
-
{editorContent}
|
|
297
|
-
</Layout.Sidebar>
|
|
298
|
-
</ErrorBoundary>
|
|
299
|
-
)
|
|
300
|
-
})
|
|
301
|
-
|
|
302
|
-
export default EditorPanel
|