@cdc/core 4.24.10 → 4.24.12
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/components/AdvancedEditor/AdvancedEditor.tsx +17 -13
- package/components/Alert/components/Alert.tsx +39 -8
- package/components/DataTable/DataTable.tsx +31 -10
- package/components/DataTable/components/ExpandCollapse.tsx +1 -1
- package/components/DataTable/components/SortIcon/sort-icon.css +15 -0
- package/components/DataTable/data-table.css +4 -22
- package/components/DataTable/helpers/boxplotCellMatrix.tsx +19 -14
- package/components/DataTable/helpers/getChartCellValue.ts +25 -7
- package/components/EditorPanel/ColumnsEditor.tsx +81 -36
- package/components/EditorPanel/DataTableEditor.tsx +62 -56
- package/components/EditorPanel/FieldSetWrapper.tsx +2 -2
- package/components/EditorPanel/Inputs.tsx +26 -16
- package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +43 -56
- package/components/Filters/Filters.tsx +16 -11
- package/components/Footnotes/FootnotesStandAlone.tsx +17 -4
- package/components/Layout/components/Sidebar/components/sidebar.styles.scss +0 -4
- package/components/Layout/components/Visualization/visualizations.scss +1 -1
- package/components/Legend/Legend.Gradient.tsx +50 -35
- package/components/Loader/Loader.tsx +10 -5
- package/components/MultiSelect/MultiSelect.tsx +56 -33
- package/components/MultiSelect/multiselect.styles.css +20 -7
- package/components/NestedDropdown/NestedDropdown.tsx +55 -32
- package/components/NestedDropdown/nesteddropdown.styles.css +26 -13
- package/components/Table/Table.tsx +102 -34
- package/components/Table/components/Row.tsx +1 -1
- package/components/_stories/DataTable.stories.tsx +14 -0
- package/components/_stories/Filters.stories.tsx +57 -0
- package/components/_stories/_mocks/DataTable/no-data.json +108 -0
- package/components/inputs/{InputToggle.jsx → InputToggle.tsx} +35 -29
- package/components/ui/Icon.tsx +19 -6
- package/dist/cove-main.css +26 -57
- package/dist/cove-main.css.map +1 -1
- package/helpers/DataTransform.ts +2 -1
- package/helpers/cove/{number.js → number.ts} +25 -11
- package/helpers/fetchRemoteData.js +32 -37
- package/helpers/formatConfigBeforeSave.ts +1 -0
- package/helpers/gatherQueryParams.ts +2 -3
- package/helpers/queryStringUtils.ts +16 -1
- package/helpers/useDataVizClasses.ts +44 -21
- package/helpers/ver/versionNeedsUpdate.ts +2 -0
- package/helpers/viewports.ts +8 -7
- package/package.json +2 -2
- package/styles/_button-section.scss +1 -1
- package/styles/_global-variables.scss +9 -4
- package/styles/_global.scss +21 -22
- package/styles/_reset.scss +0 -12
- package/styles/filters.scss +0 -22
- package/styles/v2/base/_reset.scss +0 -7
- package/styles/v2/components/editor.scss +0 -4
- package/styles/v2/components/icon.scss +1 -1
- package/types/Axis.ts +2 -0
- package/types/BoxPlot.ts +5 -3
- package/types/Color.ts +1 -1
- package/types/Legend.ts +1 -2
- package/types/MarkupInclude.ts +1 -0
- package/types/Runtime.ts +3 -1
- package/types/Series.ts +8 -1
- package/types/Table.ts +1 -1
- package/types/Version.ts +1 -0
- package/types/Visualization.ts +7 -8
- package/components/ui/Select.jsx +0 -30
- package/helpers/getGradientLegendWidth.ts +0 -15
|
@@ -6,6 +6,7 @@ import { FilterFunction, JsonEditor, UpdateFunction } from 'json-edit-react'
|
|
|
6
6
|
import { formatConfigBeforeSave as stripConfig } from '../../helpers/formatConfigBeforeSave'
|
|
7
7
|
import './advanced-editor-styles.css'
|
|
8
8
|
import _ from 'lodash'
|
|
9
|
+
import Tooltip from '../ui/Tooltip'
|
|
9
10
|
|
|
10
11
|
export const AdvancedEditor = ({ loadConfig, config, convertStateToConfig, onExpandCollapse = () => {} }) => {
|
|
11
12
|
const [advancedToggle, _setAdvancedToggle] = useState(false)
|
|
@@ -37,7 +38,11 @@ export const AdvancedEditor = ({ loadConfig, config, convertStateToConfig, onExp
|
|
|
37
38
|
chart: ['Charts', 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/bar-chart.html', <ChartIcon />],
|
|
38
39
|
dashboard: ['Dashboard', 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/bar-chart.html', <ChartIcon />],
|
|
39
40
|
map: ['Maps', 'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/data-map.html', <MapIcon />],
|
|
40
|
-
'markup-include': [
|
|
41
|
+
'markup-include': [
|
|
42
|
+
'Markup Include',
|
|
43
|
+
'https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/Markup-Include.html',
|
|
44
|
+
<MarkupIncludeIcon />
|
|
45
|
+
]
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
if (!config.type) return <></>
|
|
@@ -63,25 +68,24 @@ export const AdvancedEditor = ({ loadConfig, config, convertStateToConfig, onExp
|
|
|
63
68
|
</div>
|
|
64
69
|
</section>
|
|
65
70
|
<p className='pb-2'>
|
|
66
|
-
This tool displays the actual <acronym title='JavaScript Object Notation'>JSON</acronym> configuration
|
|
71
|
+
This tool displays the actual <acronym title='JavaScript Object Notation'>JSON</acronym> configuration
|
|
72
|
+
that is generated by this editor and allows you to edit properties directly and apply them.
|
|
67
73
|
</p>
|
|
74
|
+
<JsonEditor
|
|
75
|
+
className='advanced-json-editor'
|
|
76
|
+
data={configTextboxValue}
|
|
77
|
+
onUpdate={onUpdate}
|
|
78
|
+
rootName=''
|
|
79
|
+
collapse={collapseFields}
|
|
80
|
+
/>
|
|
68
81
|
<button
|
|
69
|
-
className='btn '
|
|
70
|
-
onClick={() => {
|
|
71
|
-
navigator.clipboard.writeText(JSON.stringify(configTextboxValue))
|
|
72
|
-
}}
|
|
73
|
-
>
|
|
74
|
-
Copy to Clipboard
|
|
75
|
-
</button>
|
|
76
|
-
<JsonEditor className='advanced-json-editor' data={configTextboxValue} onUpdate={onUpdate} rootName='' collapse={collapseFields} />
|
|
77
|
-
<button
|
|
78
|
-
className='btn full-width'
|
|
82
|
+
className='btn btn-success m-2 p-2'
|
|
79
83
|
onClick={() => {
|
|
80
84
|
loadConfig(configTextboxValue)
|
|
81
85
|
setAdvancedToggle(!advancedToggle)
|
|
82
86
|
}}
|
|
83
87
|
>
|
|
84
|
-
Apply
|
|
88
|
+
Apply Configuration Changes
|
|
85
89
|
</button>
|
|
86
90
|
</React.Fragment>
|
|
87
91
|
)}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Icon from '../../ui/Icon'
|
|
2
2
|
|
|
3
3
|
import DOMPurify from 'dompurify'
|
|
4
|
-
import React from 'react'
|
|
4
|
+
import React, { useEffect } from 'react'
|
|
5
5
|
|
|
6
6
|
import './Alert.styles.css'
|
|
7
7
|
|
|
@@ -14,10 +14,34 @@ type AlertProps = {
|
|
|
14
14
|
iconSize?: number
|
|
15
15
|
// heading for the alert box
|
|
16
16
|
heading?: string
|
|
17
|
+
// dismiss function
|
|
18
|
+
onDismiss?: Function
|
|
19
|
+
// make the alert dismiss on it's own
|
|
20
|
+
autoDismiss?: boolean
|
|
21
|
+
// set seconds until autoDismiss, default is 5 seconds
|
|
22
|
+
secondsBeforeDismiss?: number
|
|
23
|
+
// provide option for non dismissable alert
|
|
24
|
+
showCloseButton?: boolean
|
|
17
25
|
}
|
|
18
26
|
|
|
19
|
-
const Alert: React.FC<AlertProps> = ({
|
|
27
|
+
const Alert: React.FC<AlertProps> = ({
|
|
28
|
+
type = 'info',
|
|
29
|
+
message = '',
|
|
30
|
+
iconSize = 21,
|
|
31
|
+
heading,
|
|
32
|
+
onDismiss,
|
|
33
|
+
autoDismiss,
|
|
34
|
+
secondsBeforeDismiss = 5,
|
|
35
|
+
showCloseButton = true
|
|
36
|
+
}) => {
|
|
20
37
|
// sanitize the text for setting dangerouslySetInnerHTML
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (autoDismiss) {
|
|
41
|
+
setTimeout(() => onDismiss(), secondsBeforeDismiss * 1000)
|
|
42
|
+
}
|
|
43
|
+
}, [])
|
|
44
|
+
|
|
21
45
|
const sanitizedData = () => ({
|
|
22
46
|
__html: DOMPurify.sanitize(message)
|
|
23
47
|
})
|
|
@@ -26,12 +50,19 @@ const Alert: React.FC<AlertProps> = ({ type = 'info', message = '', iconSize = 2
|
|
|
26
50
|
const styleResets = { width: 'unset', height: 'unset', paddingRight: '5px' }
|
|
27
51
|
|
|
28
52
|
return (
|
|
29
|
-
<div className={`alert alert-${type} p-1`} role='alert'>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
53
|
+
<div className={`alert alert-${type} p-1 d-flex justify-content-between`} role='alert'>
|
|
54
|
+
<div className='d-flex'>
|
|
55
|
+
{heading && <h4 className='alert-heading'>{heading}</h4>}
|
|
56
|
+
{type === 'success' && <Icon display='check' size={iconSize} />}
|
|
57
|
+
{type === 'danger' && <Icon display='warningCircle' size={iconSize} />}
|
|
58
|
+
{type === 'info' && <Icon display='info' size={iconSize} />}
|
|
59
|
+
<span dangerouslySetInnerHTML={sanitizedData()} />
|
|
60
|
+
</div>
|
|
61
|
+
{showCloseButton && (
|
|
62
|
+
<button type='button' className='close pl-5' aria-label='Close' onClick={() => onDismiss()}>
|
|
63
|
+
X
|
|
64
|
+
</button>
|
|
65
|
+
)}
|
|
35
66
|
</div>
|
|
36
67
|
)
|
|
37
68
|
}
|
|
@@ -22,6 +22,7 @@ import { Column } from '../../types/Column'
|
|
|
22
22
|
import { pivotData } from '../../helpers/pivotData'
|
|
23
23
|
import { isLegendWrapViewport } from '@cdc/core/helpers/viewports'
|
|
24
24
|
import './data-table.css'
|
|
25
|
+
import _ from 'lodash'
|
|
25
26
|
|
|
26
27
|
export type DataTableProps = {
|
|
27
28
|
applyLegendToRow?: Function
|
|
@@ -73,9 +74,14 @@ const DataTable = (props: DataTableProps) => {
|
|
|
73
74
|
const runtimeData = useMemo(() => {
|
|
74
75
|
const data = removeNullColumns(parentRuntimeData)
|
|
75
76
|
if (config.table.pivot) {
|
|
77
|
+
const excludeColumns = Object.values(config.columns || {})
|
|
78
|
+
.filter(column => column.dataTable === false)
|
|
79
|
+
.map(col => col.name)
|
|
76
80
|
const { columnName, valueColumns } = config.table.pivot
|
|
77
81
|
if (columnName && valueColumns) {
|
|
78
|
-
|
|
82
|
+
// remove excluded columns so that they aren't included in the pivot calculation
|
|
83
|
+
const _data = data.map(row => _.omit(row, excludeColumns))
|
|
84
|
+
return pivotData(_data, columnName, valueColumns)
|
|
79
85
|
}
|
|
80
86
|
}
|
|
81
87
|
return data
|
|
@@ -84,7 +90,7 @@ const DataTable = (props: DataTableProps) => {
|
|
|
84
90
|
const [expanded, setExpanded] = useState(expandDataTable)
|
|
85
91
|
|
|
86
92
|
const [sortBy, setSortBy] = useState<any>({
|
|
87
|
-
column:
|
|
93
|
+
column: '',
|
|
88
94
|
asc: false,
|
|
89
95
|
colIndex: null
|
|
90
96
|
})
|
|
@@ -196,10 +202,11 @@ const DataTable = (props: DataTableProps) => {
|
|
|
196
202
|
: config.visualizationType === 'Pie'
|
|
197
203
|
? [config.yAxis.dataKey]
|
|
198
204
|
: config.visualizationType === 'Box Plot'
|
|
199
|
-
? Object.entries(config.boxplot.
|
|
205
|
+
? config?.boxplot?.plots?.[0] ? Object.entries(config.boxplot.plots[0]) : []
|
|
200
206
|
: config.runtime?.seriesKeys),
|
|
201
207
|
[config.runtime?.seriesKeys]) // eslint-disable-line
|
|
202
208
|
|
|
209
|
+
const hasNoData = runtimeData.length === 0
|
|
203
210
|
if (config.visualizationType !== 'Box Plot') {
|
|
204
211
|
const getDownloadData = () => {
|
|
205
212
|
// only use fullGeoName on County maps and no other
|
|
@@ -237,17 +244,28 @@ const DataTable = (props: DataTableProps) => {
|
|
|
237
244
|
</MediaControls.Section>
|
|
238
245
|
)
|
|
239
246
|
}
|
|
247
|
+
const getClassNames = (): string => {
|
|
248
|
+
const classes = ['data-table-container']
|
|
249
|
+
const isBrushActive = config?.brush?.active && config.legend?.position !== 'bottom'
|
|
250
|
+
|
|
251
|
+
if (isBrushActive) {
|
|
252
|
+
classes.push('brush-active')
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
classes.push(viewport)
|
|
256
|
+
|
|
257
|
+
const downloadLinkClass = !config.table.showDownloadLinkBelow ? 'download-link-above' : ''
|
|
258
|
+
if (downloadLinkClass) {
|
|
259
|
+
classes.push(downloadLinkClass)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return classes.join(' ')
|
|
263
|
+
}
|
|
240
264
|
|
|
241
265
|
return (
|
|
242
266
|
<ErrorBoundary component='DataTable'>
|
|
243
267
|
{!config.table.showDownloadLinkBelow && <TableMediaControls />}
|
|
244
|
-
<section
|
|
245
|
-
id={tabbingId.replace('#', '')}
|
|
246
|
-
className={`data-table-container ${viewport} ${
|
|
247
|
-
!config.table.showDownloadLinkBelow ? 'download-link-above' : ''
|
|
248
|
-
}`}
|
|
249
|
-
aria-label={accessibilityLabel}
|
|
250
|
-
>
|
|
268
|
+
<section id={tabbingId.replace('#', '')} className={getClassNames()} aria-label={accessibilityLabel}>
|
|
251
269
|
<SkipTo skipId={skipId} skipMessage='Skip Data Table' />
|
|
252
270
|
{config.table.collapsible !== false && (
|
|
253
271
|
<ExpandCollapse
|
|
@@ -263,6 +281,7 @@ const DataTable = (props: DataTableProps) => {
|
|
|
263
281
|
preliminaryData={config.preliminaryData}
|
|
264
282
|
viewport={viewport}
|
|
265
283
|
wrapColumns={wrapColumns}
|
|
284
|
+
noData={hasNoData}
|
|
266
285
|
childrenMatrix={
|
|
267
286
|
config.type === 'map'
|
|
268
287
|
? mapCellMatrix({ rows, wrapColumns, ...props, runtimeData, viewport })
|
|
@@ -306,6 +325,7 @@ const DataTable = (props: DataTableProps) => {
|
|
|
306
325
|
viewport={viewport}
|
|
307
326
|
wrapColumns={wrapColumns}
|
|
308
327
|
childrenMatrix={regionCellMatrix({ config })}
|
|
328
|
+
noData={hasNoData}
|
|
309
329
|
tableName={config.visualizationType}
|
|
310
330
|
caption='Table of the highlighted regions in the visualization'
|
|
311
331
|
headContent={
|
|
@@ -343,6 +363,7 @@ const DataTable = (props: DataTableProps) => {
|
|
|
343
363
|
viewport={viewport}
|
|
344
364
|
wrapColumns={wrapColumns}
|
|
345
365
|
childrenMatrix={boxplotCellMatrix({ rows: tableData, config })}
|
|
366
|
+
noData={hasNoData}
|
|
346
367
|
tableName={config.visualizationType}
|
|
347
368
|
caption={caption}
|
|
348
369
|
stickyHeader
|
|
@@ -2,7 +2,7 @@ import Icon from '../../ui/Icon'
|
|
|
2
2
|
import { fontSizes } from '../../../helpers/cove/fontSettings'
|
|
3
3
|
|
|
4
4
|
const ExpandCollapse = ({ expanded, setExpanded, tableTitle, fontSize, viewport }) => {
|
|
5
|
-
const titleFontSize = ['
|
|
5
|
+
const titleFontSize = ['xs', 'xxs'].includes(viewport) ? '13px' : `${fontSizes[fontSize]}px`
|
|
6
6
|
return (
|
|
7
7
|
<div
|
|
8
8
|
style={{ fontSize: titleFontSize }}
|
|
@@ -211,33 +211,15 @@ table.data-table {
|
|
|
211
211
|
}
|
|
212
212
|
button {
|
|
213
213
|
background: var(--mediumGray);
|
|
214
|
-
padding: 0.6rem 0.8rem;
|
|
215
214
|
&:hover {
|
|
216
215
|
background: lighten(var(--mediumGray), 5%);
|
|
217
216
|
}
|
|
218
217
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
background-image: url(../assets/icon-caret-filled-up.svg);
|
|
223
|
-
background-size: 10px 5px;
|
|
224
|
-
width: 10px;
|
|
225
|
-
height: 5px;
|
|
226
|
-
display: block;
|
|
227
|
-
transform: rotate(90deg);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
button.btn-prev {
|
|
231
|
-
&::before {
|
|
232
|
-
content: ' ';
|
|
233
|
-
background-image: url(../assets/icon-caret-filled-up.svg);
|
|
234
|
-
background-size: 10px 5px;
|
|
235
|
-
width: 10px;
|
|
236
|
-
height: 5px;
|
|
237
|
-
display: block;
|
|
238
|
-
transform: rotate(-90deg);
|
|
239
|
-
}
|
|
218
|
+
|
|
219
|
+
button.btn svg {
|
|
220
|
+
margin: 0px 0 3px 0;
|
|
240
221
|
}
|
|
222
|
+
|
|
241
223
|
button[disabled] {
|
|
242
224
|
background: var(--mediumGray);
|
|
243
225
|
opacity: 0.3;
|
|
@@ -16,9 +16,9 @@ const boxplotCellMatrix = ({ rows, config }): CellMatrix => {
|
|
|
16
16
|
columnThirdQuartile: labels.q3,
|
|
17
17
|
columnOutliers: labels.outliers,
|
|
18
18
|
values: labels.values,
|
|
19
|
-
|
|
19
|
+
columnCount: labels.count,
|
|
20
20
|
columnSd: 'Standard Deviation',
|
|
21
|
-
|
|
21
|
+
columnNonOutliers: 'Non Outliers',
|
|
22
22
|
columnLowerBounds: labels.lowerBounds,
|
|
23
23
|
columnUpperBounds: labels.upperBounds
|
|
24
24
|
}
|
|
@@ -28,30 +28,35 @@ const boxplotCellMatrix = ({ rows, config }): CellMatrix => {
|
|
|
28
28
|
return resolvedName
|
|
29
29
|
}
|
|
30
30
|
let resolveCell = (rowid, plot) => {
|
|
31
|
-
if (Number(rowid) === 0) return
|
|
32
|
-
if (Number(rowid) === 1) return plot.
|
|
33
|
-
if (Number(rowid) === 2) return plot.
|
|
34
|
-
if (Number(rowid) === 3) return plot.
|
|
35
|
-
if (Number(rowid) === 4) return plot.
|
|
36
|
-
if (Number(rowid) === 5) return plot.
|
|
37
|
-
if (Number(rowid) === 6) return plot.
|
|
38
|
-
if (Number(rowid) === 7) return plot.
|
|
39
|
-
if (Number(rowid) === 8) return plot.
|
|
40
|
-
if (Number(rowid) === 9) return plot.
|
|
41
|
-
if (Number(rowid) === 10) return plot.
|
|
31
|
+
if (Number(rowid) === 0) return plot.columnMax
|
|
32
|
+
if (Number(rowid) === 1) return plot.columnThirdQuartile
|
|
33
|
+
if (Number(rowid) === 2) return plot.columnMedian
|
|
34
|
+
if (Number(rowid) === 3) return plot.columnFirstQuartile
|
|
35
|
+
if (Number(rowid) === 4) return plot.columnMin
|
|
36
|
+
if (Number(rowid) === 5) return plot.columnCount
|
|
37
|
+
if (Number(rowid) === 6) return plot.columnSd
|
|
38
|
+
if (Number(rowid) === 7) return plot.columnMean
|
|
39
|
+
if (Number(rowid) === 8) return plot.columnIqr
|
|
40
|
+
if (Number(rowid) === 9) return plot.values.length > 0 ? plot.values.toString() : '-'
|
|
41
|
+
if (Number(rowid) === 10) return plot.columnLowerBounds
|
|
42
|
+
if (Number(rowid) === 11) return plot.columnUpperBounds
|
|
43
|
+
if (Number(rowid) === 12) return plot.columnOutliers.length > 0 ? plot.columnOutliers.toString() : '-'
|
|
44
|
+
if (Number(rowid) === 13) return plot.columnNonOutliers.length > 0 ? plot.columnNonOutliers.toString() : '-'
|
|
42
45
|
return <p>-</p>
|
|
43
46
|
}
|
|
44
47
|
// get list of data keys for each row
|
|
45
48
|
let dataKeys = rows.map(row => {
|
|
46
49
|
return row[0]
|
|
47
50
|
})
|
|
51
|
+
|
|
48
52
|
let columns = ['Measures', ...config.boxplot.categories]
|
|
49
53
|
dataKeys.shift() // remove index 0 // we did header column separately
|
|
54
|
+
|
|
50
55
|
return dataKeys.map((rowkey, index) => {
|
|
51
56
|
return columns.map((column, colnum) => {
|
|
52
57
|
let cellValue
|
|
53
58
|
if (column === 'Measures') {
|
|
54
|
-
let labelValue =
|
|
59
|
+
let labelValue = resolveName(rowkey)
|
|
55
60
|
cellValue = <>{labelValue}</>
|
|
56
61
|
} else {
|
|
57
62
|
cellValue = resolveCell(index, config.boxplot.plots[colnum - 1])
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseDate, formatDate } from '@cdc/core/helpers/cove/date'
|
|
2
|
-
import { formatNumber } from '
|
|
2
|
+
import { formatNumber } from '../../../helpers/cove/number'
|
|
3
3
|
import { TableConfig } from '../types/TableConfig'
|
|
4
4
|
|
|
5
5
|
// if its additional column, return formatting params
|
|
@@ -29,10 +29,18 @@ export const getChartCellValue = (row: string, column: string, config: TableConf
|
|
|
29
29
|
|
|
30
30
|
const rowObj = runtimeData[row]
|
|
31
31
|
let cellValue // placeholder for formatting below
|
|
32
|
-
|
|
32
|
+
const labelValue = rowObj[column] // just raw X axis string
|
|
33
33
|
if (column === config.xAxis?.dataKey) {
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
const { type, dateDisplayFormat, dateParseFormat } = config.xAxis || {}
|
|
35
|
+
const dateFormat = config.table?.dateDisplayFormat || dateDisplayFormat
|
|
36
|
+
|
|
37
|
+
if (type === 'date' || type === 'date-time') {
|
|
38
|
+
cellValue = formatDate(dateFormat, parseDate(dateParseFormat, labelValue))
|
|
39
|
+
} else if (type === 'continuous') {
|
|
40
|
+
cellValue = formatNumber(runtimeData[row][column], 'bottom', false, config)
|
|
41
|
+
} else {
|
|
42
|
+
cellValue = labelValue
|
|
43
|
+
}
|
|
36
44
|
} else {
|
|
37
45
|
let resolvedAxis = 'left'
|
|
38
46
|
let leftAxisItems = config.series ? config.series.filter(item => item?.axis === 'Left') : []
|
|
@@ -48,9 +56,13 @@ export const getChartCellValue = (row: string, column: string, config: TableConf
|
|
|
48
56
|
|
|
49
57
|
let addColParams = isAdditionalColumn(column, config)
|
|
50
58
|
if (addColParams) {
|
|
51
|
-
cellValue = config.dataFormat
|
|
59
|
+
cellValue = config.dataFormat
|
|
60
|
+
? formatNumber(runtimeData[row][column], resolvedAxis, false, config, addColParams)
|
|
61
|
+
: runtimeData[row][column]
|
|
52
62
|
} else {
|
|
53
|
-
cellValue = config.dataFormat
|
|
63
|
+
cellValue = config.dataFormat
|
|
64
|
+
? formatNumber(runtimeData[row][column], resolvedAxis, false, config)
|
|
65
|
+
: runtimeData[row][column]
|
|
54
66
|
}
|
|
55
67
|
}
|
|
56
68
|
|
|
@@ -63,7 +75,13 @@ export const getChartCellValue = (row: string, column: string, config: TableConf
|
|
|
63
75
|
const barSeriesExist = config.runtime?.barSeriesKeys?.includes(column)
|
|
64
76
|
const lineSeriesExist = config.runtime?.lineSeriesKeys?.includes(column)
|
|
65
77
|
const showSymbol = config.general.showSuppressedSymbol
|
|
66
|
-
if (
|
|
78
|
+
if (
|
|
79
|
+
isValueMatch &&
|
|
80
|
+
isColumnMatch &&
|
|
81
|
+
pd.displayTable &&
|
|
82
|
+
pd.type === 'suppression' &&
|
|
83
|
+
config.visualizationSubType !== 'stacked'
|
|
84
|
+
) {
|
|
67
85
|
switch (config.visualizationType) {
|
|
68
86
|
case 'Combo':
|
|
69
87
|
cellValue = barSeriesExist && showSymbol ? pd.iconCode : lineSeriesExist && showSymbol ? pd.lineCode : ''
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Tooltip from '../ui/Tooltip'
|
|
2
2
|
import Icon from '../ui/Icon'
|
|
3
|
-
import { TextField } from './Inputs'
|
|
3
|
+
import { Select, TextField } from './Inputs'
|
|
4
4
|
import { Visualization } from '../../types/Visualization'
|
|
5
5
|
import { UpdateFieldFunc } from '../../types/UpdateFieldFunc'
|
|
6
6
|
import { Column } from '../../types/Column'
|
|
@@ -16,7 +16,13 @@ interface ColumnsEditorProps {
|
|
|
16
16
|
|
|
17
17
|
type OpenControls = [Record<string, boolean>, Function] // useState type
|
|
18
18
|
|
|
19
|
-
const FieldSet: React.FC<ColumnsEditorProps & { colKey: string; controls: OpenControls }> = ({
|
|
19
|
+
const FieldSet: React.FC<ColumnsEditorProps & { colKey: string; controls: OpenControls }> = ({
|
|
20
|
+
config,
|
|
21
|
+
deleteColumn,
|
|
22
|
+
updateField,
|
|
23
|
+
colKey,
|
|
24
|
+
controls
|
|
25
|
+
}) => {
|
|
20
26
|
const [openControls, setOpenControls] = controls
|
|
21
27
|
|
|
22
28
|
const editColumn = (key, value) => {
|
|
@@ -63,43 +69,69 @@ const FieldSet: React.FC<ColumnsEditorProps & { colKey: string; controls: OpenCo
|
|
|
63
69
|
const colName = config.columns[colKey]?.name
|
|
64
70
|
|
|
65
71
|
return (
|
|
66
|
-
<FieldSetWrapper
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
<FieldSetWrapper
|
|
73
|
+
fieldName={colName}
|
|
74
|
+
fieldKey={colKey}
|
|
75
|
+
fieldType='Column'
|
|
76
|
+
controls={controls}
|
|
77
|
+
deleteField={() => deleteColumn(colKey)}
|
|
78
|
+
>
|
|
79
|
+
<Select
|
|
80
|
+
label='Column'
|
|
81
|
+
value={config.columns[colKey]?.name}
|
|
82
|
+
fieldName='name'
|
|
83
|
+
section={'columns'}
|
|
84
|
+
initial={'-Select-'}
|
|
85
|
+
options={getColumns()}
|
|
86
|
+
updateField={(_section, _subsection, _fieldName, value) => changeName(value)}
|
|
87
|
+
/>
|
|
80
88
|
{config.type !== 'table' && (
|
|
81
|
-
<
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
{(config.series || []).map(series => (
|
|
91
|
-
<option key={series.dataKey}>{series.dataKey}</option>
|
|
92
|
-
))}
|
|
93
|
-
</select>
|
|
94
|
-
</label>
|
|
89
|
+
<Select
|
|
90
|
+
label='Associate to Series'
|
|
91
|
+
value={config.columns[colKey]?.series}
|
|
92
|
+
fieldName={'series'}
|
|
93
|
+
section='columns'
|
|
94
|
+
initial={'Select series'}
|
|
95
|
+
options={config.series?.map(series => series.dataKey) || []}
|
|
96
|
+
updateField={(_section, _subsection, _fieldName, value) => editColumn('series', value)}
|
|
97
|
+
/>
|
|
95
98
|
)}
|
|
96
99
|
|
|
97
|
-
<TextField
|
|
100
|
+
<TextField
|
|
101
|
+
value={config.columns[colKey].label}
|
|
102
|
+
section='columns'
|
|
103
|
+
subsection={colKey}
|
|
104
|
+
fieldName='label'
|
|
105
|
+
label='Label'
|
|
106
|
+
updateField={updateField}
|
|
107
|
+
/>
|
|
98
108
|
<ul className='column-edit'>
|
|
99
109
|
<li className='three-col'>
|
|
100
|
-
<TextField
|
|
101
|
-
|
|
102
|
-
|
|
110
|
+
<TextField
|
|
111
|
+
value={config.columns[colKey].prefix}
|
|
112
|
+
section='columns'
|
|
113
|
+
subsection={colKey}
|
|
114
|
+
fieldName='prefix'
|
|
115
|
+
label='Prefix'
|
|
116
|
+
updateField={updateField}
|
|
117
|
+
/>
|
|
118
|
+
<TextField
|
|
119
|
+
value={config.columns[colKey].suffix}
|
|
120
|
+
section='columns'
|
|
121
|
+
subsection={colKey}
|
|
122
|
+
fieldName='suffix'
|
|
123
|
+
label='Suffix'
|
|
124
|
+
updateField={updateField}
|
|
125
|
+
/>
|
|
126
|
+
<TextField
|
|
127
|
+
type='number'
|
|
128
|
+
value={config.columns[colKey].roundToPlace}
|
|
129
|
+
section='columns'
|
|
130
|
+
subsection={colKey}
|
|
131
|
+
fieldName='roundToPlace'
|
|
132
|
+
label='Round'
|
|
133
|
+
updateField={updateField}
|
|
134
|
+
/>
|
|
103
135
|
</li>
|
|
104
136
|
<li>
|
|
105
137
|
<label className='checkbox'>
|
|
@@ -202,7 +234,13 @@ const FieldSet: React.FC<ColumnsEditorProps & { colKey: string; controls: OpenCo
|
|
|
202
234
|
</ul>
|
|
203
235
|
<label>
|
|
204
236
|
<span className='edit-label column-heading'>Order</span>
|
|
205
|
-
<input
|
|
237
|
+
<input
|
|
238
|
+
onWheel={e => e.currentTarget.blur()}
|
|
239
|
+
type='number'
|
|
240
|
+
min='1'
|
|
241
|
+
value={config.columns[colKey].order}
|
|
242
|
+
onChange={e => updateField('columns', colKey, 'order', parseInt(e.target.value))}
|
|
243
|
+
/>
|
|
206
244
|
</label>
|
|
207
245
|
</FieldSetWrapper>
|
|
208
246
|
)
|
|
@@ -252,7 +290,14 @@ const ColumnsEditor: React.FC<ColumnsEditorProps> = ({ config, updateField, dele
|
|
|
252
290
|
</span>
|
|
253
291
|
</label>
|
|
254
292
|
{additionalColumns.map((val, i) => (
|
|
255
|
-
<FieldSet
|
|
293
|
+
<FieldSet
|
|
294
|
+
key={val + i}
|
|
295
|
+
controls={openControls}
|
|
296
|
+
config={config}
|
|
297
|
+
deleteColumn={deleteColumn}
|
|
298
|
+
updateField={updateField}
|
|
299
|
+
colKey={val}
|
|
300
|
+
/>
|
|
256
301
|
))}
|
|
257
302
|
<button
|
|
258
303
|
className={'btn btn-primary'}
|