@cdc/core 4.23.10 → 4.24.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/LICENSE +201 -0
- package/assets/icon-deviation-bar.svg +1 -0
- package/components/DataTable/DataTable.tsx +223 -0
- package/components/DataTable/components/BoxplotHeader.tsx +16 -0
- package/components/DataTable/components/CellAnchor.tsx +44 -0
- package/components/DataTable/components/ChartHeader.tsx +103 -0
- package/components/DataTable/components/ExpandCollapse.tsx +21 -0
- package/components/DataTable/components/Icons.tsx +10 -0
- package/components/DataTable/components/MapHeader.tsx +56 -0
- package/components/DataTable/components/SkipNav.tsx +7 -0
- package/components/DataTable/helpers/boxplotCellMatrix.tsx +64 -0
- package/components/DataTable/helpers/chartCellMatrix.tsx +92 -0
- package/components/DataTable/helpers/customColumns.ts +25 -0
- package/components/DataTable/helpers/customSort.ts +55 -0
- package/components/DataTable/helpers/getChartCellValue.ts +56 -0
- package/components/DataTable/helpers/getDataSeriesColumns.ts +29 -0
- package/components/DataTable/helpers/getSeriesName.ts +26 -0
- package/components/DataTable/helpers/mapCellMatrix.tsx +56 -0
- package/components/DataTable/helpers/regionCellMatrix.tsx +13 -0
- package/components/DataTable/helpers/standardizeState.js +76 -0
- package/components/DataTable/index.ts +1 -0
- package/components/DataTable/types/TableConfig.ts +52 -0
- package/components/DownloadButton.tsx +29 -0
- package/components/EditorPanel/DataTableEditor.tsx +133 -0
- package/components/EditorPanel/Inputs.tsx +150 -0
- package/components/Filters.jsx +3 -3
- package/components/LegendCircle.jsx +2 -2
- package/components/MediaControls.jsx +1 -1
- package/components/MultiSelect/MultiSelect.tsx +95 -0
- package/components/MultiSelect/index.ts +1 -0
- package/components/MultiSelect/multiselect.styles.css +50 -0
- package/components/Table/Table.tsx +69 -0
- package/components/Table/components/Cell.tsx +9 -0
- package/components/Table/components/GroupRow.tsx +20 -0
- package/components/Table/components/Row.tsx +26 -0
- package/components/Table/index.ts +1 -0
- package/components/Table/types/CellMatrix.ts +4 -0
- package/components/Table/types/RowType.ts +5 -0
- package/components/_stories/DataTable.stories.tsx +103 -0
- package/components/_stories/EditorPanel.stories.tsx +53 -0
- package/components/_stories/Inputs.stories.tsx +37 -0
- package/components/_stories/MultiSelect.stories.tsx +24 -0
- package/components/_stories/Table.stories.tsx +53 -0
- package/components/_stories/_mocks/dashboard_no_filter.json +121 -0
- package/components/_stories/_mocks/example-city-state.json +808 -0
- package/components/_stories/_mocks/row_type.json +42 -0
- package/components/_stories/styles.scss +9 -0
- package/components/inputs/{InputSelect.jsx → InputSelect.tsx} +15 -5
- package/components/managers/{DataDesigner.jsx → DataDesigner.tsx} +103 -94
- package/components/ui/{Icon.jsx → Icon.tsx} +3 -3
- package/components/ui/Title/Title.scss +95 -0
- package/components/ui/Title/index.tsx +34 -0
- package/components/ui/_stories/Title.stories.tsx +21 -0
- package/helpers/DataTransform.ts +75 -20
- package/helpers/cove/string.ts +11 -0
- package/helpers/fetchRemoteData.js +1 -1
- package/helpers/getFileExtension.ts +28 -5
- package/package.json +2 -2
- package/styles/_data-table.scss +3 -0
- package/styles/heading-colors.scss +0 -3
- package/styles/v2/layout/_component.scss +0 -11
- package/types/Axis.ts +41 -0
- package/types/Color.ts +5 -0
- package/types/Column.ts +15 -0
- package/types/ComponentStyles.ts +7 -0
- package/types/ComponentThemes.ts +13 -0
- package/types/EditorColumnProperties.ts +8 -0
- package/types/FilterBehavior.ts +1 -0
- package/types/Runtime.ts +29 -0
- package/types/Series.ts +1 -0
- package/types/Table.ts +18 -0
- package/types/UpdateFieldFunc.ts +1 -0
- package/types/Visualization.ts +21 -0
- package/components/DataTable.jsx +0 -754
package/helpers/DataTransform.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type DataArray = Record<string,any>[]
|
|
1
|
+
type DataArray = Record<string, any>[]
|
|
2
2
|
|
|
3
3
|
export class DataTransform {
|
|
4
4
|
constants: any
|
|
@@ -17,12 +17,12 @@ export class DataTransform {
|
|
|
17
17
|
const errorsFound: any[] = []
|
|
18
18
|
|
|
19
19
|
// Empty data
|
|
20
|
-
if (0 === data.length) {
|
|
20
|
+
if (!data || 0 === data.length) {
|
|
21
21
|
errorsFound.push(this.constants.errorMessageEmptyData)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
// Does it have the correct data structure?
|
|
25
|
-
if (!data
|
|
25
|
+
if (!data?.filter || data.filter(row => typeof row !== 'object').length > 0) {
|
|
26
26
|
errorsFound.push(this.constants.errorMessageFormat)
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -49,6 +49,10 @@ export class DataTransform {
|
|
|
49
49
|
|
|
50
50
|
//Performs standardizations based on developer provided description of the data
|
|
51
51
|
developerStandardize(data, description) {
|
|
52
|
+
if (!data) {
|
|
53
|
+
return []
|
|
54
|
+
}
|
|
55
|
+
|
|
52
56
|
//Validate the description object
|
|
53
57
|
if (!description) {
|
|
54
58
|
return undefined
|
|
@@ -98,7 +102,7 @@ export class DataTransform {
|
|
|
98
102
|
|
|
99
103
|
return standardized
|
|
100
104
|
} else {
|
|
101
|
-
let standardized: {key: string
|
|
105
|
+
let standardized: { key: string; value: any }[] = []
|
|
102
106
|
|
|
103
107
|
data.forEach(row => {
|
|
104
108
|
let nonNumericKeys: string[] = []
|
|
@@ -124,8 +128,36 @@ export class DataTransform {
|
|
|
124
128
|
return standardized
|
|
125
129
|
}
|
|
126
130
|
} else if (description.series === true && description.singleRow === false) {
|
|
127
|
-
if (description.seriesKey !== undefined && description.xKey !== undefined && (description.valueKey !== undefined || (description.valueKeys !== undefined && description.valueKeys.length > 0))) {
|
|
128
|
-
if (description.
|
|
131
|
+
if (description.seriesKey !== undefined && description.xKey !== undefined && (description.valueKey !== undefined || (description.valueKeys !== undefined && description.valueKeys.length > 0) || (description.valueKeysTallSupport !== undefined && description.valueKeysTallSupport.length > 0))) {
|
|
132
|
+
if (description.valueKeysTallSupport !== undefined) {
|
|
133
|
+
let standardizedMapped = {}
|
|
134
|
+
let standardized: string[] = []
|
|
135
|
+
|
|
136
|
+
data.forEach(row => {
|
|
137
|
+
let uniqueKey = row[description.xKey];
|
|
138
|
+
Object.keys(row).forEach(key => {
|
|
139
|
+
if(key !== description.xKey && key !== description.seriesKey && description.valueKeysTallSupport.indexOf(key) === -1 && (!description.ignoredKeys || description.ignoredKeys.indexOf(key) === -1)){
|
|
140
|
+
uniqueKey += "|" + row[key];
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
if(!standardizedMapped[uniqueKey]){
|
|
145
|
+
standardizedMapped[uniqueKey] = {[description.xKey]: row[description.xKey]}
|
|
146
|
+
}
|
|
147
|
+
Object.keys(row).forEach(key => {
|
|
148
|
+
if(key !== description.xKey && key !== description.seriesKey && description.valueKeysTallSupport.indexOf(key) === -1 && (!description.ignoredKeys || description.ignoredKeys.indexOf(key) === -1)){
|
|
149
|
+
standardizedMapped[uniqueKey][key] = row[key];
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
description.valueKeysTallSupport.forEach(valueKey => {
|
|
153
|
+
standardizedMapped[uniqueKey][row[description.seriesKey] + '-' + valueKey] = row[valueKey];
|
|
154
|
+
})
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
standardized = Object.keys(standardizedMapped).map(key => standardizedMapped[key]);
|
|
158
|
+
|
|
159
|
+
return standardized
|
|
160
|
+
} else if (description.valueKeys !== undefined) {
|
|
129
161
|
let standardizedMapped = {}
|
|
130
162
|
let standardized: string[] = []
|
|
131
163
|
let valueKeys = description.valueKeys
|
|
@@ -218,7 +250,7 @@ export class DataTransform {
|
|
|
218
250
|
*/
|
|
219
251
|
cleanData(data: DataArray, excludeKey, testing = false): DataArray {
|
|
220
252
|
let cleanedupData: DataArray = []
|
|
221
|
-
if(!Array.isArray(data)) debugger
|
|
253
|
+
if (!Array.isArray(data)) debugger
|
|
222
254
|
if (testing) console.log('## Data to clean=', data)
|
|
223
255
|
if (excludeKey === undefined) {
|
|
224
256
|
console.log('COVE: cleanData excludeKey undefined')
|
|
@@ -228,7 +260,7 @@ export class DataTransform {
|
|
|
228
260
|
if (testing) console.log('clean', i, ' d', d)
|
|
229
261
|
let cleaned = {}
|
|
230
262
|
Object.keys(d).forEach(function (key) {
|
|
231
|
-
const value = d[key]
|
|
263
|
+
const value = d[key]
|
|
232
264
|
if (key === excludeKey) {
|
|
233
265
|
// pass thru
|
|
234
266
|
cleaned[key] = value
|
|
@@ -259,21 +291,44 @@ export class DataTransform {
|
|
|
259
291
|
return cleanedupData
|
|
260
292
|
}
|
|
261
293
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (testing) console.log('clean', data)
|
|
265
|
-
let cleaned = ''
|
|
294
|
+
applySuppression = (data, suppressedData) => {
|
|
295
|
+
if (!suppressedData || suppressedData.length === 0) return data
|
|
266
296
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
297
|
+
// Create a new array to store the result without modifying the original data
|
|
298
|
+
const result = data.map(item => {
|
|
299
|
+
// Create a new object to store the updated item without modifying the original item
|
|
300
|
+
const newItem = { ...item }
|
|
301
|
+
|
|
302
|
+
// For each suppressedData item
|
|
303
|
+
for (let i = 0; i < suppressedData.length; i++) {
|
|
304
|
+
// If the object contains the column and its value matches the suppressed one
|
|
305
|
+
if (newItem[suppressedData[i].column] && newItem[suppressedData[i].column] === suppressedData[i].value) {
|
|
306
|
+
// Replace the value with the label in the new object
|
|
307
|
+
newItem[suppressedData[i].column] = suppressedData[i].label
|
|
308
|
+
}
|
|
273
309
|
}
|
|
274
310
|
|
|
275
|
-
|
|
276
|
-
|
|
311
|
+
return newItem
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
return result
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// clean out %, $, commas from numbers when needing to do sorting!
|
|
318
|
+
cleanDataPoint(data, testing = false) {
|
|
319
|
+
if (testing) console.log('clean', data)
|
|
320
|
+
let cleaned = ''
|
|
321
|
+
|
|
322
|
+
// remove comma and dollar signs
|
|
323
|
+
let tmp = ''
|
|
324
|
+
if (typeof data === 'string') {
|
|
325
|
+
tmp = data !== null && data !== '' ? data.replace(/[,\$\%]/g, '') : ''
|
|
326
|
+
} else {
|
|
327
|
+
tmp = data !== null && data !== '' ? data : ''
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (testing) console.log('## cleanedData =', tmp)
|
|
331
|
+
return tmp
|
|
277
332
|
}
|
|
278
333
|
}
|
|
279
334
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* regex
|
|
3
|
+
* - /\w\S* replaces zero or more whitespace characters
|
|
4
|
+
* - g makes it find all matches in the string
|
|
5
|
+
* - the callback function capitalizes the word
|
|
6
|
+
* */
|
|
7
|
+
export const capitalizeSplitAndJoin = function (splittingCharacter: string = ' ', joiningCharacter: string = '') {
|
|
8
|
+
return this.split(splittingCharacter)
|
|
9
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
10
|
+
.join(joiningCharacter)
|
|
11
|
+
}
|
|
@@ -1,5 +1,28 @@
|
|
|
1
|
-
export const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
1
|
+
// export const getFileExtensionx = (path: string): string => {
|
|
2
|
+
// const regex = /(?:\.([^.]+))?$/
|
|
3
|
+
// const outCome: RegExpExecArray | null = regex.exec(path)
|
|
4
|
+
// return outCome ? outCome[1] : ''
|
|
5
|
+
// }
|
|
6
|
+
|
|
7
|
+
export const getFileExtension = (url: string): string => {
|
|
8
|
+
const regexForExtension = /(?:\.([^.]+))$/
|
|
9
|
+
const regexForQueryParam = /[?&]wt=(csv|json)(?:&|$)/ // Regular expression for 'wt' query parameter
|
|
10
|
+
|
|
11
|
+
const urlObject = new URL(url, window.location.origin)
|
|
12
|
+
const pathname = urlObject.pathname
|
|
13
|
+
const searchParams = urlObject.search
|
|
14
|
+
|
|
15
|
+
// First, try to get the extension from the pathname
|
|
16
|
+
const pathnameMatch = regexForExtension.exec(pathname)
|
|
17
|
+
if (pathnameMatch && pathnameMatch[1]) {
|
|
18
|
+
return pathnameMatch[1]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Then, try to get it from the query parameter 'wt'
|
|
22
|
+
const queryParamsMatch = regexForQueryParam.exec(searchParams)
|
|
23
|
+
if (queryParamsMatch && queryParamsMatch[1]) {
|
|
24
|
+
return queryParamsMatch[1]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return ''
|
|
28
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.24.1",
|
|
4
4
|
"description": "Core components, styles, hooks, and helpers, for the CDC Open Visualization project",
|
|
5
5
|
"moduleName": "CdcCore",
|
|
6
6
|
"main": "dist/cdccore",
|
|
@@ -30,5 +30,5 @@
|
|
|
30
30
|
"react": "^18.2.0",
|
|
31
31
|
"react-dom": "^18.2.0"
|
|
32
32
|
},
|
|
33
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "a352a3f74f4b681191e3244061dbb3621f36eec3"
|
|
34
34
|
}
|
package/styles/_data-table.scss
CHANGED
|
@@ -51,6 +51,7 @@ table.data-table {
|
|
|
51
51
|
overflow: auto;
|
|
52
52
|
appearance: none;
|
|
53
53
|
table-layout: fixed;
|
|
54
|
+
display: grid;
|
|
54
55
|
* {
|
|
55
56
|
box-sizing: border-box;
|
|
56
57
|
}
|
|
@@ -64,6 +65,7 @@ table.data-table {
|
|
|
64
65
|
background: none;
|
|
65
66
|
font-size: initial;
|
|
66
67
|
color: #fff;
|
|
68
|
+
border: 0;
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
tr {
|
|
@@ -136,6 +138,7 @@ table.data-table {
|
|
|
136
138
|
}
|
|
137
139
|
|
|
138
140
|
tbody {
|
|
141
|
+
display: table-cell;
|
|
139
142
|
tr {
|
|
140
143
|
width: 100%;
|
|
141
144
|
&:hover {
|
|
@@ -3,17 +3,6 @@
|
|
|
3
3
|
// box-shadow: rgba(0, 0, 0, 0.2) 3px 6px 10px; // no box shadows
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
.cove-component__header {
|
|
7
|
-
width: 100%;
|
|
8
|
-
padding: 0.6rem 0.8rem;
|
|
9
|
-
border-bottom-width: 3px;
|
|
10
|
-
border-bottom-style: solid;
|
|
11
|
-
border-radius: 3px 3px 0 0;
|
|
12
|
-
font-size: 1.1rem;
|
|
13
|
-
transition: background-color 200ms ease, border-color 200ms ease;
|
|
14
|
-
color: #fff;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
6
|
.cove-component__content {
|
|
18
7
|
padding-top: 1rem;
|
|
19
8
|
border: solid 1px #ccc;
|
package/types/Axis.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type Anchor = {
|
|
2
|
+
value: string
|
|
3
|
+
color: string
|
|
4
|
+
lineStyle: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type Axis = {
|
|
8
|
+
anchors?: Anchor[]
|
|
9
|
+
dataKey: string
|
|
10
|
+
dateDisplayFormat: string
|
|
11
|
+
dateParseFormat: string
|
|
12
|
+
displayNumbersOnBar?: boolean
|
|
13
|
+
enablePadding?: boolean
|
|
14
|
+
gridLines?: boolean
|
|
15
|
+
hideAxis?: boolean
|
|
16
|
+
hideLabel?: boolean
|
|
17
|
+
hideTicks?: boolean
|
|
18
|
+
label?: string
|
|
19
|
+
labelOffset?: number
|
|
20
|
+
labelPlacement?: string
|
|
21
|
+
max?: string
|
|
22
|
+
maxTickRotation?: number
|
|
23
|
+
min?: string
|
|
24
|
+
numTicks?: number
|
|
25
|
+
rightAxisSize?: number
|
|
26
|
+
rightHideAxis?: boolean
|
|
27
|
+
rightHideLabel?: boolean
|
|
28
|
+
rightHideTicks?: boolean
|
|
29
|
+
rightLabel?: string
|
|
30
|
+
rightLabelOffsetSize?: number
|
|
31
|
+
rightMax?: string
|
|
32
|
+
rightNumTicks?: number
|
|
33
|
+
sortDates?: boolean
|
|
34
|
+
showTargetLabel?: boolean
|
|
35
|
+
size?: number
|
|
36
|
+
target?: number
|
|
37
|
+
targetLabel?: string
|
|
38
|
+
tickRotation?: number
|
|
39
|
+
tickWidthMax?: number
|
|
40
|
+
type: string
|
|
41
|
+
}
|
package/types/Color.ts
ADDED
package/types/Column.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type Column = {
|
|
2
|
+
name?: string
|
|
3
|
+
label: string
|
|
4
|
+
prefix: string
|
|
5
|
+
suffix: string
|
|
6
|
+
roundToPlace: number
|
|
7
|
+
commas: boolean
|
|
8
|
+
dataTable: boolean
|
|
9
|
+
startingPoint: string
|
|
10
|
+
series?: string
|
|
11
|
+
tooltips: boolean
|
|
12
|
+
forestPlot: boolean
|
|
13
|
+
forestPlotAlignRight: boolean
|
|
14
|
+
forestPlotStartingPoint: number
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type FilterBehavior = 'Apply Button' | 'Filter Change'
|
package/types/Runtime.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Axis } from './Axis'
|
|
2
|
+
|
|
3
|
+
export type ForecastingSeriesKey = {
|
|
4
|
+
stages: {
|
|
5
|
+
key: string
|
|
6
|
+
color: string
|
|
7
|
+
}[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type BarSeriesKey = {
|
|
11
|
+
key: string
|
|
12
|
+
color: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type Runtime = {
|
|
16
|
+
barSeriesKeys?: BarSeriesKey[]
|
|
17
|
+
forecastingSeriesKeys?: ForecastingSeriesKey[]
|
|
18
|
+
originalXAxis: {
|
|
19
|
+
dataKey: string
|
|
20
|
+
name: string
|
|
21
|
+
axis: string
|
|
22
|
+
}
|
|
23
|
+
xAxis: Axis
|
|
24
|
+
yAxis: Axis
|
|
25
|
+
seriesKeys: any[]
|
|
26
|
+
seriesLabels: string[]
|
|
27
|
+
seriesLabelsAll: string[]
|
|
28
|
+
editorErrorMessage: string
|
|
29
|
+
}
|
package/types/Series.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type Series = { dataKey: string; name: string; axis: string; type: string }[]
|
package/types/Table.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type Table = {
|
|
2
|
+
cellMinWidth?: number
|
|
3
|
+
label?: string
|
|
4
|
+
show?: boolean
|
|
5
|
+
showVertical?: boolean
|
|
6
|
+
indexLabel?: string
|
|
7
|
+
caption?: string
|
|
8
|
+
limitHeight?: boolean
|
|
9
|
+
height?: number
|
|
10
|
+
expanded?: boolean
|
|
11
|
+
showDataTableLink?: boolean
|
|
12
|
+
showDownloadUrl?: boolean
|
|
13
|
+
download?: boolean
|
|
14
|
+
showDownloadImgButton?: boolean
|
|
15
|
+
showDownloadPdfButton?: boolean
|
|
16
|
+
customTableConfig?: boolean
|
|
17
|
+
excludeColumns?: string[]
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type UpdateFieldFunc<T> = (section: string | null, subsection: string | null, fieldName: string, value: T) => void
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type Visualization = {
|
|
2
|
+
autoLoad: boolean
|
|
3
|
+
data: any
|
|
4
|
+
dataDescription: Object
|
|
5
|
+
dataKey: string
|
|
6
|
+
editing: boolean
|
|
7
|
+
formattedData: any
|
|
8
|
+
general: any
|
|
9
|
+
hide: any[]
|
|
10
|
+
newViz: boolean
|
|
11
|
+
openModal: boolean
|
|
12
|
+
originalFormattedData: any
|
|
13
|
+
table: {
|
|
14
|
+
showDataTableLink: boolean
|
|
15
|
+
}
|
|
16
|
+
title: string
|
|
17
|
+
type: 'chart' | 'map' | 'data-bite' | 'waffle-chart' | 'markup-include' | 'filtered-text' | 'filter-dropdowns'
|
|
18
|
+
uid: string
|
|
19
|
+
usesSharedFilter: any
|
|
20
|
+
visualizationType: string
|
|
21
|
+
}
|