@odoo/o-spreadsheet 18.1.0-alpha.0 → 18.1.0-alpha.1
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 +571 -358
- package/dist/o-spreadsheet.d.ts +40 -18
- package/dist/o-spreadsheet.esm.js +571 -358
- package/dist/o-spreadsheet.iife.js +571 -358
- package/dist/o-spreadsheet.iife.min.js +517 -519
- package/dist/o_spreadsheet.xml +154 -9
- package/package.json +12 -12
|
@@ -2,14 +2,120 @@
|
|
|
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-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.1.0-alpha.1
|
|
6
|
+
* @date 2024-10-14T07:53:17.717Z
|
|
7
|
+
* @hash e9ce3aa
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
11
11
|
'use strict';
|
|
12
12
|
|
|
13
|
+
function createActions(menuItems) {
|
|
14
|
+
return menuItems.map(createAction).sort((a, b) => a.sequence - b.sequence);
|
|
15
|
+
}
|
|
16
|
+
let nextItemId = 1;
|
|
17
|
+
function createAction(item) {
|
|
18
|
+
const name = item.name;
|
|
19
|
+
const children = item.children;
|
|
20
|
+
const description = item.description;
|
|
21
|
+
const icon = item.icon;
|
|
22
|
+
const secondaryIcon = item.secondaryIcon;
|
|
23
|
+
const itemId = item.id || nextItemId++;
|
|
24
|
+
return {
|
|
25
|
+
id: itemId.toString(),
|
|
26
|
+
name: typeof name === "function" ? name : () => name,
|
|
27
|
+
isVisible: item.isVisible ? item.isVisible : () => true,
|
|
28
|
+
isEnabled: item.isEnabled ? item.isEnabled : () => true,
|
|
29
|
+
isActive: item.isActive,
|
|
30
|
+
execute: item.execute,
|
|
31
|
+
children: children
|
|
32
|
+
? (env) => {
|
|
33
|
+
return children
|
|
34
|
+
.map((child) => (typeof child === "function" ? child(env) : child))
|
|
35
|
+
.flat()
|
|
36
|
+
.map(createAction);
|
|
37
|
+
}
|
|
38
|
+
: () => [],
|
|
39
|
+
isReadonlyAllowed: item.isReadonlyAllowed || false,
|
|
40
|
+
separator: item.separator || false,
|
|
41
|
+
icon: typeof icon === "function" ? icon : () => icon || "",
|
|
42
|
+
iconColor: item.iconColor,
|
|
43
|
+
secondaryIcon: typeof secondaryIcon === "function" ? secondaryIcon : () => secondaryIcon || "",
|
|
44
|
+
description: typeof description === "function" ? description : () => description || "",
|
|
45
|
+
textColor: item.textColor,
|
|
46
|
+
sequence: item.sequence || 0,
|
|
47
|
+
onStartHover: item.onStartHover,
|
|
48
|
+
onStopHover: item.onStopHover,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Registry
|
|
54
|
+
*
|
|
55
|
+
* The Registry class is basically just a mapping from a string key to an object.
|
|
56
|
+
* It is really not much more than an object. It is however useful for the
|
|
57
|
+
* following reasons:
|
|
58
|
+
*
|
|
59
|
+
* 1. it let us react and execute code when someone add something to the registry
|
|
60
|
+
* (for example, the FunctionRegistry subclass this for this purpose)
|
|
61
|
+
* 2. it throws an error when the get operation fails
|
|
62
|
+
* 3. it provides a chained API to add items to the registry.
|
|
63
|
+
*/
|
|
64
|
+
class Registry {
|
|
65
|
+
content = {};
|
|
66
|
+
/**
|
|
67
|
+
* Add an item to the registry
|
|
68
|
+
*
|
|
69
|
+
* Note that this also returns the registry, so another add method call can
|
|
70
|
+
* be chained
|
|
71
|
+
*/
|
|
72
|
+
add(key, value) {
|
|
73
|
+
this.content[key] = value;
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get an item from the registry
|
|
78
|
+
*/
|
|
79
|
+
get(key) {
|
|
80
|
+
/**
|
|
81
|
+
* Note: key in {} is ~12 times slower than {}[key].
|
|
82
|
+
* So, we check the absence of key only when the direct access returns
|
|
83
|
+
* a falsy value. It's done to ensure that the registry can contains falsy values
|
|
84
|
+
*/
|
|
85
|
+
const content = this.content[key];
|
|
86
|
+
if (!content) {
|
|
87
|
+
if (!(key in this.content)) {
|
|
88
|
+
throw new Error(`Cannot find ${key} in this registry!`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return content;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Check if the key is already in the registry
|
|
95
|
+
*/
|
|
96
|
+
contains(key) {
|
|
97
|
+
return key in this.content;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get a list of all elements in the registry
|
|
101
|
+
*/
|
|
102
|
+
getAll() {
|
|
103
|
+
return Object.values(this.content);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get a list of all keys in the registry
|
|
107
|
+
*/
|
|
108
|
+
getKeys() {
|
|
109
|
+
return Object.keys(this.content);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Remove an item from the registry
|
|
113
|
+
*/
|
|
114
|
+
remove(key) {
|
|
115
|
+
delete this.content[key];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
13
119
|
const CANVAS_SHIFT = 0.5;
|
|
14
120
|
// Colors
|
|
15
121
|
const HIGHLIGHT_COLOR = "#37A850";
|
|
@@ -5969,18 +6075,9 @@
|
|
|
5969
6075
|
* https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
|
|
5970
6076
|
* */
|
|
5971
6077
|
class UuidGenerator {
|
|
5972
|
-
isFastIdStrategy = false;
|
|
5973
|
-
fastIdStart = 0;
|
|
5974
|
-
setIsFastStrategy(isFast) {
|
|
5975
|
-
this.isFastIdStrategy = isFast;
|
|
5976
|
-
}
|
|
5977
6078
|
uuidv4() {
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
return String(this.fastIdStart);
|
|
5981
|
-
//@ts-ignore
|
|
5982
|
-
}
|
|
5983
|
-
else if (window.crypto && window.crypto.getRandomValues) {
|
|
6079
|
+
//@ts-ignore
|
|
6080
|
+
if (window.crypto && window.crypto.getRandomValues) {
|
|
5984
6081
|
//@ts-ignore
|
|
5985
6082
|
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
|
|
5986
6083
|
}
|
|
@@ -5994,111 +6091,6 @@
|
|
|
5994
6091
|
}
|
|
5995
6092
|
}
|
|
5996
6093
|
|
|
5997
|
-
function createActions(menuItems) {
|
|
5998
|
-
return menuItems.map(createAction).sort((a, b) => a.sequence - b.sequence);
|
|
5999
|
-
}
|
|
6000
|
-
const uuidGenerator$1 = new UuidGenerator();
|
|
6001
|
-
function createAction(item) {
|
|
6002
|
-
const name = item.name;
|
|
6003
|
-
const children = item.children;
|
|
6004
|
-
const description = item.description;
|
|
6005
|
-
const icon = item.icon;
|
|
6006
|
-
const secondaryIcon = item.secondaryIcon;
|
|
6007
|
-
return {
|
|
6008
|
-
id: item.id || uuidGenerator$1.uuidv4(),
|
|
6009
|
-
name: typeof name === "function" ? name : () => name,
|
|
6010
|
-
isVisible: item.isVisible ? item.isVisible : () => true,
|
|
6011
|
-
isEnabled: item.isEnabled ? item.isEnabled : () => true,
|
|
6012
|
-
isActive: item.isActive,
|
|
6013
|
-
execute: item.execute,
|
|
6014
|
-
children: children
|
|
6015
|
-
? (env) => {
|
|
6016
|
-
return children
|
|
6017
|
-
.map((child) => (typeof child === "function" ? child(env) : child))
|
|
6018
|
-
.flat()
|
|
6019
|
-
.map(createAction);
|
|
6020
|
-
}
|
|
6021
|
-
: () => [],
|
|
6022
|
-
isReadonlyAllowed: item.isReadonlyAllowed || false,
|
|
6023
|
-
separator: item.separator || false,
|
|
6024
|
-
icon: typeof icon === "function" ? icon : () => icon || "",
|
|
6025
|
-
iconColor: item.iconColor,
|
|
6026
|
-
secondaryIcon: typeof secondaryIcon === "function" ? secondaryIcon : () => secondaryIcon || "",
|
|
6027
|
-
description: typeof description === "function" ? description : () => description || "",
|
|
6028
|
-
textColor: item.textColor,
|
|
6029
|
-
sequence: item.sequence || 0,
|
|
6030
|
-
onStartHover: item.onStartHover,
|
|
6031
|
-
onStopHover: item.onStopHover,
|
|
6032
|
-
};
|
|
6033
|
-
}
|
|
6034
|
-
|
|
6035
|
-
/**
|
|
6036
|
-
* Registry
|
|
6037
|
-
*
|
|
6038
|
-
* The Registry class is basically just a mapping from a string key to an object.
|
|
6039
|
-
* It is really not much more than an object. It is however useful for the
|
|
6040
|
-
* following reasons:
|
|
6041
|
-
*
|
|
6042
|
-
* 1. it let us react and execute code when someone add something to the registry
|
|
6043
|
-
* (for example, the FunctionRegistry subclass this for this purpose)
|
|
6044
|
-
* 2. it throws an error when the get operation fails
|
|
6045
|
-
* 3. it provides a chained API to add items to the registry.
|
|
6046
|
-
*/
|
|
6047
|
-
class Registry {
|
|
6048
|
-
content = {};
|
|
6049
|
-
/**
|
|
6050
|
-
* Add an item to the registry
|
|
6051
|
-
*
|
|
6052
|
-
* Note that this also returns the registry, so another add method call can
|
|
6053
|
-
* be chained
|
|
6054
|
-
*/
|
|
6055
|
-
add(key, value) {
|
|
6056
|
-
this.content[key] = value;
|
|
6057
|
-
return this;
|
|
6058
|
-
}
|
|
6059
|
-
/**
|
|
6060
|
-
* Get an item from the registry
|
|
6061
|
-
*/
|
|
6062
|
-
get(key) {
|
|
6063
|
-
/**
|
|
6064
|
-
* Note: key in {} is ~12 times slower than {}[key].
|
|
6065
|
-
* So, we check the absence of key only when the direct access returns
|
|
6066
|
-
* a falsy value. It's done to ensure that the registry can contains falsy values
|
|
6067
|
-
*/
|
|
6068
|
-
const content = this.content[key];
|
|
6069
|
-
if (!content) {
|
|
6070
|
-
if (!(key in this.content)) {
|
|
6071
|
-
throw new Error(`Cannot find ${key} in this registry!`);
|
|
6072
|
-
}
|
|
6073
|
-
}
|
|
6074
|
-
return content;
|
|
6075
|
-
}
|
|
6076
|
-
/**
|
|
6077
|
-
* Check if the key is already in the registry
|
|
6078
|
-
*/
|
|
6079
|
-
contains(key) {
|
|
6080
|
-
return key in this.content;
|
|
6081
|
-
}
|
|
6082
|
-
/**
|
|
6083
|
-
* Get a list of all elements in the registry
|
|
6084
|
-
*/
|
|
6085
|
-
getAll() {
|
|
6086
|
-
return Object.values(this.content);
|
|
6087
|
-
}
|
|
6088
|
-
/**
|
|
6089
|
-
* Get a list of all keys in the registry
|
|
6090
|
-
*/
|
|
6091
|
-
getKeys() {
|
|
6092
|
-
return Object.keys(this.content);
|
|
6093
|
-
}
|
|
6094
|
-
/**
|
|
6095
|
-
* Remove an item from the registry
|
|
6096
|
-
*/
|
|
6097
|
-
remove(key) {
|
|
6098
|
-
delete this.content[key];
|
|
6099
|
-
}
|
|
6100
|
-
}
|
|
6101
|
-
|
|
6102
6094
|
function getClipboardDataPositions(sheetId, zones) {
|
|
6103
6095
|
const lefts = new Set(zones.map((z) => z.left));
|
|
6104
6096
|
const rights = new Set(zones.map((z) => z.right));
|
|
@@ -8453,31 +8445,34 @@
|
|
|
8453
8445
|
for (let col of columnsIndexes) {
|
|
8454
8446
|
const position = { col, row, sheetId };
|
|
8455
8447
|
const table = this.getters.getTable(position);
|
|
8456
|
-
if (!table
|
|
8448
|
+
if (!table) {
|
|
8457
8449
|
tableCellsInRow.push({});
|
|
8458
8450
|
continue;
|
|
8459
8451
|
}
|
|
8460
8452
|
const coreTable = this.getters.getCoreTable(position);
|
|
8461
8453
|
const tableZone = coreTable?.range.zone;
|
|
8454
|
+
let copiedTable = undefined;
|
|
8462
8455
|
// Copy whole table
|
|
8463
|
-
if (
|
|
8464
|
-
|
|
8456
|
+
if (!copiedTablesIds.has(table.id) &&
|
|
8457
|
+
coreTable &&
|
|
8458
|
+
tableZone &&
|
|
8459
|
+
zones.some((z) => isZoneInside(tableZone, z))) {
|
|
8460
|
+
copiedTablesIds.add(table.id);
|
|
8465
8461
|
const values = [];
|
|
8466
8462
|
for (const col of range(tableZone.left, tableZone.right + 1)) {
|
|
8467
8463
|
values.push(this.getters.getFilterHiddenValues({ sheetId, col, row: tableZone.top }));
|
|
8468
8464
|
}
|
|
8469
|
-
|
|
8470
|
-
|
|
8471
|
-
|
|
8472
|
-
|
|
8473
|
-
|
|
8474
|
-
},
|
|
8475
|
-
});
|
|
8476
|
-
}
|
|
8477
|
-
// Copy only style of cell
|
|
8478
|
-
else if (table) {
|
|
8479
|
-
tableCellsInRow.push({ style: this.getTableStyleToCopy(position) });
|
|
8465
|
+
copiedTable = {
|
|
8466
|
+
range: coreTable.range.rangeData,
|
|
8467
|
+
config: coreTable.config,
|
|
8468
|
+
type: coreTable.type,
|
|
8469
|
+
};
|
|
8480
8470
|
}
|
|
8471
|
+
tableCellsInRow.push({
|
|
8472
|
+
table: copiedTable,
|
|
8473
|
+
style: this.getTableStyleToCopy(position),
|
|
8474
|
+
isWholeTableCopied: copiedTablesIds.has(table.id),
|
|
8475
|
+
});
|
|
8481
8476
|
}
|
|
8482
8477
|
}
|
|
8483
8478
|
return {
|
|
@@ -8558,11 +8553,14 @@
|
|
|
8558
8553
|
tableType: tableCell.table.type,
|
|
8559
8554
|
});
|
|
8560
8555
|
}
|
|
8561
|
-
// Do not paste table style if we're inside another table
|
|
8562
8556
|
// We cannot check for dynamic tables, because at this point the paste can have changed the evaluation, and the
|
|
8563
8557
|
// dynamic tables are not yet computed
|
|
8564
|
-
if (
|
|
8565
|
-
|
|
8558
|
+
if (this.getters.getCoreTable(position) || options?.pasteOption === "asValue") {
|
|
8559
|
+
return;
|
|
8560
|
+
}
|
|
8561
|
+
if ((!options?.pasteOption && !tableCell.isWholeTableCopied) ||
|
|
8562
|
+
options?.pasteOption === "onlyFormat") {
|
|
8563
|
+
if (tableCell.style?.style) {
|
|
8566
8564
|
this.dispatch("UPDATE_CELL", { ...position, style: tableCell.style.style });
|
|
8567
8565
|
}
|
|
8568
8566
|
if (tableCell.style?.border) {
|
|
@@ -9282,6 +9280,49 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9282
9280
|
useLeftAxis ||= !useRightAxis;
|
|
9283
9281
|
return { useLeftAxis, useRightAxis };
|
|
9284
9282
|
}
|
|
9283
|
+
function getChartAxis(definition, position, type, options) {
|
|
9284
|
+
const { useLeftAxis, useRightAxis } = getDefinedAxis(definition);
|
|
9285
|
+
if ((position === "left" && !useLeftAxis) || (position === "right" && !useRightAxis)) {
|
|
9286
|
+
return undefined;
|
|
9287
|
+
}
|
|
9288
|
+
const fontColor = chartFontColor(definition.background);
|
|
9289
|
+
let design;
|
|
9290
|
+
if (position === "bottom") {
|
|
9291
|
+
design = definition.axesDesign?.x;
|
|
9292
|
+
}
|
|
9293
|
+
else if (position === "left") {
|
|
9294
|
+
design = definition.axesDesign?.y;
|
|
9295
|
+
}
|
|
9296
|
+
else {
|
|
9297
|
+
design = definition.axesDesign?.y1;
|
|
9298
|
+
}
|
|
9299
|
+
if (type === "values") {
|
|
9300
|
+
const displayGridLines = position === "left" || (position === "right" && !useLeftAxis);
|
|
9301
|
+
return {
|
|
9302
|
+
position: position,
|
|
9303
|
+
title: getChartAxisTitleRuntime(design),
|
|
9304
|
+
grid: {
|
|
9305
|
+
display: displayGridLines,
|
|
9306
|
+
},
|
|
9307
|
+
beginAtZero: true,
|
|
9308
|
+
stacked: options?.stacked,
|
|
9309
|
+
ticks: {
|
|
9310
|
+
color: fontColor,
|
|
9311
|
+
callback: formatTickValue(options),
|
|
9312
|
+
},
|
|
9313
|
+
};
|
|
9314
|
+
}
|
|
9315
|
+
else {
|
|
9316
|
+
return {
|
|
9317
|
+
ticks: {
|
|
9318
|
+
padding: 5,
|
|
9319
|
+
color: fontColor,
|
|
9320
|
+
},
|
|
9321
|
+
stacked: options?.stacked,
|
|
9322
|
+
title: getChartAxisTitleRuntime(design),
|
|
9323
|
+
};
|
|
9324
|
+
}
|
|
9325
|
+
}
|
|
9285
9326
|
function computeChartPadding({ displayTitle, displayLegend, }) {
|
|
9286
9327
|
let top = 25;
|
|
9287
9328
|
if (displayTitle) {
|
|
@@ -9368,6 +9409,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9368
9409
|
return [];
|
|
9369
9410
|
}
|
|
9370
9411
|
}
|
|
9412
|
+
function formatChartDatasetValue(axisFormats, locale) {
|
|
9413
|
+
return (value, axisId) => {
|
|
9414
|
+
const format = axisId ? axisFormats?.[axisId] : undefined;
|
|
9415
|
+
return formatTickValue({ format, locale })(value);
|
|
9416
|
+
};
|
|
9417
|
+
}
|
|
9371
9418
|
function formatTickValue(localeFormat) {
|
|
9372
9419
|
return (value) => {
|
|
9373
9420
|
value = Number(value);
|
|
@@ -9430,10 +9477,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9430
9477
|
case "bar":
|
|
9431
9478
|
case "line": {
|
|
9432
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;
|
|
9433
9482
|
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
9434
9483
|
const point = dataset.data[i];
|
|
9435
9484
|
const value = options.horizontal ? dataset._parsed[i].x : dataset._parsed[i].y;
|
|
9436
|
-
const displayedValue = options.callback(value - 0);
|
|
9485
|
+
const displayedValue = options.callback(value - 0, axisId);
|
|
9437
9486
|
let xPosition = 0, yPosition = 0;
|
|
9438
9487
|
if (options.horizontal) {
|
|
9439
9488
|
yPosition = point.y;
|
|
@@ -17842,7 +17891,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
17842
17891
|
throw new EvaluationError(_t("Function PIVOT takes an even number of arguments."));
|
|
17843
17892
|
}
|
|
17844
17893
|
}
|
|
17845
|
-
function addPivotDependencies(evalContext, coreDefinition) {
|
|
17894
|
+
function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
|
|
17846
17895
|
//TODO This function can be very costly when used with PIVOT.VALUE and PIVOT.HEADER
|
|
17847
17896
|
const dependencies = [];
|
|
17848
17897
|
if (coreDefinition.type === "SPREADSHEET" && coreDefinition.dataSet) {
|
|
@@ -17854,7 +17903,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
17854
17903
|
}
|
|
17855
17904
|
dependencies.push(range);
|
|
17856
17905
|
}
|
|
17857
|
-
for (const measure of
|
|
17906
|
+
for (const measure of forMeasures) {
|
|
17858
17907
|
if (measure.computedBy) {
|
|
17859
17908
|
const formula = evalContext.getters.getMeasureCompiledFormula(measure);
|
|
17860
17909
|
dependencies.push(...formula.dependencies.filter((range) => !range.invalidXc));
|
|
@@ -18287,7 +18336,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18287
18336
|
assertDomainLength(domainArgs);
|
|
18288
18337
|
const pivot = this.getters.getPivot(pivotId);
|
|
18289
18338
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
18290
|
-
addPivotDependencies(this, coreDefinition);
|
|
18339
|
+
addPivotDependencies(this, coreDefinition, coreDefinition.measures.filter((m) => m.id === _measure));
|
|
18291
18340
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
18292
18341
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
18293
18342
|
if (error) {
|
|
@@ -18317,7 +18366,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18317
18366
|
assertDomainLength(domainArgs);
|
|
18318
18367
|
const pivot = this.getters.getPivot(_pivotId);
|
|
18319
18368
|
const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
|
|
18320
|
-
addPivotDependencies(this, coreDefinition);
|
|
18369
|
+
addPivotDependencies(this, coreDefinition, []);
|
|
18321
18370
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
18322
18371
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
18323
18372
|
if (error) {
|
|
@@ -18368,7 +18417,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
18368
18417
|
const pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
18369
18418
|
const pivot = this.getters.getPivot(pivotId);
|
|
18370
18419
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
18371
|
-
addPivotDependencies(this, coreDefinition);
|
|
18420
|
+
addPivotDependencies(this, coreDefinition, coreDefinition.measures);
|
|
18372
18421
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
18373
18422
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
18374
18423
|
if (error) {
|
|
@@ -20164,7 +20213,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
20164
20213
|
let startNode = this.findChildAtCharacterIndex(start);
|
|
20165
20214
|
let endNode = this.findChildAtCharacterIndex(end);
|
|
20166
20215
|
range.setStart(startNode.node, startNode.offset);
|
|
20167
|
-
|
|
20216
|
+
range.setEnd(endNode.node, endNode.offset);
|
|
20168
20217
|
}
|
|
20169
20218
|
}
|
|
20170
20219
|
/**
|
|
@@ -20662,7 +20711,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
20662
20711
|
"Alt+Enter": this.processNewLineEvent,
|
|
20663
20712
|
"Ctrl+Enter": this.processNewLineEvent,
|
|
20664
20713
|
Escape: this.processEscapeKey,
|
|
20665
|
-
F2: () =>
|
|
20714
|
+
F2: (ev) => this.toggleEditionMode(ev),
|
|
20666
20715
|
F4: (ev) => this.processF4Key(ev),
|
|
20667
20716
|
Tab: (ev) => this.processTabKey(ev, "right"),
|
|
20668
20717
|
"Shift+Tab": (ev) => this.processTabKey(ev, "left"),
|
|
@@ -20781,6 +20830,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
20781
20830
|
this.props.composerStore.cycleReferences();
|
|
20782
20831
|
this.processContent();
|
|
20783
20832
|
}
|
|
20833
|
+
toggleEditionMode(ev) {
|
|
20834
|
+
ev.stopPropagation();
|
|
20835
|
+
this.props.composerStore.toggleEditionMode();
|
|
20836
|
+
this.processContent();
|
|
20837
|
+
}
|
|
20784
20838
|
processNumpadDecimal(ev) {
|
|
20785
20839
|
ev.stopPropagation();
|
|
20786
20840
|
ev.preventDefault();
|
|
@@ -21006,7 +21060,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21006
21060
|
break;
|
|
21007
21061
|
case "REFERENCE":
|
|
21008
21062
|
const { xc, sheetName } = splitReference(token.value);
|
|
21009
|
-
result.push({
|
|
21063
|
+
result.push({
|
|
21064
|
+
value: token.value,
|
|
21065
|
+
color: this.rangeColor(xc, sheetName) || "#000",
|
|
21066
|
+
class: tokenAtCursor === token && this.props.composerStore.editionMode === "selecting"
|
|
21067
|
+
? "text-decoration-underline"
|
|
21068
|
+
: undefined,
|
|
21069
|
+
});
|
|
21010
21070
|
break;
|
|
21011
21071
|
case "SYMBOL":
|
|
21012
21072
|
const value = token.value;
|
|
@@ -21577,6 +21637,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21577
21637
|
// replace the whole token
|
|
21578
21638
|
start = tokenAtCursor.start;
|
|
21579
21639
|
}
|
|
21640
|
+
this.composer.stopComposerRangeSelection();
|
|
21580
21641
|
this.composer.changeComposerCursorSelection(start, end);
|
|
21581
21642
|
this.composer.replaceComposerCursorSelection(value);
|
|
21582
21643
|
}
|
|
@@ -21594,6 +21655,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
21594
21655
|
// replace the whole token
|
|
21595
21656
|
start = tokenAtCursor.start;
|
|
21596
21657
|
}
|
|
21658
|
+
this.composer.stopComposerRangeSelection();
|
|
21597
21659
|
this.composer.changeComposerCursorSelection(start, end);
|
|
21598
21660
|
this.composer.replaceComposerCursorSelection(value);
|
|
21599
21661
|
}
|
|
@@ -22186,6 +22248,27 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22186
22248
|
tooltip: content ? { props: { content: tooltipValue } } : undefined,
|
|
22187
22249
|
};
|
|
22188
22250
|
},
|
|
22251
|
+
})
|
|
22252
|
+
.add("DATE_INCREMENT_MODIFIER", {
|
|
22253
|
+
apply: (rule, data, getters) => {
|
|
22254
|
+
const date = toJsDate(rule.current, getters.getLocale());
|
|
22255
|
+
date.setFullYear(date.getFullYear() + rule.increment.years || 0);
|
|
22256
|
+
date.setMonth(date.getMonth() + rule.increment.months || 0);
|
|
22257
|
+
date.setDate(date.getDate() + rule.increment.days || 0);
|
|
22258
|
+
const value = jsDateToNumber(date);
|
|
22259
|
+
rule.current = value;
|
|
22260
|
+
const locale = getters.getLocale();
|
|
22261
|
+
const tooltipValue = formatValue(value, { format: data.cell?.format, locale });
|
|
22262
|
+
return {
|
|
22263
|
+
cellData: {
|
|
22264
|
+
border: data.border,
|
|
22265
|
+
style: data.cell && data.cell.style,
|
|
22266
|
+
format: data.cell && data.cell.format,
|
|
22267
|
+
content: value.toString(),
|
|
22268
|
+
},
|
|
22269
|
+
tooltip: value ? { props: { content: tooltipValue } } : undefined,
|
|
22270
|
+
};
|
|
22271
|
+
},
|
|
22189
22272
|
})
|
|
22190
22273
|
.add("COPY_MODIFIER", {
|
|
22191
22274
|
apply: (rule, data, getters) => {
|
|
@@ -22266,7 +22349,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22266
22349
|
if (x === cell) {
|
|
22267
22350
|
found = true;
|
|
22268
22351
|
}
|
|
22269
|
-
const cellValue = x === undefined || x.isFormula
|
|
22352
|
+
const cellValue = x === undefined || x.isFormula
|
|
22353
|
+
? undefined
|
|
22354
|
+
: evaluateLiteral(x, { locale: DEFAULT_LOCALE, format: x.format });
|
|
22270
22355
|
if (cellValue && filter(cellValue)) {
|
|
22271
22356
|
group.push(cellValue);
|
|
22272
22357
|
}
|
|
@@ -22302,6 +22387,72 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22302
22387
|
}
|
|
22303
22388
|
return increment;
|
|
22304
22389
|
}
|
|
22390
|
+
/**
|
|
22391
|
+
* Iterates on a list of date intervals.
|
|
22392
|
+
* if every interval is the same, return the interval
|
|
22393
|
+
* Otherwise return undefined
|
|
22394
|
+
*
|
|
22395
|
+
*/
|
|
22396
|
+
function getEqualInterval(intervals) {
|
|
22397
|
+
if (intervals.length < 2) {
|
|
22398
|
+
return intervals[0] || { years: 0, months: 0, days: 0 };
|
|
22399
|
+
}
|
|
22400
|
+
const equal = intervals.every((interval) => interval.years === intervals[0].years &&
|
|
22401
|
+
interval.months === intervals[0].months &&
|
|
22402
|
+
interval.days === intervals[0].days);
|
|
22403
|
+
return equal ? intervals[0] : undefined;
|
|
22404
|
+
}
|
|
22405
|
+
/**
|
|
22406
|
+
* Based on a group of dates, calculate the increment that should be applied
|
|
22407
|
+
* to the next date.
|
|
22408
|
+
*
|
|
22409
|
+
* This will compute the date difference in calendar terms (years, months, days)
|
|
22410
|
+
* In order to make abstraction of leap years and months with different number of days.
|
|
22411
|
+
*
|
|
22412
|
+
* In case the dates are not equidistant in calendar terms, no rule can be extrapolated
|
|
22413
|
+
* In case of equidistant dates, we either have in that order:
|
|
22414
|
+
* - exact date interval (e.g. +n year OR +n month OR +n day) in which case we increment by the same interval
|
|
22415
|
+
* - exact day interval (e.g. +n days) in which case we increment by the same day interval
|
|
22416
|
+
* - equidistant dates but not the same interval, in which case we return increment of the same interval
|
|
22417
|
+
*
|
|
22418
|
+
* */
|
|
22419
|
+
function calculateDateIncrementBasedOnGroup(group) {
|
|
22420
|
+
if (group.length < 2) {
|
|
22421
|
+
return 1;
|
|
22422
|
+
}
|
|
22423
|
+
const jsDates = group.map((date) => toJsDate(date, DEFAULT_LOCALE));
|
|
22424
|
+
const datesIntervals = getDateIntervals(jsDates);
|
|
22425
|
+
const datesEquidistantInterval = getEqualInterval(datesIntervals);
|
|
22426
|
+
if (datesEquidistantInterval === undefined) {
|
|
22427
|
+
// dates are not equidistant in terms of years, months or days, thus no rule can be extrapolated
|
|
22428
|
+
return undefined;
|
|
22429
|
+
}
|
|
22430
|
+
// The dates are apart by an exact interval of years, months or days
|
|
22431
|
+
// but not a combination of them
|
|
22432
|
+
const exactDateInterval = Object.values(datesEquidistantInterval).filter((value) => value !== 0).length === 1;
|
|
22433
|
+
const isSameDay = Object.values(datesEquidistantInterval).every((el) => el === 0); // handles time values (strict decimals)
|
|
22434
|
+
if (!exactDateInterval || isSameDay) {
|
|
22435
|
+
const timeIntervals = jsDates
|
|
22436
|
+
.map((date, index) => {
|
|
22437
|
+
if (index === 0) {
|
|
22438
|
+
return 0;
|
|
22439
|
+
}
|
|
22440
|
+
const previous = jsDates[index - 1];
|
|
22441
|
+
const days = Math.floor(date.getTime()) - Math.floor(previous.getTime());
|
|
22442
|
+
return days;
|
|
22443
|
+
})
|
|
22444
|
+
.slice(1);
|
|
22445
|
+
const equidistantDates = timeIntervals.every((interval) => interval === timeIntervals[0]);
|
|
22446
|
+
if (equidistantDates) {
|
|
22447
|
+
return group.length * (group[1] - group[0]);
|
|
22448
|
+
}
|
|
22449
|
+
}
|
|
22450
|
+
return {
|
|
22451
|
+
years: datesEquidistantInterval.years * group.length,
|
|
22452
|
+
months: datesEquidistantInterval.months * group.length,
|
|
22453
|
+
days: datesEquidistantInterval.days * group.length,
|
|
22454
|
+
};
|
|
22455
|
+
}
|
|
22305
22456
|
autofillRulesRegistry
|
|
22306
22457
|
.add("simple_value_copy", {
|
|
22307
22458
|
condition: (cell, cells) => {
|
|
@@ -22349,12 +22500,47 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22349
22500
|
return { type: "FORMULA_MODIFIER", increment: cells.length, current: 0 };
|
|
22350
22501
|
},
|
|
22351
22502
|
sequence: 30,
|
|
22503
|
+
})
|
|
22504
|
+
.add("increment_dates", {
|
|
22505
|
+
condition: (cell, cells) => {
|
|
22506
|
+
return (!cell.isFormula &&
|
|
22507
|
+
evaluateLiteral(cell, { locale: DEFAULT_LOCALE }).type === CellValueType.number &&
|
|
22508
|
+
!!cell.format &&
|
|
22509
|
+
isDateTimeFormat(cell.format));
|
|
22510
|
+
},
|
|
22511
|
+
generateRule: (cell, cells) => {
|
|
22512
|
+
const group = getGroup(cell, cells, (evaluatedCell) => evaluatedCell.type === CellValueType.number &&
|
|
22513
|
+
!!evaluatedCell.format &&
|
|
22514
|
+
isDateTimeFormat(evaluatedCell.format)).map((cell) => Number(cell.value));
|
|
22515
|
+
const increment = calculateDateIncrementBasedOnGroup(group);
|
|
22516
|
+
if (increment === undefined) {
|
|
22517
|
+
return { type: "COPY_MODIFIER" };
|
|
22518
|
+
}
|
|
22519
|
+
/** requires to detect the current date (requires to be an integer value with the right format)
|
|
22520
|
+
* detect if year or if month or if day then extrapolate increment required (+1 month, +1 year + 1 day)
|
|
22521
|
+
*/
|
|
22522
|
+
const evaluation = evaluateLiteral(cell, { locale: DEFAULT_LOCALE });
|
|
22523
|
+
if (typeof increment === "object") {
|
|
22524
|
+
return {
|
|
22525
|
+
type: "DATE_INCREMENT_MODIFIER",
|
|
22526
|
+
increment,
|
|
22527
|
+
current: evaluation.type === CellValueType.number ? evaluation.value : 0,
|
|
22528
|
+
};
|
|
22529
|
+
}
|
|
22530
|
+
return {
|
|
22531
|
+
type: "INCREMENT_MODIFIER",
|
|
22532
|
+
increment,
|
|
22533
|
+
current: evaluation.type === CellValueType.number ? evaluation.value : 0,
|
|
22534
|
+
};
|
|
22535
|
+
},
|
|
22536
|
+
sequence: 25,
|
|
22352
22537
|
})
|
|
22353
22538
|
.add("increment_number", {
|
|
22354
22539
|
condition: (cell) => !cell.isFormula &&
|
|
22355
22540
|
evaluateLiteral(cell, { locale: DEFAULT_LOCALE }).type === CellValueType.number,
|
|
22356
22541
|
generateRule: (cell, cells) => {
|
|
22357
|
-
const group = getGroup(cell, cells, (evaluatedCell) => evaluatedCell.type === CellValueType.number
|
|
22542
|
+
const group = getGroup(cell, cells, (evaluatedCell) => evaluatedCell.type === CellValueType.number &&
|
|
22543
|
+
!isDateTimeFormat(evaluatedCell.format || "")).map((cell) => Number(cell.value));
|
|
22358
22544
|
const increment = calculateIncrementBasedOnGroup(group);
|
|
22359
22545
|
const evaluation = evaluateLiteral(cell, { locale: DEFAULT_LOCALE });
|
|
22360
22546
|
return {
|
|
@@ -22365,6 +22551,37 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22365
22551
|
},
|
|
22366
22552
|
sequence: 40,
|
|
22367
22553
|
});
|
|
22554
|
+
/**
|
|
22555
|
+
* Returns the date intervals between consecutive dates of an array
|
|
22556
|
+
* in the format of { years: number, months: number, days: number }
|
|
22557
|
+
*
|
|
22558
|
+
* The split is necessary to make abstraction of leap years and
|
|
22559
|
+
* months with different number of days.
|
|
22560
|
+
*
|
|
22561
|
+
* @param dates
|
|
22562
|
+
*/
|
|
22563
|
+
function getDateIntervals(dates) {
|
|
22564
|
+
if (dates.length < 2) {
|
|
22565
|
+
return [{ years: 0, months: 0, days: 0 }];
|
|
22566
|
+
}
|
|
22567
|
+
const res = dates.map((date, index) => {
|
|
22568
|
+
if (index === 0) {
|
|
22569
|
+
return { years: 0, months: 0, days: 0 };
|
|
22570
|
+
}
|
|
22571
|
+
const previous = DateTime.fromTimestamp(dates[index - 1].getTime());
|
|
22572
|
+
const years = getTimeDifferenceInWholeYears(previous, date);
|
|
22573
|
+
const months = getTimeDifferenceInWholeMonths(previous, date) % 12;
|
|
22574
|
+
previous.setFullYear(previous.getFullYear() + years);
|
|
22575
|
+
previous.setMonth(previous.getMonth() + months);
|
|
22576
|
+
const days = getTimeDifferenceInWholeDays(previous, date);
|
|
22577
|
+
return {
|
|
22578
|
+
years,
|
|
22579
|
+
months,
|
|
22580
|
+
days,
|
|
22581
|
+
};
|
|
22582
|
+
});
|
|
22583
|
+
return res.slice(1);
|
|
22584
|
+
}
|
|
22368
22585
|
|
|
22369
22586
|
const cellPopoverRegistry = new Registry();
|
|
22370
22587
|
|
|
@@ -27875,9 +28092,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27875
28092
|
/**
|
|
27876
28093
|
* Get a default chart js configuration
|
|
27877
28094
|
*/
|
|
27878
|
-
function getDefaultChartJsRuntime(chart, labels, fontColor, {
|
|
28095
|
+
function getDefaultChartJsRuntime(chart, labels, fontColor, { axisFormats, locale, truncateLabels = true, horizontalChart }) {
|
|
27879
28096
|
const chartTitle = chart.title.text ? chart.title : { ...chart.title, content: "" };
|
|
27880
|
-
const
|
|
28097
|
+
const chartOptions = {
|
|
27881
28098
|
// https://www.chartjs.org/docs/latest/general/responsive.html
|
|
27882
28099
|
responsive: true, // will resize when its container is resized
|
|
27883
28100
|
maintainAspectRatio: false, // doesn't maintain the aspect ration (width/height =2 by default) so the user has the choice of the exact layout
|
|
@@ -27924,8 +28141,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27924
28141
|
if (!yLabel) {
|
|
27925
28142
|
yLabel = tooltipItem.parsed;
|
|
27926
28143
|
}
|
|
27927
|
-
const
|
|
27928
|
-
|
|
28144
|
+
const axisId = horizontalChart
|
|
28145
|
+
? tooltipItem.dataset.xAxisID
|
|
28146
|
+
: tooltipItem.dataset.yAxisID;
|
|
28147
|
+
const yLabelStr = formatChartDatasetValue(axisFormats, locale)(yLabel, axisId);
|
|
27929
28148
|
return xLabel ? `${xLabel}: ${yLabelStr}` : yLabelStr;
|
|
27930
28149
|
},
|
|
27931
28150
|
},
|
|
@@ -27934,7 +28153,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27934
28153
|
};
|
|
27935
28154
|
return {
|
|
27936
28155
|
type: chart.type,
|
|
27937
|
-
options,
|
|
28156
|
+
options: chartOptions,
|
|
27938
28157
|
data: {
|
|
27939
28158
|
labels: truncateLabels ? labels.map(truncateLabel) : labels,
|
|
27940
28159
|
datasets: [],
|
|
@@ -27993,7 +28212,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27993
28212
|
* Get the format to apply to the the dataset values. This format is defined as the first format
|
|
27994
28213
|
* found in the dataset ranges that isn't a date format.
|
|
27995
28214
|
*/
|
|
27996
|
-
function getChartDatasetFormat(getters,
|
|
28215
|
+
function getChartDatasetFormat(getters, allDataSets, axis) {
|
|
28216
|
+
const dataSets = allDataSets.filter((ds) => (axis === "right") === !!ds.rightYAxis);
|
|
27997
28217
|
for (const ds of dataSets) {
|
|
27998
28218
|
const formatsInDataset = getters.getRangeFormats(ds.dataRange);
|
|
27999
28219
|
const format = formatsInDataset.find((f) => f !== undefined && !isDateTimeFormat(f));
|
|
@@ -28247,12 +28467,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28247
28467
|
if (chart.aggregated) {
|
|
28248
28468
|
({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
|
|
28249
28469
|
}
|
|
28250
|
-
const
|
|
28470
|
+
const leftAxisFormat = getChartDatasetFormat(getters, chart.dataSets, "left");
|
|
28471
|
+
const rightAxisFormat = getChartDatasetFormat(getters, chart.dataSets, "right");
|
|
28251
28472
|
const locale = getters.getLocale();
|
|
28252
|
-
const localeFormat = { format: dataSetFormat, locale };
|
|
28253
28473
|
const fontColor = chartFontColor(chart.background);
|
|
28474
|
+
const axisFormats = chart.horizontal
|
|
28475
|
+
? { x: leftAxisFormat || rightAxisFormat }
|
|
28476
|
+
: { y: leftAxisFormat, y1: rightAxisFormat };
|
|
28254
28477
|
const config = getDefaultChartJsRuntime(chart, labels, fontColor, {
|
|
28255
|
-
|
|
28478
|
+
locale,
|
|
28479
|
+
axisFormats,
|
|
28256
28480
|
horizontalChart: chart.horizontal,
|
|
28257
28481
|
});
|
|
28258
28482
|
const legend = {
|
|
@@ -28273,51 +28497,27 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28273
28497
|
};
|
|
28274
28498
|
config.options.indexAxis = chart.horizontal ? "y" : "x";
|
|
28275
28499
|
config.options.scales = {};
|
|
28276
|
-
const
|
|
28277
|
-
const
|
|
28278
|
-
|
|
28279
|
-
|
|
28280
|
-
|
|
28281
|
-
|
|
28282
|
-
},
|
|
28283
|
-
};
|
|
28284
|
-
const xAxis = chart.horizontal ? valuesAxis : labelsAxis;
|
|
28285
|
-
const yAxis = chart.horizontal ? labelsAxis : valuesAxis;
|
|
28286
|
-
const { useLeftAxis, useRightAxis } = getDefinedAxis(chart.getDefinition());
|
|
28287
|
-
config.options.scales.x = { ...xAxis, title: getChartAxisTitleRuntime(chart.axesDesign?.x) };
|
|
28288
|
-
if (useLeftAxis) {
|
|
28289
|
-
config.options.scales.y = {
|
|
28290
|
-
...yAxis,
|
|
28291
|
-
position: "left",
|
|
28292
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.y),
|
|
28293
|
-
};
|
|
28294
|
-
}
|
|
28295
|
-
if (useRightAxis) {
|
|
28296
|
-
config.options.scales.y1 = {
|
|
28297
|
-
...yAxis,
|
|
28298
|
-
position: "right",
|
|
28299
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.y1),
|
|
28300
|
-
};
|
|
28500
|
+
const definition = chart.getDefinition();
|
|
28501
|
+
const options = { stacked: chart.stacked, locale };
|
|
28502
|
+
if (chart.horizontal) {
|
|
28503
|
+
const format = leftAxisFormat || rightAxisFormat;
|
|
28504
|
+
config.options.scales.x = getChartAxis(definition, "bottom", "values", { ...options, format });
|
|
28505
|
+
config.options.scales.y = getChartAxis(definition, "left", "labels", options);
|
|
28301
28506
|
}
|
|
28302
|
-
|
|
28303
|
-
|
|
28304
|
-
|
|
28305
|
-
|
|
28306
|
-
|
|
28307
|
-
|
|
28308
|
-
}
|
|
28309
|
-
if (useRightAxis) {
|
|
28310
|
-
// @ts-ignore chart.js type is broken
|
|
28311
|
-
config.options.scales.y1.stacked = true;
|
|
28312
|
-
}
|
|
28507
|
+
else {
|
|
28508
|
+
config.options.scales.x = getChartAxis(definition, "bottom", "labels", options);
|
|
28509
|
+
const leftAxisOptions = { ...options, format: leftAxisFormat };
|
|
28510
|
+
config.options.scales.y = getChartAxis(definition, "left", "values", leftAxisOptions);
|
|
28511
|
+
const rightAxisOptions = { ...options, format: rightAxisFormat };
|
|
28512
|
+
config.options.scales.y1 = getChartAxis(definition, "right", "values", rightAxisOptions);
|
|
28313
28513
|
}
|
|
28514
|
+
config.options.scales = removeFalsyAttributes(config.options.scales);
|
|
28314
28515
|
config.options.plugins.chartShowValuesPlugin = {
|
|
28315
28516
|
showValues: chart.showValues,
|
|
28316
28517
|
background: chart.background,
|
|
28317
28518
|
horizontal: chart.horizontal,
|
|
28318
|
-
callback:
|
|
28519
|
+
callback: formatChartDatasetValue(axisFormats, locale),
|
|
28319
28520
|
};
|
|
28320
|
-
const definition = chart.getDefinition();
|
|
28321
28521
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28322
28522
|
const trendDatasets = [];
|
|
28323
28523
|
for (const index in dataSetsValues) {
|
|
@@ -28335,9 +28535,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28335
28535
|
const label = definition.dataSets[index].label;
|
|
28336
28536
|
dataset.label = label;
|
|
28337
28537
|
}
|
|
28338
|
-
|
|
28339
|
-
|
|
28340
|
-
}
|
|
28538
|
+
dataset.yAxisID = chart.horizontal ? "y" : definition.dataSets[index].yAxisId || "y";
|
|
28539
|
+
dataset.xAxisID = "x";
|
|
28341
28540
|
const trend = definition.dataSets?.[index].trend;
|
|
28342
28541
|
if (!trend?.display || chart.horizontal) {
|
|
28343
28542
|
continue;
|
|
@@ -28353,7 +28552,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28353
28552
|
*/
|
|
28354
28553
|
const maxLength = Math.max(...trendDatasets.map((trendDataset) => trendDataset.data.length));
|
|
28355
28554
|
config.options.scales[TREND_LINE_XAXIS_ID] = {
|
|
28356
|
-
...
|
|
28555
|
+
...config.options.scales.x,
|
|
28357
28556
|
labels: Array(maxLength).fill(""),
|
|
28358
28557
|
offset: false,
|
|
28359
28558
|
display: false,
|
|
@@ -28643,8 +28842,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28643
28842
|
}
|
|
28644
28843
|
const locale = getters.getLocale();
|
|
28645
28844
|
const truncateLabels = axisType === "category";
|
|
28646
|
-
const
|
|
28647
|
-
const
|
|
28845
|
+
const leftAxisFormat = getChartDatasetFormat(getters, chart.dataSets, "left");
|
|
28846
|
+
const rightAxisFormat = getChartDatasetFormat(getters, chart.dataSets, "right");
|
|
28847
|
+
const axisFormats = { y: leftAxisFormat, y1: rightAxisFormat };
|
|
28848
|
+
const options = { locale, truncateLabels, axisFormats };
|
|
28648
28849
|
const fontColor = chartFontColor(chart.background);
|
|
28649
28850
|
const config = getDefaultChartJsRuntime(chart, labels, fontColor, options);
|
|
28650
28851
|
const legend = {
|
|
@@ -28674,52 +28875,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28674
28875
|
displayLegend: chart.legendPosition === "top",
|
|
28675
28876
|
}),
|
|
28676
28877
|
};
|
|
28677
|
-
const
|
|
28678
|
-
|
|
28679
|
-
padding: 5,
|
|
28680
|
-
color: fontColor,
|
|
28681
|
-
},
|
|
28682
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.x),
|
|
28683
|
-
};
|
|
28878
|
+
const definition = chart.getDefinition();
|
|
28879
|
+
const stacked = "stacked" in chart && chart.stacked;
|
|
28684
28880
|
config.options.scales = {
|
|
28685
|
-
x:
|
|
28686
|
-
|
|
28687
|
-
|
|
28688
|
-
beginAtZero: true, // the origin of the y axis is always zero
|
|
28689
|
-
ticks: {
|
|
28690
|
-
color: fontColor,
|
|
28691
|
-
callback: formatTickValue(options),
|
|
28692
|
-
},
|
|
28881
|
+
x: getChartAxis(definition, "bottom", "labels", { locale }),
|
|
28882
|
+
y: getChartAxis(definition, "left", "values", { locale, stacked, format: leftAxisFormat }),
|
|
28883
|
+
y1: getChartAxis(definition, "right", "values", { locale, stacked, format: rightAxisFormat }),
|
|
28693
28884
|
};
|
|
28694
|
-
|
|
28695
|
-
if (useLeftAxis) {
|
|
28696
|
-
config.options.scales.y = {
|
|
28697
|
-
...yAxis,
|
|
28698
|
-
position: "left",
|
|
28699
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.y),
|
|
28700
|
-
};
|
|
28701
|
-
}
|
|
28702
|
-
if (useRightAxis) {
|
|
28703
|
-
config.options.scales.y1 = {
|
|
28704
|
-
...yAxis,
|
|
28705
|
-
position: "right",
|
|
28706
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.y1),
|
|
28707
|
-
};
|
|
28708
|
-
}
|
|
28709
|
-
if ("stacked" in chart && chart.stacked) {
|
|
28710
|
-
if (useLeftAxis) {
|
|
28711
|
-
// @ts-ignore chart.js type is broken
|
|
28712
|
-
config.options.scales.y.stacked = true;
|
|
28713
|
-
}
|
|
28714
|
-
if (useRightAxis) {
|
|
28715
|
-
// @ts-ignore chart.js type is broken
|
|
28716
|
-
config.options.scales.y1.stacked = true;
|
|
28717
|
-
}
|
|
28718
|
-
}
|
|
28885
|
+
config.options.scales = removeFalsyAttributes(config.options.scales);
|
|
28719
28886
|
config.options.plugins.chartShowValuesPlugin = {
|
|
28720
28887
|
showValues: chart.showValues,
|
|
28721
28888
|
background: chart.background,
|
|
28722
|
-
callback:
|
|
28889
|
+
callback: formatChartDatasetValue(axisFormats, locale),
|
|
28723
28890
|
};
|
|
28724
28891
|
if (chart.dataSetsHaveTitle &&
|
|
28725
28892
|
dataSetsValues[0] &&
|
|
@@ -28746,7 +28913,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28746
28913
|
label = toNumber(label, locale);
|
|
28747
28914
|
}
|
|
28748
28915
|
const formattedX = formatValue(label, { locale, format: labelFormat });
|
|
28749
|
-
const formattedY = formatValue(dataSetPoint, { locale, format:
|
|
28916
|
+
const formattedY = formatValue(dataSetPoint, { locale, format: leftAxisFormat });
|
|
28750
28917
|
const dataSetTitle = tooltipItem.dataset.label;
|
|
28751
28918
|
return formattedX
|
|
28752
28919
|
? `${dataSetTitle}: (${formattedX}, ${formattedY})`
|
|
@@ -28756,7 +28923,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28756
28923
|
const areaChart = "fillArea" in chart ? chart.fillArea : false;
|
|
28757
28924
|
const stackedChart = "stacked" in chart ? chart.stacked : false;
|
|
28758
28925
|
const cumulative = "cumulative" in chart ? chart.cumulative : false;
|
|
28759
|
-
const definition = chart.getDefinition();
|
|
28760
28926
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28761
28927
|
for (let [index, { label, data }] of dataSetsValues.entries()) {
|
|
28762
28928
|
const color = colors.next();
|
|
@@ -28797,9 +28963,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28797
28963
|
const label = definition.dataSets[index].label;
|
|
28798
28964
|
dataset.label = label;
|
|
28799
28965
|
}
|
|
28800
|
-
|
|
28801
|
-
dataset["yAxisID"] = definition.dataSets[index].yAxisId;
|
|
28802
|
-
}
|
|
28966
|
+
dataset["yAxisID"] = definition.dataSets[index].yAxisId || "y";
|
|
28803
28967
|
const trend = definition.dataSets?.[index].trend;
|
|
28804
28968
|
if (!trend?.display) {
|
|
28805
28969
|
continue;
|
|
@@ -28816,7 +28980,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28816
28980
|
* set so that the second axis points match the classical x axis
|
|
28817
28981
|
*/
|
|
28818
28982
|
config.options.scales[TREND_LINE_XAXIS_ID] = {
|
|
28819
|
-
...
|
|
28983
|
+
...config.options.scales.x,
|
|
28820
28984
|
type: "category",
|
|
28821
28985
|
labels: range(0, maxLength).map((x) => x.toString()),
|
|
28822
28986
|
offset: false,
|
|
@@ -28838,10 +29002,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28838
29002
|
return {
|
|
28839
29003
|
chartJsConfig: config,
|
|
28840
29004
|
background: chart.background || BACKGROUND_CHART_COLOR,
|
|
28841
|
-
dataSetsValues,
|
|
28842
|
-
labelValues,
|
|
28843
|
-
dataSetFormat,
|
|
28844
|
-
labelFormat,
|
|
28845
29005
|
};
|
|
28846
29006
|
}
|
|
28847
29007
|
|
|
@@ -28899,6 +29059,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28899
29059
|
ranges.push({
|
|
28900
29060
|
...this.dataSetDesign?.[i],
|
|
28901
29061
|
dataRange: this.getters.getRangeString(dataSet.dataRange, targetSheetId || this.sheetId),
|
|
29062
|
+
type: this.dataSetDesign?.[i]?.type ?? (i ? "line" : "bar"),
|
|
28902
29063
|
});
|
|
28903
29064
|
}
|
|
28904
29065
|
return {
|
|
@@ -28944,9 +29105,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28944
29105
|
return new ComboChart(definition, this.sheetId, this.getters);
|
|
28945
29106
|
}
|
|
28946
29107
|
static getDefinitionFromContextCreation(context) {
|
|
29108
|
+
const dataSets = (context.range ?? []).map((ds, index) => ({
|
|
29109
|
+
...ds,
|
|
29110
|
+
type: index ? "line" : "bar",
|
|
29111
|
+
}));
|
|
28947
29112
|
return {
|
|
28948
29113
|
background: context.background,
|
|
28949
|
-
dataSets
|
|
29114
|
+
dataSets,
|
|
28950
29115
|
dataSetsHaveTitle: context.dataSetsHaveTitle ?? false,
|
|
28951
29116
|
aggregated: context.aggregated,
|
|
28952
29117
|
legendPosition: context.legendPosition ?? "top",
|
|
@@ -28969,10 +29134,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28969
29134
|
}
|
|
28970
29135
|
}
|
|
28971
29136
|
function createComboChartRuntime(chart, getters) {
|
|
28972
|
-
const mainDataSetFormat = chart.dataSets
|
|
28973
|
-
|
|
28974
|
-
: undefined;
|
|
28975
|
-
const lineDataSetsFormat = getChartDatasetFormat(getters, chart.dataSets.slice(1));
|
|
29137
|
+
const mainDataSetFormat = getChartDatasetFormat(getters, chart.dataSets, "left");
|
|
29138
|
+
const lineDataSetsFormat = getChartDatasetFormat(getters, chart.dataSets, "right");
|
|
28976
29139
|
const locale = getters.getLocale();
|
|
28977
29140
|
const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
|
|
28978
29141
|
let labels = labelValues.formattedValues;
|
|
@@ -28986,12 +29149,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28986
29149
|
if (chart.aggregated) {
|
|
28987
29150
|
({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
|
|
28988
29151
|
}
|
|
28989
|
-
const localeFormat = { format: mainDataSetFormat, locale };
|
|
28990
29152
|
const fontColor = chartFontColor(chart.background);
|
|
28991
|
-
const
|
|
29153
|
+
const axisFormats = { y: mainDataSetFormat, y1: lineDataSetsFormat };
|
|
29154
|
+
const config = getDefaultChartJsRuntime(chart, labels, fontColor, { locale, axisFormats });
|
|
28992
29155
|
const legend = {
|
|
28993
29156
|
labels: { color: fontColor },
|
|
28994
|
-
reverse: true,
|
|
28995
29157
|
};
|
|
28996
29158
|
if (chart.legendPosition === "none") {
|
|
28997
29159
|
legend.display = false;
|
|
@@ -29006,52 +29168,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29006
29168
|
displayLegend: chart.legendPosition === "top",
|
|
29007
29169
|
}),
|
|
29008
29170
|
};
|
|
29171
|
+
const definition = chart.getDefinition();
|
|
29009
29172
|
config.options.scales = {
|
|
29010
|
-
x: {
|
|
29011
|
-
|
|
29012
|
-
|
|
29013
|
-
color: fontColor,
|
|
29014
|
-
},
|
|
29015
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.x),
|
|
29016
|
-
},
|
|
29173
|
+
x: getChartAxis(definition, "bottom", "labels", { locale }),
|
|
29174
|
+
y: getChartAxis(definition, "left", "values", { locale, format: mainDataSetFormat }),
|
|
29175
|
+
y1: getChartAxis(definition, "right", "values", { locale, format: lineDataSetsFormat }),
|
|
29017
29176
|
};
|
|
29018
|
-
|
|
29019
|
-
beginAtZero: true, // the origin of the y axis is always zero
|
|
29020
|
-
ticks: {
|
|
29021
|
-
color: fontColor,
|
|
29022
|
-
callback: formatTickValue({ format: mainDataSetFormat, locale }),
|
|
29023
|
-
},
|
|
29024
|
-
};
|
|
29025
|
-
const rightVerticalAxis = {
|
|
29026
|
-
beginAtZero: true, // the origin of the y axis is always zero
|
|
29027
|
-
ticks: {
|
|
29028
|
-
color: fontColor,
|
|
29029
|
-
callback: formatTickValue({ format: lineDataSetsFormat, locale }),
|
|
29030
|
-
},
|
|
29031
|
-
};
|
|
29032
|
-
const definition = chart.getDefinition();
|
|
29033
|
-
const { useLeftAxis, useRightAxis } = getDefinedAxis(definition);
|
|
29034
|
-
if (useLeftAxis) {
|
|
29035
|
-
config.options.scales.y = {
|
|
29036
|
-
...leftVerticalAxis,
|
|
29037
|
-
position: "left",
|
|
29038
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.y),
|
|
29039
|
-
};
|
|
29040
|
-
}
|
|
29041
|
-
if (useRightAxis) {
|
|
29042
|
-
config.options.scales.y1 = {
|
|
29043
|
-
...rightVerticalAxis,
|
|
29044
|
-
position: "right",
|
|
29045
|
-
grid: {
|
|
29046
|
-
display: false,
|
|
29047
|
-
},
|
|
29048
|
-
title: getChartAxisTitleRuntime(chart.axesDesign?.y1),
|
|
29049
|
-
};
|
|
29050
|
-
}
|
|
29177
|
+
config.options.scales = removeFalsyAttributes(config.options.scales);
|
|
29051
29178
|
config.options.plugins.chartShowValuesPlugin = {
|
|
29052
29179
|
showValues: chart.showValues,
|
|
29053
29180
|
background: chart.background,
|
|
29054
|
-
callback:
|
|
29181
|
+
callback: formatChartDatasetValue(axisFormats, locale),
|
|
29055
29182
|
};
|
|
29056
29183
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
29057
29184
|
let maxLength = 0;
|
|
@@ -29059,14 +29186,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29059
29186
|
for (let [index, { label, data }] of dataSetsValues.entries()) {
|
|
29060
29187
|
const design = definition.dataSets[index];
|
|
29061
29188
|
const color = colors.next();
|
|
29189
|
+
const type = design?.type ?? "line";
|
|
29062
29190
|
const dataset = {
|
|
29063
29191
|
label: design?.label ?? label,
|
|
29064
29192
|
data,
|
|
29065
29193
|
borderColor: color,
|
|
29066
29194
|
backgroundColor: color,
|
|
29067
29195
|
yAxisID: design?.yAxisId ?? "y",
|
|
29068
|
-
type
|
|
29069
|
-
order:
|
|
29196
|
+
type,
|
|
29197
|
+
order: type === "bar" ? dataSetsValues.length + index : index,
|
|
29070
29198
|
};
|
|
29071
29199
|
config.data.datasets.push(dataset);
|
|
29072
29200
|
const trend = definition.dataSets?.[index].trend;
|
|
@@ -29679,7 +29807,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29679
29807
|
({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
|
|
29680
29808
|
}
|
|
29681
29809
|
({ dataSetsValues, labels } = filterNegativeValues(labels, dataSetsValues));
|
|
29682
|
-
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets);
|
|
29810
|
+
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets, "left");
|
|
29683
29811
|
const locale = getters.getLocale();
|
|
29684
29812
|
const config = getPieConfiguration(chart, labels, { format: dataSetFormat, locale });
|
|
29685
29813
|
const dataSetsLength = Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0));
|
|
@@ -29834,7 +29962,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29834
29962
|
return tooltipLabelCallback(tooltipItem);
|
|
29835
29963
|
};
|
|
29836
29964
|
const callback = config.options.plugins.chartShowValuesPlugin.callback;
|
|
29837
|
-
config.options.plugins.chartShowValuesPlugin.callback = (x) => callback(Math.abs(x));
|
|
29965
|
+
config.options.plugins.chartShowValuesPlugin.callback = (x, axisId) => callback(Math.abs(x), axisId);
|
|
29838
29966
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
29839
29967
|
}
|
|
29840
29968
|
|
|
@@ -30225,7 +30353,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30225
30353
|
if (chart.showSubTotals) {
|
|
30226
30354
|
labels.push(_t("Subtotal"));
|
|
30227
30355
|
}
|
|
30228
|
-
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets)
|
|
30356
|
+
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets, "left") ||
|
|
30357
|
+
getChartDatasetFormat(getters, chart.dataSets, "right");
|
|
30229
30358
|
const locale = getters.getLocale();
|
|
30230
30359
|
const dataSeriesLabels = dataSetsValues.map((dataSet) => dataSet.label);
|
|
30231
30360
|
const config = getWaterfallConfiguration(chart, labels, dataSeriesLabels, {
|
|
@@ -35295,6 +35424,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
35295
35424
|
<path fill='none' stroke='#FFF' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/>
|
|
35296
35425
|
</svg>
|
|
35297
35426
|
`;
|
|
35427
|
+
const CHECKBOX_WIDTH = 14;
|
|
35298
35428
|
css /* scss */ `
|
|
35299
35429
|
label.o-checkbox {
|
|
35300
35430
|
input {
|
|
@@ -35302,8 +35432,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
35302
35432
|
-webkit-appearance: none;
|
|
35303
35433
|
-moz-appearance: none;
|
|
35304
35434
|
border-radius: 0;
|
|
35305
|
-
width:
|
|
35306
|
-
height:
|
|
35435
|
+
width: ${CHECKBOX_WIDTH}px;
|
|
35436
|
+
height: ${CHECKBOX_WIDTH}px;
|
|
35307
35437
|
vertical-align: top;
|
|
35308
35438
|
box-sizing: border-box;
|
|
35309
35439
|
outline: none;
|
|
@@ -37213,6 +37343,32 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37213
37343
|
}
|
|
37214
37344
|
}
|
|
37215
37345
|
|
|
37346
|
+
class ComboChartDesignPanel extends ChartWithAxisDesignPanel {
|
|
37347
|
+
static template = "o-spreadsheet-ComboChartDesignPanel";
|
|
37348
|
+
seriesTypeChoices = [
|
|
37349
|
+
{ value: "bar", label: _t("Bar") },
|
|
37350
|
+
{ value: "line", label: _t("Line") },
|
|
37351
|
+
];
|
|
37352
|
+
updateDataSeriesType(type) {
|
|
37353
|
+
const dataSets = [...this.props.definition.dataSets];
|
|
37354
|
+
if (!dataSets?.[this.state.index]) {
|
|
37355
|
+
return;
|
|
37356
|
+
}
|
|
37357
|
+
dataSets[this.state.index] = {
|
|
37358
|
+
...dataSets[this.state.index],
|
|
37359
|
+
type,
|
|
37360
|
+
};
|
|
37361
|
+
this.props.updateChart(this.props.figureId, { dataSets });
|
|
37362
|
+
}
|
|
37363
|
+
getDataSeriesType() {
|
|
37364
|
+
const dataSets = this.props.definition.dataSets;
|
|
37365
|
+
if (!dataSets?.[this.state.index]) {
|
|
37366
|
+
return "bar";
|
|
37367
|
+
}
|
|
37368
|
+
return dataSets[this.state.index].type ?? "line";
|
|
37369
|
+
}
|
|
37370
|
+
}
|
|
37371
|
+
|
|
37216
37372
|
class GaugeChartConfigPanel extends owl.Component {
|
|
37217
37373
|
static template = "o-spreadsheet-GaugeChartConfigPanel";
|
|
37218
37374
|
static components = { ChartErrorSection, ChartDataSeries };
|
|
@@ -37639,7 +37795,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37639
37795
|
})
|
|
37640
37796
|
.add("combo", {
|
|
37641
37797
|
configuration: GenericChartConfigPanel,
|
|
37642
|
-
design:
|
|
37798
|
+
design: ComboChartDesignPanel,
|
|
37643
37799
|
})
|
|
37644
37800
|
.add("pie", {
|
|
37645
37801
|
configuration: GenericChartConfigPanel,
|
|
@@ -37925,6 +38081,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37925
38081
|
"stopComposerRangeSelection",
|
|
37926
38082
|
"cancelEdition",
|
|
37927
38083
|
"cycleReferences",
|
|
38084
|
+
"toggleEditionMode",
|
|
37928
38085
|
"changeComposerCursorSelection",
|
|
37929
38086
|
"replaceComposerCursorSelection",
|
|
37930
38087
|
];
|
|
@@ -38080,6 +38237,42 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38080
38237
|
}
|
|
38081
38238
|
this.setCurrentContent(updated.content, updated.selection);
|
|
38082
38239
|
}
|
|
38240
|
+
toggleEditionMode() {
|
|
38241
|
+
if (this.editionMode === "inactive")
|
|
38242
|
+
return;
|
|
38243
|
+
const start = Math.min(this.selectionStart, this.selectionEnd);
|
|
38244
|
+
const end = Math.max(this.selectionStart, this.selectionEnd);
|
|
38245
|
+
const refToken = [...this.currentTokens]
|
|
38246
|
+
.reverse()
|
|
38247
|
+
.find((tk) => tk.end >= start && end >= tk.start && tk.type === "REFERENCE");
|
|
38248
|
+
if (this.editionMode === "editing" && refToken) {
|
|
38249
|
+
const currentSheetId = this.getters.getActiveSheetId();
|
|
38250
|
+
const { sheetName, xc } = splitReference(refToken.value);
|
|
38251
|
+
const sheetId = this.getters.getSheetIdByName(sheetName);
|
|
38252
|
+
if (sheetId && sheetId !== currentSheetId) {
|
|
38253
|
+
this.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: currentSheetId, sheetIdTo: sheetId });
|
|
38254
|
+
}
|
|
38255
|
+
// move cursor to the right part of the token
|
|
38256
|
+
this.selectionStart = this.selectionEnd = refToken.end;
|
|
38257
|
+
const zone = this.getters.getRangeFromSheetXC(this.sheetId, xc).zone;
|
|
38258
|
+
this.captureSelection(zone);
|
|
38259
|
+
this.editionMode = "selecting";
|
|
38260
|
+
}
|
|
38261
|
+
else {
|
|
38262
|
+
this.editionMode = "editing";
|
|
38263
|
+
}
|
|
38264
|
+
}
|
|
38265
|
+
captureSelection(zone, col, row) {
|
|
38266
|
+
this.model.selection.capture(this, {
|
|
38267
|
+
cell: { col: col || zone.left, row: row || zone.right },
|
|
38268
|
+
zone,
|
|
38269
|
+
}, {
|
|
38270
|
+
handleEvent: this.handleEvent.bind(this),
|
|
38271
|
+
release: () => {
|
|
38272
|
+
this._stopEdition();
|
|
38273
|
+
},
|
|
38274
|
+
});
|
|
38275
|
+
}
|
|
38083
38276
|
isSelectionValid(length, start, end) {
|
|
38084
38277
|
return start >= 0 && start <= length && end >= 0 && end <= length;
|
|
38085
38278
|
}
|
|
@@ -38118,12 +38311,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38118
38311
|
this.setContent(str || this.initialContent, selection);
|
|
38119
38312
|
this.colorIndexByRange = {};
|
|
38120
38313
|
const zone = positionToZone({ col: this.col, row: this.row });
|
|
38121
|
-
this.
|
|
38122
|
-
handleEvent: this.handleEvent.bind(this),
|
|
38123
|
-
release: () => {
|
|
38124
|
-
this._stopEdition();
|
|
38125
|
-
},
|
|
38126
|
-
});
|
|
38314
|
+
this.captureSelection(zone, col, row);
|
|
38127
38315
|
}
|
|
38128
38316
|
_stopEdition() {
|
|
38129
38317
|
if (this.editionMode !== "inactive") {
|
|
@@ -42818,8 +43006,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
42818
43006
|
* This function converts a list of data entry into a spreadsheet pivot table.
|
|
42819
43007
|
*/
|
|
42820
43008
|
function dataEntriesToSpreadsheetPivotTable(dataEntries, definition) {
|
|
43009
|
+
const measureIds = definition.measures.filter((measure) => !measure.isHidden).map((m) => m.id);
|
|
42821
43010
|
const columnsTree = dataEntriesToColumnsTree(dataEntries, definition.columns, 0);
|
|
42822
|
-
computeWidthOfColumnsNodes(columnsTree,
|
|
43011
|
+
computeWidthOfColumnsNodes(columnsTree, measureIds.length);
|
|
42823
43012
|
const cols = columnsTreeToColumns(columnsTree, definition);
|
|
42824
43013
|
const rows = dataEntriesToRows(dataEntries, 0, definition.rows, [], []);
|
|
42825
43014
|
// Add the total row
|
|
@@ -42828,7 +43017,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
42828
43017
|
values: [],
|
|
42829
43018
|
indent: 0,
|
|
42830
43019
|
});
|
|
42831
|
-
const measureIds = definition.measures.filter((measure) => !measure.isHidden).map((m) => m.id);
|
|
42832
43020
|
const fieldsType = {};
|
|
42833
43021
|
for (const columns of definition.columns) {
|
|
42834
43022
|
fieldsType[columns.fieldName] = columns.type;
|
|
@@ -43589,7 +43777,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
43589
43777
|
onIterationEndEvaluation: (pivot) => pivot.markAsDirtyForEvaluation(),
|
|
43590
43778
|
dateGranularities: [...dateGranularities],
|
|
43591
43779
|
datetimeGranularities: [...dateGranularities, "hour_number", "minute_number", "second_number"],
|
|
43592
|
-
isMeasureCandidate: (field) => !["
|
|
43780
|
+
isMeasureCandidate: (field) => !["datetime", "boolean"].includes(field.type),
|
|
43593
43781
|
isGroupable: () => true,
|
|
43594
43782
|
});
|
|
43595
43783
|
|
|
@@ -46118,13 +46306,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46118
46306
|
}
|
|
46119
46307
|
}
|
|
46120
46308
|
|
|
46121
|
-
const CHECKBOX_WIDTH = 15;
|
|
46122
46309
|
const MARGIN = (GRID_ICON_EDGE_LENGTH - CHECKBOX_WIDTH) / 2;
|
|
46123
46310
|
css /* scss */ `
|
|
46124
46311
|
.o-dv-checkbox {
|
|
46125
46312
|
box-sizing: border-box !important;
|
|
46126
|
-
width: ${CHECKBOX_WIDTH}px;
|
|
46127
|
-
height: ${CHECKBOX_WIDTH}px;
|
|
46128
46313
|
accent-color: #808080;
|
|
46129
46314
|
margin: ${MARGIN}px;
|
|
46130
46315
|
/** required to prevent the checkbox position to be sensible to the font-size (affects Firefox) */
|
|
@@ -46133,13 +46318,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46133
46318
|
`;
|
|
46134
46319
|
class DataValidationCheckbox extends owl.Component {
|
|
46135
46320
|
static template = "o-spreadsheet-DataValidationCheckbox";
|
|
46321
|
+
static components = {
|
|
46322
|
+
Checkbox,
|
|
46323
|
+
};
|
|
46136
46324
|
static props = {
|
|
46137
46325
|
cellPosition: Object,
|
|
46138
46326
|
};
|
|
46139
|
-
onCheckboxChange(
|
|
46140
|
-
const newValue = ev.target.checked;
|
|
46327
|
+
onCheckboxChange(value) {
|
|
46141
46328
|
const { sheetId, col, row } = this.props.cellPosition;
|
|
46142
|
-
const cellContent =
|
|
46329
|
+
const cellContent = value ? "TRUE" : "FALSE";
|
|
46143
46330
|
this.env.model.dispatch("UPDATE_CELL", { sheetId, col, row, content: cellContent });
|
|
46144
46331
|
}
|
|
46145
46332
|
get checkBoxValue() {
|
|
@@ -46953,7 +47140,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46953
47140
|
class PaintFormatStore extends SpreadsheetStore {
|
|
46954
47141
|
mutators = ["activate", "cancel", "pasteFormat"];
|
|
46955
47142
|
highlightStore = this.get(HighlightStore);
|
|
46956
|
-
|
|
47143
|
+
clipboardHandlers = [
|
|
47144
|
+
new CellClipboardHandler(this.getters, this.model.dispatch),
|
|
47145
|
+
new BorderClipboardHandler(this.getters, this.model.dispatch),
|
|
47146
|
+
new TableClipboardHandler(this.getters, this.model.dispatch),
|
|
47147
|
+
];
|
|
46957
47148
|
status = "inactive";
|
|
46958
47149
|
copiedData;
|
|
46959
47150
|
constructor(get) {
|
|
@@ -46974,10 +47165,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46974
47165
|
pasteFormat(target) {
|
|
46975
47166
|
if (this.copiedData) {
|
|
46976
47167
|
const sheetId = this.getters.getActiveSheetId();
|
|
46977
|
-
|
|
46978
|
-
|
|
46979
|
-
|
|
46980
|
-
|
|
47168
|
+
for (const handler of this.clipboardHandlers) {
|
|
47169
|
+
handler.paste({ zones: target, sheetId }, this.copiedData, {
|
|
47170
|
+
isCutOperation: false,
|
|
47171
|
+
pasteOption: "onlyFormat",
|
|
47172
|
+
});
|
|
47173
|
+
}
|
|
46981
47174
|
}
|
|
46982
47175
|
if (this.status === "oneOff") {
|
|
46983
47176
|
this.cancel();
|
|
@@ -46989,7 +47182,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46989
47182
|
copyFormats() {
|
|
46990
47183
|
const sheetId = this.getters.getActiveSheetId();
|
|
46991
47184
|
const zones = this.getters.getSelectedZones();
|
|
46992
|
-
|
|
47185
|
+
const copiedData = {};
|
|
47186
|
+
for (const handler of this.clipboardHandlers) {
|
|
47187
|
+
Object.assign(copiedData, handler.copy(getClipboardDataPositions(sheetId, zones)));
|
|
47188
|
+
}
|
|
47189
|
+
return copiedData;
|
|
46993
47190
|
}
|
|
46994
47191
|
get highlights() {
|
|
46995
47192
|
const data = this.copiedData;
|
|
@@ -49797,12 +49994,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
49797
49994
|
*/
|
|
49798
49995
|
class CorePlugin extends BasePlugin {
|
|
49799
49996
|
getters;
|
|
49800
|
-
|
|
49801
|
-
constructor({ getters, stateObserver, range, dispatch, canDispatch, uuidGenerator, }) {
|
|
49997
|
+
constructor({ getters, stateObserver, range, dispatch, canDispatch }) {
|
|
49802
49998
|
super(stateObserver, dispatch, canDispatch);
|
|
49803
49999
|
range.addRangeProvider(this.adaptRanges.bind(this));
|
|
49804
50000
|
this.getters = getters;
|
|
49805
|
-
this.uuidGenerator = uuidGenerator;
|
|
49806
50001
|
}
|
|
49807
50002
|
// ---------------------------------------------------------------------------
|
|
49808
50003
|
// Import/Export
|
|
@@ -54300,6 +54495,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
54300
54495
|
}
|
|
54301
54496
|
}
|
|
54302
54497
|
|
|
54498
|
+
let nextTableId = 1;
|
|
54303
54499
|
class TablePlugin extends CorePlugin {
|
|
54304
54500
|
static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
|
|
54305
54501
|
tables = {};
|
|
@@ -54367,7 +54563,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
54367
54563
|
const union = this.getters.getRangesUnion(ranges);
|
|
54368
54564
|
const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, union.zone);
|
|
54369
54565
|
this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
|
|
54370
|
-
const id =
|
|
54566
|
+
const id = `${nextTableId++}`;
|
|
54371
54567
|
const config = cmd.config || DEFAULT_TABLE_CONFIG;
|
|
54372
54568
|
const newTable = cmd.tableType === "dynamic"
|
|
54373
54569
|
? this.createDynamicTable(id, union, config)
|
|
@@ -54520,7 +54716,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
54520
54716
|
filters = [];
|
|
54521
54717
|
for (const i of range(zone.left, zone.right + 1)) {
|
|
54522
54718
|
const filterZone = { ...zone, left: i, right: i };
|
|
54523
|
-
const uid =
|
|
54719
|
+
const uid = `${nextTableId++}`;
|
|
54524
54720
|
filters.push(this.createFilterFromZone(uid, tableRange.sheetId, filterZone, config));
|
|
54525
54721
|
}
|
|
54526
54722
|
}
|
|
@@ -54585,7 +54781,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
54585
54781
|
? table.filters.find((f) => f.col === i)
|
|
54586
54782
|
: undefined;
|
|
54587
54783
|
const filterZone = { ...tableZone, left: i, right: i };
|
|
54588
|
-
const filterId = oldFilter?.id ||
|
|
54784
|
+
const filterId = oldFilter?.id || `${nextTableId++}`;
|
|
54589
54785
|
filters.push(this.createFilterFromZone(filterId, tableRange.sheetId, filterZone, config));
|
|
54590
54786
|
}
|
|
54591
54787
|
}
|
|
@@ -54686,7 +54882,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
54686
54882
|
if (filters.length < zoneToDimension(tableZone).numberOfCols) {
|
|
54687
54883
|
for (let col = tableZone.left; col <= tableZone.right; col++) {
|
|
54688
54884
|
if (!filters.find((filter) => filter.col === col)) {
|
|
54689
|
-
const uid =
|
|
54885
|
+
const uid = `${nextTableId++}`;
|
|
54690
54886
|
const filterZone = { ...tableZone, left: col, right: col };
|
|
54691
54887
|
filters.push(this.createFilterFromZone(uid, sheetId, filterZone, table.config));
|
|
54692
54888
|
}
|
|
@@ -54702,7 +54898,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
54702
54898
|
import(data) {
|
|
54703
54899
|
for (const sheet of data.sheets) {
|
|
54704
54900
|
for (const tableData of sheet.tables || []) {
|
|
54705
|
-
const uuid =
|
|
54901
|
+
const uuid = `${nextTableId++}`;
|
|
54706
54902
|
const tableConfig = tableData.config || DEFAULT_TABLE_CONFIG;
|
|
54707
54903
|
const range = this.getters.getRangeFromSheetXC(sheet.id, tableData.range);
|
|
54708
54904
|
const tableType = tableData.type || "static";
|
|
@@ -59051,7 +59247,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59051
59247
|
const ranking = {};
|
|
59052
59248
|
const mainDimension = getFieldDimensionType(this, fieldNameWithGranularity);
|
|
59053
59249
|
const secondaryDimension = mainDimension === "row" ? "column" : "row";
|
|
59054
|
-
let pivotCells = this.getPivotValueCells();
|
|
59250
|
+
let pivotCells = this.getPivotValueCells(measure.id);
|
|
59055
59251
|
if (mainDimension === "column") {
|
|
59056
59252
|
// Transpose the pivot cells so we can do the same operations on the columns as on the rows
|
|
59057
59253
|
// This means that we need to transpose back the ranking at the end
|
|
@@ -59095,7 +59291,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59095
59291
|
const cellsRunningTotals = {};
|
|
59096
59292
|
const mainDimension = getFieldDimensionType(this, fieldNameWithGranularity);
|
|
59097
59293
|
const secondaryDimension = mainDimension === "row" ? "column" : "row";
|
|
59098
|
-
let pivotCells = this.getPivotValueCells();
|
|
59294
|
+
let pivotCells = this.getPivotValueCells(measure.id);
|
|
59099
59295
|
if (mainDimension === "column") {
|
|
59100
59296
|
// Transpose the pivot cells so we can do the same operations on the columns as on the rows
|
|
59101
59297
|
// This means that we need to transpose back the totals at the end
|
|
@@ -59174,10 +59370,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59174
59370
|
const comparedValueNumber = this.strictMeasureValueToNumber(comparedValue);
|
|
59175
59371
|
return comparedValueNumber;
|
|
59176
59372
|
}
|
|
59177
|
-
getPivotValueCells() {
|
|
59373
|
+
getPivotValueCells(measureId) {
|
|
59178
59374
|
return this.getTableStructure()
|
|
59179
59375
|
.getPivotCells()
|
|
59180
|
-
.map((col) => col.filter((cell) => cell.type === "VALUE"))
|
|
59376
|
+
.map((col) => col.filter((cell) => cell.type === "VALUE" && cell.measure === measureId))
|
|
59181
59377
|
.filter((col) => col.length > 0);
|
|
59182
59378
|
}
|
|
59183
59379
|
measureValueToNumber(result) {
|
|
@@ -60945,6 +61141,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60945
61141
|
case "REMOTE_REVISION":
|
|
60946
61142
|
case "REVISION_REDONE":
|
|
60947
61143
|
case "REVISION_UNDONE":
|
|
61144
|
+
case "SNAPSHOT_CREATED":
|
|
60948
61145
|
return this.processedRevisions.has(message.nextRevisionId);
|
|
60949
61146
|
default:
|
|
60950
61147
|
return false;
|
|
@@ -61507,7 +61704,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61507
61704
|
const position = this.getters.getSheetIds().indexOf(activeSheetId) + 1;
|
|
61508
61705
|
const formulaId = this.getters.getPivotFormulaId(newPivotId);
|
|
61509
61706
|
const newPivotName = this.getters.getPivotName(newPivotId);
|
|
61510
|
-
this.dispatch("CREATE_SHEET", {
|
|
61707
|
+
const result = this.dispatch("CREATE_SHEET", {
|
|
61511
61708
|
sheetId: newSheetId,
|
|
61512
61709
|
name: this.getPivotDuplicateSheetName(_t("%(newPivotName)s (Pivot #%(formulaId)s)", {
|
|
61513
61710
|
newPivotName,
|
|
@@ -61515,20 +61712,19 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61515
61712
|
})),
|
|
61516
61713
|
position,
|
|
61517
61714
|
});
|
|
61518
|
-
|
|
61519
|
-
|
|
61520
|
-
|
|
61521
|
-
|
|
61522
|
-
|
|
61523
|
-
content: `=PIVOT(${formulaId})`,
|
|
61524
|
-
});
|
|
61715
|
+
if (result.isSuccessful) {
|
|
61716
|
+
this.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: newSheetId });
|
|
61717
|
+
const pivot = this.getters.getPivot(pivotId);
|
|
61718
|
+
this.insertPivotWithTable(newSheetId, 0, 0, newPivotId, pivot.getTableStructure().export(), "dynamic");
|
|
61719
|
+
}
|
|
61525
61720
|
}
|
|
61526
61721
|
getPivotDuplicateSheetName(pivotName) {
|
|
61527
61722
|
let i = 1;
|
|
61528
61723
|
const names = this.getters.getSheetIds().map((id) => this.getters.getSheetName(id));
|
|
61529
|
-
|
|
61724
|
+
const sanitizedName = pivotName.replace(new RegExp(FORBIDDEN_IN_EXCEL_REGEX, "g"), " ");
|
|
61725
|
+
let name = sanitizedName;
|
|
61530
61726
|
while (names.includes(name)) {
|
|
61531
|
-
name = `${
|
|
61727
|
+
name = `${sanitizedName} (${i})`;
|
|
61532
61728
|
i++;
|
|
61533
61729
|
}
|
|
61534
61730
|
return name;
|
|
@@ -70881,6 +71077,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
70881
71077
|
["id", i + 1], // id cannot be 0
|
|
70882
71078
|
["name", colName],
|
|
70883
71079
|
];
|
|
71080
|
+
if (table.config.totalRow) {
|
|
71081
|
+
// Note: To be 100% complete, we could also add a `totalsRowLabel` attribute for total strings, and a tag
|
|
71082
|
+
// `<totalsRowFormula>` for the formula of the total. But those doesn't seem to be mandatory for Excel.
|
|
71083
|
+
const colTotalXc = toXC(tableZone.left + i, tableZone.bottom);
|
|
71084
|
+
const colTotalContent = sheetData.cells[colTotalXc]?.content;
|
|
71085
|
+
if (colTotalContent?.startsWith("=")) {
|
|
71086
|
+
colAttributes.push(["totalsRowFunction", "custom"]);
|
|
71087
|
+
}
|
|
71088
|
+
}
|
|
70884
71089
|
columns.push(escapeXml /*xml*/ `<tableColumn ${formatAttributes(colAttributes)}/>`);
|
|
70885
71090
|
}
|
|
70886
71091
|
return escapeXml /*xml*/ `
|
|
@@ -70975,8 +71180,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
70975
71180
|
}
|
|
70976
71181
|
else if (cell.content && cell.content !== "") {
|
|
70977
71182
|
const isTableHeader = isCellTableHeader(c, r, sheet);
|
|
71183
|
+
const isTableTotal = isCellTableTotal(c, r, sheet);
|
|
70978
71184
|
const isPlainText = !!(cell.format && isTextFormat(data.formats[cell.format]));
|
|
70979
|
-
({ attrs: additionalAttrs, node: cellNode } = addContent(cell.content, construct.sharedStrings, isTableHeader || isPlainText));
|
|
71185
|
+
({ attrs: additionalAttrs, node: cellNode } = addContent(cell.content, construct.sharedStrings, isTableHeader || isTableTotal || isPlainText));
|
|
70980
71186
|
}
|
|
70981
71187
|
attributes.push(...additionalAttrs);
|
|
70982
71188
|
// prettier-ignore
|
|
@@ -71010,6 +71216,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71010
71216
|
return isInside(col, row, headerZone);
|
|
71011
71217
|
});
|
|
71012
71218
|
}
|
|
71219
|
+
function isCellTableTotal(col, row, sheet) {
|
|
71220
|
+
return sheet.tables.some((table) => {
|
|
71221
|
+
if (!table.config.totalRow) {
|
|
71222
|
+
return false;
|
|
71223
|
+
}
|
|
71224
|
+
const zone = toZone(table.range);
|
|
71225
|
+
const totalZone = { ...zone, top: zone.bottom };
|
|
71226
|
+
return isInside(col, row, totalZone);
|
|
71227
|
+
});
|
|
71228
|
+
}
|
|
71013
71229
|
function addHyperlinks(construct, data, sheetIndex) {
|
|
71014
71230
|
const sheet = data.sheets[sheetIndex];
|
|
71015
71231
|
const cells = sheet.cells;
|
|
@@ -71500,7 +71716,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71500
71716
|
isReadonly: () => this.config.mode === "readonly" || this.config.mode === "dashboard",
|
|
71501
71717
|
isDashboard: () => this.config.mode === "dashboard",
|
|
71502
71718
|
};
|
|
71503
|
-
this.uuidGenerator.setIsFastStrategy(true);
|
|
71504
71719
|
// Initiate stream processor
|
|
71505
71720
|
this.selection = new SelectionStreamProcessorImpl(this.getters);
|
|
71506
71721
|
this.coreHandlers.push(this.range);
|
|
@@ -71532,7 +71747,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71532
71747
|
this.handlers.push(plugin);
|
|
71533
71748
|
this.uiHandlers.push(plugin);
|
|
71534
71749
|
}
|
|
71535
|
-
this.uuidGenerator.setIsFastStrategy(false);
|
|
71536
71750
|
// starting plugins
|
|
71537
71751
|
this.dispatch("START");
|
|
71538
71752
|
// Model should be the last permanent subscriber in the list since he should render
|
|
@@ -71680,7 +71894,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71680
71894
|
range: this.range,
|
|
71681
71895
|
dispatch: this.dispatchFromCorePlugin,
|
|
71682
71896
|
canDispatch: this.canDispatch,
|
|
71683
|
-
uuidGenerator: this.uuidGenerator,
|
|
71684
71897
|
custom: this.config.custom,
|
|
71685
71898
|
external: this.config.external,
|
|
71686
71899
|
};
|
|
@@ -72174,9 +72387,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
72174
72387
|
exports.tokenize = tokenize;
|
|
72175
72388
|
|
|
72176
72389
|
|
|
72177
|
-
__info__.version = "18.1.0-alpha.
|
|
72178
|
-
__info__.date = "2024-
|
|
72179
|
-
__info__.hash = "
|
|
72390
|
+
__info__.version = "18.1.0-alpha.1";
|
|
72391
|
+
__info__.date = "2024-10-14T07:53:17.717Z";
|
|
72392
|
+
__info__.hash = "e9ce3aa";
|
|
72180
72393
|
|
|
72181
72394
|
|
|
72182
72395
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|