@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
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -8959,7 +8959,7 @@ class NotificationStore {
|
|
|
8959
8959
|
"askConfirmation",
|
|
8960
8960
|
"updateNotificationCallbacks",
|
|
8961
8961
|
];
|
|
8962
|
-
notifyUser = (notification) => window.alert(notification);
|
|
8962
|
+
notifyUser = (notification) => window.alert(notification.text);
|
|
8963
8963
|
askConfirmation = (content, confirm, cancel) => {
|
|
8964
8964
|
if (window.confirm(content)) {
|
|
8965
8965
|
confirm();
|
|
@@ -18375,6 +18375,131 @@ var logical = /*#__PURE__*/Object.freeze({
|
|
|
18375
18375
|
const supportedPivotExplodedFormulaRegistry = new Registry();
|
|
18376
18376
|
supportedPivotExplodedFormulaRegistry.add("SPREADSHEET", false);
|
|
18377
18377
|
|
|
18378
|
+
const AGGREGATOR_NAMES = {
|
|
18379
|
+
count: _t("Count"),
|
|
18380
|
+
count_distinct: _t("Count Distinct"),
|
|
18381
|
+
bool_and: _t("Boolean And"),
|
|
18382
|
+
bool_or: _t("Boolean Or"),
|
|
18383
|
+
max: _t("Maximum"),
|
|
18384
|
+
min: _t("Minimum"),
|
|
18385
|
+
avg: _t("Average"),
|
|
18386
|
+
sum: _t("Sum"),
|
|
18387
|
+
};
|
|
18388
|
+
const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
|
|
18389
|
+
const AGGREGATORS_BY_FIELD_TYPE = {
|
|
18390
|
+
integer: NUMBER_CHAR_AGGREGATORS,
|
|
18391
|
+
char: NUMBER_CHAR_AGGREGATORS,
|
|
18392
|
+
//TODO Support for date and boolean
|
|
18393
|
+
};
|
|
18394
|
+
const AGGREGATORS = {};
|
|
18395
|
+
for (const type in AGGREGATORS_BY_FIELD_TYPE) {
|
|
18396
|
+
AGGREGATORS[type] = {};
|
|
18397
|
+
for (const aggregator of AGGREGATORS_BY_FIELD_TYPE[type]) {
|
|
18398
|
+
AGGREGATORS[type][aggregator] = AGGREGATOR_NAMES[aggregator];
|
|
18399
|
+
}
|
|
18400
|
+
}
|
|
18401
|
+
const AGGREGATORS_FN = {
|
|
18402
|
+
count: {
|
|
18403
|
+
fn: (args) => countAny([args]),
|
|
18404
|
+
format: () => "0",
|
|
18405
|
+
},
|
|
18406
|
+
count_distinct: {
|
|
18407
|
+
fn: (args) => countUnique([args]),
|
|
18408
|
+
format: () => "0",
|
|
18409
|
+
},
|
|
18410
|
+
bool_and: {
|
|
18411
|
+
fn: (args) => boolAnd([args]).result,
|
|
18412
|
+
format: () => undefined,
|
|
18413
|
+
},
|
|
18414
|
+
bool_or: {
|
|
18415
|
+
fn: (args) => boolOr([args]).result,
|
|
18416
|
+
format: () => undefined,
|
|
18417
|
+
},
|
|
18418
|
+
max: {
|
|
18419
|
+
fn: (args, locale) => max([args], locale),
|
|
18420
|
+
format: inferFormat,
|
|
18421
|
+
},
|
|
18422
|
+
min: {
|
|
18423
|
+
fn: (args, locale) => min([args], locale),
|
|
18424
|
+
format: inferFormat,
|
|
18425
|
+
},
|
|
18426
|
+
avg: {
|
|
18427
|
+
fn: (args, locale) => average([args], locale),
|
|
18428
|
+
format: inferFormat,
|
|
18429
|
+
},
|
|
18430
|
+
sum: {
|
|
18431
|
+
fn: (args, locale) => sum([args], locale),
|
|
18432
|
+
format: inferFormat,
|
|
18433
|
+
},
|
|
18434
|
+
};
|
|
18435
|
+
/**
|
|
18436
|
+
* Build a pivot formula expression
|
|
18437
|
+
*/
|
|
18438
|
+
function makePivotFormula(formula, args) {
|
|
18439
|
+
return `=${formula}(${args
|
|
18440
|
+
.map((arg) => {
|
|
18441
|
+
const stringIsNumber = typeof arg == "string" && !isNaN(Number(arg)) && Number(arg).toString() === arg;
|
|
18442
|
+
const convertToNumber = typeof arg == "number" || stringIsNumber;
|
|
18443
|
+
return convertToNumber ? `${arg}` : `"${arg.toString().replace(/"/g, '\\"')}"`;
|
|
18444
|
+
})
|
|
18445
|
+
.join(",")})`;
|
|
18446
|
+
}
|
|
18447
|
+
/**
|
|
18448
|
+
* Given an object of form {"1": {...}, "2": {...}, ...} get the maximum ID used
|
|
18449
|
+
* in this object
|
|
18450
|
+
* If the object has no keys, return 0
|
|
18451
|
+
*
|
|
18452
|
+
*/
|
|
18453
|
+
function getMaxObjectId(o) {
|
|
18454
|
+
const keys = Object.keys(o);
|
|
18455
|
+
if (!keys.length) {
|
|
18456
|
+
return 0;
|
|
18457
|
+
}
|
|
18458
|
+
const nums = keys.map((id) => parseInt(id, 10));
|
|
18459
|
+
const max = Math.max(...nums);
|
|
18460
|
+
return max;
|
|
18461
|
+
}
|
|
18462
|
+
const ALL_PERIODS = {
|
|
18463
|
+
year: _t("Year"),
|
|
18464
|
+
quarter: _t("Quarter"),
|
|
18465
|
+
month: _t("Month"),
|
|
18466
|
+
week: _t("Week"),
|
|
18467
|
+
day: _t("Day"),
|
|
18468
|
+
year_number: _t("Year"),
|
|
18469
|
+
quarter_number: _t("Quarter"),
|
|
18470
|
+
month_number: _t("Month"),
|
|
18471
|
+
iso_week_number: _t("Week"),
|
|
18472
|
+
day_of_month: _t("Day of Month"),
|
|
18473
|
+
};
|
|
18474
|
+
const DATE_FIELDS = ["date", "datetime"];
|
|
18475
|
+
/**
|
|
18476
|
+
* Parse a dimension string into a pivot dimension definition.
|
|
18477
|
+
* e.g "create_date:month" => { name: "create_date", granularity: "month" }
|
|
18478
|
+
*/
|
|
18479
|
+
function parseDimension(dimension) {
|
|
18480
|
+
const [name, granularity] = dimension.split(":");
|
|
18481
|
+
if (granularity) {
|
|
18482
|
+
return { name, granularity };
|
|
18483
|
+
}
|
|
18484
|
+
return { name };
|
|
18485
|
+
}
|
|
18486
|
+
function isDateField(field) {
|
|
18487
|
+
return DATE_FIELDS.includes(field.type);
|
|
18488
|
+
}
|
|
18489
|
+
function toPivotDomain(domainStr) {
|
|
18490
|
+
if (domainStr.length % 2 !== 0) {
|
|
18491
|
+
throw new Error("Invalid domain: odd number of elements");
|
|
18492
|
+
}
|
|
18493
|
+
const domain = [];
|
|
18494
|
+
for (let i = 0; i < domainStr.length - 1; i += 2) {
|
|
18495
|
+
domain.push({ field: domainStr[i], value: domainStr[i + 1] });
|
|
18496
|
+
}
|
|
18497
|
+
return domain;
|
|
18498
|
+
}
|
|
18499
|
+
function flatPivotDomain(domain) {
|
|
18500
|
+
return domain.flatMap((arg) => [arg.field, arg.value]);
|
|
18501
|
+
}
|
|
18502
|
+
|
|
18378
18503
|
/**
|
|
18379
18504
|
* Get the pivot ID from the formula pivot ID.
|
|
18380
18505
|
*/
|
|
@@ -18854,13 +18979,13 @@ const PIVOT_VALUE = {
|
|
|
18854
18979
|
arg("domain_field_name (string,optional,repeating)", _t("Field name.")),
|
|
18855
18980
|
arg("domain_value (string,optional,repeating)", _t("Value.")),
|
|
18856
18981
|
],
|
|
18857
|
-
compute: function (formulaId, measureName, ...
|
|
18982
|
+
compute: function (formulaId, measureName, ...domainArgs) {
|
|
18858
18983
|
const _pivotFormulaId = toString(formulaId);
|
|
18859
|
-
const
|
|
18860
|
-
const
|
|
18984
|
+
const _measure = toString(measureName);
|
|
18985
|
+
const _domainArgs = domainArgs.map(toString);
|
|
18861
18986
|
const pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
18862
|
-
assertMeasureExist(pivotId,
|
|
18863
|
-
assertDomainLength(
|
|
18987
|
+
assertMeasureExist(pivotId, _measure, this.getters);
|
|
18988
|
+
assertDomainLength(_domainArgs);
|
|
18864
18989
|
const pivot = this.getters.getPivot(pivotId);
|
|
18865
18990
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
18866
18991
|
if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
|
|
@@ -18874,8 +18999,9 @@ const PIVOT_VALUE = {
|
|
|
18874
18999
|
if (error) {
|
|
18875
19000
|
return error;
|
|
18876
19001
|
}
|
|
18877
|
-
const
|
|
18878
|
-
|
|
19002
|
+
const domain = toPivotDomain(_domainArgs);
|
|
19003
|
+
const { value, format } = pivot.getPivotCellValueAndFormat(_measure, domain);
|
|
19004
|
+
if (!value && !this.getters.areDomainArgsFieldsValid(pivotId, domain)) {
|
|
18879
19005
|
return {
|
|
18880
19006
|
value: CellErrorType.GenericError,
|
|
18881
19007
|
message: _t("Dimensions don't match the pivot definition"),
|
|
@@ -18892,11 +19018,11 @@ const PIVOT_HEADER = {
|
|
|
18892
19018
|
arg("domain_field_name (string,optional,repeating)", _t("Field name.")),
|
|
18893
19019
|
arg("domain_value (string,optional,repeating)", _t("Value.")),
|
|
18894
19020
|
],
|
|
18895
|
-
compute: function (pivotId, ...
|
|
19021
|
+
compute: function (pivotId, ...domainArgs) {
|
|
18896
19022
|
const _pivotFormulaId = toString(pivotId);
|
|
18897
|
-
const
|
|
19023
|
+
const _domainArgs = domainArgs.map(toString);
|
|
18898
19024
|
const _pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
18899
|
-
assertDomainLength(
|
|
19025
|
+
assertDomainLength(_domainArgs);
|
|
18900
19026
|
const pivot = this.getters.getPivot(_pivotId);
|
|
18901
19027
|
const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
|
|
18902
19028
|
if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
|
|
@@ -18910,18 +19036,23 @@ const PIVOT_HEADER = {
|
|
|
18910
19036
|
if (error) {
|
|
18911
19037
|
return error;
|
|
18912
19038
|
}
|
|
18913
|
-
const
|
|
18914
|
-
const
|
|
18915
|
-
if (!this.getters.areDomainArgsFieldsValid(_pivotId,
|
|
19039
|
+
const domain = toPivotDomain(_domainArgs);
|
|
19040
|
+
const lastNode = domain.at(-1);
|
|
19041
|
+
if (!this.getters.areDomainArgsFieldsValid(_pivotId, lastNode?.field === "measure" ? domain.slice(0, -1) : domain)) {
|
|
18916
19042
|
return {
|
|
18917
19043
|
value: CellErrorType.GenericError,
|
|
18918
19044
|
message: _t("Dimensions don't match the pivot definition"),
|
|
18919
19045
|
};
|
|
18920
19046
|
}
|
|
18921
|
-
|
|
19047
|
+
if (lastNode?.field === "measure") {
|
|
19048
|
+
return pivot.getPivotMeasureValue(toString(lastNode.value), domain);
|
|
19049
|
+
}
|
|
19050
|
+
const { value, format } = pivot.getPivotHeaderValueAndFormat(domain);
|
|
18922
19051
|
return {
|
|
18923
19052
|
value,
|
|
18924
|
-
format: !
|
|
19053
|
+
format: !lastNode || lastNode.field === "measure" || lastNode.value === "false"
|
|
19054
|
+
? undefined
|
|
19055
|
+
: format,
|
|
18925
19056
|
};
|
|
18926
19057
|
},
|
|
18927
19058
|
returns: ["NUMBER", "STRING"],
|
|
@@ -18934,11 +19065,14 @@ const PIVOT = {
|
|
|
18934
19065
|
arg("include_total (boolean, default=TRUE)", _t("Whether to include total/sub-totals or not.")),
|
|
18935
19066
|
arg("include_column_titles (boolean, default=TRUE)", _t("Whether to include the column titles or not.")),
|
|
18936
19067
|
],
|
|
18937
|
-
compute: function (
|
|
18938
|
-
const _pivotFormulaId = toString(
|
|
18939
|
-
const
|
|
18940
|
-
const
|
|
18941
|
-
const
|
|
19068
|
+
compute: function (pivotFormulaId, rowCount = { value: 10000 }, includeTotal = { value: true }, includeColumnHeaders = { value: true }) {
|
|
19069
|
+
const _pivotFormulaId = toString(pivotFormulaId);
|
|
19070
|
+
const _rowCount = toNumber(rowCount, this.locale);
|
|
19071
|
+
const _includeColumnHeaders = toBoolean(includeColumnHeaders);
|
|
19072
|
+
const _includedTotal = toBoolean(includeTotal);
|
|
19073
|
+
const pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
19074
|
+
const pivot = this.getters.getPivot(pivotId);
|
|
19075
|
+
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
18942
19076
|
addPivotDependencies(this, coreDefinition);
|
|
18943
19077
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
18944
19078
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
@@ -18946,11 +19080,9 @@ const PIVOT = {
|
|
|
18946
19080
|
return error;
|
|
18947
19081
|
}
|
|
18948
19082
|
const table = pivot.getTableStructure();
|
|
18949
|
-
const
|
|
18950
|
-
const cells = table.getPivotCells(toBoolean(includeTotal), _includeColumnHeaders);
|
|
19083
|
+
const cells = table.getPivotCells(_includedTotal, _includeColumnHeaders);
|
|
18951
19084
|
const headerRows = _includeColumnHeaders ? table.columns.length : 0;
|
|
18952
|
-
const pivotTitle = this.getters.getPivotDisplayName(
|
|
18953
|
-
const _rowCount = toNumber(rowCount, this.locale);
|
|
19085
|
+
const pivotTitle = this.getters.getPivotDisplayName(pivotId);
|
|
18954
19086
|
if (_rowCount < 0) {
|
|
18955
19087
|
throw new EvaluationError(_t("The number of rows must be positive."));
|
|
18956
19088
|
}
|
|
@@ -18965,17 +19097,23 @@ const PIVOT = {
|
|
|
18965
19097
|
result[col] = [];
|
|
18966
19098
|
for (const row of tableRows) {
|
|
18967
19099
|
const pivotCell = cells[col][row];
|
|
18968
|
-
|
|
18969
|
-
|
|
18970
|
-
|
|
18971
|
-
|
|
18972
|
-
|
|
18973
|
-
|
|
18974
|
-
|
|
18975
|
-
|
|
18976
|
-
|
|
18977
|
-
|
|
18978
|
-
|
|
19100
|
+
switch (pivotCell.type) {
|
|
19101
|
+
case "EMPTY":
|
|
19102
|
+
result[col].push({ value: "" });
|
|
19103
|
+
break;
|
|
19104
|
+
case "HEADER":
|
|
19105
|
+
const domain = pivotCell.domain;
|
|
19106
|
+
const lastNode = domain.at(-1);
|
|
19107
|
+
if (lastNode?.field === "measure") {
|
|
19108
|
+
result[col].push(pivot.getPivotMeasureValue(toString(lastNode.value), domain));
|
|
19109
|
+
}
|
|
19110
|
+
else {
|
|
19111
|
+
result[col].push(pivot.getPivotHeaderValueAndFormat(domain));
|
|
19112
|
+
}
|
|
19113
|
+
break;
|
|
19114
|
+
case "VALUE":
|
|
19115
|
+
result[col].push(pivot.getPivotCellValueAndFormat(pivotCell.measure, pivotCell.domain));
|
|
19116
|
+
break;
|
|
18979
19117
|
}
|
|
18980
19118
|
}
|
|
18981
19119
|
}
|
|
@@ -20900,8 +21038,15 @@ class Composer extends Component {
|
|
|
20900
21038
|
}
|
|
20901
21039
|
onPaste(ev) {
|
|
20902
21040
|
if (this.composerStore.editionMode !== "inactive") {
|
|
21041
|
+
// let the browser clipboard work
|
|
20903
21042
|
ev.stopPropagation();
|
|
20904
21043
|
}
|
|
21044
|
+
else {
|
|
21045
|
+
// the user meant to paste in the sheet, not open the composer with the pasted content
|
|
21046
|
+
// While we're not editing, we still have the focus and should therefore prevent
|
|
21047
|
+
// the native "paste" to occur.
|
|
21048
|
+
ev.preventDefault();
|
|
21049
|
+
}
|
|
20905
21050
|
}
|
|
20906
21051
|
/*
|
|
20907
21052
|
* Triggered automatically by the content-editable between the keydown and key up
|
|
@@ -20910,9 +21055,6 @@ class Composer extends Component {
|
|
|
20910
21055
|
if (!this.shouldProcessInputEvents) {
|
|
20911
21056
|
return;
|
|
20912
21057
|
}
|
|
20913
|
-
if (ev.inputType === "insertFromPaste" && this.composerStore.editionMode === "inactive") {
|
|
20914
|
-
return;
|
|
20915
|
-
}
|
|
20916
21058
|
ev.stopPropagation();
|
|
20917
21059
|
let content;
|
|
20918
21060
|
if (this.composerStore.editionMode === "inactive") {
|
|
@@ -21565,132 +21707,8 @@ function getFunctionsFromAST(ast, functionNames) {
|
|
|
21565
21707
|
}
|
|
21566
21708
|
|
|
21567
21709
|
const PIVOT_FUNCTIONS = ["PIVOT.VALUE", "PIVOT.HEADER", "PIVOT"];
|
|
21568
|
-
const AGGREGATOR_NAMES = {
|
|
21569
|
-
count: _t("Count"),
|
|
21570
|
-
count_distinct: _t("Count Distinct"),
|
|
21571
|
-
bool_and: _t("Boolean And"),
|
|
21572
|
-
bool_or: _t("Boolean Or"),
|
|
21573
|
-
max: _t("Maximum"),
|
|
21574
|
-
min: _t("Minimum"),
|
|
21575
|
-
avg: _t("Average"),
|
|
21576
|
-
sum: _t("Sum"),
|
|
21577
|
-
};
|
|
21578
|
-
const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
|
|
21579
|
-
const AGGREGATORS_BY_FIELD_TYPE = {
|
|
21580
|
-
integer: NUMBER_CHAR_AGGREGATORS,
|
|
21581
|
-
char: NUMBER_CHAR_AGGREGATORS,
|
|
21582
|
-
//TODO Support for date and boolean
|
|
21583
|
-
};
|
|
21584
|
-
const AGGREGATORS = {};
|
|
21585
|
-
for (const type in AGGREGATORS_BY_FIELD_TYPE) {
|
|
21586
|
-
AGGREGATORS[type] = {};
|
|
21587
|
-
for (const aggregator of AGGREGATORS_BY_FIELD_TYPE[type]) {
|
|
21588
|
-
AGGREGATORS[type][aggregator] = AGGREGATOR_NAMES[aggregator];
|
|
21589
|
-
}
|
|
21590
|
-
}
|
|
21591
|
-
const AGGREGATORS_FN = {
|
|
21592
|
-
count: {
|
|
21593
|
-
fn: (args) => countAny([args]),
|
|
21594
|
-
format: () => "0",
|
|
21595
|
-
},
|
|
21596
|
-
count_distinct: {
|
|
21597
|
-
fn: (args) => countUnique([args]),
|
|
21598
|
-
format: () => "0",
|
|
21599
|
-
},
|
|
21600
|
-
bool_and: {
|
|
21601
|
-
fn: (args) => boolAnd([args]).result,
|
|
21602
|
-
format: () => undefined,
|
|
21603
|
-
},
|
|
21604
|
-
bool_or: {
|
|
21605
|
-
fn: (args) => boolOr([args]).result,
|
|
21606
|
-
format: () => undefined,
|
|
21607
|
-
},
|
|
21608
|
-
max: {
|
|
21609
|
-
fn: (args, locale) => max([args], locale),
|
|
21610
|
-
format: inferFormat,
|
|
21611
|
-
},
|
|
21612
|
-
min: {
|
|
21613
|
-
fn: (args, locale) => min([args], locale),
|
|
21614
|
-
format: inferFormat,
|
|
21615
|
-
},
|
|
21616
|
-
avg: {
|
|
21617
|
-
fn: (args, locale) => average([args], locale),
|
|
21618
|
-
format: inferFormat,
|
|
21619
|
-
},
|
|
21620
|
-
sum: {
|
|
21621
|
-
fn: (args, locale) => sum([args], locale),
|
|
21622
|
-
format: inferFormat,
|
|
21623
|
-
},
|
|
21624
|
-
};
|
|
21625
|
-
/**
|
|
21626
|
-
* Build a pivot formula expression
|
|
21627
|
-
*/
|
|
21628
|
-
function makePivotFormula(formula, args) {
|
|
21629
|
-
return `=${formula}(${args
|
|
21630
|
-
.map((arg) => {
|
|
21631
|
-
const stringIsNumber = typeof arg == "string" && !isNaN(Number(arg)) && Number(arg).toString() === arg;
|
|
21632
|
-
const convertToNumber = typeof arg == "number" || stringIsNumber;
|
|
21633
|
-
return convertToNumber ? `${arg}` : `"${arg.toString().replace(/"/g, '\\"')}"`;
|
|
21634
|
-
})
|
|
21635
|
-
.join(",")})`;
|
|
21636
|
-
}
|
|
21637
|
-
/**
|
|
21638
|
-
* Given an object of form {"1": {...}, "2": {...}, ...} get the maximum ID used
|
|
21639
|
-
* in this object
|
|
21640
|
-
* If the object has no keys, return 0
|
|
21641
|
-
*
|
|
21642
|
-
*/
|
|
21643
|
-
function getMaxObjectId(o) {
|
|
21644
|
-
const keys = Object.keys(o);
|
|
21645
|
-
if (!keys.length) {
|
|
21646
|
-
return 0;
|
|
21647
|
-
}
|
|
21648
|
-
const nums = keys.map((id) => parseInt(id, 10));
|
|
21649
|
-
const max = Math.max(...nums);
|
|
21650
|
-
return max;
|
|
21651
|
-
}
|
|
21652
|
-
/**
|
|
21653
|
-
* Get the first Pivot function description of the given formula.
|
|
21654
|
-
*/
|
|
21655
|
-
function getFirstPivotFunction(tokens) {
|
|
21656
|
-
return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS)[0];
|
|
21657
|
-
}
|
|
21658
|
-
/**
|
|
21659
|
-
* Parse a spreadsheet formula and detect the number of PIVOT functions that are
|
|
21660
|
-
* present in the given formula.
|
|
21661
|
-
*/
|
|
21662
|
-
function getNumberOfPivotFunctions(tokens) {
|
|
21663
|
-
return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS).length;
|
|
21664
|
-
}
|
|
21665
|
-
const ALL_PERIODS = {
|
|
21666
|
-
year: _t("Year"),
|
|
21667
|
-
quarter: _t("Quarter"),
|
|
21668
|
-
month: _t("Month"),
|
|
21669
|
-
week: _t("Week"),
|
|
21670
|
-
day: _t("Day"),
|
|
21671
|
-
year_number: _t("Year"),
|
|
21672
|
-
quarter_number: _t("Quarter"),
|
|
21673
|
-
month_number: _t("Month"),
|
|
21674
|
-
iso_week_number: _t("Week"),
|
|
21675
|
-
day_of_month: _t("Day of Month"),
|
|
21676
|
-
};
|
|
21677
|
-
const DATE_FIELDS = ["date", "datetime"];
|
|
21678
|
-
/**
|
|
21679
|
-
* Parse a dimension string into a pivot dimension definition.
|
|
21680
|
-
* e.g "create_date:month" => { name: "create_date", granularity: "month" }
|
|
21681
|
-
*/
|
|
21682
|
-
function parseDimension(dimension) {
|
|
21683
|
-
const [name, granularity] = dimension.split(":");
|
|
21684
|
-
if (granularity) {
|
|
21685
|
-
return { name, granularity };
|
|
21686
|
-
}
|
|
21687
|
-
return { name };
|
|
21688
|
-
}
|
|
21689
|
-
function isDateField(field) {
|
|
21690
|
-
return DATE_FIELDS.includes(field.type);
|
|
21691
|
-
}
|
|
21692
21710
|
/**
|
|
21693
|
-
* Create a proposal entry for the compose
|
|
21711
|
+
* Create a proposal entry for the compose autowcomplete
|
|
21694
21712
|
* to insert a field name string in a formula.
|
|
21695
21713
|
*/
|
|
21696
21714
|
function makeFieldProposal(field, granularity) {
|
|
@@ -21746,15 +21764,18 @@ function extractFormulaIdFromToken(tokenAtCursor) {
|
|
|
21746
21764
|
}
|
|
21747
21765
|
return idAst.value;
|
|
21748
21766
|
}
|
|
21749
|
-
|
|
21750
|
-
|
|
21751
|
-
|
|
21752
|
-
|
|
21753
|
-
|
|
21754
|
-
|
|
21755
|
-
|
|
21756
|
-
|
|
21757
|
-
|
|
21767
|
+
/**
|
|
21768
|
+
* Get the first Pivot function description of the given formula.
|
|
21769
|
+
*/
|
|
21770
|
+
function getFirstPivotFunction(tokens) {
|
|
21771
|
+
return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS)[0];
|
|
21772
|
+
}
|
|
21773
|
+
/**
|
|
21774
|
+
* Parse a spreadsheet formula and detect the number of PIVOT functions that are
|
|
21775
|
+
* present in the given formula.
|
|
21776
|
+
*/
|
|
21777
|
+
function getNumberOfPivotFunctions(tokens) {
|
|
21778
|
+
return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS).length;
|
|
21758
21779
|
}
|
|
21759
21780
|
|
|
21760
21781
|
autoCompleteProviders.add("pivot_ids", {
|
|
@@ -32782,7 +32803,7 @@ css /* scss */ `
|
|
|
32782
32803
|
vertical-align: middle;
|
|
32783
32804
|
}
|
|
32784
32805
|
.o_cf_radio_item {
|
|
32785
|
-
margin-right:
|
|
32806
|
+
margin-right: 30px;
|
|
32786
32807
|
}
|
|
32787
32808
|
.radio input:checked {
|
|
32788
32809
|
color: #e9ecef;
|
|
@@ -32802,6 +32823,9 @@ css /* scss */ `
|
|
|
32802
32823
|
}
|
|
32803
32824
|
margin-top: 10px;
|
|
32804
32825
|
display: flex;
|
|
32826
|
+
.form-check {
|
|
32827
|
+
padding-left: 1rem;
|
|
32828
|
+
}
|
|
32805
32829
|
}
|
|
32806
32830
|
.o-section-subtitle:first-child {
|
|
32807
32831
|
margin-top: 0px;
|
|
@@ -32810,7 +32834,7 @@ css /* scss */ `
|
|
|
32810
32834
|
font-size: 12px;
|
|
32811
32835
|
line-height: 1.5;
|
|
32812
32836
|
.o-selection-cf {
|
|
32813
|
-
margin-bottom:
|
|
32837
|
+
margin-bottom: 9px;
|
|
32814
32838
|
}
|
|
32815
32839
|
.o-cell-content {
|
|
32816
32840
|
font-size: 12px;
|
|
@@ -32851,7 +32875,7 @@ css /* scss */ `
|
|
|
32851
32875
|
width: 100%;
|
|
32852
32876
|
}
|
|
32853
32877
|
.o-threshold-value {
|
|
32854
|
-
margin-left:
|
|
32878
|
+
margin-left: 6px;
|
|
32855
32879
|
width: 20%;
|
|
32856
32880
|
min-width: 0px; // input overflows in Firefox otherwise
|
|
32857
32881
|
}
|
|
@@ -32880,8 +32904,8 @@ css /* scss */ `
|
|
|
32880
32904
|
justify-content: space-between;
|
|
32881
32905
|
.o-cf-icon {
|
|
32882
32906
|
display: inline;
|
|
32883
|
-
margin-left:
|
|
32884
|
-
margin-right:
|
|
32907
|
+
margin-left: 3px;
|
|
32908
|
+
margin-right: 3px;
|
|
32885
32909
|
}
|
|
32886
32910
|
svg {
|
|
32887
32911
|
vertical-align: baseline;
|
|
@@ -32904,7 +32928,7 @@ css /* scss */ `
|
|
|
32904
32928
|
}
|
|
32905
32929
|
table {
|
|
32906
32930
|
table-layout: fixed;
|
|
32907
|
-
margin-top:
|
|
32931
|
+
margin-top: 6px;
|
|
32908
32932
|
display: table;
|
|
32909
32933
|
text-align: left;
|
|
32910
32934
|
font-size: 12px;
|
|
@@ -32934,8 +32958,8 @@ css /* scss */ `
|
|
|
32934
32958
|
}
|
|
32935
32959
|
}
|
|
32936
32960
|
.o-cf-iconset-reverse {
|
|
32937
|
-
margin-bottom:
|
|
32938
|
-
margin-top:
|
|
32961
|
+
margin-bottom: 6px;
|
|
32962
|
+
margin-top: 6px;
|
|
32939
32963
|
.o-cf-label {
|
|
32940
32964
|
display: inline-block;
|
|
32941
32965
|
vertical-align: bottom;
|
|
@@ -34642,6 +34666,10 @@ css /* scss */ `
|
|
|
34642
34666
|
select > option {
|
|
34643
34667
|
background-color: white;
|
|
34644
34668
|
}
|
|
34669
|
+
|
|
34670
|
+
.pivot-dim-operator-label {
|
|
34671
|
+
min-width: 120px;
|
|
34672
|
+
}
|
|
34645
34673
|
}
|
|
34646
34674
|
`;
|
|
34647
34675
|
class PivotDimension extends Component {
|
|
@@ -34882,7 +34910,7 @@ class PivotRuntimeDefinition {
|
|
|
34882
34910
|
getMeasure(name) {
|
|
34883
34911
|
const measure = this.measures.find((measure) => measure.name === name);
|
|
34884
34912
|
if (!measure) {
|
|
34885
|
-
throw new EvaluationError(_t("Field %s
|
|
34913
|
+
throw new EvaluationError(_t("Field %s is not a measure", name));
|
|
34886
34914
|
}
|
|
34887
34915
|
return measure;
|
|
34888
34916
|
}
|
|
@@ -35008,10 +35036,9 @@ class SpreadsheetPivotTable {
|
|
|
35008
35036
|
columns;
|
|
35009
35037
|
rows;
|
|
35010
35038
|
measures;
|
|
35011
|
-
rowTitle;
|
|
35012
35039
|
maxIndent;
|
|
35013
35040
|
pivotCells = {};
|
|
35014
|
-
constructor(columns, rows, measures
|
|
35041
|
+
constructor(columns, rows, measures) {
|
|
35015
35042
|
this.columns = columns.map((row) => {
|
|
35016
35043
|
// offset in the pivot table
|
|
35017
35044
|
// starts at 1 because the first column is the row title
|
|
@@ -35024,7 +35051,6 @@ class SpreadsheetPivotTable {
|
|
|
35024
35051
|
});
|
|
35025
35052
|
this.rows = rows;
|
|
35026
35053
|
this.measures = measures;
|
|
35027
|
-
this.rowTitle = rowTitle;
|
|
35028
35054
|
this.maxIndent = Math.max(...this.rows.map((row) => row.indent));
|
|
35029
35055
|
}
|
|
35030
35056
|
/**
|
|
@@ -35066,26 +35092,23 @@ class SpreadsheetPivotTable {
|
|
|
35066
35092
|
}
|
|
35067
35093
|
getPivotCell(col, row, includeTotal = true) {
|
|
35068
35094
|
const colHeadersHeight = this.columns.length;
|
|
35069
|
-
if (
|
|
35070
|
-
return { content: this.rowTitle, isHeader: true };
|
|
35071
|
-
}
|
|
35072
|
-
else if (row <= colHeadersHeight - 1) {
|
|
35095
|
+
if (row <= colHeadersHeight - 1) {
|
|
35073
35096
|
const domain = this.getColHeaderDomain(col, row);
|
|
35074
|
-
return {
|
|
35097
|
+
return domain ? { type: "HEADER", domain } : { type: "EMPTY" };
|
|
35075
35098
|
}
|
|
35076
35099
|
else if (col === 0) {
|
|
35077
35100
|
const rowIndex = row - colHeadersHeight;
|
|
35078
35101
|
const domain = this.getRowDomain(rowIndex);
|
|
35079
|
-
return {
|
|
35102
|
+
return { type: "HEADER", domain };
|
|
35080
35103
|
}
|
|
35081
35104
|
else {
|
|
35082
35105
|
const rowIndex = row - colHeadersHeight;
|
|
35083
35106
|
if (!includeTotal && this.isTotalRow(rowIndex)) {
|
|
35084
|
-
return {
|
|
35107
|
+
return { type: "EMPTY" };
|
|
35085
35108
|
}
|
|
35086
35109
|
const domain = [...this.getRowDomain(rowIndex), ...this.getColDomain(col)];
|
|
35087
35110
|
const measure = this.getColMeasure(col);
|
|
35088
|
-
return {
|
|
35111
|
+
return { type: "VALUE", domain, measure };
|
|
35089
35112
|
}
|
|
35090
35113
|
}
|
|
35091
35114
|
getColHeaderDomain(col, row) {
|
|
@@ -35098,24 +35121,32 @@ class SpreadsheetPivotTable {
|
|
|
35098
35121
|
return undefined;
|
|
35099
35122
|
}
|
|
35100
35123
|
for (let i = 0; i < pivotCol.fields.length; i++) {
|
|
35101
|
-
domain.push(
|
|
35102
|
-
|
|
35124
|
+
domain.push({
|
|
35125
|
+
field: pivotCol.fields[i],
|
|
35126
|
+
value: pivotCol.values[i],
|
|
35127
|
+
});
|
|
35103
35128
|
}
|
|
35104
35129
|
return domain;
|
|
35105
35130
|
}
|
|
35106
35131
|
getColDomain(col) {
|
|
35107
35132
|
const domain = this.getColHeaderDomain(col, this.columns.length - 1);
|
|
35108
|
-
return domain ? domain.slice(0, -
|
|
35133
|
+
return domain ? domain.slice(0, -1) : []; // slice: remove measure and value
|
|
35109
35134
|
}
|
|
35110
35135
|
getColMeasure(col) {
|
|
35111
35136
|
const domain = this.getColHeaderDomain(col, this.columns.length - 1);
|
|
35112
|
-
|
|
35137
|
+
const measure = domain?.at(-1)?.value;
|
|
35138
|
+
if (measure === undefined) {
|
|
35139
|
+
throw new Error("Measure isd missing");
|
|
35140
|
+
}
|
|
35141
|
+
return measure.toString();
|
|
35113
35142
|
}
|
|
35114
35143
|
getRowDomain(row) {
|
|
35115
35144
|
const domain = [];
|
|
35116
35145
|
for (let i = 0; i < this.rows[row].fields.length; i++) {
|
|
35117
|
-
domain.push(
|
|
35118
|
-
|
|
35146
|
+
domain.push({
|
|
35147
|
+
field: this.rows[row].fields[i],
|
|
35148
|
+
value: this.rows[row].values[i],
|
|
35149
|
+
});
|
|
35119
35150
|
}
|
|
35120
35151
|
return domain;
|
|
35121
35152
|
}
|
|
@@ -35124,7 +35155,6 @@ class SpreadsheetPivotTable {
|
|
|
35124
35155
|
cols: this.columns,
|
|
35125
35156
|
rows: this.rows,
|
|
35126
35157
|
measures: this.measures,
|
|
35127
|
-
rowTitle: this.rowTitle,
|
|
35128
35158
|
};
|
|
35129
35159
|
}
|
|
35130
35160
|
}
|
|
@@ -35144,8 +35174,7 @@ function dataEntriesToSpreadsheetPivotTable(dataEntries, definition) {
|
|
|
35144
35174
|
indent: 0,
|
|
35145
35175
|
});
|
|
35146
35176
|
const measureNames = definition.measures.map((m) => m.name);
|
|
35147
|
-
|
|
35148
|
-
return new SpreadsheetPivotTable(cols, rows, measureNames, rowTitle);
|
|
35177
|
+
return new SpreadsheetPivotTable(cols, rows, measureNames);
|
|
35149
35178
|
}
|
|
35150
35179
|
// -----------------------------------------------------------------------------
|
|
35151
35180
|
// ROWS
|
|
@@ -35488,7 +35517,10 @@ class SpreadsheetPivot {
|
|
|
35488
35517
|
}
|
|
35489
35518
|
get definition() {
|
|
35490
35519
|
if (!this._definition) {
|
|
35491
|
-
|
|
35520
|
+
this.init();
|
|
35521
|
+
}
|
|
35522
|
+
if (!this._definition) {
|
|
35523
|
+
throw new Error("Pivot definition should be defined at this point.");
|
|
35492
35524
|
}
|
|
35493
35525
|
return this._definition;
|
|
35494
35526
|
}
|
|
@@ -35537,15 +35569,16 @@ class SpreadsheetPivot {
|
|
|
35537
35569
|
getMeasure(name) {
|
|
35538
35570
|
return this.definition.getMeasure(name);
|
|
35539
35571
|
}
|
|
35540
|
-
|
|
35541
|
-
|
|
35572
|
+
getPivotMeasureValue(name) {
|
|
35573
|
+
return {
|
|
35574
|
+
value: this.getMeasure(name).displayName,
|
|
35575
|
+
};
|
|
35576
|
+
}
|
|
35577
|
+
getPivotHeaderValueAndFormat(domain) {
|
|
35542
35578
|
const lastNode = domain.at(-1);
|
|
35543
35579
|
if (!lastNode) {
|
|
35544
35580
|
return { value: _t("Total") };
|
|
35545
35581
|
}
|
|
35546
|
-
if (lastNode.field === "measure") {
|
|
35547
|
-
return { value: this.getMeasure(lastNode.value).displayName };
|
|
35548
|
-
}
|
|
35549
35582
|
const dimension = this.getDimension(lastNode.field);
|
|
35550
35583
|
const cells = this.filterDataEntriesFromDomain(this.dataEntries, domain);
|
|
35551
35584
|
const finalCell = cells[0]?.[dimension.nameWithGranularity];
|
|
@@ -35573,8 +35606,7 @@ class SpreadsheetPivot {
|
|
|
35573
35606
|
format: finalCell.format,
|
|
35574
35607
|
};
|
|
35575
35608
|
}
|
|
35576
|
-
getPivotCellValueAndFormat(measure,
|
|
35577
|
-
const domain = toDomainArgs(domainStr);
|
|
35609
|
+
getPivotCellValueAndFormat(measure, domain) {
|
|
35578
35610
|
const dataEntries = this.filterDataEntriesFromDomain(this.dataEntries, domain);
|
|
35579
35611
|
if (dataEntries.length === 0) {
|
|
35580
35612
|
return { value: "" };
|
|
@@ -35751,7 +35783,14 @@ pivotRegistry.add("SPREADSHEET", {
|
|
|
35751
35783
|
|
|
35752
35784
|
class PivotSidePanelStore extends SpreadsheetStore {
|
|
35753
35785
|
pivotId;
|
|
35754
|
-
mutators = [
|
|
35786
|
+
mutators = [
|
|
35787
|
+
"reset",
|
|
35788
|
+
"deferUpdates",
|
|
35789
|
+
"applyUpdate",
|
|
35790
|
+
"discardPendingUpdate",
|
|
35791
|
+
"renamePivot",
|
|
35792
|
+
"update",
|
|
35793
|
+
];
|
|
35755
35794
|
updatesAreDeferred = true;
|
|
35756
35795
|
draft = null;
|
|
35757
35796
|
constructor(get, pivotId) {
|
|
@@ -35968,7 +36007,6 @@ class PivotSpreadsheetSidePanel extends Component {
|
|
|
35968
36007
|
state;
|
|
35969
36008
|
setup() {
|
|
35970
36009
|
this.store = useLocalStore(PivotSidePanelStore, this.props.pivotId);
|
|
35971
|
-
this.pivot.init();
|
|
35972
36010
|
this.state = useState({
|
|
35973
36011
|
range: undefined,
|
|
35974
36012
|
rangeHasChanged: false,
|
|
@@ -36845,7 +36883,7 @@ css /* scss */ `
|
|
|
36845
36883
|
}
|
|
36846
36884
|
|
|
36847
36885
|
.o-table-style-list-item {
|
|
36848
|
-
padding: 3px;
|
|
36886
|
+
padding: 3px 2px;
|
|
36849
36887
|
margin: 2px 1px;
|
|
36850
36888
|
|
|
36851
36889
|
.o-table-style-picker-preview {
|
|
@@ -36866,10 +36904,10 @@ class TableStylePicker extends Component {
|
|
|
36866
36904
|
const styles = Object.keys(allStyles).filter((key) => allStyles[key].category === selectedStyleCategory);
|
|
36867
36905
|
const selectedStyleIndex = styles.indexOf(this.props.table.config.styleId);
|
|
36868
36906
|
if (selectedStyleIndex === -1) {
|
|
36869
|
-
return
|
|
36907
|
+
return selectedStyleIndex;
|
|
36870
36908
|
}
|
|
36871
36909
|
const index = Math.floor(selectedStyleIndex / 4) * 4;
|
|
36872
|
-
return styles.slice(index
|
|
36910
|
+
return styles.slice(index);
|
|
36873
36911
|
}
|
|
36874
36912
|
onStylePicked(styleId) {
|
|
36875
36913
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
@@ -37909,10 +37947,7 @@ class GridComposer extends Component {
|
|
|
37909
37947
|
}
|
|
37910
37948
|
get containerStyle() {
|
|
37911
37949
|
if (this.composerStore.editionMode === "inactive") {
|
|
37912
|
-
return `
|
|
37913
|
-
position: absolute;
|
|
37914
|
-
z-index: -1000;
|
|
37915
|
-
`;
|
|
37950
|
+
return `z-index: -1000;`;
|
|
37916
37951
|
}
|
|
37917
37952
|
const isFormula = this.composerStore.currentContent.startsWith("=");
|
|
37918
37953
|
const cell = this.env.model.getters.getActiveCell();
|
|
@@ -38788,6 +38823,7 @@ class FilterIcon extends Component {
|
|
|
38788
38823
|
|
|
38789
38824
|
class FilterIconsOverlay extends Component {
|
|
38790
38825
|
static template = "o-spreadsheet-FilterIconsOverlay";
|
|
38826
|
+
static props = {};
|
|
38791
38827
|
static components = {
|
|
38792
38828
|
GridCellIcon,
|
|
38793
38829
|
FilterIcon,
|
|
@@ -40755,10 +40791,13 @@ class VerticalScrollBar extends Component {
|
|
|
40755
40791
|
}
|
|
40756
40792
|
}
|
|
40757
40793
|
|
|
40794
|
+
const DEFAULT_SIDE_PANEL_SIZE = 350;
|
|
40795
|
+
const MIN_SHEET_VIEW_WIDTH = 150;
|
|
40758
40796
|
class SidePanelStore extends SpreadsheetStore {
|
|
40759
|
-
mutators = ["open", "toggle", "close"];
|
|
40797
|
+
mutators = ["open", "toggle", "close", "changePanelSize", "resetPanelSize"];
|
|
40760
40798
|
initialPanelProps = {};
|
|
40761
40799
|
componentTag = "";
|
|
40800
|
+
panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
40762
40801
|
get isOpen() {
|
|
40763
40802
|
if (!this.componentTag) {
|
|
40764
40803
|
return false;
|
|
@@ -40803,6 +40842,20 @@ class SidePanelStore extends SpreadsheetStore {
|
|
|
40803
40842
|
this.initialPanelProps = {};
|
|
40804
40843
|
this.componentTag = "";
|
|
40805
40844
|
}
|
|
40845
|
+
changePanelSize(size, spreadsheetElWidth) {
|
|
40846
|
+
if (size < DEFAULT_SIDE_PANEL_SIZE) {
|
|
40847
|
+
this.panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
40848
|
+
}
|
|
40849
|
+
else if (size > spreadsheetElWidth - MIN_SHEET_VIEW_WIDTH) {
|
|
40850
|
+
this.panelSize = Math.max(spreadsheetElWidth - MIN_SHEET_VIEW_WIDTH, DEFAULT_SIDE_PANEL_SIZE);
|
|
40851
|
+
}
|
|
40852
|
+
else {
|
|
40853
|
+
this.panelSize = size;
|
|
40854
|
+
}
|
|
40855
|
+
}
|
|
40856
|
+
resetPanelSize() {
|
|
40857
|
+
this.panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
40858
|
+
}
|
|
40806
40859
|
computeState(componentTag, panelProps) {
|
|
40807
40860
|
const customComputeState = sidePanelRegistry.get(componentTag).computeState;
|
|
40808
40861
|
if (!customComputeState) {
|
|
@@ -41923,7 +41976,7 @@ class XLSXImportWarningManager {
|
|
|
41923
41976
|
}
|
|
41924
41977
|
}
|
|
41925
41978
|
|
|
41926
|
-
const SUPPORTED_BORDER_STYLES = ["thin"];
|
|
41979
|
+
const SUPPORTED_BORDER_STYLES = ["thin", "medium", "thick", "dashed", "dotted"];
|
|
41927
41980
|
const SUPPORTED_HORIZONTAL_ALIGNMENTS = [
|
|
41928
41981
|
"general",
|
|
41929
41982
|
"left",
|
|
@@ -51062,8 +51115,8 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
51062
51115
|
case "INSERT_PIVOT": {
|
|
51063
51116
|
const { sheetId, col, row, pivotId, table } = cmd;
|
|
51064
51117
|
const position = { sheetId, col, row };
|
|
51065
|
-
const { cols, rows, measures
|
|
51066
|
-
const spTable = new SpreadsheetPivotTable(cols, rows, measures
|
|
51118
|
+
const { cols, rows, measures } = table;
|
|
51119
|
+
const spTable = new SpreadsheetPivotTable(cols, rows, measures);
|
|
51067
51120
|
const formulaId = this.getPivotFormulaId(pivotId);
|
|
51068
51121
|
this.insertPivot(position, formulaId, spTable);
|
|
51069
51122
|
break;
|
|
@@ -51192,13 +51245,18 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
51192
51245
|
}
|
|
51193
51246
|
}
|
|
51194
51247
|
addPivotFormula(position, formulaId, pivotCell) {
|
|
51195
|
-
|
|
51196
|
-
|
|
51197
|
-
|
|
51198
|
-
|
|
51248
|
+
let content = undefined;
|
|
51249
|
+
switch (pivotCell.type) {
|
|
51250
|
+
case "HEADER":
|
|
51251
|
+
content = makePivotFormula("PIVOT.HEADER", [formulaId, ...flatPivotDomain(pivotCell.domain)].filter(isDefined));
|
|
51252
|
+
break;
|
|
51253
|
+
case "VALUE":
|
|
51254
|
+
content = makePivotFormula("PIVOT.VALUE", [formulaId, pivotCell.measure, ...flatPivotDomain(pivotCell.domain)].filter(isDefined));
|
|
51255
|
+
break;
|
|
51256
|
+
}
|
|
51199
51257
|
this.dispatch("UPDATE_CELL", {
|
|
51200
51258
|
...position,
|
|
51201
|
-
content
|
|
51259
|
+
content,
|
|
51202
51260
|
});
|
|
51203
51261
|
}
|
|
51204
51262
|
getPivotCore(pivotId) {
|
|
@@ -51217,7 +51275,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
51217
51275
|
import(data) {
|
|
51218
51276
|
if (data.pivots) {
|
|
51219
51277
|
for (const [id, pivot] of Object.entries(data.pivots)) {
|
|
51220
|
-
this.addPivot(id,
|
|
51278
|
+
this.addPivot(id, pivot, pivot.formulaId);
|
|
51221
51279
|
}
|
|
51222
51280
|
}
|
|
51223
51281
|
this.history.update("nextFormulaId", data.pivotNextId || getMaxObjectId(this.pivots) + 1);
|
|
@@ -54558,15 +54616,18 @@ class PivotUIPlugin extends UIPlugin {
|
|
|
54558
54616
|
const pivotCol = position.col - mainPosition.col;
|
|
54559
54617
|
const pivotRow = position.row - mainPosition.row;
|
|
54560
54618
|
const pivotCell = pivotCells[pivotCol][pivotRow];
|
|
54619
|
+
if (pivotCell.type === "EMPTY") {
|
|
54620
|
+
return undefined;
|
|
54621
|
+
}
|
|
54561
54622
|
const domain = pivotCell.domain;
|
|
54562
|
-
if (domain
|
|
54563
|
-
return domain.slice(0, -
|
|
54623
|
+
if (domain.at(-1)?.field === "measure") {
|
|
54624
|
+
return domain.slice(0, -1);
|
|
54564
54625
|
}
|
|
54565
54626
|
return domain;
|
|
54566
54627
|
}
|
|
54567
|
-
const domain = args.slice(functionName === "PIVOT.VALUE" ? 2 : 1);
|
|
54568
|
-
if (domain.at(-
|
|
54569
|
-
return domain.slice(0, -
|
|
54628
|
+
const domain = toPivotDomain(args.slice(functionName === "PIVOT.VALUE" ? 2 : 1).map((x) => `${x}`));
|
|
54629
|
+
if (domain.at(-1)?.field === "measure") {
|
|
54630
|
+
return domain.slice(0, -1);
|
|
54570
54631
|
}
|
|
54571
54632
|
return domain;
|
|
54572
54633
|
}
|
|
@@ -54581,9 +54642,9 @@ class PivotUIPlugin extends UIPlugin {
|
|
|
54581
54642
|
* a pivot function are valid according to the pivot definition.
|
|
54582
54643
|
* e.g. =PIVOT.VALUE(1,"revenue","country_id",...,"create_date:month",...,"source_id",...)
|
|
54583
54644
|
*/
|
|
54584
|
-
areDomainArgsFieldsValid(pivotId,
|
|
54585
|
-
const dimensions =
|
|
54586
|
-
.
|
|
54645
|
+
areDomainArgsFieldsValid(pivotId, domain) {
|
|
54646
|
+
const dimensions = domain
|
|
54647
|
+
.map((node) => node.field)
|
|
54587
54648
|
.map((name) => (name.startsWith("#") ? name.slice(1) : name));
|
|
54588
54649
|
let argIndex = 0;
|
|
54589
54650
|
let definitionIndex = 0;
|
|
@@ -61597,6 +61658,10 @@ css /* scss */ `
|
|
|
61597
61658
|
}
|
|
61598
61659
|
}
|
|
61599
61660
|
}
|
|
61661
|
+
.o-sidePanelBody-container {
|
|
61662
|
+
/* This overwrites the min-height: auto; of flex. Without this, a flex div cannot be smaller than its children */
|
|
61663
|
+
min-height: 0;
|
|
61664
|
+
}
|
|
61600
61665
|
.o-sidePanelBody {
|
|
61601
61666
|
overflow: auto;
|
|
61602
61667
|
width: 100%;
|
|
@@ -61675,24 +61740,6 @@ css /* scss */ `
|
|
|
61675
61740
|
text-align: left;
|
|
61676
61741
|
}
|
|
61677
61742
|
|
|
61678
|
-
.o-inflection {
|
|
61679
|
-
table {
|
|
61680
|
-
table-layout: fixed;
|
|
61681
|
-
margin-top: 2%;
|
|
61682
|
-
display: table;
|
|
61683
|
-
text-align: left;
|
|
61684
|
-
font-size: 12px;
|
|
61685
|
-
line-height: 18px;
|
|
61686
|
-
width: 100%;
|
|
61687
|
-
}
|
|
61688
|
-
input,
|
|
61689
|
-
select {
|
|
61690
|
-
width: 100%;
|
|
61691
|
-
height: 100%;
|
|
61692
|
-
box-sizing: border-box;
|
|
61693
|
-
}
|
|
61694
|
-
}
|
|
61695
|
-
|
|
61696
61743
|
.o-sidePanel-tools {
|
|
61697
61744
|
color: #333;
|
|
61698
61745
|
font-size: 13px;
|
|
@@ -61711,12 +61758,25 @@ css /* scss */ `
|
|
|
61711
61758
|
}
|
|
61712
61759
|
}
|
|
61713
61760
|
}
|
|
61761
|
+
|
|
61762
|
+
.o-sidePanel-handle-container {
|
|
61763
|
+
width: 8px;
|
|
61764
|
+
}
|
|
61765
|
+
.o-sidePanel-handle {
|
|
61766
|
+
cursor: col-resize;
|
|
61767
|
+
color: #a9a9a9;
|
|
61768
|
+
.o-icon {
|
|
61769
|
+
height: 25px;
|
|
61770
|
+
margin-left: -5px;
|
|
61771
|
+
}
|
|
61772
|
+
}
|
|
61714
61773
|
}
|
|
61715
61774
|
`;
|
|
61716
61775
|
class SidePanel extends Component {
|
|
61717
61776
|
static template = "o-spreadsheet-SidePanel";
|
|
61718
61777
|
static props = {};
|
|
61719
61778
|
sidePanelStore;
|
|
61779
|
+
spreadsheetRect = useSpreadsheetRect();
|
|
61720
61780
|
setup() {
|
|
61721
61781
|
this.sidePanelStore = useStore(SidePanelStore);
|
|
61722
61782
|
useEffect((isOpen) => {
|
|
@@ -61737,6 +61797,20 @@ class SidePanel extends Component {
|
|
|
61737
61797
|
? panel.title(this.env, this.sidePanelStore.panelProps)
|
|
61738
61798
|
: panel.title;
|
|
61739
61799
|
}
|
|
61800
|
+
startHandleDrag(ev) {
|
|
61801
|
+
const startingCursor = document.body.style.cursor;
|
|
61802
|
+
const startSize = this.sidePanelStore.panelSize;
|
|
61803
|
+
const startPosition = ev.clientX;
|
|
61804
|
+
const onMouseMove = (ev) => {
|
|
61805
|
+
document.body.style.cursor = "col-resize";
|
|
61806
|
+
const newSize = startSize + startPosition - ev.clientX;
|
|
61807
|
+
this.sidePanelStore.changePanelSize(newSize, this.spreadsheetRect.width);
|
|
61808
|
+
};
|
|
61809
|
+
const cleanUp = () => {
|
|
61810
|
+
document.body.style.cursor = startingCursor;
|
|
61811
|
+
};
|
|
61812
|
+
startDnd(onMouseMove, cleanUp);
|
|
61813
|
+
}
|
|
61740
61814
|
}
|
|
61741
61815
|
|
|
61742
61816
|
css /* scss */ `
|
|
@@ -62520,7 +62594,6 @@ css /* scss */ `
|
|
|
62520
62594
|
.o-spreadsheet {
|
|
62521
62595
|
position: relative;
|
|
62522
62596
|
display: grid;
|
|
62523
|
-
grid-template-columns: auto 350px;
|
|
62524
62597
|
color: #333;
|
|
62525
62598
|
font-size: 14px;
|
|
62526
62599
|
|
|
@@ -62718,6 +62791,7 @@ class Spreadsheet extends Component {
|
|
|
62718
62791
|
};
|
|
62719
62792
|
sidePanel;
|
|
62720
62793
|
spreadsheetRef = useRef("spreadsheet");
|
|
62794
|
+
spreadsheetRect = useSpreadsheetRect();
|
|
62721
62795
|
_focusGrid;
|
|
62722
62796
|
keyDownMapping;
|
|
62723
62797
|
isViewportTooSmall = false;
|
|
@@ -62727,10 +62801,15 @@ class Spreadsheet extends Component {
|
|
|
62727
62801
|
return this.props.model;
|
|
62728
62802
|
}
|
|
62729
62803
|
getStyle() {
|
|
62804
|
+
const properties = {};
|
|
62730
62805
|
if (this.env.isDashboard()) {
|
|
62731
|
-
|
|
62806
|
+
properties["grid-template-rows"] = `auto`;
|
|
62732
62807
|
}
|
|
62733
|
-
|
|
62808
|
+
else {
|
|
62809
|
+
properties["grid-template-rows"] = `${TOPBAR_HEIGHT}px auto ${BOTTOMBAR_HEIGHT + 1}px`;
|
|
62810
|
+
}
|
|
62811
|
+
properties["grid-template-columns"] = `auto ${this.sidePanel.panelSize}px`;
|
|
62812
|
+
return cssPropertiesToCss(properties);
|
|
62734
62813
|
}
|
|
62735
62814
|
setup() {
|
|
62736
62815
|
const stores = useStoreProvider();
|
|
@@ -62780,7 +62859,9 @@ class Spreadsheet extends Component {
|
|
|
62780
62859
|
if (nextProps.model !== this.props.model) {
|
|
62781
62860
|
throw new Error("Changing the props model is not supported at the moment.");
|
|
62782
62861
|
}
|
|
62783
|
-
if (
|
|
62862
|
+
if (nextProps.notifyUser !== this.props.notifyUser ||
|
|
62863
|
+
nextProps.askConfirmation !== this.props.askConfirmation ||
|
|
62864
|
+
nextProps.raiseError !== this.props.raiseError) {
|
|
62784
62865
|
this.notificationStore.updateNotificationCallbacks({ ...nextProps });
|
|
62785
62866
|
}
|
|
62786
62867
|
});
|
|
@@ -62788,14 +62869,19 @@ class Spreadsheet extends Component {
|
|
|
62788
62869
|
onMounted(() => {
|
|
62789
62870
|
this.checkViewportSize();
|
|
62790
62871
|
stores.on("store-updated", this, render);
|
|
62872
|
+
resizeObserver.observe(this.spreadsheetRef.el);
|
|
62791
62873
|
});
|
|
62792
62874
|
onWillUnmount(() => {
|
|
62793
62875
|
this.unbindModelEvents();
|
|
62794
62876
|
stores.off("store-updated", this);
|
|
62877
|
+
resizeObserver.disconnect();
|
|
62795
62878
|
});
|
|
62796
62879
|
onPatched(() => {
|
|
62797
62880
|
this.checkViewportSize();
|
|
62798
62881
|
});
|
|
62882
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
62883
|
+
this.sidePanel.changePanelSize(this.sidePanel.panelSize, this.spreadsheetRect.width);
|
|
62884
|
+
});
|
|
62799
62885
|
}
|
|
62800
62886
|
bindModelEvents() {
|
|
62801
62887
|
this.model.on("update", this, () => this.render(true));
|
|
@@ -66850,6 +66936,8 @@ const helpers = {
|
|
|
66850
66936
|
insertTokenAfterLeftParenthesis,
|
|
66851
66937
|
mergeContiguousZones,
|
|
66852
66938
|
getPivotHighlights,
|
|
66939
|
+
toPivotDomain,
|
|
66940
|
+
flatPivotDomain,
|
|
66853
66941
|
pivotTimeAdapter,
|
|
66854
66942
|
UNDO_REDO_PIVOT_COMMANDS,
|
|
66855
66943
|
};
|
|
@@ -66934,6 +67022,6 @@ const constants = {
|
|
|
66934
67022
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
66935
67023
|
|
|
66936
67024
|
|
|
66937
|
-
__info__.version = "17.4.0-alpha.
|
|
66938
|
-
__info__.date = "2024-
|
|
66939
|
-
__info__.hash = "
|
|
67025
|
+
__info__.version = "17.4.0-alpha.2";
|
|
67026
|
+
__info__.date = "2024-06-06T13:31:21.327Z";
|
|
67027
|
+
__info__.hash = "e07794d";
|