@odoo/o-spreadsheet 18.1.7 → 18.1.9
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 +499 -284
- package/dist/o-spreadsheet.d.ts +51 -46
- package/dist/o-spreadsheet.esm.js +499 -284
- package/dist/o-spreadsheet.iife.js +499 -284
- package/dist/o-spreadsheet.iife.min.js +358 -354
- package/dist/o_spreadsheet.xml +17 -14
- package/package.json +4 -2
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 18.1.
|
|
6
|
-
* @date 2025-02-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.1.9
|
|
6
|
+
* @date 2025-02-25T05:59:45.472Z
|
|
7
|
+
* @hash 6789c1c
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -2220,17 +2220,7 @@ function toZoneWithoutBoundaryChanges(xc) {
|
|
|
2220
2220
|
*/
|
|
2221
2221
|
function toUnboundedZone(xc) {
|
|
2222
2222
|
const zone = toZoneWithoutBoundaryChanges(xc);
|
|
2223
|
-
|
|
2224
|
-
const tmp = zone.left;
|
|
2225
|
-
zone.left = zone.right;
|
|
2226
|
-
zone.right = tmp;
|
|
2227
|
-
}
|
|
2228
|
-
if (zone.bottom !== undefined && zone.bottom < zone.top) {
|
|
2229
|
-
const tmp = zone.top;
|
|
2230
|
-
zone.top = zone.bottom;
|
|
2231
|
-
zone.bottom = tmp;
|
|
2232
|
-
}
|
|
2233
|
-
return zone;
|
|
2223
|
+
return reorderZone(zone);
|
|
2234
2224
|
}
|
|
2235
2225
|
/**
|
|
2236
2226
|
* Convert from a cartesian reference to a Zone.
|
|
@@ -2504,11 +2494,11 @@ function positions(zone) {
|
|
|
2504
2494
|
return positions;
|
|
2505
2495
|
}
|
|
2506
2496
|
function reorderZone(zone) {
|
|
2507
|
-
if (zone.left > zone.right) {
|
|
2508
|
-
zone = { left: zone.right, right: zone.left
|
|
2497
|
+
if (zone.right !== undefined && zone.left > zone.right) {
|
|
2498
|
+
zone = { ...zone, left: zone.right, right: zone.left };
|
|
2509
2499
|
}
|
|
2510
|
-
if (zone.top > zone.bottom) {
|
|
2511
|
-
zone = {
|
|
2500
|
+
if (zone.bottom !== undefined && zone.top > zone.bottom) {
|
|
2501
|
+
zone = { ...zone, top: zone.bottom, bottom: zone.top };
|
|
2512
2502
|
}
|
|
2513
2503
|
return zone;
|
|
2514
2504
|
}
|
|
@@ -3413,12 +3403,12 @@ function isTargetDependent(cmd) {
|
|
|
3413
3403
|
function isRangeDependant(cmd) {
|
|
3414
3404
|
return "ranges" in cmd;
|
|
3415
3405
|
}
|
|
3416
|
-
function isZoneDependent(cmd) {
|
|
3417
|
-
return "zone" in cmd;
|
|
3418
|
-
}
|
|
3419
3406
|
function isPositionDependent(cmd) {
|
|
3420
3407
|
return "col" in cmd && "row" in cmd && "sheetId" in cmd;
|
|
3421
3408
|
}
|
|
3409
|
+
function isZoneDependent(cmd) {
|
|
3410
|
+
return "sheetId" in cmd && "zone" in cmd;
|
|
3411
|
+
}
|
|
3422
3412
|
const invalidateEvaluationCommands = new Set([
|
|
3423
3413
|
"RENAME_SHEET",
|
|
3424
3414
|
"DELETE_SHEET",
|
|
@@ -3430,6 +3420,7 @@ const invalidateEvaluationCommands = new Set([
|
|
|
3430
3420
|
"REDO",
|
|
3431
3421
|
"ADD_MERGE",
|
|
3432
3422
|
"REMOVE_MERGE",
|
|
3423
|
+
"DUPLICATE_SHEET",
|
|
3433
3424
|
"UPDATE_LOCALE",
|
|
3434
3425
|
"ADD_PIVOT",
|
|
3435
3426
|
"UPDATE_PIVOT",
|
|
@@ -3459,7 +3450,6 @@ const invalidateChartEvaluationCommands = new Set([
|
|
|
3459
3450
|
]);
|
|
3460
3451
|
const invalidateDependenciesCommands = new Set(["MOVE_RANGES"]);
|
|
3461
3452
|
const invalidateCFEvaluationCommands = new Set([
|
|
3462
|
-
"DUPLICATE_SHEET",
|
|
3463
3453
|
"EVALUATE_CELLS",
|
|
3464
3454
|
"ADD_CONDITIONAL_FORMAT",
|
|
3465
3455
|
"REMOVE_CONDITIONAL_FORMAT",
|
|
@@ -3629,6 +3619,7 @@ exports.CommandResult = void 0;
|
|
|
3629
3619
|
CommandResult["InvalidRange"] = "InvalidRange";
|
|
3630
3620
|
CommandResult["InvalidZones"] = "InvalidZones";
|
|
3631
3621
|
CommandResult["InvalidSheetId"] = "InvalidSheetId";
|
|
3622
|
+
CommandResult["InvalidCellId"] = "InvalidCellId";
|
|
3632
3623
|
CommandResult["InvalidFigureId"] = "InvalidFigureId";
|
|
3633
3624
|
CommandResult["InputAlreadyFocused"] = "InputAlreadyFocused";
|
|
3634
3625
|
CommandResult["MaximumRangesReached"] = "MaximumRangesReached";
|
|
@@ -4460,7 +4451,7 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
|
|
|
4460
4451
|
* @param reverseSearch if true, search in the array starting from the end.
|
|
4461
4452
|
|
|
4462
4453
|
*/
|
|
4463
|
-
function linearSearch(data, target, mode, numberOfValues, getValueInData, reverseSearch = false) {
|
|
4454
|
+
function linearSearch(data, target, mode, numberOfValues, getValueInData, lookupCaches, reverseSearch = false) {
|
|
4464
4455
|
if (target === undefined || target.value === null) {
|
|
4465
4456
|
return -1;
|
|
4466
4457
|
}
|
|
@@ -4469,17 +4460,48 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
|
|
|
4469
4460
|
}
|
|
4470
4461
|
const _target = normalizeValue(target.value);
|
|
4471
4462
|
const getValue = reverseSearch
|
|
4472
|
-
? (data, i) => getValueInData(data, numberOfValues - i - 1)
|
|
4473
|
-
: getValueInData;
|
|
4463
|
+
? (data, i) => normalizeValue(getValueInData(data, numberOfValues - i - 1))
|
|
4464
|
+
: (data, i) => normalizeValue(getValueInData(data, i));
|
|
4465
|
+
// first check if the target is in the cache
|
|
4466
|
+
const isNotWildcardTarget = mode !== "wildcard" ||
|
|
4467
|
+
typeof _target !== "string" ||
|
|
4468
|
+
!(_target.includes("*") || _target.includes("?"));
|
|
4469
|
+
if (lookupCaches && isNotWildcardTarget) {
|
|
4470
|
+
const searchMode = reverseSearch ? "reverseSearch" : "forwardSearch";
|
|
4471
|
+
let cache = lookupCaches[searchMode].get(data);
|
|
4472
|
+
if (cache === undefined) {
|
|
4473
|
+
// build the cache for all the values
|
|
4474
|
+
cache = new Map();
|
|
4475
|
+
for (let i = 0; i < numberOfValues; i++) {
|
|
4476
|
+
const value = getValue(data, i) ?? null;
|
|
4477
|
+
if (!cache.has(value)) {
|
|
4478
|
+
cache.set(value, i);
|
|
4479
|
+
}
|
|
4480
|
+
}
|
|
4481
|
+
lookupCaches[searchMode].set(data, cache);
|
|
4482
|
+
}
|
|
4483
|
+
if (cache.has(_target)) {
|
|
4484
|
+
const resultIndex = cache.get(_target);
|
|
4485
|
+
return reverseSearch ? numberOfValues - resultIndex - 1 : resultIndex;
|
|
4486
|
+
}
|
|
4487
|
+
if (mode === "strict") {
|
|
4488
|
+
return -1;
|
|
4489
|
+
}
|
|
4490
|
+
}
|
|
4491
|
+
// else perform the linear search
|
|
4492
|
+
const resultIndex = _linearSearch(data, _target, mode, numberOfValues, getValue);
|
|
4493
|
+
return reverseSearch && resultIndex !== -1 ? numberOfValues - resultIndex - 1 : resultIndex;
|
|
4494
|
+
}
|
|
4495
|
+
function _linearSearch(data, _target, mode, numberOfValues, getNormalizeValue) {
|
|
4474
4496
|
let indexMatchTarget = (i) => {
|
|
4475
|
-
return
|
|
4497
|
+
return getNormalizeValue(data, i) === _target;
|
|
4476
4498
|
};
|
|
4477
4499
|
if (mode === "wildcard" &&
|
|
4478
4500
|
typeof _target === "string" &&
|
|
4479
4501
|
(_target.includes("*") || _target.includes("?"))) {
|
|
4480
4502
|
const regExp = wildcardToRegExp(_target);
|
|
4481
4503
|
indexMatchTarget = (i) => {
|
|
4482
|
-
const value =
|
|
4504
|
+
const value = getNormalizeValue(data, i);
|
|
4483
4505
|
if (typeof value === "string") {
|
|
4484
4506
|
return regExp.test(value);
|
|
4485
4507
|
}
|
|
@@ -4490,7 +4512,7 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
|
|
|
4490
4512
|
let closestMatchIndex = -1;
|
|
4491
4513
|
if (mode === "nextSmaller") {
|
|
4492
4514
|
indexMatchTarget = (i) => {
|
|
4493
|
-
const value =
|
|
4515
|
+
const value = getNormalizeValue(data, i);
|
|
4494
4516
|
if ((!closestMatch && compareCellValues(_target, value) >= 0) ||
|
|
4495
4517
|
(compareCellValues(_target, value) >= 0 && compareCellValues(value, closestMatch) > 0)) {
|
|
4496
4518
|
closestMatch = value;
|
|
@@ -4501,7 +4523,7 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
|
|
|
4501
4523
|
}
|
|
4502
4524
|
if (mode === "nextGreater") {
|
|
4503
4525
|
indexMatchTarget = (i) => {
|
|
4504
|
-
const value =
|
|
4526
|
+
const value = getNormalizeValue(data, i);
|
|
4505
4527
|
if ((!closestMatch && compareCellValues(_target, value) <= 0) ||
|
|
4506
4528
|
(compareCellValues(_target, value) <= 0 && compareCellValues(value, closestMatch) < 0)) {
|
|
4507
4529
|
closestMatch = value;
|
|
@@ -4512,12 +4534,10 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
|
|
|
4512
4534
|
}
|
|
4513
4535
|
for (let i = 0; i < numberOfValues; i++) {
|
|
4514
4536
|
if (indexMatchTarget(i)) {
|
|
4515
|
-
return
|
|
4537
|
+
return i;
|
|
4516
4538
|
}
|
|
4517
4539
|
}
|
|
4518
|
-
return
|
|
4519
|
-
? numberOfValues - closestMatchIndex - 1
|
|
4520
|
-
: closestMatchIndex;
|
|
4540
|
+
return closestMatchIndex;
|
|
4521
4541
|
}
|
|
4522
4542
|
/**
|
|
4523
4543
|
* Normalize a value.
|
|
@@ -6481,11 +6501,40 @@ function drawDecoratedText(context, text, position, underline = false, strikethr
|
|
|
6481
6501
|
* https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
|
|
6482
6502
|
* */
|
|
6483
6503
|
class UuidGenerator {
|
|
6504
|
+
/**
|
|
6505
|
+
* Generates a custom UUID using a simple 36^12 method (8-character alphanumeric string with lowercase letters)
|
|
6506
|
+
* This has a higher chance of collision than a UUIDv4, but not only faster to generate than an UUIDV4,
|
|
6507
|
+
* it also has a smaller size, which is preferable to alleviate the overall data size.
|
|
6508
|
+
*
|
|
6509
|
+
* This method is preferable when generating uuids for the core data (sheetId, figureId, etc)
|
|
6510
|
+
* as they will appear several times in the revisions and local history.
|
|
6511
|
+
*
|
|
6512
|
+
*/
|
|
6513
|
+
smallUuid() {
|
|
6514
|
+
if (window.crypto) {
|
|
6515
|
+
return "10000000-1000".replace(/[01]/g, (c) => {
|
|
6516
|
+
const n = Number(c);
|
|
6517
|
+
return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
|
|
6518
|
+
});
|
|
6519
|
+
}
|
|
6520
|
+
else {
|
|
6521
|
+
// mainly for jest and other browsers that do not have the crypto functionality
|
|
6522
|
+
return "xxxxxxxx-xxxx".replace(/[xy]/g, function (c) {
|
|
6523
|
+
const r = (Math.random() * 16) | 0, v = c == "x" ? r : (r & 0x3) | 0x8;
|
|
6524
|
+
return v.toString(16);
|
|
6525
|
+
});
|
|
6526
|
+
}
|
|
6527
|
+
}
|
|
6528
|
+
/**
|
|
6529
|
+
* Generates an UUIDV4, has astronomically low chance of collision, but is larger in size than the smallUuid.
|
|
6530
|
+
* This method should be used when you need to avoid collisions at all costs, like the id of a revision.
|
|
6531
|
+
*/
|
|
6484
6532
|
uuidv4() {
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
6533
|
+
if (window.crypto) {
|
|
6534
|
+
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => {
|
|
6535
|
+
const n = Number(c);
|
|
6536
|
+
return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
|
|
6537
|
+
});
|
|
6489
6538
|
}
|
|
6490
6539
|
else {
|
|
6491
6540
|
// mainly for jest and other browsers that do not have the crypto functionality
|
|
@@ -8515,7 +8564,7 @@ class ChartClipboardHandler extends AbstractFigureClipboardHandler {
|
|
|
8515
8564
|
};
|
|
8516
8565
|
}
|
|
8517
8566
|
getPasteTarget(sheetId, target, content, options) {
|
|
8518
|
-
const newId = new UuidGenerator().
|
|
8567
|
+
const newId = new UuidGenerator().smallUuid();
|
|
8519
8568
|
return { zones: [], figureId: newId, sheetId };
|
|
8520
8569
|
}
|
|
8521
8570
|
paste(target, clippedContent, options) {
|
|
@@ -8681,7 +8730,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8681
8730
|
if (!targetCF && queuedCfs) {
|
|
8682
8731
|
targetCF = queuedCfs.find((queued) => queued.cf.stopIfTrue === originCF.stopIfTrue && deepEquals(queued.cf.rule, originCF.rule))?.cf;
|
|
8683
8732
|
}
|
|
8684
|
-
return targetCF || { ...originCF, id: this.uuidGenerator.
|
|
8733
|
+
return targetCF || { ...originCF, id: this.uuidGenerator.smallUuid(), ranges: [] };
|
|
8685
8734
|
}
|
|
8686
8735
|
}
|
|
8687
8736
|
|
|
@@ -8774,7 +8823,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8774
8823
|
}
|
|
8775
8824
|
return (targetRule || {
|
|
8776
8825
|
...originRule,
|
|
8777
|
-
id: newId ? this.uuidGenerator.
|
|
8826
|
+
id: newId ? this.uuidGenerator.smallUuid() : originRule.id,
|
|
8778
8827
|
ranges: [],
|
|
8779
8828
|
});
|
|
8780
8829
|
}
|
|
@@ -8836,7 +8885,7 @@ class ImageClipboardHandler extends AbstractFigureClipboardHandler {
|
|
|
8836
8885
|
};
|
|
8837
8886
|
}
|
|
8838
8887
|
getPasteTarget(sheetId, target, content, options) {
|
|
8839
|
-
const newId = new UuidGenerator().
|
|
8888
|
+
const newId = new UuidGenerator().smallUuid();
|
|
8840
8889
|
return { sheetId, zones: [], figureId: newId };
|
|
8841
8890
|
}
|
|
8842
8891
|
paste(target, clippedContent, options) {
|
|
@@ -12038,6 +12087,25 @@ const LN = {
|
|
|
12038
12087
|
isExported: true,
|
|
12039
12088
|
};
|
|
12040
12089
|
// -----------------------------------------------------------------------------
|
|
12090
|
+
// LOG
|
|
12091
|
+
// -----------------------------------------------------------------------------
|
|
12092
|
+
const LOG = {
|
|
12093
|
+
description: _t("The logarithm of a number, for a given base."),
|
|
12094
|
+
args: [
|
|
12095
|
+
arg("value (number)", _t("The value for which to calculate the logarithm.")),
|
|
12096
|
+
arg("base (number, default=10)", _t("The base of the logarithm.")),
|
|
12097
|
+
],
|
|
12098
|
+
compute: function (value, base = { value: 10 }) {
|
|
12099
|
+
const _value = toNumber(value, this.locale);
|
|
12100
|
+
const _base = toNumber(base, this.locale);
|
|
12101
|
+
assert(() => _value > 0, _t("The value (%s) must be strictly positive.", _value.toString()));
|
|
12102
|
+
assert(() => _base > 0, _t("The base (%s) must be strictly positive.", _base.toString()));
|
|
12103
|
+
assert(() => _base !== 1, _t("The base must be different from 1."));
|
|
12104
|
+
return Math.log10(_value) / Math.log10(_base);
|
|
12105
|
+
},
|
|
12106
|
+
isExported: true,
|
|
12107
|
+
};
|
|
12108
|
+
// -----------------------------------------------------------------------------
|
|
12041
12109
|
// MOD
|
|
12042
12110
|
// -----------------------------------------------------------------------------
|
|
12043
12111
|
function mod(dividend, divisor) {
|
|
@@ -12577,6 +12645,7 @@ var math = /*#__PURE__*/Object.freeze({
|
|
|
12577
12645
|
ISODD: ISODD,
|
|
12578
12646
|
ISO_CEILING: ISO_CEILING,
|
|
12579
12647
|
LN: LN,
|
|
12648
|
+
LOG: LOG,
|
|
12580
12649
|
MOD: MOD,
|
|
12581
12650
|
MUNIT: MUNIT,
|
|
12582
12651
|
ODD: ODD,
|
|
@@ -15111,7 +15180,7 @@ const SORTN = {
|
|
|
15111
15180
|
}
|
|
15112
15181
|
}
|
|
15113
15182
|
},
|
|
15114
|
-
isExported:
|
|
15183
|
+
isExported: false,
|
|
15115
15184
|
};
|
|
15116
15185
|
// -----------------------------------------------------------------------------
|
|
15117
15186
|
// UNIQUE
|
|
@@ -18475,7 +18544,7 @@ const HLOOKUP = {
|
|
|
18475
18544
|
const _isSorted = toBoolean(isSorted.value);
|
|
18476
18545
|
const colIndex = _isSorted
|
|
18477
18546
|
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
|
|
18478
|
-
: linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
|
|
18547
|
+
: linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange, this.lookupCaches);
|
|
18479
18548
|
const col = _range[colIndex];
|
|
18480
18549
|
if (col === undefined) {
|
|
18481
18550
|
return valueNotAvailable(searchKey);
|
|
@@ -18630,7 +18699,7 @@ const MATCH = {
|
|
|
18630
18699
|
index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
|
|
18631
18700
|
break;
|
|
18632
18701
|
case 0:
|
|
18633
|
-
index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
|
|
18702
|
+
index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement, this.lookupCaches);
|
|
18634
18703
|
break;
|
|
18635
18704
|
case -1:
|
|
18636
18705
|
index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
|
|
@@ -18698,7 +18767,7 @@ const VLOOKUP = {
|
|
|
18698
18767
|
const _isSorted = toBoolean(isSorted.value);
|
|
18699
18768
|
const rowIndex = _isSorted
|
|
18700
18769
|
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
|
|
18701
|
-
: linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
|
|
18770
|
+
: linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange, this.lookupCaches);
|
|
18702
18771
|
const value = _range[_index - 1][rowIndex];
|
|
18703
18772
|
if (value === undefined) {
|
|
18704
18773
|
return valueNotAvailable(searchKey);
|
|
@@ -18754,7 +18823,7 @@ const XLOOKUP = {
|
|
|
18754
18823
|
const reverseSearch = _searchMode === -1;
|
|
18755
18824
|
const index = _searchMode === 2 || _searchMode === -2
|
|
18756
18825
|
? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
|
|
18757
|
-
: linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
|
|
18826
|
+
: linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, this.lookupCaches, reverseSearch);
|
|
18758
18827
|
if (index !== -1) {
|
|
18759
18828
|
return lookupDirection === "col"
|
|
18760
18829
|
? _returnRange.map((col) => [col[index]])
|
|
@@ -27624,7 +27693,7 @@ function forceUnicityOfFigure(data) {
|
|
|
27624
27693
|
for (const sheet of data.sheets || []) {
|
|
27625
27694
|
for (const figure of sheet.figures || []) {
|
|
27626
27695
|
if (figureIds.has(figure.id)) {
|
|
27627
|
-
figure.id += uuidGenerator.
|
|
27696
|
+
figure.id += uuidGenerator.smallUuid();
|
|
27628
27697
|
}
|
|
27629
27698
|
figureIds.add(figure.id);
|
|
27630
27699
|
}
|
|
@@ -28209,9 +28278,7 @@ function getBarChartData(definition, dataSets, labelRange, getters) {
|
|
|
28209
28278
|
const labelValues = getChartLabelValues(getters, dataSets, labelRange);
|
|
28210
28279
|
let labels = labelValues.formattedValues;
|
|
28211
28280
|
let dataSetsValues = getChartDatasetValues(getters, dataSets);
|
|
28212
|
-
if (definition.dataSetsHaveTitle
|
|
28213
|
-
dataSetsValues[0] &&
|
|
28214
|
-
labels.length > dataSetsValues[0].data.length) {
|
|
28281
|
+
if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
|
|
28215
28282
|
labels.shift();
|
|
28216
28283
|
}
|
|
28217
28284
|
({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
|
|
@@ -28244,7 +28311,7 @@ function getBarChartData(definition, dataSets, labelRange, getters) {
|
|
|
28244
28311
|
}
|
|
28245
28312
|
function getPyramidChartData(definition, dataSets, labelRange, getters) {
|
|
28246
28313
|
const barChartData = getBarChartData(definition, dataSets, labelRange, getters);
|
|
28247
|
-
const barDataset = barChartData.dataSetsValues;
|
|
28314
|
+
const barDataset = barChartData.dataSetsValues.filter((ds) => !ds.hidden);
|
|
28248
28315
|
const pyramidDatasetValues = [];
|
|
28249
28316
|
if (barDataset[0]) {
|
|
28250
28317
|
const pyramidData = barDataset[0].data.map((value) => (value > 0 ? value : 0));
|
|
@@ -28260,13 +28327,12 @@ function getPyramidChartData(definition, dataSets, labelRange, getters) {
|
|
|
28260
28327
|
};
|
|
28261
28328
|
}
|
|
28262
28329
|
function getLineChartData(definition, dataSets, labelRange, getters) {
|
|
28263
|
-
const axisType = getChartAxisType(definition, labelRange, getters);
|
|
28330
|
+
const axisType = getChartAxisType(definition, dataSets, labelRange, getters);
|
|
28264
28331
|
const labelValues = getChartLabelValues(getters, dataSets, labelRange);
|
|
28265
28332
|
let labels = axisType === "linear" ? labelValues.values : labelValues.formattedValues;
|
|
28266
28333
|
let dataSetsValues = getChartDatasetValues(getters, dataSets);
|
|
28267
|
-
|
|
28268
|
-
|
|
28269
|
-
labels.length > dataSetsValues[0].data.length) {
|
|
28334
|
+
const removeFirstLabel = shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false);
|
|
28335
|
+
if (removeFirstLabel) {
|
|
28270
28336
|
labels.shift();
|
|
28271
28337
|
}
|
|
28272
28338
|
({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
|
|
@@ -28278,7 +28344,7 @@ function getLineChartData(definition, dataSets, labelRange, getters) {
|
|
|
28278
28344
|
}
|
|
28279
28345
|
const leftAxisFormat = getChartDatasetFormat(getters, dataSets, "left");
|
|
28280
28346
|
const rightAxisFormat = getChartDatasetFormat(getters, dataSets, "right");
|
|
28281
|
-
const labelsFormat = getChartLabelFormat(getters, labelRange);
|
|
28347
|
+
const labelsFormat = getChartLabelFormat(getters, labelRange, removeFirstLabel);
|
|
28282
28348
|
const axisFormats = { y: leftAxisFormat, y1: rightAxisFormat, x: labelsFormat };
|
|
28283
28349
|
const trendDataSetsValues = [];
|
|
28284
28350
|
for (const index in dataSetsValues) {
|
|
@@ -28314,9 +28380,7 @@ function getPieChartData(definition, dataSets, labelRange, getters) {
|
|
|
28314
28380
|
const labelValues = getChartLabelValues(getters, dataSets, labelRange);
|
|
28315
28381
|
let labels = labelValues.formattedValues;
|
|
28316
28382
|
let dataSetsValues = getChartDatasetValues(getters, dataSets);
|
|
28317
|
-
if (definition.dataSetsHaveTitle
|
|
28318
|
-
dataSetsValues[0] &&
|
|
28319
|
-
labels.length > dataSetsValues[0].data.length) {
|
|
28383
|
+
if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
|
|
28320
28384
|
labels.shift();
|
|
28321
28385
|
}
|
|
28322
28386
|
({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
|
|
@@ -28336,9 +28400,7 @@ function getRadarChartData(definition, dataSets, labelRange, getters) {
|
|
|
28336
28400
|
const labelValues = getChartLabelValues(getters, dataSets, labelRange);
|
|
28337
28401
|
let labels = labelValues.formattedValues;
|
|
28338
28402
|
let dataSetsValues = getChartDatasetValues(getters, dataSets);
|
|
28339
|
-
if (definition.dataSetsHaveTitle
|
|
28340
|
-
dataSetsValues[0] &&
|
|
28341
|
-
labels.length > dataSetsValues[0].data.length) {
|
|
28403
|
+
if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
|
|
28342
28404
|
labels.shift();
|
|
28343
28405
|
}
|
|
28344
28406
|
({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
|
|
@@ -28358,7 +28420,7 @@ function getRadarChartData(definition, dataSets, labelRange, getters) {
|
|
|
28358
28420
|
function getGeoChartData(definition, dataSets, labelRange, getters) {
|
|
28359
28421
|
const labelValues = getChartLabelValues(getters, dataSets, labelRange);
|
|
28360
28422
|
let labels = labelValues.formattedValues;
|
|
28361
|
-
if (definition.dataSetsHaveTitle) {
|
|
28423
|
+
if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
|
|
28362
28424
|
labels.shift();
|
|
28363
28425
|
}
|
|
28364
28426
|
let dataSetsValues = getChartDatasetValues(getters, dataSets);
|
|
@@ -28519,36 +28581,41 @@ function normalizeLabels(labels, newLabels, config) {
|
|
|
28519
28581
|
}
|
|
28520
28582
|
return { normalizedLabels, normalizedNewLabels };
|
|
28521
28583
|
}
|
|
28522
|
-
function getChartAxisType(
|
|
28523
|
-
if (isDateChart(
|
|
28584
|
+
function getChartAxisType(definition, dataSets, labelRange, getters) {
|
|
28585
|
+
if (isDateChart(definition, dataSets, labelRange, getters) && isLuxonTimeAdapterInstalled()) {
|
|
28524
28586
|
return "time";
|
|
28525
28587
|
}
|
|
28526
|
-
if (isLinearChart(
|
|
28588
|
+
if (isLinearChart(definition, dataSets, labelRange, getters)) {
|
|
28527
28589
|
return "linear";
|
|
28528
28590
|
}
|
|
28529
28591
|
return "category";
|
|
28530
28592
|
}
|
|
28531
|
-
function isDateChart(definition, labelRange, getters) {
|
|
28532
|
-
return !definition.labelsAsText && canBeDateChart(labelRange, getters);
|
|
28593
|
+
function isDateChart(definition, dataSets, labelRange, getters) {
|
|
28594
|
+
return !definition.labelsAsText && canBeDateChart(definition, dataSets, labelRange, getters);
|
|
28533
28595
|
}
|
|
28534
|
-
function isLinearChart(definition, labelRange, getters) {
|
|
28535
|
-
return !definition.labelsAsText && canBeLinearChart(labelRange, getters);
|
|
28596
|
+
function isLinearChart(definition, dataSets, labelRange, getters) {
|
|
28597
|
+
return !definition.labelsAsText && canBeLinearChart(definition, dataSets, labelRange, getters);
|
|
28536
28598
|
}
|
|
28537
|
-
function canChartParseLabels(labelRange, getters) {
|
|
28538
|
-
return canBeDateChart(
|
|
28599
|
+
function canChartParseLabels(definition, dataSets, labelRange, getters) {
|
|
28600
|
+
return (canBeDateChart(definition, dataSets, labelRange, getters) ||
|
|
28601
|
+
canBeLinearChart(definition, dataSets, labelRange, getters));
|
|
28539
28602
|
}
|
|
28540
|
-
function canBeDateChart(labelRange, getters) {
|
|
28541
|
-
if (!labelRange || !canBeLinearChart(labelRange, getters)) {
|
|
28603
|
+
function canBeDateChart(definition, dataSets, labelRange, getters) {
|
|
28604
|
+
if (!labelRange || !canBeLinearChart(definition, dataSets, labelRange, getters)) {
|
|
28542
28605
|
return false;
|
|
28543
28606
|
}
|
|
28544
|
-
const
|
|
28607
|
+
const removeFirstLabel = shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false);
|
|
28608
|
+
const labelFormat = getChartLabelFormat(getters, labelRange, removeFirstLabel);
|
|
28545
28609
|
return Boolean(labelFormat && timeFormatLuxonCompatible.test(labelFormat));
|
|
28546
28610
|
}
|
|
28547
|
-
function canBeLinearChart(labelRange, getters) {
|
|
28611
|
+
function canBeLinearChart(definition, dataSets, labelRange, getters) {
|
|
28548
28612
|
if (!labelRange) {
|
|
28549
28613
|
return false;
|
|
28550
28614
|
}
|
|
28551
28615
|
const labels = getters.getRangeValues(labelRange);
|
|
28616
|
+
if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
|
|
28617
|
+
labels.shift();
|
|
28618
|
+
}
|
|
28552
28619
|
if (labels.some((label) => isNaN(Number(label)) && label)) {
|
|
28553
28620
|
return false;
|
|
28554
28621
|
}
|
|
@@ -28657,17 +28724,15 @@ function aggregateDataForLabels(labels, datasets) {
|
|
|
28657
28724
|
})),
|
|
28658
28725
|
};
|
|
28659
28726
|
}
|
|
28660
|
-
function getChartLabelFormat(getters, range) {
|
|
28727
|
+
function getChartLabelFormat(getters, range, shouldRemoveFirstLabel) {
|
|
28661
28728
|
if (!range)
|
|
28662
28729
|
return undefined;
|
|
28663
|
-
const { sheetId, zone
|
|
28664
|
-
|
|
28665
|
-
|
|
28666
|
-
|
|
28667
|
-
return format;
|
|
28668
|
-
}
|
|
28730
|
+
const { sheetId, zone } = range;
|
|
28731
|
+
const formats = positions(zone).map((position) => getters.getEvaluatedCell({ sheetId, ...position }).format);
|
|
28732
|
+
if (shouldRemoveFirstLabel) {
|
|
28733
|
+
formats.shift();
|
|
28669
28734
|
}
|
|
28670
|
-
return undefined;
|
|
28735
|
+
return formats.find((format) => format !== undefined);
|
|
28671
28736
|
}
|
|
28672
28737
|
function getChartLabelValues(getters, dataSets, labelRange) {
|
|
28673
28738
|
let labels = { values: [], formattedValues: [] };
|
|
@@ -28723,10 +28788,8 @@ function getChartDatasetFormat(getters, allDataSets, axis) {
|
|
|
28723
28788
|
function getChartDatasetValues(getters, dataSets) {
|
|
28724
28789
|
const datasetValues = [];
|
|
28725
28790
|
for (const [dsIndex, ds] of Object.entries(dataSets)) {
|
|
28726
|
-
if (getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left)) {
|
|
28727
|
-
continue;
|
|
28728
|
-
}
|
|
28729
28791
|
let label;
|
|
28792
|
+
let hidden = getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left);
|
|
28730
28793
|
if (ds.labelCell) {
|
|
28731
28794
|
const labelRange = ds.labelCell;
|
|
28732
28795
|
const cell = labelRange
|
|
@@ -28753,9 +28816,9 @@ function getChartDatasetValues(getters, dataSets) {
|
|
|
28753
28816
|
data.fill(1);
|
|
28754
28817
|
}
|
|
28755
28818
|
else if (data.every((cell) => cell === undefined || cell === null || !isNumber(cell.toString(), DEFAULT_LOCALE))) {
|
|
28756
|
-
|
|
28819
|
+
hidden = true;
|
|
28757
28820
|
}
|
|
28758
|
-
datasetValues.push({ data, label });
|
|
28821
|
+
datasetValues.push({ data, label, hidden });
|
|
28759
28822
|
}
|
|
28760
28823
|
return datasetValues;
|
|
28761
28824
|
}
|
|
@@ -28766,12 +28829,13 @@ function getBarChartDatasets(definition, args) {
|
|
|
28766
28829
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28767
28830
|
const trendDatasets = [];
|
|
28768
28831
|
for (const index in dataSetsValues) {
|
|
28769
|
-
let { label, data } = dataSetsValues[index];
|
|
28832
|
+
let { label, data, hidden } = dataSetsValues[index];
|
|
28770
28833
|
label = definition.dataSets?.[index].label || label;
|
|
28771
28834
|
const backgroundColor = colors.next();
|
|
28772
28835
|
const dataset = {
|
|
28773
28836
|
label,
|
|
28774
28837
|
data,
|
|
28838
|
+
hidden,
|
|
28775
28839
|
borderColor: definition.background || BACKGROUND_CHART_COLOR,
|
|
28776
28840
|
borderWidth: definition.stacked ? 1 : 0,
|
|
28777
28841
|
backgroundColor,
|
|
@@ -28804,6 +28868,9 @@ function getWaterfallDatasetAndLabels(definition, args) {
|
|
|
28804
28868
|
const labelsWithSubTotals = [];
|
|
28805
28869
|
let lastValue = 0;
|
|
28806
28870
|
for (const dataSetsValue of dataSetsValues) {
|
|
28871
|
+
if (dataSetsValue.hidden) {
|
|
28872
|
+
continue;
|
|
28873
|
+
}
|
|
28807
28874
|
for (let i = 0; i < dataSetsValue.data.length; i++) {
|
|
28808
28875
|
const data = dataSetsValue.data[i];
|
|
28809
28876
|
labelsWithSubTotals.push(labels[i]);
|
|
@@ -28839,7 +28906,7 @@ function getLineChartDatasets(definition, args) {
|
|
|
28839
28906
|
const trendDatasets = [];
|
|
28840
28907
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28841
28908
|
for (let index = 0; index < dataSetsValues.length; index++) {
|
|
28842
|
-
let { label, data } = dataSetsValues[index];
|
|
28909
|
+
let { label, data, hidden } = dataSetsValues[index];
|
|
28843
28910
|
label = definition.dataSets?.[index].label || label;
|
|
28844
28911
|
const color = colors.next();
|
|
28845
28912
|
if (axisType && ["linear", "time"].includes(axisType)) {
|
|
@@ -28849,6 +28916,7 @@ function getLineChartDatasets(definition, args) {
|
|
|
28849
28916
|
const dataset = {
|
|
28850
28917
|
label,
|
|
28851
28918
|
data,
|
|
28919
|
+
hidden,
|
|
28852
28920
|
tension: 0, // 0 -> render straight lines, which is much faster
|
|
28853
28921
|
borderColor: color,
|
|
28854
28922
|
backgroundColor: areaChart ? setColorAlpha(color, LINE_FILL_TRANSPARENCY) : color,
|
|
@@ -28881,11 +28949,13 @@ function getPieChartDatasets(definition, args) {
|
|
|
28881
28949
|
const dataSets = [];
|
|
28882
28950
|
const dataSetsLength = Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0));
|
|
28883
28951
|
const backgroundColor = getPieColors(new ColorGenerator(dataSetsLength), dataSetsValues);
|
|
28884
|
-
for (const { label, data } of dataSetsValues) {
|
|
28952
|
+
for (const { label, data, hidden } of dataSetsValues) {
|
|
28953
|
+
if (hidden)
|
|
28954
|
+
continue;
|
|
28885
28955
|
const dataset = {
|
|
28886
28956
|
label,
|
|
28887
28957
|
data,
|
|
28888
|
-
borderColor:
|
|
28958
|
+
borderColor: definition.background || "#FFFFFF",
|
|
28889
28959
|
backgroundColor,
|
|
28890
28960
|
hoverOffset: 30,
|
|
28891
28961
|
};
|
|
@@ -28899,7 +28969,7 @@ function getComboChartDatasets(definition, args) {
|
|
|
28899
28969
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28900
28970
|
const trendDatasets = [];
|
|
28901
28971
|
for (let index = 0; index < dataSetsValues.length; index++) {
|
|
28902
|
-
let { label, data } = dataSetsValues[index];
|
|
28972
|
+
let { label, data, hidden } = dataSetsValues[index];
|
|
28903
28973
|
label = definition.dataSets?.[index].label || label;
|
|
28904
28974
|
const design = definition.dataSets?.[index];
|
|
28905
28975
|
const color = colors.next();
|
|
@@ -28907,6 +28977,7 @@ function getComboChartDatasets(definition, args) {
|
|
|
28907
28977
|
const dataset = {
|
|
28908
28978
|
label: label,
|
|
28909
28979
|
data,
|
|
28980
|
+
hidden,
|
|
28910
28981
|
borderColor: color,
|
|
28911
28982
|
backgroundColor: color,
|
|
28912
28983
|
yAxisID: definition.dataSets?.[index].yAxisId || "y",
|
|
@@ -28931,7 +29002,7 @@ function getRadarChartDatasets(definition, args) {
|
|
|
28931
29002
|
const fill = definition.fillArea ?? false;
|
|
28932
29003
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28933
29004
|
for (let i = 0; i < dataSetsValues.length; i++) {
|
|
28934
|
-
let { label, data } = dataSetsValues[i];
|
|
29005
|
+
let { label, data, hidden } = dataSetsValues[i];
|
|
28935
29006
|
if (definition.dataSets?.[i]?.label) {
|
|
28936
29007
|
label = definition.dataSets[i].label;
|
|
28937
29008
|
}
|
|
@@ -28939,6 +29010,7 @@ function getRadarChartDatasets(definition, args) {
|
|
|
28939
29010
|
const dataset = {
|
|
28940
29011
|
label,
|
|
28941
29012
|
data,
|
|
29013
|
+
hidden,
|
|
28942
29014
|
borderColor,
|
|
28943
29015
|
backgroundColor: borderColor,
|
|
28944
29016
|
};
|
|
@@ -29084,6 +29156,11 @@ function getPieChartLegend(definition, args) {
|
|
|
29084
29156
|
hidden: false,
|
|
29085
29157
|
lineWidth: 2,
|
|
29086
29158
|
})),
|
|
29159
|
+
filter: (legendItem, data) => {
|
|
29160
|
+
return "datasetIndex" in legendItem
|
|
29161
|
+
? !data.datasets[legendItem.datasetIndex].hidden
|
|
29162
|
+
: true;
|
|
29163
|
+
},
|
|
29087
29164
|
},
|
|
29088
29165
|
};
|
|
29089
29166
|
}
|
|
@@ -29145,6 +29222,11 @@ function getWaterfallChartLegend(definition, args) {
|
|
|
29145
29222
|
}
|
|
29146
29223
|
return legendValues;
|
|
29147
29224
|
},
|
|
29225
|
+
filter: (legendItem, data) => {
|
|
29226
|
+
return "datasetIndex" in legendItem
|
|
29227
|
+
? !data.datasets[legendItem.datasetIndex].hidden
|
|
29228
|
+
: true;
|
|
29229
|
+
},
|
|
29148
29230
|
},
|
|
29149
29231
|
onClick: () => { }, // Disables click interaction with the waterfall chart legend items
|
|
29150
29232
|
};
|
|
@@ -29228,6 +29310,11 @@ function getCustomLegendLabels(fontColor, legendLabelConfig) {
|
|
|
29228
29310
|
...legendLabelConfig,
|
|
29229
29311
|
};
|
|
29230
29312
|
}),
|
|
29313
|
+
filter: (legendItem, data) => {
|
|
29314
|
+
return "datasetIndex" in legendItem
|
|
29315
|
+
? !data.datasets[legendItem.datasetIndex].hidden
|
|
29316
|
+
: true;
|
|
29317
|
+
},
|
|
29231
29318
|
},
|
|
29232
29319
|
};
|
|
29233
29320
|
}
|
|
@@ -32900,7 +32987,7 @@ const linkSheet = {
|
|
|
32900
32987
|
const deleteSheet = {
|
|
32901
32988
|
name: _t("Delete"),
|
|
32902
32989
|
isVisible: (env) => {
|
|
32903
|
-
return env.model.getters.
|
|
32990
|
+
return env.model.getters.getVisibleSheetIds().length > 1;
|
|
32904
32991
|
},
|
|
32905
32992
|
execute: (env) => env.askConfirmation(_t("Are you sure you want to delete this sheet?"), () => {
|
|
32906
32993
|
env.model.dispatch("DELETE_SHEET", { sheetId: env.model.getters.getActiveSheetId() });
|
|
@@ -32911,7 +32998,7 @@ const duplicateSheet = {
|
|
|
32911
32998
|
name: _t("Duplicate"),
|
|
32912
32999
|
execute: (env) => {
|
|
32913
33000
|
const sheetIdFrom = env.model.getters.getActiveSheetId();
|
|
32914
|
-
const sheetIdTo = env.model.uuidGenerator.
|
|
33001
|
+
const sheetIdTo = env.model.uuidGenerator.smallUuid();
|
|
32915
33002
|
env.model.dispatch("DUPLICATE_SHEET", {
|
|
32916
33003
|
sheetId: sheetIdFrom,
|
|
32917
33004
|
sheetIdTo,
|
|
@@ -33017,6 +33104,100 @@ function* iterateChildren(el) {
|
|
|
33017
33104
|
function getOpenedMenus() {
|
|
33018
33105
|
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
33019
33106
|
}
|
|
33107
|
+
function getCurrentSelection(el) {
|
|
33108
|
+
let { startElement, endElement, startSelectionOffset, endSelectionOffset } = getStartAndEndSelection(el);
|
|
33109
|
+
let startSizeBefore = findSelectionIndex(el, startElement, startSelectionOffset);
|
|
33110
|
+
let endSizeBefore = findSelectionIndex(el, endElement, endSelectionOffset);
|
|
33111
|
+
return {
|
|
33112
|
+
start: startSizeBefore,
|
|
33113
|
+
end: endSizeBefore,
|
|
33114
|
+
};
|
|
33115
|
+
}
|
|
33116
|
+
function getStartAndEndSelection(el) {
|
|
33117
|
+
const selection = document.getSelection();
|
|
33118
|
+
return {
|
|
33119
|
+
startElement: selection.anchorNode || el,
|
|
33120
|
+
startSelectionOffset: selection.anchorOffset,
|
|
33121
|
+
endElement: selection.focusNode || el,
|
|
33122
|
+
endSelectionOffset: selection.focusOffset,
|
|
33123
|
+
};
|
|
33124
|
+
}
|
|
33125
|
+
/**
|
|
33126
|
+
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
33127
|
+
* The selected node is either a Text node or an Element node.
|
|
33128
|
+
*
|
|
33129
|
+
* case 1 -Text node:
|
|
33130
|
+
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
33131
|
+
* content length of all previous nodes.
|
|
33132
|
+
*
|
|
33133
|
+
* case 2 - Element node:
|
|
33134
|
+
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
33135
|
+
* all the nodes prior to the selected node as well as the content of the child node before the offset.
|
|
33136
|
+
*
|
|
33137
|
+
* See the MDN documentation for more details.
|
|
33138
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
33139
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
33140
|
+
*
|
|
33141
|
+
*/
|
|
33142
|
+
function findSelectionIndex(el, nodeToFind, nodeOffset) {
|
|
33143
|
+
let usedCharacters = 0;
|
|
33144
|
+
let it = iterateChildren(el);
|
|
33145
|
+
let current = it.next();
|
|
33146
|
+
let isFirstParagraph = true;
|
|
33147
|
+
while (!current.done && current.value !== nodeToFind) {
|
|
33148
|
+
if (!current.value.hasChildNodes()) {
|
|
33149
|
+
if (current.value.textContent) {
|
|
33150
|
+
usedCharacters += current.value.textContent.length;
|
|
33151
|
+
}
|
|
33152
|
+
}
|
|
33153
|
+
// One new paragraph = one new line character, except for the first paragraph
|
|
33154
|
+
if (current.value.nodeName === "P" ||
|
|
33155
|
+
(current.value.nodeName === "DIV" && current.value !== el) // On paste, the HTML may contain <div> instead of <p>
|
|
33156
|
+
) {
|
|
33157
|
+
if (isFirstParagraph) {
|
|
33158
|
+
isFirstParagraph = false;
|
|
33159
|
+
}
|
|
33160
|
+
else {
|
|
33161
|
+
usedCharacters++;
|
|
33162
|
+
}
|
|
33163
|
+
}
|
|
33164
|
+
current = it.next();
|
|
33165
|
+
}
|
|
33166
|
+
if (current.value !== nodeToFind) {
|
|
33167
|
+
/** This situation can happen if the code is called while the selection is not currently on the element.
|
|
33168
|
+
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
33169
|
+
*
|
|
33170
|
+
* A known occurrence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
33171
|
+
*/
|
|
33172
|
+
return 0;
|
|
33173
|
+
}
|
|
33174
|
+
else {
|
|
33175
|
+
if (!current.value.hasChildNodes()) {
|
|
33176
|
+
usedCharacters += nodeOffset;
|
|
33177
|
+
}
|
|
33178
|
+
else {
|
|
33179
|
+
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
33180
|
+
usedCharacters += children.reduce((acc, child, index) => {
|
|
33181
|
+
if (child.textContent !== null) {
|
|
33182
|
+
// need to account for paragraph nodes that implicitly add a new line
|
|
33183
|
+
// except for the last paragraph
|
|
33184
|
+
let chars = child.textContent.length;
|
|
33185
|
+
if (child.nodeName === "P" && index !== children.length - 1) {
|
|
33186
|
+
chars++;
|
|
33187
|
+
}
|
|
33188
|
+
return acc + chars;
|
|
33189
|
+
}
|
|
33190
|
+
else {
|
|
33191
|
+
return acc;
|
|
33192
|
+
}
|
|
33193
|
+
}, 0);
|
|
33194
|
+
}
|
|
33195
|
+
}
|
|
33196
|
+
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") {
|
|
33197
|
+
usedCharacters++;
|
|
33198
|
+
}
|
|
33199
|
+
return usedCharacters;
|
|
33200
|
+
}
|
|
33020
33201
|
const letterRegex = /^[a-zA-Z]$/;
|
|
33021
33202
|
/**
|
|
33022
33203
|
* Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
|
|
@@ -33614,20 +33795,21 @@ function getSmartChartDefinition(zone, getters) {
|
|
|
33614
33795
|
}
|
|
33615
33796
|
// Only display legend for several datasets.
|
|
33616
33797
|
const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
|
|
33617
|
-
const
|
|
33618
|
-
|
|
33619
|
-
|
|
33620
|
-
|
|
33621
|
-
|
|
33622
|
-
|
|
33623
|
-
|
|
33624
|
-
|
|
33625
|
-
|
|
33626
|
-
|
|
33627
|
-
|
|
33628
|
-
|
|
33629
|
-
|
|
33630
|
-
|
|
33798
|
+
const lineChartDefinition = {
|
|
33799
|
+
title: {},
|
|
33800
|
+
dataSets,
|
|
33801
|
+
labelsAsText: false,
|
|
33802
|
+
stacked: false,
|
|
33803
|
+
aggregated: false,
|
|
33804
|
+
cumulative: false,
|
|
33805
|
+
labelRange: labelRangeXc,
|
|
33806
|
+
type: "line",
|
|
33807
|
+
dataSetsHaveTitle,
|
|
33808
|
+
legendPosition: newLegendPos,
|
|
33809
|
+
};
|
|
33810
|
+
const chart = new LineChart(lineChartDefinition, sheetId, getters);
|
|
33811
|
+
if (canChartParseLabels(lineChartDefinition, chart.dataSets, chart.labelRange, getters)) {
|
|
33812
|
+
return lineChartDefinition;
|
|
33631
33813
|
}
|
|
33632
33814
|
const _dataSets = createDataSets(getters, dataSets, sheetId, dataSetsHaveTitle);
|
|
33633
33815
|
if (singleColumn &&
|
|
@@ -34041,7 +34223,7 @@ const HIDE_ROWS_NAME = (env) => {
|
|
|
34041
34223
|
//------------------------------------------------------------------------------
|
|
34042
34224
|
const CREATE_CHART = (env) => {
|
|
34043
34225
|
const getters = env.model.getters;
|
|
34044
|
-
const id = env.model.uuidGenerator.
|
|
34226
|
+
const id = env.model.uuidGenerator.smallUuid();
|
|
34045
34227
|
const sheetId = getters.getActiveSheetId();
|
|
34046
34228
|
if (getZoneArea(env.model.getters.getSelectedZone()) === 1) {
|
|
34047
34229
|
env.model.selection.selectTableAroundSelection();
|
|
@@ -34064,8 +34246,8 @@ const CREATE_CHART = (env) => {
|
|
|
34064
34246
|
// Pivots
|
|
34065
34247
|
//------------------------------------------------------------------------------
|
|
34066
34248
|
const CREATE_PIVOT = (env) => {
|
|
34067
|
-
const pivotId = env.model.uuidGenerator.
|
|
34068
|
-
const newSheetId = env.model.uuidGenerator.
|
|
34249
|
+
const pivotId = env.model.uuidGenerator.smallUuid();
|
|
34250
|
+
const newSheetId = env.model.uuidGenerator.smallUuid();
|
|
34069
34251
|
const result = env.model.dispatch("INSERT_NEW_PIVOT", { pivotId, newSheetId });
|
|
34070
34252
|
if (result.isSuccessful) {
|
|
34071
34253
|
env.openSidePanel("PivotSidePanel", { pivotId });
|
|
@@ -34124,7 +34306,7 @@ async function requestImage(env) {
|
|
|
34124
34306
|
const CREATE_IMAGE = async (env) => {
|
|
34125
34307
|
if (env.imageProvider) {
|
|
34126
34308
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
34127
|
-
const figureId = env.model.uuidGenerator.
|
|
34309
|
+
const figureId = env.model.uuidGenerator.smallUuid();
|
|
34128
34310
|
const image = await requestImage(env);
|
|
34129
34311
|
if (!image) {
|
|
34130
34312
|
throw new Error("No image provider was given to the environment");
|
|
@@ -34677,7 +34859,7 @@ const insertCheckbox = {
|
|
|
34677
34859
|
ranges,
|
|
34678
34860
|
sheetId,
|
|
34679
34861
|
rule: {
|
|
34680
|
-
id: env.model.uuidGenerator.
|
|
34862
|
+
id: env.model.uuidGenerator.smallUuid(),
|
|
34681
34863
|
criterion: {
|
|
34682
34864
|
type: "isBoolean",
|
|
34683
34865
|
values: [],
|
|
@@ -34693,7 +34875,7 @@ const insertDropdown = {
|
|
|
34693
34875
|
const zones = env.model.getters.getSelectedZones();
|
|
34694
34876
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
34695
34877
|
const ranges = zones.map((zone) => env.model.getters.getRangeDataFromZone(sheetId, zone));
|
|
34696
|
-
const ruleID = env.model.uuidGenerator.
|
|
34878
|
+
const ruleID = env.model.uuidGenerator.smallUuid();
|
|
34697
34879
|
env.model.dispatch("ADD_DATA_VALIDATION_RULE", {
|
|
34698
34880
|
ranges,
|
|
34699
34881
|
sheetId,
|
|
@@ -34724,7 +34906,7 @@ const insertSheet = {
|
|
|
34724
34906
|
execute: (env) => {
|
|
34725
34907
|
const activeSheetId = env.model.getters.getActiveSheetId();
|
|
34726
34908
|
const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
|
|
34727
|
-
const sheetId = env.model.uuidGenerator.
|
|
34909
|
+
const sheetId = env.model.uuidGenerator.smallUuid();
|
|
34728
34910
|
env.model.dispatch("CREATE_SHEET", { sheetId, position });
|
|
34729
34911
|
env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
|
|
34730
34912
|
},
|
|
@@ -38251,7 +38433,7 @@ css /* scss */ `
|
|
|
38251
38433
|
.o-font-size-editor {
|
|
38252
38434
|
height: calc(100% - 4px);
|
|
38253
38435
|
input.o-font-size {
|
|
38254
|
-
outline
|
|
38436
|
+
outline: none;
|
|
38255
38437
|
height: 20px;
|
|
38256
38438
|
width: 23px;
|
|
38257
38439
|
}
|
|
@@ -39213,7 +39395,7 @@ class LineConfigPanel extends GenericChartConfigPanel {
|
|
|
39213
39395
|
get canTreatLabelsAsText() {
|
|
39214
39396
|
const chart = this.env.model.getters.getChart(this.props.figureId);
|
|
39215
39397
|
if (chart && chart instanceof LineChart) {
|
|
39216
|
-
return canChartParseLabels(chart.labelRange, this.env.model.getters);
|
|
39398
|
+
return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
|
|
39217
39399
|
}
|
|
39218
39400
|
return false;
|
|
39219
39401
|
}
|
|
@@ -39290,7 +39472,7 @@ class ScatterConfigPanel extends GenericChartConfigPanel {
|
|
|
39290
39472
|
get canTreatLabelsAsText() {
|
|
39291
39473
|
const chart = this.env.model.getters.getChart(this.props.figureId);
|
|
39292
39474
|
if (chart && chart instanceof ScatterChart) {
|
|
39293
|
-
return canChartParseLabels(chart.labelRange, this.env.model.getters);
|
|
39475
|
+
return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
|
|
39294
39476
|
}
|
|
39295
39477
|
return false;
|
|
39296
39478
|
}
|
|
@@ -39864,6 +40046,10 @@ class ContentEditableHelper {
|
|
|
39864
40046
|
if (currentStart === start && currentEnd === end) {
|
|
39865
40047
|
return;
|
|
39866
40048
|
}
|
|
40049
|
+
if (selection.rangeCount === 0) {
|
|
40050
|
+
const range = document.createRange();
|
|
40051
|
+
selection.addRange(range);
|
|
40052
|
+
}
|
|
39867
40053
|
const currentRange = selection.getRangeAt(0);
|
|
39868
40054
|
let range;
|
|
39869
40055
|
if (this.el.contains(currentRange.startContainer)) {
|
|
@@ -39891,8 +40077,16 @@ class ContentEditableHelper {
|
|
|
39891
40077
|
}
|
|
39892
40078
|
let startNode = this.findChildAtCharacterIndex(start);
|
|
39893
40079
|
let endNode = this.findChildAtCharacterIndex(end);
|
|
39894
|
-
|
|
39895
|
-
|
|
40080
|
+
// setEnd (setStart) will result in a collapsed range if the end point is before the start point
|
|
40081
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Range/setEnd
|
|
40082
|
+
if (start <= end) {
|
|
40083
|
+
range.setStart(startNode.node, startNode.offset);
|
|
40084
|
+
range.setEnd(endNode.node, endNode.offset);
|
|
40085
|
+
}
|
|
40086
|
+
else {
|
|
40087
|
+
range.setStart(endNode.node, endNode.offset);
|
|
40088
|
+
range.setEnd(startNode.node, startNode.offset);
|
|
40089
|
+
}
|
|
39896
40090
|
}
|
|
39897
40091
|
}
|
|
39898
40092
|
/**
|
|
@@ -40026,7 +40220,7 @@ class ContentEditableHelper {
|
|
|
40026
40220
|
if (!focusedNode || !this.el.contains(focusedNode))
|
|
40027
40221
|
return;
|
|
40028
40222
|
const element = focusedNode instanceof HTMLElement ? focusedNode : focusedNode.parentElement;
|
|
40029
|
-
element?.scrollIntoView({ block: "nearest" });
|
|
40223
|
+
element?.scrollIntoView?.({ block: "nearest" });
|
|
40030
40224
|
}
|
|
40031
40225
|
/**
|
|
40032
40226
|
* remove the current selection of the user
|
|
@@ -40046,100 +40240,7 @@ class ContentEditableHelper {
|
|
|
40046
40240
|
* finds the indexes of the current selection.
|
|
40047
40241
|
* */
|
|
40048
40242
|
getCurrentSelection() {
|
|
40049
|
-
|
|
40050
|
-
let startSizeBefore = this.findSelectionIndex(startElement, startSelectionOffset);
|
|
40051
|
-
let endSizeBefore = this.findSelectionIndex(endElement, endSelectionOffset);
|
|
40052
|
-
return {
|
|
40053
|
-
start: startSizeBefore,
|
|
40054
|
-
end: endSizeBefore,
|
|
40055
|
-
};
|
|
40056
|
-
}
|
|
40057
|
-
/**
|
|
40058
|
-
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
40059
|
-
* The selected node is either a Text node or an Element node.
|
|
40060
|
-
*
|
|
40061
|
-
* case 1 -Text node:
|
|
40062
|
-
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
40063
|
-
* content length of all previous nodes.
|
|
40064
|
-
*
|
|
40065
|
-
* case 2 - Element node:
|
|
40066
|
-
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
40067
|
-
* all the bnodes prior to the selected node as well as the content of the child node before the offset.
|
|
40068
|
-
*
|
|
40069
|
-
* See the MDN documentation for more details.
|
|
40070
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
40071
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
40072
|
-
*
|
|
40073
|
-
*/
|
|
40074
|
-
findSelectionIndex(nodeToFind, nodeOffset) {
|
|
40075
|
-
let usedCharacters = 0;
|
|
40076
|
-
let it = iterateChildren(this.el);
|
|
40077
|
-
let current = it.next();
|
|
40078
|
-
let isFirstParagraph = true;
|
|
40079
|
-
while (!current.done && current.value !== nodeToFind) {
|
|
40080
|
-
if (!current.value.hasChildNodes()) {
|
|
40081
|
-
if (current.value.textContent) {
|
|
40082
|
-
usedCharacters += current.value.textContent.length;
|
|
40083
|
-
}
|
|
40084
|
-
}
|
|
40085
|
-
// One new paragraph = one new line character, except for the first paragraph
|
|
40086
|
-
if (current.value.nodeName === "P" ||
|
|
40087
|
-
(current.value.nodeName === "DIV" && current.value !== this.el) // On paste, the HTML may contain <div> instead of <p>
|
|
40088
|
-
) {
|
|
40089
|
-
if (isFirstParagraph) {
|
|
40090
|
-
isFirstParagraph = false;
|
|
40091
|
-
}
|
|
40092
|
-
else {
|
|
40093
|
-
usedCharacters++;
|
|
40094
|
-
}
|
|
40095
|
-
}
|
|
40096
|
-
current = it.next();
|
|
40097
|
-
}
|
|
40098
|
-
if (current.value !== nodeToFind) {
|
|
40099
|
-
/** This situation can happen if the code is called while the selection is not currently on the ContentEditableHelper.
|
|
40100
|
-
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
40101
|
-
*
|
|
40102
|
-
* A known occurence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
40103
|
-
*
|
|
40104
|
-
* FIXME: find a way to test eventhough the selection API is not available in jsDOM.
|
|
40105
|
-
*/
|
|
40106
|
-
return 0;
|
|
40107
|
-
}
|
|
40108
|
-
else {
|
|
40109
|
-
if (!current.value.hasChildNodes()) {
|
|
40110
|
-
usedCharacters += nodeOffset;
|
|
40111
|
-
}
|
|
40112
|
-
else {
|
|
40113
|
-
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
40114
|
-
usedCharacters += children.reduce((acc, child, index) => {
|
|
40115
|
-
if (child.textContent !== null) {
|
|
40116
|
-
// need to account for paragraph nodes that implicitely add a new line
|
|
40117
|
-
// except for the last paragraph
|
|
40118
|
-
let chars = child.textContent.length;
|
|
40119
|
-
if (child.nodeName === "P" && index !== children.length - 1) {
|
|
40120
|
-
chars++;
|
|
40121
|
-
}
|
|
40122
|
-
return acc + chars;
|
|
40123
|
-
}
|
|
40124
|
-
else {
|
|
40125
|
-
return acc;
|
|
40126
|
-
}
|
|
40127
|
-
}, 0);
|
|
40128
|
-
}
|
|
40129
|
-
}
|
|
40130
|
-
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") {
|
|
40131
|
-
usedCharacters++;
|
|
40132
|
-
}
|
|
40133
|
-
return usedCharacters;
|
|
40134
|
-
}
|
|
40135
|
-
getStartAndEndSelection() {
|
|
40136
|
-
const selection = document.getSelection();
|
|
40137
|
-
return {
|
|
40138
|
-
startElement: selection.anchorNode || this.el,
|
|
40139
|
-
startSelectionOffset: selection.anchorOffset,
|
|
40140
|
-
endElement: selection.focusNode || this.el,
|
|
40141
|
-
endSelectionOffset: selection.focusOffset,
|
|
40142
|
-
};
|
|
40243
|
+
return getCurrentSelection(this.el);
|
|
40143
40244
|
}
|
|
40144
40245
|
getText() {
|
|
40145
40246
|
let text = "";
|
|
@@ -42068,7 +42169,7 @@ class ConditionalFormattingPanel extends owl.Component {
|
|
|
42068
42169
|
this.originalEditedCf = undefined;
|
|
42069
42170
|
}
|
|
42070
42171
|
addConditionalFormat() {
|
|
42071
|
-
const cfId = this.env.model.uuidGenerator.
|
|
42172
|
+
const cfId = this.env.model.uuidGenerator.smallUuid();
|
|
42072
42173
|
this.env.model.dispatch("ADD_CONDITIONAL_FORMAT", {
|
|
42073
42174
|
sheetId: this.activeSheetId,
|
|
42074
42175
|
ranges: this.env.model.getters
|
|
@@ -43338,7 +43439,7 @@ class DataValidationEditor extends owl.Component {
|
|
|
43338
43439
|
.getSelectedZones()
|
|
43339
43440
|
.map((zone) => zoneToXc(this.env.model.getters.getUnboundedZone(sheetId, zone)));
|
|
43340
43441
|
return {
|
|
43341
|
-
id: this.env.model.uuidGenerator.
|
|
43442
|
+
id: this.env.model.uuidGenerator.smallUuid(),
|
|
43342
43443
|
criterion: { type: "textContains", values: [""] },
|
|
43343
43444
|
ranges,
|
|
43344
43445
|
};
|
|
@@ -44956,8 +45057,8 @@ class PivotTitleSection extends owl.Component {
|
|
|
44956
45057
|
return this.env.model.getters.getPivotDisplayName(this.props.pivotId);
|
|
44957
45058
|
}
|
|
44958
45059
|
duplicatePivot() {
|
|
44959
|
-
const newPivotId = this.env.model.uuidGenerator.
|
|
44960
|
-
const newSheetId = this.env.model.uuidGenerator.
|
|
45060
|
+
const newPivotId = this.env.model.uuidGenerator.smallUuid();
|
|
45061
|
+
const newSheetId = this.env.model.uuidGenerator.smallUuid();
|
|
44961
45062
|
const result = this.env.model.dispatch("DUPLICATE_PIVOT_IN_NEW_SHEET", {
|
|
44962
45063
|
pivotId: this.props.pivotId,
|
|
44963
45064
|
newPivotId,
|
|
@@ -47582,7 +47683,7 @@ class TableStyleEditorPanel extends owl.Component {
|
|
|
47582
47683
|
this.state.selectedTemplateName = templateName;
|
|
47583
47684
|
}
|
|
47584
47685
|
onConfirm() {
|
|
47585
|
-
const tableStyleId = this.props.styleId || this.env.model.uuidGenerator.
|
|
47686
|
+
const tableStyleId = this.props.styleId || this.env.model.uuidGenerator.smallUuid();
|
|
47586
47687
|
this.env.model.dispatch("CREATE_TABLE_STYLE", {
|
|
47587
47688
|
tableStyleId,
|
|
47588
47689
|
tableStyleName: this.state.styleName,
|
|
@@ -53094,6 +53195,10 @@ class CellPlugin extends CorePlugin {
|
|
|
53094
53195
|
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessUpdateCell);
|
|
53095
53196
|
case "CLEAR_CELL":
|
|
53096
53197
|
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessClearCell);
|
|
53198
|
+
case "UPDATE_CELL_POSITION":
|
|
53199
|
+
return !cmd.cellId || this.cells[cmd.sheetId]?.[cmd.cellId]
|
|
53200
|
+
? "Success" /* CommandResult.Success */
|
|
53201
|
+
: "InvalidCellId" /* CommandResult.InvalidCellId */;
|
|
53097
53202
|
default:
|
|
53098
53203
|
return "Success" /* CommandResult.Success */;
|
|
53099
53204
|
}
|
|
@@ -53138,6 +53243,9 @@ class CellPlugin extends CorePlugin {
|
|
|
53138
53243
|
case "DELETE_CONTENT":
|
|
53139
53244
|
this.clearZones(cmd.sheetId, cmd.target);
|
|
53140
53245
|
break;
|
|
53246
|
+
case "DELETE_SHEET": {
|
|
53247
|
+
this.history.update("cells", cmd.sheetId, undefined);
|
|
53248
|
+
}
|
|
53141
53249
|
}
|
|
53142
53250
|
}
|
|
53143
53251
|
clearZones(sheetId, zones) {
|
|
@@ -53928,6 +54036,9 @@ class ConditionalFormatPlugin extends CorePlugin {
|
|
|
53928
54036
|
allowDispatch(cmd) {
|
|
53929
54037
|
switch (cmd.type) {
|
|
53930
54038
|
case "ADD_CONDITIONAL_FORMAT":
|
|
54039
|
+
if (cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
|
|
54040
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
54041
|
+
}
|
|
53931
54042
|
return this.checkValidations(cmd, this.checkCFRule, this.checkEmptyRange, this.checkCFHasChanged);
|
|
53932
54043
|
case "CHANGE_CONDITIONAL_FORMAT_PRIORITY":
|
|
53933
54044
|
return this.checkValidPriorityChange(cmd.cfId, cmd.delta, cmd.sheetId);
|
|
@@ -54344,8 +54455,17 @@ class DataValidationPlugin extends CorePlugin {
|
|
|
54344
54455
|
allowDispatch(cmd) {
|
|
54345
54456
|
switch (cmd.type) {
|
|
54346
54457
|
case "ADD_DATA_VALIDATION_RULE":
|
|
54458
|
+
if (!this.getters.tryGetSheet(cmd.sheetId)) {
|
|
54459
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
54460
|
+
}
|
|
54461
|
+
if (cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
|
|
54462
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
54463
|
+
}
|
|
54347
54464
|
return this.checkValidations(cmd, this.chainValidations(this.checkEmptyRange, this.checkValidRange, this.checkCriterionTypeIsValid, this.checkCriterionHasValidNumberOfValues, this.checkCriterionValuesAreValid));
|
|
54348
54465
|
case "REMOVE_DATA_VALIDATION_RULE":
|
|
54466
|
+
if (!this.getters.tryGetSheet(cmd.sheetId)) {
|
|
54467
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
54468
|
+
}
|
|
54349
54469
|
if (!this.rules[cmd.sheetId].find((rule) => rule.id === cmd.id)) {
|
|
54350
54470
|
return "UnknownDataValidationRule" /* CommandResult.UnknownDataValidationRule */;
|
|
54351
54471
|
}
|
|
@@ -54572,6 +54692,7 @@ class DataValidationPlugin extends CorePlugin {
|
|
|
54572
54692
|
class FigurePlugin extends CorePlugin {
|
|
54573
54693
|
static getters = ["getFigures", "getFigure", "getFigureSheetId"];
|
|
54574
54694
|
figures = {};
|
|
54695
|
+
insertionOrders = []; // TODO use a list in master
|
|
54575
54696
|
// ---------------------------------------------------------------------------
|
|
54576
54697
|
// Command Handling
|
|
54577
54698
|
// ---------------------------------------------------------------------------
|
|
@@ -54674,11 +54795,14 @@ class FigurePlugin extends CorePlugin {
|
|
|
54674
54795
|
}
|
|
54675
54796
|
addFigure(figure, sheetId) {
|
|
54676
54797
|
this.history.update("figures", sheetId, figure.id, figure);
|
|
54798
|
+
this.history.update("insertionOrders", this.insertionOrders.length, figure.id);
|
|
54677
54799
|
}
|
|
54678
54800
|
deleteSheet(sheetId) {
|
|
54801
|
+
this.history.update("insertionOrders", this.insertionOrders.filter((id) => !this.figures[sheetId]?.[id]));
|
|
54679
54802
|
this.history.update("figures", sheetId, undefined);
|
|
54680
54803
|
}
|
|
54681
54804
|
removeFigure(id, sheetId) {
|
|
54805
|
+
this.history.update("insertionOrders", this.insertionOrders.filter((figureId) => figureId !== id));
|
|
54682
54806
|
this.history.update("figures", sheetId, id, undefined);
|
|
54683
54807
|
}
|
|
54684
54808
|
checkFigureExists(sheetId, figureId) {
|
|
@@ -54697,7 +54821,14 @@ class FigurePlugin extends CorePlugin {
|
|
|
54697
54821
|
// Getters
|
|
54698
54822
|
// ---------------------------------------------------------------------------
|
|
54699
54823
|
getFigures(sheetId) {
|
|
54700
|
-
|
|
54824
|
+
const figures = [];
|
|
54825
|
+
for (const figureId of this.insertionOrders) {
|
|
54826
|
+
const figure = this.figures[sheetId]?.[figureId];
|
|
54827
|
+
if (figure) {
|
|
54828
|
+
figures.push(figure);
|
|
54829
|
+
}
|
|
54830
|
+
}
|
|
54831
|
+
return figures;
|
|
54701
54832
|
}
|
|
54702
54833
|
getFigure(sheetId, figureId) {
|
|
54703
54834
|
return this.figures[sheetId]?.[figureId];
|
|
@@ -54710,11 +54841,9 @@ class FigurePlugin extends CorePlugin {
|
|
|
54710
54841
|
// ---------------------------------------------------------------------------
|
|
54711
54842
|
import(data) {
|
|
54712
54843
|
for (let sheet of data.sheets) {
|
|
54713
|
-
const figures
|
|
54714
|
-
|
|
54715
|
-
|
|
54716
|
-
});
|
|
54717
|
-
this.figures[sheet.id] = figures;
|
|
54844
|
+
for (const figure of sheet.figures) {
|
|
54845
|
+
this.addFigure(figure, sheet.id);
|
|
54846
|
+
}
|
|
54718
54847
|
}
|
|
54719
54848
|
}
|
|
54720
54849
|
export(data) {
|
|
@@ -56140,6 +56269,9 @@ class SheetPlugin extends CorePlugin {
|
|
|
56140
56269
|
case "CREATE_SHEET": {
|
|
56141
56270
|
return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
|
|
56142
56271
|
}
|
|
56272
|
+
case "DUPLICATE_SHEET": {
|
|
56273
|
+
return this.sheets[cmd.sheetIdTo] ? "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */ : "Success" /* CommandResult.Success */;
|
|
56274
|
+
}
|
|
56143
56275
|
case "MOVE_SHEET":
|
|
56144
56276
|
try {
|
|
56145
56277
|
const currentIndex = this.orderedSheetIds.findIndex((id) => id === cmd.sheetId);
|
|
@@ -56156,7 +56288,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
56156
56288
|
? "Success" /* CommandResult.Success */
|
|
56157
56289
|
: "InvalidColor" /* CommandResult.InvalidColor */;
|
|
56158
56290
|
case "DELETE_SHEET":
|
|
56159
|
-
return this.
|
|
56291
|
+
return this.getVisibleSheetIds().length > 1
|
|
56160
56292
|
? "Success" /* CommandResult.Success */
|
|
56161
56293
|
: "NotEnoughSheets" /* CommandResult.NotEnoughSheets */;
|
|
56162
56294
|
case "ADD_COLUMNS_ROWS":
|
|
@@ -56951,6 +57083,10 @@ class SheetPlugin extends CorePlugin {
|
|
|
56951
57083
|
checkZonesAreInSheet(cmd) {
|
|
56952
57084
|
if (!("sheetId" in cmd))
|
|
56953
57085
|
return "Success" /* CommandResult.Success */;
|
|
57086
|
+
if ("ranges" in cmd &&
|
|
57087
|
+
cmd.ranges.some((rangeData) => rangeData._sheetId !== "" && !this.getters.tryGetSheet(rangeData._sheetId))) {
|
|
57088
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
57089
|
+
}
|
|
56954
57090
|
return this.checkZonesExistInSheet(cmd.sheetId, this.getCommandZones(cmd));
|
|
56955
57091
|
}
|
|
56956
57092
|
}
|
|
@@ -56959,6 +57095,7 @@ let nextTableId = 1;
|
|
|
56959
57095
|
class TablePlugin extends CorePlugin {
|
|
56960
57096
|
static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
|
|
56961
57097
|
tables = {};
|
|
57098
|
+
insertionOrders = {};
|
|
56962
57099
|
adaptRanges(applyChange, sheetId) {
|
|
56963
57100
|
const sheetIds = sheetId ? [sheetId] : this.getters.getSheetIds();
|
|
56964
57101
|
for (const sheetId of sheetIds) {
|
|
@@ -56970,6 +57107,9 @@ class TablePlugin extends CorePlugin {
|
|
|
56970
57107
|
allowDispatch(cmd) {
|
|
56971
57108
|
switch (cmd.type) {
|
|
56972
57109
|
case "CREATE_TABLE":
|
|
57110
|
+
if (cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId) || rangeData._sheetId !== cmd.sheetId)) {
|
|
57111
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
57112
|
+
}
|
|
56973
57113
|
const zones = cmd.ranges.map((rangeData) => this.getters.getRangeFromRangeData(rangeData).zone);
|
|
56974
57114
|
if (!areZonesContinuous(zones)) {
|
|
56975
57115
|
return "NonContinuousTargets" /* CommandResult.NonContinuousTargets */;
|
|
@@ -57000,11 +57140,13 @@ class TablePlugin extends CorePlugin {
|
|
|
57000
57140
|
switch (cmd.type) {
|
|
57001
57141
|
case "CREATE_SHEET":
|
|
57002
57142
|
this.history.update("tables", cmd.sheetId, {});
|
|
57143
|
+
this.history.update("insertionOrders", cmd.sheetId, []);
|
|
57003
57144
|
break;
|
|
57004
57145
|
case "DELETE_SHEET": {
|
|
57005
57146
|
const tables = { ...this.tables };
|
|
57006
57147
|
delete tables[cmd.sheetId];
|
|
57007
57148
|
this.history.update("tables", tables);
|
|
57149
|
+
this.history.update("insertionOrders", cmd.sheetId, undefined);
|
|
57008
57150
|
break;
|
|
57009
57151
|
}
|
|
57010
57152
|
case "DUPLICATE_SHEET": {
|
|
@@ -57016,6 +57158,9 @@ class TablePlugin extends CorePlugin {
|
|
|
57016
57158
|
: this.copyStaticTableForSheet(cmd.sheetIdTo, table);
|
|
57017
57159
|
}
|
|
57018
57160
|
this.history.update("tables", cmd.sheetIdTo, newTables);
|
|
57161
|
+
this.history.update("insertionOrders", cmd.sheetIdTo, [
|
|
57162
|
+
...(this.insertionOrders[cmd.sheetId] ?? []),
|
|
57163
|
+
]);
|
|
57019
57164
|
break;
|
|
57020
57165
|
}
|
|
57021
57166
|
case "CREATE_TABLE": {
|
|
@@ -57029,6 +57174,10 @@ class TablePlugin extends CorePlugin {
|
|
|
57029
57174
|
? this.createDynamicTable(id, union, config)
|
|
57030
57175
|
: this.createStaticTable(id, cmd.tableType, union, config);
|
|
57031
57176
|
this.history.update("tables", cmd.sheetId, newTable.id, newTable);
|
|
57177
|
+
this.history.update("insertionOrders", cmd.sheetId, [
|
|
57178
|
+
...(this.insertionOrders[cmd.sheetId] ?? []),
|
|
57179
|
+
newTable.id,
|
|
57180
|
+
]);
|
|
57032
57181
|
break;
|
|
57033
57182
|
}
|
|
57034
57183
|
case "REMOVE_TABLE": {
|
|
@@ -57039,6 +57188,7 @@ class TablePlugin extends CorePlugin {
|
|
|
57039
57188
|
}
|
|
57040
57189
|
}
|
|
57041
57190
|
this.history.update("tables", cmd.sheetId, tables);
|
|
57191
|
+
this.history.update("insertionOrders", cmd.sheetId, this.insertionOrders[cmd.sheetId]?.filter((id) => id in tables));
|
|
57042
57192
|
break;
|
|
57043
57193
|
}
|
|
57044
57194
|
case "UPDATE_TABLE": {
|
|
@@ -57074,7 +57224,14 @@ class TablePlugin extends CorePlugin {
|
|
|
57074
57224
|
}
|
|
57075
57225
|
}
|
|
57076
57226
|
getCoreTables(sheetId) {
|
|
57077
|
-
|
|
57227
|
+
const tables = [];
|
|
57228
|
+
for (const tableId of this.insertionOrders[sheetId] || []) {
|
|
57229
|
+
const table = this.tables[sheetId][tableId];
|
|
57230
|
+
if (table) {
|
|
57231
|
+
tables.push(table);
|
|
57232
|
+
}
|
|
57233
|
+
}
|
|
57234
|
+
return tables;
|
|
57078
57235
|
}
|
|
57079
57236
|
getCoreTable({ sheetId, col, row }) {
|
|
57080
57237
|
return this.getCoreTables(sheetId).find((table) => isInside(col, row, table.range.zone));
|
|
@@ -57357,6 +57514,7 @@ class TablePlugin extends CorePlugin {
|
|
|
57357
57514
|
// ---------------------------------------------------------------------------
|
|
57358
57515
|
import(data) {
|
|
57359
57516
|
for (const sheet of data.sheets) {
|
|
57517
|
+
const tableIds = [];
|
|
57360
57518
|
for (const tableData of sheet.tables || []) {
|
|
57361
57519
|
const uuid = `${nextTableId++}`;
|
|
57362
57520
|
const tableConfig = tableData.config || DEFAULT_TABLE_CONFIG;
|
|
@@ -57366,7 +57524,9 @@ class TablePlugin extends CorePlugin {
|
|
|
57366
57524
|
? this.createDynamicTable(uuid, range, tableConfig)
|
|
57367
57525
|
: this.createStaticTable(uuid, tableType, range, tableConfig);
|
|
57368
57526
|
this.history.update("tables", sheet.id, table.id, table);
|
|
57527
|
+
tableIds.push(table.id);
|
|
57369
57528
|
}
|
|
57529
|
+
this.history.update("insertionOrders", sheet.id, tableIds);
|
|
57370
57530
|
}
|
|
57371
57531
|
}
|
|
57372
57532
|
export(data) {
|
|
@@ -57406,7 +57566,10 @@ class HeaderGroupingPlugin extends CorePlugin {
|
|
|
57406
57566
|
allowDispatch(cmd) {
|
|
57407
57567
|
switch (cmd.type) {
|
|
57408
57568
|
case "GROUP_HEADERS": {
|
|
57409
|
-
const { start, end } = cmd;
|
|
57569
|
+
const { start, end, sheetId } = cmd;
|
|
57570
|
+
if (!this.getters.tryGetSheet(sheetId)) {
|
|
57571
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
57572
|
+
}
|
|
57410
57573
|
if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
|
|
57411
57574
|
return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
|
|
57412
57575
|
}
|
|
@@ -57419,7 +57582,10 @@ class HeaderGroupingPlugin extends CorePlugin {
|
|
|
57419
57582
|
break;
|
|
57420
57583
|
}
|
|
57421
57584
|
case "UNGROUP_HEADERS": {
|
|
57422
|
-
const { start, end } = cmd;
|
|
57585
|
+
const { start, end, sheetId } = cmd;
|
|
57586
|
+
if (!this.getters.tryGetSheet(sheetId)) {
|
|
57587
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
57588
|
+
}
|
|
57423
57589
|
if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
|
|
57424
57590
|
return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
|
|
57425
57591
|
}
|
|
@@ -57430,6 +57596,9 @@ class HeaderGroupingPlugin extends CorePlugin {
|
|
|
57430
57596
|
}
|
|
57431
57597
|
case "UNFOLD_HEADER_GROUP":
|
|
57432
57598
|
case "FOLD_HEADER_GROUP":
|
|
57599
|
+
if (!this.getters.tryGetSheet(cmd.sheetId)) {
|
|
57600
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
57601
|
+
}
|
|
57433
57602
|
const group = this.findGroupWithStartEnd(cmd.sheetId, cmd.dimension, cmd.start, cmd.end);
|
|
57434
57603
|
if (!group) {
|
|
57435
57604
|
return "UnknownHeaderGroup" /* CommandResult.UnknownHeaderGroup */;
|
|
@@ -57830,6 +57999,9 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
57830
57999
|
return this.checkDuplicatedMeasureIds(cmd.pivot);
|
|
57831
58000
|
}
|
|
57832
58001
|
case "UPDATE_PIVOT": {
|
|
58002
|
+
if (!(cmd.pivotId in this.pivots)) {
|
|
58003
|
+
return "PivotIdNotFound" /* CommandResult.PivotIdNotFound */;
|
|
58004
|
+
}
|
|
57833
58005
|
if (deepEquals(cmd.pivot, this.pivots[cmd.pivotId]?.definition)) {
|
|
57834
58006
|
return "NoChanges" /* CommandResult.NoChanges */;
|
|
57835
58007
|
}
|
|
@@ -57846,6 +58018,8 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
57846
58018
|
return "EmptyName" /* CommandResult.EmptyName */;
|
|
57847
58019
|
}
|
|
57848
58020
|
break;
|
|
58021
|
+
case "REMOVE_PIVOT":
|
|
58022
|
+
case "DUPLICATE_PIVOT":
|
|
57849
58023
|
case "INSERT_PIVOT": {
|
|
57850
58024
|
if (!(cmd.pivotId in this.pivots)) {
|
|
57851
58025
|
return "PivotIdNotFound" /* CommandResult.PivotIdNotFound */;
|
|
@@ -57895,7 +58069,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
57895
58069
|
break;
|
|
57896
58070
|
}
|
|
57897
58071
|
case "UPDATE_PIVOT": {
|
|
57898
|
-
this.history.update("pivots", cmd.pivotId, "definition", cmd.pivot);
|
|
58072
|
+
this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
|
|
57899
58073
|
this.compileCalculatedMeasures(cmd.pivot.measures);
|
|
57900
58074
|
break;
|
|
57901
58075
|
}
|
|
@@ -57966,7 +58140,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
57966
58140
|
// Private
|
|
57967
58141
|
// -------------------------------------------------------------------------
|
|
57968
58142
|
addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
|
|
57969
|
-
this.history.update("pivots", pivotId, { definition: pivot, formulaId });
|
|
58143
|
+
this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
|
|
57970
58144
|
this.compileCalculatedMeasures(pivot.measures);
|
|
57971
58145
|
this.history.update("formulaIds", formulaId, pivotId);
|
|
57972
58146
|
this.history.update("nextFormulaId", this.nextFormulaId + 1);
|
|
@@ -59552,6 +59726,10 @@ class Evaluator {
|
|
|
59552
59726
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
59553
59727
|
this.compilationParams.evalContext.updateDependencies = this.updateDependencies.bind(this);
|
|
59554
59728
|
this.compilationParams.evalContext.addDependencies = this.addDependencies.bind(this);
|
|
59729
|
+
this.compilationParams.evalContext.lookupCaches = {
|
|
59730
|
+
forwardSearch: new Map(),
|
|
59731
|
+
reverseSearch: new Map(),
|
|
59732
|
+
};
|
|
59555
59733
|
}
|
|
59556
59734
|
createEmptyPositionSet() {
|
|
59557
59735
|
const sheetSizes = {};
|
|
@@ -62872,6 +63050,9 @@ function updateChartRangesTransformation(toTransform, executed) {
|
|
|
62872
63050
|
};
|
|
62873
63051
|
}
|
|
62874
63052
|
function createSheetTransformation(toTransform, executed) {
|
|
63053
|
+
if (toTransform.sheetId === executed.sheetId) {
|
|
63054
|
+
toTransform = { ...toTransform, sheetId: `${toTransform.sheetId}~` };
|
|
63055
|
+
}
|
|
62875
63056
|
if (toTransform.name === executed.name) {
|
|
62876
63057
|
return {
|
|
62877
63058
|
...toTransform,
|
|
@@ -63523,21 +63704,14 @@ class Session extends EventBus {
|
|
|
63523
63704
|
if (!message)
|
|
63524
63705
|
return;
|
|
63525
63706
|
if (message.type === "REMOTE_REVISION") {
|
|
63526
|
-
|
|
63707
|
+
let revision = this.revisions.get(message.nextRevisionId);
|
|
63527
63708
|
if (revision.commands.length === 0) {
|
|
63528
63709
|
/**
|
|
63529
|
-
* The command is empty, we have to
|
|
63710
|
+
* The command is empty, we have to rebase all the next local revisions
|
|
63530
63711
|
* to avoid issues with undo/redo
|
|
63531
63712
|
*/
|
|
63532
|
-
this.revisions.
|
|
63533
|
-
|
|
63534
|
-
.filter((message) => message.type === "REMOTE_REVISION")
|
|
63535
|
-
.map((message) => message.nextRevisionId);
|
|
63536
|
-
this.trigger("pending-revisions-dropped", { revisionIds });
|
|
63537
|
-
this.waitingAck = false;
|
|
63538
|
-
this.waitingUndoRedoAck = false;
|
|
63539
|
-
this.pendingMessages = [];
|
|
63540
|
-
return;
|
|
63713
|
+
this.revisions.rebase(revision.id);
|
|
63714
|
+
revision = this.revisions.get(message.nextRevisionId);
|
|
63541
63715
|
}
|
|
63542
63716
|
message = {
|
|
63543
63717
|
...message,
|
|
@@ -63562,7 +63736,6 @@ class Session extends EventBus {
|
|
|
63562
63736
|
switch (message.type) {
|
|
63563
63737
|
case "REMOTE_REVISION":
|
|
63564
63738
|
case "REVISION_REDONE":
|
|
63565
|
-
case "REVISION_UNDONE":
|
|
63566
63739
|
case "SNAPSHOT_CREATED":
|
|
63567
63740
|
this.waitingAck = false;
|
|
63568
63741
|
this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
|
|
@@ -63571,6 +63744,25 @@ class Session extends EventBus {
|
|
|
63571
63744
|
this.lastRevisionMessage = message;
|
|
63572
63745
|
this.sendPendingMessage();
|
|
63573
63746
|
break;
|
|
63747
|
+
case "REVISION_UNDONE": {
|
|
63748
|
+
this.waitingAck = false;
|
|
63749
|
+
this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
|
|
63750
|
+
const firstPendingRevisionId = this.pendingMessages.findIndex((message) => message.type === "REMOTE_REVISION");
|
|
63751
|
+
if (firstPendingRevisionId !== -1) {
|
|
63752
|
+
/**
|
|
63753
|
+
* Some revisions undergo transformations that may cause issues with
|
|
63754
|
+
* undo/redo if the transformation is destructive (we don't get back
|
|
63755
|
+
* the original command by transforming it with the inverse).
|
|
63756
|
+
* To prevent these problems, we must rebase all subsequent local
|
|
63757
|
+
* revisions.
|
|
63758
|
+
*/
|
|
63759
|
+
this.revisions.rebase(this.pendingMessages[firstPendingRevisionId].nextRevisionId);
|
|
63760
|
+
}
|
|
63761
|
+
this.serverRevisionId = message.nextRevisionId;
|
|
63762
|
+
this.processedRevisions.add(message.nextRevisionId);
|
|
63763
|
+
this.sendPendingMessage();
|
|
63764
|
+
break;
|
|
63765
|
+
}
|
|
63574
63766
|
}
|
|
63575
63767
|
}
|
|
63576
63768
|
isAlreadyProcessed(message) {
|
|
@@ -64692,6 +64884,10 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
64692
64884
|
*/
|
|
64693
64885
|
checkZonesAreInSheet(cmd) {
|
|
64694
64886
|
const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.tryGetActiveSheetId();
|
|
64887
|
+
if ("ranges" in cmd &&
|
|
64888
|
+
cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
|
|
64889
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
64890
|
+
}
|
|
64695
64891
|
const zones = this.getters.getCommandZones(cmd);
|
|
64696
64892
|
if (!sheetId && zones.length > 0) {
|
|
64697
64893
|
return "NoActiveSheet" /* CommandResult.NoActiveSheet */;
|
|
@@ -65041,23 +65237,23 @@ const uuidGenerator = new UuidGenerator();
|
|
|
65041
65237
|
function repeatCreateChartCommand(getters, cmd) {
|
|
65042
65238
|
return {
|
|
65043
65239
|
...repeatSheetDependantCommand(getters, cmd),
|
|
65044
|
-
id: uuidGenerator.
|
|
65240
|
+
id: uuidGenerator.smallUuid(),
|
|
65045
65241
|
};
|
|
65046
65242
|
}
|
|
65047
65243
|
function repeatCreateImageCommand(getters, cmd) {
|
|
65048
65244
|
return {
|
|
65049
65245
|
...repeatSheetDependantCommand(getters, cmd),
|
|
65050
|
-
figureId: uuidGenerator.
|
|
65246
|
+
figureId: uuidGenerator.smallUuid(),
|
|
65051
65247
|
};
|
|
65052
65248
|
}
|
|
65053
65249
|
function repeatCreateFigureCommand(getters, cmd) {
|
|
65054
65250
|
const newCmd = repeatSheetDependantCommand(getters, cmd);
|
|
65055
|
-
newCmd.figure.id = uuidGenerator.
|
|
65251
|
+
newCmd.figure.id = uuidGenerator.smallUuid();
|
|
65056
65252
|
return newCmd;
|
|
65057
65253
|
}
|
|
65058
65254
|
function repeatCreateSheetCommand(getters, cmd) {
|
|
65059
65255
|
const newCmd = deepCopy(cmd);
|
|
65060
|
-
newCmd.sheetId = uuidGenerator.
|
|
65256
|
+
newCmd.sheetId = uuidGenerator.smallUuid();
|
|
65061
65257
|
const sheetName = cmd.name || getters.getSheet(getters.getActiveSheetId()).name;
|
|
65062
65258
|
// Extract the prefix of the sheet name (everything before the number at the end of the name)
|
|
65063
65259
|
const namePrefix = sheetName.match(/(.+?)\d*$/)?.[1] || sheetName;
|
|
@@ -65246,7 +65442,6 @@ class HistoryPlugin extends UIPlugin {
|
|
|
65246
65442
|
super(config);
|
|
65247
65443
|
this.session = config.session;
|
|
65248
65444
|
this.session.on("new-local-state-update", this, this.onNewLocalStateUpdate);
|
|
65249
|
-
this.session.on("pending-revisions-dropped", this, ({ revisionIds }) => this.drop(revisionIds));
|
|
65250
65445
|
this.session.on("snapshot", this, () => {
|
|
65251
65446
|
this.undoStack = [];
|
|
65252
65447
|
this.redoStack = [];
|
|
@@ -65316,10 +65511,6 @@ class HistoryPlugin extends UIPlugin {
|
|
|
65316
65511
|
const lastNonRedoRevision = this.getPossibleRevisionToRepeat();
|
|
65317
65512
|
return canRepeatRevision(lastNonRedoRevision);
|
|
65318
65513
|
}
|
|
65319
|
-
drop(revisionIds) {
|
|
65320
|
-
this.undoStack = this.undoStack.filter((id) => !revisionIds.includes(id));
|
|
65321
|
-
this.redoStack = [];
|
|
65322
|
-
}
|
|
65323
65514
|
onNewLocalStateUpdate({ id }) {
|
|
65324
65515
|
this.undoStack.push(id);
|
|
65325
65516
|
this.redoStack = [];
|
|
@@ -66520,23 +66711,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
66520
66711
|
gridSelection: deepCopy(gridSelection),
|
|
66521
66712
|
};
|
|
66522
66713
|
}
|
|
66523
|
-
|
|
66524
|
-
const currentSheetIds = this.getters.getVisibleSheetIds();
|
|
66525
|
-
this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
|
|
66526
|
-
if (this.activeSheet.id in this.sheetsData) {
|
|
66527
|
-
const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
|
|
66528
|
-
this.selectCell(anchor.cell.col, anchor.cell.row);
|
|
66529
|
-
}
|
|
66530
|
-
else {
|
|
66531
|
-
this.selectCell(0, 0);
|
|
66532
|
-
}
|
|
66533
|
-
const { col, row } = this.gridSelection.anchor.cell;
|
|
66534
|
-
this.moveClient({
|
|
66535
|
-
sheetId: this.getters.getActiveSheetId(),
|
|
66536
|
-
col,
|
|
66537
|
-
row,
|
|
66538
|
-
});
|
|
66539
|
-
}
|
|
66714
|
+
this.fallbackToVisibleSheet();
|
|
66540
66715
|
const sheetId = this.getters.getActiveSheetId();
|
|
66541
66716
|
this.gridSelection.zones = this.gridSelection.zones.map((z) => this.getters.expandZone(sheetId, z));
|
|
66542
66717
|
this.gridSelection.anchor.zone = this.getters.expandZone(sheetId, this.gridSelection.anchor.zone);
|
|
@@ -66546,6 +66721,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
66546
66721
|
}
|
|
66547
66722
|
}
|
|
66548
66723
|
finalize() {
|
|
66724
|
+
this.fallbackToVisibleSheet();
|
|
66549
66725
|
/** Any change to the selection has to be reflected in the selection processor. */
|
|
66550
66726
|
this.selection.resetDefaultAnchor(this, deepCopy(this.gridSelection.anchor));
|
|
66551
66727
|
}
|
|
@@ -66856,6 +67032,25 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
66856
67032
|
}
|
|
66857
67033
|
return "Success" /* CommandResult.Success */;
|
|
66858
67034
|
}
|
|
67035
|
+
fallbackToVisibleSheet() {
|
|
67036
|
+
if (!this.getters.tryGetSheet(this.getters.getActiveSheetId())) {
|
|
67037
|
+
const currentSheetIds = this.getters.getVisibleSheetIds();
|
|
67038
|
+
this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
|
|
67039
|
+
if (this.activeSheet.id in this.sheetsData) {
|
|
67040
|
+
const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
|
|
67041
|
+
this.selectCell(anchor.cell.col, anchor.cell.row);
|
|
67042
|
+
}
|
|
67043
|
+
else {
|
|
67044
|
+
this.selectCell(0, 0);
|
|
67045
|
+
}
|
|
67046
|
+
const { col, row } = this.gridSelection.anchor.cell;
|
|
67047
|
+
this.moveClient({
|
|
67048
|
+
sheetId: this.getters.getActiveSheetId(),
|
|
67049
|
+
col,
|
|
67050
|
+
row,
|
|
67051
|
+
});
|
|
67052
|
+
}
|
|
67053
|
+
}
|
|
66859
67054
|
//-------------------------------------------
|
|
66860
67055
|
// Helpers for extensions
|
|
66861
67056
|
// ------------------------------------------
|
|
@@ -68019,7 +68214,9 @@ class HeaderPositionsUIPlugin extends UIPlugin {
|
|
|
68019
68214
|
case "UNGROUP_HEADERS":
|
|
68020
68215
|
case "GROUP_HEADERS":
|
|
68021
68216
|
case "CREATE_SHEET":
|
|
68022
|
-
this.
|
|
68217
|
+
if (this.getters.tryGetSheet(cmd.sheetId)) {
|
|
68218
|
+
this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
|
|
68219
|
+
}
|
|
68023
68220
|
break;
|
|
68024
68221
|
case "DUPLICATE_SHEET":
|
|
68025
68222
|
this.headerPositions[cmd.sheetIdTo] = deepCopy(this.headerPositions[cmd.sheetId]);
|
|
@@ -68027,12 +68224,14 @@ class HeaderPositionsUIPlugin extends UIPlugin {
|
|
|
68027
68224
|
}
|
|
68028
68225
|
}
|
|
68029
68226
|
finalize() {
|
|
68030
|
-
|
|
68031
|
-
|
|
68227
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
68228
|
+
// sheets can be created without this plugin being aware of it
|
|
68229
|
+
// in concurrent situations.
|
|
68230
|
+
if (this.isDirty || !this.headerPositions[sheetId]) {
|
|
68032
68231
|
this.headerPositions[sheetId] = this.computeHeaderPositionsOfSheet(sheetId);
|
|
68033
68232
|
}
|
|
68034
|
-
this.isDirty = false;
|
|
68035
68233
|
}
|
|
68234
|
+
this.isDirty = false;
|
|
68036
68235
|
}
|
|
68037
68236
|
/**
|
|
68038
68237
|
* Returns the size, start and end coordinates of a column on an unfolded sheet
|
|
@@ -68856,7 +69055,7 @@ class BottomBar extends owl.Component {
|
|
|
68856
69055
|
clickAddSheet(ev) {
|
|
68857
69056
|
const activeSheetId = this.env.model.getters.getActiveSheetId();
|
|
68858
69057
|
const position = this.env.model.getters.getSheetIds().findIndex((sheetId) => sheetId === activeSheetId) + 1;
|
|
68859
|
-
const sheetId = this.env.model.uuidGenerator.
|
|
69058
|
+
const sheetId = this.env.model.uuidGenerator.smallUuid();
|
|
68860
69059
|
const name = this.env.model.getters.getNextSheetName(_t("Sheet"));
|
|
68861
69060
|
this.env.model.dispatch("CREATE_SHEET", { sheetId, position, name });
|
|
68862
69061
|
this.env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
|
|
@@ -69871,6 +70070,10 @@ const FX_SVG = /*xml*/ `
|
|
|
69871
70070
|
</svg>
|
|
69872
70071
|
`;
|
|
69873
70072
|
css /* scss */ `
|
|
70073
|
+
.o-topbar-composer-container {
|
|
70074
|
+
height: ${TOPBAR_TOOLBAR_HEIGHT}px;
|
|
70075
|
+
}
|
|
70076
|
+
|
|
69874
70077
|
.o-topbar-composer {
|
|
69875
70078
|
height: fit-content;
|
|
69876
70079
|
margin-top: -1px;
|
|
@@ -71144,7 +71347,7 @@ class Tree {
|
|
|
71144
71347
|
}
|
|
71145
71348
|
/**
|
|
71146
71349
|
* Drop the operation and all following operations in every
|
|
71147
|
-
*
|
|
71350
|
+
* branches
|
|
71148
71351
|
*/
|
|
71149
71352
|
drop(operationId) {
|
|
71150
71353
|
for (const branch of this.branches) {
|
|
@@ -71449,9 +71652,16 @@ class SelectiveHistory {
|
|
|
71449
71652
|
this.fastForward();
|
|
71450
71653
|
this.insert(redoId, this.buildEmpty(redoId), insertAfter);
|
|
71451
71654
|
}
|
|
71452
|
-
|
|
71655
|
+
rebase(operationId) {
|
|
71656
|
+
const operation = this.get(operationId);
|
|
71657
|
+
const execution = [...this.tree.execution(this.HEAD_BRANCH).startAfter(operationId)];
|
|
71453
71658
|
this.revertBefore(operationId);
|
|
71659
|
+
const baseId = this.HEAD_OPERATION.id;
|
|
71454
71660
|
this.tree.drop(operationId);
|
|
71661
|
+
this.insert(operationId, operation, baseId);
|
|
71662
|
+
for (const { operation } of execution) {
|
|
71663
|
+
this.insert(operation.id, operation.data, this.HEAD_OPERATION.id);
|
|
71664
|
+
}
|
|
71455
71665
|
}
|
|
71456
71666
|
/**
|
|
71457
71667
|
* Revert the state as it was *before* the given operation was executed.
|
|
@@ -74562,6 +74772,11 @@ class Model extends EventBus {
|
|
|
74562
74772
|
dispatch: (command) => {
|
|
74563
74773
|
const result = this.checkDispatchAllowed(command);
|
|
74564
74774
|
if (!result.isSuccessful) {
|
|
74775
|
+
// core views plugins need to be invalidated
|
|
74776
|
+
this.dispatchToHandlers(this.coreHandlers, {
|
|
74777
|
+
type: "UNDO",
|
|
74778
|
+
commands: [command],
|
|
74779
|
+
});
|
|
74565
74780
|
return;
|
|
74566
74781
|
}
|
|
74567
74782
|
this.isReplayingCommand = true;
|
|
@@ -74589,7 +74804,7 @@ class Model extends EventBus {
|
|
|
74589
74804
|
}
|
|
74590
74805
|
setupConfig(config) {
|
|
74591
74806
|
const client = config.client || {
|
|
74592
|
-
id: this.uuidGenerator.
|
|
74807
|
+
id: this.uuidGenerator.smallUuid(),
|
|
74593
74808
|
name: _t("Anonymous").toString(),
|
|
74594
74809
|
};
|
|
74595
74810
|
const transportService = config.transportService || new LocalTransportService();
|
|
@@ -75112,6 +75327,6 @@ exports.tokenColors = tokenColors;
|
|
|
75112
75327
|
exports.tokenize = tokenize;
|
|
75113
75328
|
|
|
75114
75329
|
|
|
75115
|
-
__info__.version = "18.1.
|
|
75116
|
-
__info__.date = "2025-02-
|
|
75117
|
-
__info__.hash = "
|
|
75330
|
+
__info__.version = "18.1.9";
|
|
75331
|
+
__info__.date = "2025-02-25T05:59:45.472Z";
|
|
75332
|
+
__info__.hash = "6789c1c";
|