@odoo/o-spreadsheet 17.3.2 → 17.3.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.
@@ -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.3.2
7
- * @date 2024-06-10T09:38:56.657Z
8
- * @hash c3b358f
6
+ * @version 17.3.3
7
+ * @date 2024-06-14T10:02:58.082Z
8
+ * @hash c690e9f
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';
@@ -2779,7 +2779,7 @@ function evaluatePredicate(value, criterion) {
2779
2779
  return false;
2780
2780
  }
2781
2781
  if (typeof operand === "number" && operator === "=") {
2782
- return toString(value) === toString(operand);
2782
+ return value.toString() === operand.toString();
2783
2783
  }
2784
2784
  if (operator === "<>" || operator === "=") {
2785
2785
  let result;
@@ -2839,14 +2839,13 @@ function visitMatchingRanges(args, cb, locale, isQuery = false) {
2839
2839
  if (countArg % 2 === 1) {
2840
2840
  throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects criteria_range and criterion to be in pairs."));
2841
2841
  }
2842
- const dimRow = args[0].length;
2843
- const dimCol = args[0][0].length;
2842
+ const firstArg = toMatrix(args[0]);
2843
+ const dimRow = firstArg.length;
2844
+ const dimCol = firstArg[0].length;
2844
2845
  let predicates = [];
2845
2846
  for (let i = 0; i < countArg - 1; i += 2) {
2846
- const criteriaRange = args[i];
2847
- if (!isMatrix(criteriaRange) ||
2848
- criteriaRange.length !== dimRow ||
2849
- criteriaRange[0].length !== dimCol) {
2847
+ const criteriaRange = toMatrix(args[i]);
2848
+ if (criteriaRange.length !== dimRow || criteriaRange[0].length !== dimCol) {
2850
2849
  throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects criteria_range to have the same dimension"));
2851
2850
  }
2852
2851
  const description = toString(args[i + 1]);
@@ -2860,7 +2859,7 @@ function visitMatchingRanges(args, cb, locale, isQuery = false) {
2860
2859
  for (let j = 0; j < dimCol; j++) {
2861
2860
  let validatedPredicates = true;
2862
2861
  for (let k = 0; k < countArg - 1; k += 2) {
2863
- const criteriaValue = args[k][i][j].value;
2862
+ const criteriaValue = toMatrix(args[k])[i][j].value;
2864
2863
  const criterion = predicates[k / 2];
2865
2864
  validatedPredicates = evaluatePredicate(criteriaValue ?? undefined, criterion);
2866
2865
  if (!validatedPredicates) {
@@ -10988,6 +10987,9 @@ function makeArg(str, description) {
10988
10987
  if (types.some((t) => t.startsWith("RANGE"))) {
10989
10988
  result.acceptMatrix = true;
10990
10989
  }
10990
+ if (types.every((t) => t.startsWith("RANGE"))) {
10991
+ result.acceptMatrixOnly = true;
10992
+ }
10991
10993
  return result;
10992
10994
  }
10993
10995
  /**
@@ -11269,11 +11271,16 @@ const CHOOSECOLS = {
11269
11271
  compute: function (array, ...columns) {
11270
11272
  const _array = toMatrix(array);
11271
11273
  const _columns = flattenRowFirst(columns, (item) => toInteger(item?.value, this.locale));
11272
- assert(() => _columns.every((col) => col > 0 && col <= _array.length), _t("The columns arguments must be between 1 and %s (got %s).", _array.length.toString(), (_columns.find((col) => col <= 0 || col > _array.length) || 0).toString()));
11274
+ const argOutOfRange = _columns.filter((col) => col === 0 || _array.length < Math.abs(col));
11275
+ assert(() => argOutOfRange.length === 0, _t("The columns arguments must be between -%s and %s (got %s), excluding 0.", _array.length.toString(), _array.length.toString(), argOutOfRange.join(",")));
11273
11276
  const result = Array(_columns.length);
11274
11277
  for (let col = 0; col < _columns.length; col++) {
11275
- const colIndex = _columns[col] - 1; // -1 because columns arguments are 1-indexed
11276
- result[col] = _array[colIndex];
11278
+ if (_columns[col] > 0) {
11279
+ result[col] = _array[_columns[col] - 1]; // -1 because columns arguments are 1-indexed
11280
+ }
11281
+ else {
11282
+ result[col] = _array[_array.length + _columns[col]];
11283
+ }
11277
11284
  }
11278
11285
  return result;
11279
11286
  },
@@ -11294,8 +11301,14 @@ const CHOOSEROWS = {
11294
11301
  const _array = toMatrix(array);
11295
11302
  const _rows = flattenRowFirst(rows, (item) => toInteger(item?.value, this.locale));
11296
11303
  const _nbColumns = _array.length;
11297
- assert(() => _rows.every((row) => row > 0 && row <= _array[0].length), _t("The rows arguments must be between 1 and %s (got %s).", _array[0].length.toString(), (_rows.find((row) => row <= 0 || row > _array[0].length) || 0).toString()));
11298
- return generateMatrix(_nbColumns, _rows.length, (col, row) => _array[col][_rows[row] - 1]); // -1 because rows arguments are 1-indexed
11304
+ const argOutOfRange = _rows.filter((row) => row === 0 || _array[0].length < Math.abs(row));
11305
+ assert(() => argOutOfRange.length === 0, _t("The rows arguments must be between -%s and %s (got %s), excluding 0.", _array[0].length.toString(), _array[0].length.toString(), argOutOfRange.join(",")));
11306
+ return generateMatrix(_nbColumns, _rows.length, (col, row) => {
11307
+ if (_rows[row] > 0) {
11308
+ return _array[col][_rows[row] - 1]; // -1 because columns arguments are 1-indexed
11309
+ }
11310
+ return _array[col][_array[col].length + _rows[row]];
11311
+ });
11299
11312
  },
11300
11313
  isExported: true,
11301
11314
  };
@@ -19762,6 +19775,9 @@ function addInputHandling(descr) {
19762
19775
  }
19763
19776
  args[i] = arg[0][0];
19764
19777
  }
19778
+ if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) {
19779
+ throw new BadExpressionError(_t("Function [[FUNCTION_NAME]] expects the parameter '%s' to be reference to a cell or range.", (i + 1).toString()));
19780
+ }
19765
19781
  }
19766
19782
  return descr.compute.apply(this, args);
19767
19783
  }
@@ -21356,12 +21372,6 @@ function compileTokens(tokens) {
21356
21372
  // detect when an argument need to be evaluated as a meta argument
21357
21373
  const isMeta = argTypes.includes("META");
21358
21374
  const hasRange = argTypes.some((t) => isRangeType(t));
21359
- const isRangeOnly = argTypes.every((t) => isRangeType(t));
21360
- if (isRangeOnly) {
21361
- if (!isRangeInput(currentArg)) {
21362
- throw new BadExpressionError(_t("Function %(function_name)s expects the parameter %(arg_index)s to be a reference to a cell or a range.", { function_name: functionName, arg_index: i + 1 }));
21363
- }
21364
- }
21365
21375
  compiledArgs.push(compileAST(currentArg, isMeta, hasRange));
21366
21376
  }
21367
21377
  return compiledArgs;
@@ -21526,16 +21536,6 @@ function assertEnoughArgs(ast) {
21526
21536
  function isRangeType(type) {
21527
21537
  return type.startsWith("RANGE");
21528
21538
  }
21529
- function isRangeInput(arg) {
21530
- if (arg.type === "REFERENCE") {
21531
- return true;
21532
- }
21533
- if (arg.type === "FUNCALL") {
21534
- const fnDef = functions$1[arg.value.toUpperCase()];
21535
- return fnDef && isRangeType(fnDef.returns[0]);
21536
- }
21537
- return false;
21538
- }
21539
21539
 
21540
21540
  const functions = functionRegistry.content;
21541
21541
  function isExportableToExcel(tokens) {
@@ -21964,7 +21964,9 @@ autoCompleteProviders.add("pivot_group_values", {
21964
21964
  if (!groupByField) {
21965
21965
  return;
21966
21966
  }
21967
- return dataSource.getPossibleFieldValues(groupByField.split(":")[0]).map(({ value, label }) => {
21967
+ return dataSource
21968
+ .getPossibleFieldValues(groupByField.toString().split(":")[0])
21969
+ .map(({ value, label }) => {
21968
21970
  const isString = typeof value === "string";
21969
21971
  const text = isString ? `"${value}"` : value.toString();
21970
21972
  const color = isString ? tokenColors.STRING : tokenColors.NUMBER;
@@ -25450,7 +25452,7 @@ class Popover extends Component {
25450
25452
  if (!anchor)
25451
25453
  return;
25452
25454
  const propsMaxSize = { width: this.props.maxWidth, height: this.props.maxHeight };
25453
- const elDims = {
25455
+ let elDims = {
25454
25456
  width: el.getBoundingClientRect().width,
25455
25457
  height: el.getBoundingClientRect().height,
25456
25458
  };
@@ -25458,7 +25460,14 @@ class Popover extends Component {
25458
25460
  const popoverPositionHelper = this.props.positioning === "BottomLeft"
25459
25461
  ? new BottomLeftPopoverContext(anchor, this.containerRect, propsMaxSize, spreadsheetRect)
25460
25462
  : new TopRightPopoverContext(anchor, this.containerRect, propsMaxSize, spreadsheetRect);
25461
- const style = popoverPositionHelper.getCss(elDims, this.props.verticalOffset);
25463
+ el.style["max-height"] = popoverPositionHelper.getMaxHeight(elDims.height) + "px";
25464
+ el.style["max-width"] = popoverPositionHelper.getMaxWidth(elDims.width) + "px";
25465
+ // Re-compute the dimensions after setting the max-width and max-height
25466
+ elDims = {
25467
+ width: el.getBoundingClientRect().width,
25468
+ height: el.getBoundingClientRect().height,
25469
+ };
25470
+ let style = popoverPositionHelper.getCss(elDims, this.props.verticalOffset);
25462
25471
  for (const property of Object.keys(style)) {
25463
25472
  el.style[property] = style[property];
25464
25473
  }
@@ -25521,8 +25530,6 @@ class PopoverPositionContext {
25521
25530
  const shouldRenderAtRight = this.shouldRenderAtRight(elDims.width);
25522
25531
  verticalOffset = shouldRenderAtBottom ? verticalOffset : -verticalOffset;
25523
25532
  const cssProperties = {
25524
- "max-height": maxHeight + "px",
25525
- "max-width": maxWidth + "px",
25526
25533
  top: this.getTopCoordinate(actualHeight, shouldRenderAtBottom) -
25527
25534
  this.spreadsheetOffset.y -
25528
25535
  verticalOffset +
@@ -31336,10 +31343,8 @@ class ChartTitle extends Component {
31336
31343
 
31337
31344
  class AxisDesignEditor extends Component {
31338
31345
  static template = "o-spreadsheet-AxisDesignEditor";
31339
- static components = {
31340
- Section,
31341
- ChartTitle,
31342
- };
31346
+ static components = { Section, ChartTitle };
31347
+ static props = { figureId: String, definition: Object, updateChart: Function, axesList: Array };
31343
31348
  state = useState({ currentAxis: "x" });
31344
31349
  get axisTitleStyle() {
31345
31350
  const axisDesign = this.props.definition.axesDesign?.[this.state.currentAxis] ?? {};
@@ -31490,6 +31495,12 @@ class ChartWithAxisDesignPanel extends Component {
31490
31495
  AxisDesignEditor,
31491
31496
  RoundColorPicker,
31492
31497
  };
31498
+ static props = {
31499
+ figureId: String,
31500
+ definition: Object,
31501
+ canUpdateChart: Function,
31502
+ updateChart: Function,
31503
+ };
31493
31504
  state = useState({ index: 0 });
31494
31505
  get axesList() {
31495
31506
  const { useLeftAxis, useRightAxis } = getDefinedAxis(this.props.definition);
@@ -31671,14 +31682,6 @@ class GaugeChartDesignPanel extends Component {
31671
31682
  const cancelledReasons = [...(this.state.sectionRuleDispatchResult?.reasons || [])];
31672
31683
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
31673
31684
  }
31674
- updateBackgroundColor(color) {
31675
- this.props.updateChart(this.props.figureId, {
31676
- background: color,
31677
- });
31678
- }
31679
- updateTitle(content) {
31680
- this.props.updateChart(this.props.figureId, { title: { text: content } });
31681
- }
31682
31685
  isRangeMinInvalid() {
31683
31686
  return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause("EmptyGaugeRangeMin" /* CommandResult.EmptyGaugeRangeMin */) ||
31684
31687
  this.state.sectionRuleDispatchResult?.isCancelledBecause("GaugeRangeMinNaN" /* CommandResult.GaugeRangeMinNaN */) ||
@@ -31718,9 +31721,6 @@ class GaugeChartDesignPanel extends Component {
31718
31721
  sectionRule,
31719
31722
  });
31720
31723
  }
31721
- get backgroundColorTitle() {
31722
- return ChartTerms.BackgroundColor;
31723
- }
31724
31724
  }
31725
31725
 
31726
31726
  class LineConfigPanel extends GenericChartConfigPanel {
@@ -31903,9 +31903,6 @@ class ScorecardChartDesignPanel extends Component {
31903
31903
  get humanizeNumbersLabel() {
31904
31904
  return _t("Humanize numbers");
31905
31905
  }
31906
- updateTitle(content) {
31907
- this.props.updateChart(this.props.figureId, { title: { text: content } });
31908
- }
31909
31906
  updateHumanizeNumbers(humanize) {
31910
31907
  this.props.updateChart(this.props.figureId, { humanize });
31911
31908
  }
@@ -31928,9 +31925,6 @@ class ScorecardChartDesignPanel extends Component {
31928
31925
  break;
31929
31926
  }
31930
31927
  }
31931
- get backgroundColorTitle() {
31932
- return ChartTerms.BackgroundColor;
31933
- }
31934
31928
  }
31935
31929
 
31936
31930
  class WaterfallChartDesignPanel extends Component {
@@ -33431,13 +33425,17 @@ class SelectMenu extends Component {
33431
33425
  class: { type: String, optional: true },
33432
33426
  };
33433
33427
  static components = { Menu };
33428
+ menuId = new UuidGenerator().uuidv4();
33434
33429
  selectRef = useRef("select");
33435
33430
  selectRect = useAbsoluteBoundingRect(this.selectRef);
33436
33431
  state = useState({
33437
33432
  isMenuOpen: false,
33438
33433
  });
33439
- onClick() {
33440
- this.state.isMenuOpen = true;
33434
+ onClick(ev) {
33435
+ if (ev.closedMenuId === this.menuId) {
33436
+ return;
33437
+ }
33438
+ this.state.isMenuOpen = !this.state.isMenuOpen;
33441
33439
  }
33442
33440
  onMenuClosed() {
33443
33441
  this.state.isMenuOpen = false;
@@ -33445,7 +33443,7 @@ class SelectMenu extends Component {
33445
33443
  get menuPosition() {
33446
33444
  return {
33447
33445
  x: this.selectRect.x,
33448
- y: this.selectRect.y,
33446
+ y: this.selectRect.y + this.selectRect.height,
33449
33447
  };
33450
33448
  }
33451
33449
  }
@@ -34385,9 +34383,9 @@ class FindAndReplacePanel extends Component {
34385
34383
  static props = {
34386
34384
  onCloseSidePanel: Function,
34387
34385
  };
34388
- dataRange = "";
34389
34386
  searchInput = useRef("searchInput");
34390
34387
  store;
34388
+ state;
34391
34389
  get hasSearchResult() {
34392
34390
  return this.store.selectedMatchIndex !== null;
34393
34391
  }
@@ -34417,6 +34415,7 @@ class FindAndReplacePanel extends Component {
34417
34415
  }
34418
34416
  setup() {
34419
34417
  this.store = useLocalStore(FindAndReplaceStore);
34418
+ this.state = useState({ dataRange: "" });
34420
34419
  onMounted(() => this.searchInput.el?.focus());
34421
34420
  }
34422
34421
  onFocusSearch() {
@@ -34453,13 +34452,13 @@ class FindAndReplacePanel extends Component {
34453
34452
  this.store.updateSearchOptions({ searchScope });
34454
34453
  }
34455
34454
  onSearchRangeChanged(ranges) {
34456
- this.dataRange = ranges[0];
34455
+ this.state.dataRange = ranges[0];
34457
34456
  }
34458
34457
  updateDataRange() {
34459
- if (!this.dataRange || this.searchOptions.searchScope !== "specificRange") {
34458
+ if (!this.state.dataRange || this.searchOptions.searchScope !== "specificRange") {
34460
34459
  return;
34461
34460
  }
34462
- const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.dataRange);
34461
+ const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
34463
34462
  this.store.updateSearchOptions({ specificRange });
34464
34463
  }
34465
34464
  }
@@ -36130,6 +36129,7 @@ css /* scss */ `
36130
36129
  class RemoveDuplicatesPanel extends Component {
36131
36130
  static template = "o-spreadsheet-RemoveDuplicatesPanel";
36132
36131
  static components = { ValidationMessages, Section, Checkbox };
36132
+ static props = { onCloseSidePanel: Function };
36133
36133
  state = useState({
36134
36134
  hasHeader: false,
36135
36135
  columns: {},
@@ -38554,7 +38554,7 @@ class FiguresContainer extends Component {
38554
38554
  });
38555
38555
  }
38556
38556
  getContainerRect(container) {
38557
- const { width: viewWidth, height: viewHeight } = this.env.model.getters.getMainViewportRect();
38557
+ const { width: viewWidth, height: viewHeight } = this.env.model.getters.getSheetViewDimension();
38558
38558
  const { x: viewportX, y: viewportY } = this.env.model.getters.getMainViewportCoordinates();
38559
38559
  const x = ["bottomRight", "topRight"].includes(container) ? viewportX : 0;
38560
38560
  const width = viewWidth - x;
@@ -51159,22 +51159,6 @@ class PivotCorePlugin extends CorePlugin {
51159
51159
  this.addPivotFormula(cellPosition, formulaId, pivotCell);
51160
51160
  }
51161
51161
  }
51162
- const pivotZone = {
51163
- top: position.row,
51164
- bottom: position.row + pivotCells[0].length - 1,
51165
- left: position.col,
51166
- right: position.col + pivotCells.length - 1,
51167
- };
51168
- const numberOfHeaders = table.columns.length - 1;
51169
- const cmdContent = {
51170
- sheetId: position.sheetId,
51171
- ranges: [this.getters.getRangeDataFromZone(position.sheetId, pivotZone)],
51172
- config: { ...PIVOT_TABLE_CONFIG, numberOfHeaders },
51173
- tableType: "static",
51174
- };
51175
- if (this.canDispatch("CREATE_TABLE", cmdContent).isSuccessful) {
51176
- this.dispatch("CREATE_TABLE", cmdContent);
51177
- }
51178
51162
  }
51179
51163
  resizeSheet(sheetId, { col, row }, table) {
51180
51164
  const colLimit = table.getNumberOfDataColumns() + 1; // +1 for the Top-Left
@@ -55900,7 +55884,10 @@ class Session extends EventBus {
55900
55884
  /**
55901
55885
  * Notify the server that the user client left the collaborative session
55902
55886
  */
55903
- leave() {
55887
+ leave(data) {
55888
+ if (Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
55889
+ this.snapshot(data);
55890
+ }
55904
55891
  delete this.clients[this.clientId];
55905
55892
  this.transportService.leave(this.clientId);
55906
55893
  this.transportService.sendMessage({
@@ -55913,6 +55900,9 @@ class Session extends EventBus {
55913
55900
  * Send a snapshot of the spreadsheet to the collaboration server
55914
55901
  */
55915
55902
  snapshot(data) {
55903
+ if (this.pendingMessages.length !== 0) {
55904
+ return;
55905
+ }
55916
55906
  const snapshotId = this.uuidGenerator.uuidv4();
55917
55907
  this.transportService.sendMessage({
55918
55908
  type: "SNAPSHOT",
@@ -66400,7 +66390,7 @@ class Model extends EventBus {
66400
66390
  this.session.join(this.config.client);
66401
66391
  }
66402
66392
  leaveSession() {
66403
- this.session.leave();
66393
+ this.session.leave(this.exportData());
66404
66394
  }
66405
66395
  setupUiPlugin(Plugin) {
66406
66396
  const plugin = new Plugin(this.uiPluginConfig);
@@ -66948,6 +66938,6 @@ const constants = {
66948
66938
  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 };
66949
66939
 
66950
66940
 
66951
- __info__.version = "17.3.2";
66952
- __info__.date = "2024-06-10T09:38:56.657Z";
66953
- __info__.hash = "c3b358f";
66941
+ __info__.version = "17.3.3";
66942
+ __info__.date = "2024-06-14T10:02:58.082Z";
66943
+ __info__.hash = "c690e9f";