@graphenedata/cli 0.0.14 → 0.0.16
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.md +3 -3
- package/README.md +138 -0
- package/THIRD_PARTY_NOTICES.md +1 -0
- package/bin.js +2 -2
- package/dist/cli/bigQuery-I3F46SC6.js +75 -0
- package/dist/cli/bigQuery-I3F46SC6.js.map +7 -0
- package/dist/cli/chunk-OVWODUTJ.js +12849 -0
- package/dist/cli/chunk-OVWODUTJ.js.map +7 -0
- package/dist/cli/chunk-QAXEOZ43.js +53 -0
- package/dist/cli/chunk-QAXEOZ43.js.map +7 -0
- package/dist/cli/cli.js +245 -10290
- package/dist/cli/clickhouse-ZN5AN2UL.js +64 -0
- package/dist/cli/clickhouse-ZN5AN2UL.js.map +7 -0
- package/dist/cli/duckdb-IYBIO5KJ.js +87 -0
- package/dist/cli/duckdb-IYBIO5KJ.js.map +7 -0
- package/dist/cli/serve2-TNN5EROW.js +447 -0
- package/dist/cli/serve2-TNN5EROW.js.map +7 -0
- package/dist/cli/snowflake-MOQB5GA4.js +128 -0
- package/dist/cli/snowflake-MOQB5GA4.js.map +7 -0
- package/dist/index.d.ts +63 -0
- package/dist/lang/index.d.ts +63 -0
- package/dist/skills/graphene/SKILL.md +235 -0
- package/dist/skills/graphene/references/big-value.md +20 -0
- package/dist/skills/graphene/references/date-range.md +64 -0
- package/dist/skills/graphene/references/dropdown.md +62 -0
- package/dist/skills/graphene/references/echarts.md +162 -0
- package/dist/skills/graphene/references/gsql.md +393 -0
- package/dist/skills/graphene/references/model-gsql.md +72 -0
- package/dist/skills/graphene/references/table.md +143 -0
- package/dist/skills/graphene/references/text-input.md +29 -0
- package/dist/ui/app.css +263 -299
- package/dist/ui/component-utilities/dataShaping.ts +484 -0
- package/dist/ui/component-utilities/dataSummary.ts +57 -0
- package/dist/ui/component-utilities/enrich.ts +763 -0
- package/dist/ui/component-utilities/format.ts +177 -0
- package/dist/ui/component-utilities/inputUtils.ts +48 -9
- package/dist/ui/component-utilities/theme.ts +200 -0
- package/dist/ui/component-utilities/themeStores.ts +26 -21
- package/dist/ui/component-utilities/types.ts +70 -0
- package/dist/ui/components/AreaChart.svelte +57 -105
- package/dist/ui/components/BarChart.svelte +71 -129
- package/dist/ui/components/BigValue.svelte +24 -40
- package/dist/ui/components/Column.svelte +11 -19
- package/dist/ui/components/DateRange.svelte +71 -34
- package/dist/ui/components/Dropdown.svelte +82 -49
- package/dist/ui/components/DropdownOption.svelte +1 -2
- package/dist/ui/components/ECharts.svelte +179 -60
- package/dist/ui/components/InlineDelta.svelte +51 -32
- package/dist/ui/components/LineChart.svelte +54 -125
- package/dist/ui/components/PieChart.svelte +27 -37
- package/dist/ui/components/QueryLoad.svelte +78 -44
- package/dist/ui/components/Row.svelte +2 -1
- package/dist/ui/components/ScatterPlot.svelte +52 -0
- package/dist/ui/components/Skeleton.svelte +32 -0
- package/dist/ui/components/Table.svelte +3 -2
- package/dist/ui/components/TableGroupRow.svelte +28 -36
- package/dist/ui/components/TableHarness.svelte +32 -0
- package/dist/ui/components/TableHeader.svelte +34 -59
- package/dist/ui/components/TableRow.svelte +15 -39
- package/dist/ui/components/TableSubtotalRow.svelte +26 -21
- package/dist/ui/components/TableTotalRow.svelte +27 -37
- package/dist/ui/components/TextInput.svelte +17 -14
- package/dist/ui/components/Value.svelte +25 -0
- package/dist/ui/components/_Table.svelte +80 -76
- package/dist/ui/internal/ChartGallery.svelte +527 -0
- package/dist/ui/internal/ErrorDisplay.svelte +60 -0
- package/dist/ui/internal/LocalApp.svelte +87 -19
- package/dist/ui/internal/PageNavGroup.svelte +269 -0
- package/dist/ui/internal/Sidebar.svelte +178 -0
- package/dist/ui/internal/SidebarToggle.svelte +47 -0
- package/dist/ui/internal/StyleGallery.svelte +244 -0
- package/dist/ui/internal/clientCache.ts +15 -13
- package/dist/ui/internal/pageInputs.svelte.js +292 -0
- package/dist/ui/internal/queryEngine.ts +124 -132
- package/dist/ui/internal/runSocket.ts +59 -0
- package/dist/ui/internal/sidebar.svelte.js +18 -0
- package/dist/ui/internal/telemetry.ts +52 -17
- package/dist/ui/internal/types.d.ts +7 -0
- package/dist/ui/web.js +55 -13
- package/package.json +40 -41
- package/dist/docs/agent-instructions.md +0 -18
- package/dist/docs/base.md +0 -98
- package/dist/docs/cli.md +0 -22
- package/dist/docs/graphene.md +0 -1462
- package/dist/ui/component-utilities/autoFormatting.js +0 -301
- package/dist/ui/component-utilities/builtInFormats.js +0 -482
- package/dist/ui/component-utilities/chartContext.js +0 -12
- package/dist/ui/component-utilities/chartWindowDebug.js +0 -21
- package/dist/ui/component-utilities/checkInputs.js +0 -95
- package/dist/ui/component-utilities/convert.js +0 -15
- package/dist/ui/component-utilities/dateParsing.js +0 -57
- package/dist/ui/component-utilities/dropdownContext.ts +0 -1
- package/dist/ui/component-utilities/echarts.js +0 -272
- package/dist/ui/component-utilities/echartsThemes.js +0 -453
- package/dist/ui/component-utilities/formatTitle.js +0 -24
- package/dist/ui/component-utilities/formatting.js +0 -250
- package/dist/ui/component-utilities/getColumnExtents.js +0 -79
- package/dist/ui/component-utilities/getColumnSummary.js +0 -67
- package/dist/ui/component-utilities/getCompletedData.js +0 -114
- package/dist/ui/component-utilities/getDistinctCount.js +0 -7
- package/dist/ui/component-utilities/getDistinctValues.js +0 -15
- package/dist/ui/component-utilities/getSeriesConfig.js +0 -237
- package/dist/ui/component-utilities/getSortedData.js +0 -7
- package/dist/ui/component-utilities/getStackPercentages.js +0 -43
- package/dist/ui/component-utilities/getStackedData.js +0 -17
- package/dist/ui/component-utilities/getYAxisIndex.js +0 -15
- package/dist/ui/component-utilities/globalContexts.js +0 -1
- package/dist/ui/component-utilities/helpers/getCompletedData.helpers.js +0 -119
- package/dist/ui/component-utilities/replaceNulls.js +0 -14
- package/dist/ui/component-utilities/tableUtils.ts +0 -120
- package/dist/ui/components/Area.svelte +0 -214
- package/dist/ui/components/Bar.svelte +0 -350
- package/dist/ui/components/Chart.svelte +0 -989
- package/dist/ui/components/ErrorChart.svelte +0 -118
- package/dist/ui/components/Line.svelte +0 -227
- package/dist/ui/internal/NavSidebar.svelte +0 -396
- package/dist/ui/internal/PageError.svelte +0 -23
- package/dist/ui/internal/checkSocket.ts +0 -48
- package/dist/ui/internal/theme.ts +0 -88
- package/dist/ui/public/inter-latin-ext.woff2 +0 -0
- package/dist/ui/public/inter-latin.woff2 +0 -0
|
@@ -1,989 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import {setContext, type Snippet} from 'svelte'
|
|
3
|
-
import {type Writable, writable, get} from 'svelte/store'
|
|
4
|
-
import {propKey, configKey} from '../component-utilities/chartContext.js'
|
|
5
|
-
import ECharts from './ECharts.svelte'
|
|
6
|
-
import getColumnSummary from '../component-utilities/getColumnSummary.js'
|
|
7
|
-
import getDistinctValues from '../component-utilities/getDistinctValues.js'
|
|
8
|
-
import getDistinctCount from '../component-utilities/getDistinctCount.js'
|
|
9
|
-
import getStackPercentages from '../component-utilities/getStackPercentages.js'
|
|
10
|
-
import getSortedData from '../component-utilities/getSortedData.js'
|
|
11
|
-
import getYAxisIndex from '../component-utilities/getYAxisIndex.js'
|
|
12
|
-
import {standardizeDateColumn} from '../component-utilities/dateParsing.js'
|
|
13
|
-
import {formatAxisValue, formatValue, getFormatObjectFromString} from '../component-utilities/formatting.js'
|
|
14
|
-
import formatTitle from '../component-utilities/formatTitle.js'
|
|
15
|
-
import ErrorChart from './ErrorChart.svelte'
|
|
16
|
-
import checkInputs from '../component-utilities/checkInputs.js'
|
|
17
|
-
import {getThemeStores} from '../component-utilities/themeStores'
|
|
18
|
-
import {toBoolean} from '../component-utilities/convert'
|
|
19
|
-
import {parseCommaList} from '../component-utilities/inputUtils.ts'
|
|
20
|
-
import {logError} from '../internal/telemetry.ts'
|
|
21
|
-
|
|
22
|
-
interface Props {
|
|
23
|
-
data?: any, chartContext?: any, queryID?: any, x?: any, y?: any, y2?: any, series?: any, size?: any
|
|
24
|
-
tooltipTitle?: any, showAllXAxisLabels?: any, swapXY?: boolean | string, title?: string, subtitle?: string
|
|
25
|
-
chartType?: string, bubble?: boolean, hist?: boolean, boxplot?: boolean, xType?: string
|
|
26
|
-
xAxisTitle?: string, xBaseline?: boolean | string, xTickMarks?: boolean | string
|
|
27
|
-
xGridlines?: boolean | string, xAxisLabels?: boolean | string, sort?: boolean | string, xFmt?: any
|
|
28
|
-
xMin?: any, xMax?: any, yLog?: boolean | string, yType?: string, yLogBase?: number, yAxisTitle?: string
|
|
29
|
-
yBaseline?: boolean | string, yTickMarks?: boolean | string, yGridlines?: boolean | string
|
|
30
|
-
yAxisLabels?: boolean | string, yMin?: any, yMax?: any, yScale?: boolean | string, yFmt?: any
|
|
31
|
-
yAxisColor?: string, y2AxisTitle?: string, y2Baseline?: boolean | string, y2TickMarks?: boolean | string
|
|
32
|
-
y2Gridlines?: boolean | string, y2AxisLabels?: boolean | string, y2Min?: any, y2Max?: any
|
|
33
|
-
y2Scale?: boolean | string, y2Fmt?: any, y2AxisColor?: string, sizeFmt?: any, colorPalette?: string
|
|
34
|
-
legend?: any, echartsOptions?: any, seriesOptions?: any, seriesColors?: any, stackType?: string
|
|
35
|
-
stacked100?: boolean, chartAreaHeight?: any, connectGroup?: string, leftPadding?: any, rightPadding?: any
|
|
36
|
-
xLabelWrap?: boolean | string, children?: Snippet
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Note: renamed from 'props' to 'chartProps' to avoid conflict with $props() rune
|
|
40
|
-
let chartProps = writable({})
|
|
41
|
-
let config: Writable<any> = writable({})
|
|
42
|
-
|
|
43
|
-
setContext(propKey, chartProps)
|
|
44
|
-
setContext(configKey, config)
|
|
45
|
-
|
|
46
|
-
const {theme, resolveColor, resolveColorsObject, resolveColorPalette} = getThemeStores()
|
|
47
|
-
|
|
48
|
-
let {
|
|
49
|
-
data = undefined, chartContext = undefined, queryID = undefined, x = undefined, y = undefined,
|
|
50
|
-
y2 = undefined, series = undefined, size = undefined, tooltipTitle = undefined,
|
|
51
|
-
showAllXAxisLabels = undefined, swapXY = false, title = undefined, subtitle = undefined,
|
|
52
|
-
chartType = 'Chart', bubble = false, hist = false, boxplot = false, xType = undefined,
|
|
53
|
-
xAxisTitle = 'false', xBaseline = true, xTickMarks = false, xGridlines = false, xAxisLabels = true,
|
|
54
|
-
sort = true, xFmt = undefined, xMin = undefined, xMax = undefined, yLog = false, yType = undefined,
|
|
55
|
-
yLogBase = 10, yAxisTitle = 'false', yBaseline = false, yTickMarks = false, yGridlines = true,
|
|
56
|
-
yAxisLabels = true, yMin = undefined, yMax = undefined, yScale = false, yFmt = undefined,
|
|
57
|
-
yAxisColor = 'true', y2AxisTitle = 'false', y2Baseline = false, y2TickMarks = false,
|
|
58
|
-
y2Gridlines = true, y2AxisLabels = true, y2Min = undefined, y2Max = undefined, y2Scale = false,
|
|
59
|
-
y2Fmt = undefined, y2AxisColor = 'true', sizeFmt = undefined, colorPalette = 'default',
|
|
60
|
-
legend = undefined, echartsOptions = undefined, seriesOptions = undefined, seriesColors = undefined,
|
|
61
|
-
stackType = undefined, stacked100 = false, chartAreaHeight = undefined, connectGroup = undefined,
|
|
62
|
-
leftPadding = undefined, rightPadding = undefined, xLabelWrap = false, children,
|
|
63
|
-
}: Props = $props()
|
|
64
|
-
|
|
65
|
-
// This should be reworked to fit better with svelte's reactivity.
|
|
66
|
-
|
|
67
|
-
// We rewrite the x and y values with fallbacks if they aren't present
|
|
68
|
-
// the fallback logic *depends* on the values of x and y
|
|
69
|
-
// when x and y are replaced by the fallbacks, the fallback logic doesn't reset.
|
|
70
|
-
// if the y value isn't set, var y gets populated with a fall back from the data.
|
|
71
|
-
// if the data changes, we are now acting as if the fallback from above was entered by the user, and
|
|
72
|
-
// then we throw if the fallback column is now missing.
|
|
73
|
-
|
|
74
|
-
// This is a hack to get around the above
|
|
75
|
-
// Track whether x/y were initially set (not using fallbacks)
|
|
76
|
-
// These capture the initial values intentionally - they're set once on mount
|
|
77
|
-
// and updated in the effect. Using closure pattern to silence state_referenced_locally warning.
|
|
78
|
-
let ySet = $state((() => y ? true : false)())
|
|
79
|
-
// const y2Set = y2 ? true : false;
|
|
80
|
-
let xSet = $state((() => x ? true : false)())
|
|
81
|
-
|
|
82
|
-
// Convert boolean string props to actual booleans
|
|
83
|
-
let swapXY_bool = $derived(toBoolean(swapXY))
|
|
84
|
-
let xBaseline_bool = $derived(toBoolean(xBaseline))
|
|
85
|
-
let xTickMarks_bool = $derived(toBoolean(xTickMarks))
|
|
86
|
-
let xGridlines_bool = $derived(toBoolean(xGridlines))
|
|
87
|
-
let xAxisLabels_bool = $derived(toBoolean(xAxisLabels))
|
|
88
|
-
let sort_bool = $derived(toBoolean(sort))
|
|
89
|
-
let yLog_bool = $derived(toBoolean(yLog))
|
|
90
|
-
let yBaseline_bool = $derived(toBoolean(yBaseline))
|
|
91
|
-
let yTickMarks_bool = $derived(toBoolean(yTickMarks))
|
|
92
|
-
let yGridlines_bool = $derived(toBoolean(yGridlines))
|
|
93
|
-
let yAxisLabels_bool = $derived(toBoolean(yAxisLabels))
|
|
94
|
-
let yScale_bool = $derived(toBoolean(yScale))
|
|
95
|
-
let y2Baseline_bool = $derived(toBoolean(y2Baseline))
|
|
96
|
-
let y2TickMarks_bool = $derived(toBoolean(y2TickMarks))
|
|
97
|
-
let y2Gridlines_bool = $derived(toBoolean(y2Gridlines))
|
|
98
|
-
let y2AxisLabels_bool = $derived(toBoolean(y2AxisLabels))
|
|
99
|
-
let y2Scale_bool = $derived(toBoolean(y2Scale))
|
|
100
|
-
let xLabelWrap_bool = $derived(toBoolean(xLabelWrap))
|
|
101
|
-
|
|
102
|
-
let yAxisColorStore = $derived(resolveColor(yAxisColor))
|
|
103
|
-
let y2AxisColorStore = $derived(resolveColor(y2AxisColor))
|
|
104
|
-
let colorPaletteResolved = $derived(resolveColorPalette(colorPalette))
|
|
105
|
-
let seriesColorsResolved = $derived(resolveColorsObject(seriesColors))
|
|
106
|
-
|
|
107
|
-
let reqCols
|
|
108
|
-
|
|
109
|
-
let xAxisLabelOverflow = $derived(xLabelWrap_bool ? 'break' : 'truncate')
|
|
110
|
-
|
|
111
|
-
// ---------------------------------------------------------------------------------------
|
|
112
|
-
// Variable Declaration
|
|
113
|
-
// ---------------------------------------------------------------------------------------
|
|
114
|
-
// Column Summary:
|
|
115
|
-
let columnSummary
|
|
116
|
-
let columnNames
|
|
117
|
-
let uColNames = []
|
|
118
|
-
let unusedColumns = []
|
|
119
|
-
let uColType
|
|
120
|
-
let uColName
|
|
121
|
-
let xDataType
|
|
122
|
-
let xMismatch
|
|
123
|
-
let xFormat
|
|
124
|
-
let yFormat
|
|
125
|
-
let y2Format
|
|
126
|
-
let sizeFormat
|
|
127
|
-
let xUnitSummary
|
|
128
|
-
let yUnitSummary
|
|
129
|
-
let y2UnitSummary
|
|
130
|
-
let xDistinct
|
|
131
|
-
|
|
132
|
-
// Individual Config Sections:
|
|
133
|
-
let horizAxisConfig
|
|
134
|
-
let verticalAxisConfig
|
|
135
|
-
let horizAxisTitleConfig
|
|
136
|
-
let chartConfig
|
|
137
|
-
|
|
138
|
-
// Chart area sizing:
|
|
139
|
-
let hasTitle
|
|
140
|
-
let hasSubtitle
|
|
141
|
-
let hasLegend
|
|
142
|
-
let hasTopAxisTitle
|
|
143
|
-
let hasBottomAxisTitle
|
|
144
|
-
let titleFontSize
|
|
145
|
-
let subtitleFontSize
|
|
146
|
-
let titleBoxPadding
|
|
147
|
-
let titleBoxHeight
|
|
148
|
-
let chartAreaPaddingTop
|
|
149
|
-
let chartAreaPaddingBottom
|
|
150
|
-
let bottomAxisTitleSize
|
|
151
|
-
let topAxisTitleSize
|
|
152
|
-
let legendHeight
|
|
153
|
-
let legendPaddingTop
|
|
154
|
-
let legendTop
|
|
155
|
-
let chartTop
|
|
156
|
-
let chartBottom
|
|
157
|
-
let chartContainerHeight
|
|
158
|
-
let topAxisTitleTop
|
|
159
|
-
|
|
160
|
-
let horizAxisTitle
|
|
161
|
-
|
|
162
|
-
// Adjustment to avoid small bars on horizontal bar chart (extend chart height to accomodate):
|
|
163
|
-
let maxBars
|
|
164
|
-
let barCount
|
|
165
|
-
let heightMultiplier
|
|
166
|
-
|
|
167
|
-
// Set final chart height:
|
|
168
|
-
// Using a separate writable store for dimensions so they're reactive in the template
|
|
169
|
-
// without causing infinite effect loops (which $state would cause since the effect reads+writes them).
|
|
170
|
-
let dimensions = writable<{height?: string, width?: string}>({})
|
|
171
|
-
|
|
172
|
-
let missingCols = []
|
|
173
|
-
|
|
174
|
-
let originalRun = true
|
|
175
|
-
|
|
176
|
-
// Error Handling:
|
|
177
|
-
|
|
178
|
-
let inputCols = []
|
|
179
|
-
let optCols = []
|
|
180
|
-
let i
|
|
181
|
-
|
|
182
|
-
// svelte-ignore non_reactive_update
|
|
183
|
-
let error
|
|
184
|
-
|
|
185
|
-
// Date String Handling:
|
|
186
|
-
let columnSummaryArray
|
|
187
|
-
let dateCols
|
|
188
|
-
|
|
189
|
-
$effect(() => {
|
|
190
|
-
try {
|
|
191
|
-
error = undefined
|
|
192
|
-
missingCols = []
|
|
193
|
-
unusedColumns = []
|
|
194
|
-
// Error Handling:
|
|
195
|
-
inputCols = []
|
|
196
|
-
optCols = []
|
|
197
|
-
uColName = []
|
|
198
|
-
// Normalize list-like inputs first - use local variables instead of reassigning props
|
|
199
|
-
let yLocal = parseCommaList(y)
|
|
200
|
-
let y2Local = parseCommaList(y2)
|
|
201
|
-
ySet = yLocal.length > 0
|
|
202
|
-
xSet = x ? true : false
|
|
203
|
-
|
|
204
|
-
checkInputs(data) // check that dataset exists
|
|
205
|
-
|
|
206
|
-
// ---------------------------------------------------------------------------------------
|
|
207
|
-
// Get column information
|
|
208
|
-
// ---------------------------------------------------------------------------------------
|
|
209
|
-
// Get column summary:
|
|
210
|
-
columnSummary = getColumnSummary(data)
|
|
211
|
-
|
|
212
|
-
// Get column names:
|
|
213
|
-
columnNames = Object.keys(columnSummary)
|
|
214
|
-
|
|
215
|
-
// ---------------------------------------------------------------------------------------
|
|
216
|
-
// Make assumptions to complete required props
|
|
217
|
-
// ---------------------------------------------------------------------------------------
|
|
218
|
-
// If no x column was supplied, assume first column in dataset is x
|
|
219
|
-
let xLocal = x
|
|
220
|
-
if (!xSet) {
|
|
221
|
-
xLocal = columnNames[0]
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// If no y column(s) supplied, assume all number columns other than x are the y columns:
|
|
225
|
-
if (!ySet) {
|
|
226
|
-
uColNames = columnNames.filter(function (col) {
|
|
227
|
-
return ![xLocal, series, size].includes(col)
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
for (let i = 0; i < uColNames.length; i++) {
|
|
231
|
-
uColName = uColNames[i]
|
|
232
|
-
uColType = columnSummary[uColName].type
|
|
233
|
-
if (uColType === 'number') {
|
|
234
|
-
unusedColumns.push(uColName)
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
yLocal = unusedColumns // always array; empty handled by required prop checks
|
|
239
|
-
}
|
|
240
|
-
// Establish required columns based on chart type:
|
|
241
|
-
if (bubble) {
|
|
242
|
-
reqCols = {
|
|
243
|
-
x: xLocal,
|
|
244
|
-
y: yLocal,
|
|
245
|
-
size: size,
|
|
246
|
-
}
|
|
247
|
-
} else if (hist) {
|
|
248
|
-
reqCols = {
|
|
249
|
-
x: xLocal,
|
|
250
|
-
}
|
|
251
|
-
} else if (boxplot) {
|
|
252
|
-
reqCols = {}
|
|
253
|
-
} else {
|
|
254
|
-
reqCols = {
|
|
255
|
-
x: xLocal,
|
|
256
|
-
y: yLocal,
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Check which columns were not supplied to the chart:
|
|
261
|
-
for (let property in reqCols) {
|
|
262
|
-
if (reqCols[property] == null) {
|
|
263
|
-
missingCols.push(property)
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (missingCols.length === 1) {
|
|
268
|
-
throw Error(new Intl.ListFormat().format(missingCols) + ' is required')
|
|
269
|
-
} else if (missingCols.length > 1) {
|
|
270
|
-
throw Error(new Intl.ListFormat().format(missingCols) + ' are required')
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Fix for stacked100 overwriting y variable. Bandaid fix - not a long-term solution:
|
|
274
|
-
if (stacked100 === true && Array.isArray(yLocal) && yLocal.some(col => col.includes('_pct')) && originalRun === false) {
|
|
275
|
-
yLocal = yLocal.map(col => col.replace('_pct', ''))
|
|
276
|
-
originalRun = false
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Check the inputs supplied to the chart:
|
|
280
|
-
if (xLocal) {
|
|
281
|
-
inputCols.push(xLocal)
|
|
282
|
-
}
|
|
283
|
-
if (Array.isArray(yLocal)) for (i = 0; i < yLocal.length; i++) inputCols.push(yLocal[i])
|
|
284
|
-
if (Array.isArray(y2Local)) for (i = 0; i < y2Local.length; i++) inputCols.push(y2Local[i])
|
|
285
|
-
if (size) {
|
|
286
|
-
inputCols.push(size)
|
|
287
|
-
}
|
|
288
|
-
if (series) {
|
|
289
|
-
optCols.push(series)
|
|
290
|
-
}
|
|
291
|
-
if (tooltipTitle) {
|
|
292
|
-
optCols.push(tooltipTitle)
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
checkInputs(data, inputCols, optCols)
|
|
296
|
-
|
|
297
|
-
// ---------------------------------------------------------------------------------------
|
|
298
|
-
// Aggregate Data if Required
|
|
299
|
-
// ---------------------------------------------------------------------------------------
|
|
300
|
-
let dataLocal = data
|
|
301
|
-
if (stacked100 === true) {
|
|
302
|
-
dataLocal = getStackPercentages(dataLocal, xLocal, yLocal)
|
|
303
|
-
yLocal = yLocal.map(col => col + '_pct')
|
|
304
|
-
originalRun = false
|
|
305
|
-
columnSummary = getColumnSummary(dataLocal)
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// ---------------------------------------------------------------------------------------
|
|
309
|
-
// Define x axis type
|
|
310
|
-
// ---------------------------------------------------------------------------------------
|
|
311
|
-
xDataType = columnSummary[xLocal].type
|
|
312
|
-
|
|
313
|
-
// Get xDataType into ECharts default types:
|
|
314
|
-
switch (xDataType) {
|
|
315
|
-
case 'number':
|
|
316
|
-
xDataType = 'value'
|
|
317
|
-
break
|
|
318
|
-
case 'string':
|
|
319
|
-
xDataType = 'category'
|
|
320
|
-
break
|
|
321
|
-
case 'date':
|
|
322
|
-
xDataType = 'time'
|
|
323
|
-
break
|
|
324
|
-
default:
|
|
325
|
-
break
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
let xTypeLocal = xType === 'category' ? 'category' : xDataType
|
|
329
|
-
|
|
330
|
-
// Set xAxisLabel overflow behaviour based on column type
|
|
331
|
-
let showAllXAxisLabelsLocal = showAllXAxisLabels
|
|
332
|
-
if (!showAllXAxisLabelsLocal) {
|
|
333
|
-
// if user has not set showXAxisLabels
|
|
334
|
-
showAllXAxisLabelsLocal = xTypeLocal === 'category'
|
|
335
|
-
} else {
|
|
336
|
-
// if user has set showXAxisLabels, convert to boolean
|
|
337
|
-
showAllXAxisLabelsLocal = showAllXAxisLabelsLocal === 'true' || showAllXAxisLabelsLocal === true
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// Throw error if attempting to plot value or time on horizontal x-axis:
|
|
341
|
-
if (swapXY_bool && xTypeLocal !== 'category') {
|
|
342
|
-
throw Error(
|
|
343
|
-
'Horizontal charts do not support a value or time-based x-axis. You can either change your SQL query to output string values or set swapXY=false.',
|
|
344
|
-
)
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Throw error if attempting to plot secondary y-axis on horizontal chart:
|
|
348
|
-
if (swapXY_bool && y2Local.length) {
|
|
349
|
-
throw Error(
|
|
350
|
-
'Horizontal charts do not support a secondary y-axis. You can either set swapXY=false or remove the y2 prop from your chart.',
|
|
351
|
-
)
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// Override xType if axes are swapped - only category enabled on horizontal axis
|
|
355
|
-
if (swapXY_bool) {
|
|
356
|
-
xTypeLocal = 'category'
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// Check for x mismatch:
|
|
360
|
-
xMismatch = xDataType === 'value' && xTypeLocal === 'category'
|
|
361
|
-
|
|
362
|
-
// ---------------------------------------------------------------------------------------
|
|
363
|
-
// Sort data based on xType
|
|
364
|
-
// ---------------------------------------------------------------------------------------
|
|
365
|
-
if (sort_bool) {
|
|
366
|
-
let sortColumn = xLocal
|
|
367
|
-
if (xDataType === 'category') {
|
|
368
|
-
sortColumn = Array.isArray(yLocal) ? (yLocal[0] ?? xLocal) : xLocal
|
|
369
|
-
}
|
|
370
|
-
let sortAscending = xDataType !== 'category'
|
|
371
|
-
dataLocal = getSortedData(dataLocal, sortColumn, sortAscending)
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// Always sort time axes by x - this prevents the lines from being drawn out of order
|
|
375
|
-
if (xDataType === 'time') {
|
|
376
|
-
dataLocal = getSortedData(dataLocal, xLocal, true)
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// ---------------------------------------------------------------------------------------
|
|
380
|
-
// Standardize date columns
|
|
381
|
-
// ---------------------------------------------------------------------------------------
|
|
382
|
-
|
|
383
|
-
columnSummaryArray = getColumnSummary(dataLocal, 'array')
|
|
384
|
-
dateCols = columnSummaryArray.filter((d) => d.type === 'date')
|
|
385
|
-
dateCols = dateCols.map((d) => d.id)
|
|
386
|
-
|
|
387
|
-
if (dateCols.length > 0) {
|
|
388
|
-
for (let i = 0; i < dateCols.length; i++) {
|
|
389
|
-
dataLocal = standardizeDateColumn(dataLocal, dateCols[i])
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// ---------------------------------------------------------------------------------------
|
|
394
|
-
// Get format codes for axes
|
|
395
|
-
// ---------------------------------------------------------------------------------------
|
|
396
|
-
if (xFmt) {
|
|
397
|
-
xFormat = getFormatObjectFromString(xFmt, columnSummary[xLocal].format?.valueType)
|
|
398
|
-
} else {
|
|
399
|
-
xFormat = columnSummary[xLocal].format
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
if (yLocal.length === 0) {
|
|
403
|
-
yFormat = 'str'
|
|
404
|
-
} else {
|
|
405
|
-
if (yFmt) yFormat = getFormatObjectFromString(yFmt, columnSummary[yLocal[0]].format?.valueType)
|
|
406
|
-
else yFormat = columnSummary[yLocal[0]].format
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
if (y2Local.length) {
|
|
410
|
-
if (y2Fmt) y2Format = getFormatObjectFromString(y2Fmt, columnSummary[y2Local[0]].format?.valueType)
|
|
411
|
-
else y2Format = columnSummary[y2Local[0]].format
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
if (size) {
|
|
415
|
-
if (sizeFmt) {
|
|
416
|
-
sizeFormat = getFormatObjectFromString(sizeFmt, columnSummary[size].format?.valueType)
|
|
417
|
-
} else {
|
|
418
|
-
sizeFormat = columnSummary[size].format
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
xUnitSummary = columnSummary[xLocal].columnUnitSummary
|
|
423
|
-
|
|
424
|
-
if (yLocal.length) yUnitSummary = columnSummary[yLocal[0]].columnUnitSummary
|
|
425
|
-
|
|
426
|
-
if (y2Local.length) y2UnitSummary = columnSummary[y2Local[0]].columnUnitSummary
|
|
427
|
-
|
|
428
|
-
let xAxisTitleLocal = xAxisTitle
|
|
429
|
-
if (xAxisTitleLocal === 'true') {
|
|
430
|
-
xAxisTitleLocal = formatTitle(xLocal, xFormat)
|
|
431
|
-
} else if (xAxisTitleLocal === 'false') {
|
|
432
|
-
xAxisTitleLocal = ''
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
let yAxisTitleLocal = yAxisTitle
|
|
436
|
-
if (yAxisTitleLocal === 'true') {
|
|
437
|
-
if (yLocal.length === 1) {
|
|
438
|
-
yAxisTitleLocal = formatTitle(yLocal[0], yFormat)
|
|
439
|
-
} else {
|
|
440
|
-
yAxisTitleLocal = ''
|
|
441
|
-
}
|
|
442
|
-
} else if (yAxisTitleLocal === 'false') {
|
|
443
|
-
yAxisTitleLocal = ''
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
let y2AxisTitleLocal = y2AxisTitle
|
|
447
|
-
if (y2AxisTitleLocal === 'true') {
|
|
448
|
-
if (y2Local.length === 1) {
|
|
449
|
-
y2AxisTitleLocal = formatTitle(y2Local[0], y2Format)
|
|
450
|
-
} else {
|
|
451
|
-
y2AxisTitleLocal = ''
|
|
452
|
-
}
|
|
453
|
-
} else if (y2AxisTitleLocal === 'false') {
|
|
454
|
-
y2AxisTitleLocal = ''
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
// ---------------------------------------------------------------------------------------
|
|
458
|
-
// Get total series count
|
|
459
|
-
// ---------------------------------------------------------------------------------------
|
|
460
|
-
let yCount = yLocal.length
|
|
461
|
-
let seriesCount = series ? getDistinctCount(dataLocal, series) : 1
|
|
462
|
-
let ySeriesCount = yCount * seriesCount
|
|
463
|
-
|
|
464
|
-
// y2Count may need to be adjusted to also factor in the series column. For now, we really
|
|
465
|
-
// only need to know that it's multi-series, so > 1 is sufficient
|
|
466
|
-
let y2Count = y2Local.length
|
|
467
|
-
let totalSeriesCount = ySeriesCount + y2Count
|
|
468
|
-
|
|
469
|
-
// ---------------------------------------------------------------------------------------
|
|
470
|
-
// Set legend flag
|
|
471
|
-
// ---------------------------------------------------------------------------------------
|
|
472
|
-
let legendLocal = legend
|
|
473
|
-
if (legendLocal !== undefined) {
|
|
474
|
-
legendLocal = legendLocal === 'true' || legendLocal === true
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
legendLocal = legendLocal ?? totalSeriesCount > 1
|
|
478
|
-
|
|
479
|
-
// ---------------------------------------------------------------------------------------
|
|
480
|
-
// Handle errors for log axes (cannot be used with stacked charts)
|
|
481
|
-
// ---------------------------------------------------------------------------------------
|
|
482
|
-
|
|
483
|
-
if (stacked100 === true && yLog_bool === true) {
|
|
484
|
-
throw Error('Log axis cannot be used in a 100% stacked chart')
|
|
485
|
-
} else if (stackType === 'stacked' && totalSeriesCount > 1 && yLog_bool === true) {
|
|
486
|
-
throw Error('Log axis cannot be used in a stacked chart')
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
let minYValue
|
|
490
|
-
if (yLocal.length) {
|
|
491
|
-
minYValue = columnSummary[yLocal[0]].columnUnitSummary.min
|
|
492
|
-
for (let i = 0; i < yLocal.length; i++) {
|
|
493
|
-
if (columnSummary[yLocal[i]].columnUnitSummary.min < minYValue) {
|
|
494
|
-
minYValue = columnSummary[yLocal[i]].columnUnitSummary.min
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
if (yLog_bool === true && minYValue <= 0 && minYValue !== null) {
|
|
500
|
-
throw Error('Log axis cannot display values less than or equal to zero')
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
// ---------------------------------------------------------------------------------------
|
|
504
|
-
// Compute chartAreaHeight locally
|
|
505
|
-
// ---------------------------------------------------------------------------------------
|
|
506
|
-
let chartAreaHeightLocal = chartAreaHeight
|
|
507
|
-
if (chartAreaHeightLocal) {
|
|
508
|
-
// if chartAreaHeight was user-supplied
|
|
509
|
-
chartAreaHeightLocal = Number(chartAreaHeightLocal)
|
|
510
|
-
if (isNaN(chartAreaHeightLocal)) {
|
|
511
|
-
// input must be a number
|
|
512
|
-
throw Error('chartAreaHeight must be a number')
|
|
513
|
-
} else if (chartAreaHeightLocal <= 0) {
|
|
514
|
-
throw Error('chartAreaHeight must be a positive number')
|
|
515
|
-
}
|
|
516
|
-
} else {
|
|
517
|
-
chartAreaHeightLocal = 220
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
// Compute yType locally
|
|
521
|
-
let yTypeLocal = yLog_bool === true ? 'log' : (yType ?? 'value')
|
|
522
|
-
|
|
523
|
-
// ---------------------------------------------------------------------------------------
|
|
524
|
-
// Add props to store to let child components access them
|
|
525
|
-
// ---------------------------------------------------------------------------------------
|
|
526
|
-
chartProps.update((d) => {
|
|
527
|
-
return {
|
|
528
|
-
...d,
|
|
529
|
-
error: undefined,
|
|
530
|
-
data: dataLocal,
|
|
531
|
-
x: xLocal,
|
|
532
|
-
y: yLocal,
|
|
533
|
-
y2: y2Local,
|
|
534
|
-
series,
|
|
535
|
-
swapXY: swapXY_bool,
|
|
536
|
-
sort: sort_bool,
|
|
537
|
-
xType: xTypeLocal,
|
|
538
|
-
xFormat,
|
|
539
|
-
yFormat,
|
|
540
|
-
y2Format,
|
|
541
|
-
sizeFormat,
|
|
542
|
-
xMismatch,
|
|
543
|
-
size,
|
|
544
|
-
yMin,
|
|
545
|
-
y2Min,
|
|
546
|
-
columnSummary,
|
|
547
|
-
xAxisTitle: xAxisTitleLocal,
|
|
548
|
-
yAxisTitle: yAxisTitleLocal,
|
|
549
|
-
y2AxisTitle: y2AxisTitleLocal,
|
|
550
|
-
tooltipTitle,
|
|
551
|
-
chartAreaHeight: chartAreaHeightLocal,
|
|
552
|
-
chartType,
|
|
553
|
-
yCount,
|
|
554
|
-
y2Count,
|
|
555
|
-
}
|
|
556
|
-
})
|
|
557
|
-
|
|
558
|
-
// ---------------------------------------------------------------------------------------
|
|
559
|
-
// Axis Configuration
|
|
560
|
-
// ---------------------------------------------------------------------------------------
|
|
561
|
-
xDistinct = getDistinctValues(dataLocal, xLocal)
|
|
562
|
-
let secondaryAxis
|
|
563
|
-
|
|
564
|
-
if (swapXY_bool) {
|
|
565
|
-
horizAxisConfig = {
|
|
566
|
-
type: yTypeLocal,
|
|
567
|
-
logBase: yLogBase,
|
|
568
|
-
position: 'top',
|
|
569
|
-
axisLabel: {
|
|
570
|
-
show: yAxisLabels_bool,
|
|
571
|
-
hideOverlap: true,
|
|
572
|
-
showMaxLabel: true,
|
|
573
|
-
formatter: function (value) {
|
|
574
|
-
return formatAxisValue(value, yFormat, yUnitSummary)
|
|
575
|
-
},
|
|
576
|
-
margin: 4,
|
|
577
|
-
},
|
|
578
|
-
min: yMin,
|
|
579
|
-
max: yMax,
|
|
580
|
-
minInterval: yUnitSummary?.maxDecimals === 0 ? 1 : undefined,
|
|
581
|
-
scale: yScale_bool,
|
|
582
|
-
splitLine: {
|
|
583
|
-
show: yGridlines_bool,
|
|
584
|
-
},
|
|
585
|
-
axisLine: {
|
|
586
|
-
show: yBaseline_bool,
|
|
587
|
-
onZero: false,
|
|
588
|
-
},
|
|
589
|
-
axisTick: {
|
|
590
|
-
show: yTickMarks_bool,
|
|
591
|
-
},
|
|
592
|
-
boundaryGap: false,
|
|
593
|
-
z: 2,
|
|
594
|
-
}
|
|
595
|
-
} else {
|
|
596
|
-
horizAxisConfig = {
|
|
597
|
-
type: xTypeLocal,
|
|
598
|
-
min: xMin,
|
|
599
|
-
max: xMax,
|
|
600
|
-
tooltip: {
|
|
601
|
-
show: true,
|
|
602
|
-
position: 'inside',
|
|
603
|
-
formatter (p) {
|
|
604
|
-
if (p.isTruncated()) {
|
|
605
|
-
return p.name
|
|
606
|
-
}
|
|
607
|
-
},
|
|
608
|
-
},
|
|
609
|
-
splitLine: {
|
|
610
|
-
show: xGridlines_bool,
|
|
611
|
-
},
|
|
612
|
-
axisLine: {
|
|
613
|
-
show: xBaseline_bool,
|
|
614
|
-
},
|
|
615
|
-
axisTick: {
|
|
616
|
-
show: xTickMarks_bool,
|
|
617
|
-
},
|
|
618
|
-
axisLabel: {
|
|
619
|
-
show: xAxisLabels_bool,
|
|
620
|
-
hideOverlap: true,
|
|
621
|
-
showMaxLabel: xTypeLocal === 'category' || xTypeLocal === 'value', // max label for ECharts' time axis is a stub - default for that is false
|
|
622
|
-
formatter:
|
|
623
|
-
xTypeLocal === 'time' || xTypeLocal === 'category'
|
|
624
|
-
? false
|
|
625
|
-
: function (value) {
|
|
626
|
-
return formatAxisValue(value, xFormat, xUnitSummary)
|
|
627
|
-
},
|
|
628
|
-
margin: 6,
|
|
629
|
-
},
|
|
630
|
-
scale: true,
|
|
631
|
-
z: 2,
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
if (swapXY_bool) {
|
|
636
|
-
verticalAxisConfig = {
|
|
637
|
-
type: xTypeLocal,
|
|
638
|
-
inverse: 'true',
|
|
639
|
-
splitLine: {
|
|
640
|
-
show: xGridlines_bool,
|
|
641
|
-
},
|
|
642
|
-
axisLine: {
|
|
643
|
-
show: xBaseline_bool,
|
|
644
|
-
},
|
|
645
|
-
axisTick: {
|
|
646
|
-
show: xTickMarks_bool,
|
|
647
|
-
},
|
|
648
|
-
axisLabel: {
|
|
649
|
-
show: xAxisLabels_bool,
|
|
650
|
-
hideOverlap: true,
|
|
651
|
-
// formatter:
|
|
652
|
-
// function(value){
|
|
653
|
-
// return formatAxisValue(value, xFormat, xUnitSummary)
|
|
654
|
-
// },
|
|
655
|
-
},
|
|
656
|
-
scale: true,
|
|
657
|
-
min: xMin,
|
|
658
|
-
max: xMax,
|
|
659
|
-
z: 2,
|
|
660
|
-
}
|
|
661
|
-
} else {
|
|
662
|
-
let primaryAxisColor = (() => {
|
|
663
|
-
if (!(Array.isArray(y2Local) && y2Local.length)) return undefined
|
|
664
|
-
let yColor = get(yAxisColorStore)
|
|
665
|
-
if (yColor === 'true') return $colorPaletteResolved?.[0]
|
|
666
|
-
if (yColor === 'false') return undefined
|
|
667
|
-
return yColor
|
|
668
|
-
})()
|
|
669
|
-
let secondaryAxisColor = (() => {
|
|
670
|
-
let y2Color = get(y2AxisColorStore)
|
|
671
|
-
if (y2Color === 'true') return $colorPaletteResolved?.[ySeriesCount]
|
|
672
|
-
if (y2Color === 'false') return undefined
|
|
673
|
-
return y2Color
|
|
674
|
-
})()
|
|
675
|
-
|
|
676
|
-
verticalAxisConfig = {
|
|
677
|
-
type: yTypeLocal,
|
|
678
|
-
logBase: yLogBase,
|
|
679
|
-
splitLine: {
|
|
680
|
-
show: yGridlines_bool,
|
|
681
|
-
},
|
|
682
|
-
axisLine: {
|
|
683
|
-
show: yBaseline_bool,
|
|
684
|
-
onZero: false,
|
|
685
|
-
},
|
|
686
|
-
axisTick: {
|
|
687
|
-
show: yTickMarks_bool,
|
|
688
|
-
},
|
|
689
|
-
axisLabel: {
|
|
690
|
-
show: yAxisLabels_bool,
|
|
691
|
-
hideOverlap: true,
|
|
692
|
-
margin: 4,
|
|
693
|
-
formatter: function (value) {
|
|
694
|
-
return formatAxisValue(value, yFormat, yUnitSummary)
|
|
695
|
-
},
|
|
696
|
-
color: primaryAxisColor,
|
|
697
|
-
},
|
|
698
|
-
name: yAxisTitleLocal,
|
|
699
|
-
nameLocation: 'end',
|
|
700
|
-
nameTextStyle: {
|
|
701
|
-
align: 'left',
|
|
702
|
-
verticalAlign: 'top',
|
|
703
|
-
padding: [0, 5, 0, 0],
|
|
704
|
-
color: primaryAxisColor,
|
|
705
|
-
},
|
|
706
|
-
nameGap: 6,
|
|
707
|
-
min: yMin,
|
|
708
|
-
max: yMax,
|
|
709
|
-
minInterval: yUnitSummary?.maxDecimals === 0 ? 1 : undefined,
|
|
710
|
-
scale: yScale_bool,
|
|
711
|
-
boundaryGap: yUnitSummary?.maxDecimals === 0 ? false : ['0%', '1%'],
|
|
712
|
-
z: 2,
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
secondaryAxis = {
|
|
716
|
-
type: 'value',
|
|
717
|
-
show: y2Count > 0,
|
|
718
|
-
alignTicks: true,
|
|
719
|
-
splitLine: {
|
|
720
|
-
show: y2Gridlines_bool,
|
|
721
|
-
},
|
|
722
|
-
axisLine: {
|
|
723
|
-
show: y2Baseline_bool,
|
|
724
|
-
onZero: false,
|
|
725
|
-
},
|
|
726
|
-
axisTick: {
|
|
727
|
-
show: y2TickMarks_bool,
|
|
728
|
-
},
|
|
729
|
-
axisLabel: {
|
|
730
|
-
show: y2AxisLabels_bool,
|
|
731
|
-
hideOverlap: true,
|
|
732
|
-
margin: 4,
|
|
733
|
-
formatter: function (value) {
|
|
734
|
-
return formatAxisValue(value, y2Format, y2UnitSummary)
|
|
735
|
-
},
|
|
736
|
-
color: secondaryAxisColor,
|
|
737
|
-
},
|
|
738
|
-
name: y2AxisTitleLocal,
|
|
739
|
-
nameLocation: 'end',
|
|
740
|
-
nameTextStyle: {
|
|
741
|
-
align: 'right',
|
|
742
|
-
verticalAlign: 'top',
|
|
743
|
-
padding: [0, 0, 0, 5],
|
|
744
|
-
color: secondaryAxisColor,
|
|
745
|
-
},
|
|
746
|
-
nameGap: 6,
|
|
747
|
-
min: y2Min,
|
|
748
|
-
max: y2Max,
|
|
749
|
-
minInterval: y2UnitSummary?.maxDecimals === 0 ? 1 : undefined,
|
|
750
|
-
scale: y2Scale_bool,
|
|
751
|
-
boundaryGap: y2UnitSummary?.maxDecimals === 0 ? false : ['0%', '1%'],
|
|
752
|
-
z: 2,
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
verticalAxisConfig = [verticalAxisConfig, secondaryAxis]
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
// ---------------------------------------------------------------------------------------
|
|
759
|
-
// Set up chart area
|
|
760
|
-
// ---------------------------------------------------------------------------------------
|
|
761
|
-
|
|
762
|
-
hasTitle = title ? true : false
|
|
763
|
-
hasSubtitle = subtitle ? true : false
|
|
764
|
-
hasLegend = legendLocal * (series !== null || (yLocal.length > 1))
|
|
765
|
-
hasTopAxisTitle = yAxisTitleLocal !== '' && swapXY_bool
|
|
766
|
-
hasBottomAxisTitle = xAxisTitleLocal !== '' && !swapXY_bool
|
|
767
|
-
|
|
768
|
-
titleFontSize = 15
|
|
769
|
-
subtitleFontSize = 13
|
|
770
|
-
titleBoxPadding = 6 * hasSubtitle
|
|
771
|
-
|
|
772
|
-
titleBoxHeight =
|
|
773
|
-
hasTitle * titleFontSize +
|
|
774
|
-
hasSubtitle * subtitleFontSize +
|
|
775
|
-
titleBoxPadding * Math.max(hasTitle, hasSubtitle)
|
|
776
|
-
|
|
777
|
-
chartAreaPaddingTop = 10
|
|
778
|
-
chartAreaPaddingBottom = 10
|
|
779
|
-
|
|
780
|
-
bottomAxisTitleSize = 14
|
|
781
|
-
topAxisTitleSize = 14 + 0 // font size + padding top
|
|
782
|
-
|
|
783
|
-
legendHeight = 15
|
|
784
|
-
legendHeight = legendHeight * hasLegend
|
|
785
|
-
|
|
786
|
-
legendPaddingTop = 7
|
|
787
|
-
legendPaddingTop = legendPaddingTop * Math.max(hasTitle, hasSubtitle)
|
|
788
|
-
|
|
789
|
-
legendTop = titleBoxHeight + legendPaddingTop
|
|
790
|
-
chartTop =
|
|
791
|
-
legendTop + legendHeight + topAxisTitleSize * hasTopAxisTitle + chartAreaPaddingTop
|
|
792
|
-
chartBottom = hasBottomAxisTitle * bottomAxisTitleSize + chartAreaPaddingBottom
|
|
793
|
-
|
|
794
|
-
// Adjustment to avoid small bars on horizontal bar chart (extend chart height to accomodate)
|
|
795
|
-
// Small bars are allowed on normal bar chart (e.g., time series bar chart)
|
|
796
|
-
maxBars = 8
|
|
797
|
-
heightMultiplier = 1
|
|
798
|
-
if (swapXY_bool) {
|
|
799
|
-
barCount = xDistinct.length
|
|
800
|
-
heightMultiplier = Math.max(1, barCount / maxBars)
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
chartContainerHeight = chartAreaHeightLocal * heightMultiplier + chartTop + chartBottom
|
|
804
|
-
|
|
805
|
-
topAxisTitleTop = legendTop + legendHeight + 7
|
|
806
|
-
|
|
807
|
-
// Set final chart height:
|
|
808
|
-
dimensions.set({height: chartContainerHeight + 'px', width: '100%'})
|
|
809
|
-
|
|
810
|
-
// ---------------------------------------------------------------------------------------
|
|
811
|
-
// Set up horizontal axis title (custom graphic)
|
|
812
|
-
// ---------------------------------------------------------------------------------------
|
|
813
|
-
horizAxisTitle = swapXY_bool ? yAxisTitleLocal : xAxisTitleLocal
|
|
814
|
-
if (horizAxisTitle !== '') {
|
|
815
|
-
horizAxisTitle = horizAxisTitle + ' →' // u2192 is js escaped version of →
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
horizAxisTitleConfig = {
|
|
819
|
-
id: 'horiz-axis-title',
|
|
820
|
-
type: 'text',
|
|
821
|
-
style: {
|
|
822
|
-
text: horizAxisTitle,
|
|
823
|
-
textAlign: 'right',
|
|
824
|
-
fill: $theme.colors['base-content-muted'],
|
|
825
|
-
},
|
|
826
|
-
cursor: 'auto',
|
|
827
|
-
// Positioning (if swapXY, top right; otherwise bottom right)
|
|
828
|
-
right: swapXY_bool ? '2%' : '3%',
|
|
829
|
-
top: swapXY_bool ? topAxisTitleTop : null,
|
|
830
|
-
bottom: swapXY_bool ? null : '2%',
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
// ---------------------------------------------------------------------------------------
|
|
834
|
-
// Build chart config and update config store so child components can access it
|
|
835
|
-
// ---------------------------------------------------------------------------------------
|
|
836
|
-
|
|
837
|
-
chartConfig = {
|
|
838
|
-
title: {
|
|
839
|
-
text: title,
|
|
840
|
-
subtext: subtitle,
|
|
841
|
-
subtextStyle: {
|
|
842
|
-
width: '100%',
|
|
843
|
-
},
|
|
844
|
-
},
|
|
845
|
-
tooltip: {
|
|
846
|
-
trigger: 'axis',
|
|
847
|
-
show: true,
|
|
848
|
-
// formatter function is overridden in ScatterPlot, BubbleChart, and Histogram
|
|
849
|
-
formatter: function (params) {
|
|
850
|
-
let output
|
|
851
|
-
let xVal
|
|
852
|
-
let yVal
|
|
853
|
-
let yCol
|
|
854
|
-
if (totalSeriesCount > 1) {
|
|
855
|
-
// If multi-series, add series name as title of tooltip
|
|
856
|
-
xVal = params[0].value[swapXY_bool ? 1 : 0]
|
|
857
|
-
output = `<span id="tooltip" style='font-weight: 600;'>${formatValue(
|
|
858
|
-
xVal,
|
|
859
|
-
xFormat,
|
|
860
|
-
)}</span>`
|
|
861
|
-
for (let i = params.length - 1; i >= 0; i--) {
|
|
862
|
-
if (params[i].seriesName !== 'stackTotal') {
|
|
863
|
-
yVal = params[i].value[swapXY_bool ? 0 : 1]
|
|
864
|
-
output =
|
|
865
|
-
output +
|
|
866
|
-
`<br> <span style='font-size: 11px;'>${params[i].marker} ${
|
|
867
|
-
params[i].seriesName
|
|
868
|
-
}<span/><span style='float:right; margin-left: 10px; font-size: 12px;'>${formatValue(
|
|
869
|
-
yVal,
|
|
870
|
-
// Not sure if this will work. Need to check with multi series on both axes
|
|
871
|
-
// Check if echarts does the order in the same way - y first, then y2
|
|
872
|
-
getYAxisIndex(params[i].componentIndex, yCount, y2Count) === 0
|
|
873
|
-
? yFormat
|
|
874
|
-
: y2Format,
|
|
875
|
-
)}</span>`
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
} else if (xTypeLocal === 'value') {
|
|
879
|
-
// If single-series and a numerical x-axis, include x column as a normal column rather than title (so as not to show a number as the title)
|
|
880
|
-
xVal = params[0].value[swapXY_bool ? 1 : 0]
|
|
881
|
-
yVal = params[0].value[swapXY_bool ? 0 : 1]
|
|
882
|
-
yCol = params[0].seriesName
|
|
883
|
-
output = `<span id="tooltip" style='font-weight: 600;'>${formatTitle(
|
|
884
|
-
xLocal,
|
|
885
|
-
xFormat,
|
|
886
|
-
)}: </span><span style='float:right; margin-left: 10px;'>${formatValue(
|
|
887
|
-
xVal,
|
|
888
|
-
xFormat,
|
|
889
|
-
)}</span><br/><span style='font-weight: 600;'>${formatTitle(
|
|
890
|
-
yCol,
|
|
891
|
-
yFormat,
|
|
892
|
-
)}: </span><span style='float:right; margin-left: 10px;'>${formatValue(
|
|
893
|
-
yVal,
|
|
894
|
-
yFormat,
|
|
895
|
-
)}</span>`
|
|
896
|
-
} else {
|
|
897
|
-
// If single series and categorical or date x-axis, use x value as title of tooltip
|
|
898
|
-
xVal = params[0].value[swapXY_bool ? 1 : 0]
|
|
899
|
-
yVal = params[0].value[swapXY_bool ? 0 : 1]
|
|
900
|
-
yCol = params[0].seriesName
|
|
901
|
-
output = `<span id="tooltip" style='font-weight: 600;'>${formatValue(
|
|
902
|
-
xVal,
|
|
903
|
-
xFormat,
|
|
904
|
-
)}</span><br/><span>${formatTitle(
|
|
905
|
-
yCol,
|
|
906
|
-
yFormat,
|
|
907
|
-
)}: </span><span style='float:right; margin-left: 10px;'>${formatValue(
|
|
908
|
-
yVal,
|
|
909
|
-
yFormat,
|
|
910
|
-
)}</span>`
|
|
911
|
-
}
|
|
912
|
-
return output
|
|
913
|
-
},
|
|
914
|
-
confine: true,
|
|
915
|
-
axisPointer: {
|
|
916
|
-
// Use axis to trigger tooltip
|
|
917
|
-
type: 'shadow', // 'shadow' as default; can also be 'line' or 'shadow'
|
|
918
|
-
},
|
|
919
|
-
extraCssText:
|
|
920
|
-
'box-shadow: 0 3px 6px rgba(0,0,0,.15); box-shadow: 0 2px 4px rgba(0,0,0,.12); z-index: 1; font-feature-settings: "cv02", "tnum";',
|
|
921
|
-
order: 'valueDesc',
|
|
922
|
-
},
|
|
923
|
-
legend: {
|
|
924
|
-
show: legendLocal,
|
|
925
|
-
type: 'scroll',
|
|
926
|
-
top: legendTop,
|
|
927
|
-
padding: [0, 0, 0, 0],
|
|
928
|
-
data: [],
|
|
929
|
-
},
|
|
930
|
-
grid: {
|
|
931
|
-
left: leftPadding ?? (swapXY_bool ? '1%' : '0.8%'),
|
|
932
|
-
right: rightPadding ?? (swapXY_bool ? '4%' : '3%'),
|
|
933
|
-
bottom: chartBottom,
|
|
934
|
-
top: chartTop,
|
|
935
|
-
containLabel: true,
|
|
936
|
-
},
|
|
937
|
-
xAxis: horizAxisConfig,
|
|
938
|
-
yAxis: verticalAxisConfig,
|
|
939
|
-
series: [],
|
|
940
|
-
animation: false,
|
|
941
|
-
graphic: horizAxisTitleConfig,
|
|
942
|
-
color: $colorPaletteResolved,
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
config.update(() => {
|
|
946
|
-
return chartConfig
|
|
947
|
-
})
|
|
948
|
-
} catch (e) {
|
|
949
|
-
// svelte-ignore non_reactive_update
|
|
950
|
-
error = e.message
|
|
951
|
-
let setTextRed = '\x1b[31m%s\x1b[0m'
|
|
952
|
-
console.error(setTextRed, `Error in ${chartType}: ${e.message}`)
|
|
953
|
-
|
|
954
|
-
// Make an "id" for the chart so its clear to users/agents exactly which caused an error.
|
|
955
|
-
let fieldStr = Object.entries(chartContext || {})
|
|
956
|
-
.filter(([_, val]) => {
|
|
957
|
-
if (Array.isArray(val)) return val.length > 0
|
|
958
|
-
if (typeof val === 'string') return val.trim().length > 0
|
|
959
|
-
return Boolean(val)
|
|
960
|
-
})
|
|
961
|
-
.map(([name, val]) => `${name}="${Array.isArray(val) ? val.join(', ') : val}"`)
|
|
962
|
-
let id = `${title || chartType} (${fieldStr.join(' ')})`
|
|
963
|
-
logError(e, {id})
|
|
964
|
-
|
|
965
|
-
chartProps.update((d) => {
|
|
966
|
-
return {...d, error}
|
|
967
|
-
})
|
|
968
|
-
}
|
|
969
|
-
})
|
|
970
|
-
</script>
|
|
971
|
-
|
|
972
|
-
{#if !$chartProps.error}
|
|
973
|
-
{@render children?.()}
|
|
974
|
-
<ECharts
|
|
975
|
-
config={$config}
|
|
976
|
-
height={$dimensions.height}
|
|
977
|
-
width={$dimensions.width}
|
|
978
|
-
{data}
|
|
979
|
-
{queryID}
|
|
980
|
-
chartTitle={title}
|
|
981
|
-
{echartsOptions}
|
|
982
|
-
{seriesOptions}
|
|
983
|
-
{connectGroup}
|
|
984
|
-
{xAxisLabelOverflow}
|
|
985
|
-
seriesColors={$seriesColorsResolved}
|
|
986
|
-
/>
|
|
987
|
-
{:else}
|
|
988
|
-
<ErrorChart error={$chartProps.error} title={chartType} />
|
|
989
|
-
{/if}
|