@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
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -3319,7 +3319,7 @@ function isDateAfter(date, dateAfter) {
|
|
|
3319
3319
|
*/
|
|
3320
3320
|
const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSeparator) {
|
|
3321
3321
|
decimalSeparator = escapeRegExp(decimalSeparator);
|
|
3322
|
-
return new RegExp(`(?:^-?\\d+(?:${decimalSeparator}?\\d*(?:e
|
|
3322
|
+
return new RegExp(`(?:^-?\\d+(?:${decimalSeparator}?\\d*(?:e(\\+|-)?\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
|
|
3323
3323
|
});
|
|
3324
3324
|
const getNumberRegex = memoize(function getNumberRegex(locale) {
|
|
3325
3325
|
const decimalSeparator = escapeRegExp(locale.decimalSeparator);
|
|
@@ -6000,6 +6000,67 @@ function scrollDelay(value) {
|
|
|
6000
6000
|
return MIN_DELAY + (MAX_DELAY - MIN_DELAY) * Math.exp(-ACCELERATION * (value - 1));
|
|
6001
6001
|
}
|
|
6002
6002
|
|
|
6003
|
+
function createDefaultRows(rowNumber) {
|
|
6004
|
+
const rows = [];
|
|
6005
|
+
for (let i = 0; i < rowNumber; i++) {
|
|
6006
|
+
const row = {
|
|
6007
|
+
cells: {},
|
|
6008
|
+
};
|
|
6009
|
+
rows.push(row);
|
|
6010
|
+
}
|
|
6011
|
+
return rows;
|
|
6012
|
+
}
|
|
6013
|
+
function moveHeaderIndexesOnHeaderAddition(indexHeaderAdded, numberAdded, headers) {
|
|
6014
|
+
return headers.map((header) => {
|
|
6015
|
+
if (header >= indexHeaderAdded) {
|
|
6016
|
+
return header + numberAdded;
|
|
6017
|
+
}
|
|
6018
|
+
return header;
|
|
6019
|
+
});
|
|
6020
|
+
}
|
|
6021
|
+
function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
|
|
6022
|
+
deletedHeaders = [...deletedHeaders].sort((a, b) => b - a);
|
|
6023
|
+
return headers
|
|
6024
|
+
.map((header) => {
|
|
6025
|
+
for (const deletedHeader of deletedHeaders) {
|
|
6026
|
+
if (header > deletedHeader) {
|
|
6027
|
+
header--;
|
|
6028
|
+
}
|
|
6029
|
+
else if (header === deletedHeader) {
|
|
6030
|
+
return undefined;
|
|
6031
|
+
}
|
|
6032
|
+
}
|
|
6033
|
+
return header;
|
|
6034
|
+
})
|
|
6035
|
+
.filter(isDefined);
|
|
6036
|
+
}
|
|
6037
|
+
function getNextSheetName(existingNames, baseName = "Sheet") {
|
|
6038
|
+
let i = 1;
|
|
6039
|
+
let name = `${baseName}${i}`;
|
|
6040
|
+
while (existingNames.includes(name)) {
|
|
6041
|
+
name = `${baseName}${i}`;
|
|
6042
|
+
i++;
|
|
6043
|
+
}
|
|
6044
|
+
return name;
|
|
6045
|
+
}
|
|
6046
|
+
function getDuplicateSheetName(nameToDuplicate, existingNames) {
|
|
6047
|
+
let i = 1;
|
|
6048
|
+
const baseName = _t("Copy of %s", nameToDuplicate);
|
|
6049
|
+
let name = baseName.toString();
|
|
6050
|
+
while (existingNames.includes(name)) {
|
|
6051
|
+
name = `${baseName} (${i})`;
|
|
6052
|
+
i++;
|
|
6053
|
+
}
|
|
6054
|
+
return name;
|
|
6055
|
+
}
|
|
6056
|
+
function isSheetNameEqual(name1, name2) {
|
|
6057
|
+
if (name1 === undefined || name2 === undefined) {
|
|
6058
|
+
return false;
|
|
6059
|
+
}
|
|
6060
|
+
return (getUnquotedSheetName(name1.trim().toUpperCase()) ===
|
|
6061
|
+
getUnquotedSheetName(name2.trim().toUpperCase()));
|
|
6062
|
+
}
|
|
6063
|
+
|
|
6003
6064
|
function createRange(args, getSheetSize) {
|
|
6004
6065
|
const unboundedZone = args.zone;
|
|
6005
6066
|
const zone = boundUnboundedZone(unboundedZone, getSheetSize(args.sheetId));
|
|
@@ -6290,7 +6351,7 @@ function getApplyRangeChangeRemoveColRow(cmd) {
|
|
|
6290
6351
|
elements.sort((a, b) => b - a);
|
|
6291
6352
|
const groups = groupConsecutive(elements);
|
|
6292
6353
|
return (range) => {
|
|
6293
|
-
if (range.sheetId
|
|
6354
|
+
if (!isSheetNameEqual(range.sheetId, cmd.sheetId)) {
|
|
6294
6355
|
return { changeType: "NONE" };
|
|
6295
6356
|
}
|
|
6296
6357
|
let newRange = range;
|
|
@@ -6497,41 +6558,6 @@ function fuzzyLookup(pattern, list, fn) {
|
|
|
6497
6558
|
return results.map((r) => r.elem);
|
|
6498
6559
|
}
|
|
6499
6560
|
|
|
6500
|
-
function createDefaultRows(rowNumber) {
|
|
6501
|
-
const rows = [];
|
|
6502
|
-
for (let i = 0; i < rowNumber; i++) {
|
|
6503
|
-
const row = {
|
|
6504
|
-
cells: {},
|
|
6505
|
-
};
|
|
6506
|
-
rows.push(row);
|
|
6507
|
-
}
|
|
6508
|
-
return rows;
|
|
6509
|
-
}
|
|
6510
|
-
function moveHeaderIndexesOnHeaderAddition(indexHeaderAdded, numberAdded, headers) {
|
|
6511
|
-
return headers.map((header) => {
|
|
6512
|
-
if (header >= indexHeaderAdded) {
|
|
6513
|
-
return header + numberAdded;
|
|
6514
|
-
}
|
|
6515
|
-
return header;
|
|
6516
|
-
});
|
|
6517
|
-
}
|
|
6518
|
-
function moveHeaderIndexesOnHeaderDeletion(deletedHeaders, headers) {
|
|
6519
|
-
deletedHeaders = [...deletedHeaders].sort((a, b) => b - a);
|
|
6520
|
-
return headers
|
|
6521
|
-
.map((header) => {
|
|
6522
|
-
for (const deletedHeader of deletedHeaders) {
|
|
6523
|
-
if (header > deletedHeader) {
|
|
6524
|
-
header--;
|
|
6525
|
-
}
|
|
6526
|
-
else if (header === deletedHeader) {
|
|
6527
|
-
return undefined;
|
|
6528
|
-
}
|
|
6529
|
-
}
|
|
6530
|
-
return header;
|
|
6531
|
-
})
|
|
6532
|
-
.filter(isDefined);
|
|
6533
|
-
}
|
|
6534
|
-
|
|
6535
6561
|
function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
|
|
6536
6562
|
return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
|
|
6537
6563
|
}
|
|
@@ -8273,6 +8299,25 @@ const monthNumberAdapter = {
|
|
|
8273
8299
|
return `${normalizedValue}`;
|
|
8274
8300
|
},
|
|
8275
8301
|
};
|
|
8302
|
+
/**
|
|
8303
|
+
* normalizes month number + year
|
|
8304
|
+
*/
|
|
8305
|
+
const monthAdapter = {
|
|
8306
|
+
normalizeFunctionValue(value) {
|
|
8307
|
+
const date = toNumber(value, DEFAULT_LOCALE);
|
|
8308
|
+
return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/yyyy" });
|
|
8309
|
+
},
|
|
8310
|
+
toValueAndFormat(normalizedValue) {
|
|
8311
|
+
return {
|
|
8312
|
+
value: toNumber(normalizedValue, DEFAULT_LOCALE),
|
|
8313
|
+
format: "mmmm yyyy",
|
|
8314
|
+
};
|
|
8315
|
+
},
|
|
8316
|
+
toFunctionValue(normalizedValue) {
|
|
8317
|
+
const jsDate = toJsDate(normalizedValue, DEFAULT_LOCALE);
|
|
8318
|
+
return `DATE(${jsDate.getFullYear()},${jsDate.getMonth() + 1},1)`;
|
|
8319
|
+
},
|
|
8320
|
+
};
|
|
8276
8321
|
/**
|
|
8277
8322
|
* normalizes quarter number
|
|
8278
8323
|
*/
|
|
@@ -8408,6 +8453,7 @@ pivotTimeAdapterRegistry
|
|
|
8408
8453
|
.add("day_of_month", nullHandlerDecorator(dayOfMonthAdapter))
|
|
8409
8454
|
.add("iso_week_number", nullHandlerDecorator(isoWeekNumberAdapter))
|
|
8410
8455
|
.add("month_number", nullHandlerDecorator(monthNumberAdapter))
|
|
8456
|
+
.add("month", nullHandlerDecorator(monthAdapter))
|
|
8411
8457
|
.add("quarter_number", nullHandlerDecorator(quarterNumberAdapter))
|
|
8412
8458
|
.add("day_of_week", nullHandlerDecorator(dayOfWeekAdapter))
|
|
8413
8459
|
.add("hour_number", nullHandlerDecorator(hourNumberAdapter))
|
|
@@ -8424,10 +8470,9 @@ const AGGREGATOR_NAMES = {
|
|
|
8424
8470
|
avg: _t("Average"),
|
|
8425
8471
|
sum: _t("Sum"),
|
|
8426
8472
|
};
|
|
8427
|
-
const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
|
|
8428
8473
|
const AGGREGATORS_BY_FIELD_TYPE = {
|
|
8429
|
-
integer:
|
|
8430
|
-
char:
|
|
8474
|
+
integer: ["max", "min", "avg", "sum", "count_distinct", "count"],
|
|
8475
|
+
char: ["count_distinct", "count"],
|
|
8431
8476
|
boolean: ["count_distinct", "count", "bool_and", "bool_or"],
|
|
8432
8477
|
datetime: ["max", "min", "count_distinct", "count"],
|
|
8433
8478
|
};
|
|
@@ -8588,10 +8633,7 @@ function toNormalizedPivotValue(dimension, groupValue) {
|
|
|
8588
8633
|
return normalizer(groupValueString, dimension.granularity);
|
|
8589
8634
|
}
|
|
8590
8635
|
function normalizeDateTime(value, granularity) {
|
|
8591
|
-
|
|
8592
|
-
throw new Error("Missing granularity");
|
|
8593
|
-
}
|
|
8594
|
-
return pivotTimeAdapter(granularity).normalizeFunctionValue(value);
|
|
8636
|
+
return pivotTimeAdapter(granularity ?? "month").normalizeFunctionValue(value);
|
|
8595
8637
|
}
|
|
8596
8638
|
function toFunctionPivotValue(value, dimension) {
|
|
8597
8639
|
if (value === null) {
|
|
@@ -8603,10 +8645,7 @@ function toFunctionPivotValue(value, dimension) {
|
|
|
8603
8645
|
return pivotToFunctionValueRegistry.get(dimension.type)(value, dimension.granularity);
|
|
8604
8646
|
}
|
|
8605
8647
|
function toFunctionValueDateTime(value, granularity) {
|
|
8606
|
-
|
|
8607
|
-
throw new Error("Missing granularity");
|
|
8608
|
-
}
|
|
8609
|
-
return pivotTimeAdapter(granularity).toFunctionValue(value);
|
|
8648
|
+
return pivotTimeAdapter(granularity ?? "month").toFunctionValue(value);
|
|
8610
8649
|
}
|
|
8611
8650
|
const pivotNormalizationValueRegistry = new Registry();
|
|
8612
8651
|
pivotNormalizationValueRegistry
|
|
@@ -9801,7 +9840,10 @@ function proxifyStoreMutation(store, callback) {
|
|
|
9801
9840
|
const functionProxy = new Proxy(value, {
|
|
9802
9841
|
// trap the function call
|
|
9803
9842
|
apply(target, thisArg, argArray) {
|
|
9804
|
-
Reflect.apply(target, thisStore, argArray);
|
|
9843
|
+
const res = Reflect.apply(target, thisStore, argArray);
|
|
9844
|
+
if (res === "noStateChange") {
|
|
9845
|
+
return;
|
|
9846
|
+
}
|
|
9805
9847
|
callback();
|
|
9806
9848
|
},
|
|
9807
9849
|
});
|
|
@@ -9823,7 +9865,7 @@ function getDependencyContainer(env) {
|
|
|
9823
9865
|
const ModelStore = createAbstractStore("Model");
|
|
9824
9866
|
|
|
9825
9867
|
class RendererStore {
|
|
9826
|
-
mutators = ["register", "unRegister"];
|
|
9868
|
+
mutators = ["register", "unRegister", "drawLayer"];
|
|
9827
9869
|
renderers = {};
|
|
9828
9870
|
register(renderer) {
|
|
9829
9871
|
if (!renderer.renderingLayers.length) {
|
|
@@ -9843,14 +9885,14 @@ class RendererStore {
|
|
|
9843
9885
|
}
|
|
9844
9886
|
drawLayer(context, layer) {
|
|
9845
9887
|
const renderers = this.renderers[layer];
|
|
9846
|
-
if (
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
context.ctx.restore();
|
|
9888
|
+
if (renderers) {
|
|
9889
|
+
for (const renderer of renderers) {
|
|
9890
|
+
context.ctx.save();
|
|
9891
|
+
renderer.drawLayer(context, layer);
|
|
9892
|
+
context.ctx.restore();
|
|
9893
|
+
}
|
|
9853
9894
|
}
|
|
9895
|
+
return "noStateChange";
|
|
9854
9896
|
}
|
|
9855
9897
|
}
|
|
9856
9898
|
|
|
@@ -9903,16 +9945,17 @@ class ComposerFocusStore extends SpreadsheetStore {
|
|
|
9903
9945
|
focusComposer(listener, args) {
|
|
9904
9946
|
this.activeComposer = listener;
|
|
9905
9947
|
if (this.getters.isReadonly()) {
|
|
9906
|
-
return;
|
|
9948
|
+
return "noStateChange";
|
|
9907
9949
|
}
|
|
9908
9950
|
this._focusMode = args.focusMode || "contentFocus";
|
|
9909
9951
|
if (this._focusMode !== "inactive") {
|
|
9910
9952
|
this.setComposerContent(args);
|
|
9911
9953
|
}
|
|
9954
|
+
return;
|
|
9912
9955
|
}
|
|
9913
9956
|
focusActiveComposer(args) {
|
|
9914
9957
|
if (this.getters.isReadonly()) {
|
|
9915
|
-
return;
|
|
9958
|
+
return "noStateChange";
|
|
9916
9959
|
}
|
|
9917
9960
|
if (!this.activeComposer) {
|
|
9918
9961
|
throw new Error("No composer is registered");
|
|
@@ -9921,6 +9964,7 @@ class ComposerFocusStore extends SpreadsheetStore {
|
|
|
9921
9964
|
if (this._focusMode !== "inactive") {
|
|
9922
9965
|
this.setComposerContent(args);
|
|
9923
9966
|
}
|
|
9967
|
+
return;
|
|
9924
9968
|
}
|
|
9925
9969
|
/**
|
|
9926
9970
|
* Start the edition or update the content if it's already started.
|
|
@@ -10080,20 +10124,24 @@ function getElementMargins(el) {
|
|
|
10080
10124
|
}
|
|
10081
10125
|
|
|
10082
10126
|
const chartJsExtensionRegistry = new Registry();
|
|
10083
|
-
|
|
10084
|
-
|
|
10085
|
-
|
|
10086
|
-
|
|
10087
|
-
|
|
10088
|
-
|
|
10089
|
-
|
|
10090
|
-
|
|
10091
|
-
|
|
10092
|
-
|
|
10093
|
-
|
|
10094
|
-
|
|
10127
|
+
function areChartJSExtensionsLoaded() {
|
|
10128
|
+
return !!window.Chart.registry.plugins.get("chartShowValuesPlugin");
|
|
10129
|
+
}
|
|
10130
|
+
function registerChartJSExtensions() {
|
|
10131
|
+
if (!window.Chart || areChartJSExtensionsLoaded()) {
|
|
10132
|
+
return;
|
|
10133
|
+
}
|
|
10134
|
+
for (const registryItem of chartJsExtensionRegistry.getAll()) {
|
|
10135
|
+
registryItem.register(window.Chart);
|
|
10136
|
+
}
|
|
10137
|
+
}
|
|
10138
|
+
function unregisterChartJsExtensions() {
|
|
10139
|
+
if (!window.Chart) {
|
|
10140
|
+
return;
|
|
10141
|
+
}
|
|
10142
|
+
for (const registryItem of chartJsExtensionRegistry.getAll()) {
|
|
10143
|
+
registryItem.unregister(window.Chart);
|
|
10095
10144
|
}
|
|
10096
|
-
return window.Chart;
|
|
10097
10145
|
}
|
|
10098
10146
|
|
|
10099
10147
|
function getFunnelChartController() {
|
|
@@ -10520,7 +10568,7 @@ function getDefinedAxis(definition) {
|
|
|
10520
10568
|
}
|
|
10521
10569
|
function formatChartDatasetValue(axisFormats, locale) {
|
|
10522
10570
|
return (value, axisId) => {
|
|
10523
|
-
const format =
|
|
10571
|
+
const format = axisFormats?.[axisId];
|
|
10524
10572
|
return formatTickValue({ format, locale })(value);
|
|
10525
10573
|
};
|
|
10526
10574
|
}
|
|
@@ -10697,7 +10745,7 @@ function drawPieChartValues(chart, options, ctx) {
|
|
|
10697
10745
|
const y = bar.y + midRadius * Math.sin(midAngle) + 7;
|
|
10698
10746
|
ctx.fillStyle = chartFontColor(options.background);
|
|
10699
10747
|
ctx.strokeStyle = options.background || "#ffffff";
|
|
10700
|
-
const displayValue = options.callback(value);
|
|
10748
|
+
const displayValue = options.callback(value, "y");
|
|
10701
10749
|
drawTextWithBackground(displayValue, x, y, ctx);
|
|
10702
10750
|
}
|
|
10703
10751
|
}
|
|
@@ -11459,13 +11507,35 @@ css /* scss */ `
|
|
|
11459
11507
|
}
|
|
11460
11508
|
}
|
|
11461
11509
|
`;
|
|
11462
|
-
chartJsExtensionRegistry.add("chartShowValuesPlugin",
|
|
11463
|
-
|
|
11464
|
-
|
|
11465
|
-
|
|
11466
|
-
chartJsExtensionRegistry.add("
|
|
11467
|
-
|
|
11468
|
-
|
|
11510
|
+
chartJsExtensionRegistry.add("chartShowValuesPlugin", {
|
|
11511
|
+
register: (Chart) => Chart.register(chartShowValuesPlugin),
|
|
11512
|
+
unregister: (Chart) => Chart.unregister(chartShowValuesPlugin),
|
|
11513
|
+
});
|
|
11514
|
+
chartJsExtensionRegistry.add("waterfallLinesPlugin", {
|
|
11515
|
+
register: (Chart) => Chart.register(waterfallLinesPlugin),
|
|
11516
|
+
unregister: (Chart) => Chart.unregister(waterfallLinesPlugin),
|
|
11517
|
+
});
|
|
11518
|
+
chartJsExtensionRegistry.add("funnelController", {
|
|
11519
|
+
register: (Chart) => Chart.register(getFunnelChartController()),
|
|
11520
|
+
unregister: (Chart) => Chart.unregister(getFunnelChartController()),
|
|
11521
|
+
});
|
|
11522
|
+
chartJsExtensionRegistry.add("funnelElement", {
|
|
11523
|
+
register: (Chart) => Chart.register(getFunnelChartElement()),
|
|
11524
|
+
unregister: (Chart) => Chart.unregister(getFunnelChartElement()),
|
|
11525
|
+
});
|
|
11526
|
+
chartJsExtensionRegistry.add("funnelTooltipPositioner", {
|
|
11527
|
+
register: (Chart) => (Chart.Tooltip.positioners.funnelTooltipPositioner = funnelTooltipPositioner),
|
|
11528
|
+
// @ts-expect-error
|
|
11529
|
+
unregister: (Chart) => (Chart.Tooltip.positioners.funnelTooltipPositioner = undefined),
|
|
11530
|
+
});
|
|
11531
|
+
chartJsExtensionRegistry.add("sunburstLabelsPlugin", {
|
|
11532
|
+
register: (Chart) => Chart.register(sunburstLabelsPlugin),
|
|
11533
|
+
unregister: (Chart) => Chart.unregister(sunburstLabelsPlugin),
|
|
11534
|
+
});
|
|
11535
|
+
chartJsExtensionRegistry.add("sunburstHoverPlugin", {
|
|
11536
|
+
register: (Chart) => Chart.register(sunburstHoverPlugin),
|
|
11537
|
+
unregister: (Chart) => Chart.unregister(sunburstHoverPlugin),
|
|
11538
|
+
});
|
|
11469
11539
|
class ChartJsComponent extends Component {
|
|
11470
11540
|
static template = "o-spreadsheet-ChartJsComponent";
|
|
11471
11541
|
static props = {
|
|
@@ -11517,8 +11587,7 @@ class ChartJsComponent extends Component {
|
|
|
11517
11587
|
createChart(chartData) {
|
|
11518
11588
|
const canvas = this.canvas.el;
|
|
11519
11589
|
const ctx = canvas.getContext("2d");
|
|
11520
|
-
|
|
11521
|
-
this.chart = new Chart(ctx, chartData);
|
|
11590
|
+
this.chart = new window.Chart(ctx, chartData);
|
|
11522
11591
|
}
|
|
11523
11592
|
updateChartJs(chartData) {
|
|
11524
11593
|
if (chartData.data && chartData.data.datasets) {
|
|
@@ -19823,7 +19892,7 @@ const IF = {
|
|
|
19823
19892
|
return { value: "" };
|
|
19824
19893
|
}
|
|
19825
19894
|
if (result.value === null) {
|
|
19826
|
-
result
|
|
19895
|
+
return { ...result, value: "" };
|
|
19827
19896
|
}
|
|
19828
19897
|
return result;
|
|
19829
19898
|
},
|
|
@@ -19844,7 +19913,7 @@ const IFERROR = {
|
|
|
19844
19913
|
return { value: "" };
|
|
19845
19914
|
}
|
|
19846
19915
|
if (result.value === null) {
|
|
19847
|
-
result
|
|
19916
|
+
return { ...result, value: "" };
|
|
19848
19917
|
}
|
|
19849
19918
|
return result;
|
|
19850
19919
|
},
|
|
@@ -19865,7 +19934,7 @@ const IFNA = {
|
|
|
19865
19934
|
return { value: "" };
|
|
19866
19935
|
}
|
|
19867
19936
|
if (result.value === null) {
|
|
19868
|
-
result
|
|
19937
|
+
return { ...result, value: "" };
|
|
19869
19938
|
}
|
|
19870
19939
|
return result;
|
|
19871
19940
|
},
|
|
@@ -19891,7 +19960,7 @@ const IFS = {
|
|
|
19891
19960
|
return { value: "" };
|
|
19892
19961
|
}
|
|
19893
19962
|
if (result.value === null) {
|
|
19894
|
-
result
|
|
19963
|
+
return { ...result, value: "" };
|
|
19895
19964
|
}
|
|
19896
19965
|
return result;
|
|
19897
19966
|
}
|
|
@@ -20038,6 +20107,11 @@ function addPivotDependencies(evalContext, coreDefinition, forMeasures) {
|
|
|
20038
20107
|
if (range === undefined || range.invalidXc || range.invalidSheetName) {
|
|
20039
20108
|
throw new InvalidReferenceError();
|
|
20040
20109
|
}
|
|
20110
|
+
if (evalContext.__originCellPosition &&
|
|
20111
|
+
range.sheetId === evalContext.__originSheetId &&
|
|
20112
|
+
isZoneInside(positionToZone(evalContext.__originCellPosition), zone)) {
|
|
20113
|
+
throw new CircularDependencyError();
|
|
20114
|
+
}
|
|
20041
20115
|
dependencies.push(range);
|
|
20042
20116
|
}
|
|
20043
20117
|
for (const measure of forMeasures) {
|
|
@@ -20480,6 +20554,9 @@ const PIVOT_VALUE = {
|
|
|
20480
20554
|
};
|
|
20481
20555
|
}
|
|
20482
20556
|
const domain = pivot.parseArgsToPivotDomain(domainArgs);
|
|
20557
|
+
if (this.getters.getActiveSheetId() === this.__originSheetId) {
|
|
20558
|
+
this.getters.getPivotPresenceTracker(pivotId)?.trackValue(_measure, domain);
|
|
20559
|
+
}
|
|
20483
20560
|
return pivot.getPivotCellValueAndFormat(_measure, domain);
|
|
20484
20561
|
},
|
|
20485
20562
|
};
|
|
@@ -20511,6 +20588,9 @@ const PIVOT_HEADER = {
|
|
|
20511
20588
|
};
|
|
20512
20589
|
}
|
|
20513
20590
|
const domain = pivot.parseArgsToPivotDomain(domainArgs);
|
|
20591
|
+
if (this.getters.getActiveSheetId() === this.__originSheetId) {
|
|
20592
|
+
this.getters.getPivotPresenceTracker(_pivotId)?.trackHeader(domain);
|
|
20593
|
+
}
|
|
20514
20594
|
const lastNode = domain.at(-1);
|
|
20515
20595
|
if (lastNode?.field === "measure") {
|
|
20516
20596
|
return pivot.getPivotMeasureValue(toString(lastNode.value), domain);
|
|
@@ -20733,6 +20813,9 @@ function isEmpty(data) {
|
|
|
20733
20813
|
return data === undefined || data.value === null;
|
|
20734
20814
|
}
|
|
20735
20815
|
const getNeutral = { number: 0, string: "", boolean: false };
|
|
20816
|
+
function areAlmostEqual(value1, value2, epsilon = 2e-16) {
|
|
20817
|
+
return Math.abs(value1 - value2) < epsilon;
|
|
20818
|
+
}
|
|
20736
20819
|
const EQ = {
|
|
20737
20820
|
description: _t("Equal."),
|
|
20738
20821
|
args: [
|
|
@@ -20754,6 +20837,9 @@ const EQ = {
|
|
|
20754
20837
|
if (typeof _value2 === "string") {
|
|
20755
20838
|
_value2 = _value2.toUpperCase();
|
|
20756
20839
|
}
|
|
20840
|
+
if (typeof _value1 === "number" && typeof _value2 === "number") {
|
|
20841
|
+
return { value: areAlmostEqual(_value1, _value2) };
|
|
20842
|
+
}
|
|
20757
20843
|
return { value: _value1 === _value2 };
|
|
20758
20844
|
},
|
|
20759
20845
|
};
|
|
@@ -20793,6 +20879,9 @@ const GT = {
|
|
|
20793
20879
|
],
|
|
20794
20880
|
compute: function (value1, value2) {
|
|
20795
20881
|
return applyRelationalOperator(value1, value2, (v1, v2) => {
|
|
20882
|
+
if (typeof v1 === "number" && typeof v2 === "number") {
|
|
20883
|
+
return !areAlmostEqual(v1, v2) && v1 > v2;
|
|
20884
|
+
}
|
|
20796
20885
|
return v1 > v2;
|
|
20797
20886
|
});
|
|
20798
20887
|
},
|
|
@@ -20808,6 +20897,9 @@ const GTE = {
|
|
|
20808
20897
|
],
|
|
20809
20898
|
compute: function (value1, value2) {
|
|
20810
20899
|
return applyRelationalOperator(value1, value2, (v1, v2) => {
|
|
20900
|
+
if (typeof v1 === "number" && typeof v2 === "number") {
|
|
20901
|
+
return areAlmostEqual(v1, v2) || v1 > v2;
|
|
20902
|
+
}
|
|
20811
20903
|
return v1 >= v2;
|
|
20812
20904
|
});
|
|
20813
20905
|
},
|
|
@@ -22500,7 +22592,7 @@ class AbstractComposerStore extends SpreadsheetStore {
|
|
|
22500
22592
|
.find((token) => {
|
|
22501
22593
|
const { xc, sheetName: sheet } = splitReference(token.value);
|
|
22502
22594
|
const sheetName = sheet || this.getters.getSheetName(this.sheetId);
|
|
22503
|
-
if (this.getters.getSheetName(activeSheetId)
|
|
22595
|
+
if (!isSheetNameEqual(this.getters.getSheetName(activeSheetId), sheetName)) {
|
|
22504
22596
|
return false;
|
|
22505
22597
|
}
|
|
22506
22598
|
const refRange = this.getters.getRangeFromSheetXC(activeSheetId, xc);
|
|
@@ -24397,6 +24489,7 @@ const CHART_COMMON_OPTIONS = {
|
|
|
24397
24489
|
},
|
|
24398
24490
|
},
|
|
24399
24491
|
animation: false,
|
|
24492
|
+
events: ["mousemove", "mouseout", "click", "touchstart", "touchmove", "mouseup"],
|
|
24400
24493
|
};
|
|
24401
24494
|
function chartToImageUrl(runtime, figure, type) {
|
|
24402
24495
|
// wrap the canvas in a div with a fixed size because chart.js would
|
|
@@ -24436,6 +24529,8 @@ async function chartToImageFile(runtime, figure, type) {
|
|
|
24436
24529
|
const div = document.createElement("div");
|
|
24437
24530
|
div.style.width = `${figure.width}px`;
|
|
24438
24531
|
div.style.height = `${figure.height}px`;
|
|
24532
|
+
div.style.position = "fixed";
|
|
24533
|
+
div.style.opacity = "0";
|
|
24439
24534
|
const canvas = document.createElement("canvas");
|
|
24440
24535
|
div.append(canvas);
|
|
24441
24536
|
canvas.setAttribute("width", figure.width.toString());
|
|
@@ -24446,8 +24541,7 @@ async function chartToImageFile(runtime, figure, type) {
|
|
|
24446
24541
|
if ("chartJsConfig" in runtime) {
|
|
24447
24542
|
const config = deepCopy(runtime.chartJsConfig);
|
|
24448
24543
|
config.plugins = [backgroundColorChartJSPlugin];
|
|
24449
|
-
const
|
|
24450
|
-
const chart = new Chart(canvas, config);
|
|
24544
|
+
const chart = new window.Chart(canvas, config);
|
|
24451
24545
|
chartBlob = await new Promise((resolve) => canvas.toBlob(resolve, "image/png"));
|
|
24452
24546
|
chart.destroy();
|
|
24453
24547
|
}
|
|
@@ -25199,11 +25293,10 @@ function canBeLinearChart(definition, dataSets, labelRange, getters) {
|
|
|
25199
25293
|
}
|
|
25200
25294
|
let missingTimeAdapterAlreadyWarned = false;
|
|
25201
25295
|
function isLuxonTimeAdapterInstalled() {
|
|
25202
|
-
|
|
25203
|
-
if (!Chart) {
|
|
25296
|
+
if (!window.Chart) {
|
|
25204
25297
|
return false;
|
|
25205
25298
|
}
|
|
25206
|
-
const adapter = new Chart._adapters._date({});
|
|
25299
|
+
const adapter = new window.Chart._adapters._date({});
|
|
25207
25300
|
// @ts-ignore
|
|
25208
25301
|
const isInstalled = adapter._id === "luxon";
|
|
25209
25302
|
if (!isInstalled && !missingTimeAdapterAlreadyWarned) {
|
|
@@ -25701,6 +25794,9 @@ const INTERACTIVE_LEGEND_CONFIG = {
|
|
|
25701
25794
|
target.style.cursor = "default";
|
|
25702
25795
|
},
|
|
25703
25796
|
onClick: (event, legendItem, legend) => {
|
|
25797
|
+
if (event.type !== "click") {
|
|
25798
|
+
return;
|
|
25799
|
+
}
|
|
25704
25800
|
const index = legendItem.datasetIndex;
|
|
25705
25801
|
if (!legend.legendItems || index === undefined) {
|
|
25706
25802
|
return;
|
|
@@ -29637,10 +29733,15 @@ function getChartMenu(figureId, onFigureDeleted, env) {
|
|
|
29637
29733
|
const imageUrl = chartToImageUrl(runtime, figure, chartType);
|
|
29638
29734
|
const innerHTML = `<img src="${xmlEscape(imageUrl)}" />`;
|
|
29639
29735
|
const blob = await chartToImageFile(runtime, figure, chartType);
|
|
29640
|
-
env.clipboard.write({
|
|
29736
|
+
await env.clipboard.write({
|
|
29641
29737
|
"text/html": innerHTML,
|
|
29642
29738
|
"image/png": blob,
|
|
29643
29739
|
});
|
|
29740
|
+
env.notifyUser({
|
|
29741
|
+
text: _t("The chart was copied to your clipboard"),
|
|
29742
|
+
sticky: false,
|
|
29743
|
+
type: "info",
|
|
29744
|
+
});
|
|
29644
29745
|
},
|
|
29645
29746
|
},
|
|
29646
29747
|
{
|
|
@@ -31490,7 +31591,7 @@ function getRangeSize(reference, defaultSheetIndex, data) {
|
|
|
31490
31591
|
({ xc, sheetName } = splitReference(reference));
|
|
31491
31592
|
let rangeSheetIndex;
|
|
31492
31593
|
if (sheetName) {
|
|
31493
|
-
const index = data.sheets.findIndex((sheet) => sheet.name
|
|
31594
|
+
const index = data.sheets.findIndex((sheet) => isSheetNameEqual(sheet.name, sheetName));
|
|
31494
31595
|
if (index < 0) {
|
|
31495
31596
|
throw new Error("Unable to find a sheet with the name " + sheetName);
|
|
31496
31597
|
}
|
|
@@ -31847,7 +31948,7 @@ function convertFormula(formula, data) {
|
|
|
31847
31948
|
formula = formula.replace(externalReferenceRegex, (match, externalRefId, sheetName, cellRef) => {
|
|
31848
31949
|
externalRefId = Number(externalRefId) - 1;
|
|
31849
31950
|
cellRef = cellRef.replace(/\$/g, "");
|
|
31850
|
-
const sheetIndex = data.externalBooks[externalRefId].sheetNames.findIndex((name) => name
|
|
31951
|
+
const sheetIndex = data.externalBooks[externalRefId].sheetNames.findIndex((name) => isSheetNameEqual(name, sheetName));
|
|
31851
31952
|
if (sheetIndex === -1) {
|
|
31852
31953
|
return match;
|
|
31853
31954
|
}
|
|
@@ -32498,7 +32599,7 @@ function convertPivotTableConfig(pivotTable) {
|
|
|
32498
32599
|
*/
|
|
32499
32600
|
function convertTableFormulaReferences(convertedSheets, xlsxSheets) {
|
|
32500
32601
|
for (let tableSheet of convertedSheets) {
|
|
32501
|
-
const tables = xlsxSheets.find((s) => s.sheetName
|
|
32602
|
+
const tables = xlsxSheets.find((s) => isSheetNameEqual(s.sheetName, tableSheet.name)).tables;
|
|
32502
32603
|
for (let table of tables) {
|
|
32503
32604
|
const tabRef = table.name + "[";
|
|
32504
32605
|
for (let sheet of convertedSheets) {
|
|
@@ -34847,6 +34948,7 @@ function repairInitialMessages(data, initialMessages) {
|
|
|
34847
34948
|
initialMessages = dropCommands(initialMessages, "SET_DECIMAL");
|
|
34848
34949
|
initialMessages = fixChartDefinitions(data, initialMessages);
|
|
34849
34950
|
initialMessages = fixFigureOffset(data, initialMessages);
|
|
34951
|
+
initialMessages = fixTranslatedDuplicateSheetName(data, initialMessages);
|
|
34850
34952
|
return initialMessages;
|
|
34851
34953
|
}
|
|
34852
34954
|
/**
|
|
@@ -34979,6 +35081,42 @@ function fixFigureOffset(data, messages) {
|
|
|
34979
35081
|
}
|
|
34980
35082
|
return messages;
|
|
34981
35083
|
}
|
|
35084
|
+
function fixTranslatedDuplicateSheetName(data, initialMessages) {
|
|
35085
|
+
const sheetNames = {};
|
|
35086
|
+
for (const sheet of data.sheets || []) {
|
|
35087
|
+
sheetNames[sheet.id] = sheet.name;
|
|
35088
|
+
}
|
|
35089
|
+
const messages = [];
|
|
35090
|
+
for (const message of initialMessages) {
|
|
35091
|
+
if (message.type === "REMOTE_REVISION") {
|
|
35092
|
+
const commands = [];
|
|
35093
|
+
for (const cmd of message.commands) {
|
|
35094
|
+
switch (cmd.type) {
|
|
35095
|
+
case "DUPLICATE_SHEET":
|
|
35096
|
+
cmd.sheetNameTo =
|
|
35097
|
+
cmd.sheetNameTo ??
|
|
35098
|
+
getDuplicateSheetName(sheetNames[cmd.sheetId], Object.values(sheetNames));
|
|
35099
|
+
break;
|
|
35100
|
+
case "CREATE_SHEET":
|
|
35101
|
+
sheetNames[cmd.sheetId] = cmd.name || getNextSheetName(Object.values(sheetNames));
|
|
35102
|
+
break;
|
|
35103
|
+
case "RENAME_SHEET":
|
|
35104
|
+
sheetNames[cmd.sheetId] = cmd.newName || getNextSheetName(Object.values(sheetNames));
|
|
35105
|
+
break;
|
|
35106
|
+
}
|
|
35107
|
+
commands.push(cmd);
|
|
35108
|
+
}
|
|
35109
|
+
messages.push({
|
|
35110
|
+
...message,
|
|
35111
|
+
commands,
|
|
35112
|
+
});
|
|
35113
|
+
}
|
|
35114
|
+
else {
|
|
35115
|
+
messages.push(message);
|
|
35116
|
+
}
|
|
35117
|
+
}
|
|
35118
|
+
return initialMessages;
|
|
35119
|
+
}
|
|
34982
35120
|
// -----------------------------------------------------------------------------
|
|
34983
35121
|
// Helpers
|
|
34984
35122
|
// -----------------------------------------------------------------------------
|
|
@@ -35116,12 +35254,20 @@ class DelayedHoveredCellStore extends SpreadsheetStore {
|
|
|
35116
35254
|
}
|
|
35117
35255
|
}
|
|
35118
35256
|
hover(position) {
|
|
35257
|
+
if (position.col === this.col && position.row === this.row) {
|
|
35258
|
+
return "noStateChange";
|
|
35259
|
+
}
|
|
35119
35260
|
this.col = position.col;
|
|
35120
35261
|
this.row = position.row;
|
|
35262
|
+
return;
|
|
35121
35263
|
}
|
|
35122
35264
|
clear() {
|
|
35265
|
+
if (this.col === undefined && this.row === undefined) {
|
|
35266
|
+
return "noStateChange";
|
|
35267
|
+
}
|
|
35123
35268
|
this.col = undefined;
|
|
35124
35269
|
this.row = undefined;
|
|
35270
|
+
return;
|
|
35125
35271
|
}
|
|
35126
35272
|
}
|
|
35127
35273
|
|
|
@@ -35143,7 +35289,11 @@ class CellPopoverStore extends SpreadsheetStore {
|
|
|
35143
35289
|
this.persistentPopover = { col, row, sheetId, type };
|
|
35144
35290
|
}
|
|
35145
35291
|
close() {
|
|
35292
|
+
if (!this.persistentPopover) {
|
|
35293
|
+
return "noStateChange";
|
|
35294
|
+
}
|
|
35146
35295
|
this.persistentPopover = undefined;
|
|
35296
|
+
return;
|
|
35147
35297
|
}
|
|
35148
35298
|
get persistentCellPopover() {
|
|
35149
35299
|
return ((this.persistentPopover && { isOpen: true, ...this.persistentPopover }) || { isOpen: false });
|
|
@@ -36037,10 +36187,13 @@ const duplicateSheet = {
|
|
|
36037
36187
|
name: _t("Duplicate"),
|
|
36038
36188
|
execute: (env) => {
|
|
36039
36189
|
const sheetIdFrom = env.model.getters.getActiveSheetId();
|
|
36190
|
+
const sheetNameFrom = env.model.getters.getSheetName(sheetIdFrom);
|
|
36040
36191
|
const sheetIdTo = env.model.uuidGenerator.smallUuid();
|
|
36192
|
+
const sheetNameTo = env.model.getters.getDuplicateSheetName(sheetNameFrom);
|
|
36041
36193
|
env.model.dispatch("DUPLICATE_SHEET", {
|
|
36042
36194
|
sheetId: sheetIdFrom,
|
|
36043
36195
|
sheetIdTo,
|
|
36196
|
+
sheetNameTo,
|
|
36044
36197
|
});
|
|
36045
36198
|
env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom, sheetIdTo });
|
|
36046
36199
|
},
|
|
@@ -40681,7 +40834,7 @@ class GenericChartConfigPanel extends Component {
|
|
|
40681
40834
|
const cancelledReasons = [
|
|
40682
40835
|
...(this.state.datasetDispatchResult?.reasons || []),
|
|
40683
40836
|
...(this.state.labelsDispatchResult?.reasons || []),
|
|
40684
|
-
];
|
|
40837
|
+
].filter((reason) => reason !== "NoChanges" /* CommandResult.NoChanges */);
|
|
40685
40838
|
return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
|
|
40686
40839
|
}
|
|
40687
40840
|
get isDatasetInvalid() {
|
|
@@ -42258,10 +42411,18 @@ class GaugeChartConfigPanel extends Component {
|
|
|
42258
42411
|
}
|
|
42259
42412
|
|
|
42260
42413
|
class DOMFocusableElementStore {
|
|
42261
|
-
mutators = ["setFocusableElement"];
|
|
42414
|
+
mutators = ["setFocusableElement", "focus"];
|
|
42262
42415
|
focusableElement = undefined;
|
|
42263
42416
|
setFocusableElement(element) {
|
|
42264
42417
|
this.focusableElement = element;
|
|
42418
|
+
return "noStateChange";
|
|
42419
|
+
}
|
|
42420
|
+
focus() {
|
|
42421
|
+
if (this.focusableElement === document.activeElement) {
|
|
42422
|
+
return "noStateChange";
|
|
42423
|
+
}
|
|
42424
|
+
this.focusableElement?.focus();
|
|
42425
|
+
return;
|
|
42265
42426
|
}
|
|
42266
42427
|
}
|
|
42267
42428
|
|
|
@@ -42933,7 +43094,7 @@ class Composer extends Component {
|
|
|
42933
43094
|
if (document.activeElement === this.contentHelper.el &&
|
|
42934
43095
|
this.props.composerStore.editionMode === "inactive" &&
|
|
42935
43096
|
!this.props.isDefaultFocus) {
|
|
42936
|
-
this.DOMFocusableElementStore.
|
|
43097
|
+
this.DOMFocusableElementStore.focus();
|
|
42937
43098
|
}
|
|
42938
43099
|
});
|
|
42939
43100
|
useEffect(() => {
|
|
@@ -43213,6 +43374,13 @@ class Composer extends Component {
|
|
|
43213
43374
|
openAssistant() {
|
|
43214
43375
|
this.assistant.forcedClosed = false;
|
|
43215
43376
|
}
|
|
43377
|
+
onWheel(event) {
|
|
43378
|
+
// detect if scrollbar is available
|
|
43379
|
+
if (this.composerRef.el &&
|
|
43380
|
+
this.composerRef.el.scrollHeight > this.composerRef.el.clientHeight) {
|
|
43381
|
+
event.stopPropagation();
|
|
43382
|
+
}
|
|
43383
|
+
}
|
|
43216
43384
|
// ---------------------------------------------------------------------------
|
|
43217
43385
|
// Private
|
|
43218
43386
|
// ---------------------------------------------------------------------------
|
|
@@ -48937,8 +49105,8 @@ function compareDimensionValues(dimension, a, b) {
|
|
|
48937
49105
|
|
|
48938
49106
|
const NULL_SYMBOL = Symbol("NULL");
|
|
48939
49107
|
function createDate(dimension, value, locale) {
|
|
48940
|
-
const granularity = dimension.granularity;
|
|
48941
|
-
if (!
|
|
49108
|
+
const granularity = dimension.granularity || "month";
|
|
49109
|
+
if (!(granularity in MAP_VALUE_DIMENSION_DATE)) {
|
|
48942
49110
|
throw new Error(`Unknown date granularity: ${granularity}`);
|
|
48943
49111
|
}
|
|
48944
49112
|
const keyInMap = typeof value === "number" || typeof value === "string" ? value : NULL_SYMBOL;
|
|
@@ -48957,6 +49125,9 @@ function createDate(dimension, value, locale) {
|
|
|
48957
49125
|
case "month_number":
|
|
48958
49126
|
number = date.getMonth() + 1;
|
|
48959
49127
|
break;
|
|
49128
|
+
case "month":
|
|
49129
|
+
number = Math.floor(toNumber(value, locale));
|
|
49130
|
+
break;
|
|
48960
49131
|
case "iso_week_number":
|
|
48961
49132
|
number = date.getIsoWeek();
|
|
48962
49133
|
break;
|
|
@@ -49050,6 +49221,10 @@ const MAP_VALUE_DIMENSION_DATE = {
|
|
|
49050
49221
|
set: new Set(),
|
|
49051
49222
|
values: {},
|
|
49052
49223
|
},
|
|
49224
|
+
month: {
|
|
49225
|
+
set: new Set(),
|
|
49226
|
+
values: {},
|
|
49227
|
+
},
|
|
49053
49228
|
iso_week_number: {
|
|
49054
49229
|
set: new Set(),
|
|
49055
49230
|
values: {},
|
|
@@ -49260,7 +49435,7 @@ class SpreadsheetPivot {
|
|
|
49260
49435
|
const cells = this.filterDataEntriesFromDomain(this.dataEntries, domain);
|
|
49261
49436
|
const finalCell = cells[0]?.[dimension.nameWithGranularity];
|
|
49262
49437
|
if (dimension.type === "datetime") {
|
|
49263
|
-
const adapter = pivotTimeAdapter(dimension.granularity);
|
|
49438
|
+
const adapter = pivotTimeAdapter((dimension.granularity || "month"));
|
|
49264
49439
|
return adapter.toValueAndFormat(lastNode.value, this.getters.getLocale());
|
|
49265
49440
|
}
|
|
49266
49441
|
if (!finalCell) {
|
|
@@ -49378,7 +49553,7 @@ class SpreadsheetPivot {
|
|
|
49378
49553
|
if (nonEmptyCells.length === 0) {
|
|
49379
49554
|
return "integer";
|
|
49380
49555
|
}
|
|
49381
|
-
if (nonEmptyCells.every((cell) => cell.format && isDateTimeFormat(cell.format))) {
|
|
49556
|
+
if (nonEmptyCells.every((cell) => cell.type === CellValueType.number && cell.format && isDateTimeFormat(cell.format))) {
|
|
49382
49557
|
return "datetime";
|
|
49383
49558
|
}
|
|
49384
49559
|
if (nonEmptyCells.every((cell) => cell.type === CellValueType.boolean)) {
|
|
@@ -49457,7 +49632,12 @@ class SpreadsheetPivot {
|
|
|
49457
49632
|
entry[field.name] = { value: null, type: CellValueType.empty, formattedValue: "" };
|
|
49458
49633
|
}
|
|
49459
49634
|
else {
|
|
49460
|
-
|
|
49635
|
+
if (field.type === "char") {
|
|
49636
|
+
entry[field.name] = { ...cell, value: cell.formattedValue || null };
|
|
49637
|
+
}
|
|
49638
|
+
else {
|
|
49639
|
+
entry[field.name] = cell;
|
|
49640
|
+
}
|
|
49461
49641
|
}
|
|
49462
49642
|
}
|
|
49463
49643
|
entry["__count"] = { value: 1, type: CellValueType.number, formattedValue: "1" };
|
|
@@ -49471,7 +49651,7 @@ class SpreadsheetPivot {
|
|
|
49471
49651
|
for (const entry of dataEntries) {
|
|
49472
49652
|
for (const dimension of dateDimensions) {
|
|
49473
49653
|
const value = createDate(dimension, entry[dimension.fieldName]?.value || null, this.getters.getLocale());
|
|
49474
|
-
const adapter = pivotTimeAdapter(dimension.granularity);
|
|
49654
|
+
const adapter = pivotTimeAdapter((dimension.granularity || "month"));
|
|
49475
49655
|
const { format, value: valueToFormat } = adapter.toValueAndFormat(value, locale);
|
|
49476
49656
|
entry[dimension.nameWithGranularity] = {
|
|
49477
49657
|
value,
|
|
@@ -49491,6 +49671,7 @@ const dateGranularities = [
|
|
|
49491
49671
|
"year",
|
|
49492
49672
|
"quarter_number",
|
|
49493
49673
|
"month_number",
|
|
49674
|
+
"month",
|
|
49494
49675
|
"iso_week_number",
|
|
49495
49676
|
"day_of_month",
|
|
49496
49677
|
"day",
|
|
@@ -49741,7 +49922,7 @@ class PivotSidePanelStore extends SpreadsheetStore {
|
|
|
49741
49922
|
: this.datetimeGranularities);
|
|
49742
49923
|
}
|
|
49743
49924
|
for (const field of dateFields) {
|
|
49744
|
-
granularitiesPerFields[field.fieldName].delete(field.granularity);
|
|
49925
|
+
granularitiesPerFields[field.fieldName].delete(field.granularity || "month");
|
|
49745
49926
|
}
|
|
49746
49927
|
return granularitiesPerFields;
|
|
49747
49928
|
}
|
|
@@ -52081,6 +52262,8 @@ class GridComposer extends Component {
|
|
|
52081
52262
|
}
|
|
52082
52263
|
get composerProps() {
|
|
52083
52264
|
const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
|
|
52265
|
+
// Remove the wrapper border width
|
|
52266
|
+
const maxHeight = this.props.gridDims.height - this.rect.y - 2 * COMPOSER_BORDER_WIDTH;
|
|
52084
52267
|
return {
|
|
52085
52268
|
rect: { ...this.rect },
|
|
52086
52269
|
delimitation: {
|
|
@@ -52098,6 +52281,7 @@ class GridComposer extends Component {
|
|
|
52098
52281
|
}),
|
|
52099
52282
|
onInputContextMenu: this.props.onInputContextMenu,
|
|
52100
52283
|
composerStore: this.composerStore,
|
|
52284
|
+
inputStyle: `max-height: ${maxHeight}px;`,
|
|
52101
52285
|
};
|
|
52102
52286
|
}
|
|
52103
52287
|
get containerStyle() {
|
|
@@ -53178,9 +53362,13 @@ class HoveredTableStore extends SpreadsheetStore {
|
|
|
53178
53362
|
}
|
|
53179
53363
|
}
|
|
53180
53364
|
hover(position) {
|
|
53365
|
+
if (position.col === this.col && position.row === this.row) {
|
|
53366
|
+
return "noStateChange";
|
|
53367
|
+
}
|
|
53181
53368
|
this.col = position.col;
|
|
53182
53369
|
this.row = position.row;
|
|
53183
53370
|
this.computeOverlay();
|
|
53371
|
+
return;
|
|
53184
53372
|
}
|
|
53185
53373
|
clear() {
|
|
53186
53374
|
this.col = undefined;
|
|
@@ -54812,10 +55000,6 @@ function useGridDrawing(refName, model, canvasSize) {
|
|
|
54812
55000
|
ctx.scale(dpr, dpr);
|
|
54813
55001
|
for (const layer of OrderedLayers()) {
|
|
54814
55002
|
model.drawLayer(renderingContext, layer);
|
|
54815
|
-
// @ts-ignore 'drawLayer' is not declated as a mutator because:
|
|
54816
|
-
// it does not mutate anything. Most importantly it's used
|
|
54817
|
-
// during rendering. Invoking a mutator during rendering would
|
|
54818
|
-
// trigger another rendering, ultimately resulting in an infinite loop.
|
|
54819
55003
|
rendererStore.drawLayer(renderingContext, layer);
|
|
54820
55004
|
}
|
|
54821
55005
|
}
|
|
@@ -55509,7 +55693,7 @@ class Grid extends Component {
|
|
|
55509
55693
|
this.cellPopovers = useStore(CellPopoverStore);
|
|
55510
55694
|
useEffect(() => {
|
|
55511
55695
|
if (!this.sidePanel.isOpen) {
|
|
55512
|
-
this.DOMFocusableElementStore.
|
|
55696
|
+
this.DOMFocusableElementStore.focus();
|
|
55513
55697
|
}
|
|
55514
55698
|
}, () => [this.sidePanel.isOpen]);
|
|
55515
55699
|
useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
|
|
@@ -55718,7 +55902,7 @@ class Grid extends Component {
|
|
|
55718
55902
|
focusDefaultElement() {
|
|
55719
55903
|
if (!this.env.model.getters.getSelectedFigureId() &&
|
|
55720
55904
|
this.composerFocusStore.activeComposer.editionMode === "inactive") {
|
|
55721
|
-
this.DOMFocusableElementStore.
|
|
55905
|
+
this.DOMFocusableElementStore.focus();
|
|
55722
55906
|
}
|
|
55723
55907
|
}
|
|
55724
55908
|
get gridEl() {
|
|
@@ -56067,6 +56251,322 @@ class Grid extends Component {
|
|
|
56067
56251
|
}
|
|
56068
56252
|
}
|
|
56069
56253
|
|
|
56254
|
+
css /* scss */ `
|
|
56255
|
+
.o_pivot_html_renderer {
|
|
56256
|
+
width: 100%;
|
|
56257
|
+
border-collapse: collapse;
|
|
56258
|
+
|
|
56259
|
+
&:hover {
|
|
56260
|
+
cursor: pointer;
|
|
56261
|
+
}
|
|
56262
|
+
|
|
56263
|
+
td,
|
|
56264
|
+
th {
|
|
56265
|
+
border: 1px solid #dee2e6;
|
|
56266
|
+
background-color: #fff;
|
|
56267
|
+
padding: 0.3rem;
|
|
56268
|
+
white-space: nowrap;
|
|
56269
|
+
|
|
56270
|
+
&:hover {
|
|
56271
|
+
filter: brightness(0.9);
|
|
56272
|
+
}
|
|
56273
|
+
}
|
|
56274
|
+
|
|
56275
|
+
td {
|
|
56276
|
+
text-align: right;
|
|
56277
|
+
}
|
|
56278
|
+
|
|
56279
|
+
th {
|
|
56280
|
+
background-color: #f5f5f5;
|
|
56281
|
+
font-weight: bold;
|
|
56282
|
+
color: black;
|
|
56283
|
+
}
|
|
56284
|
+
|
|
56285
|
+
.o_missing_value {
|
|
56286
|
+
color: #46646d;
|
|
56287
|
+
background: #e7f2f6;
|
|
56288
|
+
}
|
|
56289
|
+
}
|
|
56290
|
+
`;
|
|
56291
|
+
class PivotHTMLRenderer extends Component {
|
|
56292
|
+
static template = "o_spreadsheet.PivotHTMLRenderer";
|
|
56293
|
+
static components = { Checkbox };
|
|
56294
|
+
static props = {
|
|
56295
|
+
pivotId: String,
|
|
56296
|
+
onCellClicked: Function,
|
|
56297
|
+
};
|
|
56298
|
+
pivot = this.env.model.getters.getPivot(this.props.pivotId);
|
|
56299
|
+
data = {
|
|
56300
|
+
columns: [],
|
|
56301
|
+
rows: [],
|
|
56302
|
+
values: [],
|
|
56303
|
+
};
|
|
56304
|
+
state = useState({
|
|
56305
|
+
showMissingValuesOnly: false,
|
|
56306
|
+
});
|
|
56307
|
+
setup() {
|
|
56308
|
+
const table = this.pivot.getTableStructure();
|
|
56309
|
+
const formulaId = this.env.model.getters.getPivotFormulaId(this.props.pivotId);
|
|
56310
|
+
this.data = {
|
|
56311
|
+
columns: this._buildColHeaders(formulaId, table),
|
|
56312
|
+
rows: this._buildRowHeaders(formulaId, table),
|
|
56313
|
+
values: this._buildValues(formulaId, table),
|
|
56314
|
+
};
|
|
56315
|
+
}
|
|
56316
|
+
get tracker() {
|
|
56317
|
+
return this.env.model.getters.getPivotPresenceTracker(this.props.pivotId);
|
|
56318
|
+
}
|
|
56319
|
+
// ---------------------------------------------------------------------
|
|
56320
|
+
// Missing values building
|
|
56321
|
+
// ---------------------------------------------------------------------
|
|
56322
|
+
/**
|
|
56323
|
+
* Retrieve the data to display in the Pivot Table
|
|
56324
|
+
* In the case when showMissingValuesOnly is false, the returned value
|
|
56325
|
+
* is the complete data
|
|
56326
|
+
* In the case when showMissingValuesOnly is true, the returned value is
|
|
56327
|
+
* the data which contains only missing values in the rows and cols. In
|
|
56328
|
+
* the rows, we also return the parent rows of rows which contains missing
|
|
56329
|
+
* values, to give context to the user.
|
|
56330
|
+
*
|
|
56331
|
+
*/
|
|
56332
|
+
getTableData() {
|
|
56333
|
+
if (!this.state.showMissingValuesOnly) {
|
|
56334
|
+
return this.data;
|
|
56335
|
+
}
|
|
56336
|
+
const colIndexes = this.getColumnsIndexes();
|
|
56337
|
+
const rowIndexes = this.getRowsIndexes();
|
|
56338
|
+
const columns = this.buildColumnsMissing(colIndexes);
|
|
56339
|
+
const rows = this.buildRowsMissing(rowIndexes);
|
|
56340
|
+
const values = this.buildValuesMissing(colIndexes, rowIndexes);
|
|
56341
|
+
return { columns, rows, values };
|
|
56342
|
+
}
|
|
56343
|
+
/**
|
|
56344
|
+
* Retrieve the parents of the given row
|
|
56345
|
+
* ex:
|
|
56346
|
+
* Australia
|
|
56347
|
+
* January
|
|
56348
|
+
* February
|
|
56349
|
+
* The parent of "January" is "Australia"
|
|
56350
|
+
*/
|
|
56351
|
+
addRecursiveRow(index) {
|
|
56352
|
+
const rows = this.pivot.getTableStructure().rows;
|
|
56353
|
+
const row = [...rows[index].values];
|
|
56354
|
+
if (row.length <= 1) {
|
|
56355
|
+
return [index];
|
|
56356
|
+
}
|
|
56357
|
+
row.pop();
|
|
56358
|
+
const parentRowIndex = rows.findIndex((r) => JSON.stringify(r.values) === JSON.stringify(row));
|
|
56359
|
+
return [index].concat(this.addRecursiveRow(parentRowIndex));
|
|
56360
|
+
}
|
|
56361
|
+
/**
|
|
56362
|
+
* Create the columns to be used, based on the indexes of the columns in
|
|
56363
|
+
* which a missing value is present
|
|
56364
|
+
*
|
|
56365
|
+
*/
|
|
56366
|
+
buildColumnsMissing(indexes) {
|
|
56367
|
+
// columnsMap explode the columns in an array of array of the same
|
|
56368
|
+
// size with the index of each column, repeated 'span' times.
|
|
56369
|
+
// ex:
|
|
56370
|
+
// | A | B |
|
|
56371
|
+
// | 1 | 2 | 3 |
|
|
56372
|
+
// => [
|
|
56373
|
+
// [0, 0, 1]
|
|
56374
|
+
// [0, 1, 2]
|
|
56375
|
+
// ]
|
|
56376
|
+
const columnsMap = [];
|
|
56377
|
+
for (const column of this.data.columns) {
|
|
56378
|
+
const columnMap = [];
|
|
56379
|
+
for (const index in column) {
|
|
56380
|
+
for (let i = 0; i < column[index].span; i++) {
|
|
56381
|
+
columnMap.push(parseInt(index, 10));
|
|
56382
|
+
}
|
|
56383
|
+
}
|
|
56384
|
+
columnsMap.push(columnMap);
|
|
56385
|
+
}
|
|
56386
|
+
// Remove the columns that are not present in indexes
|
|
56387
|
+
for (let i = columnsMap[columnsMap.length - 1].length; i >= 0; i--) {
|
|
56388
|
+
if (!indexes.includes(i)) {
|
|
56389
|
+
for (const columnMap of columnsMap) {
|
|
56390
|
+
columnMap.splice(i, 1);
|
|
56391
|
+
}
|
|
56392
|
+
}
|
|
56393
|
+
}
|
|
56394
|
+
// Build the columns
|
|
56395
|
+
const columns = [];
|
|
56396
|
+
for (const mapIndex in columnsMap) {
|
|
56397
|
+
const column = [];
|
|
56398
|
+
let index = undefined;
|
|
56399
|
+
let span = 1;
|
|
56400
|
+
for (let i = 0; i < columnsMap[mapIndex].length; i++) {
|
|
56401
|
+
if (index !== columnsMap[mapIndex][i]) {
|
|
56402
|
+
if (index !== undefined) {
|
|
56403
|
+
column.push(Object.assign({}, this.data.columns[mapIndex][index], { span }));
|
|
56404
|
+
}
|
|
56405
|
+
index = columnsMap[mapIndex][i];
|
|
56406
|
+
span = 1;
|
|
56407
|
+
}
|
|
56408
|
+
else {
|
|
56409
|
+
span++;
|
|
56410
|
+
}
|
|
56411
|
+
}
|
|
56412
|
+
if (index !== undefined) {
|
|
56413
|
+
column.push(Object.assign({}, this.data.columns[mapIndex][index], { span }));
|
|
56414
|
+
}
|
|
56415
|
+
columns.push(column);
|
|
56416
|
+
}
|
|
56417
|
+
return columns;
|
|
56418
|
+
}
|
|
56419
|
+
/**
|
|
56420
|
+
* Create the rows to be used, based on the indexes of the rows in
|
|
56421
|
+
* which a missing value is present.
|
|
56422
|
+
*/
|
|
56423
|
+
buildRowsMissing(indexes) {
|
|
56424
|
+
return indexes.map((index) => this.data.rows[index]);
|
|
56425
|
+
}
|
|
56426
|
+
/**
|
|
56427
|
+
* Create the value to be used, based on the indexes of the columns and
|
|
56428
|
+
* rows in which a missing value is present.
|
|
56429
|
+
*/
|
|
56430
|
+
buildValuesMissing(colIndexes, rowIndexes) {
|
|
56431
|
+
const values = colIndexes.map(() => []);
|
|
56432
|
+
for (const row of rowIndexes) {
|
|
56433
|
+
for (const col in colIndexes) {
|
|
56434
|
+
values[col].push(this.data.values[colIndexes[col]][row]);
|
|
56435
|
+
}
|
|
56436
|
+
}
|
|
56437
|
+
return values;
|
|
56438
|
+
}
|
|
56439
|
+
getColumnsIndexes() {
|
|
56440
|
+
const indexes = new Set();
|
|
56441
|
+
for (let i = 0; i < this.data.columns.length; i++) {
|
|
56442
|
+
const exploded = [];
|
|
56443
|
+
for (let y = 0; y < this.data.columns[i].length; y++) {
|
|
56444
|
+
for (let x = 0; x < this.data.columns[i][y].span; x++) {
|
|
56445
|
+
exploded.push(this.data.columns[i][y]);
|
|
56446
|
+
}
|
|
56447
|
+
}
|
|
56448
|
+
for (let y = 0; y < exploded.length; y++) {
|
|
56449
|
+
if (exploded[y].isMissing) {
|
|
56450
|
+
indexes.add(y);
|
|
56451
|
+
}
|
|
56452
|
+
}
|
|
56453
|
+
}
|
|
56454
|
+
for (let i = 0; i < this.data.columns[this.data.columns.length - 1].length; i++) {
|
|
56455
|
+
const values = this.data.values[i];
|
|
56456
|
+
if (values.find((x) => x.isMissing)) {
|
|
56457
|
+
indexes.add(i);
|
|
56458
|
+
}
|
|
56459
|
+
}
|
|
56460
|
+
return Array.from(indexes).sort((a, b) => a - b);
|
|
56461
|
+
}
|
|
56462
|
+
getRowsIndexes() {
|
|
56463
|
+
const rowIndexes = new Set();
|
|
56464
|
+
for (let i = 0; i < this.data.rows.length; i++) {
|
|
56465
|
+
if (this.data.rows[i].isMissing) {
|
|
56466
|
+
rowIndexes.add(i);
|
|
56467
|
+
}
|
|
56468
|
+
for (const col of this.data.values) {
|
|
56469
|
+
if (col[i].isMissing) {
|
|
56470
|
+
this.addRecursiveRow(i).forEach((x) => rowIndexes.add(x));
|
|
56471
|
+
}
|
|
56472
|
+
}
|
|
56473
|
+
}
|
|
56474
|
+
return Array.from(rowIndexes).sort((a, b) => a - b);
|
|
56475
|
+
}
|
|
56476
|
+
// ---------------------------------------------------------------------
|
|
56477
|
+
// Data table creation
|
|
56478
|
+
// ---------------------------------------------------------------------
|
|
56479
|
+
_buildColHeaders(id, table) {
|
|
56480
|
+
const headers = [];
|
|
56481
|
+
for (const row of table.columns) {
|
|
56482
|
+
const current = [];
|
|
56483
|
+
for (const cell of row) {
|
|
56484
|
+
const args = [];
|
|
56485
|
+
for (let i = 0; i < cell.fields.length; i++) {
|
|
56486
|
+
args.push({ value: cell.fields[i] }, { value: cell.values[i] });
|
|
56487
|
+
}
|
|
56488
|
+
const domain = this.pivot.parseArgsToPivotDomain(args);
|
|
56489
|
+
const locale = this.env.model.getters.getLocale();
|
|
56490
|
+
if (domain.at(-1)?.field === "measure") {
|
|
56491
|
+
const { value, format } = this.pivot.getPivotMeasureValue(toString(domain.at(-1).value), domain);
|
|
56492
|
+
current.push({
|
|
56493
|
+
formula: `=PIVOT.HEADER(${generatePivotArgs(id, domain).join(",")})`,
|
|
56494
|
+
value: formatValue(value, { format, locale }),
|
|
56495
|
+
span: cell.width,
|
|
56496
|
+
isMissing: !this.tracker?.isHeaderPresent(domain),
|
|
56497
|
+
});
|
|
56498
|
+
}
|
|
56499
|
+
else {
|
|
56500
|
+
const { value, format } = this.pivot.getPivotHeaderValueAndFormat(domain);
|
|
56501
|
+
current.push({
|
|
56502
|
+
formula: `=PIVOT.HEADER(${generatePivotArgs(id, domain).join(",")})`,
|
|
56503
|
+
value: formatValue(value, { format, locale }),
|
|
56504
|
+
span: cell.width,
|
|
56505
|
+
isMissing: !this.tracker?.isHeaderPresent(domain),
|
|
56506
|
+
});
|
|
56507
|
+
}
|
|
56508
|
+
}
|
|
56509
|
+
headers.push(current);
|
|
56510
|
+
}
|
|
56511
|
+
const last = headers[headers.length - 1];
|
|
56512
|
+
headers[headers.length - 1] = last.map((cell) => {
|
|
56513
|
+
if (!cell.isMissing) {
|
|
56514
|
+
cell.style = "color: #756f6f;";
|
|
56515
|
+
}
|
|
56516
|
+
return cell;
|
|
56517
|
+
});
|
|
56518
|
+
return headers;
|
|
56519
|
+
}
|
|
56520
|
+
_buildRowHeaders(id, table) {
|
|
56521
|
+
const headers = [];
|
|
56522
|
+
for (const row of table.rows) {
|
|
56523
|
+
const args = [];
|
|
56524
|
+
for (let i = 0; i < row.fields.length; i++) {
|
|
56525
|
+
args.push({ value: row.fields[i] }, { value: row.values[i] });
|
|
56526
|
+
}
|
|
56527
|
+
const domain = this.pivot.parseArgsToPivotDomain(args);
|
|
56528
|
+
const { value, format } = this.pivot.getPivotHeaderValueAndFormat(domain);
|
|
56529
|
+
const locale = this.env.model.getters.getLocale();
|
|
56530
|
+
const cell = {
|
|
56531
|
+
formula: `=PIVOT.HEADER(${generatePivotArgs(id, domain).join(",")})`,
|
|
56532
|
+
value: formatValue(value, { format, locale }),
|
|
56533
|
+
isMissing: !this.tracker?.isHeaderPresent(domain),
|
|
56534
|
+
};
|
|
56535
|
+
if (row.indent > 1) {
|
|
56536
|
+
cell.style = `padding-left: ${row.indent - 1 * 10}px`;
|
|
56537
|
+
}
|
|
56538
|
+
headers.push(cell);
|
|
56539
|
+
}
|
|
56540
|
+
return headers;
|
|
56541
|
+
}
|
|
56542
|
+
_buildValues(id, table) {
|
|
56543
|
+
const values = [];
|
|
56544
|
+
for (const col of table.columns.at(-1) || []) {
|
|
56545
|
+
const current = [];
|
|
56546
|
+
const measure = toString(col.values[col.values.length - 1]);
|
|
56547
|
+
for (const row of table.rows) {
|
|
56548
|
+
const args = [];
|
|
56549
|
+
for (let i = 0; i < row.fields.length; i++) {
|
|
56550
|
+
args.push({ value: row.fields[i] }, { value: row.values[i] });
|
|
56551
|
+
}
|
|
56552
|
+
for (let i = 0; i < col.fields.length - 1; i++) {
|
|
56553
|
+
args.push({ value: col.fields[i] }, { value: col.values[i] });
|
|
56554
|
+
}
|
|
56555
|
+
const domain = this.pivot.parseArgsToPivotDomain(args);
|
|
56556
|
+
const { value, format } = this.pivot.getPivotCellValueAndFormat(measure, domain);
|
|
56557
|
+
const locale = this.env.model.getters.getLocale();
|
|
56558
|
+
current.push({
|
|
56559
|
+
formula: `=PIVOT.VALUE(${generatePivotArgs(id, domain, measure).join(",")})`,
|
|
56560
|
+
value: formatValue(value, { format, locale }),
|
|
56561
|
+
isMissing: !this.tracker?.isValuePresent(measure, domain),
|
|
56562
|
+
});
|
|
56563
|
+
}
|
|
56564
|
+
values.push(current);
|
|
56565
|
+
}
|
|
56566
|
+
return values;
|
|
56567
|
+
}
|
|
56568
|
+
}
|
|
56569
|
+
|
|
56070
56570
|
/**
|
|
56071
56571
|
* BasePlugin
|
|
56072
56572
|
*
|
|
@@ -57419,7 +57919,7 @@ class ChartPlugin extends CorePlugin {
|
|
|
57419
57919
|
case "CREATE_CHART":
|
|
57420
57920
|
return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartDuplicate));
|
|
57421
57921
|
case "UPDATE_CHART":
|
|
57422
|
-
return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartExists));
|
|
57922
|
+
return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartExists, this.checkChartChanged));
|
|
57423
57923
|
default:
|
|
57424
57924
|
return "Success" /* CommandResult.Success */;
|
|
57425
57925
|
}
|
|
@@ -57573,10 +58073,15 @@ class ChartPlugin extends CorePlugin {
|
|
|
57573
58073
|
: "Success" /* CommandResult.Success */;
|
|
57574
58074
|
}
|
|
57575
58075
|
checkChartExists(cmd) {
|
|
57576
|
-
return this.
|
|
58076
|
+
return this.isChartDefined(cmd.figureId)
|
|
57577
58077
|
? "Success" /* CommandResult.Success */
|
|
57578
58078
|
: "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
|
|
57579
58079
|
}
|
|
58080
|
+
checkChartChanged(cmd) {
|
|
58081
|
+
return deepEquals(this.getChartDefinition(cmd.figureId), cmd.definition)
|
|
58082
|
+
? "NoChanges" /* CommandResult.NoChanges */
|
|
58083
|
+
: "Success" /* CommandResult.Success */;
|
|
58084
|
+
}
|
|
57580
58085
|
}
|
|
57581
58086
|
|
|
57582
58087
|
// -----------------------------------------------------------------------------
|
|
@@ -59834,6 +60339,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
59834
60339
|
"getCommandZones",
|
|
59835
60340
|
"getUnboundedZone",
|
|
59836
60341
|
"checkElementsIncludeAllNonFrozenHeaders",
|
|
60342
|
+
"getDuplicateSheetName",
|
|
59837
60343
|
];
|
|
59838
60344
|
sheetIdsMapName = {};
|
|
59839
60345
|
orderedSheetIds = [];
|
|
@@ -59858,7 +60364,11 @@ class SheetPlugin extends CorePlugin {
|
|
|
59858
60364
|
return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
|
|
59859
60365
|
}
|
|
59860
60366
|
case "DUPLICATE_SHEET": {
|
|
59861
|
-
|
|
60367
|
+
if (this.sheets[cmd.sheetIdTo])
|
|
60368
|
+
return "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */;
|
|
60369
|
+
if (this.orderedSheetIds.map(this.getSheetName.bind(this)).includes(cmd.sheetNameTo))
|
|
60370
|
+
return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
|
|
60371
|
+
return "Success" /* CommandResult.Success */;
|
|
59862
60372
|
}
|
|
59863
60373
|
case "MOVE_SHEET":
|
|
59864
60374
|
try {
|
|
@@ -59935,7 +60445,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
59935
60445
|
this.showSheet(cmd.sheetId);
|
|
59936
60446
|
break;
|
|
59937
60447
|
case "DUPLICATE_SHEET":
|
|
59938
|
-
this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo);
|
|
60448
|
+
this.duplicateSheet(cmd.sheetId, cmd.sheetIdTo, cmd.sheetNameTo);
|
|
59939
60449
|
break;
|
|
59940
60450
|
case "DELETE_SHEET":
|
|
59941
60451
|
this.deleteSheet(this.sheets[cmd.sheetId]);
|
|
@@ -60076,7 +60586,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
60076
60586
|
if (name) {
|
|
60077
60587
|
const unquotedName = getUnquotedSheetName(name);
|
|
60078
60588
|
for (const key in this.sheetIdsMapName) {
|
|
60079
|
-
if (key
|
|
60589
|
+
if (isSheetNameEqual(key, unquotedName)) {
|
|
60080
60590
|
return this.sheetIdsMapName[key];
|
|
60081
60591
|
}
|
|
60082
60592
|
}
|
|
@@ -60142,10 +60652,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
60142
60652
|
}
|
|
60143
60653
|
getNextSheetName(baseName = "Sheet") {
|
|
60144
60654
|
const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
|
|
60145
|
-
return
|
|
60146
|
-
compute: (name, i) => `${name}${i}`,
|
|
60147
|
-
computeFirstOne: true,
|
|
60148
|
-
});
|
|
60655
|
+
return getNextSheetName(names, baseName);
|
|
60149
60656
|
}
|
|
60150
60657
|
getSheetSize(sheetId) {
|
|
60151
60658
|
return {
|
|
@@ -60328,7 +60835,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
60328
60835
|
}
|
|
60329
60836
|
const { orderedSheetIds, sheets } = this;
|
|
60330
60837
|
const name = sheetName && sheetName.trim().toLowerCase();
|
|
60331
|
-
if (orderedSheetIds.find((id) => sheets[id]?.name
|
|
60838
|
+
if (orderedSheetIds.find((id) => isSheetNameEqual(sheets[id]?.name, name) && id !== cmd.sheetId)) {
|
|
60332
60839
|
return "DuplicatedSheetName" /* CommandResult.DuplicatedSheetName */;
|
|
60333
60840
|
}
|
|
60334
60841
|
if (FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX.test(name)) {
|
|
@@ -60392,9 +60899,8 @@ class SheetPlugin extends CorePlugin {
|
|
|
60392
60899
|
showSheet(sheetId) {
|
|
60393
60900
|
this.history.update("sheets", sheetId, "isVisible", true);
|
|
60394
60901
|
}
|
|
60395
|
-
duplicateSheet(fromId, toId) {
|
|
60902
|
+
duplicateSheet(fromId, toId, toName) {
|
|
60396
60903
|
const sheet = this.getSheet(fromId);
|
|
60397
|
-
const toName = this.getDuplicateSheetName(sheet.name);
|
|
60398
60904
|
const newSheet = deepCopy(sheet);
|
|
60399
60905
|
newSheet.id = toId;
|
|
60400
60906
|
newSheet.name = toName;
|
|
@@ -60427,8 +60933,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
60427
60933
|
}
|
|
60428
60934
|
getDuplicateSheetName(sheetName) {
|
|
60429
60935
|
const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
|
|
60430
|
-
|
|
60431
|
-
return getUniqueText(baseName.toString(), names);
|
|
60936
|
+
return getDuplicateSheetName(sheetName, names);
|
|
60432
60937
|
}
|
|
60433
60938
|
deleteSheet(sheet) {
|
|
60434
60939
|
const name = sheet.name;
|
|
@@ -63232,8 +63737,8 @@ class SpreadingRelation {
|
|
|
63232
63737
|
const EMPTY_ARRAY = [];
|
|
63233
63738
|
|
|
63234
63739
|
const MAX_ITERATION = 30;
|
|
63235
|
-
const ERROR_CYCLE_CELL = createEvaluatedCell(new CircularDependencyError());
|
|
63236
|
-
const EMPTY_CELL = createEvaluatedCell({ value: null });
|
|
63740
|
+
const ERROR_CYCLE_CELL = Object.freeze(createEvaluatedCell(new CircularDependencyError()));
|
|
63741
|
+
const EMPTY_CELL = Object.freeze(createEvaluatedCell({ value: null }));
|
|
63237
63742
|
class Evaluator {
|
|
63238
63743
|
context;
|
|
63239
63744
|
getters;
|
|
@@ -69414,6 +69919,55 @@ class HistoryPlugin extends UIPlugin {
|
|
|
69414
69919
|
}
|
|
69415
69920
|
}
|
|
69416
69921
|
|
|
69922
|
+
class PivotPresenceTracker {
|
|
69923
|
+
trackedValues = new Set();
|
|
69924
|
+
domainToArray(domain) {
|
|
69925
|
+
return domain.flatMap((node) => [node.field, toString(node.value)]);
|
|
69926
|
+
}
|
|
69927
|
+
isValuePresent(measure, domain) {
|
|
69928
|
+
const key = JSON.stringify({ measure, domain: this.domainToArray(domain) });
|
|
69929
|
+
return this.trackedValues.has(key);
|
|
69930
|
+
}
|
|
69931
|
+
isHeaderPresent(domain) {
|
|
69932
|
+
const key = JSON.stringify({ domain: this.domainToArray(domain) });
|
|
69933
|
+
return this.trackedValues.has(key);
|
|
69934
|
+
}
|
|
69935
|
+
trackValue(measure, domain) {
|
|
69936
|
+
const key = JSON.stringify({ measure, domain: this.domainToArray(domain) });
|
|
69937
|
+
this.trackedValues.add(key);
|
|
69938
|
+
}
|
|
69939
|
+
trackHeader(domain) {
|
|
69940
|
+
const key = JSON.stringify({ domain: this.domainToArray(domain) });
|
|
69941
|
+
this.trackedValues.add(key);
|
|
69942
|
+
}
|
|
69943
|
+
}
|
|
69944
|
+
|
|
69945
|
+
class PivotPresencePlugin extends UIPlugin {
|
|
69946
|
+
static getters = ["getPivotPresenceTracker"];
|
|
69947
|
+
trackPresencePivotId;
|
|
69948
|
+
tracker;
|
|
69949
|
+
handle(cmd) {
|
|
69950
|
+
switch (cmd.type) {
|
|
69951
|
+
case "PIVOT_START_PRESENCE_TRACKING":
|
|
69952
|
+
this.tracker = new PivotPresenceTracker();
|
|
69953
|
+
this.trackPresencePivotId = cmd.pivotId;
|
|
69954
|
+
break;
|
|
69955
|
+
case "PIVOT_STOP_PRESENCE_TRACKING":
|
|
69956
|
+
this.trackPresencePivotId = undefined;
|
|
69957
|
+
break;
|
|
69958
|
+
}
|
|
69959
|
+
}
|
|
69960
|
+
getPivotPresenceTracker(pivotId) {
|
|
69961
|
+
if (this.trackPresencePivotId !== pivotId) {
|
|
69962
|
+
return undefined;
|
|
69963
|
+
}
|
|
69964
|
+
if (!this.tracker) {
|
|
69965
|
+
throw new Error("Tracker not initialized");
|
|
69966
|
+
}
|
|
69967
|
+
return this.tracker;
|
|
69968
|
+
}
|
|
69969
|
+
}
|
|
69970
|
+
|
|
69417
69971
|
class SplitToColumnsPlugin extends UIPlugin {
|
|
69418
69972
|
static getters = ["getAutomaticSeparator"];
|
|
69419
69973
|
allowDispatch(cmd) {
|
|
@@ -72382,6 +72936,7 @@ const featurePluginRegistry = new Registry()
|
|
|
72382
72936
|
.add("automatic_sum", AutomaticSumPlugin)
|
|
72383
72937
|
.add("format", FormatPlugin)
|
|
72384
72938
|
.add("insert_pivot", InsertPivotPlugin)
|
|
72939
|
+
.add("pivot_presence", PivotPresencePlugin)
|
|
72385
72940
|
.add("split_to_columns", SplitToColumnsPlugin)
|
|
72386
72941
|
.add("collaborative", CollaborativePlugin)
|
|
72387
72942
|
.add("history", HistoryPlugin)
|
|
@@ -72771,11 +73326,11 @@ class BottomBarSheet extends Component {
|
|
|
72771
73326
|
if (ev.key === "Enter") {
|
|
72772
73327
|
ev.preventDefault();
|
|
72773
73328
|
this.stopEdition();
|
|
72774
|
-
this.DOMFocusableElementStore.
|
|
73329
|
+
this.DOMFocusableElementStore.focus();
|
|
72775
73330
|
}
|
|
72776
73331
|
if (ev.key === "Escape") {
|
|
72777
73332
|
this.cancelEdition();
|
|
72778
|
-
this.DOMFocusableElementStore.
|
|
73333
|
+
this.DOMFocusableElementStore.focus();
|
|
72779
73334
|
}
|
|
72780
73335
|
}
|
|
72781
73336
|
onMouseEventSheetName(ev) {
|
|
@@ -75336,11 +75891,13 @@ class Spreadsheet extends Component {
|
|
|
75336
75891
|
this.checkViewportSize();
|
|
75337
75892
|
stores.on("store-updated", this, render);
|
|
75338
75893
|
resizeObserver.observe(this.spreadsheetRef.el);
|
|
75894
|
+
registerChartJSExtensions();
|
|
75339
75895
|
});
|
|
75340
75896
|
onWillUnmount(() => {
|
|
75341
75897
|
this.unbindModelEvents();
|
|
75342
75898
|
stores.off("store-updated", this);
|
|
75343
75899
|
resizeObserver.disconnect();
|
|
75900
|
+
unregisterChartJsExtensions();
|
|
75344
75901
|
});
|
|
75345
75902
|
onPatched(() => {
|
|
75346
75903
|
this.checkViewportSize();
|
|
@@ -79782,6 +80339,7 @@ const components = {
|
|
|
79782
80339
|
PivotDimensionOrder,
|
|
79783
80340
|
PivotDimension,
|
|
79784
80341
|
PivotLayoutConfigurator,
|
|
80342
|
+
PivotHTMLRenderer,
|
|
79785
80343
|
PivotDeferUpdate,
|
|
79786
80344
|
PivotTitleSection,
|
|
79787
80345
|
CogWheelMenu,
|
|
@@ -79833,6 +80391,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
79833
80391
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
79834
80392
|
|
|
79835
80393
|
|
|
79836
|
-
__info__.version = "18.3.
|
|
79837
|
-
__info__.date = "2025-05-
|
|
79838
|
-
__info__.hash = "
|
|
80394
|
+
__info__.version = "18.3.3";
|
|
80395
|
+
__info__.date = "2025-05-13T17:54:43.312Z";
|
|
80396
|
+
__info__.hash = "b79924a";
|