@cdc/data-bite 4.25.5-1 → 4.25.6-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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cdc/data-bite",
3
- "version": "4.25.5-1",
3
+ "version": "4.25.6-1",
4
4
  "description": "React component for displaying a single piece of data in a card module",
5
5
  "moduleName": "CdcDataBite",
6
6
  "main": "dist/cdcdatabite",
@@ -27,14 +27,13 @@
27
27
  "license": "Apache-2.0",
28
28
  "homepage": "https://github.com/CDCgov/cdc-open-viz#readme",
29
29
  "dependencies": {
30
- "@cdc/core": "^4.25.5-1",
30
+ "@cdc/core": "^4.25.6-1",
31
31
  "chroma": "0.0.1",
32
- "react-accessible-accordion": "^3.3.4",
33
- "react-beautiful-dnd": "^13.0.0"
32
+ "react-accessible-accordion": "^3.3.4"
34
33
  },
35
34
  "peerDependencies": {
36
35
  "react": "^18.2.0",
37
36
  "react-dom": "^18.2.0"
38
37
  },
39
- "gitHead": "1d0a6e716bc113e6bea3636fcae90ebf2d19bb5c"
38
+ "gitHead": "ac45ee0f1d6a4045648c4e083992fc091795e084"
40
39
  }
@@ -28,6 +28,20 @@ import cacheBustingString from '@cdc/core/helpers/cacheBustingString'
28
28
  import coveUpdateWorker from '@cdc/core/helpers/coveUpdateWorker'
29
29
  import { Config } from './types/Config'
30
30
  import dataBiteReducer from './store/db.reducer'
31
+ import {
32
+ DATA_FUNCTION_COUNT,
33
+ DATA_FUNCTION_MAX,
34
+ DATA_FUNCTION_MEAN,
35
+ DATA_FUNCTION_MEDIAN,
36
+ DATA_FUNCTION_MIN,
37
+ DATA_FUNCTION_MODE,
38
+ DATA_FUNCTION_RANGE,
39
+ DATA_FUNCTION_SUM,
40
+ IMAGE_POSITION_LEFT,
41
+ IMAGE_POSITION_RIGHT,
42
+ IMAGE_POSITION_TOP,
43
+ IMAGE_POSITION_BOTTOM
44
+ } from './constants'
31
45
 
32
46
  // styles
33
47
  import './scss/main.scss'
@@ -340,7 +354,7 @@ const CdcDataBite = (props: CdcDataBiteProps) => {
340
354
  config.dataFormat.suffix
341
355
  break
342
356
  default:
343
- console.warn('Data bite function not recognized: ' + dataFunction)
357
+ console.warn('Data bite function not recognized: ' + dataFunction) // eslint-disable-line no-console
344
358
  }
345
359
 
346
360
  // If not the range, then round and format here
@@ -643,57 +657,3 @@ const CdcDataBite = (props: CdcDataBiteProps) => {
643
657
  }
644
658
 
645
659
  export default CdcDataBite
