@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
|
@@ -1,719 +0,0 @@
|
|
|
1
|
-
import React, { memo, useContext, useEffect, useState } from 'react'
|
|
2
|
-
import cloneConfig from '@cdc/core/helpers/cloneConfig'
|
|
3
|
-
import _ from 'lodash'
|
|
4
|
-
import {
|
|
5
|
-
Accordion,
|
|
6
|
-
AccordionItem,
|
|
7
|
-
AccordionItemButton,
|
|
8
|
-
AccordionItemHeading,
|
|
9
|
-
AccordionItemPanel
|
|
10
|
-
} from 'react-accessible-accordion'
|
|
11
|
-
|
|
12
|
-
import Context from '../context'
|
|
13
|
-
import WarningImage from '@cdc/core/assets/icon-warning-circle.svg'
|
|
14
|
-
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
15
|
-
import Icon from '@cdc/core/components/ui/Icon'
|
|
16
|
-
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
17
|
-
import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
|
|
18
|
-
import { BITE_LOCATIONS, DATA_FUNCTIONS, IMAGE_POSITIONS, DATA_OPERATORS, HEADER_COLORS } from './../constants'
|
|
19
|
-
import Layout from '@cdc/core/components/Layout'
|
|
20
|
-
import { Select, TextField, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
|
|
21
|
-
import Button from '@cdc/core/components/elements/Button'
|
|
22
|
-
import PanelMarkup from '@cdc/core/components/EditorPanel/components/PanelMarkup'
|
|
23
|
-
|
|
24
|
-
const EditorPanel = memo(() => {
|
|
25
|
-
const { config, updateConfig, loading, data, setParentConfig, isDashboard, isEditor } = useContext(Context)
|
|
26
|
-
|
|
27
|
-
const [displayPanel, setDisplayPanel] = useState(true)
|
|
28
|
-
|
|
29
|
-
const updateField = updateFieldFactory(config, updateConfig, true)
|
|
30
|
-
|
|
31
|
-
const missingRequiredSections = () => {
|
|
32
|
-
//Whether to show error message if something is required to show a data-bite and isn't filled in
|
|
33
|
-
return false
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
// Pass up to Editor if needed
|
|
38
|
-
if (setParentConfig) {
|
|
39
|
-
const newConfig = convertStateToConfig()
|
|
40
|
-
delete newConfig.newViz
|
|
41
|
-
|
|
42
|
-
setParentConfig(newConfig)
|
|
43
|
-
}
|
|
44
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
45
|
-
}, [config])
|
|
46
|
-
|
|
47
|
-
const onBackClick = () => {
|
|
48
|
-
setDisplayPanel(!displayPanel)
|
|
49
|
-
updateConfig({
|
|
50
|
-
...config,
|
|
51
|
-
showEditorPanel: !displayPanel
|
|
52
|
-
})
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const convertStateToConfig = () => {
|
|
56
|
-
let strippedState = cloneConfig(config)
|
|
57
|
-
//if(false === missingRequiredSections()) {
|
|
58
|
-
//strippedState.newViz
|
|
59
|
-
//}
|
|
60
|
-
delete strippedState.runtime
|
|
61
|
-
|
|
62
|
-
return strippedState
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Filters -----------------------------------------------
|
|
66
|
-
const removeFilter = index => {
|
|
67
|
-
let filters = [...config.filters]
|
|
68
|
-
|
|
69
|
-
filters.splice(index, 1)
|
|
70
|
-
|
|
71
|
-
updateConfig({ ...config, filters })
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const updateFilterProp = (name, index, value) => {
|
|
75
|
-
let filters = [...config.filters]
|
|
76
|
-
|
|
77
|
-
filters[index][name] = value
|
|
78
|
-
|
|
79
|
-
updateConfig({ ...config, filters })
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const addNewFilter = () => {
|
|
83
|
-
let filters = config.filters ? [...config.filters] : []
|
|
84
|
-
|
|
85
|
-
filters.push({ values: [] })
|
|
86
|
-
|
|
87
|
-
updateConfig({ ...config, filters })
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const getColumns = (filter = true) => {
|
|
91
|
-
let columns = {}
|
|
92
|
-
if (data.length) {
|
|
93
|
-
data.map(row => {
|
|
94
|
-
return Object.keys(row).forEach(columnName => (columns[columnName] = true))
|
|
95
|
-
})
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return Object.keys(columns)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const getFilterColumnValues = index => {
|
|
102
|
-
let filterDataOptions = []
|
|
103
|
-
const filterColumnName = config.filters[index].columnName
|
|
104
|
-
if (data && filterColumnName) {
|
|
105
|
-
data.forEach(function (row) {
|
|
106
|
-
if (undefined !== row[filterColumnName] && -1 === filterDataOptions.indexOf(row[filterColumnName])) {
|
|
107
|
-
filterDataOptions.push(row[filterColumnName])
|
|
108
|
-
}
|
|
109
|
-
})
|
|
110
|
-
filterDataOptions.sort()
|
|
111
|
-
}
|
|
112
|
-
return filterDataOptions
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Dynamic Images ----------------------------------------
|
|
116
|
-
const updateDynamicImage = (name, index, subindex = null, value) => {
|
|
117
|
-
let imageOptions = [...config.imageData.options]
|
|
118
|
-
null === subindex ? (imageOptions[index][name] = value) : (imageOptions[index].arguments[subindex][name] = value)
|
|
119
|
-
|
|
120
|
-
let payload = { ...config.imageData, options: imageOptions }
|
|
121
|
-
updateConfig({ ...config, imageData: payload })
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const setDynamicArgument = (optionIndex, name, value) => {
|
|
125
|
-
let imageArguments = [...config.imageData.options[optionIndex].arguments]
|
|
126
|
-
imageArguments[1] = { ...imageArguments[1], [name]: value }
|
|
127
|
-
let argumentsPayload = { ...config.imageData.options[optionIndex], arguments: imageArguments }
|
|
128
|
-
let optionsPayload = [...config.imageData.options]
|
|
129
|
-
optionsPayload[optionIndex] = argumentsPayload
|
|
130
|
-
let payload = { ...config.imageData, options: optionsPayload }
|
|
131
|
-
updateConfig({ ...config, imageData: payload })
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const removeDynamicArgument = optionIndex => {
|
|
135
|
-
if (config.imageData.options[optionIndex].arguments.length > 1) {
|
|
136
|
-
let imageArguments = [...config.imageData.options[optionIndex].arguments]
|
|
137
|
-
imageArguments.pop()
|
|
138
|
-
let argumentsPayload = { ...config.imageData.options[optionIndex], arguments: imageArguments }
|
|
139
|
-
let optionsPayload = [...config.imageData.options]
|
|
140
|
-
optionsPayload[optionIndex] = argumentsPayload
|
|
141
|
-
let payload = { ...config.imageData, options: optionsPayload }
|
|
142
|
-
updateConfig({ ...config, imageData: payload })
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const addDynamicImage = () => {
|
|
147
|
-
let imageOptions = config.imageData.options ? [...config.imageData.options] : []
|
|
148
|
-
imageOptions.push({ source: '', arguments: [{ operator: '', threshold: '' }], alt: '', secondArgument: false })
|
|
149
|
-
|
|
150
|
-
let payload = { ...config.imageData, options: imageOptions }
|
|
151
|
-
updateConfig({ ...config, imageData: payload })
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const removeDynamicImage = index => {
|
|
155
|
-
let imageOptions = [...config.imageData.options]
|
|
156
|
-
imageOptions.splice(index, 1)
|
|
157
|
-
|
|
158
|
-
let payload = { ...config.imageData, options: imageOptions }
|
|
159
|
-
updateConfig({ ...config, imageData: payload })
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// General -----------------------------------------------
|
|
163
|
-
if (loading) {
|
|
164
|
-
return null
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return (
|
|
168
|
-
<ErrorBoundary component='EditorPanel'>
|
|
169
|
-
<Layout.Sidebar
|
|
170
|
-
isEditor={true}
|
|
171
|
-
config={config}
|
|
172
|
-
title='Configure Data Bites'
|
|
173
|
-
onBackClick={onBackClick}
|
|
174
|
-
displayPanel={displayPanel}
|
|
175
|
-
>
|
|
176
|
-
<section className='form-container'>
|
|
177
|
-
<form>
|
|
178
|
-
<Accordion allowZeroExpanded={true}>
|
|
179
|
-
<AccordionItem>
|
|
180
|
-
{' '}
|
|
181
|
-
{/* General */}
|
|
182
|
-
<AccordionItemHeading>
|
|
183
|
-
<AccordionItemButton>General</AccordionItemButton>
|
|
184
|
-
</AccordionItemHeading>
|
|
185
|
-
<AccordionItemPanel>
|
|
186
|
-
<Select
|
|
187
|
-
value={config.biteStyle}
|
|
188
|
-
fieldName='biteStyle'
|
|
189
|
-
label='Data Bite Style'
|
|
190
|
-
updateField={updateField}
|
|
191
|
-
options={Object.entries(BITE_LOCATIONS).map(([key, value]) => ({ value: key, label: value }))}
|
|
192
|
-
initial='Select'
|
|
193
|
-
/>
|
|
194
|
-
<TextField
|
|
195
|
-
value={config.title}
|
|
196
|
-
fieldName='title'
|
|
197
|
-
label='Title'
|
|
198
|
-
placeholder='Data Bite Title'
|
|
199
|
-
updateField={updateField}
|
|
200
|
-
/>
|
|
201
|
-
<CheckBox
|
|
202
|
-
value={config.visual?.showTitle}
|
|
203
|
-
section='visual'
|
|
204
|
-
checked={config.visual?.showTitle}
|
|
205
|
-
fieldName='showTitle'
|
|
206
|
-
label='Show Title'
|
|
207
|
-
updateField={updateField}
|
|
208
|
-
/>
|
|
209
|
-
|
|
210
|
-
<TextField
|
|
211
|
-
type='textarea'
|
|
212
|
-
value={config.biteBody}
|
|
213
|
-
fieldName='biteBody'
|
|
214
|
-
label='Message'
|
|
215
|
-
updateField={updateField}
|
|
216
|
-
tooltip={
|
|
217
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
218
|
-
<Tooltip.Target>
|
|
219
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
220
|
-
</Tooltip.Target>
|
|
221
|
-
<Tooltip.Content>
|
|
222
|
-
<p>
|
|
223
|
-
Enter the message text for the visualization. The following HTML tags are supported: strong,
|
|
224
|
-
em, sup, and sub.
|
|
225
|
-
</p>
|
|
226
|
-
</Tooltip.Content>
|
|
227
|
-
</Tooltip>
|
|
228
|
-
}
|
|
229
|
-
/>
|
|
230
|
-
<TextField
|
|
231
|
-
value={config.subtext}
|
|
232
|
-
fieldName='subtext'
|
|
233
|
-
label='Subtext/Citation'
|
|
234
|
-
placeholder='Data Bite Subtext or Citation'
|
|
235
|
-
updateField={updateField}
|
|
236
|
-
tooltip={
|
|
237
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
238
|
-
<Tooltip.Target>
|
|
239
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
240
|
-
</Tooltip.Target>
|
|
241
|
-
<Tooltip.Content>
|
|
242
|
-
<p>
|
|
243
|
-
Enter supporting text to display below the data visualization, if applicable. The following
|
|
244
|
-
HTML tags are supported: strong, em, sup, and sub. You can also use markup variables like{' '}
|
|
245
|
-
{'{{variable-name}}'} to display dynamic data.
|
|
246
|
-
</p>
|
|
247
|
-
</Tooltip.Content>
|
|
248
|
-
</Tooltip>
|
|
249
|
-
}
|
|
250
|
-
/>
|
|
251
|
-
</AccordionItemPanel>
|
|
252
|
-
</AccordionItem>
|
|
253
|
-
|
|
254
|
-
<AccordionItem>
|
|
255
|
-
{' '}
|
|
256
|
-
{/*Data*/}
|
|
257
|
-
<AccordionItemHeading>
|
|
258
|
-
<AccordionItemButton>
|
|
259
|
-
Data{' '}
|
|
260
|
-
{(!config.dataColumn || !config.dataFunction) && (
|
|
261
|
-
<WarningImage width='25' className='warning-icon' />
|
|
262
|
-
)}
|
|
263
|
-
</AccordionItemButton>
|
|
264
|
-
</AccordionItemHeading>
|
|
265
|
-
<AccordionItemPanel>
|
|
266
|
-
<ul className='column-edit'>
|
|
267
|
-
<li className='two-col'>
|
|
268
|
-
<Select
|
|
269
|
-
value={config.dataColumn || ''}
|
|
270
|
-
fieldName='dataColumn'
|
|
271
|
-
label='Data Column'
|
|
272
|
-
updateField={updateField}
|
|
273
|
-
initial='Select'
|
|
274
|
-
required={true}
|
|
275
|
-
options={getColumns() ? Array.from(getColumns()) : []}
|
|
276
|
-
/>
|
|
277
|
-
<Select
|
|
278
|
-
value={config.dataFunction || ''}
|
|
279
|
-
fieldName='dataFunction'
|
|
280
|
-
label='Data Function'
|
|
281
|
-
updateField={updateField}
|
|
282
|
-
initial='Select'
|
|
283
|
-
required={true}
|
|
284
|
-
options={
|
|
285
|
-
Array.isArray(DATA_FUNCTIONS)
|
|
286
|
-
? DATA_FUNCTIONS
|
|
287
|
-
: DATA_FUNCTIONS
|
|
288
|
-
? Object.values(DATA_FUNCTIONS)
|
|
289
|
-
: []
|
|
290
|
-
}
|
|
291
|
-
/>
|
|
292
|
-
</li>
|
|
293
|
-
</ul>
|
|
294
|
-
<span className='divider-heading'>Number Formatting</span>
|
|
295
|
-
<ul className='column-edit'>
|
|
296
|
-
<li className='three-col'>
|
|
297
|
-
<TextField
|
|
298
|
-
value={config.dataFormat.prefix}
|
|
299
|
-
section='dataFormat'
|
|
300
|
-
fieldName='prefix'
|
|
301
|
-
label='Prefix'
|
|
302
|
-
updateField={updateField}
|
|
303
|
-
/>
|
|
304
|
-
<TextField
|
|
305
|
-
value={config.dataFormat.suffix}
|
|
306
|
-
section='dataFormat'
|
|
307
|
-
fieldName='suffix'
|
|
308
|
-
label='Suffix'
|
|
309
|
-
updateField={updateField}
|
|
310
|
-
/>
|
|
311
|
-
<TextField
|
|
312
|
-
type='number'
|
|
313
|
-
value={config.dataFormat.roundToPlace}
|
|
314
|
-
section='dataFormat'
|
|
315
|
-
fieldName='roundToPlace'
|
|
316
|
-
label='Round'
|
|
317
|
-
updateField={updateField}
|
|
318
|
-
min='0'
|
|
319
|
-
max='99'
|
|
320
|
-
/>
|
|
321
|
-
</li>
|
|
322
|
-
</ul>
|
|
323
|
-
<CheckBox
|
|
324
|
-
value={config.dataFormat.commas}
|
|
325
|
-
section='dataFormat'
|
|
326
|
-
fieldName='commas'
|
|
327
|
-
label='Add commas'
|
|
328
|
-
updateField={updateField}
|
|
329
|
-
/>
|
|
330
|
-
<CheckBox
|
|
331
|
-
value={config.dataFormat.ignoreZeros}
|
|
332
|
-
section='dataFormat'
|
|
333
|
-
fieldName='ignoreZeros'
|
|
334
|
-
label='Ignore Zeros'
|
|
335
|
-
updateField={updateField}
|
|
336
|
-
/>
|
|
337
|
-
<hr className='accordion__divider' />
|
|
338
|
-
|
|
339
|
-
<label style={{ marginBottom: '1rem' }}>
|
|
340
|
-
<span className='edit-label'>
|
|
341
|
-
Data Point Filters
|
|
342
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
343
|
-
<Tooltip.Target>
|
|
344
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
345
|
-
</Tooltip.Target>
|
|
346
|
-
<Tooltip.Content>
|
|
347
|
-
<p>
|
|
348
|
-
To refine the highlighted data point, specify one or more filters (e.g., "Male" and "Female"
|
|
349
|
-
for a column called "Sex").
|
|
350
|
-
</p>
|
|
351
|
-
</Tooltip.Content>
|
|
352
|
-
</Tooltip>
|
|
353
|
-
</span>
|
|
354
|
-
</label>
|
|
355
|
-
{config.filters && (
|
|
356
|
-
<ul className='filters-list'>
|
|
357
|
-
{config.filters.map((filter, index) => (
|
|
358
|
-
<fieldset className='edit-block' key={index}>
|
|
359
|
-
<button
|
|
360
|
-
type='button'
|
|
361
|
-
className='btn btn-danger'
|
|
362
|
-
onClick={() => {
|
|
363
|
-
removeFilter(index)
|
|
364
|
-
}}
|
|
365
|
-
>
|
|
366
|
-
Remove
|
|
367
|
-
</button>
|
|
368
|
-
<Select
|
|
369
|
-
value={filter.columnName ? filter.columnName : ''}
|
|
370
|
-
fieldName='columnName'
|
|
371
|
-
label={'Column Name'}
|
|
372
|
-
updateField={(section, subsection, fieldName, value) =>
|
|
373
|
-
updateFilterProp(fieldName, index, value)
|
|
374
|
-
}
|
|
375
|
-
options={getColumns()}
|
|
376
|
-
initial='- Select Option -'
|
|
377
|
-
/>
|
|
378
|
-
<Select
|
|
379
|
-
value={filter.columnValue || ''}
|
|
380
|
-
fieldName='columnValue'
|
|
381
|
-
label='Column Value'
|
|
382
|
-
updateField={(section, subsection, fieldName, value) =>
|
|
383
|
-
updateFilterProp(fieldName, index, value)
|
|
384
|
-
}
|
|
385
|
-
options={Array.isArray(getFilterColumnValues(index)) ? getFilterColumnValues(index) : []}
|
|
386
|
-
initial='- Select Option -'
|
|
387
|
-
/>
|
|
388
|
-
</fieldset>
|
|
389
|
-
))}
|
|
390
|
-
</ul>
|
|
391
|
-
)}
|
|
392
|
-
{(!config.filters || config.filters.length === 0) && (
|
|
393
|
-
<div>
|
|
394
|
-
<fieldset className='edit-block'>
|
|
395
|
-
<p style={{ textAlign: 'center' }}>There are currently no filters.</p>
|
|
396
|
-
</fieldset>
|
|
397
|
-
</div>
|
|
398
|
-
)}
|
|
399
|
-
<Button type='button' onClick={addNewFilter} className='btn btn-primary full-width mt-3'>
|
|
400
|
-
Add Filter
|
|
401
|
-
</Button>
|
|
402
|
-
</AccordionItemPanel>
|
|
403
|
-
</AccordionItem>
|
|
404
|
-
|
|
405
|
-
<AccordionItem>
|
|
406
|
-
{' '}
|
|
407
|
-
{/*Visual*/}
|
|
408
|
-
<AccordionItemHeading>
|
|
409
|
-
<AccordionItemButton>Visual</AccordionItemButton>
|
|
410
|
-
</AccordionItemHeading>
|
|
411
|
-
<AccordionItemPanel>
|
|
412
|
-
<TextField
|
|
413
|
-
type='number'
|
|
414
|
-
value={config.biteFontSize}
|
|
415
|
-
fieldName='biteFontSize'
|
|
416
|
-
label='Bite Font Size'
|
|
417
|
-
updateField={updateField}
|
|
418
|
-
min='17'
|
|
419
|
-
max='65'
|
|
420
|
-
/>
|
|
421
|
-
<Select
|
|
422
|
-
value={config.fontSize}
|
|
423
|
-
fieldName='fontSize'
|
|
424
|
-
label='Overall Font Size'
|
|
425
|
-
updateField={updateField}
|
|
426
|
-
options={['small', 'medium', 'large']}
|
|
427
|
-
/>
|
|
428
|
-
<div className='checkbox-group'>
|
|
429
|
-
<CheckBox
|
|
430
|
-
value={config.visual?.border}
|
|
431
|
-
section='visual'
|
|
432
|
-
fieldName='border'
|
|
433
|
-
label='Display Border'
|
|
434
|
-
updateField={updateField}
|
|
435
|
-
/>
|
|
436
|
-
<CheckBox
|
|
437
|
-
value={config.visual?.borderColorTheme}
|
|
438
|
-
section='visual'
|
|
439
|
-
fieldName='borderColorTheme'
|
|
440
|
-
label='Use Border Color Theme'
|
|
441
|
-
updateField={updateField}
|
|
442
|
-
/>
|
|
443
|
-
<CheckBox
|
|
444
|
-
value={config.visual?.accent}
|
|
445
|
-
section='visual'
|
|
446
|
-
fieldName='accent'
|
|
447
|
-
label='Use Accent Style'
|
|
448
|
-
updateField={updateField}
|
|
449
|
-
/>
|
|
450
|
-
<CheckBox
|
|
451
|
-
value={config.visual?.background}
|
|
452
|
-
section='visual'
|
|
453
|
-
fieldName='background'
|
|
454
|
-
label='Use Theme Background Color'
|
|
455
|
-
updateField={updateField}
|
|
456
|
-
/>
|
|
457
|
-
<CheckBox
|
|
458
|
-
value={config.visual?.hideBackgroundColor}
|
|
459
|
-
section='visual'
|
|
460
|
-
fieldName='hideBackgroundColor'
|
|
461
|
-
label='Hide Background Color'
|
|
462
|
-
updateField={updateField}
|
|
463
|
-
/>
|
|
464
|
-
</div>
|
|
465
|
-
<label>
|
|
466
|
-
<span className='edit-label'>Theme</span>
|
|
467
|
-
<ul className='color-palette'>
|
|
468
|
-
{HEADER_COLORS.map(palette => (
|
|
469
|
-
<button
|
|
470
|
-
title={palette}
|
|
471
|
-
key={palette}
|
|
472
|
-
onClick={e => {
|
|
473
|
-
e.preventDefault()
|
|
474
|
-
updateConfig({ ...config, theme: palette })
|
|
475
|
-
}}
|
|
476
|
-
className={config.theme === palette ? 'selected ' + palette : palette}
|
|
477
|
-
/>
|
|
478
|
-
))}
|
|
479
|
-
</ul>
|
|
480
|
-
</label>
|
|
481
|
-
</AccordionItemPanel>
|
|
482
|
-
</AccordionItem>
|
|
483
|
-
|
|
484
|
-
{['title', 'body', 'graphic'].includes(config.biteStyle) && (
|
|
485
|
-
<AccordionItem>
|
|
486
|
-
{' '}
|
|
487
|
-
{/*Image & Dynamic Images*/}
|
|
488
|
-
<AccordionItemHeading>
|
|
489
|
-
<AccordionItemButton>
|
|
490
|
-
Image
|
|
491
|
-
{['dynamic'].includes(config.imageData.display) && 's'}
|
|
492
|
-
</AccordionItemButton>
|
|
493
|
-
</AccordionItemHeading>
|
|
494
|
-
<AccordionItemPanel>
|
|
495
|
-
<Select
|
|
496
|
-
value={config.imageData.display || ''}
|
|
497
|
-
section='imageData'
|
|
498
|
-
fieldName='display'
|
|
499
|
-
label='Image Display Type'
|
|
500
|
-
updateField={updateField}
|
|
501
|
-
options={['none', 'static', 'dynamic']}
|
|
502
|
-
/>
|
|
503
|
-
<Select
|
|
504
|
-
value={config.bitePosition || ''}
|
|
505
|
-
fieldName='bitePosition'
|
|
506
|
-
label='Image/Graphic Position'
|
|
507
|
-
updateField={updateField}
|
|
508
|
-
initial='Select'
|
|
509
|
-
options={IMAGE_POSITIONS}
|
|
510
|
-
/>
|
|
511
|
-
{['static'].includes(config.imageData.display) && (
|
|
512
|
-
<>
|
|
513
|
-
<TextField
|
|
514
|
-
value={config.imageData.url}
|
|
515
|
-
section='imageData'
|
|
516
|
-
fieldName='url'
|
|
517
|
-
label='Image URL'
|
|
518
|
-
updateField={updateField}
|
|
519
|
-
/>
|
|
520
|
-
<TextField
|
|
521
|
-
value={config.imageData.alt}
|
|
522
|
-
section='imageData'
|
|
523
|
-
fieldName='alt'
|
|
524
|
-
label='Alt Text'
|
|
525
|
-
updateField={updateField}
|
|
526
|
-
/>
|
|
527
|
-
</>
|
|
528
|
-
)}
|
|
529
|
-
|
|
530
|
-
{['dynamic'].includes(config.imageData.display) && (
|
|
531
|
-
<>
|
|
532
|
-
<TextField
|
|
533
|
-
value={config.imageData.url || ''}
|
|
534
|
-
section='imageData'
|
|
535
|
-
fieldName='url'
|
|
536
|
-
label='Image URL (default)'
|
|
537
|
-
updateField={updateField}
|
|
538
|
-
/>
|
|
539
|
-
<TextField
|
|
540
|
-
value={config.imageData.alt}
|
|
541
|
-
section='imageData'
|
|
542
|
-
fieldName='alt'
|
|
543
|
-
label='Alt Text (default)'
|
|
544
|
-
updateField={updateField}
|
|
545
|
-
/>
|
|
546
|
-
|
|
547
|
-
<hr className='accordion__divider' />
|
|
548
|
-
|
|
549
|
-
{(!config.imageData.options || config.imageData.options.length === 0) && (
|
|
550
|
-
<p style={{ textAlign: 'center' }}>There are currently no dynamic images.</p>
|
|
551
|
-
)}
|
|
552
|
-
{config.imageData.options && config.imageData.options.length > 0 && (
|
|
553
|
-
<>
|
|
554
|
-
<ul>
|
|
555
|
-
{config.imageData.options.map((option, index) => (
|
|
556
|
-
<fieldset className='edit-block' key={index}>
|
|
557
|
-
<button
|
|
558
|
-
type='button'
|
|
559
|
-
className='remove-column'
|
|
560
|
-
onClick={() => {
|
|
561
|
-
removeDynamicImage(index)
|
|
562
|
-
}}
|
|
563
|
-
>
|
|
564
|
-
Remove
|
|
565
|
-
</button>
|
|
566
|
-
<label>
|
|
567
|
-
<span className='edit-label column-heading'>
|
|
568
|
-
<strong>{'Image #' + (index + 1)}</strong>
|
|
569
|
-
</span>
|
|
570
|
-
|
|
571
|
-
<div className='accordion__panel-row align-center'>
|
|
572
|
-
<div className='accordion__panel-col flex-auto'>If Value</div>
|
|
573
|
-
<div className='accordion__panel-col flex-auto'>
|
|
574
|
-
<select
|
|
575
|
-
value={option.arguments[0]?.operator || ''}
|
|
576
|
-
onChange={e => {
|
|
577
|
-
updateDynamicImage('operator', index, 0, e.target.value)
|
|
578
|
-
}}
|
|
579
|
-
>
|
|
580
|
-
<option value='' disabled />
|
|
581
|
-
{DATA_OPERATORS.map((operator, index) => (
|
|
582
|
-
<option value={operator} key={index}>
|
|
583
|
-
{operator}
|
|
584
|
-
</option>
|
|
585
|
-
))}
|
|
586
|
-
</select>
|
|
587
|
-
</div>
|
|
588
|
-
<div className='accordion__panel-col flex-grow flex-shrink'>
|
|
589
|
-
<input
|
|
590
|
-
type='number'
|
|
591
|
-
value={option.arguments[0]?.threshold || ''}
|
|
592
|
-
onChange={e => {
|
|
593
|
-
updateDynamicImage('threshold', index, 0, e.target.value)
|
|
594
|
-
}}
|
|
595
|
-
/>
|
|
596
|
-
</div>
|
|
597
|
-
</div>
|
|
598
|
-
|
|
599
|
-
<div className='accordion__panel-row mb-2 align-center'>
|
|
600
|
-
<div className='accordion__panel-col flex-grow'>
|
|
601
|
-
<select
|
|
602
|
-
className='border-dashed text-center'
|
|
603
|
-
value={option.secondArgument ? 'and' : 'then'}
|
|
604
|
-
onChange={e => {
|
|
605
|
-
if ('then' === e.target.value) {
|
|
606
|
-
updateDynamicImage('secondArgument', index, null, false)
|
|
607
|
-
removeDynamicArgument(index)
|
|
608
|
-
}
|
|
609
|
-
if ('and' === e.target.value) {
|
|
610
|
-
updateDynamicImage('secondArgument', index, null, true)
|
|
611
|
-
}
|
|
612
|
-
}}
|
|
613
|
-
>
|
|
614
|
-
<option value={'then'}>Then</option>
|
|
615
|
-
<option value={'and'}>And</option>
|
|
616
|
-
</select>
|
|
617
|
-
</div>
|
|
618
|
-
</div>
|
|
619
|
-
|
|
620
|
-
{option.secondArgument && true === option.secondArgument && (
|
|
621
|
-
<>
|
|
622
|
-
<div className='accordion__panel-row align-center'>
|
|
623
|
-
<div className='accordion__panel-col flex-auto'>If Value</div>
|
|
624
|
-
<div className='accordion__panel-col flex-auto'>
|
|
625
|
-
<select
|
|
626
|
-
value={option.arguments[1]?.operator || ''}
|
|
627
|
-
onChange={e => {
|
|
628
|
-
setDynamicArgument(index, 'operator', e.target.value)
|
|
629
|
-
}}
|
|
630
|
-
>
|
|
631
|
-
<option value='' disabled />
|
|
632
|
-
{DATA_OPERATORS.map((operator, index) => (
|
|
633
|
-
<option value={operator} key={index}>
|
|
634
|
-
{operator}
|
|
635
|
-
</option>
|
|
636
|
-
))}
|
|
637
|
-
</select>
|
|
638
|
-
</div>
|
|
639
|
-
<div className='accordion__panel-col flex-grow flex-shrink'>
|
|
640
|
-
<input
|
|
641
|
-
type='number'
|
|
642
|
-
value={option.arguments[1]?.threshold || ''}
|
|
643
|
-
onChange={e => {
|
|
644
|
-
setDynamicArgument(index, 'threshold', e.target.value)
|
|
645
|
-
}}
|
|
646
|
-
/>
|
|
647
|
-
</div>
|
|
648
|
-
</div>
|
|
649
|
-
<div className='accordion__panel-row mb-2 align-center text-center text-capitalize'>
|
|
650
|
-
<div className='accordion__panel-col flex-grow'>Then</div>
|
|
651
|
-
</div>
|
|
652
|
-
</>
|
|
653
|
-
)}
|
|
654
|
-
|
|
655
|
-
<div className='accordion__panel-row mb-2 align-center'>
|
|
656
|
-
<div className='accordion__panel-col flex-auto'>Show</div>
|
|
657
|
-
<div className='accordion__panel-col flex-grow'>
|
|
658
|
-
<input
|
|
659
|
-
type='text'
|
|
660
|
-
value={option.source || ''}
|
|
661
|
-
onChange={e => {
|
|
662
|
-
updateDynamicImage('source', index, null, e.target.value)
|
|
663
|
-
}}
|
|
664
|
-
/>
|
|
665
|
-
</div>
|
|
666
|
-
</div>
|
|
667
|
-
|
|
668
|
-
<div className='accordion__panel-row mb-2 align-center'>
|
|
669
|
-
<div className='accordion__panel-col flex-auto'>Alt Text</div>
|
|
670
|
-
<div className='accordion__panel-col flex-grow'>
|
|
671
|
-
<input
|
|
672
|
-
type='text'
|
|
673
|
-
value={option.alt || ''}
|
|
674
|
-
onChange={e => {
|
|
675
|
-
updateDynamicImage('alt', index, null, e.target.value)
|
|
676
|
-
}}
|
|
677
|
-
/>
|
|
678
|
-
</div>
|
|
679
|
-
</div>
|
|
680
|
-
</label>
|
|
681
|
-
</fieldset>
|
|
682
|
-
))}
|
|
683
|
-
</ul>
|
|
684
|
-
</>
|
|
685
|
-
)}
|
|
686
|
-
<button type='button' onClick={addDynamicImage} className='btn btn-primary full-width'>
|
|
687
|
-
Add Dynamic Image
|
|
688
|
-
</button>
|
|
689
|
-
</>
|
|
690
|
-
)}
|
|
691
|
-
</AccordionItemPanel>
|
|
692
|
-
</AccordionItem>
|
|
693
|
-
)}
|
|
694
|
-
|
|
695
|
-
<AccordionItem>
|
|
696
|
-
<AccordionItemHeading>
|
|
697
|
-
<AccordionItemButton>Markup Variables</AccordionItemButton>
|
|
698
|
-
</AccordionItemHeading>
|
|
699
|
-
<AccordionItemPanel>
|
|
700
|
-
<PanelMarkup
|
|
701
|
-
name='Markup Variables'
|
|
702
|
-
markupVariables={config.markupVariables || []}
|
|
703
|
-
data={data}
|
|
704
|
-
enableMarkupVariables={config.enableMarkupVariables || false}
|
|
705
|
-
onMarkupVariablesChange={variables => updateField(null, null, 'markupVariables', variables)}
|
|
706
|
-
onToggleEnable={enabled => updateField(null, null, 'enableMarkupVariables', enabled)}
|
|
707
|
-
withAccordion={false}
|
|
708
|
-
/>
|
|
709
|
-
</AccordionItemPanel>
|
|
710
|
-
</AccordionItem>
|
|
711
|
-
</Accordion>
|
|
712
|
-
</form>
|
|
713
|
-
</section>
|
|
714
|
-
</Layout.Sidebar>
|
|
715
|
-
</ErrorBoundary>
|
|
716
|
-
)
|
|
717
|
-
})
|
|
718
|
-
|
|
719
|
-
export default EditorPanel
|