@odoo/o-spreadsheet 17.0.49 → 17.0.51
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 +285 -188
- package/dist/o-spreadsheet.d.ts +23 -11
- package/dist/o-spreadsheet.esm.js +285 -188
- package/dist/o-spreadsheet.iife.js +285 -188
- package/dist/o-spreadsheet.iife.min.js +215 -219
- package/dist/o_spreadsheet.xml +31 -26
- package/package.json +3 -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 17.0.
|
|
6
|
-
* @date 2025-02-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.0.51
|
|
6
|
+
* @date 2025-02-25T05:56:10.869Z
|
|
7
|
+
* @hash b433912
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -1910,12 +1910,12 @@ function isTargetDependent(cmd) {
|
|
|
1910
1910
|
function isRangeDependant(cmd) {
|
|
1911
1911
|
return "ranges" in cmd;
|
|
1912
1912
|
}
|
|
1913
|
-
function isZoneDependent(cmd) {
|
|
1914
|
-
return "zone" in cmd;
|
|
1915
|
-
}
|
|
1916
1913
|
function isPositionDependent(cmd) {
|
|
1917
1914
|
return "col" in cmd && "row" in cmd && "sheetId" in cmd;
|
|
1918
1915
|
}
|
|
1916
|
+
function isZoneDependent(cmd) {
|
|
1917
|
+
return "sheetId" in cmd && "zone" in cmd;
|
|
1918
|
+
}
|
|
1919
1919
|
const invalidateEvaluationCommands = new Set([
|
|
1920
1920
|
"RENAME_SHEET",
|
|
1921
1921
|
"DELETE_SHEET",
|
|
@@ -1925,6 +1925,7 @@ const invalidateEvaluationCommands = new Set([
|
|
|
1925
1925
|
"UNDO",
|
|
1926
1926
|
"REDO",
|
|
1927
1927
|
"ADD_MERGE",
|
|
1928
|
+
"DUPLICATE_SHEET",
|
|
1928
1929
|
"UPDATE_LOCALE",
|
|
1929
1930
|
]);
|
|
1930
1931
|
const invalidateDependenciesCommands = new Set([
|
|
@@ -1933,7 +1934,6 @@ const invalidateDependenciesCommands = new Set([
|
|
|
1933
1934
|
]);
|
|
1934
1935
|
const invalidateCFEvaluationCommands = new Set([
|
|
1935
1936
|
...invalidateEvaluationCommands,
|
|
1936
|
-
"DUPLICATE_SHEET",
|
|
1937
1937
|
"EVALUATE_CELLS",
|
|
1938
1938
|
"ADD_CONDITIONAL_FORMAT",
|
|
1939
1939
|
"REMOVE_CONDITIONAL_FORMAT",
|
|
@@ -2093,6 +2093,7 @@ exports.CommandResult = void 0;
|
|
|
2093
2093
|
CommandResult["InvalidRange"] = "InvalidRange";
|
|
2094
2094
|
CommandResult["InvalidZones"] = "InvalidZones";
|
|
2095
2095
|
CommandResult["InvalidSheetId"] = "InvalidSheetId";
|
|
2096
|
+
CommandResult["InvalidCellId"] = "InvalidCellId";
|
|
2096
2097
|
CommandResult["InvalidFigureId"] = "InvalidFigureId";
|
|
2097
2098
|
CommandResult["InputAlreadyFocused"] = "InputAlreadyFocused";
|
|
2098
2099
|
CommandResult["MaximumRangesReached"] = "MaximumRangesReached";
|
|
@@ -3673,17 +3674,20 @@ function toZoneWithoutBoundaryChanges(xc) {
|
|
|
3673
3674
|
*/
|
|
3674
3675
|
function toUnboundedZone(xc) {
|
|
3675
3676
|
const zone = toZoneWithoutBoundaryChanges(xc);
|
|
3677
|
+
reorderZone(zone);
|
|
3678
|
+
return zone;
|
|
3679
|
+
}
|
|
3680
|
+
function reorderZone(zone) {
|
|
3676
3681
|
if (zone.right !== undefined && zone.right < zone.left) {
|
|
3677
|
-
const
|
|
3682
|
+
const right = zone.left;
|
|
3678
3683
|
zone.left = zone.right;
|
|
3679
|
-
zone.right =
|
|
3684
|
+
zone.right = right;
|
|
3680
3685
|
}
|
|
3681
3686
|
if (zone.bottom !== undefined && zone.bottom < zone.top) {
|
|
3682
|
-
const
|
|
3687
|
+
const bottom = zone.top;
|
|
3683
3688
|
zone.top = zone.bottom;
|
|
3684
|
-
zone.bottom =
|
|
3689
|
+
zone.bottom = bottom;
|
|
3685
3690
|
}
|
|
3686
|
-
return zone;
|
|
3687
3691
|
}
|
|
3688
3692
|
/**
|
|
3689
3693
|
* Convert from a cartesian reference to a Zone.
|
|
@@ -4716,20 +4720,53 @@ class UuidGenerator {
|
|
|
4716
4720
|
setIsFastStrategy(isFast) {
|
|
4717
4721
|
this.isFastIdStrategy = isFast;
|
|
4718
4722
|
}
|
|
4723
|
+
/**
|
|
4724
|
+
* Generates a custom UUID using a simple 26^8 method (8-character alphanumeric string with lowercase letters)
|
|
4725
|
+
* This has a higher chance of collision than a UUIDv4, but not only faster to generate than an UUIDV4,
|
|
4726
|
+
* it also has a smaller size, which is preferable to alleviate the overall data size.
|
|
4727
|
+
*
|
|
4728
|
+
* This method is preferable when generating uuids for the core data (sheetId, figureId, etc)
|
|
4729
|
+
* as they will appear several times in the revisions and local history.
|
|
4730
|
+
*
|
|
4731
|
+
*/
|
|
4732
|
+
smallUuid() {
|
|
4733
|
+
if (this.isFastIdStrategy) {
|
|
4734
|
+
this.fastIdStart++;
|
|
4735
|
+
return String(this.fastIdStart);
|
|
4736
|
+
}
|
|
4737
|
+
else if (window.crypto) {
|
|
4738
|
+
return "10000000-1000".replace(/[01]/g, (c) => {
|
|
4739
|
+
const n = Number(c);
|
|
4740
|
+
return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
|
|
4741
|
+
});
|
|
4742
|
+
}
|
|
4743
|
+
else {
|
|
4744
|
+
// mainly for jest and other browsers that do not have the crypto functionality
|
|
4745
|
+
return "xxxxxxxx-xxxx".replace(/[xy]/g, function (c) {
|
|
4746
|
+
var r = (Math.random() * 16) | 0, v = c == "x" ? r : (r & 0x3) | 0x8;
|
|
4747
|
+
return v.toString(16);
|
|
4748
|
+
});
|
|
4749
|
+
}
|
|
4750
|
+
}
|
|
4751
|
+
/**
|
|
4752
|
+
* Generates an UUIDV4, has astronomically low chance of collision, but is larger in size than the smallUuid.
|
|
4753
|
+
* This method should be used when you need to avoid collisions at all costs, like the id of a revision.
|
|
4754
|
+
*/
|
|
4719
4755
|
uuidv4() {
|
|
4720
4756
|
if (this.isFastIdStrategy) {
|
|
4721
4757
|
this.fastIdStart++;
|
|
4722
4758
|
return String(this.fastIdStart);
|
|
4723
|
-
//@ts-ignore
|
|
4724
4759
|
}
|
|
4725
|
-
else if (window.crypto
|
|
4726
|
-
|
|
4727
|
-
|
|
4760
|
+
else if (window.crypto) {
|
|
4761
|
+
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => {
|
|
4762
|
+
const n = Number(c);
|
|
4763
|
+
return (n ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (n / 4)))).toString(16);
|
|
4764
|
+
});
|
|
4728
4765
|
}
|
|
4729
4766
|
else {
|
|
4730
4767
|
// mainly for jest and other browsers that do not have the crypto functionality
|
|
4731
4768
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
4732
|
-
var r = (Math.random() * 16) | 0, v = c
|
|
4769
|
+
var r = (Math.random() * 16) | 0, v = c == "x" ? r : (r & 0x3) | 0x8;
|
|
4733
4770
|
return v.toString(16);
|
|
4734
4771
|
});
|
|
4735
4772
|
}
|
|
@@ -6950,10 +6987,6 @@ class Popover extends owl.Component {
|
|
|
6950
6987
|
this.currentDisplayValue = newDisplay;
|
|
6951
6988
|
if (!anchor)
|
|
6952
6989
|
return;
|
|
6953
|
-
el.style.top = "";
|
|
6954
|
-
el.style.left = "";
|
|
6955
|
-
el.style["max-height"] = "";
|
|
6956
|
-
el.style["max-width"] = "";
|
|
6957
6990
|
const propsMaxSize = { width: this.props.maxWidth, height: this.props.maxHeight };
|
|
6958
6991
|
let elDims = {
|
|
6959
6992
|
width: el.getBoundingClientRect().width,
|
|
@@ -7942,7 +7975,7 @@ const linkSheet = {
|
|
|
7942
7975
|
const deleteSheet = {
|
|
7943
7976
|
name: _t("Delete"),
|
|
7944
7977
|
isVisible: (env) => {
|
|
7945
|
-
return env.model.getters.
|
|
7978
|
+
return env.model.getters.getVisibleSheetIds().length > 1;
|
|
7946
7979
|
},
|
|
7947
7980
|
execute: (env) => env.askConfirmation(_t("Are you sure you want to delete this sheet?"), () => {
|
|
7948
7981
|
env.model.dispatch("DELETE_SHEET", { sheetId: env.model.getters.getActiveSheetId() });
|
|
@@ -7952,7 +7985,7 @@ const duplicateSheet = {
|
|
|
7952
7985
|
name: _t("Duplicate"),
|
|
7953
7986
|
execute: (env) => {
|
|
7954
7987
|
const sheetIdFrom = env.model.getters.getActiveSheetId();
|
|
7955
|
-
const sheetIdTo = env.model.uuidGenerator.
|
|
7988
|
+
const sheetIdTo = env.model.uuidGenerator.smallUuid();
|
|
7956
7989
|
env.model.dispatch("DUPLICATE_SHEET", {
|
|
7957
7990
|
sheetId: sheetIdFrom,
|
|
7958
7991
|
sheetIdTo,
|
|
@@ -8502,17 +8535,15 @@ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, tr
|
|
|
8502
8535
|
plugins: [],
|
|
8503
8536
|
};
|
|
8504
8537
|
}
|
|
8505
|
-
function getChartLabelFormat(getters, range) {
|
|
8538
|
+
function getChartLabelFormat(getters, range, shouldRemoveFirstLabel) {
|
|
8506
8539
|
if (!range)
|
|
8507
8540
|
return undefined;
|
|
8508
|
-
const { sheetId, zone
|
|
8509
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8512
|
-
return format;
|
|
8513
|
-
}
|
|
8541
|
+
const { sheetId, zone } = range;
|
|
8542
|
+
const formats = positions(zone).map((position) => getters.getEvaluatedCell({ sheetId, ...position }).format);
|
|
8543
|
+
if (shouldRemoveFirstLabel) {
|
|
8544
|
+
formats.shift();
|
|
8514
8545
|
}
|
|
8515
|
-
return undefined;
|
|
8546
|
+
return formats.find((format) => format !== undefined);
|
|
8516
8547
|
}
|
|
8517
8548
|
function getChartLabelValues(getters, dataSets, labelRange) {
|
|
8518
8549
|
let labels = { values: [], formattedValues: [] };
|
|
@@ -8793,9 +8824,7 @@ function createBarChartRuntime(chart, getters) {
|
|
|
8793
8824
|
const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
|
|
8794
8825
|
let labels = labelValues.formattedValues;
|
|
8795
8826
|
let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
|
|
8796
|
-
if (chart.dataSetsHaveTitle
|
|
8797
|
-
dataSetsValues[0] &&
|
|
8798
|
-
labels.length > dataSetsValues[0].data.length) {
|
|
8827
|
+
if (shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle)) {
|
|
8799
8828
|
labels.shift();
|
|
8800
8829
|
}
|
|
8801
8830
|
({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
|
|
@@ -9339,8 +9368,8 @@ function fixEmptyLabelsForDateCharts(labels, dataSetsValues) {
|
|
|
9339
9368
|
}
|
|
9340
9369
|
return { labels: newLabels, dataSetsValues: newDatasets };
|
|
9341
9370
|
}
|
|
9342
|
-
function canChartParseLabels(
|
|
9343
|
-
return canBeDateChart(
|
|
9371
|
+
function canChartParseLabels(chart, getters) {
|
|
9372
|
+
return canBeDateChart(chart, getters) || canBeLinearChart(chart, getters);
|
|
9344
9373
|
}
|
|
9345
9374
|
function getChartAxisType(chart, getters) {
|
|
9346
9375
|
if (isDateChart(chart, getters) && isLuxonTimeAdapterInstalled()) {
|
|
@@ -9352,23 +9381,26 @@ function getChartAxisType(chart, getters) {
|
|
|
9352
9381
|
return "category";
|
|
9353
9382
|
}
|
|
9354
9383
|
function isDateChart(chart, getters) {
|
|
9355
|
-
return !chart.labelsAsText && canBeDateChart(chart
|
|
9384
|
+
return !chart.labelsAsText && canBeDateChart(chart, getters);
|
|
9356
9385
|
}
|
|
9357
9386
|
function isLinearChart(chart, getters) {
|
|
9358
|
-
return !chart.labelsAsText && canBeLinearChart(chart
|
|
9387
|
+
return !chart.labelsAsText && canBeLinearChart(chart, getters);
|
|
9359
9388
|
}
|
|
9360
|
-
function canBeDateChart(
|
|
9361
|
-
if (!labelRange || !canBeLinearChart(
|
|
9389
|
+
function canBeDateChart(chart, getters) {
|
|
9390
|
+
if (!chart.labelRange || !canBeLinearChart(chart, getters)) {
|
|
9362
9391
|
return false;
|
|
9363
9392
|
}
|
|
9364
|
-
const labelFormat = getChartLabelFormat(getters, labelRange);
|
|
9393
|
+
const labelFormat = getChartLabelFormat(getters, chart.labelRange, shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle));
|
|
9365
9394
|
return Boolean(labelFormat && timeFormatLuxonCompatible.test(labelFormat));
|
|
9366
9395
|
}
|
|
9367
|
-
function canBeLinearChart(
|
|
9368
|
-
if (!labelRange) {
|
|
9396
|
+
function canBeLinearChart(chart, getters) {
|
|
9397
|
+
if (!chart.labelRange) {
|
|
9369
9398
|
return false;
|
|
9370
9399
|
}
|
|
9371
|
-
const labels = getters.getRangeValues(labelRange);
|
|
9400
|
+
const labels = getters.getRangeValues(chart.labelRange);
|
|
9401
|
+
if (shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle)) {
|
|
9402
|
+
labels.shift();
|
|
9403
|
+
}
|
|
9372
9404
|
if (labels.some((label) => isNaN(Number(label)) && label)) {
|
|
9373
9405
|
return false;
|
|
9374
9406
|
}
|
|
@@ -9442,9 +9474,8 @@ function createLineChartRuntime(chart, getters) {
|
|
|
9442
9474
|
const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
|
|
9443
9475
|
let labels = axisType === "linear" ? labelValues.values : labelValues.formattedValues;
|
|
9444
9476
|
let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
|
|
9445
|
-
|
|
9446
|
-
|
|
9447
|
-
labels.length > dataSetsValues[0].data.length) {
|
|
9477
|
+
const removeFirstLabel = shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle);
|
|
9478
|
+
if (removeFirstLabel) {
|
|
9448
9479
|
labels.shift();
|
|
9449
9480
|
}
|
|
9450
9481
|
({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
|
|
@@ -9459,7 +9490,7 @@ function createLineChartRuntime(chart, getters) {
|
|
|
9459
9490
|
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets);
|
|
9460
9491
|
const options = { format: dataSetFormat, locale, truncateLabels };
|
|
9461
9492
|
const config = getLineConfiguration(chart, labels, options);
|
|
9462
|
-
const labelFormat = getChartLabelFormat(getters, chart.labelRange);
|
|
9493
|
+
const labelFormat = getChartLabelFormat(getters, chart.labelRange, removeFirstLabel);
|
|
9463
9494
|
if (axisType === "time") {
|
|
9464
9495
|
const axis = {
|
|
9465
9496
|
type: "time",
|
|
@@ -9681,9 +9712,7 @@ function createPieChartRuntime(chart, getters) {
|
|
|
9681
9712
|
const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
|
|
9682
9713
|
let labels = labelValues.formattedValues;
|
|
9683
9714
|
let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
|
|
9684
|
-
if (chart.dataSetsHaveTitle
|
|
9685
|
-
dataSetsValues[0] &&
|
|
9686
|
-
labels.length > dataSetsValues[0].data.length) {
|
|
9715
|
+
if (shouldRemoveFirstLabel(chart.labelRange, chart.dataSets[0], chart.dataSetsHaveTitle)) {
|
|
9687
9716
|
labels.shift();
|
|
9688
9717
|
}
|
|
9689
9718
|
({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
|
|
@@ -9699,7 +9728,7 @@ function createPieChartRuntime(chart, getters) {
|
|
|
9699
9728
|
const dataset = {
|
|
9700
9729
|
label,
|
|
9701
9730
|
data,
|
|
9702
|
-
borderColor: "#FFFFFF",
|
|
9731
|
+
borderColor: chart.background || "#FFFFFF",
|
|
9703
9732
|
backgroundColor,
|
|
9704
9733
|
};
|
|
9705
9734
|
config.data.datasets.push(dataset);
|
|
@@ -10204,21 +10233,22 @@ function getSmartChartDefinition(zone, getters) {
|
|
|
10204
10233
|
}
|
|
10205
10234
|
// Only display legend for several datasets.
|
|
10206
10235
|
const newLegendPos = dataSetZone.right === dataSetZone.left ? "none" : "top";
|
|
10207
|
-
const
|
|
10208
|
-
|
|
10209
|
-
|
|
10210
|
-
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
10236
|
+
const lineChartDefinition = {
|
|
10237
|
+
title,
|
|
10238
|
+
dataSets,
|
|
10239
|
+
labelsAsText: false,
|
|
10240
|
+
stacked: false,
|
|
10241
|
+
aggregated: false,
|
|
10242
|
+
cumulative: false,
|
|
10243
|
+
labelRange: labelRangeXc,
|
|
10244
|
+
type: "line",
|
|
10245
|
+
dataSetsHaveTitle,
|
|
10246
|
+
verticalAxisPosition: "left",
|
|
10247
|
+
legendPosition: newLegendPos,
|
|
10248
|
+
};
|
|
10249
|
+
const chart = new LineChart(lineChartDefinition, sheetId, getters);
|
|
10250
|
+
if (canChartParseLabels(chart, getters)) {
|
|
10251
|
+
return lineChartDefinition;
|
|
10222
10252
|
}
|
|
10223
10253
|
return {
|
|
10224
10254
|
title,
|
|
@@ -10818,7 +10848,7 @@ const HIDE_ROWS_NAME = (env) => {
|
|
|
10818
10848
|
//------------------------------------------------------------------------------
|
|
10819
10849
|
const CREATE_CHART = (env) => {
|
|
10820
10850
|
const getters = env.model.getters;
|
|
10821
|
-
const id = env.model.uuidGenerator.
|
|
10851
|
+
const id = env.model.uuidGenerator.smallUuid();
|
|
10822
10852
|
const sheetId = getters.getActiveSheetId();
|
|
10823
10853
|
if (getZoneArea(env.model.getters.getSelectedZone()) === 1) {
|
|
10824
10854
|
env.model.selection.selectTableAroundSelection();
|
|
@@ -10852,7 +10882,7 @@ async function requestImage(env) {
|
|
|
10852
10882
|
const CREATE_IMAGE = async (env) => {
|
|
10853
10883
|
if (env.imageProvider) {
|
|
10854
10884
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
10855
|
-
const figureId = env.model.uuidGenerator.
|
|
10885
|
+
const figureId = env.model.uuidGenerator.smallUuid();
|
|
10856
10886
|
const image = await requestImage(env);
|
|
10857
10887
|
if (!image) {
|
|
10858
10888
|
throw new Error("No image provider was given to the environment");
|
|
@@ -12573,6 +12603,26 @@ const LN = {
|
|
|
12573
12603
|
isExported: true,
|
|
12574
12604
|
};
|
|
12575
12605
|
// -----------------------------------------------------------------------------
|
|
12606
|
+
// LOG
|
|
12607
|
+
// -----------------------------------------------------------------------------
|
|
12608
|
+
const LOG = {
|
|
12609
|
+
description: _t("The logarithm of a number, for a given base."),
|
|
12610
|
+
args: [
|
|
12611
|
+
arg("value (number)", _t("The value for which to calculate the logarithm.")),
|
|
12612
|
+
arg("base (number, default=10)", _t("The base of the logarithm.")),
|
|
12613
|
+
],
|
|
12614
|
+
returns: ["NUMBER"],
|
|
12615
|
+
compute: function (value, base = 10) {
|
|
12616
|
+
const _value = toNumber(value, this.locale);
|
|
12617
|
+
const _base = toNumber(base, this.locale);
|
|
12618
|
+
assert(() => _value > 0, _t("The value (%s) must be strictly positive.", _value.toString()));
|
|
12619
|
+
assert(() => _base > 0, _t("The base (%s) must be strictly positive.", _base.toString()));
|
|
12620
|
+
assert(() => _base !== 1, _t("The base must be different from 1."));
|
|
12621
|
+
return Math.log10(_value) / Math.log10(_base);
|
|
12622
|
+
},
|
|
12623
|
+
isExported: true,
|
|
12624
|
+
};
|
|
12625
|
+
// -----------------------------------------------------------------------------
|
|
12576
12626
|
// MOD
|
|
12577
12627
|
// -----------------------------------------------------------------------------
|
|
12578
12628
|
const MOD = {
|
|
@@ -13093,6 +13143,7 @@ var math = /*#__PURE__*/Object.freeze({
|
|
|
13093
13143
|
ISODD: ISODD,
|
|
13094
13144
|
ISO_CEILING: ISO_CEILING,
|
|
13095
13145
|
LN: LN,
|
|
13146
|
+
LOG: LOG,
|
|
13096
13147
|
MOD: MOD,
|
|
13097
13148
|
MUNIT: MUNIT,
|
|
13098
13149
|
ODD: ODD,
|
|
@@ -15954,7 +16005,7 @@ const SORTN = {
|
|
|
15954
16005
|
}
|
|
15955
16006
|
}
|
|
15956
16007
|
},
|
|
15957
|
-
isExported:
|
|
16008
|
+
isExported: false,
|
|
15958
16009
|
};
|
|
15959
16010
|
// -----------------------------------------------------------------------------
|
|
15960
16011
|
// UNIQUE
|
|
@@ -19855,7 +19906,7 @@ const insertSheet = {
|
|
|
19855
19906
|
execute: (env) => {
|
|
19856
19907
|
const activeSheetId = env.model.getters.getActiveSheetId();
|
|
19857
19908
|
const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1;
|
|
19858
|
-
const sheetId = env.model.uuidGenerator.
|
|
19909
|
+
const sheetId = env.model.uuidGenerator.smallUuid();
|
|
19859
19910
|
env.model.dispatch("CREATE_SHEET", { sheetId, position });
|
|
19860
19911
|
env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
|
|
19861
19912
|
},
|
|
@@ -21531,7 +21582,7 @@ css /* scss */ `
|
|
|
21531
21582
|
*/
|
|
21532
21583
|
class SelectionInput extends owl.Component {
|
|
21533
21584
|
static template = "o-spreadsheet-SelectionInput";
|
|
21534
|
-
id = uuidGenerator$1.
|
|
21585
|
+
id = uuidGenerator$1.smallUuid();
|
|
21535
21586
|
previousRanges = this.props.ranges() || [];
|
|
21536
21587
|
originSheet = this.env.model.getters.getActiveSheetId();
|
|
21537
21588
|
state = owl.useState({
|
|
@@ -22581,7 +22632,7 @@ class LineConfigPanel extends LineBarPieConfigPanel {
|
|
|
22581
22632
|
get canTreatLabelsAsText() {
|
|
22582
22633
|
const chart = this.env.model.getters.getChart(this.props.figureId);
|
|
22583
22634
|
if (chart && chart instanceof LineChart) {
|
|
22584
|
-
return canChartParseLabels(chart
|
|
22635
|
+
return canChartParseLabels(chart, this.env.model.getters);
|
|
22585
22636
|
}
|
|
22586
22637
|
return false;
|
|
22587
22638
|
}
|
|
@@ -23609,7 +23660,7 @@ class ConditionalFormattingEditor extends owl.Component {
|
|
|
23609
23660
|
state;
|
|
23610
23661
|
setup() {
|
|
23611
23662
|
const cf = this.props.editedCf || {
|
|
23612
|
-
id: this.env.model.uuidGenerator.
|
|
23663
|
+
id: this.env.model.uuidGenerator.smallUuid(),
|
|
23613
23664
|
ranges: this.env.model.getters
|
|
23614
23665
|
.getSelectedZones()
|
|
23615
23666
|
.map((zone) => this.env.model.getters.zoneToXC(this.env.model.getters.getActiveSheetId(), zone)),
|
|
@@ -25558,7 +25609,7 @@ class DataValidationEditor extends owl.Component {
|
|
|
25558
25609
|
.getSelectedZones()
|
|
25559
25610
|
.map((zone) => zoneToXc(this.env.model.getters.getUnboundedZone(sheetId, zone)));
|
|
25560
25611
|
return {
|
|
25561
|
-
id: this.env.model.uuidGenerator.
|
|
25612
|
+
id: this.env.model.uuidGenerator.smallUuid(),
|
|
25562
25613
|
criterion: { type: "textContains", values: [""] },
|
|
25563
25614
|
ranges,
|
|
25564
25615
|
};
|
|
@@ -26709,25 +26760,21 @@ css /* scss */ `
|
|
|
26709
26760
|
}
|
|
26710
26761
|
}
|
|
26711
26762
|
}
|
|
26763
|
+
}
|
|
26764
|
+
.o-spreadsheet .o-composer-assistant {
|
|
26765
|
+
pointer-events: none;
|
|
26712
26766
|
|
|
26713
|
-
.o-
|
|
26714
|
-
|
|
26715
|
-
|
|
26716
|
-
|
|
26717
|
-
|
|
26718
|
-
|
|
26719
|
-
.o-semi-bold {
|
|
26720
|
-
/** FIXME: to remove in favor of Bootstrap
|
|
26721
|
-
* 'fw-semibold' when we upgrade to Bootstrap 5.2
|
|
26722
|
-
*/
|
|
26723
|
-
font-weight: 600 !important;
|
|
26724
|
-
}
|
|
26767
|
+
.o-semi-bold {
|
|
26768
|
+
/** FIXME: to remove in favor of Bootstrap
|
|
26769
|
+
* 'fw-semibold' when we upgrade to Bootstrap 5.2
|
|
26770
|
+
*/
|
|
26771
|
+
font-weight: 600 !important;
|
|
26725
26772
|
}
|
|
26726
26773
|
}
|
|
26727
26774
|
`;
|
|
26728
26775
|
class Composer extends owl.Component {
|
|
26729
26776
|
static template = "o-spreadsheet-Composer";
|
|
26730
|
-
static components = { TextValueProvider, FunctionDescriptionProvider };
|
|
26777
|
+
static components = { TextValueProvider, FunctionDescriptionProvider, Popover };
|
|
26731
26778
|
static defaultProps = {
|
|
26732
26779
|
inputStyle: "",
|
|
26733
26780
|
isDefaultFocus: false,
|
|
@@ -26752,35 +26799,13 @@ class Composer extends owl.Component {
|
|
|
26752
26799
|
argToFocus: 0,
|
|
26753
26800
|
});
|
|
26754
26801
|
compositionActive = false;
|
|
26755
|
-
spreadsheetRect = useSpreadsheetRect();
|
|
26756
26802
|
get assistantStyle() {
|
|
26757
|
-
const composerRect = this.composerRef.el.getBoundingClientRect();
|
|
26758
26803
|
const assistantStyle = {};
|
|
26759
|
-
|
|
26804
|
+
const minWidth = Math.min(getBoundingRectAsPOJO(this.composerRef.el).width || Infinity, ASSISTANT_WIDTH);
|
|
26805
|
+
assistantStyle["min-width"] = `${minWidth}px`;
|
|
26760
26806
|
if (this.autoCompleteState.type === "function") {
|
|
26761
26807
|
assistantStyle.width = `${ASSISTANT_WIDTH}px`;
|
|
26762
26808
|
}
|
|
26763
|
-
if (this.props.delimitation && this.props.rect) {
|
|
26764
|
-
const { x: cellX, y: cellY, height: cellHeight } = this.props.rect;
|
|
26765
|
-
const remainingHeight = this.props.delimitation.height - (cellY + cellHeight);
|
|
26766
|
-
assistantStyle["max-height"] = `${remainingHeight}px`;
|
|
26767
|
-
if (cellY > remainingHeight) {
|
|
26768
|
-
const availableSpaceAbove = cellY;
|
|
26769
|
-
assistantStyle["max-height"] = `${availableSpaceAbove}px`;
|
|
26770
|
-
// render top
|
|
26771
|
-
// We compensate 2 px of margin on the assistant style + 1px for design reasons
|
|
26772
|
-
assistantStyle.top = `-3px`;
|
|
26773
|
-
assistantStyle.transform = `translate(0, -100%)`;
|
|
26774
|
-
}
|
|
26775
|
-
if (cellX + ASSISTANT_WIDTH > this.props.delimitation.width) {
|
|
26776
|
-
// render left
|
|
26777
|
-
assistantStyle.right = `0px`;
|
|
26778
|
-
}
|
|
26779
|
-
}
|
|
26780
|
-
if (this.props.focus === "contentFocus" &&
|
|
26781
|
-
composerRect.left + ASSISTANT_WIDTH > this.spreadsheetRect.width) {
|
|
26782
|
-
assistantStyle.right = "0px";
|
|
26783
|
-
}
|
|
26784
26809
|
return cssPropertiesToCss(assistantStyle);
|
|
26785
26810
|
}
|
|
26786
26811
|
// we can't allow input events to be triggered while we remove and add back the content of the composer in processContent
|
|
@@ -27029,7 +27054,7 @@ class Composer extends owl.Component {
|
|
|
27029
27054
|
this.autoCompleteState.selectedIndex = 0;
|
|
27030
27055
|
}
|
|
27031
27056
|
updateAutoCompleteIndex(index) {
|
|
27032
|
-
this.autoCompleteState.selectedIndex =
|
|
27057
|
+
this.autoCompleteState.selectedIndex = index;
|
|
27033
27058
|
}
|
|
27034
27059
|
/**
|
|
27035
27060
|
* This is required to ensure the content helper selection is
|
|
@@ -27317,11 +27342,16 @@ class Composer extends owl.Component {
|
|
|
27317
27342
|
this.autoCompleteState.values = values.map((value) => ({ text: value, description: "" }));
|
|
27318
27343
|
this.autoCompleteState.getHtmlContent = (value) => [{ value }];
|
|
27319
27344
|
}
|
|
27345
|
+
get popoverProps() {
|
|
27346
|
+
return {
|
|
27347
|
+
anchorRect: getBoundingRectAsPOJO(this.composerRef.el),
|
|
27348
|
+
positioning: "BottomLeft",
|
|
27349
|
+
verticalOffset: 0,
|
|
27350
|
+
};
|
|
27351
|
+
}
|
|
27320
27352
|
}
|
|
27321
27353
|
Composer.props = {
|
|
27322
27354
|
inputStyle: { type: String, optional: true },
|
|
27323
|
-
rect: { type: Object, optional: true },
|
|
27324
|
-
delimitation: { type: Object, optional: true },
|
|
27325
27355
|
focus: { validate: (value) => ["inactive", "cellFocus", "contentFocus"].includes(value) },
|
|
27326
27356
|
onComposerCellFocused: { type: Function, optional: true },
|
|
27327
27357
|
onComposerContentFocused: Function,
|
|
@@ -27391,13 +27421,7 @@ class GridComposer extends owl.Component {
|
|
|
27391
27421
|
});
|
|
27392
27422
|
}
|
|
27393
27423
|
get composerProps() {
|
|
27394
|
-
const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders();
|
|
27395
27424
|
return {
|
|
27396
|
-
rect: { ...this.rect },
|
|
27397
|
-
delimitation: {
|
|
27398
|
-
width,
|
|
27399
|
-
height,
|
|
27400
|
-
},
|
|
27401
27425
|
focus: this.props.focus,
|
|
27402
27426
|
isDefaultFocus: true,
|
|
27403
27427
|
onComposerContentFocused: this.props.onComposerContentFocused,
|
|
@@ -33844,7 +33868,7 @@ function normalizeV9(formula) {
|
|
|
33844
33868
|
* a breaking change is made in the way the state is handled, and an upgrade
|
|
33845
33869
|
* function should be defined
|
|
33846
33870
|
*/
|
|
33847
|
-
const CURRENT_VERSION = 14;
|
|
33871
|
+
const CURRENT_VERSION = 14.5;
|
|
33848
33872
|
const INITIAL_SHEET_ID = "Sheet1";
|
|
33849
33873
|
/**
|
|
33850
33874
|
* This function tries to load anything that could look like a valid
|
|
@@ -34178,7 +34202,7 @@ function forceUnicityOfFigure(data) {
|
|
|
34178
34202
|
for (const sheet of data.sheets || []) {
|
|
34179
34203
|
for (const figure of sheet.figures || []) {
|
|
34180
34204
|
if (figureIds.has(figure.id)) {
|
|
34181
|
-
figure.id += uuidGenerator.
|
|
34205
|
+
figure.id += uuidGenerator.smallUuid();
|
|
34182
34206
|
}
|
|
34183
34207
|
figureIds.add(figure.id);
|
|
34184
34208
|
}
|
|
@@ -35854,6 +35878,10 @@ class CellPlugin extends CorePlugin {
|
|
|
35854
35878
|
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessUpdateCell);
|
|
35855
35879
|
case "CLEAR_CELL":
|
|
35856
35880
|
return this.checkValidations(cmd, this.checkCellOutOfSheet, this.checkUselessClearCell);
|
|
35881
|
+
case "UPDATE_CELL_POSITION":
|
|
35882
|
+
return !cmd.cellId || this.cells[cmd.sheetId]?.[cmd.cellId]
|
|
35883
|
+
? "Success" /* CommandResult.Success */
|
|
35884
|
+
: "InvalidCellId" /* CommandResult.InvalidCellId */;
|
|
35857
35885
|
default:
|
|
35858
35886
|
return "Success" /* CommandResult.Success */;
|
|
35859
35887
|
}
|
|
@@ -35895,6 +35923,9 @@ class CellPlugin extends CorePlugin {
|
|
|
35895
35923
|
case "CLEAR_CELLS":
|
|
35896
35924
|
this.clearCells(cmd.sheetId, cmd.target);
|
|
35897
35925
|
break;
|
|
35926
|
+
case "DELETE_SHEET": {
|
|
35927
|
+
this.history.update("cells", cmd.sheetId, undefined);
|
|
35928
|
+
}
|
|
35898
35929
|
}
|
|
35899
35930
|
}
|
|
35900
35931
|
/**
|
|
@@ -36973,8 +37004,14 @@ class DataValidationPlugin extends CorePlugin {
|
|
|
36973
37004
|
allowDispatch(cmd) {
|
|
36974
37005
|
switch (cmd.type) {
|
|
36975
37006
|
case "ADD_DATA_VALIDATION_RULE":
|
|
37007
|
+
if (!this.getters.tryGetSheet(cmd.sheetId)) {
|
|
37008
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
37009
|
+
}
|
|
36976
37010
|
return this.checkValidations(cmd, this.chainValidations(this.checkCriterionTypeIsValid, this.checkCriterionHasValidNumberOfValues, this.checkCriterionValuesAreValid));
|
|
36977
37011
|
case "REMOVE_DATA_VALIDATION_RULE":
|
|
37012
|
+
if (!this.getters.tryGetSheet(cmd.sheetId)) {
|
|
37013
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
37014
|
+
}
|
|
36978
37015
|
if (!this.rules[cmd.sheetId].find((rule) => rule.id === cmd.id)) {
|
|
36979
37016
|
return "UnknownDataValidationRule" /* CommandResult.UnknownDataValidationRule */;
|
|
36980
37017
|
}
|
|
@@ -37148,6 +37185,7 @@ class DataValidationPlugin extends CorePlugin {
|
|
|
37148
37185
|
class FigurePlugin extends CorePlugin {
|
|
37149
37186
|
static getters = ["getFigures", "getFigure", "getFigureSheetId"];
|
|
37150
37187
|
figures = {};
|
|
37188
|
+
insertionOrders = []; // TODO use a list in master
|
|
37151
37189
|
// ---------------------------------------------------------------------------
|
|
37152
37190
|
// Command Handling
|
|
37153
37191
|
// ---------------------------------------------------------------------------
|
|
@@ -37250,11 +37288,14 @@ class FigurePlugin extends CorePlugin {
|
|
|
37250
37288
|
}
|
|
37251
37289
|
addFigure(figure, sheetId) {
|
|
37252
37290
|
this.history.update("figures", sheetId, figure.id, figure);
|
|
37291
|
+
this.history.update("insertionOrders", this.insertionOrders.length, figure.id);
|
|
37253
37292
|
}
|
|
37254
37293
|
deleteSheet(sheetId) {
|
|
37294
|
+
this.history.update("insertionOrders", this.insertionOrders.filter((id) => !this.figures[sheetId]?.[id]));
|
|
37255
37295
|
this.history.update("figures", sheetId, undefined);
|
|
37256
37296
|
}
|
|
37257
37297
|
removeFigure(id, sheetId) {
|
|
37298
|
+
this.history.update("insertionOrders", this.insertionOrders.filter((figureId) => figureId !== id));
|
|
37258
37299
|
this.history.update("figures", sheetId, id, undefined);
|
|
37259
37300
|
}
|
|
37260
37301
|
checkFigureExists(sheetId, figureId) {
|
|
@@ -37273,7 +37314,14 @@ class FigurePlugin extends CorePlugin {
|
|
|
37273
37314
|
// Getters
|
|
37274
37315
|
// ---------------------------------------------------------------------------
|
|
37275
37316
|
getFigures(sheetId) {
|
|
37276
|
-
|
|
37317
|
+
const figures = [];
|
|
37318
|
+
for (const figureId of this.insertionOrders) {
|
|
37319
|
+
const figure = this.figures[sheetId]?.[figureId];
|
|
37320
|
+
if (figure) {
|
|
37321
|
+
figures.push(figure);
|
|
37322
|
+
}
|
|
37323
|
+
}
|
|
37324
|
+
return figures;
|
|
37277
37325
|
}
|
|
37278
37326
|
getFigure(sheetId, figureId) {
|
|
37279
37327
|
return this.figures[sheetId]?.[figureId];
|
|
@@ -37286,11 +37334,9 @@ class FigurePlugin extends CorePlugin {
|
|
|
37286
37334
|
// ---------------------------------------------------------------------------
|
|
37287
37335
|
import(data) {
|
|
37288
37336
|
for (let sheet of data.sheets) {
|
|
37289
|
-
const figures
|
|
37290
|
-
|
|
37291
|
-
|
|
37292
|
-
});
|
|
37293
|
-
this.figures[sheet.id] = figures;
|
|
37337
|
+
for (const figure of sheet.figures) {
|
|
37338
|
+
this.addFigure(figure, sheet.id);
|
|
37339
|
+
}
|
|
37294
37340
|
}
|
|
37295
37341
|
}
|
|
37296
37342
|
export(data) {
|
|
@@ -37314,10 +37360,10 @@ class FilterTable {
|
|
|
37314
37360
|
this.filters = [];
|
|
37315
37361
|
this.zone = zone;
|
|
37316
37362
|
const uuid = new UuidGenerator();
|
|
37317
|
-
this.id = uuid.
|
|
37363
|
+
this.id = uuid.smallUuid();
|
|
37318
37364
|
for (const i of range(zone.left, zone.right + 1)) {
|
|
37319
37365
|
const filterZone = { ...this.zone, left: i, right: i };
|
|
37320
|
-
this.filters.push(new Filter(uuid.
|
|
37366
|
+
this.filters.push(new Filter(uuid.smallUuid(), filterZone));
|
|
37321
37367
|
}
|
|
37322
37368
|
}
|
|
37323
37369
|
/** Get zone of the table without the headers */
|
|
@@ -37519,7 +37565,7 @@ class FiltersPlugin extends CorePlugin {
|
|
|
37519
37565
|
if (filters.length < zoneToDimension(zone).numberOfCols) {
|
|
37520
37566
|
for (let col = zone.left; col <= zone.right; col++) {
|
|
37521
37567
|
if (!filters.find((filter) => filter.col === col)) {
|
|
37522
|
-
filters.push(new Filter(this.uuidGenerator.
|
|
37568
|
+
filters.push(new Filter(this.uuidGenerator.smallUuid(), { ...zone, left: col, right: col }));
|
|
37523
37569
|
}
|
|
37524
37570
|
}
|
|
37525
37571
|
filters.sort((f1, f2) => f1.col - f2.col);
|
|
@@ -39008,6 +39054,9 @@ class SheetPlugin extends CorePlugin {
|
|
|
39008
39054
|
case "CREATE_SHEET": {
|
|
39009
39055
|
return this.checkValidations(cmd, this.checkSheetName, this.checkSheetPosition);
|
|
39010
39056
|
}
|
|
39057
|
+
case "DUPLICATE_SHEET": {
|
|
39058
|
+
return this.sheets[cmd.sheetIdTo] ? "DuplicatedSheetId" /* CommandResult.DuplicatedSheetId */ : "Success" /* CommandResult.Success */;
|
|
39059
|
+
}
|
|
39011
39060
|
case "MOVE_SHEET":
|
|
39012
39061
|
try {
|
|
39013
39062
|
const currentIndex = this.orderedSheetIds.findIndex((id) => id === cmd.sheetId);
|
|
@@ -39020,7 +39069,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
39020
39069
|
case "RENAME_SHEET":
|
|
39021
39070
|
return this.isRenameAllowed(cmd);
|
|
39022
39071
|
case "DELETE_SHEET":
|
|
39023
|
-
return this.
|
|
39072
|
+
return this.getVisibleSheetIds().length > 1
|
|
39024
39073
|
? "Success" /* CommandResult.Success */
|
|
39025
39074
|
: "NotEnoughSheets" /* CommandResult.NotEnoughSheets */;
|
|
39026
39075
|
case "ADD_COLUMNS_ROWS":
|
|
@@ -39833,6 +39882,10 @@ class SheetPlugin extends CorePlugin {
|
|
|
39833
39882
|
checkZonesAreInSheet(cmd) {
|
|
39834
39883
|
if (!("sheetId" in cmd))
|
|
39835
39884
|
return "Success" /* CommandResult.Success */;
|
|
39885
|
+
if ("ranges" in cmd &&
|
|
39886
|
+
cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
|
|
39887
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
39888
|
+
}
|
|
39836
39889
|
return this.checkZonesExistInSheet(cmd.sheetId, this.getCommandZones(cmd));
|
|
39837
39890
|
}
|
|
39838
39891
|
}
|
|
@@ -39852,7 +39905,10 @@ class HeaderGroupingPlugin extends CorePlugin {
|
|
|
39852
39905
|
allowDispatch(cmd) {
|
|
39853
39906
|
switch (cmd.type) {
|
|
39854
39907
|
case "GROUP_HEADERS": {
|
|
39855
|
-
const { start, end } = cmd;
|
|
39908
|
+
const { start, end, sheetId } = cmd;
|
|
39909
|
+
if (!this.getters.tryGetSheet(sheetId)) {
|
|
39910
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
39911
|
+
}
|
|
39856
39912
|
if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
|
|
39857
39913
|
return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
|
|
39858
39914
|
}
|
|
@@ -39865,7 +39921,10 @@ class HeaderGroupingPlugin extends CorePlugin {
|
|
|
39865
39921
|
break;
|
|
39866
39922
|
}
|
|
39867
39923
|
case "UNGROUP_HEADERS": {
|
|
39868
|
-
const { start, end } = cmd;
|
|
39924
|
+
const { start, end, sheetId } = cmd;
|
|
39925
|
+
if (!this.getters.tryGetSheet(sheetId)) {
|
|
39926
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
39927
|
+
}
|
|
39869
39928
|
if (!this.getters.doesHeadersExist(cmd.sheetId, cmd.dimension, [start, end])) {
|
|
39870
39929
|
return "InvalidHeaderGroupStartEnd" /* CommandResult.InvalidHeaderGroupStartEnd */;
|
|
39871
39930
|
}
|
|
@@ -39876,6 +39935,9 @@ class HeaderGroupingPlugin extends CorePlugin {
|
|
|
39876
39935
|
}
|
|
39877
39936
|
case "UNFOLD_HEADER_GROUP":
|
|
39878
39937
|
case "FOLD_HEADER_GROUP":
|
|
39938
|
+
if (!this.getters.tryGetSheet(cmd.sheetId)) {
|
|
39939
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
39940
|
+
}
|
|
39879
39941
|
const group = this.findGroupWithStartEnd(cmd.sheetId, cmd.dimension, cmd.start, cmd.end);
|
|
39880
39942
|
if (!group) {
|
|
39881
39943
|
return "UnknownHeaderGroup" /* CommandResult.UnknownHeaderGroup */;
|
|
@@ -44145,6 +44207,9 @@ function updateChartRangesTransformation(toTransform, executed) {
|
|
|
44145
44207
|
};
|
|
44146
44208
|
}
|
|
44147
44209
|
function createSheetTransformation(toTransform, executed) {
|
|
44210
|
+
if (toTransform.sheetId === executed.sheetId) {
|
|
44211
|
+
toTransform = { ...toTransform, sheetId: `${toTransform.sheetId}~` };
|
|
44212
|
+
}
|
|
44148
44213
|
if (toTransform.name === executed.name) {
|
|
44149
44214
|
return {
|
|
44150
44215
|
...toTransform,
|
|
@@ -44781,21 +44846,14 @@ class Session extends EventBus {
|
|
|
44781
44846
|
if (!message)
|
|
44782
44847
|
return;
|
|
44783
44848
|
if (message.type === "REMOTE_REVISION") {
|
|
44784
|
-
|
|
44849
|
+
let revision = this.revisions.get(message.nextRevisionId);
|
|
44785
44850
|
if (revision.commands.length === 0) {
|
|
44786
44851
|
/**
|
|
44787
|
-
* The command is empty, we have to
|
|
44852
|
+
* The command is empty, we have to rebase all the next local revisions
|
|
44788
44853
|
* to avoid issues with undo/redo
|
|
44789
44854
|
*/
|
|
44790
|
-
this.revisions.
|
|
44791
|
-
|
|
44792
|
-
.filter((message) => message.type === "REMOTE_REVISION")
|
|
44793
|
-
.map((message) => message.nextRevisionId);
|
|
44794
|
-
this.trigger("pending-revisions-dropped", { revisionIds });
|
|
44795
|
-
this.waitingAck = false;
|
|
44796
|
-
this.waitingUndoRedoAck = false;
|
|
44797
|
-
this.pendingMessages = [];
|
|
44798
|
-
return;
|
|
44855
|
+
this.revisions.rebase(revision.id);
|
|
44856
|
+
revision = this.revisions.get(message.nextRevisionId);
|
|
44799
44857
|
}
|
|
44800
44858
|
message = {
|
|
44801
44859
|
...message,
|
|
@@ -44819,7 +44877,6 @@ class Session extends EventBus {
|
|
|
44819
44877
|
switch (message.type) {
|
|
44820
44878
|
case "REMOTE_REVISION":
|
|
44821
44879
|
case "REVISION_REDONE":
|
|
44822
|
-
case "REVISION_UNDONE":
|
|
44823
44880
|
case "SNAPSHOT_CREATED":
|
|
44824
44881
|
this.waitingAck = false;
|
|
44825
44882
|
this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
|
|
@@ -44827,6 +44884,25 @@ class Session extends EventBus {
|
|
|
44827
44884
|
this.processedRevisions.add(message.nextRevisionId);
|
|
44828
44885
|
this.sendPendingMessage();
|
|
44829
44886
|
break;
|
|
44887
|
+
case "REVISION_UNDONE": {
|
|
44888
|
+
this.waitingAck = false;
|
|
44889
|
+
this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
|
|
44890
|
+
const firstPendingRevisionId = this.pendingMessages.findIndex((message) => message.type === "REMOTE_REVISION");
|
|
44891
|
+
if (firstPendingRevisionId !== -1) {
|
|
44892
|
+
/**
|
|
44893
|
+
* Some revisions undergo transformations that may cause issues with
|
|
44894
|
+
* undo/redo if the transformation is destructive (we don't get back
|
|
44895
|
+
* the original command by transforming it with the inverse).
|
|
44896
|
+
* To prevent these problems, we must rebase all subsequent local
|
|
44897
|
+
* revisions.
|
|
44898
|
+
*/
|
|
44899
|
+
this.revisions.rebase(this.pendingMessages[firstPendingRevisionId].nextRevisionId);
|
|
44900
|
+
}
|
|
44901
|
+
this.serverRevisionId = message.nextRevisionId;
|
|
44902
|
+
this.processedRevisions.add(message.nextRevisionId);
|
|
44903
|
+
this.sendPendingMessage();
|
|
44904
|
+
break;
|
|
44905
|
+
}
|
|
44830
44906
|
}
|
|
44831
44907
|
}
|
|
44832
44908
|
isAlreadyProcessed(message) {
|
|
@@ -45531,7 +45607,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
45531
45607
|
const cfInTarget = this.getters
|
|
45532
45608
|
.getConditionalFormats(targetSheetId)
|
|
45533
45609
|
.find((cf) => cf.stopIfTrue === originCF.stopIfTrue && deepEquals(cf.rule, originCF.rule));
|
|
45534
|
-
return cfInTarget
|
|
45610
|
+
return cfInTarget
|
|
45611
|
+
? cfInTarget
|
|
45612
|
+
: { ...originCF, id: this.uuidGenerator.smallUuid(), ranges: [] };
|
|
45535
45613
|
}
|
|
45536
45614
|
pasteDataValidation(origin, target) {
|
|
45537
45615
|
const rule = this.getters.getValidationRuleForCell(origin);
|
|
@@ -45563,7 +45641,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
45563
45641
|
originRule.isBlocking === rule.isBlocking);
|
|
45564
45642
|
return ruleInTargetSheet
|
|
45565
45643
|
? ruleInTargetSheet
|
|
45566
|
-
: { ...originRule, id: this.uuidGenerator.
|
|
45644
|
+
: { ...originRule, id: this.uuidGenerator.smallUuid(), ranges: [] };
|
|
45567
45645
|
}
|
|
45568
45646
|
/**
|
|
45569
45647
|
* Add or remove XCs to a given data validation rule.
|
|
@@ -47755,6 +47833,10 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
47755
47833
|
*/
|
|
47756
47834
|
checkZonesAreInSheet(cmd) {
|
|
47757
47835
|
const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.tryGetActiveSheetId();
|
|
47836
|
+
if ("ranges" in cmd &&
|
|
47837
|
+
cmd.ranges.some((rangeData) => !this.getters.tryGetSheet(rangeData._sheetId))) {
|
|
47838
|
+
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
47839
|
+
}
|
|
47758
47840
|
const zones = this.getters.getCommandZones(cmd);
|
|
47759
47841
|
if (!sheetId && zones.length > 0) {
|
|
47760
47842
|
return "NoActiveSheet" /* CommandResult.NoActiveSheet */;
|
|
@@ -47803,23 +47885,23 @@ const uuidGenerator = new UuidGenerator();
|
|
|
47803
47885
|
function repeatCreateChartCommand(getters, cmd) {
|
|
47804
47886
|
return {
|
|
47805
47887
|
...repeatSheetDependantCommand(getters, cmd),
|
|
47806
|
-
id: uuidGenerator.
|
|
47888
|
+
id: uuidGenerator.smallUuid(),
|
|
47807
47889
|
};
|
|
47808
47890
|
}
|
|
47809
47891
|
function repeatCreateImageCommand(getters, cmd) {
|
|
47810
47892
|
return {
|
|
47811
47893
|
...repeatSheetDependantCommand(getters, cmd),
|
|
47812
|
-
figureId: uuidGenerator.
|
|
47894
|
+
figureId: uuidGenerator.smallUuid(),
|
|
47813
47895
|
};
|
|
47814
47896
|
}
|
|
47815
47897
|
function repeatCreateFigureCommand(getters, cmd) {
|
|
47816
47898
|
const newCmd = repeatSheetDependantCommand(getters, cmd);
|
|
47817
|
-
newCmd.figure.id = uuidGenerator.
|
|
47899
|
+
newCmd.figure.id = uuidGenerator.smallUuid();
|
|
47818
47900
|
return newCmd;
|
|
47819
47901
|
}
|
|
47820
47902
|
function repeatCreateSheetCommand(getters, cmd) {
|
|
47821
47903
|
const newCmd = deepCopy(cmd);
|
|
47822
|
-
newCmd.sheetId = uuidGenerator.
|
|
47904
|
+
newCmd.sheetId = uuidGenerator.smallUuid();
|
|
47823
47905
|
const sheetName = cmd.name || getters.getSheet(getters.getActiveSheetId()).name;
|
|
47824
47906
|
// Extract the prefix of the sheet name (everything before the number at the end of the name)
|
|
47825
47907
|
const namePrefix = sheetName.match(/(.+?)\d*$/)?.[1] || sheetName;
|
|
@@ -48014,7 +48096,6 @@ class HistoryPlugin extends UIPlugin {
|
|
|
48014
48096
|
super(config);
|
|
48015
48097
|
this.session = config.session;
|
|
48016
48098
|
this.session.on("new-local-state-update", this, this.onNewLocalStateUpdate);
|
|
48017
|
-
this.session.on("pending-revisions-dropped", this, ({ revisionIds }) => this.drop(revisionIds));
|
|
48018
48099
|
this.session.on("snapshot", this, () => {
|
|
48019
48100
|
this.undoStack = [];
|
|
48020
48101
|
this.redoStack = [];
|
|
@@ -48084,10 +48165,6 @@ class HistoryPlugin extends UIPlugin {
|
|
|
48084
48165
|
const lastNonRedoRevision = this.getPossibleRevisionToRepeat();
|
|
48085
48166
|
return canRepeatRevision(lastNonRedoRevision);
|
|
48086
48167
|
}
|
|
48087
|
-
drop(revisionIds) {
|
|
48088
|
-
this.undoStack = this.undoStack.filter((id) => !revisionIds.includes(id));
|
|
48089
|
-
this.redoStack = [];
|
|
48090
|
-
}
|
|
48091
48168
|
onNewLocalStateUpdate({ id }) {
|
|
48092
48169
|
this.undoStack.push(id);
|
|
48093
48170
|
this.redoStack = [];
|
|
@@ -48354,7 +48431,7 @@ class ClipboardFigureState {
|
|
|
48354
48431
|
x: maxX < width ? 0 : Math.min(targetX, maxX - width),
|
|
48355
48432
|
y: maxY < height ? 0 : Math.min(targetY, maxY - height),
|
|
48356
48433
|
};
|
|
48357
|
-
const newId = new UuidGenerator().
|
|
48434
|
+
const newId = new UuidGenerator().smallUuid();
|
|
48358
48435
|
this.copiedFigureContent.paste(sheetId, newId, position, { height, width });
|
|
48359
48436
|
if (this.operation === "CUT") {
|
|
48360
48437
|
this.dispatch("DELETE_FIGURE", {
|
|
@@ -50057,23 +50134,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
50057
50134
|
gridSelection: deepCopy(gridSelection),
|
|
50058
50135
|
};
|
|
50059
50136
|
}
|
|
50060
|
-
|
|
50061
|
-
const currentSheetIds = this.getters.getVisibleSheetIds();
|
|
50062
|
-
this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
|
|
50063
|
-
if (this.activeSheet.id in this.sheetsData) {
|
|
50064
|
-
const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
|
|
50065
|
-
this.selectCell(anchor.cell.col, anchor.cell.row);
|
|
50066
|
-
}
|
|
50067
|
-
else {
|
|
50068
|
-
this.selectCell(0, 0);
|
|
50069
|
-
}
|
|
50070
|
-
const { col, row } = this.gridSelection.anchor.cell;
|
|
50071
|
-
this.moveClient({
|
|
50072
|
-
sheetId: this.getters.getActiveSheetId(),
|
|
50073
|
-
col,
|
|
50074
|
-
row,
|
|
50075
|
-
});
|
|
50076
|
-
}
|
|
50137
|
+
this.fallbackToVisibleSheet();
|
|
50077
50138
|
const sheetId = this.getters.getActiveSheetId();
|
|
50078
50139
|
this.gridSelection.zones = this.gridSelection.zones.map((z) => this.getters.expandZone(sheetId, z));
|
|
50079
50140
|
this.gridSelection.anchor.zone = this.getters.expandZone(sheetId, this.gridSelection.anchor.zone);
|
|
@@ -50083,6 +50144,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
50083
50144
|
}
|
|
50084
50145
|
}
|
|
50085
50146
|
finalize() {
|
|
50147
|
+
this.fallbackToVisibleSheet();
|
|
50086
50148
|
/** Any change to the selection has to be reflected in the selection processor. */
|
|
50087
50149
|
this.selection.resetDefaultAnchor(this, deepCopy(this.gridSelection.anchor));
|
|
50088
50150
|
}
|
|
@@ -50434,6 +50496,25 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
50434
50496
|
}
|
|
50435
50497
|
return "Success" /* CommandResult.Success */;
|
|
50436
50498
|
}
|
|
50499
|
+
fallbackToVisibleSheet() {
|
|
50500
|
+
if (!this.getters.tryGetSheet(this.getters.getActiveSheetId())) {
|
|
50501
|
+
const currentSheetIds = this.getters.getVisibleSheetIds();
|
|
50502
|
+
this.activeSheet = this.getters.getSheet(currentSheetIds[0]);
|
|
50503
|
+
if (this.activeSheet.id in this.sheetsData) {
|
|
50504
|
+
const { anchor } = this.clipSelection(this.activeSheet.id, this.sheetsData[this.activeSheet.id].gridSelection);
|
|
50505
|
+
this.selectCell(anchor.cell.col, anchor.cell.row);
|
|
50506
|
+
}
|
|
50507
|
+
else {
|
|
50508
|
+
this.selectCell(0, 0);
|
|
50509
|
+
}
|
|
50510
|
+
const { col, row } = this.gridSelection.anchor.cell;
|
|
50511
|
+
this.moveClient({
|
|
50512
|
+
sheetId: this.getters.getActiveSheetId(),
|
|
50513
|
+
col,
|
|
50514
|
+
row,
|
|
50515
|
+
});
|
|
50516
|
+
}
|
|
50517
|
+
}
|
|
50437
50518
|
//-------------------------------------------
|
|
50438
50519
|
// Helpers for extensions
|
|
50439
50520
|
// ------------------------------------------
|
|
@@ -51581,7 +51662,9 @@ class HeaderPositionsUIPlugin extends UIPlugin {
|
|
|
51581
51662
|
case "UNGROUP_HEADERS":
|
|
51582
51663
|
case "GROUP_HEADERS":
|
|
51583
51664
|
case "CREATE_SHEET":
|
|
51584
|
-
this.
|
|
51665
|
+
if (this.getters.tryGetSheet(cmd.sheetId)) {
|
|
51666
|
+
this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
|
|
51667
|
+
}
|
|
51585
51668
|
break;
|
|
51586
51669
|
case "DUPLICATE_SHEET":
|
|
51587
51670
|
this.headerPositions[cmd.sheetIdTo] = deepCopy(this.headerPositions[cmd.sheetId]);
|
|
@@ -51589,12 +51672,14 @@ class HeaderPositionsUIPlugin extends UIPlugin {
|
|
|
51589
51672
|
}
|
|
51590
51673
|
}
|
|
51591
51674
|
finalize() {
|
|
51592
|
-
|
|
51593
|
-
|
|
51675
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
51676
|
+
// sheets can be created without this plugin being aware of it
|
|
51677
|
+
// in concurrent situations.
|
|
51678
|
+
if (this.isDirty || !this.headerPositions[sheetId]) {
|
|
51594
51679
|
this.headerPositions[sheetId] = this.computeHeaderPositionsOfSheet(sheetId);
|
|
51595
51680
|
}
|
|
51596
|
-
this.isDirty = false;
|
|
51597
51681
|
}
|
|
51682
|
+
this.isDirty = false;
|
|
51598
51683
|
}
|
|
51599
51684
|
/**
|
|
51600
51685
|
* Returns the size, start and end coordinates of a column on an unfolded sheet
|
|
@@ -52278,7 +52363,7 @@ class BottomBar extends owl.Component {
|
|
|
52278
52363
|
clickAddSheet(ev) {
|
|
52279
52364
|
const activeSheetId = this.env.model.getters.getActiveSheetId();
|
|
52280
52365
|
const position = this.env.model.getters.getSheetIds().findIndex((sheetId) => sheetId === activeSheetId) + 1;
|
|
52281
|
-
const sheetId = this.env.model.uuidGenerator.
|
|
52366
|
+
const sheetId = this.env.model.uuidGenerator.smallUuid();
|
|
52282
52367
|
const name = this.env.model.getters.getNextSheetName(_t("Sheet"));
|
|
52283
52368
|
this.env.model.dispatch("CREATE_SHEET", { sheetId, position, name });
|
|
52284
52369
|
this.env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId });
|
|
@@ -53340,7 +53425,7 @@ css /* scss */ `
|
|
|
53340
53425
|
.o-font-size-editor {
|
|
53341
53426
|
height: calc(100% - 4px);
|
|
53342
53427
|
input.o-font-size {
|
|
53343
|
-
outline
|
|
53428
|
+
outline: none;
|
|
53344
53429
|
height: 20px;
|
|
53345
53430
|
width: 23px;
|
|
53346
53431
|
}
|
|
@@ -54515,7 +54600,7 @@ class Tree {
|
|
|
54515
54600
|
}
|
|
54516
54601
|
/**
|
|
54517
54602
|
* Drop the operation and all following operations in every
|
|
54518
|
-
*
|
|
54603
|
+
* branches
|
|
54519
54604
|
*/
|
|
54520
54605
|
drop(operationId) {
|
|
54521
54606
|
for (const branch of this.branches) {
|
|
@@ -54820,9 +54905,16 @@ class SelectiveHistory {
|
|
|
54820
54905
|
this.fastForward();
|
|
54821
54906
|
this.insert(redoId, this.buildEmpty(redoId), insertAfter);
|
|
54822
54907
|
}
|
|
54823
|
-
|
|
54908
|
+
rebase(operationId) {
|
|
54909
|
+
const operation = this.get(operationId);
|
|
54910
|
+
const execution = [...this.tree.execution(this.HEAD_BRANCH).startAfter(operationId)];
|
|
54824
54911
|
this.revertBefore(operationId);
|
|
54912
|
+
const baseId = this.HEAD_OPERATION.id;
|
|
54825
54913
|
this.tree.drop(operationId);
|
|
54914
|
+
this.insert(operationId, operation, baseId);
|
|
54915
|
+
for (const { operation } of execution) {
|
|
54916
|
+
this.insert(operation.id, operation.data, this.HEAD_OPERATION.id);
|
|
54917
|
+
}
|
|
54826
54918
|
}
|
|
54827
54919
|
getRevertedExecution() {
|
|
54828
54920
|
const data = [];
|
|
@@ -57399,6 +57491,11 @@ class Model extends EventBus {
|
|
|
57399
57491
|
dispatch: (command) => {
|
|
57400
57492
|
const result = this.checkDispatchAllowed(command);
|
|
57401
57493
|
if (!result.isSuccessful) {
|
|
57494
|
+
// core views plugins need to be invalidated
|
|
57495
|
+
this.dispatchToHandlers(this.coreHandlers, {
|
|
57496
|
+
type: "UNDO",
|
|
57497
|
+
commands: [command],
|
|
57498
|
+
});
|
|
57402
57499
|
return;
|
|
57403
57500
|
}
|
|
57404
57501
|
this.isReplayingCommand = true;
|
|
@@ -57427,7 +57524,7 @@ class Model extends EventBus {
|
|
|
57427
57524
|
}
|
|
57428
57525
|
setupConfig(config) {
|
|
57429
57526
|
const client = config.client || {
|
|
57430
|
-
id: this.uuidGenerator.
|
|
57527
|
+
id: this.uuidGenerator.smallUuid(),
|
|
57431
57528
|
name: _t("Anonymous").toString(),
|
|
57432
57529
|
};
|
|
57433
57530
|
const transportService = config.transportService || new LocalTransportService();
|
|
@@ -57848,6 +57945,6 @@ exports.setTranslationMethod = setTranslationMethod;
|
|
|
57848
57945
|
exports.tokenize = tokenize;
|
|
57849
57946
|
|
|
57850
57947
|
|
|
57851
|
-
__info__.version = "17.0.
|
|
57852
|
-
__info__.date = "2025-02-
|
|
57853
|
-
__info__.hash = "
|
|
57948
|
+
__info__.version = "17.0.51";
|
|
57949
|
+
__info__.date = "2025-02-25T05:56:10.869Z";
|
|
57950
|
+
__info__.hash = "b433912";
|