646
-
647
- /* Constant */
648
- export const DATA_FUNCTION_MAX = 'Max'
649
- export const DATA_FUNCTION_COUNT = 'Count'
650
- export const DATA_FUNCTION_MEAN = 'Mean (Average)'
651
- export const DATA_FUNCTION_MEDIAN = 'Median'
652
- export const DATA_FUNCTION_MIN = 'Min'
653
- export const DATA_FUNCTION_MODE = 'Mode'
654
- export const DATA_FUNCTION_RANGE = 'Range'
655
- export const DATA_FUNCTION_SUM = 'Sum'
656
- export const DATA_FUNCTIONS = [
657
- DATA_FUNCTION_COUNT,
658
- DATA_FUNCTION_MAX,
659
- DATA_FUNCTION_MEAN,
660
- DATA_FUNCTION_MEDIAN,
661
- DATA_FUNCTION_MIN,
662
- DATA_FUNCTION_MODE,
663
- DATA_FUNCTION_RANGE,
664
- DATA_FUNCTION_SUM
665
- ]
666
-
667
- export const BITE_LOCATION_TITLE = 'title'
668
- export const BITE_LOCATION_BODY = 'body'
669
- export const BITE_LOCATION_GRAPHIC = 'graphic'
670
- export const BITE_LOCATIONS = {
671
- graphic: 'Graphic',
672
- split: 'Split Graphic and Message',
673
- title: 'Value above Message',
674
- body: 'Value before Message',
675
- end: 'Value after Message',
676
- gradient: 'Gradient'
677
- }
678
-
679
- export const IMAGE_POSITION_LEFT = 'Left'
680
- export const IMAGE_POSITION_RIGHT = 'Right'
681
- export const IMAGE_POSITION_TOP = 'Top'
682
- export const IMAGE_POSITION_BOTTOM = 'Bottom'
683
- export const IMAGE_POSITIONS = [IMAGE_POSITION_LEFT, IMAGE_POSITION_RIGHT, IMAGE_POSITION_TOP, IMAGE_POSITION_BOTTOM]
684
-
685
- export const DATA_OPERATOR_LESS = '<'
686
- export const DATA_OPERATOR_GREATER = '>'
687
- export const DATA_OPERATOR_LESSEQUAL = '<='
688
- export const DATA_OPERATOR_GREATEREQUAL = '>='
689
- export const DATA_OPERATOR_EQUAL = '='
690
- export const DATA_OPERATOR_NOTEQUAL = '≠'
691
-
692
- export const DATA_OPERATORS = [
693
- DATA_OPERATOR_LESS,
694
- DATA_OPERATOR_GREATER,
695
- DATA_OPERATOR_LESSEQUAL,
696
- DATA_OPERATOR_GREATEREQUAL,
697
- DATA_OPERATOR_EQUAL,
698
- DATA_OPERATOR_NOTEQUAL
699
- ]
@@ -1,4 +1,4 @@
1
- import React, { memo, useContext, useEffect, useState } from 'react'
1
+ import { memo, useContext, useEffect, useState } from 'react'
2
2
  import _ from 'lodash'
