@cdc/data-bite 4.25.10 → 4.26.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.
- package/dist/cdcdatabite.js +9523 -8407
- package/examples/tp5-style.json +59 -0
- package/examples/tp5-white-background.json +60 -0
- package/index.html +8 -4
- package/package.json +5 -5
- package/src/CdcDataBite.tsx +106 -62
- package/src/_stories/DataBite.Editor.stories.tsx +6 -3
- package/src/_stories/DataBite.stories.tsx +28 -0
- package/src/components/EditorPanel/EditorPanel.tsx +542 -0
- package/src/components/EditorPanel/index.tsx +3 -0
- package/src/constants.ts +2 -53
- package/src/images/callout-flag.svg +7 -0
- package/src/index.jsx +1 -0
- package/src/scss/bite.scss +84 -1
- package/src/scss/editor-panel.scss +13 -485
- package/src/scss/main.scss +1 -33
- package/src/store/db.reducer.ts +1 -1
- package/src/test/CdcDataBite.test.jsx +1 -1
- package/src/types/Config.ts +1 -0
- package/LICENSE +0 -201
- package/src/components/EditorPanel.jsx +0 -719
- package/src/scss/variables.scss +0 -1
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
import { useContext } from 'react'
|
|
2
|
+
|
|
3
|
+
import { DATA_FUNCTIONS, DATA_OPERATORS } from '@cdc/core/helpers/constants'
|
|
4
|
+
|
|
5
|
+
// Context
|
|
6
|
+
import Context from '../../context'
|
|
7
|
+
|
|
8
|
+
// Components
|
|
9
|
+
import { EditorPanel as BaseEditorPanel } from '@cdc/core/components/EditorPanel/EditorPanel'
|
|
10
|
+
import '@cdc/core/styles/v2/components/editor.scss'
|
|
11
|
+
import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
|
|
12
|
+
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
13
|
+
import Icon from '@cdc/core/components/ui/Icon'
|
|
14
|
+
import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
|
|
15
|
+
import { useFilterManagement } from '@cdc/core/hooks/useFilterManagement'
|
|
16
|
+
import { useDataColumns } from '@cdc/core/hooks/useDataColumns'
|
|
17
|
+
import { useListManagement } from '@cdc/core/hooks/useListManagement'
|
|
18
|
+
import { BITE_LOCATIONS, IMAGE_POSITIONS } from '../../constants'
|
|
19
|
+
import { Select, TextField, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
|
|
20
|
+
import Button from '@cdc/core/components/elements/Button'
|
|
21
|
+
import PanelMarkup from '@cdc/core/components/EditorPanel/components/PanelMarkup'
|
|
22
|
+
import { VisualSection } from '@cdc/core/components/EditorPanel/sections/VisualSection'
|
|
23
|
+
import Accordion from '@cdc/core/components/ui/Accordion'
|
|
24
|
+
|
|
25
|
+
type DataBiteEditorPanelProps = {
|
|
26
|
+
// Add any props if needed
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const EditorPanel: React.FC<DataBiteEditorPanelProps> = () => {
|
|
30
|
+
const { config, updateConfig, loading, data, setParentConfig, isDashboard } = useContext(Context)
|
|
31
|
+
|
|
32
|
+
const updateField = updateFieldFactory(config, updateConfig, true)
|
|
33
|
+
|
|
34
|
+
// Filters -----------------------------------------------
|
|
35
|
+
const { addNewFilter, removeFilter, updateFilterProp, getFilterColumnValues } = useFilterManagement(
|
|
36
|
+
config,
|
|
37
|
+
updateConfig,
|
|
38
|
+
data
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
// Extract column names from data with memoization (replaces getColumns)
|
|
42
|
+
const columns = useDataColumns(data)
|
|
43
|
+
|
|
44
|
+
// Dynamic Images ----------------------------------------
|
|
45
|
+
// Use standardized list management hook (Phase 2 improvement)
|
|
46
|
+
const images = useListManagement({
|
|
47
|
+
config,
|
|
48
|
+
updateConfig,
|
|
49
|
+
listPath: 'imageData.options',
|
|
50
|
+
createItem: () => ({
|
|
51
|
+
source: '',
|
|
52
|
+
arguments: [{ operator: '', threshold: '' }],
|
|
53
|
+
alt: '',
|
|
54
|
+
secondArgument: false
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
// Helper for removing second argument from dynamic image conditions
|
|
59
|
+
const removeDynamicArgument = (index: number) => {
|
|
60
|
+
const item = images.items[index]
|
|
61
|
+
if (item?.arguments?.length > 1) {
|
|
62
|
+
const updatedArguments = [...item.arguments]
|
|
63
|
+
updatedArguments.pop()
|
|
64
|
+
images.updateField(index, 'arguments', updatedArguments)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<BaseEditorPanel
|
|
70
|
+
config={config}
|
|
71
|
+
updateConfig={updateConfig as (config: any) => void}
|
|
72
|
+
loading={loading}
|
|
73
|
+
setParentConfig={setParentConfig as ((config: any) => void) | undefined}
|
|
74
|
+
isDashboard={isDashboard}
|
|
75
|
+
title='Configure Data Bites'
|
|
76
|
+
>
|
|
77
|
+
{({ convertStateToConfig }) => (
|
|
78
|
+
<Accordion>
|
|
79
|
+
<Accordion.Section title='General'>
|
|
80
|
+
<Select
|
|
81
|
+
value={config.biteStyle}
|
|
82
|
+
fieldName='biteStyle'
|
|
83
|
+
label='Data Bite Style'
|
|
84
|
+
updateField={updateField}
|
|
85
|
+
options={Object.entries(BITE_LOCATIONS).map(([key, value]) => ({ value: key, label: value }))}
|
|
86
|
+
initial='Select'
|
|
87
|
+
/>
|
|
88
|
+
<TextField
|
|
89
|
+
value={config.title}
|
|
90
|
+
fieldName='title'
|
|
91
|
+
label='Title'
|
|
92
|
+
placeholder='Data Bite Title'
|
|
93
|
+
updateField={updateField}
|
|
94
|
+
/>
|
|
95
|
+
<CheckBox
|
|
96
|
+
value={config.visual?.showTitle}
|
|
97
|
+
section='visual'
|
|
98
|
+
checked={config.visual?.showTitle}
|
|
99
|
+
fieldName='showTitle'
|
|
100
|
+
label='Show Title'
|
|
101
|
+
updateField={updateField}
|
|
102
|
+
/>
|
|
103
|
+
|
|
104
|
+
<TextField
|
|
105
|
+
type='textarea'
|
|
106
|
+
value={config.biteBody}
|
|
107
|
+
fieldName='biteBody'
|
|
108
|
+
label='Message'
|
|
109
|
+
updateField={updateField}
|
|
110
|
+
tooltip={
|
|
111
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
112
|
+
<Tooltip.Target>
|
|
113
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
114
|
+
</Tooltip.Target>
|
|
115
|
+
<Tooltip.Content>
|
|
116
|
+
<p>
|
|
117
|
+
Enter the message text for the visualization. The following HTML tags are supported: strong, em,
|
|
118
|
+
sup, and sub.
|
|
119
|
+
</p>
|
|
120
|
+
</Tooltip.Content>
|
|
121
|
+
</Tooltip>
|
|
122
|
+
}
|
|
123
|
+
/>
|
|
124
|
+
<TextField
|
|
125
|
+
value={config.subtext}
|
|
126
|
+
fieldName='subtext'
|
|
127
|
+
label='Subtext/Citation'
|
|
128
|
+
placeholder='Data Bite Subtext or Citation'
|
|
129
|
+
updateField={updateField}
|
|
130
|
+
tooltip={
|
|
131
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
132
|
+
<Tooltip.Target>
|
|
133
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
134
|
+
</Tooltip.Target>
|
|
135
|
+
<Tooltip.Content>
|
|
136
|
+
<p>
|
|
137
|
+
Enter supporting text to display below the data visualization, if applicable. The following HTML
|
|
138
|
+
tags are supported: strong, em, sup, and sub. You can also use markup variables like{' '}
|
|
139
|
+
{'{{variable-name}}'} to display dynamic data.
|
|
140
|
+
</p>
|
|
141
|
+
</Tooltip.Content>
|
|
142
|
+
</Tooltip>
|
|
143
|
+
}
|
|
144
|
+
/>
|
|
145
|
+
</Accordion.Section>
|
|
146
|
+
|
|
147
|
+
<Accordion.Section title='Data'>
|
|
148
|
+
<ul className='column-edit'>
|
|
149
|
+
<li className='two-col'>
|
|
150
|
+
<Select
|
|
151
|
+
value={config.dataColumn || ''}
|
|
152
|
+
fieldName='dataColumn'
|
|
153
|
+
label='Data Column'
|
|
154
|
+
updateField={updateField}
|
|
155
|
+
initial='Select'
|
|
156
|
+
required={true}
|
|
157
|
+
options={columns}
|
|
158
|
+
/>
|
|
159
|
+
<Select
|
|
160
|
+
value={config.dataFunction || ''}
|
|
161
|
+
fieldName='dataFunction'
|
|
162
|
+
label='Data Function'
|
|
163
|
+
updateField={updateField}
|
|
164
|
+
initial='Select'
|
|
165
|
+
required={true}
|
|
166
|
+
options={
|
|
167
|
+
Array.isArray(DATA_FUNCTIONS) ? DATA_FUNCTIONS : DATA_FUNCTIONS ? Object.values(DATA_FUNCTIONS) : []
|
|
168
|
+
}
|
|
169
|
+
/>
|
|
170
|
+
</li>
|
|
171
|
+
</ul>
|
|
172
|
+
<span className='divider-heading'>Number Formatting</span>
|
|
173
|
+
<ul className='column-edit'>
|
|
174
|
+
<li className='three-col'>
|
|
175
|
+
<TextField
|
|
176
|
+
value={config.dataFormat.prefix}
|
|
177
|
+
section='dataFormat'
|
|
178
|
+
fieldName='prefix'
|
|
179
|
+
label='Prefix'
|
|
180
|
+
updateField={updateField}
|
|
181
|
+
/>
|
|
182
|
+
<TextField
|
|
183
|
+
value={config.dataFormat.suffix}
|
|
184
|
+
section='dataFormat'
|
|
185
|
+
fieldName='suffix'
|
|
186
|
+
label='Suffix'
|
|
187
|
+
updateField={updateField}
|
|
188
|
+
/>
|
|
189
|
+
<TextField
|
|
190
|
+
type='number'
|
|
191
|
+
value={config.dataFormat.roundToPlace}
|
|
192
|
+
section='dataFormat'
|
|
193
|
+
fieldName='roundToPlace'
|
|
194
|
+
label='Round'
|
|
195
|
+
updateField={updateField}
|
|
196
|
+
min='0'
|
|
197
|
+
max='99'
|
|
198
|
+
/>
|
|
199
|
+
</li>
|
|
200
|
+
</ul>
|
|
201
|
+
<CheckBox
|
|
202
|
+
value={config.dataFormat.commas}
|
|
203
|
+
section='dataFormat'
|
|
204
|
+
fieldName='commas'
|
|
205
|
+
label='Add commas'
|
|
206
|
+
updateField={updateField}
|
|
207
|
+
/>
|
|
208
|
+
<CheckBox
|
|
209
|
+
value={config.dataFormat.ignoreZeros}
|
|
210
|
+
section='dataFormat'
|
|
211
|
+
fieldName='ignoreZeros'
|
|
212
|
+
label='Ignore Zeros'
|
|
213
|
+
updateField={updateField}
|
|
214
|
+
/>
|
|
215
|
+
<hr className='accordion__divider' />
|
|
216
|
+
|
|
217
|
+
<label style={{ marginBottom: '1rem' }}>
|
|
218
|
+
<span className='edit-label'>
|
|
219
|
+
Data Point Filters
|
|
220
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
221
|
+
<Tooltip.Target>
|
|
222
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
223
|
+
</Tooltip.Target>
|
|
224
|
+
<Tooltip.Content>
|
|
225
|
+
<p>
|
|
226
|
+
To refine the highlighted data point, specify one or more filters (e.g., "Male" and "Female" for a
|
|
227
|
+
column called "Sex").
|
|
228
|
+
</p>
|
|
229
|
+
</Tooltip.Content>
|
|
230
|
+
</Tooltip>
|
|
231
|
+
</span>
|
|
232
|
+
</label>
|
|
233
|
+
{config.filters && (
|
|
234
|
+
<ul className='filters-list'>
|
|
235
|
+
{config.filters.map((filter: any, index: number) => (
|
|
236
|
+
<fieldset className='edit-block' key={index}>
|
|
237
|
+
<button
|
|
238
|
+
type='button'
|
|
239
|
+
className='btn btn-danger'
|
|
240
|
+
onClick={() => {
|
|
241
|
+
removeFilter(index)
|
|
242
|
+
}}
|
|
243
|
+
>
|
|
244
|
+
Remove
|
|
245
|
+
</button>
|
|
246
|
+
<Select
|
|
247
|
+
value={filter.columnName ? filter.columnName : ''}
|
|
248
|
+
fieldName='columnName'
|
|
249
|
+
label={'Column Name'}
|
|
250
|
+
updateField={(section, subsection, fieldName, value) => updateFilterProp(fieldName, index, value)}
|
|
251
|
+
options={columns}
|
|
252
|
+
initial='- Select Option -'
|
|
253
|
+
/>
|
|
254
|
+
<Select
|
|
255
|
+
value={filter.columnValue || ''}
|
|
256
|
+
fieldName='columnValue'
|
|
257
|
+
label='Column Value'
|
|
258
|
+
updateField={(section, subsection, fieldName, value) => updateFilterProp(fieldName, index, value)}
|
|
259
|
+
options={Array.isArray(getFilterColumnValues(index)) ? getFilterColumnValues(index) : []}
|
|
260
|
+
initial='- Select Option -'
|
|
261
|
+
/>
|
|
262
|
+
</fieldset>
|
|
263
|
+
))}
|
|
264
|
+
</ul>
|
|
265
|
+
)}
|
|
266
|
+
{(!config.filters || config.filters.length === 0) && (
|
|
267
|
+
<div>
|
|
268
|
+
<fieldset className='edit-block'>
|
|
269
|
+
<p style={{ textAlign: 'center' }}>There are currently no filters.</p>
|
|
270
|
+
</fieldset>
|
|
271
|
+
</div>
|
|
272
|
+
)}
|
|
273
|
+
<Button type='button' onClick={addNewFilter} className='btn btn-primary full-width mt-3'>
|
|
274
|
+
Add Filter
|
|
275
|
+
</Button>
|
|
276
|
+
</Accordion.Section>
|
|
277
|
+
|
|
278
|
+
{/* Visual section for TP5 style */}
|
|
279
|
+
{config.biteStyle === 'tp5' && (
|
|
280
|
+
<Accordion.Section title='Visual'>
|
|
281
|
+
<CheckBox
|
|
282
|
+
value={config.visual?.whiteBackground}
|
|
283
|
+
section='visual'
|
|
284
|
+
fieldName='whiteBackground'
|
|
285
|
+
label='Use White Background Style'
|
|
286
|
+
updateField={updateField}
|
|
287
|
+
/>
|
|
288
|
+
{/* TODO: Uncomment when ready to release Display Border feature
|
|
289
|
+
<CheckBox
|
|
290
|
+
value={config.visual?.border}
|
|
291
|
+
section='visual'
|
|
292
|
+
fieldName='border'
|
|
293
|
+
label='Display Border'
|
|
294
|
+
updateField={updateField}
|
|
295
|
+
/>
|
|
296
|
+
*/}
|
|
297
|
+
</Accordion.Section>
|
|
298
|
+
)}
|
|
299
|
+
|
|
300
|
+
{/* Visual section for other bite styles */}
|
|
301
|
+
{config.biteStyle !== 'tp5' && (
|
|
302
|
+
<Accordion.Section title='Visual'>
|
|
303
|
+
<VisualSection
|
|
304
|
+
config={config}
|
|
305
|
+
updateField={updateField}
|
|
306
|
+
updateConfig={updateConfig}
|
|
307
|
+
themeSelectorPosition='after'
|
|
308
|
+
beforeCheckboxes={
|
|
309
|
+
<>
|
|
310
|
+
<TextField
|
|
311
|
+
type='number'
|
|
312
|
+
value={config.biteFontSize}
|
|
313
|
+
fieldName='biteFontSize'
|
|
314
|
+
label='Bite Font Size'
|
|
315
|
+
updateField={updateField}
|
|
316
|
+
min={17}
|
|
317
|
+
max={65}
|
|
318
|
+
/>
|
|
319
|
+
<Select
|
|
320
|
+
value={config.fontSize}
|
|
321
|
+
fieldName='fontSize'
|
|
322
|
+
label='Overall Font Size'
|
|
323
|
+
updateField={updateField}
|
|
324
|
+
options={['small', 'medium', 'large']}
|
|
325
|
+
/>
|
|
326
|
+
</>
|
|
327
|
+
}
|
|
328
|
+
/>
|
|
329
|
+
</Accordion.Section>
|
|
330
|
+
)}
|
|
331
|
+
|
|
332
|
+
{['title', 'body', 'graphic'].includes(config.biteStyle) && (
|
|
333
|
+
<Accordion.Section title={`Image${['dynamic'].includes(config.imageData.display) ? 's' : ''}`}>
|
|
334
|
+
<Select
|
|
335
|
+
value={config.imageData.display || ''}
|
|
336
|
+
section='imageData'
|
|
337
|
+
fieldName='display'
|
|
338
|
+
label='Image Display Type'
|
|
339
|
+
updateField={updateField}
|
|
340
|
+
options={['none', 'static', 'dynamic']}
|
|
341
|
+
/>
|
|
342
|
+
<Select
|
|
343
|
+
value={config.bitePosition || ''}
|
|
344
|
+
fieldName='bitePosition'
|
|
345
|
+
label='Image/Graphic Position'
|
|
346
|
+
updateField={updateField}
|
|
347
|
+
initial='Select'
|
|
348
|
+
options={IMAGE_POSITIONS}
|
|
349
|
+
/>
|
|
350
|
+
{['static'].includes(config.imageData.display) && (
|
|
351
|
+
<>
|
|
352
|
+
<TextField
|
|
353
|
+
value={config.imageData.url}
|
|
354
|
+
section='imageData'
|
|
355
|
+
fieldName='url'
|
|
356
|
+
label='Image URL'
|
|
357
|
+
updateField={updateField}
|
|
358
|
+
/>
|
|
359
|
+
<TextField
|
|
360
|
+
value={config.imageData.alt}
|
|
361
|
+
section='imageData'
|
|
362
|
+
fieldName='alt'
|
|
363
|
+
label='Alt Text'
|
|
364
|
+
updateField={updateField}
|
|
365
|
+
/>
|
|
366
|
+
</>
|
|
367
|
+
)}
|
|
368
|
+
|
|
369
|
+
{['dynamic'].includes(config.imageData.display) && (
|
|
370
|
+
<>
|
|
371
|
+
<TextField
|
|
372
|
+
value={config.imageData.url || ''}
|
|
373
|
+
section='imageData'
|
|
374
|
+
fieldName='url'
|
|
375
|
+
label='Image URL (default)'
|
|
376
|
+
updateField={updateField}
|
|
377
|
+
/>
|
|
378
|
+
<TextField
|
|
379
|
+
value={config.imageData.alt}
|
|
380
|
+
section='imageData'
|
|
381
|
+
fieldName='alt'
|
|
382
|
+
label='Alt Text (default)'
|
|
383
|
+
updateField={updateField}
|
|
384
|
+
/>
|
|
385
|
+
|
|
386
|
+
<hr className='accordion__divider' />
|
|
387
|
+
|
|
388
|
+
{(!images.items || images.items.length === 0) && (
|
|
389
|
+
<p style={{ textAlign: 'center' }}>There are currently no dynamic images.</p>
|
|
390
|
+
)}
|
|
391
|
+
{images.items && images.items.length > 0 && (
|
|
392
|
+
<>
|
|
393
|
+
<ul>
|
|
394
|
+
{images.items.map((option: any, index: number) => (
|
|
395
|
+
<fieldset className='edit-block' key={index}>
|
|
396
|
+
<button
|
|
397
|
+
type='button'
|
|
398
|
+
className='remove-column'
|
|
399
|
+
onClick={() => {
|
|
400
|
+
images.remove(index)
|
|
401
|
+
}}
|
|
402
|
+
>
|
|
403
|
+
Remove
|
|
404
|
+
</button>
|
|
405
|
+
<label>
|
|
406
|
+
<span className='edit-label column-heading'>
|
|
407
|
+
<strong>{'Image #' + (index + 1)}</strong>
|
|
408
|
+
</span>
|
|
409
|
+
|
|
410
|
+
<div className='accordion__panel-row align-center'>
|
|
411
|
+
<div className='accordion__panel-col flex-auto'>If Value</div>
|
|
412
|
+
<div className='accordion__panel-col flex-auto'>
|
|
413
|
+
<Select
|
|
414
|
+
label=''
|
|
415
|
+
value={option.arguments[0]?.operator || ''}
|
|
416
|
+
options={DATA_OPERATORS}
|
|
417
|
+
onChange={e => {
|
|
418
|
+
images.updateNested(index, 'arguments', 0, 'operator', e.target.value)
|
|
419
|
+
}}
|
|
420
|
+
/>
|
|
421
|
+
</div>
|
|
422
|
+
<div className='accordion__panel-col flex-grow flex-shrink'>
|
|
423
|
+
<input
|
|
424
|
+
type='number'
|
|
425
|
+
value={option.arguments[0]?.threshold || ''}
|
|
426
|
+
onChange={e => {
|
|
427
|
+
images.updateNested(index, 'arguments', 0, 'threshold', e.target.value)
|
|
428
|
+
}}
|
|
429
|
+
/>
|
|
430
|
+
</div>
|
|
431
|
+
</div>
|
|
432
|
+
|
|
433
|
+
<div className='accordion__panel-row mb-2 align-center'>
|
|
434
|
+
<div className='accordion__panel-col flex-grow'>
|
|
435
|
+
<Select
|
|
436
|
+
label=''
|
|
437
|
+
value={option.secondArgument ? 'and' : 'then'}
|
|
438
|
+
options={[
|
|
439
|
+
{ value: 'then', label: 'Then' },
|
|
440
|
+
{ value: 'and', label: 'And' }
|
|
441
|
+
]}
|
|
442
|
+
onChange={e => {
|
|
443
|
+
if ('then' === e.target.value) {
|
|
444
|
+
images.updateField(index, 'secondArgument', false)
|
|
445
|
+
removeDynamicArgument(index)
|
|
446
|
+
}
|
|
447
|
+
if ('and' === e.target.value) {
|
|
448
|
+
images.updateField(index, 'secondArgument', true)
|
|
449
|
+
}
|
|
450
|
+
}}
|
|
451
|
+
/>
|
|
452
|
+
</div>
|
|
453
|
+
</div>
|
|
454
|
+
|
|
455
|
+
{option.secondArgument && true === option.secondArgument && (
|
|
456
|
+
<>
|
|
457
|
+
<div className='accordion__panel-row align-center'>
|
|
458
|
+
<div className='accordion__panel-col flex-auto'>If Value</div>
|
|
459
|
+
<div className='accordion__panel-col flex-auto'>
|
|
460
|
+
<Select
|
|
461
|
+
label=''
|
|
462
|
+
value={option.arguments[1]?.operator || ''}
|
|
463
|
+
options={DATA_OPERATORS}
|
|
464
|
+
onChange={e => {
|
|
465
|
+
images.updateNested(index, 'arguments', 1, 'operator', e.target.value)
|
|
466
|
+
}}
|
|
467
|
+
/>
|
|
468
|
+
</div>
|
|
469
|
+
<div className='accordion__panel-col flex-grow flex-shrink'>
|
|
470
|
+
<input
|
|
471
|
+
type='number'
|
|
472
|
+
value={option.arguments[1]?.threshold || ''}
|
|
473
|
+
onChange={e => {
|
|
474
|
+
images.updateNested(index, 'arguments', 1, 'threshold', e.target.value)
|
|
475
|
+
}}
|
|
476
|
+
/>
|
|
477
|
+
</div>
|
|
478
|
+
</div>
|
|
479
|
+
<div className='accordion__panel-row mb-2 align-center text-center text-capitalize'>
|
|
480
|
+
<div className='accordion__panel-col flex-grow'>Then</div>
|
|
481
|
+
</div>
|
|
482
|
+
</>
|
|
483
|
+
)}
|
|
484
|
+
|
|
485
|
+
<div className='accordion__panel-row mb-2 align-center'>
|
|
486
|
+
<div className='accordion__panel-col flex-auto'>Show</div>
|
|
487
|
+
<div className='accordion__panel-col flex-grow'>
|
|
488
|
+
<input
|
|
489
|
+
type='text'
|
|
490
|
+
value={option.source || ''}
|
|
491
|
+
onChange={e => {
|
|
492
|
+
images.updateField(index, 'source', e.target.value)
|
|
493
|
+
}}
|
|
494
|
+
/>
|
|
495
|
+
</div>
|
|
496
|
+
</div>
|
|
497
|
+
|
|
498
|
+
<div className='accordion__panel-row mb-2 align-center'>
|
|
499
|
+
<div className='accordion__panel-col flex-auto'>Alt Text</div>
|
|
500
|
+
<div className='accordion__panel-col flex-grow'>
|
|
501
|
+
<input
|
|
502
|
+
type='text'
|
|
503
|
+
value={option.alt || ''}
|
|
504
|
+
onChange={e => {
|
|
505
|
+
images.updateField(index, 'alt', e.target.value)
|
|
506
|
+
}}
|
|
507
|
+
/>
|
|
508
|
+
</div>
|
|
509
|
+
</div>
|
|
510
|
+
</label>
|
|
511
|
+
</fieldset>
|
|
512
|
+
))}
|
|
513
|
+
</ul>
|
|
514
|
+
</>
|
|
515
|
+
)}
|
|
516
|
+
<button type='button' onClick={images.add} className='btn btn-primary full-width'>
|
|
517
|
+
Add Dynamic Image
|
|
518
|
+
</button>
|
|
519
|
+
</>
|
|
520
|
+
)}
|
|
521
|
+
</Accordion.Section>
|
|
522
|
+
)}
|
|
523
|
+
|
|
524
|
+
<Accordion.Section title='Markup Variables'>
|
|
525
|
+
<PanelMarkup
|
|
526
|
+
name='Markup Variables'
|
|
527
|
+
markupVariables={config.markupVariables || []}
|
|
528
|
+
data={data}
|
|
529
|
+
enableMarkupVariables={config.enableMarkupVariables || false}
|
|
530
|
+
onMarkupVariablesChange={variables => updateField(null, null, 'markupVariables', variables)}
|
|
531
|
+
onToggleEnable={enabled => updateField(null, null, 'enableMarkupVariables', enabled)}
|
|
532
|
+
withAccordion={false}
|
|
533
|
+
/>
|
|
534
|
+
</Accordion.Section>
|
|
535
|
+
<AdvancedEditor loadConfig={updateConfig} config={config} convertStateToConfig={convertStateToConfig} />
|
|
536
|
+
</Accordion>
|
|
537
|
+
)}
|
|
538
|
+
</BaseEditorPanel>
|
|
539
|
+
)
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
export default EditorPanel
|
package/src/constants.ts
CHANGED
|
@@ -1,32 +1,11 @@
|
|
|
1
|
-
export const DATA_FUNCTION_MAX = 'Max'
|
|
2
|
-
export const DATA_FUNCTION_COUNT = 'Count'
|
|
3
|
-
export const DATA_FUNCTION_MEAN = 'Mean (Average)'
|
|
4
|
-
export const DATA_FUNCTION_MEDIAN = 'Median'
|
|
5
|
-
export const DATA_FUNCTION_MIN = 'Min'
|
|
6
|
-
export const DATA_FUNCTION_MODE = 'Mode'
|
|
7
|
-
export const DATA_FUNCTION_RANGE = 'Range'
|
|
8
|
-
export const DATA_FUNCTION_SUM = 'Sum'
|
|
9
|
-
export const DATA_FUNCTIONS = [
|
|
10
|
-
DATA_FUNCTION_COUNT,
|
|
11
|
-
DATA_FUNCTION_MAX,
|
|
12
|
-
DATA_FUNCTION_MEAN,
|
|
13
|
-
DATA_FUNCTION_MEDIAN,
|
|
14
|
-
DATA_FUNCTION_MIN,
|
|
15
|
-
DATA_FUNCTION_MODE,
|
|
16
|
-
DATA_FUNCTION_RANGE,
|
|
17
|
-
DATA_FUNCTION_SUM
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
export const BITE_LOCATION_TITLE = 'title'
|
|
21
|
-
export const BITE_LOCATION_BODY = 'body'
|
|
22
|
-
export const BITE_LOCATION_GRAPHIC = 'graphic'
|
|
23
1
|
export const BITE_LOCATIONS = {
|
|
24
2
|
graphic: 'Graphic',
|
|
25
3
|
split: 'Split Graphic and Message',
|
|
26
4
|
title: 'Value above Message',
|
|
27
5
|
body: 'Value before Message',
|
|
28
6
|
end: 'Value after Message',
|
|
29
|
-
gradient: 'Gradient'
|
|
7
|
+
gradient: 'Gradient',
|
|
8
|
+
tp5: 'TP5 Style'
|
|
30
9
|
}
|
|
31
10
|
|
|
32
11
|
export const IMAGE_POSITION_LEFT = 'Left'
|
|
@@ -34,33 +13,3 @@ export const IMAGE_POSITION_RIGHT = 'Right'
|
|
|
34
13
|
export const IMAGE_POSITION_TOP = 'Top'
|
|
35
14
|
export const IMAGE_POSITION_BOTTOM = 'Bottom'
|
|
36
15
|
export const IMAGE_POSITIONS = [IMAGE_POSITION_LEFT, IMAGE_POSITION_RIGHT, IMAGE_POSITION_TOP, IMAGE_POSITION_BOTTOM]
|
|
37
|
-
|
|
38
|
-
export const DATA_OPERATOR_LESS = '<'
|
|
39
|
-
export const DATA_OPERATOR_GREATER = '>'
|
|
40
|
-
export const DATA_OPERATOR_LESSEQUAL = '<='
|
|
41
|
-
export const DATA_OPERATOR_GREATEREQUAL = '>='
|
|
42
|
-
export const DATA_OPERATOR_EQUAL = '='
|
|
43
|
-
export const DATA_OPERATOR_NOTEQUAL = '≠'
|
|
44
|
-
|
|
45
|
-
export const DATA_OPERATORS = [
|
|
46
|
-
DATA_OPERATOR_LESS,
|
|
47
|
-
DATA_OPERATOR_GREATER,
|
|
48
|
-
DATA_OPERATOR_LESSEQUAL,
|
|
49
|
-
DATA_OPERATOR_GREATEREQUAL,
|
|
50
|
-
DATA_OPERATOR_EQUAL,
|
|
51
|
-
DATA_OPERATOR_NOTEQUAL
|
|
52
|
-
]
|
|
53
|
-
|
|
54
|
-
export const HEADER_COLORS = [
|
|
55
|
-
'theme-blue',
|
|
56
|
-
'theme-purple',
|
|
57
|
-
'theme-brown',
|
|
58
|
-
'theme-teal',
|
|
59
|
-
'theme-pink',
|
|
60
|
-
'theme-orange',
|
|
61
|
-
'theme-slate',
|
|
62
|
-
'theme-indigo',
|
|
63
|
-
'theme-cyan',
|
|
64
|
-
'theme-green',
|
|
65
|
-
'theme-amber'
|
|
66
|
-
]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<?xml version="1.0" standalone="no"?>
|
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
|
3
|
+
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="481.000000pt" height="563.000000pt" viewBox="0 0 481.000000 563.000000" preserveAspectRatio="xMidYMid meet">
|
|
4
|
+
<g transform="translate(0.000000,563.000000) scale(0.100000,-0.100000)" fill="#2c7a99" stroke="none">
|
|
5
|
+
<path d="M890 5514 c-161 -43 -308 -201 -354 -381 -14 -55 -16 -314 -16 -2527 0 -2015 2 -2466 13 -2466 7 0 51 14 97 30 47 17 92 33 100 35 8 2 16 4 18 5 1 2 7 4 12 5 6 1 11 3 13 4 1 2 13 4 26 7 14 2 30 9 38 15 7 6 13 8 13 4 0 -4 7 -2 15 5 8 7 15 10 15 6 0 -3 17 1 38 10 49 21 856 293 905 305 21 5 45 13 55 19 9 5 40 16 67 24 28 8 162 52 299 99 l249 85 151 -53 c83 -29 253 -90 379 -134 264 -94 556 -198 974 -346 164 -58 308 -110 321 -115 13 -6 27 -10 33 -10 11 0 8 4951 -4 4994 -22 80 -84 183 -152 252 -75 76 -141 114 -233 133 -38 8 -477 11 -1535 10 -1268 0 -1490 -3 -1537 -15z m2687 -1570 c49 -31 82 -134 64 -201 -10 -37 -41 -64 -422 -369 -227 -181 -430 -341 -452 -356 -43 -30 -84 -35 -136 -17 -17 6 -156 107 -309 224 l-277 213 -40 -31 c-50 -39 -318 -259 -325 -267 -3 -3 -27 -24 -55 -45 -27 -22 -55 -44 -61 -50 -86 -77 -253 -202 -277 -207 -20 -4 -53 -1 -84 8 -69 19 -105 64 -111 140 -6 70 8 100 69 149 105 84 134 107 168 133 19 15 92 74 164 132 71 58 144 116 162 130 86 68 114 90 187 150 124 102 156 120 206 120 23 0 57 -7 75 -16 18 -9 145 -103 282 -209 283 -217 293 -224 303 -210 4 6 42 39 86 74 43 35 88 71 100 81 31 27 153 127 231 190 37 30 111 91 164 135 142 119 217 145 288 99z m-1431 -983 c60 -44 59 -29 62 -601 3 -596 4 -589 -70 -638 -76 -49 -171 -29 -228 50 l-30 41 0 526 c0 591 -3 569 75 623 35 25 48 28 100 25 44 -2 69 -9 91 -26z m1252 15 c37 -19 67 -55 81 -95 8 -25 10 -183 9 -555 -3 -579 -1 -555 -71 -603 -67 -45 -144 -35 -211 27 l-41 39 -3 543 -2 544 23 35 c46 68 149 99 215 65z m-610 -343 c71 -57 71 -57 71 -448 0 -322 -1 -353 -19 -392 -27 -60 -83 -95 -155 -95 -63 -1 -95 16 -132 72 -23 33 -23 36 -23 407 0 406 -1 401 57 455 34 32 54 38 116 34 35 -2 57 -11 85 -33z m-1313 -142 c54 -24 92 -71 100 -124 4 -23 5 -159 3 -302 -3 -293 -3 -293 -82 -343 -66 -41 -160 -30 -207 24 -34 40 -39 84 -39 361 0 303 3 322 61 366 53 39 105 45 164 18z"/>
|
|
6
|
+
</g>
|
|
7
|
+
</svg>
|