@odoo/o-spreadsheet 16.1.26 → 16.1.28

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.
@@ -622,13 +622,6 @@ function getYearFrac(startDate, endDate, _dayCountConvention) {
622
622
  }
623
623
 
624
624
  //------------------------------------------------------------------------------
625
- /**
626
- * Stringify an object, like JSON.stringify, except that the first level of keys
627
- * is ordered.
628
- */
629
- function stringify(obj) {
630
- return JSON.stringify(obj, Object.keys(obj).sort());
631
- }
632
625
  /**
633
626
  * Remove quotes from a quoted string
634
627
  * ```js
@@ -924,7 +917,7 @@ function isObjectEmptyRecursive(argument) {
924
917
  */
925
918
  function getItemId(item, itemsDic) {
926
919
  for (let [key, value] of Object.entries(itemsDic)) {
927
- if (stringify(value) === stringify(item)) {
920
+ if (deepEquals(value, item)) {
928
921
  return parseInt(key, 10);
929
922
  }
930
923
  }
@@ -1060,6 +1053,22 @@ function transpose2dArray(matrix) {
1060
1053
  if (!matrix.length)
1061
1054
  return matrix;
1062
1055
  return matrix[0].map((_, i) => matrix.map((row) => row[i]));
1056
+ }
1057
+ /**
1058
+ * Creates a version of the function that's memoized on the value of its first
1059
+ * argument, if any.
1060
+ */
1061
+ function memoize(func) {
1062
+ const cache = new Map();
1063
+ const funcName = func.name ? func.name + " (memoized)" : "memoized";
1064
+ return {
1065
+ [funcName](...args) {
1066
+ if (!cache.has(args[0])) {
1067
+ cache.set(args[0], func(...args));
1068
+ }
1069
+ return cache.get(args[0]);
1070
+ },
1071
+ }[funcName];
1063
1072
  }
1064
1073
 
1065
1074
  const RBA_REGEX = /rgba?\(|\s+|\)/gi;
@@ -3656,6 +3665,7 @@ var CommandResult;
3656
3665
  CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
3657
3666
  CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
3658
3667
  CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
3668
+ CommandResult[CommandResult["NoChanges"] = 88] = "NoChanges";
3659
3669
  })(CommandResult || (CommandResult = {}));
3660
3670
 
3661
3671
  function isMatrix(x) {
@@ -8019,12 +8029,12 @@ function toString(value) {
8019
8029
  }
8020
8030
  }
