@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
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -309,7 +309,10 @@ function deepCopy(obj) {
|
|
|
309
309
|
* Check if the object is a plain old javascript object.
|
|
310
310
|
*/
|
|
311
311
|
function isPlainObject(obj) {
|
|
312
|
-
return typeof obj === "object" &&
|
|
312
|
+
return (typeof obj === "object" &&
|
|
313
|
+
obj !== null &&
|
|
314
|
+
// obj.constructor can be undefined when there's no prototype (`Object.create(null, {})`)
|
|
315
|
+
(obj?.constructor === Object || obj?.constructor === undefined));
|
|
313
316
|
}
|
|
314
317
|
/**
|
|
315
318
|
* Sanitize the name of a sheet, by eventually removing quotes
|
|
@@ -18375,6 +18378,131 @@ var logical = /*#__PURE__*/Object.freeze({
|
|
|
18375
18378
|
const supportedPivotExplodedFormulaRegistry = new Registry();
|
|
18376
18379
|
supportedPivotExplodedFormulaRegistry.add("SPREADSHEET", false);
|
|
18377
18380
|
|
|
18381
|
+
const AGGREGATOR_NAMES = {
|
|
18382
|
+
count: _t("Count"),
|
|
18383
|
+
count_distinct: _t("Count Distinct"),
|
|
18384
|
+
bool_and: _t("Boolean And"),
|
|
18385
|
+
bool_or: _t("Boolean Or"),
|
|
18386
|
+
max: _t("Maximum"),
|
|
18387
|
+
min: _t("Minimum"),
|
|
18388
|
+
avg: _t("Average"),
|
|
18389
|
+
sum: _t("Sum"),
|
|
18390
|
+
};
|
|
18391
|
+
const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "count"];
|
|
18392
|
+
const AGGREGATORS_BY_FIELD_TYPE = {
|
|
18393
|
+
integer: NUMBER_CHAR_AGGREGATORS,
|
|
18394
|
+
char: NUMBER_CHAR_AGGREGATORS,
|
|
18395
|
+
//TODO Support for date and boolean
|
|
18396
|
+
};
|
|
18397
|
+
const AGGREGATORS = {};
|
|
18398
|
+
for (const type in AGGREGATORS_BY_FIELD_TYPE) {
|
|
18399
|
+
AGGREGATORS[type] = {};
|
|
18400
|
+
for (const aggregator of AGGREGATORS_BY_FIELD_TYPE[type]) {
|
|
18401
|
+
AGGREGATORS[type][aggregator] = AGGREGATOR_NAMES[aggregator];
|
|
18402
|
+
}
|
|
18403
|
+
}
|
|
18404
|
+
const AGGREGATORS_FN = {
|
|
18405
|
+
count: {
|
|
18406
|
+
fn: (args) => countAny([args]),
|
|
18407
|
+
format: () => "0",
|
|
18408
|
+
},
|
|
18409
|
+
count_distinct: {
|
|
18410
|
+
fn: (args) => countUnique([args]),
|
|
18411
|
+
format: () => "0",
|
|
18412
|
+
},
|
|
18413
|
+
bool_and: {
|
|
18414
|
+
fn: (args) => boolAnd([args]).result,
|
|
18415
|
+
format: () => undefined,
|
|
18416
|
+
},
|
|
18417
|
+
bool_or: {
|
|
18418
|
+
fn: (args) => boolOr([args]).result,
|
|
18419
|
+
format: () => undefined,
|
|
18420
|
+
},
|
|
18421
|
+
max: {
|
|
18422
|
+
fn: (args, locale) => max([args], locale),
|
|
18423
|
+
format: inferFormat,
|
|
18424
|
+
},
|
|
18425
|
+
min: {
|
|
18426
|
+
fn: (args, locale) => min([args], locale),
|
|
18427
|
+
format: inferFormat,
|
|
18428
|
+
},
|
|
18429
|
+
avg: {
|
|
18430
|
+
fn: (args, locale) => average([args], locale),
|
|
18431
|
+
format: inferFormat,
|
|
18432
|
+
},
|
|
18433
|
+
sum: {
|
|
18434
|
+
fn: (args, locale) => sum([args], locale),
|
|
18435
|
+
format: inferFormat,
|
|
18436
|
+
},
|
|
18437
|
+
};
|
|
18438
|
+
/**
|
|
18439
|
+
* Build a pivot formula expression
|
|
18440
|
+
*/
|
|
18441
|
+
function makePivotFormula(formula, args) {
|
|
18442
|
+
return `=${formula}(${args
|
|
18443
|
+
.map((arg) => {
|
|
18444
|
+
const stringIsNumber = typeof arg == "string" && !isNaN(Number(arg)) && Number(arg).toString() === arg;
|
|
18445
|
+
const convertToNumber = typeof arg == "number" || stringIsNumber;
|
|
18446
|
+
return convertToNumber ? `${arg}` : `"${arg.toString().replace(/"/g, '\\"')}"`;
|
|
18447
|
+
})
|
|
18448
|
+
.join(",")})`;
|
|
18449
|
+
}
|
|
18450
|
+
/**
|
|
18451
|
+
* Given an object of form {"1": {...}, "2": {...}, ...} get the maximum ID used
|
|
18452
|
+
* in this object
|
|
18453
|
+
* If the object has no keys, return 0
|
|
18454
|
+
*
|
|
18455
|
+
*/
|
|
18456
|
+
function getMaxObjectId(o) {
|
|
18457
|
+
const keys = Object.keys(o);
|
|
18458
|
+
if (!keys.length) {
|
|
18459
|
+
return 0;
|
|
18460
|
+
}
|
|
18461
|
+
const nums = keys.map((id) => parseInt(id, 10));
|
|
18462
|
+
const max = Math.max(...nums);
|
|
18463
|
+
return max;
|
|
18464
|
+
}
|
|
18465
|
+
const ALL_PERIODS = {
|
|
18466
|
+
year: _t("Year"),
|
|
18467
|
+
quarter: _t("Quarter"),
|
|
18468
|
+
month: _t("Month"),
|
|
18469
|
+
week: _t("Week"),
|
|
18470
|
+
day: _t("Day"),
|
|
18471
|
+
year_number: _t("Year"),
|
|
18472
|
+
quarter_number: _t("Quarter"),
|
|
18473
|
+
month_number: _t("Month"),
|
|
18474
|
+
iso_week_number: _t("Week"),
|
|
18475
|
+
day_of_month: _t("Day of Month"),
|
|
18476
|
+
};
|
|
18477
|
+
const DATE_FIELDS = ["date", "datetime"];
|
|
18478
|
+
/**
|
|
18479
|
+
* Parse a dimension string into a pivot dimension definition.
|
|
18480
|
+
* e.g "create_date:month" => { name: "create_date", granularity: "month" }
|
|
18481
|
+
*/
|
|
18482
|
+
function parseDimension(dimension) {
|
|
18483
|
+
const [name, granularity] = dimension.split(":");
|
|
18484
|
+
if (granularity) {
|
|
18485
|
+
return { name, granularity };
|
|
18486
|
+
}
|
|
18487
|
+
return { name };
|
|
18488
|
+
}
|
|
18489
|
+
function isDateField(field) {
|
|
18490
|
+
return DATE_FIELDS.includes(field.type);
|
|
18491
|
+
}
|
|
18492
|
+
function toPivotDomain(domainStr) {
|
|
18493
|
+
if (domainStr.length % 2 !== 0) {
|
|
18494
|
+
throw new Error("Invalid domain: odd number of elements");
|
|
18495
|
+
}
|
|
18496
|
+
const domain = [];
|
|
18497
|
+
for (let i = 0; i < domainStr.length - 1; i += 2) {
|
|
18498
|
+
domain.push({ field: domainStr[i], value: domainStr[i + 1] });
|
|
18499
|
+
}
|
|
18500
|
+
return domain;
|
|
18501
|
+
}
|
|
18502
|
+
function flatPivotDomain(domain) {
|
|
18503
|
+
return domain.flatMap((arg) => [arg.field, arg.value]);
|
|
18504
|
+
}
|
|
18505
|
+
|
|
18378
18506
|
/**
|
|
18379
18507
|
* Get the pivot ID from the formula pivot ID.
|
|
18380
18508
|
*/
|
|
@@ -18854,13 +18982,13 @@ const PIVOT_VALUE = {
|
|
|
18854
18982
|
arg("domain_field_name (string,optional,repeating)", _t("Field name.")),
|
|
18855
18983
|
arg("domain_value (string,optional,repeating)", _t("Value.")),
|
|
18856
18984
|
],
|
|
18857
|
-
compute: function (formulaId, measureName, ...
|
|
18985
|
+
compute: function (formulaId, measureName, ...domainArgs) {
|
|
18858
18986
|
const _pivotFormulaId = toString(formulaId);
|
|
18859
|
-
const
|
|
18860
|
-
const
|
|
18987
|
+
const _measure = toString(measureName);
|
|
18988
|
+
const _domainArgs = domainArgs.map(toString);
|
|
18861
18989
|
const pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
18862
|
-
assertMeasureExist(pivotId,
|
|
18863
|
-
assertDomainLength(
|
|
18990
|
+
assertMeasureExist(pivotId, _measure, this.getters);
|
|
18991
|
+
assertDomainLength(_domainArgs);
|
|
18864
18992
|
const pivot = this.getters.getPivot(pivotId);
|
|
18865
18993
|
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
18866
18994
|
if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
|
|
@@ -18874,8 +19002,9 @@ const PIVOT_VALUE = {
|
|
|
18874
19002
|
if (error) {
|
|
18875
19003
|
return error;
|
|
18876
19004
|
}
|
|
18877
|
-
const
|
|
18878
|
-
|
|
19005
|
+
const domain = toPivotDomain(_domainArgs);
|
|
19006
|
+
const { value, format } = pivot.getPivotCellValueAndFormat(_measure, domain);
|
|
19007
|
+
if (!value && !this.getters.areDomainArgsFieldsValid(pivotId, domain)) {
|
|
18879
19008
|
return {
|
|
18880
19009
|
value: CellErrorType.GenericError,
|
|
18881
19010
|
message: _t("Dimensions don't match the pivot definition"),
|
|
@@ -18892,11 +19021,11 @@ const PIVOT_HEADER = {
|
|
|
18892
19021
|
arg("domain_field_name (string,optional,repeating)", _t("Field name.")),
|
|
18893
19022
|
arg("domain_value (string,optional,repeating)", _t("Value.")),
|
|
18894
19023
|
],
|
|
18895
|
-
compute: function (pivotId, ...
|
|
19024
|
+
compute: function (pivotId, ...domainArgs) {
|
|
18896
19025
|
const _pivotFormulaId = toString(pivotId);
|
|
18897
|
-
const
|
|
19026
|
+
const _domainArgs = domainArgs.map(toString);
|
|
18898
19027
|
const _pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
18899
|
-
assertDomainLength(
|
|
19028
|
+
assertDomainLength(_domainArgs);
|
|
18900
19029
|
const pivot = this.getters.getPivot(_pivotId);
|
|
18901
19030
|
const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
|
|
18902
19031
|
if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
|
|
@@ -18910,18 +19039,23 @@ const PIVOT_HEADER = {
|
|
|
18910
19039
|
if (error) {
|
|
18911
19040
|
return error;
|
|
18912
19041
|
}
|
|
18913
|
-
const
|
|
18914
|
-
const
|
|
18915
|
-
if (!this.getters.areDomainArgsFieldsValid(_pivotId,
|
|
19042
|
+
const domain = toPivotDomain(_domainArgs);
|
|
19043
|
+
const lastNode = domain.at(-1);
|
|
19044
|
+
if (!this.getters.areDomainArgsFieldsValid(_pivotId, lastNode?.field === "measure" ? domain.slice(0, -1) : domain)) {
|
|
18916
19045
|
return {
|
|
18917
19046
|
value: CellErrorType.GenericError,
|
|
18918
19047
|
message: _t("Dimensions don't match the pivot definition"),
|
|
18919
19048
|
};
|
|
18920
19049
|
}
|
|
18921
|
-
|
|
19050
|
+
if (lastNode?.field === "measure") {
|
|
19051
|
+
return pivot.getPivotMeasureValue(toString(lastNode.value), domain);
|
|
19052
|
+
}
|
|
19053
|
+
const { value, format } = pivot.getPivotHeaderValueAndFormat(domain);
|
|
18922
19054
|
return {
|
|
18923
19055
|
value,
|
|
18924
|
-
format: !
|
|
19056
|
+
format: !lastNode || lastNode.field === "measure" || lastNode.value === "false"
|
|
19057
|
+
? undefined
|
|
19058
|
+
: format,
|
|
18925
19059
|
};
|
|
18926
19060
|
},
|
|
18927
19061
|
returns: ["NUMBER", "STRING"],
|
|
@@ -18934,11 +19068,14 @@ const PIVOT = {
|
|
|
18934
19068
|
arg("include_total (boolean, default=TRUE)", _t("Whether to include total/sub-totals or not.")),
|
|
18935
19069
|
arg("include_column_titles (boolean, default=TRUE)", _t("Whether to include the column titles or not.")),
|
|
18936
19070
|
],
|
|
18937
|
-
compute: function (
|
|
18938
|
-
const _pivotFormulaId = toString(
|
|
18939
|
-
const
|
|
18940
|
-
const
|
|
18941
|
-
const
|
|
19071
|
+
compute: function (pivotFormulaId, rowCount = { value: 10000 }, includeTotal = { value: true }, includeColumnHeaders = { value: true }) {
|
|
19072
|
+
const _pivotFormulaId = toString(pivotFormulaId);
|
|
19073
|
+
const _rowCount = toNumber(rowCount, this.locale);
|
|
19074
|
+
const _includeColumnHeaders = toBoolean(includeColumnHeaders);
|
|
19075
|
+
const _includedTotal = toBoolean(includeTotal);
|
|
19076
|
+
const pivotId = getPivotId(_pivotFormulaId, this.getters);
|
|
19077
|
+
const pivot = this.getters.getPivot(pivotId);
|
|
19078
|
+
const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
|
|
18942
19079
|
addPivotDependencies(this, coreDefinition);
|
|
18943
19080
|
pivot.init({ reload: pivot.needsReevaluation });
|
|
18944
19081
|
const error = pivot.assertIsValid({ throwOnError: false });
|
|
@@ -18946,11 +19083,9 @@ const PIVOT = {
|
|
|
18946
19083
|
return error;
|
|
18947
19084
|
}
|
|
18948
19085
|
const table = pivot.getTableStructure();
|
|
18949
|
-
const
|
|
18950
|
-
const cells = table.getPivotCells(toBoolean(includeTotal), _includeColumnHeaders);
|
|
19086
|
+
const cells = table.getPivotCells(_includedTotal, _includeColumnHeaders);
|
|
18951
19087
|
const headerRows = _includeColumnHeaders ? table.columns.length : 0;
|
|
18952
|
-
const pivotTitle = this.getters.getPivotDisplayName(
|
|
18953
|
-
const _rowCount = toNumber(rowCount, this.locale);
|
|
19088
|
+
const pivotTitle = this.getters.getPivotDisplayName(pivotId);
|
|
18954
19089
|
if (_rowCount < 0) {
|
|
18955
19090
|
throw new EvaluationError(_t("The number of rows must be positive."));
|
|
18956
19091
|
}
|
|
@@ -18965,17 +19100,23 @@ const PIVOT = {
|
|
|
18965
19100
|
result[col] = [];
|
|
18966
19101
|
for (const row of tableRows) {
|
|
18967
19102
|
const pivotCell = cells[col][row];
|
|
18968
|
-
|
|
18969
|
-
|
|
18970
|
-
|
|
18971
|
-
|
|
18972
|
-
|
|
18973
|
-
|
|
18974
|
-
|
|
18975
|
-
|
|
18976
|
-
|
|
18977
|
-
|
|
18978
|
-
|
|
19103
|
+
switch (pivotCell.type) {
|
|
19104
|
+
case "EMPTY":
|
|
19105
|
+
result[col].push({ value: "" });
|
|
19106
|
+
break;
|
|
19107
|
+
case "HEADER":
|
|
19108
|
+
const domain = pivotCell.domain;
|
|
19109
|
+
const lastNode = domain.at(-1);
|
|
19110
|
+
if (lastNode?.field === "measure") {
|
|
19111
|
+
result[col].push(pivot.getPivotMeasureValue(toString(lastNode.value), domain));
|
|
19112
|
+
}
|
|
19113
|
+
else {
|
|
19114
|
+
result[col].push(pivot.getPivotHeaderValueAndFormat(domain));
|
|
19115
|
+
}
|
|
19116
|
+
break;
|
|
19117
|
+
case "VALUE":
|
|
19118
|
+
result[col].push(pivot.getPivotCellValueAndFormat(pivotCell.measure, pivotCell.domain));
|
|
19119
|
+
break;
|
|
18979
19120
|
}
|
|
18980
19121
|
}
|
|
18981
19122
|
}
|
|
@@ -20900,8 +21041,15 @@ class Composer extends Component {
|
|
|
20900
21041
|
}
|
|
20901
21042
|
onPaste(ev) {
|
|
20902
21043
|
if (this.composerStore.editionMode !== "inactive") {
|
|
21044
|
+
// let the browser clipboard work
|
|
20903
21045
|
ev.stopPropagation();
|
|
20904
21046
|
}
|
|
21047
|
+
else {
|
|
21048
|
+
// the user meant to paste in the sheet, not open the composer with the pasted content
|
|
21049
|
+
// While we're not editing, we still have the focus and should therefore prevent
|
|
21050
|
+
// the native "paste" to occur.
|
|
21051
|
+
ev.preventDefault();
|
|
21052
|
+
}
|
|
20905
21053
|
}
|
|
20906
21054
|
/*
|
|
20907
21055
|
* Triggered automatically by the content-editable between the keydown and key up
|
|
@@ -20910,9 +21058,6 @@ class Composer extends Component {
|
|
|
20910
21058
|
if (!this.shouldProcessInputEvents) {
|
|
20911
21059
|
return;
|
|
20912
21060
|
}
|
|
20913
|
-
if (ev.inputType === "insertFromPaste" && this.composerStore.editionMode === "inactive") {
|
|
20914
|
-
return;
|
|
20915
|
-
}
|
|
20916
21061
|
ev.stopPropagation();
|
|
20917
21062
|
let content;
|
|
20918
21063
|
if (this.composerStore.editionMode === "inactive") {
|
|
@@ -21565,132 +21710,8 @@ function getFunctionsFromAST(ast, functionNames) {
|
|
|
21565
21710
|
}
|
|
21566
21711
|
|
|
21567
21712
|
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
21713
|
/**
|
|
21693
|
-
* Create a proposal entry for the compose
|
|
21714
|
+
* Create a proposal entry for the compose autowcomplete
|
|
21694
21715
|
* to insert a field name string in a formula.
|
|
21695
21716
|
*/
|
|
21696
21717
|
function makeFieldProposal(field, granularity) {
|
|
@@ -21746,15 +21767,18 @@ function extractFormulaIdFromToken(tokenAtCursor) {
|
|
|
21746
21767
|
}
|
|
21747
21768
|
return idAst.value;
|
|
21748
21769
|
}
|
|
21749
|
-
|
|
21750
|
-
|
|
21751
|
-
|
|
21752
|
-
|
|
21753
|
-
|
|
21754
|
-
|
|
21755
|
-
|
|
21756
|
-
|
|
21757
|
-
|
|
21770
|
+
/**
|
|
21771
|
+
* Get the first Pivot function description of the given formula.
|
|
21772
|
+
*/
|
|
21773
|
+
function getFirstPivotFunction(tokens) {
|
|
21774
|
+
return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS)[0];
|
|
21775
|
+
}
|
|
21776
|
+
/**
|
|
21777
|
+
* Parse a spreadsheet formula and detect the number of PIVOT functions that are
|
|
21778
|
+
* present in the given formula.
|
|
21779
|
+
*/
|
|
21780
|
+
function getNumberOfPivotFunctions(tokens) {
|
|
21781
|
+
return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS).length;
|
|
21758
21782
|
}
|
|
21759
21783
|
|
|
21760
21784
|
autoCompleteProviders.add("pivot_ids", {
|
|
@@ -25321,8 +25345,7 @@ function zoneToRect(zone) {
|
|
|
25321
25345
|
*/
|
|
25322
25346
|
function useSpreadsheetRect() {
|
|
25323
25347
|
const position = useState({ x: 0, y: 0, width: 0, height: 0 });
|
|
25324
|
-
let spreadsheetElement =
|
|
25325
|
-
updatePosition();
|
|
25348
|
+
let spreadsheetElement = null;
|
|
25326
25349
|
function updatePosition() {
|
|
25327
25350
|
if (!spreadsheetElement) {
|
|
25328
25351
|
spreadsheetElement = document.querySelector(".o-spreadsheet");
|
|
@@ -32782,7 +32805,7 @@ css /* scss */ `
|
|
|
32782
32805
|
vertical-align: middle;
|
|
32783
32806
|
}
|
|
32784
32807
|
.o_cf_radio_item {
|
|
32785
|
-
margin-right:
|
|
32808
|
+
margin-right: 30px;
|
|
32786
32809
|
}
|
|
32787
32810
|
.radio input:checked {
|
|
32788
32811
|
color: #e9ecef;
|
|
@@ -32802,6 +32825,9 @@ css /* scss */ `
|
|
|
32802
32825
|
}
|
|
32803
32826
|
margin-top: 10px;
|
|
32804
32827
|
display: flex;
|
|
32828
|
+
.form-check {
|
|
32829
|
+
padding-left: 1rem;
|
|
32830
|
+
}
|
|
32805
32831
|
}
|
|
32806
32832
|
.o-section-subtitle:first-child {
|
|
32807
32833
|
margin-top: 0px;
|
|
@@ -32810,7 +32836,7 @@ css /* scss */ `
|
|
|
32810
32836
|
font-size: 12px;
|
|
32811
32837
|
line-height: 1.5;
|
|
32812
32838
|
.o-selection-cf {
|
|
32813
|
-
margin-bottom:
|
|
32839
|
+
margin-bottom: 9px;
|
|
32814
32840
|
}
|
|
32815
32841
|
.o-cell-content {
|
|
32816
32842
|
font-size: 12px;
|
|
@@ -32851,7 +32877,7 @@ css /* scss */ `
|
|
|
32851
32877
|
width: 100%;
|
|
32852
32878
|
}
|
|
32853
32879
|
.o-threshold-value {
|
|
32854
|
-
margin-left:
|
|
32880
|
+
margin-left: 6px;
|
|
32855
32881
|
width: 20%;
|
|
32856
32882
|
min-width: 0px; // input overflows in Firefox otherwise
|
|
32857
32883
|
}
|
|
@@ -32880,8 +32906,8 @@ css /* scss */ `
|
|
|
32880
32906
|
justify-content: space-between;
|
|
32881
32907
|
.o-cf-icon {
|
|
32882
32908
|
display: inline;
|
|
32883
|
-
margin-left:
|
|
32884
|
-
margin-right:
|
|
32909
|
+
margin-left: 3px;
|
|
32910
|
+
margin-right: 3px;
|
|
32885
32911
|
}
|
|
32886
32912
|
svg {
|
|
32887
32913
|
vertical-align: baseline;
|
|
@@ -32904,7 +32930,7 @@ css /* scss */ `
|
|
|
32904
32930
|
}
|
|
32905
32931
|
table {
|
|
32906
32932
|
table-layout: fixed;
|
|
32907
|
-
margin-top:
|
|
32933
|
+
margin-top: 6px;
|
|
32908
32934
|
display: table;
|
|
32909
32935
|
text-align: left;
|
|
32910
32936
|
font-size: 12px;
|
|
@@ -32934,8 +32960,8 @@ css /* scss */ `
|
|
|
32934
32960
|
}
|
|
32935
32961
|
}
|
|
32936
32962
|
.o-cf-iconset-reverse {
|
|
32937
|
-
margin-bottom:
|
|
32938
|
-
margin-top:
|
|
32963
|
+
margin-bottom: 6px;
|
|
32964
|
+
margin-top: 6px;
|
|
32939
32965
|
.o-cf-label {
|
|
32940
32966
|
display: inline-block;
|
|
32941
32967
|
vertical-align: bottom;
|
|
@@ -34523,6 +34549,33 @@ class EditableName extends Component {
|
|
|
34523
34549
|
}
|
|
34524
34550
|
}
|
|
34525
34551
|
|
|
34552
|
+
css /* scss */ `
|
|
34553
|
+
.pivot-defer-update {
|
|
34554
|
+
min-height: 35px;
|
|
34555
|
+
background-color: #f8f9fa;
|
|
34556
|
+
}
|
|
34557
|
+
`;
|
|
34558
|
+
class PivotDeferUpdate extends Component {
|
|
34559
|
+
static template = "o-spreadsheet-PivotDeferUpdate";
|
|
34560
|
+
static props = {
|
|
34561
|
+
deferUpdate: Boolean,
|
|
34562
|
+
isDirty: Boolean,
|
|
34563
|
+
toggleDeferUpdate: Function,
|
|
34564
|
+
discard: Function,
|
|
34565
|
+
apply: Function,
|
|
34566
|
+
};
|
|
34567
|
+
static components = {
|
|
34568
|
+
Section,
|
|
34569
|
+
Checkbox,
|
|
34570
|
+
};
|
|
34571
|
+
get deferUpdatesLabel() {
|
|
34572
|
+
return _t("Defer updates");
|
|
34573
|
+
}
|
|
34574
|
+
get deferUpdatesTooltip() {
|
|
34575
|
+
return _t("Changing the pivot definition requires to reload the data. It may take some time.");
|
|
34576
|
+
}
|
|
34577
|
+
}
|
|
34578
|
+
|
|
34526
34579
|
function useAutofocus({ refName }) {
|
|
34527
34580
|
const ref = useRef(refName);
|
|
34528
34581
|
useEffect((el) => {
|
|
@@ -34642,6 +34695,10 @@ css /* scss */ `
|
|
|
34642
34695
|
select > option {
|
|
34643
34696
|
background-color: white;
|
|
34644
34697
|
}
|
|
34698
|
+
|
|
34699
|
+
.pivot-dim-operator-label {
|
|
34700
|
+
min-width: 120px;
|
|
34701
|
+
}
|
|
34645
34702
|
}
|
|
34646
34703
|
`;
|
|
34647
34704
|
class PivotDimension extends Component {
|
|
@@ -34882,7 +34939,7 @@ class PivotRuntimeDefinition {
|
|
|
34882
34939
|
getMeasure(name) {
|
|
34883
34940
|
const measure = this.measures.find((measure) => measure.name === name);
|
|
34884
34941
|
if (!measure) {
|
|
34885
|
-
throw new EvaluationError(_t("Field %s
|
|
34942
|
+
throw new EvaluationError(_t("Field %s is not a measure", name));
|
|
34886
34943
|
}
|
|
34887
34944
|
return measure;
|
|
34888
34945
|
}
|
|
@@ -35008,10 +35065,9 @@ class SpreadsheetPivotTable {
|
|
|
35008
35065
|
columns;
|
|
35009
35066
|
rows;
|
|
35010
35067
|
measures;
|
|
35011
|
-
rowTitle;
|
|
35012
35068
|
maxIndent;
|
|
35013
35069
|
pivotCells = {};
|
|
35014
|
-
constructor(columns, rows, measures
|
|
35070
|
+
constructor(columns, rows, measures) {
|
|
35015
35071
|
this.columns = columns.map((row) => {
|
|
35016
35072
|
// offset in the pivot table
|
|
35017
35073
|
// starts at 1 because the first column is the row title
|
|
@@ -35024,7 +35080,6 @@ class SpreadsheetPivotTable {
|
|
|
35024
35080
|
});
|
|
35025
35081
|
this.rows = rows;
|
|
35026
35082
|
this.measures = measures;
|
|
35027
|
-
this.rowTitle = rowTitle;
|
|
35028
35083
|
this.maxIndent = Math.max(...this.rows.map((row) => row.indent));
|
|
35029
35084
|
}
|
|
35030
35085
|
/**
|
|
@@ -35066,26 +35121,23 @@ class SpreadsheetPivotTable {
|
|
|
35066
35121
|
}
|
|
35067
35122
|
getPivotCell(col, row, includeTotal = true) {
|
|
35068
35123
|
const colHeadersHeight = this.columns.length;
|
|
35069
|
-
if (
|
|
35070
|
-
return { content: this.rowTitle, isHeader: true };
|
|
35071
|
-
}
|
|
35072
|
-
else if (row <= colHeadersHeight - 1) {
|
|
35124
|
+
if (row <= colHeadersHeight - 1) {
|
|
35073
35125
|
const domain = this.getColHeaderDomain(col, row);
|
|
35074
|
-
return {
|
|
35126
|
+
return domain ? { type: "HEADER", domain } : { type: "EMPTY" };
|
|
35075
35127
|
}
|
|
35076
35128
|
else if (col === 0) {
|
|
35077
35129
|
const rowIndex = row - colHeadersHeight;
|
|
35078
35130
|
const domain = this.getRowDomain(rowIndex);
|
|
35079
|
-
return {
|
|
35131
|
+
return { type: "HEADER", domain };
|
|
35080
35132
|
}
|
|
35081
35133
|
else {
|
|
35082
35134
|
const rowIndex = row - colHeadersHeight;
|
|
35083
35135
|
if (!includeTotal && this.isTotalRow(rowIndex)) {
|
|
35084
|
-
return {
|
|
35136
|
+
return { type: "EMPTY" };
|
|
35085
35137
|
}
|
|
35086
35138
|
const domain = [...this.getRowDomain(rowIndex), ...this.getColDomain(col)];
|
|
35087
35139
|
const measure = this.getColMeasure(col);
|
|
35088
|
-
return {
|
|
35140
|
+
return { type: "VALUE", domain, measure };
|
|
35089
35141
|
}
|
|
35090
35142
|
}
|
|
35091
35143
|
getColHeaderDomain(col, row) {
|
|
@@ -35098,24 +35150,32 @@ class SpreadsheetPivotTable {
|
|
|
35098
35150
|
return undefined;
|
|
35099
35151
|
}
|
|
35100
35152
|
for (let i = 0; i < pivotCol.fields.length; i++) {
|
|
35101
|
-
domain.push(
|
|
35102
|
-
|
|
35153
|
+
domain.push({
|
|
35154
|
+
field: pivotCol.fields[i],
|
|
35155
|
+
value: pivotCol.values[i],
|
|
35156
|
+
});
|
|
35103
35157
|
}
|
|
35104
35158
|
return domain;
|
|
35105
35159
|
}
|
|
35106
35160
|
getColDomain(col) {
|
|
35107
35161
|
const domain = this.getColHeaderDomain(col, this.columns.length - 1);
|
|
35108
|
-
return domain ? domain.slice(0, -
|
|
35162
|
+
return domain ? domain.slice(0, -1) : []; // slice: remove measure and value
|
|
35109
35163
|
}
|
|
35110
35164
|
getColMeasure(col) {
|
|
35111
35165
|
const domain = this.getColHeaderDomain(col, this.columns.length - 1);
|
|
35112
|
-
|
|
35166
|
+
const measure = domain?.at(-1)?.value;
|
|
35167
|
+
if (measure === undefined) {
|
|
35168
|
+
throw new Error("Measure isd missing");
|
|
35169
|
+
}
|
|
35170
|
+
return measure.toString();
|
|
35113
35171
|
}
|
|
35114
35172
|
getRowDomain(row) {
|
|
35115
35173
|
const domain = [];
|
|
35116
35174
|
for (let i = 0; i < this.rows[row].fields.length; i++) {
|
|
35117
|
-
domain.push(
|
|
35118
|
-
|
|
35175
|
+
domain.push({
|
|
35176
|
+
field: this.rows[row].fields[i],
|
|
35177
|
+
value: this.rows[row].values[i],
|
|
35178
|
+
});
|
|
35119
35179
|
}
|
|
35120
35180
|
return domain;
|
|
35121
35181
|
}
|
|
@@ -35124,7 +35184,6 @@ class SpreadsheetPivotTable {
|
|
|
35124
35184
|
cols: this.columns,
|
|
35125
35185
|
rows: this.rows,
|
|
35126
35186
|
measures: this.measures,
|
|
35127
|
-
rowTitle: this.rowTitle,
|
|
35128
35187
|
};
|
|
35129
35188
|
}
|
|
35130
35189
|
}
|
|
@@ -35144,8 +35203,7 @@ function dataEntriesToSpreadsheetPivotTable(dataEntries, definition) {
|
|
|
35144
35203
|
indent: 0,
|
|
35145
35204
|
});
|
|
35146
35205
|
const measureNames = definition.measures.map((m) => m.name);
|
|
35147
|
-
|
|
35148
|
-
return new SpreadsheetPivotTable(cols, rows, measureNames, rowTitle);
|
|
35206
|
+
return new SpreadsheetPivotTable(cols, rows, measureNames);
|
|
35149
35207
|
}
|
|
35150
35208
|
// -----------------------------------------------------------------------------
|
|
35151
35209
|
// ROWS
|
|
@@ -35488,7 +35546,10 @@ class SpreadsheetPivot {
|
|
|
35488
35546
|
}
|
|
35489
35547
|
get definition() {
|
|
35490
35548
|
if (!this._definition) {
|
|
35491
|
-
|
|
35549
|
+
this.init();
|
|
35550
|
+
}
|
|
35551
|
+
if (!this._definition) {
|
|
35552
|
+
throw new Error("Pivot definition should be defined at this point.");
|
|
35492
35553
|
}
|
|
35493
35554
|
return this._definition;
|
|
35494
35555
|
}
|
|
@@ -35537,15 +35598,16 @@ class SpreadsheetPivot {
|
|
|
35537
35598
|
getMeasure(name) {
|
|
35538
35599
|
return this.definition.getMeasure(name);
|
|
35539
35600
|
}
|
|
35540
|
-
|
|
35541
|
-
|
|
35601
|
+
getPivotMeasureValue(name) {
|
|
35602
|
+
return {
|
|
35603
|
+
value: this.getMeasure(name).displayName,
|
|
35604
|
+
};
|
|
35605
|
+
}
|
|
35606
|
+
getPivotHeaderValueAndFormat(domain) {
|
|
35542
35607
|
const lastNode = domain.at(-1);
|
|
35543
35608
|
if (!lastNode) {
|
|
35544
35609
|
return { value: _t("Total") };
|
|
35545
35610
|
}
|
|
35546
|
-
if (lastNode.field === "measure") {
|
|
35547
|
-
return { value: this.getMeasure(lastNode.value).displayName };
|
|
35548
|
-
}
|
|
35549
35611
|
const dimension = this.getDimension(lastNode.field);
|
|
35550
35612
|
const cells = this.filterDataEntriesFromDomain(this.dataEntries, domain);
|
|
35551
35613
|
const finalCell = cells[0]?.[dimension.nameWithGranularity];
|
|
@@ -35573,8 +35635,7 @@ class SpreadsheetPivot {
|
|
|
35573
35635
|
format: finalCell.format,
|
|
35574
35636
|
};
|
|
35575
35637
|
}
|
|
35576
|
-
getPivotCellValueAndFormat(measure,
|
|
35577
|
-
const domain = toDomainArgs(domainStr);
|
|
35638
|
+
getPivotCellValueAndFormat(measure, domain) {
|
|
35578
35639
|
const dataEntries = this.filterDataEntriesFromDomain(this.dataEntries, domain);
|
|
35579
35640
|
if (dataEntries.length === 0) {
|
|
35580
35641
|
return { value: "" };
|
|
@@ -35970,12 +36031,12 @@ class PivotSpreadsheetSidePanel extends Component {
|
|
|
35970
36031
|
SelectionInput,
|
|
35971
36032
|
EditableName,
|
|
35972
36033
|
Checkbox,
|
|
36034
|
+
PivotDeferUpdate,
|
|
35973
36035
|
};
|
|
35974
36036
|
store;
|
|
35975
36037
|
state;
|
|
35976
36038
|
setup() {
|
|
35977
36039
|
this.store = useLocalStore(PivotSidePanelStore, this.props.pivotId);
|
|
35978
|
-
this.pivot.init();
|
|
35979
36040
|
this.state = useState({
|
|
35980
36041
|
range: undefined,
|
|
35981
36042
|
rangeHasChanged: false,
|
|
@@ -36008,12 +36069,6 @@ class PivotSpreadsheetSidePanel extends Component {
|
|
|
36008
36069
|
get definition() {
|
|
36009
36070
|
return this.store.definition;
|
|
36010
36071
|
}
|
|
36011
|
-
get deferUpdatesLabel() {
|
|
36012
|
-
return _t("Defer updates");
|
|
36013
|
-
}
|
|
36014
|
-
get deferUpdatesTooltip() {
|
|
36015
|
-
return _t("Changing the pivot definition requires to reload the data. It may take some time.");
|
|
36016
|
-
}
|
|
36017
36072
|
onSelectionChanged(ranges) {
|
|
36018
36073
|
this.state.rangeHasChanged = true;
|
|
36019
36074
|
this.state.range = ranges[0];
|
|
@@ -36852,7 +36907,7 @@ css /* scss */ `
|
|
|
36852
36907
|
}
|
|
36853
36908
|
|
|
36854
36909
|
.o-table-style-list-item {
|
|
36855
|
-
padding: 3px;
|
|
36910
|
+
padding: 3px 2px;
|
|
36856
36911
|
margin: 2px 1px;
|
|
36857
36912
|
|
|
36858
36913
|
.o-table-style-picker-preview {
|
|
@@ -36873,10 +36928,10 @@ class TableStylePicker extends Component {
|
|
|
36873
36928
|
const styles = Object.keys(allStyles).filter((key) => allStyles[key].category === selectedStyleCategory);
|
|
36874
36929
|
const selectedStyleIndex = styles.indexOf(this.props.table.config.styleId);
|
|
36875
36930
|
if (selectedStyleIndex === -1) {
|
|
36876
|
-
return
|
|
36931
|
+
return selectedStyleIndex;
|
|
36877
36932
|
}
|
|
36878
36933
|
const index = Math.floor(selectedStyleIndex / 4) * 4;
|
|
36879
|
-
return styles.slice(index
|
|
36934
|
+
return styles.slice(index);
|
|
36880
36935
|
}
|
|
36881
36936
|
onStylePicked(styleId) {
|
|
36882
36937
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
@@ -37916,10 +37971,7 @@ class GridComposer extends Component {
|
|
|
37916
37971
|
}
|
|
37917
37972
|
get containerStyle() {
|
|
37918
37973
|
if (this.composerStore.editionMode === "inactive") {
|
|
37919
|
-
return `
|
|
37920
|
-
position: absolute;
|
|
37921
|
-
z-index: -1000;
|
|
37922
|
-
`;
|
|
37974
|
+
return `z-index: -1000;`;
|
|
37923
37975
|
}
|
|
37924
37976
|
const isFormula = this.composerStore.currentContent.startsWith("=");
|
|
37925
37977
|
const cell = this.env.model.getters.getActiveCell();
|
|
@@ -40763,10 +40815,13 @@ class VerticalScrollBar extends Component {
|
|
|
40763
40815
|
}
|
|
40764
40816
|
}
|
|
40765
40817
|
|
|
40818
|
+
const DEFAULT_SIDE_PANEL_SIZE = 350;
|
|
40819
|
+
const MIN_SHEET_VIEW_WIDTH = 150;
|
|
40766
40820
|
class SidePanelStore extends SpreadsheetStore {
|
|
40767
|
-
mutators = ["open", "toggle", "close"];
|
|
40821
|
+
mutators = ["open", "toggle", "close", "changePanelSize", "resetPanelSize"];
|
|
40768
40822
|
initialPanelProps = {};
|
|
40769
40823
|
componentTag = "";
|
|
40824
|
+
panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
40770
40825
|
get isOpen() {
|
|
40771
40826
|
if (!this.componentTag) {
|
|
40772
40827
|
return false;
|
|
@@ -40811,6 +40866,20 @@ class SidePanelStore extends SpreadsheetStore {
|
|
|
40811
40866
|
this.initialPanelProps = {};
|
|
40812
40867
|
this.componentTag = "";
|
|
40813
40868
|
}
|
|
40869
|
+
changePanelSize(size, spreadsheetElWidth) {
|
|
40870
|
+
if (size < DEFAULT_SIDE_PANEL_SIZE) {
|
|
40871
|
+
this.panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
40872
|
+
}
|
|
40873
|
+
else if (size > spreadsheetElWidth - MIN_SHEET_VIEW_WIDTH) {
|
|
40874
|
+
this.panelSize = Math.max(spreadsheetElWidth - MIN_SHEET_VIEW_WIDTH, DEFAULT_SIDE_PANEL_SIZE);
|
|
40875
|
+
}
|
|
40876
|
+
else {
|
|
40877
|
+
this.panelSize = size;
|
|
40878
|
+
}
|
|
40879
|
+
}
|
|
40880
|
+
resetPanelSize() {
|
|
40881
|
+
this.panelSize = DEFAULT_SIDE_PANEL_SIZE;
|
|
40882
|
+
}
|
|
40814
40883
|
computeState(componentTag, panelProps) {
|
|
40815
40884
|
const customComputeState = sidePanelRegistry.get(componentTag).computeState;
|
|
40816
40885
|
if (!customComputeState) {
|
|
@@ -41931,7 +42000,7 @@ class XLSXImportWarningManager {
|
|
|
41931
42000
|
}
|
|
41932
42001
|
}
|
|
41933
42002
|
|
|
41934
|
-
const SUPPORTED_BORDER_STYLES = ["thin"];
|
|
42003
|
+
const SUPPORTED_BORDER_STYLES = ["thin", "medium", "thick", "dashed", "dotted"];
|
|
41935
42004
|
const SUPPORTED_HORIZONTAL_ALIGNMENTS = [
|
|
41936
42005
|
"general",
|
|
41937
42006
|
"left",
|
|
@@ -51070,8 +51139,8 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
51070
51139
|
case "INSERT_PIVOT": {
|
|
51071
51140
|
const { sheetId, col, row, pivotId, table } = cmd;
|
|
51072
51141
|
const position = { sheetId, col, row };
|
|
51073
|
-
const { cols, rows, measures
|
|
51074
|
-
const spTable = new SpreadsheetPivotTable(cols, rows, measures
|
|
51142
|
+
const { cols, rows, measures } = table;
|
|
51143
|
+
const spTable = new SpreadsheetPivotTable(cols, rows, measures);
|
|
51075
51144
|
const formulaId = this.getPivotFormulaId(pivotId);
|
|
51076
51145
|
this.insertPivot(position, formulaId, spTable);
|
|
51077
51146
|
break;
|
|
@@ -51200,13 +51269,18 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
51200
51269
|
}
|
|
51201
51270
|
}
|
|
51202
51271
|
addPivotFormula(position, formulaId, pivotCell) {
|
|
51203
|
-
|
|
51204
|
-
|
|
51205
|
-
|
|
51206
|
-
|
|
51272
|
+
let content = undefined;
|
|
51273
|
+
switch (pivotCell.type) {
|
|
51274
|
+
case "HEADER":
|
|
51275
|
+
content = makePivotFormula("PIVOT.HEADER", [formulaId, ...flatPivotDomain(pivotCell.domain)].filter(isDefined));
|
|
51276
|
+
break;
|
|
51277
|
+
case "VALUE":
|
|
51278
|
+
content = makePivotFormula("PIVOT.VALUE", [formulaId, pivotCell.measure, ...flatPivotDomain(pivotCell.domain)].filter(isDefined));
|
|
51279
|
+
break;
|
|
51280
|
+
}
|
|
51207
51281
|
this.dispatch("UPDATE_CELL", {
|
|
51208
51282
|
...position,
|
|
51209
|
-
content
|
|
51283
|
+
content,
|
|
51210
51284
|
});
|
|
51211
51285
|
}
|
|
51212
51286
|
getPivotCore(pivotId) {
|
|
@@ -51225,7 +51299,7 @@ class PivotCorePlugin extends CorePlugin {
|
|
|
51225
51299
|
import(data) {
|
|
51226
51300
|
if (data.pivots) {
|
|
51227
51301
|
for (const [id, pivot] of Object.entries(data.pivots)) {
|
|
51228
|
-
this.addPivot(id,
|
|
51302
|
+
this.addPivot(id, pivot, pivot.formulaId);
|
|
51229
51303
|
}
|
|
51230
51304
|
}
|
|
51231
51305
|
this.history.update("nextFormulaId", data.pivotNextId || getMaxObjectId(this.pivots) + 1);
|
|
@@ -54566,17 +54640,21 @@ class PivotUIPlugin extends UIPlugin {
|
|
|
54566
54640
|
const pivotCol = position.col - mainPosition.col;
|
|
54567
54641
|
const pivotRow = position.row - mainPosition.row;
|
|
54568
54642
|
const pivotCell = pivotCells[pivotCol][pivotRow];
|
|
54569
|
-
|
|
54570
|
-
|
|
54571
|
-
|
|
54643
|
+
if (pivotCell.type === "EMPTY") {
|
|
54644
|
+
return undefined;
|
|
54645
|
+
}
|
|
54646
|
+
let domain = pivotCell.domain;
|
|
54647
|
+
if (domain.at(-1)?.field === "measure") {
|
|
54648
|
+
domain = domain.slice(0, -1);
|
|
54572
54649
|
}
|
|
54573
|
-
return domain;
|
|
54650
|
+
return { domainArgs: domain, isHeader: pivotCell.type === "HEADER" };
|
|
54574
54651
|
}
|
|
54575
|
-
|
|
54576
|
-
if (domain.at(-
|
|
54577
|
-
|
|
54652
|
+
let domain = toPivotDomain(args.slice(functionName === "PIVOT.VALUE" ? 2 : 1).map((x) => `${x}`));
|
|
54653
|
+
if (domain.at(-1)?.field === "measure") {
|
|
54654
|
+
domain = domain.slice(0, -1);
|
|
54578
54655
|
}
|
|
54579
|
-
|
|
54656
|
+
const isHeader = functionName === "PIVOT.HEADER";
|
|
54657
|
+
return { domainArgs: domain, isHeader };
|
|
54580
54658
|
}
|
|
54581
54659
|
getPivot(pivotId) {
|
|
54582
54660
|
return this.pivots[pivotId];
|
|
@@ -54589,9 +54667,9 @@ class PivotUIPlugin extends UIPlugin {
|
|
|
54589
54667
|
* a pivot function are valid according to the pivot definition.
|
|
54590
54668
|
* e.g. =PIVOT.VALUE(1,"revenue","country_id",...,"create_date:month",...,"source_id",...)
|
|
54591
54669
|
*/
|
|
54592
|
-
areDomainArgsFieldsValid(pivotId,
|
|
54593
|
-
const dimensions =
|
|
54594
|
-
.
|
|
54670
|
+
areDomainArgsFieldsValid(pivotId, domain) {
|
|
54671
|
+
const dimensions = domain
|
|
54672
|
+
.map((node) => node.field)
|
|
54595
54673
|
.map((name) => (name.startsWith("#") ? name.slice(1) : name));
|
|
54596
54674
|
let argIndex = 0;
|
|
54597
54675
|
let definitionIndex = 0;
|
|
@@ -61605,6 +61683,10 @@ css /* scss */ `
|
|
|
61605
61683
|
}
|
|
61606
61684
|
}
|
|
61607
61685
|
}
|
|
61686
|
+
.o-sidePanelBody-container {
|
|
61687
|
+
/* This overwrites the min-height: auto; of flex. Without this, a flex div cannot be smaller than its children */
|
|
61688
|
+
min-height: 0;
|
|
61689
|
+
}
|
|
61608
61690
|
.o-sidePanelBody {
|
|
61609
61691
|
overflow: auto;
|
|
61610
61692
|
width: 100%;
|
|
@@ -61683,24 +61765,6 @@ css /* scss */ `
|
|
|
61683
61765
|
text-align: left;
|
|
61684
61766
|
}
|
|
61685
61767
|
|
|
61686
|
-
.o-inflection {
|
|
61687
|
-
table {
|
|
61688
|
-
table-layout: fixed;
|
|
61689
|
-
margin-top: 2%;
|
|
61690
|
-
display: table;
|
|
61691
|
-
text-align: left;
|
|
61692
|
-
font-size: 12px;
|
|
61693
|
-
line-height: 18px;
|
|
61694
|
-
width: 100%;
|
|
61695
|
-
}
|
|
61696
|
-
input,
|
|
61697
|
-
select {
|
|
61698
|
-
width: 100%;
|
|
61699
|
-
height: 100%;
|
|
61700
|
-
box-sizing: border-box;
|
|
61701
|
-
}
|
|
61702
|
-
}
|
|
61703
|
-
|
|
61704
61768
|
.o-sidePanel-tools {
|
|
61705
61769
|
color: #333;
|
|
61706
61770
|
font-size: 13px;
|
|
@@ -61719,12 +61783,25 @@ css /* scss */ `
|
|
|
61719
61783
|
}
|
|
61720
61784
|
}
|
|
61721
61785
|
}
|
|
61786
|
+
|
|
61787
|
+
.o-sidePanel-handle-container {
|
|
61788
|
+
width: 8px;
|
|
61789
|
+
}
|
|
61790
|
+
.o-sidePanel-handle {
|
|
61791
|
+
cursor: col-resize;
|
|
61792
|
+
color: #a9a9a9;
|
|
61793
|
+
.o-icon {
|
|
61794
|
+
height: 25px;
|
|
61795
|
+
margin-left: -5px;
|
|
61796
|
+
}
|
|
61797
|
+
}
|
|
61722
61798
|
}
|
|
61723
61799
|
`;
|
|
61724
61800
|
class SidePanel extends Component {
|
|
61725
61801
|
static template = "o-spreadsheet-SidePanel";
|
|
61726
61802
|
static props = {};
|
|
61727
61803
|
sidePanelStore;
|
|
61804
|
+
spreadsheetRect = useSpreadsheetRect();
|
|
61728
61805
|
setup() {
|
|
61729
61806
|
this.sidePanelStore = useStore(SidePanelStore);
|
|
61730
61807
|
useEffect((isOpen) => {
|
|
@@ -61745,6 +61822,20 @@ class SidePanel extends Component {
|
|
|
61745
61822
|
? panel.title(this.env, this.sidePanelStore.panelProps)
|
|
61746
61823
|
: panel.title;
|
|
61747
61824
|
}
|
|
61825
|
+
startHandleDrag(ev) {
|
|
61826
|
+
const startingCursor = document.body.style.cursor;
|
|
61827
|
+
const startSize = this.sidePanelStore.panelSize;
|
|
61828
|
+
const startPosition = ev.clientX;
|
|
61829
|
+
const onMouseMove = (ev) => {
|
|
61830
|
+
document.body.style.cursor = "col-resize";
|
|
61831
|
+
const newSize = startSize + startPosition - ev.clientX;
|
|
61832
|
+
this.sidePanelStore.changePanelSize(newSize, this.spreadsheetRect.width);
|
|
61833
|
+
};
|
|
61834
|
+
const cleanUp = () => {
|
|
61835
|
+
document.body.style.cursor = startingCursor;
|
|
61836
|
+
};
|
|
61837
|
+
startDnd(onMouseMove, cleanUp);
|
|
61838
|
+
}
|
|
61748
61839
|
}
|
|
61749
61840
|
|
|
61750
61841
|
css /* scss */ `
|
|
@@ -62528,7 +62619,6 @@ css /* scss */ `
|
|
|
62528
62619
|
.o-spreadsheet {
|
|
62529
62620
|
position: relative;
|
|
62530
62621
|
display: grid;
|
|
62531
|
-
grid-template-columns: auto 350px;
|
|
62532
62622
|
color: #333;
|
|
62533
62623
|
font-size: 14px;
|
|
62534
62624
|
|
|
@@ -62726,6 +62816,7 @@ class Spreadsheet extends Component {
|
|
|
62726
62816
|
};
|
|
62727
62817
|
sidePanel;
|
|
62728
62818
|
spreadsheetRef = useRef("spreadsheet");
|
|
62819
|
+
spreadsheetRect = useSpreadsheetRect();
|
|
62729
62820
|
_focusGrid;
|
|
62730
62821
|
keyDownMapping;
|
|
62731
62822
|
isViewportTooSmall = false;
|
|
@@ -62735,10 +62826,15 @@ class Spreadsheet extends Component {
|
|
|
62735
62826
|
return this.props.model;
|
|
62736
62827
|
}
|
|
62737
62828
|
getStyle() {
|
|
62829
|
+
const properties = {};
|
|
62738
62830
|
if (this.env.isDashboard()) {
|
|
62739
|
-
|
|
62831
|
+
properties["grid-template-rows"] = `auto`;
|
|
62832
|
+
}
|
|
62833
|
+
else {
|
|
62834
|
+
properties["grid-template-rows"] = `${TOPBAR_HEIGHT}px auto ${BOTTOMBAR_HEIGHT + 1}px`;
|
|
62740
62835
|
}
|
|
62741
|
-
|
|
62836
|
+
properties["grid-template-columns"] = `auto ${this.sidePanel.panelSize}px`;
|
|
62837
|
+
return cssPropertiesToCss(properties);
|
|
62742
62838
|
}
|
|
62743
62839
|
setup() {
|
|
62744
62840
|
const stores = useStoreProvider();
|
|
@@ -62798,14 +62894,19 @@ class Spreadsheet extends Component {
|
|
|
62798
62894
|
onMounted(() => {
|
|
62799
62895
|
this.checkViewportSize();
|
|
62800
62896
|
stores.on("store-updated", this, render);
|
|
62897
|
+
resizeObserver.observe(this.spreadsheetRef.el);
|
|
62801
62898
|
});
|
|
62802
62899
|
onWillUnmount(() => {
|
|
62803
62900
|
this.unbindModelEvents();
|
|
62804
62901
|
stores.off("store-updated", this);
|
|
62902
|
+
resizeObserver.disconnect();
|
|
62805
62903
|
});
|
|
62806
62904
|
onPatched(() => {
|
|
62807
62905
|
this.checkViewportSize();
|
|
62808
62906
|
});
|
|
62907
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
62908
|
+
this.sidePanel.changePanelSize(this.sidePanel.panelSize, this.spreadsheetRect.width);
|
|
62909
|
+
});
|
|
62809
62910
|
}
|
|
62810
62911
|
bindModelEvents() {
|
|
62811
62912
|
this.model.on("update", this, () => this.render(true));
|
|
@@ -66860,6 +66961,8 @@ const helpers = {
|
|
|
66860
66961
|
insertTokenAfterLeftParenthesis,
|
|
66861
66962
|
mergeContiguousZones,
|
|
66862
66963
|
getPivotHighlights,
|
|
66964
|
+
toPivotDomain,
|
|
66965
|
+
flatPivotDomain,
|
|
66863
66966
|
pivotTimeAdapter,
|
|
66864
66967
|
UNDO_REDO_PIVOT_COMMANDS,
|
|
66865
66968
|
};
|
|
@@ -66904,6 +67007,7 @@ const components = {
|
|
|
66904
67007
|
PivotDimension,
|
|
66905
67008
|
PivotLayoutConfigurator,
|
|
66906
67009
|
EditableName,
|
|
67010
|
+
PivotDeferUpdate,
|
|
66907
67011
|
};
|
|
66908
67012
|
const hooks = {
|
|
66909
67013
|
useDragAndDropListItems,
|
|
@@ -66944,6 +67048,6 @@ const constants = {
|
|
|
66944
67048
|
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 };
|
|
66945
67049
|
|
|
66946
67050
|
|
|
66947
|
-
__info__.version = "17.4.0-alpha.
|
|
66948
|
-
__info__.date = "2024-06-
|
|
66949
|
-
__info__.hash = "
|
|
67051
|
+
__info__.version = "17.4.0-alpha.3";
|
|
67052
|
+
__info__.date = "2024-06-10T09:38:53.982Z";
|
|
67053
|
+
__info__.hash = "a45ed6a";
|