@odoo/o-spreadsheet 16.5.0-alpha.3 → 16.5.0-alpha.4
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/dist/o-spreadsheet.cjs.js +418 -138
- package/dist/o-spreadsheet.d.ts +31 -23
- package/dist/o-spreadsheet.esm.js +418 -138
- package/dist/o-spreadsheet.iife.js +418 -138
- package/dist/o-spreadsheet.iife.min.js +241 -241
- package/package.json +5 -4
|
@@ -3478,14 +3478,15 @@ class ChartJsComponent extends owl.Component {
|
|
|
3478
3478
|
createChart(chartData) {
|
|
3479
3479
|
const canvas = this.canvas.el;
|
|
3480
3480
|
const ctx = canvas.getContext("2d");
|
|
3481
|
+
// @ts-ignore
|
|
3481
3482
|
this.chart = new window.Chart(ctx, chartData);
|
|
3482
3483
|
}
|
|
3483
3484
|
updateChartJs(chartRuntime) {
|
|
3484
3485
|
const chartData = chartRuntime.chartJsConfig;
|
|
3485
3486
|
if (chartData.data && chartData.data.datasets) {
|
|
3486
3487
|
this.chart.data = chartData.data;
|
|
3487
|
-
if (chartData.options?.title) {
|
|
3488
|
-
this.chart.config.options.title = chartData.options.title;
|
|
3488
|
+
if (chartData.options?.plugins?.title) {
|
|
3489
|
+
this.chart.config.options.plugins.title = chartData.options.plugins.title;
|
|
3489
3490
|
}
|
|
3490
3491
|
if (chartData.options && "valueLabel" in chartData.options) {
|
|
3491
3492
|
if (chartData.options?.valueLabel) {
|
|
@@ -3495,12 +3496,13 @@ class ChartJsComponent extends owl.Component {
|
|
|
3495
3496
|
}
|
|
3496
3497
|
}
|
|
3497
3498
|
else {
|
|
3498
|
-
this.chart.data.datasets =
|
|
3499
|
+
this.chart.data.datasets = [];
|
|
3499
3500
|
}
|
|
3500
|
-
this.chart.config.options.
|
|
3501
|
-
this.chart.config.options.legend = chartData.options
|
|
3501
|
+
this.chart.config.options.plugins.tooltip = chartData.options.plugins.tooltip;
|
|
3502
|
+
this.chart.config.options.plugins.legend = chartData.options.plugins.legend;
|
|
3502
3503
|
this.chart.config.options.scales = chartData.options?.scales;
|
|
3503
|
-
|
|
3504
|
+
// ?
|
|
3505
|
+
this.chart.update("active");
|
|
3504
3506
|
}
|
|
3505
3507
|
}
|
|
3506
3508
|
ChartJsComponent.props = {
|
|
@@ -16182,49 +16184,40 @@ function truncateLabel(label) {
|
|
|
16182
16184
|
* Get a default chart js configuration
|
|
16183
16185
|
*/
|
|
16184
16186
|
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale }) {
|
|
16185
|
-
|
|
16186
|
-
|
|
16187
|
-
|
|
16188
|
-
|
|
16189
|
-
|
|
16190
|
-
|
|
16191
|
-
|
|
16192
|
-
|
|
16193
|
-
|
|
16194
|
-
|
|
16195
|
-
line: {
|
|
16196
|
-
fill: false, // do not fill the area under line charts
|
|
16197
|
-
},
|
|
16198
|
-
point: {
|
|
16199
|
-
hitRadius: 15, // increased hit radius to display point tooltip when hovering nearby
|
|
16200
|
-
},
|
|
16201
|
-
},
|
|
16202
|
-
animation: {
|
|
16203
|
-
duration: 0, // general animation time
|
|
16187
|
+
const options = {
|
|
16188
|
+
// https://www.chartjs.org/docs/latest/general/responsive.html
|
|
16189
|
+
responsive: true,
|
|
16190
|
+
maintainAspectRatio: false,
|
|
16191
|
+
layout: {
|
|
16192
|
+
padding: { left: 20, right: 20, top: chart.title ? 10 : 25, bottom: 10 },
|
|
16193
|
+
},
|
|
16194
|
+
elements: {
|
|
16195
|
+
line: {
|
|
16196
|
+
fill: false, // do not fill the area under line charts
|
|
16204
16197
|
},
|
|
16205
|
-
|
|
16206
|
-
|
|
16198
|
+
point: {
|
|
16199
|
+
hitRadius: 15, // increased hit radius to display point tooltip when hovering nearby
|
|
16207
16200
|
},
|
|
16208
|
-
|
|
16201
|
+
},
|
|
16202
|
+
animation: false,
|
|
16203
|
+
plugins: {
|
|
16209
16204
|
title: {
|
|
16210
16205
|
display: !!chart.title,
|
|
16211
|
-
fontSize: 22,
|
|
16212
|
-
fontStyle: "normal",
|
|
16213
16206
|
text: _t(chart.title),
|
|
16214
|
-
fontColor,
|
|
16207
|
+
color: fontColor,
|
|
16208
|
+
font: { size: 22, weight: "normal" },
|
|
16215
16209
|
},
|
|
16216
16210
|
legend: {
|
|
16217
16211
|
// Disable default legend onClick (show/hide dataset), to allow us to set a global onClick on the chart container.
|
|
16218
16212
|
// If we want to re-enable this in the future, we need to override the default onClick to stop the event propagation
|
|
16219
|
-
onClick:
|
|
16213
|
+
onClick: () => { },
|
|
16220
16214
|
},
|
|
16221
|
-
|
|
16215
|
+
tooltip: {
|
|
16222
16216
|
callbacks: {
|
|
16223
|
-
label: function (tooltipItem
|
|
16224
|
-
let xLabel =
|
|
16225
|
-
|
|
16226
|
-
|
|
16227
|
-
: data.datasets?.[tooltipItem.datasetIndex || 0]?.data?.[tooltipItem.index || 0];
|
|
16217
|
+
label: function (tooltipItem) {
|
|
16218
|
+
let xLabel = tooltipItem.label;
|
|
16219
|
+
// tooltipItem.parsed.y can be an object or a number for pie charts
|
|
16220
|
+
const yLabel = tooltipItem.parsed.y ?? tooltipItem.parsed;
|
|
16228
16221
|
const yLabelStr = format && typeof yLabel === "number"
|
|
16229
16222
|
? formatValue(yLabel, { format, locale })
|
|
16230
16223
|
: yLabel?.toLocaleString() || "";
|
|
@@ -16233,10 +16226,15 @@ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale })
|
|
|
16233
16226
|
},
|
|
16234
16227
|
},
|
|
16235
16228
|
},
|
|
16229
|
+
};
|
|
16230
|
+
return {
|
|
16231
|
+
type: chart.type,
|
|
16232
|
+
options,
|
|
16236
16233
|
data: {
|
|
16237
16234
|
labels: labels.map(truncateLabel),
|
|
16238
16235
|
datasets: [],
|
|
16239
16236
|
},
|
|
16237
|
+
plugins: [],
|
|
16240
16238
|
};
|
|
16241
16239
|
}
|
|
16242
16240
|
function getChartLabelFormat(getters, range) {
|
|
@@ -16433,7 +16431,7 @@ function getBarConfiguration(chart, labels, localeFormat) {
|
|
|
16433
16431
|
const fontColor = chartFontColor(chart.background);
|
|
16434
16432
|
const config = getDefaultChartJsRuntime(chart, labels, fontColor, localeFormat);
|
|
16435
16433
|
const legend = {
|
|
16436
|
-
labels: { fontColor },
|
|
16434
|
+
labels: { color: fontColor },
|
|
16437
16435
|
};
|
|
16438
16436
|
if ((!chart.labelRange && chart.dataSets.length === 1) || chart.legendPosition === "none") {
|
|
16439
16437
|
legend.display = false;
|
|
@@ -16441,42 +16439,35 @@ function getBarConfiguration(chart, labels, localeFormat) {
|
|
|
16441
16439
|
else {
|
|
16442
16440
|
legend.position = chart.legendPosition;
|
|
16443
16441
|
}
|
|
16444
|
-
config.options.legend = { ...config.options?.legend, ...legend };
|
|
16442
|
+
config.options.plugins.legend = { ...config.options.plugins?.legend, ...legend };
|
|
16445
16443
|
config.options.layout = {
|
|
16446
16444
|
padding: { left: 20, right: 20, top: chart.title ? 10 : 25, bottom: 10 },
|
|
16447
16445
|
};
|
|
16448
16446
|
config.options.scales = {
|
|
16449
|
-
|
|
16450
|
-
{
|
|
16451
|
-
|
|
16452
|
-
|
|
16453
|
-
maxRotation: 60,
|
|
16454
|
-
minRotation: 15,
|
|
16455
|
-
padding: 5,
|
|
16456
|
-
labelOffset: 2,
|
|
16457
|
-
fontColor,
|
|
16458
|
-
},
|
|
16447
|
+
x: {
|
|
16448
|
+
ticks: {
|
|
16449
|
+
padding: 5,
|
|
16450
|
+
color: fontColor,
|
|
16459
16451
|
},
|
|
16460
|
-
|
|
16461
|
-
|
|
16462
|
-
|
|
16463
|
-
|
|
16464
|
-
|
|
16465
|
-
|
|
16466
|
-
|
|
16467
|
-
|
|
16468
|
-
|
|
16469
|
-
|
|
16470
|
-
? formatValue(value, localeFormat)
|
|
16471
|
-
: value?.toLocaleString() || value;
|
|
16472
|
-
},
|
|
16452
|
+
},
|
|
16453
|
+
y: {
|
|
16454
|
+
position: chart.verticalAxisPosition,
|
|
16455
|
+
beginAtZero: true,
|
|
16456
|
+
ticks: {
|
|
16457
|
+
color: fontColor,
|
|
16458
|
+
callback: (value) => {
|
|
16459
|
+
return localeFormat.format
|
|
16460
|
+
? formatValue(value, localeFormat)
|
|
16461
|
+
: value?.toLocaleString() || value;
|
|
16473
16462
|
},
|
|
16474
16463
|
},
|
|
16475
|
-
|
|
16464
|
+
},
|
|
16476
16465
|
};
|
|
16477
16466
|
if (chart.stacked) {
|
|
16478
|
-
|
|
16479
|
-
config.options.scales.
|
|
16467
|
+
// @ts-ignore chart.js type is broken
|
|
16468
|
+
config.options.scales.x.stacked = true;
|
|
16469
|
+
// @ts-ignore chart.js type is broken
|
|
16470
|
+
config.options.scales.y.stacked = true;
|
|
16480
16471
|
}
|
|
16481
16472
|
return config;
|
|
16482
16473
|
}
|
|
@@ -16680,17 +16671,18 @@ function getGaugeConfiguration(chart, locale) {
|
|
|
16680
16671
|
padding: { left: 30, right: 30, top: chart.title ? 10 : 25, bottom: 25 },
|
|
16681
16672
|
};
|
|
16682
16673
|
config.options.needle = {
|
|
16683
|
-
|
|
16684
|
-
|
|
16685
|
-
|
|
16686
|
-
color: "#000000",
|
|
16674
|
+
width: 10,
|
|
16675
|
+
borderColor: "#000000",
|
|
16676
|
+
backgroundColor: "#000000",
|
|
16687
16677
|
};
|
|
16688
16678
|
config.options.valueLabel = {
|
|
16689
16679
|
display: false,
|
|
16690
|
-
|
|
16691
|
-
|
|
16680
|
+
font: {
|
|
16681
|
+
size: 30,
|
|
16682
|
+
color: "#FFFFFF",
|
|
16683
|
+
},
|
|
16692
16684
|
backgroundColor: "#000000",
|
|
16693
|
-
|
|
16685
|
+
borderColor: "#000000",
|
|
16694
16686
|
borderRadius: 5,
|
|
16695
16687
|
padding: {
|
|
16696
16688
|
top: 5,
|
|
@@ -16698,7 +16690,6 @@ function getGaugeConfiguration(chart, locale) {
|
|
|
16698
16690
|
bottom: 5,
|
|
16699
16691
|
left: 5,
|
|
16700
16692
|
},
|
|
16701
|
-
bottomMarginPercentage: 5,
|
|
16702
16693
|
};
|
|
16703
16694
|
return config;
|
|
16704
16695
|
}
|
|
@@ -16740,16 +16731,12 @@ function createGaugeChartRuntime(chart, getters) {
|
|
|
16740
16731
|
data.push(point.value);
|
|
16741
16732
|
backgroundColor.push(point.color);
|
|
16742
16733
|
});
|
|
16743
|
-
// There's a bug in gauge lib when the last element in `data` is 0 (i.e. when the range maximum is 0).
|
|
16744
|
-
// The value wrongly fallbacks to 1 because 0 is falsy
|
|
16745
|
-
// See https://github.com/haiiaaa/chartjs-gauge/pull/33
|
|
16746
|
-
// https://github.com/haiiaaa/chartjs-gauge/blob/2ea50541d754d710cb30c2502fa690ac5dc27afd/src/controllers/controller.gauge.js#L52
|
|
16747
16734
|
data.push(maxNeedleValue);
|
|
16748
16735
|
backgroundColor.push(colors.upperColor);
|
|
16749
16736
|
const dataRange = chart.dataRange;
|
|
16750
16737
|
const deltaBeyondRangeLimit = needleCoverage / 30;
|
|
16751
16738
|
let needleValue = minNeedleValue - deltaBeyondRangeLimit; // make needle value always at the minimum by default
|
|
16752
|
-
let cellFormatter =
|
|
16739
|
+
let cellFormatter = undefined;
|
|
16753
16740
|
let displayValue = false;
|
|
16754
16741
|
if (dataRange !== undefined) {
|
|
16755
16742
|
const cell = getters.getEvaluatedCell({
|
|
@@ -16764,6 +16751,7 @@ function createGaugeChartRuntime(chart, getters) {
|
|
|
16764
16751
|
// smaller and slightly larger than minRange and maxRange to mark the fact
|
|
16765
16752
|
// that the needle is out of the range limits
|
|
16766
16753
|
needleValue = clip(cell.value, minNeedleValue - deltaBeyondRangeLimit, maxNeedleValue + deltaBeyondRangeLimit);
|
|
16754
|
+
// show the original value, not the clipped one
|
|
16767
16755
|
cellFormatter = () => getters.getRangeFormattedValues(dataRange)[0];
|
|
16768
16756
|
displayValue = true;
|
|
16769
16757
|
}
|
|
@@ -16811,31 +16799,29 @@ const Milliseconds = {
|
|
|
16811
16799
|
},
|
|
16812
16800
|
};
|
|
16813
16801
|
/**
|
|
16814
|
-
* Regex to test if a format string is a date format that can be translated into a
|
|
16802
|
+
* Regex to test if a format string is a date format that can be translated into a luxon time format
|
|
16815
16803
|
*/
|
|
16816
|
-
const
|
|
16804
|
+
const timeFormatLuxonCompatible = /^((d|dd|m|mm|yyyy|yy|hh|h|ss|a)(-|:|\s|\/))*(d|dd|m|mm|yyyy|yy|hh|h|ss|a)$/i;
|
|
16817
16805
|
/** Get the time options for the XAxis of ChartJS */
|
|
16818
16806
|
function getChartTimeOptions(labels, labelFormat, locale) {
|
|
16819
|
-
const
|
|
16820
|
-
const timeUnit = getBestTimeUnitForScale(labels,
|
|
16807
|
+
const luxonFormat = convertDateFormatForLuxon(labelFormat);
|
|
16808
|
+
const timeUnit = getBestTimeUnitForScale(labels, luxonFormat, locale);
|
|
16821
16809
|
const displayFormats = {};
|
|
16822
16810
|
if (timeUnit) {
|
|
16823
|
-
displayFormats[timeUnit] =
|
|
16811
|
+
displayFormats[timeUnit] = luxonFormat;
|
|
16824
16812
|
}
|
|
16825
16813
|
return {
|
|
16826
|
-
parser:
|
|
16814
|
+
parser: luxonFormat,
|
|
16827
16815
|
displayFormats,
|
|
16828
|
-
unit: timeUnit,
|
|
16816
|
+
unit: timeUnit ?? false,
|
|
16829
16817
|
};
|
|
16830
16818
|
}
|
|
16831
16819
|
/**
|
|
16832
16820
|
* Convert the given date format into a format that moment.js understands.
|
|
16833
16821
|
*
|
|
16834
|
-
* https://
|
|
16822
|
+
* https://github.com/moment/luxon/blob/master/docs/formatting.md#table-of-tokens
|
|
16835
16823
|
*/
|
|
16836
|
-
function
|
|
16837
|
-
format = format.replace(/y/g, "Y");
|
|
16838
|
-
format = format.replace(/d/g, "D");
|
|
16824
|
+
function convertDateFormatForLuxon(format) {
|
|
16839
16825
|
// "m" before "h" === month, "m" after "h" === minute
|
|
16840
16826
|
const indexH = format.indexOf("h");
|
|
16841
16827
|
if (indexH >= 0) {
|
|
@@ -16906,6 +16892,8 @@ function getBestTimeUnitForScale(labels, format, locale) {
|
|
|
16906
16892
|
return "year";
|
|
16907
16893
|
}
|
|
16908
16894
|
|
|
16895
|
+
// @ts-ignore
|
|
16896
|
+
const Chart = window.Chart;
|
|
16909
16897
|
class LineChart extends AbstractChart {
|
|
16910
16898
|
dataSets;
|
|
16911
16899
|
labelRange;
|
|
@@ -17035,7 +17023,7 @@ function canChartParseLabels(labelRange, getters) {
|
|
|
17035
17023
|
return canBeDateChart(labelRange, getters) || canBeLinearChart(labelRange, getters);
|
|
17036
17024
|
}
|
|
17037
17025
|
function getChartAxisType(chart, getters) {
|
|
17038
|
-
if (isDateChart(chart, getters)) {
|
|
17026
|
+
if (isDateChart(chart, getters) && isLuxonTimeAdapterInstalled()) {
|
|
17039
17027
|
return "time";
|
|
17040
17028
|
}
|
|
17041
17029
|
if (isLinearChart(chart, getters)) {
|
|
@@ -17058,7 +17046,7 @@ function canBeDateChart(labelRange, getters) {
|
|
|
17058
17046
|
col: labelRange.zone.left,
|
|
17059
17047
|
row: labelRange.zone.top,
|
|
17060
17048
|
}).format;
|
|
17061
|
-
return Boolean(labelFormat &&
|
|
17049
|
+
return Boolean(labelFormat && timeFormatLuxonCompatible.test(labelFormat));
|
|
17062
17050
|
}
|
|
17063
17051
|
function canBeLinearChart(labelRange, getters) {
|
|
17064
17052
|
if (!labelRange) {
|
|
@@ -17078,10 +17066,11 @@ function getLineConfiguration(chart, labels, localeFormat) {
|
|
|
17078
17066
|
const config = getDefaultChartJsRuntime(chart, labels, fontColor, localeFormat);
|
|
17079
17067
|
const legend = {
|
|
17080
17068
|
labels: {
|
|
17081
|
-
fontColor,
|
|
17069
|
+
color: fontColor,
|
|
17082
17070
|
generateLabels(chart) {
|
|
17071
|
+
// color the legend labels with the dataset color, without any transparency
|
|
17083
17072
|
const { data } = chart;
|
|
17084
|
-
const labels =
|
|
17073
|
+
const labels = Chart.defaults.plugins.legend.labels.generateLabels(chart);
|
|
17085
17074
|
for (const [index, label] of labels.entries()) {
|
|
17086
17075
|
label.fillStyle = data.datasets[index].borderColor;
|
|
17087
17076
|
}
|
|
@@ -17095,41 +17084,33 @@ function getLineConfiguration(chart, labels, localeFormat) {
|
|
|
17095
17084
|
else {
|
|
17096
17085
|
legend.position = chart.legendPosition;
|
|
17097
17086
|
}
|
|
17098
|
-
config.options.legend
|
|
17087
|
+
Object.assign(config.options.plugins.legend || {}, legend);
|
|
17099
17088
|
config.options.layout = {
|
|
17100
17089
|
padding: { left: 20, right: 20, top: chart.title ? 10 : 25, bottom: 10 },
|
|
17101
17090
|
};
|
|
17102
17091
|
config.options.scales = {
|
|
17103
|
-
|
|
17104
|
-
{
|
|
17105
|
-
|
|
17106
|
-
|
|
17107
|
-
maxRotation: 60,
|
|
17108
|
-
minRotation: 15,
|
|
17109
|
-
padding: 5,
|
|
17110
|
-
labelOffset: 2,
|
|
17111
|
-
fontColor,
|
|
17112
|
-
},
|
|
17092
|
+
x: {
|
|
17093
|
+
ticks: {
|
|
17094
|
+
padding: 5,
|
|
17095
|
+
color: fontColor,
|
|
17113
17096
|
},
|
|
17114
|
-
|
|
17115
|
-
|
|
17116
|
-
|
|
17117
|
-
|
|
17118
|
-
|
|
17119
|
-
|
|
17120
|
-
|
|
17121
|
-
|
|
17122
|
-
|
|
17123
|
-
|
|
17124
|
-
? formatValue(value, localeFormat)
|
|
17125
|
-
: value?.toLocaleString() || value;
|
|
17126
|
-
},
|
|
17097
|
+
},
|
|
17098
|
+
y: {
|
|
17099
|
+
position: chart.verticalAxisPosition,
|
|
17100
|
+
beginAtZero: true,
|
|
17101
|
+
ticks: {
|
|
17102
|
+
color: fontColor,
|
|
17103
|
+
callback: (value) => {
|
|
17104
|
+
return localeFormat.format
|
|
17105
|
+
? formatValue(value, localeFormat)
|
|
17106
|
+
: value?.toLocaleString() || value;
|
|
17127
17107
|
},
|
|
17128
17108
|
},
|
|
17129
|
-
|
|
17109
|
+
},
|
|
17130
17110
|
};
|
|
17131
|
-
if (chart.stacked) {
|
|
17132
|
-
|
|
17111
|
+
if (chart.stacked && config.options?.scales?.y) {
|
|
17112
|
+
// @ts-ignore chart.js type is wrong
|
|
17113
|
+
config.options.scales.y.stacked = true;
|
|
17133
17114
|
}
|
|
17134
17115
|
return config;
|
|
17135
17116
|
}
|
|
@@ -17156,15 +17137,18 @@ function createLineChartRuntime(chart, getters) {
|
|
|
17156
17137
|
const config = getLineConfiguration(chart, labels, localeFormat);
|
|
17157
17138
|
const labelFormat = getChartLabelFormat(getters, chart.labelRange);
|
|
17158
17139
|
if (axisType === "time") {
|
|
17159
|
-
|
|
17160
|
-
|
|
17161
|
-
|
|
17140
|
+
const axis = {
|
|
17141
|
+
type: "time",
|
|
17142
|
+
time: getChartTimeOptions(labels, labelFormat, locale),
|
|
17143
|
+
};
|
|
17144
|
+
Object.assign(config.options.scales.x, axis);
|
|
17145
|
+
config.options.scales.x.ticks.maxTicksLimit = 15;
|
|
17162
17146
|
}
|
|
17163
17147
|
else if (axisType === "linear") {
|
|
17164
|
-
config.options.scales.
|
|
17165
|
-
config.options.scales.
|
|
17166
|
-
config.options.
|
|
17167
|
-
return formatValue(tooltipItem[0]?.
|
|
17148
|
+
config.options.scales.x.type = "linear";
|
|
17149
|
+
config.options.scales.x.ticks.callback = (value) => formatValue(value, { format: labelFormat, locale });
|
|
17150
|
+
config.options.plugins.tooltip.callbacks.title = (tooltipItem) => {
|
|
17151
|
+
return formatValue(tooltipItem[0]?.label || "", localeFormat);
|
|
17168
17152
|
};
|
|
17169
17153
|
}
|
|
17170
17154
|
const colors = new ChartColors();
|
|
@@ -17182,7 +17166,7 @@ function createLineChartRuntime(chart, getters) {
|
|
|
17182
17166
|
const dataset = {
|
|
17183
17167
|
label,
|
|
17184
17168
|
data,
|
|
17185
|
-
|
|
17169
|
+
tension: 0,
|
|
17186
17170
|
borderColor: color,
|
|
17187
17171
|
backgroundColor,
|
|
17188
17172
|
pointBackgroundColor: color,
|
|
@@ -17191,6 +17175,22 @@ function createLineChartRuntime(chart, getters) {
|
|
|
17191
17175
|
config.data.datasets.push(dataset);
|
|
17192
17176
|
}
|
|
17193
17177
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
17178
|
+
}
|
|
17179
|
+
let missingTimeAdapterAlreadyWarned = false;
|
|
17180
|
+
function isLuxonTimeAdapterInstalled() {
|
|
17181
|
+
// @ts-ignore
|
|
17182
|
+
if (!window.Chart) {
|
|
17183
|
+
return false;
|
|
17184
|
+
}
|
|
17185
|
+
// @ts-ignore
|
|
17186
|
+
const adapter = new window.Chart._adapters._date({});
|
|
17187
|
+
// @ts-ignore
|
|
17188
|
+
const isInstalled = adapter._id === "luxon";
|
|
17189
|
+
if (!isInstalled && !missingTimeAdapterAlreadyWarned) {
|
|
17190
|
+
missingTimeAdapterAlreadyWarned = true;
|
|
17191
|
+
console.warn("'chartjs-adapter-luxon' time adapter is not installed. Time scale axes are disabled.");
|
|
17192
|
+
}
|
|
17193
|
+
return isInstalled;
|
|
17194
17194
|
}
|
|
17195
17195
|
|
|
17196
17196
|
class PieChart extends AbstractChart {
|
|
@@ -17295,7 +17295,7 @@ function getPieConfiguration(chart, labels, localeFormat) {
|
|
|
17295
17295
|
const fontColor = chartFontColor(chart.background);
|
|
17296
17296
|
const config = getDefaultChartJsRuntime(chart, labels, fontColor, localeFormat);
|
|
17297
17297
|
const legend = {
|
|
17298
|
-
labels: { fontColor },
|
|
17298
|
+
labels: { color: fontColor },
|
|
17299
17299
|
};
|
|
17300
17300
|
if ((!chart.labelRange && chart.dataSets.length === 1) || chart.legendPosition === "none") {
|
|
17301
17301
|
legend.display = false;
|
|
@@ -17303,12 +17303,12 @@ function getPieConfiguration(chart, labels, localeFormat) {
|
|
|
17303
17303
|
else {
|
|
17304
17304
|
legend.position = chart.legendPosition;
|
|
17305
17305
|
}
|
|
17306
|
-
config.options.legend
|
|
17306
|
+
Object.assign(config.options.plugins.legend || {}, legend);
|
|
17307
17307
|
config.options.layout = {
|
|
17308
17308
|
padding: { left: 20, right: 20, top: chart.title ? 10 : 25, bottom: 10 },
|
|
17309
17309
|
};
|
|
17310
|
-
config.options.
|
|
17311
|
-
return
|
|
17310
|
+
config.options.plugins.tooltip.callbacks.title = function (tooltipItems) {
|
|
17311
|
+
return tooltipItems[0].dataset.label;
|
|
17312
17312
|
};
|
|
17313
17313
|
return config;
|
|
17314
17314
|
}
|
|
@@ -18072,6 +18072,278 @@ function getSmartChartDefinition(zone, getters) {
|
|
|
18072
18072
|
};
|
|
18073
18073
|
}
|
|
18074
18074
|
|
|
18075
|
+
// @ts-ignore
|
|
18076
|
+
if (window.Chart) {
|
|
18077
|
+
// @ts-ignore
|
|
18078
|
+
const DoughnutController = window.Chart?.DoughnutController;
|
|
18079
|
+
/**
|
|
18080
|
+
* Example :
|
|
18081
|
+
* const chart = new Chart(ctx, {
|
|
18082
|
+
* type: "gauge",
|
|
18083
|
+
* data: {
|
|
18084
|
+
* datasets: [
|
|
18085
|
+
* {
|
|
18086
|
+
* borderWidth: 5,
|
|
18087
|
+
* data: [10, 20, 10],
|
|
18088
|
+
* value: 23,
|
|
18089
|
+
* backgroundColor: [
|
|
18090
|
+
* "#dc3545", //red
|
|
18091
|
+
* "#ffc107", //orange
|
|
18092
|
+
* "#28a745", //green
|
|
18093
|
+
* ],
|
|
18094
|
+
* },
|
|
18095
|
+
* ],
|
|
18096
|
+
* },
|
|
18097
|
+
* options: {
|
|
18098
|
+
* plugins: {
|
|
18099
|
+
* title: {
|
|
18100
|
+
* display: true,
|
|
18101
|
+
* text: "Custom Chart Title",
|
|
18102
|
+
* padding: {
|
|
18103
|
+
* top: 10,
|
|
18104
|
+
* bottom: 30,
|
|
18105
|
+
* },
|
|
18106
|
+
* font : {
|
|
18107
|
+
* size : 30
|
|
18108
|
+
* }
|
|
18109
|
+
* },
|
|
18110
|
+
* },
|
|
18111
|
+
* valueLabel: {
|
|
18112
|
+
* display: true,
|
|
18113
|
+
* format: (value) => {
|
|
18114
|
+
* return value.toFixed(2) + "%";
|
|
18115
|
+
* },
|
|
18116
|
+
* font : {
|
|
18117
|
+
* size : 35,
|
|
18118
|
+
* family : "Arial",
|
|
18119
|
+
* color : "#FC0",
|
|
18120
|
+
* },
|
|
18121
|
+
* backgroundColor : "#ccc",
|
|
18122
|
+
* borderColor : "#090",
|
|
18123
|
+
* borderRadius : 50
|
|
18124
|
+
* },
|
|
18125
|
+
* needle: {
|
|
18126
|
+
* display: true,
|
|
18127
|
+
* width: 50,
|
|
18128
|
+
* color: "#DC5",
|
|
18129
|
+
* backgroundColor : "#ccc",
|
|
18130
|
+
* },
|
|
18131
|
+
* },
|
|
18132
|
+
* });
|
|
18133
|
+
*/
|
|
18134
|
+
class GaugeController extends DoughnutController {
|
|
18135
|
+
static id = "gauge";
|
|
18136
|
+
static defaults = {
|
|
18137
|
+
...DoughnutController.defaults,
|
|
18138
|
+
circumference: 180,
|
|
18139
|
+
rotation: 270,
|
|
18140
|
+
};
|
|
18141
|
+
static overrides = {
|
|
18142
|
+
aspectRatio: 2,
|
|
18143
|
+
plugins: {
|
|
18144
|
+
legend: {
|
|
18145
|
+
display: false,
|
|
18146
|
+
},
|
|
18147
|
+
tooltip: {
|
|
18148
|
+
enabled: false,
|
|
18149
|
+
},
|
|
18150
|
+
},
|
|
18151
|
+
};
|
|
18152
|
+
get chartHeight() {
|
|
18153
|
+
return Math.abs(this.chart.chartArea.top - this.chart.chartArea.bottom);
|
|
18154
|
+
}
|
|
18155
|
+
get chartWidth() {
|
|
18156
|
+
return Math.abs(this.chart.chartArea.left - this.chart.chartArea.right);
|
|
18157
|
+
}
|
|
18158
|
+
get needleOptions() {
|
|
18159
|
+
const { config } = this.chart;
|
|
18160
|
+
const options = config.options;
|
|
18161
|
+
// @ts-ignore
|
|
18162
|
+
return options?.needle || {};
|
|
18163
|
+
}
|
|
18164
|
+
get valueLabelOptions() {
|
|
18165
|
+
const { config } = this.chart;
|
|
18166
|
+
const options = config.options;
|
|
18167
|
+
// @ts-ignore
|
|
18168
|
+
return options?.valueLabel || {};
|
|
18169
|
+
}
|
|
18170
|
+
get minValue() {
|
|
18171
|
+
const dataset = this.getDataset();
|
|
18172
|
+
// @ts-ignore
|
|
18173
|
+
return dataset.minValue || 0;
|
|
18174
|
+
}
|
|
18175
|
+
getValueAngleInPercent(value) {
|
|
18176
|
+
const dataset = this.getDataset();
|
|
18177
|
+
const data = dataset.data || [];
|
|
18178
|
+
const max = Math.max(...data);
|
|
18179
|
+
const min = this.minValue;
|
|
18180
|
+
return (value - min) / (max - min);
|
|
18181
|
+
}
|
|
18182
|
+
drawValueLabel(params) {
|
|
18183
|
+
const { ctx } = this.chart;
|
|
18184
|
+
if (this.valueLabelOptions.display === false) {
|
|
18185
|
+
return;
|
|
18186
|
+
}
|
|
18187
|
+
// draw background rectangle
|
|
18188
|
+
ctx.save();
|
|
18189
|
+
ctx.beginPath();
|
|
18190
|
+
ctx.fillStyle = params.valueLabel.backgroundColor;
|
|
18191
|
+
ctx.strokeStyle = params.valueLabel.borderColor;
|
|
18192
|
+
ctx.roundRect(params.valueLabel.rect.x, params.valueLabel.rect.y, params.valueLabel.rect.width, params.valueLabel.rect.height, params.valueLabel.borderRadius);
|
|
18193
|
+
ctx.stroke();
|
|
18194
|
+
ctx.fill();
|
|
18195
|
+
// draw value text
|
|
18196
|
+
ctx.textAlign = "center";
|
|
18197
|
+
ctx.textBaseline = "middle";
|
|
18198
|
+
ctx.font = params.valueLabel.font;
|
|
18199
|
+
ctx.fillStyle = params.valueLabel.textColor;
|
|
18200
|
+
ctx.fillText(params.valueLabel.valueText, params.valueLabel.textPosition.x, params.valueLabel.textPosition.y);
|
|
18201
|
+
ctx.restore();
|
|
18202
|
+
}
|
|
18203
|
+
drawNeedle(params) {
|
|
18204
|
+
const { ctx } = this.chart;
|
|
18205
|
+
if (this.needleOptions.display === false) {
|
|
18206
|
+
return;
|
|
18207
|
+
}
|
|
18208
|
+
// translate & rotate next paths
|
|
18209
|
+
ctx.save();
|
|
18210
|
+
ctx.translate(params.needle.position.x, params.needle.position.y);
|
|
18211
|
+
ctx.rotate(-Math.PI / 2 + Math.PI * params.needle.percent);
|
|
18212
|
+
// draw circle
|
|
18213
|
+
ctx.beginPath();
|
|
18214
|
+
ctx.fillStyle = params.needle.backgroundColor;
|
|
18215
|
+
ctx.strokeStyle = params.needle.borderColor;
|
|
18216
|
+
ctx.ellipse(0, 0, params.needle.width / 2, params.needle.width / 2, 0, 0, 2 * Math.PI);
|
|
18217
|
+
ctx.fill();
|
|
18218
|
+
ctx.stroke();
|
|
18219
|
+
ctx.closePath();
|
|
18220
|
+
// draw needle
|
|
18221
|
+
ctx.fillStyle = params.needle.backgroundColor;
|
|
18222
|
+
ctx.strokeStyle = params.needle.borderColor;
|
|
18223
|
+
ctx.beginPath();
|
|
18224
|
+
ctx.moveTo(-params.needle.width / 2, 0);
|
|
18225
|
+
ctx.lineTo(0, -params.needle.height + 10);
|
|
18226
|
+
ctx.lineTo(+params.needle.width / 2, 0);
|
|
18227
|
+
ctx.closePath();
|
|
18228
|
+
ctx.fill();
|
|
18229
|
+
ctx.stroke();
|
|
18230
|
+
ctx.restore();
|
|
18231
|
+
}
|
|
18232
|
+
computeRenderingParams() {
|
|
18233
|
+
const { ctx, config } = this.chart;
|
|
18234
|
+
const options = config.options;
|
|
18235
|
+
options.layout = options.layout || {};
|
|
18236
|
+
options.layout.padding = options.layout.padding || {};
|
|
18237
|
+
const formatter = this.valueLabelOptions.formatter;
|
|
18238
|
+
const fmt = typeof formatter === "function" ? formatter : (value) => value;
|
|
18239
|
+
const dataset = this.getDataset();
|
|
18240
|
+
// @ts-ignore value is a custom property for gauge charts
|
|
18241
|
+
const value = dataset.value || 0;
|
|
18242
|
+
const valueText = fmt(value).toString();
|
|
18243
|
+
const percent = this.getValueAngleInPercent(value);
|
|
18244
|
+
const fontFamily = this.valueLabelOptions.font?.family || "Arial";
|
|
18245
|
+
const optionsFontSize = this.valueLabelOptions.font?.size || 0;
|
|
18246
|
+
const fontSize = optionsFontSize >= 1 ? optionsFontSize : 30;
|
|
18247
|
+
const font = `${fontSize}px ${fontFamily}`;
|
|
18248
|
+
const padding = {
|
|
18249
|
+
right: 0,
|
|
18250
|
+
left: 0,
|
|
18251
|
+
top: 0,
|
|
18252
|
+
bottom: 0,
|
|
18253
|
+
...this.valueLabelOptions.padding,
|
|
18254
|
+
};
|
|
18255
|
+
padding.left = padding.left >= 0 ? padding.left : 10;
|
|
18256
|
+
padding.right = padding.right >= 0 ? padding.right : 10;
|
|
18257
|
+
padding.top = padding.top >= 0 ? padding.top : 10;
|
|
18258
|
+
padding.bottom = padding.bottom >= 0 ? padding.bottom : 10;
|
|
18259
|
+
const chartArea = this.chart.chartArea;
|
|
18260
|
+
const offsetX = this.offsetX || 0;
|
|
18261
|
+
const offsetY = this.offsetY || 0;
|
|
18262
|
+
const centerX = (chartArea.left + chartArea.right) / 2;
|
|
18263
|
+
const centerY = (chartArea.top + chartArea.bottom) / 2;
|
|
18264
|
+
const center = {
|
|
18265
|
+
x: centerX + offsetX,
|
|
18266
|
+
y: centerY + offsetY,
|
|
18267
|
+
};
|
|
18268
|
+
const textPosition = {
|
|
18269
|
+
x: center.x,
|
|
18270
|
+
y: center.y,
|
|
18271
|
+
};
|
|
18272
|
+
ctx.save();
|
|
18273
|
+
ctx.font = font;
|
|
18274
|
+
const metrics = ctx.measureText(valueText);
|
|
18275
|
+
ctx.restore();
|
|
18276
|
+
const textHeight = metrics.fontBoundingBoxAscent - metrics.fontBoundingBoxDescent;
|
|
18277
|
+
return {
|
|
18278
|
+
needle: {
|
|
18279
|
+
borderColor: this.needleOptions.borderColor || "#000",
|
|
18280
|
+
backgroundColor: this.needleOptions.backgroundColor || "#000",
|
|
18281
|
+
width: this.needleOptions.width || 10,
|
|
18282
|
+
height: Math.min(this.chartHeight, this.chartWidth / 2),
|
|
18283
|
+
position: {
|
|
18284
|
+
x: textPosition.x,
|
|
18285
|
+
y: textPosition.y,
|
|
18286
|
+
},
|
|
18287
|
+
percent,
|
|
18288
|
+
},
|
|
18289
|
+
valueLabel: {
|
|
18290
|
+
textColor: this.valueLabelOptions.font?.color || "#FFF",
|
|
18291
|
+
backgroundColor: this.valueLabelOptions.backgroundColor || "#000",
|
|
18292
|
+
borderColor: this.valueLabelOptions.borderColor || "#000",
|
|
18293
|
+
borderRadius: this.valueLabelOptions.borderRadius || 10,
|
|
18294
|
+
rect: {
|
|
18295
|
+
x: center.x - metrics.width / 2 - padding.left,
|
|
18296
|
+
y: center.y + textHeight / 2 + padding.top,
|
|
18297
|
+
width: metrics.width + padding.left + padding.right,
|
|
18298
|
+
height: -(textHeight + 6 + padding.top + padding.bottom),
|
|
18299
|
+
},
|
|
18300
|
+
valueText,
|
|
18301
|
+
textPosition,
|
|
18302
|
+
textHeight,
|
|
18303
|
+
font,
|
|
18304
|
+
},
|
|
18305
|
+
};
|
|
18306
|
+
}
|
|
18307
|
+
draw() {
|
|
18308
|
+
super.draw();
|
|
18309
|
+
const params = this.computeRenderingParams();
|
|
18310
|
+
this.drawNeedle(params);
|
|
18311
|
+
this.drawValueLabel(params);
|
|
18312
|
+
}
|
|
18313
|
+
updateElements(elements, start, count, mode) {
|
|
18314
|
+
super.updateElements(elements, start, count, mode);
|
|
18315
|
+
const dataset = this.getDataset();
|
|
18316
|
+
const data = this.getDataset().data;
|
|
18317
|
+
// @ts-ignore
|
|
18318
|
+
const minValue = dataset.minValue;
|
|
18319
|
+
// @ts-ignore
|
|
18320
|
+
const rotation = this.chart.options.rotation || 0;
|
|
18321
|
+
// @ts-ignore
|
|
18322
|
+
const circumference = this.chart.options.circumference || 0;
|
|
18323
|
+
for (let arcIndex = 0; arcIndex < data.length; arcIndex++) {
|
|
18324
|
+
const previousValue = arcIndex === 0 ? minValue : data[arcIndex - 1];
|
|
18325
|
+
const startAngleInPercent = this.getValueAngleInPercent(previousValue);
|
|
18326
|
+
const endAngleInPercent = this.getValueAngleInPercent(data[arcIndex]);
|
|
18327
|
+
const startAngle = degreesToRadians(rotation + circumference * startAngleInPercent) - Math.PI / 2;
|
|
18328
|
+
const endAngle = degreesToRadians(rotation + circumference * endAngleInPercent) - Math.PI / 2;
|
|
18329
|
+
const arcCircumference = endAngle - startAngle;
|
|
18330
|
+
const arc = elements[arcIndex];
|
|
18331
|
+
const propertiesUpdates = {
|
|
18332
|
+
startAngle,
|
|
18333
|
+
endAngle,
|
|
18334
|
+
circumference: arcCircumference,
|
|
18335
|
+
};
|
|
18336
|
+
this.updateElement(arc, arcIndex, propertiesUpdates, mode);
|
|
18337
|
+
}
|
|
18338
|
+
}
|
|
18339
|
+
}
|
|
18340
|
+
function degreesToRadians(degrees) {
|
|
18341
|
+
return (degrees * Math.PI) / 180;
|
|
18342
|
+
}
|
|
18343
|
+
// @ts-ignore
|
|
18344
|
+
window.Chart.register(GaugeController);
|
|
18345
|
+
}
|
|
18346
|
+
|
|
18075
18347
|
//------------------------------------------------------------------------------
|
|
18076
18348
|
// Helpers
|
|
18077
18349
|
//------------------------------------------------------------------------------
|
|
@@ -36421,7 +36693,8 @@ class EvaluationChartPlugin extends UIPlugin {
|
|
|
36421
36693
|
if (!chart) {
|
|
36422
36694
|
throw new Error(`No chart for the given id: ${figureId}`);
|
|
36423
36695
|
}
|
|
36424
|
-
|
|
36696
|
+
const runtime = this.createRuntimeChart(chart);
|
|
36697
|
+
this.history.update("charts", figureId, runtime);
|
|
36425
36698
|
}
|
|
36426
36699
|
return this.charts[figureId];
|
|
36427
36700
|
}
|
|
@@ -49509,7 +49782,14 @@ function addCellWiseConditionalFormatting(dxfs // cell-wise CF
|
|
|
49509
49782
|
`;
|
|
49510
49783
|
}
|
|
49511
49784
|
|
|
49512
|
-
const
|
|
49785
|
+
const TABLE_DEFAULT_ATTRS = [
|
|
49786
|
+
["name", "TableStyleLight8"],
|
|
49787
|
+
["showFirstColumn", "0"],
|
|
49788
|
+
["showLastColumn", "0"],
|
|
49789
|
+
["showRowStripes", "0"],
|
|
49790
|
+
["showColumnStripes", "0"],
|
|
49791
|
+
];
|
|
49792
|
+
const TABLE_DEFAULT_STYLE = escapeXml /*xml*/ `<tableStyleInfo ${formatAttributes(TABLE_DEFAULT_ATTRS)}/>`;
|
|
49513
49793
|
function createTable(table, tableId, sheetData) {
|
|
49514
49794
|
const tableAttributes = [
|
|
49515
49795
|
["id", tableId],
|
|
@@ -50626,6 +50906,6 @@ exports.setTranslationMethod = setTranslationMethod;
|
|
|
50626
50906
|
exports.tokenize = tokenize;
|
|
50627
50907
|
|
|
50628
50908
|
|
|
50629
|
-
__info__.version = '16.5.0-alpha.
|
|
50630
|
-
__info__.date = '2023-08-
|
|
50631
|
-
__info__.hash = '
|
|
50909
|
+
__info__.version = '16.5.0-alpha.4';
|
|
50910
|
+
__info__.date = '2023-08-10T09:39:12.478Z';
|
|
50911
|
+
__info__.hash = 'c8db018';
|