8021
8031
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
8022
- function normalizeString(str) {
8032
+ const normalizeString = memoize(function normalizeString(str) {
8023
8033
  return str
8024
8034
  .toLowerCase()
8025
8035
  .normalize("NFD")
8026
8036
  .replace(/[\u0300-\u036f]/g, "");
8027
- }
8037
+ });
8028
8038
  /**
8029
8039
  * Normalize a value.
8030
8040
  * If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
@@ -21757,7 +21767,7 @@ css /* scss */ `
21757
21767
  }
21758
21768
  .o-input-count {
21759
21769
  width: fit-content;
21760
- padding: 4 0 4 4;
21770
+ padding: 4px 0 4px 4px;
21761
21771
  }
21762
21772
  }
21763
21773
  }
@@ -27941,6 +27951,14 @@ class BordersPlugin extends CorePlugin {
27941
27951
  // ---------------------------------------------------------------------------
27942
27952
  // Command Handling
27943
27953
  // ---------------------------------------------------------------------------
27954
+ allowDispatch(cmd) {
27955
+ switch (cmd.type) {
27956
+ case "SET_BORDER":
27957
+ return this.checkBordersUnchanged(cmd);
27958
+ default:
27959
+ return 0 /* CommandResult.Success */;
27960
+ }
27961
+ }
27944
27962
  handle(cmd) {
27945
27963
  switch (cmd.type) {
27946
27964
  case "ADD_MERGE":
@@ -28336,6 +28354,15 @@ class BordersPlugin extends CorePlugin {
28336
28354
  this.setBorders(sheetId, [{ ...zone, left: right }], "right");
28337
28355
  }
28338
28356
  }
28357
+ checkBordersUnchanged(cmd) {
28358
+ var _a, _b, _c, _d;
28359
+ const currentBorder = this.getCellBorder(cmd);
28360
+ const areAllNewBordersUndefined = !((_a = cmd.border) === null || _a === void 0 ? void 0 : _a.bottom) && !((_b = cmd.border) === null || _b === void 0 ? void 0 : _b.left) && !((_c = cmd.border) === null || _c === void 0 ? void 0 : _c.right) && !((_d = cmd.border) === null || _d === void 0 ? void 0 : _d.top);
28361
+ if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
28362
+ return 88 /* CommandResult.NoChanges */;
28363
+ }
28364
+ return 0 /* CommandResult.Success */;
28365
+ }
28339
28366
  // ---------------------------------------------------------------------------
28340
28367
  // Import/Export
28341
28368
  // ---------------------------------------------------------------------------
@@ -28371,7 +28398,7 @@ class BordersPlugin extends CorePlugin {
28371
28398
  */
28372
28399
  function getBorderId(border) {
28373
28400
  for (let [key, value] of Object.entries(borders)) {
28374
- if (stringify(value) === stringify(border)) {
28401
+ if (deepEquals(value, border)) {
28375
28402
  return parseInt(key, 10);
28376
28403
  }
28377
28404
  }
@@ -28439,8 +28466,9 @@ class CellPlugin extends CorePlugin {
28439
28466
  allowDispatch(cmd) {
28440
28467
  switch (cmd.type) {
28441
28468
  case "UPDATE_CELL":
28469
+ return this.checkCellOutOfSheet(cmd);
28442
28470
  case "CLEAR_CELL":
28443
- return this.checkCellOutOfSheet(cmd.sheetId, cmd.col, cmd.row);
28471
+ return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
28444
28472
  default:
28445
28473
  return 0 /* CommandResult.Success */;
28446
28474
  }
@@ -28599,14 +28627,9 @@ class CellPlugin extends CorePlugin {
28599
28627
  */
28600
28628
  getCellById(cellId) {
28601
28629
  // this must be as fast as possible
28602
- for (const sheetId in this.cells) {
28603
- const sheet = this.cells[sheetId];
28604
- const cell = sheet[cellId];
28605
- if (cell) {
28606
- return cell;
28607
- }
28608
- }
28609
- return undefined;
28630
+ const position = this.getters.getCellPosition(cellId);
28631
+ const sheet = this.cells[position.sheetId];
28632
+ return sheet[cellId];
28610
28633
  }
28611
28634
  /*
28612
28635
  * Reconstructs the original formula string based on a normalized form and its dependencies
@@ -28847,13 +28870,23 @@ class CellPlugin extends CorePlugin {
28847
28870
  dependencies: [],
28848
28871
  };
28849
28872
  }
28850
- checkCellOutOfSheet(sheetId, col, row) {
28873
+ checkCellOutOfSheet(cmd) {
28874
+ const { sheetId, col, row } = cmd;
28851
28875
  const sheet = this.getters.tryGetSheet(sheetId);
28852
28876
  if (!sheet)
28853
28877
  return 27 /* CommandResult.InvalidSheetId */;
28854
28878
  const sheetZone = this.getters.getSheetZone(sheetId);
28855
28879
  return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
28856
28880
  }
28881
+ checkUselessClearCell(cmd) {
28882
+ const cell = this.getters.getCell(cmd);
28883
+ if (!cell)
28884
+ return 88 /* CommandResult.NoChanges */;
28885
+ if (!cell.content && !cell.style && !cell.format) {
28886
+ return 88 /* CommandResult.NoChanges */;
28887
+ }
28888
+ return 0 /* CommandResult.Success */;
28889
+ }
28857
28890
  }
28858
28891
  CellPlugin.getters = [
28859
28892
  "zoneToXC",
@@ -29756,6 +29789,13 @@ class FiltersPlugin extends CorePlugin {
29756
29789
  }
29757
29790
  onDeleteColumnsRows(cmd) {
29758
29791
  for (const table of this.getFilterTables(cmd.sheetId)) {
29792
+ // Remove the filter tables whose data filter headers are in the removed rows.
29793
+ if (cmd.dimension === "ROW" && cmd.elements.includes(table.zone.top)) {
29794
+ const tables = { ...this.tables[cmd.sheetId] };
29795
+ delete tables[table.id];
29796
+ this.history.update("tables", cmd.sheetId, tables);
29797
+ continue;
29798
+ }
29759
29799
  const zone = reduceZoneOnDeletion(table.zone, cmd.dimension === "COL" ? "left" : "top", cmd.elements);
29760
29800
  if (!zone) {
29761
29801
  const tables = { ...this.tables[cmd.sheetId] };
@@ -31907,10 +31947,13 @@ class SheetPlugin extends CorePlugin {
31907
31947
  // begin with the end.
31908
31948
  rows.sort((a, b) => b - a);
31909
31949
  for (let group of groupConsecutive(rows)) {
31950
+ // indexes are sorted in the descending order
31951
+ const from = group[group.length - 1];
31952
+ const to = group[0];
31910
31953
  // Move the cells.
31911
- this.moveCellOnRowsDeletion(sheet, group[group.length - 1], group[0]);
31912
- // Effectively delete the element and recompute the left-right/top-bottom.
31913
- group.map((row) => this.updateRowsStructureOnDeletion(row, sheet));
31954
+ this.moveCellOnRowsDeletion(sheet, from, to);
31955
+ // Effectively delete the rows
31956
+ this.updateRowsStructureOnDeletion(sheet, from, to);
31914
31957
  }
31915
31958
  const count = rows.filter((row) => row < sheet.panes.ySplit).length;
31916
31959
  if (count) {
@@ -31932,8 +31975,6 @@ class SheetPlugin extends CorePlugin {
31932
31975
  this.addEmptyRows(sheet, quantity);
31933
31976
  // Move the cells.
31934
31977
  this.moveCellsOnAddition(sheet, index, quantity, "rows");
31935
- // Recompute the left-right/top-bottom.
31936
- this.updateRowsStructureOnAddition(sheet, row, quantity);
31937
31978
  if (index < sheet.panes.ySplit) {
31938
31979
  this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
31939
31980
  }
@@ -32034,35 +32075,20 @@ class SheetPlugin extends CorePlugin {
32034
32075
  }
32035
32076
  }
32036
32077
  }
32037
- updateRowsStructureOnDeletion(index, sheet) {
32078
+ updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
32038
32079
  const rows = [];
32039
- const cellsQueue = sheet.rows.map((row) => row.cells);
32080
+ const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
32040
32081
  for (let i in sheet.rows) {
32041
- if (Number(i) === index) {
32082
+ const row = Number(i);
32083
+ if (row >= deleteFromRow && row <= deleteToRow) {
32042
32084
  continue;
32043
32085
  }
32044
32086
  rows.push({
32045
- cells: cellsQueue.shift(),
32087
+ cells: cellsQueue.pop(),
32046
32088
  });
32047
32089
  }
32048
32090
  this.history.update("sheets", sheet.id, "rows", rows);
32049
32091
  }
32050
- /**
32051
- * Update the rows of the sheet after an addition:
32052
- * - Rename the rows
32053
- *
32054
- * @param sheet Sheet on which the deletion occurs
32055
- * @param addedRow Index of the added row
32056
- * @param rowsToAdd Number of the rows to add
32057
- */
32058
- updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
32059
- const rows = [];
32060
- const cellsQueue = sheet.rows.map((row) => row.cells);
32061
- sheet.rows.forEach(() => rows.push({
32062
- cells: cellsQueue.shift(),
32063
- }));
32064
- this.history.update("sheets", sheet.id, "rows", rows);
32065
- }
32066
32092
  /**
32067
32093
  * Add empty rows at the end of the rows
32068
32094
  *
@@ -32519,6 +32545,7 @@ class EvaluationPlugin extends UIPlugin {
32519
32545
  }
32520
32546
  return evaluatedCell;
32521
32547
  };
32548
+ const rangeCache = {};
32522
32549
  /**
32523
32550
  * Return the values of the cell(s) used in reference, but always in the format of a range even
32524
32551
  * if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
@@ -32535,21 +32562,26 @@ class EvaluationPlugin extends UIPlugin {
32535
32562
  // Performance issue: Avoid fetching data on positions that are out of the spreadsheet
32536
32563
  // e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
32537
32564
  const sheetZone = getters.getSheetZone(sheetId);
32538
- const result = [];
32539
32565
  const zone = intersection(range.zone, sheetZone);
32540
32566
  if (!zone) {
32541
- result.push([]);
32542
- return result;
32567
+ return [[]];
32568
+ }
32569
+ const { top, left, bottom, right } = zone;
32570
+ const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
32571
+ if (cacheKey in rangeCache) {
32572
+ return rangeCache[cacheKey];
32543
32573
  }
32574
+ const result = new Array(right - left + 1);
32544
32575
  // Performance issue: nested loop is faster than a map here
32545
- for (let col = zone.left; col <= zone.right; col++) {
32546
- const rowValues = [];
32547
- for (let row = zone.top; row <= zone.bottom; row++) {
32576
+ for (let col = left; col <= right; col++) {
32577
+ const rowValues = new Array(bottom - top + 1);
32578
+ for (let row = top; row <= bottom; row++) {
32548
32579
  const cell = evalContext.getters.getCell({ sheetId: range.sheetId, col, row });
32549
- rowValues.push(cell ? getEvaluatedCell(cell) : undefined);
32580
+ rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
32550
32581
  }
32551
- result.push(rowValues);
32582
+ result[col - left] = rowValues;
32552
32583
  }
32584
+ rangeCache[cacheKey] = result;
32553
32585
  return result;
32554
32586
  }
32555
32587
  /**
@@ -33095,6 +33127,8 @@ class FilterEvaluationPlugin extends UIPlugin {
33095
33127
  case "EVALUATE_CELLS":
33096
33128
  case "ACTIVATE_SHEET":
33097
33129
  case "REMOVE_FILTER_TABLE":
33130
+ case "ADD_COLUMNS_ROWS":
33131
+ case "REMOVE_COLUMNS_ROWS":
33098
33132
  this.isEvaluationDirty = true;
33099
33133
  break;
33100
33134
  case "START":
@@ -41661,9 +41695,9 @@ function revertChanges(revisions) {
41661
41695
  * Apply the changes of the given HistoryChange to the state
41662
41696
  */
41663
41697
  function applyChange(change, target) {
41664
- let val = change.root;
41665
- let key = change.path[change.path.length - 1];
41666
- for (let pathIndex = 0; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
41698
+ let val = change.path[0];
41699
+ const key = change.path[change.path.length - 1];
41700
+ for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
41667
41701
  const p = change.path[pathIndex];
41668
41702
  if (val[p] === undefined) {
41669
41703
  const nextPath = change.path[pathIndex + 1];
@@ -42418,13 +42452,14 @@ class StateObserver {
42418
42452
  }
42419
42453
  addChange(...args) {
42420
42454
  const val = args.pop();
42421
- const [root, ...path] = args;
42455
+ const root = args[0];
42422
42456
  let value = root;
42423
- let key = path[path.length - 1];
42424
- for (let pathIndex = 0; pathIndex <= path.length - 2; pathIndex++) {
42425
- const p = path[pathIndex];
42457
+ let key = args[args.length - 1];
42458
+ const pathLength = args.length - 2;
42459
+ for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
42460
+ const p = args[pathIndex];
42426
42461
  if (value[p] === undefined) {
42427
- const nextPath = path[pathIndex + 1];
42462
+ const nextPath = args[pathIndex + 1];
42428
42463
  value[p] = createEmptyStructure(nextPath);
42429
42464
  }
42430
42465
  value = value[p];
@@ -42433,8 +42468,7 @@ class StateObserver {
42433
42468
  return;
42434
42469
  }
42435
42470
  this.changes.push({
42436
- root,
42437
- path,
42471
+ path: args,
42438
42472
  before: value[key],
42439
42473
  after: val,
42440
42474
  });
@@ -44208,7 +44242,10 @@ class Model extends EventBus {
44208
44242
  */
44209
44243
  checkDispatchAllowed(command) {
44210
44244
  const results = this.handlers.map((handler) => handler.allowDispatch(command));
44211
- return new DispatchResult(results.flat());
44245
+ if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
44246
+ return new DispatchResult(results.flat());
44247
+ }
44248
+ return DispatchResult.Success;
44212
44249
  }
44213
44250
  finalize() {
44214
44251
  this.status = 3 /* Status.Finalizing */;
@@ -44408,6 +44445,6 @@ function addFunction(functionName, functionDescription) {
44408
44445
  export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
44409
44446
 
44410
44447
 
44411
- __info__.version = '16.1.26';
44412
- __info__.date = '2023-11-02T09:31:23.420Z';
44413
- __info__.hash = '1ddd8d0';
44448
+ __info__.version = '16.1.28';
44449
+ __info__.date = '2023-11-24T13:11:01.992Z';
44450
+ __info__.hash = '257f369';