@odoo/o-spreadsheet 17.1.21 → 17.1.23
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.
|
@@ -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.1.
|
|
6
|
-
* @date 2024-07-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.1.23
|
|
6
|
+
* @date 2024-07-11T06:37:01.931Z
|
|
7
|
+
* @hash 31e8450
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Component, useRef, onMounted, onWillUnmount, useEffect, onWillPatch, useState, onWillUpdateProps, onPatched, useComponent, useExternalListener, onWillStart, xml, useChildSubEnv, useSubEnv, markRaw } from '@odoo/owl';
|
|
@@ -544,7 +544,7 @@ function getAddHeaderStartIndex(position, base) {
|
|
|
544
544
|
/**
|
|
545
545
|
* Compares two objects.
|
|
546
546
|
*/
|
|
547
|
-
function deepEquals(o1, o2
|
|
547
|
+
function deepEquals(o1, o2) {
|
|
548
548
|
if (o1 === o2)
|
|
549
549
|
return true;
|
|
550
550
|
if ((o1 && !o2) || (o2 && !o1))
|
|
@@ -560,17 +560,13 @@ function deepEquals(o1, o2, ignoreFunctions) {
|
|
|
560
560
|
}
|
|
561
561
|
}
|
|
562
562
|
for (const key in o1) {
|
|
563
|
-
|
|
564
|
-
if (typeOfO1Key !== typeof o2[key])
|
|
563
|
+
if (typeof o1[key] !== typeof o2[key])
|
|
565
564
|
return false;
|
|
566
|
-
if (
|
|
567
|
-
if (!deepEquals(o1[key], o2[key]
|
|
565
|
+
if (typeof o1[key] === "object") {
|
|
566
|
+
if (!deepEquals(o1[key], o2[key]))
|
|
568
567
|
return false;
|
|
569
568
|
}
|
|
570
569
|
else {
|
|
571
|
-
if (ignoreFunctions && typeOfO1Key === "function") {
|
|
572
|
-
continue;
|
|
573
|
-
}
|
|
574
570
|
if (o1[key] !== o2[key])
|
|
575
571
|
return false;
|
|
576
572
|
}
|
|
@@ -641,11 +637,9 @@ class JetSet extends Set {
|
|
|
641
637
|
return this;
|
|
642
638
|
}
|
|
643
639
|
deleteMany(iterable) {
|
|
644
|
-
let wasDeleted = false;
|
|
645
640
|
for (const element of iterable) {
|
|
646
|
-
|
|
641
|
+
super.delete(element);
|
|
647
642
|
}
|
|
648
|
-
return wasDeleted;
|
|
649
643
|
}
|
|
650
644
|
}
|
|
651
645
|
/**
|
|
@@ -1702,7 +1696,7 @@ const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSepa
|
|
|
1702
1696
|
});
|
|
1703
1697
|
const getNumberRegex = memoize(function getNumberRegex(locale) {
|
|
1704
1698
|
const decimalSeparator = escapeRegExp(locale.decimalSeparator);
|
|
1705
|
-
const thousandsSeparator = escapeRegExp(locale.thousandsSeparator);
|
|
1699
|
+
const thousandsSeparator = escapeRegExp(locale.thousandsSeparator || "");
|
|
1706
1700
|
const pIntegerAndDecimals = `(\\d+(${thousandsSeparator}\\d{3,})*(${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
|
|
1707
1701
|
const pOnlyDecimals = `(${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
|
|
1708
1702
|
const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
|
|
@@ -1729,7 +1723,7 @@ function isNumber(value, locale) {
|
|
|
1729
1723
|
return getNumberRegex(locale).test(value.trim());
|
|
1730
1724
|
}
|
|
1731
1725
|
const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(locale) {
|
|
1732
|
-
return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator)}]`, "g");
|
|
1726
|
+
return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator || "")}]`, "g");
|
|
1733
1727
|
});
|
|
1734
1728
|
/**
|
|
1735
1729
|
* Convert a string into a number. It assumes that the string actually represents
|
|
@@ -2593,6 +2587,9 @@ function getPredicate(descr, isQuery, locale) {
|
|
|
2593
2587
|
return result;
|
|
2594
2588
|
}
|
|
2595
2589
|
function operandToRegExp(operand) {
|
|
2590
|
+
if (operand === "*") {
|
|
2591
|
+
return /.+/;
|
|
2592
|
+
}
|
|
2596
2593
|
let exp = "";
|
|
2597
2594
|
let predecessor = "";
|
|
2598
2595
|
for (let char of operand) {
|
|
@@ -2616,9 +2613,9 @@ function operandToRegExp(operand) {
|
|
|
2616
2613
|
}
|
|
2617
2614
|
return new RegExp("^" + exp + "$", "i");
|
|
2618
2615
|
}
|
|
2619
|
-
function evaluatePredicate(value, criterion) {
|
|
2616
|
+
function evaluatePredicate(value = "", criterion) {
|
|
2620
2617
|
const { operator, operand } = criterion;
|
|
2621
|
-
if (
|
|
2618
|
+
if (operand === undefined || value === null || operand === null) {
|
|
2622
2619
|
return false;
|
|
2623
2620
|
}
|
|
2624
2621
|
if (typeof operand === "number" && operator === "=") {
|
|
@@ -4852,7 +4849,6 @@ class ChartJsComponent extends Component {
|
|
|
4852
4849
|
};
|
|
4853
4850
|
canvas = useRef("graphContainer");
|
|
4854
4851
|
chart;
|
|
4855
|
-
currentRuntime;
|
|
4856
4852
|
get background() {
|
|
4857
4853
|
return this.chartRuntime.background;
|
|
4858
4854
|
}
|
|
@@ -4869,18 +4865,11 @@ class ChartJsComponent extends Component {
|
|
|
4869
4865
|
setup() {
|
|
4870
4866
|
onMounted(() => {
|
|
4871
4867
|
const runtime = this.chartRuntime;
|
|
4872
|
-
this.currentRuntime = runtime;
|
|
4873
4868
|
// Note: chartJS modify the runtime in place, so it's important to give it a copy
|
|
4874
4869
|
this.createChart(deepCopy(runtime.chartJsConfig));
|
|
4875
4870
|
});
|
|
4876
4871
|
onWillUnmount(() => this.chart?.destroy());
|
|
4877
|
-
useEffect(() =>
|
|
4878
|
-
const runtime = this.chartRuntime;
|
|
4879
|
-
if (!deepEquals(runtime, this.currentRuntime, "ignoreFunctions")) {
|
|
4880
|
-
this.currentRuntime = runtime;
|
|
4881
|
-
this.updateChartJs(deepCopy(runtime));
|
|
4882
|
-
}
|
|
4883
|
-
});
|
|
4872
|
+
useEffect(() => this.updateChartJs(deepCopy(this.chartRuntime)), () => [this.chartRuntime]);
|
|
4884
4873
|
}
|
|
4885
4874
|
createChart(chartData) {
|
|
4886
4875
|
const canvas = this.canvas.el;
|
|
@@ -7716,19 +7705,22 @@ class TokenizingChars {
|
|
|
7716
7705
|
}
|
|
7717
7706
|
|
|
7718
7707
|
function isValidLocale(locale) {
|
|
7719
|
-
if (!
|
|
7720
|
-
typeof locale
|
|
7721
|
-
typeof locale.
|
|
7722
|
-
typeof locale.code === "string" &&
|
|
7723
|
-
typeof locale.thousandsSeparator === "string" &&
|
|
7724
|
-
typeof locale.decimalSeparator === "string" &&
|
|
7725
|
-
typeof locale.dateFormat === "string" &&
|
|
7726
|
-
typeof locale.timeFormat === "string" &&
|
|
7727
|
-
typeof locale.formulaArgSeparator === "string")) {
|
|
7708
|
+
if (!locale ||
|
|
7709
|
+
typeof locale !== "object" ||
|
|
7710
|
+
!(!locale.thousandsSeparator || typeof locale.thousandsSeparator === "string")) {
|
|
7728
7711
|
return false;
|
|
7729
7712
|
}
|
|
7730
|
-
|
|
7731
|
-
|
|
7713
|
+
for (const property of [
|
|
7714
|
+
"code",
|
|
7715
|
+
"name",
|
|
7716
|
+
"decimalSeparator",
|
|
7717
|
+
"dateFormat",
|
|
7718
|
+
"timeFormat",
|
|
7719
|
+
"formulaArgSeparator",
|
|
7720
|
+
]) {
|
|
7721
|
+
if (!locale[property] || typeof locale[property] !== "string") {
|
|
7722
|
+
return false;
|
|
7723
|
+
}
|
|
7732
7724
|
}
|
|
7733
7725
|
if (locale.formulaArgSeparator === locale.decimalSeparator) {
|
|
7734
7726
|
return false;
|
|
@@ -7826,7 +7818,10 @@ function canonicalizeNumberLiteral(content, locale) {
|
|
|
7826
7818
|
if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
|
|
7827
7819
|
return content;
|
|
7828
7820
|
}
|
|
7829
|
-
|
|
7821
|
+
if (locale.thousandsSeparator) {
|
|
7822
|
+
content = content.replaceAll(locale.thousandsSeparator, "");
|
|
7823
|
+
}
|
|
7824
|
+
return content.replace(locale.decimalSeparator, ".");
|
|
7830
7825
|
}
|
|
7831
7826
|
/**
|
|
7832
7827
|
* Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
|
|
@@ -8472,7 +8467,7 @@ function truncateLabel(label) {
|
|
|
8472
8467
|
/**
|
|
8473
8468
|
* Get a default chart js configuration
|
|
8474
8469
|
*/
|
|
8475
|
-
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels }) {
|
|
8470
|
+
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels = true }) {
|
|
8476
8471
|
const options = {
|
|
8477
8472
|
// https://www.chartjs.org/docs/latest/general/responsive.html
|
|
8478
8473
|
responsive: true,
|
|
@@ -9505,15 +9500,6 @@ function createLineChartRuntime(chart, getters) {
|
|
|
9505
9500
|
}
|
|
9506
9501
|
const colors = new ChartColors();
|
|
9507
9502
|
for (let [index, { label, data }] of dataSetsValues.entries()) {
|
|
9508
|
-
if (["linear", "time"].includes(axisType)) {
|
|
9509
|
-
// Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
|
|
9510
|
-
data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
|
|
9511
|
-
}
|
|
9512
|
-
const color = colors.next();
|
|
9513
|
-
let backgroundRGBA = colorToRGBA(color);
|
|
9514
|
-
if (chart.stacked) {
|
|
9515
|
-
backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
|
|
9516
|
-
}
|
|
9517
9503
|
if (chart.cumulative) {
|
|
9518
9504
|
let accumulator = 0;
|
|
9519
9505
|
data = data.map((value) => {
|
|
@@ -9524,6 +9510,15 @@ function createLineChartRuntime(chart, getters) {
|
|
|
9524
9510
|
return value;
|
|
9525
9511
|
});
|
|
9526
9512
|
}
|
|
9513
|
+
if (["linear", "time"].includes(axisType)) {
|
|
9514
|
+
// Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
|
|
9515
|
+
data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
|
|
9516
|
+
}
|
|
9517
|
+
const color = colors.next();
|
|
9518
|
+
let backgroundRGBA = colorToRGBA(color);
|
|
9519
|
+
if (chart.stacked) {
|
|
9520
|
+
backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
|
|
9521
|
+
}
|
|
9527
9522
|
const backgroundColor = rgbaToHex(backgroundRGBA);
|
|
9528
9523
|
const dataset = {
|
|
9529
9524
|
label,
|
|
@@ -24779,7 +24774,13 @@ class SettingsPanel extends Component {
|
|
|
24779
24774
|
}
|
|
24780
24775
|
async loadLocales() {
|
|
24781
24776
|
this.loadedLocales = (await this.env.loadLocales())
|
|
24782
|
-
.filter(
|
|
24777
|
+
.filter((locale) => {
|
|
24778
|
+
const isValid = isValidLocale(locale);
|
|
24779
|
+
if (!isValid) {
|
|
24780
|
+
console.warn(`Invalid locale: ${locale["code"]} ${locale}`);
|
|
24781
|
+
}
|
|
24782
|
+
return isValid;
|
|
24783
|
+
})
|
|
24783
24784
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
24784
24785
|
}
|
|
24785
24786
|
get numberFormatPreview() {
|
|
@@ -30535,6 +30536,7 @@ class Grid extends Component {
|
|
|
30535
30536
|
return;
|
|
30536
30537
|
}
|
|
30537
30538
|
if (clipboardData.types.indexOf(ClipboardMIMEType.PlainText) > -1) {
|
|
30539
|
+
ev.preventDefault();
|
|
30538
30540
|
const content = clipboardData.getData(ClipboardMIMEType.PlainText);
|
|
30539
30541
|
const target = this.env.model.getters.getSelectedZones();
|
|
30540
30542
|
const clipboardString = this.env.model.getters.getClipboardTextContent();
|
|
@@ -35132,6 +35134,21 @@ class BordersPlugin extends CorePlugin {
|
|
|
35132
35134
|
return [];
|
|
35133
35135
|
return Object.keys(sheetBorders).map((index) => parseInt(index, 10));
|
|
35134
35136
|
}
|
|
35137
|
+
/**
|
|
35138
|
+
* Get all the rows which contains at least a border
|
|
35139
|
+
*/
|
|
35140
|
+
getRowsWithBorders(sheetId) {
|
|
35141
|
+
const sheetBorders = this.borders[sheetId]?.filter(isDefined$1);
|
|
35142
|
+
if (!sheetBorders)
|
|
35143
|
+
return [];
|
|
35144
|
+
const rowsWithBorders = new Set();
|
|
35145
|
+
for (const rowBorders of sheetBorders) {
|
|
35146
|
+
for (const rowBorder in rowBorders) {
|
|
35147
|
+
rowsWithBorders.add(parseInt(rowBorder, 10));
|
|
35148
|
+
}
|
|
35149
|
+
}
|
|
35150
|
+
return Array.from(rowsWithBorders);
|
|
35151
|
+
}
|
|
35135
35152
|
/**
|
|
35136
35153
|
* Get the range of all the rows in the sheet
|
|
35137
35154
|
*/
|
|
@@ -35181,7 +35198,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
35181
35198
|
destructive: false,
|
|
35182
35199
|
});
|
|
35183
35200
|
}
|
|
35184
|
-
this.
|
|
35201
|
+
this.getRowsWithBorders(sheetId)
|
|
35185
35202
|
.filter((row) => row >= start)
|
|
35186
35203
|
.sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
|
|
35187
35204
|
.forEach((row) => {
|
|
@@ -35636,7 +35653,7 @@ function parseExpression(tokens, parent_priority = 0) {
|
|
|
35636
35653
|
* Parse an expression (as a string) into an AST.
|
|
35637
35654
|
*/
|
|
35638
35655
|
function parse(str) {
|
|
35639
|
-
return parseTokens(
|
|
35656
|
+
return parseTokens(rangeTokenize(str));
|
|
35640
35657
|
}
|
|
35641
35658
|
function parseTokens(tokens) {
|
|
35642
35659
|
tokens = tokens.filter((x) => x.type !== "SPACE");
|
|
@@ -42130,6 +42147,7 @@ class Evaluator {
|
|
|
42130
42147
|
}
|
|
42131
42148
|
finally {
|
|
42132
42149
|
this.cellsBeingComputed.delete(cellId);
|
|
42150
|
+
this.nextPositionsToUpdate.delete(positionId);
|
|
42133
42151
|
}
|
|
42134
42152
|
}
|
|
42135
42153
|
computeAndSave(position) {
|
|
@@ -42158,11 +42176,36 @@ class Evaluator {
|
|
|
42158
42176
|
forEachSpreadPositionInMatrix(nbColumns, nbRows,
|
|
42159
42177
|
// thanks to the isMatrix check above, we know that formulaReturn is MatrixFunctionReturn
|
|
42160
42178
|
this.spreadValues(formulaPosition, formulaReturn));
|
|
42179
|
+
this.invalidatePositionsDependingOnSpread(formulaPosition, nbColumns, nbRows);
|
|
42161
42180
|
return createEvaluatedCell(formulaReturn[0][0].value, {
|
|
42162
42181
|
format: cellData.format || formulaReturn[0][0]?.format,
|
|
42163
42182
|
locale: this.getters.getLocale(),
|
|
42164
42183
|
}, formulaReturn[0][0].message);
|
|
42165
42184
|
}
|
|
42185
|
+
invalidatePositionsDependingOnSpread(arrayFormulaPosition, nbColumns, nbRows) {
|
|
42186
|
+
// the result matrix is split in 2 zones to exclude the array formula position
|
|
42187
|
+
const top = arrayFormulaPosition.row;
|
|
42188
|
+
const left = arrayFormulaPosition.col;
|
|
42189
|
+
const bottom = top + nbRows - 1;
|
|
42190
|
+
const leftColumnZone = {
|
|
42191
|
+
top: top + 1,
|
|
42192
|
+
bottom,
|
|
42193
|
+
left,
|
|
42194
|
+
right: left,
|
|
42195
|
+
};
|
|
42196
|
+
const rightPartZone = {
|
|
42197
|
+
top,
|
|
42198
|
+
bottom,
|
|
42199
|
+
left: left + 1,
|
|
42200
|
+
right: left + nbColumns - 1,
|
|
42201
|
+
};
|
|
42202
|
+
const sheetId = arrayFormulaPosition.sheetId;
|
|
42203
|
+
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn([
|
|
42204
|
+
{ sheetId, zone: rightPartZone },
|
|
42205
|
+
{ sheetId, zone: leftColumnZone },
|
|
42206
|
+
]);
|
|
42207
|
+
this.nextPositionsToUpdate.addMany(invalidatedPositions);
|
|
42208
|
+
}
|
|
42166
42209
|
assertSheetHasEnoughSpaceToSpreadFormulaResult({ sheetId, col, row }, matrixResult) {
|
|
42167
42210
|
const numberOfCols = this.getters.getNumberCols(sheetId);
|
|
42168
42211
|
const numberOfRows = this.getters.getNumberRows(sheetId);
|
|
@@ -42211,9 +42254,6 @@ class Evaluator {
|
|
|
42211
42254
|
}, matrixResult[i][j].message);
|
|
42212
42255
|
const positionId = this.encoder.encode(position);
|
|
42213
42256
|
this.setEvaluatedCell(positionId, evaluatedCell);
|
|
42214
|
-
// check if formula dependencies present in the spread zone
|
|
42215
|
-
// if so, they need to be recomputed
|
|
42216
|
-
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([positionId]));
|
|
42217
42257
|
};
|
|
42218
42258
|
}
|
|
42219
42259
|
invalidateSpreading(positionId) {
|
|
@@ -57801,6 +57841,6 @@ const constants = {
|
|
|
57801
57841
|
export { AbstractChart, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
|
|
57802
57842
|
|
|
57803
57843
|
|
|
57804
|
-
__info__.version = "17.1.
|
|
57805
|
-
__info__.date = "2024-07-
|
|
57806
|
-
__info__.hash = "
|
|
57844
|
+
__info__.version = "17.1.23";
|
|
57845
|
+
__info__.date = "2024-07-11T06:37:01.931Z";
|
|
57846
|
+
__info__.hash = "31e8450";
|
|
@@ -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.1.
|
|
6
|
-
* @date 2024-07-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.1.23
|
|
6
|
+
* @date 2024-07-11T06:37:01.931Z
|
|
7
|
+
* @hash 31e8450
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -545,7 +545,7 @@
|
|
|
545
545
|
/**
|
|
546
546
|
* Compares two objects.
|
|
547
547
|
*/
|
|
548
|
-
function deepEquals(o1, o2
|
|
548
|
+
function deepEquals(o1, o2) {
|
|
549
549
|
if (o1 === o2)
|
|
550
550
|
return true;
|
|
551
551
|
if ((o1 && !o2) || (o2 && !o1))
|
|
@@ -561,17 +561,13 @@
|
|
|
561
561
|
}
|
|
562
562
|
}
|
|
563
563
|
for (const key in o1) {
|
|
564
|
-
|
|
565
|
-
if (typeOfO1Key !== typeof o2[key])
|
|
564
|
+
if (typeof o1[key] !== typeof o2[key])
|
|
566
565
|
return false;
|
|
567
|
-
if (
|
|
568
|
-
if (!deepEquals(o1[key], o2[key]
|
|
566
|
+
if (typeof o1[key] === "object") {
|
|
567
|
+
if (!deepEquals(o1[key], o2[key]))
|
|
569
568
|
return false;
|
|
570
569
|
}
|
|
571
570
|
else {
|
|
572
|
-
if (ignoreFunctions && typeOfO1Key === "function") {
|
|
573
|
-
continue;
|
|
574
|
-
}
|
|
575
571
|
if (o1[key] !== o2[key])
|
|
576
572
|
return false;
|
|
577
573
|
}
|
|
@@ -642,11 +638,9 @@
|
|
|
642
638
|
return this;
|
|
643
639
|
}
|
|
644
640
|
deleteMany(iterable) {
|
|
645
|
-
let wasDeleted = false;
|
|
646
641
|
for (const element of iterable) {
|
|
647
|
-
|
|
642
|
+
super.delete(element);
|
|
648
643
|
}
|
|
649
|
-
return wasDeleted;
|
|
650
644
|
}
|
|
651
645
|
}
|
|
652
646
|
/**
|
|
@@ -1703,7 +1697,7 @@
|
|
|
1703
1697
|
});
|
|
1704
1698
|
const getNumberRegex = memoize(function getNumberRegex(locale) {
|
|
1705
1699
|
const decimalSeparator = escapeRegExp(locale.decimalSeparator);
|
|
1706
|
-
const thousandsSeparator = escapeRegExp(locale.thousandsSeparator);
|
|
1700
|
+
const thousandsSeparator = escapeRegExp(locale.thousandsSeparator || "");
|
|
1707
1701
|
const pIntegerAndDecimals = `(\\d+(${thousandsSeparator}\\d{3,})*(${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
|
|
1708
1702
|
const pOnlyDecimals = `(${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
|
|
1709
1703
|
const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
|
|
@@ -1730,7 +1724,7 @@
|
|
|
1730
1724
|
return getNumberRegex(locale).test(value.trim());
|
|
1731
1725
|
}
|
|
1732
1726
|
const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(locale) {
|
|
1733
|
-
return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator)}]`, "g");
|
|
1727
|
+
return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator || "")}]`, "g");
|
|
1734
1728
|
});
|
|
1735
1729
|
/**
|
|
1736
1730
|
* Convert a string into a number. It assumes that the string actually represents
|
|
@@ -2594,6 +2588,9 @@
|
|
|
2594
2588
|
return result;
|
|
2595
2589
|
}
|
|
2596
2590
|
function operandToRegExp(operand) {
|
|
2591
|
+
if (operand === "*") {
|
|
2592
|
+
return /.+/;
|
|
2593
|
+
}
|
|
2597
2594
|
let exp = "";
|
|
2598
2595
|
let predecessor = "";
|
|
2599
2596
|
for (let char of operand) {
|
|
@@ -2617,9 +2614,9 @@
|
|
|
2617
2614
|
}
|
|
2618
2615
|
return new RegExp("^" + exp + "$", "i");
|
|
2619
2616
|
}
|
|
2620
|
-
function evaluatePredicate(value, criterion) {
|
|
2617
|
+
function evaluatePredicate(value = "", criterion) {
|
|
2621
2618
|
const { operator, operand } = criterion;
|
|
2622
|
-
if (
|
|
2619
|
+
if (operand === undefined || value === null || operand === null) {
|
|
2623
2620
|
return false;
|
|
2624
2621
|
}
|
|
2625
2622
|
if (typeof operand === "number" && operator === "=") {
|
|
@@ -4853,7 +4850,6 @@
|
|
|
4853
4850
|
};
|
|
4854
4851
|
canvas = owl.useRef("graphContainer");
|
|
4855
4852
|
chart;
|
|
4856
|
-
currentRuntime;
|
|
4857
4853
|
get background() {
|
|
4858
4854
|
return this.chartRuntime.background;
|
|
4859
4855
|
}
|
|
@@ -4870,18 +4866,11 @@
|
|
|
4870
4866
|
setup() {
|
|
4871
4867
|
owl.onMounted(() => {
|
|
4872
4868
|
const runtime = this.chartRuntime;
|
|
4873
|
-
this.currentRuntime = runtime;
|
|
4874
4869
|
// Note: chartJS modify the runtime in place, so it's important to give it a copy
|
|
4875
4870
|
this.createChart(deepCopy(runtime.chartJsConfig));
|
|
4876
4871
|
});
|
|
4877
4872
|
owl.onWillUnmount(() => this.chart?.destroy());
|
|
4878
|
-
owl.useEffect(() =>
|
|
4879
|
-
const runtime = this.chartRuntime;
|
|
4880
|
-
if (!deepEquals(runtime, this.currentRuntime, "ignoreFunctions")) {
|
|
4881
|
-
this.currentRuntime = runtime;
|
|
4882
|
-
this.updateChartJs(deepCopy(runtime));
|
|
4883
|
-
}
|
|
4884
|
-
});
|
|
4873
|
+
owl.useEffect(() => this.updateChartJs(deepCopy(this.chartRuntime)), () => [this.chartRuntime]);
|
|
4885
4874
|
}
|
|
4886
4875
|
createChart(chartData) {
|
|
4887
4876
|
const canvas = this.canvas.el;
|
|
@@ -7717,19 +7706,22 @@
|
|
|
7717
7706
|
}
|
|
7718
7707
|
|
|
7719
7708
|
function isValidLocale(locale) {
|
|
7720
|
-
if (!
|
|
7721
|
-
typeof locale
|
|
7722
|
-
typeof locale.
|
|
7723
|
-
typeof locale.code === "string" &&
|
|
7724
|
-
typeof locale.thousandsSeparator === "string" &&
|
|
7725
|
-
typeof locale.decimalSeparator === "string" &&
|
|
7726
|
-
typeof locale.dateFormat === "string" &&
|
|
7727
|
-
typeof locale.timeFormat === "string" &&
|
|
7728
|
-
typeof locale.formulaArgSeparator === "string")) {
|
|
7709
|
+
if (!locale ||
|
|
7710
|
+
typeof locale !== "object" ||
|
|
7711
|
+
!(!locale.thousandsSeparator || typeof locale.thousandsSeparator === "string")) {
|
|
7729
7712
|
return false;
|
|
7730
7713
|
}
|
|
7731
|
-
|
|
7732
|
-
|
|
7714
|
+
for (const property of [
|
|
7715
|
+
"code",
|
|
7716
|
+
"name",
|
|
7717
|
+
"decimalSeparator",
|
|
7718
|
+
"dateFormat",
|
|
7719
|
+
"timeFormat",
|
|
7720
|
+
"formulaArgSeparator",
|
|
7721
|
+
]) {
|
|
7722
|
+
if (!locale[property] || typeof locale[property] !== "string") {
|
|
7723
|
+
return false;
|
|
7724
|
+
}
|
|
7733
7725
|
}
|
|
7734
7726
|
if (locale.formulaArgSeparator === locale.decimalSeparator) {
|
|
7735
7727
|
return false;
|
|
@@ -7827,7 +7819,10 @@
|
|
|
7827
7819
|
if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
|
|
7828
7820
|
return content;
|
|
7829
7821
|
}
|
|
7830
|
-
|
|
7822
|
+
if (locale.thousandsSeparator) {
|
|
7823
|
+
content = content.replaceAll(locale.thousandsSeparator, "");
|
|
7824
|
+
}
|
|
7825
|
+
return content.replace(locale.decimalSeparator, ".");
|
|
7831
7826
|
}
|
|
7832
7827
|
/**
|
|
7833
7828
|
* Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
|
|
@@ -8473,7 +8468,7 @@
|
|
|
8473
8468
|
/**
|
|
8474
8469
|
* Get a default chart js configuration
|
|
8475
8470
|
*/
|
|
8476
|
-
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels }) {
|
|
8471
|
+
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels = true }) {
|
|
8477
8472
|
const options = {
|
|
8478
8473
|
// https://www.chartjs.org/docs/latest/general/responsive.html
|
|
8479
8474
|
responsive: true,
|
|
@@ -9506,15 +9501,6 @@
|
|
|
9506
9501
|
}
|
|
9507
9502
|
const colors = new ChartColors();
|
|
9508
9503
|
for (let [index, { label, data }] of dataSetsValues.entries()) {
|
|
9509
|
-
if (["linear", "time"].includes(axisType)) {
|
|
9510
|
-
// Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
|
|
9511
|
-
data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
|
|
9512
|
-
}
|
|
9513
|
-
const color = colors.next();
|
|
9514
|
-
let backgroundRGBA = colorToRGBA(color);
|
|
9515
|
-
if (chart.stacked) {
|
|
9516
|
-
backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
|
|
9517
|
-
}
|
|
9518
9504
|
if (chart.cumulative) {
|
|
9519
9505
|
let accumulator = 0;
|
|
9520
9506
|
data = data.map((value) => {
|
|
@@ -9525,6 +9511,15 @@
|
|
|
9525
9511
|
return value;
|
|
9526
9512
|
});
|
|
9527
9513
|
}
|
|
9514
|
+
if (["linear", "time"].includes(axisType)) {
|
|
9515
|
+
// Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
|
|
9516
|
+
data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
|
|
9517
|
+
}
|
|
9518
|
+
const color = colors.next();
|
|
9519
|
+
let backgroundRGBA = colorToRGBA(color);
|
|
9520
|
+
if (chart.stacked) {
|
|
9521
|
+
backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
|
|
9522
|
+
}
|
|
9528
9523
|
const backgroundColor = rgbaToHex(backgroundRGBA);
|
|
9529
9524
|
const dataset = {
|
|
9530
9525
|
label,
|
|
@@ -24780,7 +24775,13 @@
|
|
|
24780
24775
|
}
|
|
24781
24776
|
async loadLocales() {
|
|
24782
24777
|
this.loadedLocales = (await this.env.loadLocales())
|
|
24783
|
-
.filter(
|
|
24778
|
+
.filter((locale) => {
|
|
24779
|
+
const isValid = isValidLocale(locale);
|
|
24780
|
+
if (!isValid) {
|
|
24781
|
+
console.warn(`Invalid locale: ${locale["code"]} ${locale}`);
|
|
24782
|
+
}
|
|
24783
|
+
return isValid;
|
|
24784
|
+
})
|
|
24784
24785
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
24785
24786
|
}
|
|
24786
24787
|
get numberFormatPreview() {
|
|
@@ -30536,6 +30537,7 @@
|
|
|
30536
30537
|
return;
|
|
30537
30538
|
}
|
|
30538
30539
|
if (clipboardData.types.indexOf(ClipboardMIMEType.PlainText) > -1) {
|
|
30540
|
+
ev.preventDefault();
|
|
30539
30541
|
const content = clipboardData.getData(ClipboardMIMEType.PlainText);
|
|
30540
30542
|
const target = this.env.model.getters.getSelectedZones();
|
|
30541
30543
|
const clipboardString = this.env.model.getters.getClipboardTextContent();
|
|
@@ -35133,6 +35135,21 @@
|
|
|
35133
35135
|
return [];
|
|
35134
35136
|
return Object.keys(sheetBorders).map((index) => parseInt(index, 10));
|
|
35135
35137
|
}
|
|
35138
|
+
/**
|
|
35139
|
+
* Get all the rows which contains at least a border
|
|
35140
|
+
*/
|
|
35141
|
+
getRowsWithBorders(sheetId) {
|
|
35142
|
+
const sheetBorders = this.borders[sheetId]?.filter(isDefined$1);
|
|
35143
|
+
if (!sheetBorders)
|
|
35144
|
+
return [];
|
|
35145
|
+
const rowsWithBorders = new Set();
|
|
35146
|
+
for (const rowBorders of sheetBorders) {
|
|
35147
|
+
for (const rowBorder in rowBorders) {
|
|
35148
|
+
rowsWithBorders.add(parseInt(rowBorder, 10));
|
|
35149
|
+
}
|
|
35150
|
+
}
|
|
35151
|
+
return Array.from(rowsWithBorders);
|
|
35152
|
+
}
|
|
35136
35153
|
/**
|
|
35137
35154
|
* Get the range of all the rows in the sheet
|
|
35138
35155
|
*/
|
|
@@ -35182,7 +35199,7 @@
|
|
|
35182
35199
|
destructive: false,
|
|
35183
35200
|
});
|
|
35184
35201
|
}
|
|
35185
|
-
this.
|
|
35202
|
+
this.getRowsWithBorders(sheetId)
|
|
35186
35203
|
.filter((row) => row >= start)
|
|
35187
35204
|
.sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
|
|
35188
35205
|
.forEach((row) => {
|
|
@@ -35637,7 +35654,7 @@
|
|
|
35637
35654
|
* Parse an expression (as a string) into an AST.
|
|
35638
35655
|
*/
|
|
35639
35656
|
function parse(str) {
|
|
35640
|
-
return parseTokens(
|
|
35657
|
+
return parseTokens(rangeTokenize(str));
|
|
35641
35658
|
}
|
|
35642
35659
|
function parseTokens(tokens) {
|
|
35643
35660
|
tokens = tokens.filter((x) => x.type !== "SPACE");
|
|
@@ -42131,6 +42148,7 @@
|
|
|
42131
42148
|
}
|
|
42132
42149
|
finally {
|
|
42133
42150
|
this.cellsBeingComputed.delete(cellId);
|
|
42151
|
+
this.nextPositionsToUpdate.delete(positionId);
|
|
42134
42152
|
}
|
|
42135
42153
|
}
|
|
42136
42154
|
computeAndSave(position) {
|
|
@@ -42159,11 +42177,36 @@
|
|
|
42159
42177
|
forEachSpreadPositionInMatrix(nbColumns, nbRows,
|
|
42160
42178
|
// thanks to the isMatrix check above, we know that formulaReturn is MatrixFunctionReturn
|
|
42161
42179
|
this.spreadValues(formulaPosition, formulaReturn));
|
|
42180
|
+
this.invalidatePositionsDependingOnSpread(formulaPosition, nbColumns, nbRows);
|
|
42162
42181
|
return createEvaluatedCell(formulaReturn[0][0].value, {
|
|
42163
42182
|
format: cellData.format || formulaReturn[0][0]?.format,
|
|
42164
42183
|
locale: this.getters.getLocale(),
|
|
42165
42184
|
}, formulaReturn[0][0].message);
|
|
42166
42185
|
}
|
|
42186
|
+
invalidatePositionsDependingOnSpread(arrayFormulaPosition, nbColumns, nbRows) {
|
|
42187
|
+
// the result matrix is split in 2 zones to exclude the array formula position
|
|
42188
|
+
const top = arrayFormulaPosition.row;
|
|
42189
|
+
const left = arrayFormulaPosition.col;
|
|
42190
|
+
const bottom = top + nbRows - 1;
|
|
42191
|
+
const leftColumnZone = {
|
|
42192
|
+
top: top + 1,
|
|
42193
|
+
bottom,
|
|
42194
|
+
left,
|
|
42195
|
+
right: left,
|
|
42196
|
+
};
|
|
42197
|
+
const rightPartZone = {
|
|
42198
|
+
top,
|
|
42199
|
+
bottom,
|
|
42200
|
+
left: left + 1,
|
|
42201
|
+
right: left + nbColumns - 1,
|
|
42202
|
+
};
|
|
42203
|
+
const sheetId = arrayFormulaPosition.sheetId;
|
|
42204
|
+
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn([
|
|
42205
|
+
{ sheetId, zone: rightPartZone },
|
|
42206
|
+
{ sheetId, zone: leftColumnZone },
|
|
42207
|
+
]);
|
|
42208
|
+
this.nextPositionsToUpdate.addMany(invalidatedPositions);
|
|
42209
|
+
}
|
|
42167
42210
|
assertSheetHasEnoughSpaceToSpreadFormulaResult({ sheetId, col, row }, matrixResult) {
|
|
42168
42211
|
const numberOfCols = this.getters.getNumberCols(sheetId);
|
|
42169
42212
|
const numberOfRows = this.getters.getNumberRows(sheetId);
|
|
@@ -42212,9 +42255,6 @@
|
|
|
42212
42255
|
}, matrixResult[i][j].message);
|
|
42213
42256
|
const positionId = this.encoder.encode(position);
|
|
42214
42257
|
this.setEvaluatedCell(positionId, evaluatedCell);
|
|
42215
|
-
// check if formula dependencies present in the spread zone
|
|
42216
|
-
// if so, they need to be recomputed
|
|
42217
|
-
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([positionId]));
|
|
42218
42258
|
};
|
|
42219
42259
|
}
|
|
42220
42260
|
invalidateSpreading(positionId) {
|
|
@@ -57838,9 +57878,9 @@
|
|
|
57838
57878
|
exports.tokenize = tokenize;
|
|
57839
57879
|
|
|
57840
57880
|
|
|
57841
|
-
__info__.version = "17.1.
|
|
57842
|
-
__info__.date = "2024-07-
|
|
57843
|
-
__info__.hash = "
|
|
57881
|
+
__info__.version = "17.1.23";
|
|
57882
|
+
__info__.date = "2024-07-11T06:37:01.931Z";
|
|
57883
|
+
__info__.hash = "31e8450";
|
|
57844
57884
|
|
|
57845
57885
|
|
|
57846
57886
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|