@odoo/o-spreadsheet 18.2.0-alpha.0 → 18.2.0-alpha.2
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 +697 -427
- package/dist/o-spreadsheet.d.ts +88 -34
- package/dist/o-spreadsheet.esm.js +698 -429
- package/dist/o-spreadsheet.iife.js +697 -427
- package/dist/o-spreadsheet.iife.min.js +394 -383
- package/dist/o_spreadsheet.xml +5 -5
- package/package.json +2 -2
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 18.2.0-alpha.
|
|
6
|
-
* @date
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.2.0-alpha.2
|
|
6
|
+
* @date 2025-01-15T08:06:32.137Z
|
|
7
|
+
* @hash 4f96c47
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -356,6 +356,7 @@
|
|
|
356
356
|
ComponentsImportance[ComponentsImportance["Popover"] = 35] = "Popover";
|
|
357
357
|
ComponentsImportance[ComponentsImportance["FigureAnchor"] = 1000] = "FigureAnchor";
|
|
358
358
|
ComponentsImportance[ComponentsImportance["FigureSnapLine"] = 1001] = "FigureSnapLine";
|
|
359
|
+
ComponentsImportance[ComponentsImportance["FigureTooltip"] = 1002] = "FigureTooltip";
|
|
359
360
|
})(ComponentsImportance || (ComponentsImportance = {}));
|
|
360
361
|
let DEFAULT_SHEETVIEW_SIZE = 0;
|
|
361
362
|
function getDefaultSheetViewSize() {
|
|
@@ -975,6 +976,16 @@
|
|
|
975
976
|
}
|
|
976
977
|
return result;
|
|
977
978
|
}
|
|
979
|
+
function getUniqueText(text, texts, options = {}) {
|
|
980
|
+
const compute = options.compute ?? ((text, i) => `${text} (${i})`);
|
|
981
|
+
const computeFirstOne = options.computeFirstOne ?? false;
|
|
982
|
+
let i = options.start ?? 1;
|
|
983
|
+
let newText = computeFirstOne ? compute(text, i) : text;
|
|
984
|
+
while (texts.includes(newText)) {
|
|
985
|
+
newText = compute(text, i++);
|
|
986
|
+
}
|
|
987
|
+
return newText;
|
|
988
|
+
}
|
|
978
989
|
|
|
979
990
|
const RBA_REGEX = /rgba?\(|\s+|\)/gi;
|
|
980
991
|
const HEX_MATCH = /^#([A-F\d]{2}){3,4}$/;
|
|
@@ -3710,6 +3721,7 @@
|
|
|
3710
3721
|
CommandResult["SheetIsHidden"] = "SheetIsHidden";
|
|
3711
3722
|
CommandResult["InvalidTableResize"] = "InvalidTableResize";
|
|
3712
3723
|
CommandResult["PivotIdNotFound"] = "PivotIdNotFound";
|
|
3724
|
+
CommandResult["PivotInError"] = "PivotInError";
|
|
3713
3725
|
CommandResult["EmptyName"] = "EmptyName";
|
|
3714
3726
|
CommandResult["ValueCellIsInvalidFormula"] = "ValueCellIsInvalidFormula";
|
|
3715
3727
|
CommandResult["InvalidDefinition"] = "InvalidDefinition";
|
|
@@ -6027,10 +6039,10 @@
|
|
|
6027
6039
|
}
|
|
6028
6040
|
}
|
|
6029
6041
|
/**
|
|
6030
|
-
*
|
|
6042
|
+
* Duplicate a range. If the range is on the sheetIdFrom, the range will target
|
|
6031
6043
|
* sheetIdTo.
|
|
6032
6044
|
*/
|
|
6033
|
-
function
|
|
6045
|
+
function duplicateRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, range) {
|
|
6034
6046
|
const sheetId = range.sheetId === sheetIdFrom ? sheetIdTo : range.sheetId;
|
|
6035
6047
|
return range.clone({ sheetId });
|
|
6036
6048
|
}
|
|
@@ -7478,18 +7490,18 @@
|
|
|
7478
7490
|
});
|
|
7479
7491
|
return newY.length === newX.length ? newY : transposeMatrix(newY);
|
|
7480
7492
|
}
|
|
7481
|
-
function getMovingAverageValues(dataset, windowSize = DEFAULT_WINDOW_SIZE) {
|
|
7493
|
+
function getMovingAverageValues(dataset, labels, windowSize = DEFAULT_WINDOW_SIZE) {
|
|
7482
7494
|
const values = [];
|
|
7483
7495
|
// Fill the starting values with null until we have a full window
|
|
7484
7496
|
for (let i = 0; i < windowSize - 1; i++) {
|
|
7485
|
-
values.push(
|
|
7497
|
+
values.push({ x: labels[i], y: NaN });
|
|
7486
7498
|
}
|
|
7487
7499
|
for (let i = 0; i <= dataset.length - windowSize; i++) {
|
|
7488
7500
|
let sum = 0;
|
|
7489
7501
|
for (let j = i; j < i + windowSize; j++) {
|
|
7490
7502
|
sum += dataset[j];
|
|
7491
7503
|
}
|
|
7492
|
-
values.push(sum / windowSize);
|
|
7504
|
+
values.push({ x: labels[i + windowSize - 1], y: sum / windowSize });
|
|
7493
7505
|
}
|
|
7494
7506
|
return values;
|
|
7495
7507
|
}
|
|
@@ -9463,6 +9475,150 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9463
9475
|
}
|
|
9464
9476
|
}
|
|
9465
9477
|
|
|
9478
|
+
/**
|
|
9479
|
+
* This file is largely inspired by owl 1.
|
|
9480
|
+
* `css` tag has been removed from owl 2 without workaround to manage css.
|
|
9481
|
+
* So, the solution was to import the behavior of owl 1 directly in our
|
|
9482
|
+
* codebase, with one difference: the css is added to the sheet as soon as the
|
|
9483
|
+
* css tag is executed. In owl 1, the css was added as soon as a Component was
|
|
9484
|
+
* created for the first time.
|
|
9485
|
+
*/
|
|
9486
|
+
const STYLESHEETS = {};
|
|
9487
|
+
let nextId = 0;
|
|
9488
|
+
/**
|
|
9489
|
+
* CSS tag helper for defining inline stylesheets. With this, one can simply define
|
|
9490
|
+
* an inline stylesheet with just the following code:
|
|
9491
|
+
* ```js
|
|
9492
|
+
* css`.component-a { color: red; }`;
|
|
9493
|
+
* ```
|
|
9494
|
+
*/
|
|
9495
|
+
function css(strings, ...args) {
|
|
9496
|
+
const name = `__sheet__${nextId++}`;
|
|
9497
|
+
const value = String.raw(strings, ...args);
|
|
9498
|
+
registerSheet(name, value);
|
|
9499
|
+
activateSheet(name);
|
|
9500
|
+
return name;
|
|
9501
|
+
}
|
|
9502
|
+
function processSheet(str) {
|
|
9503
|
+
const tokens = str.split(/(\{|\}|;)/).map((s) => s.trim());
|
|
9504
|
+
const selectorStack = [];
|
|
9505
|
+
const parts = [];
|
|
9506
|
+
let rules = [];
|
|
9507
|
+
function generateSelector(stackIndex, parentSelector) {
|
|
9508
|
+
const parts = [];
|
|
9509
|
+
for (const selector of selectorStack[stackIndex]) {
|
|
9510
|
+
let part = (parentSelector && parentSelector + " " + selector) || selector;
|
|
9511
|
+
if (part.includes("&")) {
|
|
9512
|
+
part = selector.replace(/&/g, parentSelector || "");
|
|
9513
|
+
}
|
|
9514
|
+
if (stackIndex < selectorStack.length - 1) {
|
|
9515
|
+
part = generateSelector(stackIndex + 1, part);
|
|
9516
|
+
}
|
|
9517
|
+
parts.push(part);
|
|
9518
|
+
}
|
|
9519
|
+
return parts.join(", ");
|
|
9520
|
+
}
|
|
9521
|
+
function generateRules() {
|
|
9522
|
+
if (rules.length) {
|
|
9523
|
+
parts.push(generateSelector(0) + " {");
|
|
9524
|
+
parts.push(...rules);
|
|
9525
|
+
parts.push("}");
|
|
9526
|
+
rules = [];
|
|
9527
|
+
}
|
|
9528
|
+
}
|
|
9529
|
+
while (tokens.length) {
|
|
9530
|
+
let token = tokens.shift();
|
|
9531
|
+
if (token === "}") {
|
|
9532
|
+
generateRules();
|
|
9533
|
+
selectorStack.pop();
|
|
9534
|
+
}
|
|
9535
|
+
else {
|
|
9536
|
+
if (tokens[0] === "{") {
|
|
9537
|
+
generateRules();
|
|
9538
|
+
selectorStack.push(token.split(/\s*,\s*/));
|
|
9539
|
+
tokens.shift();
|
|
9540
|
+
}
|
|
9541
|
+
if (tokens[0] === ";") {
|
|
9542
|
+
rules.push(" " + token + ";");
|
|
9543
|
+
}
|
|
9544
|
+
}
|
|
9545
|
+
}
|
|
9546
|
+
return parts.join("\n");
|
|
9547
|
+
}
|
|
9548
|
+
function registerSheet(id, css) {
|
|
9549
|
+
const sheet = document.createElement("style");
|
|
9550
|
+
sheet.textContent = processSheet(css);
|
|
9551
|
+
STYLESHEETS[id] = sheet;
|
|
9552
|
+
}
|
|
9553
|
+
function activateSheet(id) {
|
|
9554
|
+
const sheet = STYLESHEETS[id];
|
|
9555
|
+
sheet.setAttribute("component", id);
|
|
9556
|
+
document.head.appendChild(sheet);
|
|
9557
|
+
}
|
|
9558
|
+
function getTextDecoration({ strikethrough, underline, }) {
|
|
9559
|
+
if (!strikethrough && !underline) {
|
|
9560
|
+
return "none";
|
|
9561
|
+
}
|
|
9562
|
+
return `${strikethrough ? "line-through" : ""} ${underline ? "underline" : ""}`;
|
|
9563
|
+
}
|
|
9564
|
+
/**
|
|
9565
|
+
* Convert the cell style to CSS properties.
|
|
9566
|
+
*/
|
|
9567
|
+
function cellStyleToCss(style) {
|
|
9568
|
+
const attributes = cellTextStyleToCss(style);
|
|
9569
|
+
if (!style)
|
|
9570
|
+
return attributes;
|
|
9571
|
+
if (style.fillColor) {
|
|
9572
|
+
attributes["background"] = style.fillColor;
|
|
9573
|
+
}
|
|
9574
|
+
return attributes;
|
|
9575
|
+
}
|
|
9576
|
+
/**
|
|
9577
|
+
* Convert the cell text style to CSS properties.
|
|
9578
|
+
*/
|
|
9579
|
+
function cellTextStyleToCss(style) {
|
|
9580
|
+
const attributes = {};
|
|
9581
|
+
if (!style)
|
|
9582
|
+
return attributes;
|
|
9583
|
+
if (style.bold) {
|
|
9584
|
+
attributes["font-weight"] = "bold";
|
|
9585
|
+
}
|
|
9586
|
+
if (style.italic) {
|
|
9587
|
+
attributes["font-style"] = "italic";
|
|
9588
|
+
}
|
|
9589
|
+
if (style.strikethrough || style.underline) {
|
|
9590
|
+
let decoration = style.strikethrough ? "line-through" : "";
|
|
9591
|
+
decoration = style.underline ? decoration + " underline" : decoration;
|
|
9592
|
+
attributes["text-decoration"] = decoration;
|
|
9593
|
+
}
|
|
9594
|
+
if (style.textColor) {
|
|
9595
|
+
attributes["color"] = style.textColor;
|
|
9596
|
+
}
|
|
9597
|
+
return attributes;
|
|
9598
|
+
}
|
|
9599
|
+
/**
|
|
9600
|
+
* Transform CSS properties into a CSS string.
|
|
9601
|
+
*/
|
|
9602
|
+
function cssPropertiesToCss(attributes) {
|
|
9603
|
+
let styleStr = "";
|
|
9604
|
+
for (const attName in attributes) {
|
|
9605
|
+
if (!attributes[attName]) {
|
|
9606
|
+
continue;
|
|
9607
|
+
}
|
|
9608
|
+
styleStr += `${attName}:${attributes[attName]}; `;
|
|
9609
|
+
}
|
|
9610
|
+
return styleStr;
|
|
9611
|
+
}
|
|
9612
|
+
function getElementMargins(el) {
|
|
9613
|
+
const style = window.getComputedStyle(el);
|
|
9614
|
+
return {
|
|
9615
|
+
top: parseInt(style.marginTop, 10) || 0,
|
|
9616
|
+
bottom: parseInt(style.marginBottom, 10) || 0,
|
|
9617
|
+
left: parseInt(style.marginLeft, 10) || 0,
|
|
9618
|
+
right: parseInt(style.marginRight, 10) || 0,
|
|
9619
|
+
};
|
|
9620
|
+
}
|
|
9621
|
+
|
|
9466
9622
|
const TREND_LINE_XAXIS_ID = "x1";
|
|
9467
9623
|
/**
|
|
9468
9624
|
* This file contains helpers that are common to different charts (mainly
|
|
@@ -9515,25 +9671,25 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9515
9671
|
};
|
|
9516
9672
|
}
|
|
9517
9673
|
/**
|
|
9518
|
-
*
|
|
9674
|
+
* Duplicate the dataSets. All ranges on sheetIdFrom are adapted to target
|
|
9519
9675
|
* sheetIdTo.
|
|
9520
9676
|
*/
|
|
9521
|
-
function
|
|
9677
|
+
function duplicateDataSetsInDuplicatedSheet(sheetIdFrom, sheetIdTo, dataSets) {
|
|
9522
9678
|
return dataSets.map((ds) => {
|
|
9523
9679
|
return {
|
|
9524
|
-
dataRange:
|
|
9680
|
+
dataRange: duplicateRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, ds.dataRange),
|
|
9525
9681
|
labelCell: ds.labelCell
|
|
9526
|
-
?
|
|
9682
|
+
? duplicateRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, ds.labelCell)
|
|
9527
9683
|
: undefined,
|
|
9528
9684
|
};
|
|
9529
9685
|
});
|
|
9530
9686
|
}
|
|
9531
9687
|
/**
|
|
9532
|
-
*
|
|
9688
|
+
* Duplicate a range. If the range is on the sheetIdFrom, the range will target
|
|
9533
9689
|
* sheetIdTo.
|
|
9534
9690
|
*/
|
|
9535
|
-
function
|
|
9536
|
-
return range ?
|
|
9691
|
+
function duplicateLabelRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, range) {
|
|
9692
|
+
return range ? duplicateRangeInDuplicatedSheet(sheetIdFrom, sheetIdTo, range) : undefined;
|
|
9537
9693
|
}
|
|
9538
9694
|
/**
|
|
9539
9695
|
* Adapt a single range of a chart
|
|
@@ -9786,10 +9942,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9786
9942
|
if (isNaN(value))
|
|
9787
9943
|
return value;
|
|
9788
9944
|
const { locale, format } = localeFormat;
|
|
9789
|
-
|
|
9945
|
+
const formattedValue = formatValue(value, {
|
|
9790
9946
|
locale,
|
|
9791
9947
|
format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
|
|
9792
9948
|
});
|
|
9949
|
+
return truncateLabel(formattedValue);
|
|
9793
9950
|
};
|
|
9794
9951
|
}
|
|
9795
9952
|
const CHART_AXIS_CHOICES = [
|
|
@@ -9804,6 +9961,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9804
9961
|
}
|
|
9805
9962
|
return pieColors;
|
|
9806
9963
|
}
|
|
9964
|
+
function truncateLabel(label) {
|
|
9965
|
+
if (!label) {
|
|
9966
|
+
return "";
|
|
9967
|
+
}
|
|
9968
|
+
if (label.length > MAX_CHAR_LABEL) {
|
|
9969
|
+
return label.substring(0, MAX_CHAR_LABEL) + "…";
|
|
9970
|
+
}
|
|
9971
|
+
return label;
|
|
9972
|
+
}
|
|
9807
9973
|
|
|
9808
9974
|
/** This is a chartJS plugin that will draw the values of each data next to the point/bar/pie slice */
|
|
9809
9975
|
const chartShowValuesPlugin = {
|
|
@@ -9999,6 +10165,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9999
10165
|
|
|
10000
10166
|
window.Chart?.register(waterfallLinesPlugin);
|
|
10001
10167
|
window.Chart?.register(chartShowValuesPlugin);
|
|
10168
|
+
css /* scss */ `
|
|
10169
|
+
.o-spreadsheet {
|
|
10170
|
+
.o-chart-custom-tooltip {
|
|
10171
|
+
font-size: 12px;
|
|
10172
|
+
background-color: #fff;
|
|
10173
|
+
z-index: ${ComponentsImportance.FigureTooltip};
|
|
10174
|
+
table td span {
|
|
10175
|
+
box-sizing: border-box;
|
|
10176
|
+
}
|
|
10177
|
+
}
|
|
10178
|
+
}
|
|
10179
|
+
`;
|
|
10002
10180
|
class ChartJsComponent extends owl.Component {
|
|
10003
10181
|
static template = "o-spreadsheet-ChartJsComponent";
|
|
10004
10182
|
static props = {
|
|
@@ -10237,11 +10415,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10237
10415
|
keyValue: keyValueZone ? zoneToXc(keyValueZone) : undefined,
|
|
10238
10416
|
};
|
|
10239
10417
|
}
|
|
10240
|
-
|
|
10241
|
-
const baseline =
|
|
10242
|
-
const keyValue =
|
|
10243
|
-
const definition = this.getDefinitionWithSpecificRanges(baseline, keyValue,
|
|
10244
|
-
return new ScorecardChart(definition,
|
|
10418
|
+
duplicateInDuplicatedSheet(newSheetId) {
|
|
10419
|
+
const baseline = duplicateLabelRangeInDuplicatedSheet(this.sheetId, newSheetId, this.baseline);
|
|
10420
|
+
const keyValue = duplicateLabelRangeInDuplicatedSheet(this.sheetId, newSheetId, this.keyValue);
|
|
10421
|
+
const definition = this.getDefinitionWithSpecificRanges(baseline, keyValue, newSheetId);
|
|
10422
|
+
return new ScorecardChart(definition, newSheetId, this.getters);
|
|
10245
10423
|
}
|
|
10246
10424
|
copyInSheetId(sheetId) {
|
|
10247
10425
|
const definition = this.getDefinitionWithSpecificRanges(this.baseline, this.keyValue, sheetId);
|
|
@@ -19931,6 +20109,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
19931
20109
|
},
|
|
19932
20110
|
isExported: true,
|
|
19933
20111
|
};
|
|
20112
|
+
// -----------------------------------------------------------------------------
|
|
20113
|
+
// VALUE
|
|
20114
|
+
// -----------------------------------------------------------------------------
|
|
20115
|
+
const VALUE = {
|
|
20116
|
+
description: _t("Converts a string to a numeric value."),
|
|
20117
|
+
args: [arg("value (number)", _t("the string to be converted"))],
|
|
20118
|
+
compute: function (value) {
|
|
20119
|
+
return toNumber(value, this.locale);
|
|
20120
|
+
},
|
|
20121
|
+
isExported: true,
|
|
20122
|
+
};
|
|
19934
20123
|
|
|
19935
20124
|
var text = /*#__PURE__*/Object.freeze({
|
|
19936
20125
|
__proto__: null,
|
|
@@ -19953,7 +20142,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
19953
20142
|
TEXT: TEXT,
|
|
19954
20143
|
TEXTJOIN: TEXTJOIN,
|
|
19955
20144
|
TRIM: TRIM,
|
|
19956
|
-
UPPER: UPPER
|
|
20145
|
+
UPPER: UPPER,
|
|
20146
|
+
VALUE: VALUE
|
|
19957
20147
|
});
|
|
19958
20148
|
|
|
19959
20149
|
// -----------------------------------------------------------------------------
|
|
@@ -22556,15 +22746,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22556
22746
|
},
|
|
22557
22747
|
animation: false,
|
|
22558
22748
|
};
|
|
22559
|
-
function truncateLabel(label) {
|
|
22560
|
-
if (!label) {
|
|
22561
|
-
return "";
|
|
22562
|
-
}
|
|
22563
|
-
if (label.length > MAX_CHAR_LABEL) {
|
|
22564
|
-
return label.substring(0, MAX_CHAR_LABEL) + "…";
|
|
22565
|
-
}
|
|
22566
|
-
return label;
|
|
22567
|
-
}
|
|
22568
22749
|
function chartToImage(runtime, figure, type) {
|
|
22569
22750
|
// wrap the canvas in a div with a fixed size because chart.js would
|
|
22570
22751
|
// fill the whole page otherwise
|
|
@@ -22886,150 +23067,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22886
23067
|
*/
|
|
22887
23068
|
const iconsOnCellRegistry = new Registry();
|
|
22888
23069
|
|
|
22889
|
-
/**
|
|
22890
|
-
* This file is largely inspired by owl 1.
|
|
22891
|
-
* `css` tag has been removed from owl 2 without workaround to manage css.
|
|
22892
|
-
* So, the solution was to import the behavior of owl 1 directly in our
|
|
22893
|
-
* codebase, with one difference: the css is added to the sheet as soon as the
|
|
22894
|
-
* css tag is executed. In owl 1, the css was added as soon as a Component was
|
|
22895
|
-
* created for the first time.
|
|
22896
|
-
*/
|
|
22897
|
-
const STYLESHEETS = {};
|
|
22898
|
-
let nextId = 0;
|
|
22899
|
-
/**
|
|
22900
|
-
* CSS tag helper for defining inline stylesheets. With this, one can simply define
|
|
22901
|
-
* an inline stylesheet with just the following code:
|
|
22902
|
-
* ```js
|
|
22903
|
-
* css`.component-a { color: red; }`;
|
|
22904
|
-
* ```
|
|
22905
|
-
*/
|
|
22906
|
-
function css(strings, ...args) {
|
|
22907
|
-
const name = `__sheet__${nextId++}`;
|
|
22908
|
-
const value = String.raw(strings, ...args);
|
|
22909
|
-
registerSheet(name, value);
|
|
22910
|
-
activateSheet(name);
|
|
22911
|
-
return name;
|
|
22912
|
-
}
|
|
22913
|
-
function processSheet(str) {
|
|
22914
|
-
const tokens = str.split(/(\{|\}|;)/).map((s) => s.trim());
|
|
22915
|
-
const selectorStack = [];
|
|
22916
|
-
const parts = [];
|
|
22917
|
-
let rules = [];
|
|
22918
|
-
function generateSelector(stackIndex, parentSelector) {
|
|
22919
|
-
const parts = [];
|
|
22920
|
-
for (const selector of selectorStack[stackIndex]) {
|
|
22921
|
-
let part = (parentSelector && parentSelector + " " + selector) || selector;
|
|
22922
|
-
if (part.includes("&")) {
|
|
22923
|
-
part = selector.replace(/&/g, parentSelector || "");
|
|
22924
|
-
}
|
|
22925
|
-
if (stackIndex < selectorStack.length - 1) {
|
|
22926
|
-
part = generateSelector(stackIndex + 1, part);
|
|
22927
|
-
}
|
|
22928
|
-
parts.push(part);
|
|
22929
|
-
}
|
|
22930
|
-
return parts.join(", ");
|
|
22931
|
-
}
|
|
22932
|
-
function generateRules() {
|
|
22933
|
-
if (rules.length) {
|
|
22934
|
-
parts.push(generateSelector(0) + " {");
|
|
22935
|
-
parts.push(...rules);
|
|
22936
|
-
parts.push("}");
|
|
22937
|
-
rules = [];
|
|
22938
|
-
}
|
|
22939
|
-
}
|
|
22940
|
-
while (tokens.length) {
|
|
22941
|
-
let token = tokens.shift();
|
|
22942
|
-
if (token === "}") {
|
|
22943
|
-
generateRules();
|
|
22944
|
-
selectorStack.pop();
|
|
22945
|
-
}
|
|
22946
|
-
else {
|
|
22947
|
-
if (tokens[0] === "{") {
|
|
22948
|
-
generateRules();
|
|
22949
|
-
selectorStack.push(token.split(/\s*,\s*/));
|
|
22950
|
-
tokens.shift();
|
|
22951
|
-
}
|
|
22952
|
-
if (tokens[0] === ";") {
|
|
22953
|
-
rules.push(" " + token + ";");
|
|
22954
|
-
}
|
|
22955
|
-
}
|
|
22956
|
-
}
|
|
22957
|
-
return parts.join("\n");
|
|
22958
|
-
}
|
|
22959
|
-
function registerSheet(id, css) {
|
|
22960
|
-
const sheet = document.createElement("style");
|
|
22961
|
-
sheet.textContent = processSheet(css);
|
|
22962
|
-
STYLESHEETS[id] = sheet;
|
|
22963
|
-
}
|
|
22964
|
-
function activateSheet(id) {
|
|
22965
|
-
const sheet = STYLESHEETS[id];
|
|
22966
|
-
sheet.setAttribute("component", id);
|
|
22967
|
-
document.head.appendChild(sheet);
|
|
22968
|
-
}
|
|
22969
|
-
function getTextDecoration({ strikethrough, underline, }) {
|
|
22970
|
-
if (!strikethrough && !underline) {
|
|
22971
|
-
return "none";
|
|
22972
|
-
}
|
|
22973
|
-
return `${strikethrough ? "line-through" : ""} ${underline ? "underline" : ""}`;
|
|
22974
|
-
}
|
|
22975
|
-
/**
|
|
22976
|
-
* Convert the cell style to CSS properties.
|
|
22977
|
-
*/
|
|
22978
|
-
function cellStyleToCss(style) {
|
|
22979
|
-
const attributes = cellTextStyleToCss(style);
|
|
22980
|
-
if (!style)
|
|
22981
|
-
return attributes;
|
|
22982
|
-
if (style.fillColor) {
|
|
22983
|
-
attributes["background"] = style.fillColor;
|
|
22984
|
-
}
|
|
22985
|
-
return attributes;
|
|
22986
|
-
}
|
|
22987
|
-
/**
|
|
22988
|
-
* Convert the cell text style to CSS properties.
|
|
22989
|
-
*/
|
|
22990
|
-
function cellTextStyleToCss(style) {
|
|
22991
|
-
const attributes = {};
|
|
22992
|
-
if (!style)
|
|
22993
|
-
return attributes;
|
|
22994
|
-
if (style.bold) {
|
|
22995
|
-
attributes["font-weight"] = "bold";
|
|
22996
|
-
}
|
|
22997
|
-
if (style.italic) {
|
|
22998
|
-
attributes["font-style"] = "italic";
|
|
22999
|
-
}
|
|
23000
|
-
if (style.strikethrough || style.underline) {
|
|
23001
|
-
let decoration = style.strikethrough ? "line-through" : "";
|
|
23002
|
-
decoration = style.underline ? decoration + " underline" : decoration;
|
|
23003
|
-
attributes["text-decoration"] = decoration;
|
|
23004
|
-
}
|
|
23005
|
-
if (style.textColor) {
|
|
23006
|
-
attributes["color"] = style.textColor;
|
|
23007
|
-
}
|
|
23008
|
-
return attributes;
|
|
23009
|
-
}
|
|
23010
|
-
/**
|
|
23011
|
-
* Transform CSS properties into a CSS string.
|
|
23012
|
-
*/
|
|
23013
|
-
function cssPropertiesToCss(attributes) {
|
|
23014
|
-
let styleStr = "";
|
|
23015
|
-
for (const attName in attributes) {
|
|
23016
|
-
if (!attributes[attName]) {
|
|
23017
|
-
continue;
|
|
23018
|
-
}
|
|
23019
|
-
styleStr += `${attName}:${attributes[attName]}; `;
|
|
23020
|
-
}
|
|
23021
|
-
return styleStr;
|
|
23022
|
-
}
|
|
23023
|
-
function getElementMargins(el) {
|
|
23024
|
-
const style = window.getComputedStyle(el);
|
|
23025
|
-
return {
|
|
23026
|
-
top: parseInt(style.marginTop, 10) || 0,
|
|
23027
|
-
bottom: parseInt(style.marginBottom, 10) || 0,
|
|
23028
|
-
left: parseInt(style.marginLeft, 10) || 0,
|
|
23029
|
-
right: parseInt(style.marginRight, 10) || 0,
|
|
23030
|
-
};
|
|
23031
|
-
}
|
|
23032
|
-
|
|
23033
23070
|
css /* scss */ `
|
|
23034
23071
|
.o-spreadsheet {
|
|
23035
23072
|
.o-icon {
|
|
@@ -24141,7 +24178,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24141
24178
|
return width;
|
|
24142
24179
|
return Math.round((width / WIDTH_FACTOR) * 100) / 100;
|
|
24143
24180
|
}
|
|
24144
|
-
function extractStyle(data, styleId, formatId, borderId) {
|
|
24181
|
+
function extractStyle(data, content, styleId, formatId, borderId) {
|
|
24145
24182
|
const style = styleId ? data.styles[styleId] : {};
|
|
24146
24183
|
const format = formatId ? data.formats[formatId] : undefined;
|
|
24147
24184
|
const styles = {
|
|
@@ -24163,7 +24200,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24163
24200
|
vertical: style.verticalAlign
|
|
24164
24201
|
? V_ALIGNMENT_EXPORT_CONVERSION_MAP[style.verticalAlign]
|
|
24165
24202
|
: undefined,
|
|
24166
|
-
wrapText: style.wrapping === "wrap" || undefined,
|
|
24203
|
+
wrapText: style.wrapping === "wrap" || content?.includes(NEWLINE) ? true : undefined,
|
|
24167
24204
|
},
|
|
24168
24205
|
};
|
|
24169
24206
|
styles.font["strike"] = !!style?.strikethrough || undefined;
|
|
@@ -24394,7 +24431,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24394
24431
|
return undefined;
|
|
24395
24432
|
}
|
|
24396
24433
|
function isChartData(data) {
|
|
24397
|
-
return "dataSets" in data;
|
|
24434
|
+
return "dataSets" in data && data.dataSets.length > 0;
|
|
24398
24435
|
}
|
|
24399
24436
|
function isImageData(data) {
|
|
24400
24437
|
return "imageSrc" in data;
|
|
@@ -24740,9 +24777,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24740
24777
|
}
|
|
24741
24778
|
return rows;
|
|
24742
24779
|
}
|
|
24743
|
-
/** Remove newlines (\n) in shared strings, We do not support them */
|
|
24744
24780
|
function convertSharedStrings(xlsxSharedStrings) {
|
|
24745
|
-
return xlsxSharedStrings.map(
|
|
24781
|
+
return xlsxSharedStrings.map(replaceNewLines);
|
|
24746
24782
|
}
|
|
24747
24783
|
function convertCells(sheet, data, sheetDims, warningManager) {
|
|
24748
24784
|
const cells = {};
|
|
@@ -25830,15 +25866,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
25830
25866
|
getSharedStrings() {
|
|
25831
25867
|
return this.mapOnElements({ parent: this.rootFile.file.xml, query: "si" }, (ssElement) => {
|
|
25832
25868
|
// Shared string can either be a simple text, or a rich text (text with formatting, possibly in multiple parts)
|
|
25833
|
-
if (ssElement.children[0].tagName === "t") {
|
|
25834
|
-
return this.extractTextContent(ssElement) || "";
|
|
25835
|
-
}
|
|
25836
25869
|
// We don't support rich text formatting, we'll only extract the text
|
|
25837
|
-
|
|
25838
|
-
return this.
|
|
25839
|
-
|
|
25840
|
-
}).join("");
|
|
25841
|
-
}
|
|
25870
|
+
return this.mapOnElements({ parent: ssElement, query: "t" }, (textElement) => {
|
|
25871
|
+
return this.extractTextContent(textElement) || "";
|
|
25872
|
+
}).join("");
|
|
25842
25873
|
});
|
|
25843
25874
|
}
|
|
25844
25875
|
}
|
|
@@ -27155,12 +27186,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27155
27186
|
}
|
|
27156
27187
|
const oldName = sheet.name;
|
|
27157
27188
|
const escapedName = sanitizeSheetName(oldName, "_");
|
|
27158
|
-
|
|
27159
|
-
|
|
27160
|
-
|
|
27161
|
-
newName = `${escapedName}${i}`;
|
|
27162
|
-
i++;
|
|
27163
|
-
}
|
|
27189
|
+
const newName = getUniqueText(escapedName, namesTaken, {
|
|
27190
|
+
compute: (name, i) => `${name}${i}`,
|
|
27191
|
+
});
|
|
27164
27192
|
sheet.name = newName;
|
|
27165
27193
|
namesTaken.push(newName);
|
|
27166
27194
|
const replaceName = (str) => {
|
|
@@ -27479,6 +27507,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27479
27507
|
}
|
|
27480
27508
|
return data;
|
|
27481
27509
|
},
|
|
27510
|
+
})
|
|
27511
|
+
.add("migration_24", {
|
|
27512
|
+
// Empty migration to allow odoo migrate pivot custom sorting.
|
|
27513
|
+
versionFrom: "24",
|
|
27514
|
+
migrate(data) {
|
|
27515
|
+
return data;
|
|
27516
|
+
},
|
|
27482
27517
|
});
|
|
27483
27518
|
function fixOverlappingFilters(data) {
|
|
27484
27519
|
for (let sheet of data.sheets || []) {
|
|
@@ -27506,7 +27541,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27506
27541
|
* a breaking change is made in the way the state is handled, and an upgrade
|
|
27507
27542
|
* function should be defined
|
|
27508
27543
|
*/
|
|
27509
|
-
const CURRENT_VERSION =
|
|
27544
|
+
const CURRENT_VERSION = 25;
|
|
27510
27545
|
const INITIAL_SHEET_ID = "Sheet1";
|
|
27511
27546
|
/**
|
|
27512
27547
|
* This function tries to load anything that could look like a valid
|
|
@@ -28407,12 +28442,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28407
28442
|
}
|
|
28408
28443
|
const numberOfStep = 5 * trendLabels.length;
|
|
28409
28444
|
const step = (xmax - xmin) / numberOfStep;
|
|
28410
|
-
const
|
|
28411
|
-
const
|
|
28412
|
-
if (!
|
|
28445
|
+
const trendNewLabels = range(xmin, xmax + step / 2, step);
|
|
28446
|
+
const trendValues = interpolateData(config, filteredValues, filteredLabels, trendNewLabels);
|
|
28447
|
+
if (!trendValues.length) {
|
|
28413
28448
|
return;
|
|
28414
28449
|
}
|
|
28415
|
-
return
|
|
28450
|
+
return trendValues;
|
|
28416
28451
|
}
|
|
28417
28452
|
function interpolateData(config, values, labels, newLabels) {
|
|
28418
28453
|
if (values.length < 2 || labels.length < 2 || newLabels.length === 0) {
|
|
@@ -28428,13 +28463,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28428
28463
|
case "polynomial": {
|
|
28429
28464
|
const order = config.order;
|
|
28430
28465
|
if (!order) {
|
|
28431
|
-
return
|
|
28466
|
+
return newLabels.map((x) => ({ x, y: NaN }));
|
|
28432
28467
|
}
|
|
28433
28468
|
if (order === 1) {
|
|
28434
|
-
return predictLinearValues([values], [normalizedLabels], [normalizedNewLabels], true)[0];
|
|
28469
|
+
return predictLinearValues([values], [normalizedLabels], [normalizedNewLabels], true)[0].map((y, i) => ({ x: newLabels[i], y }));
|
|
28435
28470
|
}
|
|
28436
28471
|
const coeffs = polynomialRegression(values, normalizedLabels, order, true).flat();
|
|
28437
|
-
return normalizedNewLabels.map((
|
|
28472
|
+
return normalizedNewLabels.map((x, i) => ({
|
|
28473
|
+
x: newLabels[i],
|
|
28474
|
+
y: evaluatePolynomial(coeffs, x, order),
|
|
28475
|
+
}));
|
|
28438
28476
|
}
|
|
28439
28477
|
case "exponential": {
|
|
28440
28478
|
const positiveLogValues = [];
|
|
@@ -28446,22 +28484,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28446
28484
|
}
|
|
28447
28485
|
}
|
|
28448
28486
|
if (!filteredLabels.length) {
|
|
28449
|
-
return
|
|
28487
|
+
return newLabels.map((x) => ({ x, y: NaN }));
|
|
28450
28488
|
}
|
|
28451
|
-
return expM(predictLinearValues([positiveLogValues], [filteredLabels], [normalizedNewLabels], true))[0];
|
|
28489
|
+
return expM(predictLinearValues([positiveLogValues], [filteredLabels], [normalizedNewLabels], true))[0].map((y, i) => ({ x: newLabels[i], y }));
|
|
28452
28490
|
}
|
|
28453
28491
|
case "logarithmic": {
|
|
28454
|
-
return predictLinearValues([values], logM([normalizedLabels]), logM([normalizedNewLabels]), true)[0];
|
|
28492
|
+
return predictLinearValues([values], logM([normalizedLabels]), logM([normalizedNewLabels]), true)[0].map((y, i) => ({ x: newLabels[i], y }));
|
|
28455
28493
|
}
|
|
28456
28494
|
case "trailingMovingAverage": {
|
|
28457
|
-
return getMovingAverageValues(values, config.window);
|
|
28495
|
+
return getMovingAverageValues(values, labels, config.window);
|
|
28458
28496
|
}
|
|
28459
28497
|
default:
|
|
28460
|
-
return
|
|
28498
|
+
return newLabels.map((x) => ({ x, y: NaN }));
|
|
28461
28499
|
}
|
|
28462
28500
|
}
|
|
28463
28501
|
catch (e) {
|
|
28464
|
-
return
|
|
28502
|
+
return newLabels.map((x) => ({ x, y: NaN }));
|
|
28465
28503
|
}
|
|
28466
28504
|
}
|
|
28467
28505
|
function getChartAxisType(chart, labelRange, getters) {
|
|
@@ -28683,7 +28721,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28683
28721
|
: undefined;
|
|
28684
28722
|
label =
|
|
28685
28723
|
cell && labelRange
|
|
28686
|
-
?
|
|
28724
|
+
? cell.formattedValue
|
|
28687
28725
|
: (label = `${ChartTerms.Series} ${parseInt(dsIndex) + 1}`);
|
|
28688
28726
|
}
|
|
28689
28727
|
else {
|
|
@@ -28697,7 +28735,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28697
28735
|
// then using the classical aggregation method to sum the values.
|
|
28698
28736
|
data.fill(1);
|
|
28699
28737
|
}
|
|
28700
|
-
else if (data.every((cell) => cell === undefined || cell === null || !isNumber(cell.toString(),
|
|
28738
|
+
else if (data.every((cell) => cell === undefined || cell === null || !isNumber(cell.toString(), DEFAULT_LOCALE))) {
|
|
28701
28739
|
continue;
|
|
28702
28740
|
}
|
|
28703
28741
|
datasetValues.push({ data, label });
|
|
@@ -28773,7 +28811,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28773
28811
|
}
|
|
28774
28812
|
return {
|
|
28775
28813
|
datasets: [dataset],
|
|
28776
|
-
labels: labelsWithSubTotals
|
|
28814
|
+
labels: labelsWithSubTotals,
|
|
28777
28815
|
};
|
|
28778
28816
|
}
|
|
28779
28817
|
function getLineChartDatasets(definition, args) {
|
|
@@ -29022,7 +29060,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29022
29060
|
generateLabels: (c) =>
|
|
29023
29061
|
//@ts-ignore
|
|
29024
29062
|
c.data.labels.map((label, index) => ({
|
|
29025
|
-
text: label,
|
|
29063
|
+
text: truncateLabel(String(label)),
|
|
29026
29064
|
strokeStyle: colors[index],
|
|
29027
29065
|
fillStyle: colors[index],
|
|
29028
29066
|
pointStyle: "rect",
|
|
@@ -29091,6 +29129,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29091
29129
|
return legendValues;
|
|
29092
29130
|
},
|
|
29093
29131
|
},
|
|
29132
|
+
onClick: () => { }, // Disables click interaction with the waterfall chart legend items
|
|
29094
29133
|
};
|
|
29095
29134
|
}
|
|
29096
29135
|
function getRadarChartLegend(definition, args) {
|
|
@@ -29152,7 +29191,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29152
29191
|
generateLabels: (chart) => chart.data.datasets.map((dataset, index) => {
|
|
29153
29192
|
if (dataset["xAxisID"] === TREND_LINE_XAXIS_ID) {
|
|
29154
29193
|
return {
|
|
29155
|
-
text: dataset.label
|
|
29194
|
+
text: truncateLabel(dataset.label),
|
|
29156
29195
|
fontColor,
|
|
29157
29196
|
strokeStyle: dataset.borderColor,
|
|
29158
29197
|
hidden: !chart.isDatasetVisible(index),
|
|
@@ -29162,7 +29201,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29162
29201
|
};
|
|
29163
29202
|
}
|
|
29164
29203
|
return {
|
|
29165
|
-
text: dataset.label
|
|
29204
|
+
text: truncateLabel(dataset.label),
|
|
29166
29205
|
fontColor,
|
|
29167
29206
|
strokeStyle: dataset.borderColor,
|
|
29168
29207
|
fillStyle: dataset.backgroundColor,
|
|
@@ -29232,14 +29271,19 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29232
29271
|
/* We add a second x axis here to draw the trend lines, with the labels length being
|
|
29233
29272
|
* set so that the second axis points match the classical x axis
|
|
29234
29273
|
*/
|
|
29235
|
-
const maxLength = Math.max(...trendDatasets.map((trendDataset) => trendDataset?.length || 0));
|
|
29236
29274
|
scales[TREND_LINE_XAXIS_ID] = {
|
|
29237
29275
|
...scales.x,
|
|
29238
|
-
type: "category",
|
|
29239
|
-
labels: range(0, maxLength).map((x) => x.toString()),
|
|
29240
|
-
offset: false,
|
|
29241
29276
|
display: false,
|
|
29242
29277
|
};
|
|
29278
|
+
if (axisType === "category" || axisType === "time") {
|
|
29279
|
+
/* We add a second x axis here to draw the trend lines, with the labels length being
|
|
29280
|
+
* set so that the second axis points match the classical x axis
|
|
29281
|
+
*/
|
|
29282
|
+
const maxLength = Math.max(...trendDatasets.map((trendDataset) => trendDataset?.length || 0));
|
|
29283
|
+
scales[TREND_LINE_XAXIS_ID]["type"] = "category";
|
|
29284
|
+
scales[TREND_LINE_XAXIS_ID]["labels"] = range(0, maxLength).map((x) => x.toString());
|
|
29285
|
+
scales[TREND_LINE_XAXIS_ID]["offset"] = false;
|
|
29286
|
+
}
|
|
29243
29287
|
}
|
|
29244
29288
|
return scales;
|
|
29245
29289
|
}
|
|
@@ -29304,7 +29348,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29304
29348
|
callback: formatTickValue({ format: axisFormats?.r, locale }),
|
|
29305
29349
|
backdropColor: definition.background || "#FFFFFF",
|
|
29306
29350
|
},
|
|
29307
|
-
pointLabels: {
|
|
29351
|
+
pointLabels: {
|
|
29352
|
+
color: chartFontColor(definition.background),
|
|
29353
|
+
callback: truncateLabel,
|
|
29354
|
+
},
|
|
29308
29355
|
suggestedMin: minValue < 0 ? minValue - 1 : 0,
|
|
29309
29356
|
},
|
|
29310
29357
|
};
|
|
@@ -29401,6 +29448,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29401
29448
|
ticks: {
|
|
29402
29449
|
padding: 5,
|
|
29403
29450
|
color: fontColor,
|
|
29451
|
+
callback: function (tickValue) {
|
|
29452
|
+
// Category axis callback's internal tick value is the index of the label
|
|
29453
|
+
// https://www.chartjs.org/docs/latest/axes/labelling.html#creating-custom-tick-formats
|
|
29454
|
+
return truncateLabel(this.getLabelForValue(tickValue));
|
|
29455
|
+
},
|
|
29404
29456
|
},
|
|
29405
29457
|
grid: {
|
|
29406
29458
|
display: false,
|
|
@@ -29480,8 +29532,70 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29480
29532
|
};
|
|
29481
29533
|
}
|
|
29482
29534
|
|
|
29535
|
+
/**
|
|
29536
|
+
* Custom tooltip for the charts. Mostly copied from Odoo's custom tooltip, with some slight changes to make it work
|
|
29537
|
+
* with o-spreadsheet chart data and CSS.
|
|
29538
|
+
*
|
|
29539
|
+
* https://github.com/odoo/odoo/blob/18.0/addons/web/static/src/views/graph/graph_renderer.xml
|
|
29540
|
+
*/
|
|
29541
|
+
const templates = /* xml */ `
|
|
29542
|
+
<templates>
|
|
29543
|
+
<t t-name="o-spreadsheet-CustomTooltip">
|
|
29544
|
+
<div
|
|
29545
|
+
class="o-chart-custom-tooltip border rounded px-2 py-1 pe-none mw-100 position-absolute text-nowrap shadow opacity-100">
|
|
29546
|
+
<table class="overflow-hidden m-0">
|
|
29547
|
+
<thead>
|
|
29548
|
+
<tr>
|
|
29549
|
+
<th class="o-tooltip-title align-baseline border-0 text-truncate" t-esc="title" t-attf-style="max-width: {{ labelsMaxWidth }}"/>
|
|
29550
|
+
</tr>
|
|
29551
|
+
</thead>
|
|
29552
|
+
<tbody>
|
|
29553
|
+
<tr t-foreach="tooltipItems" t-as="tooltipItem" t-key="tooltipItem_index">
|
|
29554
|
+
<td>
|
|
29555
|
+
<span
|
|
29556
|
+
class="badge ps-2 py-2 rounded-0 align-middle"
|
|
29557
|
+
t-attf-style="background-color: {{ tooltipItem.boxColor }}"
|
|
29558
|
+
> </span>
|
|
29559
|
+
<small
|
|
29560
|
+
t-if="tooltipItem.label"
|
|
29561
|
+
class="o-tooltip-label d-inline-block text-truncate align-middle smaller ms-2"
|
|
29562
|
+
t-esc="tooltipItem.label"
|
|
29563
|
+
t-attf-style="max-width: {{ labelsMaxWidth }}"
|
|
29564
|
+
/>
|
|
29565
|
+
</td>
|
|
29566
|
+
<td class="o-tooltip-value ps-2 fw-bolder text-end">
|
|
29567
|
+
<small class="smaller d-inline-block text-truncate align-middle" t-attf-style="max-width: {{ valuesMaxWidth }}">
|
|
29568
|
+
<t t-esc="tooltipItem.value"/>
|
|
29569
|
+
<t t-if="tooltipItem.percentage">
|
|
29570
|
+
(
|
|
29571
|
+
<t t-esc="tooltipItem.percentage"/>
|
|
29572
|
+
%)
|
|
29573
|
+
</t>
|
|
29574
|
+
</small>
|
|
29575
|
+
</td>
|
|
29576
|
+
</tr>
|
|
29577
|
+
</tbody>
|
|
29578
|
+
</table>
|
|
29579
|
+
</div>
|
|
29580
|
+
</t>
|
|
29581
|
+
</templates>
|
|
29582
|
+
`;
|
|
29583
|
+
const app = new owl.App(owl.Component, { templates, translateFn: _t });
|
|
29584
|
+
function renderToString(templateName, context = {}) {
|
|
29585
|
+
return render(templateName, context).innerHTML;
|
|
29586
|
+
}
|
|
29587
|
+
function render(templateName, context = {}) {
|
|
29588
|
+
const templateFn = app.getTemplate(templateName);
|
|
29589
|
+
const bdom = templateFn(context, {});
|
|
29590
|
+
const div = document.createElement("div");
|
|
29591
|
+
owl.blockDom.mount(bdom, div);
|
|
29592
|
+
return div;
|
|
29593
|
+
}
|
|
29594
|
+
|
|
29483
29595
|
function getBarChartTooltip(definition, args) {
|
|
29484
29596
|
return {
|
|
29597
|
+
enabled: false,
|
|
29598
|
+
external: customTooltipHandler,
|
|
29485
29599
|
callbacks: {
|
|
29486
29600
|
title: function (tooltipItems) {
|
|
29487
29601
|
return tooltipItems.some((item) => item.dataset.xAxisID !== TREND_LINE_XAXIS_ID)
|
|
@@ -29505,11 +29619,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29505
29619
|
function getLineChartTooltip(definition, args) {
|
|
29506
29620
|
const { axisType, locale, axisFormats } = args;
|
|
29507
29621
|
const labelFormat = axisFormats?.x;
|
|
29508
|
-
const tooltip = {
|
|
29622
|
+
const tooltip = {
|
|
29623
|
+
enabled: false,
|
|
29624
|
+
external: customTooltipHandler,
|
|
29625
|
+
callbacks: {},
|
|
29626
|
+
};
|
|
29509
29627
|
if (axisType === "linear") {
|
|
29510
29628
|
tooltip.callbacks.label = (tooltipItem) => {
|
|
29511
29629
|
const dataSetPoint = tooltipItem.parsed.y;
|
|
29512
|
-
let label = tooltipItem.
|
|
29630
|
+
let label = tooltipItem.dataset.xAxisID === TREND_LINE_XAXIS_ID
|
|
29631
|
+
? ""
|
|
29632
|
+
: tooltipItem.parsed.x;
|
|
29513
29633
|
if (typeof label === "string" && isNumber(label, locale)) {
|
|
29514
29634
|
label = toNumber(label, locale);
|
|
29515
29635
|
}
|
|
@@ -29542,6 +29662,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29542
29662
|
const { locale, axisFormats } = args;
|
|
29543
29663
|
const format = axisFormats?.y || axisFormats?.y1;
|
|
29544
29664
|
return {
|
|
29665
|
+
enabled: false,
|
|
29666
|
+
external: customTooltipHandler,
|
|
29545
29667
|
callbacks: {
|
|
29546
29668
|
title: function (tooltipItems) {
|
|
29547
29669
|
return tooltipItems[0].dataset.label;
|
|
@@ -29566,6 +29688,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29566
29688
|
const format = axisFormats?.y || axisFormats?.y1;
|
|
29567
29689
|
const dataSeriesLabels = dataSetsValues.map((dataSet) => dataSet.label);
|
|
29568
29690
|
return {
|
|
29691
|
+
enabled: false,
|
|
29692
|
+
external: customTooltipHandler,
|
|
29569
29693
|
callbacks: {
|
|
29570
29694
|
label: function (tooltipItem) {
|
|
29571
29695
|
const [lastValue, currentValue] = tooltipItem.raw;
|
|
@@ -29597,6 +29721,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29597
29721
|
function getRadarChartTooltip(definition, args) {
|
|
29598
29722
|
const { locale, axisFormats } = args;
|
|
29599
29723
|
return {
|
|
29724
|
+
enabled: false,
|
|
29725
|
+
external: customTooltipHandler,
|
|
29600
29726
|
callbacks: {
|
|
29601
29727
|
label: function (tooltipItem) {
|
|
29602
29728
|
const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
|
|
@@ -29635,6 +29761,48 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29635
29761
|
const percentage = (dataset[dataIndex] / total) * 100;
|
|
29636
29762
|
return percentage.toFixed(2);
|
|
29637
29763
|
}
|
|
29764
|
+
function customTooltipHandler({ chart, tooltip }) {
|
|
29765
|
+
chart.canvas.parentNode.querySelector("div.o-chart-custom-tooltip")?.remove();
|
|
29766
|
+
if (tooltip.opacity === 0 || tooltip.dataPoints.length === 0) {
|
|
29767
|
+
return;
|
|
29768
|
+
}
|
|
29769
|
+
const tooltipItems = tooltip.body.map((body, index) => {
|
|
29770
|
+
let [label, value] = body.lines[0].split(":").map((str) => str.trim());
|
|
29771
|
+
if (!value) {
|
|
29772
|
+
value = label;
|
|
29773
|
+
label = "";
|
|
29774
|
+
}
|
|
29775
|
+
const color = tooltip.labelColors[index].backgroundColor;
|
|
29776
|
+
return {
|
|
29777
|
+
label,
|
|
29778
|
+
value,
|
|
29779
|
+
boxColor: typeof color === "string" ? setColorAlpha(color, 1) : color,
|
|
29780
|
+
};
|
|
29781
|
+
});
|
|
29782
|
+
const innerHTML = renderToString("o-spreadsheet-CustomTooltip", {
|
|
29783
|
+
labelsMaxWidth: Math.floor(chart.canvas.clientWidth * 0.5) + "px",
|
|
29784
|
+
valuesMaxWidth: Math.floor(chart.canvas.clientWidth * 0.25) + "px",
|
|
29785
|
+
title: tooltip.title[0],
|
|
29786
|
+
tooltipItems,
|
|
29787
|
+
});
|
|
29788
|
+
const template = Object.assign(document.createElement("template"), { innerHTML });
|
|
29789
|
+
const newTooltipEl = template.content.firstChild;
|
|
29790
|
+
chart.canvas.parentNode?.appendChild(newTooltipEl);
|
|
29791
|
+
Object.assign(newTooltipEl.style, {
|
|
29792
|
+
left: getTooltipLeftPosition(chart, tooltip, newTooltipEl.clientWidth) + "px",
|
|
29793
|
+
top: Math.floor(tooltip.caretY - newTooltipEl.clientHeight / 2) + "px",
|
|
29794
|
+
});
|
|
29795
|
+
}
|
|
29796
|
+
/**
|
|
29797
|
+
* Get the left position for the tooltip, making sure it doesn't go out of the chart area.
|
|
29798
|
+
*/
|
|
29799
|
+
function getTooltipLeftPosition(chart, tooltip, tooltipWidth) {
|
|
29800
|
+
const x = tooltip.caretX;
|
|
29801
|
+
if (x + tooltipWidth > chart.chartArea.right) {
|
|
29802
|
+
return Math.max(0, x - tooltipWidth);
|
|
29803
|
+
}
|
|
29804
|
+
return x;
|
|
29805
|
+
}
|
|
29638
29806
|
|
|
29639
29807
|
var CHART_RUNTIME_HELPERS = /*#__PURE__*/Object.freeze({
|
|
29640
29808
|
__proto__: null,
|
|
@@ -29748,11 +29916,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29748
29916
|
: undefined,
|
|
29749
29917
|
};
|
|
29750
29918
|
}
|
|
29751
|
-
|
|
29752
|
-
const dataSets =
|
|
29753
|
-
const labelRange =
|
|
29754
|
-
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange,
|
|
29755
|
-
return new BarChart(definition,
|
|
29919
|
+
duplicateInDuplicatedSheet(newSheetId) {
|
|
29920
|
+
const dataSets = duplicateDataSetsInDuplicatedSheet(this.sheetId, newSheetId, this.dataSets);
|
|
29921
|
+
const labelRange = duplicateLabelRangeInDuplicatedSheet(this.sheetId, newSheetId, this.labelRange);
|
|
29922
|
+
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange, newSheetId);
|
|
29923
|
+
return new BarChart(definition, newSheetId, this.getters);
|
|
29756
29924
|
}
|
|
29757
29925
|
copyInSheetId(sheetId) {
|
|
29758
29926
|
const definition = this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange, sheetId);
|
|
@@ -29819,7 +29987,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29819
29987
|
const config = {
|
|
29820
29988
|
type: "bar",
|
|
29821
29989
|
data: {
|
|
29822
|
-
labels: chartData.labels
|
|
29990
|
+
labels: chartData.labels,
|
|
29823
29991
|
datasets: getBarChartDatasets(definition, chartData),
|
|
29824
29992
|
},
|
|
29825
29993
|
options: {
|
|
@@ -29955,11 +30123,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29955
30123
|
showValues: context.showValues,
|
|
29956
30124
|
};
|
|
29957
30125
|
}
|
|
29958
|
-
|
|
29959
|
-
const dataSets =
|
|
29960
|
-
const labelRange =
|
|
29961
|
-
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange,
|
|
29962
|
-
return new ComboChart(definition,
|
|
30126
|
+
duplicateInDuplicatedSheet(newSheetId) {
|
|
30127
|
+
const dataSets = duplicateDataSetsInDuplicatedSheet(this.sheetId, newSheetId, this.dataSets);
|
|
30128
|
+
const labelRange = duplicateLabelRangeInDuplicatedSheet(this.sheetId, newSheetId, this.labelRange);
|
|
30129
|
+
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange, newSheetId);
|
|
30130
|
+
return new ComboChart(definition, newSheetId, this.getters);
|
|
29963
30131
|
}
|
|
29964
30132
|
copyInSheetId(sheetId) {
|
|
29965
30133
|
const definition = this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange, sheetId);
|
|
@@ -29972,7 +30140,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29972
30140
|
const config = {
|
|
29973
30141
|
type: "bar",
|
|
29974
30142
|
data: {
|
|
29975
|
-
labels: chartData.labels
|
|
30143
|
+
labels: chartData.labels,
|
|
29976
30144
|
datasets: getComboChartDatasets(definition, chartData),
|
|
29977
30145
|
},
|
|
29978
30146
|
options: {
|
|
@@ -30106,10 +30274,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30106
30274
|
},
|
|
30107
30275
|
};
|
|
30108
30276
|
}
|
|
30109
|
-
|
|
30110
|
-
const dataRange =
|
|
30111
|
-
const definition = this.getDefinitionWithSpecificRanges(dataRange,
|
|
30112
|
-
return new GaugeChart(definition,
|
|
30277
|
+
duplicateInDuplicatedSheet(newSheetId) {
|
|
30278
|
+
const dataRange = duplicateLabelRangeInDuplicatedSheet(this.sheetId, newSheetId, this.dataRange);
|
|
30279
|
+
const definition = this.getDefinitionWithSpecificRanges(dataRange, newSheetId);
|
|
30280
|
+
return new GaugeChart(definition, newSheetId, this.getters);
|
|
30113
30281
|
}
|
|
30114
30282
|
copyInSheetId(sheetId) {
|
|
30115
30283
|
const definition = this.getDefinitionWithSpecificRanges(this.dataRange, sheetId);
|
|
@@ -30202,7 +30370,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30202
30370
|
colors.push(chartColors.upperColor);
|
|
30203
30371
|
return {
|
|
30204
30372
|
background: getters.getStyleOfSingleCellChart(chart.background, dataRange).background,
|
|
30205
|
-
title:
|
|
30373
|
+
title: {
|
|
30374
|
+
...chart.title,
|
|
30375
|
+
// chart titles are extracted from .json files and they are translated at runtime here
|
|
30376
|
+
text: _t(chart.title.text ?? ""),
|
|
30377
|
+
},
|
|
30206
30378
|
minValue: {
|
|
30207
30379
|
value: minValue,
|
|
30208
30380
|
label: formatValue(minValue, { locale, format }),
|
|
@@ -30286,11 +30458,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30286
30458
|
: undefined,
|
|
30287
30459
|
};
|
|
30288
30460
|
}
|
|
30289
|
-
|
|
30290
|
-
const dataSets =
|
|
30291
|
-
const labelRange =
|
|
30292
|
-
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange,
|
|
30293
|
-
return new GeoChart(definition,
|
|
30461
|
+
duplicateInDuplicatedSheet(newSheetId) {
|
|
30462
|
+
const dataSets = duplicateDataSetsInDuplicatedSheet(this.sheetId, newSheetId, this.dataSets);
|
|
30463
|
+
const labelRange = duplicateLabelRangeInDuplicatedSheet(this.sheetId, newSheetId, this.labelRange);
|
|
30464
|
+
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange, newSheetId);
|
|
30465
|
+
return new GeoChart(definition, newSheetId, this.getters);
|
|
30294
30466
|
}
|
|
30295
30467
|
copyInSheetId(sheetId) {
|
|
30296
30468
|
const definition = this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange, sheetId);
|
|
@@ -30483,11 +30655,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30483
30655
|
verticalAxis: getDefinedAxis(definition),
|
|
30484
30656
|
};
|
|
30485
30657
|
}
|
|
30486
|
-
|
|
30487
|
-
const dataSets =
|
|
30488
|
-
const labelRange =
|
|
30489
|
-
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange,
|
|
30490
|
-
return new LineChart(definition,
|
|
30658
|
+
duplicateInDuplicatedSheet(newSheetId) {
|
|
30659
|
+
const dataSets = duplicateDataSetsInDuplicatedSheet(this.sheetId, newSheetId, this.dataSets);
|
|
30660
|
+
const labelRange = duplicateLabelRangeInDuplicatedSheet(this.sheetId, newSheetId, this.labelRange);
|
|
30661
|
+
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange, newSheetId);
|
|
30662
|
+
return new LineChart(definition, newSheetId, this.getters);
|
|
30491
30663
|
}
|
|
30492
30664
|
copyInSheetId(sheetId) {
|
|
30493
30665
|
const definition = this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange, sheetId);
|
|
@@ -30500,7 +30672,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30500
30672
|
const config = {
|
|
30501
30673
|
type: "line",
|
|
30502
30674
|
data: {
|
|
30503
|
-
labels: chartData.
|
|
30675
|
+
labels: chartData.labels,
|
|
30504
30676
|
datasets: getLineChartDatasets(definition, chartData),
|
|
30505
30677
|
},
|
|
30506
30678
|
options: {
|
|
@@ -30594,11 +30766,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30594
30766
|
showValues: this.showValues,
|
|
30595
30767
|
};
|
|
30596
30768
|
}
|
|
30597
|
-
|
|
30598
|
-
const dataSets =
|
|
30599
|
-
const labelRange =
|
|
30600
|
-
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange,
|
|
30601
|
-
return new PieChart(definition,
|
|
30769
|
+
duplicateInDuplicatedSheet(newSheetId) {
|
|
30770
|
+
const dataSets = duplicateDataSetsInDuplicatedSheet(this.sheetId, newSheetId, this.dataSets);
|
|
30771
|
+
const labelRange = duplicateLabelRangeInDuplicatedSheet(this.sheetId, newSheetId, this.labelRange);
|
|
30772
|
+
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange, newSheetId);
|
|
30773
|
+
return new PieChart(definition, newSheetId, this.getters);
|
|
30602
30774
|
}
|
|
30603
30775
|
copyInSheetId(sheetId) {
|
|
30604
30776
|
const definition = this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange, sheetId);
|
|
@@ -30635,7 +30807,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30635
30807
|
const config = {
|
|
30636
30808
|
type: chart.isDoughnut ? "doughnut" : "pie",
|
|
30637
30809
|
data: {
|
|
30638
|
-
labels: chartData.labels
|
|
30810
|
+
labels: chartData.labels,
|
|
30639
30811
|
datasets: getPieChartDatasets(definition, chartData),
|
|
30640
30812
|
},
|
|
30641
30813
|
options: {
|
|
@@ -30715,11 +30887,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30715
30887
|
: undefined,
|
|
30716
30888
|
};
|
|
30717
30889
|
}
|
|
30718
|
-
|
|
30719
|
-
const dataSets =
|
|
30720
|
-
const labelRange =
|
|
30721
|
-
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange,
|
|
30722
|
-
return new PyramidChart(definition,
|
|
30890
|
+
duplicateInDuplicatedSheet(newSheetId) {
|
|
30891
|
+
const dataSets = duplicateDataSetsInDuplicatedSheet(this.sheetId, newSheetId, this.dataSets);
|
|
30892
|
+
const labelRange = duplicateLabelRangeInDuplicatedSheet(this.sheetId, newSheetId, this.labelRange);
|
|
30893
|
+
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange, newSheetId);
|
|
30894
|
+
return new PyramidChart(definition, newSheetId, this.getters);
|
|
30723
30895
|
}
|
|
30724
30896
|
copyInSheetId(sheetId) {
|
|
30725
30897
|
const definition = this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange, sheetId);
|
|
@@ -30771,7 +30943,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30771
30943
|
const config = {
|
|
30772
30944
|
type: "bar",
|
|
30773
30945
|
data: {
|
|
30774
|
-
labels: chartData.labels
|
|
30946
|
+
labels: chartData.labels,
|
|
30775
30947
|
datasets: getBarChartDatasets(definition, chartData),
|
|
30776
30948
|
},
|
|
30777
30949
|
options: {
|
|
@@ -30852,11 +31024,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30852
31024
|
: undefined,
|
|
30853
31025
|
};
|
|
30854
31026
|
}
|
|
30855
|
-
|
|
30856
|
-
const dataSets =
|
|
30857
|
-
const labelRange =
|
|
30858
|
-
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange,
|
|
30859
|
-
return new RadarChart(definition,
|
|
31027
|
+
duplicateInDuplicatedSheet(newSheetId) {
|
|
31028
|
+
const dataSets = duplicateDataSetsInDuplicatedSheet(this.sheetId, newSheetId, this.dataSets);
|
|
31029
|
+
const labelRange = duplicateLabelRangeInDuplicatedSheet(this.sheetId, newSheetId, this.labelRange);
|
|
31030
|
+
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange, newSheetId);
|
|
31031
|
+
return new RadarChart(definition, newSheetId, this.getters);
|
|
30860
31032
|
}
|
|
30861
31033
|
copyInSheetId(sheetId) {
|
|
30862
31034
|
const definition = this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange, sheetId);
|
|
@@ -30921,7 +31093,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30921
31093
|
const config = {
|
|
30922
31094
|
type: "radar",
|
|
30923
31095
|
data: {
|
|
30924
|
-
labels: chartData.labels
|
|
31096
|
+
labels: chartData.labels,
|
|
30925
31097
|
datasets: getRadarChartDatasets(definition, chartData),
|
|
30926
31098
|
},
|
|
30927
31099
|
options: {
|
|
@@ -31055,11 +31227,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31055
31227
|
verticalAxis: getDefinedAxis(definition),
|
|
31056
31228
|
};
|
|
31057
31229
|
}
|
|
31058
|
-
|
|
31059
|
-
const dataSets =
|
|
31060
|
-
const labelRange =
|
|
31061
|
-
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange,
|
|
31062
|
-
return new ScatterChart(definition,
|
|
31230
|
+
duplicateInDuplicatedSheet(newSheetId) {
|
|
31231
|
+
const dataSets = duplicateDataSetsInDuplicatedSheet(this.sheetId, newSheetId, this.dataSets);
|
|
31232
|
+
const labelRange = duplicateLabelRangeInDuplicatedSheet(this.sheetId, newSheetId, this.labelRange);
|
|
31233
|
+
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange, newSheetId);
|
|
31234
|
+
return new ScatterChart(definition, newSheetId, this.getters);
|
|
31063
31235
|
}
|
|
31064
31236
|
copyInSheetId(sheetId) {
|
|
31065
31237
|
const definition = this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange, sheetId);
|
|
@@ -31074,7 +31246,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31074
31246
|
// have less options than the line chart (it only works with linear labels)
|
|
31075
31247
|
type: "line",
|
|
31076
31248
|
data: {
|
|
31077
|
-
labels: chartData.
|
|
31249
|
+
labels: chartData.labels,
|
|
31078
31250
|
datasets: getScatterChartDatasets(definition, chartData),
|
|
31079
31251
|
},
|
|
31080
31252
|
options: {
|
|
@@ -31172,11 +31344,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31172
31344
|
: undefined,
|
|
31173
31345
|
};
|
|
31174
31346
|
}
|
|
31175
|
-
|
|
31176
|
-
const dataSets =
|
|
31177
|
-
const labelRange =
|
|
31178
|
-
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange,
|
|
31179
|
-
return new WaterfallChart(definition,
|
|
31347
|
+
duplicateInDuplicatedSheet(newSheetId) {
|
|
31348
|
+
const dataSets = duplicateDataSetsInDuplicatedSheet(this.sheetId, newSheetId, this.dataSets);
|
|
31349
|
+
const labelRange = duplicateLabelRangeInDuplicatedSheet(this.sheetId, newSheetId, this.labelRange);
|
|
31350
|
+
const definition = this.getDefinitionWithSpecificDataSets(dataSets, labelRange, newSheetId);
|
|
31351
|
+
return new WaterfallChart(definition, newSheetId, this.getters);
|
|
31180
31352
|
}
|
|
31181
31353
|
copyInSheetId(sheetId) {
|
|
31182
31354
|
const definition = this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange, sheetId);
|
|
@@ -33603,8 +33775,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
33603
33775
|
chartToImage: chartToImage,
|
|
33604
33776
|
checkDataset: checkDataset,
|
|
33605
33777
|
checkLabelRange: checkLabelRange,
|
|
33606
|
-
copyDataSetsWithNewSheetId: copyDataSetsWithNewSheetId,
|
|
33607
|
-
copyLabelRangeWithNewSheetId: copyLabelRangeWithNewSheetId,
|
|
33608
33778
|
createBarChartRuntime: createBarChartRuntime,
|
|
33609
33779
|
createDataSets: createDataSets,
|
|
33610
33780
|
createGaugeChartRuntime: createGaugeChartRuntime,
|
|
@@ -33613,6 +33783,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
33613
33783
|
createScorecardChartRuntime: createScorecardChartRuntime,
|
|
33614
33784
|
createWaterfallChartRuntime: createWaterfallChartRuntime,
|
|
33615
33785
|
drawScoreChart: drawScoreChart,
|
|
33786
|
+
duplicateDataSetsInDuplicatedSheet: duplicateDataSetsInDuplicatedSheet,
|
|
33787
|
+
duplicateLabelRangeInDuplicatedSheet: duplicateLabelRangeInDuplicatedSheet,
|
|
33616
33788
|
formatChartDatasetValue: formatChartDatasetValue,
|
|
33617
33789
|
formatTickValue: formatTickValue,
|
|
33618
33790
|
getChartPositionAtCenterOfViewport: getChartPositionAtCenterOfViewport,
|
|
@@ -35333,12 +35505,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
35333
35505
|
});
|
|
35334
35506
|
}
|
|
35335
35507
|
function isAutomaticFormatSelected(env) {
|
|
35336
|
-
const
|
|
35337
|
-
|
|
35508
|
+
const activePosition = env.model.getters.getActivePosition();
|
|
35509
|
+
const pivotCell = env.model.getters.getPivotCellFromPosition(activePosition);
|
|
35510
|
+
if (pivotCell.type === "VALUE") {
|
|
35511
|
+
return !env.model.getters.getEvaluatedCell(activePosition).format;
|
|
35512
|
+
}
|
|
35513
|
+
return !env.model.getters.getCell(activePosition)?.format;
|
|
35338
35514
|
}
|
|
35339
35515
|
function isFormatSelected(env, format) {
|
|
35340
|
-
const
|
|
35341
|
-
|
|
35516
|
+
const activePosition = env.model.getters.getActivePosition();
|
|
35517
|
+
const pivotCell = env.model.getters.getPivotCellFromPosition(activePosition);
|
|
35518
|
+
if (pivotCell.type === "VALUE") {
|
|
35519
|
+
return env.model.getters.getEvaluatedCell(activePosition).format === format;
|
|
35520
|
+
}
|
|
35521
|
+
return env.model.getters.getCell(activePosition)?.format === format;
|
|
35342
35522
|
}
|
|
35343
35523
|
function isFontSizeSelected(env, fontSize) {
|
|
35344
35524
|
const currentFontSize = env.model.getters.getCurrentStyle().fontSize || DEFAULT_FONT_SIZE;
|
|
@@ -39677,14 +39857,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
39677
39857
|
}
|
|
39678
39858
|
|
|
39679
39859
|
class DOMFocusableElementStore {
|
|
39680
|
-
mutators = ["setFocusableElement"
|
|
39860
|
+
mutators = ["setFocusableElement"];
|
|
39681
39861
|
focusableElement = undefined;
|
|
39682
39862
|
setFocusableElement(element) {
|
|
39683
39863
|
this.focusableElement = element;
|
|
39684
39864
|
}
|
|
39685
|
-
focus() {
|
|
39686
|
-
this.focusableElement?.focus();
|
|
39687
|
-
}
|
|
39688
39865
|
}
|
|
39689
39866
|
|
|
39690
39867
|
css /* scss */ `
|
|
@@ -40332,7 +40509,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40332
40509
|
if (document.activeElement === this.contentHelper.el &&
|
|
40333
40510
|
this.props.composerStore.editionMode === "inactive" &&
|
|
40334
40511
|
!this.props.isDefaultFocus) {
|
|
40335
|
-
this.DOMFocusableElementStore.focus();
|
|
40512
|
+
this.DOMFocusableElementStore.focusableElement?.focus();
|
|
40336
40513
|
}
|
|
40337
40514
|
});
|
|
40338
40515
|
owl.useEffect(() => {
|
|
@@ -44313,16 +44490,21 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44313
44490
|
}
|
|
44314
44491
|
this.inputRef.el?.blur();
|
|
44315
44492
|
}
|
|
44316
|
-
|
|
44317
|
-
|
|
44318
|
-
if (
|
|
44319
|
-
|
|
44320
|
-
|
|
44321
|
-
|
|
44322
|
-
|
|
44323
|
-
|
|
44324
|
-
|
|
44325
|
-
|
|
44493
|
+
onMouseDown(ev) {
|
|
44494
|
+
// Stop the event if the input is not focused, we handle everything in onMouseUp
|
|
44495
|
+
if (ev.target !== document.activeElement) {
|
|
44496
|
+
ev.preventDefault();
|
|
44497
|
+
ev.stopPropagation();
|
|
44498
|
+
}
|
|
44499
|
+
}
|
|
44500
|
+
onMouseUp(ev) {
|
|
44501
|
+
const target = ev.target;
|
|
44502
|
+
if (target !== document.activeElement) {
|
|
44503
|
+
target.focus();
|
|
44504
|
+
target.select();
|
|
44505
|
+
ev.preventDefault();
|
|
44506
|
+
ev.stopPropagation();
|
|
44507
|
+
}
|
|
44326
44508
|
}
|
|
44327
44509
|
}
|
|
44328
44510
|
|
|
@@ -44875,7 +45057,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44875
45057
|
newPivotId,
|
|
44876
45058
|
newSheetId,
|
|
44877
45059
|
});
|
|
44878
|
-
|
|
45060
|
+
let text;
|
|
45061
|
+
if (result.isSuccessful) {
|
|
45062
|
+
text = _t("Pivot duplicated.");
|
|
45063
|
+
}
|
|
45064
|
+
else if (result.isCancelledBecause("PivotInError" /* CommandResult.PivotInError */)) {
|
|
45065
|
+
text = _t("Cannot duplicate a pivot in error.");
|
|
45066
|
+
}
|
|
45067
|
+
else {
|
|
45068
|
+
text = _t("Pivot duplication failed.");
|
|
45069
|
+
}
|
|
44879
45070
|
const type = result.isSuccessful ? "success" : "danger";
|
|
44880
45071
|
this.env.notifyUser({
|
|
44881
45072
|
text,
|
|
@@ -46026,12 +46217,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46026
46217
|
* Take cares of double names
|
|
46027
46218
|
*/
|
|
46028
46219
|
findName(name, fields) {
|
|
46029
|
-
|
|
46030
|
-
|
|
46031
|
-
|
|
46032
|
-
|
|
46033
|
-
}
|
|
46034
|
-
return name;
|
|
46220
|
+
return getUniqueText(name, Object.keys(fields), {
|
|
46221
|
+
compute: (name, i) => `${name}${i}`,
|
|
46222
|
+
start: 2,
|
|
46223
|
+
});
|
|
46035
46224
|
}
|
|
46036
46225
|
extractDataEntriesFromRange(range) {
|
|
46037
46226
|
const dataEntries = [];
|
|
@@ -46214,7 +46403,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46214
46403
|
pivot: this.draft,
|
|
46215
46404
|
});
|
|
46216
46405
|
this.draft = null;
|
|
46217
|
-
if (!this.alreadyNotified &&
|
|
46406
|
+
if (!this.alreadyNotified &&
|
|
46407
|
+
!this.isDynamicPivotInViewport() &&
|
|
46408
|
+
this.isStaticPivotInViewport()) {
|
|
46218
46409
|
const formulaId = this.getters.getPivotFormulaId(this.pivotId);
|
|
46219
46410
|
const pivotExample = `=PIVOT(${formulaId})`;
|
|
46220
46411
|
this.alreadyNotified = true;
|
|
@@ -46271,11 +46462,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46271
46462
|
}
|
|
46272
46463
|
}
|
|
46273
46464
|
isDynamicPivotInViewport() {
|
|
46274
|
-
const
|
|
46275
|
-
|
|
46276
|
-
|
|
46277
|
-
|
|
46278
|
-
|
|
46465
|
+
for (const position of this.getters.getVisibleCellPositions()) {
|
|
46466
|
+
const isDynamicPivot = this.getters.isSpillPivotFormula(position);
|
|
46467
|
+
if (isDynamicPivot) {
|
|
46468
|
+
return true;
|
|
46469
|
+
}
|
|
46470
|
+
}
|
|
46471
|
+
return false;
|
|
46472
|
+
}
|
|
46473
|
+
isStaticPivotInViewport() {
|
|
46474
|
+
for (const position of this.getters.getVisibleCellPositions()) {
|
|
46475
|
+
const cell = this.getters.getCell(position);
|
|
46476
|
+
if (cell?.isFormula) {
|
|
46477
|
+
const pivotFunction = getFirstPivotFunction(cell.compiledFormula.tokens);
|
|
46478
|
+
if (pivotFunction && pivotFunction.functionName !== "PIVOT") {
|
|
46279
46479
|
return true;
|
|
46280
46480
|
}
|
|
46281
46481
|
}
|
|
@@ -51694,7 +51894,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51694
51894
|
this.cellPopovers = useStore(CellPopoverStore);
|
|
51695
51895
|
owl.useEffect(() => {
|
|
51696
51896
|
if (!this.sidePanel.isOpen) {
|
|
51697
|
-
this.DOMFocusableElementStore.focus();
|
|
51897
|
+
this.DOMFocusableElementStore.focusableElement?.focus();
|
|
51698
51898
|
}
|
|
51699
51899
|
}, () => [this.sidePanel.isOpen]);
|
|
51700
51900
|
}
|
|
@@ -51900,7 +52100,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51900
52100
|
focusDefaultElement() {
|
|
51901
52101
|
if (!this.env.model.getters.getSelectedFigureId() &&
|
|
51902
52102
|
this.composerFocusStore.activeComposer.editionMode === "inactive") {
|
|
51903
|
-
this.DOMFocusableElementStore.focus();
|
|
52103
|
+
this.DOMFocusableElementStore.focusableElement?.focus();
|
|
51904
52104
|
}
|
|
51905
52105
|
}
|
|
51906
52106
|
get gridEl() {
|
|
@@ -52259,15 +52459,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52259
52459
|
class BasePlugin {
|
|
52260
52460
|
static getters = [];
|
|
52261
52461
|
history;
|
|
52262
|
-
|
|
52263
|
-
canDispatch;
|
|
52264
|
-
constructor(stateObserver, dispatch, canDispatch) {
|
|
52462
|
+
constructor(stateObserver) {
|
|
52265
52463
|
this.history = Object.assign(Object.create(stateObserver), {
|
|
52266
52464
|
update: stateObserver.addChange.bind(stateObserver, this),
|
|
52267
52465
|
selectCell: () => { },
|
|
52268
52466
|
});
|
|
52269
|
-
this.dispatch = dispatch;
|
|
52270
|
-
this.canDispatch = canDispatch;
|
|
52271
52467
|
}
|
|
52272
52468
|
/**
|
|
52273
52469
|
* Export for excel should be available for all plugins, even for the UI.
|
|
@@ -52345,10 +52541,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52345
52541
|
*/
|
|
52346
52542
|
class CorePlugin extends BasePlugin {
|
|
52347
52543
|
getters;
|
|
52544
|
+
dispatch;
|
|
52545
|
+
canDispatch;
|
|
52348
52546
|
constructor({ getters, stateObserver, range, dispatch, canDispatch }) {
|
|
52349
|
-
super(stateObserver
|
|
52547
|
+
super(stateObserver);
|
|
52350
52548
|
range.addRangeProvider(this.adaptRanges.bind(this));
|
|
52351
52549
|
this.getters = getters;
|
|
52550
|
+
this.dispatch = dispatch;
|
|
52551
|
+
this.canDispatch = canDispatch;
|
|
52352
52552
|
}
|
|
52353
52553
|
// ---------------------------------------------------------------------------
|
|
52354
52554
|
// Import/Export
|
|
@@ -52437,10 +52637,34 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52437
52637
|
const elements = [...cmd.elements].sort((a, b) => b - a);
|
|
52438
52638
|
for (const group of groupConsecutive(elements)) {
|
|
52439
52639
|
if (cmd.dimension === "COL") {
|
|
52440
|
-
|
|
52640
|
+
if (group[0] >= this.getters.getNumberCols(cmd.sheetId)) {
|
|
52641
|
+
for (let row = 0; row < this.getters.getNumberRows(cmd.sheetId); row++) {
|
|
52642
|
+
this.history.update("borders", cmd.sheetId, group[0] + 1, row, "vertical", undefined);
|
|
52643
|
+
}
|
|
52644
|
+
}
|
|
52645
|
+
if (group[group.length - 1] === 0) {
|
|
52646
|
+
for (let row = 0; row < this.getters.getNumberRows(cmd.sheetId); row++) {
|
|
52647
|
+
this.history.update("borders", cmd.sheetId, 0, row, "vertical", undefined);
|
|
52648
|
+
}
|
|
52649
|
+
}
|
|
52650
|
+
const zone = this.getters.getColsZone(cmd.sheetId, group[group.length - 1] + 1, group[0]);
|
|
52651
|
+
this.clearInsideBorders(cmd.sheetId, [zone]);
|
|
52652
|
+
this.shiftBordersHorizontally(cmd.sheetId, group[0] + 1, -group.length);
|
|
52441
52653
|
}
|
|
52442
52654
|
else {
|
|
52443
|
-
|
|
52655
|
+
if (group[0] >= this.getters.getNumberRows(cmd.sheetId)) {
|
|
52656
|
+
for (let col = 0; col < this.getters.getNumberCols(cmd.sheetId); col++) {
|
|
52657
|
+
this.history.update("borders", cmd.sheetId, col, group[0] + 1, "horizontal", undefined);
|
|
52658
|
+
}
|
|
52659
|
+
}
|
|
52660
|
+
if (group[group.length - 1] === 0) {
|
|
52661
|
+
for (let col = 0; col < this.getters.getNumberCols(cmd.sheetId); col++) {
|
|
52662
|
+
this.history.update("borders", cmd.sheetId, col, 0, "horizontal", undefined);
|
|
52663
|
+
}
|
|
52664
|
+
}
|
|
52665
|
+
const zone = this.getters.getRowsZone(cmd.sheetId, group[group.length - 1] + 1, group[0]);
|
|
52666
|
+
this.clearInsideBorders(cmd.sheetId, [zone]);
|
|
52667
|
+
this.shiftBordersVertically(cmd.sheetId, group[0] + 1, -group.length);
|
|
52444
52668
|
}
|
|
52445
52669
|
}
|
|
52446
52670
|
break;
|
|
@@ -52747,6 +52971,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52747
52971
|
}
|
|
52748
52972
|
}
|
|
52749
52973
|
}
|
|
52974
|
+
/**
|
|
52975
|
+
* Remove the borders inside of a zone
|
|
52976
|
+
*/
|
|
52977
|
+
clearInsideBorders(sheetId, zones) {
|
|
52978
|
+
for (let zone of zones) {
|
|
52979
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
52980
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
52981
|
+
this.history.update("borders", sheetId, col, row, undefined);
|
|
52982
|
+
}
|
|
52983
|
+
}
|
|
52984
|
+
}
|
|
52985
|
+
}
|
|
52750
52986
|
/**
|
|
52751
52987
|
* Add a border to the existing one to a cell
|
|
52752
52988
|
*/
|
|
@@ -53549,7 +53785,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53549
53785
|
if (fig.tag === "chart") {
|
|
53550
53786
|
const figureIdBase = fig.id.split(FIGURE_ID_SPLITTER).pop();
|
|
53551
53787
|
const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
|
|
53552
|
-
const chart = this.charts[fig.id]?.
|
|
53788
|
+
const chart = this.charts[fig.id]?.duplicateInDuplicatedSheet(cmd.sheetIdTo);
|
|
53553
53789
|
if (chart) {
|
|
53554
53790
|
this.dispatch("CREATE_CHART", {
|
|
53555
53791
|
id: duplicatedFigureId,
|
|
@@ -54193,7 +54429,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
54193
54429
|
case "DUPLICATE_SHEET": {
|
|
54194
54430
|
const rules = deepCopy(this.rules[cmd.sheetId]).map((rule) => ({
|
|
54195
54431
|
...rule,
|
|
54196
|
-
ranges: rule.ranges.map((range) =>
|
|
54432
|
+
ranges: rule.ranges.map((range) => duplicateRangeInDuplicatedSheet(cmd.sheetId, cmd.sheetIdTo, range)),
|
|
54197
54433
|
}));
|
|
54198
54434
|
this.history.update("rules", cmd.sheetIdTo, rules);
|
|
54199
54435
|
break;
|
|
@@ -56242,14 +56478,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
56242
56478
|
return dimension === "COL" ? this.getNumberCols(sheetId) : this.getNumberRows(sheetId);
|
|
56243
56479
|
}
|
|
56244
56480
|
getNextSheetName(baseName = "Sheet") {
|
|
56245
|
-
let i = 1;
|
|
56246
56481
|
const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
|
|
56247
|
-
|
|
56248
|
-
|
|
56249
|
-
|
|
56250
|
-
|
|
56251
|
-
}
|
|
56252
|
-
return name;
|
|
56482
|
+
return getUniqueText(baseName, names, {
|
|
56483
|
+
compute: (name, i) => `${name}${i}`,
|
|
56484
|
+
computeFirstOne: true,
|
|
56485
|
+
});
|
|
56253
56486
|
}
|
|
56254
56487
|
getSheetSize(sheetId) {
|
|
56255
56488
|
return {
|
|
@@ -56529,15 +56762,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
56529
56762
|
this.history.update("sheetIdsMapName", sheetIdsMapName);
|
|
56530
56763
|
}
|
|
56531
56764
|
getDuplicateSheetName(sheetName) {
|
|
56532
|
-
let i = 1;
|
|
56533
56765
|
const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
|
|
56534
56766
|
const baseName = _t("Copy of %s", sheetName);
|
|
56535
|
-
|
|
56536
|
-
while (names.includes(name)) {
|
|
56537
|
-
name = `${baseName} (${i})`;
|
|
56538
|
-
i++;
|
|
56539
|
-
}
|
|
56540
|
-
return name;
|
|
56767
|
+
return getUniqueText(baseName.toString(), names);
|
|
56541
56768
|
}
|
|
56542
56769
|
deleteSheet(sheet) {
|
|
56543
56770
|
const name = sheet.name;
|
|
@@ -58067,15 +58294,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58067
58294
|
}
|
|
58068
58295
|
getNewCustomTableStyleName() {
|
|
58069
58296
|
let name = _t("Custom Table Style");
|
|
58070
|
-
const styleNames =
|
|
58071
|
-
|
|
58072
|
-
return name;
|
|
58073
|
-
}
|
|
58074
|
-
let i = 2;
|
|
58075
|
-
while (styleNames.has(`${name} ${i}`)) {
|
|
58076
|
-
i++;
|
|
58077
|
-
}
|
|
58078
|
-
return `${name} ${i}`;
|
|
58297
|
+
const styleNames = Object.values(this.styles).map((style) => style.displayName);
|
|
58298
|
+
return getUniqueText(name, styleNames, { compute: (name, i) => `${name} ${i}`, start: 2 });
|
|
58079
58299
|
}
|
|
58080
58300
|
isTableStyleEditable(styleId) {
|
|
58081
58301
|
return !TABLE_PRESETS[styleId];
|
|
@@ -58105,24 +58325,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58105
58325
|
}
|
|
58106
58326
|
|
|
58107
58327
|
/**
|
|
58108
|
-
*
|
|
58109
|
-
* They
|
|
58328
|
+
* Core view plugins handle any data derived from core date (i.e. evaluation).
|
|
58329
|
+
* They cannot impact the model data (i.e. cannot dispatch commands).
|
|
58110
58330
|
*/
|
|
58111
|
-
class
|
|
58112
|
-
static layers = [];
|
|
58331
|
+
class CoreViewPlugin extends BasePlugin {
|
|
58113
58332
|
getters;
|
|
58114
|
-
|
|
58115
|
-
|
|
58116
|
-
constructor({ getters, stateObserver, dispatch, canDispatch, uiActions, selection, }) {
|
|
58117
|
-
super(stateObserver, dispatch, canDispatch);
|
|
58333
|
+
constructor({ getters, stateObserver }) {
|
|
58334
|
+
super(stateObserver);
|
|
58118
58335
|
this.getters = getters;
|
|
58119
|
-
this.ui = uiActions;
|
|
58120
|
-
this.selection = selection;
|
|
58121
58336
|
}
|
|
58122
|
-
// ---------------------------------------------------------------------------
|
|
58123
|
-
// Grid rendering
|
|
58124
|
-
// ---------------------------------------------------------------------------
|
|
58125
|
-
drawLayer(ctx, layer) { }
|
|
58126
58337
|
}
|
|
58127
58338
|
|
|
58128
58339
|
/**
|
|
@@ -59817,7 +60028,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59817
60028
|
// as necessary in several iterations, where evaluated cells can trigger the evaluation
|
|
59818
60029
|
// of other cells depending on it, at the next iteration.
|
|
59819
60030
|
//#endregion
|
|
59820
|
-
class EvaluationPlugin extends
|
|
60031
|
+
class EvaluationPlugin extends CoreViewPlugin {
|
|
59821
60032
|
static getters = [
|
|
59822
60033
|
"evaluateFormula",
|
|
59823
60034
|
"evaluateFormulaResult",
|
|
@@ -60084,7 +60295,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60084
60295
|
* This plugins aims to compute and keep to custom colors used in the
|
|
60085
60296
|
* current spreadsheet
|
|
60086
60297
|
*/
|
|
60087
|
-
class CustomColorsPlugin extends
|
|
60298
|
+
class CustomColorsPlugin extends CoreViewPlugin {
|
|
60088
60299
|
customColors = {};
|
|
60089
60300
|
shouldUpdateColors = true;
|
|
60090
60301
|
static getters = ["getCustomColors"];
|
|
@@ -60220,7 +60431,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60220
60431
|
}
|
|
60221
60432
|
}
|
|
60222
60433
|
|
|
60223
|
-
class EvaluationChartPlugin extends
|
|
60434
|
+
class EvaluationChartPlugin extends CoreViewPlugin {
|
|
60224
60435
|
static getters = ["getChartRuntime", "getStyleOfSingleCellChart"];
|
|
60225
60436
|
charts = {};
|
|
60226
60437
|
createRuntimeChart = chartRuntimeFactory(this.getters);
|
|
@@ -60324,7 +60535,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60324
60535
|
}
|
|
60325
60536
|
}
|
|
60326
60537
|
|
|
60327
|
-
class EvaluationConditionalFormatPlugin extends
|
|
60538
|
+
class EvaluationConditionalFormatPlugin extends CoreViewPlugin {
|
|
60328
60539
|
static getters = [
|
|
60329
60540
|
"getConditionalIcon",
|
|
60330
60541
|
"getCellConditionalFormatStyle",
|
|
@@ -60642,7 +60853,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60642
60853
|
}
|
|
60643
60854
|
|
|
60644
60855
|
const VALID_RESULT = { isValid: true };
|
|
60645
|
-
class EvaluationDataValidationPlugin extends
|
|
60856
|
+
class EvaluationDataValidationPlugin extends CoreViewPlugin {
|
|
60646
60857
|
static getters = [
|
|
60647
60858
|
"getDataValidationInvalidCriterionValueMessage",
|
|
60648
60859
|
"getInvalidDataValidationMessage",
|
|
@@ -60773,7 +60984,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60773
60984
|
}
|
|
60774
60985
|
}
|
|
60775
60986
|
|
|
60776
|
-
class DynamicTablesPlugin extends
|
|
60987
|
+
class DynamicTablesPlugin extends CoreViewPlugin {
|
|
60777
60988
|
static getters = [
|
|
60778
60989
|
"canCreateDynamicTableOnZones",
|
|
60779
60990
|
"doesZonesContainFilter",
|
|
@@ -60947,7 +61158,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60947
61158
|
}
|
|
60948
61159
|
}
|
|
60949
61160
|
|
|
60950
|
-
class HeaderSizeUIPlugin extends
|
|
61161
|
+
class HeaderSizeUIPlugin extends CoreViewPlugin {
|
|
60951
61162
|
static getters = ["getRowSize", "getHeaderSize"];
|
|
60952
61163
|
tallestCellInRow = {};
|
|
60953
61164
|
ctx = document.createElement("canvas").getContext("2d");
|
|
@@ -61653,7 +61864,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61653
61864
|
function isPivotCommand(cmd) {
|
|
61654
61865
|
return UNDO_REDO_PIVOT_COMMANDS.includes(cmd.type);
|
|
61655
61866
|
}
|
|
61656
|
-
class PivotUIPlugin extends
|
|
61867
|
+
class PivotUIPlugin extends CoreViewPlugin {
|
|
61657
61868
|
static getters = [
|
|
61658
61869
|
"getPivot",
|
|
61659
61870
|
"getFirstPivotFunction",
|
|
@@ -61857,13 +62068,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61857
62068
|
}
|
|
61858
62069
|
generateNewCalculatedMeasureName(measures) {
|
|
61859
62070
|
const existingMeasures = measures.map((m) => m.fieldName);
|
|
61860
|
-
|
|
61861
|
-
|
|
61862
|
-
|
|
61863
|
-
i++;
|
|
61864
|
-
name = _t("Calculated measure %s", i);
|
|
61865
|
-
}
|
|
61866
|
-
return name;
|
|
62071
|
+
return getUniqueText(_t("Calculated measure 1"), existingMeasures, {
|
|
62072
|
+
compute: (name, i) => _t("Calculated measure %s", i),
|
|
62073
|
+
});
|
|
61867
62074
|
}
|
|
61868
62075
|
getPivot(pivotId) {
|
|
61869
62076
|
if (!this.getters.isExistingPivot(pivotId)) {
|
|
@@ -61917,6 +62124,31 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61917
62124
|
}
|
|
61918
62125
|
}
|
|
61919
62126
|
|
|
62127
|
+
/**
|
|
62128
|
+
* UI plugins handle any transient data required to display a spreadsheet.
|
|
62129
|
+
* They can draw on the grid canvas.
|
|
62130
|
+
*/
|
|
62131
|
+
class UIPlugin extends BasePlugin {
|
|
62132
|
+
static layers = [];
|
|
62133
|
+
getters;
|
|
62134
|
+
ui;
|
|
62135
|
+
selection;
|
|
62136
|
+
dispatch;
|
|
62137
|
+
canDispatch;
|
|
62138
|
+
constructor({ getters, stateObserver, dispatch, canDispatch, uiActions, selection, }) {
|
|
62139
|
+
super(stateObserver);
|
|
62140
|
+
this.getters = getters;
|
|
62141
|
+
this.ui = uiActions;
|
|
62142
|
+
this.selection = selection;
|
|
62143
|
+
this.dispatch = dispatch;
|
|
62144
|
+
this.canDispatch = canDispatch;
|
|
62145
|
+
}
|
|
62146
|
+
// ---------------------------------------------------------------------------
|
|
62147
|
+
// Grid rendering
|
|
62148
|
+
// ---------------------------------------------------------------------------
|
|
62149
|
+
drawLayer(ctx, layer) { }
|
|
62150
|
+
}
|
|
62151
|
+
|
|
61920
62152
|
/**
|
|
61921
62153
|
* This plugin manage the autofill.
|
|
61922
62154
|
*
|
|
@@ -63943,6 +64175,19 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63943
64175
|
|
|
63944
64176
|
class InsertPivotPlugin extends UIPlugin {
|
|
63945
64177
|
static getters = [];
|
|
64178
|
+
allowDispatch(cmd) {
|
|
64179
|
+
switch (cmd.type) {
|
|
64180
|
+
case "DUPLICATE_PIVOT_IN_NEW_SHEET":
|
|
64181
|
+
if (!this.getters.isExistingPivot(cmd.pivotId)) {
|
|
64182
|
+
return "PivotIdNotFound" /* CommandResult.PivotIdNotFound */;
|
|
64183
|
+
}
|
|
64184
|
+
if (!this.getters.getPivot(cmd.pivotId).isValid()) {
|
|
64185
|
+
return "PivotInError" /* CommandResult.PivotInError */;
|
|
64186
|
+
}
|
|
64187
|
+
break;
|
|
64188
|
+
}
|
|
64189
|
+
return "Success" /* CommandResult.Success */;
|
|
64190
|
+
}
|
|
63946
64191
|
handle(cmd) {
|
|
63947
64192
|
switch (cmd.type) {
|
|
63948
64193
|
case "INSERT_NEW_PIVOT":
|
|
@@ -64016,15 +64261,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
64016
64261
|
}
|
|
64017
64262
|
}
|
|
64018
64263
|
getPivotDuplicateSheetName(pivotName) {
|
|
64019
|
-
let i = 1;
|
|
64020
64264
|
const names = this.getters.getSheetIds().map((id) => this.getters.getSheetName(id));
|
|
64021
64265
|
const sanitizedName = sanitizeSheetName(pivotName);
|
|
64022
|
-
|
|
64023
|
-
while (names.includes(name)) {
|
|
64024
|
-
name = `${sanitizedName} (${i})`;
|
|
64025
|
-
i++;
|
|
64026
|
-
}
|
|
64027
|
-
return name;
|
|
64266
|
+
return getUniqueText(sanitizedName, names);
|
|
64028
64267
|
}
|
|
64029
64268
|
insertPivotWithTable(sheetId, col, row, pivotId, table, mode) {
|
|
64030
64269
|
const { cols, rows, measures, fieldsType } = table;
|
|
@@ -66131,13 +66370,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
66131
66370
|
if (!colName) {
|
|
66132
66371
|
colName = `Column${colIndex}`;
|
|
66133
66372
|
}
|
|
66134
|
-
|
|
66135
|
-
|
|
66136
|
-
|
|
66137
|
-
|
|
66138
|
-
i++;
|
|
66139
|
-
}
|
|
66140
|
-
return currentColName;
|
|
66373
|
+
return getUniqueText(colName, usedColNames, {
|
|
66374
|
+
compute: (name, i) => colName + String(i),
|
|
66375
|
+
start: 2,
|
|
66376
|
+
});
|
|
66141
66377
|
}
|
|
66142
66378
|
}
|
|
66143
66379
|
|
|
@@ -68179,11 +68415,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
68179
68415
|
editionState = "initializing";
|
|
68180
68416
|
DOMFocusableElementStore;
|
|
68181
68417
|
setup() {
|
|
68182
|
-
owl.onMounted(() => {
|
|
68183
|
-
if (this.isSheetActive) {
|
|
68184
|
-
this.scrollToSheet();
|
|
68185
|
-
}
|
|
68186
|
-
});
|
|
68187
68418
|
owl.onPatched(() => {
|
|
68188
68419
|
if (this.sheetNameRef.el && this.state.isEditing && this.editionState === "initializing") {
|
|
68189
68420
|
this.editionState = "editing";
|
|
@@ -68192,6 +68423,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
68192
68423
|
});
|
|
68193
68424
|
this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
|
|
68194
68425
|
owl.useExternalListener(window, "click", () => (this.state.pickerOpened = false));
|
|
68426
|
+
owl.useEffect((sheetId) => {
|
|
68427
|
+
if (this.props.sheetId === sheetId) {
|
|
68428
|
+
this.scrollToSheet();
|
|
68429
|
+
}
|
|
68430
|
+
}, () => [this.env.model.getters.getActiveSheetId()]);
|
|
68195
68431
|
}
|
|
68196
68432
|
focusInputAndSelectContent() {
|
|
68197
68433
|
if (!this.state.isEditing || !this.sheetNameRef.el)
|
|
@@ -68203,7 +68439,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
68203
68439
|
}
|
|
68204
68440
|
}
|
|
68205
68441
|
scrollToSheet() {
|
|
68206
|
-
this.sheetDivRef.el?.scrollIntoView?.(
|
|
68442
|
+
this.sheetDivRef.el?.scrollIntoView?.({
|
|
68443
|
+
behavior: "smooth",
|
|
68444
|
+
inline: "nearest",
|
|
68445
|
+
});
|
|
68207
68446
|
}
|
|
68208
68447
|
onFocusOut() {
|
|
68209
68448
|
if (this.state.isEditing && this.editionState !== "initializing") {
|
|
@@ -68233,11 +68472,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
68233
68472
|
if (ev.key === "Enter") {
|
|
68234
68473
|
ev.preventDefault();
|
|
68235
68474
|
this.stopEdition();
|
|
68236
|
-
this.DOMFocusableElementStore.focus();
|
|
68475
|
+
this.DOMFocusableElementStore.focusableElement?.focus();
|
|
68237
68476
|
}
|
|
68238
68477
|
if (ev.key === "Escape") {
|
|
68239
68478
|
this.cancelEdition();
|
|
68240
|
-
this.DOMFocusableElementStore.focus();
|
|
68479
|
+
this.DOMFocusableElementStore.focusableElement?.focus();
|
|
68241
68480
|
}
|
|
68242
68481
|
}
|
|
68243
68482
|
onMouseEventSheetName(ev) {
|
|
@@ -68786,23 +69025,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
68786
69025
|
const cells = [];
|
|
68787
69026
|
const getters = this.getters;
|
|
68788
69027
|
const sheetId = getters.getActiveSheetId();
|
|
68789
|
-
for (const
|
|
68790
|
-
|
|
68791
|
-
|
|
68792
|
-
|
|
68793
|
-
continue;
|
|
68794
|
-
}
|
|
68795
|
-
const action = this.getClickableAction(position);
|
|
68796
|
-
if (!action) {
|
|
68797
|
-
continue;
|
|
68798
|
-
}
|
|
68799
|
-
const zone = getters.expandZone(sheetId, positionToZone(position));
|
|
68800
|
-
cells.push({
|
|
68801
|
-
coordinates: getters.getVisibleRect(zone),
|
|
68802
|
-
position,
|
|
68803
|
-
action,
|
|
68804
|
-
});
|
|
69028
|
+
for (const position of this.getters.getVisibleCellPositions()) {
|
|
69029
|
+
const action = this.getClickableAction(position);
|
|
69030
|
+
if (!action) {
|
|
69031
|
+
continue;
|
|
68805
69032
|
}
|
|
69033
|
+
const zone = getters.expandZone(sheetId, positionToZone(position));
|
|
69034
|
+
cells.push({
|
|
69035
|
+
coordinates: getters.getVisibleRect(zone),
|
|
69036
|
+
position,
|
|
69037
|
+
action,
|
|
69038
|
+
});
|
|
68806
69039
|
}
|
|
68807
69040
|
return cells;
|
|
68808
69041
|
}
|
|
@@ -73613,7 +73846,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
73613
73846
|
if (content || styleId || formatId || borderId || value !== undefined) {
|
|
73614
73847
|
const attributes = [["r", xc]];
|
|
73615
73848
|
// style
|
|
73616
|
-
const id = normalizeStyle(construct, extractStyle(data, styleId, formatId, borderId));
|
|
73849
|
+
const id = normalizeStyle(construct, extractStyle(data, content, styleId, formatId, borderId));
|
|
73617
73850
|
// don't add style if default
|
|
73618
73851
|
if (id) {
|
|
73619
73852
|
attributes.push(["s", id]);
|
|
@@ -73967,7 +74200,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
73967
74200
|
["count", strings.length],
|
|
73968
74201
|
["uniqueCount", strings.length],
|
|
73969
74202
|
];
|
|
73970
|
-
const stringNodes = strings.map((string) =>
|
|
74203
|
+
const stringNodes = strings.map((string) => {
|
|
74204
|
+
if (string.trim() !== string) {
|
|
74205
|
+
return escapeXml /*xml*/ `<si><t xml:space="preserve">${string}</t></si>`;
|
|
74206
|
+
}
|
|
74207
|
+
return escapeXml /*xml*/ `<si><t>${string}</t></si>`;
|
|
74208
|
+
});
|
|
73971
74209
|
const xml = escapeXml /*xml*/ `
|
|
73972
74210
|
<sst ${formatAttributes(namespaces)}>
|
|
73973
74211
|
${joinXmlNodes(stringNodes)}
|
|
@@ -74048,14 +74286,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
74048
74286
|
*/
|
|
74049
74287
|
function fixLengthySheetNames(data) {
|
|
74050
74288
|
const nameMapping = {};
|
|
74051
|
-
const newNames =
|
|
74289
|
+
const newNames = [];
|
|
74052
74290
|
for (const sheet of data.sheets) {
|
|
74053
74291
|
let newName = sheet.name.slice(0, 31);
|
|
74054
|
-
|
|
74055
|
-
|
|
74056
|
-
|
|
74057
|
-
|
|
74058
|
-
newNames.add(newName);
|
|
74292
|
+
newName = getUniqueText(newName, newNames, {
|
|
74293
|
+
compute: (name, i) => name.slice(0, 31 - String(i).length) + i,
|
|
74294
|
+
});
|
|
74295
|
+
newNames.push(newName);
|
|
74059
74296
|
if (newName !== sheet.name) {
|
|
74060
74297
|
nameMapping[sheet.name] = newName;
|
|
74061
74298
|
sheet.name = newName;
|
|
@@ -74120,6 +74357,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
74120
74357
|
*/
|
|
74121
74358
|
config;
|
|
74122
74359
|
corePluginConfig;
|
|
74360
|
+
coreViewPluginConfig;
|
|
74123
74361
|
uiPluginConfig;
|
|
74124
74362
|
state;
|
|
74125
74363
|
selection;
|
|
@@ -74172,6 +74410,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
74172
74410
|
this.coreHandlers.push(this.range);
|
|
74173
74411
|
this.handlers.push(this.range);
|
|
74174
74412
|
this.corePluginConfig = this.setupCorePluginConfig();
|
|
74413
|
+
this.coreViewPluginConfig = this.setupCoreViewPluginConfig();
|
|
74175
74414
|
this.uiPluginConfig = this.setupUiPluginConfig();
|
|
74176
74415
|
// registering plugins
|
|
74177
74416
|
for (let Plugin of corePluginRegistry.getAll()) {
|
|
@@ -74180,7 +74419,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
74180
74419
|
Object.assign(this.getters, this.coreGetters);
|
|
74181
74420
|
this.session.loadInitialMessages(stateUpdateMessages);
|
|
74182
74421
|
for (let Plugin of coreViewsPluginRegistry.getAll()) {
|
|
74183
|
-
const plugin = this.
|
|
74422
|
+
const plugin = this.setupCoreViewPlugin(Plugin);
|
|
74184
74423
|
this.handlers.push(plugin);
|
|
74185
74424
|
this.uiHandlers.push(plugin);
|
|
74186
74425
|
this.coreHandlers.push(plugin);
|
|
@@ -74207,7 +74446,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
74207
74446
|
// events
|
|
74208
74447
|
this.setupSessionEvents();
|
|
74209
74448
|
this.joinSession();
|
|
74210
|
-
if (config.snapshotRequested) {
|
|
74449
|
+
if (config.snapshotRequested || (data["[Content_Types].xml"] && !this.getters.isReadonly())) {
|
|
74211
74450
|
const startSnapshot = performance.now();
|
|
74212
74451
|
console.debug("Snapshot requested");
|
|
74213
74452
|
this.session.snapshot(this.exportData());
|
|
@@ -74246,6 +74485,19 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
74246
74485
|
}
|
|
74247
74486
|
return plugin;
|
|
74248
74487
|
}
|
|
74488
|
+
setupCoreViewPlugin(Plugin) {
|
|
74489
|
+
const plugin = new Plugin(this.coreViewPluginConfig);
|
|
74490
|
+
for (let name of Plugin.getters) {
|
|
74491
|
+
if (!(name in plugin)) {
|
|
74492
|
+
throw new Error(`Invalid getter name: ${name} for plugin ${plugin.constructor}`);
|
|
74493
|
+
}
|
|
74494
|
+
if (name in this.getters) {
|
|
74495
|
+
throw new Error(`Getter "${name}" is already defined.`);
|
|
74496
|
+
}
|
|
74497
|
+
this.getters[name] = plugin[name].bind(plugin);
|
|
74498
|
+
}
|
|
74499
|
+
return plugin;
|
|
74500
|
+
}
|
|
74249
74501
|
/**
|
|
74250
74502
|
* Initialize and properly configure a plugin.
|
|
74251
74503
|
*
|
|
@@ -74347,6 +74599,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
74347
74599
|
external: this.config.external,
|
|
74348
74600
|
};
|
|
74349
74601
|
}
|
|
74602
|
+
setupCoreViewPluginConfig() {
|
|
74603
|
+
return {
|
|
74604
|
+
getters: this.getters,
|
|
74605
|
+
stateObserver: this.state,
|
|
74606
|
+
selection: this.selection,
|
|
74607
|
+
moveClient: this.session.move.bind(this.session),
|
|
74608
|
+
custom: this.config.custom,
|
|
74609
|
+
uiActions: this.config,
|
|
74610
|
+
session: this.session,
|
|
74611
|
+
defaultCurrency: this.config.defaultCurrency,
|
|
74612
|
+
customColors: this.config.customColors || [],
|
|
74613
|
+
external: this.config.external,
|
|
74614
|
+
};
|
|
74615
|
+
}
|
|
74350
74616
|
setupUiPluginConfig() {
|
|
74351
74617
|
return {
|
|
74352
74618
|
getters: this.getters,
|
|
@@ -74694,6 +74960,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
74694
74960
|
areDomainArgsFieldsValid,
|
|
74695
74961
|
splitReference,
|
|
74696
74962
|
sanitizeSheetName,
|
|
74963
|
+
getUniqueText,
|
|
74964
|
+
isNumber,
|
|
74965
|
+
isDateTime,
|
|
74697
74966
|
};
|
|
74698
74967
|
const links = {
|
|
74699
74968
|
isMarkdownLink,
|
|
@@ -74790,6 +75059,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
74790
75059
|
exports.AbstractFigureClipboardHandler = AbstractFigureClipboardHandler;
|
|
74791
75060
|
exports.CellErrorType = CellErrorType;
|
|
74792
75061
|
exports.CorePlugin = CorePlugin;
|
|
75062
|
+
exports.CoreViewPlugin = CoreViewPlugin;
|
|
74793
75063
|
exports.DispatchResult = DispatchResult;
|
|
74794
75064
|
exports.EvaluationError = EvaluationError;
|
|
74795
75065
|
exports.Model = Model;
|
|
@@ -74832,9 +75102,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
74832
75102
|
exports.tokenize = tokenize;
|
|
74833
75103
|
|
|
74834
75104
|
|
|
74835
|
-
__info__.version = "18.2.0-alpha.
|
|
74836
|
-
__info__.date = "
|
|
74837
|
-
__info__.hash = "
|
|
75105
|
+
__info__.version = "18.2.0-alpha.2";
|
|
75106
|
+
__info__.date = "2025-01-15T08:06:32.137Z";
|
|
75107
|
+
__info__.hash = "4f96c47";
|
|
74838
75108
|
|
|
74839
75109
|
|
|
74840
75110
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|