@odoo/o-spreadsheet 17.4.0-alpha.1 → 17.4.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/o-spreadsheet.cjs.js +378 -274
- package/dist/o-spreadsheet.d.ts +198 -154
- package/dist/o-spreadsheet.esm.js +378 -274
- package/dist/o-spreadsheet.iife.js +378 -274
- package/dist/o-spreadsheet.iife.min.js +380 -371
- package/dist/o_spreadsheet.xml +66 -48
- 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-06-
|
|
8
|
-
* @hash
|
|
6
|
+
* @version 17.4.0-alpha.3
|
|
7
|
+
* @date 2024-06-10T09:38:53.982Z
|
|
8
|
+
* @hash a45ed6a
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
'use strict';
|
|
@@ -311,7 +311,10 @@ function deepCopy(obj) {
|
|
|
311
311
|
* Check if the object is a plain old javascript object.
|
|
312
312
|
*/
|
|
313
313
|
function isPlainObject(obj) {
|
|
314
|
-
return typeof obj === "object" &&
|
|
314
|
+
return (typeof obj === "object" &&
|
|
315
|
+
obj !== null &&
|
|
316
|
+
// obj.constructor can be undefined when there's no prototype (`Object.create(null, {})`)
|
|
317
|
+
(obj?.constructor === Object || obj?.constructor === undefined));
|
|
315
318
|
}
|
|
316
319
|
/**
|
|
317
320
|
* Sanitize the name of a sheet, by eventually removing quotes
|
|
@@ -18377,6 +18380,131 @@ var logical = /*#__PURE__*/Object.freeze({
|
|
|
18377
18380
|
const supportedPivotExplodedFormulaRegistry = new Registry();
|
|
18378
18381
|
supportedPivotExplodedFormulaRegistry.add("SPREADSHEET", false);
|
|
18379
18382
|
|
|
18383
|
+
const AGGREGATOR_NAMES = {
|
|
18384
|
+
count: _t("Count"),
|
|
18385
|
+
count_distinct: _t("Count Distinct"),
|
|
18386
|
+
bool_and: _t("Boolean And"),
|
|
18387
|
+
bool_or: _t("Boolean Or"),
|
|
18388
|
+
max: _t("Maximum"),
|
|
18389
|
+
min: _t("Minimum"),
|
|
18390
|
+
avg: _t("Average"),
|
|
18391
|
+
sum: _t("Sum"),
|
|
18392
|
+
};
|
|
18393
|
+
const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
|
|
18394
|
+
const AGGREGATORS_BY_FIELD_TYPE = {
|
|
18395
|
+
integer: NUMBER_CHAR_AGGREGATORS,
|
|
18396
|
+
char: NUMBER_CHAR_AGGREGATORS,
|
|
18397
|
+
//TODO Support for date and boolean
|
|
18398
|
+
};
|
|
18399
|
+
const AGGREGATORS = {};
|
|
18400
|
+
for (const type in AGGREGATORS_BY_FIELD_TYPE) {
|
|
18401
|
+
AGGREGATORS[type] = {};
|
|
18402
|
+
for (const aggregator of AGGREGATORS_BY_FIELD_TYPE[type]) {
|
|
18403
|
+
AGGREGATORS[type][aggregator] = AGGREGATOR_NAMES[aggregator];
|
|
18404
|
+
}
|
|
18405
|
+
}
|
|
18406
|
+
const AGGREGATORS_FN = {
|
|
18407
|
+
count: {
|
|
18408
|
+
fn: (args) => countAny([args]),
|
|
18409
|
+
format: () => "0",
|
|
18410
|
+
},
|
|
18411
|
+
count_distinct: {
|
|
18412
|
+
fn: (args) => countUnique([args]),
|
|
18413
|
+
format: () => "0",
|
|
18414
|
+
},
|
|
18415
|
+
bool_and: {
|
|
18416
|
+
fn: (args) => boolAnd([args]).result,
|
|
18417
|
+
format: () => undefined,
|
|
18418
|
+
},
|
|
18419
|
+
bool_or: {
|
|
18420
|
+
fn: (args) => boolOr([args]).result,
|
|
18421
|
+
format: () => undefined,
|
|
18422
|
+
},
|
|
18423
|
+
max: {
|
|
18424
|
+
fn: (args, locale) => max([args], locale),
|
|
18425
|
+
format: inferFormat,
|
|
18426
|
+
},
|
|
18427
|
+
min: {
|
|
18428
|
+
fn: (args, locale) => min([args], locale),
|
|
18429
|
+
format: inferFormat,
|
|
18430
|
+
},
|
|
18431
|
+
avg: {
|
|
18432
|
+
fn: (args, locale) => average([args], locale),
|
|
18433
|
+
format: inferFormat,
|
|
18434
|
+
},
|
|
18435
|
+
sum: {
|
|
18436
|
+
fn: (args, locale) => sum([args], locale),
|
|
18437
|
+
format: inferFormat,
|
|
18438
|
+
},
|
|
18439
|
+
};
|
|
18440
|
+
/**
|
|
18441
|
+
* Build a pivot formula expression
|
|
18442
|
+
*/
|
|
18443
|
+
function makePivotFormula(formula, args) {
|
|
18444
|
+
return `=${formula}(${args
|
|
18445
|
+
.map((arg) => {
|
|
18446
|
+
const stringIsNumber = typeof arg == "string" && !isNaN(Number(arg)) && Number(arg).toString() === arg;
|
|
18447
|
+
const convertToNumber = typeof arg == "number" || stringIsNumber;
|
|
18448
|
+
return convertToNumber ? `${arg}` : `"${arg.toString().replace(/"/g, '\\"')}"`;
|
|
18449
|
+
})
|
|
18450
|
+
.join(",")})`;
|
|
18451
|
+
}
|
|
18452
|
+
/**
|
|
18453
|
+
* Given an object of form {"1": {...}, "2": {...}, ...} get the maximum ID used
|
|
18454
|
+
* in this object
|
|
18455
|
+
* If the object has no keys, return 0
|
|
18456
|
+
*
|
|
18457
|
+
*/
|
|
18458
|
+
function getMaxObjectId(o) {
|
|
18459
|
+
const keys = Object.keys(o);
|
|
18460
|
+
if (!keys.length) {
|
|
18461
|
+
return 0;
|
|
18462
|
+
}
|
|
18463
|
+
const nums = keys.map((id) => parseInt(id, 10));
|
|
18464
|
+
const max = Math.max(...nums);
|
|
18465
|
+
return max;
|
|
18466
|
+
}
|
|
18467
|
+
const ALL_PERIODS = {
|
|
18468
|
+
year: _t("Year"),
|
|
18469
|
+
quarter: _t("Quarter"),
|
|
18470
|
+
month: _t("Month"),
|
|
18471
|
+
week: _t("Week"),
|
|
18472
|
+
day: _t("Day"),
|
|
18473
|
+
year_number: _t("Year"),
|
|
18474
|
+
quarter_number: _t("Quarter"),
|
|
18475
|
+
month_number: _t("Month"),
|
|
18476
|
+
iso_week_number: _t("Week"),
|
|
18477
|
+
day_of_month: _t("Day of Month"),
|
|
18478
|
+
};
|
|
18479
|
+
const DATE_FIELDS = ["date", "datetime"];
|
|
18480
|
+
/**
|
|
18481
|
+
* Parse a dimension string into a pivot dimension definition.
|
|
18482
|
+
* e.g "create_date:month" => { name: "create_date", granularity: "month" }
|
|
18483
|
+
*/
|
|
18484
|
+
function parseDimension(dimension) {
|
|
18485
|
+
const [name, granularity] = dimension.split(":");
|
|
18486
|
+
if (granularity) {
|
|
18487
|
+
return { name, granularity };
|
|
18488
|
+
}
|
|
18489
|
+
return { name };
|
|
18490
|
+
}
|
|
18491
|
+
function isDateField(field) {
|
|
18492
|
+
return DATE_FIELDS.includes(field.type);
|
|
18493
|
+
}
|
|
18494
|
+
function toPivotDomain(domainStr) {
|
|
18495
|
+
if (domainStr.length % 2 !== 0) {
|
|
18496
|
+
throw new Error("Invalid domain: odd number of elements");
|
|
18497
|
+
}
|
|
18498
|
+
const domain = [];
|
|
18499
|
+
for (let i = 0; i < domainStr.length - 1; i += 2) {
|
|
18500
|
+
domain.push({ field: domainStr[i], value: domainStr[i + 1] });
|
|
18501
|
+
}
|
|
18502
|
+
return domain;
|
|
18503
|
+
}
|
|
18504
|
+
function flatPivotDomain(domain) {
|
|
18505
|
+
return domain.flatMap((arg) => [arg.field, arg.value]);
|
|
18506
|
+
}
|
|
18507
|
+
|
|
18380
18508
|
/**
|
|
18381
18509
|
* Get the pivot ID from the formula pivot ID.
|
|
18382
18510
|
*/
|
|
@@ -18856,13 +18984,13 @@ const PIVOT_VALUE = {
|
|
|
18856
18984
|
arg("domain_field_name (string,optional,repeating)", _t("Field name.")),
|
|
18857
18985
|
arg("domain_value (string,optional,repeating)", _t("Value.")),
|
|
18858
18986
|
],
|
|
18859
|
-
compute: function (formulaId, measureName, ...
|
|
18987
|
+
compute: function (formulaId, measureName, ...domainArgs) {
|
|
18860
18988
|
const _pivotFormulaId = toString(formulaId);
|
|
18861
|
-
const
|
|
18862
|
-
const
|
|
18989
|
+
const _measure = toString(measureName);
|
|
18990
|
+
const _domainArgs = domainArgs.map(toString);
|
|
18863
18991
|
const pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
18864
|
-
assertMeasureExist(pivotId,
|
|
18865
|
-
assertDomainLength(
|
|
18992
|
+
assertMeasureExist(pivotId, _measure, this.getters);
|
|
18993
|
+
assertDomainLength(_domainArgs);
|
|
18866
18994
|
const pivot = this.getters.getPivot(pivotId);
|
|
18867
18995
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
18868
18996
|
if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
|
|
@@ -18876,8 +19004,9 @@ const PIVOT_VALUE = {
|
|
|
18876
19004
|
if (error) {
|
|
18877
19005
|
return error;
|
|
18878
19006
|
}
|
|
18879
|
-
const
|
|
18880
|
-
|
|
19007
|
+
const domain = toPivotDomain(_domainArgs);
|
|
19008
|
+
const { value, format } = pivot.getPivotCellValueAndFormat(_measure, domain);
|
|
19009
|
+
if (!value && !this.getters.areDomainArgsFieldsValid(pivotId, domain)) {
|
|
18881
19010
|
return {
|
|
18882
19011
|
value: CellErrorType.GenericError,
|
|
18883
19012
|
message: _t("Dimensions don't match the pivot definition"),
|
|
@@ -18894,11 +19023,11 @@ const PIVOT_HEADER = {
|
|
|
18894
19023
|
arg("domain_field_name (string,optional,repeating)", _t("Field name.")),
|
|
18895
19024
|
arg("domain_value (string,optional,repeating)", _t("Value.")),
|
|
18896
19025
|
],
|
|
18897
|
-
compute: function (pivotId, ...
|
|
19026
|
+
compute: function (pivotId, ...domainArgs) {
|
|
18898
19027
|
const _pivotFormulaId = toString(pivotId);
|
|
18899
|
-
const
|
|
19028
|
+
const _domainArgs = domainArgs.map(toString);
|
|
18900
19029
|
const _pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
18901
|
-
assertDomainLength(
|
|
19030
|
+
assertDomainLength(_domainArgs);
|
|
18902
19031
|
const pivot = this.getters.getPivot(_pivotId);
|
|
18903
19032
|
const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
|
|
18904
19033
|
if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
|
|
@@ -18912,18 +19041,23 @@ const PIVOT_HEADER = {
|
|
|
18912
19041
|
if (error) {
|
|
18913
19042
|
return error;
|
|
18914
19043
|
}
|
|
18915
|
-
const
|
|
18916
|
-
const
|
|
18917
|
-
if (!this.getters.areDomainArgsFieldsValid(_pivotId,
|
|
19044
|
+
const domain = toPivotDomain(_domainArgs);
|
|
19045
|
+
const lastNode = domain.at(-1);
|
|
19046
|
+
if (!this.getters.areDomainArgsFieldsValid(_pivotId, lastNode?.field === "measure" ? domain.slice(0, -1) : domain)) {
|
|
18918
19047
|
return {
|
|
18919
19048
|
value: CellErrorType.GenericError,
|
|
18920
19049
|
message: _t("Dimensions don't match the pivot definition"),
|
|
18921
19050
|
};
|
|
18922
19051
|
}
|
|
18923
|
-
|
|
19052
|
+
if (lastNode?.field === "measure") {
|
|
19053
|
+
return pivot.getPivotMeasureValue(toString(lastNode.value), domain);
|
|
19054
|
+
}
|
|
19055
|
+
const { value, format } = pivot.getPivotHeaderValueAndFormat(domain);
|
|
18924
19056
|
return {
|
|
18925
19057
|
value,
|
|
18926
|
-
format: !
|
|
19058
|
+
format: !lastNode || lastNode.field === "measure" || lastNode.value === "false"
|
|
19059
|
+
? undefined
|
|
19060
|
+
: format,
|
|
18927
19061
|
};
|
|
18928
19062
|
},
|
|
18929
19063
|
returns: ["NUMBER", "STRING"],
|
|
@@ -18936,11 +19070,14 @@ const PIVOT = {
|
|
|
18936
19070
|
arg("include_total (boolean, default=TRUE)", _t("Whether to include total/sub-totals or not.")),
|
|
18937
19071
|
arg("include_column_titles (boolean, default=TRUE)", _t("Whether to include the column titles or not.")),
|
|
18938
19072
|
],
|
|
18939
|
-
compute: function (
|
|
18940
|
-
const _pivotFormulaId = toString(
|
|
18941
|
-
const
|
|
18942
|
-
const
|
|
18943
|
-
const
|
|
19073
|
+
compute: function (pivotFormulaId, rowCount = { value: 10000 }, includeTotal = { value: true }, includeColumnHeaders = { value: true }) {
|
|
19074
|
+
const _pivotFormulaId = toString(pivotFormulaId);
|
|
19075
|
+
const _rowCount = toNumber(rowCount, this.locale);
|
|
19076
|
+
const _includeColumnHeaders = toBoolean(includeColumnHeaders);
|
|
19077
|
+
const _includedTotal = toBoolean(includeTotal);
|
|
19078
|
+
const pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
19079
|
+
const pivot = this.getters.getPivot(pivotId);
|
|
19080
|
+
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
18944
19081
|
addPivotDependencies(this, coreDefinition);
|
|
18945
19082
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
18946
19083
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
@@ -18948,11 +19085,9 @@ const PIVOT = {
|
|
|
18948
19085
|
return error;
|
|
18949
19086
|
}
|
|
18950
19087
|
const table = pivot.getTableStructure();
|
|
18951
|
-
const
|
|
18952
|
-
const cells = table.getPivotCells(toBoolean(includeTotal), _includeColumnHeaders);
|
|
19088
|
+
const cells = table.getPivotCells(_includedTotal, _includeColumnHeaders);
|
|
18953
19089
|
const headerRows = _includeColumnHeaders ? table.columns.length : 0;
|
|
18954
|
-
const pivotTitle = this.getters.getPivotDisplayName(
|
|
18955
|
-
const _rowCount = toNumber(rowCount, this.locale);
|
|
19090
|
+
const pivotTitle = this.getters.getPivotDisplayName(pivotId);
|
|
18956
19091
|
if (_rowCount < 0) {
|
|
18957
19092
|
throw new EvaluationError(_t("The number of rows must be positive."));
|
|
18958
19093
|
}
|
|
@@ -18967,17 +19102,23 @@ const PIVOT = {
|
|
|
18967
19102
|
result[col] = [];
|
|
18968
19103
|
for (const row of tableRows) {
|
|
18969
19104
|
const pivotCell = cells[col][row];
|
|
18970
|
-
|
|
18971
|
-
|
|
18972
|
-
|
|
18973
|
-
|
|
18974
|
-
|
|
18975
|
-
|
|
18976
|
-
|
|
18977
|
-
|
|
18978
|
-
|
|
18979
|
-
|
|
18980
|
-
|
|
19105
|
+
switch (pivotCell.type) {
|
|
19106
|
+
case "EMPTY":
|
|
19107
|
+
result[col].push({ value: "" });
|
|
19108
|
+
break;
|
|
19109
|
+
case "HEADER":
|
|
19110
|
+
const domain = pivotCell.domain;
|
|
19111
|
+
const lastNode = domain.at(-1);
|
|
19112
|
+
if (lastNode?.field === "measure") {
|
|
19113
|
+
result[col].push(pivot.getPivotMeasureValue(toString(lastNode.value), domain));
|
|
19114
|
+
}
|
|
19115
|
+
else {
|
|
19116
|
+
result[col].push(pivot.getPivotHeaderValueAndFormat(domain));
|
|
19117
|
+
}
|
|
19118
|
+
break;
|
|
19119
|
+
case "VALUE":
|
|
19120
|
+
result[col].push(pivot.getPivotCellValueAndFormat(pivotCell.measure, pivotCell.domain));
|
|
19121
|
+
break;
|
|
18981
19122
|
}
|
|
18982
19123
|
}
|
|
18983
19124
|
}
|
|
@@ -20902,8 +21043,15 @@ class Composer extends owl.Component {
|
|
|
20902
21043
|
}
|
|
20903
21044
|
onPaste(ev) {
|
|
20904
21045
|
if (this.composerStore.editionMode !== "inactive") {
|
|
21046
|
+
// let the browser clipboard work
|
|
20905
21047
|
ev.stopPropagation();
|
|
20906
21048
|
}
|
|
21049
|
+
else {
|
|
21050
|
+
// the user meant to paste in the sheet, not open the composer with the pasted content
|
|
21051
|
+
// While we're not editing, we still have the focus and should therefore prevent
|
|
21052
|
+
// the native "paste" to occur.
|
|
21053
|
+
ev.preventDefault();
|
|
21054
|
+
}
|
|
20907
21055
|
}
|
|
20908
21056
|
/*
|
|
20909
21057
|
* Triggered automatically by the content-editable between the keydown and key up
|
|
@@ -20912,9 +21060,6 @@ class Composer extends owl.Component {
|
|
|
20912
21060
|
if (!this.shouldProcessInputEvents) {
|
|
20913
21061
|
return;
|
|
20914
21062
|
}
|
|
20915
|
-
if (ev.inputType === "insertFromPaste" && this.composerStore.editionMode === "inactive") {
|
|
20916
|
-
return;
|
|
20917
|
-
}
|
|
20918
21063
|
ev.stopPropagation();
|
|
20919
21064
|
let content;
|
|
20920
21065
|
if (this.composerStore.editionMode === "inactive") {
|
|
@@ -21567,132 +21712,8 @@ function getFunctionsFromAST(ast, functionNames) {
|
|
|
21567
21712
|
}
|
|
21568
21713
|
|
|
21569
21714
|
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
21715
|
/**
|
|
21695
|
-
* Create a proposal entry for the compose
|
|
21716
|
+
* Create a proposal entry for the compose autowcomplete
|
|
21696
21717
|
* to insert a field name string in a formula.
|
|
21697
21718
|
*/
|
|
21698
21719
|
function makeFieldProposal(field, granularity) {
|
|
@@ -21748,15 +21769,18 @@ function extractFormulaIdFromToken(tokenAtCursor) {
|
|
|
21748
21769
|
}
|
|
21749
21770
|
return idAst.value;
|
|
21750
21771
|
}
|
|
21751
|
-
|
|
21752
|
-
|
|
21753
|
-
|
|
21754
|
-
|
|
21755
|
-
|
|
21756
|
-
|
|
21757
|
-
|
|
21758
|
-
|
|
21759
|
-
|
|
21772
|
+
/**
|
|
21773
|
+
* Get the first Pivot function description of the given formula.
|
|
21774
|
+
*/
|
|
21775
|
+
function getFirstPivotFunction(tokens) {
|
|
21776
|
+
return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS)[0];
|
|
21777
|
+
}
|
|
21778
|
+
/**
|
|
21779
|
+
* Parse a spreadsheet formula and detect the number of PIVOT functions that are
|
|
21780
|
+
* present in the given formula.
|
|
21781
|
+
*/
|
|
21782
|
+
function getNumberOfPivotFunctions(tokens) {
|
|
21783
|
+
return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS).length;
|
|
21760
21784
|
}
|
|
21761
21785
|
|
|
21762
21786
|
autoCompleteProviders.add("pivot_ids", {
|
|
@@ -25323,8 +25347,7 @@ function zoneToRect(zone) {
|
|
|
25323
25347
|
*/
|
|
25324
25348
|
function useSpreadsheetRect() {
|
|
25325
25349
|
const position = owl.useState({ x: 0, y: 0, width: 0, height: 0 });
|
|
25326
|
-
let spreadsheetElement =
|
|
25327
|
-
updatePosition();
|
|
25350
|
+
let spreadsheetElement = null;
|
|
25328
25351
|
function updatePosition() {
|
|
25329
25352
|
if (!spreadsheetElement) {
|
|
25330
25353
|
spreadsheetElement = document.querySelector(".o-spreadsheet");
|
|
@@ -32784,7 +32807,7 @@ css /* scss */ `
|
|
|
32784
32807
|
vertical-align: middle;
|
|
32785
32808
|
}
|
|
32786
32809
|
.o_cf_radio_item {
|
|
32787
|
-
margin-right:
|
|
32810
|
+
margin-right: 30px;
|
|
32788
32811
|
}
|
|
32789
32812
|
.radio input:checked {
|
|
32790
32813
|
color: #e9ecef;
|
|
@@ -32804,6 +32827,9 @@ css /* scss */ `
|
|
|
32804
32827
|
}
|
|
32805
32828
|
margin-top: 10px;
|
|
32806
32829
|
display: flex;
|
|
32830
|
+
.form-check {
|
|
32831
|
+
padding-left: 1rem;
|
|
32832
|
+
}
|
|
32807
32833
|
}
|
|
32808
32834
|
.o-section-subtitle:first-child {
|
|
32809
32835
|
margin-top: 0px;
|
|
@@ -32812,7 +32838,7 @@ css /* scss */ `
|
|
|
32812
32838
|
font-size: 12px;
|
|
32813
32839
|
line-height: 1.5;
|
|
32814
32840
|
.o-selection-cf {
|
|
32815
|
-
margin-bottom:
|
|
32841
|
+
margin-bottom: 9px;
|
|
32816
32842
|
}
|
|
32817
32843
|
.o-cell-content {
|
|
32818
32844
|
font-size: 12px;
|
|
@@ -32853,7 +32879,7 @@ css /* scss */ `
|
|
|
32853
32879
|
width: 100%;
|
|
32854
32880
|
}
|
|
32855
32881
|
.o-threshold-value {
|
|
32856
|
-
margin-left:
|
|
32882
|
+
margin-left: 6px;
|
|
32857
32883
|
width: 20%;
|
|
32858
32884
|
min-width: 0px; // input overflows in Firefox otherwise
|
|
32859
32885
|
}
|
|
@@ -32882,8 +32908,8 @@ css /* scss */ `
|
|
|
32882
32908
|
justify-content: space-between;
|
|
32883
32909
|
.o-cf-icon {
|
|
32884
32910
|
display: inline;
|
|
32885
|
-
margin-left:
|
|
32886
|
-
margin-right:
|
|
32911
|
+
margin-left: 3px;
|
|
32912
|
+
margin-right: 3px;
|
|
32887
32913
|
}
|
|
32888
32914
|
svg {
|
|
32889
32915
|
vertical-align: baseline;
|
|
@@ -32906,7 +32932,7 @@ css /* scss */ `
|
|
|
32906
32932
|
}
|
|
32907
32933
|
table {
|
|
32908
32934
|
table-layout: fixed;
|
|
32909
|
-
margin-top:
|
|
32935
|
+
margin-top: 6px;
|
|
32910
32936
|
display: table;
|
|
32911
32937
|
text-align: left;
|
|
32912
32938
|
font-size: 12px;
|
|
@@ -32936,8 +32962,8 @@ css /* scss */ `
|
|
|
32936
32962
|
}
|
|
32937
32963
|
}
|
|
32938
32964
|
.o-cf-iconset-reverse {
|
|
32939
|
-
margin-bottom:
|
|
32940
|
-
margin-top:
|
|
32965
|
+
margin-bottom: 6px;
|
|
32966
|
+
margin-top: 6px;
|
|
32941
32967
|
.o-cf-label {
|
|
32942
32968
|
display: inline-block;
|
|
32943
32969
|
vertical-align: bottom;
|
|
@@ -34525,6 +34551,33 @@ class EditableName extends owl.Component {
|
|
|
34525
34551
|
}
|
|
34526
34552
|
}
|
|
34527
34553
|
|
|
34554
|
+
css /* scss */ `
|
|
34555
|
+
.pivot-defer-update {
|
|
34556
|
+
min-height: 35px;
|
|
34557
|
+
background-color: #f8f9fa;
|
|
34558
|
+
}
|
|
34559
|
+
`;
|
|
34560
|
+
class PivotDeferUpdate extends owl.Component {
|
|
34561
|
+
static template = "o-spreadsheet-PivotDeferUpdate";
|
|
34562
|
+
static props = {
|
|
34563
|
+
deferUpdate: Boolean,
|
|
34564
|
+
isDirty: Boolean,
|
|
34565
|
+
toggleDeferUpdate: Function,
|
|
34566
|
+
discard: Function,
|
|
34567
|
+
apply: Function,
|
|
34568
|
+
};
|
|
34569
|
+
static components = {
|
|
34570
|
+
Section,
|
|
34571
|
+
Checkbox,
|
|
34572
|
+
};
|
|
34573
|
+
get deferUpdatesLabel() {
|
|
34574
|
+
return _t("Defer updates");
|
|
34575
|
+
}
|
|
34576
|
+
get deferUpdatesTooltip() {
|
|
34577
|
+
return _t("Changing the pivot definition requires to reload the data. It may take some time.");
|
|
34578
|
+
}
|
|
34579
|
+
}
|
|
34580
|
+
|
|
34528
34581
|
function useAutofocus({ refName }) {
|
|
34529
34582
|
const ref = owl.useRef(refName);
|
|
34530
34583
|
owl.useEffect((el) => {
|
|
@@ -34644,6 +34697,10 @@ css /* scss */ `
|
|
|
34644
34697
|
select > option {
|
|
34645
34698
|
background-color: white;
|
|
34646
34699
|
}
|
|
34700
|
+
|
|
34701
|
+
.pivot-dim-operator-label {
|
|
34702
|
+
min-width: 120px;
|
|
34703
|
+
}
|
|
34647
34704
|
}
|
|
34648
34705
|
`;
|
|
34649
34706
|
class PivotDimension extends owl.Component {
|
|
@@ -34884,7 +34941,7 @@ class PivotRuntimeDefinition {
|
|
|
34884
34941
|
getMeasure(name) {
|
|
34885
34942
|
const measure = this.measures.find((measure) => measure.name === name);
|
|
34886
34943
|
if (!measure) {
|
|
34887
|
-
throw new EvaluationError(_t("Field %s
|
|
34944
|
+
throw new EvaluationError(_t("Field %s is not a measure", name));
|
|
34888
34945
|
}
|
|
34889
34946
|
return measure;
|
|
34890
34947
|
}
|
|
@@ -35010,10 +35067,9 @@ class SpreadsheetPivotTable {
|
|
|
35010
35067
|
columns;
|
|
35011
35068
|
rows;
|
|
35012
35069
|
measures;
|
|
35013
|
-
rowTitle;
|
|
35014
35070
|
maxIndent;
|
|
35015
35071
|
pivotCells = {};
|
|
35016
|
-
constructor(columns, rows, measures
|
|
35072
|
+
constructor(columns, rows, measures) {
|
|
35017
35073
|
this.columns = columns.map((row) => {
|
|
35018
35074
|
// offset in the pivot table
|
|
35019
35075
|
// starts at 1 because the first column is the row title
|
|
@@ -35026,7 +35082,6 @@ class SpreadsheetPivotTable {
|
|
|
35026
35082
|
});
|
|
35027
35083
|
this.rows = rows;
|
|
35028
35084
|
this.measures = measures;
|
|
35029
|
-
this.rowTitle = rowTitle;
|
|
35030
35085
|
this.maxIndent = Math.max(...this.rows.map((row) => row.indent));
|
|
35031
35086
|
}
|
|
35032
35087
|
/**
|
|
@@ -35068,26 +35123,23 @@ class SpreadsheetPivotTable {
|
|
|
35068
35123
|
}
|
|
35069
35124
|
getPivotCell(col, row, includeTotal = true) {
|
|
35070
35125
|
const colHeadersHeight = this.columns.length;
|
|
35071
|
-
if (
|
|
35072
|
-
return { content: this.rowTitle, isHeader: true };
|
|
35073
|
-
}
|
|
35074
|
-
else if (row <= colHeadersHeight - 1) {
|
|
35126
|
+
if (row <= colHeadersHeight - 1) {
|
|
35075
35127
|
const domain = this.getColHeaderDomain(col, row);
|
|
35076
|
-
return {
|
|
35128
|
+
return domain ? { type: "HEADER", domain } : { type: "EMPTY" };
|
|
35077
35129
|
}
|
|
35078
35130
|
else if (col === 0) {
|
|
35079
35131
|
const rowIndex = row - colHeadersHeight;
|
|
35080
35132
|
const domain = this.getRowDomain(rowIndex);
|
|
35081
|
-
return {
|
|
35133
|
+
return { type: "HEADER", domain };
|
|
35082
35134
|
}
|
|
35083
35135
|
else {
|
|
35084
35136
|
const rowIndex = row - colHeadersHeight;
|
|
35085
35137
|
if (!includeTotal && this.isTotalRow(rowIndex)) {
|
|
35086
|
-
return {
|
|
35138
|
+
return { type: "EMPTY" };
|
|
35087
35139
|
}
|
|
35088
35140
|
const domain = [...this.getRowDomain(rowIndex), ...this.getColDomain(col)];
|
|
35089
35141
|
const measure = this.getColMeasure(col);
|
|
35090
|
-
return {
|
|
35142
|
+
return { type: "VALUE", domain, measure };
|
|
35091
35143
|
}
|
|
35092
35144
|
}
|
|
35093
35145
|
getColHeaderDomain(col, row) {
|
|
@@ -35100,24 +35152,32 @@ class SpreadsheetPivotTable {
|
|
|
35100
35152
|
return undefined;
|
|
35101
35153
|
}
|
|
35102
35154
|
for (let i = 0; i < pivotCol.fields.length; i++) {
|
|
35103
|
-
domain.push(
|
|
35104
|
-
|
|
35155
|
+
domain.push({
|
|
35156
|
+
field: pivotCol.fields[i],
|
|
35157
|
+
value: pivotCol.values[i],
|
|
35158
|
+
});
|
|
35105
35159
|
}
|
|
35106
35160
|
return domain;
|
|
35107
35161
|
}
|
|
35108
35162
|
getColDomain(col) {
|
|
35109
35163
|
const domain = this.getColHeaderDomain(col, this.columns.length - 1);
|
|
35110
|
-
return domain ? domain.slice(0, -
|
|
35164
|
+
return domain ? domain.slice(0, -1) : []; // slice: remove measure and value
|
|
35111
35165
|
}
|
|
35112
35166
|
getColMeasure(col) {
|
|
35113
35167
|
const domain = this.getColHeaderDomain(col, this.columns.length - 1);
|
|
35114
|
-
|
|
35168
|
+
const measure = domain?.at(-1)?.value;
|
|
35169
|
+
if (measure === undefined) {
|
|
35170
|
+
throw new Error("Measure isd missing");
|
|
35171
|
+
}
|
|
35172
|
+
return measure.toString();
|
|
35115
35173
|
}
|
|
35116
35174
|
getRowDomain(row) {
|
|
35117
35175
|
const domain = [];
|
|
35118
35176
|
for (let i = 0; i < this.rows[row].fields.length; i++) {
|
|
35119
|
-
domain.push(
|
|
35120
|
-
|
|
35177
|
+
domain.push({
|
|
35178
|
+
field: this.rows[row].fields[i],
|
|
35179
|
+
value: this.rows[row].values[i],
|
|
35180
|
+
});
|
|
35121
35181
|
}
|
|
35122
35182
|
return domain;
|
|
35123
35183
|
}
|
|
@@ -35126,7 +35186,6 @@ class SpreadsheetPivotTable {
|
|
|
35126
35186
|
cols: this.columns,
|
|
35127
35187
|
rows: this.rows,
|
|
35128
35188
|
measures: this.measures,
|
|
35129
|
-
rowTitle: this.rowTitle,
|
|
35130
35189
|
};
|
|
35131
35190
|
}
|
|
35132
35191
|
}
|
|
@@ -35146,8 +35205,7 @@ function dataEntriesToSpreadsheetPivotTable(dataEntries, definition) {
|
|
|
35146
35205
|
indent: 0,
|
|
35147
35206
|
});
|
|
35148
35207
|
const measureNames = definition.measures.map((m) => m.name);
|
|
35149
|
-
|
|
35150
|
-
return new SpreadsheetPivotTable(cols, rows, measureNames, rowTitle);
|
|
35208
|
+
return new SpreadsheetPivotTable(cols, rows, measureNames);
|
|
35151
35209
|
}
|
|
35152
35210
|
// -----------------------------------------------------------------------------
|
|
35153
35211
|
// ROWS
|
|
@@ -35490,7 +35548,10 @@ class SpreadsheetPivot {
|
|
|
35490
35548
|
}
|
|
35491
35549
|
get definition() {
|
|
35492
35550
|
if (!this._definition) {
|
|
35493
|
-
|
|
35551
|
+
this.init();
|
|
35552
|
+
}
|
|
35553
|
+
if (!this._definition) {
|
|
35554
|
+
throw new Error("Pivot definition should be defined at this point.");
|
|
35494
35555
|
}
|
|
35495
35556
|
return this._definition;
|
|
35496
35557
|
}
|
|
@@ -35539,15 +35600,16 @@ class SpreadsheetPivot {
|
|
|
35539
35600
|
getMeasure(name) {
|
|
35540
35601
|
return this.definition.getMeasure(name);
|
|
35541
35602
|
}
|
|
35542
|
-
|
|
35543
|
-
|
|
35603
|
+
getPivotMeasureValue(name) {
|
|
35604
|
+
return {
|
|
35605
|
+
value: this.getMeasure(name).displayName,
|
|
35606
|
+
};
|
|
35607
|
+
}
|
|
35608
|
+
getPivotHeaderValueAndFormat(domain) {
|
|
35544
35609
|
const lastNode = domain.at(-1);
|
|
35545
35610
|
if (!lastNode) {
|
|
35546
35611
|
return { value: _t("Total") };
|
|
35547
35612
|
}
|
|
35548
|
-
if (lastNode.field === "measure") {
|
|
35549
|
-
return { value: this.getMeasure(lastNode.value).displayName };
|
|
35550
|
-
}
|
|
35551
35613
|
const dimension = this.getDimension(lastNode.field);
|
|
35552
35614
|
const cells = this.filterDataEntriesFromDomain(this.dataEntries, domain);
|
|
35553
35615
|
const finalCell = cells[0]?.[dimension.nameWithGranularity];
|
|
@@ -35575,8 +35637,7 @@ class SpreadsheetPivot {
|
|
|
35575
35637
|
format: finalCell.format,
|
|
35576
35638
|
};
|
|
35577
35639
|
}
|
|
35578
|
-
getPivotCellValueAndFormat(measure,
|
|
35579
|
-
const domain = toDomainArgs(domainStr);
|
|
35640
|
+
getPivotCellValueAndFormat(measure, domain) {
|
|
35580
35641
|
const dataEntries = this.filterDataEntriesFromDomain(this.dataEntries, domain);
|
|
35581
35642
|
if (dataEntries.length === 0) {
|
|
35582
35643
|
return { value: "" };
|
|
@@ -35972,12 +36033,12 @@ class PivotSpreadsheetSidePanel extends owl.Component {
|
|
|
35972
36033
|
SelectionInput,
|
|
35973
36034
|
EditableName,
|
|
35974
36035
|
Checkbox,
|
|
36036
|
+
PivotDeferUpdate,
|
|
35975
36037
|
};
|
|
35976
36038
|
store;
|
|
35977
36039
|
state;
|
|
35978
36040
|
setup() {
|
|
35979
36041
|
this.store = useLocalStore(PivotSidePanelStore, this.props.pivotId);
|
|
35980
|
-
this.pivot.init();
|
|
35981
36042
|
this.state = owl.useState({
|
|
35982
36043
|
range: undefined,
|
|
35983
36044
|
rangeHasChanged: false,
|
|
@@ -36010,12 +36071,6 @@ class PivotSpreadsheetSidePanel extends owl.Component {
|
|
|
36010
36071
|
get definition() {
|
|
36011
36072
|
return this.store.definition;
|
|
36012
36073
|
}
|
|
36013
|
-
get deferUpdatesLabel() {
|
|
36014
|
-
return _t("Defer updates");
|
|
36015
|
-
}
|
|
36016
|
-
get deferUpdatesTooltip() {
|
|
36017
|
-
return _t("Changing the pivot definition requires to reload the data. It may take some time.");
|
|
36018
|
-
}
|
|
36019
36074
|
onSelectionChanged(ranges) {
|
|
36020
36075
|
this.state.rangeHasChanged = true;
|
|
36021
36076
|
this.state.range = ranges[0];
|
|
@@ -36854,7 +36909,7 @@ css /* scss */ `
|
|
|
36854
36909
|
}
|
|
36855
36910
|
|
|
36856
36911
|
.o-table-style-list-item {
|
|
36857
|
-
padding: 3px;
|
|
36912
|
+
padding: 3px 2px;
|
|
36858
36913
|
margin: 2px 1px;
|
|
36859
36914
|
|
|
36860
36915
|
.o-table-style-picker-preview {
|
|
@@ -36875,10 +36930,10 @@ class TableStylePicker extends owl.Component {
|
|
|
36875
36930
|
const styles = Object.keys(allStyles).filter((key) => allStyles[key].category === selectedStyleCategory);
|
|
36876
36931
|
const selectedStyleIndex = styles.indexOf(this.props.table.config.styleId);
|
|
36877
36932
|
if (selectedStyleIndex === -1) {
|
|
36878
|
-
return
|
|
36933
|
+
return selectedStyleIndex;
|
|
36879
36934
|
}
|
|
36880
36935
|
const index = Math.floor(selectedStyleIndex / 4) * 4;
|
|
36881
|
-
return styles.slice(index
|
|
36936
|
+
return styles.slice(index);
|
|
36882
36937
|
}
|
|
36883
36938
|
onStylePicked(styleId) {
|
|
36884
36939
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
@@ -37918,10 +37973,7 @@ class GridComposer extends owl.Component {
|
|
|
37918
37973
|
}
|
|
37919
37974
|
get containerStyle() {
|
|
37920
37975
|
if (this.composerStore.editionMode === "inactive") {
|
|
37921
|
-
return `
|
|
37922
|
-
position: absolute;
|
|
37923
|
-
z-index: -1000;
|
|
37924
|
-
`;
|
|
37976
|
+
return `z-index: -1000;`;
|
|
37925
37977
|
}
|
|
37926
37978
|
const isFormula = this.composerStore.currentContent.startsWith("=");
|
|
37927
37979
|
const cell = this.env.model.getters.getActiveCell();
|
|
@@ -40765,10 +40817,13 @@ class VerticalScrollBar extends owl.Component {
|
|
|
40765
40817
|
}
|
|
40766
40818
|
}
|
|
40767
40819
|
|
|
40820
|
+
const DEFAULT_SIDE_PANEL_SIZE = 350;
|
|
40821
|
+
const MIN_SHEET_VIEW_WIDTH = 150;
|
|
40768
40822
|
class SidePanelStore extends SpreadsheetStore {
|
|
40769
|
-
mutators = ["open", "toggle", "close"];
|
|
40823
|
+
mutators = ["open", "toggle", "close", "changePanelSize", "resetPanelSize"];
|
|
40770
40824
|
initialPanelProps = {};
|
|
40771
40825
|
componentTag = "";
|
|
40826
|
+
panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
40772
40827
|
get isOpen() {
|
|
40773
40828
|
if (!this.componentTag) {
|
|
40774
40829
|
return false;
|
|
@@ -40813,6 +40868,20 @@ class SidePanelStore extends SpreadsheetStore {
|
|
|
40813
40868
|
this.initialPanelProps = {};
|
|
40814
40869
|
this.componentTag = "";
|
|
40815
40870
|
}
|
|
40871
|
+
changePanelSize(size, spreadsheetElWidth) {
|
|
40872
|
+
if (size < DEFAULT_SIDE_PANEL_SIZE) {
|
|
40873
|
+
this.panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
40874
|
+
}
|
|
40875
|
+
else if (size > spreadsheetElWidth - MIN_SHEET_VIEW_WIDTH) {
|
|
40876
|
+
this.panelSize = Math.max(spreadsheetElWidth - MIN_SHEET_VIEW_WIDTH, DEFAULT_SIDE_PANEL_SIZE);
|
|
40877
|
+
}
|
|
40878
|
+
else {
|
|
40879
|
+
this.panelSize = size;
|
|
40880
|
+
}
|
|
40881
|
+
}
|
|
40882
|
+
resetPanelSize() {
|
|
40883
|
+
this.panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
40884
|
+
}
|
|
40816
40885
|
computeState(componentTag, panelProps) {
|
|
40817
40886
|
const customComputeState = sidePanelRegistry.get(componentTag).computeState;
|
|
40818
40887
|
if (!customComputeState) {
|
|
@@ -41933,7 +42002,7 @@ class XLSXImportWarningManager {
|
|
|
41933
42002
|
}
|
|
41934
42003
|
}
|
|
41935
42004
|
|
|
41936
|
-
const SUPPORTED_BORDER_STYLES = ["thin"];
|
|
42005
|
+
const SUPPORTED_BORDER_STYLES = ["thin", "medium", "thick", "dashed", "dotted"];
|
|
41937
42006
|
const SUPPORTED_HORIZONTAL_ALIGNMENTS = [
|
|
41938
42007
|
"general",
|
|
41939
42008
|
"left",
|
|
@@ -51072,8 +51141,8 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
51072
51141
|
case "INSERT_PIVOT": {
|
|
51073
51142
|
const { sheetId, col, row, pivotId, table } = cmd;
|
|
51074
51143
|
const position = { sheetId, col, row };
|
|
51075
|
-
const { cols, rows, measures
|
|
51076
|
-
const spTable = new SpreadsheetPivotTable(cols, rows, measures
|
|
51144
|
+
const { cols, rows, measures } = table;
|
|
51145
|
+
const spTable = new SpreadsheetPivotTable(cols, rows, measures);
|
|
51077
51146
|
const formulaId = this.getPivotFormulaId(pivotId);
|
|
51078
51147
|
this.insertPivot(position, formulaId, spTable);
|
|
51079
51148
|
break;
|
|
@@ -51202,13 +51271,18 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
51202
51271
|
}
|
|
51203
51272
|
}
|
|
51204
51273
|
addPivotFormula(position, formulaId, pivotCell) {
|
|
51205
|
-
|
|
51206
|
-
|
|
51207
|
-
|
|
51208
|
-
|
|
51274
|
+
let content = undefined;
|
|
51275
|
+
switch (pivotCell.type) {
|
|
51276
|
+
case "HEADER":
|
|
51277
|
+
content = makePivotFormula("PIVOT.HEADER", [formulaId, ...flatPivotDomain(pivotCell.domain)].filter(isDefined));
|
|
51278
|
+
break;
|
|
51279
|
+
case "VALUE":
|
|
51280
|
+
content = makePivotFormula("PIVOT.VALUE", [formulaId, pivotCell.measure, ...flatPivotDomain(pivotCell.domain)].filter(isDefined));
|
|
51281
|
+
break;
|
|
51282
|
+
}
|
|
51209
51283
|
this.dispatch("UPDATE_CELL", {
|
|
51210
51284
|
...position,
|
|
51211
|
-
content
|
|
51285
|
+
content,
|
|
51212
51286
|
});
|
|
51213
51287
|
}
|
|
51214
51288
|
getPivotCore(pivotId) {
|
|
@@ -51227,7 +51301,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
51227
51301
|
import(data) {
|
|
51228
51302
|
if (data.pivots) {
|
|
51229
51303
|
for (const [id, pivot] of Object.entries(data.pivots)) {
|
|
51230
|
-
this.addPivot(id,
|
|
51304
|
+
this.addPivot(id, pivot, pivot.formulaId);
|
|
51231
51305
|
}
|
|
51232
51306
|
}
|
|
51233
51307
|
this.history.update("nextFormulaId", data.pivotNextId || getMaxObjectId(this.pivots) + 1);
|
|
@@ -54568,17 +54642,21 @@ class PivotUIPlugin extends UIPlugin {
|
|
|
54568
54642
|
const pivotCol = position.col - mainPosition.col;
|
|
54569
54643
|
const pivotRow = position.row - mainPosition.row;
|
|
54570
54644
|
const pivotCell = pivotCells[pivotCol][pivotRow];
|
|
54571
|
-
|
|
54572
|
-
|
|
54573
|
-
|
|
54645
|
+
if (pivotCell.type === "EMPTY") {
|
|
54646
|
+
return undefined;
|
|
54647
|
+
}
|
|
54648
|
+
let domain = pivotCell.domain;
|
|
54649
|
+
if (domain.at(-1)?.field === "measure") {
|
|
54650
|
+
domain = domain.slice(0, -1);
|
|
54574
54651
|
}
|
|
54575
|
-
return domain;
|
|
54652
|
+
return { domainArgs: domain, isHeader: pivotCell.type === "HEADER" };
|
|
54576
54653
|
}
|
|
54577
|
-
|
|
54578
|
-
if (domain.at(-
|
|
54579
|
-
|
|
54654
|
+
let domain = toPivotDomain(args.slice(functionName === "PIVOT.VALUE" ? 2 : 1).map((x) => `${x}`));
|
|
54655
|
+
if (domain.at(-1)?.field === "measure") {
|
|
54656
|
+
domain = domain.slice(0, -1);
|
|
54580
54657
|
}
|
|
54581
|
-
|
|
54658
|
+
const isHeader = functionName === "PIVOT.HEADER";
|
|
54659
|
+
return { domainArgs: domain, isHeader };
|
|
54582
54660
|
}
|
|
54583
54661
|
getPivot(pivotId) {
|
|
54584
54662
|
return this.pivots[pivotId];
|
|
@@ -54591,9 +54669,9 @@ class PivotUIPlugin extends UIPlugin {
|
|
|
54591
54669
|
* a pivot function are valid according to the pivot definition.
|
|
54592
54670
|
* e.g. =PIVOT.VALUE(1,"revenue","country_id",...,"create_date:month",...,"source_id",...)
|
|
54593
54671
|
*/
|
|
54594
|
-
areDomainArgsFieldsValid(pivotId,
|
|
54595
|
-
const dimensions =
|
|
54596
|
-
.
|
|
54672
|
+
areDomainArgsFieldsValid(pivotId, domain) {
|
|
54673
|
+
const dimensions = domain
|
|
54674
|
+
.map((node) => node.field)
|
|
54597
54675
|
.map((name) => (name.startsWith("#") ? name.slice(1) : name));
|
|
54598
54676
|
let argIndex = 0;
|
|
54599
54677
|
let definitionIndex = 0;
|
|
@@ -61607,6 +61685,10 @@ css /* scss */ `
|
|
|
61607
61685
|
}
|
|
61608
61686
|
}
|
|
61609
61687
|
}
|
|
61688
|
+
.o-sidePanelBody-container {
|
|
61689
|
+
/* This overwrites the min-height: auto; of flex. Without this, a flex div cannot be smaller than its children */
|
|
61690
|
+
min-height: 0;
|
|
61691
|
+
}
|
|
61610
61692
|
.o-sidePanelBody {
|
|
61611
61693
|
overflow: auto;
|
|
61612
61694
|
width: 100%;
|
|
@@ -61685,24 +61767,6 @@ css /* scss */ `
|
|
|
61685
61767
|
text-align: left;
|
|
61686
61768
|
}
|
|
61687
61769
|
|
|
61688
|
-
.o-inflection {
|
|
61689
|
-
table {
|
|
61690
|
-
table-layout: fixed;
|
|
61691
|
-
margin-top: 2%;
|
|
61692
|
-
display: table;
|
|
61693
|
-
text-align: left;
|
|
61694
|
-
font-size: 12px;
|
|
61695
|
-
line-height: 18px;
|
|
61696
|
-
width: 100%;
|
|
61697
|
-
}
|
|
61698
|
-
input,
|
|
61699
|
-
select {
|
|
61700
|
-
width: 100%;
|
|
61701
|
-
height: 100%;
|
|
61702
|
-
box-sizing: border-box;
|
|
61703
|
-
}
|
|
61704
|
-
}
|
|
61705
|
-
|
|
61706
61770
|
.o-sidePanel-tools {
|
|
61707
61771
|
color: #333;
|
|
61708
61772
|
font-size: 13px;
|
|
@@ -61721,12 +61785,25 @@ css /* scss */ `
|
|
|
61721
61785
|
}
|
|
61722
61786
|
}
|
|
61723
61787
|
}
|
|
61788
|
+
|
|
61789
|
+
.o-sidePanel-handle-container {
|
|
61790
|
+
width: 8px;
|
|
61791
|
+
}
|
|
61792
|
+
.o-sidePanel-handle {
|
|
61793
|
+
cursor: col-resize;
|
|
61794
|
+
color: #a9a9a9;
|
|
61795
|
+
.o-icon {
|
|
61796
|
+
height: 25px;
|
|
61797
|
+
margin-left: -5px;
|
|
61798
|
+
}
|
|
61799
|
+
}
|
|
61724
61800
|
}
|
|
61725
61801
|
`;
|
|
61726
61802
|
class SidePanel extends owl.Component {
|
|
61727
61803
|
static template = "o-spreadsheet-SidePanel";
|
|
61728
61804
|
static props = {};
|
|
61729
61805
|
sidePanelStore;
|
|
61806
|
+
spreadsheetRect = useSpreadsheetRect();
|
|
61730
61807
|
setup() {
|
|
61731
61808
|
this.sidePanelStore = useStore(SidePanelStore);
|
|
61732
61809
|
owl.useEffect((isOpen) => {
|
|
@@ -61747,6 +61824,20 @@ class SidePanel extends owl.Component {
|
|
|
61747
61824
|
? panel.title(this.env, this.sidePanelStore.panelProps)
|
|
61748
61825
|
: panel.title;
|
|
61749
61826
|
}
|
|
61827
|
+
startHandleDrag(ev) {
|
|
61828
|
+
const startingCursor = document.body.style.cursor;
|
|
61829
|
+
const startSize = this.sidePanelStore.panelSize;
|
|
61830
|
+
const startPosition = ev.clientX;
|
|
61831
|
+
const onMouseMove = (ev) => {
|
|
61832
|
+
document.body.style.cursor = "col-resize";
|
|
61833
|
+
const newSize = startSize + startPosition - ev.clientX;
|
|
61834
|
+
this.sidePanelStore.changePanelSize(newSize, this.spreadsheetRect.width);
|
|
61835
|
+
};
|
|
61836
|
+
const cleanUp = () => {
|
|
61837
|
+
document.body.style.cursor = startingCursor;
|
|
61838
|
+
};
|
|
61839
|
+
startDnd(onMouseMove, cleanUp);
|
|
61840
|
+
}
|
|
61750
61841
|
}
|
|
61751
61842
|
|
|
61752
61843
|
css /* scss */ `
|
|
@@ -62530,7 +62621,6 @@ css /* scss */ `
|
|
|
62530
62621
|
.o-spreadsheet {
|
|
62531
62622
|
position: relative;
|
|
62532
62623
|
display: grid;
|
|
62533
|
-
grid-template-columns: auto 350px;
|
|
62534
62624
|
color: #333;
|
|
62535
62625
|
font-size: 14px;
|
|
62536
62626
|
|
|
@@ -62728,6 +62818,7 @@ class Spreadsheet extends owl.Component {
|
|
|
62728
62818
|
};
|
|
62729
62819
|
sidePanel;
|
|
62730
62820
|
spreadsheetRef = owl.useRef("spreadsheet");
|
|
62821
|
+
spreadsheetRect = useSpreadsheetRect();
|
|
62731
62822
|
_focusGrid;
|
|
62732
62823
|
keyDownMapping;
|
|
62733
62824
|
isViewportTooSmall = false;
|
|
@@ -62737,10 +62828,15 @@ class Spreadsheet extends owl.Component {
|
|
|
62737
62828
|
return this.props.model;
|
|
62738
62829
|
}
|
|
62739
62830
|
getStyle() {
|
|
62831
|
+
const properties = {};
|
|
62740
62832
|
if (this.env.isDashboard()) {
|
|
62741
|
-
|
|
62833
|
+
properties["grid-template-rows"] = `auto`;
|
|
62834
|
+
}
|
|
62835
|
+
else {
|
|
62836
|
+
properties["grid-template-rows"] = `${TOPBAR_HEIGHT}px auto ${BOTTOMBAR_HEIGHT + 1}px`;
|
|
62742
62837
|
}
|
|
62743
|
-
|
|
62838
|
+
properties["grid-template-columns"] = `auto ${this.sidePanel.panelSize}px`;
|
|
62839
|
+
return cssPropertiesToCss(properties);
|
|
62744
62840
|
}
|
|
62745
62841
|
setup() {
|
|
62746
62842
|
const stores = useStoreProvider();
|
|
@@ -62800,14 +62896,19 @@ class Spreadsheet extends owl.Component {
|
|
|
62800
62896
|
owl.onMounted(() => {
|
|
62801
62897
|
this.checkViewportSize();
|
|
62802
62898
|
stores.on("store-updated", this, render);
|
|
62899
|
+
resizeObserver.observe(this.spreadsheetRef.el);
|
|
62803
62900
|
});
|
|
62804
62901
|
owl.onWillUnmount(() => {
|
|
62805
62902
|
this.unbindModelEvents();
|
|
62806
62903
|
stores.off("store-updated", this);
|
|
62904
|
+
resizeObserver.disconnect();
|
|
62807
62905
|
});
|
|
62808
62906
|
owl.onPatched(() => {
|
|
62809
62907
|
this.checkViewportSize();
|
|
62810
62908
|
});
|
|
62909
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
62910
|
+
this.sidePanel.changePanelSize(this.sidePanel.panelSize, this.spreadsheetRect.width);
|
|
62911
|
+
});
|
|
62811
62912
|
}
|
|
62812
62913
|
bindModelEvents() {
|
|
62813
62914
|
this.model.on("update", this, () => this.render(true));
|
|
@@ -66862,6 +66963,8 @@ const helpers = {
|
|
|
66862
66963
|
insertTokenAfterLeftParenthesis,
|
|
66863
66964
|
mergeContiguousZones,
|
|
66864
66965
|
getPivotHighlights,
|
|
66966
|
+
toPivotDomain,
|
|
66967
|
+
flatPivotDomain,
|
|
66865
66968
|
pivotTimeAdapter,
|
|
66866
66969
|
UNDO_REDO_PIVOT_COMMANDS,
|
|
66867
66970
|
};
|
|
@@ -66906,6 +67009,7 @@ const components = {
|
|
|
66906
67009
|
PivotDimension,
|
|
66907
67010
|
PivotLayoutConfigurator,
|
|
66908
67011
|
EditableName,
|
|
67012
|
+
PivotDeferUpdate,
|
|
66909
67013
|
};
|
|
66910
67014
|
const hooks = {
|
|
66911
67015
|
useDragAndDropListItems,
|
|
@@ -66989,6 +67093,6 @@ exports.tokenColors = tokenColors;
|
|
|
66989
67093
|
exports.tokenize = tokenize;
|
|
66990
67094
|
|
|
66991
67095
|
|
|
66992
|
-
__info__.version = "17.4.0-alpha.
|
|
66993
|
-
__info__.date = "2024-06-
|
|
66994
|
-
__info__.hash = "
|
|
67096
|
+
__info__.version = "17.4.0-alpha.3";
|
|
67097
|
+
__info__.date = "2024-06-10T09:38:53.982Z";
|
|
67098
|
+
__info__.hash = "a45ed6a";
|