@odoo/o-spreadsheet 17.4.0-alpha.0 → 17.4.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/o-spreadsheet.cjs.js +353 -265
- package/dist/o-spreadsheet.d.ts +80 -63
- package/dist/o-spreadsheet.esm.js +353 -265
- package/dist/o-spreadsheet.iife.js +353 -265
- package/dist/o-spreadsheet.iife.min.js +375 -371
- package/dist/o_spreadsheet.xml +33 -23
- package/package.json +1 -1
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
5
5
|
* @see https://github.com/odoo/o-spreadsheet
|
|
6
|
-
* @version 17.4.0-alpha.
|
|
7
|
-
* @date 2024-
|
|
8
|
-
* @hash
|
|
6
|
+
* @version 17.4.0-alpha.2
|
|
7
|
+
* @date 2024-06-06T13:31:21.327Z
|
|
8
|
+
* @hash e07794d
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
'use strict';
|
|
@@ -8961,7 +8961,7 @@ class NotificationStore {
|
|
|
8961
8961
|
"askConfirmation",
|
|
8962
8962
|
"updateNotificationCallbacks",
|
|
8963
8963
|
];
|
|
8964
|
-
notifyUser = (notification) => window.alert(notification);
|
|
8964
|
+
notifyUser = (notification) => window.alert(notification.text);
|
|
8965
8965
|
askConfirmation = (content, confirm, cancel) => {
|
|
8966
8966
|
if (window.confirm(content)) {
|
|
8967
8967
|
confirm();
|
|
@@ -18377,6 +18377,131 @@ var logical = /*#__PURE__*/Object.freeze({
|
|
|
18377
18377
|
const supportedPivotExplodedFormulaRegistry = new Registry();
|
|
18378
18378
|
supportedPivotExplodedFormulaRegistry.add("SPREADSHEET", false);
|
|
18379
18379
|
|
|
18380
|
+
const AGGREGATOR_NAMES = {
|
|
18381
|
+
count: _t("Count"),
|
|
18382
|
+
count_distinct: _t("Count Distinct"),
|
|
18383
|
+
bool_and: _t("Boolean And"),
|
|
18384
|
+
bool_or: _t("Boolean Or"),
|
|
18385
|
+
max: _t("Maximum"),
|
|
18386
|
+
min: _t("Minimum"),
|
|
18387
|
+
avg: _t("Average"),
|
|
18388
|
+
sum: _t("Sum"),
|
|
18389
|
+
};
|
|
18390
|
+
const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
|
|
18391
|
+
const AGGREGATORS_BY_FIELD_TYPE = {
|
|
18392
|
+
integer: NUMBER_CHAR_AGGREGATORS,
|
|
18393
|
+
char: NUMBER_CHAR_AGGREGATORS,
|
|
18394
|
+
//TODO Support for date and boolean
|
|
18395
|
+
};
|
|
18396
|
+
const AGGREGATORS = {};
|
|
18397
|
+
for (const type in AGGREGATORS_BY_FIELD_TYPE) {
|
|
18398
|
+
AGGREGATORS[type] = {};
|
|
18399
|
+
for (const aggregator of AGGREGATORS_BY_FIELD_TYPE[type]) {
|
|
18400
|
+
AGGREGATORS[type][aggregator] = AGGREGATOR_NAMES[aggregator];
|
|
18401
|
+
}
|
|
18402
|
+
}
|
|
18403
|
+
const AGGREGATORS_FN = {
|
|
18404
|
+
count: {
|
|
18405
|
+
fn: (args) => countAny([args]),
|
|
18406
|
+
format: () => "0",
|
|
18407
|
+
},
|
|
18408
|
+
count_distinct: {
|
|
18409
|
+
fn: (args) => countUnique([args]),
|
|
18410
|
+
format: () => "0",
|
|
18411
|
+
},
|
|
18412
|
+
bool_and: {
|
|
18413
|
+
fn: (args) => boolAnd([args]).result,
|
|
18414
|
+
format: () => undefined,
|
|
18415
|
+
},
|
|
18416
|
+
bool_or: {
|
|
18417
|
+
fn: (args) => boolOr([args]).result,
|
|
18418
|
+
format: () => undefined,
|
|
18419
|
+
},
|
|
18420
|
+
max: {
|
|
18421
|
+
fn: (args, locale) => max([args], locale),
|
|
18422
|
+
format: inferFormat,
|
|
18423
|
+
},
|
|
18424
|
+
min: {
|
|
18425
|
+
fn: (args, locale) => min([args], locale),
|
|
18426
|
+
format: inferFormat,
|
|
18427
|
+
},
|
|
18428
|
+
avg: {
|
|
18429
|
+
fn: (args, locale) => average([args], locale),
|
|
18430
|
+
format: inferFormat,
|
|
18431
|
+
},
|
|
18432
|
+
sum: {
|
|
18433
|
+
fn: (args, locale) => sum([args], locale),
|
|
18434
|
+
format: inferFormat,
|
|
18435
|
+
},
|
|
18436
|
+
};
|
|
18437
|
+
/**
|
|
18438
|
+
* Build a pivot formula expression
|
|
18439
|
+
*/
|
|
18440
|
+
function makePivotFormula(formula, args) {
|
|
18441
|
+
return `=${formula}(${args
|
|
18442
|
+
.map((arg) => {
|
|
18443
|
+
const stringIsNumber = typeof arg == "string" && !isNaN(Number(arg)) && Number(arg).toString() === arg;
|
|
18444
|
+
const convertToNumber = typeof arg == "number" || stringIsNumber;
|
|
18445
|
+
return convertToNumber ? `${arg}` : `"${arg.toString().replace(/"/g, '\\"')}"`;
|
|
18446
|
+
})
|
|
18447
|
+
.join(",")})`;
|
|
18448
|
+
}
|
|
18449
|
+
/**
|
|
18450
|
+
* Given an object of form {"1": {...}, "2": {...}, ...} get the maximum ID used
|
|
18451
|
+
* in this object
|
|
18452
|
+
* If the object has no keys, return 0
|
|
18453
|
+
*
|
|
18454
|
+
*/
|
|
18455
|
+
function getMaxObjectId(o) {
|
|
18456
|
+
const keys = Object.keys(o);
|
|
18457
|
+
if (!keys.length) {
|
|
18458
|
+
return 0;
|
|
18459
|
+
}
|
|
18460
|
+
const nums = keys.map((id) => parseInt(id, 10));
|
|
18461
|
+
const max = Math.max(...nums);
|
|
18462
|
+
return max;
|
|
18463
|
+
}
|
|
18464
|
+
const ALL_PERIODS = {
|
|
18465
|
+
year: _t("Year"),
|
|
18466
|
+
quarter: _t("Quarter"),
|
|
18467
|
+
month: _t("Month"),
|
|
18468
|
+
week: _t("Week"),
|
|
18469
|
+
day: _t("Day"),
|
|
18470
|
+
year_number: _t("Year"),
|
|
18471
|
+
quarter_number: _t("Quarter"),
|
|
18472
|
+
month_number: _t("Month"),
|
|
18473
|
+
iso_week_number: _t("Week"),
|
|
18474
|
+
day_of_month: _t("Day of Month"),
|
|
18475
|
+
};
|
|
18476
|
+
const DATE_FIELDS = ["date", "datetime"];
|
|
18477
|
+
/**
|
|
18478
|
+
* Parse a dimension string into a pivot dimension definition.
|
|
18479
|
+
* e.g "create_date:month" => { name: "create_date", granularity: "month" }
|
|
18480
|
+
*/
|
|
18481
|
+
function parseDimension(dimension) {
|
|
18482
|
+
const [name, granularity] = dimension.split(":");
|
|
18483
|
+
if (granularity) {
|
|
18484
|
+
return { name, granularity };
|
|
18485
|
+
}
|
|
18486
|
+
return { name };
|
|
18487
|
+
}
|
|
18488
|
+
function isDateField(field) {
|
|
18489
|
+
return DATE_FIELDS.includes(field.type);
|
|
18490
|
+
}
|
|
18491
|
+
function toPivotDomain(domainStr) {
|
|
18492
|
+
if (domainStr.length % 2 !== 0) {
|
|
18493
|
+
throw new Error("Invalid domain: odd number of elements");
|
|
18494
|
+
}
|
|
18495
|
+
const domain = [];
|
|
18496
|
+
for (let i = 0; i < domainStr.length - 1; i += 2) {
|
|
18497
|
+
domain.push({ field: domainStr[i], value: domainStr[i + 1] });
|
|
18498
|
+
}
|
|
18499
|
+
return domain;
|
|
18500
|
+
}
|
|
18501
|
+
function flatPivotDomain(domain) {
|
|
18502
|
+
return domain.flatMap((arg) => [arg.field, arg.value]);
|
|
18503
|
+
}
|
|
18504
|
+
|
|
18380
18505
|
/**
|
|
18381
18506
|
* Get the pivot ID from the formula pivot ID.
|
|
18382
18507
|
*/
|
|
@@ -18856,13 +18981,13 @@ const PIVOT_VALUE = {
|
|
|
18856
18981
|
arg("domain_field_name (string,optional,repeating)", _t("Field name.")),
|
|
18857
18982
|
arg("domain_value (string,optional,repeating)", _t("Value.")),
|
|
18858
18983
|
],
|
|
18859
|
-
compute: function (formulaId, measureName, ...
|
|
18984
|
+
compute: function (formulaId, measureName, ...domainArgs) {
|
|
18860
18985
|
const _pivotFormulaId = toString(formulaId);
|
|
18861
|
-
const
|
|
18862
|
-
const
|
|
18986
|
+
const _measure = toString(measureName);
|
|
18987
|
+
const _domainArgs = domainArgs.map(toString);
|
|
18863
18988
|
const pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
18864
|
-
assertMeasureExist(pivotId,
|
|
18865
|
-
assertDomainLength(
|
|
18989
|
+
assertMeasureExist(pivotId, _measure, this.getters);
|
|
18990
|
+
assertDomainLength(_domainArgs);
|
|
18866
18991
|
const pivot = this.getters.getPivot(pivotId);
|
|
18867
18992
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
18868
18993
|
if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
|
|
@@ -18876,8 +19001,9 @@ const PIVOT_VALUE = {
|
|
|
18876
19001
|
if (error) {
|
|
18877
19002
|
return error;
|
|
18878
19003
|
}
|
|
18879
|
-
const
|
|
18880
|
-
|
|
19004
|
+
const domain = toPivotDomain(_domainArgs);
|
|
19005
|
+
const { value, format } = pivot.getPivotCellValueAndFormat(_measure, domain);
|
|
19006
|
+
if (!value && !this.getters.areDomainArgsFieldsValid(pivotId, domain)) {
|
|
18881
19007
|
return {
|
|
18882
19008
|
value: CellErrorType.GenericError,
|
|
18883
19009
|
message: _t("Dimensions don't match the pivot definition"),
|
|
@@ -18894,11 +19020,11 @@ const PIVOT_HEADER = {
|
|
|
18894
19020
|
arg("domain_field_name (string,optional,repeating)", _t("Field name.")),
|
|
18895
19021
|
arg("domain_value (string,optional,repeating)", _t("Value.")),
|
|
18896
19022
|
],
|
|
18897
|
-
compute: function (pivotId, ...
|
|
19023
|
+
compute: function (pivotId, ...domainArgs) {
|
|
18898
19024
|
const _pivotFormulaId = toString(pivotId);
|
|
18899
|
-
const
|
|
19025
|
+
const _domainArgs = domainArgs.map(toString);
|
|
18900
19026
|
const _pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
18901
|
-
assertDomainLength(
|
|
19027
|
+
assertDomainLength(_domainArgs);
|
|
18902
19028
|
const pivot = this.getters.getPivot(_pivotId);
|
|
18903
19029
|
const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
|
|
18904
19030
|
if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
|
|
@@ -18912,18 +19038,23 @@ const PIVOT_HEADER = {
|
|
|
18912
19038
|
if (error) {
|
|
18913
19039
|
return error;
|
|
18914
19040
|
}
|
|
18915
|
-
const
|
|
18916
|
-
const
|
|
18917
|
-
if (!this.getters.areDomainArgsFieldsValid(_pivotId,
|
|
19041
|
+
const domain = toPivotDomain(_domainArgs);
|
|
19042
|
+
const lastNode = domain.at(-1);
|
|
19043
|
+
if (!this.getters.areDomainArgsFieldsValid(_pivotId, lastNode?.field === "measure" ? domain.slice(0, -1) : domain)) {
|
|
18918
19044
|
return {
|
|
18919
19045
|
value: CellErrorType.GenericError,
|
|
18920
19046
|
message: _t("Dimensions don't match the pivot definition"),
|
|
18921
19047
|
};
|
|
18922
19048
|
}
|
|
18923
|
-
|
|
19049
|
+
if (lastNode?.field === "measure") {
|
|
19050
|
+
return pivot.getPivotMeasureValue(toString(lastNode.value), domain);
|
|
19051
|
+
}
|
|
19052
|
+
const { value, format } = pivot.getPivotHeaderValueAndFormat(domain);
|
|
18924
19053
|
return {
|
|
18925
19054
|
value,
|
|
18926
|
-
format: !
|
|
19055
|
+
format: !lastNode || lastNode.field === "measure" || lastNode.value === "false"
|
|
19056
|
+
? undefined
|
|
19057
|
+
: format,
|
|
18927
19058
|
};
|
|
18928
19059
|
},
|
|
18929
19060
|
returns: ["NUMBER", "STRING"],
|
|
@@ -18936,11 +19067,14 @@ const PIVOT = {
|
|
|
18936
19067
|
arg("include_total (boolean, default=TRUE)", _t("Whether to include total/sub-totals or not.")),
|
|
18937
19068
|
arg("include_column_titles (boolean, default=TRUE)", _t("Whether to include the column titles or not.")),
|
|
18938
19069
|
],
|
|
18939
|
-
compute: function (
|
|
18940
|
-
const _pivotFormulaId = toString(
|
|
18941
|
-
const
|
|
18942
|
-
const
|
|
18943
|
-
const
|
|
19070
|
+
compute: function (pivotFormulaId, rowCount = { value: 10000 }, includeTotal = { value: true }, includeColumnHeaders = { value: true }) {
|
|
19071
|
+
const _pivotFormulaId = toString(pivotFormulaId);
|
|
19072
|
+
const _rowCount = toNumber(rowCount, this.locale);
|
|
19073
|
+
const _includeColumnHeaders = toBoolean(includeColumnHeaders);
|
|
19074
|
+
const _includedTotal = toBoolean(includeTotal);
|
|
19075
|
+
const pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
19076
|
+
const pivot = this.getters.getPivot(pivotId);
|
|
19077
|
+
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
18944
19078
|
addPivotDependencies(this, coreDefinition);
|
|
18945
19079
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
18946
19080
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
@@ -18948,11 +19082,9 @@ const PIVOT = {
|
|
|
18948
19082
|
return error;
|
|
18949
19083
|
}
|
|
18950
19084
|
const table = pivot.getTableStructure();
|
|
18951
|
-
const
|
|
18952
|
-
const cells = table.getPivotCells(toBoolean(includeTotal), _includeColumnHeaders);
|
|
19085
|
+
const cells = table.getPivotCells(_includedTotal, _includeColumnHeaders);
|
|
18953
19086
|
const headerRows = _includeColumnHeaders ? table.columns.length : 0;
|
|
18954
|
-
const pivotTitle = this.getters.getPivotDisplayName(
|
|
18955
|
-
const _rowCount = toNumber(rowCount, this.locale);
|
|
19087
|
+
const pivotTitle = this.getters.getPivotDisplayName(pivotId);
|
|
18956
19088
|
if (_rowCount < 0) {
|
|
18957
19089
|
throw new EvaluationError(_t("The number of rows must be positive."));
|
|
18958
19090
|
}
|
|
@@ -18967,17 +19099,23 @@ const PIVOT = {
|
|
|
18967
19099
|
result[col] = [];
|
|
18968
19100
|
for (const row of tableRows) {
|
|
18969
19101
|
const pivotCell = cells[col][row];
|
|
18970
|
-
|
|
18971
|
-
|
|
18972
|
-
|
|
18973
|
-
|
|
18974
|
-
|
|
18975
|
-
|
|
18976
|
-
|
|
18977
|
-
|
|
18978
|
-
|
|
18979
|
-
|
|
18980
|
-
|
|
19102
|
+
switch (pivotCell.type) {
|
|
19103
|
+
case "EMPTY":
|
|
19104
|
+
result[col].push({ value: "" });
|
|
19105
|
+
break;
|
|
19106
|
+
case "HEADER":
|
|
19107
|
+
const domain = pivotCell.domain;
|
|
19108
|
+
const lastNode = domain.at(-1);
|
|
19109
|
+
if (lastNode?.field === "measure") {
|
|
19110
|
+
result[col].push(pivot.getPivotMeasureValue(toString(lastNode.value), domain));
|
|
19111
|
+
}
|
|
19112
|
+
else {
|
|
19113
|
+
result[col].push(pivot.getPivotHeaderValueAndFormat(domain));
|
|
19114
|
+
}
|
|
19115
|
+
break;
|
|
19116
|
+
case "VALUE":
|
|
19117
|
+
result[col].push(pivot.getPivotCellValueAndFormat(pivotCell.measure, pivotCell.domain));
|
|
19118
|
+
break;
|
|
18981
19119
|
}
|
|
18982
19120
|
}
|
|
18983
19121
|
}
|
|
@@ -20902,8 +21040,15 @@ class Composer extends owl.Component {
|
|
|
20902
21040
|
}
|
|
20903
21041
|
onPaste(ev) {
|
|
20904
21042
|
if (this.composerStore.editionMode !== "inactive") {
|
|
21043
|
+
// let the browser clipboard work
|
|
20905
21044
|
ev.stopPropagation();
|
|
20906
21045
|
}
|
|
21046
|
+
else {
|
|
21047
|
+
// the user meant to paste in the sheet, not open the composer with the pasted content
|
|
21048
|
+
// While we're not editing, we still have the focus and should therefore prevent
|
|
21049
|
+
// the native "paste" to occur.
|
|
21050
|
+
ev.preventDefault();
|
|
21051
|
+
}
|
|
20907
21052
|
}
|
|
20908
21053
|
/*
|
|
20909
21054
|
* Triggered automatically by the content-editable between the keydown and key up
|
|
@@ -20912,9 +21057,6 @@ class Composer extends owl.Component {
|
|
|
20912
21057
|
if (!this.shouldProcessInputEvents) {
|
|
20913
21058
|
return;
|
|
20914
21059
|
}
|
|
20915
|
-
if (ev.inputType === "insertFromPaste" && this.composerStore.editionMode === "inactive") {
|
|
20916
|
-
return;
|
|
20917
|
-
}
|
|
20918
21060
|
ev.stopPropagation();
|
|
20919
21061
|
let content;
|
|
20920
21062
|
if (this.composerStore.editionMode === "inactive") {
|
|
@@ -21567,132 +21709,8 @@ function getFunctionsFromAST(ast, functionNames) {
|
|
|
21567
21709
|
}
|
|
21568
21710
|
|
|
21569
21711
|
const PIVOT_FUNCTIONS = ["PIVOT.VALUE", "PIVOT.HEADER", "PIVOT"];
|
|
21570
|
-
const AGGREGATOR_NAMES = {
|
|
21571
|
-
count: _t("Count"),
|
|
21572
|
-
count_distinct: _t("Count Distinct"),
|
|
21573
|
-
bool_and: _t("Boolean And"),
|
|
21574
|
-
bool_or: _t("Boolean Or"),
|
|
21575
|
-
max: _t("Maximum"),
|
|
21576
|
-
min: _t("Minimum"),
|
|
21577
|
-
avg: _t("Average"),
|
|
21578
|
-
sum: _t("Sum"),
|
|
21579
|
-
};
|
|
21580
|
-
const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
|
|
21581
|
-
const AGGREGATORS_BY_FIELD_TYPE = {
|
|
21582
|
-
integer: NUMBER_CHAR_AGGREGATORS,
|
|
21583
|
-
char: NUMBER_CHAR_AGGREGATORS,
|
|
21584
|
-
//TODO Support for date and boolean
|
|
21585
|
-
};
|
|
21586
|
-
const AGGREGATORS = {};
|
|
21587
|
-
for (const type in AGGREGATORS_BY_FIELD_TYPE) {
|
|
21588
|
-
AGGREGATORS[type] = {};
|
|
21589
|
-
for (const aggregator of AGGREGATORS_BY_FIELD_TYPE[type]) {
|
|
21590
|
-
AGGREGATORS[type][aggregator] = AGGREGATOR_NAMES[aggregator];
|
|
21591
|
-
}
|
|
21592
|
-
}
|
|
21593
|
-
const AGGREGATORS_FN = {
|
|
21594
|
-
count: {
|
|
21595
|
-
fn: (args) => countAny([args]),
|
|
21596
|
-
format: () => "0",
|
|
21597
|
-
},
|
|
21598
|
-
count_distinct: {
|
|
21599
|
-
fn: (args) => countUnique([args]),
|
|
21600
|
-
format: () => "0",
|
|
21601
|
-
},
|
|
21602
|
-
bool_and: {
|
|
21603
|
-
fn: (args) => boolAnd([args]).result,
|
|
21604
|
-
format: () => undefined,
|
|
21605
|
-
},
|
|
21606
|
-
bool_or: {
|
|
21607
|
-
fn: (args) => boolOr([args]).result,
|
|
21608
|
-
format: () => undefined,
|
|
21609
|
-
},
|
|
21610
|
-
max: {
|
|
21611
|
-
fn: (args, locale) => max([args], locale),
|
|
21612
|
-
format: inferFormat,
|
|
21613
|
-
},
|
|
21614
|
-
min: {
|
|
21615
|
-
fn: (args, locale) => min([args], locale),
|
|
21616
|
-
format: inferFormat,
|
|
21617
|
-
},
|
|
21618
|
-
avg: {
|
|
21619
|
-
fn: (args, locale) => average([args], locale),
|
|
21620
|
-
format: inferFormat,
|
|
21621
|
-
},
|
|
21622
|
-
sum: {
|
|
21623
|
-
fn: (args, locale) => sum([args], locale),
|
|
21624
|
-
format: inferFormat,
|
|
21625
|
-
},
|
|
21626
|
-
};
|
|
21627
|
-
/**
|
|
21628
|
-
* Build a pivot formula expression
|
|
21629
|
-
*/
|
|
21630
|
-
function makePivotFormula(formula, args) {
|
|
21631
|
-
return `=${formula}(${args
|
|
21632
|
-
.map((arg) => {
|
|
21633
|
-
const stringIsNumber = typeof arg == "string" && !isNaN(Number(arg)) && Number(arg).toString() === arg;
|
|
21634
|
-
const convertToNumber = typeof arg == "number" || stringIsNumber;
|
|
21635
|
-
return convertToNumber ? `${arg}` : `"${arg.toString().replace(/"/g, '\\"')}"`;
|
|
21636
|
-
})
|
|
21637
|
-
.join(",")})`;
|
|
21638
|
-
}
|
|
21639
|
-
/**
|
|
21640
|
-
* Given an object of form {"1": {...}, "2": {...}, ...} get the maximum ID used
|
|
21641
|
-
* in this object
|
|
21642
|
-
* If the object has no keys, return 0
|
|
21643
|
-
*
|
|
21644
|
-
*/
|
|
21645
|
-
function getMaxObjectId(o) {
|
|
21646
|
-
const keys = Object.keys(o);
|
|
21647
|
-
if (!keys.length) {
|
|
21648
|
-
return 0;
|
|
21649
|
-
}
|
|
21650
|
-
const nums = keys.map((id) => parseInt(id, 10));
|
|
21651
|
-
const max = Math.max(...nums);
|
|
21652
|
-
return max;
|
|
21653
|
-
}
|
|
21654
|
-
/**
|
|
21655
|
-
* Get the first Pivot function description of the given formula.
|
|
21656
|
-
*/
|
|
21657
|
-
function getFirstPivotFunction(tokens) {
|
|
21658
|
-
return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS)[0];
|
|
21659
|
-
}
|
|
21660
|
-
/**
|
|
21661
|
-
* Parse a spreadsheet formula and detect the number of PIVOT functions that are
|
|
21662
|
-
* present in the given formula.
|
|
21663
|
-
*/
|
|
21664
|
-
function getNumberOfPivotFunctions(tokens) {
|
|
21665
|
-
return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS).length;
|
|
21666
|
-
}
|
|
21667
|
-
const ALL_PERIODS = {
|
|
21668
|
-
year: _t("Year"),
|
|
21669
|
-
quarter: _t("Quarter"),
|
|
21670
|
-
month: _t("Month"),
|
|
21671
|
-
week: _t("Week"),
|
|
21672
|
-
day: _t("Day"),
|
|
21673
|
-
year_number: _t("Year"),
|
|
21674
|
-
quarter_number: _t("Quarter"),
|
|
21675
|
-
month_number: _t("Month"),
|
|
21676
|
-
iso_week_number: _t("Week"),
|
|
21677
|
-
day_of_month: _t("Day of Month"),
|
|
21678
|
-
};
|
|
21679
|
-
const DATE_FIELDS = ["date", "datetime"];
|
|
21680
|
-
/**
|
|
21681
|
-
* Parse a dimension string into a pivot dimension definition.
|
|
21682
|
-
* e.g "create_date:month" => { name: "create_date", granularity: "month" }
|
|
21683
|
-
*/
|
|
21684
|
-
function parseDimension(dimension) {
|
|
21685
|
-
const [name, granularity] = dimension.split(":");
|
|
21686
|
-
if (granularity) {
|
|
21687
|
-
return { name, granularity };
|
|
21688
|
-
}
|
|
21689
|
-
return { name };
|
|
21690
|
-
}
|
|
21691
|
-
function isDateField(field) {
|
|
21692
|
-
return DATE_FIELDS.includes(field.type);
|
|
21693
|
-
}
|
|
21694
21712
|
/**
|
|
21695
|
-
* Create a proposal entry for the compose
|
|
21713
|
+
* Create a proposal entry for the compose autowcomplete
|
|
21696
21714
|
* to insert a field name string in a formula.
|
|
21697
21715
|
*/
|
|
21698
21716
|
function makeFieldProposal(field, granularity) {
|
|
@@ -21748,15 +21766,18 @@ function extractFormulaIdFromToken(tokenAtCursor) {
|
|
|
21748
21766
|
}
|
|
21749
21767
|
return idAst.value;
|
|
21750
21768
|
}
|
|
21751
|
-
|
|
21752
|
-
|
|
21753
|
-
|
|
21754
|
-
|
|
21755
|
-
|
|
21756
|
-
|
|
21757
|
-
|
|
21758
|
-
|
|
21759
|
-
|
|
21769
|
+
/**
|
|
21770
|
+
* Get the first Pivot function description of the given formula.
|
|
21771
|
+
*/
|
|
21772
|
+
function getFirstPivotFunction(tokens) {
|
|
21773
|
+
return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS)[0];
|
|
21774
|
+
}
|
|
21775
|
+
/**
|
|
21776
|
+
* Parse a spreadsheet formula and detect the number of PIVOT functions that are
|
|
21777
|
+
* present in the given formula.
|
|
21778
|
+
*/
|
|
21779
|
+
function getNumberOfPivotFunctions(tokens) {
|
|
21780
|
+
return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS).length;
|
|
21760
21781
|
}
|
|
21761
21782
|
|
|
21762
21783
|
autoCompleteProviders.add("pivot_ids", {
|
|
@@ -32784,7 +32805,7 @@ css /* scss */ `
|
|
|
32784
32805
|
vertical-align: middle;
|
|
32785
32806
|
}
|
|
32786
32807
|
.o_cf_radio_item {
|
|
32787
|
-
margin-right:
|
|
32808
|
+
margin-right: 30px;
|
|
32788
32809
|
}
|
|
32789
32810
|
.radio input:checked {
|
|
32790
32811
|
color: #e9ecef;
|
|
@@ -32804,6 +32825,9 @@ css /* scss */ `
|
|
|
32804
32825
|
}
|
|
32805
32826
|
margin-top: 10px;
|
|
32806
32827
|
display: flex;
|
|
32828
|
+
.form-check {
|
|
32829
|
+
padding-left: 1rem;
|
|
32830
|
+
}
|
|
32807
32831
|
}
|
|
32808
32832
|
.o-section-subtitle:first-child {
|
|
32809
32833
|
margin-top: 0px;
|
|
@@ -32812,7 +32836,7 @@ css /* scss */ `
|
|
|
32812
32836
|
font-size: 12px;
|
|
32813
32837
|
line-height: 1.5;
|
|
32814
32838
|
.o-selection-cf {
|
|
32815
|
-
margin-bottom:
|
|
32839
|
+
margin-bottom: 9px;
|
|
32816
32840
|
}
|
|
32817
32841
|
.o-cell-content {
|
|
32818
32842
|
font-size: 12px;
|
|
@@ -32853,7 +32877,7 @@ css /* scss */ `
|
|
|
32853
32877
|
width: 100%;
|
|
32854
32878
|
}
|
|
32855
32879
|
.o-threshold-value {
|
|
32856
|
-
margin-left:
|
|
32880
|
+
margin-left: 6px;
|
|
32857
32881
|
width: 20%;
|
|
32858
32882
|
min-width: 0px; // input overflows in Firefox otherwise
|
|
32859
32883
|
}
|
|
@@ -32882,8 +32906,8 @@ css /* scss */ `
|
|
|
32882
32906
|
justify-content: space-between;
|
|
32883
32907
|
.o-cf-icon {
|
|
32884
32908
|
display: inline;
|
|
32885
|
-
margin-left:
|
|
32886
|
-
margin-right:
|
|
32909
|
+
margin-left: 3px;
|
|
32910
|
+
margin-right: 3px;
|
|
32887
32911
|
}
|
|
32888
32912
|
svg {
|
|
32889
32913
|
vertical-align: baseline;
|
|
@@ -32906,7 +32930,7 @@ css /* scss */ `
|
|
|
32906
32930
|
}
|
|
32907
32931
|
table {
|
|
32908
32932
|
table-layout: fixed;
|
|
32909
|
-
margin-top:
|
|
32933
|
+
margin-top: 6px;
|
|
32910
32934
|
display: table;
|
|
32911
32935
|
text-align: left;
|
|
32912
32936
|
font-size: 12px;
|
|
@@ -32936,8 +32960,8 @@ css /* scss */ `
|
|
|
32936
32960
|
}
|
|
32937
32961
|
}
|
|
32938
32962
|
.o-cf-iconset-reverse {
|
|
32939
|
-
margin-bottom:
|
|
32940
|
-
margin-top:
|
|
32963
|
+
margin-bottom: 6px;
|
|
32964
|
+
margin-top: 6px;
|
|
32941
32965
|
.o-cf-label {
|
|
32942
32966
|
display: inline-block;
|
|
32943
32967
|
vertical-align: bottom;
|
|
@@ -34644,6 +34668,10 @@ css /* scss */ `
|
|
|
34644
34668
|
select > option {
|
|
34645
34669
|
background-color: white;
|
|
34646
34670
|
}
|
|
34671
|
+
|
|
34672
|
+
.pivot-dim-operator-label {
|
|
34673
|
+
min-width: 120px;
|
|
34674
|
+
}
|
|
34647
34675
|
}
|
|
34648
34676
|
`;
|
|
34649
34677
|
class PivotDimension extends owl.Component {
|
|
@@ -34884,7 +34912,7 @@ class PivotRuntimeDefinition {
|
|
|
34884
34912
|
getMeasure(name) {
|
|
34885
34913
|
const measure = this.measures.find((measure) => measure.name === name);
|
|
34886
34914
|
if (!measure) {
|
|
34887
|
-
throw new EvaluationError(_t("Field %s
|
|
34915
|
+
throw new EvaluationError(_t("Field %s is not a measure", name));
|
|
34888
34916
|
}
|
|
34889
34917
|
return measure;
|
|
34890
34918
|
}
|
|
@@ -35010,10 +35038,9 @@ class SpreadsheetPivotTable {
|
|
|
35010
35038
|
columns;
|
|
35011
35039
|
rows;
|
|
35012
35040
|
measures;
|
|
35013
|
-
rowTitle;
|
|
35014
35041
|
maxIndent;
|
|
35015
35042
|
pivotCells = {};
|
|
35016
|
-
constructor(columns, rows, measures
|
|
35043
|
+
constructor(columns, rows, measures) {
|
|
35017
35044
|
this.columns = columns.map((row) => {
|
|
35018
35045
|
// offset in the pivot table
|
|
35019
35046
|
// starts at 1 because the first column is the row title
|
|
@@ -35026,7 +35053,6 @@ class SpreadsheetPivotTable {
|
|
|
35026
35053
|
});
|
|
35027
35054
|
this.rows = rows;
|
|
35028
35055
|
this.measures = measures;
|
|
35029
|
-
this.rowTitle = rowTitle;
|
|
35030
35056
|
this.maxIndent = Math.max(...this.rows.map((row) => row.indent));
|
|
35031
35057
|
}
|
|
35032
35058
|
/**
|
|
@@ -35068,26 +35094,23 @@ class SpreadsheetPivotTable {
|
|
|
35068
35094
|
}
|
|
35069
35095
|
getPivotCell(col, row, includeTotal = true) {
|
|
35070
35096
|
const colHeadersHeight = this.columns.length;
|
|
35071
|
-
if (
|
|
35072
|
-
return { content: this.rowTitle, isHeader: true };
|
|
35073
|
-
}
|
|
35074
|
-
else if (row <= colHeadersHeight - 1) {
|
|
35097
|
+
if (row <= colHeadersHeight - 1) {
|
|
35075
35098
|
const domain = this.getColHeaderDomain(col, row);
|
|
35076
|
-
return {
|
|
35099
|
+
return domain ? { type: "HEADER", domain } : { type: "EMPTY" };
|
|
35077
35100
|
}
|
|
35078
35101
|
else if (col === 0) {
|
|
35079
35102
|
const rowIndex = row - colHeadersHeight;
|
|
35080
35103
|
const domain = this.getRowDomain(rowIndex);
|
|
35081
|
-
return {
|
|
35104
|
+
return { type: "HEADER", domain };
|
|
35082
35105
|
}
|
|
35083
35106
|
else {
|
|
35084
35107
|
const rowIndex = row - colHeadersHeight;
|
|
35085
35108
|
if (!includeTotal && this.isTotalRow(rowIndex)) {
|
|
35086
|
-
return {
|
|
35109
|
+
return { type: "EMPTY" };
|
|
35087
35110
|
}
|
|
35088
35111
|
const domain = [...this.getRowDomain(rowIndex), ...this.getColDomain(col)];
|
|
35089
35112
|
const measure = this.getColMeasure(col);
|
|
35090
|
-
return {
|
|
35113
|
+
return { type: "VALUE", domain, measure };
|
|
35091
35114
|
}
|
|
35092
35115
|
}
|
|
35093
35116
|
getColHeaderDomain(col, row) {
|
|
@@ -35100,24 +35123,32 @@ class SpreadsheetPivotTable {
|
|
|
35100
35123
|
return undefined;
|
|
35101
35124
|
}
|
|
35102
35125
|
for (let i = 0; i < pivotCol.fields.length; i++) {
|
|
35103
|
-
domain.push(
|
|
35104
|
-
|
|
35126
|
+
domain.push({
|
|
35127
|
+
field: pivotCol.fields[i],
|
|
35128
|
+
value: pivotCol.values[i],
|
|
35129
|
+
});
|
|
35105
35130
|
}
|
|
35106
35131
|
return domain;
|
|
35107
35132
|
}
|
|
35108
35133
|
getColDomain(col) {
|
|
35109
35134
|
const domain = this.getColHeaderDomain(col, this.columns.length - 1);
|
|
35110
|
-
return domain ? domain.slice(0, -
|
|
35135
|
+
return domain ? domain.slice(0, -1) : []; // slice: remove measure and value
|
|
35111
35136
|
}
|
|
35112
35137
|
getColMeasure(col) {
|
|
35113
35138
|
const domain = this.getColHeaderDomain(col, this.columns.length - 1);
|
|
35114
|
-
|
|
35139
|
+
const measure = domain?.at(-1)?.value;
|
|
35140
|
+
if (measure === undefined) {
|
|
35141
|
+
throw new Error("Measure isd missing");
|
|
35142
|
+
}
|
|
35143
|
+
return measure.toString();
|
|
35115
35144
|
}
|
|
35116
35145
|
getRowDomain(row) {
|
|
35117
35146
|
const domain = [];
|
|
35118
35147
|
for (let i = 0; i < this.rows[row].fields.length; i++) {
|
|
35119
|
-
domain.push(
|
|
35120
|
-
|
|
35148
|
+
domain.push({
|
|
35149
|
+
field: this.rows[row].fields[i],
|
|
35150
|
+
value: this.rows[row].values[i],
|
|
35151
|
+
});
|
|
35121
35152
|
}
|
|
35122
35153
|
return domain;
|
|
35123
35154
|
}
|
|
@@ -35126,7 +35157,6 @@ class SpreadsheetPivotTable {
|
|
|
35126
35157
|
cols: this.columns,
|
|
35127
35158
|
rows: this.rows,
|
|
35128
35159
|
measures: this.measures,
|
|
35129
|
-
rowTitle: this.rowTitle,
|
|
35130
35160
|
};
|
|
35131
35161
|
}
|
|
35132
35162
|
}
|
|
@@ -35146,8 +35176,7 @@ function dataEntriesToSpreadsheetPivotTable(dataEntries, definition) {
|
|
|
35146
35176
|
indent: 0,
|
|
35147
35177
|
});
|
|
35148
35178
|
const measureNames = definition.measures.map((m) => m.name);
|
|
35149
|
-
|
|
35150
|
-
return new SpreadsheetPivotTable(cols, rows, measureNames, rowTitle);
|
|
35179
|
+
return new SpreadsheetPivotTable(cols, rows, measureNames);
|
|
35151
35180
|
}
|
|
35152
35181
|
// -----------------------------------------------------------------------------
|
|
35153
35182
|
// ROWS
|
|
@@ -35490,7 +35519,10 @@ class SpreadsheetPivot {
|
|
|
35490
35519
|
}
|
|
35491
35520
|
get definition() {
|
|
35492
35521
|
if (!this._definition) {
|
|
35493
|
-
|
|
35522
|
+
this.init();
|
|
35523
|
+
}
|
|
35524
|
+
if (!this._definition) {
|
|
35525
|
+
throw new Error("Pivot definition should be defined at this point.");
|
|
35494
35526
|
}
|
|
35495
35527
|
return this._definition;
|
|
35496
35528
|
}
|
|
@@ -35539,15 +35571,16 @@ class SpreadsheetPivot {
|
|
|
35539
35571
|
getMeasure(name) {
|
|
35540
35572
|
return this.definition.getMeasure(name);
|
|
35541
35573
|
}
|
|
35542
|
-
|
|
35543
|
-
|
|
35574
|
+
getPivotMeasureValue(name) {
|
|
35575
|
+
return {
|
|
35576
|
+
value: this.getMeasure(name).displayName,
|
|
35577
|
+
};
|
|
35578
|
+
}
|
|
35579
|
+
getPivotHeaderValueAndFormat(domain) {
|
|
35544
35580
|
const lastNode = domain.at(-1);
|
|
35545
35581
|
if (!lastNode) {
|
|
35546
35582
|
return { value: _t("Total") };
|
|
35547
35583
|
}
|
|
35548
|
-
if (lastNode.field === "measure") {
|
|
35549
|
-
return { value: this.getMeasure(lastNode.value).displayName };
|
|
35550
|
-
}
|
|
35551
35584
|
const dimension = this.getDimension(lastNode.field);
|
|
35552
35585
|
const cells = this.filterDataEntriesFromDomain(this.dataEntries, domain);
|
|
35553
35586
|
const finalCell = cells[0]?.[dimension.nameWithGranularity];
|
|
@@ -35575,8 +35608,7 @@ class SpreadsheetPivot {
|
|
|
35575
35608
|
format: finalCell.format,
|
|
35576
35609
|
};
|
|
35577
35610
|
}
|
|
35578
|
-
getPivotCellValueAndFormat(measure,
|
|
35579
|
-
const domain = toDomainArgs(domainStr);
|
|
35611
|
+
getPivotCellValueAndFormat(measure, domain) {
|
|
35580
35612
|
const dataEntries = this.filterDataEntriesFromDomain(this.dataEntries, domain);
|
|
35581
35613
|
if (dataEntries.length === 0) {
|
|
35582
35614
|
return { value: "" };
|
|
@@ -35753,7 +35785,14 @@ pivotRegistry.add("SPREADSHEET", {
|
|
|
35753
35785
|
|
|
35754
35786
|
class PivotSidePanelStore extends SpreadsheetStore {
|
|
35755
35787
|
pivotId;
|
|
35756
|
-
mutators = [
|
|
35788
|
+
mutators = [
|
|
35789
|
+
"reset",
|
|
35790
|
+
"deferUpdates",
|
|
35791
|
+
"applyUpdate",
|
|
35792
|
+
"discardPendingUpdate",
|
|
35793
|
+
"renamePivot",
|
|
35794
|
+
"update",
|
|
35795
|
+
];
|
|
35757
35796
|
updatesAreDeferred = true;
|
|
35758
35797
|
draft = null;
|
|
35759
35798
|
constructor(get, pivotId) {
|
|
@@ -35970,7 +36009,6 @@ class PivotSpreadsheetSidePanel extends owl.Component {
|
|
|
35970
36009
|
state;
|
|
35971
36010
|
setup() {
|
|
35972
36011
|
this.store = useLocalStore(PivotSidePanelStore, this.props.pivotId);
|
|
35973
|
-
this.pivot.init();
|
|
35974
36012
|
this.state = owl.useState({
|
|
35975
36013
|
range: undefined,
|
|
35976
36014
|
rangeHasChanged: false,
|
|
@@ -36847,7 +36885,7 @@ css /* scss */ `
|
|
|
36847
36885
|
}
|
|
36848
36886
|
|
|
36849
36887
|
.o-table-style-list-item {
|
|
36850
|
-
padding: 3px;
|
|
36888
|
+
padding: 3px 2px;
|
|
36851
36889
|
margin: 2px 1px;
|
|
36852
36890
|
|
|
36853
36891
|
.o-table-style-picker-preview {
|
|
@@ -36868,10 +36906,10 @@ class TableStylePicker extends owl.Component {
|
|
|
36868
36906
|
const styles = Object.keys(allStyles).filter((key) => allStyles[key].category === selectedStyleCategory);
|
|
36869
36907
|
const selectedStyleIndex = styles.indexOf(this.props.table.config.styleId);
|
|
36870
36908
|
if (selectedStyleIndex === -1) {
|
|
36871
|
-
return
|
|
36909
|
+
return selectedStyleIndex;
|
|
36872
36910
|
}
|
|
36873
36911
|
const index = Math.floor(selectedStyleIndex / 4) * 4;
|
|
36874
|
-
return styles.slice(index
|
|
36912
|
+
return styles.slice(index);
|
|
36875
36913
|
}
|
|
36876
36914
|
onStylePicked(styleId) {
|
|
36877
36915
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
@@ -37911,10 +37949,7 @@ class GridComposer extends owl.Component {
|
|
|
37911
37949
|
}
|
|
37912
37950
|
get containerStyle() {
|
|
37913
37951
|
if (this.composerStore.editionMode === "inactive") {
|
|
37914
|
-
return `
|
|
37915
|
-
position: absolute;
|
|
37916
|
-
z-index: -1000;
|
|
37917
|
-
`;
|
|
37952
|
+
return `z-index: -1000;`;
|
|
37918
37953
|
}
|
|
37919
37954
|
const isFormula = this.composerStore.currentContent.startsWith("=");
|
|
37920
37955
|
const cell = this.env.model.getters.getActiveCell();
|
|
@@ -38790,6 +38825,7 @@ class FilterIcon extends owl.Component {
|
|
|
38790
38825
|
|
|
38791
38826
|
class FilterIconsOverlay extends owl.Component {
|
|
38792
38827
|
static template = "o-spreadsheet-FilterIconsOverlay";
|
|
38828
|
+
static props = {};
|
|
38793
38829
|
static components = {
|
|
38794
38830
|
GridCellIcon,
|
|
38795
38831
|
FilterIcon,
|
|
@@ -40757,10 +40793,13 @@ class VerticalScrollBar extends owl.Component {
|
|
|
40757
40793
|
}
|
|
40758
40794
|
}
|
|
40759
40795
|
|
|
40796
|
+
const DEFAULT_SIDE_PANEL_SIZE = 350;
|
|
40797
|
+
const MIN_SHEET_VIEW_WIDTH = 150;
|
|
40760
40798
|
class SidePanelStore extends SpreadsheetStore {
|
|
40761
|
-
mutators = ["open", "toggle", "close"];
|
|
40799
|
+
mutators = ["open", "toggle", "close", "changePanelSize", "resetPanelSize"];
|
|
40762
40800
|
initialPanelProps = {};
|
|
40763
40801
|
componentTag = "";
|
|
40802
|
+
panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
40764
40803
|
get isOpen() {
|
|
40765
40804
|
if (!this.componentTag) {
|
|
40766
40805
|
return false;
|
|
@@ -40805,6 +40844,20 @@ class SidePanelStore extends SpreadsheetStore {
|
|
|
40805
40844
|
this.initialPanelProps = {};
|
|
40806
40845
|
this.componentTag = "";
|
|
40807
40846
|
}
|
|
40847
|
+
changePanelSize(size, spreadsheetElWidth) {
|
|
40848
|
+
if (size < DEFAULT_SIDE_PANEL_SIZE) {
|
|
40849
|
+
this.panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
40850
|
+
}
|
|
40851
|
+
else if (size > spreadsheetElWidth - MIN_SHEET_VIEW_WIDTH) {
|
|
40852
|
+
this.panelSize = Math.max(spreadsheetElWidth - MIN_SHEET_VIEW_WIDTH, DEFAULT_SIDE_PANEL_SIZE);
|
|
40853
|
+
}
|
|
40854
|
+
else {
|
|
40855
|
+
this.panelSize = size;
|
|
40856
|
+
}
|
|
40857
|
+
}
|
|
40858
|
+
resetPanelSize() {
|
|
40859
|
+
this.panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
40860
|
+
}
|
|
40808
40861
|
computeState(componentTag, panelProps) {
|
|
40809
40862
|
const customComputeState = sidePanelRegistry.get(componentTag).computeState;
|
|
40810
40863
|
if (!customComputeState) {
|
|
@@ -41925,7 +41978,7 @@ class XLSXImportWarningManager {
|
|
|
41925
41978
|
}
|
|
41926
41979
|
}
|
|
41927
41980
|
|
|
41928
|
-
const SUPPORTED_BORDER_STYLES = ["thin"];
|
|
41981
|
+
const SUPPORTED_BORDER_STYLES = ["thin", "medium", "thick", "dashed", "dotted"];
|
|
41929
41982
|
const SUPPORTED_HORIZONTAL_ALIGNMENTS = [
|
|
41930
41983
|
"general",
|
|
41931
41984
|
"left",
|
|
@@ -51064,8 +51117,8 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
51064
51117
|
case "INSERT_PIVOT": {
|
|
51065
51118
|
const { sheetId, col, row, pivotId, table } = cmd;
|
|
51066
51119
|
const position = { sheetId, col, row };
|
|
51067
|
-
const { cols, rows, measures
|
|
51068
|
-
const spTable = new SpreadsheetPivotTable(cols, rows, measures
|
|
51120
|
+
const { cols, rows, measures } = table;
|
|
51121
|
+
const spTable = new SpreadsheetPivotTable(cols, rows, measures);
|
|
51069
51122
|
const formulaId = this.getPivotFormulaId(pivotId);
|
|
51070
51123
|
this.insertPivot(position, formulaId, spTable);
|
|
51071
51124
|
break;
|
|
@@ -51194,13 +51247,18 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
51194
51247
|
}
|
|
51195
51248
|
}
|
|
51196
51249
|
addPivotFormula(position, formulaId, pivotCell) {
|
|
51197
|
-
|
|
51198
|
-
|
|
51199
|
-
|
|
51200
|
-
|
|
51250
|
+
let content = undefined;
|
|
51251
|
+
switch (pivotCell.type) {
|
|
51252
|
+
case "HEADER":
|
|
51253
|
+
content = makePivotFormula("PIVOT.HEADER", [formulaId, ...flatPivotDomain(pivotCell.domain)].filter(isDefined));
|
|
51254
|
+
break;
|
|
51255
|
+
case "VALUE":
|
|
51256
|
+
content = makePivotFormula("PIVOT.VALUE", [formulaId, pivotCell.measure, ...flatPivotDomain(pivotCell.domain)].filter(isDefined));
|
|
51257
|
+
break;
|
|
51258
|
+
}
|
|
51201
51259
|
this.dispatch("UPDATE_CELL", {
|
|
51202
51260
|
...position,
|
|
51203
|
-
content
|
|
51261
|
+
content,
|
|
51204
51262
|
});
|
|
51205
51263
|
}
|
|
51206
51264
|
getPivotCore(pivotId) {
|
|
@@ -51219,7 +51277,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
51219
51277
|
import(data) {
|
|
51220
51278
|
if (data.pivots) {
|
|
51221
51279
|
for (const [id, pivot] of Object.entries(data.pivots)) {
|
|
51222
|
-
this.addPivot(id,
|
|
51280
|
+
this.addPivot(id, pivot, pivot.formulaId);
|
|
51223
51281
|
}
|
|
51224
51282
|
}
|
|
51225
51283
|
this.history.update("nextFormulaId", data.pivotNextId || getMaxObjectId(this.pivots) + 1);
|
|
@@ -54560,15 +54618,18 @@ class PivotUIPlugin extends UIPlugin {
|
|
|
54560
54618
|
const pivotCol = position.col - mainPosition.col;
|
|
54561
54619
|
const pivotRow = position.row - mainPosition.row;
|
|
54562
54620
|
const pivotCell = pivotCells[pivotCol][pivotRow];
|
|
54621
|
+
if (pivotCell.type === "EMPTY") {
|
|
54622
|
+
return undefined;
|
|
54623
|
+
}
|
|
54563
54624
|
const domain = pivotCell.domain;
|
|
54564
|
-
if (domain
|
|
54565
|
-
return domain.slice(0, -
|
|
54625
|
+
if (domain.at(-1)?.field === "measure") {
|
|
54626
|
+
return domain.slice(0, -1);
|
|
54566
54627
|
}
|
|
54567
54628
|
return domain;
|
|
54568
54629
|
}
|
|
54569
|
-
const domain = args.slice(functionName === "PIVOT.VALUE" ? 2 : 1);
|
|
54570
|
-
if (domain.at(-
|
|
54571
|
-
return domain.slice(0, -
|
|
54630
|
+
const domain = toPivotDomain(args.slice(functionName === "PIVOT.VALUE" ? 2 : 1).map((x) => `${x}`));
|
|
54631
|
+
if (domain.at(-1)?.field === "measure") {
|
|
54632
|
+
return domain.slice(0, -1);
|
|
54572
54633
|
}
|
|
54573
54634
|
return domain;
|
|
54574
54635
|
}
|
|
@@ -54583,9 +54644,9 @@ class PivotUIPlugin extends UIPlugin {
|
|
|
54583
54644
|
* a pivot function are valid according to the pivot definition.
|
|
54584
54645
|
* e.g. =PIVOT.VALUE(1,"revenue","country_id",...,"create_date:month",...,"source_id",...)
|
|
54585
54646
|
*/
|
|
54586
|
-
areDomainArgsFieldsValid(pivotId,
|
|
54587
|
-
const dimensions =
|
|
54588
|
-
.
|
|
54647
|
+
areDomainArgsFieldsValid(pivotId, domain) {
|
|
54648
|
+
const dimensions = domain
|
|
54649
|
+
.map((node) => node.field)
|
|
54589
54650
|
.map((name) => (name.startsWith("#") ? name.slice(1) : name));
|
|
54590
54651
|
let argIndex = 0;
|
|
54591
54652
|
let definitionIndex = 0;
|
|
@@ -61599,6 +61660,10 @@ css /* scss */ `
|
|
|
61599
61660
|
}
|
|
61600
61661
|
}
|
|
61601
61662
|
}
|
|
61663
|
+
.o-sidePanelBody-container {
|
|
61664
|
+
/* This overwrites the min-height: auto; of flex. Without this, a flex div cannot be smaller than its children */
|
|
61665
|
+
min-height: 0;
|
|
61666
|
+
}
|
|
61602
61667
|
.o-sidePanelBody {
|
|
61603
61668
|
overflow: auto;
|
|
61604
61669
|
width: 100%;
|
|
@@ -61677,24 +61742,6 @@ css /* scss */ `
|
|
|
61677
61742
|
text-align: left;
|
|
61678
61743
|
}
|
|
61679
61744
|
|
|
61680
|
-
.o-inflection {
|
|
61681
|
-
table {
|
|
61682
|
-
table-layout: fixed;
|
|
61683
|
-
margin-top: 2%;
|
|
61684
|
-
display: table;
|
|
61685
|
-
text-align: left;
|
|
61686
|
-
font-size: 12px;
|
|
61687
|
-
line-height: 18px;
|
|
61688
|
-
width: 100%;
|
|
61689
|
-
}
|
|
61690
|
-
input,
|
|
61691
|
-
select {
|
|
61692
|
-
width: 100%;
|
|
61693
|
-
height: 100%;
|
|
61694
|
-
box-sizing: border-box;
|
|
61695
|
-
}
|
|
61696
|
-
}
|
|
61697
|
-
|
|
61698
61745
|
.o-sidePanel-tools {
|
|
61699
61746
|
color: #333;
|
|
61700
61747
|
font-size: 13px;
|
|
@@ -61713,12 +61760,25 @@ css /* scss */ `
|
|
|
61713
61760
|
}
|
|
61714
61761
|
}
|
|
61715
61762
|
}
|
|
61763
|
+
|
|
61764
|
+
.o-sidePanel-handle-container {
|
|
61765
|
+
width: 8px;
|
|
61766
|
+
}
|
|
61767
|
+
.o-sidePanel-handle {
|
|
61768
|
+
cursor: col-resize;
|
|
61769
|
+
color: #a9a9a9;
|
|
61770
|
+
.o-icon {
|
|
61771
|
+
height: 25px;
|
|
61772
|
+
margin-left: -5px;
|
|
61773
|
+
}
|
|
61774
|
+
}
|
|
61716
61775
|
}
|
|
61717
61776
|
`;
|
|
61718
61777
|
class SidePanel extends owl.Component {
|
|
61719
61778
|
static template = "o-spreadsheet-SidePanel";
|
|
61720
61779
|
static props = {};
|
|
61721
61780
|
sidePanelStore;
|
|
61781
|
+
spreadsheetRect = useSpreadsheetRect();
|
|
61722
61782
|
setup() {
|
|
61723
61783
|
this.sidePanelStore = useStore(SidePanelStore);
|
|
61724
61784
|
owl.useEffect((isOpen) => {
|
|
@@ -61739,6 +61799,20 @@ class SidePanel extends owl.Component {
|
|
|
61739
61799
|
? panel.title(this.env, this.sidePanelStore.panelProps)
|
|
61740
61800
|
: panel.title;
|
|
61741
61801
|
}
|
|
61802
|
+
startHandleDrag(ev) {
|
|
61803
|
+
const startingCursor = document.body.style.cursor;
|
|
61804
|
+
const startSize = this.sidePanelStore.panelSize;
|
|
61805
|
+
const startPosition = ev.clientX;
|
|
61806
|
+
const onMouseMove = (ev) => {
|
|
61807
|
+
document.body.style.cursor = "col-resize";
|
|
61808
|
+
const newSize = startSize + startPosition - ev.clientX;
|
|
61809
|
+
this.sidePanelStore.changePanelSize(newSize, this.spreadsheetRect.width);
|
|
61810
|
+
};
|
|
61811
|
+
const cleanUp = () => {
|
|
61812
|
+
document.body.style.cursor = startingCursor;
|
|
61813
|
+
};
|
|
61814
|
+
startDnd(onMouseMove, cleanUp);
|
|
61815
|
+
}
|
|
61742
61816
|
}
|
|
61743
61817
|
|
|
61744
61818
|
css /* scss */ `
|
|
@@ -62522,7 +62596,6 @@ css /* scss */ `
|
|
|
62522
62596
|
.o-spreadsheet {
|
|
62523
62597
|
position: relative;
|
|
62524
62598
|
display: grid;
|
|
62525
|
-
grid-template-columns: auto 350px;
|
|
62526
62599
|
color: #333;
|
|
62527
62600
|
font-size: 14px;
|
|
62528
62601
|
|
|
@@ -62720,6 +62793,7 @@ class Spreadsheet extends owl.Component {
|
|
|
62720
62793
|
};
|
|
62721
62794
|
sidePanel;
|
|
62722
62795
|
spreadsheetRef = owl.useRef("spreadsheet");
|
|
62796
|
+
spreadsheetRect = useSpreadsheetRect();
|
|
62723
62797
|
_focusGrid;
|
|
62724
62798
|
keyDownMapping;
|
|
62725
62799
|
isViewportTooSmall = false;
|
|
@@ -62729,10 +62803,15 @@ class Spreadsheet extends owl.Component {
|
|
|
62729
62803
|
return this.props.model;
|
|
62730
62804
|
}
|
|
62731
62805
|
getStyle() {
|
|
62806
|
+
const properties = {};
|
|
62732
62807
|
if (this.env.isDashboard()) {
|
|
62733
|
-
|
|
62808
|
+
properties["grid-template-rows"] = `auto`;
|
|
62734
62809
|
}
|
|
62735
|
-
|
|
62810
|
+
else {
|
|
62811
|
+
properties["grid-template-rows"] = `${TOPBAR_HEIGHT}px auto ${BOTTOMBAR_HEIGHT + 1}px`;
|
|
62812
|
+
}
|
|
62813
|
+
properties["grid-template-columns"] = `auto ${this.sidePanel.panelSize}px`;
|
|
62814
|
+
return cssPropertiesToCss(properties);
|
|
62736
62815
|
}
|
|
62737
62816
|
setup() {
|
|
62738
62817
|
const stores = useStoreProvider();
|
|
@@ -62782,7 +62861,9 @@ class Spreadsheet extends owl.Component {
|
|
|
62782
62861
|
if (nextProps.model !== this.props.model) {
|
|
62783
62862
|
throw new Error("Changing the props model is not supported at the moment.");
|
|
62784
62863
|
}
|
|
62785
|
-
if (
|
|
62864
|
+
if (nextProps.notifyUser !== this.props.notifyUser ||
|
|
62865
|
+
nextProps.askConfirmation !== this.props.askConfirmation ||
|
|
62866
|
+
nextProps.raiseError !== this.props.raiseError) {
|
|
62786
62867
|
this.notificationStore.updateNotificationCallbacks({ ...nextProps });
|
|
62787
62868
|
}
|
|
62788
62869
|
});
|
|
@@ -62790,14 +62871,19 @@ class Spreadsheet extends owl.Component {
|
|
|
62790
62871
|
owl.onMounted(() => {
|
|
62791
62872
|
this.checkViewportSize();
|
|
62792
62873
|
stores.on("store-updated", this, render);
|
|
62874
|
+
resizeObserver.observe(this.spreadsheetRef.el);
|
|
62793
62875
|
});
|
|
62794
62876
|
owl.onWillUnmount(() => {
|
|
62795
62877
|
this.unbindModelEvents();
|
|
62796
62878
|
stores.off("store-updated", this);
|
|
62879
|
+
resizeObserver.disconnect();
|
|
62797
62880
|
});
|
|
62798
62881
|
owl.onPatched(() => {
|
|
62799
62882
|
this.checkViewportSize();
|
|
62800
62883
|
});
|
|
62884
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
62885
|
+
this.sidePanel.changePanelSize(this.sidePanel.panelSize, this.spreadsheetRect.width);
|
|
62886
|
+
});
|
|
62801
62887
|
}
|
|
62802
62888
|
bindModelEvents() {
|
|
62803
62889
|
this.model.on("update", this, () => this.render(true));
|
|
@@ -66852,6 +66938,8 @@ const helpers = {
|
|
|
66852
66938
|
insertTokenAfterLeftParenthesis,
|
|
66853
66939
|
mergeContiguousZones,
|
|
66854
66940
|
getPivotHighlights,
|
|
66941
|
+
toPivotDomain,
|
|
66942
|
+
flatPivotDomain,
|
|
66855
66943
|
pivotTimeAdapter,
|
|
66856
66944
|
UNDO_REDO_PIVOT_COMMANDS,
|
|
66857
66945
|
};
|
|
@@ -66979,6 +67067,6 @@ exports.tokenColors = tokenColors;
|
|
|
66979
67067
|
exports.tokenize = tokenize;
|
|
66980
67068
|
|
|
66981
67069
|
|
|
66982
|
-
__info__.version = "17.4.0-alpha.
|
|
66983
|
-
__info__.date = "2024-
|
|
66984
|
-
__info__.hash = "
|
|
67070
|
+
__info__.version = "17.4.0-alpha.2";
|
|
67071
|
+
__info__.date = "2024-06-06T13:31:21.327Z";
|
|
67072
|
+
__info__.hash = "e07794d";
|