@cdc/core 4.23.5 → 4.23.7
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/assets/icon-filter-dropdowns.svg +1 -0
- package/assets/icon-linear-gauge.svg +1 -0
- package/components/AdvancedEditor.jsx +7 -1
- package/components/DataTable.jsx +91 -44
- package/components/Filters.jsx +2 -0
- package/components/{CoveMediaControls.jsx → MediaControls.jsx} +6 -6
- package/components/RepeatableGroup.jsx +37 -0
- package/components/inputs/InputSelect.jsx +1 -1
- package/components/ui/Accordion.jsx +3 -0
- package/components/ui/Icon.jsx +4 -2
- package/components/ui/Tooltip.jsx +10 -22
- package/helpers/DataTransform.js +65 -65
- package/helpers/cove/date.js +9 -0
- package/helpers/cove/number.js +166 -0
- package/helpers/coveUpdateWorker.js +15 -0
- package/helpers/fetchRemoteData.js +12 -2
- package/helpers/ver/4.23.js +10 -0
- package/package.json +2 -2
- package/styles/v2/components/input/_input.scss +3 -3
- package/styles/v2/components/ui/tooltip.scss +90 -73
- package/styles/v2/layout/_component.scss +1 -1
- package/LICENSE +0 -201
- /package/assets/{filtered-text.svg → icon-filtered-text.svg} +0 -0
package/helpers/DataTransform.js
CHANGED
|
@@ -11,109 +11,109 @@ export class DataTransform {
|
|
|
11
11
|
|
|
12
12
|
//Performs standardizations that can be completed automatically without use input
|
|
13
13
|
autoStandardize(data) {
|
|
14
|
-
const errorsFound = []
|
|
14
|
+
const errorsFound = []
|
|
15
15
|
|
|
16
16
|
// Empty data
|
|
17
17
|
if (0 === data.length) {
|
|
18
|
-
errorsFound.push(this.constants.errorMessageEmptyData)
|
|
18
|
+
errorsFound.push(this.constants.errorMessageEmptyData)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
// Does it have the correct data structure?
|
|
22
22
|
if (!data.filter || data.filter(row => typeof row !== 'object').length > 0) {
|
|
23
|
-
errorsFound.push(this.constants.errorMessageFormat)
|
|
23
|
+
errorsFound.push(this.constants.errorMessageFormat)
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
if (errorsFound.length > 0) {
|
|
27
|
-
console.error(errorsFound)
|
|
28
|
-
return undefined
|
|
27
|
+
console.error(errorsFound)
|
|
28
|
+
return undefined
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
//Convert array of arrays, to array of objects
|
|
32
32
|
if (data.filter(row => row.constructor !== Object).length > 0) {
|
|
33
|
-
let standardizedData = []
|
|
33
|
+
let standardizedData = []
|
|
34
34
|
for (let row = 1; row < data.length; row++) {
|
|
35
|
-
let standardizedRow = {}
|
|
35
|
+
let standardizedRow = {}
|
|
36
36
|
data[row].forEach((datum, col) => {
|
|
37
|
-
standardizedRow[data[0][col]] = datum
|
|
37
|
+
standardizedRow[data[0][col]] = datum
|
|
38
38
|
})
|
|
39
|
-
standardizedData.push(standardizedRow)
|
|
39
|
+
standardizedData.push(standardizedRow)
|
|
40
40
|
}
|
|
41
|
-
data = standardizedData
|
|
41
|
+
data = standardizedData
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
return data
|
|
44
|
+
return data
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
//Performs standardizations based on developer provided description of the data
|
|
48
48
|
developerStandardize(data, description) {
|
|
49
49
|
//Validate the description object
|
|
50
50
|
if (!description) {
|
|
51
|
-
return undefined
|
|
51
|
+
return undefined
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
if (description.horizontal === undefined || description.series === undefined) {
|
|
55
|
-
return undefined
|
|
55
|
+
return undefined
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
if (description.series === true && description.horizontal === false && description.singleRow === undefined) {
|
|
59
|
-
return undefined
|
|
59
|
+
return undefined
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
if (description.horizontal === true) {
|
|
63
63
|
if (description.series === true) {
|
|
64
64
|
if (!description.seriesKey) {
|
|
65
|
-
return undefined
|
|
65
|
+
return undefined
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
let standardizedMapped = {}
|
|
69
|
-
let standardized = []
|
|
68
|
+
let standardizedMapped = {}
|
|
69
|
+
let standardized = []
|
|
70
70
|
data.forEach(row => {
|
|
71
|
-
let nonNumericKeys = []
|
|
71
|
+
let nonNumericKeys = []
|
|
72
72
|
Object.keys(row).forEach(key => {
|
|
73
73
|
if (key !== description.seriesKey && isNaN(parseFloat(row[key]))) {
|
|
74
|
-
nonNumericKeys.push(key)
|
|
74
|
+
nonNumericKeys.push(key)
|
|
75
75
|
}
|
|
76
76
|
})
|
|
77
77
|
|
|
78
78
|
Object.keys(row).forEach(key => {
|
|
79
79
|
if (key !== description.seriesKey && nonNumericKeys.indexOf(key) === -1) {
|
|
80
|
-
let uniqueKey = key + '|' + nonNumericKeys.map(nonNumericKey => nonNumericKey + '=' + row[nonNumericKey])
|
|
80
|
+
let uniqueKey = key + '|' + nonNumericKeys.map(nonNumericKey => nonNumericKey + '=' + row[nonNumericKey])
|
|
81
81
|
if (!standardizedMapped[uniqueKey]) {
|
|
82
|
-
standardizedMapped[uniqueKey] = { [row[description.seriesKey]]: row[key], key }
|
|
82
|
+
standardizedMapped[uniqueKey] = { [row[description.seriesKey]]: row[key], key }
|
|
83
83
|
nonNumericKeys.forEach(nonNumericKey => {
|
|
84
|
-
standardizedMapped[uniqueKey][nonNumericKey] = row[nonNumericKey]
|
|
84
|
+
standardizedMapped[uniqueKey][nonNumericKey] = row[nonNumericKey]
|
|
85
85
|
})
|
|
86
86
|
}
|
|
87
|
-
standardizedMapped[uniqueKey][row[description.seriesKey]] = row[key]
|
|
87
|
+
standardizedMapped[uniqueKey][row[description.seriesKey]] = row[key]
|
|
88
88
|
}
|
|
89
89
|
})
|
|
90
90
|
})
|
|
91
91
|
|
|
92
92
|
Object.keys(standardizedMapped).forEach(key => {
|
|
93
|
-
standardized.push(standardizedMapped[key])
|
|
93
|
+
standardized.push(standardizedMapped[key])
|
|
94
94
|
})
|
|
95
95
|
|
|
96
|
-
return standardized
|
|
96
|
+
return standardized
|
|
97
97
|
} else {
|
|
98
|
-
let standardized = []
|
|
98
|
+
let standardized = []
|
|
99
99
|
|
|
100
100
|
data.forEach(row => {
|
|
101
|
-
let nonNumericKeys = []
|
|
101
|
+
let nonNumericKeys = []
|
|
102
102
|
Object.keys(row).forEach(key => {
|
|
103
103
|
if (isNaN(parseFloat(row[key]))) {
|
|
104
|
-
nonNumericKeys.push(key)
|
|
104
|
+
nonNumericKeys.push(key)
|
|
105
105
|
}
|
|
106
106
|
})
|
|
107
107
|
|
|
108
108
|
Object.keys(row).forEach(key => {
|
|
109
109
|
if (nonNumericKeys.indexOf(key) === -1) {
|
|
110
|
-
let newRow = { key, value: row[key] }
|
|
110
|
+
let newRow = { key, value: row[key] }
|
|
111
111
|
|
|
112
112
|
nonNumericKeys.forEach(nonNumericKey => {
|
|
113
|
-
newRow[nonNumericKey] = row[nonNumericKey]
|
|
113
|
+
newRow[nonNumericKey] = row[nonNumericKey]
|
|
114
114
|
})
|
|
115
115
|
|
|
116
|
-
standardized.push(newRow)
|
|
116
|
+
standardized.push(newRow)
|
|
117
117
|
}
|
|
118
118
|
})
|
|
119
119
|
})
|
|
@@ -122,43 +122,43 @@ export class DataTransform {
|
|
|
122
122
|
}
|
|
123
123
|
} else if (description.series === true && description.singleRow === false) {
|
|
124
124
|
if (description.seriesKey !== undefined && description.xKey !== undefined && (description.valueKey !== undefined || (description.valueKeys !== undefined && description.valueKeys.length > 0))) {
|
|
125
|
-
if(description.valueKeys !== undefined){
|
|
126
|
-
let standardizedMapped = {}
|
|
127
|
-
let standardized = []
|
|
128
|
-
let valueKeys = description.valueKeys
|
|
129
|
-
if(description.ignoredKeys && description.ignoredKeys.length > 0){
|
|
130
|
-
valueKeys = valueKeys.concat(description.ignoredKeys)
|
|
125
|
+
if (description.valueKeys !== undefined) {
|
|
126
|
+
let standardizedMapped = {}
|
|
127
|
+
let standardized = []
|
|
128
|
+
let valueKeys = description.valueKeys
|
|
129
|
+
if (description.ignoredKeys && description.ignoredKeys.length > 0) {
|
|
130
|
+
valueKeys = valueKeys.concat(description.ignoredKeys)
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
data.forEach(row => {
|
|
134
134
|
valueKeys.forEach(valueKey => {
|
|
135
|
-
let extraKeys = []
|
|
136
|
-
let uniqueKey = row[description.xKey] + '|' + valueKey
|
|
135
|
+
let extraKeys = []
|
|
136
|
+
let uniqueKey = row[description.xKey] + '|' + valueKey
|
|
137
137
|
Object.keys(row).forEach(key => {
|
|
138
138
|
if (key !== description.xKey && key !== description.seriesKey && valueKeys.indexOf(key) === -1) {
|
|
139
|
-
uniqueKey += '|' + key + '=' + row[key]
|
|
140
|
-
extraKeys.push(key)
|
|
139
|
+
uniqueKey += '|' + key + '=' + row[key]
|
|
140
|
+
extraKeys.push(key)
|
|
141
141
|
}
|
|
142
142
|
})
|
|
143
143
|
|
|
144
|
-
if(!standardizedMapped[uniqueKey]){
|
|
145
|
-
standardizedMapped[uniqueKey] = { [description.xKey]: row[description.xKey], '**Numeric Value Property**': valueKey }
|
|
144
|
+
if (!standardizedMapped[uniqueKey]) {
|
|
145
|
+
standardizedMapped[uniqueKey] = { [description.xKey]: row[description.xKey], '**Numeric Value Property**': valueKey }
|
|
146
146
|
extraKeys.forEach(key => {
|
|
147
|
-
standardizedMapped[uniqueKey][key] = row[key]
|
|
147
|
+
standardizedMapped[uniqueKey][key] = row[key]
|
|
148
148
|
})
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
standardizedMapped[uniqueKey][row[description.seriesKey]] = row[valueKey]
|
|
152
|
-
})
|
|
151
|
+
standardizedMapped[uniqueKey][row[description.seriesKey]] = row[valueKey]
|
|
152
|
+
})
|
|
153
153
|
})
|
|
154
154
|
|
|
155
155
|
Object.keys(standardizedMapped).forEach(key => {
|
|
156
|
-
if(!description.ignoredKeys || description.ignoredKeys.indexOf(standardizedMapped[key]['**Numeric Value Property**']) === -1){
|
|
157
|
-
standardized.push(standardizedMapped[key])
|
|
156
|
+
if (!description.ignoredKeys || description.ignoredKeys.indexOf(standardizedMapped[key]['**Numeric Value Property**']) === -1) {
|
|
157
|
+
standardized.push(standardizedMapped[key])
|
|
158
158
|
}
|
|
159
159
|
})
|
|
160
160
|
|
|
161
|
-
return standardized
|
|
161
|
+
return standardized
|
|
162
162
|
} else {
|
|
163
163
|
let standardizedMapped = {}
|
|
164
164
|
let standardized = []
|
|
@@ -190,14 +190,14 @@ export class DataTransform {
|
|
|
190
190
|
return standardized
|
|
191
191
|
}
|
|
192
192
|
} else {
|
|
193
|
-
return undefined
|
|
193
|
+
return undefined
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
return data
|
|
197
|
+
return data
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
|
|
200
|
+
/**
|
|
201
201
|
* cleanData
|
|
202
202
|
*
|
|
203
203
|
// This cleans a data set by:
|
|
@@ -207,21 +207,21 @@ export class DataTransform {
|
|
|
207
207
|
*
|
|
208
208
|
* Inputs: data as array, excludeKey indicates which key to use to NOT clean
|
|
209
209
|
* Example: "Date" should not be cleaned if part of the data
|
|
210
|
-
*
|
|
210
|
+
*
|
|
211
211
|
* Output: returns the cleanedData
|
|
212
|
-
*
|
|
212
|
+
*
|
|
213
213
|
* Set testing = true if you need to see before and after data
|
|
214
|
-
*
|
|
214
|
+
*
|
|
215
215
|
*/
|
|
216
|
-
cleanData
|
|
216
|
+
cleanData(data, excludeKey, testing = false) {
|
|
217
217
|
let cleanedupData = []
|
|
218
218
|
if (testing) console.log('## Data to clean=', data)
|
|
219
219
|
if (excludeKey === undefined) {
|
|
220
220
|
console.log('COVE: cleanData excludeKey undefined')
|
|
221
|
-
return data // because no excludeKey
|
|
221
|
+
return data // because no excludeKey
|
|
222
222
|
}
|
|
223
223
|
data.forEach(function (d, i) {
|
|
224
|
-
if (testing) console.log(
|
|
224
|
+
if (testing) console.log('clean', i, ' d', d)
|
|
225
225
|
let cleaned = {}
|
|
226
226
|
Object.keys(d).forEach(function (key) {
|
|
227
227
|
if (key === excludeKey) {
|
|
@@ -229,27 +229,27 @@ export class DataTransform {
|
|
|
229
229
|
cleaned[key] = d[key]
|
|
230
230
|
} else {
|
|
231
231
|
// remove comma and dollar signs
|
|
232
|
-
if (testing) console.log(
|
|
233
|
-
let tmp =
|
|
232
|
+
if (testing) console.log('typeof d[key] is ', typeof d[key])
|
|
233
|
+
let tmp = ''
|
|
234
234
|
if (typeof d[key] === 'string') {
|
|
235
235
|
tmp = d[key] !== null && d[key] !== '' ? d[key].replace(/[,\$]/g, '') : ''
|
|
236
236
|
} else {
|
|
237
|
-
tmp =
|
|
237
|
+
tmp = d[key] !== null && d[key] !== '' ? d[key] : ''
|
|
238
238
|
}
|
|
239
239
|
if ((tmp !== '' && tmp !== null && !isNaN(tmp)) || (tmp !== '' && tmp !== null && /\d+\.?\d*/.test(tmp))) {
|
|
240
240
|
cleaned[key] = tmp
|
|
241
|
-
} else {
|
|
241
|
+
} else {
|
|
242
|
+
cleaned[key] = ''
|
|
243
|
+
}
|
|
242
244
|
// if you get here, then return nothing to skip bad data point
|
|
243
245
|
}
|
|
244
246
|
})
|
|
245
|
-
if (testing) console.log(
|
|
247
|
+
if (testing) console.log('cleaned=', cleaned)
|
|
246
248
|
cleanedupData.push(cleaned)
|
|
247
249
|
})
|
|
248
250
|
if (testing) console.log('## cleanedData =', cleanedupData)
|
|
249
251
|
return cleanedupData
|
|
250
252
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
export default DataTransform
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { timeFormat, timeParse } from 'd3-time-format'
|
|
2
|
+
|
|
3
|
+
export function formatDate(format = undefined, date) {
|
|
4
|
+
return timeFormat(format)(date)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function parseDate(format = undefined, dateString) {
|
|
8
|
+
return timeParse(format)(dateString) || new Date()
|
|
9
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import numberFromString from '@cdc/core/helpers/numberFromString'
|
|
2
|
+
|
|
3
|
+
const abbreviateNumber = num => {
|
|
4
|
+
let unit = ''
|
|
5
|
+
let absNum = Math.abs(num)
|
|
6
|
+
|
|
7
|
+
if (absNum >= 1e9) {
|
|
8
|
+
unit = 'B'
|
|
9
|
+
num = num / 1e9
|
|
10
|
+
} else if (absNum >= 1e6) {
|
|
11
|
+
unit = 'M'
|
|
12
|
+
num = num / 1e6
|
|
13
|
+
} else if (absNum >= 1e3) {
|
|
14
|
+
unit = 'K'
|
|
15
|
+
num = num / 1e3
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return num + unit
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Format numeric data based on settings in config
|
|
22
|
+
const formatNumber = (num, axis, shouldAbbreviate = false, config = null, addColParams = null) => {
|
|
23
|
+
if (!config) console.error('no config found in formatNumber')
|
|
24
|
+
// if num is NaN return num
|
|
25
|
+
if (isNaN(num) || !num) return num
|
|
26
|
+
// Check if the input number is negative
|
|
27
|
+
const isNegative = num < 0
|
|
28
|
+
|
|
29
|
+
// If the input number is negative, take the absolute value
|
|
30
|
+
if (isNegative) {
|
|
31
|
+
num = Math.abs(num)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// destructure dataFormat values
|
|
35
|
+
let {
|
|
36
|
+
dataFormat: { commas, abbreviated, roundTo, prefix, suffix, rightRoundTo, bottomRoundTo, rightPrefix, rightSuffix, bottomPrefix, bottomSuffix, bottomAbbreviated }
|
|
37
|
+
} = config
|
|
38
|
+
|
|
39
|
+
// destructure Additional Col dataformat values
|
|
40
|
+
const { addColCommas, addColRoundTo, addColPrefix, addColSuffix } = addColParams
|
|
41
|
+
|
|
42
|
+
// check if value contains comma and remove it. later will add comma below.
|
|
43
|
+
if (String(num).indexOf(',') !== -1) num = num.replaceAll(',', '')
|
|
44
|
+
|
|
45
|
+
let original = num
|
|
46
|
+
let stringFormattingOptions
|
|
47
|
+
if (axis === 'left') {
|
|
48
|
+
let roundToPlace
|
|
49
|
+
if (addColRoundTo !== undefined) {
|
|
50
|
+
// if its an Additional Column
|
|
51
|
+
roundToPlace = addColRoundTo ? Number(addColRoundTo) : 0
|
|
52
|
+
} else {
|
|
53
|
+
roundToPlace = roundTo ? Number(roundTo) : 0
|
|
54
|
+
}
|
|
55
|
+
// Need to prevent negative values in rounding
|
|
56
|
+
if (roundToPlace < 0) roundToPlace = 0
|
|
57
|
+
let useCommas
|
|
58
|
+
if (addColCommas !== undefined) {
|
|
59
|
+
// if its an Additional Column
|
|
60
|
+
useCommas = addColCommas ? true : false
|
|
61
|
+
} else {
|
|
62
|
+
useCommas = config.dataFormat.commas ? true : false
|
|
63
|
+
}
|
|
64
|
+
stringFormattingOptions = {
|
|
65
|
+
useGrouping: useCommas,
|
|
66
|
+
minimumFractionDigits: roundToPlace,
|
|
67
|
+
maximumFractionDigits: roundToPlace
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (axis === 'right') {
|
|
72
|
+
stringFormattingOptions = {
|
|
73
|
+
useGrouping: config.dataFormat.rightCommas ? true : false,
|
|
74
|
+
minimumFractionDigits: rightRoundTo ? Number(rightRoundTo) : 0,
|
|
75
|
+
maximumFractionDigits: rightRoundTo ? Number(rightRoundTo) : 0
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (axis === 'bottom') {
|
|
80
|
+
stringFormattingOptions = {
|
|
81
|
+
useGrouping: config.dataFormat.bottomCommas ? true : false,
|
|
82
|
+
minimumFractionDigits: bottomRoundTo ? Number(bottomRoundTo) : 0,
|
|
83
|
+
maximumFractionDigits: bottomRoundTo ? Number(bottomRoundTo) : 0
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
num = numberFromString(num)
|
|
88
|
+
|
|
89
|
+
if (isNaN(num)) {
|
|
90
|
+
config.runtime.editorErrorMessage = `Unable to parse number from data ${original}. Try reviewing your data and selections in the Data Series section.`
|
|
91
|
+
return original
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!config.dataFormat) return num
|
|
95
|
+
if (config.dataCutoff) {
|
|
96
|
+
let cutoff = numberFromString(config.dataCutoff)
|
|
97
|
+
|
|
98
|
+
if (num < cutoff) {
|
|
99
|
+
num = cutoff
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// When we're formatting the left axis
|
|
104
|
+
// Use commas also updates bars and the data table
|
|
105
|
+
// We can't use commas when we're formatting the dataFormatted number
|
|
106
|
+
// Example: commas -> 12,000; abbreviated -> 12k (correct); abbreviated & commas -> 12 (incorrect)
|
|
107
|
+
//
|
|
108
|
+
// Edge case for small numbers with decimals
|
|
109
|
+
// - if roundTo undefined which means it is blank, then do not round
|
|
110
|
+
|
|
111
|
+
if ((axis === 'left' && commas && abbreviated && shouldAbbreviate) || (axis === 'bottom' && commas && abbreviated && shouldAbbreviate)) {
|
|
112
|
+
num = num // eslint-disable-line
|
|
113
|
+
} else {
|
|
114
|
+
num = num.toLocaleString('en-US', stringFormattingOptions)
|
|
115
|
+
}
|
|
116
|
+
let result = ''
|
|
117
|
+
|
|
118
|
+
if (abbreviated && axis === 'left' && shouldAbbreviate) {
|
|
119
|
+
num = abbreviateNumber(parseFloat(num))
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (bottomAbbreviated && axis === 'bottom' && shouldAbbreviate) {
|
|
123
|
+
num = abbreviateNumber(parseFloat(num))
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (addColPrefix !== undefined && axis === 'left') {
|
|
127
|
+
result = addColPrefix + result
|
|
128
|
+
} else {
|
|
129
|
+
if (prefix && axis === 'left') {
|
|
130
|
+
result = prefix + result
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (rightPrefix && axis === 'right') {
|
|
135
|
+
result += rightPrefix
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (bottomPrefix && axis === 'bottom') {
|
|
139
|
+
result += bottomPrefix
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
result += num
|
|
143
|
+
|
|
144
|
+
if (addColSuffix !== undefined && axis === 'left') {
|
|
145
|
+
result += addColSuffix
|
|
146
|
+
} else {
|
|
147
|
+
if (suffix && axis === 'left') {
|
|
148
|
+
result += suffix
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (rightSuffix && axis === 'right') {
|
|
153
|
+
result += rightSuffix
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (bottomSuffix && axis === 'bottom') {
|
|
157
|
+
result += bottomSuffix
|
|
158
|
+
}
|
|
159
|
+
if (isNegative) {
|
|
160
|
+
result = '-' + result
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return String(result)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export { formatNumber }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// If config key names or position in the config have been changed with a version change,
|
|
2
|
+
// process those config entries and format old values into new
|
|
3
|
+
import update_4_23 from './ver/4.23'
|
|
4
|
+
|
|
5
|
+
// 4.23.6 ------------------------------------------------------
|
|
6
|
+
const coveUpdateWorker = async config => {
|
|
7
|
+
let genConfig = config
|
|
8
|
+
|
|
9
|
+
// v4.23
|
|
10
|
+
genConfig = await update_4_23(genConfig)
|
|
11
|
+
|
|
12
|
+
return genConfig
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default coveUpdateWorker
|
|
@@ -14,10 +14,20 @@ export default async function (url, visualizationType = '') {
|
|
|
14
14
|
data = await fetch(url.href)
|
|
15
15
|
.then(response => response.text())
|
|
16
16
|
.then(responseText => {
|
|
17
|
+
// for every comma NOT inside quotes, replace with a pipe delimiter
|
|
18
|
+
// - this will let commas inside the quotes not be parsed as a new column
|
|
19
|
+
// - Limitation: if a delimiter other than comma is used in the csv this will break
|
|
20
|
+
// Examples of other delimiters that would break: tab
|
|
21
|
+
responseText = responseText.replace(/(".*?")|,/g, (...m) => m[1] || '|')
|
|
22
|
+
// now strip the double quotes
|
|
23
|
+
responseText = responseText.replace(/["]+/g, '')
|
|
17
24
|
const parsedCsv = Papa.parse(responseText, {
|
|
25
|
+
//quotes: "true", // dont need these
|
|
26
|
+
//quoteChar: "'", // has no effect that I can tell
|
|
18
27
|
header: true,
|
|
19
|
-
|
|
20
|
-
|
|
28
|
+
skipEmptyLines: true,
|
|
29
|
+
delimiter: '|', // we are using pipe symbol as delimiter so setting this explicitly for Papa.parse
|
|
30
|
+
dynamicTyping: false
|
|
21
31
|
})
|
|
22
32
|
return parsedCsv.data
|
|
23
33
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/core",
|
|
3
|
-
"version": "4.23.
|
|
3
|
+
"version": "4.23.7",
|
|
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": "6c7ac5215dcf3bc1cc7d199089c8c2e75f53a93e"
|
|
34
34
|
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
display: block;
|
|
3
3
|
position: relative;
|
|
4
4
|
padding: 0.5em 0.5em;
|
|
5
|
-
border-width: 1px;
|
|
6
|
-
border-style: solid;
|
|
7
|
-
border-color: #cbcbcb;
|
|
5
|
+
border-width: 1px !important; // intentional use of !important for CDC
|
|
6
|
+
border-style: solid !important; // intentional use of !important for CDC
|
|
7
|
+
border-color: #cbcbcb !important; // intentional use of !important for CDC
|
|
8
8
|
border-radius: 0.1875rem;
|
|
9
9
|
transition: border-color 200ms $transition-expo-out;
|
|
10
10
|
font-family: sans-serif;
|