@odoo/o-spreadsheet 16.2.21 → 16.2.23

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.
@@ -604,13 +604,6 @@
604
604
  }
605
605
 
606
606
  //------------------------------------------------------------------------------
607
- /**
608
- * Stringify an object, like JSON.stringify, except that the first level of keys
609
- * is ordered.
610
- */
611
- function stringify(obj) {
612
- return JSON.stringify(obj, Object.keys(obj).sort());
613
- }
614
607
  /**
615
608
  * Remove quotes from a quoted string
616
609
  * ```js
@@ -910,7 +903,7 @@
910
903
  */
911
904
  function getItemId(item, itemsDic) {
912
905
  for (let [key, value] of Object.entries(itemsDic)) {
913
- if (stringify(value) === stringify(item)) {
906
+ if (deepEquals(value, item)) {
914
907
  return parseInt(key, 10);
915
908
  }
916
909
  }
@@ -976,6 +969,22 @@
976
969
  lazyValue.map = (callback) => lazy(() => callback(lazyValue()));
977
970
  return lazyValue;
978
971
  }
972
+ /**
973
+ * Creates a version of the function that's memoized on the value of its first
974
+ * argument, if any.
975
+ */
976
+ function memoize(func) {
977
+ const cache = new Map();
978
+ const funcName = func.name ? func.name + " (memoized)" : "memoized";
979
+ return {
980
+ [funcName](...args) {
981
+ if (!cache.has(args[0])) {
982
+ cache.set(args[0], func(...args));
983
+ }
984
+ return cache.get(args[0]);
985
+ },
986
+ }[funcName];
987
+ }
979
988
  /**
980
989
  * Find the next defined value after the given index in an array of strings. If there is no defined value
981
990
  * after the index, return the closest defined value before the index. Return an empty string if no
@@ -3573,12 +3582,12 @@
3573
3582
  }
3574
3583
  }
3575
3584
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
3576
- function normalizeString(str) {
3585
+ const normalizeString = memoize(function normalizeString(str) {
3577
3586
  return str
3578
3587
  .toLowerCase()
3579
3588
  .normalize("NFD")
3580
3589
  .replace(/[\u0300-\u036f]/g, "");
3581
- }
3590
+ });
3582
3591
  /**
3583
3592
  * Normalize a value.
3584
3593
  * If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
@@ -4302,6 +4311,7 @@
4302
4311
  CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
4303
4312
  CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
4304
4313
  CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
4314
+ CommandResult[CommandResult["NoChanges"] = 88] = "NoChanges";
4305
4315
  })(exports.CommandResult || (exports.CommandResult = {}));
4306
4316
 
4307
4317
  function isMatrix(x) {
@@ -18733,7 +18743,7 @@
18733
18743
  }
18734
18744
  .o-input-count {
18735
18745
  width: fit-content;
18736
- padding: 4 0 4 4;
18746
+ padding: 4px 0 4px 4px;
18737
18747
  }
18738
18748
  }
18739
18749
  }
@@ -27517,6 +27527,14 @@
27517
27527
  // ---------------------------------------------------------------------------
27518
27528
  // Command Handling
27519
27529
  // ---------------------------------------------------------------------------
27530
+ allowDispatch(cmd) {
27531
+ switch (cmd.type) {
27532
+ case "SET_BORDER":
27533
+ return this.checkBordersUnchanged(cmd);
27534
+ default:
27535
+ return 0 /* CommandResult.Success */;
27536
+ }
27537
+ }
27520
27538
  handle(cmd) {
27521
27539
  switch (cmd.type) {
27522
27540
  case "ADD_MERGE":
@@ -27912,6 +27930,15 @@
27912
27930
  this.setBorders(sheetId, [{ ...zone, left: right }], "right");
27913
27931
  }
27914
27932
  }
27933
+ checkBordersUnchanged(cmd) {
27934
+ var _a, _b, _c, _d;
27935
+ const currentBorder = this.getCellBorder(cmd);
27936
+ 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);
27937
+ if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
27938
+ return 88 /* CommandResult.NoChanges */;
27939
+ }
27940
+ return 0 /* CommandResult.Success */;
27941
+ }
27915
27942
  // ---------------------------------------------------------------------------
