line chart
This commit is contained in:
parent
5751e92bbd
commit
441595dd6d
|
@ -1859,7 +1859,7 @@
|
|||
"type": "select",
|
||||
"label": "Colors",
|
||||
"key": "palette",
|
||||
"defaultValue": "Palette 1",
|
||||
"defaultValue": "palette1",
|
||||
"options": [
|
||||
{ "label": "Custom", "value": "Custom" },
|
||||
{ "label": "Palette 1", "value": "palette1" },
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
let chart;
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
$: labelType = dataProvider?.schema?.[labelColumn]?.type === 'datetime' ?
|
||||
"datetime" : "category"
|
||||
$: formatter = getFormatter(labelType, valueUnits)
|
||||
$: xAxisFormatter = getFormatter(labelType, valueUnits, horizontal, "x")
|
||||
$: yAxisFormatter = getFormatter(labelType, valueUnits, horizontal, "y")
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
export let dataLabels
|
||||
export let curve
|
||||
export let legend
|
||||
export let yAxisUnits
|
||||
export let valueUnits
|
||||
export let palette
|
||||
export let c1, c2, c3, c4, c5
|
||||
|
||||
|
@ -25,122 +25,124 @@
|
|||
export let stacked
|
||||
export let gradient
|
||||
|
||||
$: options = setUpChart(
|
||||
title,
|
||||
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
|
||||
)
|
||||
$: {
|
||||
console.log(palette);
|
||||
}
|
||||
|
||||
$: 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 = (
|
||||
title,
|
||||
dataProvider,
|
||||
labelColumn,
|
||||
valueColumns,
|
||||
xAxisLabel,
|
||||
yAxisLabel,
|
||||
height,
|
||||
width,
|
||||
animate,
|
||||
dataLabels,
|
||||
curve,
|
||||
legend,
|
||||
yAxisUnits,
|
||||
palette,
|
||||
area,
|
||||
stacked,
|
||||
gradient,
|
||||
colors,
|
||||
customColor
|
||||
) => {
|
||||
const allCols = [labelColumn, ...(valueColumns || [null])]
|
||||
if (
|
||||
!dataProvider ||
|
||||
!dataProvider.rows?.length ||
|
||||
allCols.find(x => x == null)
|
||||
) {
|
||||
return null
|
||||
$: series = getSeries(dataProvider, valueColumns)
|
||||
$: categories = getCategories(dataProvider, labelColumn);
|
||||
|
||||
$: labelType = dataProvider?.schema?.[labelColumn]?.type === 'datetime' ?
|
||||
"datetime" : "category"
|
||||
$: xAxisFormatter = getFormatter(labelType, valueUnits, "x")
|
||||
$: yAxisFormatter = getFormatter(labelType, valueUnits, "y")
|
||||
|
||||
$: options = {
|
||||
series,
|
||||
stroke: {
|
||||
curve: curve.toLowerCase()
|
||||
},
|
||||
colors: palette === "Custom" ? [c1, c2, c3, c4, c5] : [],
|
||||
theme: {
|
||||
palette: palette === "Custom" ? null : palette
|
||||
},
|
||||
legend: {
|
||||
show: legend,
|
||||
position: "top",
|
||||
horizontalAlign: "right",
|
||||
showForSingleSeries: true,
|
||||
showForNullSeries: true,
|
||||
showForZeroSeries: true,
|
||||
},
|
||||
title: {
|
||||
text: title,
|
||||
},
|
||||
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 { schema, rows } = dataProvider
|
||||
const data = rows
|
||||
if (!schema || !data.length) {
|
||||
return null
|
||||
}
|
||||
const getSeries = (datasource, valueColumns = []) => {
|
||||
const rows = datasource.rows ?? [];
|
||||
|
||||
// Initialise default chart
|
||||
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 => ({
|
||||
return valueColumns.map(column => ({
|
||||
name: column,
|
||||
data: data.map(row => {
|
||||
if (!useDates) {
|
||||
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]]
|
||||
}
|
||||
data: rows.map(row => {
|
||||
return row?.[column]
|
||||
}),
|
||||
}))
|
||||
builder = builder.series(series)
|
||||
if (!useDates) {
|
||||
builder = builder.xCategories(data.map(row => row[labelColumn]))
|
||||
} else {
|
||||
builder = builder.clearXFormatter()
|
||||
}
|
||||
|
||||
const getCategories = (datasource, labelColumn) => {
|
||||
const rows = datasource.rows ?? [];
|
||||
|
||||
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
|
||||
return builder.getOptions()
|
||||
if (isLabelAxis) {
|
||||
return formatters["Default"]
|
||||
}
|
||||
|
||||
return formatters[valueUnits]
|
||||
}
|
||||
|
||||
$: console.log("opt", options);
|
||||
</script>
|
||||
|
||||
<ApexChart {options} />
|
||||
|
|
Loading…
Reference in New Issue