3
3
  import {
4
4
  Accordion,
@@ -8,177 +8,16 @@ import {
8
8
  AccordionItemPanel
9
9
  } from 'react-accessible-accordion'
10
10
 
11
- import { useDebounce } from 'use-debounce'
12
11
  import Context from '../context'
13
12
  import WarningImage from '@cdc/core/assets/icon-warning-circle.svg'
14
13
  import Tooltip from '@cdc/core/components/ui/Tooltip'
15
14
  import Icon from '@cdc/core/components/ui/Icon'
16
15
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
17
16
  import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
18
- import { BITE_LOCATIONS, DATA_FUNCTIONS, IMAGE_POSITIONS, DATA_OPERATORS } from '../CdcDataBite'
17
+ import { BITE_LOCATIONS, DATA_FUNCTIONS, IMAGE_POSITIONS, DATA_OPERATORS, HEADER_COLORS } from './../constants'
19
18
  import Layout from '@cdc/core/components/Layout'
20
-
21
- const TextField = memo(
22
- ({
23
- label,
24
- section = null,
25
- subsection = null,
26
- fieldName,
27
- updateField,
28
- value: stateValue,
29
- tooltip,
30
- type = 'input',
31
- i = null,
32
- min = null,
33
- max = null,
34
- ...attributes
35
- }) => {
36
- const [value, setValue] = useState(stateValue)
37
-
38
- const [debouncedValue] = useDebounce(value, 500)
39
-
40
- useEffect(() => {
41
- if ('string' === typeof debouncedValue && stateValue !== debouncedValue) {
42
- updateField(section, subsection, fieldName, debouncedValue, i)
43
- }
44
- }, [debouncedValue, section, subsection, fieldName, i, stateValue, updateField])
45
-
46
- let name = subsection ? `${section}-${subsection}-${fieldName}` : `${section}-${subsection}-${fieldName}`
47
-
48
- const onChange = e => {
49
- //TODO: This block gives a warning/error in the console, but it still works.
50
- if ('number' !== type || min === null) {
51
- setValue(e.target.value)
52
- } else {
53
- if (
54
- !e.target.value ||
55
- (parseFloat(min) <= parseFloat(e.target.value)) & (parseFloat(max) >= parseFloat(e.target.value))
56
- ) {
57
- setValue(e.target.value)
58
- } else {
59
- setValue(min.toString())
60
- }
61
- }
62
- }
63
-
64
- let formElement = <input type='text' name={name} onChange={onChange} {...attributes} value={value} />
65
-
66
- if ('textarea' === type) {
67
- formElement = <textarea name={name} onChange={onChange} {...attributes} value={value}></textarea>
68
- }
69
-
70
- if ('number' === type) {
71
- formElement = <input type='number' name={name} onChange={onChange} {...attributes} value={value} />
72
- }
73
-
74
- return (
75
- <>
76
- {label && label.length > 0 && (
77
- <label>
78
- <span className='edit-label column-heading'>
79
- {label}
80
- {tooltip}
81
- </span>
82
- {formElement}
83
- </label>
84
- )}
85
- {(!label || label.length === 0) && formElement}
86
- </>
87
- )
88
- }
89
- )
90
-
91
- const CheckBox = memo(
92
- ({ label, value, fieldName, section = null, subsection = null, tooltip, updateField, ...attributes }) => (
93
- <label className='checkbox'>
94
- <input
95
- type='checkbox'
96
- name={fieldName}
97
- checked={value}
98
- onChange={() => {
99
- updateField(section, subsection, fieldName, !value)
100
- }}
101
- {...attributes}
102
- />
103
- <span className='edit-label column-heading'>{label}</span>
104
- <span className='cove-icon'>{tooltip}</span>
105
- </label>
106
- )
107
- )
108
-
109
- const Select = memo(
110
- ({
111
- label,
112
- value,
113
- options,
114
- fieldName,
115
- section = null,
116
- subsection = null,
117
- required = false,
118
- updateField,
119
- initial: initialValue,
120
- ...attributes
121
- }) => {
122
- let optionsJsx = ''
123
- if (Array.isArray(options)) {
124
- //Handle basic array
125
- optionsJsx = options.map(optionName => (
126
- <option value={optionName} key={optionName}>
127
- {optionName}
128
- </option>
129
- ))
130
- } else {
131
- //Handle object with value/name pairs
132
- optionsJsx = []
133
- for (const [optionValue, optionName] of Object.entries(options)) {
134
- optionsJsx.push(
135
- <option value={optionValue} key={optionValue}>
136
- {optionName}
137
- </option>
138
- )
139
- }
140
- }
141
-
142
- if (initialValue) {
143
- optionsJsx.unshift(
144
- <option value='' key='initial'>
145
- {initialValue}
146
- </option>
147
- )
148
- }
149
-
150
- return (
151
- <label>
152
- <span className='edit-label'>{label}</span>
153
- <select
154
- className={required && !value ? 'warning' : ''}
155
- name={fieldName}
156
- value={value}
157
- onChange={event => {
158
- updateField(section, subsection, fieldName, event.target.value)
159
- }}
160
- {...attributes}
161
- >
162
- {optionsJsx}
163
- </select>
164
- </label>
165
- )
166
- }
167
- )
168
-
169
- const headerColors = [
170
- 'theme-blue',
171
- 'theme-purple',
172
- 'theme-brown',
173
- 'theme-teal',
174
- 'theme-pink',
175
- 'theme-orange',
176
- 'theme-slate',
177
- 'theme-indigo',
178
- 'theme-cyan',
179
- 'theme-green',
180
- 'theme-amber'
181
- ]
19
+ import { Select, TextField, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
20
+ import Button from '@cdc/core/components/elements/Button'
182
21
 
183
22
  const EditorPanel = memo(() => {
184
23
  const { config, updateConfig, loading, data, setParentConfig, isDashboard, isEditor } = useContext(Context)
@@ -347,7 +186,7 @@ const EditorPanel = memo(() => {
347
186
  fieldName='biteStyle'
348
187
  label='Data Bite Style'
349
188
  updateField={updateField}
350
- options={BITE_LOCATIONS}
189
+ options={Object.entries(BITE_LOCATIONS).map(([key, value]) => ({ value: key, label: value }))}
351
190
  initial='Select'
352
191
  />
353
192
  <TextField
@@ -430,7 +269,7 @@ const EditorPanel = memo(() => {
430
269
  updateField={updateField}
431
270
  initial='Select'
432
271
  required={true}
433
- options={getColumns()}
272
+ options={getColumns() ? Array.from(getColumns()) : []}
434
273
  />
435
274
  <Select
436
275
  value={config.dataFunction || ''}
@@ -439,7 +278,13 @@ const EditorPanel = memo(() => {
439
278
  updateField={updateField}
440
279
  initial='Select'
441
280
  required={true}
442
- options={DATA_FUNCTIONS}
281
+ options={
282
+ Array.isArray(DATA_FUNCTIONS)
283
+ ? DATA_FUNCTIONS
284
+ : DATA_FUNCTIONS
285
+ ? Object.values(DATA_FUNCTIONS)
286
+ : []
287
+ }
443
288
  />
444
289
  </li>
445
290
  </ul>
@@ -510,45 +355,33 @@ const EditorPanel = memo(() => {
510
355
  <fieldset className='edit-block' key={index}>
511
356
  <button
512
357
  type='button'
513
- className='remove-column'
358
+ className='btn btn-danger'
514
359
  onClick={() => {
515
360
  removeFilter(index)
516
361
  }}
517
362
  >
518
363
  Remove
519
364
  </button>
520
- <label>
521
- <span className='edit-label column-heading'>Column</span>
522
- <select
523
- value={filter.columnName ? filter.columnName : ''}
524
- onChange={e => {
525
- updateFilterProp('columnName', index, e.target.value)
526
- }}
527
- >
528
- <option value=''>- Select Option -</option>
529
- {getColumns().map((dataKey, index) => (
530
- <option value={dataKey} key={index}>
531
- {dataKey}
532
- </option>
533
- ))}
534
- </select>
535
- </label>
536
- <label>
537
- <span className='edit-label column-heading'>Column Value</span>
538
- <select
539
- value={filter.columnValue}
540
- onChange={e => {
541
- updateFilterProp('columnValue', index, e.target.value)
542
- }}
543
- >
544
- <option value=''>- Select Option -</option>
545
- {getFilterColumnValues(index).map((dataKey, index) => (
546
- <option value={dataKey} key={index}>
547
- {dataKey}
548
- </option>
549
- ))}
550
- </select>
551
- </label>
365
+ <Select
366
+ value={filter.columnName ? filter.columnName : ''}
367
+ fieldName='columnName'
368
+ label={'Column Name'}
369
+ updateField={(section, subsection, fieldName, value) =>
370
+ updateFilterProp(fieldName, index, value)
371
+ }
372
+ options={getColumns()}
373
+ initial='- Select Option -'
374
+ />
375
+ <Select
376
+ value={filter.columnValue || ''}
377
+ fieldName='columnValue'
378
+ label='Column Value'
379
+ updateField={(section, subsection, fieldName, value) =>
380
+ updateFilterProp(fieldName, index, value)
381
+ }
382
+ options={Array.isArray(getFilterColumnValues(index)) ? getFilterColumnValues(index) : []}
383
+ initial='- Select Option -'
384
+ />
552
385
  </fieldset>
553
386
  ))}
554
387
  </ul>
@@ -560,9 +393,9 @@ const EditorPanel = memo(() => {
560
393
  </fieldset>
561
394
  </div>
562
395
  )}
563
- <button type='button' onClick={addNewFilter} className='btn btn-primary full-width'>
396
+ <Button type='button' onClick={addNewFilter} className='btn btn-primary full-width mt-3'>
564
397
  Add Filter
565
- </button>
398
+ </Button>
566
399
  </AccordionItemPanel>
567
400
  </AccordionItem>
568
401
 
@@ -629,11 +462,12 @@ const EditorPanel = memo(() => {
629
462
  <label>
630
463
  <span className='edit-label'>Theme</span>
631
464
  <ul className='color-palette'>
632
- {headerColors.map(palette => (
633
- <li
465
+ {HEADER_COLORS.map(palette => (
466
+ <button
634
467
  title={palette}
635
468
  key={palette}
636
- onClick={() => {
469
+ onClick={e => {
470
+ e.preventDefault()
637
471
  updateConfig({ ...config, theme: palette })
638
472
  }}
639
473
  className={config.theme === palette ? 'selected ' + palette : palette}
@@ -0,0 +1,66 @@
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
+ export const BITE_LOCATIONS = {
24
+ graphic: 'Graphic',
25
+ split: 'Split Graphic and Message',
26
+ title: 'Value above Message',
27
+ body: 'Value before Message',
28
+ end: 'Value after Message',
29
+ gradient: 'Gradient'
30
+ }
31
+
32
+ export const IMAGE_POSITION_LEFT = 'Left'
33
+ export const IMAGE_POSITION_RIGHT = 'Right'
34
+ export const IMAGE_POSITION_TOP = 'Top'
35
+ export const IMAGE_POSITION_BOTTOM = 'Bottom'
36
+ 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
+ ]