@odoo/o-spreadsheet 18.5.0-alpha.11 → 18.5.0-alpha.12
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 +145 -42
- package/dist/o-spreadsheet.d.ts +167 -142
- package/dist/o-spreadsheet.esm.js +145 -42
- package/dist/o-spreadsheet.iife.js +145 -42
- package/dist/o-spreadsheet.iife.min.js +286 -286
- package/dist/o_spreadsheet.xml +18 -5
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 18.5.0-alpha.
|
|
6
|
-
* @date 2025-08-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.5.0-alpha.12
|
|
6
|
+
* @date 2025-08-29T08:05:09.767Z
|
|
7
|
+
* @hash 8ee7677
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, useExternalListener, onWillUpdateProps, onWillStart, onWillPatch, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -1345,6 +1345,18 @@ function hslaToHex(hsla) {
|
|
|
1345
1345
|
function hexToHSLA(hex) {
|
|
1346
1346
|
return rgbaToHSLA(colorToRGBA(hex));
|
|
1347
1347
|
}
|
|
1348
|
+
/**
|
|
1349
|
+
* Blend color2 on top of color1, with alpha blending.
|
|
1350
|
+
*/
|
|
1351
|
+
function blendColors(color1, color2) {
|
|
1352
|
+
const rgba2 = colorToRGBA(color2);
|
|
1353
|
+
const rgba1 = colorToRGBA(color1);
|
|
1354
|
+
const a = rgba2.a + rgba1.a * (1 - rgba2.a);
|
|
1355
|
+
const r = Math.round((rgba2.r * rgba2.a + rgba1.r * rgba1.a * (1 - rgba2.a)) / a);
|
|
1356
|
+
const g = Math.round((rgba2.g * rgba2.a + rgba1.g * rgba1.a * (1 - rgba2.a)) / a);
|
|
1357
|
+
const b = Math.round((rgba2.b * rgba2.a + rgba1.b * rgba1.a * (1 - rgba2.a)) / a);
|
|
1358
|
+
return rgbaToHex({ r, g, b, a });
|
|
1359
|
+
}
|
|
1348
1360
|
function colorOrNumberToRGBA(color) {
|
|
1349
1361
|
if (typeof color === "number") {
|
|
1350
1362
|
return colorToRGBA(colorNumberToHex(color));
|
|
@@ -2659,6 +2671,7 @@ const invalidateBordersCommands = new Set([
|
|
|
2659
2671
|
"AUTOFILL_CELL",
|
|
2660
2672
|
"SET_BORDER",
|
|
2661
2673
|
"SET_ZONE_BORDERS",
|
|
2674
|
+
"SET_BORDERS_ON_TARGET",
|
|
2662
2675
|
]);
|
|
2663
2676
|
const invalidSubtotalFormulasCommands = new Set([
|
|
2664
2677
|
"UNHIDE_COLUMNS_ROWS",
|
|
@@ -2686,6 +2699,7 @@ const readonlyAllowedCommands = new Set([
|
|
|
2686
2699
|
"UPDATE_FILTER",
|
|
2687
2700
|
"UPDATE_CHART",
|
|
2688
2701
|
"UPDATE_CAROUSEL_ACTIVE_ITEM",
|
|
2702
|
+
"UPDATE_PIVOT",
|
|
2689
2703
|
]);
|
|
2690
2704
|
const coreTypes = new Set([
|
|
2691
2705
|
/** CELLS */
|
|
@@ -46924,18 +46938,18 @@ const pivotProperties = {
|
|
|
46924
46938
|
};
|
|
46925
46939
|
const pivotSortingAsc = {
|
|
46926
46940
|
name: _t("Ascending"),
|
|
46927
|
-
execute: (env) => sortPivot(env, "asc"),
|
|
46928
|
-
isActive: (env) =>
|
|
46941
|
+
execute: (env) => sortPivot(env, env.model.getters.getActivePosition(), "asc"),
|
|
46942
|
+
isActive: (env) => env.model.getters.getPivotCellSortDirection(env.model.getters.getActivePosition()) === "asc",
|
|
46929
46943
|
};
|
|
46930
46944
|
const pivotSortingDesc = {
|
|
46931
46945
|
name: _t("Descending"),
|
|
46932
|
-
execute: (env) => sortPivot(env, "desc"),
|
|
46933
|
-
isActive: (env) =>
|
|
46946
|
+
execute: (env) => sortPivot(env, env.model.getters.getActivePosition(), "desc"),
|
|
46947
|
+
isActive: (env) => env.model.getters.getPivotCellSortDirection(env.model.getters.getActivePosition()) === "desc",
|
|
46934
46948
|
};
|
|
46935
46949
|
const noPivotSorting = {
|
|
46936
46950
|
name: _t("No sorting"),
|
|
46937
|
-
execute: (env) => sortPivot(env, "none"),
|
|
46938
|
-
isActive: (env) =>
|
|
46951
|
+
execute: (env) => sortPivot(env, env.model.getters.getActivePosition(), "none"),
|
|
46952
|
+
isActive: (env) => env.model.getters.getPivotCellSortDirection(env.model.getters.getActivePosition()) === "none",
|
|
46939
46953
|
};
|
|
46940
46954
|
const FIX_FORMULAS = {
|
|
46941
46955
|
name: _t("Convert to individual formulas"),
|
|
@@ -47071,23 +47085,19 @@ const ungroupPivotHeadersAction = {
|
|
|
47071
47085
|
return areFieldValuesInGroups(definition, values, field, pivot.getFields());
|
|
47072
47086
|
},
|
|
47073
47087
|
};
|
|
47074
|
-
function canSortPivot(
|
|
47075
|
-
const
|
|
47076
|
-
|
|
47077
|
-
if (!pivotId ||
|
|
47078
|
-
!env.model.getters.isExistingPivot(pivotId) ||
|
|
47079
|
-
!env.model.getters.isSpillPivotFormula(position)) {
|
|
47088
|
+
function canSortPivot(getters, position) {
|
|
47089
|
+
const pivotId = getters.getPivotIdFromPosition(position);
|
|
47090
|
+
if (!pivotId || !getters.isExistingPivot(pivotId) || !getters.isSpillPivotFormula(position)) {
|
|
47080
47091
|
return false;
|
|
47081
47092
|
}
|
|
47082
|
-
const pivot =
|
|
47093
|
+
const pivot = getters.getPivot(pivotId);
|
|
47083
47094
|
if (!pivot.isValid()) {
|
|
47084
47095
|
return false;
|
|
47085
47096
|
}
|
|
47086
|
-
const pivotCell =
|
|
47097
|
+
const pivotCell = getters.getPivotCellFromPosition(position);
|
|
47087
47098
|
return pivotCell.type === "VALUE" || pivotCell.type === "MEASURE_HEADER";
|
|
47088
47099
|
}
|
|
47089
|
-
function sortPivot(env, order) {
|
|
47090
|
-
const position = env.model.getters.getActivePosition();
|
|
47100
|
+
function sortPivot(env, position, order) {
|
|
47091
47101
|
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
47092
47102
|
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
47093
47103
|
if (pivotCell.type === "EMPTY" || pivotCell.type === "HEADER" || !pivotId) {
|
|
@@ -47113,24 +47123,6 @@ function sortPivot(env, order) {
|
|
|
47113
47123
|
},
|
|
47114
47124
|
});
|
|
47115
47125
|
}
|
|
47116
|
-
function isPivotSortMenuItemActive(env, order) {
|
|
47117
|
-
const position = env.model.getters.getActivePosition();
|
|
47118
|
-
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
47119
|
-
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
47120
|
-
if (pivotCell.type === "EMPTY" || pivotCell.type === "HEADER" || !pivotId) {
|
|
47121
|
-
return false;
|
|
47122
|
-
}
|
|
47123
|
-
const pivot = env.model.getters.getPivot(pivotId);
|
|
47124
|
-
const colDomain = domainToColRowDomain(pivot, pivotCell.domain).colDomain;
|
|
47125
|
-
const sortedColumn = pivot.definition.sortedColumn;
|
|
47126
|
-
if (order === "none") {
|
|
47127
|
-
return !sortedColumn;
|
|
47128
|
-
}
|
|
47129
|
-
if (!sortedColumn || sortedColumn.order !== order) {
|
|
47130
|
-
return false;
|
|
47131
|
-
}
|
|
47132
|
-
return sortedColumn.measure === pivotCell.measure && deepEquals(sortedColumn.domain, colDomain);
|
|
47133
|
-
}
|
|
47134
47126
|
/*
|
|
47135
47127
|
* Get the values of the pivot headers in the current selection, if all the pivot headers on the selection belong
|
|
47136
47128
|
* to the same pivot, the same field and that the pivot formula is a dynamic pivot. Otherwise return undefined.
|
|
@@ -47433,7 +47425,10 @@ cellMenuRegistry
|
|
|
47433
47425
|
name: _t("Sort pivot"),
|
|
47434
47426
|
sequence: 155,
|
|
47435
47427
|
icon: "o-spreadsheet-Icon.SORT_RANGE",
|
|
47436
|
-
isVisible:
|
|
47428
|
+
isVisible: (env) => {
|
|
47429
|
+
const position = env.model.getters.getActivePosition();
|
|
47430
|
+
return canSortPivot(env.model.getters, position);
|
|
47431
|
+
},
|
|
47437
47432
|
})
|
|
47438
47433
|
.add("pivot_fix_formulas", {
|
|
47439
47434
|
...FIX_FORMULAS,
|
|
@@ -60699,6 +60694,42 @@ class Grid extends Component {
|
|
|
60699
60694
|
const supportedPivotPositionalFormulaRegistry = new Registry();
|
|
60700
60695
|
supportedPivotPositionalFormulaRegistry.add("SPREADSHEET", false);
|
|
60701
60696
|
|
|
60697
|
+
class ClickableCellSortIcon extends Component {
|
|
60698
|
+
static template = "o-spreadsheet-ClickableCellSortIcon";
|
|
60699
|
+
static props = {
|
|
60700
|
+
position: Object,
|
|
60701
|
+
sortDirection: String,
|
|
60702
|
+
};
|
|
60703
|
+
hoveredTableStore;
|
|
60704
|
+
setup() {
|
|
60705
|
+
this.hoveredTableStore = useStore(HoveredTableStore);
|
|
60706
|
+
}
|
|
60707
|
+
get style() {
|
|
60708
|
+
const cellStyle = this.env.model.getters.getCellComputedStyle(this.props.position);
|
|
60709
|
+
return cssPropertiesToCss({
|
|
60710
|
+
color: cellStyle.textColor || TEXT_BODY_MUTED,
|
|
60711
|
+
"background-color": this.getBackgroundColor(cellStyle),
|
|
60712
|
+
});
|
|
60713
|
+
}
|
|
60714
|
+
get icon() {
|
|
60715
|
+
switch (this.props.sortDirection) {
|
|
60716
|
+
case "asc":
|
|
60717
|
+
return "fa-sort-asc";
|
|
60718
|
+
case "desc":
|
|
60719
|
+
return "fa-sort-desc";
|
|
60720
|
+
default:
|
|
60721
|
+
return "fa-sort";
|
|
60722
|
+
}
|
|
60723
|
+
}
|
|
60724
|
+
getBackgroundColor(cellStyle) {
|
|
60725
|
+
const overlayColor = this.hoveredTableStore.overlayColors.get(this.props.position);
|
|
60726
|
+
if (overlayColor) {
|
|
60727
|
+
return blendColors(cellStyle.fillColor || "#FFFFFF", overlayColor);
|
|
60728
|
+
}
|
|
60729
|
+
return cellStyle.fillColor || "#FFFFFF";
|
|
60730
|
+
}
|
|
60731
|
+
}
|
|
60732
|
+
|
|
60702
60733
|
class FullScreenChart extends Component {
|
|
60703
60734
|
static template = "o-spreadsheet-FullScreenChart";
|
|
60704
60735
|
static props = {};
|
|
@@ -71055,6 +71086,7 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
71055
71086
|
static getters = [
|
|
71056
71087
|
"getPivot",
|
|
71057
71088
|
"getFirstPivotFunction",
|
|
71089
|
+
"getPivotCellSortDirection",
|
|
71058
71090
|
"getPivotIdFromPosition",
|
|
71059
71091
|
"getPivotCellFromPosition",
|
|
71060
71092
|
"generateNewCalculatedMeasureName",
|
|
@@ -71275,6 +71307,20 @@ class PivotUIPlugin extends CoreViewPlugin {
|
|
|
71275
71307
|
isPivotUnused(pivotId) {
|
|
71276
71308
|
return this._getUnusedPivots().includes(pivotId);
|
|
71277
71309
|
}
|
|
71310
|
+
getPivotCellSortDirection(position) {
|
|
71311
|
+
const pivotId = this.getters.getPivotIdFromPosition(position);
|
|
71312
|
+
const pivotCell = this.getters.getPivotCellFromPosition(position);
|
|
71313
|
+
if (pivotCell.type === "EMPTY" || pivotCell.type === "HEADER" || !pivotId) {
|
|
71314
|
+
return undefined;
|
|
71315
|
+
}
|
|
71316
|
+
const pivot = this.getters.getPivot(pivotId);
|
|
71317
|
+
const colDomain = domainToColRowDomain(pivot, pivotCell.domain).colDomain;
|
|
71318
|
+
const sortedColumn = pivot.definition.sortedColumn;
|
|
71319
|
+
if (sortedColumn?.measure === pivotCell.measure && deepEquals(sortedColumn.domain, colDomain)) {
|
|
71320
|
+
return sortedColumn.order;
|
|
71321
|
+
}
|
|
71322
|
+
return "none";
|
|
71323
|
+
}
|
|
71278
71324
|
// ---------------------------------------------------------------------
|
|
71279
71325
|
// Private
|
|
71280
71326
|
// ---------------------------------------------------------------------
|
|
@@ -78967,6 +79013,34 @@ clickableCellRegistry.add("link", {
|
|
|
78967
79013
|
},
|
|
78968
79014
|
sequence: 5,
|
|
78969
79015
|
});
|
|
79016
|
+
clickableCellRegistry.add("dashboard_pivot_sorting", {
|
|
79017
|
+
condition: (position, getters) => {
|
|
79018
|
+
if (!getters.isDashboard()) {
|
|
79019
|
+
return false;
|
|
79020
|
+
}
|
|
79021
|
+
const pivotCell = getters.getPivotCellFromPosition(position);
|
|
79022
|
+
return canSortPivot(getters, position) && pivotCell.type === "MEASURE_HEADER";
|
|
79023
|
+
},
|
|
79024
|
+
execute: (position, env) => {
|
|
79025
|
+
sortPivot(env, position, getNextSortDirection(env.model.getters, position));
|
|
79026
|
+
},
|
|
79027
|
+
component: ClickableCellSortIcon,
|
|
79028
|
+
componentProps: (position, getters) => {
|
|
79029
|
+
return {
|
|
79030
|
+
position,
|
|
79031
|
+
sortDirection: getters.getPivotCellSortDirection(position),
|
|
79032
|
+
};
|
|
79033
|
+
},
|
|
79034
|
+
sequence: 2,
|
|
79035
|
+
});
|
|
79036
|
+
const NEXT_SORT_DIRECTION = {
|
|
79037
|
+
none: "asc",
|
|
79038
|
+
asc: "desc",
|
|
79039
|
+
desc: "none",
|
|
79040
|
+
};
|
|
79041
|
+
function getNextSortDirection(getters, position) {
|
|
79042
|
+
return NEXT_SORT_DIRECTION[getters.getPivotCellSortDirection(position) ?? "none"];
|
|
79043
|
+
}
|
|
78970
79044
|
|
|
78971
79045
|
const inverseCommandRegistry = new Registry()
|
|
78972
79046
|
.add("ADD_COLUMNS_ROWS", inverseAddColumnsRows)
|
|
@@ -80683,6 +80757,8 @@ class ClickableCellsStore extends SpreadsheetStore {
|
|
|
80683
80757
|
position,
|
|
80684
80758
|
action: item.execute,
|
|
80685
80759
|
title: title || "",
|
|
80760
|
+
component: item.component,
|
|
80761
|
+
componentProps: item.componentProps?.(position, getters) ?? {},
|
|
80686
80762
|
});
|
|
80687
80763
|
}
|
|
80688
80764
|
return cells;
|
|
@@ -83029,6 +83105,27 @@ class Spreadsheet extends Component {
|
|
|
83029
83105
|
}
|
|
83030
83106
|
}
|
|
83031
83107
|
|
|
83108
|
+
class ReadonlyTransportFilter {
|
|
83109
|
+
transportService;
|
|
83110
|
+
constructor(transportService) {
|
|
83111
|
+
this.transportService = transportService;
|
|
83112
|
+
}
|
|
83113
|
+
async sendMessage(message) {
|
|
83114
|
+
if (message.type === "CLIENT_JOINED" ||
|
|
83115
|
+
message.type === "CLIENT_LEFT" ||
|
|
83116
|
+
message.type === "CLIENT_MOVED") {
|
|
83117
|
+
this.transportService.sendMessage(message);
|
|
83118
|
+
}
|
|
83119
|
+
// ignore all other messages
|
|
83120
|
+
}
|
|
83121
|
+
onNewMessage(id, callback) {
|
|
83122
|
+
this.transportService.onNewMessage(id, callback);
|
|
83123
|
+
}
|
|
83124
|
+
leave(id) {
|
|
83125
|
+
this.transportService.leave(id);
|
|
83126
|
+
}
|
|
83127
|
+
}
|
|
83128
|
+
|
|
83032
83129
|
function inverseCommand(cmd) {
|
|
83033
83130
|
return inverseCommandRegistry.get(cmd.type)(cmd);
|
|
83034
83131
|
}
|
|
@@ -87121,12 +87218,15 @@ class Model extends EventBus {
|
|
|
87121
87218
|
name: _t("Anonymous").toString(),
|
|
87122
87219
|
};
|
|
87123
87220
|
const transportService = config.transportService || new LocalTransportService();
|
|
87221
|
+
const isReadonly = config.mode === "readonly" || config.mode === "dashboard";
|
|
87124
87222
|
return {
|
|
87125
87223
|
...config,
|
|
87126
87224
|
mode: config.mode || "normal",
|
|
87127
87225
|
custom: config.custom || {},
|
|
87128
87226
|
external: this.setupExternalConfig(config.external || {}),
|
|
87129
|
-
transportService
|
|
87227
|
+
transportService: isReadonly
|
|
87228
|
+
? new ReadonlyTransportFilter(transportService)
|
|
87229
|
+
: transportService,
|
|
87130
87230
|
client,
|
|
87131
87231
|
moveClient: () => { },
|
|
87132
87232
|
snapshotRequested: false,
|
|
@@ -87539,6 +87639,7 @@ const components = {
|
|
|
87539
87639
|
ChartPanel,
|
|
87540
87640
|
ChartFigure,
|
|
87541
87641
|
ChartJsComponent,
|
|
87642
|
+
ClickableCellSortIcon,
|
|
87542
87643
|
ZoomableChartJsComponent,
|
|
87543
87644
|
Grid,
|
|
87544
87645
|
GridOverlay,
|
|
@@ -87624,12 +87725,14 @@ const constants = {
|
|
|
87624
87725
|
PIVOT_TABLE_CONFIG,
|
|
87625
87726
|
ChartTerms,
|
|
87626
87727
|
FIGURE_ID_SPLITTER,
|
|
87728
|
+
GRID_ICON_EDGE_LENGTH,
|
|
87729
|
+
GRID_ICON_MARGIN,
|
|
87627
87730
|
};
|
|
87628
87731
|
const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
87629
87732
|
|
|
87630
87733
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, LocalTransportService, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
87631
87734
|
|
|
87632
87735
|
|
|
87633
|
-
__info__.version = "18.5.0-alpha.
|
|
87634
|
-
__info__.date = "2025-08-
|
|
87635
|
-
__info__.hash = "
|
|
87736
|
+
__info__.version = "18.5.0-alpha.12";
|
|
87737
|
+
__info__.date = "2025-08-29T08:05:09.767Z";
|
|
87738
|
+
__info__.hash = "8ee7677";
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 18.5.0-alpha.
|
|
6
|
-
* @date 2025-08-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.5.0-alpha.12
|
|
6
|
+
* @date 2025-08-29T08:05:09.767Z
|
|
7
|
+
* @hash 8ee7677
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -1346,6 +1346,18 @@
|
|
|
1346
1346
|
function hexToHSLA(hex) {
|
|
1347
1347
|
return rgbaToHSLA(colorToRGBA(hex));
|
|
1348
1348
|
}
|
|
1349
|
+
/**
|
|
1350
|
+
* Blend color2 on top of color1, with alpha blending.
|
|
1351
|
+
*/
|
|
1352
|
+
function blendColors(color1, color2) {
|
|
1353
|
+
const rgba2 = colorToRGBA(color2);
|
|
1354
|
+
const rgba1 = colorToRGBA(color1);
|
|
1355
|
+
const a = rgba2.a + rgba1.a * (1 - rgba2.a);
|
|
1356
|
+
const r = Math.round((rgba2.r * rgba2.a + rgba1.r * rgba1.a * (1 - rgba2.a)) / a);
|
|
1357
|
+
const g = Math.round((rgba2.g * rgba2.a + rgba1.g * rgba1.a * (1 - rgba2.a)) / a);
|
|
1358
|
+
const b = Math.round((rgba2.b * rgba2.a + rgba1.b * rgba1.a * (1 - rgba2.a)) / a);
|
|
1359
|
+
return rgbaToHex({ r, g, b, a });
|
|
1360
|
+
}
|
|
1349
1361
|
function colorOrNumberToRGBA(color) {
|
|
1350
1362
|
if (typeof color === "number") {
|
|
1351
1363
|
return colorToRGBA(colorNumberToHex(color));
|
|
@@ -2660,6 +2672,7 @@
|
|
|
2660
2672
|
"AUTOFILL_CELL",
|
|
2661
2673
|
"SET_BORDER",
|
|
2662
2674
|
"SET_ZONE_BORDERS",
|
|
2675
|
+
"SET_BORDERS_ON_TARGET",
|
|
2663
2676
|
]);
|
|
2664
2677
|
const invalidSubtotalFormulasCommands = new Set([
|
|
2665
2678
|
"UNHIDE_COLUMNS_ROWS",
|
|
@@ -2687,6 +2700,7 @@
|
|
|
2687
2700
|
"UPDATE_FILTER",
|
|
2688
2701
|
"UPDATE_CHART",
|
|
2689
2702
|
"UPDATE_CAROUSEL_ACTIVE_ITEM",
|
|
2703
|
+
"UPDATE_PIVOT",
|
|
2690
2704
|
]);
|
|
2691
2705
|
const coreTypes = new Set([
|
|
2692
2706
|
/** CELLS */
|
|
@@ -46925,18 +46939,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46925
46939
|
};
|
|
46926
46940
|
const pivotSortingAsc = {
|
|
46927
46941
|
name: _t("Ascending"),
|
|
46928
|
-
execute: (env) => sortPivot(env, "asc"),
|
|
46929
|
-
isActive: (env) =>
|
|
46942
|
+
execute: (env) => sortPivot(env, env.model.getters.getActivePosition(), "asc"),
|
|
46943
|
+
isActive: (env) => env.model.getters.getPivotCellSortDirection(env.model.getters.getActivePosition()) === "asc",
|
|
46930
46944
|
};
|
|
46931
46945
|
const pivotSortingDesc = {
|
|
46932
46946
|
name: _t("Descending"),
|
|
46933
|
-
execute: (env) => sortPivot(env, "desc"),
|
|
46934
|
-
isActive: (env) =>
|
|
46947
|
+
execute: (env) => sortPivot(env, env.model.getters.getActivePosition(), "desc"),
|
|
46948
|
+
isActive: (env) => env.model.getters.getPivotCellSortDirection(env.model.getters.getActivePosition()) === "desc",
|
|
46935
46949
|
};
|
|
46936
46950
|
const noPivotSorting = {
|
|
46937
46951
|
name: _t("No sorting"),
|
|
46938
|
-
execute: (env) => sortPivot(env, "none"),
|
|
46939
|
-
isActive: (env) =>
|
|
46952
|
+
execute: (env) => sortPivot(env, env.model.getters.getActivePosition(), "none"),
|
|
46953
|
+
isActive: (env) => env.model.getters.getPivotCellSortDirection(env.model.getters.getActivePosition()) === "none",
|
|
46940
46954
|
};
|
|
46941
46955
|
const FIX_FORMULAS = {
|
|
46942
46956
|
name: _t("Convert to individual formulas"),
|
|
@@ -47072,23 +47086,19 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
47072
47086
|
return areFieldValuesInGroups(definition, values, field, pivot.getFields());
|
|
47073
47087
|
},
|
|
47074
47088
|
};
|
|
47075
|
-
function canSortPivot(
|
|
47076
|
-
const
|
|
47077
|
-
|
|
47078
|
-
if (!pivotId ||
|
|
47079
|
-
!env.model.getters.isExistingPivot(pivotId) ||
|
|
47080
|
-
!env.model.getters.isSpillPivotFormula(position)) {
|
|
47089
|
+
function canSortPivot(getters, position) {
|
|
47090
|
+
const pivotId = getters.getPivotIdFromPosition(position);
|
|
47091
|
+
if (!pivotId || !getters.isExistingPivot(pivotId) || !getters.isSpillPivotFormula(position)) {
|
|
47081
47092
|
return false;
|
|
47082
47093
|
}
|
|
47083
|
-
const pivot =
|
|
47094
|
+
const pivot = getters.getPivot(pivotId);
|
|
47084
47095
|
if (!pivot.isValid()) {
|
|
47085
47096
|
return false;
|
|
47086
47097
|
}
|
|
47087
|
-
const pivotCell =
|
|
47098
|
+
const pivotCell = getters.getPivotCellFromPosition(position);
|
|
47088
47099
|
return pivotCell.type === "VALUE" || pivotCell.type === "MEASURE_HEADER";
|
|
47089
47100
|
}
|
|
47090
|
-
function sortPivot(env, order) {
|
|
47091
|
-
const position = env.model.getters.getActivePosition();
|
|
47101
|
+
function sortPivot(env, position, order) {
|
|
47092
47102
|
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
47093
47103
|
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
47094
47104
|
if (pivotCell.type === "EMPTY" || pivotCell.type === "HEADER" || !pivotId) {
|
|
@@ -47114,24 +47124,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
47114
47124
|
},
|
|
47115
47125
|
});
|
|
47116
47126
|
}
|
|
47117
|
-
function isPivotSortMenuItemActive(env, order) {
|
|
47118
|
-
const position = env.model.getters.getActivePosition();
|
|
47119
|
-
const pivotId = env.model.getters.getPivotIdFromPosition(position);
|
|
47120
|
-
const pivotCell = env.model.getters.getPivotCellFromPosition(position);
|
|
47121
|
-
if (pivotCell.type === "EMPTY" || pivotCell.type === "HEADER" || !pivotId) {
|
|
47122
|
-
return false;
|
|
47123
|
-
}
|
|
47124
|
-
const pivot = env.model.getters.getPivot(pivotId);
|
|
47125
|
-
const colDomain = domainToColRowDomain(pivot, pivotCell.domain).colDomain;
|
|
47126
|
-
const sortedColumn = pivot.definition.sortedColumn;
|
|
47127
|
-
if (order === "none") {
|
|
47128
|
-
return !sortedColumn;
|
|
47129
|
-
}
|
|
47130
|
-
if (!sortedColumn || sortedColumn.order !== order) {
|
|
47131
|
-
return false;
|
|
47132
|
-
}
|
|
47133
|
-
return sortedColumn.measure === pivotCell.measure && deepEquals(sortedColumn.domain, colDomain);
|
|
47134
|
-
}
|
|
47135
47127
|
/*
|
|
47136
47128
|
* Get the values of the pivot headers in the current selection, if all the pivot headers on the selection belong
|
|
47137
47129
|
* to the same pivot, the same field and that the pivot formula is a dynamic pivot. Otherwise return undefined.
|
|
@@ -47434,7 +47426,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
47434
47426
|
name: _t("Sort pivot"),
|
|
47435
47427
|
sequence: 155,
|
|
47436
47428
|
icon: "o-spreadsheet-Icon.SORT_RANGE",
|
|
47437
|
-
isVisible:
|
|
47429
|
+
isVisible: (env) => {
|
|
47430
|
+
const position = env.model.getters.getActivePosition();
|
|
47431
|
+
return canSortPivot(env.model.getters, position);
|
|
47432
|
+
},
|
|
47438
47433
|
})
|
|
47439
47434
|
.add("pivot_fix_formulas", {
|
|
47440
47435
|
...FIX_FORMULAS,
|
|
@@ -60700,6 +60695,42 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60700
60695
|
const supportedPivotPositionalFormulaRegistry = new Registry();
|
|
60701
60696
|
supportedPivotPositionalFormulaRegistry.add("SPREADSHEET", false);
|
|
60702
60697
|
|
|
60698
|
+
class ClickableCellSortIcon extends owl.Component {
|
|
60699
|
+
static template = "o-spreadsheet-ClickableCellSortIcon";
|
|
60700
|
+
static props = {
|
|
60701
|
+
position: Object,
|
|
60702
|
+
sortDirection: String,
|
|
60703
|
+
};
|
|
60704
|
+
hoveredTableStore;
|
|
60705
|
+
setup() {
|
|
60706
|
+
this.hoveredTableStore = useStore(HoveredTableStore);
|
|
60707
|
+
}
|
|
60708
|
+
get style() {
|
|
60709
|
+
const cellStyle = this.env.model.getters.getCellComputedStyle(this.props.position);
|
|
60710
|
+
return cssPropertiesToCss({
|
|
60711
|
+
color: cellStyle.textColor || TEXT_BODY_MUTED,
|
|
60712
|
+
"background-color": this.getBackgroundColor(cellStyle),
|
|
60713
|
+
});
|
|
60714
|
+
}
|
|
60715
|
+
get icon() {
|
|
60716
|
+
switch (this.props.sortDirection) {
|
|
60717
|
+
case "asc":
|
|
60718
|
+
return "fa-sort-asc";
|
|
60719
|
+
case "desc":
|
|
60720
|
+
return "fa-sort-desc";
|
|
60721
|
+
default:
|
|
60722
|
+
return "fa-sort";
|
|
60723
|
+
}
|
|
60724
|
+
}
|
|
60725
|
+
getBackgroundColor(cellStyle) {
|
|
60726
|
+
const overlayColor = this.hoveredTableStore.overlayColors.get(this.props.position);
|
|
60727
|
+
if (overlayColor) {
|
|
60728
|
+
return blendColors(cellStyle.fillColor || "#FFFFFF", overlayColor);
|
|
60729
|
+
}
|
|
60730
|
+
return cellStyle.fillColor || "#FFFFFF";
|
|
60731
|
+
}
|
|
60732
|
+
}
|
|
60733
|
+
|
|
60703
60734
|
class FullScreenChart extends owl.Component {
|
|
60704
60735
|
static template = "o-spreadsheet-FullScreenChart";
|
|
60705
60736
|
static props = {};
|
|
@@ -71056,6 +71087,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71056
71087
|
static getters = [
|
|
71057
71088
|
"getPivot",
|
|
71058
71089
|
"getFirstPivotFunction",
|
|
71090
|
+
"getPivotCellSortDirection",
|
|
71059
71091
|
"getPivotIdFromPosition",
|
|
71060
71092
|
"getPivotCellFromPosition",
|
|
71061
71093
|
"generateNewCalculatedMeasureName",
|
|
@@ -71276,6 +71308,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71276
71308
|
isPivotUnused(pivotId) {
|
|
71277
71309
|
return this._getUnusedPivots().includes(pivotId);
|
|
71278
71310
|
}
|
|
71311
|
+
getPivotCellSortDirection(position) {
|
|
71312
|
+
const pivotId = this.getters.getPivotIdFromPosition(position);
|
|
71313
|
+
const pivotCell = this.getters.getPivotCellFromPosition(position);
|
|
71314
|
+
if (pivotCell.type === "EMPTY" || pivotCell.type === "HEADER" || !pivotId) {
|
|
71315
|
+
return undefined;
|
|
71316
|
+
}
|
|
71317
|
+
const pivot = this.getters.getPivot(pivotId);
|
|
71318
|
+
const colDomain = domainToColRowDomain(pivot, pivotCell.domain).colDomain;
|
|
71319
|
+
const sortedColumn = pivot.definition.sortedColumn;
|
|
71320
|
+
if (sortedColumn?.measure === pivotCell.measure && deepEquals(sortedColumn.domain, colDomain)) {
|
|
71321
|
+
return sortedColumn.order;
|
|
71322
|
+
}
|
|
71323
|
+
return "none";
|
|
71324
|
+
}
|
|
71279
71325
|
// ---------------------------------------------------------------------
|
|
71280
71326
|
// Private
|
|
71281
71327
|
// ---------------------------------------------------------------------
|
|
@@ -78968,6 +79014,34 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78968
79014
|
},
|
|
78969
79015
|
sequence: 5,
|
|
78970
79016
|
});
|
|
79017
|
+
clickableCellRegistry.add("dashboard_pivot_sorting", {
|
|
79018
|
+
condition: (position, getters) => {
|
|
79019
|
+
if (!getters.isDashboard()) {
|
|
79020
|
+
return false;
|
|
79021
|
+
}
|
|
79022
|
+
const pivotCell = getters.getPivotCellFromPosition(position);
|
|
79023
|
+
return canSortPivot(getters, position) && pivotCell.type === "MEASURE_HEADER";
|
|
79024
|
+
},
|
|
79025
|
+
execute: (position, env) => {
|
|
79026
|
+
sortPivot(env, position, getNextSortDirection(env.model.getters, position));
|
|
79027
|
+
},
|
|
79028
|
+
component: ClickableCellSortIcon,
|
|
79029
|
+
componentProps: (position, getters) => {
|
|
79030
|
+
return {
|
|
79031
|
+
position,
|
|
79032
|
+
sortDirection: getters.getPivotCellSortDirection(position),
|
|
79033
|
+
};
|
|
79034
|
+
},
|
|
79035
|
+
sequence: 2,
|
|
79036
|
+
});
|
|
79037
|
+
const NEXT_SORT_DIRECTION = {
|
|
79038
|
+
none: "asc",
|
|
79039
|
+
asc: "desc",
|
|
79040
|
+
desc: "none",
|
|
79041
|
+
};
|
|
79042
|
+
function getNextSortDirection(getters, position) {
|
|
79043
|
+
return NEXT_SORT_DIRECTION[getters.getPivotCellSortDirection(position) ?? "none"];
|
|
79044
|
+
}
|
|
78971
79045
|
|
|
78972
79046
|
const inverseCommandRegistry = new Registry()
|
|
78973
79047
|
.add("ADD_COLUMNS_ROWS", inverseAddColumnsRows)
|
|
@@ -80684,6 +80758,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
80684
80758
|
position,
|
|
80685
80759
|
action: item.execute,
|
|
80686
80760
|
title: title || "",
|
|
80761
|
+
component: item.component,
|
|
80762
|
+
componentProps: item.componentProps?.(position, getters) ?? {},
|
|
80687
80763
|
});
|
|
80688
80764
|
}
|
|
80689
80765
|
return cells;
|
|
@@ -83030,6 +83106,27 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83030
83106
|
}
|
|
83031
83107
|
}
|
|
83032
83108
|
|
|
83109
|
+
class ReadonlyTransportFilter {
|
|
83110
|
+
transportService;
|
|
83111
|
+
constructor(transportService) {
|
|
83112
|
+
this.transportService = transportService;
|
|
83113
|
+
}
|
|
83114
|
+
async sendMessage(message) {
|
|
83115
|
+
if (message.type === "CLIENT_JOINED" ||
|
|
83116
|
+
message.type === "CLIENT_LEFT" ||
|
|
83117
|
+
message.type === "CLIENT_MOVED") {
|
|
83118
|
+
this.transportService.sendMessage(message);
|
|
83119
|
+
}
|
|
83120
|
+
// ignore all other messages
|
|
83121
|
+
}
|
|
83122
|
+
onNewMessage(id, callback) {
|
|
83123
|
+
this.transportService.onNewMessage(id, callback);
|
|
83124
|
+
}
|
|
83125
|
+
leave(id) {
|
|
83126
|
+
this.transportService.leave(id);
|
|
83127
|
+
}
|
|
83128
|
+
}
|
|
83129
|
+
|
|
83033
83130
|
function inverseCommand(cmd) {
|
|
83034
83131
|
return inverseCommandRegistry.get(cmd.type)(cmd);
|
|
83035
83132
|
}
|
|
@@ -87122,12 +87219,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
87122
87219
|
name: _t("Anonymous").toString(),
|
|
87123
87220
|
};
|
|
87124
87221
|
const transportService = config.transportService || new LocalTransportService();
|
|
87222
|
+
const isReadonly = config.mode === "readonly" || config.mode === "dashboard";
|
|
87125
87223
|
return {
|
|
87126
87224
|
...config,
|
|
87127
87225
|
mode: config.mode || "normal",
|
|
87128
87226
|
custom: config.custom || {},
|
|
87129
87227
|
external: this.setupExternalConfig(config.external || {}),
|
|
87130
|
-
transportService
|
|
87228
|
+
transportService: isReadonly
|
|
87229
|
+
? new ReadonlyTransportFilter(transportService)
|
|
87230
|
+
: transportService,
|
|
87131
87231
|
client,
|
|
87132
87232
|
moveClient: () => { },
|
|
87133
87233
|
snapshotRequested: false,
|
|
@@ -87540,6 +87640,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
87540
87640
|
ChartPanel,
|
|
87541
87641
|
ChartFigure,
|
|
87542
87642
|
ChartJsComponent,
|
|
87643
|
+
ClickableCellSortIcon,
|
|
87543
87644
|
ZoomableChartJsComponent,
|
|
87544
87645
|
Grid,
|
|
87545
87646
|
GridOverlay,
|
|
@@ -87625,6 +87726,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
87625
87726
|
PIVOT_TABLE_CONFIG,
|
|
87626
87727
|
ChartTerms,
|
|
87627
87728
|
FIGURE_ID_SPLITTER,
|
|
87729
|
+
GRID_ICON_EDGE_LENGTH,
|
|
87730
|
+
GRID_ICON_MARGIN,
|
|
87628
87731
|
};
|
|
87629
87732
|
const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
87630
87733
|
|
|
@@ -87679,9 +87782,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
87679
87782
|
exports.tokenize = tokenize;
|
|
87680
87783
|
|
|
87681
87784
|
|
|
87682
|
-
__info__.version = "18.5.0-alpha.
|
|
87683
|
-
__info__.date = "2025-08-
|
|
87684
|
-
__info__.hash = "
|
|
87785
|
+
__info__.version = "18.5.0-alpha.12";
|
|
87786
|
+
__info__.date = "2025-08-29T08:05:09.767Z";
|
|
87787
|
+
__info__.hash = "8ee7677";
|
|
87685
87788
|
|
|
87686
87789
|
|
|
87687
87790
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|