@odoo/o-spreadsheet 17.4.8 → 17.4.10
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 +333 -231
- package/dist/o-spreadsheet.d.ts +4 -0
- package/dist/o-spreadsheet.esm.js +333 -231
- package/dist/o-spreadsheet.iife.js +333 -231
- package/dist/o-spreadsheet.iife.min.js +425 -425
- package/dist/o_spreadsheet.xml +3 -3
- package/package.json +2 -2
|
@@ -2,13 +2,118 @@
|
|
|
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 17.4.
|
|
6
|
-
* @date 2024-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.4.10
|
|
6
|
+
* @date 2024-10-24T08:54:56.262Z
|
|
7
|
+
* @hash c82d9c1
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
11
11
|
|
|
12
|
+
function createActions(menuItems) {
|
|
13
|
+
return menuItems.map(createAction).sort((a, b) => a.sequence - b.sequence);
|
|
14
|
+
}
|
|
15
|
+
let nextItemId = 1;
|
|
16
|
+
function createAction(item) {
|
|
17
|
+
const name = item.name;
|
|
18
|
+
const children = item.children;
|
|
19
|
+
const description = item.description;
|
|
20
|
+
const icon = item.icon;
|
|
21
|
+
const secondaryIcon = item.secondaryIcon;
|
|
22
|
+
const itemId = item.id || nextItemId++;
|
|
23
|
+
return {
|
|
24
|
+
id: itemId.toString(),
|
|
25
|
+
name: typeof name === "function" ? name : () => name,
|
|
26
|
+
isVisible: item.isVisible ? item.isVisible : () => true,
|
|
27
|
+
isEnabled: item.isEnabled ? item.isEnabled : () => true,
|
|
28
|
+
isActive: item.isActive,
|
|
29
|
+
execute: item.execute,
|
|
30
|
+
children: children
|
|
31
|
+
? (env) => {
|
|
32
|
+
return children
|
|
33
|
+
.map((child) => (typeof child === "function" ? child(env) : child))
|
|
34
|
+
.flat()
|
|
35
|
+
.map(createAction);
|
|
36
|
+
}
|
|
37
|
+
: () => [],
|
|
38
|
+
isReadonlyAllowed: item.isReadonlyAllowed || false,
|
|
39
|
+
separator: item.separator || false,
|
|
40
|
+
icon: typeof icon === "function" ? icon : () => icon || "",
|
|
41
|
+
secondaryIcon: typeof secondaryIcon === "function" ? secondaryIcon : () => secondaryIcon || "",
|
|
42
|
+
description: typeof description === "function" ? description : () => description || "",
|
|
43
|
+
textColor: item.textColor,
|
|
44
|
+
sequence: item.sequence || 0,
|
|
45
|
+
onStartHover: item.onStartHover,
|
|
46
|
+
onStopHover: item.onStopHover,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Registry
|
|
52
|
+
*
|
|
53
|
+
* The Registry class is basically just a mapping from a string key to an object.
|
|
54
|
+
* It is really not much more than an object. It is however useful for the
|
|
55
|
+
* following reasons:
|
|
56
|
+
*
|
|
57
|
+
* 1. it let us react and execute code when someone add something to the registry
|
|
58
|
+
* (for example, the FunctionRegistry subclass this for this purpose)
|
|
59
|
+
* 2. it throws an error when the get operation fails
|
|
60
|
+
* 3. it provides a chained API to add items to the registry.
|
|
61
|
+
*/
|
|
62
|
+
class Registry {
|
|
63
|
+
content = {};
|
|
64
|
+
/**
|
|
65
|
+
* Add an item to the registry
|
|
66
|
+
*
|
|
67
|
+
* Note that this also returns the registry, so another add method call can
|
|
68
|
+
* be chained
|
|
69
|
+
*/
|
|
70
|
+
add(key, value) {
|
|
71
|
+
this.content[key] = value;
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get an item from the registry
|
|
76
|
+
*/
|
|
77
|
+
get(key) {
|
|
78
|
+
/**
|
|
79
|
+
* Note: key in {} is ~12 times slower than {}[key].
|
|
80
|
+
* So, we check the absence of key only when the direct access returns
|
|
81
|
+
* a falsy value. It's done to ensure that the registry can contains falsy values
|
|
82
|
+
*/
|
|
83
|
+
const content = this.content[key];
|
|
84
|
+
if (!content) {
|
|
85
|
+
if (!(key in this.content)) {
|
|
86
|
+
throw new Error(`Cannot find ${key} in this registry!`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return content;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Check if the key is already in the registry
|
|
93
|
+
*/
|
|
94
|
+
contains(key) {
|
|
95
|
+
return key in this.content;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get a list of all elements in the registry
|
|
99
|
+
*/
|
|
100
|
+
getAll() {
|
|
101
|
+
return Object.values(this.content);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Get a list of all keys in the registry
|
|
105
|
+
*/
|
|
106
|
+
getKeys() {
|
|
107
|
+
return Object.keys(this.content);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Remove an item from the registry
|
|
111
|
+
*/
|
|
112
|
+
remove(key) {
|
|
113
|
+
delete this.content[key];
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
12
117
|
const CANVAS_SHIFT = 0.5;
|
|
13
118
|
// Colors
|
|
14
119
|
const HIGHLIGHT_COLOR = "#37A850";
|
|
@@ -165,7 +270,7 @@ const DEFAULT_STYLE = {
|
|
|
165
270
|
underline: false,
|
|
166
271
|
fontSize: 10,
|
|
167
272
|
fillColor: "",
|
|
168
|
-
textColor: "
|
|
273
|
+
textColor: "",
|
|
169
274
|
};
|
|
170
275
|
const DEFAULT_VERTICAL_ALIGN = DEFAULT_STYLE.verticalAlign;
|
|
171
276
|
const DEFAULT_WRAPPING_MODE = DEFAULT_STYLE.wrapping;
|
|
@@ -5397,110 +5502,6 @@ class UuidGenerator {
|
|
|
5397
5502
|
}
|
|
5398
5503
|
}
|
|
5399
5504
|
|
|
5400
|
-
function createActions(menuItems) {
|
|
5401
|
-
return menuItems.map(createAction).sort((a, b) => a.sequence - b.sequence);
|
|
5402
|
-
}
|
|
5403
|
-
const uuidGenerator$1 = new UuidGenerator();
|
|
5404
|
-
function createAction(item) {
|
|
5405
|
-
const name = item.name;
|
|
5406
|
-
const children = item.children;
|
|
5407
|
-
const description = item.description;
|
|
5408
|
-
const icon = item.icon;
|
|
5409
|
-
const secondaryIcon = item.secondaryIcon;
|
|
5410
|
-
return {
|
|
5411
|
-
id: item.id || uuidGenerator$1.uuidv4(),
|
|
5412
|
-
name: typeof name === "function" ? name : () => name,
|
|
5413
|
-
isVisible: item.isVisible ? item.isVisible : () => true,
|
|
5414
|
-
isEnabled: item.isEnabled ? item.isEnabled : () => true,
|
|
5415
|
-
isActive: item.isActive,
|
|
5416
|
-
execute: item.execute,
|
|
5417
|
-
children: children
|
|
5418
|
-
? (env) => {
|
|
5419
|
-
return children
|
|
5420
|
-
.map((child) => (typeof child === "function" ? child(env) : child))
|
|
5421
|
-
.flat()
|
|
5422
|
-
.map(createAction);
|
|
5423
|
-
}
|
|
5424
|
-
: () => [],
|
|
5425
|
-
isReadonlyAllowed: item.isReadonlyAllowed || false,
|
|
5426
|
-
separator: item.separator || false,
|
|
5427
|
-
icon: typeof icon === "function" ? icon : () => icon || "",
|
|
5428
|
-
secondaryIcon: typeof secondaryIcon === "function" ? secondaryIcon : () => secondaryIcon || "",
|
|
5429
|
-
description: typeof description === "function" ? description : () => description || "",
|
|
5430
|
-
textColor: item.textColor,
|
|
5431
|
-
sequence: item.sequence || 0,
|
|
5432
|
-
onStartHover: item.onStartHover,
|
|
5433
|
-
onStopHover: item.onStopHover,
|
|
5434
|
-
};
|
|
5435
|
-
}
|
|
5436
|
-
|
|
5437
|
-
/**
|
|
5438
|
-
* Registry
|
|
5439
|
-
*
|
|
5440
|
-
* The Registry class is basically just a mapping from a string key to an object.
|
|
5441
|
-
* It is really not much more than an object. It is however useful for the
|
|
5442
|
-
* following reasons:
|
|
5443
|
-
*
|
|
5444
|
-
* 1. it let us react and execute code when someone add something to the registry
|
|
5445
|
-
* (for example, the FunctionRegistry subclass this for this purpose)
|
|
5446
|
-
* 2. it throws an error when the get operation fails
|
|
5447
|
-
* 3. it provides a chained API to add items to the registry.
|
|
5448
|
-
*/
|
|
5449
|
-
class Registry {
|
|
5450
|
-
content = {};
|
|
5451
|
-
/**
|
|
5452
|
-
* Add an item to the registry
|
|
5453
|
-
*
|
|
5454
|
-
* Note that this also returns the registry, so another add method call can
|
|
5455
|
-
* be chained
|
|
5456
|
-
*/
|
|
5457
|
-
add(key, value) {
|
|
5458
|
-
this.content[key] = value;
|
|
5459
|
-
return this;
|
|
5460
|
-
}
|
|
5461
|
-
/**
|
|
5462
|
-
* Get an item from the registry
|
|
5463
|
-
*/
|
|
5464
|
-
get(key) {
|
|
5465
|
-
/**
|
|
5466
|
-
* Note: key in {} is ~12 times slower than {}[key].
|
|
5467
|
-
* So, we check the absence of key only when the direct access returns
|
|
5468
|
-
* a falsy value. It's done to ensure that the registry can contains falsy values
|
|
5469
|
-
*/
|
|
5470
|
-
const content = this.content[key];
|
|
5471
|
-
if (!content) {
|
|
5472
|
-
if (!(key in this.content)) {
|
|
5473
|
-
throw new Error(`Cannot find ${key} in this registry!`);
|
|
5474
|
-
}
|
|
5475
|
-
}
|
|
5476
|
-
return content;
|
|
5477
|
-
}
|
|
5478
|
-
/**
|
|
5479
|
-
* Check if the key is already in the registry
|
|
5480
|
-
*/
|
|
5481
|
-
contains(key) {
|
|
5482
|
-
return key in this.content;
|
|
5483
|
-
}
|
|
5484
|
-
/**
|
|
5485
|
-
* Get a list of all elements in the registry
|
|
5486
|
-
*/
|
|
5487
|
-
getAll() {
|
|
5488
|
-
return Object.values(this.content);
|
|
5489
|
-
}
|
|
5490
|
-
/**
|
|
5491
|
-
* Get a list of all keys in the registry
|
|
5492
|
-
*/
|
|
5493
|
-
getKeys() {
|
|
5494
|
-
return Object.keys(this.content);
|
|
5495
|
-
}
|
|
5496
|
-
/**
|
|
5497
|
-
* Remove an item from the registry
|
|
5498
|
-
*/
|
|
5499
|
-
remove(key) {
|
|
5500
|
-
delete this.content[key];
|
|
5501
|
-
}
|
|
5502
|
-
}
|
|
5503
|
-
|
|
5504
5505
|
function getClipboardDataPositions(sheetId, zones) {
|
|
5505
5506
|
const lefts = new Set(zones.map((z) => z.left));
|
|
5506
5507
|
const rights = new Set(zones.map((z) => z.right));
|
|
@@ -7279,31 +7280,34 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
7279
7280
|
for (let col of columnsIndexes) {
|
|
7280
7281
|
const position = { col, row, sheetId };
|
|
7281
7282
|
const table = this.getters.getTable(position);
|
|
7282
|
-
if (!table
|
|
7283
|
+
if (!table) {
|
|
7283
7284
|
tableCellsInRow.push({});
|
|
7284
7285
|
continue;
|
|
7285
7286
|
}
|
|
7286
7287
|
const coreTable = this.getters.getCoreTable(position);
|
|
7287
7288
|
const tableZone = coreTable?.range.zone;
|
|
7289
|
+
let copiedTable = undefined;
|
|
7288
7290
|
// Copy whole table
|
|
7289
|
-
if (
|
|
7290
|
-
|
|
7291
|
+
if (!copiedTablesIds.has(table.id) &&
|
|
7292
|
+
coreTable &&
|
|
7293
|
+
tableZone &&
|
|
7294
|
+
zones.some((z) => isZoneInside(tableZone, z))) {
|
|
7295
|
+
copiedTablesIds.add(table.id);
|
|
7291
7296
|
const values = [];
|
|
7292
7297
|
for (const col of range(tableZone.left, tableZone.right + 1)) {
|
|
7293
7298
|
values.push(this.getters.getFilterHiddenValues({ sheetId, col, row: tableZone.top }));
|
|
7294
7299
|
}
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
},
|
|
7301
|
-
});
|
|
7302
|
-
}
|
|
7303
|
-
// Copy only style of cell
|
|
7304
|
-
else if (table) {
|
|
7305
|
-
tableCellsInRow.push({ style: this.getTableStyleToCopy(position) });
|
|
7300
|
+
copiedTable = {
|
|
7301
|
+
range: coreTable.range,
|
|
7302
|
+
config: coreTable.config,
|
|
7303
|
+
type: coreTable.type,
|
|
7304
|
+
};
|
|
7306
7305
|
}
|
|
7306
|
+
tableCellsInRow.push({
|
|
7307
|
+
table: copiedTable,
|
|
7308
|
+
style: this.getTableStyleToCopy(position),
|
|
7309
|
+
isWholeTableCopied: copiedTablesIds.has(table.id),
|
|
7310
|
+
});
|
|
7307
7311
|
}
|
|
7308
7312
|
}
|
|
7309
7313
|
return {
|
|
@@ -7384,11 +7388,14 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
7384
7388
|
tableType: tableCell.table.type,
|
|
7385
7389
|
});
|
|
7386
7390
|
}
|
|
7387
|
-
// Do not paste table style if we're inside another table
|
|
7388
7391
|
// We cannot check for dynamic tables, because at this point the paste can have changed the evaluation, and the
|
|
7389
7392
|
// dynamic tables are not yet computed
|
|
7390
|
-
if (
|
|
7391
|
-
|
|
7393
|
+
if (this.getters.getCoreTable(position) || options?.pasteOption === "asValue") {
|
|
7394
|
+
return;
|
|
7395
|
+
}
|
|
7396
|
+
if ((!options?.pasteOption && !tableCell.isWholeTableCopied) ||
|
|
7397
|
+
options?.pasteOption === "onlyFormat") {
|
|
7398
|
+
if (tableCell.style?.style) {
|
|
7392
7399
|
this.dispatch("UPDATE_CELL", { ...position, style: tableCell.style.style });
|
|
7393
7400
|
}
|
|
7394
7401
|
if (tableCell.style?.border) {
|
|
@@ -10616,67 +10623,108 @@ const chartShowValuesPlugin = {
|
|
|
10616
10623
|
ctx.save();
|
|
10617
10624
|
ctx.textAlign = "center";
|
|
10618
10625
|
ctx.textBaseline = "middle";
|
|
10619
|
-
ctx.
|
|
10620
|
-
|
|
10621
|
-
|
|
10622
|
-
|
|
10623
|
-
|
|
10624
|
-
|
|
10625
|
-
|
|
10626
|
-
|
|
10627
|
-
|
|
10628
|
-
|
|
10629
|
-
|
|
10630
|
-
|
|
10631
|
-
|
|
10632
|
-
ctx.fillStyle = chartFontColor(bar.options.backgroundColor);
|
|
10633
|
-
ctx.strokeStyle = chartFontColor(ctx.fillStyle);
|
|
10634
|
-
const value = options.callback(dataset._parsed[i]);
|
|
10635
|
-
ctx.strokeText(value, x, y);
|
|
10636
|
-
ctx.fillText(value, x, y);
|
|
10637
|
-
}
|
|
10638
|
-
break;
|
|
10639
|
-
}
|
|
10640
|
-
case "bar":
|
|
10641
|
-
case "line": {
|
|
10642
|
-
const yOffset = dataset.type === "bar" && !options.horizontal ? 0 : 3;
|
|
10643
|
-
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
10644
|
-
const point = dataset.data[i];
|
|
10645
|
-
const value = options.horizontal ? dataset._parsed[i].x : dataset._parsed[i].y;
|
|
10646
|
-
const displayedValue = options.callback(value - 0);
|
|
10647
|
-
let xPosition = 0, yPosition = 0;
|
|
10648
|
-
if (options.horizontal) {
|
|
10649
|
-
yPosition = point.y;
|
|
10650
|
-
if (value < 0) {
|
|
10651
|
-
ctx.textAlign = "right";
|
|
10652
|
-
xPosition = point.x - yOffset;
|
|
10653
|
-
}
|
|
10654
|
-
else {
|
|
10655
|
-
ctx.textAlign = "left";
|
|
10656
|
-
xPosition = point.x + yOffset;
|
|
10657
|
-
}
|
|
10658
|
-
}
|
|
10659
|
-
else {
|
|
10660
|
-
xPosition = point.x;
|
|
10661
|
-
if (value < 0) {
|
|
10662
|
-
ctx.textBaseline = "top";
|
|
10663
|
-
yPosition = point.y + yOffset;
|
|
10664
|
-
}
|
|
10665
|
-
else {
|
|
10666
|
-
ctx.textBaseline = "bottom";
|
|
10667
|
-
yPosition = point.y - yOffset;
|
|
10668
|
-
}
|
|
10669
|
-
}
|
|
10670
|
-
ctx.strokeText(displayedValue, xPosition, yPosition);
|
|
10671
|
-
ctx.fillText(displayedValue, xPosition, yPosition);
|
|
10672
|
-
}
|
|
10673
|
-
break;
|
|
10674
|
-
}
|
|
10675
|
-
}
|
|
10676
|
-
});
|
|
10626
|
+
ctx.miterLimit = 1; // Avoid sharp artifacts on strokeText
|
|
10627
|
+
switch (chart.config.type) {
|
|
10628
|
+
case "pie":
|
|
10629
|
+
case "doughnut":
|
|
10630
|
+
drawPieChartValues(chart, options, ctx);
|
|
10631
|
+
break;
|
|
10632
|
+
case "bar":
|
|
10633
|
+
case "line":
|
|
10634
|
+
options.horizontal
|
|
10635
|
+
? drawHorizontalBarChartValues(chart, options, ctx)
|
|
10636
|
+
: drawLineOrBarChartValues(chart, options, ctx);
|
|
10637
|
+
break;
|
|
10638
|
+
}
|
|
10677
10639
|
ctx.restore();
|
|
10678
10640
|
},
|
|
10679
10641
|
};
|
|
10642
|
+
function drawTextWithBackground(text, x, y, ctx) {
|
|
10643
|
+
ctx.lineWidth = 3; // Stroke the text with a big lineWidth width to have some kind of background
|
|
10644
|
+
ctx.strokeText(text, x, y);
|
|
10645
|
+
ctx.lineWidth = 1;
|
|
10646
|
+
ctx.fillText(text, x, y);
|
|
10647
|
+
}
|
|
10648
|
+
function drawLineOrBarChartValues(chart, options, ctx) {
|
|
10649
|
+
const yMax = chart.chartArea.bottom;
|
|
10650
|
+
const yMin = chart.chartArea.top;
|
|
10651
|
+
const textsPositions = {};
|
|
10652
|
+
for (const dataset of chart._metasets) {
|
|
10653
|
+
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
10654
|
+
const value = dataset._parsed[i].y;
|
|
10655
|
+
const point = dataset.data[i];
|
|
10656
|
+
const xPosition = point.x;
|
|
10657
|
+
let yPosition = 0;
|
|
10658
|
+
if (chart.config.type === "line") {
|
|
10659
|
+
yPosition = point.y - 10;
|
|
10660
|
+
}
|
|
10661
|
+
else {
|
|
10662
|
+
yPosition = value < 0 ? point.y - point.height / 2 : point.y + point.height / 2;
|
|
10663
|
+
}
|
|
10664
|
+
yPosition = Math.min(yPosition, yMax);
|
|
10665
|
+
yPosition = Math.max(yPosition, yMin);
|
|
10666
|
+
// Avoid overlapping texts with same X
|
|
10667
|
+
if (!textsPositions[xPosition]) {
|
|
10668
|
+
textsPositions[xPosition] = [];
|
|
10669
|
+
}
|
|
10670
|
+
for (const otherPosition of textsPositions[xPosition] || []) {
|
|
10671
|
+
if (Math.abs(otherPosition - yPosition) < 13) {
|
|
10672
|
+
yPosition = otherPosition - 13;
|
|
10673
|
+
}
|
|
10674
|
+
}
|
|
10675
|
+
textsPositions[xPosition].push(yPosition);
|
|
10676
|
+
ctx.fillStyle = point.options.backgroundColor;
|
|
10677
|
+
ctx.strokeStyle = options.background || "#ffffff";
|
|
10678
|
+
drawTextWithBackground(options.callback(value - 0), xPosition, yPosition, ctx);
|
|
10679
|
+
}
|
|
10680
|
+
}
|
|
10681
|
+
}
|
|
10682
|
+
function drawHorizontalBarChartValues(chart, options, ctx) {
|
|
10683
|
+
const xMax = chart.chartArea.right;
|
|
10684
|
+
const xMin = chart.chartArea.left;
|
|
10685
|
+
const textsPositions = {};
|
|
10686
|
+
for (const dataset of chart._metasets) {
|
|
10687
|
+
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
10688
|
+
const value = dataset._parsed[i].x;
|
|
10689
|
+
const displayValue = options.callback(value - 0);
|
|
10690
|
+
const point = dataset.data[i];
|
|
10691
|
+
const yPosition = point.y;
|
|
10692
|
+
let xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
|
|
10693
|
+
xPosition = Math.min(xPosition, xMax);
|
|
10694
|
+
xPosition = Math.max(xPosition, xMin);
|
|
10695
|
+
// Avoid overlapping texts with same Y
|
|
10696
|
+
if (!textsPositions[yPosition]) {
|
|
10697
|
+
textsPositions[yPosition] = [];
|
|
10698
|
+
}
|
|
10699
|
+
const textWidth = computeTextWidth(ctx, displayValue, { fontSize: 12 }, "px");
|
|
10700
|
+
for (const otherPosition of textsPositions[yPosition]) {
|
|
10701
|
+
if (Math.abs(otherPosition - xPosition) < textWidth) {
|
|
10702
|
+
xPosition = otherPosition + textWidth + 3;
|
|
10703
|
+
}
|
|
10704
|
+
}
|
|
10705
|
+
textsPositions[yPosition].push(xPosition);
|
|
10706
|
+
ctx.fillStyle = point.options.backgroundColor;
|
|
10707
|
+
ctx.strokeStyle = options.background || "#ffffff";
|
|
10708
|
+
drawTextWithBackground(displayValue, xPosition, yPosition, ctx);
|
|
10709
|
+
}
|
|
10710
|
+
}
|
|
10711
|
+
}
|
|
10712
|
+
function drawPieChartValues(chart, options, ctx) {
|
|
10713
|
+
for (const dataset of chart._metasets) {
|
|
10714
|
+
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
10715
|
+
const bar = dataset.data[i];
|
|
10716
|
+
const { startAngle, endAngle, innerRadius, outerRadius } = bar;
|
|
10717
|
+
const midAngle = (startAngle + endAngle) / 2;
|
|
10718
|
+
const midRadius = (innerRadius + outerRadius) / 2;
|
|
10719
|
+
const x = bar.x + midRadius * Math.cos(midAngle);
|
|
10720
|
+
const y = bar.y + midRadius * Math.sin(midAngle) + 7;
|
|
10721
|
+
ctx.fillStyle = chartFontColor(options.background);
|
|
10722
|
+
ctx.strokeStyle = options.background || "#ffffff";
|
|
10723
|
+
const value = options.callback(dataset._parsed[i]);
|
|
10724
|
+
drawTextWithBackground(value, x, y, ctx);
|
|
10725
|
+
}
|
|
10726
|
+
}
|
|
10727
|
+
}
|
|
10680
10728
|
|
|
10681
10729
|
/** This is a chartJS plugin that will draw connector lines between the bars of a Waterfall chart */
|
|
10682
10730
|
const waterfallLinesPlugin = {
|
|
@@ -19154,9 +19202,10 @@ const PIVOT_VALUE = {
|
|
|
19154
19202
|
return error;
|
|
19155
19203
|
}
|
|
19156
19204
|
if (!pivot.areDomainArgsFieldsValid(domainArgs)) {
|
|
19205
|
+
const suggestion = _t("Consider using a dynamic pivot formula: %s. Or re-insert the static pivot from the Data menu.", `=PIVOT(${_pivotFormulaId})`);
|
|
19157
19206
|
return {
|
|
19158
19207
|
value: CellErrorType.GenericError,
|
|
19159
|
-
message: _t("Dimensions don't match the pivot definition"),
|
|
19208
|
+
message: _t("Dimensions don't match the pivot definition") + ". " + suggestion,
|
|
19160
19209
|
};
|
|
19161
19210
|
}
|
|
19162
19211
|
const domain = pivot.parseArgsToPivotDomain(domainArgs);
|
|
@@ -19183,9 +19232,10 @@ const PIVOT_HEADER = {
|
|
|
19183
19232
|
return error;
|
|
19184
19233
|
}
|
|
19185
19234
|
if (!pivot.areDomainArgsFieldsValid(domainArgs)) {
|
|
19235
|
+
const suggestion = _t("Consider using a dynamic pivot formula: %s. Or re-insert the static pivot from the Data menu.", `=PIVOT(${_pivotFormulaId})`);
|
|
19186
19236
|
return {
|
|
19187
19237
|
value: CellErrorType.GenericError,
|
|
19188
|
-
message: _t("Dimensions don't match the pivot definition"),
|
|
19238
|
+
message: _t("Dimensions don't match the pivot definition") + ". " + suggestion,
|
|
19189
19239
|
};
|
|
19190
19240
|
}
|
|
19191
19241
|
const domain = pivot.parseArgsToPivotDomain(domainArgs);
|
|
@@ -22361,6 +22411,7 @@ function insertTokenAfterArgSeparator(tokenAtCursor, value) {
|
|
|
22361
22411
|
// replace the whole token
|
|
22362
22412
|
start = tokenAtCursor.start;
|
|
22363
22413
|
}
|
|
22414
|
+
this.composer.stopComposerRangeSelection();
|
|
22364
22415
|
this.composer.changeComposerCursorSelection(start, end);
|
|
22365
22416
|
this.composer.replaceComposerCursorSelection(value);
|
|
22366
22417
|
}
|
|
@@ -22378,6 +22429,7 @@ function insertTokenAfterLeftParenthesis(tokenAtCursor, value) {
|
|
|
22378
22429
|
// replace the whole token
|
|
22379
22430
|
start = tokenAtCursor.start;
|
|
22380
22431
|
}
|
|
22432
|
+
this.composer.stopComposerRangeSelection();
|
|
22381
22433
|
this.composer.changeComposerCursorSelection(start, end);
|
|
22382
22434
|
this.composer.replaceComposerCursorSelection(value);
|
|
22383
22435
|
}
|
|
@@ -23402,7 +23454,7 @@ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, tr
|
|
|
23402
23454
|
const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
|
|
23403
23455
|
// tooltipItem.parsed can be an object or a number for pie charts
|
|
23404
23456
|
let yLabel = horizontalChart ? tooltipItem.parsed.x : tooltipItem.parsed.y;
|
|
23405
|
-
if (
|
|
23457
|
+
if (yLabel === undefined || yLabel === null) {
|
|
23406
23458
|
yLabel = tooltipItem.parsed;
|
|
23407
23459
|
}
|
|
23408
23460
|
const toolTipFormat = !format && Math.abs(yLabel) >= 1000 ? "#,##" : format;
|
|
@@ -37193,6 +37245,8 @@ class PivotSidePanelStore extends SpreadsheetStore {
|
|
|
37193
37245
|
mutators = ["reset", "deferUpdates", "applyUpdate", "discardPendingUpdate", "update"];
|
|
37194
37246
|
updatesAreDeferred = false;
|
|
37195
37247
|
draft = null;
|
|
37248
|
+
notification = this.get(NotificationStore);
|
|
37249
|
+
alreadyNotified = false;
|
|
37196
37250
|
constructor(get, pivotId) {
|
|
37197
37251
|
super(get);
|
|
37198
37252
|
this.pivotId = pivotId;
|
|
@@ -37299,6 +37353,16 @@ class PivotSidePanelStore extends SpreadsheetStore {
|
|
|
37299
37353
|
pivot: this.draft,
|
|
37300
37354
|
});
|
|
37301
37355
|
this.draft = null;
|
|
37356
|
+
if (!this.alreadyNotified && !this.isDynamicPivotInViewport()) {
|
|
37357
|
+
const formulaId = this.getters.getPivotFormulaId(this.pivotId);
|
|
37358
|
+
const pivotExample = `=PIVOT(${formulaId})`;
|
|
37359
|
+
this.alreadyNotified = true;
|
|
37360
|
+
this.notification.notifyUser({
|
|
37361
|
+
type: "info",
|
|
37362
|
+
text: _t("Pivot updates only work with dynamic pivot tables. Use %s or re-insert the static pivot from the Data menu.", pivotExample),
|
|
37363
|
+
sticky: false,
|
|
37364
|
+
});
|
|
37365
|
+
}
|
|
37302
37366
|
}
|
|
37303
37367
|
}
|
|
37304
37368
|
discardPendingUpdate() {
|
|
@@ -37329,15 +37393,22 @@ class PivotSidePanelStore extends SpreadsheetStore {
|
|
|
37329
37393
|
return;
|
|
37330
37394
|
}
|
|
37331
37395
|
const cleanedWithGranularity = this.addDefaultDateTimeGranularity(this.fields, cleanedDefinition);
|
|
37332
|
-
|
|
37333
|
-
|
|
37396
|
+
this.draft = cleanedWithGranularity;
|
|
37397
|
+
if (!this.updatesAreDeferred) {
|
|
37398
|
+
this.applyUpdate();
|
|
37334
37399
|
}
|
|
37335
|
-
|
|
37336
|
-
|
|
37337
|
-
|
|
37338
|
-
|
|
37339
|
-
|
|
37400
|
+
}
|
|
37401
|
+
isDynamicPivotInViewport() {
|
|
37402
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
37403
|
+
for (const col of this.getters.getSheetViewVisibleCols()) {
|
|
37404
|
+
for (const row of this.getters.getSheetViewVisibleRows()) {
|
|
37405
|
+
const isDynamicPivot = this.getters.isSpillPivotFormula({ sheetId, col, row });
|
|
37406
|
+
if (isDynamicPivot) {
|
|
37407
|
+
return true;
|
|
37408
|
+
}
|
|
37409
|
+
}
|
|
37340
37410
|
}
|
|
37411
|
+
return false;
|
|
37341
37412
|
}
|
|
37342
37413
|
addDefaultDateTimeGranularity(fields, definition) {
|
|
37343
37414
|
const { columns, rows } = definition;
|
|
@@ -46500,7 +46571,7 @@ function load(data, verboseImport) {
|
|
|
46500
46571
|
if (!data) {
|
|
46501
46572
|
return createEmptyWorkbookData();
|
|
46502
46573
|
}
|
|
46503
|
-
console.
|
|
46574
|
+
console.debug("### Loading data ###");
|
|
46504
46575
|
const start = performance.now();
|
|
46505
46576
|
if (data["[Content_Types].xml"]) {
|
|
46506
46577
|
const reader = new XlsxReader(data);
|
|
@@ -46514,13 +46585,13 @@ function load(data, verboseImport) {
|
|
|
46514
46585
|
// apply migrations, if needed
|
|
46515
46586
|
if ("version" in data) {
|
|
46516
46587
|
if (data.version < CURRENT_VERSION) {
|
|
46517
|
-
console.
|
|
46588
|
+
console.debug("Migrating data from version", data.version);
|
|
46518
46589
|
data = migrate(data);
|
|
46519
46590
|
}
|
|
46520
46591
|
}
|
|
46521
46592
|
data = repairData(data);
|
|
46522
|
-
console.
|
|
46523
|
-
console.
|
|
46593
|
+
console.debug("Data loaded in", performance.now() - start, "ms");
|
|
46594
|
+
console.debug("###");
|
|
46524
46595
|
return data;
|
|
46525
46596
|
}
|
|
46526
46597
|
function migrate(data) {
|
|
@@ -46529,7 +46600,7 @@ function migrate(data) {
|
|
|
46529
46600
|
for (let i = index; i < MIGRATIONS.length; i++) {
|
|
46530
46601
|
data = MIGRATIONS[i].applyMigration(data);
|
|
46531
46602
|
}
|
|
46532
|
-
console.
|
|
46603
|
+
console.debug("Data migrated in", performance.now() - start, "ms");
|
|
46533
46604
|
return data;
|
|
46534
46605
|
}
|
|
46535
46606
|
const MIGRATIONS = [
|
|
@@ -52428,7 +52499,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
52428
52499
|
case "DUPLICATE_PIVOT": {
|
|
52429
52500
|
const { pivotId, newPivotId } = cmd;
|
|
52430
52501
|
const pivot = deepCopy(this.getPivotCore(pivotId).definition);
|
|
52431
|
-
pivot.name =
|
|
52502
|
+
pivot.name = cmd.duplicatedPivotName ?? pivot.name + " (copy)";
|
|
52432
52503
|
this.addPivot(newPivotId, pivot);
|
|
52433
52504
|
break;
|
|
52434
52505
|
}
|
|
@@ -54089,7 +54160,7 @@ class Evaluator {
|
|
|
54089
54160
|
cellsToCompute.addMany(arrayFormulasPositions);
|
|
54090
54161
|
cellsToCompute.addMany(this.getCellsDependingOn(arrayFormulasPositions));
|
|
54091
54162
|
this.evaluate(cellsToCompute);
|
|
54092
|
-
console.
|
|
54163
|
+
console.debug("evaluate Cells", performance.now() - start, "ms");
|
|
54093
54164
|
}
|
|
54094
54165
|
getArrayFormulasImpactedByChangesOf(positions) {
|
|
54095
54166
|
const impactedPositions = this.createEmptyPositionSet();
|
|
@@ -54128,7 +54199,7 @@ class Evaluator {
|
|
|
54128
54199
|
const start = performance.now();
|
|
54129
54200
|
this.evaluatedCells = new PositionMap();
|
|
54130
54201
|
this.evaluate(this.getAllCells());
|
|
54131
|
-
console.
|
|
54202
|
+
console.debug("evaluate all cells", performance.now() - start, "ms");
|
|
54132
54203
|
}
|
|
54133
54204
|
evaluateFormulaResult(sheetId, formulaString) {
|
|
54134
54205
|
try {
|
|
@@ -57278,7 +57349,7 @@ class Session extends EventBus {
|
|
|
57278
57349
|
this.onMessageReceived(message);
|
|
57279
57350
|
}
|
|
57280
57351
|
this.isReplayingInitialRevisions = false;
|
|
57281
|
-
console.
|
|
57352
|
+
console.debug("Replayed", numberOfCommands, "commands in", performance.now() - start, "ms");
|
|
57282
57353
|
}
|
|
57283
57354
|
/**
|
|
57284
57355
|
* Notify the server that the user client left the collaborative session
|
|
@@ -57517,6 +57588,7 @@ class Session extends EventBus {
|
|
|
57517
57588
|
case "REMOTE_REVISION":
|
|
57518
57589
|
case "REVISION_REDONE":
|
|
57519
57590
|
case "REVISION_UNDONE":
|
|
57591
|
+
case "SNAPSHOT_CREATED":
|
|
57520
57592
|
return this.processedRevisions.has(message.nextRevisionId);
|
|
57521
57593
|
default:
|
|
57522
57594
|
return false;
|
|
@@ -58032,12 +58104,13 @@ class InsertPivotPlugin extends UIPlugin {
|
|
|
58032
58104
|
this.dispatch("DUPLICATE_PIVOT", {
|
|
58033
58105
|
pivotId,
|
|
58034
58106
|
newPivotId,
|
|
58107
|
+
duplicatedPivotName: _t("%s (copy)", this.getters.getPivotCoreDefinition(pivotId).name),
|
|
58035
58108
|
});
|
|
58036
58109
|
const activeSheetId = this.getters.getActiveSheetId();
|
|
58037
58110
|
const position = this.getters.getSheetIds().indexOf(activeSheetId) + 1;
|
|
58038
58111
|
const formulaId = this.getters.getPivotFormulaId(newPivotId);
|
|
58039
58112
|
const newPivotName = this.getters.getPivotName(newPivotId);
|
|
58040
|
-
this.dispatch("CREATE_SHEET", {
|
|
58113
|
+
const result = this.dispatch("CREATE_SHEET", {
|
|
58041
58114
|
sheetId: newSheetId,
|
|
58042
58115
|
name: this.getPivotDuplicateSheetName(_t("%(newPivotName)s (Pivot #%(formulaId)s)", {
|
|
58043
58116
|
newPivotName,
|
|
@@ -58045,20 +58118,23 @@ class InsertPivotPlugin extends UIPlugin {
|
|
|
58045
58118
|
})),
|
|
58046
58119
|
position,
|
|
58047
58120
|
});
|
|
58048
|
-
|
|
58049
|
-
|
|
58050
|
-
|
|
58051
|
-
|
|
58052
|
-
|
|
58053
|
-
|
|
58054
|
-
|
|
58121
|
+
if (result.isSuccessful) {
|
|
58122
|
+
this.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: newSheetId });
|
|
58123
|
+
this.dispatch("UPDATE_CELL", {
|
|
58124
|
+
sheetId: newSheetId,
|
|
58125
|
+
col: 0,
|
|
58126
|
+
row: 0,
|
|
58127
|
+
content: `=PIVOT(${formulaId})`,
|
|
58128
|
+
});
|
|
58129
|
+
}
|
|
58055
58130
|
}
|
|
58056
58131
|
getPivotDuplicateSheetName(pivotName) {
|
|
58057
58132
|
let i = 1;
|
|
58058
58133
|
const names = this.getters.getSheetIds().map((id) => this.getters.getSheetName(id));
|
|
58059
|
-
|
|
58134
|
+
const sanitizedName = pivotName.replace(new RegExp(FORBIDDEN_IN_EXCEL_REGEX, "g"), " ");
|
|
58135
|
+
let name = sanitizedName;
|
|
58060
58136
|
while (names.includes(name)) {
|
|
58061
|
-
name = `${
|
|
58137
|
+
name = `${sanitizedName} (${i})`;
|
|
58062
58138
|
i++;
|
|
58063
58139
|
}
|
|
58064
58140
|
return name;
|
|
@@ -58639,9 +58715,12 @@ const invalidateTableStyleCommands = [
|
|
|
58639
58715
|
"HIDE_COLUMNS_ROWS",
|
|
58640
58716
|
"UNHIDE_COLUMNS_ROWS",
|
|
58641
58717
|
"UNFOLD_HEADER_GROUP",
|
|
58718
|
+
"UNGROUP_HEADERS",
|
|
58642
58719
|
"FOLD_HEADER_GROUP",
|
|
58643
58720
|
"FOLD_ALL_HEADER_GROUPS",
|
|
58644
58721
|
"UNFOLD_ALL_HEADER_GROUPS",
|
|
58722
|
+
"FOLD_HEADER_GROUPS_IN_ZONE",
|
|
58723
|
+
"UNFOLD_HEADER_GROUPS_IN_ZONE",
|
|
58645
58724
|
"CREATE_TABLE",
|
|
58646
58725
|
"UPDATE_TABLE",
|
|
58647
58726
|
"UPDATE_FILTER",
|
|
@@ -59957,6 +60036,8 @@ class FilterEvaluationPlugin extends UIPlugin {
|
|
|
59957
60036
|
case "UNFOLD_HEADER_GROUP":
|
|
59958
60037
|
case "FOLD_ALL_HEADER_GROUPS":
|
|
59959
60038
|
case "UNFOLD_ALL_HEADER_GROUPS":
|
|
60039
|
+
case "FOLD_HEADER_GROUPS_IN_ZONE":
|
|
60040
|
+
case "UNFOLD_HEADER_GROUPS_IN_ZONE":
|
|
59960
60041
|
this.updateHiddenRows(cmd.sheetId);
|
|
59961
60042
|
break;
|
|
59962
60043
|
case "UPDATE_FILTER":
|
|
@@ -65903,7 +65984,9 @@ class StateObserver {
|
|
|
65903
65984
|
* The value does not matter, it can be hardcoded.
|
|
65904
65985
|
*/
|
|
65905
65986
|
const catAxId = 17781237;
|
|
65987
|
+
const secondaryCatAxId = 17781238;
|
|
65906
65988
|
const valAxId = 88853993;
|
|
65989
|
+
const secondaryValAxId = 88853994;
|
|
65907
65990
|
function createChart(chart, chartSheetIndex, data) {
|
|
65908
65991
|
const namespaces = [
|
|
65909
65992
|
["xmlns:r", RELATIONSHIP_NSR],
|
|
@@ -66219,8 +66302,8 @@ function addComboChart(chart) {
|
|
|
66219
66302
|
<!-- each data marker in the series does not have a different color -->
|
|
66220
66303
|
<c:varyColors val="0"/>
|
|
66221
66304
|
${barDataSetNode}
|
|
66222
|
-
<c:axId val="${
|
|
66223
|
-
<c:axId val="${
|
|
66305
|
+
<c:axId val="${useRightAxisForBarSerie ? secondaryCatAxId : catAxId}" />
|
|
66306
|
+
<c:axId val="${useRightAxisForBarSerie ? secondaryValAxId : valAxId}" />
|
|
66224
66307
|
</c:barChart>
|
|
66225
66308
|
${leftDataSetsNodes.length
|
|
66226
66309
|
? escapeXml /*xml*/ `
|
|
@@ -66241,21 +66324,21 @@ function addComboChart(chart) {
|
|
|
66241
66324
|
<!-- each data marker in the series does not have a different color -->
|
|
66242
66325
|
<c:varyColors val="0"/>
|
|
66243
66326
|
${joinXmlNodes(rightDataSetsNodes)}
|
|
66244
|
-
<c:axId val="${
|
|
66245
|
-
<c:axId val="${
|
|
66327
|
+
<c:axId val="${secondaryCatAxId}" />
|
|
66328
|
+
<c:axId val="${secondaryValAxId}" />
|
|
66246
66329
|
</c:lineChart>
|
|
66247
66330
|
`
|
|
66248
66331
|
: ""}
|
|
66249
66332
|
${!useRightAxisForBarSerie || leftDataSetsNodes.length
|
|
66250
66333
|
? escapeXml /*xml*/ `
|
|
66251
|
-
${addAx("b", "c:catAx", catAxId
|
|
66252
|
-
${addAx("
|
|
66334
|
+
${addAx("b", "c:catAx", catAxId, valAxId, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length ? 1 : 0)}
|
|
66335
|
+
${addAx("l", "c:valAx", valAxId, catAxId, chart.axesDesign?.y?.title, chart.fontColor)}
|
|
66253
66336
|
`
|
|
66254
66337
|
: ""}
|
|
66255
66338
|
${useRightAxisForBarSerie || rightDataSetsNodes.length
|
|
66256
66339
|
? escapeXml /*xml*/ `
|
|
66257
|
-
${addAx("b", "c:catAx",
|
|
66258
|
-
${addAx("
|
|
66340
|
+
${addAx("b", "c:catAx", secondaryCatAxId, secondaryValAxId, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length || !useRightAxisForBarSerie ? 1 : 0)}
|
|
66341
|
+
${addAx("r", "c:valAx", secondaryValAxId, secondaryCatAxId, chart.axesDesign?.y1?.title, chart.fontColor)}
|
|
66259
66342
|
`
|
|
66260
66343
|
: ""}
|
|
66261
66344
|
`;
|
|
@@ -67276,6 +67359,15 @@ function addTableColumns(table, sheetData) {
|
|
|
67276
67359
|
["id", i + 1], // id cannot be 0
|
|
67277
67360
|
["name", colName],
|
|
67278
67361
|
];
|
|
67362
|
+
if (table.config.totalRow) {
|
|
67363
|
+
// Note: To be 100% complete, we could also add a `totalsRowLabel` attribute for total strings, and a tag
|
|
67364
|
+
// `<totalsRowFormula>` for the formula of the total. But those doesn't seem to be mandatory for Excel.
|
|
67365
|
+
const colTotalXc = toXC(tableZone.left + i, tableZone.bottom);
|
|
67366
|
+
const colTotalContent = sheetData.cells[colTotalXc]?.content;
|
|
67367
|
+
if (colTotalContent?.startsWith("=")) {
|
|
67368
|
+
colAttributes.push(["totalsRowFunction", "custom"]);
|
|
67369
|
+
}
|
|
67370
|
+
}
|
|
67279
67371
|
columns.push(escapeXml /*xml*/ `<tableColumn ${formatAttributes(colAttributes)}/>`);
|
|
67280
67372
|
}
|
|
67281
67373
|
return escapeXml /*xml*/ `
|
|
@@ -67370,8 +67462,9 @@ function addRows(construct, data, sheet) {
|
|
|
67370
67462
|
}
|
|
67371
67463
|
else if (cell.content && cell.content !== "") {
|
|
67372
67464
|
const isTableHeader = isCellTableHeader(c, r, sheet);
|
|
67465
|
+
const isTableTotal = isCellTableTotal(c, r, sheet);
|
|
67373
67466
|
const isPlainText = !!(cell.format && data.formats[cell.format] === PLAIN_TEXT_FORMAT);
|
|
67374
|
-
({ attrs: additionalAttrs, node: cellNode } = addContent(cell.content, construct.sharedStrings, isTableHeader || isPlainText));
|
|
67467
|
+
({ attrs: additionalAttrs, node: cellNode } = addContent(cell.content, construct.sharedStrings, isTableHeader || isTableTotal || isPlainText));
|
|
67375
67468
|
}
|
|
67376
67469
|
attributes.push(...additionalAttrs);
|
|
67377
67470
|
// prettier-ignore
|
|
@@ -67405,6 +67498,16 @@ function isCellTableHeader(col, row, sheet) {
|
|
|
67405
67498
|
return isInside(col, row, headerZone);
|
|
67406
67499
|
});
|
|
67407
67500
|
}
|
|
67501
|
+
function isCellTableTotal(col, row, sheet) {
|
|
67502
|
+
return sheet.tables.some((table) => {
|
|
67503
|
+
if (!table.config.totalRow) {
|
|
67504
|
+
return false;
|
|
67505
|
+
}
|
|
67506
|
+
const zone = toZone(table.range);
|
|
67507
|
+
const totalZone = { ...zone, top: zone.bottom };
|
|
67508
|
+
return isInside(col, row, totalZone);
|
|
67509
|
+
});
|
|
67510
|
+
}
|
|
67408
67511
|
function addHyperlinks(construct, data, sheetIndex) {
|
|
67409
67512
|
const sheet = data.sheets[sheetIndex];
|
|
67410
67513
|
const cells = sheet.cells;
|
|
@@ -67856,7 +67959,7 @@ class Model extends EventBus {
|
|
|
67856
67959
|
coreHandlers = [];
|
|
67857
67960
|
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
|
|
67858
67961
|
const start = performance.now();
|
|
67859
|
-
console.
|
|
67962
|
+
console.debug("##### Model creation #####");
|
|
67860
67963
|
super();
|
|
67861
67964
|
setDefaultTranslationMethod();
|
|
67862
67965
|
stateUpdateMessages = repairInitialMessages(data, stateUpdateMessages);
|
|
@@ -67883,7 +67986,6 @@ class Model extends EventBus {
|
|
|
67883
67986
|
isReadonly: () => this.config.mode === "readonly" || this.config.mode === "dashboard",
|
|
67884
67987
|
isDashboard: () => this.config.mode === "dashboard",
|
|
67885
67988
|
};
|
|
67886
|
-
this.uuidGenerator.setIsFastStrategy(true);
|
|
67887
67989
|
// Initiate stream processor
|
|
67888
67990
|
this.selection = new SelectionStreamProcessorImpl(this.getters);
|
|
67889
67991
|
this.coreHandlers.push(this.range);
|
|
@@ -67929,16 +68031,16 @@ class Model extends EventBus {
|
|
|
67929
68031
|
this.joinSession();
|
|
67930
68032
|
if (config.snapshotRequested) {
|
|
67931
68033
|
const startSnapshot = performance.now();
|
|
67932
|
-
console.
|
|
68034
|
+
console.debug("Snapshot requested");
|
|
67933
68035
|
this.session.snapshot(this.exportData());
|
|
67934
68036
|
this.garbageCollectExternalResources();
|
|
67935
|
-
console.
|
|
68037
|
+
console.debug("Snapshot taken in", performance.now() - startSnapshot, "ms");
|
|
67936
68038
|
}
|
|
67937
68039
|
// mark all models as "raw", so they will not be turned into reactive objects
|
|
67938
68040
|
// by owl, since we do not rely on reactivity
|
|
67939
68041
|
markRaw(this);
|
|
67940
|
-
console.
|
|
67941
|
-
console.
|
|
68042
|
+
console.debug("Model created in", performance.now() - start, "ms");
|
|
68043
|
+
console.debug("######");
|
|
67942
68044
|
}
|
|
67943
68045
|
joinSession() {
|
|
67944
68046
|
this.session.join(this.config.client);
|
|
@@ -68161,7 +68263,7 @@ class Model extends EventBus {
|
|
|
68161
68263
|
this.finalize();
|
|
68162
68264
|
const time = performance.now() - start;
|
|
68163
68265
|
if (time > 5) {
|
|
68164
|
-
console.
|
|
68266
|
+
console.debug(type, time, "ms");
|
|
68165
68267
|
}
|
|
68166
68268
|
});
|
|
68167
68269
|
this.session.save(command, commands, changes);
|
|
@@ -68504,6 +68606,6 @@ const constants = {
|
|
|
68504
68606
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
68505
68607
|
|
|
68506
68608
|
|
|
68507
|
-
__info__.version = "17.4.
|
|
68508
|
-
__info__.date = "2024-
|
|
68509
|
-
__info__.hash = "
|
|
68609
|
+
__info__.version = "17.4.10";
|
|
68610
|
+
__info__.date = "2024-10-24T08:54:56.262Z";
|
|
68611
|
+
__info__.hash = "c82d9c1";
|