@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
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -2218,17 +2218,7 @@ function toZoneWithoutBoundaryChanges(xc) {
|
|
|
2218
2218
|
*/
|
|
2219
2219
|
function toUnboundedZone(xc) {
|
|
2220
2220
|
const zone = toZoneWithoutBoundaryChanges(xc);
|
|
2221
|
-
|
|
2222
|
-
const tmp = zone.left;
|
|
2223
|
-
zone.left = zone.right;
|
|
2224
|
-
zone.right = tmp;
|
|
2225
|
-
}
|
|
2226
|
-
if (zone.bottom !== undefined && zone.bottom < zone.top) {
|
|
2227
|
-
const tmp = zone.top;
|
|
2228
|
-
zone.top = zone.bottom;
|
|
2229
|
-
zone.bottom = tmp;
|
|
2230
|
-
}
|
|
2231
|
-
return zone;
|
|
2221
|
+
return reorderZone(zone);
|
|
2232
2222
|
}
|
|
2233
2223
|
/**
|
|
2234
2224
|
* Convert from a cartesian reference to a Zone.
|
|
@@ -2502,11 +2492,11 @@ function positions(zone) {
|
|
|
2502
2492
|
return positions;
|
|
2503
2493
|
}
|
|
2504
2494
|
function reorderZone(zone) {
|
|
2505
|
-
if (zone.left > zone.right) {
|
|
2506
|
-
zone = { left: zone.right, right: zone.left
|
|
2495
|
+
if (zone.right !== undefined && zone.left > zone.right) {
|
|
2496
|
+
zone = { ...zone, left: zone.right, right: zone.left };
|
|
2507
2497
|
}
|
|
2508
|
-
if (zone.top > zone.bottom) {
|
|
2509
|
-
zone = {
|
|
2498
|
+
if (zone.bottom !== undefined && zone.top > zone.bottom) {
|
|
2499
|
+
zone = { ...zone, top: zone.bottom, bottom: zone.top };
|
|
2510
2500
|
}
|
|
2511
2501
|
return zone;
|
|
2512
2502
|
}
|
|
@@ -3411,12 +3401,12 @@ function isTargetDependent(cmd) {
|
|
|
3411
3401
|
function isRangeDependant(cmd) {
|
|
3412
3402
|
return "ranges" in cmd;
|
|
3413
3403
|
}
|
|
3414
|
-
function isZoneDependent(cmd) {
|
|
3415
|
-
return "zone" in cmd;
|
|
3416
|
-
}
|
|
3417
3404
|
function isPositionDependent(cmd) {
|
|
3418
3405
|
return "col" in cmd && "row" in cmd && "sheetId" in cmd;
|
|
3419
3406
|
}
|
|
3407
|
+
function isZoneDependent(cmd) {
|
|
3408
|
+
return "sheetId" in cmd && "zone" in cmd;
|
|
3409
|
+
}
|
|
3420
3410
|
const invalidateEvaluationCommands = new Set([
|
|
3421
3411
|
"RENAME_SHEET",
|
|
3422
3412
|
"DELETE_SHEET",
|
|
@@ -3428,6 +3418,7 @@ const invalidateEvaluationCommands = new Set([
|
|
|
3428
3418
|
"REDO",
|
|
3429
3419
|
"ADD_MERGE",
|
|
3430
3420
|
"REMOVE_MERGE",
|
|
3421
|
+
"DUPLICATE_SHEET",
|
|
3431
3422
|
"UPDATE_LOCALE",
|
|
3432
3423
|
"ADD_PIVOT",
|
|
3433
3424
|
"UPDATE_PIVOT",
|
|
@@ -3457,7 +3448,6 @@ const invalidateChartEvaluationCommands = new Set([
|
|
|
3457
3448
|
]);
|
|
3458
3449
|
const invalidateDependenciesCommands = new Set(["MOVE_RANGES"]);
|
|
3459
3450
|
const invalidateCFEvaluationCommands = new Set([
|
|
3460
|
-
"DUPLICATE_SHEET",
|
|
3461
3451
|
"EVALUATE_CELLS",
|
|
3462
3452
|
"ADD_CONDITIONAL_FORMAT",
|
|
3463
3453
|
"REMOVE_CONDITIONAL_FORMAT",
|
|
@@ -3627,6 +3617,7 @@ var CommandResult;
|
|
|
3627
3617
|
CommandResult["InvalidRange"] = "InvalidRange";
|
|
3628
3618
|
CommandResult["InvalidZones"] = "InvalidZones";
|
|
3629
3619
|
CommandResult["InvalidSheetId"] = "InvalidSheetId";
|
|
3620
|
+
CommandResult["InvalidCellId"] = "InvalidCellId";
|
|
3630
3621
|
CommandResult["InvalidFigureId"] = "InvalidFigureId";
|
|
3631
3622
|
CommandResult["InputAlreadyFocused"] = "InputAlreadyFocused";
|
|
3632
3623
|
CommandResult["MaximumRangesReached"] = "MaximumRangesReached";
|
|
@@ -4458,7 +4449,7 @@ function dichotomicSearch(data, target, mode, sortOrder, rangeLength, getValueIn
|
|
|
4458
4449
|
* @param reverseSearch if true, search in the array starting from the end.
|
|
4459
4450
|
|
|
4460
4451
|
*/
|
|
4461
|
-
function linearSearch(data, target, mode, numberOfValues, getValueInData, reverseSearch = false) {
|
|
4452
|
+
function linearSearch(data, target, mode, numberOfValues, getValueInData, lookupCaches, reverseSearch = false) {
|
|
4462
4453
|
if (target === undefined || target.value === null) {
|
|
4463
4454
|
return -1;
|
|
4464
4455
|
}
|
|
@@ -4467,17 +4458,48 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
|
|
|
4467
4458
|
}
|
|
4468
4459
|
const _target = normalizeValue(target.value);
|
|
4469
4460
|
const getValue = reverseSearch
|
|
4470
|
-
? (data, i) => getValueInData(data, numberOfValues - i - 1)
|
|
4471
|
-
: getValueInData;
|
|
4461
|
+
? (data, i) => normalizeValue(getValueInData(data, numberOfValues - i - 1))
|
|
4462
|
+
: (data, i) => normalizeValue(getValueInData(data, i));
|
|
4463
|
+
// first check if the target is in the cache
|
|
4464
|
+
const isNotWildcardTarget = mode !== "wildcard" ||
|
|
4465
|
+
typeof _target !== "string" ||
|
|
4466
|
+
!(_target.includes("*") || _target.includes("?"));
|
|
4467
|
+
if (lookupCaches && isNotWildcardTarget) {
|
|
4468
|
+
const searchMode = reverseSearch ? "reverseSearch" : "forwardSearch";
|
|
4469
|
+
let cache = lookupCaches[searchMode].get(data);
|
|
4470
|
+
if (cache === undefined) {
|
|
4471
|
+
// build the cache for all the values
|
|
4472
|
+
cache = new Map();
|
|
4473
|
+
for (let i = 0; i < numberOfValues; i++) {
|
|
4474
|
+
const value = getValue(data, i) ?? null;
|
|
4475
|
+
if (!cache.has(value)) {
|
|
4476
|
+
cache.set(value, i);
|
|
4477
|
+
}
|
|
4478
|
+
}
|
|
4479
|
+
lookupCaches[searchMode].set(data, cache);
|
|
4480
|
+
}
|
|
4481
|
+
if (cache.has(_target)) {
|
|
4482
|
+
const resultIndex = cache.get(_target);
|
|
4483
|
+
return reverseSearch ? numberOfValues - resultIndex - 1 : resultIndex;
|
|
4484
|
+
}
|
|
4485
|
+
if (mode === "strict") {
|
|
4486
|
+
return -1;
|
|
4487
|
+
}
|
|
4488
|
+
}
|
|
4489
|
+
// else perform the linear search
|
|
4490
|
+
const resultIndex = _linearSearch(data, _target, mode, numberOfValues, getValue);
|
|
4491
|
+
return reverseSearch && resultIndex !== -1 ? numberOfValues - resultIndex - 1 : resultIndex;
|
|
4492
|
+
}
|
|
4493
|
+
function _linearSearch(data, _target, mode, numberOfValues, getNormalizeValue) {
|
|
4472
4494
|
let indexMatchTarget = (i) => {
|
|
4473
|
-
return
|
|
4495
|
+
return getNormalizeValue(data, i) === _target;
|
|
4474
4496
|
};
|
|
4475
4497
|
if (mode === "wildcard" &&
|
|
4476
4498
|
typeof _target === "string" &&
|
|
4477
4499
|
(_target.includes("*") || _target.includes("?"))) {
|
|
4478
4500
|
const regExp = wildcardToRegExp(_target);
|
|
4479
4501
|
indexMatchTarget = (i) => {
|
|
4480
|
-
const value =
|
|
4502
|
+
const value = getNormalizeValue(data, i);
|
|
4481
4503
|
if (typeof value === "string") {
|
|
4482
4504
|
return regExp.test(value);
|
|
4483
4505
|
}
|
|
@@ -4488,7 +4510,7 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
|
|
|
4488
4510
|
let closestMatchIndex = -1;
|
|
4489
4511
|
if (mode === "nextSmaller") {
|
|
4490
4512
|
indexMatchTarget = (i) => {
|
|
4491
|
-
const value =
|
|
4513
|
+
const value = getNormalizeValue(data, i);
|
|
4492
4514
|
if ((!closestMatch && compareCellValues(_target, value) >= 0) ||
|
|
4493
4515
|
(compareCellValues(_target, value) >= 0 && compareCellValues(value, closestMatch) > 0)) {
|
|
4494
4516
|
closestMatch = value;
|
|
@@ -4499,7 +4521,7 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
|
|
|
4499
4521
|
}
|
|
4500
4522
|
if (mode === "nextGreater") {
|
|
4501
4523
|
indexMatchTarget = (i) => {
|
|
4502
|
-
const value =
|
|
4524
|
+
const value = getNormalizeValue(data, i);
|
|
4503
4525
|
if ((!closestMatch && compareCellValues(_target, value) <= 0) ||
|
|
4504
4526
|
(compareCellValues(_target, value) <= 0 && compareCellValues(value, closestMatch) < 0)) {
|
|
4505
4527
|
closestMatch = value;
|
|
@@ -4510,12 +4532,10 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
|
|
|
4510
4532
|
}
|
|
4511
4533
|
for (let i = 0; i < numberOfValues; i++) {
|
|
4512
4534
|
if (indexMatchTarget(i)) {
|
|
4513
|
-
return
|
|
4535
|
+
return i;
|
|
4514
4536
|
}
|
|
4515
4537
|
}
|
|
4516
|
-
return
|
|
4517
|
-
? numberOfValues - closestMatchIndex - 1
|
|
4518
|
-
: closestMatchIndex;
|
|
4538
|
+
return closestMatchIndex;
|
|
4519
4539
|
}
|
|
4520
4540
|
/**
|
|
4521
4541
|
* Normalize a value.
|
|
@@ -6479,11 +6499,40 @@ function drawDecoratedText(context, text, position, underline = false, strikethr
|
|
|
6479
6499
|
* https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
|
|
6480
6500
|
* */
|
|
6481
6501
|
class UuidGenerator {
|
|
6502
|
+
/**
|
|
6503
|
+
* Generates a custom UUID using a simple 36^12 method (8-character alphanumeric string with lowercase letters)
|
|
6504
|
+
* This has a higher chance of collision than a UUIDv4, but not only faster to generate than an UUIDV4,
|
|
6505
|
+
* it also has a smaller size, which is preferable to alleviate the overall data size.
|
|
6506
|
+
*
|
|
6507
|
+
* This method is preferable when generating uuids for the core data (sheetId, figureId, etc)
|
|
6508
|
+
* as they will appear several times in the revisions and local history.
|
|
6509
|
+
*
|
|
6510
|
+
*/
|
|
6511
|
+
smallUuid() {
|
|
6512
|
+
if (window.crypto) {
|
|
6513
|
+
return "10000000-1000".replace(/[01]/g, (c) => {
|
|
6514
|
+
const n = Number(c);
|
|
6515
|
+
return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
|
|
6516
|
+
});
|
|
6517
|
+
}
|
|
6518
|
+
else {
|
|
6519
|
+
// mainly for jest and other browsers that do not have the crypto functionality
|
|
6520
|
+
return "xxxxxxxx-xxxx".replace(/[xy]/g, function (c) {
|
|
6521
|
+
const r = (Math.random() * 16) | 0, v = c == "x" ? r : (r & 0x3) | 0x8;
|
|
6522
|
+
return v.toString(16);
|
|
6523
|
+
});
|
|
6524
|
+
}
|
|
6525
|
+
}
|
|
6526
|
+
/**
|
|
6527
|
+
* Generates an UUIDV4, has astronomically low chance of collision, but is larger in size than the smallUuid.
|
|
6528
|
+
* This method should be used when you need to avoid collisions at all costs, like the id of a revision.
|
|
6529
|
+
*/
|
|
6482
6530
|
uuidv4() {
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6531
|
+
if (window.crypto) {
|
|
6532
|
+
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => {
|
|
6533
|
+
const n = Number(c);
|
|
6534
|
+
return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
|
|
6535
|
+
});
|
|
6487
6536
|
}
|
|
6488
6537
|
else {
|
|
6489
6538
|
// mainly for jest and other browsers that do not have the crypto functionality
|
|
@@ -8513,7 +8562,7 @@ class ChartClipboardHandler extends AbstractFigureClipboardHandler {
|
|
|
8513
8562
|
};
|
|
8514
8563
|
}
|
|
8515
8564
|
getPasteTarget(sheetId, target, content, options) {
|
|
8516
|
-
const newId = new UuidGenerator().
|
|
8565
|
+
const newId = new UuidGenerator().smallUuid();
|
|
8517
8566
|
return { zones: [], figureId: newId, sheetId };
|
|
8518
8567
|
}
|
|
8519
8568
|
paste(target, clippedContent, options) {
|
|
@@ -8679,7 +8728,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8679
8728
|
if (!targetCF && queuedCfs) {
|
|
8680
8729
|
targetCF = queuedCfs.find((queued) => queued.cf.stopIfTrue === originCF.stopIfTrue && deepEquals(queued.cf.rule, originCF.rule))?.cf;
|
|
8681
8730
|
}
|
|
8682
|
-
return targetCF || { ...originCF, id: this.uuidGenerator.
|
|
8731
|
+
return targetCF || { ...originCF, id: this.uuidGenerator.smallUuid(), ranges: [] };
|
|
8683
8732
|
}
|
|
8684
8733
|
}
|
|
8685
8734
|
|
|
@@ -8772,7 +8821,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8772
8821
|
}
|
|
8773
8822
|
return (targetRule || {
|
|
8774
8823
|
...originRule,
|
|
8775
|
-
id: newId ? this.uuidGenerator.
|
|
8824
|
+
id: newId ? this.uuidGenerator.smallUuid() : originRule.id,
|
|
8776
8825
|
ranges: [],
|
|
8777
8826
|
});
|
|
8778
8827
|
}
|
|
@@ -8834,7 +8883,7 @@ class ImageClipboardHandler extends AbstractFigureClipboardHandler {
|
|
|
8834
8883
|
};
|
|
8835
8884
|
}
|
|
8836
8885
|
getPasteTarget(sheetId, target, content, options) {
|
|
8837
|
-
const newId = new UuidGenerator().
|
|
8886
|
+
const newId = new UuidGenerator().smallUuid();
|
|
8838
8887
|
return { sheetId, zones: [], figureId: newId };
|
|
8839
8888
|
}
|
|
8840
8889
|
paste(target, clippedContent, options) {
|
|
@@ -12036,6 +12085,25 @@ const LN = {
|
|
|
12036
12085
|
isExported: true,
|
|
12037
12086
|
};
|
|
12038
12087
|
// -----------------------------------------------------------------------------
|
|
12088
|
+
// LOG
|
|
12089
|
+
// -----------------------------------------------------------------------------
|
|
12090
|
+
const LOG = {
|
|
12091
|
+
description: _t("The logarithm of a number, for a given base."),
|
|
12092
|
+
args: [
|
|
12093
|
+
arg("value (number)", _t("The value for which to calculate the logarithm.")),
|
|
12094
|
+
arg("base (number, default=10)", _t("The base of the logarithm.")),
|
|
12095
|
+
],
|
|
12096
|
+
compute: function (value, base = { value: 10 }) {
|
|
12097
|
+
const _value = toNumber(value, this.locale);
|
|
12098
|
+
const _base = toNumber(base, this.locale);
|
|
12099
|
+
assert(() => _value > 0, _t("The value (%s) must be strictly positive.", _value.toString()));
|
|
12100
|
+
assert(() => _base > 0, _t("The base (%s) must be strictly positive.", _base.toString()));
|
|
12101
|
+
assert(() => _base !== 1, _t("The base must be different from 1."));
|
|
12102
|
+
return Math.log10(_value) / Math.log10(_base);
|
|
12103
|
+
},
|
|
12104
|
+
isExported: true,
|
|
12105
|
+
};
|
|
12106
|
+
// -----------------------------------------------------------------------------
|
|
12039
12107
|
// MOD
|
|
12040
12108
|
// -----------------------------------------------------------------------------
|
|
12041
12109
|
function mod(dividend, divisor) {
|
|
@@ -12575,6 +12643,7 @@ var math = /*#__PURE__*/Object.freeze({
|
|
|
12575
12643
|
ISODD: ISODD,
|
|
12576
12644
|
ISO_CEILING: ISO_CEILING,
|
|
12577
12645
|
LN: LN,
|
|
12646
|
+
LOG: LOG,
|
|
12578
12647
|
MOD: MOD,
|
|
12579
12648
|
MUNIT: MUNIT,
|
|
12580
12649
|
ODD: ODD,
|
|
@@ -15109,7 +15178,7 @@ const SORTN = {
|
|
|
15109
15178
|
}
|
|
15110
15179
|
}
|
|
15111
15180
|
},
|
|
15112
|
-
isExported:
|
|
15181
|
+
isExported: false,
|
|
15113
15182
|
};
|
|
15114
15183
|
// -----------------------------------------------------------------------------
|
|
15115
15184
|
// UNIQUE
|
|
@@ -18473,7 +18542,7 @@ const HLOOKUP = {
|
|
|
18473
18542
|
const _isSorted = toBoolean(isSorted.value);
|
|
18474
18543
|
const colIndex = _isSorted
|
|
18475
18544
|
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range.length, getValueFromRange)
|
|
18476
|
-
: linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange);
|
|
18545
|
+
: linearSearch(_range, searchKey, "wildcard", _range.length, getValueFromRange, this.lookupCaches);
|
|
18477
18546
|
const col = _range[colIndex];
|
|
18478
18547
|
if (col === undefined) {
|
|
18479
18548
|
return valueNotAvailable(searchKey);
|
|
@@ -18628,7 +18697,7 @@ const MATCH = {
|
|
|
18628
18697
|
index = dichotomicSearch(_range, searchKey, "nextSmaller", "asc", rangeLen, getElement);
|
|
18629
18698
|
break;
|
|
18630
18699
|
case 0:
|
|
18631
|
-
index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement);
|
|
18700
|
+
index = linearSearch(_range, searchKey, "wildcard", rangeLen, getElement, this.lookupCaches);
|
|
18632
18701
|
break;
|
|
18633
18702
|
case -1:
|
|
18634
18703
|
index = dichotomicSearch(_range, searchKey, "nextGreater", "desc", rangeLen, getElement);
|
|
@@ -18696,7 +18765,7 @@ const VLOOKUP = {
|
|
|
18696
18765
|
const _isSorted = toBoolean(isSorted.value);
|
|
18697
18766
|
const rowIndex = _isSorted
|
|
18698
18767
|
? dichotomicSearch(_range, searchKey, "nextSmaller", "asc", _range[0].length, getValueFromRange)
|
|
18699
|
-
: linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange);
|
|
18768
|
+
: linearSearch(_range, searchKey, "wildcard", _range[0].length, getValueFromRange, this.lookupCaches);
|
|
18700
18769
|
const value = _range[_index - 1][rowIndex];
|
|
18701
18770
|
if (value === undefined) {
|
|
18702
18771
|
return valueNotAvailable(searchKey);
|
|
@@ -18752,7 +18821,7 @@ const XLOOKUP = {
|
|
|
18752
18821
|
const reverseSearch = _searchMode === -1;
|
|
18753
18822
|
const index = _searchMode === 2 || _searchMode === -2
|
|
18754
18823
|
? dichotomicSearch(_lookupRange, searchKey, mode, _searchMode === 2 ? "asc" : "desc", rangeLen, getElement)
|
|
18755
|
-
: linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, reverseSearch);
|
|
18824
|
+
: linearSearch(_lookupRange, searchKey, mode, rangeLen, getElement, this.lookupCaches, reverseSearch);
|
|
18756
18825
|
if (index !== -1) {
|
|
18757
18826
|
return lookupDirection === "col"
|
|
18758
18827
|
? _returnRange.map((col) => [col[index]])
|
|
@@ -27622,7 +27691,7 @@ function forceUnicityOfFigure(data) {
|
|
|
27622
27691
|
for (const sheet of data.sheets || []) {
|
|
27623
27692
|
for (const figure of sheet.figures || []) {
|
|
27624
27693
|
if (figureIds.has(figure.id)) {
|
|
27625
|
-
figure.id += uuidGenerator.
|
|
27694
|
+
figure.id += uuidGenerator.smallUuid();
|
|
27626
27695
|
}
|
|
27627
27696
|
figureIds.add(figure.id);
|
|
27628
27697
|
}
|
|
@@ -28207,9 +28276,7 @@ function getBarChartData(definition, dataSets, labelRange, getters) {
|
|
|
28207
28276
|
const labelValues = getChartLabelValues(getters, dataSets, labelRange);
|
|
28208
28277
|
let labels = labelValues.formattedValues;
|
|
28209
28278
|
let dataSetsValues = getChartDatasetValues(getters, dataSets);
|
|
28210
|
-
if (definition.dataSetsHaveTitle
|
|
28211
|
-
dataSetsValues[0] &&
|
|
28212
|
-
labels.length > dataSetsValues[0].data.length) {
|
|
28279
|
+
if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
|
|
28213
28280
|
labels.shift();
|
|
28214
28281
|
}
|
|
28215
28282
|
({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
|
|
@@ -28242,7 +28309,7 @@ function getBarChartData(definition, dataSets, labelRange, getters) {
|
|
|
28242
28309
|
}
|
|
28243
28310
|
function getPyramidChartData(definition, dataSets, labelRange, getters) {
|
|
28244
28311
|
const barChartData = getBarChartData(definition, dataSets, labelRange, getters);
|
|
28245
|
-
const barDataset = barChartData.dataSetsValues;
|
|
28312
|
+
const barDataset = barChartData.dataSetsValues.filter((ds) => !ds.hidden);
|
|
28246
28313
|
const pyramidDatasetValues = [];
|
|
28247
28314
|
if (barDataset[0]) {
|
|
28248
28315
|
const pyramidData = barDataset[0].data.map((value) => (value > 0 ? value : 0));
|
|
@@ -28258,13 +28325,12 @@ function getPyramidChartData(definition, dataSets, labelRange, getters) {
|
|
|
28258
28325
|
};
|
|
28259
28326
|
}
|
|
28260
28327
|
function getLineChartData(definition, dataSets, labelRange, getters) {
|
|
28261
|
-
const axisType = getChartAxisType(definition, labelRange, getters);
|
|
28328
|
+
const axisType = getChartAxisType(definition, dataSets, labelRange, getters);
|
|
28262
28329
|
const labelValues = getChartLabelValues(getters, dataSets, labelRange);
|
|
28263
28330
|
let labels = axisType === "linear" ? labelValues.values : labelValues.formattedValues;
|
|
28264
28331
|
let dataSetsValues = getChartDatasetValues(getters, dataSets);
|
|
28265
|
-
|
|
28266
|
-
|
|
28267
|
-
labels.length > dataSetsValues[0].data.length) {
|
|
28332
|
+
const removeFirstLabel = shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false);
|
|
28333
|
+
if (removeFirstLabel) {
|
|
28268
28334
|
labels.shift();
|
|
28269
28335
|
}
|
|
28270
28336
|
({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
|
|
@@ -28276,7 +28342,7 @@ function getLineChartData(definition, dataSets, labelRange, getters) {
|
|
|
28276
28342
|
}
|
|
28277
28343
|
const leftAxisFormat = getChartDatasetFormat(getters, dataSets, "left");
|
|
28278
28344
|
const rightAxisFormat = getChartDatasetFormat(getters, dataSets, "right");
|
|
28279
|
-
const labelsFormat = getChartLabelFormat(getters, labelRange);
|
|
28345
|
+
const labelsFormat = getChartLabelFormat(getters, labelRange, removeFirstLabel);
|
|
28280
28346
|
const axisFormats = { y: leftAxisFormat, y1: rightAxisFormat, x: labelsFormat };
|
|
28281
28347
|
const trendDataSetsValues = [];
|
|
28282
28348
|
for (const index in dataSetsValues) {
|
|
@@ -28312,9 +28378,7 @@ function getPieChartData(definition, dataSets, labelRange, getters) {
|
|
|
28312
28378
|
const labelValues = getChartLabelValues(getters, dataSets, labelRange);
|
|
28313
28379
|
let labels = labelValues.formattedValues;
|
|
28314
28380
|
let dataSetsValues = getChartDatasetValues(getters, dataSets);
|
|
28315
|
-
if (definition.dataSetsHaveTitle
|
|
28316
|
-
dataSetsValues[0] &&
|
|
28317
|
-
labels.length > dataSetsValues[0].data.length) {
|
|
28381
|
+
if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
|
|
28318
28382
|
labels.shift();
|
|
28319
28383
|
}
|
|
28320
28384
|
({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
|
|
@@ -28334,9 +28398,7 @@ function getRadarChartData(definition, dataSets, labelRange, getters) {
|
|
|
28334
28398
|
const labelValues = getChartLabelValues(getters, dataSets, labelRange);
|
|
28335
28399
|
let labels = labelValues.formattedValues;
|
|
28336
28400
|
let dataSetsValues = getChartDatasetValues(getters, dataSets);
|
|
28337
|
-
if (definition.dataSetsHaveTitle
|
|
28338
|
-
dataSetsValues[0] &&
|
|
28339
|
-
labels.length > dataSetsValues[0].data.length) {
|
|
28401
|
+
if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
|
|
28340
28402
|
labels.shift();
|
|
28341
28403
|
}
|
|
28342
28404
|
({ labels, dataSetsValues } = filterInvalidDataPoints(labels, dataSetsValues));
|
|
@@ -28356,7 +28418,7 @@ function getRadarChartData(definition, dataSets, labelRange, getters) {
|
|
|
28356
28418
|
function getGeoChartData(definition, dataSets, labelRange, getters) {
|
|
28357
28419
|
const labelValues = getChartLabelValues(getters, dataSets, labelRange);
|
|
28358
28420
|
let labels = labelValues.formattedValues;
|
|
28359
|
-
if (definition.dataSetsHaveTitle) {
|
|
28421
|
+
if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
|
|
28360
28422
|
labels.shift();
|
|
28361
28423
|
}
|
|
28362
28424
|
let dataSetsValues = getChartDatasetValues(getters, dataSets);
|
|
@@ -28517,36 +28579,41 @@ function normalizeLabels(labels, newLabels, config) {
|
|
|
28517
28579
|
}
|
|
28518
28580
|
return { normalizedLabels, normalizedNewLabels };
|
|
28519
28581
|
}
|
|
28520
|
-
function getChartAxisType(
|
|
28521
|
-
if (isDateChart(
|
|
28582
|
+
function getChartAxisType(definition, dataSets, labelRange, getters) {
|
|
28583
|
+
if (isDateChart(definition, dataSets, labelRange, getters) && isLuxonTimeAdapterInstalled()) {
|
|
28522
28584
|
return "time";
|
|
28523
28585
|
}
|
|
28524
|
-
if (isLinearChart(
|
|
28586
|
+
if (isLinearChart(definition, dataSets, labelRange, getters)) {
|
|
28525
28587
|
return "linear";
|
|
28526
28588
|
}
|
|
28527
28589
|
return "category";
|
|
28528
28590
|
}
|
|
28529
|
-
function isDateChart(definition, labelRange, getters) {
|
|
28530
|
-
return !definition.labelsAsText && canBeDateChart(labelRange, getters);
|
|
28591
|
+
function isDateChart(definition, dataSets, labelRange, getters) {
|
|
28592
|
+
return !definition.labelsAsText && canBeDateChart(definition, dataSets, labelRange, getters);
|
|
28531
28593
|
}
|
|
28532
|
-
function isLinearChart(definition, labelRange, getters) {
|
|
28533
|
-
return !definition.labelsAsText && canBeLinearChart(labelRange, getters);
|
|
28594
|
+
function isLinearChart(definition, dataSets, labelRange, getters) {
|
|
28595
|
+
return !definition.labelsAsText && canBeLinearChart(definition, dataSets, labelRange, getters);
|
|
28534
28596
|
}
|
|
28535
|
-
function canChartParseLabels(labelRange, getters) {
|
|
28536
|
-
return canBeDateChart(
|
|
28597
|
+
function canChartParseLabels(definition, dataSets, labelRange, getters) {
|
|
28598
|
+
return (canBeDateChart(definition, dataSets, labelRange, getters) ||
|
|
28599
|
+
canBeLinearChart(definition, dataSets, labelRange, getters));
|
|
28537
28600
|
}
|
|
28538
|
-
function canBeDateChart(labelRange, getters) {
|
|
28539
|
-
if (!labelRange || !canBeLinearChart(labelRange, getters)) {
|
|
28601
|
+
function canBeDateChart(definition, dataSets, labelRange, getters) {
|
|
28602
|
+
if (!labelRange || !canBeLinearChart(definition, dataSets, labelRange, getters)) {
|
|
28540
28603
|
return false;
|
|
28541
28604
|
}
|
|
28542
|
-
const
|
|
28605
|
+
const removeFirstLabel = shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false);
|
|
28606
|
+
const labelFormat = getChartLabelFormat(getters, labelRange, removeFirstLabel);
|
|
28543
28607
|
return Boolean(labelFormat && timeFormatLuxonCompatible.test(labelFormat));
|
|
28544
28608
|
}
|
|
28545
|
-
function canBeLinearChart(labelRange, getters) {
|
|
28609
|
+
function canBeLinearChart(definition, dataSets, labelRange, getters) {
|
|
28546
28610
|
if (!labelRange) {
|
|
28547
28611
|
return false;
|
|
28548
28612
|
}
|
|
28549
28613
|
const labels = getters.getRangeValues(labelRange);
|
|
28614
|
+
if (shouldRemoveFirstLabel(labelRange, dataSets[0], definition.dataSetsHaveTitle || false)) {
|
|
28615
|
+
labels.shift();
|
|
28616
|
+
}
|
|
28550
28617
|
if (labels.some((label) => isNaN(Number(label)) && label)) {
|
|
28551
28618
|
return false;
|
|
28552
28619
|
}
|
|
@@ -28655,17 +28722,15 @@ function aggregateDataForLabels(labels, datasets) {
|
|
|
28655
28722
|
})),
|
|
28656
28723
|
};
|
|
28657
28724
|
}
|
|
28658
|
-
function getChartLabelFormat(getters, range) {
|
|
28725
|
+
function getChartLabelFormat(getters, range, shouldRemoveFirstLabel) {
|
|
28659
28726
|
if (!range)
|
|
28660
28727
|
return undefined;
|
|
28661
|
-
const { sheetId, zone
|
|
28662
|
-
|
|
28663
|
-
|
|
28664
|
-
|
|
28665
|
-
return format;
|
|
28666
|
-
}
|
|
28728
|
+
const { sheetId, zone } = range;
|
|
28729
|
+
const formats = positions(zone).map((position) => getters.getEvaluatedCell({ sheetId, ...position }).format);
|
|
28730
|
+
if (shouldRemoveFirstLabel) {
|
|
28731
|
+
formats.shift();
|
|
28667
28732
|
}
|
|
28668
|
-
return undefined;
|
|
28733
|
+
return formats.find((format) => format !== undefined);
|
|
28669
28734
|
}
|
|
28670
28735
|
function getChartLabelValues(getters, dataSets, labelRange) {
|
|
28671
28736
|
let labels = { values: [], formattedValues: [] };
|
|
@@ -28721,10 +28786,8 @@ function getChartDatasetFormat(getters, allDataSets, axis) {
|
|
|
28721
28786
|
function getChartDatasetValues(getters, dataSets) {
|
|
28722
28787
|
const datasetValues = [];
|
|
28723
28788
|
for (const [dsIndex, ds] of Object.entries(dataSets)) {
|
|
28724
|
-
if (getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left)) {
|
|
28725
|
-
continue;
|
|
28726
|
-
}
|
|
28727
28789
|
let label;
|
|
28790
|
+
let hidden = getters.isColHidden(ds.dataRange.sheetId, ds.dataRange.zone.left);
|
|
28728
28791
|
if (ds.labelCell) {
|
|
28729
28792
|
const labelRange = ds.labelCell;
|
|
28730
28793
|
const cell = labelRange
|
|
@@ -28751,9 +28814,9 @@ function getChartDatasetValues(getters, dataSets) {
|
|
|
28751
28814
|
data.fill(1);
|
|
28752
28815
|
}
|
|
28753
28816
|
else if (data.every((cell) => cell === undefined || cell === null || !isNumber(cell.toString(), DEFAULT_LOCALE))) {
|
|
28754
|
-
|
|
28817
|
+
hidden = true;
|
|
28755
28818
|
}
|
|
28756
|
-
datasetValues.push({ data, label });
|
|
28819
|
+
datasetValues.push({ data, label, hidden });
|
|
28757
28820
|
}
|
|
28758
28821
|
return datasetValues;
|
|
28759
28822
|
}
|
|
@@ -28764,12 +28827,13 @@ function getBarChartDatasets(definition, args) {
|
|
|
28764
28827
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28765
28828
|
const trendDatasets = [];
|
|
28766
28829
|
for (const index in dataSetsValues) {
|
|
28767
|
-
let { label, data } = dataSetsValues[index];
|
|
28830
|
+
let { label, data, hidden } = dataSetsValues[index];
|
|
28768
28831
|
label = definition.dataSets?.[index].label || label;
|
|
28769
28832
|
const backgroundColor = colors.next();
|
|
28770
28833
|
const dataset = {
|
|
28771
28834
|
label,
|
|
28772
28835
|
data,
|
|
28836
|
+
hidden,
|
|
28773
28837
|
borderColor: definition.background || BACKGROUND_CHART_COLOR,
|
|
28774
28838
|
borderWidth: definition.stacked ? 1 : 0,
|
|
28775
28839
|
backgroundColor,
|
|
@@ -28802,6 +28866,9 @@ function getWaterfallDatasetAndLabels(definition, args) {
|
|
|
28802
28866
|
const labelsWithSubTotals = [];
|
|
28803
28867
|
let lastValue = 0;
|
|
28804
28868
|
for (const dataSetsValue of dataSetsValues) {
|
|
28869
|
+
if (dataSetsValue.hidden) {
|
|
28870
|
+
continue;
|
|
28871
|
+
}
|
|
28805
28872
|
for (let i = 0; i < dataSetsValue.data.length; i++) {
|
|
28806
28873
|
const data = dataSetsValue.data[i];
|
|
28807
28874
|
labelsWithSubTotals.push(labels[i]);
|
|
@@ -28837,7 +28904,7 @@ function getLineChartDatasets(definition, args) {
|
|
|
28837
28904
|
const trendDatasets = [];
|
|
28838
28905
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28839
28906
|
for (let index = 0; index < dataSetsValues.length; index++) {
|
|
28840
|
-
let { label, data } = dataSetsValues[index];
|
|
28907
|
+
let { label, data, hidden } = dataSetsValues[index];
|
|
28841
28908
|
label = definition.dataSets?.[index].label || label;
|
|
28842
28909
|
const color = colors.next();
|
|
28843
28910
|
if (axisType && ["linear", "time"].includes(axisType)) {
|
|
@@ -28847,6 +28914,7 @@ function getLineChartDatasets(definition, args) {
|
|
|
28847
28914
|
const dataset = {
|
|
28848
28915
|
label,
|
|
28849
28916
|
data,
|
|
28917
|
+
hidden,
|
|
28850
28918
|
tension: 0, // 0 -> render straight lines, which is much faster
|
|
28851
28919
|
borderColor: color,
|
|
28852
28920
|
backgroundColor: areaChart ? setColorAlpha(color, LINE_FILL_TRANSPARENCY) : color,
|
|
@@ -28879,11 +28947,13 @@ function getPieChartDatasets(definition, args) {
|
|
|
28879
28947
|
const dataSets = [];
|
|
28880
28948
|
const dataSetsLength = Math.max(0, ...dataSetsValues.map((ds) => ds?.data?.length ?? 0));
|
|
28881
28949
|
const backgroundColor = getPieColors(new ColorGenerator(dataSetsLength), dataSetsValues);
|
|
28882
|
-
for (const { label, data } of dataSetsValues) {
|
|
28950
|
+
for (const { label, data, hidden } of dataSetsValues) {
|
|
28951
|
+
if (hidden)
|
|
28952
|
+
continue;
|
|
28883
28953
|
const dataset = {
|
|
28884
28954
|
label,
|
|
28885
28955
|
data,
|
|
28886
|
-
borderColor:
|
|
28956
|
+
borderColor: definition.background || "#FFFFFF",
|
|
28887
28957
|
backgroundColor,
|
|
28888
28958
|
hoverOffset: 30,
|
|
28889
28959
|
};
|
|
@@ -28897,7 +28967,7 @@ function getComboChartDatasets(definition, args) {
|
|
|
28897
28967
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28898
28968
|
const trendDatasets = [];
|
|
28899
28969
|
for (let index = 0; index < dataSetsValues.length; index++) {
|
|
28900
|
-
let { label, data } = dataSetsValues[index];
|
|
28970
|
+
let { label, data, hidden } = dataSetsValues[index];
|
|
28901
28971
|
label = definition.dataSets?.[index].label || label;
|
|
28902
28972
|
const design = definition.dataSets?.[index];
|
|
28903
28973
|
const color = colors.next();
|
|
@@ -28905,6 +28975,7 @@ function getComboChartDatasets(definition, args) {
|
|
|
28905
28975
|
const dataset = {
|
|
28906
28976
|
label: label,
|
|
28907
28977
|
data,
|
|
28978
|
+
hidden,
|
|
28908
28979
|
borderColor: color,
|
|
28909
28980
|
backgroundColor: color,
|
|
28910
28981
|
yAxisID: definition.dataSets?.[index].yAxisId || "y",
|
|
@@ -28929,7 +29000,7 @@ function getRadarChartDatasets(definition, args) {
|
|
|
28929
29000
|
const fill = definition.fillArea ?? false;
|
|
28930
29001
|
const colors = getChartColorsGenerator(definition, dataSetsValues.length);
|
|
28931
29002
|
for (let i = 0; i < dataSetsValues.length; i++) {
|
|
28932
|
-
let { label, data } = dataSetsValues[i];
|
|
29003
|
+
let { label, data, hidden } = dataSetsValues[i];
|
|
28933
29004
|
if (definition.dataSets?.[i]?.label) {
|
|
28934
29005
|
label = definition.dataSets[i].label;
|
|
28935
29006
|
}
|
|
@@ -28937,6 +29008,7 @@ function getRadarChartDatasets(definition, args) {
|
|
|
28937
29008
|
const dataset = {
|
|
28938
29009
|
label,
|
|
28939
29010
|
data,
|
|
29011
|
+
hidden,
|
|
28940
29012
|
borderColor,
|
|
28941
29013
|
backgroundColor: borderColor,
|
|
28942
29014
|
};
|
|
@@ -29082,6 +29154,11 @@ function getPieChartLegend(definition, args) {
|
|
|
29082
29154
|
hidden: false,
|
|
29083
29155
|
lineWidth: 2,
|
|
29084
29156
|
})),
|
|
29157
|
+
filter: (legendItem, data) => {
|
|
29158
|
+
return "datasetIndex" in legendItem
|
|
29159
|
+
? !data.datasets[legendItem.datasetIndex].hidden
|
|
29160
|
+
: true;
|
|
29161
|
+
},
|
|
29085
29162
|
},
|
|
29086
29163
|
};
|
|
29087
29164
|
}
|
|
@@ -29143,6 +29220,11 @@ function getWaterfallChartLegend(definition, args) {
|
|
|
29143
29220
|
}
|
|
29144
29221
|
return legendValues;
|
|
29145
29222
|
},
|
|
29223
|
+
filter: (legendItem, data) => {
|
|
29224
|
+
return "datasetIndex" in legendItem
|
|
29225
|
+
? !data.datasets[legendItem.datasetIndex].hidden
|
|
29226
|
+
: true;
|
|
29227
|
+
},
|
|
29146
29228
|
},
|
|
29147
29229
|
onClick: () => { }, // Disables click interaction with the waterfall chart legend items
|
|
29148
29230
|
};
|
|
@@ -29226,6 +29308,11 @@ function getCustomLegendLabels(fontColor, legendLabelConfig) {
|
|
|
29226
29308
|
...legendLabelConfig,
|
|
29227
29309
|
};
|
|
29228
29310
|
}),
|
|
29311
|
+
filter: (legendItem, data) => {
|
|
29312
|
+
return "datasetIndex" in legendItem
|
|
29313
|
+
? !data.datasets[legendItem.datasetIndex].hidden
|
|
29314
|
+
: true;
|
|
29315
|
+
},
|
|
29229
29316
|
},
|
|
29230
29317
|
};
|
|
29231
29318
|
}
|
|
@@ -32898,7 +32985,7 @@ const linkSheet = {
|
|
|
32898
32985
|
const deleteSheet = {
|
|
32899
32986
|
name: _t("Delete"),
|
|
32900
32987
|
isVisible: (env) => {
|
|
32901
|
-
return env.model.getters.
|
|
32988
|
+
return env.model.getters.getVisibleSheetIds().length > 1;
|
|
32902
32989
|
},
|
|
32903
32990
|
execute: (env) => env.askConfirmation(_t("Are you sure you want to delete this sheet?"), () => {
|
|
32904
32991
|
env.model.dispatch("DELETE_SHEET", { sheetId: env.model.getters.getActiveSheetId() });
|
|
@@ -32909,7 +32996,7 @@ const duplicateSheet = {
|
|
|
32909
32996
|
name: _t("Duplicate"),
|
|
32910
32997
|
execute: (env) => {
|
|
32911
32998
|
const sheetIdFrom = env.model.getters.getActiveSheetId();
|
|
32912
|
-
const sheetIdTo = env.model.uuidGenerator.
|
|
32999
|
+
const sheetIdTo = env.model.uuidGenerator.smallUuid();
|
|
32913
33000
|
env.model.dispatch("DUPLICATE_SHEET", {
|
|
32914
33001
|
sheetId: sheetIdFrom,
|
|
32915
33002
|
sheetIdTo,
|
|
@@ -33015,6 +33102,100 @@ function* iterateChildren(el) {
|
|
|
33015
33102
|
function getOpenedMenus() {
|
|
33016
33103
|
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
33017
33104
|
}
|
|
33105
|
+
function getCurrentSelection(el) {
|
|
33106
|
+
let { startElement, endElement, startSelectionOffset, endSelectionOffset } = getStartAndEndSelection(el);
|
|
33107
|
+
let startSizeBefore = findSelectionIndex(el, startElement, startSelectionOffset);
|
|
33108
|
+
let endSizeBefore = findSelectionIndex(el, endElement, endSelectionOffset);
|
|
33109
|
+
return {
|
|
33110
|
+
start: startSizeBefore,
|
|
33111
|
+
end: endSizeBefore,
|
|
33112
|
+
};
|
|
33113
|
+
}
|
|
33114
|
+
function getStartAndEndSelection(el) {
|
|
33115
|
+
const selection = document.getSelection();
|
|
33116
|
+
return {
|
|
33117
|
+
startElement: selection.anchorNode || el,
|
|
33118
|
+
startSelectionOffset: selection.anchorOffset,
|
|
33119
|
+
endElement: selection.focusNode || el,
|
|
33120
|
+
endSelectionOffset: selection.focusOffset,
|
|
33121
|
+
};
|
|
33122
|
+
}
|
|
33123
|
+
/**
|
|
33124
|
+
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
33125
|
+
* The selected node is either a Text node or an Element node.
|
|
33126
|
+
*
|
|
33127
|
+
* case 1 -Text node:
|
|
33128
|
+
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
33129
|
+
* content length of all previous nodes.
|
|
33130
|
+
*
|
|
33131
|
+
* case 2 - Element node:
|
|
33132
|
+
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
33133
|
+
* all the nodes prior to the selected node as well as the content of the child node before the offset.
|
|
33134
|
+
*
|
|
33135
|
+
* See the MDN documentation for more details.
|
|
33136
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
33137
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
33138
|
+
*
|
|
33139
|
+
*/
|
|
33140
|
+
function findSelectionIndex(el, nodeToFind, nodeOffset) {
|
|
33141
|
+
let usedCharacters = 0;
|
|
33142
|
+
let it = iterateChildren(el);
|
|
33143
|
+
let current = it.next();
|
|
33144
|
+
let isFirstParagraph = true;
|
|
33145
|
+
while (!current.done && current.value !== nodeToFind) {
|
|
33146
|
+
if (!current.value.hasChildNodes()) {
|
|
33147
|
+
if (current.value.textContent) {
|
|
33148
|
+
usedCharacters += current.value.textContent.length;
|
|
33149
|
+
}
|
|
33150
|
+
}
|
|
33151
|
+
// One new paragraph = one new line character, except for the first paragraph
|
|
33152
|
+
if (current.value.nodeName === "P" ||
|
|
33153
|
+
(current.value.nodeName === "DIV" && current.value !== el) // On paste, the HTML may contain <div> instead of <p>
|
|
33154
|
+
) {
|
|
33155
|
+
if (isFirstParagraph) {
|
|
33156
|
+
isFirstParagraph = false;
|
|
33157
|
+
}
|
|
33158
|
+
else {
|
|
33159
|
+
usedCharacters++;
|
|
33160
|
+
}
|
|
33161
|
+
}
|
|
33162
|
+
current = it.next();
|
|
33163
|
+
}
|
|
33164
|
+
if (current.value !== nodeToFind) {
|
|
33165
|
+
/** This situation can happen if the code is called while the selection is not currently on the element.
|
|
33166
|
+
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
33167
|
+
*
|
|
33168
|
+
* A known occurrence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
33169
|
+
*/
|
|
33170
|
+
return 0;
|
|
33171
|
+
}
|
|
33172
|
+
else {
|
|
33173
|
+
if (!current.value.hasChildNodes()) {
|
|
33174
|
+
usedCharacters += nodeOffset;
|
|
33175
|
+
}
|
|
33176
|
+
else {
|
|
33177
|
+
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
33178
|
+
usedCharacters += children.reduce((acc, child, index) => {
|
|
33179
|
+
if (child.textContent !== null) {
|
|
33180
|
+
// need to account for paragraph nodes that implicitly add a new line
|
|
33181
|
+
// except for the last paragraph
|
|
33182
|
+
let chars = child.textContent.length;
|
|
33183
|
+
if (child.nodeName === "P" && index !== children.length - 1) {
|
|
33184
|
+
chars++;
|
|
33185
|
+
}
|
|
33186
|
+
return acc + chars;
|
|
33187
|
+
}
|
|
33188
|
+
else {
|
|
33189
|
+
return acc;
|
|
33190
|
+
}
|
|
33191
|
+
}, 0);
|
|
33192
|
+
}
|
|
33193
|
+
}
|
|
33194
|
+
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") {
|
|
33195
|
+
usedCharacters++;
|
|
33196
|
+
}
|
|
33197
|
+
return usedCharacters;
|
|
33198
|
+
}
|
|
33018
33199
|
const letterRegex = /^[a-zA-Z]$/;
|
|
33019
33200
|
/**
|
|
33020
33201
|
* Transform a keyboard event into a shortcut string that represent this event. The letters keys will be uppercased.
|
|
@@ -33612,20 +33793,21 @@ function getSmartChartDefinition(zone, getters) {
|
|
|
33612
33793
|
}
|
|
33613
33794
|
// Only display legend for several datasets.
|
|
33614
33795
|
const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
|
|
33615
|
-
const
|
|
33616
|
-
|
|
33617
|
-
|
|
33618
|
-
|
|
33619
|
-
|
|
33620
|
-
|
|
33621
|
-
|
|
33622
|
-
|
|
33623
|
-
|
|
33624
|
-
|
|
33625
|
-
|
|
33626
|
-
|
|
33627
|
-
|
|
33628
|
-
|
|
33796
|
+
const lineChartDefinition = {
|
|
33797
|
+
title: {},
|
|
33798
|
+
dataSets,
|
|
33799
|
+
labelsAsText: false,
|
|
33800
|
+
stacked: false,
|
|
33801
|
+
aggregated: false,
|
|
33802
|
+
cumulative: false,
|
|
33803
|
+
labelRange: labelRangeXc,
|
|
33804
|
+
type: "line",
|
|
33805
|
+
dataSetsHaveTitle,
|
|
33806
|
+
legendPosition: newLegendPos,
|
|
33807
|
+
};
|
|
33808
|
+
const chart = new LineChart(lineChartDefinition, sheetId, getters);
|
|
33809
|
+
if (canChartParseLabels(lineChartDefinition, chart.dataSets, chart.labelRange, getters)) {
|
|
33810
|
+
return lineChartDefinition;
|
|
33629
33811
|
}
|
|
33630
33812
|
const _dataSets = createDataSets(getters, dataSets, sheetId, dataSetsHaveTitle);
|
|
33631
33813
|
if (singleColumn &&
|
|
@@ -34039,7 +34221,7 @@ const HIDE_ROWS_NAME = (env) => {
|
|
|
34039
34221
|
//------------------------------------------------------------------------------
|
|
34040
34222
|
const CREATE_CHART = (env) => {
|
|
34041
34223
|
const getters = env.model.getters;
|
|
34042
|
-
const id = env.model.uuidGenerator.
|
|
34224
|
+
const id = env.model.uuidGenerator.smallUuid();
|
|
34043
34225
|
const sheetId = getters.getActiveSheetId();
|
|
34044
34226
|
if (getZoneArea(env.model.getters.getSelectedZone()) === 1) {
|
|
34045
34227
|
env.model.selection.selectTableAroundSelection();
|
|
@@ -34062,8 +34244,8 @@ const CREATE_CHART = (env) => {
|
|
|
34062
34244
|
// Pivots
|
|
34063
34245
|
//------------------------------------------------------------------------------
|
|
34064
34246
|
const CREATE_PIVOT = (env) => {
|
|
34065
|
-
const pivotId = env.model.uuidGenerator.
|
|
34066
|
-
const newSheetId = env.model.uuidGenerator.
|
|
34247
|
+
const pivotId = env.model.uuidGenerator.smallUuid();
|
|
34248
|
+
const newSheetId = env.model.uuidGenerator.smallUuid();
|
|
34067
34249
|
const result = env.model.dispatch("INSERT_NEW_PIVOT", { pivotId, newSheetId });
|
|
34068
34250
|
if (result.isSuccessful) {
|
|
34069
34251
|
env.openSidePanel("PivotSidePanel", { pivotId });
|
|
@@ -34122,7 +34304,7 @@ async function requestImage(env) {
|
|
|
34122
34304
|
const CREATE_IMAGE = async (env) => {
|
|
34123
34305
|
if (env.imageProvider) {
|
|
34124
34306
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
34125
|
-
const figureId = env.model.uuidGenerator.
|
|
34307
|
+
const figureId = env.model.uuidGenerator.smallUuid();
|
|
34126
34308
|
const image = await requestImage(env);
|
|
34127
34309
|
if (!image) {
|
|
34128
34310
|
throw new Error("No image provider was given to the environment");
|
|
@@ -34675,7 +34857,7 @@ const insertCheckbox = {
|
|
|
34675
34857
|
ranges,
|
|
34676
34858
|
sheetId,
|
|
34677
34859
|
rule: {
|
|
34678
|
-
id: env.model.uuidGenerator.
|
|
34860
|
+
id: env.model.uuidGenerator.smallUuid(),
|
|
34679
34861
|
criterion: {
|
|
34680
34862
|
type: "isBoolean",
|
|
34681
34863
|
values: [],
|
|
@@ -34691,7 +34873,7 @@ const insertDropdown = {
|
|
|
34691
34873
|
const zones = env.model.getters.getSelectedZones();
|
|
34692
34874
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
34693
34875
|
const ranges = zones.map((zone) => env.model.getters.getRangeDataFromZone(sheetId, zone));
|
|
34694
|
-
const ruleID = env.model.uuidGenerator.
|
|
34876
|
+
const ruleID = env.model.uuidGenerator.smallUuid();
|
|
34695
34877
|
env.model.dispatch("ADD_DATA_VALIDATION_RULE", {
|
|
34696
34878
|
ranges,
|
|
34697
34879
|
sheetId,
|
|
@@ -34722,7 +34904,7 @@ const insertSheet = {
|
|
|
34722
34904
|
execute: (env) => {
|
|
34723
34905
|
const activeSheetId = env.model.getters.getActiveSheetId();
|
|
34724
34906
|
const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
|
|
34725
|
-
const sheetId = env.model.uuidGenerator.
|
|
34907
|
+
const sheetId = env.model.uuidGenerator.smallUuid();
|
|
34726
34908
|
env.model.dispatch("CREATE_SHEET", { sheetId, position });
|
|
34727
34909
|
env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
|
|
34728
34910
|
},
|
|
@@ -38249,7 +38431,7 @@ css /* scss */ `
|
|
|
38249
38431
|
.o-font-size-editor {
|
|
38250
38432
|
height: calc(100% - 4px);
|
|
38251
38433
|
input.o-font-size {
|
|
38252
|
-
outline
|
|
38434
|
+
outline: none;
|
|
38253
38435
|
height: 20px;
|
|
38254
38436
|
width: 23px;
|
|
38255
38437
|
}
|
|
@@ -39211,7 +39393,7 @@ class LineConfigPanel extends GenericChartConfigPanel {
|
|
|
39211
39393
|
get canTreatLabelsAsText() {
|
|
39212
39394
|
const chart = this.env.model.getters.getChart(this.props.figureId);
|
|
39213
39395
|
if (chart && chart instanceof LineChart) {
|
|
39214
|
-
return canChartParseLabels(chart.labelRange, this.env.model.getters);
|
|
39396
|
+
return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
|
|
39215
39397
|
}
|
|
39216
39398
|
return false;
|
|
39217
39399
|
}
|
|
@@ -39288,7 +39470,7 @@ class ScatterConfigPanel extends GenericChartConfigPanel {
|
|
|
39288
39470
|
get canTreatLabelsAsText() {
|
|
39289
39471
|
const chart = this.env.model.getters.getChart(this.props.figureId);
|
|
39290
39472
|
if (chart && chart instanceof ScatterChart) {
|
|
39291
|
-
return canChartParseLabels(chart.labelRange, this.env.model.getters);
|
|
39473
|
+
return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
|
|
39292
39474
|
}
|
|
39293
39475
|
return false;
|
|
39294
39476
|
}
|
|
@@ -39862,6 +40044,10 @@ class ContentEditableHelper {
|
|
|
39862
40044
|
if (currentStart === start && currentEnd === end) {
|
|
39863
40045
|
return;
|
|
39864
40046
|
}
|
|
40047
|
+
if (selection.rangeCount === 0) {
|
|
40048
|
+
const range = document.createRange();
|
|
40049
|
+
selection.addRange(range);
|
|
40050
|
+
}
|
|
39865
40051
|
const currentRange = selection.getRangeAt(0);
|
|
39866
40052
|
let range;
|
|
39867
40053
|
if (this.el.contains(currentRange.startContainer)) {
|
|
@@ -39889,8 +40075,16 @@ class ContentEditableHelper {
|
|
|
39889
40075
|
}
|
|
39890
40076
|
let startNode = this.findChildAtCharacterIndex(start);
|
|
39891
40077
|
let endNode = this.findChildAtCharacterIndex(end);
|
|
39892
|
-
|
|
39893
|
-
|
|
40078
|
+
// setEnd (setStart) will result in a collapsed range if the end point is before the start point
|
|
40079
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Range/setEnd
|
|
40080
|
+
if (start <= end) {
|
|
40081
|
+
range.setStart(startNode.node, startNode.offset);
|
|
40082
|
+
range.setEnd(endNode.node, endNode.offset);
|
|
40083
|
+
}
|
|
40084
|
+
else {
|
|
40085
|
+
range.setStart(endNode.node, endNode.offset);
|
|
40086
|
+
range.setEnd(startNode.node, startNode.offset);
|
|
40087
|
+
}
|
|
39894
40088
|
}
|
|
39895
40089
|
}
|
|
39896
40090
|
/**
|
|
@@ -40024,7 +40218,7 @@ class ContentEditableHelper {
|
|
|
40024
40218
|
if (!focusedNode || !this.el.contains(focusedNode))
|
|
40025
40219
|
return;
|
|
40026
40220
|
const element = focusedNode instanceof HTMLElement ? focusedNode : focusedNode.parentElement;
|
|
40027
|
-
element?.scrollIntoView({ block: "nearest" });
|
|
40221
|
+
element?.scrollIntoView?.({ block: "nearest" });
|
|
40028
40222
|
}
|
|
40029
40223
|
/**
|
|
40030
40224
|
* remove the current selection of the user
|
|
@@ -40044,100 +40238,7 @@ class ContentEditableHelper {
|
|
|
40044
40238
|
* finds the indexes of the current selection.
|
|
40045
40239
|
* */
|
|
40046
40240
|
getCurrentSelection() {
|
|
40047
|
-
|
|
40048
|
-
let startSizeBefore = this.findSelectionIndex(startElement, startSelectionOffset);
|
|
40049
|
-
let endSizeBefore = this.findSelectionIndex(endElement, endSelectionOffset);
|
|
40050
|
-
return {
|
|
40051
|
-
start: startSizeBefore,
|
|
40052
|
-
end: endSizeBefore,
|
|
40053
|
-
};
|
|
40054
|
-
}
|
|
40055
|
-
/**
|
|
40056
|
-
* Computes the text 'index' inside this.el based on the currently selected node and its offset.
|
|
40057
|
-
* The selected node is either a Text node or an Element node.
|
|
40058
|
-
*
|
|
40059
|
-
* case 1 -Text node:
|
|
40060
|
-
* the offset is the number of characters from the start of the node. We have to add this offset to the
|
|
40061
|
-
* content length of all previous nodes.
|
|
40062
|
-
*
|
|
40063
|
-
* case 2 - Element node:
|
|
40064
|
-
* the offset is the number of child nodes before the selected node. We have to add the content length of
|
|
40065
|
-
* all the bnodes prior to the selected node as well as the content of the child node before the offset.
|
|
40066
|
-
*
|
|
40067
|
-
* See the MDN documentation for more details.
|
|
40068
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/startOffset
|
|
40069
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/Range/endOffset
|
|
40070
|
-
*
|
|
40071
|
-
*/
|
|
40072
|
-
findSelectionIndex(nodeToFind, nodeOffset) {
|
|
40073
|
-
let usedCharacters = 0;
|
|
40074
|
-
let it = iterateChildren(this.el);
|
|
40075
|
-
let current = it.next();
|
|
40076
|
-
let isFirstParagraph = true;
|
|
40077
|
-
while (!current.done && current.value !== nodeToFind) {
|
|
40078
|
-
if (!current.value.hasChildNodes()) {
|
|
40079
|
-
if (current.value.textContent) {
|
|
40080
|
-
usedCharacters += current.value.textContent.length;
|
|
40081
|
-
}
|
|
40082
|
-
}
|
|
40083
|
-
// One new paragraph = one new line character, except for the first paragraph
|
|
40084
|
-
if (current.value.nodeName === "P" ||
|
|
40085
|
-
(current.value.nodeName === "DIV" && current.value !== this.el) // On paste, the HTML may contain <div> instead of <p>
|
|
40086
|
-
) {
|
|
40087
|
-
if (isFirstParagraph) {
|
|
40088
|
-
isFirstParagraph = false;
|
|
40089
|
-
}
|
|
40090
|
-
else {
|
|
40091
|
-
usedCharacters++;
|
|
40092
|
-
}
|
|
40093
|
-
}
|
|
40094
|
-
current = it.next();
|
|
40095
|
-
}
|
|
40096
|
-
if (current.value !== nodeToFind) {
|
|
40097
|
-
/** This situation can happen if the code is called while the selection is not currently on the ContentEditableHelper.
|
|
40098
|
-
* In this case, we return 0 because we don't know the size of the text before the selection.
|
|
40099
|
-
*
|
|
40100
|
-
* A known occurence is triggered since the introduction of commit d4663158 (PR #2038).
|
|
40101
|
-
*
|
|
40102
|
-
* FIXME: find a way to test eventhough the selection API is not available in jsDOM.
|
|
40103
|
-
*/
|
|
40104
|
-
return 0;
|
|
40105
|
-
}
|
|
40106
|
-
else {
|
|
40107
|
-
if (!current.value.hasChildNodes()) {
|
|
40108
|
-
usedCharacters += nodeOffset;
|
|
40109
|
-
}
|
|
40110
|
-
else {
|
|
40111
|
-
const children = [...current.value.childNodes].slice(0, nodeOffset);
|
|
40112
|
-
usedCharacters += children.reduce((acc, child, index) => {
|
|
40113
|
-
if (child.textContent !== null) {
|
|
40114
|
-
// need to account for paragraph nodes that implicitely add a new line
|
|
40115
|
-
// except for the last paragraph
|
|
40116
|
-
let chars = child.textContent.length;
|
|
40117
|
-
if (child.nodeName === "P" && index !== children.length - 1) {
|
|
40118
|
-
chars++;
|
|
40119
|
-
}
|
|
40120
|
-
return acc + chars;
|
|
40121
|
-
}
|
|
40122
|
-
else {
|
|
40123
|
-
return acc;
|
|
40124
|
-
}
|
|
40125
|
-
}, 0);
|
|
40126
|
-
}
|
|
40127
|
-
}
|
|
40128
|
-
if (nodeToFind.nodeName === "P" && !isFirstParagraph && nodeToFind.textContent === "") {
|
|
40129
|
-
usedCharacters++;
|
|
40130
|
-
}
|
|
40131
|
-
return usedCharacters;
|
|
40132
|
-
}
|
|
40133
|
-
getStartAndEndSelection() {
|
|
40134
|
-
const selection = document.getSelection();
|
|
40135
|
-
return {
|
|
40136
|
-
startElement: selection.anchorNode || this.el,
|
|
40137
|
-
startSelectionOffset: selection.anchorOffset,
|
|
40138
|
-
endElement: selection.focusNode || this.el,
|
|
40139
|
-
endSelectionOffset: selection.focusOffset,
|
|
40140
|
-
};
|
|
40241
|
+
return getCurrentSelection(this.el);
|
|
40141
40242
|
}
|
|
40142
40243
|
getText() {
|
|
40143
40244
|
let text = "";
|
|
@@ -42066,7 +42167,7 @@ class ConditionalFormattingPanel extends Component {
|
|
|
42066
42167
|
this.originalEditedCf = undefined;
|
|
42067
42168
|
}
|
|
42068
42169
|
addConditionalFormat() {
|
|
42069
|
-
const cfId = this.env.model.uuidGenerator.
|
|
42170
|
+
const cfId = this.env.model.uuidGenerator.smallUuid();
|
|
42070
42171
|
this.env.model.dispatch("ADD_CONDITIONAL_FORMAT", {
|
|
42071
42172
|
sheetId: this.activeSheetId,
|
|
42072
42173
|
ranges: this.env.model.getters
|
|
@@ -43336,7 +43437,7 @@ class DataValidationEditor extends Component {
|
|
|
43336
43437
|
.getSelectedZones()
|
|
43337
43438
|
.map((zone) => zoneToXc(this.env.model.getters.getUnboundedZone(sheetId, zone)));
|
|
43338
43439
|
return {
|
|
43339
|
-
id: this.env.model.uuidGenerator.
|
|
43440
|
+
id: this.env.model.uuidGenerator.smallUuid(),
|
|
43340
43441
|
criterion: { type: "textContains", values: [""] },
|
|
43341
43442
|
ranges,
|
|
43342
43443
|
};
|
|
@@ -44954,8 +45055,8 @@ class PivotTitleSection extends Component {
|
|
|
44954
45055
|
return this.env.model.getters.getPivotDisplayName(this.props.pivotId);
|
|
44955
45056
|
}
|
|
44956
45057
|
duplicatePivot() {
|
|
44957
|
-
const newPivotId = this.env.model.uuidGenerator.
|
|
44958
|
-
const newSheetId = this.env.model.uuidGenerator.
|
|
45058
|
+
const newPivotId = this.env.model.uuidGenerator.smallUuid();
|
|
45059
|
+
const newSheetId = this.env.model.uuidGenerator.smallUuid();
|
|
44959
45060
|
const result = this.env.model.dispatch("DUPLICATE_PIVOT_IN_NEW_SHEET", {
|
|
44960
45061
|
pivotId: this.props.pivotId,
|
|
44961
45062
|
newPivotId,
|
|
@@ -47580,7 +47681,7 @@ class TableStyleEditorPanel extends Component {
|
|
|
47580
47681
|
this.state.selectedTemplateName = templateName;
|
|
47581
47682
|
}
|
|
47582
47683
|
onConfirm() {
|
|
47583
|
-
const tableStyleId = this.props.styleId || this.env.model.uuidGenerator.
|
|
47684
|
+
const tableStyleId = this.props.styleId || this.env.model.uuidGenerator.smallUuid();
|
|
47584
47685
|
this.env.model.dispatch("CREATE_TABLE_STYLE", {
|
|
47585
47686
|
tableStyleId,
|
|
47586
47687
|
tableStyleName: this.state.styleName,
|
|
@@ -53092,6 +53193,10 @@ class CellPlugin extends CorePlugin {
|
|
|
53092
53193
|
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessUpdateCell);
|
|
53093
53194
|
case "CLEAR_CELL":
|
|
53094
53195
|
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessClearCell);
|
|
53196
|
+
case "UPDATE_CELL_POSITION":
|
|
53197
|
+
return !cmd.cellId || this.cells[cmd.sheetId]?.[cmd.cellId]
|
|
53198
|
+
? "Success" /* CommandResult.Success */
|
|
53199
|
+
: "InvalidCellId" /* CommandResult.InvalidCellId */;
|
|
53095
53200
|
default:
|
|
53096
53201
|
return "Success" /* CommandResult.Success */;
|
|
53097
53202
|
}
|
|
@@ -53136,6 +53241,9 @@ class CellPlugin extends CorePlugin {
|
|
|
53136
53241
|
case "DELETE_CONTENT":
|
|
53137
53242
|
this.clearZones(cmd.sheetId, cmd.target);
|
|
53138
53243
|
break;
|
|
53244
|
+
case "DELETE_SHEET": {
|
|
53245
|
+
this.history.update("cells", cmd.sheetId, undefined);
|
|
53246
|
+
}
|
|
53139
53247
|
}
|
|
53140
53248
|
}
|
|
53141
53249
|
clearZones(sheetId, zones) {
|
|
@@ -53926,6 +54034,9 @@ class ConditionalFormatPlugin extends CorePlugin {
|
|
|
53926
54034
|
allowDispatch(cmd) {
|
|
53927
54035
|
switch (cmd.type) {
|
|
53928
54036
|
case "ADD_CONDITIONAL_FORMAT":
|
|
54037
|
+
if (cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
|
|
54038
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
54039
|
+
}
|
|
53929
54040
|
return this.checkValidations(cmd, this.checkCFRule, this.checkEmptyRange, this.checkCFHasChanged);
|
|
53930
54041
|
case "CHANGE_CONDITIONAL_FORMAT_PRIORITY":
|
|
53931
54042
|
return this.checkValidPriorityChange(cmd.cfId, cmd.delta, cmd.sheetId);
|
|
@@ -54342,8 +54453,17 @@ class DataValidationPlugin extends CorePlugin {
|
|
|
54342
54453
|
allowDispatch(cmd) {
|
|
54343
54454
|
switch (cmd.type) {
|
|
54344
54455
|
case "ADD_DATA_VALIDATION_RULE":
|
|
54456
|
+
if (!this.getters.tryGetSheet(cmd.sheetId)) {
|
|
54457
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
54458
|
+
}
|
|
54459
|
+
if (cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
|
|
54460
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
54461
|
+
}
|
|
54345
54462
|
return this.checkValidations(cmd, this.chainValidations(this.checkEmptyRange, this.checkValidRange, this.checkCriterionTypeIsValid, this.checkCriterionHasValidNumberOfValues, this.checkCriterionValuesAreValid));
|
|
54346
54463
|
case "REMOVE_DATA_VALIDATION_RULE":
|
|
54464
|
+
if (!this.getters.tryGetSheet(cmd.sheetId)) {
|
|
54465
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
54466
|
+
}
|
|
54347
54467
|
if (!this.rules[cmd.sheetId].find((rule) => rule.id === cmd.id)) {
|
|
54348
54468
|
return "UnknownDataValidationRule" /* CommandResult.UnknownDataValidationRule */;
|
|
54349
54469
|
}
|
|
@@ -54570,6 +54690,7 @@ class DataValidationPlugin extends CorePlugin {
|
|
|
54570
54690
|
class FigurePlugin extends CorePlugin {
|
|
54571
54691
|
static getters = ["getFigures", "getFigure", "getFigureSheetId"];
|
|
54572
54692
|
figures = {};
|
|
54693
|
+
insertionOrders = []; // TODO use a list in master
|
|
54573
54694
|
// ---------------------------------------------------------------------------
|
|
54574
54695
|
// Command Handling
|
|
54575
54696
|
// ---------------------------------------------------------------------------
|
|
@@ -54672,11 +54793,14 @@ class FigurePlugin extends CorePlugin {
|
|
|
54672
54793
|
}
|
|
54673
54794
|
addFigure(figure, sheetId) {
|
|
54674
54795
|
this.history.update("figures", sheetId, figure.id, figure);
|
|
54796
|
+
this.history.update("insertionOrders", this.insertionOrders.length, figure.id);
|
|
54675
54797
|
}
|
|
54676
54798
|
deleteSheet(sheetId) {
|
|
54799
|
+
this.history.update("insertionOrders", this.insertionOrders.filter((id) => !this.figures[sheetId]?.[id]));
|
|
54677
54800
|
this.history.update("figures", sheetId, undefined);
|
|
54678
54801
|
}
|
|
54679
54802
|
removeFigure(id, sheetId) {
|
|
54803
|
+
this.history.update("insertionOrders", this.insertionOrders.filter((figureId) => figureId !== id));
|
|
54680
54804
|
this.history.update("figures", sheetId, id, undefined);
|
|
54681
54805
|
}
|
|
54682
54806
|
checkFigureExists(sheetId, figureId) {
|
|
@@ -54695,7 +54819,14 @@ class FigurePlugin extends CorePlugin {
|
|
|
54695
54819
|
// Getters
|
|
54696
54820
|
// ---------------------------------------------------------------------------
|
|
54697
54821
|
getFigures(sheetId) {
|
|
54698
|
-
|
|
54822
|
+
const figures = [];
|
|
54823
|
+
for (const figureId of this.insertionOrders) {
|
|
54824
|
+
const figure = this.figures[sheetId]?.[figureId];
|
|
54825
|
+
if (figure) {
|
|
54826
|
+
figures.push(figure);
|
|
54827
|
+
}
|
|
54828
|
+
}
|
|
54829
|
+
return figures;
|
|
54699
54830
|
}
|
|
54700
54831
|
getFigure(sheetId, figureId) {
|
|
54701
54832
|
return this.figures[sheetId]?.[figureId];
|
|
@@ -54708,11 +54839,9 @@ class FigurePlugin extends CorePlugin {
|
|
|
54708
54839
|
// ---------------------------------------------------------------------------
|
|
54709
54840
|
import(data) {
|
|
54710
54841
|
for (let sheet of data.sheets) {
|
|
54711
|
-
const figures
|
|
54712
|
-
|
|
54713
|
-
|
|
54714
|
-
});
|
|
54715
|
-
this.figures[sheet.id] = figures;
|
|
54842
|
+
for (const figure of sheet.figures) {
|
|
54843
|
+
this.addFigure(figure, sheet.id);
|
|
54844
|
+
}
|
|
54716
54845
|
}
|
|
54717
54846
|
}
|
|
54718
54847
|
export(data) {
|
|
@@ -56138,6 +56267,9 @@ class SheetPlugin extends CorePlugin {
|
|
|
56138
56267
|
case "CREATE_SHEET": {
|
|
56139
56268
|
return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
|
|
56140
56269
|
}
|
|
56270
|
+
case "DUPLICATE_SHEET": {
|
|
56271
|
+
return this.sheets[cmd.sheetIdTo] ? "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */ : "Success" /* CommandResult.Success */;
|
|
56272
|
+
}
|
|
56141
56273
|
case "MOVE_SHEET":
|
|
56142
56274
|
try {
|
|
56143
56275
|
const currentIndex = this.orderedSheetIds.findIndex((id) => id === cmd.sheetId);
|
|
@@ -56154,7 +56286,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
56154
56286
|
? "Success" /* CommandResult.Success */
|
|
56155
56287
|
: "InvalidColor" /* CommandResult.InvalidColor */;
|
|
56156
56288
|
case "DELETE_SHEET":
|
|
56157
|
-
return this.
|
|
56289
|
+
return this.getVisibleSheetIds().length > 1
|
|
56158
56290
|
? "Success" /* CommandResult.Success */
|
|
56159
56291
|
: "NotEnoughSheets" /* CommandResult.NotEnoughSheets */;
|
|
56160
56292
|
case "ADD_COLUMNS_ROWS":
|
|
@@ -56949,6 +57081,10 @@ class SheetPlugin extends CorePlugin {
|
|
|
56949
57081
|
checkZonesAreInSheet(cmd) {
|
|
56950
57082
|
if (!("sheetId" in cmd))
|
|
56951
57083
|
return "Success" /* CommandResult.Success */;
|
|
57084
|
+
if ("ranges" in cmd &&
|
|
57085
|
+
cmd.ranges.some((rangeData) => rangeData._sheetId !== "" && !this.getters.tryGetSheet(rangeData._sheetId))) {
|
|
57086
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
57087
|
+
}
|
|
56952
57088
|
return this.checkZonesExistInSheet(cmd.sheetId, this.getCommandZones(cmd));
|
|
56953
57089
|
}
|
|
56954
57090
|
}
|
|
@@ -56957,6 +57093,7 @@ let nextTableId = 1;
|
|
|
56957
57093
|
class TablePlugin extends CorePlugin {
|
|
56958
57094
|
static getters = ["getCoreTable", "getCoreTables", "getCoreTableMatchingTopLeft"];
|
|
56959
57095
|
tables = {};
|
|
57096
|
+
insertionOrders = {};
|
|
56960
57097
|
adaptRanges(applyChange, sheetId) {
|
|
56961
57098
|
const sheetIds = sheetId ? [sheetId] : this.getters.getSheetIds();
|
|
56962
57099
|
for (const sheetId of sheetIds) {
|
|
@@ -56968,6 +57105,9 @@ class TablePlugin extends CorePlugin {
|
|
|
56968
57105
|
allowDispatch(cmd) {
|
|
56969
57106
|
switch (cmd.type) {
|
|
56970
57107
|
case "CREATE_TABLE":
|
|
57108
|
+
if (cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId) || rangeData._sheetId !== cmd.sheetId)) {
|
|
57109
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
57110
|
+
}
|
|
56971
57111
|
const zones = cmd.ranges.map((rangeData) => this.getters.getRangeFromRangeData(rangeData).zone);
|
|
56972
57112
|
if (!areZonesContinuous(zones)) {
|
|
56973
57113
|
return "NonContinuousTargets" /* CommandResult.NonContinuousTargets */;
|
|
@@ -56998,11 +57138,13 @@ class TablePlugin extends CorePlugin {
|
|
|
56998
57138
|
switch (cmd.type) {
|
|
56999
57139
|
case "CREATE_SHEET":
|
|
57000
57140
|
this.history.update("tables", cmd.sheetId, {});
|
|
57141
|
+
this.history.update("insertionOrders", cmd.sheetId, []);
|
|
57001
57142
|
break;
|
|
57002
57143
|
case "DELETE_SHEET": {
|
|
57003
57144
|
const tables = { ...this.tables };
|
|
57004
57145
|
delete tables[cmd.sheetId];
|
|
57005
57146
|
this.history.update("tables", tables);
|
|
57147
|
+
this.history.update("insertionOrders", cmd.sheetId, undefined);
|
|
57006
57148
|
break;
|
|
57007
57149
|
}
|
|
57008
57150
|
case "DUPLICATE_SHEET": {
|
|
@@ -57014,6 +57156,9 @@ class TablePlugin extends CorePlugin {
|
|
|
57014
57156
|
: this.copyStaticTableForSheet(cmd.sheetIdTo, table);
|
|
57015
57157
|
}
|
|
57016
57158
|
this.history.update("tables", cmd.sheetIdTo, newTables);
|
|
57159
|
+
this.history.update("insertionOrders", cmd.sheetIdTo, [
|
|
57160
|
+
...(this.insertionOrders[cmd.sheetId] ?? []),
|
|
57161
|
+
]);
|
|
57017
57162
|
break;
|
|
57018
57163
|
}
|
|
57019
57164
|
case "CREATE_TABLE": {
|
|
@@ -57027,6 +57172,10 @@ class TablePlugin extends CorePlugin {
|
|
|
57027
57172
|
? this.createDynamicTable(id, union, config)
|
|
57028
57173
|
: this.createStaticTable(id, cmd.tableType, union, config);
|
|
57029
57174
|
this.history.update("tables", cmd.sheetId, newTable.id, newTable);
|
|
57175
|
+
this.history.update("insertionOrders", cmd.sheetId, [
|
|
57176
|
+
...(this.insertionOrders[cmd.sheetId] ?? []),
|
|
57177
|
+
newTable.id,
|
|
57178
|
+
]);
|
|
57030
57179
|
break;
|
|
57031
57180
|
}
|
|
57032
57181
|
case "REMOVE_TABLE": {
|
|
@@ -57037,6 +57186,7 @@ class TablePlugin extends CorePlugin {
|
|
|
57037
57186
|
}
|
|
57038
57187
|
}
|
|
57039
57188
|
this.history.update("tables", cmd.sheetId, tables);
|
|
57189
|
+
this.history.update("insertionOrders", cmd.sheetId, this.insertionOrders[cmd.sheetId]?.filter((id) => id in tables));
|
|
57040
57190
|
break;
|
|
57041
57191
|
}
|
|
57042
57192
|
case "UPDATE_TABLE": {
|
|
@@ -57072,7 +57222,14 @@ class TablePlugin extends CorePlugin {
|
|
|
57072
57222
|
}
|
|
57073
57223
|
}
|
|
57074
57224
|
getCoreTables(sheetId) {
|
|
57075
|
-
|
|
57225
|
+
const tables = [];
|
|
57226
|
+
for (const tableId of this.insertionOrders[sheetId] || []) {
|
|
57227
|
+
const table = this.tables[sheetId][tableId];
|
|
57228
|
+
if (table) {
|
|
57229
|
+
tables.push(table);
|
|
57230
|
+
}
|
|
57231
|
+
}
|
|
57232
|
+
return tables;
|
|
57076
57233
|
}
|
|
57077
57234
|
getCoreTable({ sheetId, col, row }) {
|
|
57078
57235
|
return this.getCoreTables(sheetId).find((table) => isInside(col, row, table.range.zone));
|
|
@@ -57355,6 +57512,7 @@ class TablePlugin extends CorePlugin {
|
|
|
57355
57512
|
// ---------------------------------------------------------------------------
|
|
57356
57513
|
import(data) {
|
|
57357
57514
|
for (const sheet of data.sheets) {
|
|
57515
|
+
const tableIds = [];
|
|
57358
57516
|
for (const tableData of sheet.tables || []) {
|
|
57359
57517
|
const uuid = `${nextTableId++}`;
|
|
57360
57518
|
const tableConfig = tableData.config || DEFAULT_TABLE_CONFIG;
|
|
@@ -57364,7 +57522,9 @@ class TablePlugin extends CorePlugin {
|
|
|
57364
57522
|
? this.createDynamicTable(uuid, range, tableConfig)
|
|
57365
57523
|
: this.createStaticTable(uuid, tableType, range, tableConfig);
|
|
57366
57524
|
this.history.update("tables", sheet.id, table.id, table);
|
|
57525
|
+
tableIds.push(table.id);
|
|
57367
57526
|
}
|
|
57527
|
+
this.history.update("insertionOrders", sheet.id, tableIds);
|
|
57368
57528
|
}
|
|
57369
57529
|
}
|
|
57370
57530
|
export(data) {
|
|
@@ -57404,7 +57564,10 @@ class HeaderGroupingPlugin extends CorePlugin {
|
|
|
57404
57564
|
allowDispatch(cmd) {
|
|
57405
57565
|
switch (cmd.type) {
|
|
57406
57566
|
case "GROUP_HEADERS": {
|
|
57407
|
-
const { start, end } = cmd;
|
|
57567
|
+
const { start, end, sheetId } = cmd;
|
|
57568
|
+
if (!this.getters.tryGetSheet(sheetId)) {
|
|
57569
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
57570
|
+
}
|
|
57408
57571
|
if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
|
|
57409
57572
|
return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
|
|
57410
57573
|
}
|
|
@@ -57417,7 +57580,10 @@ class HeaderGroupingPlugin extends CorePlugin {
|
|
|
57417
57580
|
break;
|
|
57418
57581
|
}
|
|
57419
57582
|
case "UNGROUP_HEADERS": {
|
|
57420
|
-
const { start, end } = cmd;
|
|
57583
|
+
const { start, end, sheetId } = cmd;
|
|
57584
|
+
if (!this.getters.tryGetSheet(sheetId)) {
|
|
57585
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
57586
|
+
}
|
|
57421
57587
|
if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
|
|
57422
57588
|
return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
|
|
57423
57589
|
}
|
|
@@ -57428,6 +57594,9 @@ class HeaderGroupingPlugin extends CorePlugin {
|
|
|
57428
57594
|
}
|
|
57429
57595
|
case "UNFOLD_HEADER_GROUP":
|
|
57430
57596
|
case "FOLD_HEADER_GROUP":
|
|
57597
|
+
if (!this.getters.tryGetSheet(cmd.sheetId)) {
|
|
57598
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
57599
|
+
}
|
|
57431
57600
|
const group = this.findGroupWithStartEnd(cmd.sheetId, cmd.dimension, cmd.start, cmd.end);
|
|
57432
57601
|
if (!group) {
|
|
57433
57602
|
return "UnknownHeaderGroup" /* CommandResult.UnknownHeaderGroup */;
|
|
@@ -57828,6 +57997,9 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
57828
57997
|
return this.checkDuplicatedMeasureIds(cmd.pivot);
|
|
57829
57998
|
}
|
|
57830
57999
|
case "UPDATE_PIVOT": {
|
|
58000
|
+
if (!(cmd.pivotId in this.pivots)) {
|
|
58001
|
+
return "PivotIdNotFound" /* CommandResult.PivotIdNotFound */;
|
|
58002
|
+
}
|
|
57831
58003
|
if (deepEquals(cmd.pivot, this.pivots[cmd.pivotId]?.definition)) {
|
|
57832
58004
|
return "NoChanges" /* CommandResult.NoChanges */;
|
|
57833
58005
|
}
|
|
@@ -57844,6 +58016,8 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
57844
58016
|
return "EmptyName" /* CommandResult.EmptyName */;
|
|
57845
58017
|
}
|
|
57846
58018
|
break;
|
|
58019
|
+
case "REMOVE_PIVOT":
|
|
58020
|
+
case "DUPLICATE_PIVOT":
|
|
57847
58021
|
case "INSERT_PIVOT": {
|
|
57848
58022
|
if (!(cmd.pivotId in this.pivots)) {
|
|
57849
58023
|
return "PivotIdNotFound" /* CommandResult.PivotIdNotFound */;
|
|
@@ -57893,7 +58067,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
57893
58067
|
break;
|
|
57894
58068
|
}
|
|
57895
58069
|
case "UPDATE_PIVOT": {
|
|
57896
|
-
this.history.update("pivots", cmd.pivotId, "definition", cmd.pivot);
|
|
58070
|
+
this.history.update("pivots", cmd.pivotId, "definition", deepCopy(cmd.pivot));
|
|
57897
58071
|
this.compileCalculatedMeasures(cmd.pivot.measures);
|
|
57898
58072
|
break;
|
|
57899
58073
|
}
|
|
@@ -57964,7 +58138,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
57964
58138
|
// Private
|
|
57965
58139
|
// -------------------------------------------------------------------------
|
|
57966
58140
|
addPivot(pivotId, pivot, formulaId = this.nextFormulaId.toString()) {
|
|
57967
|
-
this.history.update("pivots", pivotId, { definition: pivot, formulaId });
|
|
58141
|
+
this.history.update("pivots", pivotId, { definition: deepCopy(pivot), formulaId });
|
|
57968
58142
|
this.compileCalculatedMeasures(pivot.measures);
|
|
57969
58143
|
this.history.update("formulaIds", formulaId, pivotId);
|
|
57970
58144
|
this.history.update("nextFormulaId", this.nextFormulaId + 1);
|
|
@@ -59550,6 +59724,10 @@ class Evaluator {
|
|
|
59550
59724
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
59551
59725
|
this.compilationParams.evalContext.updateDependencies = this.updateDependencies.bind(this);
|
|
59552
59726
|
this.compilationParams.evalContext.addDependencies = this.addDependencies.bind(this);
|
|
59727
|
+
this.compilationParams.evalContext.lookupCaches = {
|
|
59728
|
+
forwardSearch: new Map(),
|
|
59729
|
+
reverseSearch: new Map(),
|
|
59730
|
+
};
|
|
59553
59731
|
}
|
|
59554
59732
|
createEmptyPositionSet() {
|
|
59555
59733
|
const sheetSizes = {};
|
|
@@ -62870,6 +63048,9 @@ function updateChartRangesTransformation(toTransform, executed) {
|
|
|
62870
63048
|
};
|
|
62871
63049
|
}
|
|
62872
63050
|
function createSheetTransformation(toTransform, executed) {
|
|
63051
|
+
if (toTransform.sheetId === executed.sheetId) {
|
|
63052
|
+
toTransform = { ...toTransform, sheetId: `${toTransform.sheetId}~` };
|
|
63053
|
+
}
|
|
62873
63054
|
if (toTransform.name === executed.name) {
|
|
62874
63055
|
return {
|
|
62875
63056
|
...toTransform,
|
|
@@ -63521,21 +63702,14 @@ class Session extends EventBus {
|
|
|
63521
63702
|
if (!message)
|
|
63522
63703
|
return;
|
|
63523
63704
|
if (message.type === "REMOTE_REVISION") {
|
|
63524
|
-
|
|
63705
|
+
let revision = this.revisions.get(message.nextRevisionId);
|
|
63525
63706
|
if (revision.commands.length === 0) {
|
|
63526
63707
|
/**
|
|
63527
|
-
* The command is empty, we have to
|
|
63708
|
+
* The command is empty, we have to rebase all the next local revisions
|
|
63528
63709
|
* to avoid issues with undo/redo
|
|
63529
63710
|
*/
|
|
63530
|
-
this.revisions.
|
|
63531
|
-
|
|
63532
|
-
.filter((message) => message.type === "REMOTE_REVISION")
|
|
63533
|
-
.map((message) => message.nextRevisionId);
|
|
63534
|
-
this.trigger("pending-revisions-dropped", { revisionIds });
|
|
63535
|
-
this.waitingAck = false;
|
|
63536
|
-
this.waitingUndoRedoAck = false;
|
|
63537
|
-
this.pendingMessages = [];
|
|
63538
|
-
return;
|
|
63711
|
+
this.revisions.rebase(revision.id);
|
|
63712
|
+
revision = this.revisions.get(message.nextRevisionId);
|
|
63539
63713
|
}
|
|
63540
63714
|
message = {
|
|
63541
63715
|
...message,
|
|
@@ -63560,7 +63734,6 @@ class Session extends EventBus {
|
|
|
63560
63734
|
switch (message.type) {
|
|
63561
63735
|
case "REMOTE_REVISION":
|
|
63562
63736
|
case "REVISION_REDONE":
|
|
63563
|
-
case "REVISION_UNDONE":
|
|
63564
63737
|
case "SNAPSHOT_CREATED":
|
|
63565
63738
|
this.waitingAck = false;
|
|
63566
63739
|
this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
|
|
@@ -63569,6 +63742,25 @@ class Session extends EventBus {
|
|
|
63569
63742
|
this.lastRevisionMessage = message;
|
|
63570
63743
|
this.sendPendingMessage();
|
|
63571
63744
|
break;
|
|
63745
|
+
case "REVISION_UNDONE": {
|
|
63746
|
+
this.waitingAck = false;
|
|
63747
|
+
this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
|
|
63748
|
+
const firstPendingRevisionId = this.pendingMessages.findIndex((message) => message.type === "REMOTE_REVISION");
|
|
63749
|
+
if (firstPendingRevisionId !== -1) {
|
|
63750
|
+
/**
|
|
63751
|
+
* Some revisions undergo transformations that may cause issues with
|
|
63752
|
+
* undo/redo if the transformation is destructive (we don't get back
|
|
63753
|
+
* the original command by transforming it with the inverse).
|
|
63754
|
+
* To prevent these problems, we must rebase all subsequent local
|
|
63755
|
+
* revisions.
|
|
63756
|
+
*/
|
|
63757
|
+
this.revisions.rebase(this.pendingMessages[firstPendingRevisionId].nextRevisionId);
|
|
63758
|
+
}
|
|
63759
|
+
this.serverRevisionId = message.nextRevisionId;
|
|
63760
|
+
this.processedRevisions.add(message.nextRevisionId);
|
|
63761
|
+
this.sendPendingMessage();
|
|
63762
|
+
break;
|
|
63763
|
+
}
|
|
63572
63764
|
}
|
|
63573
63765
|
}
|
|
63574
63766
|
isAlreadyProcessed(message) {
|
|
@@ -64690,6 +64882,10 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
64690
64882
|
*/
|
|
64691
64883
|
checkZonesAreInSheet(cmd) {
|
|
64692
64884
|
const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.tryGetActiveSheetId();
|
|
64885
|
+
if ("ranges" in cmd &&
|
|
64886
|
+
cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
|
|
64887
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
64888
|
+
}
|
|
64693
64889
|
const zones = this.getters.getCommandZones(cmd);
|
|
64694
64890
|
if (!sheetId && zones.length > 0) {
|
|
64695
64891
|
return "NoActiveSheet" /* CommandResult.NoActiveSheet */;
|
|
@@ -65039,23 +65235,23 @@ const uuidGenerator = new UuidGenerator();
|
|
|
65039
65235
|
function repeatCreateChartCommand(getters, cmd) {
|
|
65040
65236
|
return {
|
|
65041
65237
|
...repeatSheetDependantCommand(getters, cmd),
|
|
65042
|
-
id: uuidGenerator.
|
|
65238
|
+
id: uuidGenerator.smallUuid(),
|
|
65043
65239
|
};
|
|
65044
65240
|
}
|
|
65045
65241
|
function repeatCreateImageCommand(getters, cmd) {
|
|
65046
65242
|
return {
|
|
65047
65243
|
...repeatSheetDependantCommand(getters, cmd),
|
|
65048
|
-
figureId: uuidGenerator.
|
|
65244
|
+
figureId: uuidGenerator.smallUuid(),
|
|
65049
65245
|
};
|
|
65050
65246
|
}
|
|
65051
65247
|
function repeatCreateFigureCommand(getters, cmd) {
|
|
65052
65248
|
const newCmd = repeatSheetDependantCommand(getters, cmd);
|
|
65053
|
-
newCmd.figure.id = uuidGenerator.
|
|
65249
|
+
newCmd.figure.id = uuidGenerator.smallUuid();
|
|
65054
65250
|
return newCmd;
|
|
65055
65251
|
}
|
|
65056
65252
|
function repeatCreateSheetCommand(getters, cmd) {
|
|
65057
65253
|
const newCmd = deepCopy(cmd);
|
|
65058
|
-
newCmd.sheetId = uuidGenerator.
|
|
65254
|
+
newCmd.sheetId = uuidGenerator.smallUuid();
|
|
65059
65255
|
const sheetName = cmd.name || getters.getSheet(getters.getActiveSheetId()).name;
|
|
65060
65256
|
// Extract the prefix of the sheet name (everything before the number at the end of the name)
|
|
65061
65257
|
const namePrefix = sheetName.match(/(.+?)\d*$/)?.[1] || sheetName;
|
|
@@ -65244,7 +65440,6 @@ class HistoryPlugin extends UIPlugin {
|
|
|
65244
65440
|
super(config);
|
|
65245
65441
|
this.session = config.session;
|
|
65246
65442
|
this.session.on("new-local-state-update", this, this.onNewLocalStateUpdate);
|
|
65247
|
-
this.session.on("pending-revisions-dropped", this, ({ revisionIds }) => this.drop(revisionIds));
|
|
65248
65443
|
this.session.on("snapshot", this, () => {
|
|
65249
65444
|
this.undoStack = [];
|
|
65250
65445
|
this.redoStack = [];
|
|
@@ -65314,10 +65509,6 @@ class HistoryPlugin extends UIPlugin {
|
|
|
65314
65509
|
const lastNonRedoRevision = this.getPossibleRevisionToRepeat();
|
|
65315
65510
|
return canRepeatRevision(lastNonRedoRevision);
|
|
65316
65511
|
}
|
|
65317
|
-
drop(revisionIds) {
|
|
65318
|
-
this.undoStack = this.undoStack.filter((id) => !revisionIds.includes(id));
|
|
65319
|
-
this.redoStack = [];
|
|
65320
|
-
}
|
|
65321
65512
|
onNewLocalStateUpdate({ id }) {
|
|
65322
65513
|
this.undoStack.push(id);
|
|
65323
65514
|
this.redoStack = [];
|
|
@@ -66518,23 +66709,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
66518
66709
|
gridSelection: deepCopy(gridSelection),
|
|
66519
66710
|
};
|
|
66520
66711
|
}
|
|
66521
|
-
|
|
66522
|
-
const currentSheetIds = this.getters.getVisibleSheetIds();
|
|
66523
|
-
this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
|
|
66524
|
-
if (this.activeSheet.id in this.sheetsData) {
|
|
66525
|
-
const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
|
|
66526
|
-
this.selectCell(anchor.cell.col, anchor.cell.row);
|
|
66527
|
-
}
|
|
66528
|
-
else {
|
|
66529
|
-
this.selectCell(0, 0);
|
|
66530
|
-
}
|
|
66531
|
-
const { col, row } = this.gridSelection.anchor.cell;
|
|
66532
|
-
this.moveClient({
|
|
66533
|
-
sheetId: this.getters.getActiveSheetId(),
|
|
66534
|
-
col,
|
|
66535
|
-
row,
|
|
66536
|
-
});
|
|
66537
|
-
}
|
|
66712
|
+
this.fallbackToVisibleSheet();
|
|
66538
66713
|
const sheetId = this.getters.getActiveSheetId();
|
|
66539
66714
|
this.gridSelection.zones = this.gridSelection.zones.map((z) => this.getters.expandZone(sheetId, z));
|
|
66540
66715
|
this.gridSelection.anchor.zone = this.getters.expandZone(sheetId, this.gridSelection.anchor.zone);
|
|
@@ -66544,6 +66719,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
66544
66719
|
}
|
|
66545
66720
|
}
|
|
66546
66721
|
finalize() {
|
|
66722
|
+
this.fallbackToVisibleSheet();
|
|
66547
66723
|
/** Any change to the selection has to be reflected in the selection processor. */
|
|
66548
66724
|
this.selection.resetDefaultAnchor(this, deepCopy(this.gridSelection.anchor));
|
|
66549
66725
|
}
|
|
@@ -66854,6 +67030,25 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
66854
67030
|
}
|
|
66855
67031
|
return "Success" /* CommandResult.Success */;
|
|
66856
67032
|
}
|
|
67033
|
+
fallbackToVisibleSheet() {
|
|
67034
|
+
if (!this.getters.tryGetSheet(this.getters.getActiveSheetId())) {
|
|
67035
|
+
const currentSheetIds = this.getters.getVisibleSheetIds();
|
|
67036
|
+
this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
|
|
67037
|
+
if (this.activeSheet.id in this.sheetsData) {
|
|
67038
|
+
const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
|
|
67039
|
+
this.selectCell(anchor.cell.col, anchor.cell.row);
|
|
67040
|
+
}
|
|
67041
|
+
else {
|
|
67042
|
+
this.selectCell(0, 0);
|
|
67043
|
+
}
|
|
67044
|
+
const { col, row } = this.gridSelection.anchor.cell;
|
|
67045
|
+
this.moveClient({
|
|
67046
|
+
sheetId: this.getters.getActiveSheetId(),
|
|
67047
|
+
col,
|
|
67048
|
+
row,
|
|
67049
|
+
});
|
|
67050
|
+
}
|
|
67051
|
+
}
|
|
66857
67052
|
//-------------------------------------------
|
|
66858
67053
|
// Helpers for extensions
|
|
66859
67054
|
// ------------------------------------------
|
|
@@ -68017,7 +68212,9 @@ class HeaderPositionsUIPlugin extends UIPlugin {
|
|
|
68017
68212
|
case "UNGROUP_HEADERS":
|
|
68018
68213
|
case "GROUP_HEADERS":
|
|
68019
68214
|
case "CREATE_SHEET":
|
|
68020
|
-
this.
|
|
68215
|
+
if (this.getters.tryGetSheet(cmd.sheetId)) {
|
|
68216
|
+
this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
|
|
68217
|
+
}
|
|
68021
68218
|
break;
|
|
68022
68219
|
case "DUPLICATE_SHEET":
|
|
68023
68220
|
this.headerPositions[cmd.sheetIdTo] = deepCopy(this.headerPositions[cmd.sheetId]);
|
|
@@ -68025,12 +68222,14 @@ class HeaderPositionsUIPlugin extends UIPlugin {
|
|
|
68025
68222
|
}
|
|
68026
68223
|
}
|
|
68027
68224
|
finalize() {
|
|
68028
|
-
|
|
68029
|
-
|
|
68225
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
68226
|
+
// sheets can be created without this plugin being aware of it
|
|
68227
|
+
// in concurrent situations.
|
|
68228
|
+
if (this.isDirty || !this.headerPositions[sheetId]) {
|
|
68030
68229
|
this.headerPositions[sheetId] = this.computeHeaderPositionsOfSheet(sheetId);
|
|
68031
68230
|
}
|
|
68032
|
-
this.isDirty = false;
|
|
68033
68231
|
}
|
|
68232
|
+
this.isDirty = false;
|
|
68034
68233
|
}
|
|
68035
68234
|
/**
|
|
68036
68235
|
* Returns the size, start and end coordinates of a column on an unfolded sheet
|
|
@@ -68854,7 +69053,7 @@ class BottomBar extends Component {
|
|
|
68854
69053
|
clickAddSheet(ev) {
|
|
68855
69054
|
const activeSheetId = this.env.model.getters.getActiveSheetId();
|
|
68856
69055
|
const position = this.env.model.getters.getSheetIds().findIndex((sheetId) => sheetId === activeSheetId) + 1;
|
|
68857
|
-
const sheetId = this.env.model.uuidGenerator.
|
|
69056
|
+
const sheetId = this.env.model.uuidGenerator.smallUuid();
|
|
68858
69057
|
const name = this.env.model.getters.getNextSheetName(_t("Sheet"));
|
|
68859
69058
|
this.env.model.dispatch("CREATE_SHEET", { sheetId, position, name });
|
|
68860
69059
|
this.env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
|
|
@@ -69869,6 +70068,10 @@ const FX_SVG = /*xml*/ `
|
|
|
69869
70068
|
</svg>
|
|
69870
70069
|
`;
|
|
69871
70070
|
css /* scss */ `
|
|
70071
|
+
.o-topbar-composer-container {
|
|
70072
|
+
height: ${TOPBAR_TOOLBAR_HEIGHT}px;
|
|
70073
|
+
}
|
|
70074
|
+
|
|
69872
70075
|
.o-topbar-composer {
|
|
69873
70076
|
height: fit-content;
|
|
69874
70077
|
margin-top: -1px;
|
|
@@ -71142,7 +71345,7 @@ class Tree {
|
|
|
71142
71345
|
}
|
|
71143
71346
|
/**
|
|
71144
71347
|
* Drop the operation and all following operations in every
|
|
71145
|
-
*
|
|
71348
|
+
* branches
|
|
71146
71349
|
*/
|
|
71147
71350
|
drop(operationId) {
|
|
71148
71351
|
for (const branch of this.branches) {
|
|
@@ -71447,9 +71650,16 @@ class SelectiveHistory {
|
|
|
71447
71650
|
this.fastForward();
|
|
71448
71651
|
this.insert(redoId, this.buildEmpty(redoId), insertAfter);
|
|
71449
71652
|
}
|
|
71450
|
-
|
|
71653
|
+
rebase(operationId) {
|
|
71654
|
+
const operation = this.get(operationId);
|
|
71655
|
+
const execution = [...this.tree.execution(this.HEAD_BRANCH).startAfter(operationId)];
|
|
71451
71656
|
this.revertBefore(operationId);
|
|
71657
|
+
const baseId = this.HEAD_OPERATION.id;
|
|
71452
71658
|
this.tree.drop(operationId);
|
|
71659
|
+
this.insert(operationId, operation, baseId);
|
|
71660
|
+
for (const { operation } of execution) {
|
|
71661
|
+
this.insert(operation.id, operation.data, this.HEAD_OPERATION.id);
|
|
71662
|
+
}
|
|
71453
71663
|
}
|
|
71454
71664
|
/**
|
|
71455
71665
|
* Revert the state as it was *before* the given operation was executed.
|
|
@@ -74560,6 +74770,11 @@ class Model extends EventBus {
|
|
|
74560
74770
|
dispatch: (command) => {
|
|
74561
74771
|
const result = this.checkDispatchAllowed(command);
|
|
74562
74772
|
if (!result.isSuccessful) {
|
|
74773
|
+
// core views plugins need to be invalidated
|
|
74774
|
+
this.dispatchToHandlers(this.coreHandlers, {
|
|
74775
|
+
type: "UNDO",
|
|
74776
|
+
commands: [command],
|
|
74777
|
+
});
|
|
74563
74778
|
return;
|
|
74564
74779
|
}
|
|
74565
74780
|
this.isReplayingCommand = true;
|
|
@@ -74587,7 +74802,7 @@ class Model extends EventBus {
|
|
|
74587
74802
|
}
|
|
74588
74803
|
setupConfig(config) {
|
|
74589
74804
|
const client = config.client || {
|
|
74590
|
-
id: this.uuidGenerator.
|
|
74805
|
+
id: this.uuidGenerator.smallUuid(),
|
|
74591
74806
|
name: _t("Anonymous").toString(),
|
|
74592
74807
|
};
|
|
74593
74808
|
const transportService = config.transportService || new LocalTransportService();
|
|
@@ -75066,6 +75281,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
75066
75281
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
75067
75282
|
|
|
75068
75283
|
|
|
75069
|
-
__info__.version = "18.1.
|
|
75070
|
-
__info__.date = "2025-02-
|
|
75071
|
-
__info__.hash = "
|
|
75284
|
+
__info__.version = "18.1.9";
|
|
75285
|
+
__info__.date = "2025-02-25T05:59:45.472Z";
|
|
75286
|
+
__info__.hash = "6789c1c";
|