27916
27943
  // Import/Export
27917
27944
  // ---------------------------------------------------------------------------
@@ -27947,7 +27974,7 @@
27947
27974
  */
27948
27975
  function getBorderId(border) {
27949
27976
  for (let [key, value] of Object.entries(borders)) {
27950
- if (stringify(value) === stringify(border)) {
27977
+ if (deepEquals(value, border)) {
27951
27978
  return parseInt(key, 10);
27952
27979
  }
27953
27980
  }
@@ -28014,8 +28041,9 @@
28014
28041
  allowDispatch(cmd) {
28015
28042
  switch (cmd.type) {
28016
28043
  case "UPDATE_CELL":
28044
+ return this.checkCellOutOfSheet(cmd);
28017
28045
  case "CLEAR_CELL":
28018
- return this.checkCellOutOfSheet(cmd.sheetId, cmd.col, cmd.row);
28046
+ return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
28019
28047
  default:
28020
28048
  return 0 /* CommandResult.Success */;
28021
28049
  }
@@ -28174,14 +28202,9 @@
28174
28202
  */
28175
28203
  getCellById(cellId) {
28176
28204
  // this must be as fast as possible
28177
- for (const sheetId in this.cells) {
28178
- const sheet = this.cells[sheetId];
28179
- const cell = sheet[cellId];
28180
- if (cell) {
28181
- return cell;
28182
- }
28183
- }
28184
- return undefined;
28205
+ const position = this.getters.getCellPosition(cellId);
28206
+ const sheet = this.cells[position.sheetId];
28207
+ return sheet[cellId];
28185
28208
  }
28186
28209
  /*
28187
28210
  * Reconstructs the original formula string based on a normalized form and its dependencies
@@ -28419,13 +28442,23 @@
28419
28442
  dependencies: [],
28420
28443
  };
28421
28444
  }
28422
- checkCellOutOfSheet(sheetId, col, row) {
28445
+ checkCellOutOfSheet(cmd) {
28446
+ const { sheetId, col, row } = cmd;
28423
28447
  const sheet = this.getters.tryGetSheet(sheetId);
28424
28448
  if (!sheet)
28425
28449
  return 27 /* CommandResult.InvalidSheetId */;
28426
28450
  const sheetZone = this.getters.getSheetZone(sheetId);
28427
28451
  return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
28428
28452
  }
28453
+ checkUselessClearCell(cmd) {
28454
+ const cell = this.getters.getCell(cmd);
28455
+ if (!cell)
28456
+ return 88 /* CommandResult.NoChanges */;
28457
+ if (!cell.content && !cell.style && !cell.format) {
28458
+ return 88 /* CommandResult.NoChanges */;
28459
+ }
28460
+ return 0 /* CommandResult.Success */;
28461
+ }
28429
28462
  }
28430
28463
  CellPlugin.getters = [
28431
28464
  "zoneToXC",
@@ -29328,6 +29361,13 @@
29328
29361
  }
29329
29362
  onDeleteColumnsRows(cmd) {
29330
29363
  for (const table of this.getFilterTables(cmd.sheetId)) {
29364
+ // Remove the filter tables whose data filter headers are in the removed rows.
29365
+ if (cmd.dimension === "ROW" && cmd.elements.includes(table.zone.top)) {
29366
+ const tables = { ...this.tables[cmd.sheetId] };
29367
+ delete tables[table.id];
29368
+ this.history.update("tables", cmd.sheetId, tables);
29369
+ continue;
29370
+ }
29331
29371
  const zone = reduceZoneOnDeletion(table.zone, cmd.dimension === "COL" ? "left" : "top", cmd.elements);
29332
29372
  if (!zone) {
29333
29373
  const tables = { ...this.tables[cmd.sheetId] };
@@ -31484,10 +31524,13 @@
31484
31524
  // begin with the end.
31485
31525
  rows.sort((a, b) => b - a);
31486
31526
  for (let group of groupConsecutive(rows)) {
31527
+ // indexes are sorted in the descending order
31528
+ const from = group[group.length - 1];
31529
+ const to = group[0];
31487
31530
  // Move the cells.
31488
- this.moveCellOnRowsDeletion(sheet, group[group.length - 1], group[0]);
31489
- // Effectively delete the element and recompute the left-right/top-bottom.
31490
- group.map((row) => this.updateRowsStructureOnDeletion(row, sheet));
31531
+ this.moveCellOnRowsDeletion(sheet, from, to);
31532
+ // Effectively delete the rows
31533
+ this.updateRowsStructureOnDeletion(sheet, from, to);
31491
31534
  }
31492
31535
  const count = rows.filter((row) => row < sheet.panes.ySplit).length;
31493
31536
  if (count) {
@@ -31509,8 +31552,6 @@
31509
31552
  this.addEmptyRows(sheet, quantity);
31510
31553
  // Move the cells.
31511
31554
  this.moveCellsOnAddition(sheet, index, quantity, "rows");
31512
- // Recompute the left-right/top-bottom.
31513
- this.updateRowsStructureOnAddition(sheet, row, quantity);
31514
31555
  if (index < sheet.panes.ySplit) {
31515
31556
  this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
31516
31557
  }
@@ -31611,35 +31652,20 @@
31611
31652
  }
31612
31653
  }
31613
31654
  }
31614
- updateRowsStructureOnDeletion(index, sheet) {
31655
+ updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
31615
31656
  const rows = [];
31616
- const cellsQueue = sheet.rows.map((row) => row.cells);
31657
+ const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
31617
31658
  for (let i in sheet.rows) {
31618
- if (Number(i) === index) {
31659
+ const row = Number(i);
31660
+ if (row >= deleteFromRow && row <= deleteToRow) {
31619
31661
  continue;
31620
31662
  }
31621
31663
  rows.push({
31622
- cells: cellsQueue.shift(),
31664
+ cells: cellsQueue.pop(),
31623
31665
  });
31624
31666
  }
31625
31667
  this.history.update("sheets", sheet.id, "rows", rows);
31626
31668
  }
31627
- /**
31628
- * Update the rows of the sheet after an addition:
31629
- * - Rename the rows
31630
- *
31631
- * @param sheet Sheet on which the deletion occurs
31632
- * @param addedRow Index of the added row
31633
- * @param rowsToAdd Number of the rows to add
31634
- */
31635
- updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
31636
- const rows = [];
31637
- const cellsQueue = sheet.rows.map((row) => row.cells);
31638
- sheet.rows.forEach(() => rows.push({
31639
- cells: cellsQueue.shift(),
31640
- }));
31641
- this.history.update("sheets", sheet.id, "rows", rows);
31642
- }
31643
31669
  /**
31644
31670
  * Add empty rows at the end of the rows
31645
31671
  *
@@ -32123,6 +32149,7 @@
32123
32149
  }
32124
32150
  return evaluatedCell;
32125
32151
  };
32152
+ const rangeCache = {};
32126
32153
  /**
32127
32154
  * Return the values of the cell(s) used in reference, but always in the format of a range even
32128
32155
  * if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
@@ -32139,21 +32166,26 @@
32139
32166
  // Performance issue: Avoid fetching data on positions that are out of the spreadsheet
32140
32167
  // e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
32141
32168
  const sheetZone = getters.getSheetZone(sheetId);
32142
- const result = [];
32143
32169
  const zone = intersection(range.zone, sheetZone);
32144
32170
  if (!zone) {
32145
- result.push([]);
32146
- return result;
32171
+ return [[]];
32172
+ }
32173
+ const { top, left, bottom, right } = zone;
32174
+ const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
32175
+ if (cacheKey in rangeCache) {
32176
+ return rangeCache[cacheKey];
32147
32177
  }
32178
+ const result = new Array(right - left + 1);
32148
32179
  // Performance issue: nested loop is faster than a map here
32149
- for (let col = zone.left; col <= zone.right; col++) {
32150
- const rowValues = [];
32151
- for (let row = zone.top; row <= zone.bottom; row++) {
32180
+ for (let col = left; col <= right; col++) {
32181
+ const rowValues = new Array(bottom - top + 1);
32182
+ for (let row = top; row <= bottom; row++) {
32152
32183
  const cell = evalContext.getters.getCell({ sheetId: range.sheetId, col, row });
32153
- rowValues.push(cell ? getEvaluatedCell(cell) : undefined);
32184
+ rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
32154
32185
  }
32155
- result.push(rowValues);
32186
+ result[col - left] = rowValues;
32156
32187
  }
32188
+ rangeCache[cacheKey] = result;
32157
32189
  return result;
32158
32190
  }
32159
32191
  /**
@@ -32700,6 +32732,8 @@
32700
32732
  case "EVALUATE_CELLS":
32701
32733
  case "ACTIVATE_SHEET":
32702
32734
  case "REMOVE_FILTER_TABLE":
32735
+ case "ADD_COLUMNS_ROWS":
32736
+ case "REMOVE_COLUMNS_ROWS":
32703
32737
  this.isEvaluationDirty = true;
32704
32738
  break;
32705
32739
  case "START":
@@ -42678,9 +42712,9 @@
42678
42712
  * Apply the changes of the given HistoryChange to the state
42679
42713
  */
42680
42714
  function applyChange(change, target) {
42681
- let val = change.root;
42682
- let key = change.path[change.path.length - 1];
42683
- for (let pathIndex = 0; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
42715
+ let val = change.path[0];
42716
+ const key = change.path[change.path.length - 1];
42717
+ for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
42684
42718
  const p = change.path[pathIndex];
42685
42719
  if (val[p] === undefined) {
42686
42720
  const nextPath = change.path[pathIndex + 1];
@@ -43437,13 +43471,14 @@
43437
43471
  }
43438
43472
  addChange(...args) {
43439
43473
  const val = args.pop();
43440
- const [root, ...path] = args;
43474
+ const root = args[0];
43441
43475
  let value = root;
43442
- let key = path[path.length - 1];
43443
- for (let pathIndex = 0; pathIndex <= path.length - 2; pathIndex++) {
43444
- const p = path[pathIndex];
43476
+ let key = args[args.length - 1];
43477
+ const pathLength = args.length - 2;
43478
+ for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
43479
+ const p = args[pathIndex];
43445
43480
  if (value[p] === undefined) {
43446
- const nextPath = path[pathIndex + 1];
43481
+ const nextPath = args[pathIndex + 1];
43447
43482
  value[p] = createEmptyStructure(nextPath);
43448
43483
  }
43449
43484
  value = value[p];
@@ -43452,8 +43487,7 @@
43452
43487
  return;
43453
43488
  }
43454
43489
  this.changes.push({
43455
- root,
43456
- path,
43490
+ path: args,
43457
43491
  before: value[key],
43458
43492
  after: val,
43459
43493
  });
@@ -45305,7 +45339,10 @@
45305
45339
  */
45306
45340
  checkDispatchAllowed(command) {
45307
45341
  const results = this.handlers.map((handler) => handler.allowDispatch(command));
45308
- return new DispatchResult(results.flat());
45342
+ if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
45343
+ return new DispatchResult(results.flat());
45344
+ }
45345
+ return DispatchResult.Success;
45309
45346
  }
45310
45347
  finalize() {
45311
45348
  this.status = 3 /* Status.Finalizing */;
@@ -45534,9 +45571,9 @@
45534
45571
  Object.defineProperty(exports, '__esModule', { value: true });
45535
45572
 
45536
45573
 
45537
- __info__.version = '16.2.21';
45538
- __info__.date = '2023-11-02T09:31:50.545Z';
45539
- __info__.hash = 'cc30e85';
45574
+ __info__.version = '16.2.23';
45575
+ __info__.date = '2023-11-24T13:11:02.651Z';
45576
+ __info__.hash = '3c723d3';
45540
45577
 
45541
45578
 
45542
45579
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);