@odoo/o-spreadsheet 18.1.0-alpha.7 → 18.1.0
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 +1317 -315
- package/dist/o-spreadsheet.d.ts +398 -292
- package/dist/o-spreadsheet.esm.js +1317 -315
- package/dist/o-spreadsheet.iife.js +1317 -315
- package/dist/o-spreadsheet.iife.min.js +515 -515
- package/dist/o_spreadsheet.xml +217 -23
- package/package.json +4 -3
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 18.1.0
|
|
6
|
-
* @date 2024-12-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.1.0
|
|
6
|
+
* @date 2024-12-26T06:37:07.879Z
|
|
7
|
+
* @hash c520e89
|
|
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';
|
|
@@ -265,7 +265,6 @@ const MIN_ROW_HEIGHT = 10;
|
|
|
265
265
|
const MIN_COL_WIDTH = 5;
|
|
266
266
|
const HEADER_HEIGHT = 26;
|
|
267
267
|
const HEADER_WIDTH = 48;
|
|
268
|
-
const TOPBAR_HEIGHT = 63;
|
|
269
268
|
const TOPBAR_TOOLBAR_HEIGHT = 34;
|
|
270
269
|
const BOTTOMBAR_HEIGHT = 36;
|
|
271
270
|
const DEFAULT_CELL_WIDTH = 96;
|
|
@@ -789,6 +788,7 @@ function removeFalsyAttributes(obj) {
|
|
|
789
788
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
|
|
790
789
|
*/
|
|
791
790
|
const whiteSpaceSpecialCharacters = [
|
|
791
|
+
" ",
|
|
792
792
|
"\t",
|
|
793
793
|
"\f",
|
|
794
794
|
"\v",
|
|
@@ -803,17 +803,15 @@ const whiteSpaceSpecialCharacters = [
|
|
|
803
803
|
String.fromCharCode(parseInt("3000", 16)),
|
|
804
804
|
String.fromCharCode(parseInt("feff", 16)),
|
|
805
805
|
];
|
|
806
|
-
const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|")
|
|
806
|
+
const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|"), "g");
|
|
807
|
+
const newLineRegexp = /(\r\n|\r)/g;
|
|
807
808
|
/**
|
|
808
|
-
* Replace all
|
|
809
|
-
* different newlines types by \n.
|
|
809
|
+
* Replace all different newlines characters by \n
|
|
810
810
|
*/
|
|
811
|
-
function
|
|
811
|
+
function replaceNewLines(text) {
|
|
812
812
|
if (!text)
|
|
813
813
|
return "";
|
|
814
|
-
|
|
815
|
-
return text;
|
|
816
|
-
return text.replace(whiteSpaceRegexp, (match, newLine) => (newLine ? NEWLINE : " "));
|
|
814
|
+
return text.replace(newLineRegexp, NEWLINE);
|
|
817
815
|
}
|
|
818
816
|
/**
|
|
819
817
|
* Determine if the numbers are consecutive.
|
|
@@ -979,7 +977,7 @@ function transpose2dPOJO(pojo) {
|
|
|
979
977
|
|
|
980
978
|
const RBA_REGEX = /rgba?\(|\s+|\)/gi;
|
|
981
979
|
const HEX_MATCH = /^#([A-F\d]{2}){3,4}$/;
|
|
982
|
-
const colors
|
|
980
|
+
const colors = [
|
|
983
981
|
"#eb6d00",
|
|
984
982
|
"#0074d9",
|
|
985
983
|
"#ad8e00",
|
|
@@ -1002,6 +1000,12 @@ const colors$1 = [
|
|
|
1002
1000
|
function colorNumberString(color) {
|
|
1003
1001
|
return toHex(color.toString(16).padStart(6, "0"));
|
|
1004
1002
|
}
|
|
1003
|
+
function colorToNumber(color) {
|
|
1004
|
+
if (typeof color === "number") {
|
|
1005
|
+
return color;
|
|
1006
|
+
}
|
|
1007
|
+
return Number.parseInt(toHex(color).slice(1), 16);
|
|
1008
|
+
}
|
|
1005
1009
|
/**
|
|
1006
1010
|
* Converts any CSS color value to a standardized hex6 value.
|
|
1007
1011
|
* Accepts: hex3, hex6, hex8, rgb[1] and rgba[1].
|
|
@@ -1352,9 +1356,9 @@ const COLORS_XL = [
|
|
|
1352
1356
|
"#056BD9", // Blue #3
|
|
1353
1357
|
"#155193", // Blue #4
|
|
1354
1358
|
"#A76DBC", // Violet #1
|
|
1355
|
-
"#7F4295", // Violet #
|
|
1356
|
-
"#6D2387", // Violet #
|
|
1357
|
-
"#4F1565", // Violet #
|
|
1359
|
+
"#7F4295", // Violet #2
|
|
1360
|
+
"#6D2387", // Violet #3
|
|
1361
|
+
"#4F1565", // Violet #4
|
|
1358
1362
|
"#EA6175", // Red #1
|
|
1359
1363
|
"#CE4257", // Red #2
|
|
1360
1364
|
"#982738", // Red #3
|
|
@@ -1380,6 +1384,81 @@ const COLORS_XL = [
|
|
|
1380
1384
|
"#C08A16", // Yellow #3
|
|
1381
1385
|
"#936A12", // Yellow #4
|
|
1382
1386
|
];
|
|
1387
|
+
// Same as above but with alternating colors
|
|
1388
|
+
const ALTERNATING_COLORS_MD = [
|
|
1389
|
+
"#4EA7F2", // Blue #1
|
|
1390
|
+
"#43C5B1", // Teal #1
|
|
1391
|
+
"#EA6175", // Red #1
|
|
1392
|
+
"#F4A261", // Orange #1
|
|
1393
|
+
"#8481DD", // Purple #1
|
|
1394
|
+
"#FFD86D", // Yellow #1
|
|
1395
|
+
"#3188E6", // Blue #2
|
|
1396
|
+
"#00A78D", // Teal #2
|
|
1397
|
+
"#CE4257", // Red #2
|
|
1398
|
+
"#F48935", // Orange #2
|
|
1399
|
+
"#5752D1", // Purple #2
|
|
1400
|
+
"#FFBC2C", // Yellow #2
|
|
1401
|
+
];
|
|
1402
|
+
const ALTERNATING_COLORS_LG = [
|
|
1403
|
+
"#4EA7F2", // Blue #1
|
|
1404
|
+
"#A76DBC", // Violet #1
|
|
1405
|
+
"#EA6175", // Red #1
|
|
1406
|
+
"#43C5B1", // Teal #1
|
|
1407
|
+
"#F4A261", // Orange #1
|
|
1408
|
+
"#8481DD", // Purple #1
|
|
1409
|
+
"#A4A8B6", // Gray #1
|
|
1410
|
+
"#FFD86D", // Yellow #1
|
|
1411
|
+
"#3188E6", // Blue #2
|
|
1412
|
+
"#7F4295", // Violet #2
|
|
1413
|
+
"#CE4257", // Red #2
|
|
1414
|
+
"#00A78D", // Teal #2
|
|
1415
|
+
"#F48935", // Orange #2
|
|
1416
|
+
"#5752D1", // Purple #2
|
|
1417
|
+
"#7E8290", // Gray #2
|
|
1418
|
+
"#FFBC2C", // Yellow #2
|
|
1419
|
+
"#056BD9", // Blue #3
|
|
1420
|
+
"#6D2387", // Violet #3
|
|
1421
|
+
"#982738", // Red #3
|
|
1422
|
+
"#0E8270", // Teal #3
|
|
1423
|
+
"#BE5D10", // Orange #3
|
|
1424
|
+
"#3A3580", // Purple #3
|
|
1425
|
+
"#545B70", // Gray #3
|
|
1426
|
+
"#C08A16", // Yellow #3
|
|
1427
|
+
];
|
|
1428
|
+
const ALTERNATING_COLORS_XL = [
|
|
1429
|
+
"#4EA7F2", // Blue #1
|
|
1430
|
+
"#A76DBC", // Violet #1
|
|
1431
|
+
"#EA6175", // Red #1
|
|
1432
|
+
"#43C5B1", // Teal #1
|
|
1433
|
+
"#F4A261", // Orange #1
|
|
1434
|
+
"#8481DD", // Purple #1
|
|
1435
|
+
"#A4A8B6", // Grey #1
|
|
1436
|
+
"#FFD86D", // Yellow #1
|
|
1437
|
+
"#3188E6", // Blue #2
|
|
1438
|
+
"#7F4295", // Violet #2
|
|
1439
|
+
"#CE4257", // Red #2
|
|
1440
|
+
"#00A78D", // Teal #2
|
|
1441
|
+
"#F48935", // Orange #2
|
|
1442
|
+
"#5752D1", // Purple #2
|
|
1443
|
+
"#7E8290", // Grey #2
|
|
1444
|
+
"#FFBC2C", // Yellow #2
|
|
1445
|
+
"#056BD9", // Blue #3
|
|
1446
|
+
"#6D2387", // Violet #3
|
|
1447
|
+
"#982738", // Red #3
|
|
1448
|
+
"#0E8270", // Teal #3
|
|
1449
|
+
"#BE5D10", // Orange #3
|
|
1450
|
+
"#3A3580", // Purple #3
|
|
1451
|
+
"#545B70", // Grey #3
|
|
1452
|
+
"#C08A16", // Yellow #3
|
|
1453
|
+
"#155193", // Blue #4
|
|
1454
|
+
"#4F1565", // Violet #4
|
|
1455
|
+
"#791B29", // Red #4
|
|
1456
|
+
"#105F53", // Teal #4
|
|
1457
|
+
"#7D380D", // Orange #4
|
|
1458
|
+
"#26235F", // Purple #4
|
|
1459
|
+
"#3F4250", // Grey #4
|
|
1460
|
+
"#936A12", // Yellow #4
|
|
1461
|
+
];
|
|
1383
1462
|
function getNthColor(index, palette) {
|
|
1384
1463
|
return palette[index % palette.length];
|
|
1385
1464
|
}
|
|
@@ -1397,6 +1476,20 @@ function getColorsPalette(quantity) {
|
|
|
1397
1476
|
return COLORS_XL;
|
|
1398
1477
|
}
|
|
1399
1478
|
}
|
|
1479
|
+
function getAlternatingColorsPalette(quantity) {
|
|
1480
|
+
if (quantity <= 6) {
|
|
1481
|
+
return COLORS_SM;
|
|
1482
|
+
}
|
|
1483
|
+
else if (quantity <= 12) {
|
|
1484
|
+
return ALTERNATING_COLORS_MD;
|
|
1485
|
+
}
|
|
1486
|
+
else if (quantity <= 24) {
|
|
1487
|
+
return ALTERNATING_COLORS_LG;
|
|
1488
|
+
}
|
|
1489
|
+
else {
|
|
1490
|
+
return ALTERNATING_COLORS_XL;
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1400
1493
|
class ColorGenerator {
|
|
1401
1494
|
preferredColors;
|
|
1402
1495
|
currentColorIndex = 0;
|
|
@@ -1411,6 +1504,62 @@ class ColorGenerator {
|
|
|
1411
1504
|
: getNthColor(this.currentColorIndex++, this.palette);
|
|
1412
1505
|
}
|
|
1413
1506
|
}
|
|
1507
|
+
class AlternatingColorGenerator extends ColorGenerator {
|
|
1508
|
+
constructor(paletteSize, preferredColors = []) {
|
|
1509
|
+
super(paletteSize, preferredColors);
|
|
1510
|
+
this.palette = getAlternatingColorsPalette(paletteSize).filter((c) => !preferredColors.includes(c));
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
/**
|
|
1514
|
+
* Returns a function that maps a value to a color using a color scale defined by the given
|
|
1515
|
+
* color/threshold values pairs.
|
|
1516
|
+
*/
|
|
1517
|
+
function getColorScale(colorScalePoints) {
|
|
1518
|
+
if (colorScalePoints.length < 2) {
|
|
1519
|
+
throw new Error("Color scale must have at least 2 points");
|
|
1520
|
+
}
|
|
1521
|
+
const sortedColorScalePoints = [...colorScalePoints.sort((a, b) => a.value - b.value)];
|
|
1522
|
+
const thresholds = [];
|
|
1523
|
+
for (let i = 1; i < sortedColorScalePoints.length; i++) {
|
|
1524
|
+
const minColor = colorToNumber(sortedColorScalePoints[i - 1].color);
|
|
1525
|
+
const maxColor = colorToNumber(sortedColorScalePoints[i].color);
|
|
1526
|
+
thresholds.push({
|
|
1527
|
+
min: sortedColorScalePoints[i - 1].value,
|
|
1528
|
+
max: sortedColorScalePoints[i].value,
|
|
1529
|
+
minColor,
|
|
1530
|
+
maxColor,
|
|
1531
|
+
colorDiff: computeColorDiffUnits(sortedColorScalePoints[i - 1].value, sortedColorScalePoints[i].value, minColor, maxColor),
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
return (value) => {
|
|
1535
|
+
if (value < thresholds[0].min) {
|
|
1536
|
+
return colorNumberString(thresholds[0].minColor);
|
|
1537
|
+
}
|
|
1538
|
+
for (const threshold of thresholds) {
|
|
1539
|
+
if (value >= threshold.min && value <= threshold.max) {
|
|
1540
|
+
return colorNumberString(colorCell(value, threshold.min, threshold.minColor, threshold.colorDiff));
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
return colorNumberString(thresholds[thresholds.length - 1].maxColor);
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
function computeColorDiffUnits(minValue, maxValue, minColor, maxColor) {
|
|
1547
|
+
const deltaValue = maxValue - minValue;
|
|
1548
|
+
const deltaColorR = ((minColor >> 16) % 256) - ((maxColor >> 16) % 256);
|
|
1549
|
+
const deltaColorG = ((minColor >> 8) % 256) - ((maxColor >> 8) % 256);
|
|
1550
|
+
const deltaColorB = (minColor % 256) - (maxColor % 256);
|
|
1551
|
+
const colorDiffUnitR = deltaColorR / deltaValue;
|
|
1552
|
+
const colorDiffUnitG = deltaColorG / deltaValue;
|
|
1553
|
+
const colorDiffUnitB = deltaColorB / deltaValue;
|
|
1554
|
+
return [colorDiffUnitR, colorDiffUnitG, colorDiffUnitB];
|
|
1555
|
+
}
|
|
1556
|
+
function colorCell(value, minValue, minColor, colorDiffUnit) {
|
|
1557
|
+
const [colorDiffUnitR, colorDiffUnitG, colorDiffUnitB] = colorDiffUnit;
|
|
1558
|
+
const r = Math.round(((minColor >> 16) % 256) - colorDiffUnitR * (value - minValue));
|
|
1559
|
+
const g = Math.round(((minColor >> 8) % 256) - colorDiffUnitG * (value - minValue));
|
|
1560
|
+
const b = Math.round((minColor % 256) - colorDiffUnitB * (value - minValue));
|
|
1561
|
+
return (r << 16) | (g << 8) | b;
|
|
1562
|
+
}
|
|
1414
1563
|
|
|
1415
1564
|
//------------------------------------------------------------------------------
|
|
1416
1565
|
// Coordinate
|
|
@@ -3282,6 +3431,7 @@ const invalidateEvaluationCommands = new Set([
|
|
|
3282
3431
|
]);
|
|
3283
3432
|
const invalidateChartEvaluationCommands = new Set([
|
|
3284
3433
|
"EVALUATE_CELLS",
|
|
3434
|
+
"EVALUATE_CHARTS",
|
|
3285
3435
|
"UPDATE_CELL",
|
|
3286
3436
|
"UNHIDE_COLUMNS_ROWS",
|
|
3287
3437
|
"HIDE_COLUMNS_ROWS",
|
|
@@ -3318,6 +3468,7 @@ const readonlyAllowedCommands = new Set([
|
|
|
3318
3468
|
"RESIZE_SHEETVIEW",
|
|
3319
3469
|
"SET_VIEWPORT_OFFSET",
|
|
3320
3470
|
"EVALUATE_CELLS",
|
|
3471
|
+
"EVALUATE_CHARTS",
|
|
3321
3472
|
"SET_FORMULA_VISIBILITY",
|
|
3322
3473
|
"UPDATE_FILTER",
|
|
3323
3474
|
]);
|
|
@@ -6522,7 +6673,7 @@ class BorderClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
6522
6673
|
const POSTFIX_UNARY_OPERATORS = ["%"];
|
|
6523
6674
|
const OPERATORS = "+,-,*,/,:,=,<>,>=,>,<=,<,^,&".split(",").concat(POSTFIX_UNARY_OPERATORS);
|
|
6524
6675
|
function tokenize(str, locale = DEFAULT_LOCALE) {
|
|
6525
|
-
str =
|
|
6676
|
+
str = replaceNewLines(str);
|
|
6526
6677
|
const chars = new TokenizingChars(str);
|
|
6527
6678
|
const result = [];
|
|
6528
6679
|
while (!chars.isOver()) {
|
|
@@ -6669,12 +6820,12 @@ function tokenizeSpace(chars) {
|
|
|
6669
6820
|
if (length) {
|
|
6670
6821
|
return { type: "SPACE", value: NEWLINE.repeat(length) };
|
|
6671
6822
|
}
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
chars.shift();
|
|
6823
|
+
let spaces = "";
|
|
6824
|
+
while (chars.current && chars.current.match(whiteSpaceRegexp)) {
|
|
6825
|
+
spaces += chars.shift();
|
|
6675
6826
|
}
|
|
6676
|
-
if (
|
|
6677
|
-
return { type: "SPACE", value:
|
|
6827
|
+
if (spaces) {
|
|
6828
|
+
return { type: "SPACE", value: spaces };
|
|
6678
6829
|
}
|
|
6679
6830
|
return null;
|
|
6680
6831
|
}
|
|
@@ -7533,6 +7684,16 @@ function getRunningTotalDomainKey(domain, fieldNameWithGranularity) {
|
|
|
7533
7684
|
}
|
|
7534
7685
|
return domainToString([...domain.slice(0, index), ...domain.slice(index + 1)]);
|
|
7535
7686
|
}
|
|
7687
|
+
function sortPivotTree(tree, baseDomain, sortFn) {
|
|
7688
|
+
const sortedTree = [...tree];
|
|
7689
|
+
const domain = [...baseDomain];
|
|
7690
|
+
sortedTree.sort((node1, node2) => sortFn([...domain, node1], [...domain, node2]));
|
|
7691
|
+
for (const node of tree) {
|
|
7692
|
+
const children = sortPivotTree(node.children, [...domain, node], sortFn);
|
|
7693
|
+
node.children = children;
|
|
7694
|
+
}
|
|
7695
|
+
return sortedTree;
|
|
7696
|
+
}
|
|
7536
7697
|
|
|
7537
7698
|
const pivotTimeAdapterRegistry = new Registry();
|
|
7538
7699
|
function pivotTimeAdapter(granularity) {
|
|
@@ -8043,6 +8204,29 @@ function addIndentAndAlignToPivotHeader(pivot, domain, functionResult) {
|
|
|
8043
8204
|
format: `${" ".repeat(indent)}${format}* `,
|
|
8044
8205
|
};
|
|
8045
8206
|
}
|
|
8207
|
+
function isSortedColumnValid(sortedColumn, pivot) {
|
|
8208
|
+
try {
|
|
8209
|
+
if (!pivot.getMeasure(sortedColumn.measure)) {
|
|
8210
|
+
return false;
|
|
8211
|
+
}
|
|
8212
|
+
const columns = pivot.definition.columns;
|
|
8213
|
+
for (let i = 0; i < sortedColumn.domain.length; i++) {
|
|
8214
|
+
if (columns[i].nameWithGranularity !== sortedColumn.domain[i].field) {
|
|
8215
|
+
return false;
|
|
8216
|
+
}
|
|
8217
|
+
const possibleValues = pivot
|
|
8218
|
+
.getPossibleFieldValues(columns[i])
|
|
8219
|
+
.map((v) => v.value);
|
|
8220
|
+
if (!possibleValues.includes(sortedColumn.domain[i].value)) {
|
|
8221
|
+
return false;
|
|
8222
|
+
}
|
|
8223
|
+
}
|
|
8224
|
+
return true;
|
|
8225
|
+
}
|
|
8226
|
+
catch (e) {
|
|
8227
|
+
return false;
|
|
8228
|
+
}
|
|
8229
|
+
}
|
|
8046
8230
|
|
|
8047
8231
|
class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
8048
8232
|
isCutAllowed(data) {
|
|
@@ -14651,7 +14835,7 @@ const SORT_TYPES = [
|
|
|
14651
14835
|
CellValueType.boolean,
|
|
14652
14836
|
];
|
|
14653
14837
|
function cellsSortingCriterion(sortingOrder) {
|
|
14654
|
-
const inverse = sortingOrder === "
|
|
14838
|
+
const inverse = sortingOrder === "asc" ? 1 : -1;
|
|
14655
14839
|
return (left, right) => {
|
|
14656
14840
|
if (left.type === CellValueType.empty) {
|
|
14657
14841
|
return right.type === CellValueType.empty ? 0 : 1;
|
|
@@ -14743,7 +14927,7 @@ function sortMatrix(matrix, locale, ...criteria) {
|
|
|
14743
14927
|
const sortColumns = [];
|
|
14744
14928
|
const nRows = matrix.length;
|
|
14745
14929
|
for (let i = 0; i < criteria.length; i += 2) {
|
|
14746
|
-
sortingOrders.push(toBoolean(toScalar(criteria[i + 1])?.value) ? "
|
|
14930
|
+
sortingOrders.push(toBoolean(toScalar(criteria[i + 1])?.value) ? "asc" : "desc");
|
|
14747
14931
|
const sortColumn = criteria[i];
|
|
14748
14932
|
if (isMatrix(sortColumn) && (sortColumn.length > 1 || sortColumn[0].length > 1)) {
|
|
14749
14933
|
assert(() => sortColumn.length === 1 && sortColumn[0].length === nRows, _t("Wrong size for %s. Expected a range of size 1x%s. Got %sx%s.", `sort_column${i + 1}`, nRows, sortColumn.length, sortColumn[0].length));
|
|
@@ -14760,12 +14944,12 @@ function sortMatrix(matrix, locale, ...criteria) {
|
|
|
14760
14944
|
if (sortColumns.length === 0) {
|
|
14761
14945
|
for (let i = 0; i < matrix[0].length; i++) {
|
|
14762
14946
|
sortColumns.push(matrix.map((row) => row[i].value));
|
|
14763
|
-
sortingOrders.push("
|
|
14947
|
+
sortingOrders.push("asc");
|
|
14764
14948
|
}
|
|
14765
14949
|
}
|
|
14766
14950
|
const sortingCriteria = {
|
|
14767
|
-
|
|
14768
|
-
|
|
14951
|
+
desc: cellsSortingCriterion("desc"),
|
|
14952
|
+
asc: cellsSortingCriterion("asc"),
|
|
14769
14953
|
};
|
|
14770
14954
|
const indexes = range(0, matrix.length);
|
|
14771
14955
|
indexes.sort((a, b) => {
|
|
@@ -20489,20 +20673,8 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
20489
20673
|
replaceSelectedRange(zone) {
|
|
20490
20674
|
const ref = this.getZoneReference(zone);
|
|
20491
20675
|
const currentToken = this.tokenAtCursor;
|
|
20492
|
-
|
|
20493
|
-
|
|
20494
|
-
replaceStart = currentToken.start;
|
|
20495
|
-
}
|
|
20496
|
-
else if (currentToken?.type === "RIGHT_PAREN") {
|
|
20497
|
-
// match left parenthesis
|
|
20498
|
-
const leftParenthesisIndex = this.currentTokens.findIndex((token) => token.type === "LEFT_PAREN" && token.parenthesesCode === currentToken.parenthesesCode);
|
|
20499
|
-
const functionToken = this.currentTokens[leftParenthesisIndex - 1];
|
|
20500
|
-
if (functionToken === undefined) {
|
|
20501
|
-
return;
|
|
20502
|
-
}
|
|
20503
|
-
replaceStart = functionToken.start;
|
|
20504
|
-
}
|
|
20505
|
-
this.replaceText(ref, replaceStart, this.selectionEnd);
|
|
20676
|
+
const start = currentToken?.type === "REFERENCE" ? currentToken.start : this.selectionStart;
|
|
20677
|
+
this.replaceText(ref, start, this.selectionEnd);
|
|
20506
20678
|
}
|
|
20507
20679
|
/**
|
|
20508
20680
|
* Replace the reference of the old zone by the new one.
|
|
@@ -20535,17 +20707,6 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
20535
20707
|
getZoneReference(zone) {
|
|
20536
20708
|
const inputSheetId = this.sheetId;
|
|
20537
20709
|
const sheetId = this.getters.getActiveSheetId();
|
|
20538
|
-
if (zone.top === zone.bottom && zone.left === zone.right) {
|
|
20539
|
-
const position = { sheetId, col: zone.left, row: zone.top };
|
|
20540
|
-
const pivotId = this.getters.getPivotIdFromPosition(position);
|
|
20541
|
-
const pivotCell = this.getters.getPivotCellFromPosition(position);
|
|
20542
|
-
const cell = this.getters.getCell(position);
|
|
20543
|
-
if (pivotId && pivotCell.type !== "EMPTY" && !cell?.isFormula) {
|
|
20544
|
-
const formulaPivotId = this.getters.getPivotFormulaId(pivotId);
|
|
20545
|
-
const formula = createPivotFormula(formulaPivotId, pivotCell);
|
|
20546
|
-
return localizeFormula(formula, this.getters.getLocale()).slice(1); // strip leading =
|
|
20547
|
-
}
|
|
20548
|
-
}
|
|
20549
20710
|
const range = this.getters.getRangeFromZone(sheetId, zone);
|
|
20550
20711
|
return this.getters.getSelectionRangeString(range, inputSheetId);
|
|
20551
20712
|
}
|
|
@@ -20716,37 +20877,21 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
20716
20877
|
const editionSheetId = this.sheetId;
|
|
20717
20878
|
const rangeColor = (rangeString) => {
|
|
20718
20879
|
const colorIndex = this.colorIndexByRange[rangeString];
|
|
20719
|
-
return colors
|
|
20880
|
+
return colors[colorIndex % colors.length];
|
|
20720
20881
|
};
|
|
20721
|
-
|
|
20722
|
-
for (const range of this.getReferencedRanges()) {
|
|
20882
|
+
return this.getReferencedRanges().map((range) => {
|
|
20723
20883
|
const rangeString = this.getters.getRangeString(range, editionSheetId);
|
|
20724
20884
|
const { numberOfRows, numberOfCols } = zoneToDimension(range.zone);
|
|
20725
20885
|
const zone = numberOfRows * numberOfCols === 1
|
|
20726
20886
|
? this.getters.expandZone(range.sheetId, range.zone)
|
|
20727
20887
|
: range.zone;
|
|
20728
|
-
|
|
20888
|
+
return {
|
|
20729
20889
|
zone,
|
|
20730
20890
|
color: rangeColor(rangeString),
|
|
20731
20891
|
sheetId: range.sheetId,
|
|
20732
20892
|
interactive: true,
|
|
20733
|
-
}
|
|
20734
|
-
}
|
|
20735
|
-
const activeSheetId = this.getters.getActiveSheetId();
|
|
20736
|
-
const selectionZone = this.model.selection.getAnchor().zone;
|
|
20737
|
-
const isSelectionHightlighted = highlights.find((highlight) => highlight.sheetId === activeSheetId && isEqual(highlight.zone, selectionZone));
|
|
20738
|
-
if (this.editionMode === "selecting" && !isSelectionHightlighted) {
|
|
20739
|
-
highlights.push({
|
|
20740
|
-
zone: selectionZone,
|
|
20741
|
-
color: "#445566",
|
|
20742
|
-
sheetId: activeSheetId,
|
|
20743
|
-
dashed: true,
|
|
20744
|
-
interactive: false,
|
|
20745
|
-
noFill: true,
|
|
20746
|
-
thinLine: true,
|
|
20747
|
-
});
|
|
20748
|
-
}
|
|
20749
|
-
return highlights;
|
|
20893
|
+
};
|
|
20894
|
+
});
|
|
20750
20895
|
}
|
|
20751
20896
|
/**
|
|
20752
20897
|
* Return ranges currently referenced in the composer
|
|
@@ -20974,6 +21119,7 @@ function compileTokens(tokens) {
|
|
|
20974
21119
|
return error;
|
|
20975
21120
|
},
|
|
20976
21121
|
isBadExpression: true,
|
|
21122
|
+
normalizedFormula: tokens.map((t) => t.value).join(""),
|
|
20977
21123
|
};
|
|
20978
21124
|
}
|
|
20979
21125
|
}
|
|
@@ -21101,6 +21247,7 @@ function compileTokensOrThrow(tokens) {
|
|
|
21101
21247
|
symbols,
|
|
21102
21248
|
tokens,
|
|
21103
21249
|
isBadExpression: false,
|
|
21250
|
+
normalizedFormula: cacheKey,
|
|
21104
21251
|
};
|
|
21105
21252
|
return compiledFormula;
|
|
21106
21253
|
}
|
|
@@ -21365,6 +21512,7 @@ autoCompleteProviders.add("pivot_ids", {
|
|
|
21365
21512
|
description: definition.name,
|
|
21366
21513
|
htmlContent: [{ value: str, color: tokenColors.NUMBER }],
|
|
21367
21514
|
fuzzySearchKey: str + definition.name,
|
|
21515
|
+
alwaysExpanded: true,
|
|
21368
21516
|
};
|
|
21369
21517
|
})
|
|
21370
21518
|
.filter(isDefined);
|
|
@@ -27758,6 +27906,19 @@ const ChartTerms = {
|
|
|
27758
27906
|
["GaugeLowerInflectionPointNaN" /* CommandResult.GaugeLowerInflectionPointNaN */]: _t("The lower inflection point value must be a number"),
|
|
27759
27907
|
["GaugeUpperInflectionPointNaN" /* CommandResult.GaugeUpperInflectionPointNaN */]: _t("The upper inflection point value must be a number"),
|
|
27760
27908
|
},
|
|
27909
|
+
GeoChart: {
|
|
27910
|
+
ColorScales: {
|
|
27911
|
+
blues: _t("Blues"),
|
|
27912
|
+
cividis: _t("Cividis"),
|
|
27913
|
+
greens: _t("Greens"),
|
|
27914
|
+
greys: _t("Greys"),
|
|
27915
|
+
oranges: _t("Oranges"),
|
|
27916
|
+
purples: _t("Purples"),
|
|
27917
|
+
rainbow: _t("Rainbow"),
|
|
27918
|
+
reds: _t("Reds"),
|
|
27919
|
+
viridis: _t("Viridis"),
|
|
27920
|
+
},
|
|
27921
|
+
},
|
|
27761
27922
|
};
|
|
27762
27923
|
const CustomCurrencyTerms = {
|
|
27763
27924
|
Custom: _t("Custom"),
|
|
@@ -28161,6 +28322,26 @@ function getRadarChartData(definition, dataSets, labelRange, getters) {
|
|
|
28161
28322
|
locale: getters.getLocale(),
|
|
28162
28323
|
};
|
|
28163
28324
|
}
|
|
28325
|
+
function getGeoChartData(definition, dataSets, labelRange, getters) {
|
|
28326
|
+
const labelValues = getChartLabelValues(getters, dataSets, labelRange);
|
|
28327
|
+
let labels = labelValues.formattedValues;
|
|
28328
|
+
if (definition.dataSetsHaveTitle) {
|
|
28329
|
+
labels.shift();
|
|
28330
|
+
}
|
|
28331
|
+
let dataSetsValues = getChartDatasetValues(getters, dataSets);
|
|
28332
|
+
({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
|
|
28333
|
+
const format = getChartDatasetFormat(getters, dataSets, "left") ||
|
|
28334
|
+
getChartDatasetFormat(getters, dataSets, "right");
|
|
28335
|
+
return {
|
|
28336
|
+
dataSetsValues,
|
|
28337
|
+
axisFormats: { y: format },
|
|
28338
|
+
labels,
|
|
28339
|
+
locale: getters.getLocale(),
|
|
28340
|
+
availableRegions: getters.getGeoChartAvailableRegions(),
|
|
28341
|
+
geoFeatureNameToId: getters.geoFeatureNameToId,
|
|
28342
|
+
getGeoJsonFeatures: getters.getGeoJsonFeatures,
|
|
28343
|
+
};
|
|
28344
|
+
}
|
|
28164
28345
|
function getTrendDatasetForBarChart(config, data) {
|
|
28165
28346
|
const filteredValues = [];
|
|
28166
28347
|
const filteredLabels = [];
|
|
@@ -28713,6 +28894,43 @@ function getRadarChartDatasets(definition, args) {
|
|
|
28713
28894
|
}
|
|
28714
28895
|
return datasets;
|
|
28715
28896
|
}
|
|
28897
|
+
function getGeoChartDatasets(definition, args) {
|
|
28898
|
+
const { availableRegions, dataSetsValues, labels } = args;
|
|
28899
|
+
const regionName = definition.region || availableRegions[0]?.id;
|
|
28900
|
+
const features = regionName ? args.getGeoJsonFeatures(regionName) : undefined;
|
|
28901
|
+
const dataset = {
|
|
28902
|
+
outline: features,
|
|
28903
|
+
showOutline: !!features,
|
|
28904
|
+
data: [],
|
|
28905
|
+
};
|
|
28906
|
+
if (features && regionName) {
|
|
28907
|
+
const labelsAndValues = {};
|
|
28908
|
+
if (dataSetsValues[0]) {
|
|
28909
|
+
for (let i = 0; i < dataSetsValues[0].data.length; i++) {
|
|
28910
|
+
if (!labels[i] || dataSetsValues[0].data[i] === undefined) {
|
|
28911
|
+
continue;
|
|
28912
|
+
}
|
|
28913
|
+
const featureId = args.geoFeatureNameToId(regionName, labels[i]);
|
|
28914
|
+
if (featureId) {
|
|
28915
|
+
labelsAndValues[featureId] = { value: dataSetsValues[0].data[i], label: labels[i] };
|
|
28916
|
+
}
|
|
28917
|
+
}
|
|
28918
|
+
}
|
|
28919
|
+
for (const feature of features) {
|
|
28920
|
+
if (!feature.id) {
|
|
28921
|
+
continue;
|
|
28922
|
+
}
|
|
28923
|
+
dataset.data.push({
|
|
28924
|
+
feature: {
|
|
28925
|
+
...feature,
|
|
28926
|
+
properties: { name: labelsAndValues[feature.id]?.label },
|
|
28927
|
+
},
|
|
28928
|
+
value: labelsAndValues[feature.id]?.value,
|
|
28929
|
+
});
|
|
28930
|
+
}
|
|
28931
|
+
}
|
|
28932
|
+
return [dataset];
|
|
28933
|
+
}
|
|
28716
28934
|
function getTrendingLineDataSet(dataset, config, data) {
|
|
28717
28935
|
const defaultBorderColor = colorToRGBA(dataset.backgroundColor);
|
|
28718
28936
|
defaultBorderColor.a = 1;
|
|
@@ -29090,6 +29308,44 @@ function getRadarChartScales(definition, args) {
|
|
|
29090
29308
|
},
|
|
29091
29309
|
};
|
|
29092
29310
|
}
|
|
29311
|
+
function getGeoChartScales(definition, args) {
|
|
29312
|
+
const { locale, axisFormats, availableRegions } = args;
|
|
29313
|
+
const geoLegendPosition = legendPositionToGeoLegendPosition(definition.legendPosition);
|
|
29314
|
+
const region = definition.region
|
|
29315
|
+
? availableRegions.find((r) => r.id === definition.region)
|
|
29316
|
+
: availableRegions[0];
|
|
29317
|
+
const format = axisFormats?.y || axisFormats?.y1;
|
|
29318
|
+
return {
|
|
29319
|
+
projection: {
|
|
29320
|
+
// projection: region?.defaultProjection,
|
|
29321
|
+
projection: getGeoChartProjection(region?.defaultProjection || "mercator"),
|
|
29322
|
+
axis: "x",
|
|
29323
|
+
},
|
|
29324
|
+
color: {
|
|
29325
|
+
axis: "x",
|
|
29326
|
+
display: definition.legendPosition !== "none",
|
|
29327
|
+
border: { color: GRAY_300 },
|
|
29328
|
+
grid: { color: GRAY_300 },
|
|
29329
|
+
ticks: {
|
|
29330
|
+
color: chartFontColor(definition.background),
|
|
29331
|
+
callback: formatTickValue({ locale, format }),
|
|
29332
|
+
},
|
|
29333
|
+
legend: {
|
|
29334
|
+
position: geoLegendPosition,
|
|
29335
|
+
align: geoLegendPosition.includes("right") ? "left" : "right",
|
|
29336
|
+
margin: getLegendMargin(definition),
|
|
29337
|
+
},
|
|
29338
|
+
interpolate: getRuntimeColorScale(definition),
|
|
29339
|
+
missing: definition.missingValueColor || "#ffffff",
|
|
29340
|
+
},
|
|
29341
|
+
};
|
|
29342
|
+
}
|
|
29343
|
+
function getGeoChartProjection(projection) {
|
|
29344
|
+
if (projection === "conicConformal") {
|
|
29345
|
+
return window.ChartGeo.geoConicConformal().rotate([100, 0]); // Centered on the US
|
|
29346
|
+
}
|
|
29347
|
+
return projection;
|
|
29348
|
+
}
|
|
29093
29349
|
function getChartAxisTitleRuntime(design) {
|
|
29094
29350
|
if (design?.title?.text) {
|
|
29095
29351
|
const { text, color, align, italic, bold } = design.title;
|
|
@@ -29153,6 +29409,44 @@ function getChartAxis(definition, position, type, options) {
|
|
|
29153
29409
|
};
|
|
29154
29410
|
}
|
|
29155
29411
|
}
|
|
29412
|
+
function getRuntimeColorScale(definition) {
|
|
29413
|
+
if (!definition.colorScale || typeof definition.colorScale === "string") {
|
|
29414
|
+
return definition.colorScale || "oranges";
|
|
29415
|
+
}
|
|
29416
|
+
const scaleColors = [{ value: 0, color: definition.colorScale.minColor }];
|
|
29417
|
+
if (definition.colorScale.midColor) {
|
|
29418
|
+
scaleColors.push({ value: 0.5, color: definition.colorScale.midColor });
|
|
29419
|
+
}
|
|
29420
|
+
scaleColors.push({ value: 1, color: definition.colorScale.maxColor });
|
|
29421
|
+
return getColorScale(scaleColors);
|
|
29422
|
+
}
|
|
29423
|
+
function getLegendMargin(definition) {
|
|
29424
|
+
switch (definition.legendPosition) {
|
|
29425
|
+
case "top":
|
|
29426
|
+
case "right":
|
|
29427
|
+
const hasTitle = !!definition.title.text;
|
|
29428
|
+
const topMargin = hasTitle ? CHART_PADDING_TOP + 30 : CHART_PADDING_TOP;
|
|
29429
|
+
return { top: topMargin, left: CHART_PADDING$1, right: CHART_PADDING$1 };
|
|
29430
|
+
case "bottom":
|
|
29431
|
+
case "left":
|
|
29432
|
+
case "none":
|
|
29433
|
+
return { left: CHART_PADDING$1, right: CHART_PADDING$1, bottom: CHART_PADDING_BOTTOM };
|
|
29434
|
+
}
|
|
29435
|
+
}
|
|
29436
|
+
function legendPositionToGeoLegendPosition(position) {
|
|
29437
|
+
switch (position) {
|
|
29438
|
+
case "top":
|
|
29439
|
+
return "top-left";
|
|
29440
|
+
case "right":
|
|
29441
|
+
return "top-right";
|
|
29442
|
+
case "bottom":
|
|
29443
|
+
return "bottom-right";
|
|
29444
|
+
case "left":
|
|
29445
|
+
return "bottom-left";
|
|
29446
|
+
case "none":
|
|
29447
|
+
return "bottom-left";
|
|
29448
|
+
}
|
|
29449
|
+
}
|
|
29156
29450
|
|
|
29157
29451
|
function getChartShowValues(definition, args) {
|
|
29158
29452
|
const { axisFormats, locale } = args;
|
|
@@ -29312,6 +29606,25 @@ function getRadarChartTooltip(definition, args) {
|
|
|
29312
29606
|
},
|
|
29313
29607
|
};
|
|
29314
29608
|
}
|
|
29609
|
+
function getGeoChartTooltip(definition, args) {
|
|
29610
|
+
const { locale, axisFormats } = args;
|
|
29611
|
+
const format = axisFormats?.y || axisFormats?.y1;
|
|
29612
|
+
return {
|
|
29613
|
+
filter: function (tooltipItem) {
|
|
29614
|
+
return tooltipItem.raw.value !== undefined;
|
|
29615
|
+
},
|
|
29616
|
+
callbacks: {
|
|
29617
|
+
label: function (tooltipItem) {
|
|
29618
|
+
const rawItem = tooltipItem.raw;
|
|
29619
|
+
const xLabel = rawItem.feature.properties.name;
|
|
29620
|
+
const yLabel = rawItem.value;
|
|
29621
|
+
const toolTipFormat = !format && Math.abs(yLabel) >= 1000 ? "#,##" : format;
|
|
29622
|
+
const yLabelStr = formatValue(yLabel, { format: toolTipFormat, locale });
|
|
29623
|
+
return xLabel ? `${xLabel}: ${yLabelStr}` : yLabelStr;
|
|
29624
|
+
},
|
|
29625
|
+
},
|
|
29626
|
+
};
|
|
29627
|
+
}
|
|
29315
29628
|
function calculatePercentage(dataset, dataIndex) {
|
|
29316
29629
|
const numericData = dataset.filter((value) => typeof value === "number");
|
|
29317
29630
|
const total = numericData.reduce((sum, value) => sum + value, 0);
|
|
@@ -29338,6 +29651,10 @@ var CHART_RUNTIME_HELPERS = /*#__PURE__*/Object.freeze({
|
|
|
29338
29651
|
getComboChartDatasets: getComboChartDatasets,
|
|
29339
29652
|
getComboChartLegend: getComboChartLegend,
|
|
29340
29653
|
getData: getData,
|
|
29654
|
+
getGeoChartData: getGeoChartData,
|
|
29655
|
+
getGeoChartDatasets: getGeoChartDatasets,
|
|
29656
|
+
getGeoChartScales: getGeoChartScales,
|
|
29657
|
+
getGeoChartTooltip: getGeoChartTooltip,
|
|
29341
29658
|
getLineChartData: getLineChartData,
|
|
29342
29659
|
getLineChartDatasets: getLineChartDatasets,
|
|
29343
29660
|
getLineChartLegend: getLineChartLegend,
|
|
@@ -29911,6 +30228,133 @@ function getSectionThresholdValue(threshold, minValue, maxValue) {
|
|
|
29911
30228
|
return clip(value, minValue, maxValue);
|
|
29912
30229
|
}
|
|
29913
30230
|
|
|
30231
|
+
class GeoChart extends AbstractChart {
|
|
30232
|
+
dataSets;
|
|
30233
|
+
labelRange;
|
|
30234
|
+
background;
|
|
30235
|
+
legendPosition;
|
|
30236
|
+
type = "geo";
|
|
30237
|
+
dataSetsHaveTitle;
|
|
30238
|
+
dataSetDesign;
|
|
30239
|
+
colorScale;
|
|
30240
|
+
missingValueColor;
|
|
30241
|
+
region;
|
|
30242
|
+
constructor(definition, sheetId, getters) {
|
|
30243
|
+
super(definition, sheetId, getters);
|
|
30244
|
+
this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
30245
|
+
this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
|
|
30246
|
+
this.background = definition.background;
|
|
30247
|
+
this.legendPosition = definition.legendPosition;
|
|
30248
|
+
this.dataSetsHaveTitle = definition.dataSetsHaveTitle;
|
|
30249
|
+
this.dataSetDesign = definition.dataSets;
|
|
30250
|
+
this.colorScale = definition.colorScale;
|
|
30251
|
+
this.missingValueColor = definition.missingValueColor;
|
|
30252
|
+
this.region = definition.region;
|
|
30253
|
+
}
|
|
30254
|
+
static transformDefinition(definition, executed) {
|
|
30255
|
+
return transformChartDefinitionWithDataSetsWithZone(definition, executed);
|
|
30256
|
+
}
|
|
30257
|
+
static validateChartDefinition(validator, definition) {
|
|
30258
|
+
return validator.checkValidations(definition, checkDataset, checkLabelRange);
|
|
30259
|
+
}
|
|
30260
|
+
static getDefinitionFromContextCreation(context) {
|
|
30261
|
+
return {
|
|
30262
|
+
background: context.background,
|
|
30263
|
+
dataSets: context.range ?? [],
|
|
30264
|
+
dataSetsHaveTitle: context.dataSetsHaveTitle ?? false,
|
|
30265
|
+
legendPosition: context.legendPosition ?? "top",
|
|
30266
|
+
title: context.title || { text: "" },
|
|
30267
|
+
type: "geo",
|
|
30268
|
+
labelRange: context.auxiliaryRange || undefined,
|
|
30269
|
+
aggregated: context.aggregated,
|
|
30270
|
+
};
|
|
30271
|
+
}
|
|
30272
|
+
getContextCreation() {
|
|
30273
|
+
const range = [];
|
|
30274
|
+
for (const [i, dataSet] of this.dataSets.entries()) {
|
|
30275
|
+
range.push({
|
|
30276
|
+
...this.dataSetDesign?.[i],
|
|
30277
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, this.sheetId),
|
|
30278
|
+
});
|
|
30279
|
+
}
|
|
30280
|
+
return {
|
|
30281
|
+
...this,
|
|
30282
|
+
range,
|
|
30283
|
+
auxiliaryRange: this.labelRange
|
|
30284
|
+
? this.getters.getRangeString(this.labelRange, this.sheetId)
|
|
30285
|
+
: undefined,
|
|
30286
|
+
};
|
|
30287
|
+
}
|
|
30288
|
+
copyForSheetId(sheetId) {
|
|
30289
|
+
const dataSets = copyDataSetsWithNewSheetId(this.sheetId, sheetId, this.dataSets);
|
|
30290
|
+
const labelRange = copyLabelRangeWithNewSheetId(this.sheetId, sheetId, this.labelRange);
|
|
30291
|
+
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange, sheetId);
|
|
30292
|
+
return new GeoChart(definition, sheetId, this.getters);
|
|
30293
|
+
}
|
|
30294
|
+
copyInSheetId(sheetId) {
|
|
30295
|
+
const definition = this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange, sheetId);
|
|
30296
|
+
return new GeoChart(definition, sheetId, this.getters);
|
|
30297
|
+
}
|
|
30298
|
+
getDefinition() {
|
|
30299
|
+
return this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange);
|
|
30300
|
+
}
|
|
30301
|
+
getDefinitionWithSpecificDataSets(dataSets, labelRange, targetSheetId) {
|
|
30302
|
+
const ranges = [];
|
|
30303
|
+
for (const [i, dataSet] of dataSets.entries()) {
|
|
30304
|
+
ranges.push({
|
|
30305
|
+
...this.dataSetDesign?.[i],
|
|
30306
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, targetSheetId || this.sheetId),
|
|
30307
|
+
});
|
|
30308
|
+
}
|
|
30309
|
+
return {
|
|
30310
|
+
type: "geo",
|
|
30311
|
+
dataSetsHaveTitle: dataSets.length ? Boolean(dataSets[0].labelCell) : false,
|
|
30312
|
+
background: this.background,
|
|
30313
|
+
dataSets: ranges,
|
|
30314
|
+
legendPosition: this.legendPosition,
|
|
30315
|
+
labelRange: labelRange
|
|
30316
|
+
? this.getters.getRangeString(labelRange, targetSheetId || this.sheetId)
|
|
30317
|
+
: undefined,
|
|
30318
|
+
title: this.title,
|
|
30319
|
+
colorScale: this.colorScale,
|
|
30320
|
+
missingValueColor: this.missingValueColor,
|
|
30321
|
+
region: this.region,
|
|
30322
|
+
};
|
|
30323
|
+
}
|
|
30324
|
+
getDefinitionForExcel() {
|
|
30325
|
+
return undefined;
|
|
30326
|
+
}
|
|
30327
|
+
updateRanges(applyChange) {
|
|
30328
|
+
const { dataSets, labelRange, isStale } = updateChartRangesWithDataSets(this.getters, applyChange, this.dataSets, this.labelRange);
|
|
30329
|
+
if (!isStale) {
|
|
30330
|
+
return this;
|
|
30331
|
+
}
|
|
30332
|
+
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange);
|
|
30333
|
+
return new GeoChart(definition, this.sheetId, this.getters);
|
|
30334
|
+
}
|
|
30335
|
+
}
|
|
30336
|
+
function createGeoChartRuntime(chart, getters) {
|
|
30337
|
+
const definition = chart.getDefinition();
|
|
30338
|
+
const chartData = getGeoChartData(definition, chart.dataSets, chart.labelRange, getters);
|
|
30339
|
+
const config = {
|
|
30340
|
+
type: "choropleth",
|
|
30341
|
+
data: {
|
|
30342
|
+
datasets: getGeoChartDatasets(definition, chartData),
|
|
30343
|
+
},
|
|
30344
|
+
options: {
|
|
30345
|
+
...CHART_COMMON_OPTIONS,
|
|
30346
|
+
layout: getChartLayout(),
|
|
30347
|
+
scales: getGeoChartScales(definition, chartData),
|
|
30348
|
+
plugins: {
|
|
30349
|
+
title: getChartTitle(definition),
|
|
30350
|
+
tooltip: getGeoChartTooltip(definition, chartData),
|
|
30351
|
+
legend: { display: false },
|
|
30352
|
+
},
|
|
30353
|
+
},
|
|
30354
|
+
};
|
|
30355
|
+
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
30356
|
+
}
|
|
30357
|
+
|
|
29914
30358
|
class LineChart extends AbstractChart {
|
|
29915
30359
|
dataSets;
|
|
29916
30360
|
labelRange;
|
|
@@ -30904,6 +31348,15 @@ chartRegistry.add("radar", {
|
|
|
30904
31348
|
getChartDefinitionFromContextCreation: RadarChart.getDefinitionFromContextCreation,
|
|
30905
31349
|
sequence: 80,
|
|
30906
31350
|
});
|
|
31351
|
+
chartRegistry.add("geo", {
|
|
31352
|
+
match: (type) => type === "geo",
|
|
31353
|
+
createChart: (definition, sheetId, getters) => new GeoChart(definition, sheetId, getters),
|
|
31354
|
+
getChartRuntime: createGeoChartRuntime,
|
|
31355
|
+
validateChartDefinition: GeoChart.validateChartDefinition,
|
|
31356
|
+
transformDefinition: GeoChart.transformDefinition,
|
|
31357
|
+
getChartDefinitionFromContextCreation: GeoChart.getDefinitionFromContextCreation,
|
|
31358
|
+
sequence: 90,
|
|
31359
|
+
});
|
|
30907
31360
|
const chartComponentRegistry = new Registry();
|
|
30908
31361
|
chartComponentRegistry.add("line", ChartJsComponent);
|
|
30909
31362
|
chartComponentRegistry.add("bar", ChartJsComponent);
|
|
@@ -30915,6 +31368,7 @@ chartComponentRegistry.add("scorecard", ScorecardChart);
|
|
|
30915
31368
|
chartComponentRegistry.add("waterfall", ChartJsComponent);
|
|
30916
31369
|
chartComponentRegistry.add("pyramid", ChartJsComponent);
|
|
30917
31370
|
chartComponentRegistry.add("radar", ChartJsComponent);
|
|
31371
|
+
chartComponentRegistry.add("geo", ChartJsComponent);
|
|
30918
31372
|
const chartCategories = {
|
|
30919
31373
|
line: _t("Line"),
|
|
30920
31374
|
column: _t("Column"),
|
|
@@ -31074,6 +31528,13 @@ chartSubtypeRegistry
|
|
|
31074
31528
|
subtypeDefinition: { fillArea: true },
|
|
31075
31529
|
category: "misc",
|
|
31076
31530
|
preview: "o-spreadsheet-ChartPreview.FILLED_RADAR_CHART",
|
|
31531
|
+
})
|
|
31532
|
+
.add("geo", {
|
|
31533
|
+
displayName: _t("Geo Chart"),
|
|
31534
|
+
chartSubtype: "geo",
|
|
31535
|
+
chartType: "geo",
|
|
31536
|
+
category: "misc",
|
|
31537
|
+
preview: "o-spreadsheet-ChartPreview.GEO_CHART",
|
|
31077
31538
|
});
|
|
31078
31539
|
|
|
31079
31540
|
/**
|
|
@@ -31924,18 +32385,66 @@ const ErrorToolTipPopoverBuilder = {
|
|
|
31924
32385
|
},
|
|
31925
32386
|
};
|
|
31926
32387
|
|
|
31927
|
-
|
|
31928
|
-
|
|
31929
|
-
|
|
31930
|
-
|
|
31931
|
-
|
|
31932
|
-
|
|
31933
|
-
|
|
32388
|
+
const CHECK_SVG = /*xml*/ `
|
|
32389
|
+
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'>
|
|
32390
|
+
<path fill='none' stroke='#FFF' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/>
|
|
32391
|
+
</svg>
|
|
32392
|
+
`;
|
|
32393
|
+
const CHECKBOX_WIDTH = 14;
|
|
32394
|
+
css /* scss */ `
|
|
32395
|
+
label.o-checkbox {
|
|
32396
|
+
input {
|
|
32397
|
+
appearance: none;
|
|
32398
|
+
-webkit-appearance: none;
|
|
32399
|
+
-moz-appearance: none;
|
|
32400
|
+
border-radius: 0;
|
|
32401
|
+
width: ${CHECKBOX_WIDTH}px;
|
|
32402
|
+
height: ${CHECKBOX_WIDTH}px;
|
|
32403
|
+
vertical-align: top;
|
|
32404
|
+
box-sizing: border-box;
|
|
32405
|
+
outline: none;
|
|
32406
|
+
border: 1px solid ${GRAY_300};
|
|
32407
|
+
cursor: pointer;
|
|
32408
|
+
|
|
32409
|
+
&:hover {
|
|
32410
|
+
border-color: ${ACTION_COLOR};
|
|
32411
|
+
}
|
|
32412
|
+
|
|
32413
|
+
&:checked {
|
|
32414
|
+
background: url("data:image/svg+xml,${encodeURIComponent(CHECK_SVG)}");
|
|
32415
|
+
background-color: ${ACTION_COLOR};
|
|
32416
|
+
border-color: ${ACTION_COLOR};
|
|
32417
|
+
}
|
|
32418
|
+
|
|
32419
|
+
&:focus {
|
|
32420
|
+
outline: none;
|
|
32421
|
+
box-shadow: 0 0 0 0.25rem rgba(113, 75, 103, 0.25);
|
|
32422
|
+
border-color: ${ACTION_COLOR};
|
|
32423
|
+
}
|
|
31934
32424
|
}
|
|
31935
32425
|
}
|
|
31936
32426
|
`;
|
|
32427
|
+
class Checkbox extends Component {
|
|
32428
|
+
static template = "o-spreadsheet.Checkbox";
|
|
32429
|
+
static props = {
|
|
32430
|
+
label: { type: String, optional: true },
|
|
32431
|
+
value: { type: Boolean, optional: true },
|
|
32432
|
+
className: { type: String, optional: true },
|
|
32433
|
+
name: { type: String, optional: true },
|
|
32434
|
+
title: { type: String, optional: true },
|
|
32435
|
+
disabled: { type: Boolean, optional: true },
|
|
32436
|
+
onChange: Function,
|
|
32437
|
+
};
|
|
32438
|
+
static defaultProps = { value: false };
|
|
32439
|
+
onChange(ev) {
|
|
32440
|
+
const value = ev.target.checked;
|
|
32441
|
+
this.props.onChange(value);
|
|
32442
|
+
}
|
|
32443
|
+
}
|
|
32444
|
+
|
|
31937
32445
|
class FilterMenuValueItem extends Component {
|
|
31938
32446
|
static template = "o-spreadsheet-FilterMenuValueItem";
|
|
32447
|
+
static components = { Checkbox };
|
|
31939
32448
|
static props = {
|
|
31940
32449
|
value: String,
|
|
31941
32450
|
isChecked: Boolean,
|
|
@@ -31973,8 +32482,6 @@ const CSS = css /* scss */ `
|
|
|
31973
32482
|
.o-filter-menu-item {
|
|
31974
32483
|
display: flex;
|
|
31975
32484
|
box-sizing: border-box;
|
|
31976
|
-
height: ${MENU_ITEM_HEIGHT}px;
|
|
31977
|
-
padding: 4px 4px 4px 0px;
|
|
31978
32485
|
cursor: pointer;
|
|
31979
32486
|
user-select: none;
|
|
31980
32487
|
|
|
@@ -31983,14 +32490,6 @@ const CSS = css /* scss */ `
|
|
|
31983
32490
|
}
|
|
31984
32491
|
}
|
|
31985
32492
|
|
|
31986
|
-
input {
|
|
31987
|
-
box-sizing: border-box;
|
|
31988
|
-
margin-bottom: 5px;
|
|
31989
|
-
border: 1px solid #949494;
|
|
31990
|
-
height: 24px;
|
|
31991
|
-
padding-right: 28px;
|
|
31992
|
-
}
|
|
31993
|
-
|
|
31994
32493
|
.o-search-icon {
|
|
31995
32494
|
right: 5px;
|
|
31996
32495
|
top: 3px;
|
|
@@ -32007,19 +32506,12 @@ const CSS = css /* scss */ `
|
|
|
32007
32506
|
display: flex;
|
|
32008
32507
|
flex-direction: row;
|
|
32009
32508
|
margin-bottom: 4px;
|
|
32010
|
-
|
|
32011
|
-
.o-filter-menu-action-text {
|
|
32012
|
-
cursor: pointer;
|
|
32013
|
-
margin-right: 10px;
|
|
32014
|
-
color: blue;
|
|
32015
|
-
text-decoration: underline;
|
|
32016
|
-
}
|
|
32017
32509
|
}
|
|
32018
32510
|
|
|
32019
32511
|
.o-filter-menu-list {
|
|
32020
32512
|
flex: auto;
|
|
32021
32513
|
overflow-y: auto;
|
|
32022
|
-
border: 1px solid
|
|
32514
|
+
border: 1px solid ${GRAY_300};
|
|
32023
32515
|
|
|
32024
32516
|
.o-filter-menu-no-values {
|
|
32025
32517
|
color: #949494;
|
|
@@ -34211,6 +34703,21 @@ const pivotProperties = {
|
|
|
34211
34703
|
isReadonlyAllowed: true,
|
|
34212
34704
|
icon: "o-spreadsheet-Icon.PIVOT",
|
|
34213
34705
|
};
|
|
34706
|
+
const pivotSortingAsc = {
|
|
34707
|
+
name: _t("Ascending"),
|
|
34708
|
+
execute: (env) => sortPivot(env, "asc"),
|
|
34709
|
+
isActive: (env) => isPivotSortMenuItemActive(env, "asc"),
|
|
34710
|
+
};
|
|
34711
|
+
const pivotSortingDesc = {
|
|
34712
|
+
name: _t("Descending"),
|
|
34713
|
+
execute: (env) => sortPivot(env, "desc"),
|
|
34714
|
+
isActive: (env) => isPivotSortMenuItemActive(env, "desc"),
|
|
34715
|
+
};
|
|
34716
|
+
const noPivotSorting = {
|
|
34717
|
+
name: _t("No sorting"),
|
|
34718
|
+
execute: (env) => sortPivot(env, "none"),
|
|
34719
|
+
isActive: (env) => isPivotSortMenuItemActive(env, "none"),
|
|
34720
|
+
};
|
|
34214
34721
|
const FIX_FORMULAS = {
|
|
34215
34722
|
name: _t("Convert to individual formulas"),
|
|
34216
34723
|
execute(env) {
|
|
@@ -34247,6 +34754,66 @@ const FIX_FORMULAS = {
|
|
|
34247
34754
|
},
|
|
34248
34755
|
icon: "o-spreadsheet-Icon.PIVOT",
|
|
34249
34756
|
};
|
|
34757
|
+
function canSortPivot(env) {
|
|
34758
|
+
const position = env.model.getters.getActivePosition();
|
|
34759
|
+
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
34760
|
+
if (!pivotId ||
|
|
34761
|
+
!env.model.getters.isExistingPivot(pivotId) ||
|
|
34762
|
+
!env.model.getters.isSpillPivotFormula(position)) {
|
|
34763
|
+
return false;
|
|
34764
|
+
}
|
|
34765
|
+
const pivot = env.model.getters.getPivot(pivotId);
|
|
34766
|
+
if (!pivot.isValid()) {
|
|
34767
|
+
return false;
|
|
34768
|
+
}
|
|
34769
|
+
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
34770
|
+
return pivotCell.type === "VALUE" || pivotCell.type === "MEASURE_HEADER";
|
|
34771
|
+
}
|
|
34772
|
+
function sortPivot(env, order) {
|
|
34773
|
+
const position = env.model.getters.getActivePosition();
|
|
34774
|
+
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
34775
|
+
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
34776
|
+
if (pivotCell.type === "EMPTY" || pivotCell.type === "HEADER" || !pivotId) {
|
|
34777
|
+
return;
|
|
34778
|
+
}
|
|
34779
|
+
if (order === "none") {
|
|
34780
|
+
env.model.dispatch("UPDATE_PIVOT", {
|
|
34781
|
+
pivotId: pivotId,
|
|
34782
|
+
pivot: {
|
|
34783
|
+
...env.model.getters.getPivotCoreDefinition(pivotId),
|
|
34784
|
+
sortedColumn: undefined,
|
|
34785
|
+
},
|
|
34786
|
+
});
|
|
34787
|
+
return;
|
|
34788
|
+
}
|
|
34789
|
+
const pivot = env.model.getters.getPivot(pivotId);
|
|
34790
|
+
const colDomain = domainToColRowDomain(pivot, pivotCell.domain).colDomain;
|
|
34791
|
+
env.model.dispatch("UPDATE_PIVOT", {
|
|
34792
|
+
pivotId: pivotId,
|
|
34793
|
+
pivot: {
|
|
34794
|
+
...env.model.getters.getPivotCoreDefinition(pivotId),
|
|
34795
|
+
sortedColumn: { domain: colDomain, order, measure: pivotCell.measure },
|
|
34796
|
+
},
|
|
34797
|
+
});
|
|
34798
|
+
}
|
|
34799
|
+
function isPivotSortMenuItemActive(env, order) {
|
|
34800
|
+
const position = env.model.getters.getActivePosition();
|
|
34801
|
+
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
34802
|
+
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
34803
|
+
if (pivotCell.type === "EMPTY" || pivotCell.type === "HEADER" || !pivotId) {
|
|
34804
|
+
return false;
|
|
34805
|
+
}
|
|
34806
|
+
const pivot = env.model.getters.getPivot(pivotId);
|
|
34807
|
+
const colDomain = domainToColRowDomain(pivot, pivotCell.domain).colDomain;
|
|
34808
|
+
const sortedColumn = pivot.definition.sortedColumn;
|
|
34809
|
+
if (order === "none") {
|
|
34810
|
+
return !sortedColumn;
|
|
34811
|
+
}
|
|
34812
|
+
if (!sortedColumn || sortedColumn.order !== order) {
|
|
34813
|
+
return false;
|
|
34814
|
+
}
|
|
34815
|
+
return sortedColumn.measure === pivotCell.measure && deepEquals(sortedColumn.domain, colDomain);
|
|
34816
|
+
}
|
|
34250
34817
|
|
|
34251
34818
|
//------------------------------------------------------------------------------
|
|
34252
34819
|
// Context Menu Registry
|
|
@@ -34345,14 +34912,33 @@ cellMenuRegistry
|
|
|
34345
34912
|
name: INSERT_LINK_NAME,
|
|
34346
34913
|
sequence: 150,
|
|
34347
34914
|
separator: true,
|
|
34915
|
+
})
|
|
34916
|
+
.add("pivot_sorting", {
|
|
34917
|
+
name: _t("Sort pivot"),
|
|
34918
|
+
sequence: 155,
|
|
34919
|
+
icon: "o-spreadsheet-Icon.SORT_RANGE",
|
|
34920
|
+
isVisible: canSortPivot,
|
|
34348
34921
|
})
|
|
34349
34922
|
.add("pivot_fix_formulas", {
|
|
34350
34923
|
...FIX_FORMULAS,
|
|
34351
|
-
sequence:
|
|
34924
|
+
sequence: 160,
|
|
34352
34925
|
})
|
|
34353
34926
|
.add("pivot_properties", {
|
|
34354
34927
|
...pivotProperties,
|
|
34355
34928
|
sequence: 170,
|
|
34929
|
+
separator: true,
|
|
34930
|
+
})
|
|
34931
|
+
.addChild("pivot_sorting_asc", ["pivot_sorting"], {
|
|
34932
|
+
...pivotSortingAsc,
|
|
34933
|
+
sequence: 10,
|
|
34934
|
+
})
|
|
34935
|
+
.addChild("pivot_sorting_desc", ["pivot_sorting"], {
|
|
34936
|
+
...pivotSortingDesc,
|
|
34937
|
+
sequence: 20,
|
|
34938
|
+
})
|
|
34939
|
+
.addChild("pivot_sorting_none", ["pivot_sorting"], {
|
|
34940
|
+
...noPivotSorting,
|
|
34941
|
+
sequence: 30,
|
|
34356
34942
|
});
|
|
34357
34943
|
|
|
34358
34944
|
const sortRange = {
|
|
@@ -34365,7 +34951,7 @@ const sortAscending = {
|
|
|
34365
34951
|
execute: (env) => {
|
|
34366
34952
|
const { anchor, zones } = env.model.getters.getSelection();
|
|
34367
34953
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
34368
|
-
interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "
|
|
34954
|
+
interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "asc");
|
|
34369
34955
|
},
|
|
34370
34956
|
icon: "o-spreadsheet-Icon.SORT_ASCENDING",
|
|
34371
34957
|
};
|
|
@@ -34393,7 +34979,7 @@ const sortDescending = {
|
|
|
34393
34979
|
execute: (env) => {
|
|
34394
34980
|
const { anchor, zones } = env.model.getters.getSelection();
|
|
34395
34981
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
34396
|
-
interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "
|
|
34982
|
+
interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "desc");
|
|
34397
34983
|
},
|
|
34398
34984
|
icon: "o-spreadsheet-Icon.SORT_DESCENDING",
|
|
34399
34985
|
};
|
|
@@ -34876,6 +35462,227 @@ function interactiveFreezeColumnsRows(env, dimension, base) {
|
|
|
34876
35462
|
}
|
|
34877
35463
|
}
|
|
34878
35464
|
|
|
35465
|
+
class PositionMap {
|
|
35466
|
+
map = {};
|
|
35467
|
+
constructor(entries = []) {
|
|
35468
|
+
for (const [position, value] of entries) {
|
|
35469
|
+
this.set(position, value);
|
|
35470
|
+
}
|
|
35471
|
+
}
|
|
35472
|
+
set({ sheetId, col, row }, value) {
|
|
35473
|
+
const map = this.map;
|
|
35474
|
+
if (!map[sheetId]) {
|
|
35475
|
+
map[sheetId] = {};
|
|
35476
|
+
}
|
|
35477
|
+
if (!map[sheetId][col]) {
|
|
35478
|
+
map[sheetId][col] = {};
|
|
35479
|
+
}
|
|
35480
|
+
map[sheetId][col][row] = value;
|
|
35481
|
+
}
|
|
35482
|
+
get({ sheetId, col, row }) {
|
|
35483
|
+
return this.map[sheetId]?.[col]?.[row];
|
|
35484
|
+
}
|
|
35485
|
+
getSheet(sheetId) {
|
|
35486
|
+
return this.map[sheetId];
|
|
35487
|
+
}
|
|
35488
|
+
has({ sheetId, col, row }) {
|
|
35489
|
+
return this.map[sheetId]?.[col]?.[row] !== undefined;
|
|
35490
|
+
}
|
|
35491
|
+
delete({ sheetId, col, row }) {
|
|
35492
|
+
delete this.map[sheetId]?.[col]?.[row];
|
|
35493
|
+
}
|
|
35494
|
+
keys() {
|
|
35495
|
+
const map = this.map;
|
|
35496
|
+
const keys = [];
|
|
35497
|
+
for (const sheetId in map) {
|
|
35498
|
+
for (const col in map[sheetId]) {
|
|
35499
|
+
for (const row in map[sheetId][col]) {
|
|
35500
|
+
keys.push({ sheetId, col: parseInt(col), row: parseInt(row) });
|
|
35501
|
+
}
|
|
35502
|
+
}
|
|
35503
|
+
}
|
|
35504
|
+
return keys;
|
|
35505
|
+
}
|
|
35506
|
+
keysForSheet(sheetId) {
|
|
35507
|
+
const map = this.map[sheetId];
|
|
35508
|
+
if (!map) {
|
|
35509
|
+
return [];
|
|
35510
|
+
}
|
|
35511
|
+
const keys = [];
|
|
35512
|
+
for (const col in map) {
|
|
35513
|
+
for (const row in map[col]) {
|
|
35514
|
+
keys.push({ sheetId, col: parseInt(col), row: parseInt(row) });
|
|
35515
|
+
}
|
|
35516
|
+
}
|
|
35517
|
+
return keys;
|
|
35518
|
+
}
|
|
35519
|
+
*entries() {
|
|
35520
|
+
const map = this.map;
|
|
35521
|
+
for (const position of this.keys()) {
|
|
35522
|
+
const { sheetId, col, row } = position;
|
|
35523
|
+
yield [position, map[sheetId][col][row]];
|
|
35524
|
+
}
|
|
35525
|
+
}
|
|
35526
|
+
}
|
|
35527
|
+
|
|
35528
|
+
class FormulaFingerprintStore extends SpreadsheetStore {
|
|
35529
|
+
mutators = ["enable", "disable"];
|
|
35530
|
+
isInvalidated = false;
|
|
35531
|
+
fingerprintColors = {
|
|
35532
|
+
[DATA_FINGERPRINT]: "#D9D9D9",
|
|
35533
|
+
};
|
|
35534
|
+
isEnabled = false;
|
|
35535
|
+
colors = new PositionMap();
|
|
35536
|
+
handle(cmd) {
|
|
35537
|
+
if (isCoreCommand(cmd) && this.isEnabled) {
|
|
35538
|
+
this.isInvalidated = true;
|
|
35539
|
+
}
|
|
35540
|
+
switch (cmd.type) {
|
|
35541
|
+
case "UNDO":
|
|
35542
|
+
case "REDO":
|
|
35543
|
+
case "ACTIVATE_SHEET":
|
|
35544
|
+
if (this.isEnabled) {
|
|
35545
|
+
this.isInvalidated = true;
|
|
35546
|
+
}
|
|
35547
|
+
break;
|
|
35548
|
+
}
|
|
35549
|
+
}
|
|
35550
|
+
finalize() {
|
|
35551
|
+
if (this.isInvalidated) {
|
|
35552
|
+
this.isInvalidated = false;
|
|
35553
|
+
this.computeFingerprints();
|
|
35554
|
+
}
|
|
35555
|
+
}
|
|
35556
|
+
enable() {
|
|
35557
|
+
this.isEnabled = true;
|
|
35558
|
+
this.computeFingerprints();
|
|
35559
|
+
}
|
|
35560
|
+
disable() {
|
|
35561
|
+
this.isEnabled = false;
|
|
35562
|
+
this.colors = new PositionMap();
|
|
35563
|
+
}
|
|
35564
|
+
computeFingerprints() {
|
|
35565
|
+
this.colors = new PositionMap();
|
|
35566
|
+
const fingerprints = new PositionMap();
|
|
35567
|
+
const allFingerprints = new Set();
|
|
35568
|
+
const activeSheetId = this.getters.getActiveSheetId();
|
|
35569
|
+
const cells = this.getters.getCells(activeSheetId);
|
|
35570
|
+
for (const cellId in cells) {
|
|
35571
|
+
const fingerprint = this.computeFingerprint(cells[cellId]);
|
|
35572
|
+
if (!fingerprint) {
|
|
35573
|
+
continue;
|
|
35574
|
+
}
|
|
35575
|
+
allFingerprints.add(fingerprint);
|
|
35576
|
+
const position = this.getters.getCellPosition(cellId);
|
|
35577
|
+
fingerprints.set(position, fingerprint);
|
|
35578
|
+
}
|
|
35579
|
+
this.assignColors(allFingerprints);
|
|
35580
|
+
for (const [position, fingerprint] of fingerprints.entries()) {
|
|
35581
|
+
const color = this.fingerprintColors[fingerprint];
|
|
35582
|
+
this.colors.set(position, color);
|
|
35583
|
+
this.colorSpreadZone(position, color);
|
|
35584
|
+
}
|
|
35585
|
+
}
|
|
35586
|
+
colorSpreadZone(position, fingerprintColor) {
|
|
35587
|
+
const spreadZone = this.getters.getSpreadZone(position);
|
|
35588
|
+
if (!spreadZone) {
|
|
35589
|
+
return;
|
|
35590
|
+
}
|
|
35591
|
+
const sheetId = position.sheetId;
|
|
35592
|
+
for (let row = spreadZone.top; row <= spreadZone.bottom; row++) {
|
|
35593
|
+
for (let col = spreadZone.left; col <= spreadZone.right; col++) {
|
|
35594
|
+
const spreadPosition = { sheetId, col, row };
|
|
35595
|
+
this.colors.set(spreadPosition, fingerprintColor);
|
|
35596
|
+
}
|
|
35597
|
+
}
|
|
35598
|
+
}
|
|
35599
|
+
assignColors(fingerprints) {
|
|
35600
|
+
const colors = new AlternatingColorGenerator(fingerprints.size);
|
|
35601
|
+
Object.keys(this.fingerprintColors).forEach(() => colors.next());
|
|
35602
|
+
for (const fingerprint of fingerprints) {
|
|
35603
|
+
if (!this.fingerprintColors[fingerprint]) {
|
|
35604
|
+
this.fingerprintColors[fingerprint] = setColorAlpha(colors.next(), 0.8);
|
|
35605
|
+
}
|
|
35606
|
+
}
|
|
35607
|
+
}
|
|
35608
|
+
computeFingerprint(cell) {
|
|
35609
|
+
const position = this.getters.getCellPosition(cell.id);
|
|
35610
|
+
if (cell.isFormula) {
|
|
35611
|
+
return this.computeFormulaFingerprint(position, cell);
|
|
35612
|
+
}
|
|
35613
|
+
else {
|
|
35614
|
+
return this.getLiteralFingerprint(position);
|
|
35615
|
+
}
|
|
35616
|
+
}
|
|
35617
|
+
computeFormulaFingerprint(position, cell) {
|
|
35618
|
+
const dependencies = cell.compiledFormula.dependencies;
|
|
35619
|
+
const colCellOffset = position.col;
|
|
35620
|
+
const rowCellOffset = position.row;
|
|
35621
|
+
const positionSheetIndex = this.getters.getSheetIds().indexOf(position.sheetId);
|
|
35622
|
+
// As an optimization, we do not build each reference vector individually
|
|
35623
|
+
// to sum them up, but instead we directly add each component to the resulting
|
|
35624
|
+
// vector. This is equivalent to summing up all reference vectors.
|
|
35625
|
+
const fingerprintVector = {
|
|
35626
|
+
dx: 0,
|
|
35627
|
+
dy: 0,
|
|
35628
|
+
dSheet: 0,
|
|
35629
|
+
};
|
|
35630
|
+
for (const range of dependencies) {
|
|
35631
|
+
const zone = range.zone;
|
|
35632
|
+
const [left, right] = range.parts;
|
|
35633
|
+
const rangeSheetIndex = this.getters.getSheetIds().indexOf(range.sheetId);
|
|
35634
|
+
fingerprintVector.dSheet = rangeSheetIndex - positionSheetIndex;
|
|
35635
|
+
// in relative mode, we offset the col and row by the cell's position
|
|
35636
|
+
// in absolute mode, we offset the col and row relative to the sheet
|
|
35637
|
+
const isLeftUnbounded = range.isFullRow && !range.unboundedZone.hasHeader;
|
|
35638
|
+
const isTopUnbounded = range.isFullCol && !range.unboundedZone.hasHeader;
|
|
35639
|
+
const leftOffset = isLeftUnbounded || left?.colFixed ? 0 : colCellOffset;
|
|
35640
|
+
const topOffset = isTopUnbounded || left?.rowFixed ? 0 : rowCellOffset;
|
|
35641
|
+
const isRightFixed = (!right && left?.colFixed) || right?.colFixed;
|
|
35642
|
+
const isBottomFixed = (!right && left.rowFixed) || right?.rowFixed;
|
|
35643
|
+
const isRightUnbounded = range.unboundedZone.right === undefined;
|
|
35644
|
+
const isBottomUnbounded = range.unboundedZone.bottom === undefined;
|
|
35645
|
+
const rightOffset = isRightUnbounded || isRightFixed ? 0 : colCellOffset;
|
|
35646
|
+
const bottomOffset = isBottomUnbounded || isBottomFixed ? 0 : rowCellOffset;
|
|
35647
|
+
const referenceZone = reorderZone({
|
|
35648
|
+
top: zone.top - topOffset,
|
|
35649
|
+
left: zone.left - leftOffset,
|
|
35650
|
+
right: zone.right - rightOffset,
|
|
35651
|
+
bottom: zone.bottom - bottomOffset,
|
|
35652
|
+
});
|
|
35653
|
+
for (let dy = referenceZone.top; dy <= referenceZone.bottom; dy++) {
|
|
35654
|
+
for (let dx = referenceZone.left; dx <= referenceZone.right; dx++) {
|
|
35655
|
+
fingerprintVector.dx += dx;
|
|
35656
|
+
fingerprintVector.dy += dy;
|
|
35657
|
+
}
|
|
35658
|
+
}
|
|
35659
|
+
}
|
|
35660
|
+
// removes the index placeholders from the normalized formula
|
|
35661
|
+
// =|N0|+|N1|+|N0| -> =|N|+|N|+|N|
|
|
35662
|
+
const normalizedFormula = cell.compiledFormula.normalizedFormula.replace(/(|\w)(\d)(|)/g, "$1$3");
|
|
35663
|
+
return hash(fingerprintVector) + normalizedFormula;
|
|
35664
|
+
}
|
|
35665
|
+
getLiteralFingerprint(position) {
|
|
35666
|
+
const evaluatedCell = this.getters.getEvaluatedCell(position);
|
|
35667
|
+
switch (evaluatedCell.type) {
|
|
35668
|
+
case CellValueType.number:
|
|
35669
|
+
case CellValueType.boolean:
|
|
35670
|
+
return DATA_FINGERPRINT;
|
|
35671
|
+
case CellValueType.text:
|
|
35672
|
+
case CellValueType.empty:
|
|
35673
|
+
case CellValueType.error:
|
|
35674
|
+
return undefined;
|
|
35675
|
+
}
|
|
35676
|
+
}
|
|
35677
|
+
}
|
|
35678
|
+
function hash(vector) {
|
|
35679
|
+
return Object.entries(vector)
|
|
35680
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
35681
|
+
.map(([_, value]) => value)
|
|
35682
|
+
.join(",");
|
|
35683
|
+
}
|
|
35684
|
+
const DATA_FINGERPRINT = "DATA_FINGERPRINT";
|
|
35685
|
+
|
|
34879
35686
|
const hideCols = {
|
|
34880
35687
|
name: HIDE_COLUMNS_NAME,
|
|
34881
35688
|
execute: (env) => {
|
|
@@ -35047,6 +35854,19 @@ const viewGridlines = {
|
|
|
35047
35854
|
return env.model.getters.getGridLinesVisibility(sheetId);
|
|
35048
35855
|
},
|
|
35049
35856
|
};
|
|
35857
|
+
const irregularityMap = {
|
|
35858
|
+
name: _t("Irregularity map"),
|
|
35859
|
+
execute: (env) => {
|
|
35860
|
+
const fingerprintStore = env.getStore(FormulaFingerprintStore);
|
|
35861
|
+
if (fingerprintStore.isEnabled) {
|
|
35862
|
+
fingerprintStore.disable();
|
|
35863
|
+
}
|
|
35864
|
+
else {
|
|
35865
|
+
fingerprintStore.enable();
|
|
35866
|
+
}
|
|
35867
|
+
},
|
|
35868
|
+
icon: "o-spreadsheet-Icon.IRREGULARITY_MAP",
|
|
35869
|
+
};
|
|
35050
35870
|
const viewFormulas = {
|
|
35051
35871
|
name: _t("Formulas"),
|
|
35052
35872
|
isActive: (env) => env.model.getters.shouldShowFormulas(),
|
|
@@ -35664,6 +36484,11 @@ topbarMenuRegistry
|
|
|
35664
36484
|
.addChild("view_formulas", ["view", "show"], {
|
|
35665
36485
|
...viewFormulas,
|
|
35666
36486
|
sequence: 10,
|
|
36487
|
+
})
|
|
36488
|
+
.addChild("view_irregularity_map", ["view"], {
|
|
36489
|
+
...irregularityMap,
|
|
36490
|
+
sequence: 40,
|
|
36491
|
+
separator: true,
|
|
35667
36492
|
})
|
|
35668
36493
|
// ---------------------------------------------------------------------
|
|
35669
36494
|
// INSERT MENU ITEMS
|
|
@@ -35966,62 +36791,6 @@ class OTRegistry extends Registry {
|
|
|
35966
36791
|
}
|
|
35967
36792
|
const otRegistry = new OTRegistry();
|
|
35968
36793
|
|
|
35969
|
-
const CHECK_SVG = /*xml*/ `
|
|
35970
|
-
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'>
|
|
35971
|
-
<path fill='none' stroke='#FFF' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/>
|
|
35972
|
-
</svg>
|
|
35973
|
-
`;
|
|
35974
|
-
const CHECKBOX_WIDTH = 14;
|
|
35975
|
-
css /* scss */ `
|
|
35976
|
-
label.o-checkbox {
|
|
35977
|
-
input {
|
|
35978
|
-
appearance: none;
|
|
35979
|
-
-webkit-appearance: none;
|
|
35980
|
-
-moz-appearance: none;
|
|
35981
|
-
border-radius: 0;
|
|
35982
|
-
width: ${CHECKBOX_WIDTH}px;
|
|
35983
|
-
height: ${CHECKBOX_WIDTH}px;
|
|
35984
|
-
vertical-align: top;
|
|
35985
|
-
box-sizing: border-box;
|
|
35986
|
-
outline: none;
|
|
35987
|
-
border: 1px solid ${GRAY_300};
|
|
35988
|
-
|
|
35989
|
-
&:hover {
|
|
35990
|
-
border-color: ${ACTION_COLOR};
|
|
35991
|
-
}
|
|
35992
|
-
|
|
35993
|
-
&:checked {
|
|
35994
|
-
background: url("data:image/svg+xml,${encodeURIComponent(CHECK_SVG)}");
|
|
35995
|
-
background-color: ${ACTION_COLOR};
|
|
35996
|
-
border-color: ${ACTION_COLOR};
|
|
35997
|
-
}
|
|
35998
|
-
|
|
35999
|
-
&:focus {
|
|
36000
|
-
outline: none;
|
|
36001
|
-
box-shadow: 0 0 0 0.25rem rgba(113, 75, 103, 0.25);
|
|
36002
|
-
border-color: ${ACTION_COLOR};
|
|
36003
|
-
}
|
|
36004
|
-
}
|
|
36005
|
-
}
|
|
36006
|
-
`;
|
|
36007
|
-
class Checkbox extends Component {
|
|
36008
|
-
static template = "o-spreadsheet.Checkbox";
|
|
36009
|
-
static props = {
|
|
36010
|
-
label: { type: String, optional: true },
|
|
36011
|
-
value: { type: Boolean, optional: true },
|
|
36012
|
-
className: { type: String, optional: true },
|
|
36013
|
-
name: { type: String, optional: true },
|
|
36014
|
-
title: { type: String, optional: true },
|
|
36015
|
-
disabled: { type: Boolean, optional: true },
|
|
36016
|
-
onChange: Function,
|
|
36017
|
-
};
|
|
36018
|
-
static defaultProps = { value: false };
|
|
36019
|
-
onChange(ev) {
|
|
36020
|
-
const value = ev.target.checked;
|
|
36021
|
-
this.props.onChange(value);
|
|
36022
|
-
}
|
|
36023
|
-
}
|
|
36024
|
-
|
|
36025
36794
|
class Section extends Component {
|
|
36026
36795
|
static template = "o_spreadsheet.Section";
|
|
36027
36796
|
static props = {
|
|
@@ -38261,6 +39030,104 @@ class GaugeChartDesignPanel extends Component {
|
|
|
38261
39030
|
}
|
|
38262
39031
|
}
|
|
38263
39032
|
|
|
39033
|
+
class GeoChartRegionSelectSection extends Component {
|
|
39034
|
+
static template = "o-spreadsheet-GeoChartRegionSelectSection";
|
|
39035
|
+
static components = { Section };
|
|
39036
|
+
static props = {
|
|
39037
|
+
figureId: String,
|
|
39038
|
+
definition: Object,
|
|
39039
|
+
updateChart: Function,
|
|
39040
|
+
};
|
|
39041
|
+
updateSelectedRegion(ev) {
|
|
39042
|
+
const value = ev.target.value;
|
|
39043
|
+
this.props.updateChart(this.props.figureId, { region: value });
|
|
39044
|
+
}
|
|
39045
|
+
get availableRegions() {
|
|
39046
|
+
return this.env.model.getters.getGeoChartAvailableRegions();
|
|
39047
|
+
}
|
|
39048
|
+
get selectedRegion() {
|
|
39049
|
+
return this.props.definition.region || this.availableRegions[0]?.id;
|
|
39050
|
+
}
|
|
39051
|
+
}
|
|
39052
|
+
|
|
39053
|
+
class GeoChartConfigPanel extends GenericChartConfigPanel {
|
|
39054
|
+
static template = "o-spreadsheet-GeoChartConfigPanel";
|
|
39055
|
+
static components = { ...GenericChartConfigPanel.components, GeoChartRegionSelectSection };
|
|
39056
|
+
get dataRanges() {
|
|
39057
|
+
return this.getDataSeriesRanges().slice(0, 1);
|
|
39058
|
+
}
|
|
39059
|
+
onDataSeriesConfirmed() {
|
|
39060
|
+
this.dataSeriesRanges = spreadRange(this.env.model.getters, this.dataSeriesRanges).slice(0, 1);
|
|
39061
|
+
this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
|
|
39062
|
+
dataSets: this.dataSeriesRanges,
|
|
39063
|
+
});
|
|
39064
|
+
}
|
|
39065
|
+
getLabelRangeOptions() {
|
|
39066
|
+
return [
|
|
39067
|
+
{
|
|
39068
|
+
name: "dataSetsHaveTitle",
|
|
39069
|
+
label: this.dataSetsHaveTitleLabel,
|
|
39070
|
+
value: this.props.definition.dataSetsHaveTitle,
|
|
39071
|
+
onChange: this.onUpdateDataSetsHaveTitle.bind(this),
|
|
39072
|
+
},
|
|
39073
|
+
];
|
|
39074
|
+
}
|
|
39075
|
+
}
|
|
39076
|
+
|
|
39077
|
+
const DEFAULT_CUSTOM_COLOR_SCALE = {
|
|
39078
|
+
minColor: "#FFF5EB",
|
|
39079
|
+
midColor: "#FD8D3C",
|
|
39080
|
+
maxColor: "#7F2704",
|
|
39081
|
+
};
|
|
39082
|
+
class GeoChartDesignPanel extends ChartWithAxisDesignPanel {
|
|
39083
|
+
static template = "o-spreadsheet-GeoChartDesignPanel";
|
|
39084
|
+
static components = { ...ChartWithAxisDesignPanel.components, RoundColorPicker };
|
|
39085
|
+
colorScalesChoices = ChartTerms.GeoChart.ColorScales;
|
|
39086
|
+
updateColorScaleType(ev) {
|
|
39087
|
+
const value = ev.target.value;
|
|
39088
|
+
value === "custom"
|
|
39089
|
+
? this.updateColorScale(DEFAULT_CUSTOM_COLOR_SCALE)
|
|
39090
|
+
: this.updateColorScale(value);
|
|
39091
|
+
}
|
|
39092
|
+
updateColorScale(colorScale) {
|
|
39093
|
+
this.props.updateChart(this.props.figureId, { colorScale });
|
|
39094
|
+
}
|
|
39095
|
+
updateMissingValueColor(color) {
|
|
39096
|
+
this.props.updateChart(this.props.figureId, { missingValueColor: color });
|
|
39097
|
+
}
|
|
39098
|
+
updateLegendPosition(ev) {
|
|
39099
|
+
const value = ev.target.value;
|
|
39100
|
+
this.props.updateChart(this.props.figureId, { legendPosition: value });
|
|
39101
|
+
}
|
|
39102
|
+
get selectedColorScale() {
|
|
39103
|
+
return typeof this.props.definition.colorScale === "object"
|
|
39104
|
+
? "custom"
|
|
39105
|
+
: this.props.definition.colorScale || "oranges";
|
|
39106
|
+
}
|
|
39107
|
+
get selectedMissingValueColor() {
|
|
39108
|
+
return this.props.definition.missingValueColor || "#ffffff";
|
|
39109
|
+
}
|
|
39110
|
+
get customColorScale() {
|
|
39111
|
+
if (typeof this.props.definition.colorScale === "object") {
|
|
39112
|
+
return this.props.definition.colorScale;
|
|
39113
|
+
}
|
|
39114
|
+
return undefined;
|
|
39115
|
+
}
|
|
39116
|
+
getCustomColorScaleColor(color) {
|
|
39117
|
+
return this.customColorScale?.[color] ?? "";
|
|
39118
|
+
}
|
|
39119
|
+
setCustomColorScaleColor(colorType, color) {
|
|
39120
|
+
if (!color && colorType !== "midColor") {
|
|
39121
|
+
color = "#fff";
|
|
39122
|
+
}
|
|
39123
|
+
const customColorScale = this.customColorScale;
|
|
39124
|
+
if (!customColorScale) {
|
|
39125
|
+
return;
|
|
39126
|
+
}
|
|
39127
|
+
this.updateColorScale({ ...customColorScale, [colorType]: color });
|
|
39128
|
+
}
|
|
39129
|
+
}
|
|
39130
|
+
|
|
38264
39131
|
class LineConfigPanel extends GenericChartConfigPanel {
|
|
38265
39132
|
static template = "o-spreadsheet-LineConfigPanel";
|
|
38266
39133
|
get canTreatLabelsAsText() {
|
|
@@ -38574,6 +39441,10 @@ chartSidePanelComponentRegistry
|
|
|
38574
39441
|
.add("radar", {
|
|
38575
39442
|
configuration: GenericChartConfigPanel,
|
|
38576
39443
|
design: RadarChartDesignPanel,
|
|
39444
|
+
})
|
|
39445
|
+
.add("geo", {
|
|
39446
|
+
configuration: GeoChartConfigPanel,
|
|
39447
|
+
design: GeoChartDesignPanel,
|
|
38577
39448
|
});
|
|
38578
39449
|
|
|
38579
39450
|
css /* scss */ `
|
|
@@ -39937,7 +40808,7 @@ css /* scss */ `
|
|
|
39937
40808
|
border-color: ${GRAY_300};
|
|
39938
40809
|
|
|
39939
40810
|
&.active {
|
|
39940
|
-
border-color: ${
|
|
40811
|
+
border-color: ${ACTION_COLOR};
|
|
39941
40812
|
}
|
|
39942
40813
|
|
|
39943
40814
|
&.o-invalid {
|
|
@@ -40895,7 +41766,7 @@ class ConditionalFormattingEditor extends Component {
|
|
|
40895
41766
|
}
|
|
40896
41767
|
const point = this.state.rules.colorScale[target];
|
|
40897
41768
|
if (point) {
|
|
40898
|
-
point.color =
|
|
41769
|
+
point.color = colorToNumber(color);
|
|
40899
41770
|
}
|
|
40900
41771
|
this.updateConditionalFormat({ rule: this.state.rules.colorScale });
|
|
40901
41772
|
this.closeMenus();
|
|
@@ -41040,6 +41911,9 @@ class ConditionalFormattingEditor extends Component {
|
|
|
41040
41911
|
return [this.state.rules.dataBar.rangeValues || ""];
|
|
41041
41912
|
}
|
|
41042
41913
|
updateDataBarColor(color) {
|
|
41914
|
+
if (!isColorValid(color)) {
|
|
41915
|
+
return;
|
|
41916
|
+
}
|
|
41043
41917
|
this.state.rules.dataBar.color = Number.parseInt(color.slice(1), 16);
|
|
41044
41918
|
this.updateConditionalFormat({ rule: this.state.rules.dataBar });
|
|
41045
41919
|
}
|
|
@@ -41170,6 +42044,10 @@ css /* scss */ `
|
|
|
41170
42044
|
border: 1px solid #d8dadd;
|
|
41171
42045
|
color: #374151;
|
|
41172
42046
|
}
|
|
42047
|
+
|
|
42048
|
+
table {
|
|
42049
|
+
table-layout: fixed;
|
|
42050
|
+
}
|
|
41173
42051
|
}
|
|
41174
42052
|
`;
|
|
41175
42053
|
class CustomCurrencyPanel extends Component {
|
|
@@ -43643,6 +44521,64 @@ class PivotMeasureEditor extends Component {
|
|
|
43643
44521
|
}
|
|
43644
44522
|
}
|
|
43645
44523
|
|
|
44524
|
+
css /* scss */ `
|
|
44525
|
+
.o-pivot-sort {
|
|
44526
|
+
.o-sort-card {
|
|
44527
|
+
width: fit-content;
|
|
44528
|
+
background-color: ${GRAY_100};
|
|
44529
|
+
border: 1px solid ${GRAY_300};
|
|
44530
|
+
|
|
44531
|
+
.o-sort-value {
|
|
44532
|
+
color: ${PRIMARY_BUTTON_BG};
|
|
44533
|
+
}
|
|
44534
|
+
}
|
|
44535
|
+
}
|
|
44536
|
+
`;
|
|
44537
|
+
class PivotSortSection extends Component {
|
|
44538
|
+
static template = "o-spreadsheet-PivotSortSection";
|
|
44539
|
+
static components = {
|
|
44540
|
+
Section,
|
|
44541
|
+
};
|
|
44542
|
+
static props = {
|
|
44543
|
+
definition: Object,
|
|
44544
|
+
pivotId: String,
|
|
44545
|
+
};
|
|
44546
|
+
get hasValidSort() {
|
|
44547
|
+
const pivot = this.env.model.getters.getPivot(this.props.pivotId);
|
|
44548
|
+
return (!!this.props.definition.sortedColumn &&
|
|
44549
|
+
isSortedColumnValid(this.props.definition.sortedColumn, pivot));
|
|
44550
|
+
}
|
|
44551
|
+
get sortDescription() {
|
|
44552
|
+
const sortOrder = this.props.definition.sortedColumn?.order === "asc" ? _t("ascending") : _t("descending");
|
|
44553
|
+
return _t("Sorted on column (%(ascOrDesc)s):", {
|
|
44554
|
+
ascOrDesc: sortOrder,
|
|
44555
|
+
});
|
|
44556
|
+
}
|
|
44557
|
+
get sortValuesAndFields() {
|
|
44558
|
+
const sortedColumn = this.props.definition.sortedColumn;
|
|
44559
|
+
if (!sortedColumn) {
|
|
44560
|
+
return [];
|
|
44561
|
+
}
|
|
44562
|
+
const pivot = this.env.model.getters.getPivot(this.props.pivotId);
|
|
44563
|
+
const locale = this.env.model.getters.getLocale();
|
|
44564
|
+
const currentDomain = [];
|
|
44565
|
+
const sortValues = [];
|
|
44566
|
+
for (const domainItem of sortedColumn.domain) {
|
|
44567
|
+
currentDomain.push(domainItem);
|
|
44568
|
+
const { value, format } = pivot.getPivotHeaderValueAndFormat(currentDomain);
|
|
44569
|
+
const label = formatValue(value, { format, locale });
|
|
44570
|
+
const field = pivot.definition.getDimension(domainItem.field);
|
|
44571
|
+
sortValues.push({ field: getFieldDisplayName(field), value: label });
|
|
44572
|
+
}
|
|
44573
|
+
if (sortedColumn.domain.length === 0) {
|
|
44574
|
+
sortValues.push({ value: _t("Total") });
|
|
44575
|
+
}
|
|
44576
|
+
const measureLabel = pivot.getMeasure(sortedColumn.measure).displayName;
|
|
44577
|
+
sortValues.push({ value: measureLabel, field: _t("Measure") });
|
|
44578
|
+
return sortValues;
|
|
44579
|
+
}
|
|
44580
|
+
}
|
|
44581
|
+
|
|
43646
44582
|
css /* scss */ `
|
|
43647
44583
|
.add-calculated-measure {
|
|
43648
44584
|
cursor: pointer;
|
|
@@ -43656,6 +44592,7 @@ class PivotLayoutConfigurator extends Component {
|
|
|
43656
44592
|
PivotDimensionOrder,
|
|
43657
44593
|
PivotDimensionGranularity,
|
|
43658
44594
|
PivotMeasureEditor,
|
|
44595
|
+
PivotSortSection,
|
|
43659
44596
|
};
|
|
43660
44597
|
static props = {
|
|
43661
44598
|
definition: Object,
|
|
@@ -43812,9 +44749,13 @@ class PivotLayoutConfigurator extends Component {
|
|
|
43812
44749
|
}
|
|
43813
44750
|
updateMeasure(measure, newMeasure) {
|
|
43814
44751
|
const { measures } = this.props.definition;
|
|
43815
|
-
|
|
44752
|
+
const update = {
|
|
43816
44753
|
measures: measures.map((m) => (m.id === measure.id ? newMeasure : m)),
|
|
43817
|
-
}
|
|
44754
|
+
};
|
|
44755
|
+
if (this.props.definition.sortedColumn?.measure === measure.id) {
|
|
44756
|
+
update.sortedColumn = { ...this.props.definition.sortedColumn, measure: newMeasure.id };
|
|
44757
|
+
}
|
|
44758
|
+
this.props.onDimensionsUpdated(update);
|
|
43818
44759
|
}
|
|
43819
44760
|
getMeasureId(fieldName, aggregator) {
|
|
43820
44761
|
const baseId = fieldName + (aggregator ? `:${aggregator}` : "");
|
|
@@ -43970,10 +44911,12 @@ class PivotRuntimeDefinition {
|
|
|
43970
44911
|
measures;
|
|
43971
44912
|
columns;
|
|
43972
44913
|
rows;
|
|
44914
|
+
sortedColumn;
|
|
43973
44915
|
constructor(definition, fields) {
|
|
43974
44916
|
this.measures = definition.measures.map((measure) => createMeasure(fields, measure));
|
|
43975
44917
|
this.columns = definition.columns.map((dimension) => createPivotDimension(fields, dimension));
|
|
43976
44918
|
this.rows = definition.rows.map((dimension) => createPivotDimension(fields, dimension));
|
|
44919
|
+
this.sortedColumn = definition.sortedColumn;
|
|
43977
44920
|
}
|
|
43978
44921
|
getDimension(nameWithGranularity) {
|
|
43979
44922
|
const dimension = this.columns.find((d) => d.nameWithGranularity === nameWithGranularity) ||
|
|
@@ -44127,6 +45070,7 @@ class SpreadsheetPivotTable {
|
|
|
44127
45070
|
pivotCells = {};
|
|
44128
45071
|
rowTree;
|
|
44129
45072
|
colTree;
|
|
45073
|
+
isSorted = false;
|
|
44130
45074
|
constructor(columns, rows, measures, fieldsType) {
|
|
44131
45075
|
this.columns = columns.map((row) => {
|
|
44132
45076
|
// offset in the pivot table
|
|
@@ -44300,6 +45244,7 @@ class SpreadsheetPivotTable {
|
|
|
44300
45244
|
value,
|
|
44301
45245
|
field: row.fields[rowDepth],
|
|
44302
45246
|
children: [],
|
|
45247
|
+
type: this.fieldsType[fieldName] || "char",
|
|
44303
45248
|
width: 0, // not used
|
|
44304
45249
|
};
|
|
44305
45250
|
treesAtDepth[depth].push(node);
|
|
@@ -44322,6 +45267,7 @@ class SpreadsheetPivotTable {
|
|
|
44322
45267
|
field: leaf.fields[depth],
|
|
44323
45268
|
children: [],
|
|
44324
45269
|
width: leaf.width,
|
|
45270
|
+
type: this.fieldsType[fieldName] || "char",
|
|
44325
45271
|
};
|
|
44326
45272
|
if (treesAtDepth[depth]?.at(-1)?.value !== value) {
|
|
44327
45273
|
treesAtDepth[depth + 1] = [];
|
|
@@ -44340,6 +45286,35 @@ class SpreadsheetPivotTable {
|
|
|
44340
45286
|
fieldsType: this.fieldsType,
|
|
44341
45287
|
};
|
|
44342
45288
|
}
|
|
45289
|
+
sort(measure, sortedColumn, getValue) {
|
|
45290
|
+
if (this.isSorted) {
|
|
45291
|
+
return;
|
|
45292
|
+
}
|
|
45293
|
+
const getSortValue = (measure, domain) => {
|
|
45294
|
+
const rawValue = getValue(measure, domain).value;
|
|
45295
|
+
return typeof rawValue === "number" ? rawValue : -Infinity;
|
|
45296
|
+
};
|
|
45297
|
+
const sortColDomain = sortedColumn.domain;
|
|
45298
|
+
const sortFn = (rowDomain1, rowDomain2) => {
|
|
45299
|
+
const value1 = getSortValue(measure, [...rowDomain1, ...sortColDomain]);
|
|
45300
|
+
const value2 = getSortValue(measure, [...rowDomain2, ...sortColDomain]);
|
|
45301
|
+
return sortedColumn.order === "asc" ? value1 - value2 : value2 - value1;
|
|
45302
|
+
};
|
|
45303
|
+
const sortedRowTree = sortPivotTree(this.rowTree(), [], sortFn);
|
|
45304
|
+
this.rowTree = lazy(sortedRowTree);
|
|
45305
|
+
this.rows = [...this.rowTreeToRows(sortedRowTree), this.rows[this.rows.length - 1]];
|
|
45306
|
+
this.isSorted = true;
|
|
45307
|
+
}
|
|
45308
|
+
rowTreeToRows(tree, parentRow) {
|
|
45309
|
+
return tree.flatMap((node) => {
|
|
45310
|
+
const row = {
|
|
45311
|
+
indent: parentRow ? parentRow.indent + 1 : 0,
|
|
45312
|
+
fields: [...(parentRow?.fields || []), node.field],
|
|
45313
|
+
values: [...(parentRow?.values || []), node.value],
|
|
45314
|
+
};
|
|
45315
|
+
return [row, ...this.rowTreeToRows(node.children, row)];
|
|
45316
|
+
});
|
|
45317
|
+
}
|
|
44343
45318
|
}
|
|
44344
45319
|
const EMPTY_PIVOT_CELL = { type: "EMPTY" };
|
|
44345
45320
|
|
|
@@ -44417,6 +45392,7 @@ function dataEntriesToColumnsTree(dataEntries, columns, index) {
|
|
|
44417
45392
|
value: groups[key]?.[0]?.[column.nameWithGranularity]?.value ?? null,
|
|
44418
45393
|
field: colName,
|
|
44419
45394
|
children: dataEntriesToColumnsTree(groups[key] || [], columns, index + 1),
|
|
45395
|
+
type: column.type,
|
|
44420
45396
|
width: 0,
|
|
44421
45397
|
};
|
|
44422
45398
|
});
|
|
@@ -45282,6 +46258,7 @@ class PivotSidePanelStore extends SpreadsheetStore {
|
|
|
45282
46258
|
format: measure.format,
|
|
45283
46259
|
display: measure.display,
|
|
45284
46260
|
})),
|
|
46261
|
+
sortedColumn: this.shouldKeepSortedColumn(definition) ? definition.sortedColumn : undefined,
|
|
45285
46262
|
};
|
|
45286
46263
|
if (!this.draft && deepEquals(coreDefinition, cleanedDefinition)) {
|
|
45287
46264
|
return;
|
|
@@ -45340,6 +46317,19 @@ class PivotSidePanelStore extends SpreadsheetStore {
|
|
|
45340
46317
|
}
|
|
45341
46318
|
return granularitiesPerFields;
|
|
45342
46319
|
}
|
|
46320
|
+
/**
|
|
46321
|
+
* Check if we want to keep the sorted column when updating the pivot definition. We should remove it if either
|
|
46322
|
+
* the measure is not in the new definition or the columns have changed.
|
|
46323
|
+
*/
|
|
46324
|
+
shouldKeepSortedColumn(newDefinition) {
|
|
46325
|
+
const { sortedColumn } = newDefinition;
|
|
46326
|
+
if (!sortedColumn) {
|
|
46327
|
+
return true;
|
|
46328
|
+
}
|
|
46329
|
+
const oldDefinition = this.getters.getPivotCoreDefinition(this.pivotId);
|
|
46330
|
+
return (newDefinition.measures.find((measure) => measure.id === sortedColumn.measure) &&
|
|
46331
|
+
deepEquals(oldDefinition.columns, newDefinition.columns));
|
|
46332
|
+
}
|
|
45343
46333
|
}
|
|
45344
46334
|
|
|
45345
46335
|
class PivotSpreadsheetSidePanel extends Component {
|
|
@@ -46441,6 +47431,7 @@ css /* scss */ `
|
|
|
46441
47431
|
}
|
|
46442
47432
|
}
|
|
46443
47433
|
`;
|
|
47434
|
+
const DEFAULT_TABLE_STYLE_COLOR = "#3C78D8";
|
|
46444
47435
|
class TableStyleEditorPanel extends Component {
|
|
46445
47436
|
static template = "o-spreadsheet-TableStyleEditorPanel";
|
|
46446
47437
|
static components = { Section, RoundColorPicker, TableStylePreview };
|
|
@@ -46459,7 +47450,7 @@ class TableStyleEditorPanel extends Component {
|
|
|
46459
47450
|
: null;
|
|
46460
47451
|
return {
|
|
46461
47452
|
pickerOpened: false,
|
|
46462
|
-
primaryColor: editedStyle?.primaryColor ||
|
|
47453
|
+
primaryColor: editedStyle?.primaryColor || DEFAULT_TABLE_STYLE_COLOR,
|
|
46463
47454
|
selectedTemplateName: editedStyle?.templateName || "lightColoredText",
|
|
46464
47455
|
styleName: editedStyle?.displayName || this.env.model.getters.getNewCustomTableStyleName(),
|
|
46465
47456
|
};
|
|
@@ -46468,7 +47459,7 @@ class TableStyleEditorPanel extends Component {
|
|
|
46468
47459
|
this.state.pickerOpened = !this.state.pickerOpened;
|
|
46469
47460
|
}
|
|
46470
47461
|
onColorPicked(color) {
|
|
46471
|
-
this.state.primaryColor = color;
|
|
47462
|
+
this.state.primaryColor = isColorValid(color) ? color : DEFAULT_TABLE_STYLE_COLOR;
|
|
46472
47463
|
this.state.pickerOpened = false;
|
|
46473
47464
|
}
|
|
46474
47465
|
onTemplatePicked(templateName) {
|
|
@@ -48084,6 +49075,7 @@ class FiguresContainer extends Component {
|
|
|
48084
49075
|
draggedFigure: undefined,
|
|
48085
49076
|
horizontalSnap: undefined,
|
|
48086
49077
|
verticalSnap: undefined,
|
|
49078
|
+
cancelDnd: undefined,
|
|
48087
49079
|
});
|
|
48088
49080
|
setup() {
|
|
48089
49081
|
onMounted(() => {
|
|
@@ -48096,12 +49088,28 @@ class FiguresContainer extends Component {
|
|
|
48096
49088
|
// new rendering
|
|
48097
49089
|
this.render();
|
|
48098
49090
|
});
|
|
49091
|
+
onWillUpdateProps(() => {
|
|
49092
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
49093
|
+
const draggedFigureId = this.dnd.draggedFigure?.id;
|
|
49094
|
+
if (draggedFigureId && !this.env.model.getters.getFigure(sheetId, draggedFigureId)) {
|
|
49095
|
+
if (this.dnd.cancelDnd) {
|
|
49096
|
+
this.dnd.cancelDnd();
|
|
49097
|
+
}
|
|
49098
|
+
this.dnd.draggedFigure = undefined;
|
|
49099
|
+
this.dnd.horizontalSnap = undefined;
|
|
49100
|
+
this.dnd.verticalSnap = undefined;
|
|
49101
|
+
this.dnd.cancelDnd = undefined;
|
|
49102
|
+
}
|
|
49103
|
+
});
|
|
48099
49104
|
}
|
|
48100
49105
|
getVisibleFigures() {
|
|
48101
49106
|
const visibleFigures = this.env.model.getters.getVisibleFigures();
|
|
48102
49107
|
if (this.dnd.draggedFigure &&
|
|
48103
49108
|
!visibleFigures.some((figure) => figure.id === this.dnd.draggedFigure?.id)) {
|
|
48104
|
-
|
|
49109
|
+
const draggedFigure = this.env.model.getters.getFigure(this.env.model.getters.getActiveSheetId(), this.dnd.draggedFigure?.id);
|
|
49110
|
+
if (draggedFigure) {
|
|
49111
|
+
visibleFigures.push(draggedFigure);
|
|
49112
|
+
}
|
|
48105
49113
|
}
|
|
48106
49114
|
return visibleFigures;
|
|
48107
49115
|
}
|
|
@@ -48220,7 +49228,7 @@ class FiguresContainer extends Component {
|
|
|
48220
49228
|
this.dnd.verticalSnap = undefined;
|
|
48221
49229
|
this.env.model.dispatch("UPDATE_FIGURE", { sheetId, id: figure.id, x, y });
|
|
48222
49230
|
};
|
|
48223
|
-
startDnd(onMouseMove, onMouseUp);
|
|
49231
|
+
this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
|
|
48224
49232
|
}
|
|
48225
49233
|
/**
|
|
48226
49234
|
* Initialize the resize of a figure with mouse movements
|
|
@@ -48268,7 +49276,7 @@ class FiguresContainer extends Component {
|
|
|
48268
49276
|
this.dnd.horizontalSnap = undefined;
|
|
48269
49277
|
this.dnd.verticalSnap = undefined;
|
|
48270
49278
|
};
|
|
48271
|
-
startDnd(onMouseMove, onMouseUp);
|
|
49279
|
+
this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
|
|
48272
49280
|
}
|
|
48273
49281
|
getOtherFigures(figId) {
|
|
48274
49282
|
return this.getVisibleFigures().filter((f) => f.id !== figId);
|
|
@@ -49375,9 +50383,11 @@ class HeadersOverlay extends Component {
|
|
|
49375
50383
|
class GridRenderer {
|
|
49376
50384
|
getters;
|
|
49377
50385
|
renderer;
|
|
50386
|
+
fingerprints;
|
|
49378
50387
|
constructor(get) {
|
|
49379
50388
|
this.getters = get(ModelStore).getters;
|
|
49380
50389
|
this.renderer = get(RendererStore);
|
|
50390
|
+
this.fingerprints = get(FormulaFingerprintStore);
|
|
49381
50391
|
this.renderer.register(this);
|
|
49382
50392
|
}
|
|
49383
50393
|
get renderingLayers() {
|
|
@@ -49855,14 +50865,22 @@ class GridRenderer {
|
|
|
49855
50865
|
const showFormula = this.getters.shouldShowFormulas();
|
|
49856
50866
|
const { x, y, width, height } = this.getters.getVisibleRect(zone);
|
|
49857
50867
|
const { verticalAlign } = this.getters.getCellStyle(position);
|
|
50868
|
+
let style = this.getters.getCellComputedStyle(position);
|
|
50869
|
+
if (this.fingerprints.isEnabled) {
|
|
50870
|
+
const fingerprintColor = this.fingerprints.colors.get(position);
|
|
50871
|
+
style = { ...style, fillColor: fingerprintColor };
|
|
50872
|
+
}
|
|
50873
|
+
const dataBarFill = this.fingerprints.isEnabled
|
|
50874
|
+
? undefined
|
|
50875
|
+
: this.getters.getConditionalDataBar(position);
|
|
49858
50876
|
const box = {
|
|
49859
50877
|
x,
|
|
49860
50878
|
y,
|
|
49861
50879
|
width,
|
|
49862
50880
|
height,
|
|
49863
50881
|
border: this.getters.getCellComputedBorder(position) || undefined,
|
|
49864
|
-
style
|
|
49865
|
-
dataBarFill
|
|
50882
|
+
style,
|
|
50883
|
+
dataBarFill,
|
|
49866
50884
|
verticalAlign,
|
|
49867
50885
|
isError: (cell.type === CellValueType.error && !!cell.message) ||
|
|
49868
50886
|
this.getters.isDataValidationInvalid(position),
|
|
@@ -49887,7 +50905,6 @@ class GridRenderer {
|
|
|
49887
50905
|
box.hasIcon = this.getters.doesCellHaveGridIcon(position);
|
|
49888
50906
|
const headerIconWidth = box.hasIcon ? GRID_ICON_EDGE_LENGTH + GRID_ICON_MARGIN : 0;
|
|
49889
50907
|
/** Content */
|
|
49890
|
-
const style = this.getters.getCellComputedStyle(position);
|
|
49891
50908
|
const wrapping = style.wrapping || "overflow";
|
|
49892
50909
|
const wrapText = wrapping === "wrap" && !showFormula;
|
|
49893
50910
|
const maxWidth = width - 2 * MIN_CELL_TEXT_MARGIN;
|
|
@@ -51865,62 +52882,6 @@ class BordersPlugin extends CorePlugin {
|
|
|
51865
52882
|
}
|
|
51866
52883
|
}
|
|
51867
52884
|
|
|
51868
|
-
class PositionMap {
|
|
51869
|
-
map = {};
|
|
51870
|
-
constructor(entries = []) {
|
|
51871
|
-
for (const [position, value] of entries) {
|
|
51872
|
-
this.set(position, value);
|
|
51873
|
-
}
|
|
51874
|
-
}
|
|
51875
|
-
set({ sheetId, col, row }, value) {
|
|
51876
|
-
const map = this.map;
|
|
51877
|
-
if (!map[sheetId]) {
|
|
51878
|
-
map[sheetId] = {};
|
|
51879
|
-
}
|
|
51880
|
-
if (!map[sheetId][col]) {
|
|
51881
|
-
map[sheetId][col] = {};
|
|
51882
|
-
}
|
|
51883
|
-
map[sheetId][col][row] = value;
|
|
51884
|
-
}
|
|
51885
|
-
get({ sheetId, col, row }) {
|
|
51886
|
-
return this.map[sheetId]?.[col]?.[row];
|
|
51887
|
-
}
|
|
51888
|
-
getSheet(sheetId) {
|
|
51889
|
-
return this.map[sheetId];
|
|
51890
|
-
}
|
|
51891
|
-
has({ sheetId, col, row }) {
|
|
51892
|
-
return this.map[sheetId]?.[col]?.[row] !== undefined;
|
|
51893
|
-
}
|
|
51894
|
-
delete({ sheetId, col, row }) {
|
|
51895
|
-
delete this.map[sheetId]?.[col]?.[row];
|
|
51896
|
-
}
|
|
51897
|
-
keys() {
|
|
51898
|
-
const map = this.map;
|
|
51899
|
-
const keys = [];
|
|
51900
|
-
for (const sheetId in map) {
|
|
51901
|
-
for (const col in map[sheetId]) {
|
|
51902
|
-
for (const row in map[sheetId][col]) {
|
|
51903
|
-
keys.push({ sheetId, col: parseInt(col), row: parseInt(row) });
|
|
51904
|
-
}
|
|
51905
|
-
}
|
|
51906
|
-
}
|
|
51907
|
-
return keys;
|
|
51908
|
-
}
|
|
51909
|
-
keysForSheet(sheetId) {
|
|
51910
|
-
const map = this.map[sheetId];
|
|
51911
|
-
if (!map) {
|
|
51912
|
-
return [];
|
|
51913
|
-
}
|
|
51914
|
-
const keys = [];
|
|
51915
|
-
for (const col in map) {
|
|
51916
|
-
for (const row in map[col]) {
|
|
51917
|
-
keys.push({ sheetId, col: parseInt(col), row: parseInt(row) });
|
|
51918
|
-
}
|
|
51919
|
-
}
|
|
51920
|
-
return keys;
|
|
51921
|
-
}
|
|
51922
|
-
}
|
|
51923
|
-
|
|
51924
52885
|
/**
|
|
51925
52886
|
* Core Plugin
|
|
51926
52887
|
*
|
|
@@ -52359,7 +53320,7 @@ class CellPlugin extends CorePlugin {
|
|
|
52359
53320
|
const before = this.getters.getCell({ sheetId, col, row });
|
|
52360
53321
|
const hasContent = "content" in after || "formula" in after;
|
|
52361
53322
|
// Compute the new cell properties
|
|
52362
|
-
const afterContent = hasContent ?
|
|
53323
|
+
const afterContent = hasContent ? replaceNewLines(after?.content) : before?.content || "";
|
|
52363
53324
|
let style;
|
|
52364
53325
|
if (after.style !== undefined) {
|
|
52365
53326
|
style = after.style || undefined;
|
|
@@ -55304,6 +56265,9 @@ class SheetPlugin extends CorePlugin {
|
|
|
55304
56265
|
};
|
|
55305
56266
|
}
|
|
55306
56267
|
getUnboundedZone(sheetId, zone) {
|
|
56268
|
+
if (zone.bottom === undefined || zone.right === undefined) {
|
|
56269
|
+
return zone;
|
|
56270
|
+
}
|
|
55307
56271
|
const isFullRow = zone.left === 0 && zone.right === this.getNumberCols(sheetId) - 1;
|
|
55308
56272
|
const isFullCol = zone.top === 0 && zone.bottom === this.getNumberRows(sheetId) - 1;
|
|
55309
56273
|
return {
|
|
@@ -59587,66 +60551,25 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
59587
60551
|
return;
|
|
59588
60552
|
}
|
|
59589
60553
|
const zone = this.getters.getRangeFromSheetXC(sheetId, range).zone;
|
|
59590
|
-
const
|
|
60554
|
+
const colorThresholds = [{ value: minValue, color: rule.minimum.color }];
|
|
59591
60555
|
if (rule.midpoint && midValue) {
|
|
59592
|
-
|
|
59593
|
-
minValue,
|
|
59594
|
-
minColor: rule.minimum.color,
|
|
59595
|
-
colorDiffUnit: this.computeColorDiffUnits(minValue, midValue, rule.minimum.color, rule.midpoint.color),
|
|
59596
|
-
});
|
|
59597
|
-
colorCellArgs.push({
|
|
59598
|
-
minValue: midValue,
|
|
59599
|
-
minColor: rule.midpoint.color,
|
|
59600
|
-
colorDiffUnit: this.computeColorDiffUnits(midValue, maxValue, rule.midpoint.color, rule.maximum.color),
|
|
59601
|
-
});
|
|
59602
|
-
}
|
|
59603
|
-
else {
|
|
59604
|
-
colorCellArgs.push({
|
|
59605
|
-
minValue,
|
|
59606
|
-
minColor: rule.minimum.color,
|
|
59607
|
-
colorDiffUnit: this.computeColorDiffUnits(minValue, maxValue, rule.minimum.color, rule.maximum.color),
|
|
59608
|
-
});
|
|
60556
|
+
colorThresholds.push({ value: midValue, color: rule.midpoint.color });
|
|
59609
60557
|
}
|
|
60558
|
+
colorThresholds.push({ value: maxValue, color: rule.maximum.color });
|
|
60559
|
+
const colorScale = getColorScale(colorThresholds);
|
|
59610
60560
|
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
59611
60561
|
for (let col = zone.left; col <= zone.right; col++) {
|
|
59612
60562
|
const cell = this.getters.getEvaluatedCell({ sheetId, col, row });
|
|
59613
60563
|
if (cell.type === CellValueType.number) {
|
|
59614
60564
|
const value = clip(cell.value, minValue, maxValue);
|
|
59615
|
-
let color;
|
|
59616
|
-
if (colorCellArgs.length === 2 && midValue) {
|
|
59617
|
-
color =
|
|
59618
|
-
value <= midValue
|
|
59619
|
-
? this.colorCell(value, colorCellArgs[0].minValue, colorCellArgs[0].minColor, colorCellArgs[0].colorDiffUnit)
|
|
59620
|
-
: this.colorCell(value, colorCellArgs[1].minValue, colorCellArgs[1].minColor, colorCellArgs[1].colorDiffUnit);
|
|
59621
|
-
}
|
|
59622
|
-
else {
|
|
59623
|
-
color = this.colorCell(value, colorCellArgs[0].minValue, colorCellArgs[0].minColor, colorCellArgs[0].colorDiffUnit);
|
|
59624
|
-
}
|
|
59625
60565
|
if (!computedStyle[col])
|
|
59626
60566
|
computedStyle[col] = [];
|
|
59627
60567
|
computedStyle[col][row] = computedStyle[col]?.[row] || {};
|
|
59628
|
-
computedStyle[col][row].fillColor =
|
|
60568
|
+
computedStyle[col][row].fillColor = colorScale(value);
|
|
59629
60569
|
}
|
|
59630
60570
|
}
|
|
59631
60571
|
}
|
|
59632
60572
|
}
|
|
59633
|
-
computeColorDiffUnits(minValue, maxValue, minColor, maxColor) {
|
|
59634
|
-
const deltaValue = maxValue - minValue;
|
|
59635
|
-
const deltaColorR = ((minColor >> 16) % 256) - ((maxColor >> 16) % 256);
|
|
59636
|
-
const deltaColorG = ((minColor >> 8) % 256) - ((maxColor >> 8) % 256);
|
|
59637
|
-
const deltaColorB = (minColor % 256) - (maxColor % 256);
|
|
59638
|
-
const colorDiffUnitR = deltaColorR / deltaValue;
|
|
59639
|
-
const colorDiffUnitG = deltaColorG / deltaValue;
|
|
59640
|
-
const colorDiffUnitB = deltaColorB / deltaValue;
|
|
59641
|
-
return [colorDiffUnitR, colorDiffUnitG, colorDiffUnitB];
|
|
59642
|
-
}
|
|
59643
|
-
colorCell(value, minValue, minColor, colorDiffUnit) {
|
|
59644
|
-
const [colorDiffUnitR, colorDiffUnitG, colorDiffUnitB] = colorDiffUnit;
|
|
59645
|
-
const r = Math.round(((minColor >> 16) % 256) - colorDiffUnitR * (value - minValue));
|
|
59646
|
-
const g = Math.round(((minColor >> 8) % 256) - colorDiffUnitG * (value - minValue));
|
|
59647
|
-
const b = Math.round((minColor % 256) - colorDiffUnitB * (value - minValue));
|
|
59648
|
-
return (r << 16) | (g << 8) | b;
|
|
59649
|
-
}
|
|
59650
60573
|
/**
|
|
59651
60574
|
* Execute the predicate to know if a conditional formatting rule should be applied to a cell
|
|
59652
60575
|
*/
|
|
@@ -60272,7 +61195,7 @@ function withPivotPresentationLayer (PivotClass) {
|
|
|
60272
61195
|
}
|
|
60273
61196
|
getValuesToAggregate(measure, domain) {
|
|
60274
61197
|
const { rowDomain, colDomain } = domainToColRowDomain(this, domain);
|
|
60275
|
-
const table =
|
|
61198
|
+
const table = super.getTableStructure();
|
|
60276
61199
|
const values = [];
|
|
60277
61200
|
if (colDomain.length === 0 &&
|
|
60278
61201
|
rowDomain.length < this.definition.rows.length &&
|
|
@@ -60706,6 +61629,21 @@ function withPivotPresentationLayer (PivotClass) {
|
|
|
60706
61629
|
}
|
|
60707
61630
|
throw new Error(`Value ${result.value} is not a number`);
|
|
60708
61631
|
}
|
|
61632
|
+
getTableStructure() {
|
|
61633
|
+
const table = super.getTableStructure();
|
|
61634
|
+
this.sortTableStructure(table);
|
|
61635
|
+
return table;
|
|
61636
|
+
}
|
|
61637
|
+
sortTableStructure(table) {
|
|
61638
|
+
if (!this.definition.sortedColumn || table.isSorted) {
|
|
61639
|
+
return;
|
|
61640
|
+
}
|
|
61641
|
+
const measure = this.definition.sortedColumn.measure;
|
|
61642
|
+
const isSortValid = isSortedColumnValid(this.definition.sortedColumn, this);
|
|
61643
|
+
if (isSortValid) {
|
|
61644
|
+
table.sort(measure, this.definition.sortedColumn, (measure, domain) => this._getPivotCellValueAndFormat(measure, domain));
|
|
61645
|
+
}
|
|
61646
|
+
}
|
|
60709
61647
|
}
|
|
60710
61648
|
return PivotPresentationLayer;
|
|
60711
61649
|
}
|
|
@@ -62481,23 +63419,6 @@ class Session extends EventBus {
|
|
|
62481
63419
|
}
|
|
62482
63420
|
}
|
|
62483
63421
|
|
|
62484
|
-
function randomChoice(arr) {
|
|
62485
|
-
return arr[Math.floor(Math.random() * arr.length)];
|
|
62486
|
-
}
|
|
62487
|
-
const colors = [
|
|
62488
|
-
"#ff851b",
|
|
62489
|
-
"#0074d9",
|
|
62490
|
-
"#7fdbff",
|
|
62491
|
-
"#b10dc9",
|
|
62492
|
-
"#39cccc",
|
|
62493
|
-
"#f012be",
|
|
62494
|
-
"#3d9970",
|
|
62495
|
-
"#111111",
|
|
62496
|
-
"#ff4136",
|
|
62497
|
-
"#aaaaaa",
|
|
62498
|
-
"#85144b",
|
|
62499
|
-
"#001f3f",
|
|
62500
|
-
];
|
|
62501
63422
|
class CollaborativePlugin extends UIPlugin {
|
|
62502
63423
|
static getters = [
|
|
62503
63424
|
"getClientsToDisplay",
|
|
@@ -62506,7 +63427,7 @@ class CollaborativePlugin extends UIPlugin {
|
|
|
62506
63427
|
"isFullySynchronized",
|
|
62507
63428
|
];
|
|
62508
63429
|
static layers = ["Selection"];
|
|
62509
|
-
availableColors = new
|
|
63430
|
+
availableColors = new AlternatingColorGenerator(12);
|
|
62510
63431
|
colors = {};
|
|
62511
63432
|
session;
|
|
62512
63433
|
constructor(config) {
|
|
@@ -62517,14 +63438,6 @@ class CollaborativePlugin extends UIPlugin {
|
|
|
62517
63438
|
return (position.row < this.getters.getNumberRows(position.sheetId) &&
|
|
62518
63439
|
position.col < this.getters.getNumberCols(position.sheetId));
|
|
62519
63440
|
}
|
|
62520
|
-
chooseNewColor() {
|
|
62521
|
-
if (this.availableColors.size === 0) {
|
|
62522
|
-
this.availableColors = new Set(colors);
|
|
62523
|
-
}
|
|
62524
|
-
const color = randomChoice([...this.availableColors.values()]);
|
|
62525
|
-
this.availableColors.delete(color);
|
|
62526
|
-
return color;
|
|
62527
|
-
}
|
|
62528
63441
|
getClient() {
|
|
62529
63442
|
return this.session.getClient();
|
|
62530
63443
|
}
|
|
@@ -62559,7 +63472,7 @@ class CollaborativePlugin extends UIPlugin {
|
|
|
62559
63472
|
this.isPositionValid(client.position)) {
|
|
62560
63473
|
const position = client.position;
|
|
62561
63474
|
if (!this.colors[client.id]) {
|
|
62562
|
-
this.colors[client.id] = this.
|
|
63475
|
+
this.colors[client.id] = this.availableColors.next();
|
|
62563
63476
|
}
|
|
62564
63477
|
const color = this.colors[client.id];
|
|
62565
63478
|
clients.push({ ...client, position, color });
|
|
@@ -62796,7 +63709,7 @@ class FormatPlugin extends UIPlugin {
|
|
|
62796
63709
|
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
62797
63710
|
const position = { sheetId, col, row };
|
|
62798
63711
|
const pivotCell = this.getters.getPivotCellFromPosition(position);
|
|
62799
|
-
if (
|
|
63712
|
+
if (this.isSpilledPivotValueFormula(position, pivotCell)) {
|
|
62800
63713
|
measurePositions.push(position);
|
|
62801
63714
|
const pivotId = this.getters.getPivotIdFromPosition(position) || "";
|
|
62802
63715
|
measuresByPivotId[pivotId] ??= new Set();
|
|
@@ -62833,6 +63746,10 @@ class FormatPlugin extends UIPlugin {
|
|
|
62833
63746
|
format,
|
|
62834
63747
|
});
|
|
62835
63748
|
}
|
|
63749
|
+
isSpilledPivotValueFormula(position, pivotCell) {
|
|
63750
|
+
const cell = this.getters.getCell(position);
|
|
63751
|
+
return pivotCell.type === "VALUE" && !cell?.isFormula;
|
|
63752
|
+
}
|
|
62836
63753
|
/**
|
|
62837
63754
|
* This function allows to adjust the quantity of decimal places after a decimal
|
|
62838
63755
|
* point on cells containing number value. It does this by changing the cells
|
|
@@ -62883,6 +63800,69 @@ class FormatPlugin extends UIPlugin {
|
|
|
62883
63800
|
}
|
|
62884
63801
|
}
|
|
62885
63802
|
|
|
63803
|
+
class GeoFeaturePlugin extends UIPlugin {
|
|
63804
|
+
static getters = [
|
|
63805
|
+
"getGeoJsonFeatures",
|
|
63806
|
+
"geoFeatureNameToId",
|
|
63807
|
+
"getGeoChartAvailableRegions",
|
|
63808
|
+
];
|
|
63809
|
+
geoJsonService;
|
|
63810
|
+
geoJsonCache = {};
|
|
63811
|
+
constructor(config) {
|
|
63812
|
+
super(config);
|
|
63813
|
+
this.geoJsonService = config.external.geoJsonService;
|
|
63814
|
+
}
|
|
63815
|
+
getGeoChartAvailableRegions() {
|
|
63816
|
+
if (!this.geoJsonService) {
|
|
63817
|
+
console.error("No geoJsonService provided to the model");
|
|
63818
|
+
return [];
|
|
63819
|
+
}
|
|
63820
|
+
return this.geoJsonService.getAvailableRegions() || [];
|
|
63821
|
+
}
|
|
63822
|
+
getGeoJsonFeatures(region) {
|
|
63823
|
+
if (!this.geoJsonService) {
|
|
63824
|
+
console.error("No geoJsonService provided to the model");
|
|
63825
|
+
return;
|
|
63826
|
+
}
|
|
63827
|
+
const cachedGeoJson = this.geoJsonCache[region];
|
|
63828
|
+
if (cachedGeoJson instanceof Promise) {
|
|
63829
|
+
return undefined;
|
|
63830
|
+
}
|
|
63831
|
+
if (cachedGeoJson !== undefined) {
|
|
63832
|
+
return cachedGeoJson ?? undefined;
|
|
63833
|
+
}
|
|
63834
|
+
this.geoJsonCache[region] = new Promise(async (resolve) => {
|
|
63835
|
+
const json = await this.geoJsonService?.getTopoJson(region);
|
|
63836
|
+
this.geoJsonCache[region] = this.convertToGeoJson(json);
|
|
63837
|
+
this.dispatch("EVALUATE_CHARTS");
|
|
63838
|
+
resolve();
|
|
63839
|
+
});
|
|
63840
|
+
return undefined;
|
|
63841
|
+
}
|
|
63842
|
+
geoFeatureNameToId(region, featureName) {
|
|
63843
|
+
if (!this.geoJsonService) {
|
|
63844
|
+
console.error("No geoJsonService provided to the model");
|
|
63845
|
+
return;
|
|
63846
|
+
}
|
|
63847
|
+
return this.geoJsonService.geoFeatureNameToId(region, featureName);
|
|
63848
|
+
}
|
|
63849
|
+
convertToGeoJson(json) {
|
|
63850
|
+
if (!json) {
|
|
63851
|
+
return null;
|
|
63852
|
+
}
|
|
63853
|
+
// TopoJSON
|
|
63854
|
+
if (json.type === "Topology") {
|
|
63855
|
+
const features = window.ChartGeo.topojson.feature(json, Object.values(json.objects)[0]);
|
|
63856
|
+
return features.type === "FeatureCollection" ? features.features : [features];
|
|
63857
|
+
}
|
|
63858
|
+
// GeoJSON
|
|
63859
|
+
else if (json.type === "FeatureCollection") {
|
|
63860
|
+
return json.features;
|
|
63861
|
+
}
|
|
63862
|
+
throw new Error("Invalid TopoJSON");
|
|
63863
|
+
}
|
|
63864
|
+
}
|
|
63865
|
+
|
|
62886
63866
|
class HeaderVisibilityUIPlugin extends UIPlugin {
|
|
62887
63867
|
static getters = [
|
|
62888
63868
|
"getNextVisibleCellPosition",
|
|
@@ -64420,10 +65400,13 @@ class TableResizeUI extends UIPlugin {
|
|
|
64420
65400
|
case "RESIZE_TABLE": {
|
|
64421
65401
|
const table = this.getters.getCoreTableMatchingTopLeft(cmd.sheetId, cmd.zone);
|
|
64422
65402
|
this.dispatch("UPDATE_TABLE", { ...cmd });
|
|
64423
|
-
if (!table
|
|
65403
|
+
if (!table)
|
|
64424
65404
|
return;
|
|
64425
|
-
const oldTableZone = table.range.zone;
|
|
64426
65405
|
const newTableZone = this.getters.getRangeFromRangeData(cmd.newTableRange).zone;
|
|
65406
|
+
this.selection.selectCell(newTableZone.right, newTableZone.bottom);
|
|
65407
|
+
if (!table.config.automaticAutofill)
|
|
65408
|
+
return;
|
|
65409
|
+
const oldTableZone = table.range.zone;
|
|
64427
65410
|
if (newTableZone.bottom >= oldTableZone.bottom) {
|
|
64428
65411
|
for (let col = newTableZone.left; col <= newTableZone.right; col++) {
|
|
64429
65412
|
const autofillSource = { col, row: oldTableZone.bottom, sheetId: cmd.sheetId };
|
|
@@ -65629,15 +66612,23 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
65629
66612
|
handler.paste({ zones: pasteTarget, sheetId }, data, { isCutOperation: true });
|
|
65630
66613
|
const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
|
|
65631
66614
|
let currentIndex = cmd.base;
|
|
66615
|
+
const resizingGroups = {};
|
|
65632
66616
|
for (const element of toRemove) {
|
|
65633
66617
|
const size = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, element);
|
|
66618
|
+
const currentSize = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, currentIndex);
|
|
66619
|
+
if (size != currentSize) {
|
|
66620
|
+
resizingGroups[size] ??= [];
|
|
66621
|
+
resizingGroups[size].push(currentIndex);
|
|
66622
|
+
currentIndex += 1;
|
|
66623
|
+
}
|
|
66624
|
+
}
|
|
66625
|
+
for (const size in resizingGroups) {
|
|
65634
66626
|
this.dispatch("RESIZE_COLUMNS_ROWS", {
|
|
65635
66627
|
dimension: cmd.dimension,
|
|
65636
66628
|
sheetId: cmd.sheetId,
|
|
65637
|
-
size,
|
|
65638
|
-
elements: [
|
|
66629
|
+
size: parseInt(size, 10),
|
|
66630
|
+
elements: resizingGroups[size],
|
|
65639
66631
|
});
|
|
65640
|
-
currentIndex += 1;
|
|
65641
66632
|
}
|
|
65642
66633
|
this.dispatch("REMOVE_COLUMNS_ROWS", {
|
|
65643
66634
|
dimension: cmd.dimension,
|
|
@@ -66219,6 +67210,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
66219
67210
|
break;
|
|
66220
67211
|
case "DELETE_SHEET":
|
|
66221
67212
|
this.cleanViewports();
|
|
67213
|
+
this.sheetsWithDirtyViewports.delete(cmd.sheetId);
|
|
66222
67214
|
break;
|
|
66223
67215
|
case "ACTIVATE_SHEET":
|
|
66224
67216
|
this.sheetsWithDirtyViewports.add(cmd.sheetIdTo);
|
|
@@ -66869,7 +67861,8 @@ const featurePluginRegistry = new Registry()
|
|
|
66869
67861
|
.add("data_cleanup", DataCleanupPlugin)
|
|
66870
67862
|
.add("table_autofill", TableAutofillPlugin)
|
|
66871
67863
|
.add("table_ui_resize", TableResizeUI)
|
|
66872
|
-
.add("datavalidation_insert", DataValidationInsertionPlugin)
|
|
67864
|
+
.add("datavalidation_insert", DataValidationInsertionPlugin)
|
|
67865
|
+
.add("geo_features", GeoFeaturePlugin);
|
|
66873
67866
|
// Plugins which have a state, but which should not be shared in collaborative
|
|
66874
67867
|
const statefulUIPluginRegistry = new Registry()
|
|
66875
67868
|
.add("selection", GridSelectionPlugin)
|
|
@@ -68613,8 +69606,8 @@ css /* scss */ `
|
|
|
68613
69606
|
.o-topbar-composer {
|
|
68614
69607
|
height: fit-content;
|
|
68615
69608
|
margin-top: -1px;
|
|
69609
|
+
margin-bottom: -1px;
|
|
68616
69610
|
border: 1px solid;
|
|
68617
|
-
z-index: ${ComponentsImportance.TopBarComposer};
|
|
68618
69611
|
font-family: ${DEFAULT_FONT};
|
|
68619
69612
|
|
|
68620
69613
|
.o-composer:empty:not(:focus):not(.active)::before {
|
|
@@ -68672,6 +69665,7 @@ class TopBarComposer extends Component {
|
|
|
68672
69665
|
}
|
|
68673
69666
|
return cssPropertiesToCss({
|
|
68674
69667
|
"border-color": SELECTION_BORDER_COLOR,
|
|
69668
|
+
"z-index": String(ComponentsImportance.TopBarComposer),
|
|
68675
69669
|
});
|
|
68676
69670
|
}
|
|
68677
69671
|
onFocus(selection) {
|
|
@@ -68780,6 +69774,15 @@ css /* scss */ `
|
|
|
68780
69774
|
}
|
|
68781
69775
|
}
|
|
68782
69776
|
|
|
69777
|
+
.irregularity-map {
|
|
69778
|
+
border-top: 1px solid ${SEPARATOR_COLOR};
|
|
69779
|
+
height: ${TOPBAR_TOOLBAR_HEIGHT}px;
|
|
69780
|
+
|
|
69781
|
+
.alert-info {
|
|
69782
|
+
border-left: 3px solid ${ALERT_INFO_BORDER};
|
|
69783
|
+
}
|
|
69784
|
+
}
|
|
69785
|
+
|
|
68783
69786
|
.o-topbar-composer {
|
|
68784
69787
|
flex-grow: 1;
|
|
68785
69788
|
}
|
|
@@ -68873,8 +69876,10 @@ class TopBar extends Component {
|
|
|
68873
69876
|
formatNumberMenuItemSpec = formatNumberMenuItemSpec;
|
|
68874
69877
|
isntToolbarMenu = false;
|
|
68875
69878
|
composerFocusStore;
|
|
69879
|
+
fingerprints;
|
|
68876
69880
|
setup() {
|
|
68877
69881
|
this.composerFocusStore = useStore(ComposerFocusStore);
|
|
69882
|
+
this.fingerprints = useStore(FormulaFingerprintStore);
|
|
68878
69883
|
useExternalListener(window, "click", this.onExternalClick);
|
|
68879
69884
|
onWillStart(() => this.updateCellState());
|
|
68880
69885
|
onWillUpdateProps(() => this.updateCellState());
|
|
@@ -69345,7 +70350,7 @@ class Spreadsheet extends Component {
|
|
|
69345
70350
|
properties["grid-template-rows"] = `auto`;
|
|
69346
70351
|
}
|
|
69347
70352
|
else {
|
|
69348
|
-
properties["grid-template-rows"] =
|
|
70353
|
+
properties["grid-template-rows"] = `max-content auto ${BOTTOMBAR_HEIGHT + 1}px`;
|
|
69349
70354
|
}
|
|
69350
70355
|
properties["grid-template-columns"] = `auto ${this.sidePanel.panelSize}px`;
|
|
69351
70356
|
return cssPropertiesToCss(properties);
|
|
@@ -70423,9 +71428,6 @@ class SelectionStreamProcessorImpl {
|
|
|
70423
71428
|
getBackToDefault() {
|
|
70424
71429
|
this.stream.getBackToDefault();
|
|
70425
71430
|
}
|
|
70426
|
-
getAnchor() {
|
|
70427
|
-
return this.anchor;
|
|
70428
|
-
}
|
|
70429
71431
|
modifyAnchor(anchor, mode, options) {
|
|
70430
71432
|
const sheetId = this.getters.getActiveSheetId();
|
|
70431
71433
|
anchor = {
|
|
@@ -73357,6 +74359,7 @@ class Model extends EventBus {
|
|
|
73357
74359
|
session: this.session,
|
|
73358
74360
|
defaultCurrency: this.config.defaultCurrency,
|
|
73359
74361
|
customColors: this.config.customColors || [],
|
|
74362
|
+
external: this.config.external,
|
|
73360
74363
|
};
|
|
73361
74364
|
}
|
|
73362
74365
|
// ---------------------------------------------------------------------------
|
|
@@ -73588,7 +74591,6 @@ const SPREADSHEET_DIMENSIONS = {
|
|
|
73588
74591
|
MIN_COL_WIDTH,
|
|
73589
74592
|
HEADER_HEIGHT,
|
|
73590
74593
|
HEADER_WIDTH,
|
|
73591
|
-
TOPBAR_HEIGHT,
|
|
73592
74594
|
BOTTOMBAR_HEIGHT,
|
|
73593
74595
|
DEFAULT_CELL_WIDTH,
|
|
73594
74596
|
DEFAULT_CELL_HEIGHT,
|
|
@@ -73785,6 +74787,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
73785
74787
|
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 };
|
|
73786
74788
|
|
|
73787
74789
|
|
|
73788
|
-
__info__.version = "18.1.0
|
|
73789
|
-
__info__.date = "2024-12-
|
|
73790
|
-
__info__.hash = "
|
|
74790
|
+
__info__.version = "18.1.0";
|
|
74791
|
+
__info__.date = "2024-12-26T06:37:07.879Z";
|
|
74792
|
+
__info__.hash = "c520e89";
|