@cdc/data-bite 4.26.2 → 4.26.3
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/LICENSE +201 -0
- package/dist/cdcdatabite.js +7008 -6727
- package/package.json +3 -3
- package/src/CdcDataBite.tsx +186 -127
- package/src/_stories/DataBite.Editor.stories.tsx +8 -8
- package/src/_stories/DataBite.stories.tsx +13 -1
- package/src/components/EditorPanel/EditorPanel.tsx +459 -418
- package/src/components/GradientBite.jsx +11 -9
- package/src/data/initial-state.js +3 -2
- package/src/scss/bite.scss +93 -49
- package/src/scss/kpi.scss +17 -2
- package/src/scss/main.scss +1 -1
- package/src/test/CdcDataBite.test.jsx +23 -2
- package/src/types/Config.ts +4 -0
- package/tests/fixtures/data-bite-config-with-metadata.json +35 -0
- package/tests/fixtures/data-with-metadata.json +30 -0
- package/src/images/callout-flag.svg +0 -7
|
@@ -7,7 +7,7 @@ import Context from '../../context'
|
|
|
7
7
|
|
|
8
8
|
// Components
|
|
9
9
|
import { EditorPanel as BaseEditorPanel } from '@cdc/core/components/EditorPanel/EditorPanel'
|
|
10
|
-
import '@cdc/core/
|
|
10
|
+
import '@cdc/core/components/EditorPanel/editor.scss'
|
|
11
11
|
import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
|
|
12
12
|
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
13
13
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
@@ -75,465 +75,506 @@ const EditorPanel: React.FC<DataBiteEditorPanelProps> = () => {
|
|
|
75
75
|
title='Configure Data Bites'
|
|
76
76
|
>
|
|
77
77
|
{({ convertStateToConfig }) => (
|
|
78
|
-
|
|
79
|
-
<Accordion
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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'
|
|
78
|
+
<>
|
|
79
|
+
<Accordion>
|
|
80
|
+
<Accordion.Section title='General'>
|
|
81
|
+
<Select
|
|
82
|
+
value={config.biteStyle}
|
|
83
|
+
fieldName='biteStyle'
|
|
84
|
+
label='Data Bite Style'
|
|
85
|
+
updateField={updateField}
|
|
86
|
+
options={Object.entries(BITE_LOCATIONS).map(([key, value]) => ({ value: key, label: value }))}
|
|
87
|
+
initial='Select'
|
|
88
|
+
/>
|
|
89
|
+
<TextField
|
|
90
|
+
value={config.title}
|
|
91
|
+
fieldName='title'
|
|
92
|
+
label='Title'
|
|
93
|
+
placeholder='Data Bite Title'
|
|
286
94
|
updateField={updateField}
|
|
287
95
|
/>
|
|
288
|
-
{/* TODO: Uncomment when ready to release Display Border feature
|
|
289
96
|
<CheckBox
|
|
290
|
-
value={config.visual?.
|
|
97
|
+
value={config.visual?.showTitle}
|
|
291
98
|
section='visual'
|
|
292
|
-
|
|
293
|
-
|
|
99
|
+
checked={config.visual?.showTitle}
|
|
100
|
+
fieldName='showTitle'
|
|
101
|
+
label='Show Title'
|
|
294
102
|
updateField={updateField}
|
|
295
103
|
/>
|
|
296
|
-
*/}
|
|
297
|
-
</Accordion.Section>
|
|
298
|
-
)}
|
|
299
104
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
105
|
+
<TextField
|
|
106
|
+
type='textarea'
|
|
107
|
+
value={config.biteBody}
|
|
108
|
+
fieldName='biteBody'
|
|
109
|
+
label='Message'
|
|
305
110
|
updateField={updateField}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
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
|
-
</>
|
|
111
|
+
tooltip={
|
|
112
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
113
|
+
<Tooltip.Target>
|
|
114
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
115
|
+
</Tooltip.Target>
|
|
116
|
+
<Tooltip.Content>
|
|
117
|
+
<p>
|
|
118
|
+
Enter the message text for the visualization. The following HTML tags are supported: strong, em,
|
|
119
|
+
sup, and sub.
|
|
120
|
+
</p>
|
|
121
|
+
</Tooltip.Content>
|
|
122
|
+
</Tooltip>
|
|
327
123
|
}
|
|
328
124
|
/>
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
<Select
|
|
335
|
-
value={config.imageData.display || ''}
|
|
336
|
-
section='imageData'
|
|
337
|
-
fieldName='display'
|
|
338
|
-
label='Image Display Type'
|
|
125
|
+
<TextField
|
|
126
|
+
value={config.subtext}
|
|
127
|
+
fieldName='subtext'
|
|
128
|
+
label='Subtext/Citation'
|
|
129
|
+
placeholder='Data Bite Subtext or Citation'
|
|
339
130
|
updateField={updateField}
|
|
340
|
-
|
|
131
|
+
tooltip={
|
|
132
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
133
|
+
<Tooltip.Target>
|
|
134
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
135
|
+
</Tooltip.Target>
|
|
136
|
+
<Tooltip.Content>
|
|
137
|
+
<p>
|
|
138
|
+
Enter supporting text to display below the data visualization, if applicable. The following HTML
|
|
139
|
+
tags are supported: strong, em, sup, and sub. You can also use markup variables like{' '}
|
|
140
|
+
{'{{variable-name}}'} to display dynamic data.
|
|
141
|
+
</p>
|
|
142
|
+
</Tooltip.Content>
|
|
143
|
+
</Tooltip>
|
|
144
|
+
}
|
|
341
145
|
/>
|
|
342
146
|
<Select
|
|
343
|
-
value={config.
|
|
344
|
-
fieldName='
|
|
345
|
-
label='
|
|
147
|
+
value={config.locale}
|
|
148
|
+
fieldName='locale'
|
|
149
|
+
label='Language for dates and numbers'
|
|
346
150
|
updateField={updateField}
|
|
347
|
-
|
|
348
|
-
|
|
151
|
+
options={[
|
|
152
|
+
{ value: 'en-US', label: 'English (en-US)' },
|
|
153
|
+
{ value: 'es-MX', label: 'Spanish (es-MX)' }
|
|
154
|
+
]}
|
|
155
|
+
tooltip={
|
|
156
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
157
|
+
<Tooltip.Target>
|
|
158
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
159
|
+
</Tooltip.Target>
|
|
160
|
+
<Tooltip.Content>
|
|
161
|
+
<p>
|
|
162
|
+
Change the language (locale) for this visualization to alter the way dates and numbers are
|
|
163
|
+
formatted.
|
|
164
|
+
</p>
|
|
165
|
+
</Tooltip.Content>
|
|
166
|
+
</Tooltip>
|
|
167
|
+
}
|
|
349
168
|
/>
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
169
|
+
</Accordion.Section>
|
|
170
|
+
|
|
171
|
+
<Accordion.Section title='Data'>
|
|
172
|
+
<ul className='column-edit'>
|
|
173
|
+
<li className='two-col'>
|
|
174
|
+
<Select
|
|
175
|
+
value={config.dataColumn || ''}
|
|
176
|
+
fieldName='dataColumn'
|
|
177
|
+
label='Data Column'
|
|
357
178
|
updateField={updateField}
|
|
179
|
+
initial='Select'
|
|
180
|
+
required={true}
|
|
181
|
+
options={columns}
|
|
358
182
|
/>
|
|
183
|
+
<Select
|
|
184
|
+
value={config.dataFunction || ''}
|
|
185
|
+
fieldName='dataFunction'
|
|
186
|
+
label='Data Function'
|
|
187
|
+
updateField={updateField}
|
|
188
|
+
initial='Select'
|
|
189
|
+
required={true}
|
|
190
|
+
options={
|
|
191
|
+
Array.isArray(DATA_FUNCTIONS)
|
|
192
|
+
? DATA_FUNCTIONS
|
|
193
|
+
: DATA_FUNCTIONS
|
|
194
|
+
? Object.values(DATA_FUNCTIONS)
|
|
195
|
+
: []
|
|
196
|
+
}
|
|
197
|
+
/>
|
|
198
|
+
</li>
|
|
199
|
+
</ul>
|
|
200
|
+
<span className='divider-heading'>Number Formatting</span>
|
|
201
|
+
<ul className='column-edit'>
|
|
202
|
+
<li className='three-col'>
|
|
359
203
|
<TextField
|
|
360
|
-
value={config.
|
|
361
|
-
section='
|
|
362
|
-
fieldName='
|
|
363
|
-
label='
|
|
204
|
+
value={config.dataFormat.prefix}
|
|
205
|
+
section='dataFormat'
|
|
206
|
+
fieldName='prefix'
|
|
207
|
+
label='Prefix'
|
|
364
208
|
updateField={updateField}
|
|
365
209
|
/>
|
|
366
|
-
</>
|
|
367
|
-
)}
|
|
368
|
-
|
|
369
|
-
{['dynamic'].includes(config.imageData.display) && (
|
|
370
|
-
<>
|
|
371
210
|
<TextField
|
|
372
|
-
value={config.
|
|
373
|
-
section='
|
|
374
|
-
fieldName='
|
|
375
|
-
label='
|
|
211
|
+
value={config.dataFormat.suffix}
|
|
212
|
+
section='dataFormat'
|
|
213
|
+
fieldName='suffix'
|
|
214
|
+
label='Suffix'
|
|
376
215
|
updateField={updateField}
|
|
377
216
|
/>
|
|
378
217
|
<TextField
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
218
|
+
type='number'
|
|
219
|
+
value={config.dataFormat.roundToPlace}
|
|
220
|
+
section='dataFormat'
|
|
221
|
+
fieldName='roundToPlace'
|
|
222
|
+
label='Round'
|
|
383
223
|
updateField={updateField}
|
|
224
|
+
min='0'
|
|
225
|
+
max='99'
|
|
384
226
|
/>
|
|
227
|
+
</li>
|
|
228
|
+
</ul>
|
|
229
|
+
<CheckBox
|
|
230
|
+
value={config.dataFormat.commas}
|
|
231
|
+
section='dataFormat'
|
|
232
|
+
fieldName='commas'
|
|
233
|
+
label='Add commas'
|
|
234
|
+
updateField={updateField}
|
|
235
|
+
/>
|
|
236
|
+
<CheckBox
|
|
237
|
+
value={config.dataFormat.ignoreZeros}
|
|
238
|
+
section='dataFormat'
|
|
239
|
+
fieldName='ignoreZeros'
|
|
240
|
+
label='Ignore Zeros'
|
|
241
|
+
updateField={updateField}
|
|
242
|
+
/>
|
|
243
|
+
<hr className='accordion__divider' />
|
|
385
244
|
|
|
386
|
-
|
|
245
|
+
<label style={{ marginBottom: '1rem' }}>
|
|
246
|
+
<span className='edit-label'>
|
|
247
|
+
Data Point Filters
|
|
248
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
249
|
+
<Tooltip.Target>
|
|
250
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
251
|
+
</Tooltip.Target>
|
|
252
|
+
<Tooltip.Content>
|
|
253
|
+
<p>
|
|
254
|
+
To refine the highlighted data point, specify one or more filters (e.g., "Male" and "Female" for
|
|
255
|
+
a column called "Sex").
|
|
256
|
+
</p>
|
|
257
|
+
</Tooltip.Content>
|
|
258
|
+
</Tooltip>
|
|
259
|
+
</span>
|
|
260
|
+
</label>
|
|
261
|
+
{config.filters && (
|
|
262
|
+
<ul className='filters-list'>
|
|
263
|
+
{config.filters.map((filter: any, index: number) => (
|
|
264
|
+
<fieldset className='edit-block' key={index}>
|
|
265
|
+
<button
|
|
266
|
+
type='button'
|
|
267
|
+
className='btn btn-danger'
|
|
268
|
+
onClick={() => {
|
|
269
|
+
removeFilter(index)
|
|
270
|
+
}}
|
|
271
|
+
>
|
|
272
|
+
Remove
|
|
273
|
+
</button>
|
|
274
|
+
<Select
|
|
275
|
+
value={filter.columnName ? filter.columnName : ''}
|
|
276
|
+
fieldName='columnName'
|
|
277
|
+
label={'Column Name'}
|
|
278
|
+
updateField={(section, subsection, fieldName, value) =>
|
|
279
|
+
updateFilterProp(fieldName, index, value)
|
|
280
|
+
}
|
|
281
|
+
options={columns}
|
|
282
|
+
initial='- Select Option -'
|
|
283
|
+
/>
|
|
284
|
+
<Select
|
|
285
|
+
value={filter.columnValue || ''}
|
|
286
|
+
fieldName='columnValue'
|
|
287
|
+
label='Column Value'
|
|
288
|
+
updateField={(section, subsection, fieldName, value) =>
|
|
289
|
+
updateFilterProp(fieldName, index, value)
|
|
290
|
+
}
|
|
291
|
+
options={Array.isArray(getFilterColumnValues(index)) ? getFilterColumnValues(index) : []}
|
|
292
|
+
initial='- Select Option -'
|
|
293
|
+
/>
|
|
294
|
+
</fieldset>
|
|
295
|
+
))}
|
|
296
|
+
</ul>
|
|
297
|
+
)}
|
|
298
|
+
{(!config.filters || config.filters.length === 0) && (
|
|
299
|
+
<div>
|
|
300
|
+
<fieldset className='edit-block'>
|
|
301
|
+
<p style={{ textAlign: 'center' }}>There are currently no filters.</p>
|
|
302
|
+
</fieldset>
|
|
303
|
+
</div>
|
|
304
|
+
)}
|
|
305
|
+
<Button type='button' onClick={addNewFilter} className='btn btn-primary full-width mt-3'>
|
|
306
|
+
Add Filter
|
|
307
|
+
</Button>
|
|
308
|
+
</Accordion.Section>
|
|
387
309
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
310
|
+
{/* Visual section for TP5 style */}
|
|
311
|
+
{config.biteStyle === 'tp5' && (
|
|
312
|
+
<Accordion.Section title='Visual'>
|
|
313
|
+
<CheckBox
|
|
314
|
+
value={config.visual?.whiteBackground}
|
|
315
|
+
section='visual'
|
|
316
|
+
fieldName='whiteBackground'
|
|
317
|
+
label='Use White Background Style'
|
|
318
|
+
updateField={updateField}
|
|
319
|
+
/>
|
|
320
|
+
<CheckBox
|
|
321
|
+
value={config.visual?.useWrap}
|
|
322
|
+
section='visual'
|
|
323
|
+
fieldName='useWrap'
|
|
324
|
+
label='Value Above Message'
|
|
325
|
+
updateField={updateField}
|
|
326
|
+
/>
|
|
327
|
+
{/* TODO: Uncomment when ready to release Display Border feature
|
|
328
|
+
<CheckBox
|
|
329
|
+
value={config.visual?.border}
|
|
330
|
+
section='visual'
|
|
331
|
+
fieldName='border'
|
|
332
|
+
label='Display Border'
|
|
333
|
+
updateField={updateField}
|
|
334
|
+
/>
|
|
335
|
+
*/}
|
|
336
|
+
</Accordion.Section>
|
|
337
|
+
)}
|
|
338
|
+
|
|
339
|
+
{/* Visual section for other bite styles */}
|
|
340
|
+
{config.biteStyle !== 'tp5' && (
|
|
341
|
+
<Accordion.Section title='Visual'>
|
|
342
|
+
<VisualSection
|
|
343
|
+
config={config}
|
|
344
|
+
updateField={updateField}
|
|
345
|
+
updateConfig={updateConfig}
|
|
346
|
+
themeSelectorPosition='after'
|
|
347
|
+
beforeCheckboxes={
|
|
392
348
|
<>
|
|
393
|
-
<
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
349
|
+
<TextField
|
|
350
|
+
type='number'
|
|
351
|
+
value={config.biteFontSize}
|
|
352
|
+
fieldName='biteFontSize'
|
|
353
|
+
label='Bite Font Size'
|
|
354
|
+
updateField={updateField}
|
|
355
|
+
min={17}
|
|
356
|
+
max={65}
|
|
357
|
+
/>
|
|
358
|
+
<Select
|
|
359
|
+
value={config.fontSize}
|
|
360
|
+
fieldName='fontSize'
|
|
361
|
+
label='Overall Font Size'
|
|
362
|
+
updateField={updateField}
|
|
363
|
+
options={['small', 'medium', 'large']}
|
|
364
|
+
/>
|
|
365
|
+
</>
|
|
366
|
+
}
|
|
367
|
+
/>
|
|
368
|
+
</Accordion.Section>
|
|
369
|
+
)}
|
|
409
370
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
371
|
+
{['title', 'body', 'graphic'].includes(config.biteStyle) && (
|
|
372
|
+
<Accordion.Section title={`Image${['dynamic'].includes(config.imageData.display) ? 's' : ''}`}>
|
|
373
|
+
<Select
|
|
374
|
+
value={config.imageData.display || ''}
|
|
375
|
+
section='imageData'
|
|
376
|
+
fieldName='display'
|
|
377
|
+
label='Image Display Type'
|
|
378
|
+
updateField={updateField}
|
|
379
|
+
options={['none', 'static', 'dynamic']}
|
|
380
|
+
/>
|
|
381
|
+
<Select
|
|
382
|
+
value={config.bitePosition || ''}
|
|
383
|
+
fieldName='bitePosition'
|
|
384
|
+
label='Image/Graphic Position'
|
|
385
|
+
updateField={updateField}
|
|
386
|
+
initial='Select'
|
|
387
|
+
options={IMAGE_POSITIONS}
|
|
388
|
+
/>
|
|
389
|
+
{['static'].includes(config.imageData.display) && (
|
|
390
|
+
<>
|
|
391
|
+
<TextField
|
|
392
|
+
value={config.imageData.url}
|
|
393
|
+
section='imageData'
|
|
394
|
+
fieldName='url'
|
|
395
|
+
label='Image URL'
|
|
396
|
+
updateField={updateField}
|
|
397
|
+
/>
|
|
398
|
+
<TextField
|
|
399
|
+
value={config.imageData.alt}
|
|
400
|
+
section='imageData'
|
|
401
|
+
fieldName='alt'
|
|
402
|
+
label='Alt Text'
|
|
403
|
+
updateField={updateField}
|
|
404
|
+
/>
|
|
405
|
+
</>
|
|
406
|
+
)}
|
|
407
|
+
|
|
408
|
+
{['dynamic'].includes(config.imageData.display) && (
|
|
409
|
+
<>
|
|
410
|
+
<TextField
|
|
411
|
+
value={config.imageData.url || ''}
|
|
412
|
+
section='imageData'
|
|
413
|
+
fieldName='url'
|
|
414
|
+
label='Image URL (default)'
|
|
415
|
+
updateField={updateField}
|
|
416
|
+
/>
|
|
417
|
+
<TextField
|
|
418
|
+
value={config.imageData.alt}
|
|
419
|
+
section='imageData'
|
|
420
|
+
fieldName='alt'
|
|
421
|
+
label='Alt Text (default)'
|
|
422
|
+
updateField={updateField}
|
|
423
|
+
/>
|
|
424
|
+
|
|
425
|
+
<hr className='accordion__divider' />
|
|
426
|
+
|
|
427
|
+
{(!images.items || images.items.length === 0) && (
|
|
428
|
+
<p style={{ textAlign: 'center' }}>There are currently no dynamic images.</p>
|
|
429
|
+
)}
|
|
430
|
+
{images.items && images.items.length > 0 && (
|
|
431
|
+
<>
|
|
432
|
+
<ul>
|
|
433
|
+
{images.items.map((option: any, index: number) => (
|
|
434
|
+
<fieldset className='edit-block' key={index}>
|
|
435
|
+
<button
|
|
436
|
+
type='button'
|
|
437
|
+
className='remove-column'
|
|
438
|
+
onClick={() => {
|
|
439
|
+
images.remove(index)
|
|
440
|
+
}}
|
|
441
|
+
>
|
|
442
|
+
Remove
|
|
443
|
+
</button>
|
|
444
|
+
<label>
|
|
445
|
+
<span className='edit-label column-heading'>
|
|
446
|
+
<strong>{'Image #' + (index + 1)}</strong>
|
|
447
|
+
</span>
|
|
448
|
+
|
|
449
|
+
<div className='accordion__panel-row align-center'>
|
|
450
|
+
<div className='accordion__panel-col flex-auto'>If Value</div>
|
|
451
|
+
<div className='accordion__panel-col flex-auto'>
|
|
452
|
+
<Select
|
|
453
|
+
label=''
|
|
454
|
+
value={option.arguments[0]?.operator || ''}
|
|
455
|
+
options={DATA_OPERATORS}
|
|
456
|
+
onChange={e => {
|
|
457
|
+
images.updateNested(index, 'arguments', 0, 'operator', e.target.value)
|
|
458
|
+
}}
|
|
459
|
+
/>
|
|
460
|
+
</div>
|
|
461
|
+
<div className='accordion__panel-col flex-grow flex-shrink'>
|
|
462
|
+
<input
|
|
463
|
+
type='number'
|
|
464
|
+
value={option.arguments[0]?.threshold || ''}
|
|
465
|
+
onChange={e => {
|
|
466
|
+
images.updateNested(index, 'arguments', 0, 'threshold', e.target.value)
|
|
467
|
+
}}
|
|
468
|
+
/>
|
|
469
|
+
</div>
|
|
430
470
|
</div>
|
|
431
|
-
</div>
|
|
432
471
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
472
|
+
<div className='accordion__panel-row mb-2 align-center'>
|
|
473
|
+
<div className='accordion__panel-col flex-grow'>
|
|
474
|
+
<Select
|
|
475
|
+
label=''
|
|
476
|
+
value={option.secondArgument ? 'and' : 'then'}
|
|
477
|
+
options={[
|
|
478
|
+
{ value: 'then', label: 'Then' },
|
|
479
|
+
{ value: 'and', label: 'And' }
|
|
480
|
+
]}
|
|
481
|
+
onChange={e => {
|
|
482
|
+
if ('then' === e.target.value) {
|
|
483
|
+
images.updateField(index, 'secondArgument', false)
|
|
484
|
+
removeDynamicArgument(index)
|
|
485
|
+
}
|
|
486
|
+
if ('and' === e.target.value) {
|
|
487
|
+
images.updateField(index, 'secondArgument', true)
|
|
488
|
+
}
|
|
489
|
+
}}
|
|
490
|
+
/>
|
|
491
|
+
</div>
|
|
452
492
|
</div>
|
|
453
|
-
</div>
|
|
454
493
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
494
|
+
{option.secondArgument && true === option.secondArgument && (
|
|
495
|
+
<>
|
|
496
|
+
<div className='accordion__panel-row align-center'>
|
|
497
|
+
<div className='accordion__panel-col flex-auto'>If Value</div>
|
|
498
|
+
<div className='accordion__panel-col flex-auto'>
|
|
499
|
+
<Select
|
|
500
|
+
label=''
|
|
501
|
+
value={option.arguments[1]?.operator || ''}
|
|
502
|
+
options={DATA_OPERATORS}
|
|
503
|
+
onChange={e => {
|
|
504
|
+
images.updateNested(index, 'arguments', 1, 'operator', e.target.value)
|
|
505
|
+
}}
|
|
506
|
+
/>
|
|
507
|
+
</div>
|
|
508
|
+
<div className='accordion__panel-col flex-grow flex-shrink'>
|
|
509
|
+
<input
|
|
510
|
+
type='number'
|
|
511
|
+
value={option.arguments[1]?.threshold || ''}
|
|
512
|
+
onChange={e => {
|
|
513
|
+
images.updateNested(index, 'arguments', 1, 'threshold', e.target.value)
|
|
514
|
+
}}
|
|
515
|
+
/>
|
|
516
|
+
</div>
|
|
468
517
|
</div>
|
|
469
|
-
<div className='accordion__panel-
|
|
470
|
-
<
|
|
471
|
-
type='number'
|
|
472
|
-
value={option.arguments[1]?.threshold || ''}
|
|
473
|
-
onChange={e => {
|
|
474
|
-
images.updateNested(index, 'arguments', 1, 'threshold', e.target.value)
|
|
475
|
-
}}
|
|
476
|
-
/>
|
|
518
|
+
<div className='accordion__panel-row mb-2 align-center text-center text-capitalize'>
|
|
519
|
+
<div className='accordion__panel-col flex-grow'>Then</div>
|
|
477
520
|
</div>
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
<div className='accordion__panel-col flex-grow'>Then</div>
|
|
481
|
-
</div>
|
|
482
|
-
</>
|
|
483
|
-
)}
|
|
521
|
+
</>
|
|
522
|
+
)}
|
|
484
523
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
524
|
+
<div className='accordion__panel-row mb-2 align-center'>
|
|
525
|
+
<div className='accordion__panel-col flex-auto'>Show</div>
|
|
526
|
+
<div className='accordion__panel-col flex-grow'>
|
|
527
|
+
<input
|
|
528
|
+
type='text'
|
|
529
|
+
value={option.source || ''}
|
|
530
|
+
onChange={e => {
|
|
531
|
+
images.updateField(index, 'source', e.target.value)
|
|
532
|
+
}}
|
|
533
|
+
/>
|
|
534
|
+
</div>
|
|
495
535
|
</div>
|
|
496
|
-
</div>
|
|
497
536
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
537
|
+
<div className='accordion__panel-row mb-2 align-center'>
|
|
538
|
+
<div className='accordion__panel-col flex-auto'>Alt Text</div>
|
|
539
|
+
<div className='accordion__panel-col flex-grow'>
|
|
540
|
+
<input
|
|
541
|
+
type='text'
|
|
542
|
+
value={option.alt || ''}
|
|
543
|
+
onChange={e => {
|
|
544
|
+
images.updateField(index, 'alt', e.target.value)
|
|
545
|
+
}}
|
|
546
|
+
/>
|
|
547
|
+
</div>
|
|
508
548
|
</div>
|
|
509
|
-
</
|
|
510
|
-
</
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
)}
|
|
549
|
+
</label>
|
|
550
|
+
</fieldset>
|
|
551
|
+
))}
|
|
552
|
+
</ul>
|
|
553
|
+
</>
|
|
554
|
+
)}
|
|
555
|
+
<button type='button' onClick={images.add} className='btn btn-primary full-width'>
|
|
556
|
+
Add Dynamic Image
|
|
557
|
+
</button>
|
|
558
|
+
</>
|
|
559
|
+
)}
|
|
560
|
+
</Accordion.Section>
|
|
561
|
+
)}
|
|
523
562
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
563
|
+
<Accordion.Section title='Markup Variables'>
|
|
564
|
+
<PanelMarkup
|
|
565
|
+
name='Markup Variables'
|
|
566
|
+
markupVariables={config.markupVariables || []}
|
|
567
|
+
data={data}
|
|
568
|
+
enableMarkupVariables={config.enableMarkupVariables || false}
|
|
569
|
+
onMarkupVariablesChange={variables => updateField(null, null, 'markupVariables', variables)}
|
|
570
|
+
onToggleEnable={enabled => updateField(null, null, 'enableMarkupVariables', enabled)}
|
|
571
|
+
withAccordion={false}
|
|
572
|
+
dataMetadata={config.dataMetadata}
|
|
573
|
+
/>
|
|
574
|
+
</Accordion.Section>
|
|
575
|
+
</Accordion>
|
|
535
576
|
<AdvancedEditor loadConfig={updateConfig} config={config} convertStateToConfig={convertStateToConfig} />
|
|
536
|
-
|
|
577
|
+
</>
|
|
537
578
|
)}
|
|
538
579
|
</BaseEditorPanel>
|
|
539
580
|
)
|