1
0
Fork 0
mirror of synced 2024-09-10 06:26:02 +12:00

line chart

This commit is contained in:
Gerard Burns 2024-04-18 10:04:01 +01:00
parent 5751e92bbd
commit 441595dd6d
4 changed files with 112 additions and 108 deletions

View file

@ -1859,7 +1859,7 @@
"type": "select", "type": "select",
"label": "Colors", "label": "Colors",
"key": "palette", "key": "palette",
"defaultValue": "Palette 1", "defaultValue": "palette1",
"options": [ "options": [
{ "label": "Custom", "value": "Custom" }, { "label": "Custom", "value": "Custom" },
{ "label": "Palette 1", "value": "palette1" }, { "label": "Palette 1", "value": "palette1" },

View file

@ -16,6 +16,9 @@
let chart; let chart;
const updateChart = async (newOptions) => { const updateChart = async (newOptions) => {
// Line charts won't transition from category to datetime types properly without
// calling this with an empty object first; I don't know why this works.
await chart?.updateOptions({})
await chart?.updateOptions(newOptions) await chart?.updateOptions(newOptions)
} }

View file

@ -33,7 +33,6 @@
$: labelType = dataProvider?.schema?.[labelColumn]?.type === 'datetime' ? $: labelType = dataProvider?.schema?.[labelColumn]?.type === 'datetime' ?
"datetime" : "category" "datetime" : "category"
$: formatter = getFormatter(labelType, valueUnits)
$: xAxisFormatter = getFormatter(labelType, valueUnits, horizontal, "x") $: xAxisFormatter = getFormatter(labelType, valueUnits, horizontal, "x")
$: yAxisFormatter = getFormatter(labelType, valueUnits, horizontal, "y") $: yAxisFormatter = getFormatter(labelType, valueUnits, horizontal, "y")

View file

@ -16,7 +16,7 @@
export let dataLabels export let dataLabels
export let curve export let curve
export let legend export let legend
export let yAxisUnits export let valueUnits
export let palette export let palette
export let c1, c2, c3, c4, c5 export let c1, c2, c3, c4, c5
@ -25,122 +25,124 @@
export let stacked export let stacked
export let gradient export let gradient
$: options = setUpChart( $: {
title, console.log(palette);
dataProvider, }
labelColumn,
valueColumns,
xAxisLabel,
yAxisLabel,
height,
width,
animate,
dataLabels,
curve,
legend,
yAxisUnits,
palette,
area,
stacked,
gradient,
c1 && c2 && c3 && c4 && c5 ? [c1, c2, c3, c4, c5] : null,
customColor
)
$: customColor = palette === "Custom" const formatters = {
["Default"]: val => val,
["Thousands"]: val => `${Math.round(val / 1000)}K`,
["Millions"]: val => `${Math.round(val / 1000000)}M`,
["Datetime"]: val => (new Date(val)).toLocaleString()
}
const setUpChart = ( $: series = getSeries(dataProvider, valueColumns)
title, $: categories = getCategories(dataProvider, labelColumn);
dataProvider,
labelColumn, $: labelType = dataProvider?.schema?.[labelColumn]?.type === 'datetime' ?
valueColumns, "datetime" : "category"
xAxisLabel, $: xAxisFormatter = getFormatter(labelType, valueUnits, "x")
yAxisLabel, $: yAxisFormatter = getFormatter(labelType, valueUnits, "y")
height,
width, $: options = {
animate, series,
dataLabels, stroke: {
curve, curve: curve.toLowerCase()
legend, },
yAxisUnits, colors: palette === "Custom" ? [c1, c2, c3, c4, c5] : [],
palette, theme: {
area, palette: palette === "Custom" ? null : palette
stacked, },
gradient, legend: {
colors, show: legend,
customColor position: "top",
) => { horizontalAlign: "right",
const allCols = [labelColumn, ...(valueColumns || [null])] showForSingleSeries: true,
if ( showForNullSeries: true,
!dataProvider || showForZeroSeries: true,
!dataProvider.rows?.length || },
allCols.find(x => x == null) title: {
) { text: title,
return null },
dataLabels: {
enabled: dataLabels
},
chart: {
height: height == null || height === "" ? "auto" : height,
width: width == null || width === "" ? "100%" : width,
type: "line",
stacked,
animations: {
enabled: animate
},
toolbar: {
show: false,
},
zoom: {
enabled: false,
},
},
xaxis: {
type: labelType,
categories,
labels: {
formatter: xAxisFormatter
},
title: {
text: xAxisLabel
}
},
yaxis: {
labels: {
formatter: yAxisFormatter
},
title: {
text: yAxisLabel
}
} }
}
// Fetch, filter and sort data const getSeries = (datasource, valueColumns = []) => {
const { schema, rows } = dataProvider const rows = datasource.rows ?? [];
const data = rows
if (!schema || !data.length) {
return null
}
// Initialise default chart return valueColumns.map(column => ({
let builder = new ApexOptionsBuilder()
.title(title)
.type(area ? "area" : "line")
.width(width)
.height(height)
.xLabel(xAxisLabel)
.yLabel(yAxisLabel)
.dataLabels(dataLabels)
.animate(animate)
.curve(curve.toLowerCase())
.gradient(gradient)
.stacked(stacked)
.legend(legend)
.yUnits(yAxisUnits)
.palette(palette)
.colors(customColor ? colors : null)
// Add data
let useDates = false
if (schema[labelColumn]) {
const labelFieldType = schema[labelColumn].type
builder = builder.xType(labelFieldType)
useDates = labelFieldType === "datetime"
}
const series = (valueColumns ?? []).map(column => ({
name: column, name: column,
data: data.map(row => { data: rows.map(row => {
if (!useDates) { return row?.[column]
const value = get(row, column);
if (Array.isArray(value)) {
return null;
}
if (Number.isNaN(parseInt(value, 10))) {
return null;
}
return value;
} else {
return [row[labelColumn], row[column]]
}
}), }),
})) }))
builder = builder.series(series) }
if (!useDates) {
builder = builder.xCategories(data.map(row => row[labelColumn])) const getCategories = (datasource, labelColumn) => {
} else { const rows = datasource.rows ?? [];
builder = builder.clearXFormatter()
return rows.map(row => {
const value = row?.[labelColumn]
// If a nullish or non-scalar type, replace it with an empty string
if (!["string", "number", "boolean"].includes(typeof value)) {
return ""
}
return value;
})
}
const getFormatter = (labelType, valueUnits, axis) => {
const isLabelAxis = axis === "x"
if (labelType === "datetime" && isLabelAxis) {
return formatters["Datetime"]
} }
// Build chart options if (isLabelAxis) {
return builder.getOptions() return formatters["Default"]
}
return formatters[valueUnits]
} }
$: console.log("opt", options);
</script> </script>
<ApexChart {options} /> <ApexChart {options} />