@odoo/o-spreadsheet 18.0.1 → 18.0.3
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 +227 -147
- package/dist/o-spreadsheet.d.ts +54 -12
- package/dist/o-spreadsheet.esm.js +227 -147
- package/dist/o-spreadsheet.iife.js +227 -147
- package/dist/o-spreadsheet.iife.min.js +341 -340
- package/dist/o_spreadsheet.xml +38 -32
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 18.0.
|
|
6
|
-
* @date 2024-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.0.3
|
|
6
|
+
* @date 2024-11-08T12:17:49.992Z
|
|
7
|
+
* @hash 5fa5fbb
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -376,7 +376,7 @@ const PIVOT_TABLE_CONFIG = {
|
|
|
376
376
|
bandedRows: true,
|
|
377
377
|
bandedColumns: false,
|
|
378
378
|
styleId: "TableStyleMedium5",
|
|
379
|
-
automaticAutofill:
|
|
379
|
+
automaticAutofill: false,
|
|
380
380
|
};
|
|
381
381
|
const DEFAULT_CURRENCY = {
|
|
382
382
|
symbol: "$",
|
|
@@ -9346,14 +9346,19 @@ function interpolateData(config, values, labels, newLabels) {
|
|
|
9346
9346
|
if (values.length < 2 || labels.length < 2 || newLabels.length === 0) {
|
|
9347
9347
|
return [];
|
|
9348
9348
|
}
|
|
9349
|
+
const labelMin = Math.min(...labels);
|
|
9350
|
+
const labelMax = Math.max(...labels);
|
|
9351
|
+
const labelRange = labelMax - labelMin;
|
|
9352
|
+
const normalizedLabels = labels.map((v) => (v - labelMin) / labelRange);
|
|
9353
|
+
const normalizedNewLabels = newLabels.map((v) => (v - labelMin) / labelRange);
|
|
9349
9354
|
switch (config.type) {
|
|
9350
9355
|
case "polynomial": {
|
|
9351
9356
|
const order = config.order ?? 2;
|
|
9352
9357
|
if (order === 1) {
|
|
9353
|
-
return predictLinearValues([values], [
|
|
9358
|
+
return predictLinearValues([values], [normalizedLabels], [normalizedNewLabels], true)[0];
|
|
9354
9359
|
}
|
|
9355
|
-
const coeffs = polynomialRegression(values,
|
|
9356
|
-
return
|
|
9360
|
+
const coeffs = polynomialRegression(values, normalizedLabels, order, true).flat();
|
|
9361
|
+
return normalizedNewLabels.map((v) => evaluatePolynomial(coeffs, v, order));
|
|
9357
9362
|
}
|
|
9358
9363
|
case "exponential": {
|
|
9359
9364
|
const positiveLogValues = [];
|
|
@@ -9361,16 +9366,16 @@ function interpolateData(config, values, labels, newLabels) {
|
|
|
9361
9366
|
for (let i = 0; i < values.length; i++) {
|
|
9362
9367
|
if (values[i] > 0) {
|
|
9363
9368
|
positiveLogValues.push(Math.log(values[i]));
|
|
9364
|
-
filteredLabels.push(
|
|
9369
|
+
filteredLabels.push(normalizedLabels[i]);
|
|
9365
9370
|
}
|
|
9366
9371
|
}
|
|
9367
9372
|
if (!filteredLabels.length) {
|
|
9368
9373
|
return [];
|
|
9369
9374
|
}
|
|
9370
|
-
return expM(predictLinearValues([positiveLogValues], [filteredLabels], [
|
|
9375
|
+
return expM(predictLinearValues([positiveLogValues], [filteredLabels], [normalizedNewLabels], true))[0];
|
|
9371
9376
|
}
|
|
9372
9377
|
case "logarithmic": {
|
|
9373
|
-
return predictLinearValues([values], logM([
|
|
9378
|
+
return predictLinearValues([values], logM([normalizedLabels]), logM([normalizedNewLabels]), true)[0];
|
|
9374
9379
|
}
|
|
9375
9380
|
default:
|
|
9376
9381
|
return [];
|
|
@@ -9411,70 +9416,118 @@ const chartShowValuesPlugin = {
|
|
|
9411
9416
|
ctx.save();
|
|
9412
9417
|
ctx.textAlign = "center";
|
|
9413
9418
|
ctx.textBaseline = "middle";
|
|
9414
|
-
ctx.
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9421
|
-
|
|
9422
|
-
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
const midRadius = (innerRadius + outerRadius) / 2;
|
|
9428
|
-
const x = bar.x + midRadius * Math.cos(midAngle);
|
|
9429
|
-
const y = bar.y + midRadius * Math.sin(midAngle) + 7;
|
|
9430
|
-
ctx.fillStyle = chartFontColor(bar.options.backgroundColor);
|
|
9431
|
-
ctx.strokeStyle = chartFontColor(ctx.fillStyle);
|
|
9432
|
-
const value = options.callback(dataset._parsed[i]);
|
|
9433
|
-
ctx.strokeText(value, x, y);
|
|
9434
|
-
ctx.fillText(value, x, y);
|
|
9435
|
-
}
|
|
9436
|
-
break;
|
|
9437
|
-
}
|
|
9438
|
-
case "bar":
|
|
9439
|
-
case "line": {
|
|
9440
|
-
const yOffset = dataset.type === "bar" && !options.horizontal ? 0 : 3;
|
|
9441
|
-
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
9442
|
-
const point = dataset.data[i];
|
|
9443
|
-
const value = options.horizontal ? dataset._parsed[i].x : dataset._parsed[i].y;
|
|
9444
|
-
const displayedValue = options.callback(value - 0);
|
|
9445
|
-
let xPosition = 0, yPosition = 0;
|
|
9446
|
-
if (options.horizontal) {
|
|
9447
|
-
yPosition = point.y;
|
|
9448
|
-
if (value < 0) {
|
|
9449
|
-
ctx.textAlign = "right";
|
|
9450
|
-
xPosition = point.x - yOffset;
|
|
9451
|
-
}
|
|
9452
|
-
else {
|
|
9453
|
-
ctx.textAlign = "left";
|
|
9454
|
-
xPosition = point.x + yOffset;
|
|
9455
|
-
}
|
|
9456
|
-
}
|
|
9457
|
-
else {
|
|
9458
|
-
xPosition = point.x;
|
|
9459
|
-
if (value < 0) {
|
|
9460
|
-
ctx.textBaseline = "top";
|
|
9461
|
-
yPosition = point.y + yOffset;
|
|
9462
|
-
}
|
|
9463
|
-
else {
|
|
9464
|
-
ctx.textBaseline = "bottom";
|
|
9465
|
-
yPosition = point.y - yOffset;
|
|
9466
|
-
}
|
|
9467
|
-
}
|
|
9468
|
-
ctx.strokeText(displayedValue, xPosition, yPosition);
|
|
9469
|
-
ctx.fillText(displayedValue, xPosition, yPosition);
|
|
9470
|
-
}
|
|
9471
|
-
break;
|
|
9472
|
-
}
|
|
9473
|
-
}
|
|
9474
|
-
});
|
|
9419
|
+
ctx.miterLimit = 1; // Avoid sharp artifacts on strokeText
|
|
9420
|
+
switch (chart.config.type) {
|
|
9421
|
+
case "pie":
|
|
9422
|
+
case "doughnut":
|
|
9423
|
+
drawPieChartValues(chart, options, ctx);
|
|
9424
|
+
break;
|
|
9425
|
+
case "bar":
|
|
9426
|
+
case "line":
|
|
9427
|
+
options.horizontal
|
|
9428
|
+
? drawHorizontalBarChartValues(chart, options, ctx)
|
|
9429
|
+
: drawLineOrBarChartValues(chart, options, ctx);
|
|
9430
|
+
break;
|
|
9431
|
+
}
|
|
9475
9432
|
ctx.restore();
|
|
9476
9433
|
},
|
|
9477
9434
|
};
|
|
9435
|
+
function drawTextWithBackground(text, x, y, ctx) {
|
|
9436
|
+
ctx.lineWidth = 3; // Stroke the text with a big lineWidth width to have some kind of background
|
|
9437
|
+
ctx.strokeText(text, x, y);
|
|
9438
|
+
ctx.lineWidth = 1;
|
|
9439
|
+
ctx.fillText(text, x, y);
|
|
9440
|
+
}
|
|
9441
|
+
function drawLineOrBarChartValues(chart, options, ctx) {
|
|
9442
|
+
const yMax = chart.chartArea.bottom;
|
|
9443
|
+
const yMin = chart.chartArea.top;
|
|
9444
|
+
const textsPositions = {};
|
|
9445
|
+
for (const dataset of chart._metasets) {
|
|
9446
|
+
if (dataset.xAxisID === TREND_LINE_XAXIS_ID) {
|
|
9447
|
+
return; // ignore trend lines
|
|
9448
|
+
}
|
|
9449
|
+
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
9450
|
+
const value = dataset._parsed[i].y;
|
|
9451
|
+
const point = dataset.data[i];
|
|
9452
|
+
const xPosition = point.x;
|
|
9453
|
+
let yPosition = 0;
|
|
9454
|
+
if (chart.config.type === "line") {
|
|
9455
|
+
yPosition = point.y - 10;
|
|
9456
|
+
}
|
|
9457
|
+
else {
|
|
9458
|
+
yPosition = value < 0 ? point.y - point.height / 2 : point.y + point.height / 2;
|
|
9459
|
+
}
|
|
9460
|
+
yPosition = Math.min(yPosition, yMax);
|
|
9461
|
+
yPosition = Math.max(yPosition, yMin);
|
|
9462
|
+
// Avoid overlapping texts with same X
|
|
9463
|
+
if (!textsPositions[xPosition]) {
|
|
9464
|
+
textsPositions[xPosition] = [];
|
|
9465
|
+
}
|
|
9466
|
+
for (const otherPosition of textsPositions[xPosition] || []) {
|
|
9467
|
+
if (Math.abs(otherPosition - yPosition) < 13) {
|
|
9468
|
+
yPosition = otherPosition - 13;
|
|
9469
|
+
}
|
|
9470
|
+
}
|
|
9471
|
+
textsPositions[xPosition].push(yPosition);
|
|
9472
|
+
ctx.fillStyle = point.options.backgroundColor;
|
|
9473
|
+
ctx.strokeStyle = options.background || "#ffffff";
|
|
9474
|
+
drawTextWithBackground(options.callback(value - 0), xPosition, yPosition, ctx);
|
|
9475
|
+
}
|
|
9476
|
+
}
|
|
9477
|
+
}
|
|
9478
|
+
function drawHorizontalBarChartValues(chart, options, ctx) {
|
|
9479
|
+
const xMax = chart.chartArea.right;
|
|
9480
|
+
const xMin = chart.chartArea.left;
|
|
9481
|
+
const textsPositions = {};
|
|
9482
|
+
for (const dataset of chart._metasets) {
|
|
9483
|
+
if (dataset.xAxisID === TREND_LINE_XAXIS_ID) {
|
|
9484
|
+
return; // ignore trend lines
|
|
9485
|
+
}
|
|
9486
|
+
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
9487
|
+
const value = dataset._parsed[i].x;
|
|
9488
|
+
const displayValue = options.callback(value - 0);
|
|
9489
|
+
const point = dataset.data[i];
|
|
9490
|
+
const yPosition = point.y;
|
|
9491
|
+
let xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
|
|
9492
|
+
xPosition = Math.min(xPosition, xMax);
|
|
9493
|
+
xPosition = Math.max(xPosition, xMin);
|
|
9494
|
+
// Avoid overlapping texts with same Y
|
|
9495
|
+
if (!textsPositions[yPosition]) {
|
|
9496
|
+
textsPositions[yPosition] = [];
|
|
9497
|
+
}
|
|
9498
|
+
const textWidth = computeTextWidth(ctx, displayValue, { fontSize: 12 }, "px");
|
|
9499
|
+
for (const otherPosition of textsPositions[yPosition]) {
|
|
9500
|
+
if (Math.abs(otherPosition - xPosition) < textWidth) {
|
|
9501
|
+
xPosition = otherPosition + textWidth + 3;
|
|
9502
|
+
}
|
|
9503
|
+
}
|
|
9504
|
+
textsPositions[yPosition].push(xPosition);
|
|
9505
|
+
ctx.fillStyle = point.options.backgroundColor;
|
|
9506
|
+
ctx.strokeStyle = options.background || "#ffffff";
|
|
9507
|
+
drawTextWithBackground(displayValue, xPosition, yPosition, ctx);
|
|
9508
|
+
}
|
|
9509
|
+
}
|
|
9510
|
+
}
|
|
9511
|
+
function drawPieChartValues(chart, options, ctx) {
|
|
9512
|
+
for (const dataset of chart._metasets) {
|
|
9513
|
+
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
9514
|
+
const value = Number(dataset._parsed[i]);
|
|
9515
|
+
if (isNaN(value) || value === 0) {
|
|
9516
|
+
continue;
|
|
9517
|
+
}
|
|
9518
|
+
const bar = dataset.data[i];
|
|
9519
|
+
const { startAngle, endAngle, innerRadius, outerRadius } = bar;
|
|
9520
|
+
const midAngle = (startAngle + endAngle) / 2;
|
|
9521
|
+
const midRadius = (innerRadius + outerRadius) / 2;
|
|
9522
|
+
const x = bar.x + midRadius * Math.cos(midAngle);
|
|
9523
|
+
const y = bar.y + midRadius * Math.sin(midAngle) + 7;
|
|
9524
|
+
ctx.fillStyle = chartFontColor(options.background);
|
|
9525
|
+
ctx.strokeStyle = options.background || "#ffffff";
|
|
9526
|
+
const displayValue = options.callback(value);
|
|
9527
|
+
drawTextWithBackground(displayValue, x, y, ctx);
|
|
9528
|
+
}
|
|
9529
|
+
}
|
|
9530
|
+
}
|
|
9478
9531
|
|
|
9479
9532
|
/** This is a chartJS plugin that will draw connector lines between the bars of a Waterfall chart */
|
|
9480
9533
|
const waterfallLinesPlugin = {
|
|
@@ -14550,7 +14603,7 @@ const FILTER = {
|
|
|
14550
14603
|
const result = [];
|
|
14551
14604
|
for (let i = 0; i < _array.length; i++) {
|
|
14552
14605
|
const row = _array[i];
|
|
14553
|
-
if (_conditions.every((c) => c[i])) {
|
|
14606
|
+
if (_conditions.every((c) => (typeof c[i] === "boolean" || typeof c[i] === "number") && c[i])) {
|
|
14554
14607
|
result.push(row);
|
|
14555
14608
|
}
|
|
14556
14609
|
}
|
|
@@ -16945,7 +16998,10 @@ function parseOperand(tokens) {
|
|
|
16945
16998
|
case "STRING":
|
|
16946
16999
|
return { type: "STRING", value: removeStringQuotes(current.value) };
|
|
16947
17000
|
case "INVALID_REFERENCE":
|
|
16948
|
-
|
|
17001
|
+
return {
|
|
17002
|
+
type: "REFERENCE",
|
|
17003
|
+
value: CellErrorType.InvalidReference,
|
|
17004
|
+
};
|
|
16949
17005
|
case "REFERENCE":
|
|
16950
17006
|
if (tokens[0]?.value === ":" && tokens[1]?.type === "REFERENCE") {
|
|
16951
17007
|
tokens.shift();
|
|
@@ -21737,9 +21793,13 @@ autoCompleteProviders.add("pivot_group_fields", {
|
|
|
21737
21793
|
const colFields = columns.map((groupBy) => groupBy.nameWithGranularity);
|
|
21738
21794
|
const rowFields = rows.map((groupBy) => groupBy.nameWithGranularity);
|
|
21739
21795
|
const proposals = [];
|
|
21740
|
-
|
|
21796
|
+
let previousGroupBy = ["ARG_SEPARATOR", "SPACE"].includes(tokenAtCursor.type)
|
|
21741
21797
|
? argGroupBys.at(-1)
|
|
21742
21798
|
: argGroupBys.at(-2);
|
|
21799
|
+
const isPositionalSupported = supportedPivotPositionalFormulaRegistry.get(pivot.type);
|
|
21800
|
+
if (isPositionalSupported && previousGroupBy?.startsWith("#")) {
|
|
21801
|
+
previousGroupBy = previousGroupBy.slice(1);
|
|
21802
|
+
}
|
|
21743
21803
|
if (previousGroupBy === undefined) {
|
|
21744
21804
|
proposals.push(colFields[0]);
|
|
21745
21805
|
proposals.push(rowFields[0]);
|
|
@@ -21761,7 +21821,7 @@ autoCompleteProviders.add("pivot_group_fields", {
|
|
|
21761
21821
|
return field ? makeFieldProposal(field, granularity) : undefined;
|
|
21762
21822
|
})
|
|
21763
21823
|
.concat(groupBys.map((groupBy) => {
|
|
21764
|
-
if (!
|
|
21824
|
+
if (!isPositionalSupported) {
|
|
21765
21825
|
return undefined;
|
|
21766
21826
|
}
|
|
21767
21827
|
const fieldName = groupBy.split(":")[0];
|
|
@@ -27457,7 +27517,7 @@ function load(data, verboseImport) {
|
|
|
27457
27517
|
if (!data) {
|
|
27458
27518
|
return createEmptyWorkbookData();
|
|
27459
27519
|
}
|
|
27460
|
-
console.
|
|
27520
|
+
console.debug("### Loading data ###");
|
|
27461
27521
|
const start = performance.now();
|
|
27462
27522
|
if (data["[Content_Types].xml"]) {
|
|
27463
27523
|
const reader = new XlsxReader(data);
|
|
@@ -27471,13 +27531,13 @@ function load(data, verboseImport) {
|
|
|
27471
27531
|
// apply migrations, if needed
|
|
27472
27532
|
if ("version" in data) {
|
|
27473
27533
|
if (data.version < CURRENT_VERSION) {
|
|
27474
|
-
console.
|
|
27534
|
+
console.debug("Migrating data from version", data.version);
|
|
27475
27535
|
data = migrate(data);
|
|
27476
27536
|
}
|
|
27477
27537
|
}
|
|
27478
27538
|
data = repairData(data);
|
|
27479
|
-
console.
|
|
27480
|
-
console.
|
|
27539
|
+
console.debug("Data loaded in", performance.now() - start, "ms");
|
|
27540
|
+
console.debug("###");
|
|
27481
27541
|
return data;
|
|
27482
27542
|
}
|
|
27483
27543
|
// -----------------------------------------------------------------------------
|
|
@@ -27507,7 +27567,7 @@ function migrate(data) {
|
|
|
27507
27567
|
for (let i = index; i < steps.length; i++) {
|
|
27508
27568
|
data = steps[i].migrate(data);
|
|
27509
27569
|
}
|
|
27510
|
-
console.
|
|
27570
|
+
console.debug("Data migrated in", performance.now() - start, "ms");
|
|
27511
27571
|
return data;
|
|
27512
27572
|
}
|
|
27513
27573
|
/**
|
|
@@ -27825,6 +27885,7 @@ const ChartTerms = {
|
|
|
27825
27885
|
StackedBarChart: _t("Stacked bar chart"),
|
|
27826
27886
|
StackedLineChart: _t("Stacked line chart"),
|
|
27827
27887
|
StackedAreaChart: _t("Stacked area chart"),
|
|
27888
|
+
StackedColumnChart: _t("Stacked column chart"),
|
|
27828
27889
|
CumulativeData: _t("Cumulative data"),
|
|
27829
27890
|
TreatLabelsAsText: _t("Treat labels as text"),
|
|
27830
27891
|
AggregatedChart: _t("Aggregate"),
|
|
@@ -28086,7 +28147,7 @@ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, tr
|
|
|
28086
28147
|
const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
|
|
28087
28148
|
// tooltipItem.parsed can be an object or a number for pie charts
|
|
28088
28149
|
let yLabel = horizontalChart ? tooltipItem.parsed.x : tooltipItem.parsed.y;
|
|
28089
|
-
if (
|
|
28150
|
+
if (yLabel === undefined || yLabel === null) {
|
|
28090
28151
|
yLabel = tooltipItem.parsed;
|
|
28091
28152
|
}
|
|
28092
28153
|
const toolTipFormat = !format && Math.abs(yLabel) >= 1000 ? "#,##" : format;
|
|
@@ -28527,13 +28588,10 @@ function createBarChartRuntime(chart, getters) {
|
|
|
28527
28588
|
* datasets to ensure the way we distinguish the originals and trendLine datasets after
|
|
28528
28589
|
*/
|
|
28529
28590
|
trendDatasets.forEach((x) => config.data.datasets.push(x));
|
|
28530
|
-
const originalTooltipTitle = config.options.plugins.tooltip.callbacks.title;
|
|
28531
28591
|
config.options.plugins.tooltip.callbacks.title = function (tooltipItems) {
|
|
28532
|
-
|
|
28533
|
-
|
|
28534
|
-
|
|
28535
|
-
}
|
|
28536
|
-
return "";
|
|
28592
|
+
return tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID)
|
|
28593
|
+
? undefined
|
|
28594
|
+
: "";
|
|
28537
28595
|
};
|
|
28538
28596
|
}
|
|
28539
28597
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
@@ -28766,8 +28824,8 @@ function getTrendDatasetForLineChart(config, dataset, axisType, locale) {
|
|
|
28766
28824
|
break;
|
|
28767
28825
|
case "time":
|
|
28768
28826
|
for (const point of dataset.data) {
|
|
28769
|
-
const date =
|
|
28770
|
-
if (
|
|
28827
|
+
const date = toNumber({ value: point.x }, locale);
|
|
28828
|
+
if (point.y !== null) {
|
|
28771
28829
|
filteredValues.push(point.y);
|
|
28772
28830
|
filteredLabels.push(date);
|
|
28773
28831
|
}
|
|
@@ -28903,7 +28961,6 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
28903
28961
|
else if (axisType === "linear") {
|
|
28904
28962
|
config.options.scales.x.type = "linear";
|
|
28905
28963
|
config.options.scales.x.ticks.callback = (value) => formatValue(value, { format: labelFormat, locale });
|
|
28906
|
-
config.options.plugins.tooltip.callbacks.title = () => "";
|
|
28907
28964
|
config.options.plugins.tooltip.callbacks.label = (tooltipItem) => {
|
|
28908
28965
|
const dataSetPoint = dataSetsValues[tooltipItem.datasetIndex].data[tooltipItem.dataIndex];
|
|
28909
28966
|
let label = tooltipItem.label || labelValues.values[tooltipItem.dataIndex];
|
|
@@ -28991,22 +29048,15 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
28991
29048
|
* distinguish the originals and trendLine datasets after
|
|
28992
29049
|
*/
|
|
28993
29050
|
trendDatasets.forEach((x) => config.data.datasets.push(x));
|
|
28994
|
-
const originalTooltipTitle = config.options.plugins.tooltip.callbacks.title;
|
|
28995
|
-
config.options.plugins.tooltip.callbacks.title = function (tooltipItems) {
|
|
28996
|
-
if (tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID)) {
|
|
28997
|
-
// @ts-expect-error
|
|
28998
|
-
return originalTooltipTitle?.(tooltipItems);
|
|
28999
|
-
}
|
|
29000
|
-
return "";
|
|
29001
|
-
};
|
|
29002
29051
|
}
|
|
29052
|
+
config.options.plugins.tooltip.callbacks.title = function (tooltipItems) {
|
|
29053
|
+
const displayTooltipTitle = axisType !== "linear" &&
|
|
29054
|
+
tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID);
|
|
29055
|
+
return displayTooltipTitle ? undefined : "";
|
|
29056
|
+
};
|
|
29003
29057
|
return {
|
|
29004
29058
|
chartJsConfig: config,
|
|
29005
29059
|
background: chart.background || BACKGROUND_CHART_COLOR,
|
|
29006
|
-
dataSetsValues,
|
|
29007
|
-
labelValues,
|
|
29008
|
-
dataSetFormat,
|
|
29009
|
-
labelFormat,
|
|
29010
29060
|
};
|
|
29011
29061
|
}
|
|
29012
29062
|
|
|
@@ -29263,13 +29313,10 @@ function createComboChartRuntime(chart, getters) {
|
|
|
29263
29313
|
* distinguish the originals and trendLine datasets after
|
|
29264
29314
|
*/
|
|
29265
29315
|
trendDatasets.forEach((x) => config.data.datasets.push(x));
|
|
29266
|
-
const originalTooltipTitle = config.options.plugins.tooltip.callbacks.title;
|
|
29267
29316
|
config.options.plugins.tooltip.callbacks.title = function (tooltipItems) {
|
|
29268
|
-
|
|
29269
|
-
|
|
29270
|
-
|
|
29271
|
-
}
|
|
29272
|
-
return "";
|
|
29317
|
+
return tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID)
|
|
29318
|
+
? undefined
|
|
29319
|
+
: "";
|
|
29273
29320
|
};
|
|
29274
29321
|
}
|
|
29275
29322
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
@@ -36244,6 +36291,12 @@ class GenericChartConfigPanel extends owl.Component {
|
|
|
36244
36291
|
|
|
36245
36292
|
class BarConfigPanel extends GenericChartConfigPanel {
|
|
36246
36293
|
static template = "o-spreadsheet-BarConfigPanel";
|
|
36294
|
+
get stackedLabel() {
|
|
36295
|
+
const definition = this.props.definition;
|
|
36296
|
+
return definition.horizontal
|
|
36297
|
+
? this.chartTerms.StackedBarChart
|
|
36298
|
+
: this.chartTerms.StackedColumnChart;
|
|
36299
|
+
}
|
|
36247
36300
|
onUpdateStacked(stacked) {
|
|
36248
36301
|
this.props.updateChart(this.props.figureId, {
|
|
36249
36302
|
stacked,
|
|
@@ -36259,7 +36312,6 @@ class BarConfigPanel extends GenericChartConfigPanel {
|
|
|
36259
36312
|
css /* scss */ `
|
|
36260
36313
|
.o_side_panel_collapsible_title {
|
|
36261
36314
|
font-size: 16px;
|
|
36262
|
-
font-weight: bold;
|
|
36263
36315
|
cursor: pointer;
|
|
36264
36316
|
padding: 6px 0px 6px 6px !important;
|
|
36265
36317
|
|
|
@@ -37239,6 +37291,9 @@ class ChartWithAxisDesignPanel extends owl.Component {
|
|
|
37239
37291
|
getDataSeries() {
|
|
37240
37292
|
return this.props.definition.dataSets.map((d, i) => d.label ?? `${ChartTerms.Series} ${i + 1}`);
|
|
37241
37293
|
}
|
|
37294
|
+
getPolynomialDegrees() {
|
|
37295
|
+
return range(1, this.getMaxPolynomialDegree() + 1);
|
|
37296
|
+
}
|
|
37242
37297
|
updateSerieEditor(ev) {
|
|
37243
37298
|
const chartId = this.props.figureId;
|
|
37244
37299
|
const selectedIndex = ev.target.selectedIndex;
|
|
@@ -37355,12 +37410,7 @@ class ChartWithAxisDesignPanel extends owl.Component {
|
|
|
37355
37410
|
}
|
|
37356
37411
|
onChangePolynomialDegree(ev) {
|
|
37357
37412
|
const element = ev.target;
|
|
37358
|
-
|
|
37359
|
-
if (order < 2) {
|
|
37360
|
-
element.value = `${this.getTrendLineConfiguration()?.order ?? 2}`;
|
|
37361
|
-
return;
|
|
37362
|
-
}
|
|
37363
|
-
this.updateTrendLineValue({ order });
|
|
37413
|
+
this.updateTrendLineValue({ order: parseInt(element.value) });
|
|
37364
37414
|
}
|
|
37365
37415
|
getTrendLineColor() {
|
|
37366
37416
|
return this.getTrendLineConfiguration()?.color ?? setColorAlpha(this.getDataSerieColor(), 0.5);
|
|
@@ -37382,6 +37432,10 @@ class ChartWithAxisDesignPanel extends owl.Component {
|
|
|
37382
37432
|
};
|
|
37383
37433
|
this.props.updateChart(this.props.figureId, { dataSets });
|
|
37384
37434
|
}
|
|
37435
|
+
getMaxPolynomialDegree() {
|
|
37436
|
+
const runtime = this.env.model.getters.getChartRuntime(this.props.figureId);
|
|
37437
|
+
return Math.min(10, runtime.chartJsConfig.data.datasets[this.state.index].data.length - 1);
|
|
37438
|
+
}
|
|
37385
37439
|
}
|
|
37386
37440
|
|
|
37387
37441
|
class ComboChartDesignPanel extends ChartWithAxisDesignPanel {
|
|
@@ -37565,7 +37619,9 @@ class LineConfigPanel extends GenericChartConfigPanel {
|
|
|
37565
37619
|
}
|
|
37566
37620
|
get stackedLabel() {
|
|
37567
37621
|
const definition = this.props.definition;
|
|
37568
|
-
return definition.fillArea
|
|
37622
|
+
return definition.fillArea
|
|
37623
|
+
? this.chartTerms.StackedAreaChart
|
|
37624
|
+
: this.chartTerms.StackedLineChart;
|
|
37569
37625
|
}
|
|
37570
37626
|
getLabelRangeOptions() {
|
|
37571
37627
|
const options = super.getLabelRangeOptions();
|
|
@@ -39210,7 +39266,6 @@ css /* scss */ `
|
|
|
39210
39266
|
width: 142px;
|
|
39211
39267
|
.o-cf-preview-description-rule {
|
|
39212
39268
|
margin-bottom: 4px;
|
|
39213
|
-
font-weight: 600;
|
|
39214
39269
|
max-height: 2.8em;
|
|
39215
39270
|
line-height: 1.4em;
|
|
39216
39271
|
}
|
|
@@ -42212,7 +42267,6 @@ function createMeasureAutoComplete(pivot, forComputedMeasure) {
|
|
|
42212
42267
|
sequence: 0,
|
|
42213
42268
|
autoSelectFirstProposal: true,
|
|
42214
42269
|
getProposals(tokenAtCursor) {
|
|
42215
|
-
// return []
|
|
42216
42270
|
const measureProposals = pivot.measures
|
|
42217
42271
|
.filter((m) => m !== forComputedMeasure)
|
|
42218
42272
|
.map((measure) => {
|
|
@@ -47153,6 +47207,7 @@ class PaintFormatStore extends SpreadsheetStore {
|
|
|
47153
47207
|
new CellClipboardHandler(this.getters, this.model.dispatch),
|
|
47154
47208
|
new BorderClipboardHandler(this.getters, this.model.dispatch),
|
|
47155
47209
|
new TableClipboardHandler(this.getters, this.model.dispatch),
|
|
47210
|
+
new ConditionalFormatClipboardHandler(this.getters, this.model.dispatch),
|
|
47156
47211
|
];
|
|
47157
47212
|
status = "inactive";
|
|
47158
47213
|
copiedData;
|
|
@@ -47163,6 +47218,13 @@ class PaintFormatStore extends SpreadsheetStore {
|
|
|
47163
47218
|
this.highlightStore.unRegister(this);
|
|
47164
47219
|
});
|
|
47165
47220
|
}
|
|
47221
|
+
handle(cmd) {
|
|
47222
|
+
switch (cmd.type) {
|
|
47223
|
+
case "PAINT_FORMAT":
|
|
47224
|
+
this.paintFormat(cmd.sheetId, cmd.target);
|
|
47225
|
+
break;
|
|
47226
|
+
}
|
|
47227
|
+
}
|
|
47166
47228
|
activate(args) {
|
|
47167
47229
|
this.copiedData = this.copyFormats();
|
|
47168
47230
|
this.status = args.persistent ? "persistent" : "oneOff";
|
|
@@ -47172,18 +47234,7 @@ class PaintFormatStore extends SpreadsheetStore {
|
|
|
47172
47234
|
this.copiedData = undefined;
|
|
47173
47235
|
}
|
|
47174
47236
|
pasteFormat(target) {
|
|
47175
|
-
|
|
47176
|
-
const sheetId = this.getters.getActiveSheetId();
|
|
47177
|
-
for (const handler of this.clipboardHandlers) {
|
|
47178
|
-
handler.paste({ zones: target, sheetId }, this.copiedData, {
|
|
47179
|
-
isCutOperation: false,
|
|
47180
|
-
pasteOption: "onlyFormat",
|
|
47181
|
-
});
|
|
47182
|
-
}
|
|
47183
|
-
}
|
|
47184
|
-
if (this.status === "oneOff") {
|
|
47185
|
-
this.cancel();
|
|
47186
|
-
}
|
|
47237
|
+
this.model.dispatch("PAINT_FORMAT", { target, sheetId: this.getters.getActiveSheetId() });
|
|
47187
47238
|
}
|
|
47188
47239
|
get isActive() {
|
|
47189
47240
|
return this.status !== "inactive";
|
|
@@ -47197,6 +47248,19 @@ class PaintFormatStore extends SpreadsheetStore {
|
|
|
47197
47248
|
}
|
|
47198
47249
|
return copiedData;
|
|
47199
47250
|
}
|
|
47251
|
+
paintFormat(sheetId, target) {
|
|
47252
|
+
if (this.copiedData) {
|
|
47253
|
+
for (const handler of this.clipboardHandlers) {
|
|
47254
|
+
handler.paste({ zones: target, sheetId }, this.copiedData, {
|
|
47255
|
+
isCutOperation: false,
|
|
47256
|
+
pasteOption: "onlyFormat",
|
|
47257
|
+
});
|
|
47258
|
+
}
|
|
47259
|
+
}
|
|
47260
|
+
if (this.status === "oneOff") {
|
|
47261
|
+
this.cancel();
|
|
47262
|
+
}
|
|
47263
|
+
}
|
|
47200
47264
|
get highlights() {
|
|
47201
47265
|
const data = this.copiedData;
|
|
47202
47266
|
if (!data) {
|
|
@@ -55440,7 +55504,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
55440
55504
|
case "DUPLICATE_PIVOT": {
|
|
55441
55505
|
const { pivotId, newPivotId } = cmd;
|
|
55442
55506
|
const pivot = deepCopy(this.getPivotCore(pivotId).definition);
|
|
55443
|
-
pivot.name =
|
|
55507
|
+
pivot.name = cmd.duplicatedPivotName ?? pivot.name + " (copy)";
|
|
55444
55508
|
this.addPivot(newPivotId, pivot);
|
|
55445
55509
|
break;
|
|
55446
55510
|
}
|
|
@@ -55480,7 +55544,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
55480
55544
|
return `(#${formulaId}) ${this.getPivotName(pivotId)}`;
|
|
55481
55545
|
}
|
|
55482
55546
|
getPivotName(pivotId) {
|
|
55483
|
-
return
|
|
55547
|
+
return this.getPivotCore(pivotId).definition.name;
|
|
55484
55548
|
}
|
|
55485
55549
|
/**
|
|
55486
55550
|
* Returns the pivot core definition of the pivot with the given id.
|
|
@@ -57122,7 +57186,7 @@ class Evaluator {
|
|
|
57122
57186
|
cellsToCompute.addMany(arrayFormulasPositions);
|
|
57123
57187
|
cellsToCompute.addMany(this.getCellsDependingOn(arrayFormulasPositions));
|
|
57124
57188
|
this.evaluate(cellsToCompute);
|
|
57125
|
-
console.
|
|
57189
|
+
console.debug("evaluate Cells", performance.now() - start, "ms");
|
|
57126
57190
|
}
|
|
57127
57191
|
getArrayFormulasImpactedByChangesOf(positions) {
|
|
57128
57192
|
const impactedPositions = this.createEmptyPositionSet();
|
|
@@ -57166,7 +57230,7 @@ class Evaluator {
|
|
|
57166
57230
|
const start = performance.now();
|
|
57167
57231
|
this.evaluatedCells = new PositionMap();
|
|
57168
57232
|
this.evaluate(this.getAllCells());
|
|
57169
|
-
console.
|
|
57233
|
+
console.debug("evaluate all cells", performance.now() - start, "ms");
|
|
57170
57234
|
}
|
|
57171
57235
|
evaluateFormulaResult(sheetId, formulaString) {
|
|
57172
57236
|
const compiledFormula = compile(formulaString);
|
|
@@ -59571,6 +59635,10 @@ class PivotUIPlugin extends UIPlugin {
|
|
|
59571
59635
|
if (!pivot.isValid()) {
|
|
59572
59636
|
return EMPTY_PIVOT_CELL;
|
|
59573
59637
|
}
|
|
59638
|
+
if (functionName === "PIVOT" &&
|
|
59639
|
+
!cell.content.replaceAll(" ", "").toUpperCase().startsWith("=PIVOT")) {
|
|
59640
|
+
return EMPTY_PIVOT_CELL;
|
|
59641
|
+
}
|
|
59574
59642
|
if (functionName === "PIVOT") {
|
|
59575
59643
|
const includeTotal = args[2] === false ? false : undefined;
|
|
59576
59644
|
const includeColumnHeaders = args[3] === false ? false : undefined;
|
|
@@ -60912,7 +60980,7 @@ class Session extends EventBus {
|
|
|
60912
60980
|
this.onMessageReceived(message);
|
|
60913
60981
|
}
|
|
60914
60982
|
this.isReplayingInitialRevisions = false;
|
|
60915
|
-
console.
|
|
60983
|
+
console.debug("Replayed", numberOfCommands, "commands in", performance.now() - start, "ms");
|
|
60916
60984
|
}
|
|
60917
60985
|
/**
|
|
60918
60986
|
* Notify the server that the user client left the collaborative session
|
|
@@ -61709,6 +61777,7 @@ class InsertPivotPlugin extends UIPlugin {
|
|
|
61709
61777
|
this.dispatch("DUPLICATE_PIVOT", {
|
|
61710
61778
|
pivotId,
|
|
61711
61779
|
newPivotId,
|
|
61780
|
+
duplicatedPivotName: _t("%s (copy)", this.getters.getPivotCoreDefinition(pivotId).name),
|
|
61712
61781
|
});
|
|
61713
61782
|
const activeSheetId = this.getters.getActiveSheetId();
|
|
61714
61783
|
const position = this.getters.getSheetIds().indexOf(activeSheetId) + 1;
|
|
@@ -66842,10 +66911,9 @@ css /* scss */ `
|
|
|
66842
66911
|
user-select: none;
|
|
66843
66912
|
color: ${TEXT_BODY};
|
|
66844
66913
|
|
|
66845
|
-
.o-
|
|
66914
|
+
.o-sidePanelTitle {
|
|
66846
66915
|
line-height: 20px;
|
|
66847
66916
|
font-size: 16px;
|
|
66848
|
-
font-weight: 600;
|
|
66849
66917
|
}
|
|
66850
66918
|
|
|
66851
66919
|
.o-sidePanelHeader {
|
|
@@ -66930,6 +66998,10 @@ css /* scss */ `
|
|
|
66930
66998
|
}
|
|
66931
66999
|
}
|
|
66932
67000
|
}
|
|
67001
|
+
|
|
67002
|
+
.o-fw-bold {
|
|
67003
|
+
font-weight: 500;
|
|
67004
|
+
}
|
|
66933
67005
|
`;
|
|
66934
67006
|
class SidePanel extends owl.Component {
|
|
66935
67007
|
static template = "o-spreadsheet-SidePanel";
|
|
@@ -70340,7 +70412,8 @@ function addFormula(cell) {
|
|
|
70340
70412
|
}
|
|
70341
70413
|
const attrs = [["t", type]];
|
|
70342
70414
|
const XlsxFormula = adaptFormulaToExcel(formula);
|
|
70343
|
-
const
|
|
70415
|
+
const exportedValue = adaptFormulaValueToExcel(cell.value);
|
|
70416
|
+
const node = escapeXml /*xml*/ `<f>${XlsxFormula}</f><v>${exportedValue}</v>`;
|
|
70344
70417
|
return { attrs, node };
|
|
70345
70418
|
}
|
|
70346
70419
|
function addContent(content, sharedStrings, forceString = false) {
|
|
@@ -70375,8 +70448,14 @@ function adaptFormulaToExcel(formulaText) {
|
|
|
70375
70448
|
ast = addMissingRequiredArgs(ast);
|
|
70376
70449
|
return ast;
|
|
70377
70450
|
});
|
|
70451
|
+
ast = convertAstNodes(ast, "REFERENCE", (ast) => {
|
|
70452
|
+
return ast.value === CellErrorType.InvalidReference ? { ...ast, value: "#REF!" } : ast;
|
|
70453
|
+
});
|
|
70378
70454
|
return ast ? astToFormula(ast) : formulaText;
|
|
70379
70455
|
}
|
|
70456
|
+
function adaptFormulaValueToExcel(formulaValue) {
|
|
70457
|
+
return formulaValue === CellErrorType.InvalidReference ? "#REF!" : formulaValue;
|
|
70458
|
+
}
|
|
70380
70459
|
/**
|
|
70381
70460
|
* Some Excel function need required args that might not be mandatory in o-spreadsheet.
|
|
70382
70461
|
* This adds those missing args.
|
|
@@ -71699,7 +71778,7 @@ class Model extends EventBus {
|
|
|
71699
71778
|
coreHandlers = [];
|
|
71700
71779
|
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = false) {
|
|
71701
71780
|
const start = performance.now();
|
|
71702
|
-
console.
|
|
71781
|
+
console.debug("##### Model creation #####");
|
|
71703
71782
|
super();
|
|
71704
71783
|
setDefaultTranslationMethod();
|
|
71705
71784
|
stateUpdateMessages = repairInitialMessages(data, stateUpdateMessages);
|
|
@@ -71771,16 +71850,16 @@ class Model extends EventBus {
|
|
|
71771
71850
|
this.joinSession();
|
|
71772
71851
|
if (config.snapshotRequested) {
|
|
71773
71852
|
const startSnapshot = performance.now();
|
|
71774
|
-
console.
|
|
71853
|
+
console.debug("Snapshot requested");
|
|
71775
71854
|
this.session.snapshot(this.exportData());
|
|
71776
71855
|
this.garbageCollectExternalResources();
|
|
71777
|
-
console.
|
|
71856
|
+
console.debug("Snapshot taken in", performance.now() - startSnapshot, "ms");
|
|
71778
71857
|
}
|
|
71779
71858
|
// mark all models as "raw", so they will not be turned into reactive objects
|
|
71780
71859
|
// by owl, since we do not rely on reactivity
|
|
71781
71860
|
owl.markRaw(this);
|
|
71782
|
-
console.
|
|
71783
|
-
console.
|
|
71861
|
+
console.debug("Model created in", performance.now() - start, "ms");
|
|
71862
|
+
console.debug("######");
|
|
71784
71863
|
}
|
|
71785
71864
|
joinSession() {
|
|
71786
71865
|
this.session.join(this.config.client);
|
|
@@ -72004,7 +72083,7 @@ class Model extends EventBus {
|
|
|
72004
72083
|
this.finalize();
|
|
72005
72084
|
const time = performance.now() - start;
|
|
72006
72085
|
if (time > 5) {
|
|
72007
|
-
console.
|
|
72086
|
+
console.debug(type, time, "ms");
|
|
72008
72087
|
}
|
|
72009
72088
|
});
|
|
72010
72089
|
this.session.save(command, commands, changes);
|
|
@@ -72351,6 +72430,7 @@ const constants = {
|
|
|
72351
72430
|
PIVOT_TABLE_CONFIG,
|
|
72352
72431
|
TREND_LINE_XAXIS_ID,
|
|
72353
72432
|
CHART_AXIS_CHOICES,
|
|
72433
|
+
ChartTerms,
|
|
72354
72434
|
};
|
|
72355
72435
|
|
|
72356
72436
|
exports.AbstractCellClipboardHandler = AbstractCellClipboardHandler;
|
|
@@ -72399,6 +72479,6 @@ exports.tokenColors = tokenColors;
|
|
|
72399
72479
|
exports.tokenize = tokenize;
|
|
72400
72480
|
|
|
72401
72481
|
|
|
72402
|
-
__info__.version = "18.0.
|
|
72403
|
-
__info__.date = "2024-
|
|
72404
|
-
__info__.hash = "
|
|
72482
|
+
__info__.version = "18.0.3";
|
|
72483
|
+
__info__.date = "2024-11-08T12:17:49.992Z";
|
|
72484
|
+
__info__.hash = "5fa5fbb";
|