@odoo/o-spreadsheet 18.1.0-alpha.1 → 18.1.0-alpha.2
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 +908 -549
- package/dist/o-spreadsheet.d.ts +310 -244
- package/dist/o-spreadsheet.esm.js +908 -549
- package/dist/o-spreadsheet.iife.js +908 -549
- package/dist/o-spreadsheet.iife.min.js +438 -408
- package/dist/o_spreadsheet.xml +264 -341
- 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.1.0-alpha.
|
|
6
|
-
* @date 2024-10-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.1.0-alpha.2
|
|
6
|
+
* @date 2024-10-24T08:53:21.828Z
|
|
7
|
+
* @hash 2a01250
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -330,6 +330,7 @@
|
|
|
330
330
|
const DEFAULT_SCORECARD_BASELINE_COLOR_UP = "#43C5B1";
|
|
331
331
|
const DEFAULT_SCORECARD_BASELINE_COLOR_DOWN = "#EA6175";
|
|
332
332
|
const LINE_FILL_TRANSPARENCY = 0.4;
|
|
333
|
+
const DEFAULT_WINDOW_SIZE = 2;
|
|
333
334
|
// session
|
|
334
335
|
const DEBOUNCE_TIME = 200;
|
|
335
336
|
const MESSAGE_VERSION = 1;
|
|
@@ -375,7 +376,7 @@
|
|
|
375
376
|
bandedRows: true,
|
|
376
377
|
bandedColumns: false,
|
|
377
378
|
styleId: "TableStyleMedium5",
|
|
378
|
-
automaticAutofill:
|
|
379
|
+
automaticAutofill: false,
|
|
379
380
|
};
|
|
380
381
|
const DEFAULT_CURRENCY = {
|
|
381
382
|
symbol: "$",
|
|
@@ -591,7 +592,7 @@
|
|
|
591
592
|
*/
|
|
592
593
|
function parseSheetUrl(sheetLink) {
|
|
593
594
|
if (sheetLink.startsWith(O_SPREADSHEET_LINK_PREFIX)) {
|
|
594
|
-
return sheetLink.
|
|
595
|
+
return sheetLink.slice(O_SPREADSHEET_LINK_PREFIX.length);
|
|
595
596
|
}
|
|
596
597
|
throw new Error(`${sheetLink} is not a valid sheet link`);
|
|
597
598
|
}
|
|
@@ -3156,8 +3157,7 @@
|
|
|
3156
3157
|
const p2 = pMinus + pNumber + pCurrencyFormat;
|
|
3157
3158
|
const p3 = pCurrencyFormat + pMinus + pNumber;
|
|
3158
3159
|
const pNumberExp = "^(?:(?:" + [p1, p2, p3].join(")|(?:") + "))$";
|
|
3159
|
-
|
|
3160
|
-
return numberRegexp;
|
|
3160
|
+
return new RegExp(pNumberExp, "i");
|
|
3161
3161
|
});
|
|
3162
3162
|
/**
|
|
3163
3163
|
* Return true if the argument is a "number string".
|
|
@@ -5831,8 +5831,7 @@
|
|
|
5831
5831
|
textWidthCache[font] = {};
|
|
5832
5832
|
}
|
|
5833
5833
|
if (textWidthCache[font][text] === undefined) {
|
|
5834
|
-
|
|
5835
|
-
textWidthCache[font][text] = textWidth;
|
|
5834
|
+
textWidthCache[font][text] = context.measureText(text).width;
|
|
5836
5835
|
}
|
|
5837
5836
|
return textWidthCache[font][text];
|
|
5838
5837
|
}
|
|
@@ -6084,7 +6083,7 @@
|
|
|
6084
6083
|
else {
|
|
6085
6084
|
// mainly for jest and other browsers that do not have the crypto functionality
|
|
6086
6085
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
6087
|
-
|
|
6086
|
+
const r = (Math.random() * 16) | 0, v = c === "x" ? r : (r & 0x3) | 0x8;
|
|
6088
6087
|
return v.toString(16);
|
|
6089
6088
|
});
|
|
6090
6089
|
}
|
|
@@ -6581,10 +6580,9 @@
|
|
|
6581
6580
|
return literal;
|
|
6582
6581
|
}
|
|
6583
6582
|
const decimalNumberRegex = getDecimalNumberRegex(DEFAULT_LOCALE);
|
|
6584
|
-
|
|
6583
|
+
return literal.replace(decimalNumberRegex, (match) => {
|
|
6585
6584
|
return match.replace(".", locale.decimalSeparator);
|
|
6586
6585
|
});
|
|
6587
|
-
return localized;
|
|
6588
6586
|
}
|
|
6589
6587
|
/**
|
|
6590
6588
|
* Change a literal string from its canonical form (en_US locale) to the given locale. Also convert date string.
|
|
@@ -7069,6 +7067,21 @@
|
|
|
7069
7067
|
});
|
|
7070
7068
|
return newY.length === newX.length ? newY : transposeMatrix(newY);
|
|
7071
7069
|
}
|
|
7070
|
+
function getMovingAverageValues(dataset, windowSize = DEFAULT_WINDOW_SIZE) {
|
|
7071
|
+
const values = [];
|
|
7072
|
+
// Fill the starting values with null until we have a full window
|
|
7073
|
+
for (let i = 0; i < windowSize - 1; i++) {
|
|
7074
|
+
values.push(null);
|
|
7075
|
+
}
|
|
7076
|
+
for (let i = 0; i <= dataset.length - windowSize; i++) {
|
|
7077
|
+
let sum = 0;
|
|
7078
|
+
for (let j = i; j < i + windowSize; j++) {
|
|
7079
|
+
sum += dataset[j];
|
|
7080
|
+
}
|
|
7081
|
+
values.push(sum / windowSize);
|
|
7082
|
+
}
|
|
7083
|
+
return values;
|
|
7084
|
+
}
|
|
7072
7085
|
|
|
7073
7086
|
const PREVIOUS_VALUE = "(previous)";
|
|
7074
7087
|
const NEXT_VALUE = "(next)";
|
|
@@ -7604,8 +7617,7 @@
|
|
|
7604
7617
|
return 0;
|
|
7605
7618
|
}
|
|
7606
7619
|
const nums = keys.map((id) => parseInt(id, 10));
|
|
7607
|
-
|
|
7608
|
-
return max;
|
|
7620
|
+
return Math.max(...nums);
|
|
7609
7621
|
}
|
|
7610
7622
|
const ALL_PERIODS = {
|
|
7611
7623
|
year: _t("Year"),
|
|
@@ -8458,10 +8470,6 @@
|
|
|
8458
8470
|
tableZone &&
|
|
8459
8471
|
zones.some((z) => isZoneInside(tableZone, z))) {
|
|
8460
8472
|
copiedTablesIds.add(table.id);
|
|
8461
|
-
const values = [];
|
|
8462
|
-
for (const col of range(tableZone.left, tableZone.right + 1)) {
|
|
8463
|
-
values.push(this.getters.getFilterHiddenValues({ sheetId, col, row: tableZone.top }));
|
|
8464
|
-
}
|
|
8465
8473
|
copiedTable = {
|
|
8466
8474
|
range: coreTable.range.rangeData,
|
|
8467
8475
|
config: coreTable.config,
|
|
@@ -9242,11 +9250,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9242
9250
|
const { x, y } = getters.getMainViewportCoordinates();
|
|
9243
9251
|
const { scrollX, scrollY } = getters.getActiveSheetScrollInfo();
|
|
9244
9252
|
const { width, height } = getters.getVisibleRect(getters.getActiveMainViewport());
|
|
9245
|
-
|
|
9253
|
+
return {
|
|
9246
9254
|
x: x + scrollX + Math.max(0, (width - chartSize.width) / 2),
|
|
9247
9255
|
y: y + scrollY + Math.max(0, (height - chartSize.height) / 2),
|
|
9248
9256
|
}; // Position at the center of the scrollable viewport
|
|
9249
|
-
return position;
|
|
9250
9257
|
}
|
|
9251
9258
|
function getChartAxisTitleRuntime(design) {
|
|
9252
9259
|
if (design?.title?.text) {
|
|
@@ -9363,7 +9370,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9363
9370
|
return {
|
|
9364
9371
|
...dataset,
|
|
9365
9372
|
type: "line",
|
|
9366
|
-
xAxisID: TREND_LINE_XAXIS_ID,
|
|
9373
|
+
xAxisID: config.type !== "trailingMovingAverage" ? TREND_LINE_XAXIS_ID : "x",
|
|
9367
9374
|
label: dataset.label ? _t("Trend line for %s", dataset.label) : "",
|
|
9368
9375
|
data,
|
|
9369
9376
|
order: -1,
|
|
@@ -9405,6 +9412,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9405
9412
|
case "logarithmic": {
|
|
9406
9413
|
return predictLinearValues([values], logM([labels]), logM([newLabels]), true)[0];
|
|
9407
9414
|
}
|
|
9415
|
+
case "trailingMovingAverage": {
|
|
9416
|
+
return getMovingAverageValues(values, config.window);
|
|
9417
|
+
}
|
|
9408
9418
|
default:
|
|
9409
9419
|
return [];
|
|
9410
9420
|
}
|
|
@@ -9450,72 +9460,115 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9450
9460
|
ctx.save();
|
|
9451
9461
|
ctx.textAlign = "center";
|
|
9452
9462
|
ctx.textBaseline = "middle";
|
|
9453
|
-
ctx.
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
const midRadius = (innerRadius + outerRadius) / 2;
|
|
9467
|
-
const x = bar.x + midRadius * Math.cos(midAngle);
|
|
9468
|
-
const y = bar.y + midRadius * Math.sin(midAngle) + 7;
|
|
9469
|
-
ctx.fillStyle = chartFontColor(bar.options.backgroundColor);
|
|
9470
|
-
ctx.strokeStyle = chartFontColor(ctx.fillStyle);
|
|
9471
|
-
const value = options.callback(dataset._parsed[i]);
|
|
9472
|
-
ctx.strokeText(value, x, y);
|
|
9473
|
-
ctx.fillText(value, x, y);
|
|
9474
|
-
}
|
|
9475
|
-
break;
|
|
9476
|
-
}
|
|
9477
|
-
case "bar":
|
|
9478
|
-
case "line": {
|
|
9479
|
-
const yOffset = dataset.type === "bar" && !options.horizontal ? 0 : 3;
|
|
9480
|
-
const horizontalChart = dataset.type === "bar" && options.horizontal;
|
|
9481
|
-
const axisId = horizontalChart ? dataset.xAxisID : dataset.yAxisID;
|
|
9482
|
-
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
9483
|
-
const point = dataset.data[i];
|
|
9484
|
-
const value = options.horizontal ? dataset._parsed[i].x : dataset._parsed[i].y;
|
|
9485
|
-
const displayedValue = options.callback(value - 0, axisId);
|
|
9486
|
-
let xPosition = 0, yPosition = 0;
|
|
9487
|
-
if (options.horizontal) {
|
|
9488
|
-
yPosition = point.y;
|
|
9489
|
-
if (value < 0) {
|
|
9490
|
-
ctx.textAlign = "right";
|
|
9491
|
-
xPosition = point.x - yOffset;
|
|
9492
|
-
}
|
|
9493
|
-
else {
|
|
9494
|
-
ctx.textAlign = "left";
|
|
9495
|
-
xPosition = point.x + yOffset;
|
|
9496
|
-
}
|
|
9497
|
-
}
|
|
9498
|
-
else {
|
|
9499
|
-
xPosition = point.x;
|
|
9500
|
-
if (value < 0) {
|
|
9501
|
-
ctx.textBaseline = "top";
|
|
9502
|
-
yPosition = point.y + yOffset;
|
|
9503
|
-
}
|
|
9504
|
-
else {
|
|
9505
|
-
ctx.textBaseline = "bottom";
|
|
9506
|
-
yPosition = point.y - yOffset;
|
|
9507
|
-
}
|
|
9508
|
-
}
|
|
9509
|
-
ctx.strokeText(displayedValue, xPosition, yPosition);
|
|
9510
|
-
ctx.fillText(displayedValue, xPosition, yPosition);
|
|
9511
|
-
}
|
|
9512
|
-
break;
|
|
9513
|
-
}
|
|
9514
|
-
}
|
|
9515
|
-
});
|
|
9463
|
+
ctx.miterLimit = 1; // Avoid sharp artifacts on strokeText
|
|
9464
|
+
switch (chart.config.type) {
|
|
9465
|
+
case "pie":
|
|
9466
|
+
case "doughnut":
|
|
9467
|
+
drawPieChartValues(chart, options, ctx);
|
|
9468
|
+
break;
|
|
9469
|
+
case "bar":
|
|
9470
|
+
case "line":
|
|
9471
|
+
options.horizontal
|
|
9472
|
+
? drawHorizontalBarChartValues(chart, options, ctx)
|
|
9473
|
+
: drawLineOrBarChartValues(chart, options, ctx);
|
|
9474
|
+
break;
|
|
9475
|
+
}
|
|
9516
9476
|
ctx.restore();
|
|
9517
9477
|
},
|
|
9518
9478
|
};
|
|
9479
|
+
function drawTextWithBackground(text, x, y, ctx) {
|
|
9480
|
+
ctx.lineWidth = 3; // Stroke the text with a big lineWidth width to have some kind of background
|
|
9481
|
+
ctx.strokeText(text, x, y);
|
|
9482
|
+
ctx.lineWidth = 1;
|
|
9483
|
+
ctx.fillText(text, x, y);
|
|
9484
|
+
}
|
|
9485
|
+
function drawLineOrBarChartValues(chart, options, ctx) {
|
|
9486
|
+
const yMax = chart.chartArea.bottom;
|
|
9487
|
+
const yMin = chart.chartArea.top;
|
|
9488
|
+
const textsPositions = {};
|
|
9489
|
+
for (const dataset of chart._metasets) {
|
|
9490
|
+
if (dataset.xAxisID === TREND_LINE_XAXIS_ID) {
|
|
9491
|
+
return; // ignore trend lines
|
|
9492
|
+
}
|
|
9493
|
+
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
9494
|
+
const value = dataset._parsed[i].y;
|
|
9495
|
+
const displayValue = options.callback(value - 0, dataset.yAxisID);
|
|
9496
|
+
const point = dataset.data[i];
|
|
9497
|
+
const xPosition = point.x;
|
|
9498
|
+
let yPosition = 0;
|
|
9499
|
+
if (chart.config.type === "line") {
|
|
9500
|
+
yPosition = point.y - 10;
|
|
9501
|
+
}
|
|
9502
|
+
else {
|
|
9503
|
+
yPosition = value < 0 ? point.y - point.height / 2 : point.y + point.height / 2;
|
|
9504
|
+
}
|
|
9505
|
+
yPosition = Math.min(yPosition, yMax);
|
|
9506
|
+
yPosition = Math.max(yPosition, yMin);
|
|
9507
|
+
// Avoid overlapping texts with same X
|
|
9508
|
+
if (!textsPositions[xPosition]) {
|
|
9509
|
+
textsPositions[xPosition] = [];
|
|
9510
|
+
}
|
|
9511
|
+
for (const otherPosition of textsPositions[xPosition] || []) {
|
|
9512
|
+
if (Math.abs(otherPosition - yPosition) < 13) {
|
|
9513
|
+
yPosition = otherPosition - 13;
|
|
9514
|
+
}
|
|
9515
|
+
}
|
|
9516
|
+
textsPositions[xPosition].push(yPosition);
|
|
9517
|
+
ctx.fillStyle = point.options.backgroundColor;
|
|
9518
|
+
ctx.strokeStyle = options.background || "#ffffff";
|
|
9519
|
+
drawTextWithBackground(displayValue, xPosition, yPosition, ctx);
|
|
9520
|
+
}
|
|
9521
|
+
}
|
|
9522
|
+
}
|
|
9523
|
+
function drawHorizontalBarChartValues(chart, options, ctx) {
|
|
9524
|
+
const xMax = chart.chartArea.right;
|
|
9525
|
+
const xMin = chart.chartArea.left;
|
|
9526
|
+
const textsPositions = {};
|
|
9527
|
+
for (const dataset of chart._metasets) {
|
|
9528
|
+
if (dataset.xAxisID === TREND_LINE_XAXIS_ID) {
|
|
9529
|
+
return; // ignore trend lines
|
|
9530
|
+
}
|
|
9531
|
+
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
9532
|
+
const value = dataset._parsed[i].x;
|
|
9533
|
+
const displayValue = options.callback(value - 0, dataset.xAxisID);
|
|
9534
|
+
const point = dataset.data[i];
|
|
9535
|
+
const yPosition = point.y;
|
|
9536
|
+
let xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
|
|
9537
|
+
xPosition = Math.min(xPosition, xMax);
|
|
9538
|
+
xPosition = Math.max(xPosition, xMin);
|
|
9539
|
+
// Avoid overlapping texts with same Y
|
|
9540
|
+
if (!textsPositions[yPosition]) {
|
|
9541
|
+
textsPositions[yPosition] = [];
|
|
9542
|
+
}
|
|
9543
|
+
const textWidth = computeTextWidth(ctx, displayValue, { fontSize: 12 }, "px");
|
|
9544
|
+
for (const otherPosition of textsPositions[yPosition]) {
|
|
9545
|
+
if (Math.abs(otherPosition - xPosition) < textWidth) {
|
|
9546
|
+
xPosition = otherPosition + textWidth + 3;
|
|
9547
|
+
}
|
|
9548
|
+
}
|
|
9549
|
+
textsPositions[yPosition].push(xPosition);
|
|
9550
|
+
ctx.fillStyle = point.options.backgroundColor;
|
|
9551
|
+
ctx.strokeStyle = options.background || "#ffffff";
|
|
9552
|
+
drawTextWithBackground(displayValue, xPosition, yPosition, ctx);
|
|
9553
|
+
}
|
|
9554
|
+
}
|
|
9555
|
+
}
|
|
9556
|
+
function drawPieChartValues(chart, options, ctx) {
|
|
9557
|
+
for (const dataset of chart._metasets) {
|
|
9558
|
+
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
9559
|
+
const bar = dataset.data[i];
|
|
9560
|
+
const { startAngle, endAngle, innerRadius, outerRadius } = bar;
|
|
9561
|
+
const midAngle = (startAngle + endAngle) / 2;
|
|
9562
|
+
const midRadius = (innerRadius + outerRadius) / 2;
|
|
9563
|
+
const x = bar.x + midRadius * Math.cos(midAngle);
|
|
9564
|
+
const y = bar.y + midRadius * Math.sin(midAngle) + 7;
|
|
9565
|
+
ctx.fillStyle = chartFontColor(options.background);
|
|
9566
|
+
ctx.strokeStyle = options.background || "#ffffff";
|
|
9567
|
+
const value = options.callback(dataset._parsed[i]);
|
|
9568
|
+
drawTextWithBackground(value, x, y, ctx);
|
|
9569
|
+
}
|
|
9570
|
+
}
|
|
9571
|
+
}
|
|
9519
9572
|
|
|
9520
9573
|
/** This is a chartJS plugin that will draw connector lines between the bars of a Waterfall chart */
|
|
9521
9574
|
const waterfallLinesPlugin = {
|
|
@@ -10293,8 +10346,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10293
10346
|
value = value.slice(index + 1);
|
|
10294
10347
|
}
|
|
10295
10348
|
pendingHtmlContent.push({ value });
|
|
10296
|
-
|
|
10297
|
-
return htmlContent;
|
|
10349
|
+
return pendingHtmlContent.filter((content) => content.value);
|
|
10298
10350
|
}
|
|
10299
10351
|
|
|
10300
10352
|
//------------------------------------------------------------------------------
|
|
@@ -10698,7 +10750,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10698
10750
|
assertSquareMatrix(_t("The argument square_matrix must have the same number of columns and rows."), _matrix);
|
|
10699
10751
|
const { inverted } = invertMatrix(_matrix);
|
|
10700
10752
|
if (!inverted) {
|
|
10701
|
-
|
|
10753
|
+
return new EvaluationError(_t("The matrix is not invertible."));
|
|
10702
10754
|
}
|
|
10703
10755
|
return inverted;
|
|
10704
10756
|
},
|
|
@@ -10777,7 +10829,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10777
10829
|
}
|
|
10778
10830
|
}
|
|
10779
10831
|
if (!validPairFound) {
|
|
10780
|
-
|
|
10832
|
+
return new EvaluationError(_t("The arguments array_x and array_y must contain at least one pair of numbers."));
|
|
10781
10833
|
}
|
|
10782
10834
|
return result;
|
|
10783
10835
|
}
|
|
@@ -10858,7 +10910,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10858
10910
|
.flat()
|
|
10859
10911
|
.filter(shouldKeepValue(_ignore));
|
|
10860
10912
|
if (result.length === 0) {
|
|
10861
|
-
|
|
10913
|
+
return new NotAvailableError(_t("No results for the given arguments of TOCOL."));
|
|
10862
10914
|
}
|
|
10863
10915
|
return [result];
|
|
10864
10916
|
},
|
|
@@ -10879,7 +10931,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10879
10931
|
.filter(shouldKeepValue(_ignore))
|
|
10880
10932
|
.map((item) => [item]);
|
|
10881
10933
|
if (result.length === 0 || result[0].length === 0) {
|
|
10882
|
-
|
|
10934
|
+
return new NotAvailableError(_t("No results for the given arguments of TOROW."));
|
|
10883
10935
|
}
|
|
10884
10936
|
return result;
|
|
10885
10937
|
},
|
|
@@ -11439,7 +11491,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
11439
11491
|
* Return error if 'value' is positive.
|
|
11440
11492
|
* Remove '-?' in the next regex to catch this error.
|
|
11441
11493
|
*/
|
|
11442
|
-
assert(() =>
|
|
11494
|
+
assert(() => DECIMAL_REPRESENTATION.test(_value), _t("The value (%s) must be a valid base %s representation.", _value, _base.toString()));
|
|
11443
11495
|
const deci = parseInt(_value, _base);
|
|
11444
11496
|
assert(() => !isNaN(deci), _t("The value (%s) must be a valid base %s representation.", _value, _base.toString()));
|
|
11445
11497
|
return deci;
|
|
@@ -11707,7 +11759,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
11707
11759
|
count += 1;
|
|
11708
11760
|
}
|
|
11709
11761
|
if (isEvaluationError(f)) {
|
|
11710
|
-
|
|
11762
|
+
return j;
|
|
11711
11763
|
}
|
|
11712
11764
|
}
|
|
11713
11765
|
}
|
|
@@ -12210,9 +12262,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
12210
12262
|
}
|
|
12211
12263
|
function variance(args, isSample, textAs0, locale) {
|
|
12212
12264
|
let count = 0;
|
|
12213
|
-
let sum = 0;
|
|
12214
12265
|
const reduceFunction = textAs0 ? reduceNumbersTextAs0 : reduceNumbers;
|
|
12215
|
-
sum = reduceFunction(args, (acc, a) => {
|
|
12266
|
+
const sum = reduceFunction(args, (acc, a) => {
|
|
12216
12267
|
count += 1;
|
|
12217
12268
|
return acc + a;
|
|
12218
12269
|
}, 0, locale);
|
|
@@ -12609,7 +12660,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
12609
12660
|
const flatY = dataY.flat();
|
|
12610
12661
|
assertSameNumberOfElements(flatX, flatY);
|
|
12611
12662
|
if (flatX.length === 0) {
|
|
12612
|
-
|
|
12663
|
+
return new EvaluationError(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
|
|
12613
12664
|
}
|
|
12614
12665
|
const n = flatX.length;
|
|
12615
12666
|
let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
|
|
@@ -13409,9 +13460,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13409
13460
|
// 4 - return for each database row corresponding, the cells corresponding to the field parameter
|
|
13410
13461
|
const fieldCol = database[index];
|
|
13411
13462
|
// Example continuation:: fieldCol = ["C", "j", "k", 7]
|
|
13412
|
-
const matchingCells = [...matchingRows].map((x) => fieldCol[x + 1]);
|
|
13413
13463
|
// Example continuation:: matchingCells = ["j", 7]
|
|
13414
|
-
return
|
|
13464
|
+
return [...matchingRows].map((x) => fieldCol[x + 1]);
|
|
13415
13465
|
}
|
|
13416
13466
|
const databaseArgs = [
|
|
13417
13467
|
arg("database (range)", _t("The array or range containing the data to consider, structured in such a way that the first row contains the labels for each column's values.")),
|
|
@@ -14596,7 +14646,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
14596
14646
|
}
|
|
14597
14647
|
}
|
|
14598
14648
|
if (!result.length) {
|
|
14599
|
-
|
|
14649
|
+
return new NotAvailableError(_t("No match found in FILTER evaluation"));
|
|
14600
14650
|
}
|
|
14601
14651
|
return mode === "row" ? transposeMatrix(result) : result;
|
|
14602
14652
|
},
|
|
@@ -17294,7 +17344,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
17294
17344
|
argsTokens[argPosition].push({ value: token.value, type: token.type });
|
|
17295
17345
|
}
|
|
17296
17346
|
}
|
|
17297
|
-
|
|
17347
|
+
return tokens.map((token, i) => {
|
|
17298
17348
|
if (!["SPACE", "LEFT_PAREN"].includes(token.type)) {
|
|
17299
17349
|
functionStarted = "";
|
|
17300
17350
|
}
|
|
@@ -17332,7 +17382,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
17332
17382
|
}
|
|
17333
17383
|
return token;
|
|
17334
17384
|
});
|
|
17335
|
-
return res;
|
|
17336
17385
|
}
|
|
17337
17386
|
/**
|
|
17338
17387
|
* Parse the list of tokens that compose the arguments of a function to
|
|
@@ -17788,7 +17837,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
17788
17837
|
return result;
|
|
17789
17838
|
}
|
|
17790
17839
|
}
|
|
17791
|
-
|
|
17840
|
+
return new EvaluationError(_t("No match."));
|
|
17792
17841
|
},
|
|
17793
17842
|
isExported: true,
|
|
17794
17843
|
};
|
|
@@ -17952,8 +18001,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
17952
18001
|
let cellReference;
|
|
17953
18002
|
if (_useA1Notation) {
|
|
17954
18003
|
const rangePart = {
|
|
17955
|
-
rowFixed: [1, 2].includes(_absoluteRelativeMode)
|
|
17956
|
-
colFixed: [1, 3].includes(_absoluteRelativeMode)
|
|
18004
|
+
rowFixed: [1, 2].includes(_absoluteRelativeMode),
|
|
18005
|
+
colFixed: [1, 3].includes(_absoluteRelativeMode),
|
|
17957
18006
|
};
|
|
17958
18007
|
cellReference = toXC(colNumber - 1, rowNumber - 1, rangePart);
|
|
17959
18008
|
}
|
|
@@ -17979,7 +18028,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
17979
18028
|
],
|
|
17980
18029
|
compute: function (cellReference) {
|
|
17981
18030
|
if (isEvaluationError(cellReference?.value)) {
|
|
17982
|
-
|
|
18031
|
+
return cellReference;
|
|
17983
18032
|
}
|
|
17984
18033
|
const column = cellReference === undefined
|
|
17985
18034
|
? this.__originCellPosition?.col
|
|
@@ -17997,7 +18046,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
17997
18046
|
args: [arg("range (meta)", _t("The range whose column count will be returned."))],
|
|
17998
18047
|
compute: function (range) {
|
|
17999
18048
|
if (isEvaluationError(range?.value)) {
|
|
18000
|
-
|
|
18049
|
+
return range;
|
|
18001
18050
|
}
|
|
18002
18051
|
const zone = toZone(range.value);
|
|
18003
18052
|
return zone.right - zone.left + 1;
|
|
@@ -18077,11 +18126,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18077
18126
|
compute: function (reference, useA1Notation = { value: true }) {
|
|
18078
18127
|
let _reference = reference?.value?.toString();
|
|
18079
18128
|
if (!_reference) {
|
|
18080
|
-
|
|
18129
|
+
return new InvalidReferenceError(_t("Reference should be defined."));
|
|
18081
18130
|
}
|
|
18082
18131
|
const _useA1Notation = toBoolean(useA1Notation);
|
|
18083
18132
|
if (!_useA1Notation) {
|
|
18084
|
-
|
|
18133
|
+
return new EvaluationError(_t("R1C1 notation is not supported."));
|
|
18085
18134
|
}
|
|
18086
18135
|
const sheetId = this.__originSheetId;
|
|
18087
18136
|
const originPosition = this.__originCellPosition;
|
|
@@ -18093,7 +18142,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18093
18142
|
}
|
|
18094
18143
|
const range = this.getters.getRangeFromSheetXC(sheetId, _reference);
|
|
18095
18144
|
if (range === undefined || range.invalidXc || range.invalidSheetName) {
|
|
18096
|
-
|
|
18145
|
+
return new InvalidReferenceError();
|
|
18097
18146
|
}
|
|
18098
18147
|
if (originPosition) {
|
|
18099
18148
|
this.addDependencies?.(originPosition, [range]);
|
|
@@ -18201,7 +18250,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18201
18250
|
],
|
|
18202
18251
|
compute: function (cellReference) {
|
|
18203
18252
|
if (isEvaluationError(cellReference?.value)) {
|
|
18204
|
-
|
|
18253
|
+
return cellReference;
|
|
18205
18254
|
}
|
|
18206
18255
|
const row = cellReference === undefined
|
|
18207
18256
|
? this.__originCellPosition?.row
|
|
@@ -18219,7 +18268,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18219
18268
|
args: [arg("range (meta)", _t("The range whose row count will be returned."))],
|
|
18220
18269
|
compute: function (range) {
|
|
18221
18270
|
if (isEvaluationError(range?.value)) {
|
|
18222
|
-
|
|
18271
|
+
return range;
|
|
18223
18272
|
}
|
|
18224
18273
|
const zone = toZone(range.value);
|
|
18225
18274
|
return zone.bottom - zone.top + 1;
|
|
@@ -18406,11 +18455,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18406
18455
|
const _pivotFormulaId = toString(pivotFormulaId);
|
|
18407
18456
|
const _rowCount = toNumber(rowCount, this.locale);
|
|
18408
18457
|
if (_rowCount < 0) {
|
|
18409
|
-
|
|
18458
|
+
return new EvaluationError(_t("The number of rows must be positive."));
|
|
18410
18459
|
}
|
|
18411
18460
|
const _columnCount = toNumber(columnCount, this.locale);
|
|
18412
18461
|
if (_columnCount < 0) {
|
|
18413
|
-
|
|
18462
|
+
return new EvaluationError(_t("The number of columns must be positive."));
|
|
18414
18463
|
}
|
|
18415
18464
|
const _includeColumnHeaders = toBoolean(includeColumnHeaders);
|
|
18416
18465
|
const _includedTotal = toBoolean(includeTotal);
|
|
@@ -18609,6 +18658,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18609
18658
|
arg("value2 (any)", _t("The value to test against value1 for equality.")),
|
|
18610
18659
|
],
|
|
18611
18660
|
compute: function (value1, value2) {
|
|
18661
|
+
if (isEvaluationError(value1?.value)) {
|
|
18662
|
+
return value1;
|
|
18663
|
+
}
|
|
18664
|
+
if (isEvaluationError(value2?.value)) {
|
|
18665
|
+
return value2;
|
|
18666
|
+
}
|
|
18612
18667
|
let _value1 = isEmpty(value1) ? getNeutral[typeof value2?.value] : value1?.value;
|
|
18613
18668
|
let _value2 = isEmpty(value2) ? getNeutral[typeof value1?.value] : value2?.value;
|
|
18614
18669
|
if (typeof _value1 === "string") {
|
|
@@ -18617,27 +18672,21 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18617
18672
|
if (typeof _value2 === "string") {
|
|
18618
18673
|
_value2 = _value2.toUpperCase();
|
|
18619
18674
|
}
|
|
18620
|
-
|
|
18621
|
-
throw value1;
|
|
18622
|
-
}
|
|
18623
|
-
if (isEvaluationError(_value2)) {
|
|
18624
|
-
throw value2;
|
|
18625
|
-
}
|
|
18626
|
-
return _value1 === _value2;
|
|
18675
|
+
return { value: _value1 === _value2 };
|
|
18627
18676
|
},
|
|
18628
18677
|
};
|
|
18629
18678
|
// -----------------------------------------------------------------------------
|
|
18630
18679
|
// GT
|
|
18631
18680
|
// -----------------------------------------------------------------------------
|
|
18632
18681
|
function applyRelationalOperator(value1, value2, cb) {
|
|
18633
|
-
|
|
18634
|
-
|
|
18635
|
-
if (isEvaluationError(_value1)) {
|
|
18636
|
-
throw value1;
|
|
18682
|
+
if (isEvaluationError(value1?.value)) {
|
|
18683
|
+
return value1;
|
|
18637
18684
|
}
|
|
18638
|
-
if (isEvaluationError(
|
|
18639
|
-
|
|
18685
|
+
if (isEvaluationError(value2?.value)) {
|
|
18686
|
+
return value2;
|
|
18640
18687
|
}
|
|
18688
|
+
let _value1 = isEmpty(value1) ? getNeutral[typeof value2?.value] : value1?.value;
|
|
18689
|
+
let _value2 = isEmpty(value2) ? getNeutral[typeof value1?.value] : value2?.value;
|
|
18641
18690
|
if (typeof _value1 !== "number") {
|
|
18642
18691
|
_value1 = toString(_value1).toUpperCase();
|
|
18643
18692
|
}
|
|
@@ -18647,12 +18696,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18647
18696
|
const tV1 = typeof _value1;
|
|
18648
18697
|
const tV2 = typeof _value2;
|
|
18649
18698
|
if (tV1 === "string" && tV2 === "number") {
|
|
18650
|
-
return true;
|
|
18699
|
+
return { value: true };
|
|
18651
18700
|
}
|
|
18652
18701
|
if (tV2 === "string" && tV1 === "number") {
|
|
18653
|
-
return false;
|
|
18702
|
+
return { value: false };
|
|
18654
18703
|
}
|
|
18655
|
-
return cb(_value1, _value2);
|
|
18704
|
+
return { value: cb(_value1, _value2) };
|
|
18656
18705
|
}
|
|
18657
18706
|
const GT = {
|
|
18658
18707
|
description: _t("Strictly greater than."),
|
|
@@ -18691,7 +18740,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18691
18740
|
arg("value2 (any)", _t("The second value.")),
|
|
18692
18741
|
],
|
|
18693
18742
|
compute: function (value1, value2) {
|
|
18694
|
-
|
|
18743
|
+
const result = GTE.compute.bind(this)(value1, value2);
|
|
18744
|
+
if (isEvaluationError(result.value)) {
|
|
18745
|
+
return result;
|
|
18746
|
+
}
|
|
18747
|
+
return { value: !result.value };
|
|
18695
18748
|
},
|
|
18696
18749
|
};
|
|
18697
18750
|
// -----------------------------------------------------------------------------
|
|
@@ -18704,7 +18757,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18704
18757
|
arg("value2 (any)", _t("The second value.")),
|
|
18705
18758
|
],
|
|
18706
18759
|
compute: function (value1, value2) {
|
|
18707
|
-
|
|
18760
|
+
const result = GT.compute.bind(this)(value1, value2);
|
|
18761
|
+
if (isEvaluationError(result.value)) {
|
|
18762
|
+
return result;
|
|
18763
|
+
}
|
|
18764
|
+
return { value: !result.value };
|
|
18708
18765
|
},
|
|
18709
18766
|
};
|
|
18710
18767
|
// -----------------------------------------------------------------------------
|
|
@@ -18749,7 +18806,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18749
18806
|
arg("value2 (any)", _t("The value to test against value1 for inequality.")),
|
|
18750
18807
|
],
|
|
18751
18808
|
compute: function (value1, value2) {
|
|
18752
|
-
|
|
18809
|
+
const result = EQ.compute.bind(this)(value1, value2);
|
|
18810
|
+
if (isEvaluationError(result.value)) {
|
|
18811
|
+
return result;
|
|
18812
|
+
}
|
|
18813
|
+
return { value: !result.value };
|
|
18753
18814
|
},
|
|
18754
18815
|
};
|
|
18755
18816
|
// -----------------------------------------------------------------------------
|
|
@@ -19908,13 +19969,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
19908
19969
|
}
|
|
19909
19970
|
function getElementMargins(el) {
|
|
19910
19971
|
const style = window.getComputedStyle(el);
|
|
19911
|
-
|
|
19972
|
+
return {
|
|
19912
19973
|
top: parseInt(style.marginTop, 10) || 0,
|
|
19913
19974
|
bottom: parseInt(style.marginBottom, 10) || 0,
|
|
19914
19975
|
left: parseInt(style.marginLeft, 10) || 0,
|
|
19915
19976
|
right: parseInt(style.marginRight, 10) || 0,
|
|
19916
19977
|
};
|
|
19917
|
-
return margins;
|
|
19918
19978
|
}
|
|
19919
19979
|
|
|
19920
19980
|
const macRegex = /Mac/i;
|
|
@@ -21789,9 +21849,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21789
21849
|
const colFields = columns.map((groupBy) => groupBy.nameWithGranularity);
|
|
21790
21850
|
const rowFields = rows.map((groupBy) => groupBy.nameWithGranularity);
|
|
21791
21851
|
const proposals = [];
|
|
21792
|
-
|
|
21852
|
+
let previousGroupBy = ["ARG_SEPARATOR", "SPACE"].includes(tokenAtCursor.type)
|
|
21793
21853
|
? argGroupBys.at(-1)
|
|
21794
21854
|
: argGroupBys.at(-2);
|
|
21855
|
+
const isPositionalSupported = supportedPivotPositionalFormulaRegistry.get(pivot.type);
|
|
21856
|
+
if (isPositionalSupported && previousGroupBy?.startsWith("#")) {
|
|
21857
|
+
previousGroupBy = previousGroupBy.slice(1);
|
|
21858
|
+
}
|
|
21795
21859
|
if (previousGroupBy === undefined) {
|
|
21796
21860
|
proposals.push(colFields[0]);
|
|
21797
21861
|
proposals.push(rowFields[0]);
|
|
@@ -21813,7 +21877,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21813
21877
|
return field ? makeFieldProposal(field, granularity) : undefined;
|
|
21814
21878
|
})
|
|
21815
21879
|
.concat(groupBys.map((groupBy) => {
|
|
21816
|
-
if (!
|
|
21880
|
+
if (!isPositionalSupported) {
|
|
21817
21881
|
return undefined;
|
|
21818
21882
|
}
|
|
21819
21883
|
const fieldName = groupBy.split(":")[0];
|
|
@@ -21822,13 +21886,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21822
21886
|
return undefined;
|
|
21823
21887
|
}
|
|
21824
21888
|
const positionalFieldArg = `"#${groupBy}"`;
|
|
21825
|
-
|
|
21889
|
+
return {
|
|
21826
21890
|
text: positionalFieldArg,
|
|
21827
21891
|
description: _t("%s (positional)", field.string) + (field.help ? ` (${field.help})` : ""),
|
|
21828
21892
|
htmlContent: [{ value: positionalFieldArg, color: tokenColors.STRING }],
|
|
21829
21893
|
fuzzySearchKey: field.string + positionalFieldArg, // search on translated name and on technical name
|
|
21830
21894
|
};
|
|
21831
|
-
return positionalProposal;
|
|
21832
21895
|
}))
|
|
21833
21896
|
.filter(isDefined);
|
|
21834
21897
|
},
|
|
@@ -22097,7 +22160,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22097
22160
|
return internalDate.value;
|
|
22098
22161
|
}
|
|
22099
22162
|
if (isBoolean(content)) {
|
|
22100
|
-
return content.toUpperCase() === "TRUE"
|
|
22163
|
+
return content.toUpperCase() === "TRUE";
|
|
22101
22164
|
}
|
|
22102
22165
|
return content;
|
|
22103
22166
|
}
|
|
@@ -22438,8 +22501,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22438
22501
|
return 0;
|
|
22439
22502
|
}
|
|
22440
22503
|
const previous = jsDates[index - 1];
|
|
22441
|
-
|
|
22442
|
-
return days;
|
|
22504
|
+
return Math.floor(date.getTime()) - Math.floor(previous.getTime());
|
|
22443
22505
|
})
|
|
22444
22506
|
.slice(1);
|
|
22445
22507
|
const equidistantDates = timeIntervals.every((interval) => interval === timeIntervals[0]);
|
|
@@ -22998,6 +23060,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22998
23060
|
"surface3DChart",
|
|
22999
23061
|
"bubbleChart",
|
|
23000
23062
|
"comboChart",
|
|
23063
|
+
"radarChart",
|
|
23001
23064
|
];
|
|
23002
23065
|
|
|
23003
23066
|
/** In XLSX color format (no #) */
|
|
@@ -23538,7 +23601,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23538
23601
|
lineChart: "line",
|
|
23539
23602
|
line3DChart: undefined,
|
|
23540
23603
|
stockChart: undefined,
|
|
23541
|
-
radarChart:
|
|
23604
|
+
radarChart: "radar",
|
|
23542
23605
|
scatterChart: "scatter",
|
|
23543
23606
|
pieChart: "pie",
|
|
23544
23607
|
pie3DChart: undefined,
|
|
@@ -24951,7 +25014,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24951
25014
|
custom: _t("Custom"),
|
|
24952
25015
|
};
|
|
24953
25016
|
const DEFAULT_TABLE_CONFIG = {
|
|
24954
|
-
hasFilters:
|
|
25017
|
+
hasFilters: false,
|
|
24955
25018
|
totalRow: false,
|
|
24956
25019
|
firstColumn: false,
|
|
24957
25020
|
lastColumn: false,
|
|
@@ -25620,12 +25683,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
25620
25683
|
* Get the list of all the XLSX files in the XLSX file structure
|
|
25621
25684
|
*/
|
|
25622
25685
|
getListOfXMLFiles() {
|
|
25623
|
-
|
|
25686
|
+
return Object.entries(this.xlsxFileStructure)
|
|
25624
25687
|
.filter(([key]) => key !== "images")
|
|
25625
25688
|
.map(([_, value]) => value)
|
|
25626
25689
|
.flat()
|
|
25627
25690
|
.filter(isDefined);
|
|
25628
|
-
return XMLFiles;
|
|
25629
25691
|
}
|
|
25630
25692
|
/**
|
|
25631
25693
|
* Return an array containing the return value of the given function applied to all the XML elements
|
|
@@ -25789,13 +25851,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
25789
25851
|
rgb = this.extractAttr(colorElement, "rgb")?.asString();
|
|
25790
25852
|
rgb = rgb === DEFAULT_SYSTEM_COLOR ? undefined : rgb;
|
|
25791
25853
|
}
|
|
25792
|
-
|
|
25854
|
+
return {
|
|
25793
25855
|
rgb: rgb || defaultColor,
|
|
25794
25856
|
auto: this.extractAttr(colorElement, "auto")?.asBool(),
|
|
25795
25857
|
indexed: this.extractAttr(colorElement, "indexed")?.asNum(),
|
|
25796
25858
|
tint: this.extractAttr(colorElement, "tint")?.asNum(),
|
|
25797
25859
|
};
|
|
25798
|
-
return color;
|
|
25799
25860
|
}
|
|
25800
25861
|
/**
|
|
25801
25862
|
* Returns the xml file targeted by a relationship.
|
|
@@ -26387,7 +26448,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26387
26448
|
hyperlinks: this.extractHyperLinks(sheetElement),
|
|
26388
26449
|
tables: this.extractTables(sheetElement),
|
|
26389
26450
|
pivotTables: this.extractPivotTables(),
|
|
26390
|
-
isVisible: sheetWorkbookInfo.state === "visible"
|
|
26451
|
+
isVisible: sheetWorkbookInfo.state === "visible",
|
|
26391
26452
|
};
|
|
26392
26453
|
})[0];
|
|
26393
26454
|
}
|
|
@@ -26458,8 +26519,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26458
26519
|
const figures = this.mapOnElements({ parent: worksheet, query: "drawing" }, (drawingElement) => {
|
|
26459
26520
|
const drawingId = this.extractAttr(drawingElement, "r:id", { required: true })?.asString();
|
|
26460
26521
|
const drawingFile = this.getTargetXmlFile(this.relationships[drawingId]);
|
|
26461
|
-
|
|
26462
|
-
return figures;
|
|
26522
|
+
return new XlsxFigureExtractor(drawingFile, this.xlsxFileStructure, this.warningManager).extractFigures();
|
|
26463
26523
|
})[0];
|
|
26464
26524
|
return figures || [];
|
|
26465
26525
|
}
|
|
@@ -26477,8 +26537,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26477
26537
|
.filter((relationship) => relationship.type.endsWith("pivotTable"))
|
|
26478
26538
|
.map((pivotRelationship) => {
|
|
26479
26539
|
const pivotFile = this.getTargetXmlFile(pivotRelationship);
|
|
26480
|
-
|
|
26481
|
-
return pivot;
|
|
26540
|
+
return new XlsxPivotExtractor(pivotFile, this.xlsxFileStructure, this.warningManager).getPivotTable();
|
|
26482
26541
|
});
|
|
26483
26542
|
}
|
|
26484
26543
|
catch (e) {
|
|
@@ -26877,8 +26936,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26877
26936
|
}
|
|
26878
26937
|
convertXlsx() {
|
|
26879
26938
|
const xlsxData = this.getXlsxData();
|
|
26880
|
-
|
|
26881
|
-
return convertedData;
|
|
26939
|
+
return this.convertImportedData(xlsxData);
|
|
26882
26940
|
}
|
|
26883
26941
|
// ---------------------------------------------------------------------------
|
|
26884
26942
|
// Parsing XMLs
|
|
@@ -27469,6 +27527,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27469
27527
|
}
|
|
27470
27528
|
return data;
|
|
27471
27529
|
},
|
|
27530
|
+
})
|
|
27531
|
+
.add("migration_22", {
|
|
27532
|
+
// "tables are no longer inserted with filters by default",
|
|
27533
|
+
versionFrom: "22",
|
|
27534
|
+
migrate(data) {
|
|
27535
|
+
for (const sheet of data.sheets || []) {
|
|
27536
|
+
for (const table of sheet.tables || []) {
|
|
27537
|
+
if (!table.config) {
|
|
27538
|
+
table.config = { ...DEFAULT_TABLE_CONFIG, hasFilters: true };
|
|
27539
|
+
}
|
|
27540
|
+
}
|
|
27541
|
+
}
|
|
27542
|
+
return data;
|
|
27543
|
+
},
|
|
27472
27544
|
});
|
|
27473
27545
|
function fixOverlappingFilters(data) {
|
|
27474
27546
|
for (let sheet of data.sheets || []) {
|
|
@@ -27496,7 +27568,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27496
27568
|
* a breaking change is made in the way the state is handled, and an upgrade
|
|
27497
27569
|
* function should be defined
|
|
27498
27570
|
*/
|
|
27499
|
-
const CURRENT_VERSION =
|
|
27571
|
+
const CURRENT_VERSION = 23;
|
|
27500
27572
|
const INITIAL_SHEET_ID = "Sheet1";
|
|
27501
27573
|
/**
|
|
27502
27574
|
* This function tries to load anything that could look like a valid
|
|
@@ -27509,7 +27581,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27509
27581
|
if (!data) {
|
|
27510
27582
|
return createEmptyWorkbookData();
|
|
27511
27583
|
}
|
|
27512
|
-
console.
|
|
27584
|
+
console.debug("### Loading data ###");
|
|
27513
27585
|
const start = performance.now();
|
|
27514
27586
|
if (data["[Content_Types].xml"]) {
|
|
27515
27587
|
const reader = new XlsxReader(data);
|
|
@@ -27523,13 +27595,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27523
27595
|
// apply migrations, if needed
|
|
27524
27596
|
if ("version" in data) {
|
|
27525
27597
|
if (data.version < CURRENT_VERSION) {
|
|
27526
|
-
console.
|
|
27598
|
+
console.debug("Migrating data from version", data.version);
|
|
27527
27599
|
data = migrate(data);
|
|
27528
27600
|
}
|
|
27529
27601
|
}
|
|
27530
27602
|
data = repairData(data);
|
|
27531
|
-
console.
|
|
27532
|
-
console.
|
|
27603
|
+
console.debug("Data loaded in", performance.now() - start, "ms");
|
|
27604
|
+
console.debug("###");
|
|
27533
27605
|
return data;
|
|
27534
27606
|
}
|
|
27535
27607
|
// -----------------------------------------------------------------------------
|
|
@@ -27559,7 +27631,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27559
27631
|
for (let i = index; i < steps.length; i++) {
|
|
27560
27632
|
data = steps[i].migrate(data);
|
|
27561
27633
|
}
|
|
27562
|
-
console.
|
|
27634
|
+
console.debug("Data migrated in", performance.now() - start, "ms");
|
|
27563
27635
|
return data;
|
|
27564
27636
|
}
|
|
27565
27637
|
/**
|
|
@@ -27741,7 +27813,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27741
27813
|
};
|
|
27742
27814
|
}
|
|
27743
27815
|
function createEmptyWorkbookData(sheetName = "Sheet1") {
|
|
27744
|
-
|
|
27816
|
+
return {
|
|
27745
27817
|
version: CURRENT_VERSION,
|
|
27746
27818
|
sheets: [createEmptySheet(INITIAL_SHEET_ID, sheetName)],
|
|
27747
27819
|
styles: {},
|
|
@@ -27754,7 +27826,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27754
27826
|
pivotNextId: 1,
|
|
27755
27827
|
customTableStyles: {},
|
|
27756
27828
|
};
|
|
27757
|
-
return data;
|
|
27758
27829
|
}
|
|
27759
27830
|
function createEmptyExcelSheet(sheetId, name) {
|
|
27760
27831
|
return {
|
|
@@ -28138,7 +28209,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28138
28209
|
const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
|
|
28139
28210
|
// tooltipItem.parsed can be an object or a number for pie charts
|
|
28140
28211
|
let yLabel = horizontalChart ? tooltipItem.parsed.x : tooltipItem.parsed.y;
|
|
28141
|
-
if (
|
|
28212
|
+
if (yLabel === undefined || yLabel === null) {
|
|
28142
28213
|
yLabel = tooltipItem.parsed;
|
|
28143
28214
|
}
|
|
28144
28215
|
const axisId = horizontalChart
|
|
@@ -28532,8 +28603,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28532
28603
|
};
|
|
28533
28604
|
config.data.datasets.push(dataset);
|
|
28534
28605
|
if (definition.dataSets?.[index]?.label) {
|
|
28535
|
-
|
|
28536
|
-
dataset.label = label;
|
|
28606
|
+
dataset.label = definition.dataSets[index].label;
|
|
28537
28607
|
}
|
|
28538
28608
|
dataset.yAxisID = chart.horizontal ? "y" : definition.dataSets[index].yAxisId || "y";
|
|
28539
28609
|
dataset.xAxisID = "x";
|
|
@@ -28561,13 +28631,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28561
28631
|
* datasets to ensure the way we distinguish the originals and trendLine datasets after
|
|
28562
28632
|
*/
|
|
28563
28633
|
trendDatasets.forEach((x) => config.data.datasets.push(x));
|
|
28564
|
-
const originalTooltipTitle = config.options.plugins.tooltip.callbacks.title;
|
|
28565
28634
|
config.options.plugins.tooltip.callbacks.title = function (tooltipItems) {
|
|
28566
|
-
|
|
28567
|
-
|
|
28568
|
-
|
|
28569
|
-
}
|
|
28570
|
-
return "";
|
|
28635
|
+
return tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID)
|
|
28636
|
+
? undefined
|
|
28637
|
+
: "";
|
|
28571
28638
|
};
|
|
28572
28639
|
}
|
|
28573
28640
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
@@ -28905,7 +28972,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28905
28972
|
else if (axisType === "linear") {
|
|
28906
28973
|
config.options.scales.x.type = "linear";
|
|
28907
28974
|
config.options.scales.x.ticks.callback = (value) => formatValue(value, { format: labelFormat, locale });
|
|
28908
|
-
config.options.plugins.tooltip.callbacks.title = () => "";
|
|
28909
28975
|
config.options.plugins.tooltip.callbacks.label = (tooltipItem) => {
|
|
28910
28976
|
const dataSetPoint = dataSetsValues[tooltipItem.datasetIndex].data[tooltipItem.dataIndex];
|
|
28911
28977
|
let label = tooltipItem.label || labelValues.values[tooltipItem.dataIndex];
|
|
@@ -28960,8 +29026,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28960
29026
|
const trendDatasets = [];
|
|
28961
29027
|
for (const [index, dataset] of config.data.datasets.entries()) {
|
|
28962
29028
|
if (definition.dataSets?.[index]?.label) {
|
|
28963
|
-
|
|
28964
|
-
dataset.label = label;
|
|
29029
|
+
dataset.label = definition.dataSets[index].label;
|
|
28965
29030
|
}
|
|
28966
29031
|
dataset["yAxisID"] = definition.dataSets[index].yAxisId || "y";
|
|
28967
29032
|
const trend = definition.dataSets?.[index].trend;
|
|
@@ -28990,15 +29055,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28990
29055
|
* distinguish the originals and trendLine datasets after
|
|
28991
29056
|
*/
|
|
28992
29057
|
trendDatasets.forEach((x) => config.data.datasets.push(x));
|
|
28993
|
-
const originalTooltipTitle = config.options.plugins.tooltip.callbacks.title;
|
|
28994
|
-
config.options.plugins.tooltip.callbacks.title = function (tooltipItems) {
|
|
28995
|
-
if (tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID)) {
|
|
28996
|
-
// @ts-expect-error
|
|
28997
|
-
return originalTooltipTitle?.(tooltipItems);
|
|
28998
|
-
}
|
|
28999
|
-
return "";
|
|
29000
|
-
};
|
|
29001
29058
|
}
|
|
29059
|
+
config.options.plugins.tooltip.callbacks.title = function (tooltipItems) {
|
|
29060
|
+
const displayTooltipTitle = axisType !== "linear" &&
|
|
29061
|
+
tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID);
|
|
29062
|
+
return displayTooltipTitle ? undefined : "";
|
|
29063
|
+
};
|
|
29002
29064
|
return {
|
|
29003
29065
|
chartJsConfig: config,
|
|
29004
29066
|
background: chart.background || BACKGROUND_CHART_COLOR,
|
|
@@ -29221,13 +29283,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29221
29283
|
* distinguish the originals and trendLine datasets after
|
|
29222
29284
|
*/
|
|
29223
29285
|
trendDatasets.forEach((x) => config.data.datasets.push(x));
|
|
29224
|
-
const originalTooltipTitle = config.options.plugins.tooltip.callbacks.title;
|
|
29225
29286
|
config.options.plugins.tooltip.callbacks.title = function (tooltipItems) {
|
|
29226
|
-
|
|
29227
|
-
|
|
29228
|
-
|
|
29229
|
-
}
|
|
29230
|
-
return "";
|
|
29287
|
+
return tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID)
|
|
29288
|
+
? undefined
|
|
29289
|
+
: "";
|
|
29231
29290
|
};
|
|
29232
29291
|
}
|
|
29233
29292
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
@@ -29966,6 +30025,198 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29966
30025
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
29967
30026
|
}
|
|
29968
30027
|
|
|
30028
|
+
class RadarChart extends AbstractChart {
|
|
30029
|
+
dataSets;
|
|
30030
|
+
labelRange;
|
|
30031
|
+
background;
|
|
30032
|
+
legendPosition;
|
|
30033
|
+
stacked;
|
|
30034
|
+
aggregated;
|
|
30035
|
+
type = "radar";
|
|
30036
|
+
dataSetsHaveTitle;
|
|
30037
|
+
dataSetDesign;
|
|
30038
|
+
fillArea;
|
|
30039
|
+
constructor(definition, sheetId, getters) {
|
|
30040
|
+
super(definition, sheetId, getters);
|
|
30041
|
+
this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
30042
|
+
this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
|
|
30043
|
+
this.background = definition.background;
|
|
30044
|
+
this.legendPosition = definition.legendPosition;
|
|
30045
|
+
this.stacked = definition.stacked;
|
|
30046
|
+
this.aggregated = definition.aggregated;
|
|
30047
|
+
this.dataSetsHaveTitle = definition.dataSetsHaveTitle;
|
|
30048
|
+
this.dataSetDesign = definition.dataSets;
|
|
30049
|
+
this.fillArea = definition.fillArea;
|
|
30050
|
+
}
|
|
30051
|
+
static transformDefinition(definition, executed) {
|
|
30052
|
+
return transformChartDefinitionWithDataSetsWithZone(definition, executed);
|
|
30053
|
+
}
|
|
30054
|
+
static validateChartDefinition(validator, definition) {
|
|
30055
|
+
return validator.checkValidations(definition, checkDataset, checkLabelRange);
|
|
30056
|
+
}
|
|
30057
|
+
static getDefinitionFromContextCreation(context) {
|
|
30058
|
+
return {
|
|
30059
|
+
background: context.background,
|
|
30060
|
+
dataSets: context.range ?? [],
|
|
30061
|
+
dataSetsHaveTitle: context.dataSetsHaveTitle ?? false,
|
|
30062
|
+
stacked: context.stacked ?? false,
|
|
30063
|
+
aggregated: context.aggregated ?? false,
|
|
30064
|
+
legendPosition: context.legendPosition ?? "top",
|
|
30065
|
+
title: context.title || { text: "" },
|
|
30066
|
+
type: "radar",
|
|
30067
|
+
labelRange: context.auxiliaryRange || undefined,
|
|
30068
|
+
fillArea: context.fillArea ?? false,
|
|
30069
|
+
};
|
|
30070
|
+
}
|
|
30071
|
+
getContextCreation() {
|
|
30072
|
+
const range = [];
|
|
30073
|
+
for (const [i, dataSet] of this.dataSets.entries()) {
|
|
30074
|
+
range.push({
|
|
30075
|
+
...this.dataSetDesign?.[i],
|
|
30076
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, this.sheetId),
|
|
30077
|
+
});
|
|
30078
|
+
}
|
|
30079
|
+
return {
|
|
30080
|
+
...this,
|
|
30081
|
+
range,
|
|
30082
|
+
auxiliaryRange: this.labelRange
|
|
30083
|
+
? this.getters.getRangeString(this.labelRange, this.sheetId)
|
|
30084
|
+
: undefined,
|
|
30085
|
+
};
|
|
30086
|
+
}
|
|
30087
|
+
copyForSheetId(sheetId) {
|
|
30088
|
+
const dataSets = copyDataSetsWithNewSheetId(this.sheetId, sheetId, this.dataSets);
|
|
30089
|
+
const labelRange = copyLabelRangeWithNewSheetId(this.sheetId, sheetId, this.labelRange);
|
|
30090
|
+
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange, sheetId);
|
|
30091
|
+
return new RadarChart(definition, sheetId, this.getters);
|
|
30092
|
+
}
|
|
30093
|
+
copyInSheetId(sheetId) {
|
|
30094
|
+
const definition = this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange, sheetId);
|
|
30095
|
+
return new RadarChart(definition, sheetId, this.getters);
|
|
30096
|
+
}
|
|
30097
|
+
getDefinition() {
|
|
30098
|
+
return this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange);
|
|
30099
|
+
}
|
|
30100
|
+
getDefinitionWithSpecificDataSets(dataSets, labelRange, targetSheetId) {
|
|
30101
|
+
const ranges = [];
|
|
30102
|
+
for (const [i, dataSet] of dataSets.entries()) {
|
|
30103
|
+
ranges.push({
|
|
30104
|
+
...this.dataSetDesign?.[i],
|
|
30105
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, targetSheetId || this.sheetId),
|
|
30106
|
+
});
|
|
30107
|
+
}
|
|
30108
|
+
return {
|
|
30109
|
+
type: "radar",
|
|
30110
|
+
dataSetsHaveTitle: dataSets.length ? Boolean(dataSets[0].labelCell) : false,
|
|
30111
|
+
background: this.background,
|
|
30112
|
+
dataSets: ranges,
|
|
30113
|
+
legendPosition: this.legendPosition,
|
|
30114
|
+
labelRange: labelRange
|
|
30115
|
+
? this.getters.getRangeString(labelRange, targetSheetId || this.sheetId)
|
|
30116
|
+
: undefined,
|
|
30117
|
+
title: this.title,
|
|
30118
|
+
stacked: this.stacked,
|
|
30119
|
+
aggregated: this.aggregated,
|
|
30120
|
+
fillArea: this.fillArea,
|
|
30121
|
+
};
|
|
30122
|
+
}
|
|
30123
|
+
getDefinitionForExcel() {
|
|
30124
|
+
if (this.aggregated) {
|
|
30125
|
+
return undefined;
|
|
30126
|
+
}
|
|
30127
|
+
const dataSets = this.dataSets
|
|
30128
|
+
.map((ds) => toExcelDataset(this.getters, ds))
|
|
30129
|
+
.filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
|
|
30130
|
+
const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
|
|
30131
|
+
const definition = this.getDefinition();
|
|
30132
|
+
return {
|
|
30133
|
+
...definition,
|
|
30134
|
+
backgroundColor: toXlsxHexColor(this.background || BACKGROUND_CHART_COLOR),
|
|
30135
|
+
fontColor: toXlsxHexColor(chartFontColor(this.background)),
|
|
30136
|
+
dataSets,
|
|
30137
|
+
labelRange,
|
|
30138
|
+
};
|
|
30139
|
+
}
|
|
30140
|
+
updateRanges(applyChange) {
|
|
30141
|
+
const { dataSets, labelRange, isStale } = updateChartRangesWithDataSets(this.getters, applyChange, this.dataSets, this.labelRange);
|
|
30142
|
+
if (!isStale) {
|
|
30143
|
+
return this;
|
|
30144
|
+
}
|
|
30145
|
+
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange);
|
|
30146
|
+
return new RadarChart(definition, this.sheetId, this.getters);
|
|
30147
|
+
}
|
|
30148
|
+
}
|
|
30149
|
+
function createRadarChartRuntime(chart, getters) {
|
|
30150
|
+
const definition = chart.getDefinition();
|
|
30151
|
+
const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
|
|
30152
|
+
let labels = labelValues.formattedValues;
|
|
30153
|
+
let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
|
|
30154
|
+
if (chart.dataSetsHaveTitle &&
|
|
30155
|
+
dataSetsValues[0] &&
|
|
30156
|
+
labels.length > dataSetsValues[0].data.length) {
|
|
30157
|
+
labels.shift();
|
|
30158
|
+
}
|
|
30159
|
+
({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
|
|
30160
|
+
if (chart.aggregated) {
|
|
30161
|
+
({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
|
|
30162
|
+
}
|
|
30163
|
+
const leftAxisFormat = getChartDatasetFormat(getters, chart.dataSets, "left");
|
|
30164
|
+
const rightAxisFormat = getChartDatasetFormat(getters, chart.dataSets, "right");
|
|
30165
|
+
const axisFormats = { y: leftAxisFormat, y1: rightAxisFormat };
|
|
30166
|
+
const locale = getters.getLocale();
|
|
30167
|
+
const fontColor = chartFontColor(chart.background);
|
|
30168
|
+
const config = getDefaultChartJsRuntime(chart, labels, fontColor, {
|
|
30169
|
+
axisFormats,
|
|
30170
|
+
locale,
|
|
30171
|
+
});
|
|
30172
|
+
const legend = {
|
|
30173
|
+
labels: { color: fontColor },
|
|
30174
|
+
};
|
|
30175
|
+
if ((!chart.labelRange && chart.dataSets.length === 1) || chart.legendPosition === "none") {
|
|
30176
|
+
legend.display = false;
|
|
30177
|
+
}
|
|
30178
|
+
else {
|
|
30179
|
+
legend.position = chart.legendPosition;
|
|
30180
|
+
}
|
|
30181
|
+
const fill = definition.fillArea ?? false;
|
|
30182
|
+
if (!fill) {
|
|
30183
|
+
legend.labels["boxHeight"] = 0;
|
|
30184
|
+
}
|
|
30185
|
+
config.options.plugins.legend = { ...config.options.plugins?.legend, ...legend };
|
|
30186
|
+
config.options.plugins.tooltip = {
|
|
30187
|
+
...config.options.plugins?.tooltip,
|
|
30188
|
+
callbacks: {
|
|
30189
|
+
label: function (tooltipItem) {
|
|
30190
|
+
const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
|
|
30191
|
+
const yLabel = tooltipItem.parsed.r;
|
|
30192
|
+
return xLabel ? `${xLabel}: ${yLabel}` : yLabel.toString();
|
|
30193
|
+
},
|
|
30194
|
+
},
|
|
30195
|
+
};
|
|
30196
|
+
config.options.layout = {
|
|
30197
|
+
padding: { left: 20, right: 20, top: chart.title ? 10 : 25, bottom: 10 },
|
|
30198
|
+
};
|
|
30199
|
+
const colorGenerator = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
30200
|
+
for (let i = 0; i < dataSetsValues.length; i++) {
|
|
30201
|
+
let { label, data } = dataSetsValues[i];
|
|
30202
|
+
if (definition.dataSets?.[i]?.label) {
|
|
30203
|
+
label = definition.dataSets[i].label;
|
|
30204
|
+
}
|
|
30205
|
+
const borderColor = colorGenerator.next();
|
|
30206
|
+
const dataset = {
|
|
30207
|
+
label,
|
|
30208
|
+
data,
|
|
30209
|
+
borderColor,
|
|
30210
|
+
};
|
|
30211
|
+
if (fill) {
|
|
30212
|
+
dataset.backgroundColor = setColorAlpha(borderColor, 0.3);
|
|
30213
|
+
dataset["fill"] = true;
|
|
30214
|
+
}
|
|
30215
|
+
config.data.datasets.push(dataset);
|
|
30216
|
+
}
|
|
30217
|
+
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
30218
|
+
}
|
|
30219
|
+
|
|
29969
30220
|
class ScatterChart extends AbstractChart {
|
|
29970
30221
|
dataSets;
|
|
29971
30222
|
labelRange;
|
|
@@ -30488,6 +30739,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30488
30739
|
getChartDefinitionFromContextCreation: PyramidChart.getDefinitionFromContextCreation,
|
|
30489
30740
|
sequence: 80,
|
|
30490
30741
|
});
|
|
30742
|
+
chartRegistry.add("radar", {
|
|
30743
|
+
match: (type) => type === "radar",
|
|
30744
|
+
createChart: (definition, sheetId, getters) => new RadarChart(definition, sheetId, getters),
|
|
30745
|
+
getChartRuntime: createRadarChartRuntime,
|
|
30746
|
+
validateChartDefinition: RadarChart.validateChartDefinition,
|
|
30747
|
+
transformDefinition: RadarChart.transformDefinition,
|
|
30748
|
+
getChartDefinitionFromContextCreation: RadarChart.getDefinitionFromContextCreation,
|
|
30749
|
+
sequence: 80,
|
|
30750
|
+
});
|
|
30491
30751
|
const chartComponentRegistry = new Registry();
|
|
30492
30752
|
chartComponentRegistry.add("line", ChartJsComponent);
|
|
30493
30753
|
chartComponentRegistry.add("bar", ChartJsComponent);
|
|
@@ -30498,6 +30758,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30498
30758
|
chartComponentRegistry.add("scorecard", ScorecardChart);
|
|
30499
30759
|
chartComponentRegistry.add("waterfall", ChartJsComponent);
|
|
30500
30760
|
chartComponentRegistry.add("pyramid", ChartJsComponent);
|
|
30761
|
+
chartComponentRegistry.add("radar", ChartJsComponent);
|
|
30501
30762
|
const chartCategories = {
|
|
30502
30763
|
line: _t("Line"),
|
|
30503
30764
|
column: _t("Column"),
|
|
@@ -30639,6 +30900,24 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30639
30900
|
chartType: "pyramid",
|
|
30640
30901
|
category: "misc",
|
|
30641
30902
|
preview: "o-spreadsheet-ChartPreview.POPULATION_PYRAMID_CHART",
|
|
30903
|
+
})
|
|
30904
|
+
.add("radar", {
|
|
30905
|
+
matcher: (definition) => definition.type === "radar" && !definition.fillArea,
|
|
30906
|
+
displayName: _t("Radar"),
|
|
30907
|
+
chartSubtype: "radar",
|
|
30908
|
+
chartType: "radar",
|
|
30909
|
+
subtypeDefinition: { fillArea: false },
|
|
30910
|
+
category: "misc",
|
|
30911
|
+
preview: "o-spreadsheet-ChartPreview.RADAR_CHART",
|
|
30912
|
+
})
|
|
30913
|
+
.add("filled_radar", {
|
|
30914
|
+
matcher: (definition) => definition.type === "radar" && !!definition.fillArea,
|
|
30915
|
+
displayName: _t("Filled Radar"),
|
|
30916
|
+
chartType: "radar",
|
|
30917
|
+
chartSubtype: "filled_radar",
|
|
30918
|
+
subtypeDefinition: { fillArea: true },
|
|
30919
|
+
category: "misc",
|
|
30920
|
+
preview: "o-spreadsheet-ChartPreview.FILLED_RADAR_CHART",
|
|
30642
30921
|
});
|
|
30643
30922
|
|
|
30644
30923
|
/**
|
|
@@ -30706,11 +30985,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30706
30985
|
const rect = getters.getVisibleRect(getters.getActiveMainViewport());
|
|
30707
30986
|
const scrollableViewportWidth = Math.min(rect.width, dim.width - offsetCorrectionX);
|
|
30708
30987
|
const scrollableViewportHeight = Math.min(rect.height, dim.height - offsetCorrectionY);
|
|
30709
|
-
|
|
30988
|
+
return {
|
|
30710
30989
|
x: offsetCorrectionX + scrollX + Math.max(0, (scrollableViewportWidth - size.width) / 2),
|
|
30711
30990
|
y: offsetCorrectionY + scrollY + Math.max(0, (scrollableViewportHeight - size.height) / 2),
|
|
30712
30991
|
}; // Position at the center of the scrollable viewport
|
|
30713
|
-
return position;
|
|
30714
30992
|
}
|
|
30715
30993
|
function getMaxFigureSize(getters, figureSize) {
|
|
30716
30994
|
const size = deepCopy(figureSize);
|
|
@@ -31283,14 +31561,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31283
31561
|
const shouldRenderAtBottom = this.shouldRenderAtBottom(elDims.height);
|
|
31284
31562
|
const shouldRenderAtRight = this.shouldRenderAtRight(elDims.width);
|
|
31285
31563
|
verticalOffset = shouldRenderAtBottom ? verticalOffset : -verticalOffset;
|
|
31286
|
-
|
|
31564
|
+
return {
|
|
31287
31565
|
top: this.getTopCoordinate(actualHeight, shouldRenderAtBottom) -
|
|
31288
31566
|
this.spreadsheetOffset.y -
|
|
31289
31567
|
verticalOffset +
|
|
31290
31568
|
"px",
|
|
31291
31569
|
left: this.getLeftCoordinate(actualWidth, shouldRenderAtRight) - this.spreadsheetOffset.x + "px",
|
|
31292
31570
|
};
|
|
31293
|
-
return cssProperties;
|
|
31294
31571
|
}
|
|
31295
31572
|
getCurrentPosition(elDims) {
|
|
31296
31573
|
const shouldRenderAtBottom = this.shouldRenderAtBottom(elDims.height);
|
|
@@ -32518,7 +32795,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
32518
32795
|
* Create a table on the selected zone, with UI warnings to the user if the creation fails.
|
|
32519
32796
|
* If a single cell is selected, expand the selection to non-empty adjacent cells to create a table.
|
|
32520
32797
|
*/
|
|
32521
|
-
function interactiveCreateTable(env, sheetId, tableConfig) {
|
|
32798
|
+
function interactiveCreateTable(env, sheetId, tableConfig = DEFAULT_TABLE_CONFIG) {
|
|
32522
32799
|
let target = env.model.getters.getSelectedZones();
|
|
32523
32800
|
let isDynamic = env.model.getters.canCreateDynamicTableOnZones(sheetId, target);
|
|
32524
32801
|
if (target.length === 1 && !isDynamic && getZoneArea(target[0]) === 1) {
|
|
@@ -33577,7 +33854,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
33577
33854
|
}
|
|
33578
33855
|
|
|
33579
33856
|
const pivotProperties = {
|
|
33580
|
-
name: _t("
|
|
33857
|
+
name: _t("See pivot properties"),
|
|
33581
33858
|
execute(env) {
|
|
33582
33859
|
const position = env.model.getters.getActivePosition();
|
|
33583
33860
|
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
@@ -33731,8 +34008,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
33731
34008
|
})
|
|
33732
34009
|
.add("pivot_properties", {
|
|
33733
34010
|
...pivotProperties,
|
|
33734
|
-
sequence:
|
|
33735
|
-
separator: true,
|
|
34011
|
+
sequence: 170,
|
|
33736
34012
|
});
|
|
33737
34013
|
|
|
33738
34014
|
const sortRange = {
|
|
@@ -35479,6 +35755,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
35479
35755
|
static template = "o_spreadsheet.Section";
|
|
35480
35756
|
static props = {
|
|
35481
35757
|
class: { type: String, optional: true },
|
|
35758
|
+
title: { type: String, optional: true },
|
|
35482
35759
|
slots: Object,
|
|
35483
35760
|
};
|
|
35484
35761
|
}
|
|
@@ -36208,17 +36485,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
36208
36485
|
stacked,
|
|
36209
36486
|
});
|
|
36210
36487
|
}
|
|
36211
|
-
onUpdateAggregated(aggregated) {
|
|
36212
|
-
this.props.updateChart(this.props.figureId, {
|
|
36213
|
-
aggregated,
|
|
36214
|
-
});
|
|
36215
|
-
}
|
|
36216
36488
|
}
|
|
36217
36489
|
|
|
36218
36490
|
css /* scss */ `
|
|
36219
36491
|
.o_side_panel_collapsible_title {
|
|
36220
36492
|
font-size: 16px;
|
|
36221
|
-
font-weight: bold;
|
|
36222
36493
|
cursor: pointer;
|
|
36223
36494
|
padding: 6px 0px 6px 6px !important;
|
|
36224
36495
|
|
|
@@ -36255,49 +36526,40 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
36255
36526
|
static template = "o-spreadsheet-SidePanelCollapsible";
|
|
36256
36527
|
static props = {
|
|
36257
36528
|
slots: Object,
|
|
36529
|
+
title: { type: String, optional: true },
|
|
36258
36530
|
collapsedAtInit: { type: Boolean, optional: true },
|
|
36259
36531
|
class: { type: String, optional: true },
|
|
36260
36532
|
};
|
|
36261
36533
|
currentId = (CURRENT_COLLAPSIBLE_ID++).toString();
|
|
36262
36534
|
}
|
|
36263
36535
|
|
|
36264
|
-
const CIRCLE_SVG = /*xml*/ `
|
|
36265
|
-
<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'>
|
|
36266
|
-
<circle r="2" fill="#FFF"/>
|
|
36267
|
-
</svg>
|
|
36268
|
-
`;
|
|
36269
36536
|
css /* scss */ `
|
|
36270
|
-
.o-
|
|
36271
|
-
|
|
36272
|
-
|
|
36273
|
-
-
|
|
36274
|
-
|
|
36275
|
-
|
|
36276
|
-
height: 14px;
|
|
36277
|
-
border: 1px solid ${GRAY_300};
|
|
36278
|
-
box-sizing: border-box;
|
|
36279
|
-
outline: none;
|
|
36280
|
-
border-radius: 8px;
|
|
36281
|
-
|
|
36282
|
-
&:checked {
|
|
36283
|
-
background: url("data:image/svg+xml,${encodeURIComponent(CIRCLE_SVG)}");
|
|
36284
|
-
background-color: ${ACTION_COLOR};
|
|
36537
|
+
.o-badge-selection {
|
|
36538
|
+
gap: 1px;
|
|
36539
|
+
button.o-button {
|
|
36540
|
+
border-radius: 0;
|
|
36541
|
+
&.selected {
|
|
36542
|
+
color: ${GRAY_900};
|
|
36285
36543
|
border-color: ${ACTION_COLOR};
|
|
36544
|
+
background: ${BADGE_SELECTED_COLOR};
|
|
36545
|
+
font-weight: 600;
|
|
36546
|
+
}
|
|
36547
|
+
|
|
36548
|
+
&:first-child {
|
|
36549
|
+
border-radius: 4px 0 0 4px;
|
|
36550
|
+
}
|
|
36551
|
+
&:last-child {
|
|
36552
|
+
border-radius: 0 4px 4px 0;
|
|
36286
36553
|
}
|
|
36287
36554
|
}
|
|
36288
36555
|
}
|
|
36289
36556
|
`;
|
|
36290
|
-
class
|
|
36291
|
-
static template = "o-spreadsheet.
|
|
36557
|
+
class BadgeSelection extends owl.Component {
|
|
36558
|
+
static template = "o-spreadsheet.BadgeSelection";
|
|
36292
36559
|
static props = {
|
|
36293
36560
|
choices: Array,
|
|
36294
36561
|
onChange: Function,
|
|
36295
|
-
selectedValue:
|
|
36296
|
-
name: String,
|
|
36297
|
-
direction: { type: String, optional: true },
|
|
36298
|
-
};
|
|
36299
|
-
static defaultProps = {
|
|
36300
|
-
direction: "horizontal",
|
|
36562
|
+
selectedValue: String,
|
|
36301
36563
|
};
|
|
36302
36564
|
}
|
|
36303
36565
|
|
|
@@ -36842,86 +37104,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
36842
37104
|
}
|
|
36843
37105
|
}
|
|
36844
37106
|
|
|
36845
|
-
const TRANSPARENT_BACKGROUND_SVG = /*xml*/ `
|
|
36846
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10">
|
|
36847
|
-
<path fill="#d9d9d9" d="M5 5h5v5H5zH0V0h5"/>
|
|
36848
|
-
</svg>
|
|
36849
|
-
`;
|
|
36850
|
-
css /* scss */ `
|
|
36851
|
-
.o-round-color-picker-button {
|
|
36852
|
-
width: 18px;
|
|
36853
|
-
height: 18px;
|
|
36854
|
-
cursor: pointer;
|
|
36855
|
-
border: 1px solid ${GRAY_300};
|
|
36856
|
-
background-position: 1px 1px;
|
|
36857
|
-
background-image: url("data:image/svg+xml,${encodeURIComponent(TRANSPARENT_BACKGROUND_SVG)}");
|
|
36858
|
-
}
|
|
36859
|
-
`;
|
|
36860
|
-
class RoundColorPicker extends owl.Component {
|
|
36861
|
-
static template = "o-spreadsheet.RoundColorPicker";
|
|
36862
|
-
static components = { ColorPickerWidget, Section, ColorPicker };
|
|
36863
|
-
static props = {
|
|
36864
|
-
currentColor: { type: String, optional: true },
|
|
36865
|
-
title: { type: String, optional: true },
|
|
36866
|
-
onColorPicked: Function,
|
|
36867
|
-
};
|
|
36868
|
-
colorPickerButtonRef = owl.useRef("colorPickerButton");
|
|
36869
|
-
state;
|
|
36870
|
-
setup() {
|
|
36871
|
-
this.state = owl.useState({ pickerOpened: false });
|
|
36872
|
-
owl.useExternalListener(window, "click", this.closePicker);
|
|
36873
|
-
}
|
|
36874
|
-
closePicker() {
|
|
36875
|
-
this.state.pickerOpened = false;
|
|
36876
|
-
}
|
|
36877
|
-
togglePicker() {
|
|
36878
|
-
this.state.pickerOpened = !this.state.pickerOpened;
|
|
36879
|
-
}
|
|
36880
|
-
onColorPicked(color) {
|
|
36881
|
-
this.props.onColorPicked(color);
|
|
36882
|
-
this.state.pickerOpened = false;
|
|
36883
|
-
}
|
|
36884
|
-
get colorPickerAnchorRect() {
|
|
36885
|
-
const button = this.colorPickerButtonRef.el;
|
|
36886
|
-
return getBoundingRectAsPOJO(button);
|
|
36887
|
-
}
|
|
36888
|
-
get buttonStyle() {
|
|
36889
|
-
return cssPropertiesToCss({
|
|
36890
|
-
background: this.props.currentColor,
|
|
36891
|
-
});
|
|
36892
|
-
}
|
|
36893
|
-
}
|
|
36894
|
-
|
|
36895
|
-
css /* scss */ `
|
|
36896
|
-
.o-badge-selection {
|
|
36897
|
-
gap: 1px;
|
|
36898
|
-
button.o-button {
|
|
36899
|
-
border-radius: 0;
|
|
36900
|
-
&.selected {
|
|
36901
|
-
color: ${GRAY_900};
|
|
36902
|
-
border-color: ${ACTION_COLOR};
|
|
36903
|
-
background: ${BADGE_SELECTED_COLOR};
|
|
36904
|
-
font-weight: 600;
|
|
36905
|
-
}
|
|
36906
|
-
|
|
36907
|
-
&:first-child {
|
|
36908
|
-
border-radius: 4px 0 0 4px;
|
|
36909
|
-
}
|
|
36910
|
-
&:last-child {
|
|
36911
|
-
border-radius: 0 4px 4px 0;
|
|
36912
|
-
}
|
|
36913
|
-
}
|
|
36914
|
-
}
|
|
36915
|
-
`;
|
|
36916
|
-
class BadgeSelection extends owl.Component {
|
|
36917
|
-
static template = "o-spreadsheet.BadgeSelection";
|
|
36918
|
-
static props = {
|
|
36919
|
-
choices: Array,
|
|
36920
|
-
onChange: Function,
|
|
36921
|
-
selectedValue: String,
|
|
36922
|
-
};
|
|
36923
|
-
}
|
|
36924
|
-
|
|
36925
37107
|
css /* scss */ `
|
|
36926
37108
|
.o-chart-title-designer {
|
|
36927
37109
|
> span {
|
|
@@ -37076,8 +37258,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37076
37258
|
this.props.updateChart(this.props.figureId, { axesDesign });
|
|
37077
37259
|
}
|
|
37078
37260
|
updateAxisEditor(ev) {
|
|
37079
|
-
|
|
37080
|
-
this.state.currentAxis = axis;
|
|
37261
|
+
this.state.currentAxis = ev.target.value;
|
|
37081
37262
|
}
|
|
37082
37263
|
getAxisTitle() {
|
|
37083
37264
|
const axesDesign = this.props.definition.axesDesign ?? {};
|
|
@@ -37096,6 +37277,56 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37096
37277
|
}
|
|
37097
37278
|
}
|
|
37098
37279
|
|
|
37280
|
+
const TRANSPARENT_BACKGROUND_SVG = /*xml*/ `
|
|
37281
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10">
|
|
37282
|
+
<path fill="#d9d9d9" d="M5 5h5v5H5zH0V0h5"/>
|
|
37283
|
+
</svg>
|
|
37284
|
+
`;
|
|
37285
|
+
css /* scss */ `
|
|
37286
|
+
.o-round-color-picker-button {
|
|
37287
|
+
width: 18px;
|
|
37288
|
+
height: 18px;
|
|
37289
|
+
cursor: pointer;
|
|
37290
|
+
border: 1px solid ${GRAY_300};
|
|
37291
|
+
background-position: 1px 1px;
|
|
37292
|
+
background-image: url("data:image/svg+xml,${encodeURIComponent(TRANSPARENT_BACKGROUND_SVG)}");
|
|
37293
|
+
}
|
|
37294
|
+
`;
|
|
37295
|
+
class RoundColorPicker extends owl.Component {
|
|
37296
|
+
static template = "o-spreadsheet.RoundColorPicker";
|
|
37297
|
+
static components = { Section, ColorPicker };
|
|
37298
|
+
static props = {
|
|
37299
|
+
currentColor: { type: String, optional: true },
|
|
37300
|
+
title: { type: String, optional: true },
|
|
37301
|
+
onColorPicked: Function,
|
|
37302
|
+
};
|
|
37303
|
+
colorPickerButtonRef = owl.useRef("colorPickerButton");
|
|
37304
|
+
state;
|
|
37305
|
+
setup() {
|
|
37306
|
+
this.state = owl.useState({ pickerOpened: false });
|
|
37307
|
+
owl.useExternalListener(window, "click", this.closePicker);
|
|
37308
|
+
}
|
|
37309
|
+
closePicker() {
|
|
37310
|
+
this.state.pickerOpened = false;
|
|
37311
|
+
}
|
|
37312
|
+
togglePicker() {
|
|
37313
|
+
this.state.pickerOpened = !this.state.pickerOpened;
|
|
37314
|
+
}
|
|
37315
|
+
onColorPicked(color) {
|
|
37316
|
+
this.props.onColorPicked(color);
|
|
37317
|
+
this.state.pickerOpened = false;
|
|
37318
|
+
}
|
|
37319
|
+
get colorPickerAnchorRect() {
|
|
37320
|
+
const button = this.colorPickerButtonRef.el;
|
|
37321
|
+
return getBoundingRectAsPOJO(button);
|
|
37322
|
+
}
|
|
37323
|
+
get buttonStyle() {
|
|
37324
|
+
return cssPropertiesToCss({
|
|
37325
|
+
background: this.props.currentColor,
|
|
37326
|
+
});
|
|
37327
|
+
}
|
|
37328
|
+
}
|
|
37329
|
+
|
|
37099
37330
|
class GeneralDesignEditor extends owl.Component {
|
|
37100
37331
|
static template = "o-spreadsheet-GeneralDesignEditor";
|
|
37101
37332
|
static components = {
|
|
@@ -37160,58 +37391,75 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37160
37391
|
}
|
|
37161
37392
|
}
|
|
37162
37393
|
|
|
37163
|
-
|
|
37164
|
-
|
|
37394
|
+
const CIRCLE_SVG = /*xml*/ `
|
|
37395
|
+
<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'>
|
|
37396
|
+
<circle r="2" fill="#FFF"/>
|
|
37397
|
+
</svg>
|
|
37398
|
+
`;
|
|
37399
|
+
css /* scss */ `
|
|
37400
|
+
.o-radio {
|
|
37401
|
+
input {
|
|
37402
|
+
appearance: none;
|
|
37403
|
+
-webkit-appearance: none;
|
|
37404
|
+
-moz-appearance: none;
|
|
37405
|
+
width: 14px;
|
|
37406
|
+
height: 14px;
|
|
37407
|
+
border: 1px solid ${GRAY_300};
|
|
37408
|
+
box-sizing: border-box;
|
|
37409
|
+
outline: none;
|
|
37410
|
+
border-radius: 8px;
|
|
37411
|
+
|
|
37412
|
+
&:checked {
|
|
37413
|
+
background: url("data:image/svg+xml,${encodeURIComponent(CIRCLE_SVG)}");
|
|
37414
|
+
background-color: ${ACTION_COLOR};
|
|
37415
|
+
border-color: ${ACTION_COLOR};
|
|
37416
|
+
}
|
|
37417
|
+
}
|
|
37418
|
+
}
|
|
37419
|
+
`;
|
|
37420
|
+
class RadioSelection extends owl.Component {
|
|
37421
|
+
static template = "o-spreadsheet.RadioSelection";
|
|
37422
|
+
static props = {
|
|
37423
|
+
choices: Array,
|
|
37424
|
+
onChange: Function,
|
|
37425
|
+
selectedValue: { optional: false },
|
|
37426
|
+
name: String,
|
|
37427
|
+
direction: { type: String, optional: true },
|
|
37428
|
+
};
|
|
37429
|
+
static defaultProps = {
|
|
37430
|
+
direction: "horizontal",
|
|
37431
|
+
};
|
|
37432
|
+
}
|
|
37433
|
+
|
|
37434
|
+
class SeriesDesignEditor extends owl.Component {
|
|
37435
|
+
static template = "o-spreadsheet-SeriesDesignEditor";
|
|
37165
37436
|
static components = {
|
|
37166
|
-
GeneralDesignEditor,
|
|
37167
37437
|
SidePanelCollapsible,
|
|
37168
37438
|
Section,
|
|
37169
|
-
AxisDesignEditor,
|
|
37170
37439
|
RoundColorPicker,
|
|
37171
|
-
Checkbox,
|
|
37172
|
-
RadioSelection,
|
|
37173
37440
|
};
|
|
37174
37441
|
static props = {
|
|
37175
37442
|
figureId: String,
|
|
37176
37443
|
definition: Object,
|
|
37177
|
-
canUpdateChart: Function,
|
|
37178
37444
|
updateChart: Function,
|
|
37445
|
+
canUpdateChart: Function,
|
|
37446
|
+
slots: { type: Object, optional: true },
|
|
37179
37447
|
};
|
|
37180
|
-
axisChoices = CHART_AXIS_CHOICES;
|
|
37181
37448
|
state = owl.useState({ index: 0 });
|
|
37182
|
-
get axesList() {
|
|
37183
|
-
const { useLeftAxis, useRightAxis } = getDefinedAxis(this.props.definition);
|
|
37184
|
-
let axes = [{ id: "x", name: _t("Horizontal axis") }];
|
|
37185
|
-
if (useLeftAxis) {
|
|
37186
|
-
axes.push({ id: "y", name: useRightAxis ? _t("Left axis") : _t("Vertical axis") });
|
|
37187
|
-
}
|
|
37188
|
-
if (useRightAxis) {
|
|
37189
|
-
axes.push({ id: "y1", name: useLeftAxis ? _t("Right axis") : _t("Vertical axis") });
|
|
37190
|
-
}
|
|
37191
|
-
return axes;
|
|
37192
|
-
}
|
|
37193
|
-
updateLegendPosition(ev) {
|
|
37194
|
-
this.props.updateChart(this.props.figureId, {
|
|
37195
|
-
legendPosition: ev.target.value,
|
|
37196
|
-
});
|
|
37197
|
-
}
|
|
37198
37449
|
getDataSeries() {
|
|
37199
|
-
|
|
37450
|
+
const runtime = this.env.model.getters.getChartRuntime(this.props.figureId);
|
|
37451
|
+
if (!runtime || !("chartJsConfig" in runtime)) {
|
|
37452
|
+
return [];
|
|
37453
|
+
}
|
|
37454
|
+
return runtime.chartJsConfig.data.datasets.map((d) => d.label);
|
|
37200
37455
|
}
|
|
37201
37456
|
updateSerieEditor(ev) {
|
|
37202
|
-
|
|
37203
|
-
const selectedIndex = ev.target.selectedIndex;
|
|
37204
|
-
const runtime = this.env.model.getters.getChartRuntime(chartId);
|
|
37205
|
-
if (!runtime) {
|
|
37206
|
-
return;
|
|
37207
|
-
}
|
|
37208
|
-
this.state.index = selectedIndex;
|
|
37457
|
+
this.state.index = ev.target.selectedIndex;
|
|
37209
37458
|
}
|
|
37210
37459
|
updateDataSeriesColor(color) {
|
|
37211
|
-
const dataSets =
|
|
37212
|
-
if (!dataSets?.[this.state.index])
|
|
37460
|
+
const dataSets = this.props.definition.dataSets;
|
|
37461
|
+
if (!dataSets?.[this.state.index])
|
|
37213
37462
|
return;
|
|
37214
|
-
}
|
|
37215
37463
|
dataSets[this.state.index] = {
|
|
37216
37464
|
...dataSets[this.state.index],
|
|
37217
37465
|
backgroundColor: color,
|
|
@@ -37220,71 +37468,87 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37220
37468
|
}
|
|
37221
37469
|
getDataSerieColor() {
|
|
37222
37470
|
const dataSets = this.props.definition.dataSets;
|
|
37223
|
-
if (!dataSets?.[this.state.index])
|
|
37471
|
+
if (!dataSets?.[this.state.index])
|
|
37224
37472
|
return "";
|
|
37225
|
-
}
|
|
37226
37473
|
const color = dataSets[this.state.index].backgroundColor;
|
|
37227
|
-
return color
|
|
37474
|
+
return color
|
|
37475
|
+
? toHex(color)
|
|
37476
|
+
: getNthColor(this.state.index, getColorsPalette(this.props.definition.dataSets.length));
|
|
37228
37477
|
}
|
|
37229
|
-
|
|
37230
|
-
const
|
|
37231
|
-
|
|
37478
|
+
updateDataSeriesLabel(ev) {
|
|
37479
|
+
const label = ev.target.value;
|
|
37480
|
+
const dataSets = this.props.definition.dataSets;
|
|
37481
|
+
if (!dataSets?.[this.state.index])
|
|
37232
37482
|
return;
|
|
37233
|
-
}
|
|
37234
37483
|
dataSets[this.state.index] = {
|
|
37235
37484
|
...dataSets[this.state.index],
|
|
37236
|
-
|
|
37485
|
+
label,
|
|
37237
37486
|
};
|
|
37238
37487
|
this.props.updateChart(this.props.figureId, { dataSets });
|
|
37239
37488
|
}
|
|
37240
|
-
|
|
37489
|
+
getDataSerieLabel() {
|
|
37241
37490
|
const dataSets = this.props.definition.dataSets;
|
|
37242
|
-
|
|
37243
|
-
return "left";
|
|
37244
|
-
}
|
|
37245
|
-
return dataSets[this.state.index].yAxisId === "y1" ? "right" : "left";
|
|
37246
|
-
}
|
|
37247
|
-
get canHaveTwoVerticalAxis() {
|
|
37248
|
-
return "horizontal" in this.props.definition ? !this.props.definition.horizontal : true;
|
|
37491
|
+
return dataSets[this.state.index]?.label || this.getDataSeries()[this.state.index];
|
|
37249
37492
|
}
|
|
37250
|
-
|
|
37251
|
-
|
|
37493
|
+
}
|
|
37494
|
+
|
|
37495
|
+
class SeriesWithAxisDesignEditor extends owl.Component {
|
|
37496
|
+
static template = "o-spreadsheet-SeriesWithAxisDesignEditor";
|
|
37497
|
+
static components = {
|
|
37498
|
+
SeriesDesignEditor,
|
|
37499
|
+
Checkbox,
|
|
37500
|
+
RadioSelection,
|
|
37501
|
+
Section,
|
|
37502
|
+
RoundColorPicker,
|
|
37503
|
+
};
|
|
37504
|
+
static props = {
|
|
37505
|
+
figureId: String,
|
|
37506
|
+
definition: Object,
|
|
37507
|
+
canUpdateChart: Function,
|
|
37508
|
+
updateChart: Function,
|
|
37509
|
+
slots: { type: Object, optional: true },
|
|
37510
|
+
};
|
|
37511
|
+
axisChoices = CHART_AXIS_CHOICES;
|
|
37512
|
+
updateDataSeriesAxis(index, axis) {
|
|
37252
37513
|
const dataSets = [...this.props.definition.dataSets];
|
|
37253
|
-
if (!dataSets?.[
|
|
37514
|
+
if (!dataSets?.[index]) {
|
|
37254
37515
|
return;
|
|
37255
37516
|
}
|
|
37256
|
-
dataSets[
|
|
37257
|
-
...dataSets[
|
|
37258
|
-
|
|
37517
|
+
dataSets[index] = {
|
|
37518
|
+
...dataSets[index],
|
|
37519
|
+
yAxisId: axis === "left" ? "y" : "y1",
|
|
37259
37520
|
};
|
|
37260
37521
|
this.props.updateChart(this.props.figureId, { dataSets });
|
|
37261
37522
|
}
|
|
37262
|
-
|
|
37523
|
+
getDataSerieAxis(index) {
|
|
37263
37524
|
const dataSets = this.props.definition.dataSets;
|
|
37264
|
-
|
|
37525
|
+
if (!dataSets?.[index]) {
|
|
37526
|
+
return "left";
|
|
37527
|
+
}
|
|
37528
|
+
return dataSets[index].yAxisId === "y1" ? "right" : "left";
|
|
37265
37529
|
}
|
|
37266
|
-
|
|
37267
|
-
this.props.
|
|
37530
|
+
get canHaveTwoVerticalAxis() {
|
|
37531
|
+
return !("horizontal" in this.props.definition && this.props.definition.horizontal);
|
|
37268
37532
|
}
|
|
37269
|
-
toggleDataTrend(display) {
|
|
37533
|
+
toggleDataTrend(index, display) {
|
|
37270
37534
|
const dataSets = [...this.props.definition.dataSets];
|
|
37271
|
-
if (!dataSets?.[
|
|
37535
|
+
if (!dataSets?.[index]) {
|
|
37272
37536
|
return;
|
|
37273
37537
|
}
|
|
37274
|
-
dataSets[
|
|
37275
|
-
...dataSets[
|
|
37538
|
+
dataSets[index] = {
|
|
37539
|
+
...dataSets[index],
|
|
37276
37540
|
trend: {
|
|
37277
37541
|
type: "polynomial",
|
|
37278
37542
|
order: 1,
|
|
37279
|
-
...dataSets[
|
|
37543
|
+
...dataSets[index].trend,
|
|
37280
37544
|
display,
|
|
37281
37545
|
},
|
|
37282
37546
|
};
|
|
37283
37547
|
this.props.updateChart(this.props.figureId, { dataSets });
|
|
37284
37548
|
}
|
|
37285
|
-
getTrendLineConfiguration() {
|
|
37549
|
+
getTrendLineConfiguration(index) {
|
|
37286
37550
|
const dataSets = this.props.definition.dataSets;
|
|
37287
|
-
return dataSets?.[
|
|
37551
|
+
return dataSets?.[index]?.trend;
|
|
37288
37552
|
}
|
|
37289
37553
|
getTrendType(config) {
|
|
37290
37554
|
if (!config) {
|
|
@@ -37292,7 +37556,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37292
37556
|
}
|
|
37293
37557
|
return config.type === "polynomial" && config.order === 1 ? "linear" : config.type;
|
|
37294
37558
|
}
|
|
37295
|
-
onChangeTrendType(ev) {
|
|
37559
|
+
onChangeTrendType(index, ev) {
|
|
37296
37560
|
const type = ev.target.value;
|
|
37297
37561
|
let config;
|
|
37298
37562
|
switch (type) {
|
|
@@ -37305,37 +37569,59 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37305
37569
|
break;
|
|
37306
37570
|
case "exponential":
|
|
37307
37571
|
case "logarithmic":
|
|
37572
|
+
case "trailingMovingAverage":
|
|
37308
37573
|
config = { type };
|
|
37309
37574
|
break;
|
|
37310
37575
|
default:
|
|
37311
37576
|
return;
|
|
37312
37577
|
}
|
|
37313
|
-
this.updateTrendLineValue(config);
|
|
37578
|
+
this.updateTrendLineValue(index, config);
|
|
37314
37579
|
}
|
|
37315
|
-
onChangePolynomialDegree(ev) {
|
|
37580
|
+
onChangePolynomialDegree(index, ev) {
|
|
37316
37581
|
const element = ev.target;
|
|
37317
37582
|
const order = parseInt(element.value || "1");
|
|
37318
37583
|
if (order < 2) {
|
|
37319
|
-
element.value = `${this.getTrendLineConfiguration()?.order ?? 2}`;
|
|
37584
|
+
element.value = `${this.getTrendLineConfiguration(index)?.order ?? 2}`;
|
|
37320
37585
|
return;
|
|
37321
37586
|
}
|
|
37322
|
-
this.updateTrendLineValue({ order });
|
|
37587
|
+
this.updateTrendLineValue(index, { order });
|
|
37323
37588
|
}
|
|
37324
|
-
|
|
37325
|
-
return
|
|
37589
|
+
get defaultWindowSize() {
|
|
37590
|
+
return DEFAULT_WINDOW_SIZE;
|
|
37326
37591
|
}
|
|
37327
|
-
|
|
37328
|
-
|
|
37592
|
+
onChangeMovingAverageWindow(index, ev) {
|
|
37593
|
+
const element = ev.target;
|
|
37594
|
+
let window = parseInt(element.value) || DEFAULT_WINDOW_SIZE;
|
|
37595
|
+
if (window <= 1) {
|
|
37596
|
+
window = DEFAULT_WINDOW_SIZE;
|
|
37597
|
+
}
|
|
37598
|
+
this.updateTrendLineValue(index, { window });
|
|
37329
37599
|
}
|
|
37330
|
-
|
|
37600
|
+
getDataSerieColor(index) {
|
|
37601
|
+
const dataSets = this.props.definition.dataSets;
|
|
37602
|
+
if (!dataSets?.[index])
|
|
37603
|
+
return "";
|
|
37604
|
+
const color = dataSets[index].backgroundColor;
|
|
37605
|
+
return color
|
|
37606
|
+
? toHex(color)
|
|
37607
|
+
: getNthColor(index, getColorsPalette(this.props.definition.dataSets.length));
|
|
37608
|
+
}
|
|
37609
|
+
getTrendLineColor(index) {
|
|
37610
|
+
return (this.getTrendLineConfiguration(index)?.color ??
|
|
37611
|
+
setColorAlpha(this.getDataSerieColor(index), 0.5));
|
|
37612
|
+
}
|
|
37613
|
+
updateTrendLineColor(index, color) {
|
|
37614
|
+
this.updateTrendLineValue(index, { color });
|
|
37615
|
+
}
|
|
37616
|
+
updateTrendLineValue(index, config) {
|
|
37331
37617
|
const dataSets = [...this.props.definition.dataSets];
|
|
37332
|
-
if (!dataSets?.[
|
|
37618
|
+
if (!dataSets?.[index]) {
|
|
37333
37619
|
return;
|
|
37334
37620
|
}
|
|
37335
|
-
dataSets[
|
|
37336
|
-
...dataSets[
|
|
37621
|
+
dataSets[index] = {
|
|
37622
|
+
...dataSets[index],
|
|
37337
37623
|
trend: {
|
|
37338
|
-
...dataSets[
|
|
37624
|
+
...dataSets[index].trend,
|
|
37339
37625
|
...config,
|
|
37340
37626
|
},
|
|
37341
37627
|
};
|
|
@@ -37343,29 +37629,67 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37343
37629
|
}
|
|
37344
37630
|
}
|
|
37345
37631
|
|
|
37632
|
+
class ChartWithAxisDesignPanel extends owl.Component {
|
|
37633
|
+
static template = "o-spreadsheet-ChartWithAxisDesignPanel";
|
|
37634
|
+
static components = {
|
|
37635
|
+
GeneralDesignEditor,
|
|
37636
|
+
SidePanelCollapsible,
|
|
37637
|
+
Section,
|
|
37638
|
+
AxisDesignEditor,
|
|
37639
|
+
Checkbox,
|
|
37640
|
+
SeriesWithAxisDesignEditor,
|
|
37641
|
+
};
|
|
37642
|
+
static props = {
|
|
37643
|
+
figureId: String,
|
|
37644
|
+
definition: Object,
|
|
37645
|
+
canUpdateChart: Function,
|
|
37646
|
+
updateChart: Function,
|
|
37647
|
+
};
|
|
37648
|
+
get axesList() {
|
|
37649
|
+
const { useLeftAxis, useRightAxis } = getDefinedAxis(this.props.definition);
|
|
37650
|
+
let axes = [{ id: "x", name: _t("Horizontal axis") }];
|
|
37651
|
+
if (useLeftAxis) {
|
|
37652
|
+
axes.push({ id: "y", name: useRightAxis ? _t("Left axis") : _t("Vertical axis") });
|
|
37653
|
+
}
|
|
37654
|
+
if (useRightAxis) {
|
|
37655
|
+
axes.push({ id: "y1", name: useLeftAxis ? _t("Right axis") : _t("Vertical axis") });
|
|
37656
|
+
}
|
|
37657
|
+
return axes;
|
|
37658
|
+
}
|
|
37659
|
+
updateLegendPosition(ev) {
|
|
37660
|
+
this.props.updateChart(this.props.figureId, {
|
|
37661
|
+
legendPosition: ev.target.value,
|
|
37662
|
+
});
|
|
37663
|
+
}
|
|
37664
|
+
}
|
|
37665
|
+
|
|
37346
37666
|
class ComboChartDesignPanel extends ChartWithAxisDesignPanel {
|
|
37347
37667
|
static template = "o-spreadsheet-ComboChartDesignPanel";
|
|
37668
|
+
static components = {
|
|
37669
|
+
...ChartWithAxisDesignPanel.components,
|
|
37670
|
+
RadioSelection,
|
|
37671
|
+
};
|
|
37348
37672
|
seriesTypeChoices = [
|
|
37349
37673
|
{ value: "bar", label: _t("Bar") },
|
|
37350
37674
|
{ value: "line", label: _t("Line") },
|
|
37351
37675
|
];
|
|
37352
|
-
updateDataSeriesType(type) {
|
|
37676
|
+
updateDataSeriesType(index, type) {
|
|
37353
37677
|
const dataSets = [...this.props.definition.dataSets];
|
|
37354
|
-
if (!dataSets?.[
|
|
37678
|
+
if (!dataSets?.[index]) {
|
|
37355
37679
|
return;
|
|
37356
37680
|
}
|
|
37357
|
-
dataSets[
|
|
37358
|
-
...dataSets[
|
|
37681
|
+
dataSets[index] = {
|
|
37682
|
+
...dataSets[index],
|
|
37359
37683
|
type,
|
|
37360
37684
|
};
|
|
37361
37685
|
this.props.updateChart(this.props.figureId, { dataSets });
|
|
37362
37686
|
}
|
|
37363
|
-
getDataSeriesType() {
|
|
37687
|
+
getDataSeriesType(index) {
|
|
37364
37688
|
const dataSets = this.props.definition.dataSets;
|
|
37365
|
-
if (!dataSets?.[
|
|
37689
|
+
if (!dataSets?.[index]) {
|
|
37366
37690
|
return "bar";
|
|
37367
37691
|
}
|
|
37368
|
-
return dataSets[
|
|
37692
|
+
return dataSets[index].type ?? "line";
|
|
37369
37693
|
}
|
|
37370
37694
|
}
|
|
37371
37695
|
|
|
@@ -37548,11 +37872,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37548
37872
|
stacked,
|
|
37549
37873
|
});
|
|
37550
37874
|
}
|
|
37551
|
-
onUpdateAggregated(aggregated) {
|
|
37552
|
-
this.props.updateChart(this.props.figureId, {
|
|
37553
|
-
aggregated,
|
|
37554
|
-
});
|
|
37555
|
-
}
|
|
37556
37875
|
onUpdateCumulative(cumulative) {
|
|
37557
37876
|
this.props.updateChart(this.props.figureId, {
|
|
37558
37877
|
cumulative,
|
|
@@ -37580,6 +37899,27 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37580
37899
|
}
|
|
37581
37900
|
}
|
|
37582
37901
|
|
|
37902
|
+
class RadarChartDesignPanel extends owl.Component {
|
|
37903
|
+
static template = "o-spreadsheet-RadarChartDesignPanel";
|
|
37904
|
+
static components = {
|
|
37905
|
+
GeneralDesignEditor,
|
|
37906
|
+
SeriesDesignEditor,
|
|
37907
|
+
Section,
|
|
37908
|
+
Checkbox,
|
|
37909
|
+
};
|
|
37910
|
+
static props = {
|
|
37911
|
+
figureId: String,
|
|
37912
|
+
definition: Object,
|
|
37913
|
+
canUpdateChart: Function,
|
|
37914
|
+
updateChart: Function,
|
|
37915
|
+
};
|
|
37916
|
+
updateLegendPosition(ev) {
|
|
37917
|
+
this.props.updateChart(this.props.figureId, {
|
|
37918
|
+
legendPosition: ev.target.value,
|
|
37919
|
+
});
|
|
37920
|
+
}
|
|
37921
|
+
}
|
|
37922
|
+
|
|
37583
37923
|
class ScatterConfigPanel extends GenericChartConfigPanel {
|
|
37584
37924
|
static template = "o-spreadsheet-ScatterConfigPanel";
|
|
37585
37925
|
get canTreatLabelsAsText() {
|
|
@@ -37774,9 +38114,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37774
38114
|
verticalAxisPosition: value,
|
|
37775
38115
|
});
|
|
37776
38116
|
}
|
|
37777
|
-
updateShowValues(showValues) {
|
|
37778
|
-
this.props.updateChart(this.props.figureId, { showValues });
|
|
37779
|
-
}
|
|
37780
38117
|
}
|
|
37781
38118
|
|
|
37782
38119
|
const chartSidePanelComponentRegistry = new Registry();
|
|
@@ -37816,6 +38153,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37816
38153
|
.add("pyramid", {
|
|
37817
38154
|
configuration: GenericChartConfigPanel,
|
|
37818
38155
|
design: ChartWithAxisDesignPanel,
|
|
38156
|
+
})
|
|
38157
|
+
.add("radar", {
|
|
38158
|
+
configuration: GenericChartConfigPanel,
|
|
38159
|
+
design: RadarChartDesignPanel,
|
|
37819
38160
|
});
|
|
37820
38161
|
|
|
37821
38162
|
css /* scss */ `
|
|
@@ -39018,13 +39359,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
39018
39359
|
return;
|
|
39019
39360
|
this.edgeScrollIntervalId = window.setInterval(() => {
|
|
39020
39361
|
const offset = direction * 3;
|
|
39021
|
-
let newPosition = this.currentMousePosition + offset;
|
|
39022
|
-
if (newPosition < Math.min(this.container.start, this.minPosition)) {
|
|
39023
|
-
newPosition = Math.min(this.container.start, this.minPosition);
|
|
39024
|
-
}
|
|
39025
|
-
else if (newPosition > Math.max(this.container.end, this.maxPosition)) {
|
|
39026
|
-
newPosition = Math.max(this.container.end, this.maxPosition);
|
|
39027
|
-
}
|
|
39028
39362
|
this.container.scroll += offset;
|
|
39029
39363
|
}, 5);
|
|
39030
39364
|
}
|
|
@@ -39201,7 +39535,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
39201
39535
|
width: 142px;
|
|
39202
39536
|
.o-cf-preview-description-rule {
|
|
39203
39537
|
margin-bottom: 4px;
|
|
39204
|
-
font-weight: 600;
|
|
39205
39538
|
max-height: 2.8em;
|
|
39206
39539
|
line-height: 1.4em;
|
|
39207
39540
|
}
|
|
@@ -39673,7 +40006,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
39673
40006
|
setColorScaleColor(target, color) {
|
|
39674
40007
|
const point = this.state.rules.colorScale[target];
|
|
39675
40008
|
if (point) {
|
|
39676
|
-
point.color = Number.parseInt(color.
|
|
40009
|
+
point.color = Number.parseInt(color.slice(1), 16);
|
|
39677
40010
|
}
|
|
39678
40011
|
this.closeMenus();
|
|
39679
40012
|
}
|
|
@@ -39784,7 +40117,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
39784
40117
|
return [this.state.rules.dataBar.rangeValues || ""];
|
|
39785
40118
|
}
|
|
39786
40119
|
updateDataBarColor(color) {
|
|
39787
|
-
this.state.rules.dataBar.color = Number.parseInt(color.
|
|
40120
|
+
this.state.rules.dataBar.color = Number.parseInt(color.slice(1), 16);
|
|
39788
40121
|
}
|
|
39789
40122
|
onDataBarRangeUpdate(ranges) {
|
|
39790
40123
|
this.state.rules.dataBar.rangeValues = ranges[0];
|
|
@@ -41197,10 +41530,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
41197
41530
|
activeSheetMatches = [];
|
|
41198
41531
|
specificRangeMatches = [];
|
|
41199
41532
|
currentSearchRegex = null;
|
|
41200
|
-
isSearchDirty = false;
|
|
41201
41533
|
initialShowFormulaState;
|
|
41202
41534
|
preserveSelectedMatchIndex = false;
|
|
41203
41535
|
irreplaceableMatchCount = 0;
|
|
41536
|
+
isSearchDirty = false;
|
|
41537
|
+
shouldFinalizeUpdateSelection = false;
|
|
41204
41538
|
notificationStore = this.get(NotificationStore);
|
|
41205
41539
|
// fixme: why do we make selectedMatchIndex on top of a selected
|
|
41206
41540
|
// property in the matches?
|
|
@@ -41246,10 +41580,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
41246
41580
|
this.updateSearchOptions({ searchFormulas: showFormula });
|
|
41247
41581
|
}
|
|
41248
41582
|
selectPreviousMatch() {
|
|
41249
|
-
this.selectNextCell(Direction.previous
|
|
41583
|
+
this.selectNextCell(Direction.previous, {
|
|
41584
|
+
jumpToMatchSheet: true,
|
|
41585
|
+
updateSelection: true,
|
|
41586
|
+
});
|
|
41250
41587
|
}
|
|
41251
41588
|
selectNextMatch() {
|
|
41252
|
-
this.selectNextCell(Direction.next);
|
|
41589
|
+
this.selectNextCell(Direction.next, { jumpToMatchSheet: true, updateSelection: true });
|
|
41253
41590
|
}
|
|
41254
41591
|
handle(cmd) {
|
|
41255
41592
|
switch (cmd.type) {
|
|
@@ -41266,8 +41603,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
41266
41603
|
case "ADD_COLUMNS_ROWS":
|
|
41267
41604
|
case "EVALUATE_CELLS":
|
|
41268
41605
|
case "UPDATE_CELL":
|
|
41606
|
+
this.isSearchDirty = true;
|
|
41607
|
+
break;
|
|
41269
41608
|
case "ACTIVATE_SHEET":
|
|
41270
41609
|
this.isSearchDirty = true;
|
|
41610
|
+
this.shouldFinalizeUpdateSelection = true;
|
|
41271
41611
|
break;
|
|
41272
41612
|
case "REPLACE_SEARCH":
|
|
41273
41613
|
for (const match of cmd.matches) {
|
|
@@ -41282,7 +41622,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
41282
41622
|
}
|
|
41283
41623
|
finalize() {
|
|
41284
41624
|
if (this.isSearchDirty) {
|
|
41285
|
-
this.refreshSearch(
|
|
41625
|
+
this.refreshSearch({
|
|
41626
|
+
jumpToMatchSheet: false,
|
|
41627
|
+
updateSelection: this.shouldFinalizeUpdateSelection,
|
|
41628
|
+
});
|
|
41629
|
+
this.shouldFinalizeUpdateSelection = false;
|
|
41286
41630
|
this.isSearchDirty = false;
|
|
41287
41631
|
}
|
|
41288
41632
|
}
|
|
@@ -41309,17 +41653,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
41309
41653
|
}
|
|
41310
41654
|
this.toSearch = toSearch;
|
|
41311
41655
|
this.currentSearchRegex = getSearchRegex(this.toSearch, this.searchOptions);
|
|
41312
|
-
this.refreshSearch();
|
|
41656
|
+
this.refreshSearch({ jumpToMatchSheet: true, updateSelection: true });
|
|
41313
41657
|
}
|
|
41314
41658
|
/**
|
|
41315
41659
|
* refresh the matches according to the current search options
|
|
41316
41660
|
*/
|
|
41317
|
-
refreshSearch(
|
|
41661
|
+
refreshSearch(options) {
|
|
41318
41662
|
if (!this.preserveSelectedMatchIndex) {
|
|
41319
41663
|
this.selectedMatchIndex = null;
|
|
41320
41664
|
}
|
|
41321
41665
|
this.findMatches();
|
|
41322
|
-
this.selectNextCell(Direction.current,
|
|
41666
|
+
this.selectNextCell(Direction.current, options);
|
|
41323
41667
|
}
|
|
41324
41668
|
getSheetsInSearchOrder() {
|
|
41325
41669
|
switch (this.searchOptions.searchScope) {
|
|
@@ -41389,7 +41733,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
41389
41733
|
* It is also used to keep coherence between the selected searchMatch
|
|
41390
41734
|
* and selectedMatchIndex.
|
|
41391
41735
|
*/
|
|
41392
|
-
selectNextCell(indexChange,
|
|
41736
|
+
selectNextCell(indexChange, options) {
|
|
41393
41737
|
const matches = this.searchMatches;
|
|
41394
41738
|
if (!matches.length) {
|
|
41395
41739
|
this.selectedMatchIndex = null;
|
|
@@ -41415,7 +41759,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
41415
41759
|
this.selectedMatchIndex = nextIndex;
|
|
41416
41760
|
const selectedMatch = matches[nextIndex];
|
|
41417
41761
|
// Switch to the sheet where the match is located
|
|
41418
|
-
if (jumpToMatchSheet && this.getters.getActiveSheetId() !== selectedMatch.sheetId) {
|
|
41762
|
+
if (options.jumpToMatchSheet && this.getters.getActiveSheetId() !== selectedMatch.sheetId) {
|
|
41419
41763
|
// We set `preserveSelectedMatchIndex` to true to avoid resetting the selected search
|
|
41420
41764
|
// index in the `refreshSearch` function when a new sheet is activated. The reason being
|
|
41421
41765
|
// that, when we automatically go back to previous sheet while performing a search, the
|
|
@@ -41431,7 +41775,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
41431
41775
|
}
|
|
41432
41776
|
// we want grid selection to capture the selection stream
|
|
41433
41777
|
this.model.selection.getBackToDefault();
|
|
41434
|
-
|
|
41778
|
+
if (options.updateSelection) {
|
|
41779
|
+
this.model.selection.selectCell(selectedMatch.col, selectedMatch.row);
|
|
41780
|
+
}
|
|
41435
41781
|
}
|
|
41436
41782
|
/**
|
|
41437
41783
|
* Replace the value of the currently selected match
|
|
@@ -41446,7 +41792,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
41446
41792
|
matches: [this.searchMatches[this.selectedMatchIndex]],
|
|
41447
41793
|
searchOptions: this.searchOptions,
|
|
41448
41794
|
});
|
|
41449
|
-
this.selectNextCell(Direction.next);
|
|
41795
|
+
this.selectNextCell(Direction.next, { jumpToMatchSheet: true, updateSelection: true });
|
|
41450
41796
|
}
|
|
41451
41797
|
/**
|
|
41452
41798
|
* Apply the replace function to all the matches one time.
|
|
@@ -41628,6 +41974,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
41628
41974
|
owl.onMounted(() => this.searchInput.el?.focus());
|
|
41629
41975
|
owl.onWillUnmount(() => this.updateSearchContent.stopDebounce());
|
|
41630
41976
|
this.updateSearchContent = debounce(this.store.updateSearchContent, 200);
|
|
41977
|
+
owl.useExternalListener(window, "keydown", (ev) => {
|
|
41978
|
+
const code = keyboardEventToShortcutString(ev);
|
|
41979
|
+
if (code === "Ctrl+F" || code === "Ctrl+H") {
|
|
41980
|
+
this.searchInput.el?.focus();
|
|
41981
|
+
ev.preventDefault();
|
|
41982
|
+
ev.stopPropagation();
|
|
41983
|
+
}
|
|
41984
|
+
}, { capture: true });
|
|
41631
41985
|
}
|
|
41632
41986
|
onFocusSearch() {
|
|
41633
41987
|
this.updateDataRange();
|
|
@@ -42203,7 +42557,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
42203
42557
|
sequence: 0,
|
|
42204
42558
|
autoSelectFirstProposal: true,
|
|
42205
42559
|
getProposals(tokenAtCursor) {
|
|
42206
|
-
// return []
|
|
42207
42560
|
const measureProposals = pivot.measures
|
|
42208
42561
|
.filter((m) => m !== forComputedMeasure)
|
|
42209
42562
|
.map((measure) => {
|
|
@@ -43784,13 +44137,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
43784
44137
|
class PivotSidePanelStore extends SpreadsheetStore {
|
|
43785
44138
|
pivotId;
|
|
43786
44139
|
mutators = ["reset", "deferUpdates", "applyUpdate", "discardPendingUpdate", "update"];
|
|
43787
|
-
updatesAreDeferred
|
|
44140
|
+
updatesAreDeferred;
|
|
43788
44141
|
draft = null;
|
|
43789
44142
|
notification = this.get(NotificationStore);
|
|
43790
44143
|
alreadyNotified = false;
|
|
43791
44144
|
constructor(get, pivotId) {
|
|
43792
44145
|
super(get);
|
|
43793
44146
|
this.pivotId = pivotId;
|
|
44147
|
+
this.updatesAreDeferred =
|
|
44148
|
+
this.getters.getPivotCoreDefinition(this.pivotId).deferUpdates ?? false;
|
|
43794
44149
|
}
|
|
43795
44150
|
handle(cmd) {
|
|
43796
44151
|
switch (cmd.type) {
|
|
@@ -43878,10 +44233,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
43878
44233
|
this.draft = null;
|
|
43879
44234
|
}
|
|
43880
44235
|
deferUpdates(shouldDefer) {
|
|
43881
|
-
this.updatesAreDeferred = shouldDefer;
|
|
43882
44236
|
if (shouldDefer === false && this.draft) {
|
|
44237
|
+
this.draft.deferUpdates = false;
|
|
43883
44238
|
this.applyUpdate();
|
|
43884
44239
|
}
|
|
44240
|
+
else {
|
|
44241
|
+
this.update({ deferUpdates: shouldDefer });
|
|
44242
|
+
}
|
|
44243
|
+
this.updatesAreDeferred = shouldDefer;
|
|
43885
44244
|
}
|
|
43886
44245
|
applyUpdate() {
|
|
43887
44246
|
if (this.draft) {
|
|
@@ -44139,7 +44498,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44139
44498
|
return colLabel;
|
|
44140
44499
|
}
|
|
44141
44500
|
get isEveryColumnSelected() {
|
|
44142
|
-
return Object.values(this.state.columns).every((value) => value
|
|
44501
|
+
return Object.values(this.state.columns).every((value) => value);
|
|
44143
44502
|
}
|
|
44144
44503
|
get errorMessages() {
|
|
44145
44504
|
const cancelledReasons = this.env.model.canDispatch("REMOVE_DUPLICATES", {
|
|
@@ -44239,8 +44598,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44239
44598
|
const currentLocale = this.currentLocale;
|
|
44240
44599
|
const localeInLoadedLocales = this.loadedLocales.find((l) => l.code === currentLocale.code);
|
|
44241
44600
|
if (!localeInLoadedLocales) {
|
|
44242
|
-
|
|
44243
|
-
return locales;
|
|
44601
|
+
return [...this.loadedLocales, currentLocale].sort((a, b) => a.name.localeCompare(b.name));
|
|
44244
44602
|
}
|
|
44245
44603
|
else if (!deepEquals(currentLocale, localeInLoadedLocales)) {
|
|
44246
44604
|
const index = this.loadedLocales.indexOf(localeInLoadedLocales);
|
|
@@ -46134,10 +46492,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46134
46492
|
});
|
|
46135
46493
|
}
|
|
46136
46494
|
get focus() {
|
|
46137
|
-
|
|
46495
|
+
return this.composerFocusStore.activeComposer === this.composerInterface
|
|
46138
46496
|
? this.composerFocusStore.focusMode
|
|
46139
46497
|
: "inactive";
|
|
46140
|
-
return focus;
|
|
46141
46498
|
}
|
|
46142
46499
|
get composerProps() {
|
|
46143
46500
|
const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
|
|
@@ -47144,6 +47501,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
47144
47501
|
new CellClipboardHandler(this.getters, this.model.dispatch),
|
|
47145
47502
|
new BorderClipboardHandler(this.getters, this.model.dispatch),
|
|
47146
47503
|
new TableClipboardHandler(this.getters, this.model.dispatch),
|
|
47504
|
+
new ConditionalFormatClipboardHandler(this.getters, this.model.dispatch),
|
|
47147
47505
|
];
|
|
47148
47506
|
status = "inactive";
|
|
47149
47507
|
copiedData;
|
|
@@ -47154,6 +47512,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
47154
47512
|
this.highlightStore.unRegister(this);
|
|
47155
47513
|
});
|
|
47156
47514
|
}
|
|
47515
|
+
handle(cmd) {
|
|
47516
|
+
switch (cmd.type) {
|
|
47517
|
+
case "PAINT_FORMAT":
|
|
47518
|
+
this.paintFormat(cmd.sheetId, cmd.target);
|
|
47519
|
+
break;
|
|
47520
|
+
}
|
|
47521
|
+
}
|
|
47157
47522
|
activate(args) {
|
|
47158
47523
|
this.copiedData = this.copyFormats();
|
|
47159
47524
|
this.status = args.persistent ? "persistent" : "oneOff";
|
|
@@ -47163,18 +47528,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
47163
47528
|
this.copiedData = undefined;
|
|
47164
47529
|
}
|
|
47165
47530
|
pasteFormat(target) {
|
|
47166
|
-
|
|
47167
|
-
const sheetId = this.getters.getActiveSheetId();
|
|
47168
|
-
for (const handler of this.clipboardHandlers) {
|
|
47169
|
-
handler.paste({ zones: target, sheetId }, this.copiedData, {
|
|
47170
|
-
isCutOperation: false,
|
|
47171
|
-
pasteOption: "onlyFormat",
|
|
47172
|
-
});
|
|
47173
|
-
}
|
|
47174
|
-
}
|
|
47175
|
-
if (this.status === "oneOff") {
|
|
47176
|
-
this.cancel();
|
|
47177
|
-
}
|
|
47531
|
+
this.model.dispatch("PAINT_FORMAT", { target, sheetId: this.getters.getActiveSheetId() });
|
|
47178
47532
|
}
|
|
47179
47533
|
get isActive() {
|
|
47180
47534
|
return this.status !== "inactive";
|
|
@@ -47188,6 +47542,19 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
47188
47542
|
}
|
|
47189
47543
|
return copiedData;
|
|
47190
47544
|
}
|
|
47545
|
+
paintFormat(sheetId, target) {
|
|
47546
|
+
if (this.copiedData) {
|
|
47547
|
+
for (const handler of this.clipboardHandlers) {
|
|
47548
|
+
handler.paste({ zones: target, sheetId }, this.copiedData, {
|
|
47549
|
+
isCutOperation: false,
|
|
47550
|
+
pasteOption: "onlyFormat",
|
|
47551
|
+
});
|
|
47552
|
+
}
|
|
47553
|
+
}
|
|
47554
|
+
if (this.status === "oneOff") {
|
|
47555
|
+
this.cancel();
|
|
47556
|
+
}
|
|
47557
|
+
}
|
|
47191
47558
|
get highlights() {
|
|
47192
47559
|
const data = this.copiedData;
|
|
47193
47560
|
if (!data) {
|
|
@@ -47564,7 +47931,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
47564
47931
|
if (index < 0) {
|
|
47565
47932
|
return;
|
|
47566
47933
|
}
|
|
47567
|
-
if (this.state.waitingForMove
|
|
47934
|
+
if (this.state.waitingForMove) {
|
|
47568
47935
|
if (!this.env.model.getters.isGridSelectionActive()) {
|
|
47569
47936
|
this._selectElement(index, false);
|
|
47570
47937
|
}
|
|
@@ -49123,7 +49490,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
49123
49490
|
}
|
|
49124
49491
|
open(componentTag, panelProps = {}) {
|
|
49125
49492
|
const state = this.computeState(componentTag, panelProps);
|
|
49126
|
-
if (state.isOpen
|
|
49493
|
+
if (!state.isOpen) {
|
|
49127
49494
|
return;
|
|
49128
49495
|
}
|
|
49129
49496
|
if (this.isOpen && componentTag !== this.componentTag) {
|
|
@@ -49462,6 +49829,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
49462
49829
|
},
|
|
49463
49830
|
"Ctrl+D": async () => this.env.model.dispatch("COPY_PASTE_CELLS_ABOVE"),
|
|
49464
49831
|
"Ctrl+R": async () => this.env.model.dispatch("COPY_PASTE_CELLS_ON_LEFT"),
|
|
49832
|
+
"Ctrl+H": () => this.sidePanel.open("FindAndReplace", {}),
|
|
49833
|
+
"Ctrl+F": () => this.sidePanel.open("FindAndReplace", {}),
|
|
49465
49834
|
"Ctrl+Shift+E": () => this.setHorizontalAlign("center"),
|
|
49466
49835
|
"Ctrl+Shift+L": () => this.setHorizontalAlign("left"),
|
|
49467
49836
|
"Ctrl+Shift+R": () => this.setHorizontalAlign("right"),
|
|
@@ -49869,31 +50238,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
49869
50238
|
}
|
|
49870
50239
|
}
|
|
49871
50240
|
|
|
49872
|
-
/** @odoo-module */
|
|
49873
|
-
class EditableName extends owl.Component {
|
|
49874
|
-
static template = "o-spreadsheet-EditableName";
|
|
49875
|
-
static props = {
|
|
49876
|
-
name: String,
|
|
49877
|
-
displayName: String,
|
|
49878
|
-
onChanged: Function,
|
|
49879
|
-
};
|
|
49880
|
-
state;
|
|
49881
|
-
setup() {
|
|
49882
|
-
this.state = owl.useState({
|
|
49883
|
-
isEditing: false,
|
|
49884
|
-
name: "",
|
|
49885
|
-
});
|
|
49886
|
-
}
|
|
49887
|
-
rename() {
|
|
49888
|
-
this.state.isEditing = true;
|
|
49889
|
-
this.state.name = this.props.name;
|
|
49890
|
-
}
|
|
49891
|
-
save() {
|
|
49892
|
-
this.props.onChanged(this.state.name.trim());
|
|
49893
|
-
this.state.isEditing = false;
|
|
49894
|
-
}
|
|
49895
|
-
}
|
|
49896
|
-
|
|
49897
50241
|
/**
|
|
49898
50242
|
* BasePlugin
|
|
49899
50243
|
*
|
|
@@ -53811,7 +54155,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53811
54155
|
this.sheetIdsMapName[sheet.name] = sheet.id;
|
|
53812
54156
|
}
|
|
53813
54157
|
for (let sheetData of data.sheets) {
|
|
53814
|
-
const name = sheetData.name ||
|
|
54158
|
+
const name = sheetData.name || "Sheet" + (Object.keys(this.sheets).length + 1);
|
|
53815
54159
|
const { colNumber, rowNumber } = this.getImportedSheetSize(sheetData);
|
|
53816
54160
|
const sheet = {
|
|
53817
54161
|
id: sheetData.id,
|
|
@@ -55430,7 +55774,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
55430
55774
|
case "DUPLICATE_PIVOT": {
|
|
55431
55775
|
const { pivotId, newPivotId } = cmd;
|
|
55432
55776
|
const pivot = deepCopy(this.getPivotCore(pivotId).definition);
|
|
55433
|
-
pivot.name =
|
|
55777
|
+
pivot.name = cmd.duplicatedPivotName ?? pivot.name + " (copy)";
|
|
55434
55778
|
this.addPivot(newPivotId, pivot);
|
|
55435
55779
|
break;
|
|
55436
55780
|
}
|
|
@@ -55470,7 +55814,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
55470
55814
|
return `(#${formulaId}) ${this.getPivotName(pivotId)}`;
|
|
55471
55815
|
}
|
|
55472
55816
|
getPivotName(pivotId) {
|
|
55473
|
-
return
|
|
55817
|
+
return this.getPivotCore(pivotId).definition.name;
|
|
55474
55818
|
}
|
|
55475
55819
|
/**
|
|
55476
55820
|
* Returns the pivot core definition of the pivot with the given id.
|
|
@@ -57112,7 +57456,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57112
57456
|
cellsToCompute.addMany(arrayFormulasPositions);
|
|
57113
57457
|
cellsToCompute.addMany(this.getCellsDependingOn(arrayFormulasPositions));
|
|
57114
57458
|
this.evaluate(cellsToCompute);
|
|
57115
|
-
console.
|
|
57459
|
+
console.debug("evaluate Cells", performance.now() - start, "ms");
|
|
57116
57460
|
}
|
|
57117
57461
|
getArrayFormulasImpactedByChangesOf(positions) {
|
|
57118
57462
|
const impactedPositions = this.createEmptyPositionSet();
|
|
@@ -57156,7 +57500,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57156
57500
|
const start = performance.now();
|
|
57157
57501
|
this.evaluatedCells = new PositionMap();
|
|
57158
57502
|
this.evaluate(this.getAllCells());
|
|
57159
|
-
console.
|
|
57503
|
+
console.debug("evaluate all cells", performance.now() - start, "ms");
|
|
57160
57504
|
}
|
|
57161
57505
|
evaluateFormulaResult(sheetId, formulaString) {
|
|
57162
57506
|
const compiledFormula = compile(formulaString);
|
|
@@ -58162,8 +58506,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58162
58506
|
.map((cell) => cell.value);
|
|
58163
58507
|
switch (threshold.type) {
|
|
58164
58508
|
case "value":
|
|
58165
|
-
|
|
58166
|
-
return result;
|
|
58509
|
+
return functionName === "max" ? largeMax(rangeValues) : largeMin(rangeValues);
|
|
58167
58510
|
case "number":
|
|
58168
58511
|
return Number(threshold.value);
|
|
58169
58512
|
case "percentage":
|
|
@@ -59367,8 +59710,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59367
59710
|
throw new NotAvailableError();
|
|
59368
59711
|
}
|
|
59369
59712
|
const comparedValue = this._getPivotCellValueAndFormat(measure.id, comparedDomain);
|
|
59370
|
-
|
|
59371
|
-
return comparedValueNumber;
|
|
59713
|
+
return this.strictMeasureValueToNumber(comparedValue);
|
|
59372
59714
|
}
|
|
59373
59715
|
getPivotValueCells(measureId) {
|
|
59374
59716
|
return this.getTableStructure()
|
|
@@ -60902,7 +61244,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60902
61244
|
this.onMessageReceived(message);
|
|
60903
61245
|
}
|
|
60904
61246
|
this.isReplayingInitialRevisions = false;
|
|
60905
|
-
console.
|
|
61247
|
+
console.debug("Replayed", numberOfCommands, "commands in", performance.now() - start, "ms");
|
|
60906
61248
|
}
|
|
60907
61249
|
/**
|
|
60908
61250
|
* Notify the server that the user client left the collaborative session
|
|
@@ -61074,7 +61416,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61074
61416
|
if (this.waitingAck) {
|
|
61075
61417
|
return;
|
|
61076
61418
|
}
|
|
61077
|
-
this.waitingAck = true;
|
|
61078
61419
|
this.sendPendingMessage();
|
|
61079
61420
|
}
|
|
61080
61421
|
/**
|
|
@@ -61111,6 +61452,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61111
61452
|
throw new Error(`Trying to send a new revision while replaying initial revision. This can lead to endless dispatches every time the spreadsheet is open.
|
|
61112
61453
|
${JSON.stringify(message)}`);
|
|
61113
61454
|
}
|
|
61455
|
+
this.waitingAck = true;
|
|
61114
61456
|
this.transportService.sendMessage({
|
|
61115
61457
|
...message,
|
|
61116
61458
|
serverRevisionId: this.serverRevisionId,
|
|
@@ -61270,8 +61612,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61270
61612
|
}
|
|
61271
61613
|
const color = client.color;
|
|
61272
61614
|
/* Cell background */
|
|
61273
|
-
|
|
61274
|
-
ctx.fillStyle = cellBackgroundColor;
|
|
61615
|
+
ctx.fillStyle = `${color}10`;
|
|
61275
61616
|
ctx.lineWidth = 4 * thinLineWidth;
|
|
61276
61617
|
ctx.strokeStyle = color;
|
|
61277
61618
|
ctx.globalCompositeOperation = "multiply";
|
|
@@ -61638,8 +61979,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61638
61979
|
exportForExcel(data) {
|
|
61639
61980
|
for (const sheetData of data.sheets) {
|
|
61640
61981
|
for (const [row, rowData] of Object.entries(sheetData.rows)) {
|
|
61641
|
-
|
|
61642
|
-
rowData.isHidden = isHidden;
|
|
61982
|
+
rowData.isHidden = this.isRowHidden(sheetData.id, Number(row));
|
|
61643
61983
|
}
|
|
61644
61984
|
}
|
|
61645
61985
|
}
|
|
@@ -61699,6 +62039,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61699
62039
|
this.dispatch("DUPLICATE_PIVOT", {
|
|
61700
62040
|
pivotId,
|
|
61701
62041
|
newPivotId,
|
|
62042
|
+
duplicatedPivotName: _t("%s (copy)", this.getters.getPivotCoreDefinition(pivotId).name),
|
|
61702
62043
|
});
|
|
61703
62044
|
const activeSheetId = this.getters.getActiveSheetId();
|
|
61704
62045
|
const position = this.getters.getSheetIds().indexOf(activeSheetId) + 1;
|
|
@@ -62163,7 +62504,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
62163
62504
|
if (!isEqual(zone, newZone)) {
|
|
62164
62505
|
hasExpanded = true;
|
|
62165
62506
|
zone = newZone;
|
|
62166
|
-
continue;
|
|
62167
62507
|
}
|
|
62168
62508
|
} while (hasExpanded);
|
|
62169
62509
|
return zone;
|
|
@@ -63256,7 +63596,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63256
63596
|
case "ADD_COLUMNS_ROWS": {
|
|
63257
63597
|
this.status = "invisible";
|
|
63258
63598
|
// If we add a col/row inside or before the cut area, we invalidate the clipboard
|
|
63259
|
-
if (this._isCutOperation
|
|
63599
|
+
if (!this._isCutOperation || cmd.sheetId !== this.copiedData?.sheetId) {
|
|
63260
63600
|
return;
|
|
63261
63601
|
}
|
|
63262
63602
|
const isClipboardDirty = this.isColRowDirtyingClipboard(cmd.position === "before" ? cmd.base : cmd.base + 1, cmd.dimension);
|
|
@@ -63268,7 +63608,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63268
63608
|
case "REMOVE_COLUMNS_ROWS": {
|
|
63269
63609
|
this.status = "invisible";
|
|
63270
63610
|
// If we remove a col/row inside or before the cut area, we invalidate the clipboard
|
|
63271
|
-
if (this._isCutOperation
|
|
63611
|
+
if (!this._isCutOperation || cmd.sheetId !== this.copiedData?.sheetId) {
|
|
63272
63612
|
return;
|
|
63273
63613
|
}
|
|
63274
63614
|
for (let el of cmd.elements) {
|
|
@@ -63290,7 +63630,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63290
63630
|
break;
|
|
63291
63631
|
}
|
|
63292
63632
|
case "DELETE_SHEET":
|
|
63293
|
-
if (this._isCutOperation
|
|
63633
|
+
if (!this._isCutOperation) {
|
|
63294
63634
|
return;
|
|
63295
63635
|
}
|
|
63296
63636
|
if (this.originSheetId === cmd.sheetId) {
|
|
@@ -64183,8 +64523,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
64183
64523
|
this.setSelectionMixin({ zone, cell: { col, row } }, [zone]);
|
|
64184
64524
|
}
|
|
64185
64525
|
setActiveSheet(id) {
|
|
64186
|
-
|
|
64187
|
-
this.activeSheet = sheet;
|
|
64526
|
+
this.activeSheet = this.getters.getSheet(id);
|
|
64188
64527
|
}
|
|
64189
64528
|
activateNextSheet(direction) {
|
|
64190
64529
|
const sheetIds = this.getters.getSheetIds();
|
|
@@ -64878,9 +65217,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
64878
65217
|
case "UNFREEZE_COLUMNS_ROWS":
|
|
64879
65218
|
this.resetViewports(this.getters.getActiveSheetId());
|
|
64880
65219
|
break;
|
|
64881
|
-
case "DELETE_SHEET":
|
|
64882
|
-
this.sheetsWithDirtyViewports.delete(cmd.sheetId);
|
|
64883
|
-
break;
|
|
64884
65220
|
case "SCROLL_TO_CELL":
|
|
64885
65221
|
this.refreshViewport(this.getters.getActiveSheetId(), { col: cmd.col, row: cmd.row });
|
|
64886
65222
|
break;
|
|
@@ -66832,10 +67168,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
66832
67168
|
user-select: none;
|
|
66833
67169
|
color: ${TEXT_BODY};
|
|
66834
67170
|
|
|
66835
|
-
.o-
|
|
67171
|
+
.o-sidePanelTitle {
|
|
66836
67172
|
line-height: 20px;
|
|
66837
67173
|
font-size: 16px;
|
|
66838
|
-
font-weight: 600;
|
|
66839
67174
|
}
|
|
66840
67175
|
|
|
66841
67176
|
.o-sidePanelHeader {
|
|
@@ -66920,6 +67255,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
66920
67255
|
}
|
|
66921
67256
|
}
|
|
66922
67257
|
}
|
|
67258
|
+
|
|
67259
|
+
.o-fw-bold {
|
|
67260
|
+
font-weight: 500;
|
|
67261
|
+
}
|
|
66923
67262
|
`;
|
|
66924
67263
|
class SidePanel extends owl.Component {
|
|
66925
67264
|
static template = "o-spreadsheet-SidePanel";
|
|
@@ -67751,8 +68090,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67751
68090
|
for (const item of clipboardItems) {
|
|
67752
68091
|
for (const type of item.types) {
|
|
67753
68092
|
const blob = await item.getType(type);
|
|
67754
|
-
|
|
67755
|
-
clipboardContent[type] = text;
|
|
68093
|
+
clipboardContent[type] = await blob.text();
|
|
67756
68094
|
}
|
|
67757
68095
|
}
|
|
67758
68096
|
return { status: "ok", content: clipboardContent };
|
|
@@ -68064,7 +68402,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
68064
68402
|
spreadsheetRef = owl.useRef("spreadsheet");
|
|
68065
68403
|
spreadsheetRect = useSpreadsheetRect();
|
|
68066
68404
|
_focusGrid;
|
|
68067
|
-
keyDownMapping;
|
|
68068
68405
|
isViewportTooSmall = false;
|
|
68069
68406
|
notificationStore;
|
|
68070
68407
|
composerFocusStore;
|
|
@@ -68088,10 +68425,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
68088
68425
|
this.notificationStore = useStore(NotificationStore);
|
|
68089
68426
|
this.composerFocusStore = useStore(ComposerFocusStore);
|
|
68090
68427
|
this.sidePanel = useStore(SidePanelStore);
|
|
68091
|
-
this.keyDownMapping = {
|
|
68092
|
-
"CTRL+H": () => this.sidePanel.toggle("FindAndReplace", {}),
|
|
68093
|
-
"CTRL+F": () => this.sidePanel.toggle("FindAndReplace", {}),
|
|
68094
|
-
};
|
|
68095
68428
|
const fileStore = this.model.config.external.fileStore;
|
|
68096
68429
|
owl.useSubEnv({
|
|
68097
68430
|
model: this.model,
|
|
@@ -68191,20 +68524,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
68191
68524
|
}
|
|
68192
68525
|
this._focusGrid();
|
|
68193
68526
|
}
|
|
68194
|
-
onKeydown(ev) {
|
|
68195
|
-
let keyDownString = "";
|
|
68196
|
-
if (isCtrlKey(ev)) {
|
|
68197
|
-
keyDownString += "CTRL+";
|
|
68198
|
-
}
|
|
68199
|
-
keyDownString += ev.key.toUpperCase();
|
|
68200
|
-
let handler = this.keyDownMapping[keyDownString];
|
|
68201
|
-
if (handler) {
|
|
68202
|
-
ev.preventDefault();
|
|
68203
|
-
ev.stopPropagation();
|
|
68204
|
-
handler();
|
|
68205
|
-
return;
|
|
68206
|
-
}
|
|
68207
|
-
}
|
|
68208
68527
|
get gridHeight() {
|
|
68209
68528
|
const { height } = this.env.model.getters.getSheetViewDimension();
|
|
68210
68529
|
return height;
|
|
@@ -69619,10 +69938,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
69619
69938
|
getNextCellPosition(currentPosition, dimension, direction) {
|
|
69620
69939
|
const dimOfInterest = dimension === "cols" ? "col" : "row";
|
|
69621
69940
|
const startingPosition = { ...currentPosition };
|
|
69622
|
-
|
|
69623
|
-
|
|
69624
|
-
|
|
69625
|
-
|
|
69941
|
+
startingPosition[dimOfInterest] =
|
|
69942
|
+
dimension === "cols"
|
|
69943
|
+
? this.getNextAvailableCol(direction, startingPosition.col, startingPosition.row)
|
|
69944
|
+
: this.getNextAvailableRow(direction, startingPosition.col, startingPosition.row);
|
|
69626
69945
|
return { col: startingPosition.col, row: startingPosition.row };
|
|
69627
69946
|
}
|
|
69628
69947
|
getPosition() {
|
|
@@ -69746,6 +70065,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
69746
70065
|
case "pie":
|
|
69747
70066
|
plot = addDoughnutChart(chart.data, chartSheetIndex, data, { holeSize: 0 });
|
|
69748
70067
|
break;
|
|
70068
|
+
case "radar":
|
|
70069
|
+
plot = addRadarChart(chart.data);
|
|
69749
70070
|
}
|
|
69750
70071
|
let position = "t";
|
|
69751
70072
|
switch (chart.data.legendPosition) {
|
|
@@ -70204,6 +70525,53 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
70204
70525
|
`
|
|
70205
70526
|
: ""}`;
|
|
70206
70527
|
}
|
|
70528
|
+
function addRadarChart(chart) {
|
|
70529
|
+
const dataSetsColors = chart.dataSets.map((ds) => ds.backgroundColor ?? "");
|
|
70530
|
+
const colors = new ColorGenerator(chart.dataSets.length, dataSetsColors);
|
|
70531
|
+
const dataSetsNodes = [];
|
|
70532
|
+
for (const [dsIndex, dataset] of Object.entries(chart.dataSets)) {
|
|
70533
|
+
const color = toXlsxHexColor(colors.next());
|
|
70534
|
+
const dataShapeProperty = shapeProperty({
|
|
70535
|
+
line: {
|
|
70536
|
+
width: 2.5,
|
|
70537
|
+
style: "solid",
|
|
70538
|
+
color,
|
|
70539
|
+
},
|
|
70540
|
+
});
|
|
70541
|
+
const dataSetNode = escapeXml /*xml*/ `
|
|
70542
|
+
<c:ser>
|
|
70543
|
+
<c:idx val="${dsIndex}"/>
|
|
70544
|
+
<c:order val="${dsIndex}"/>
|
|
70545
|
+
<c:smooth val="0"/>
|
|
70546
|
+
<c:marker>
|
|
70547
|
+
<c:symbol val="circle" />
|
|
70548
|
+
<c:size val="5"/>
|
|
70549
|
+
${shapeProperty({ backgroundColor: color, line: { color } })}
|
|
70550
|
+
</c:marker>
|
|
70551
|
+
${extractDataSetLabel(dataset.label)}
|
|
70552
|
+
${dataShapeProperty}
|
|
70553
|
+
${chart.labelRange ? escapeXml `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""} <!-- x-coordinate values -->
|
|
70554
|
+
<c:val> <!-- x-coordinate values -->
|
|
70555
|
+
${numberRef(dataset.range)}
|
|
70556
|
+
</c:val>
|
|
70557
|
+
</c:ser>
|
|
70558
|
+
`;
|
|
70559
|
+
dataSetsNodes.push(dataSetNode);
|
|
70560
|
+
}
|
|
70561
|
+
return escapeXml /*xml*/ `
|
|
70562
|
+
${escapeXml /*xml*/ `
|
|
70563
|
+
<c:radarChart>
|
|
70564
|
+
<c:radarStyle val="marker"/>
|
|
70565
|
+
<c:varyColors val="0"/>
|
|
70566
|
+
${joinXmlNodes(dataSetsNodes)}
|
|
70567
|
+
<c:axId val="${catAxId}" />
|
|
70568
|
+
<c:axId val="${valAxId}" />
|
|
70569
|
+
</c:radarChart>
|
|
70570
|
+
${addAx("b", "c:catAx", catAxId, valAxId, chart.axesDesign?.x?.title, chart.fontColor)}
|
|
70571
|
+
${addAx("l", "c:valAx", valAxId, catAxId, chart.axesDesign?.y?.title, chart.fontColor)}
|
|
70572
|
+
`}
|
|
70573
|
+
`;
|
|
70574
|
+
}
|
|
70207
70575
|
function addDoughnutChart(chart, chartSheetIndex, data, { holeSize } = { holeSize: 50 }) {
|
|
70208
70576
|
const maxLength = largeMax(chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
|
|
70209
70577
|
const colors = new ColorGenerator(maxLength);
|
|
@@ -71311,25 +71679,23 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71311
71679
|
["showGridLines", sheet.areGridLinesVisible ? 1 : 0],
|
|
71312
71680
|
["workbookViewId", 0],
|
|
71313
71681
|
];
|
|
71314
|
-
|
|
71682
|
+
return escapeXml /*xml*/ `
|
|
71315
71683
|
<sheetViews>
|
|
71316
71684
|
<sheetView ${formatAttributes(sheetViewAttrs)}>
|
|
71317
71685
|
${splitPanes}
|
|
71318
71686
|
</sheetView>
|
|
71319
71687
|
</sheetViews>
|
|
71320
71688
|
`;
|
|
71321
|
-
return sheetView;
|
|
71322
71689
|
}
|
|
71323
71690
|
function addSheetProperties(sheet) {
|
|
71324
71691
|
if (!sheet.color) {
|
|
71325
71692
|
return "";
|
|
71326
71693
|
}
|
|
71327
|
-
|
|
71694
|
+
return escapeXml /*xml*/ `
|
|
71328
71695
|
<sheetPr>
|
|
71329
71696
|
<tabColor ${formatAttributes([["rgb", toXlsxHexColor(sheet.color)]])} />
|
|
71330
71697
|
</sheetPr>
|
|
71331
71698
|
`;
|
|
71332
|
-
return sheetView;
|
|
71333
71699
|
}
|
|
71334
71700
|
|
|
71335
71701
|
/**
|
|
@@ -71642,9 +72008,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71642
72008
|
})(Status || (Status = {}));
|
|
71643
72009
|
class Model extends EventBus {
|
|
71644
72010
|
corePlugins = [];
|
|
71645
|
-
featurePlugins = [];
|
|
71646
72011
|
statefulUIPlugins = [];
|
|
71647
|
-
coreViewsPlugins = [];
|
|
71648
72012
|
range;
|
|
71649
72013
|
session;
|
|
71650
72014
|
/**
|
|
@@ -71689,7 +72053,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71689
72053
|
coreHandlers = [];
|
|
71690
72054
|
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = false) {
|
|
71691
72055
|
const start = performance.now();
|
|
71692
|
-
console.
|
|
72056
|
+
console.debug("##### Model creation #####");
|
|
71693
72057
|
super();
|
|
71694
72058
|
setDefaultTranslationMethod();
|
|
71695
72059
|
stateUpdateMessages = repairInitialMessages(data, stateUpdateMessages);
|
|
@@ -71730,7 +72094,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71730
72094
|
this.session.loadInitialMessages(stateUpdateMessages);
|
|
71731
72095
|
for (let Plugin of coreViewsPluginRegistry.getAll()) {
|
|
71732
72096
|
const plugin = this.setupUiPlugin(Plugin);
|
|
71733
|
-
this.coreViewsPlugins.push(plugin);
|
|
71734
72097
|
this.handlers.push(plugin);
|
|
71735
72098
|
this.uiHandlers.push(plugin);
|
|
71736
72099
|
this.coreHandlers.push(plugin);
|
|
@@ -71743,7 +72106,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71743
72106
|
}
|
|
71744
72107
|
for (let Plugin of featurePluginRegistry.getAll()) {
|
|
71745
72108
|
const plugin = this.setupUiPlugin(Plugin);
|
|
71746
|
-
this.featurePlugins.push(plugin);
|
|
71747
72109
|
this.handlers.push(plugin);
|
|
71748
72110
|
this.uiHandlers.push(plugin);
|
|
71749
72111
|
}
|
|
@@ -71760,16 +72122,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71760
72122
|
this.joinSession();
|
|
71761
72123
|
if (config.snapshotRequested) {
|
|
71762
72124
|
const startSnapshot = performance.now();
|
|
71763
|
-
console.
|
|
72125
|
+
console.debug("Snapshot requested");
|
|
71764
72126
|
this.session.snapshot(this.exportData());
|
|
71765
72127
|
this.garbageCollectExternalResources();
|
|
71766
|
-
console.
|
|
72128
|
+
console.debug("Snapshot taken in", performance.now() - startSnapshot, "ms");
|
|
71767
72129
|
}
|
|
71768
72130
|
// mark all models as "raw", so they will not be turned into reactive objects
|
|
71769
72131
|
// by owl, since we do not rely on reactivity
|
|
71770
72132
|
owl.markRaw(this);
|
|
71771
|
-
console.
|
|
71772
|
-
console.
|
|
72133
|
+
console.debug("Model created in", performance.now() - start, "ms");
|
|
72134
|
+
console.debug("######");
|
|
71773
72135
|
}
|
|
71774
72136
|
joinSession() {
|
|
71775
72137
|
this.session.join(this.config.client);
|
|
@@ -71828,7 +72190,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71828
72190
|
this.finalize();
|
|
71829
72191
|
}
|
|
71830
72192
|
setupSession(revisionId) {
|
|
71831
|
-
|
|
72193
|
+
return new Session(buildRevisionLog({
|
|
71832
72194
|
initialRevisionId: revisionId,
|
|
71833
72195
|
recordChanges: this.state.recordChanges.bind(this.state),
|
|
71834
72196
|
dispatch: (command) => {
|
|
@@ -71841,7 +72203,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71841
72203
|
this.isReplayingCommand = false;
|
|
71842
72204
|
},
|
|
71843
72205
|
}), this.config.transportService, revisionId);
|
|
71844
|
-
return session;
|
|
71845
72206
|
}
|
|
71846
72207
|
setupSessionEvents() {
|
|
71847
72208
|
this.session.on("remote-revision-received", this, this.onRemoteRevisionReceived);
|
|
@@ -71934,8 +72295,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71934
72295
|
return results;
|
|
71935
72296
|
}
|
|
71936
72297
|
checkDispatchAllowedLocalCommand(command) {
|
|
71937
|
-
|
|
71938
|
-
return results;
|
|
72298
|
+
return this.uiHandlers.map((handler) => handler.allowDispatch(command));
|
|
71939
72299
|
}
|
|
71940
72300
|
finalize() {
|
|
71941
72301
|
this.status = 3 /* Status.Finalizing */;
|
|
@@ -71992,7 +72352,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71992
72352
|
this.finalize();
|
|
71993
72353
|
const time = performance.now() - start;
|
|
71994
72354
|
if (time > 5) {
|
|
71995
|
-
console.
|
|
72355
|
+
console.debug(type, time, "ms");
|
|
71996
72356
|
}
|
|
71997
72357
|
});
|
|
71998
72358
|
this.session.save(command, commands, changes);
|
|
@@ -72295,7 +72655,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
72295
72655
|
PivotDimensionOrder,
|
|
72296
72656
|
PivotDimension,
|
|
72297
72657
|
PivotLayoutConfigurator,
|
|
72298
|
-
EditableName,
|
|
72299
72658
|
PivotDeferUpdate,
|
|
72300
72659
|
PivotTitleSection,
|
|
72301
72660
|
CogWheelMenu,
|
|
@@ -72387,9 +72746,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
72387
72746
|
exports.tokenize = tokenize;
|
|
72388
72747
|
|
|
72389
72748
|
|
|
72390
|
-
__info__.version = "18.1.0-alpha.
|
|
72391
|
-
__info__.date = "2024-10-
|
|
72392
|
-
__info__.hash = "
|
|
72749
|
+
__info__.version = "18.1.0-alpha.2";
|
|
72750
|
+
__info__.date = "2024-10-24T08:53:21.828Z";
|
|
72751
|
+
__info__.hash = "2a01250";
|
|
72393
72752
|
|
|
72394
72753
|
|
|
72395
72754
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|