@odoo/o-spreadsheet 18.3.1 → 18.3.3
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 +695 -137
- package/dist/o-spreadsheet.d.ts +278 -164
- package/dist/o-spreadsheet.esm.js +695 -137
- package/dist/o-spreadsheet.iife.js +695 -137
- package/dist/o-spreadsheet.iife.min.js +419 -383
- package/dist/o_spreadsheet.xml +64 -16
- package/package.json +1 -1
|
@@ -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.3.
|
|
6
|
-
* @date 2025-05-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.3.3
|
|
6
|
+
* @date 2025-05-13T17:54:43.312Z
|
|
7
|
+
* @hash b79924a
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -3321,7 +3321,7 @@ function isDateAfter(date, dateAfter) {
|
|
|
3321
3321
|
*/
|
|
3322
3322
|
const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSeparator) {
|
|
3323
3323
|
decimalSeparator = escapeRegExp(decimalSeparator);
|
|
3324
|
-
return new RegExp(`(?:^-?\\d+(?:${decimalSeparator}?\\d*(?:e
|
|
3324
|
+
return new RegExp(`(?:^-?\\d+(?:${decimalSeparator}?\\d*(?:e(\\+|-)?\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
|
|
3325
3325
|
});
|
|
3326
3326
|
const getNumberRegex = memoize(function getNumberRegex(locale) {
|
|
3327
3327
|
const decimalSeparator = escapeRegExp(locale.decimalSeparator);
|
|
@@ -6002,6 +6002,67 @@ function scrollDelay(value) {
|
|
|
6002
6002
|
return MIN_DELAY + (MAX_DELAY - MIN_DELAY) * Math.exp(-ACCELERATION * (value - 1));
|
|
6003
6003
|
}
|
|
6004
6004
|
|
|
6005
|
+
function createDefaultRows(rowNumber) {
|
|
6006
|
+
const rows = [];
|
|
6007
|
+
for (let i = 0; i < rowNumber; i++) {
|
|
6008
|
+
const row = {
|
|
6009
|
+
cells: {},
|
|
6010
|
+
};
|
|
6011
|
+
rows.push(row);
|
|
6012
|
+
}
|
|
6013
|
+
return rows;
|
|
6014
|
+
}
|
|
6015
|
+
function moveHeaderIndexesOnHeaderAddition(indexHeaderAdded, numberAdded, headers) {
|
|
6016
|
+
return headers.map((header) => {
|
|
6017
|
+
if (header >= indexHeaderAdded) {
|
|
6018
|
+
return header + numberAdded;
|
|
6019
|
+
}
|
|
6020
|
+
return header;
|
|
6021
|
+
});
|
|
6022
|
+
}
|
|
6023
|
+
function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
|
|
6024
|
+
deletedHeaders = [...deletedHeaders].sort((a, b) => b - a);
|
|
6025
|
+
return headers
|
|
6026
|
+
.map((header) => {
|
|
6027
|
+
for (const deletedHeader of deletedHeaders) {
|
|
6028
|
+
if (header > deletedHeader) {
|
|
6029
|
+
header--;
|
|
6030
|
+
}
|
|
6031
|
+
else if (header === deletedHeader) {
|
|
6032
|
+
return undefined;
|
|
6033
|
+
}
|
|
6034
|
+
}
|
|
6035
|
+
return header;
|
|
6036
|
+
})
|
|
6037
|
+
.filter(isDefined);
|
|
6038
|
+
}
|
|
6039
|
+
function getNextSheetName(existingNames, baseName = "Sheet") {
|
|
6040
|
+
let i = 1;
|
|
6041
|
+
let name = `${baseName}${i}`;
|
|
6042
|
+
while (existingNames.includes(name)) {
|
|
6043
|
+
name = `${baseName}${i}`;
|
|
6044
|
+
i++;
|
|
6045
|
+
}
|
|
6046
|
+
return name;
|
|
6047
|
+
}
|
|
6048
|
+
function getDuplicateSheetName(nameToDuplicate, existingNames) {
|
|
6049
|
+
let i = 1;
|
|
6050
|
+
const baseName = _t("Copy of %s", nameToDuplicate);
|
|
6051
|
+
let name = baseName.toString();
|
|
6052
|
+
while (existingNames.includes(name)) {
|
|
6053
|
+
name = `${baseName} (${i})`;
|
|
6054
|
+
i++;
|
|
6055
|
+
}
|
|
6056
|
+
return name;
|
|
6057
|
+
}
|
|
6058
|
+
function isSheetNameEqual(name1, name2) {
|
|
6059
|
+
if (name1 === undefined || name2 === undefined) {
|
|
6060
|
+
return false;
|
|
6061
|
+
}
|
|
6062
|
+
return (getUnquotedSheetName(name1.trim().toUpperCase()) ===
|
|
6063
|
+
getUnquotedSheetName(name2.trim().toUpperCase()));
|
|
6064
|
+
}
|
|
6065
|
+
|
|
6005
6066
|
function createRange(args, getSheetSize) {
|
|
6006
6067
|
const unboundedZone = args.zone;
|
|
6007
6068
|
const zone = boundUnboundedZone(unboundedZone, getSheetSize(args.sheetId));
|
|
@@ -6292,7 +6353,7 @@ function getApplyRangeChangeRemoveColRow(cmd) {
|
|
|
6292
6353
|
elements.sort((a, b) => b - a);
|
|
6293
6354
|
const groups = groupConsecutive(elements);
|
|
6294
6355
|
return (range) => {
|
|
6295
|
-
if (range.sheetId
|
|
6356
|
+
if (!isSheetNameEqual(range.sheetId, cmd.sheetId)) {
|
|
6296
6357
|
return { changeType: "NONE" };
|
|
6297
6358
|
}
|
|
6298
6359
|
let newRange = range;
|
|
@@ -6499,41 +6560,6 @@ function fuzzyLookup(pattern, list, fn) {
|
|
|
6499
6560
|
return results.map((r) => r.elem);
|
|
6500
6561
|
}
|
|
6501
6562
|
|
|
6502
|
-
function createDefaultRows(rowNumber) {
|
|
6503
|
-
const rows = [];
|
|
6504
|
-
for (let i = 0; i < rowNumber; i++) {
|
|
6505
|
-
const row = {
|
|
6506
|
-
cells: {},
|
|
6507
|
-
};
|
|
6508
|
-
rows.push(row);
|
|
6509
|
-
}
|
|
6510
|
-
return rows;
|
|
6511
|
-
}
|
|
6512
|
-
function moveHeaderIndexesOnHeaderAddition(indexHeaderAdded, numberAdded, headers) {
|
|
6513
|
-
return headers.map((header) => {
|
|
6514
|
-
if (header >= indexHeaderAdded) {
|
|
6515
|
-
return header + numberAdded;
|
|
6516
|
-
}
|
|
6517
|
-
return header;
|
|
6518
|
-
});
|
|
6519
|
-
}
|
|
6520
|
-
function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
|
|
6521
|
-
deletedHeaders = [...deletedHeaders].sort((a, b) => b - a);
|
|
6522
|
-
return headers
|
|
6523
|
-
.map((header) => {
|
|
6524
|
-
for (const deletedHeader of deletedHeaders) {
|
|
6525
|
-
if (header > deletedHeader) {
|
|
6526
|
-
header--;
|
|
6527
|
-
}
|
|
6528
|
-
else if (header === deletedHeader) {
|
|
6529
|
-
return undefined;
|
|
6530
|
-
}
|
|
6531
|
-
}
|
|
6532
|
-
return header;
|
|
6533
|
-
})
|
|
6534
|
-
.filter(isDefined);
|
|
6535
|
-
}
|
|
6536
|
-
|
|
6537
6563
|
function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
|
|
6538
6564
|
return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
|
|
6539
6565
|
}
|
|
@@ -8275,6 +8301,25 @@ const monthNumberAdapter = {
|
|
|
8275
8301
|
return `${normalizedValue}`;
|
|
8276
8302
|
},
|
|
8277
8303
|
};
|
|
8304
|
+
/**
|
|
8305
|
+
* normalizes month number + year
|
|
8306
|
+
*/
|
|
8307
|
+
const monthAdapter = {
|
|
8308
|
+
normalizeFunctionValue(value) {
|
|
8309
|
+
const date = toNumber(value, DEFAULT_LOCALE);
|
|
8310
|
+
return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/yyyy" });
|
|
8311
|
+
},
|
|
8312
|
+
toValueAndFormat(normalizedValue) {
|
|
8313
|
+
return {
|
|
8314
|
+
value: toNumber(normalizedValue, DEFAULT_LOCALE),
|
|
8315
|
+
format: "mmmm yyyy",
|
|
8316
|
+
};
|
|
8317
|
+
},
|
|
8318
|
+
toFunctionValue(normalizedValue) {
|
|
8319
|
+
const jsDate = toJsDate(normalizedValue, DEFAULT_LOCALE);
|
|
8320
|
+
return `DATE(${jsDate.getFullYear()},${jsDate.getMonth() + 1},1)`;
|
|
8321
|
+
},
|
|
8322
|
+
};
|
|
8278
8323
|
/**
|
|
8279
8324
|
* normalizes quarter number
|
|
8280
8325
|
*/
|
|
@@ -8410,6 +8455,7 @@ pivotTimeAdapterRegistry
|
|
|
8410
8455
|
.add("day_of_month", nullHandlerDecorator(dayOfMonthAdapter))
|
|
8411
8456
|
.add("iso_week_number", nullHandlerDecorator(isoWeekNumberAdapter))
|
|
8412
8457
|
.add("month_number", nullHandlerDecorator(monthNumberAdapter))
|
|
8458
|
+
.add("month", nullHandlerDecorator(monthAdapter))
|
|
8413
8459
|
.add("quarter_number", nullHandlerDecorator(quarterNumberAdapter))
|
|
8414
8460
|
.add("day_of_week", nullHandlerDecorator(dayOfWeekAdapter))
|
|
8415
8461
|
.add("hour_number", nullHandlerDecorator(hourNumberAdapter))
|
|
@@ -8426,10 +8472,9 @@ const AGGREGATOR_NAMES = {
|
|
|
8426
8472
|
avg: _t("Average"),
|
|
8427
8473
|
sum: _t("Sum"),
|
|
8428
8474
|
};
|
|
8429
|
-
const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
|
|
8430
8475
|
const AGGREGATORS_BY_FIELD_TYPE = {
|
|
8431
|
-
integer:
|
|
8432
|
-
char:
|
|
8476
|
+
integer: ["max", "min", "avg", "sum", "count_distinct", "count"],
|
|
8477
|
+
char: ["count_distinct", "count"],
|
|
8433
8478
|
boolean: ["count_distinct", "count", "bool_and", "bool_or"],
|
|
8434
8479
|
datetime: ["max", "min", "count_distinct", "count"],
|
|
8435
8480
|
};
|
|
@@ -8590,10 +8635,7 @@ function toNormalizedPivotValue(dimension, groupValue) {
|
|
|
8590
8635
|
return normalizer(groupValueString, dimension.granularity);
|
|
8591
8636
|
}
|
|
8592
8637
|
function normalizeDateTime(value, granularity) {
|
|
8593
|
-
|
|
8594
|
-
throw new Error("Missing granularity");
|
|
8595
|
-
}
|
|
8596
|
-
return pivotTimeAdapter(granularity).normalizeFunctionValue(value);
|
|
8638
|
+
return pivotTimeAdapter(granularity ?? "month").normalizeFunctionValue(value);
|
|
8597
8639
|
}
|
|
8598
8640
|
function toFunctionPivotValue(value, dimension) {
|
|
8599
8641
|
if (value === null) {
|
|
@@ -8605,10 +8647,7 @@ function toFunctionPivotValue(value, dimension) {
|
|
|
8605
8647
|
return pivotToFunctionValueRegistry.get(dimension.type)(value, dimension.granularity);
|
|
8606
8648
|
}
|
|
8607
8649
|
function toFunctionValueDateTime(value, granularity) {
|
|
8608
|
-
|
|
8609
|
-
throw new Error("Missing granularity");
|
|
8610
|
-
}
|
|
8611
|
-
return pivotTimeAdapter(granularity).toFunctionValue(value);
|
|
8650
|
+
return pivotTimeAdapter(granularity ?? "month").toFunctionValue(value);
|
|
8612
8651
|
}
|
|
8613
8652
|
const pivotNormalizationValueRegistry = new Registry();
|
|
8614
8653
|
pivotNormalizationValueRegistry
|
|
@@ -9803,7 +9842,10 @@ function proxifyStoreMutation(store, callback) {
|
|
|
9803
9842
|
const functionProxy = new Proxy(value, {
|
|
9804
9843
|
// trap the function call
|
|
9805
9844
|
apply(target, thisArg, argArray) {
|
|
9806
|
-
Reflect.apply(target, thisStore, argArray);
|
|
9845
|
+
const res = Reflect.apply(target, thisStore, argArray);
|
|
9846
|
+
if (res === "noStateChange") {
|
|
9847
|
+
return;
|
|
9848
|
+
}
|
|
9807
9849
|
callback();
|
|
9808
9850
|
},
|
|
9809
9851
|
});
|
|
@@ -9825,7 +9867,7 @@ function getDependencyContainer(env) {
|
|
|
9825
9867
|
const ModelStore = createAbstractStore("Model");
|
|
9826
9868
|
|
|
9827
9869
|
class RendererStore {
|
|
9828
|
-
mutators = ["register", "unRegister"];
|
|
9870
|
+
mutators = ["register", "unRegister", "drawLayer"];
|
|
9829
9871
|
renderers = {};
|
|
9830
9872
|
register(renderer) {
|
|
9831
9873
|
if (!renderer.renderingLayers.length) {
|
|
@@ -9845,14 +9887,14 @@ class RendererStore {
|
|
|
9845
9887
|
}
|
|
9846
9888
|
drawLayer(context, layer) {
|
|
9847
9889
|
const renderers = this.renderers[layer];
|
|
9848
|
-
if (
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9854
|
-
context.ctx.restore();
|
|
9890
|
+
if (renderers) {
|
|
9891
|
+
for (const renderer of renderers) {
|
|
9892
|
+
context.ctx.save();
|
|
9893
|
+
renderer.drawLayer(context, layer);
|
|
9894
|
+
context.ctx.restore();
|
|
9895
|
+
}
|
|
9855
9896
|
}
|
|
9897
|
+
return "noStateChange";
|
|
9856
9898
|
}
|
|
9857
9899
|
}
|
|
9858
9900
|
|
|
@@ -9905,16 +9947,17 @@ class ComposerFocusStore extends SpreadsheetStore {
|
|
|
9905
9947
|
focusComposer(listener, args) {
|
|
9906
9948
|
this.activeComposer = listener;
|
|
9907
9949
|
if (this.getters.isReadonly()) {
|
|
9908
|
-
return;
|
|
9950
|
+
return "noStateChange";
|
|
9909
9951
|
}
|
|
9910
9952
|
this._focusMode = args.focusMode || "contentFocus";
|
|
9911
9953
|
if (this._focusMode !== "inactive") {
|
|
9912
9954
|
this.setComposerContent(args);
|
|
9913
9955
|
}
|
|
9956
|
+
return;
|
|
9914
9957
|
}
|
|
9915
9958
|
focusActiveComposer(args) {
|
|
9916
9959
|
if (this.getters.isReadonly()) {
|
|
9917
|
-
return;
|
|
9960
|
+
return "noStateChange";
|
|
9918
9961
|
}
|
|
9919
9962
|
if (!this.activeComposer) {
|
|
9920
9963
|
throw new Error("No composer is registered");
|
|
@@ -9923,6 +9966,7 @@ class ComposerFocusStore extends SpreadsheetStore {
|
|
|
9923
9966
|
if (this._focusMode !== "inactive") {
|
|
9924
9967
|
this.setComposerContent(args);
|
|
9925
9968
|
}
|
|
9969
|
+
return;
|
|
9926
9970
|
}
|
|
9927
9971
|
/**
|
|
9928
9972
|
* Start the edition or update the content if it's already started.
|
|
@@ -10082,20 +10126,24 @@ function getElementMargins(el) {
|
|
|
10082
10126
|
}
|
|
10083
10127
|
|
|
10084
10128
|
const chartJsExtensionRegistry = new Registry();
|
|
10085
|
-
|
|
10086
|
-
|
|
10087
|
-
|
|
10088
|
-
|
|
10089
|
-
|
|
10090
|
-
|
|
10091
|
-
|
|
10092
|
-
|
|
10093
|
-
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
|
|
10129
|
+
function areChartJSExtensionsLoaded() {
|
|
10130
|
+
return !!window.Chart.registry.plugins.get("chartShowValuesPlugin");
|
|
10131
|
+
}
|
|
10132
|
+
function registerChartJSExtensions() {
|
|
10133
|
+
if (!window.Chart || areChartJSExtensionsLoaded()) {
|
|
10134
|
+
return;
|
|
10135
|
+
}
|
|
10136
|
+
for (const registryItem of chartJsExtensionRegistry.getAll()) {
|
|
10137
|
+
registryItem.register(window.Chart);
|
|
10138
|
+
}
|
|
10139
|
+
}
|
|
10140
|
+
function unregisterChartJsExtensions() {
|
|
10141
|
+
if (!window.Chart) {
|
|
10142
|
+
return;
|
|
10143
|
+
}
|
|
10144
|
+
for (const registryItem of chartJsExtensionRegistry.getAll()) {
|
|
10145
|
+
registryItem.unregister(window.Chart);
|
|
10097
10146
|
}
|
|
10098
|
-
return window.Chart;
|
|
10099
10147
|
}
|
|
10100
10148
|
|
|
10101
10149
|
function getFunnelChartController() {
|
|
@@ -10522,7 +10570,7 @@ function getDefinedAxis(definition) {
|
|
|
10522
10570
|
}
|
|
10523
10571
|
function formatChartDatasetValue(axisFormats, locale) {
|
|
10524
10572
|
return (value, axisId) => {
|
|
10525
|
-
const format =
|
|
10573
|
+
const format = axisFormats?.[axisId];
|
|
10526
10574
|
return formatTickValue({ format, locale })(value);
|
|
10527
10575
|
};
|
|
10528
10576
|
}
|
|
@@ -10699,7 +10747,7 @@ function drawPieChartValues(chart, options, ctx) {
|
|
|
10699
10747
|
const y = bar.y + midRadius * Math.sin(midAngle) + 7;
|
|
10700
10748
|
ctx.fillStyle = chartFontColor(options.background);
|
|
10701
10749
|
ctx.strokeStyle = options.background || "#ffffff";
|
|
10702
|
-
const displayValue = options.callback(value);
|
|
10750
|
+
const displayValue = options.callback(value, "y");
|
|
10703
10751
|
drawTextWithBackground(displayValue, x, y, ctx);
|
|
10704
10752
|
}
|
|
10705
10753
|
}
|
|
@@ -11461,13 +11509,35 @@ css /* scss */ `
|
|
|
11461
11509
|
}
|
|
11462
11510
|
}
|
|
11463
11511
|
`;
|
|
11464
|
-
chartJsExtensionRegistry.add("chartShowValuesPlugin",
|
|
11465
|
-
|
|
11466
|
-
|
|
11467
|
-
|
|
11468
|
-
chartJsExtensionRegistry.add("
|
|
11469
|
-
|
|
11470
|
-
|
|
11512
|
+
chartJsExtensionRegistry.add("chartShowValuesPlugin", {
|
|
11513
|
+
register: (Chart) => Chart.register(chartShowValuesPlugin),
|
|
11514
|
+
unregister: (Chart) => Chart.unregister(chartShowValuesPlugin),
|
|
11515
|
+
});
|
|
11516
|
+
chartJsExtensionRegistry.add("waterfallLinesPlugin", {
|
|
11517
|
+
register: (Chart) => Chart.register(waterfallLinesPlugin),
|
|
11518
|
+
unregister: (Chart) => Chart.unregister(waterfallLinesPlugin),
|
|
11519
|
+
});
|
|
11520
|
+
chartJsExtensionRegistry.add("funnelController", {
|
|
11521
|
+
register: (Chart) => Chart.register(getFunnelChartController()),
|
|
11522
|
+
unregister: (Chart) => Chart.unregister(getFunnelChartController()),
|
|
11523
|
+
});
|
|
11524
|
+
chartJsExtensionRegistry.add("funnelElement", {
|
|
11525
|
+
register: (Chart) => Chart.register(getFunnelChartElement()),
|
|
11526
|
+
unregister: (Chart) => Chart.unregister(getFunnelChartElement()),
|
|
11527
|
+
});
|
|
11528
|
+
chartJsExtensionRegistry.add("funnelTooltipPositioner", {
|
|
11529
|
+
register: (Chart) => (Chart.Tooltip.positioners.funnelTooltipPositioner = funnelTooltipPositioner),
|
|
11530
|
+
// @ts-expect-error
|
|
11531
|
+
unregister: (Chart) => (Chart.Tooltip.positioners.funnelTooltipPositioner = undefined),
|
|
11532
|
+
});
|
|
11533
|
+
chartJsExtensionRegistry.add("sunburstLabelsPlugin", {
|
|
11534
|
+
register: (Chart) => Chart.register(sunburstLabelsPlugin),
|
|
11535
|
+
unregister: (Chart) => Chart.unregister(sunburstLabelsPlugin),
|
|
11536
|
+
});
|
|
11537
|
+
chartJsExtensionRegistry.add("sunburstHoverPlugin", {
|
|
11538
|
+
register: (Chart) => Chart.register(sunburstHoverPlugin),
|
|
11539
|
+
unregister: (Chart) => Chart.unregister(sunburstHoverPlugin),
|
|
11540
|
+
});
|
|
11471
11541
|
class ChartJsComponent extends owl.Component {
|
|
11472
11542
|
static template = "o-spreadsheet-ChartJsComponent";
|
|
11473
11543
|
static props = {
|
|
@@ -11519,8 +11589,7 @@ class ChartJsComponent extends owl.Component {
|
|
|
11519
11589
|
createChart(chartData) {
|
|
11520
11590
|
const canvas = this.canvas.el;
|
|
11521
11591
|
const ctx = canvas.getContext("2d");
|
|
11522
|
-
|
|
11523
|
-
this.chart = new Chart(ctx, chartData);
|
|
11592
|
+
this.chart = new window.Chart(ctx, chartData);
|
|
11524
11593
|
}
|
|
11525
11594
|
updateChartJs(chartData) {
|
|
11526
11595
|
if (chartData.data && chartData.data.datasets) {
|
|
@@ -19825,7 +19894,7 @@ const IF = {
|
|
|
19825
19894
|
return { value: "" };
|
|
19826
19895
|
}
|
|
19827
19896
|
if (result.value === null) {
|
|
19828
|
-
result
|
|
19897
|
+
return { ...result, value: "" };
|
|
19829
19898
|
}
|
|
19830
19899
|
return result;
|
|
19831
19900
|
},
|
|
@@ -19846,7 +19915,7 @@ const IFERROR = {
|
|
|
19846
19915
|
return { value: "" };
|
|
19847
19916
|
}
|
|
19848
19917
|
if (result.value === null) {
|
|
19849
|
-
result
|
|
19918
|
+
return { ...result, value: "" };
|
|
19850
19919
|
}
|
|
19851
19920
|
return result;
|
|
19852
19921
|
},
|
|
@@ -19867,7 +19936,7 @@ const IFNA = {
|
|
|
19867
19936
|
return { value: "" };
|
|
19868
19937
|
}
|
|
19869
19938
|
if (result.value === null) {
|
|
19870
|
-
result
|
|
19939
|
+
return { ...result, value: "" };
|
|
19871
19940
|
}
|
|
19872
19941
|
return result;
|
|
19873
19942
|
},
|
|
@@ -19893,7 +19962,7 @@ const IFS = {
|
|
|
19893
19962
|
return { value: "" };
|
|
19894
19963
|
}
|
|
19895
19964
|
if (result.value === null) {
|
|
19896
|
-
result
|
|
19965
|
+
return { ...result, value: "" };
|
|
19897
19966
|
}
|
|
19898
19967
|
return result;
|
|
19899
19968
|
}
|
|
@@ -20040,6 +20109,11 @@ function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
|
|
|
20040
20109
|
if (range === undefined || range.invalidXc || range.invalidSheetName) {
|
|
20041
20110
|
throw new InvalidReferenceError();
|
|
20042
20111
|
}
|
|
20112
|
+
if (evalContext.__originCellPosition &&
|
|
20113
|
+
range.sheetId === evalContext.__originSheetId &&
|
|
20114
|
+
isZoneInside(positionToZone(evalContext.__originCellPosition), zone)) {
|
|
20115
|
+
throw new CircularDependencyError();
|
|
20116
|
+
}
|
|
20043
20117
|
dependencies.push(range);
|
|
20044
20118
|
}
|
|
20045
20119
|
for (const measure of forMeasures) {
|
|
@@ -20482,6 +20556,9 @@ const PIVOT_VALUE = {
|
|
|
20482
20556
|
};
|
|
20483
20557
|
}
|
|
20484
20558
|
const domain = pivot.parseArgsToPivotDomain(domainArgs);
|
|
20559
|
+
if (this.getters.getActiveSheetId() === this.__originSheetId) {
|
|
20560
|
+
this.getters.getPivotPresenceTracker(pivotId)?.trackValue(_measure, domain);
|
|
20561
|
+
}
|
|
20485
20562
|
return pivot.getPivotCellValueAndFormat(_measure, domain);
|
|
20486
20563
|
},
|
|
20487
20564
|
};
|
|
@@ -20513,6 +20590,9 @@ const PIVOT_HEADER = {
|
|
|
20513
20590
|
};
|
|
20514
20591
|
}
|
|
20515
20592
|
const domain = pivot.parseArgsToPivotDomain(domainArgs);
|
|
20593
|
+
if (this.getters.getActiveSheetId() === this.__originSheetId) {
|
|
20594
|
+
this.getters.getPivotPresenceTracker(_pivotId)?.trackHeader(domain);
|
|
20595
|
+
}
|
|
20516
20596
|
const lastNode = domain.at(-1);
|
|
20517
20597
|
if (lastNode?.field === "measure") {
|
|
20518
20598
|
return pivot.getPivotMeasureValue(toString(lastNode.value), domain);
|
|
@@ -20735,6 +20815,9 @@ function isEmpty(data) {
|
|
|
20735
20815
|
return data === undefined || data.value === null;
|
|
20736
20816
|
}
|
|
20737
20817
|
const getNeutral = { number: 0, string: "", boolean: false };
|
|
20818
|
+
function areAlmostEqual(value1, value2, epsilon = 2e-16) {
|
|
20819
|
+
return Math.abs(value1 - value2) < epsilon;
|
|
20820
|
+
}
|
|
20738
20821
|
const EQ = {
|
|
20739
20822
|
description: _t("Equal."),
|
|
20740
20823
|
args: [
|
|
@@ -20756,6 +20839,9 @@ const EQ = {
|
|
|
20756
20839
|
if (typeof _value2 === "string") {
|
|
20757
20840
|
_value2 = _value2.toUpperCase();
|
|
20758
20841
|
}
|
|
20842
|
+
if (typeof _value1 === "number" && typeof _value2 === "number") {
|
|
20843
|
+
return { value: areAlmostEqual(_value1, _value2) };
|
|
20844
|
+
}
|
|
20759
20845
|
return { value: _value1 === _value2 };
|
|
20760
20846
|
},
|
|
20761
20847
|
};
|
|
@@ -20795,6 +20881,9 @@ const GT = {
|
|
|
20795
20881
|
],
|
|
20796
20882
|
compute: function (value1, value2) {
|
|
20797
20883
|
return applyRelationalOperator(value1, value2, (v1, v2) => {
|
|
20884
|
+
if (typeof v1 === "number" && typeof v2 === "number") {
|
|
20885
|
+
return !areAlmostEqual(v1, v2) && v1 > v2;
|
|
20886
|
+
}
|
|
20798
20887
|
return v1 > v2;
|
|
20799
20888
|
});
|
|
20800
20889
|
},
|
|
@@ -20810,6 +20899,9 @@ const GTE = {
|
|
|
20810
20899
|
],
|
|
20811
20900
|
compute: function (value1, value2) {
|
|
20812
20901
|
return applyRelationalOperator(value1, value2, (v1, v2) => {
|
|
20902
|
+
if (typeof v1 === "number" && typeof v2 === "number") {
|
|
20903
|
+
return areAlmostEqual(v1, v2) || v1 > v2;
|
|
20904
|
+
}
|
|
20813
20905
|
return v1 >= v2;
|
|
20814
20906
|
});
|
|
20815
20907
|
},
|
|
@@ -22502,7 +22594,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
22502
22594
|
.find((token) => {
|
|
22503
22595
|
const { xc, sheetName: sheet } = splitReference(token.value);
|
|
22504
22596
|
const sheetName = sheet || this.getters.getSheetName(this.sheetId);
|
|
22505
|
-
if (this.getters.getSheetName(activeSheetId)
|
|
22597
|
+
if (!isSheetNameEqual(this.getters.getSheetName(activeSheetId), sheetName)) {
|
|
22506
22598
|
return false;
|
|
22507
22599
|
}
|
|
22508
22600
|
const refRange = this.getters.getRangeFromSheetXC(activeSheetId, xc);
|
|
@@ -24399,6 +24491,7 @@ const CHART_COMMON_OPTIONS = {
|
|
|
24399
24491
|
},
|
|
24400
24492
|
},
|
|
24401
24493
|
animation: false,
|
|
24494
|
+
events: ["mousemove", "mouseout", "click", "touchstart", "touchmove", "mouseup"],
|
|
24402
24495
|
};
|
|
24403
24496
|
function chartToImageUrl(runtime, figure, type) {
|
|
24404
24497
|
// wrap the canvas in a div with a fixed size because chart.js would
|
|
@@ -24438,6 +24531,8 @@ async function chartToImageFile(runtime, figure, type) {
|
|
|
24438
24531
|
const div = document.createElement("div");
|
|
24439
24532
|
div.style.width = `${figure.width}px`;
|
|
24440
24533
|
div.style.height = `${figure.height}px`;
|
|
24534
|
+
div.style.position = "fixed";
|
|
24535
|
+
div.style.opacity = "0";
|
|
24441
24536
|
const canvas = document.createElement("canvas");
|
|
24442
24537
|
div.append(canvas);
|
|
24443
24538
|
canvas.setAttribute("width", figure.width.toString());
|
|
@@ -24448,8 +24543,7 @@ async function chartToImageFile(runtime, figure, type) {
|
|
|
24448
24543
|
if ("chartJsConfig" in runtime) {
|
|
24449
24544
|
const config = deepCopy(runtime.chartJsConfig);
|
|
24450
24545
|
config.plugins = [backgroundColorChartJSPlugin];
|
|
24451
|
-
const
|
|
24452
|
-
const chart = new Chart(canvas, config);
|
|
24546
|
+
const chart = new window.Chart(canvas, config);
|
|
24453
24547
|
chartBlob = await new Promise((resolve) => canvas.toBlob(resolve, "image/png"));
|
|
24454
24548
|
chart.destroy();
|
|
24455
24549
|
}
|
|
@@ -25201,11 +25295,10 @@ function canBeLinearChart(definition, dataSets, labelRange, getters) {
|
|
|
25201
25295
|
}
|
|
25202
25296
|
let missingTimeAdapterAlreadyWarned = false;
|
|
25203
25297
|
function isLuxonTimeAdapterInstalled() {
|
|
25204
|
-
|
|
25205
|
-
if (!Chart) {
|
|
25298
|
+
if (!window.Chart) {
|
|
25206
25299
|
return false;
|
|
25207
25300
|
}
|
|
25208
|
-
const adapter = new Chart._adapters._date({});
|
|
25301
|
+
const adapter = new window.Chart._adapters._date({});
|
|
25209
25302
|
// @ts-ignore
|
|
25210
25303
|
const isInstalled = adapter._id === "luxon";
|
|
25211
25304
|
if (!isInstalled && !missingTimeAdapterAlreadyWarned) {
|
|
@@ -25703,6 +25796,9 @@ const INTERACTIVE_LEGEND_CONFIG = {
|
|
|
25703
25796
|
target.style.cursor = "default";
|
|
25704
25797
|
},
|
|
25705
25798
|
onClick: (event, legendItem, legend) => {
|
|
25799
|
+
if (event.type !== "click") {
|
|
25800
|
+
return;
|
|
25801
|
+
}
|
|
25706
25802
|
const index = legendItem.datasetIndex;
|
|
25707
25803
|
if (!legend.legendItems || index === undefined) {
|
|
25708
25804
|
return;
|
|
@@ -29639,10 +29735,15 @@ function getChartMenu(figureId, onFigureDeleted, env) {
|
|
|
29639
29735
|
const imageUrl = chartToImageUrl(runtime, figure, chartType);
|
|
29640
29736
|
const innerHTML = `<img src="${xmlEscape(imageUrl)}" />`;
|
|
29641
29737
|
const blob = await chartToImageFile(runtime, figure, chartType);
|
|
29642
|
-
env.clipboard.write({
|
|
29738
|
+
await env.clipboard.write({
|
|
29643
29739
|
"text/html": innerHTML,
|
|
29644
29740
|
"image/png": blob,
|
|
29645
29741
|
});
|
|
29742
|
+
env.notifyUser({
|
|
29743
|
+
text: _t("The chart was copied to your clipboard"),
|
|
29744
|
+
sticky: false,
|
|
29745
|
+
type: "info",
|
|
29746
|
+
});
|
|
29646
29747
|
},
|
|
29647
29748
|
},
|
|
29648
29749
|
{
|
|
@@ -31492,7 +31593,7 @@ function getRangeSize(reference, defaultSheetIndex, data) {
|
|
|
31492
31593
|
({ xc, sheetName } = splitReference(reference));
|
|
31493
31594
|
let rangeSheetIndex;
|
|
31494
31595
|
if (sheetName) {
|
|
31495
|
-
const index = data.sheets.findIndex((sheet) => sheet.name
|
|
31596
|
+
const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
|
|
31496
31597
|
if (index < 0) {
|
|
31497
31598
|
throw new Error("Unable to find a sheet with the name " + sheetName);
|
|
31498
31599
|
}
|
|
@@ -31849,7 +31950,7 @@ function convertFormula(formula, data) {
|
|
|
31849
31950
|
formula = formula.replace(externalReferenceRegex, (match, externalRefId, sheetName, cellRef) => {
|
|
31850
31951
|
externalRefId = Number(externalRefId) - 1;
|
|
31851
31952
|
cellRef = cellRef.replace(/\$/g, "");
|
|
31852
|
-
const sheetIndex = data.externalBooks[externalRefId].sheetNames.findIndex((name) => name
|
|
31953
|
+
const sheetIndex = data.externalBooks[externalRefId].sheetNames.findIndex((name) => isSheetNameEqual(name, sheetName));
|
|
31853
31954
|
if (sheetIndex === -1) {
|
|
31854
31955
|
return match;
|
|
31855
31956
|
}
|
|
@@ -32500,7 +32601,7 @@ function convertPivotTableConfig(pivotTable) {
|
|
|
32500
32601
|
*/
|
|
32501
32602
|
function convertTableFormulaReferences(convertedSheets, xlsxSheets) {
|
|
32502
32603
|
for (let tableSheet of convertedSheets) {
|
|
32503
|
-
const tables = xlsxSheets.find((s) => s.sheetName
|
|
32604
|
+
const tables = xlsxSheets.find((s) => isSheetNameEqual(s.sheetName, tableSheet.name)).tables;
|
|
32504
32605
|
for (let table of tables) {
|
|
32505
32606
|
const tabRef = table.name + "[";
|
|
32506
32607
|
for (let sheet of convertedSheets) {
|
|
@@ -34849,6 +34950,7 @@ function repairInitialMessages(data, initialMessages) {
|
|
|
34849
34950
|
initialMessages = dropCommands(initialMessages, "SET_DECIMAL");
|
|
34850
34951
|
initialMessages = fixChartDefinitions(data, initialMessages);
|
|
34851
34952
|
initialMessages = fixFigureOffset(data, initialMessages);
|
|
34953
|
+
initialMessages = fixTranslatedDuplicateSheetName(data, initialMessages);
|
|
34852
34954
|
return initialMessages;
|
|
34853
34955
|
}
|
|
34854
34956
|
/**
|
|
@@ -34981,6 +35083,42 @@ function fixFigureOffset(data, messages) {
|
|
|
34981
35083
|
}
|
|
34982
35084
|
return messages;
|
|
34983
35085
|
}
|
|
35086
|
+
function fixTranslatedDuplicateSheetName(data, initialMessages) {
|
|
35087
|
+
const sheetNames = {};
|
|
35088
|
+
for (const sheet of data.sheets || []) {
|
|
35089
|
+
sheetNames[sheet.id] = sheet.name;
|
|
35090
|
+
}
|
|
35091
|
+
const messages = [];
|
|
35092
|
+
for (const message of initialMessages) {
|
|
35093
|
+
if (message.type === "REMOTE_REVISION") {
|
|
35094
|
+
const commands = [];
|
|
35095
|
+
for (const cmd of message.commands) {
|
|
35096
|
+
switch (cmd.type) {
|
|
35097
|
+
case "DUPLICATE_SHEET":
|
|
35098
|
+
cmd.sheetNameTo =
|
|
35099
|
+
cmd.sheetNameTo ??
|
|
35100
|
+
getDuplicateSheetName(sheetNames[cmd.sheetId], Object.values(sheetNames));
|
|
35101
|
+
break;
|
|
35102
|
+
case "CREATE_SHEET":
|
|
35103
|
+
sheetNames[cmd.sheetId] = cmd.name || getNextSheetName(Object.values(sheetNames));
|
|
35104
|
+
break;
|
|
35105
|
+
case "RENAME_SHEET":
|
|
35106
|
+
sheetNames[cmd.sheetId] = cmd.newName || getNextSheetName(Object.values(sheetNames));
|
|
35107
|
+
break;
|
|
35108
|
+
}
|
|
35109
|
+
commands.push(cmd);
|
|
35110
|
+
}
|
|
35111
|
+
messages.push({
|
|
35112
|
+
...message,
|
|
35113
|
+
commands,
|
|
35114
|
+
});
|
|
35115
|
+
}
|
|
35116
|
+
else {
|
|
35117
|
+
messages.push(message);
|
|
35118
|
+
}
|
|
35119
|
+
}
|
|
35120
|
+
return initialMessages;
|
|
35121
|
+
}
|
|
34984
35122
|
// -----------------------------------------------------------------------------
|
|
34985
35123
|
// Helpers
|
|
34986
35124
|
// -----------------------------------------------------------------------------
|
|
@@ -35118,12 +35256,20 @@ class DelayedHoveredCellStore extends SpreadsheetStore {
|
|
|
35118
35256
|
}
|
|
35119
35257
|
}
|
|
35120
35258
|
hover(position) {
|
|
35259
|
+
if (position.col === this.col && position.row === this.row) {
|
|
35260
|
+
return "noStateChange";
|
|
35261
|
+
}
|
|
35121
35262
|
this.col = position.col;
|
|
35122
35263
|
this.row = position.row;
|
|
35264
|
+
return;
|
|
35123
35265
|
}
|
|
35124
35266
|
clear() {
|
|
35267
|
+
if (this.col === undefined && this.row === undefined) {
|
|
35268
|
+
return "noStateChange";
|
|
35269
|
+
}
|
|
35125
35270
|
this.col = undefined;
|
|
35126
35271
|
this.row = undefined;
|
|
35272
|
+
return;
|
|
35127
35273
|
}
|
|
35128
35274
|
}
|
|
35129
35275
|
|
|
@@ -35145,7 +35291,11 @@ class CellPopoverStore extends SpreadsheetStore {
|
|
|
35145
35291
|
this.persistentPopover = { col, row, sheetId, type };
|
|
35146
35292
|
}
|
|
35147
35293
|
close() {
|
|
35294
|
+
if (!this.persistentPopover) {
|
|
35295
|
+
return "noStateChange";
|
|
35296
|
+
}
|
|
35148
35297
|
this.persistentPopover = undefined;
|
|
35298
|
+
return;
|
|
35149
35299
|
}
|
|
35150
35300
|
get persistentCellPopover() {
|
|
35151
35301
|
return ((this.persistentPopover && { isOpen: true, ...this.persistentPopover }) || { isOpen: false });
|
|
@@ -36039,10 +36189,13 @@ const duplicateSheet = {
|
|
|
36039
36189
|
name: _t("Duplicate"),
|
|
36040
36190
|
execute: (env) => {
|
|
36041
36191
|
const sheetIdFrom = env.model.getters.getActiveSheetId();
|
|
36192
|
+
const sheetNameFrom = env.model.getters.getSheetName(sheetIdFrom);
|
|
36042
36193
|
const sheetIdTo = env.model.uuidGenerator.smallUuid();
|
|
36194
|
+
const sheetNameTo = env.model.getters.getDuplicateSheetName(sheetNameFrom);
|
|
36043
36195
|
env.model.dispatch("DUPLICATE_SHEET", {
|
|
36044
36196
|
sheetId: sheetIdFrom,
|
|
36045
36197
|
sheetIdTo,
|
|
36198
|
+
sheetNameTo,
|
|
36046
36199
|
});
|
|
36047
36200
|
env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom, sheetIdTo });
|
|
36048
36201
|
},
|
|
@@ -40683,7 +40836,7 @@ class GenericChartConfigPanel extends owl.Component {
|
|
|
40683
40836
|
const cancelledReasons = [
|
|
40684
40837
|
...(this.state.datasetDispatchResult?.reasons || []),
|
|
40685
40838
|
...(this.state.labelsDispatchResult?.reasons || []),
|
|
40686
|
-
];
|
|
40839
|
+
].filter((reason) => reason !== "NoChanges" /* CommandResult.NoChanges */);
|
|
40687
40840
|
return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
|
|
40688
40841
|
}
|
|
40689
40842
|
get isDatasetInvalid() {
|
|
@@ -42260,10 +42413,18 @@ class GaugeChartConfigPanel extends owl.Component {
|
|
|
42260
42413
|
}
|
|
42261
42414
|
|
|
42262
42415
|
class DOMFocusableElementStore {
|
|
42263
|
-
mutators = ["setFocusableElement"];
|
|
42416
|
+
mutators = ["setFocusableElement", "focus"];
|
|
42264
42417
|
focusableElement = undefined;
|
|
42265
42418
|
setFocusableElement(element) {
|
|
42266
42419
|
this.focusableElement = element;
|
|
42420
|
+
return "noStateChange";
|
|
42421
|
+
}
|
|
42422
|
+
focus() {
|
|
42423
|
+
if (this.focusableElement === document.activeElement) {
|
|
42424
|
+
return "noStateChange";
|
|
42425
|
+
}
|
|
42426
|
+
this.focusableElement?.focus();
|
|
42427
|
+
return;
|
|
42267
42428
|
}
|
|
42268
42429
|
}
|
|
42269
42430
|
|
|
@@ -42935,7 +43096,7 @@ class Composer extends owl.Component {
|
|
|
42935
43096
|
if (document.activeElement === this.contentHelper.el &&
|
|
42936
43097
|
this.props.composerStore.editionMode === "inactive" &&
|
|
42937
43098
|
!this.props.isDefaultFocus) {
|
|
42938
|
-
this.DOMFocusableElementStore.
|
|
43099
|
+
this.DOMFocusableElementStore.focus();
|
|
42939
43100
|
}
|
|
42940
43101
|
});
|
|
42941
43102
|
owl.useEffect(() => {
|
|
@@ -43215,6 +43376,13 @@ class Composer extends owl.Component {
|
|
|
43215
43376
|
openAssistant() {
|
|
43216
43377
|
this.assistant.forcedClosed = false;
|
|
43217
43378
|
}
|
|
43379
|
+
onWheel(event) {
|
|
43380
|
+
// detect if scrollbar is available
|
|
43381
|
+
if (this.composerRef.el &&
|
|
43382
|
+
this.composerRef.el.scrollHeight > this.composerRef.el.clientHeight) {
|
|
43383
|
+
event.stopPropagation();
|
|
43384
|
+
}
|
|
43385
|
+
}
|
|
43218
43386
|
// ---------------------------------------------------------------------------
|
|
43219
43387
|
// Private
|
|
43220
43388
|
// ---------------------------------------------------------------------------
|
|
@@ -48939,8 +49107,8 @@ function compareDimensionValues(dimension, a, b) {
|
|
|
48939
49107
|
|
|
48940
49108
|
const NULL_SYMBOL = Symbol("NULL");
|
|
48941
49109
|
function createDate(dimension, value, locale) {
|
|
48942
|
-
const granularity = dimension.granularity;
|
|
48943
|
-
if (!
|
|
49110
|
+
const granularity = dimension.granularity || "month";
|
|
49111
|
+
if (!(granularity in MAP_VALUE_DIMENSION_DATE)) {
|
|
48944
49112
|
throw new Error(`Unknown date granularity: ${granularity}`);
|
|
48945
49113
|
}
|
|
48946
49114
|
const keyInMap = typeof value === "number" || typeof value === "string" ? value : NULL_SYMBOL;
|
|
@@ -48959,6 +49127,9 @@ function createDate(dimension, value, locale) {
|
|
|
48959
49127
|
case "month_number":
|
|
48960
49128
|
number = date.getMonth() + 1;
|
|
48961
49129
|
break;
|
|
49130
|
+
case "month":
|
|
49131
|
+
number = Math.floor(toNumber(value, locale));
|
|
49132
|
+
break;
|
|
48962
49133
|
case "iso_week_number":
|
|
48963
49134
|
number = date.getIsoWeek();
|
|
48964
49135
|
break;
|
|
@@ -49052,6 +49223,10 @@ const MAP_VALUE_DIMENSION_DATE = {
|
|
|
49052
49223
|
set: new Set(),
|
|
49053
49224
|
values: {},
|
|
49054
49225
|
},
|
|
49226
|
+
month: {
|
|
49227
|
+
set: new Set(),
|
|
49228
|
+
values: {},
|
|
49229
|
+
},
|
|
49055
49230
|
iso_week_number: {
|
|
49056
49231
|
set: new Set(),
|
|
49057
49232
|
values: {},
|
|
@@ -49262,7 +49437,7 @@ class SpreadsheetPivot {
|
|
|
49262
49437
|
const cells = this.filterDataEntriesFromDomain(this.dataEntries, domain);
|
|
49263
49438
|
const finalCell = cells[0]?.[dimension.nameWithGranularity];
|
|
49264
49439
|
if (dimension.type === "datetime") {
|
|
49265
|
-
const adapter = pivotTimeAdapter(dimension.granularity);
|
|
49440
|
+
const adapter = pivotTimeAdapter((dimension.granularity || "month"));
|
|
49266
49441
|
return adapter.toValueAndFormat(lastNode.value, this.getters.getLocale());
|
|
49267
49442
|
}
|
|
49268
49443
|
if (!finalCell) {
|
|
@@ -49380,7 +49555,7 @@ class SpreadsheetPivot {
|
|
|
49380
49555
|
if (nonEmptyCells.length === 0) {
|
|
49381
49556
|
return "integer";
|
|
49382
49557
|
}
|
|
49383
|
-
if (nonEmptyCells.every((cell) => cell.format && isDateTimeFormat(cell.format))) {
|
|
49558
|
+
if (nonEmptyCells.every((cell) => cell.type === CellValueType.number && cell.format && isDateTimeFormat(cell.format))) {
|
|
49384
49559
|
return "datetime";
|
|
49385
49560
|
}
|
|
49386
49561
|
if (nonEmptyCells.every((cell) => cell.type === CellValueType.boolean)) {
|
|
@@ -49459,7 +49634,12 @@ class SpreadsheetPivot {
|
|
|
49459
49634
|
entry[field.name] = { value: null, type: CellValueType.empty, formattedValue: "" };
|
|
49460
49635
|
}
|
|
49461
49636
|
else {
|
|
49462
|
-
|
|
49637
|
+
if (field.type === "char") {
|
|
49638
|
+
entry[field.name] = { ...cell, value: cell.formattedValue || null };
|
|
49639
|
+
}
|
|
49640
|
+
else {
|
|
49641
|
+
entry[field.name] = cell;
|
|
49642
|
+
}
|
|
49463
49643
|
}
|
|
49464
49644
|
}
|
|
49465
49645
|
entry["__count"] = { value: 1, type: CellValueType.number, formattedValue: "1" };
|
|
@@ -49473,7 +49653,7 @@ class SpreadsheetPivot {
|
|
|
49473
49653
|
for (const entry of dataEntries) {
|
|
49474
49654
|
for (const dimension of dateDimensions) {
|
|
49475
49655
|
const value = createDate(dimension, entry[dimension.fieldName]?.value || null, this.getters.getLocale());
|
|
49476
|
-
const adapter = pivotTimeAdapter(dimension.granularity);
|
|
49656
|
+
const adapter = pivotTimeAdapter((dimension.granularity || "month"));
|
|
49477
49657
|
const { format, value: valueToFormat } = adapter.toValueAndFormat(value, locale);
|
|
49478
49658
|
entry[dimension.nameWithGranularity] = {
|
|
49479
49659
|
value,
|
|
@@ -49493,6 +49673,7 @@ const dateGranularities = [
|
|
|
49493
49673
|
"year",
|
|
49494
49674
|
"quarter_number",
|
|
49495
49675
|
"month_number",
|
|
49676
|
+
"month",
|
|
49496
49677
|
"iso_week_number",
|
|
49497
49678
|
"day_of_month",
|
|
49498
49679
|
"day",
|
|
@@ -49743,7 +49924,7 @@ class PivotSidePanelStore extends SpreadsheetStore {
|
|
|
49743
49924
|
: this.datetimeGranularities);
|
|
49744
49925
|
}
|
|
49745
49926
|
for (const field of dateFields) {
|
|
49746
|
-
granularitiesPerFields[field.fieldName].delete(field.granularity);
|
|
49927
|
+
granularitiesPerFields[field.fieldName].delete(field.granularity || "month");
|
|
49747
49928
|
}
|
|
49748
49929
|
return granularitiesPerFields;
|
|
49749
49930
|
}
|
|
@@ -52083,6 +52264,8 @@ class GridComposer extends owl.Component {
|
|
|
52083
52264
|
}
|
|
52084
52265
|
get composerProps() {
|
|
52085
52266
|
const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
|
|
52267
|
+
// Remove the wrapper border width
|
|
52268
|
+
const maxHeight = this.props.gridDims.height - this.rect.y - 2 * COMPOSER_BORDER_WIDTH;
|
|
52086
52269
|
return {
|
|
52087
52270
|
rect: { ...this.rect },
|
|
52088
52271
|
delimitation: {
|
|
@@ -52100,6 +52283,7 @@ class GridComposer extends owl.Component {
|
|
|
52100
52283
|
}),
|
|
52101
52284
|
onInputContextMenu: this.props.onInputContextMenu,
|
|
52102
52285
|
composerStore: this.composerStore,
|
|
52286
|
+
inputStyle: `max-height: ${maxHeight}px;`,
|
|
52103
52287
|
};
|
|
52104
52288
|
}
|
|
52105
52289
|
get containerStyle() {
|
|
@@ -53180,9 +53364,13 @@ class HoveredTableStore extends SpreadsheetStore {
|
|
|
53180
53364
|
}
|
|
53181
53365
|
}
|
|
53182
53366
|
hover(position) {
|
|
53367
|
+
if (position.col === this.col && position.row === this.row) {
|
|
53368
|
+
return "noStateChange";
|
|
53369
|
+
}
|
|
53183
53370
|
this.col = position.col;
|
|
53184
53371
|
this.row = position.row;
|
|
53185
53372
|
this.computeOverlay();
|
|
53373
|
+
return;
|
|
53186
53374
|
}
|
|
53187
53375
|
clear() {
|
|
53188
53376
|
this.col = undefined;
|
|
@@ -54814,10 +55002,6 @@ function useGridDrawing(refName, model, canvasSize) {
|
|
|
54814
55002
|
ctx.scale(dpr, dpr);
|
|
54815
55003
|
for (const layer of OrderedLayers()) {
|
|
54816
55004
|
model.drawLayer(renderingContext, layer);
|
|
54817
|
-
// @ts-ignore 'drawLayer' is not declated as a mutator because:
|
|
54818
|
-
// it does not mutate anything. Most importantly it's used
|
|
54819
|
-
// during rendering. Invoking a mutator during rendering would
|
|
54820
|
-
// trigger another rendering, ultimately resulting in an infinite loop.
|
|
54821
55005
|
rendererStore.drawLayer(renderingContext, layer);
|
|
54822
55006
|
}
|
|
54823
55007
|
}
|
|
@@ -55511,7 +55695,7 @@ class Grid extends owl.Component {
|
|
|
55511
55695
|
this.cellPopovers = useStore(CellPopoverStore);
|
|
55512
55696
|
owl.useEffect(() => {
|
|
55513
55697
|
if (!this.sidePanel.isOpen) {
|
|
55514
|
-
this.DOMFocusableElementStore.
|
|
55698
|
+
this.DOMFocusableElementStore.focus();
|
|
55515
55699
|
}
|
|
55516
55700
|
}, () => [this.sidePanel.isOpen]);
|
|
55517
55701
|
useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
|
|
@@ -55720,7 +55904,7 @@ class Grid extends owl.Component {
|
|
|
55720
55904
|
focusDefaultElement() {
|
|
55721
55905
|
if (!this.env.model.getters.getSelectedFigureId() &&
|
|
55722
55906
|
this.composerFocusStore.activeComposer.editionMode === "inactive") {
|
|
55723
|
-
this.DOMFocusableElementStore.
|
|
55907
|
+
this.DOMFocusableElementStore.focus();
|
|
55724
55908
|
}
|
|
55725
55909
|
}
|
|
55726
55910
|
get gridEl() {
|
|
@@ -56069,6 +56253,322 @@ class Grid extends owl.Component {
|
|
|
56069
56253
|
}
|
|
56070
56254
|
}
|
|
56071
56255
|
|
|
56256
|
+
css /* scss */ `
|
|
56257
|
+
.o_pivot_html_renderer {
|
|
56258
|
+
width: 100%;
|
|
56259
|
+
border-collapse: collapse;
|
|
56260
|
+
|
|
56261
|
+
&:hover {
|
|
56262
|
+
cursor: pointer;
|
|
56263
|
+
}
|
|
56264
|
+
|
|
56265
|
+
td,
|
|
56266
|
+
th {
|
|
56267
|
+
border: 1px solid #dee2e6;
|
|
56268
|
+
background-color: #fff;
|
|
56269
|
+
padding: 0.3rem;
|
|
56270
|
+
white-space: nowrap;
|
|
56271
|
+
|
|
56272
|
+
&:hover {
|
|
56273
|
+
filter: brightness(0.9);
|
|
56274
|
+
}
|
|
56275
|
+
}
|
|
56276
|
+
|
|
56277
|
+
td {
|
|
56278
|
+
text-align: right;
|
|
56279
|
+
}
|
|
56280
|
+
|
|
56281
|
+
th {
|
|
56282
|
+
background-color: #f5f5f5;
|
|
56283
|
+
font-weight: bold;
|
|
56284
|
+
color: black;
|
|
56285
|
+
}
|
|
56286
|
+
|
|
56287
|
+
.o_missing_value {
|
|
56288
|
+
color: #46646d;
|
|
56289
|
+
background: #e7f2f6;
|
|
56290
|
+
}
|
|
56291
|
+
}
|
|
56292
|
+
`;
|
|
56293
|
+
class PivotHTMLRenderer extends owl.Component {
|
|
56294
|
+
static template = "o_spreadsheet.PivotHTMLRenderer";
|
|
56295
|
+
static components = { Checkbox };
|
|
56296
|
+
static props = {
|
|
56297
|
+
pivotId: String,
|
|
56298
|
+
onCellClicked: Function,
|
|
56299
|
+
};
|
|
56300
|
+
pivot = this.env.model.getters.getPivot(this.props.pivotId);
|
|
56301
|
+
data = {
|
|
56302
|
+
columns: [],
|
|
56303
|
+
rows: [],
|
|
56304
|
+
values: [],
|
|
56305
|
+
};
|
|
56306
|
+
state = owl.useState({
|
|
56307
|
+
showMissingValuesOnly: false,
|
|
56308
|
+
});
|
|
56309
|
+
setup() {
|
|
56310
|
+
const table = this.pivot.getTableStructure();
|
|
56311
|
+
const formulaId = this.env.model.getters.getPivotFormulaId(this.props.pivotId);
|
|
56312
|
+
this.data = {
|
|
56313
|
+
columns: this._buildColHeaders(formulaId, table),
|
|
56314
|
+
rows: this._buildRowHeaders(formulaId, table),
|
|
56315
|
+
values: this._buildValues(formulaId, table),
|
|
56316
|
+
};
|
|
56317
|
+
}
|
|
56318
|
+
get tracker() {
|
|
56319
|
+
return this.env.model.getters.getPivotPresenceTracker(this.props.pivotId);
|
|
56320
|
+
}
|
|
56321
|
+
// ---------------------------------------------------------------------
|
|
56322
|
+
// Missing values building
|
|
56323
|
+
// ---------------------------------------------------------------------
|
|
56324
|
+
/**
|
|
56325
|
+
* Retrieve the data to display in the Pivot Table
|
|
56326
|
+
* In the case when showMissingValuesOnly is false, the returned value
|
|
56327
|
+
* is the complete data
|
|
56328
|
+
* In the case when showMissingValuesOnly is true, the returned value is
|
|
56329
|
+
* the data which contains only missing values in the rows and cols. In
|
|
56330
|
+
* the rows, we also return the parent rows of rows which contains missing
|
|
56331
|
+
* values, to give context to the user.
|
|
56332
|
+
*
|
|
56333
|
+
*/
|
|
56334
|
+
getTableData() {
|
|
56335
|
+
if (!this.state.showMissingValuesOnly) {
|
|
56336
|
+
return this.data;
|
|
56337
|
+
}
|
|
56338
|
+
const colIndexes = this.getColumnsIndexes();
|
|
56339
|
+
const rowIndexes = this.getRowsIndexes();
|
|
56340
|
+
const columns = this.buildColumnsMissing(colIndexes);
|
|
56341
|
+
const rows = this.buildRowsMissing(rowIndexes);
|
|
56342
|
+
const values = this.buildValuesMissing(colIndexes, rowIndexes);
|
|
56343
|
+
return { columns, rows, values };
|
|
56344
|
+
}
|
|
56345
|
+
/**
|
|
56346
|
+
* Retrieve the parents of the given row
|
|
56347
|
+
* ex:
|
|
56348
|
+
* Australia
|
|
56349
|
+
* January
|
|
56350
|
+
* February
|
|
56351
|
+
* The parent of "January" is "Australia"
|
|
56352
|
+
*/
|
|
56353
|
+
addRecursiveRow(index) {
|
|
56354
|
+
const rows = this.pivot.getTableStructure().rows;
|
|
56355
|
+
const row = [...rows[index].values];
|
|
56356
|
+
if (row.length <= 1) {
|
|
56357
|
+
return [index];
|
|
56358
|
+
}
|
|
56359
|
+
row.pop();
|
|
56360
|
+
const parentRowIndex = rows.findIndex((r) => JSON.stringify(r.values) === JSON.stringify(row));
|
|
56361
|
+
return [index].concat(this.addRecursiveRow(parentRowIndex));
|
|
56362
|
+
}
|
|
56363
|
+
/**
|
|
56364
|
+
* Create the columns to be used, based on the indexes of the columns in
|
|
56365
|
+
* which a missing value is present
|
|
56366
|
+
*
|
|
56367
|
+
*/
|
|
56368
|
+
buildColumnsMissing(indexes) {
|
|
56369
|
+
// columnsMap explode the columns in an array of array of the same
|
|
56370
|
+
// size with the index of each column, repeated 'span' times.
|
|
56371
|
+
// ex:
|
|
56372
|
+
// | A | B |
|
|
56373
|
+
// | 1 | 2 | 3 |
|
|
56374
|
+
// => [
|
|
56375
|
+
// [0, 0, 1]
|
|
56376
|
+
// [0, 1, 2]
|
|
56377
|
+
// ]
|
|
56378
|
+
const columnsMap = [];
|
|
56379
|
+
for (const column of this.data.columns) {
|
|
56380
|
+
const columnMap = [];
|
|
56381
|
+
for (const index in column) {
|
|
56382
|
+
for (let i = 0; i < column[index].span; i++) {
|
|
56383
|
+
columnMap.push(parseInt(index, 10));
|
|
56384
|
+
}
|
|
56385
|
+
}
|
|
56386
|
+
columnsMap.push(columnMap);
|
|
56387
|
+
}
|
|
56388
|
+
// Remove the columns that are not present in indexes
|
|
56389
|
+
for (let i = columnsMap[columnsMap.length - 1].length; i >= 0; i--) {
|
|
56390
|
+
if (!indexes.includes(i)) {
|
|
56391
|
+
for (const columnMap of columnsMap) {
|
|
56392
|
+
columnMap.splice(i, 1);
|
|
56393
|
+
}
|
|
56394
|
+
}
|
|
56395
|
+
}
|
|
56396
|
+
// Build the columns
|
|
56397
|
+
const columns = [];
|
|
56398
|
+
for (const mapIndex in columnsMap) {
|
|
56399
|
+
const column = [];
|
|
56400
|
+
let index = undefined;
|
|
56401
|
+
let span = 1;
|
|
56402
|
+
for (let i = 0; i < columnsMap[mapIndex].length; i++) {
|
|
56403
|
+
if (index !== columnsMap[mapIndex][i]) {
|
|
56404
|
+
if (index !== undefined) {
|
|
56405
|
+
column.push(Object.assign({}, this.data.columns[mapIndex][index], { span }));
|
|
56406
|
+
}
|
|
56407
|
+
index = columnsMap[mapIndex][i];
|
|
56408
|
+
span = 1;
|
|
56409
|
+
}
|
|
56410
|
+
else {
|
|
56411
|
+
span++;
|
|
56412
|
+
}
|
|
56413
|
+
}
|
|
56414
|
+
if (index !== undefined) {
|
|
56415
|
+
column.push(Object.assign({}, this.data.columns[mapIndex][index], { span }));
|
|
56416
|
+
}
|
|
56417
|
+
columns.push(column);
|
|
56418
|
+
}
|
|
56419
|
+
return columns;
|
|
56420
|
+
}
|
|
56421
|
+
/**
|
|
56422
|
+
* Create the rows to be used, based on the indexes of the rows in
|
|
56423
|
+
* which a missing value is present.
|
|
56424
|
+
*/
|
|
56425
|
+
buildRowsMissing(indexes) {
|
|
56426
|
+
return indexes.map((index) => this.data.rows[index]);
|
|
56427
|
+
}
|
|
56428
|
+
/**
|
|
56429
|
+
* Create the value to be used, based on the indexes of the columns and
|
|
56430
|
+
* rows in which a missing value is present.
|
|
56431
|
+
*/
|
|
56432
|
+
buildValuesMissing(colIndexes, rowIndexes) {
|
|
56433
|
+
const values = colIndexes.map(() => []);
|
|
56434
|
+
for (const row of rowIndexes) {
|
|
56435
|
+
for (const col in colIndexes) {
|
|
56436
|
+
values[col].push(this.data.values[colIndexes[col]][row]);
|
|
56437
|
+
}
|
|
56438
|
+
}
|
|
56439
|
+
return values;
|
|
56440
|
+
}
|
|
56441
|
+
getColumnsIndexes() {
|
|
56442
|
+
const indexes = new Set();
|
|
56443
|
+
for (let i = 0; i < this.data.columns.length; i++) {
|
|
56444
|
+
const exploded = [];
|
|
56445
|
+
for (let y = 0; y < this.data.columns[i].length; y++) {
|
|
56446
|
+
for (let x = 0; x < this.data.columns[i][y].span; x++) {
|
|
56447
|
+
exploded.push(this.data.columns[i][y]);
|
|
56448
|
+
}
|
|
56449
|
+
}
|
|
56450
|
+
for (let y = 0; y < exploded.length; y++) {
|
|
56451
|
+
if (exploded[y].isMissing) {
|
|
56452
|
+
indexes.add(y);
|
|
56453
|
+
}
|
|
56454
|
+
}
|
|
56455
|
+
}
|
|
56456
|
+
for (let i = 0; i < this.data.columns[this.data.columns.length - 1].length; i++) {
|
|
56457
|
+
const values = this.data.values[i];
|
|
56458
|
+
if (values.find((x) => x.isMissing)) {
|
|
56459
|
+
indexes.add(i);
|
|
56460
|
+
}
|
|
56461
|
+
}
|
|
56462
|
+
return Array.from(indexes).sort((a, b) => a - b);
|
|
56463
|
+
}
|
|
56464
|
+
getRowsIndexes() {
|
|
56465
|
+
const rowIndexes = new Set();
|
|
56466
|
+
for (let i = 0; i < this.data.rows.length; i++) {
|
|
56467
|
+
if (this.data.rows[i].isMissing) {
|
|
56468
|
+
rowIndexes.add(i);
|
|
56469
|
+
}
|
|
56470
|
+
for (const col of this.data.values) {
|
|
56471
|
+
if (col[i].isMissing) {
|
|
56472
|
+
this.addRecursiveRow(i).forEach((x) => rowIndexes.add(x));
|
|
56473
|
+
}
|
|
56474
|
+
}
|
|
56475
|
+
}
|
|
56476
|
+
return Array.from(rowIndexes).sort((a, b) => a - b);
|
|
56477
|
+
}
|
|
56478
|
+
// ---------------------------------------------------------------------
|
|
56479
|
+
// Data table creation
|
|
56480
|
+
// ---------------------------------------------------------------------
|
|
56481
|
+
_buildColHeaders(id, table) {
|
|
56482
|
+
const headers = [];
|
|
56483
|
+
for (const row of table.columns) {
|
|
56484
|
+
const current = [];
|
|
56485
|
+
for (const cell of row) {
|
|
56486
|
+
const args = [];
|
|
56487
|
+
for (let i = 0; i < cell.fields.length; i++) {
|
|
56488
|
+
args.push({ value: cell.fields[i] }, { value: cell.values[i] });
|
|
56489
|
+
}
|
|
56490
|
+
const domain = this.pivot.parseArgsToPivotDomain(args);
|
|
56491
|
+
const locale = this.env.model.getters.getLocale();
|
|
56492
|
+
if (domain.at(-1)?.field === "measure") {
|
|
56493
|
+
const { value, format } = this.pivot.getPivotMeasureValue(toString(domain.at(-1).value), domain);
|
|
56494
|
+
current.push({
|
|
56495
|
+
formula: `=PIVOT.HEADER(${generatePivotArgs(id, domain).join(",")})`,
|
|
56496
|
+
value: formatValue(value, { format, locale }),
|
|
56497
|
+
span: cell.width,
|
|
56498
|
+
isMissing: !this.tracker?.isHeaderPresent(domain),
|
|
56499
|
+
});
|
|
56500
|
+
}
|
|
56501
|
+
else {
|
|
56502
|
+
const { value, format } = this.pivot.getPivotHeaderValueAndFormat(domain);
|
|
56503
|
+
current.push({
|
|
56504
|
+
formula: `=PIVOT.HEADER(${generatePivotArgs(id, domain).join(",")})`,
|
|
56505
|
+
value: formatValue(value, { format, locale }),
|
|
56506
|
+
span: cell.width,
|
|
56507
|
+
isMissing: !this.tracker?.isHeaderPresent(domain),
|
|
56508
|
+
});
|
|
56509
|
+
}
|
|
56510
|
+
}
|
|
56511
|
+
headers.push(current);
|
|
56512
|
+
}
|
|
56513
|
+
const last = headers[headers.length - 1];
|
|
56514
|
+
headers[headers.length - 1] = last.map((cell) => {
|
|
56515
|
+
if (!cell.isMissing) {
|
|
56516
|
+
cell.style = "color: #756f6f;";
|
|
56517
|
+
}
|
|
56518
|
+
return cell;
|
|
56519
|
+
});
|
|
56520
|
+
return headers;
|
|
56521
|
+
}
|
|
56522
|
+
_buildRowHeaders(id, table) {
|
|
56523
|
+
const headers = [];
|
|
56524
|
+
for (const row of table.rows) {
|
|
56525
|
+
const args = [];
|
|
56526
|
+
for (let i = 0; i < row.fields.length; i++) {
|
|
56527
|
+
args.push({ value: row.fields[i] }, { value: row.values[i] });
|
|
56528
|
+
}
|
|
56529
|
+
const domain = this.pivot.parseArgsToPivotDomain(args);
|
|
56530
|
+
const { value, format } = this.pivot.getPivotHeaderValueAndFormat(domain);
|
|
56531
|
+
const locale = this.env.model.getters.getLocale();
|
|
56532
|
+
const cell = {
|
|
56533
|
+
formula: `=PIVOT.HEADER(${generatePivotArgs(id, domain).join(",")})`,
|
|
56534
|
+
value: formatValue(value, { format, locale }),
|
|
56535
|
+
isMissing: !this.tracker?.isHeaderPresent(domain),
|
|
56536
|
+
};
|
|
56537
|
+
if (row.indent > 1) {
|
|
56538
|
+
cell.style = `padding-left: ${row.indent - 1 * 10}px`;
|
|
56539
|
+
}
|
|
56540
|
+
headers.push(cell);
|
|
56541
|
+
}
|
|
56542
|
+
return headers;
|
|
56543
|
+
}
|
|
56544
|
+
_buildValues(id, table) {
|
|
56545
|
+
const values = [];
|
|
56546
|
+
for (const col of table.columns.at(-1) || []) {
|
|
56547
|
+
const current = [];
|
|
56548
|
+
const measure = toString(col.values[col.values.length - 1]);
|
|
56549
|
+
for (const row of table.rows) {
|
|
56550
|
+
const args = [];
|
|
56551
|
+
for (let i = 0; i < row.fields.length; i++) {
|
|
56552
|
+
args.push({ value: row.fields[i] }, { value: row.values[i] });
|
|
56553
|
+
}
|
|
56554
|
+
for (let i = 0; i < col.fields.length - 1; i++) {
|
|
56555
|
+
args.push({ value: col.fields[i] }, { value: col.values[i] });
|
|
56556
|
+
}
|
|
56557
|
+
const domain = this.pivot.parseArgsToPivotDomain(args);
|
|
56558
|
+
const { value, format } = this.pivot.getPivotCellValueAndFormat(measure, domain);
|
|
56559
|
+
const locale = this.env.model.getters.getLocale();
|
|
56560
|
+
current.push({
|
|
56561
|
+
formula: `=PIVOT.VALUE(${generatePivotArgs(id, domain, measure).join(",")})`,
|
|
56562
|
+
value: formatValue(value, { format, locale }),
|
|
56563
|
+
isMissing: !this.tracker?.isValuePresent(measure, domain),
|
|
56564
|
+
});
|
|
56565
|
+
}
|
|
56566
|
+
values.push(current);
|
|
56567
|
+
}
|
|
56568
|
+
return values;
|
|
56569
|
+
}
|
|
56570
|
+
}
|
|
56571
|
+
|
|
56072
56572
|
/**
|
|
56073
56573
|
* BasePlugin
|
|
56074
56574
|
*
|
|
@@ -57421,7 +57921,7 @@ class ChartPlugin extends CorePlugin {
|
|
|
57421
57921
|
case "CREATE_CHART":
|
|
57422
57922
|
return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartDuplicate));
|
|
57423
57923
|
case "UPDATE_CHART":
|
|
57424
|
-
return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartExists));
|
|
57924
|
+
return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartExists, this.checkChartChanged));
|
|
57425
57925
|
default:
|
|
57426
57926
|
return "Success" /* CommandResult.Success */;
|
|
57427
57927
|
}
|
|
@@ -57575,10 +58075,15 @@ class ChartPlugin extends CorePlugin {
|
|
|
57575
58075
|
: "Success" /* CommandResult.Success */;
|
|
57576
58076
|
}
|
|
57577
58077
|
checkChartExists(cmd) {
|
|
57578
|
-
return this.
|
|
58078
|
+
return this.isChartDefined(cmd.figureId)
|
|
57579
58079
|
? "Success" /* CommandResult.Success */
|
|
57580
58080
|
: "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
|
|
57581
58081
|
}
|
|
58082
|
+
checkChartChanged(cmd) {
|
|
58083
|
+
return deepEquals(this.getChartDefinition(cmd.figureId), cmd.definition)
|
|
58084
|
+
? "NoChanges" /* CommandResult.NoChanges */
|
|
58085
|
+
: "Success" /* CommandResult.Success */;
|
|
58086
|
+
}
|
|
57582
58087
|
}
|
|
57583
58088
|
|
|
57584
58089
|
// -----------------------------------------------------------------------------
|
|
@@ -59836,6 +60341,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
59836
60341
|
"getCommandZones",
|
|
59837
60342
|
"getUnboundedZone",
|
|
59838
60343
|
"checkElementsIncludeAllNonFrozenHeaders",
|
|
60344
|
+
"getDuplicateSheetName",
|
|
59839
60345
|
];
|
|
59840
60346
|
sheetIdsMapName = {};
|
|
59841
60347
|
orderedSheetIds = [];
|
|
@@ -59860,7 +60366,11 @@ class SheetPlugin extends CorePlugin {
|
|
|
59860
60366
|
return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
|
|
59861
60367
|
}
|
|
59862
60368
|
case "DUPLICATE_SHEET": {
|
|
59863
|
-
|
|
60369
|
+
if (this.sheets[cmd.sheetIdTo])
|
|
60370
|
+
return "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */;
|
|
60371
|
+
if (this.orderedSheetIds.map(this.getSheetName.bind(this)).includes(cmd.sheetNameTo))
|
|
60372
|
+
return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
|
|
60373
|
+
return "Success" /* CommandResult.Success */;
|
|
59864
60374
|
}
|
|
59865
60375
|
case "MOVE_SHEET":
|
|
59866
60376
|
try {
|
|
@@ -59937,7 +60447,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
59937
60447
|
this.showSheet(cmd.sheetId);
|
|
59938
60448
|
break;
|
|
59939
60449
|
case "DUPLICATE_SHEET":
|
|
59940
|
-
this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo);
|
|
60450
|
+
this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo, cmd.sheetNameTo);
|
|
59941
60451
|
break;
|
|
59942
60452
|
case "DELETE_SHEET":
|
|
59943
60453
|
this.deleteSheet(this.sheets[cmd.sheetId]);
|
|
@@ -60078,7 +60588,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
60078
60588
|
if (name) {
|
|
60079
60589
|
const unquotedName = getUnquotedSheetName(name);
|
|
60080
60590
|
for (const key in this.sheetIdsMapName) {
|
|
60081
|
-
if (key
|
|
60591
|
+
if (isSheetNameEqual(key, unquotedName)) {
|
|
60082
60592
|
return this.sheetIdsMapName[key];
|
|
60083
60593
|
}
|
|
60084
60594
|
}
|
|
@@ -60144,10 +60654,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
60144
60654
|
}
|
|
60145
60655
|
getNextSheetName(baseName = "Sheet") {
|
|
60146
60656
|
const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
|
|
60147
|
-
return
|
|
60148
|
-
compute: (name, i) => `${name}${i}`,
|
|
60149
|
-
computeFirstOne: true,
|
|
60150
|
-
});
|
|
60657
|
+
return getNextSheetName(names, baseName);
|
|
60151
60658
|
}
|
|
60152
60659
|
getSheetSize(sheetId) {
|
|
60153
60660
|
return {
|
|
@@ -60330,7 +60837,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
60330
60837
|
}
|
|
60331
60838
|
const { orderedSheetIds, sheets } = this;
|
|
60332
60839
|
const name = sheetName && sheetName.trim().toLowerCase();
|
|
60333
|
-
if (orderedSheetIds.find((id) => sheets[id]?.name
|
|
60840
|
+
if (orderedSheetIds.find((id) => isSheetNameEqual(sheets[id]?.name, name) && id !== cmd.sheetId)) {
|
|
60334
60841
|
return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
|
|
60335
60842
|
}
|
|
60336
60843
|
if (FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX.test(name)) {
|
|
@@ -60394,9 +60901,8 @@ class SheetPlugin extends CorePlugin {
|
|
|
60394
60901
|
showSheet(sheetId) {
|
|
60395
60902
|
this.history.update("sheets", sheetId, "isVisible", true);
|
|
60396
60903
|
}
|
|
60397
|
-
duplicateSheet(fromId, toId) {
|
|
60904
|
+
duplicateSheet(fromId, toId, toName) {
|
|
60398
60905
|
const sheet = this.getSheet(fromId);
|
|
60399
|
-
const toName = this.getDuplicateSheetName(sheet.name);
|
|
60400
60906
|
const newSheet = deepCopy(sheet);
|
|
60401
60907
|
newSheet.id = toId;
|
|
60402
60908
|
newSheet.name = toName;
|
|
@@ -60429,8 +60935,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
60429
60935
|
}
|
|
60430
60936
|
getDuplicateSheetName(sheetName) {
|
|
60431
60937
|
const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
|
|
60432
|
-
|
|
60433
|
-
return getUniqueText(baseName.toString(), names);
|
|
60938
|
+
return getDuplicateSheetName(sheetName, names);
|
|
60434
60939
|
}
|
|
60435
60940
|
deleteSheet(sheet) {
|
|
60436
60941
|
const name = sheet.name;
|
|
@@ -63234,8 +63739,8 @@ class SpreadingRelation {
|
|
|
63234
63739
|
const EMPTY_ARRAY = [];
|
|
63235
63740
|
|
|
63236
63741
|
const MAX_ITERATION = 30;
|
|
63237
|
-
const ERROR_CYCLE_CELL = createEvaluatedCell(new CircularDependencyError());
|
|
63238
|
-
const EMPTY_CELL = createEvaluatedCell({ value: null });
|
|
63742
|
+
const ERROR_CYCLE_CELL = Object.freeze(createEvaluatedCell(new CircularDependencyError()));
|
|
63743
|
+
const EMPTY_CELL = Object.freeze(createEvaluatedCell({ value: null }));
|
|
63239
63744
|
class Evaluator {
|
|
63240
63745
|
context;
|
|
63241
63746
|
getters;
|
|
@@ -69416,6 +69921,55 @@ class HistoryPlugin extends UIPlugin {
|
|
|
69416
69921
|
}
|
|
69417
69922
|
}
|
|
69418
69923
|
|
|
69924
|
+
class PivotPresenceTracker {
|
|
69925
|
+
trackedValues = new Set();
|
|
69926
|
+
domainToArray(domain) {
|
|
69927
|
+
return domain.flatMap((node) => [node.field, toString(node.value)]);
|
|
69928
|
+
}
|
|
69929
|
+
isValuePresent(measure, domain) {
|
|
69930
|
+
const key = JSON.stringify({ measure, domain: this.domainToArray(domain) });
|
|
69931
|
+
return this.trackedValues.has(key);
|
|
69932
|
+
}
|
|
69933
|
+
isHeaderPresent(domain) {
|
|
69934
|
+
const key = JSON.stringify({ domain: this.domainToArray(domain) });
|
|
69935
|
+
return this.trackedValues.has(key);
|
|
69936
|
+
}
|
|
69937
|
+
trackValue(measure, domain) {
|
|
69938
|
+
const key = JSON.stringify({ measure, domain: this.domainToArray(domain) });
|
|
69939
|
+
this.trackedValues.add(key);
|
|
69940
|
+
}
|
|
69941
|
+
trackHeader(domain) {
|
|
69942
|
+
const key = JSON.stringify({ domain: this.domainToArray(domain) });
|
|
69943
|
+
this.trackedValues.add(key);
|
|
69944
|
+
}
|
|
69945
|
+
}
|
|
69946
|
+
|
|
69947
|
+
class PivotPresencePlugin extends UIPlugin {
|
|
69948
|
+
static getters = ["getPivotPresenceTracker"];
|
|
69949
|
+
trackPresencePivotId;
|
|
69950
|
+
tracker;
|
|
69951
|
+
handle(cmd) {
|
|
69952
|
+
switch (cmd.type) {
|
|
69953
|
+
case "PIVOT_START_PRESENCE_TRACKING":
|
|
69954
|
+
this.tracker = new PivotPresenceTracker();
|
|
69955
|
+
this.trackPresencePivotId = cmd.pivotId;
|
|
69956
|
+
break;
|
|
69957
|
+
case "PIVOT_STOP_PRESENCE_TRACKING":
|
|
69958
|
+
this.trackPresencePivotId = undefined;
|
|
69959
|
+
break;
|
|
69960
|
+
}
|
|
69961
|
+
}
|
|
69962
|
+
getPivotPresenceTracker(pivotId) {
|
|
69963
|
+
if (this.trackPresencePivotId !== pivotId) {
|
|
69964
|
+
return undefined;
|
|
69965
|
+
}
|
|
69966
|
+
if (!this.tracker) {
|
|
69967
|
+
throw new Error("Tracker not initialized");
|
|
69968
|
+
}
|
|
69969
|
+
return this.tracker;
|
|
69970
|
+
}
|
|
69971
|
+
}
|
|
69972
|
+
|
|
69419
69973
|
class SplitToColumnsPlugin extends UIPlugin {
|
|
69420
69974
|
static getters = ["getAutomaticSeparator"];
|
|
69421
69975
|
allowDispatch(cmd) {
|
|
@@ -72384,6 +72938,7 @@ const featurePluginRegistry = new Registry()
|
|
|
72384
72938
|
.add("automatic_sum", AutomaticSumPlugin)
|
|
72385
72939
|
.add("format", FormatPlugin)
|
|
72386
72940
|
.add("insert_pivot", InsertPivotPlugin)
|
|
72941
|
+
.add("pivot_presence", PivotPresencePlugin)
|
|
72387
72942
|
.add("split_to_columns", SplitToColumnsPlugin)
|
|
72388
72943
|
.add("collaborative", CollaborativePlugin)
|
|
72389
72944
|
.add("history", HistoryPlugin)
|
|
@@ -72773,11 +73328,11 @@ class BottomBarSheet extends owl.Component {
|
|
|
72773
73328
|
if (ev.key === "Enter") {
|
|
72774
73329
|
ev.preventDefault();
|
|
72775
73330
|
this.stopEdition();
|
|
72776
|
-
this.DOMFocusableElementStore.
|
|
73331
|
+
this.DOMFocusableElementStore.focus();
|
|
72777
73332
|
}
|
|
72778
73333
|
if (ev.key === "Escape") {
|
|
72779
73334
|
this.cancelEdition();
|
|
72780
|
-
this.DOMFocusableElementStore.
|
|
73335
|
+
this.DOMFocusableElementStore.focus();
|
|
72781
73336
|
}
|
|
72782
73337
|
}
|
|
72783
73338
|
onMouseEventSheetName(ev) {
|
|
@@ -75338,11 +75893,13 @@ class Spreadsheet extends owl.Component {
|
|
|
75338
75893
|
this.checkViewportSize();
|
|
75339
75894
|
stores.on("store-updated", this, render);
|
|
75340
75895
|
resizeObserver.observe(this.spreadsheetRef.el);
|
|
75896
|
+
registerChartJSExtensions();
|
|
75341
75897
|
});
|
|
75342
75898
|
owl.onWillUnmount(() => {
|
|
75343
75899
|
this.unbindModelEvents();
|
|
75344
75900
|
stores.off("store-updated", this);
|
|
75345
75901
|
resizeObserver.disconnect();
|
|
75902
|
+
unregisterChartJsExtensions();
|
|
75346
75903
|
});
|
|
75347
75904
|
owl.onPatched(() => {
|
|
75348
75905
|
this.checkViewportSize();
|
|
@@ -79784,6 +80341,7 @@ const components = {
|
|
|
79784
80341
|
PivotDimensionOrder,
|
|
79785
80342
|
PivotDimension,
|
|
79786
80343
|
PivotLayoutConfigurator,
|
|
80344
|
+
PivotHTMLRenderer,
|
|
79787
80345
|
PivotDeferUpdate,
|
|
79788
80346
|
PivotTitleSection,
|
|
79789
80347
|
CogWheelMenu,
|
|
@@ -79881,6 +80439,6 @@ exports.tokenColors = tokenColors;
|
|
|
79881
80439
|
exports.tokenize = tokenize;
|
|
79882
80440
|
|
|
79883
80441
|
|
|
79884
|
-
__info__.version = "18.3.
|
|
79885
|
-
__info__.date = "2025-05-
|
|
79886
|
-
__info__.hash = "
|
|
80442
|
+
__info__.version = "18.3.3";
|
|
80443
|
+
__info__.date = "2025-05-13T17:54:43.312Z";
|
|
80444
|
+
__info__.hash = "b79924a";
|