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