@odoo/o-spreadsheet 17.4.4 → 17.4.6

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.
@@ -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 17.4.4
6
- * @date 2024-08-09T12:24:07.798Z
7
- * @hash a43e855
5
+ * @version 17.4.6
6
+ * @date 2024-08-26T13:50:49.623Z
7
+ * @hash f5648d9
8
8
  */
9
9
 
10
10
  'use strict';
@@ -242,6 +242,7 @@ const PIVOT_TABLE_CONFIG = {
242
242
  bandedRows: true,
243
243
  bandedColumns: false,
244
244
  styleId: "TableStyleMedium5",
245
+ automaticAutofill: true,
245
246
  };
246
247
 
247
248
  //------------------------------------------------------------------------------
@@ -2010,6 +2011,7 @@ const coreTypes = new Set([
2010
2011
  "UPDATE_CELL",
2011
2012
  "UPDATE_CELL_POSITION",
2012
2013
  "CLEAR_CELL",
2014
+ "CLEAR_CELLS",
2013
2015
  "DELETE_CONTENT",
2014
2016
  /** GRID SHAPE */
2015
2017
  "ADD_COLUMNS_ROWS",
@@ -6745,13 +6747,10 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6745
6747
  * Clear the clipped zones: remove the cells and clear the formatting
6746
6748
  */
6747
6749
  clearClippedZones(content) {
6748
- for (const row of content.cells) {
6749
- for (const cell of row) {
6750
- if (cell.cell) {
6751
- this.dispatch("CLEAR_CELL", cell.position);
6752
- }
6753
- }
6754
- }
6750
+ this.dispatch("CLEAR_CELLS", {
6751
+ sheetId: content.sheetId,
6752
+ target: content.zones,
6753
+ });
6755
6754
  this.dispatch("CLEAR_FORMATTING", {
6756
6755
  sheetId: content.sheetId,
6757
6756
  target: content.zones,
@@ -7719,7 +7718,7 @@ function parse(str) {
7719
7718
  }
7720
7719
  function parseTokens(tokens) {
7721
7720
  tokens = tokens.filter((x) => x.type !== "SPACE");
7722
- if (tokens[0].value === "=") {
7721
+ if (tokens[0]?.value === "=") {
7723
7722
  tokens.splice(0, 1);
7724
7723
  }
7725
7724
  const result = parseExpression(tokens);
@@ -9953,7 +9952,7 @@ class ComposerStore extends SpreadsheetStore {
9953
9952
  if (pivotId && pivotCell.type !== "EMPTY" && !cell?.isFormula) {
9954
9953
  const formulaPivotId = this.getters.getPivotFormulaId(pivotId);
9955
9954
  const formula = createPivotFormula(formulaPivotId, pivotCell);
9956
- return formula.slice(1); // strip leading =
9955
+ return localizeFormula(formula, this.getters.getLocale()).slice(1); // strip leading =
9957
9956
  }
9958
9957
  }
9959
9958
  const range = this.getters.getRangeFromZone(sheetId, zone);
@@ -35175,7 +35174,6 @@ class FindAndReplaceStore extends SpreadsheetStore {
35175
35174
  searchScope: "activeSheet",
35176
35175
  specificRange: undefined,
35177
35176
  };
35178
- updateSearchContent = debounce(this._updateSearchContent.bind(this), 200);
35179
35177
  constructor(get) {
35180
35178
  super(get);
35181
35179
  this.initialShowFormulaState = this.model.getters.shouldShowFormulas();
@@ -35184,7 +35182,6 @@ class FindAndReplaceStore extends SpreadsheetStore {
35184
35182
  highlightStore.register(this);
35185
35183
  this.onDispose(() => {
35186
35184
  this.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.initialShowFormulaState });
35187
- this.updateSearchContent.stopDebounce();
35188
35185
  highlightStore.unRegister(this);
35189
35186
  });
35190
35187
  }
@@ -35198,7 +35195,7 @@ class FindAndReplaceStore extends SpreadsheetStore {
35198
35195
  return this.specificRangeMatches;
35199
35196
  }
35200
35197
  }
35201
- _updateSearchContent(toSearch) {
35198
+ updateSearchContent(toSearch) {
35202
35199
  this._updateSearch(toSearch, this.searchOptions);
35203
35200
  }
35204
35201
  updateSearchOptions(searchOptions) {
@@ -35214,9 +35211,6 @@ class FindAndReplaceStore extends SpreadsheetStore {
35214
35211
  selectNextMatch() {
35215
35212
  this.selectNextCell(Direction.next);
35216
35213
  }
35217
- get pendingSearch() {
35218
- return this.updateSearchContent.isDebouncePending();
35219
- }
35220
35214
  handle(cmd) {
35221
35215
  switch (cmd.type) {
35222
35216
  case "SET_FORMULA_VISIBILITY":
@@ -35542,6 +35536,7 @@ class FindAndReplacePanel extends owl.Component {
35542
35536
  searchInput = owl.useRef("searchInput");
35543
35537
  store;
35544
35538
  state;
35539
+ updateSearchContent;
35545
35540
  get hasSearchResult() {
35546
35541
  return this.store.selectedMatchIndex !== null;
35547
35542
  }
@@ -35573,12 +35568,14 @@ class FindAndReplacePanel extends owl.Component {
35573
35568
  this.store = useLocalStore(FindAndReplaceStore);
35574
35569
  this.state = owl.useState({ dataRange: "" });
35575
35570
  owl.onMounted(() => this.searchInput.el?.focus());
35571
+ owl.onWillUnmount(() => this.updateSearchContent.stopDebounce());
35572
+ this.updateSearchContent = debounce(this.store.updateSearchContent, 200);
35576
35573
  }
35577
35574
  onFocusSearch() {
35578
35575
  this.updateDataRange();
35579
35576
  }
35580
35577
  onSearchInput(ev) {
35581
- this.store.updateSearchContent(ev.target?.value || "");
35578
+ this.updateSearchContent(ev.target.value);
35582
35579
  }
35583
35580
  onKeydownSearch(ev) {
35584
35581
  if (ev.key === "Enter") {
@@ -35617,6 +35614,9 @@ class FindAndReplacePanel extends owl.Component {
35617
35614
  const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
35618
35615
  this.store.updateSearchOptions({ specificRange });
35619
35616
  }
35617
+ get pendingSearch() {
35618
+ return this.updateSearchContent.isDebouncePending();
35619
+ }
35620
35620
  }
35621
35621
 
35622
35622
  css /* scss */ `
@@ -36670,6 +36670,12 @@ function orderDataEntriesKeys(groups, dimension) {
36670
36670
  * Used to order two values
36671
36671
  */
36672
36672
  function compareDimensionValues(dimension, a, b) {
36673
+ if (a === "null") {
36674
+ return dimension.order === "asc" ? 1 : -1;
36675
+ }
36676
+ if (b === "null") {
36677
+ return dimension.order === "asc" ? -1 : 1;
36678
+ }
36673
36679
  if (dimension.type === "integer" || dimension.type === "date") {
36674
36680
  return dimension.order === "asc" ? Number(a) - Number(b) : Number(b) - Number(a);
36675
36681
  }
@@ -37032,7 +37038,7 @@ class SpreadsheetPivot {
37032
37038
  if (cell.type === CellValueType.error) {
37033
37039
  throw new EvaluationError(_t("The pivot cannot be created because cell %s contains an error", toXC(col, row)));
37034
37040
  }
37035
- if (cell.type === CellValueType.empty) {
37041
+ if (cell.type === CellValueType.empty || cell.value === "") {
37036
37042
  throw new EvaluationError(_t("The pivot cannot be created because cell %s is empty", toXC(col, row)));
37037
37043
  }
37038
37044
  if (cell.value === "__count") {
@@ -37378,15 +37384,11 @@ class PivotSpreadsheetSidePanel extends owl.Component {
37378
37384
  }
37379
37385
  onSelectionConfirmed() {
37380
37386
  if (this.state.range) {
37381
- const { sheetName, xc } = splitReference(this.state.range);
37382
- const sheetId = sheetName
37383
- ? this.env.model.getters.getSheetIdByName(sheetName)
37384
- : this.env.model.getters.getActiveSheetId();
37385
- if (!sheetId) {
37387
+ const range = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.range);
37388
+ if (range.invalidSheetName || range.invalidXc) {
37386
37389
  return;
37387
37390
  }
37388
- const zone = toZone(xc);
37389
- const dataSet = { sheetId, zone };
37391
+ const dataSet = { sheetId: range.sheetId, zone: range.zone };
37390
37392
  this.store.update({ dataSet });
37391
37393
  // Immediately apply the update to recompute the pivot fields
37392
37394
  this.store.applyUpdate();
@@ -38319,10 +38321,6 @@ class TablePanel extends owl.Component {
38319
38321
  });
38320
38322
  }
38321
38323
  onRangeChanged(ranges) {
38322
- if (!ranges[0] || !ranges[0].match(rangeReference)) {
38323
- this.state.tableZoneErrors = ["InvalidRange" /* CommandResult.InvalidRange */];
38324
- return;
38325
- }
38326
38324
  const sheetId = this.env.model.getters.getActiveSheetId();
38327
38325
  this.state.tableXc = ranges[0];
38328
38326
  const newTableRange = this.env.model.getters.getRangeFromSheetXC(sheetId, this.state.tableXc);
@@ -38362,11 +38360,6 @@ class TablePanel extends owl.Component {
38362
38360
  const newTableRange = updatedTable.range;
38363
38361
  this.state.tableXc = this.env.model.getters.getRangeString(newTableRange, sheetId);
38364
38362
  }
38365
- else {
38366
- const oldTableRange = this.props.table.range;
38367
- this.state.tableXc = this.env.model.getters.getRangeString(oldTableRange, sheetId);
38368
- }
38369
- this.state.tableZoneErrors = [];
38370
38363
  }
38371
38364
  deleteTable() {
38372
38365
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -44356,6 +44349,7 @@ function convertChartData(chartData) {
44356
44349
  return {
44357
44350
  dataRange: convertExcelRangeToSheetXC(data.range, dataSetsHaveTitle),
44358
44351
  label,
44352
+ backgroundColor: data.backgroundColor,
44359
44353
  };
44360
44354
  });
44361
44355
  // For doughnut charts, in chartJS first dataset = outer dataset, in excel first dataset = inner dataset
@@ -45549,11 +45543,13 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
45549
45543
  label = { text };
45550
45544
  }
45551
45545
  }
45546
+ const color = this.extractChildAttr(chartDataElement, "c:spPr a:solidFill a:srgbClr", "val");
45552
45547
  return {
45553
45548
  label,
45554
45549
  range: this.extractChildTextContent(chartDataElement, "c:val c:f", {
45555
45550
  required: true,
45556
45551
  }),
45552
+ backgroundColor: color ? `${toHex(color.asString())}` : undefined,
45557
45553
  };
45558
45554
  });
45559
45555
  })
@@ -47759,6 +47755,9 @@ class CellPlugin extends CorePlugin {
47759
47755
  format: "",
47760
47756
  });
47761
47757
  break;
47758
+ case "CLEAR_CELLS":
47759
+ this.clearCells(cmd.sheetId, cmd.target);
47760
+ break;
47762
47761
  case "DELETE_CONTENT":
47763
47762
  this.clearZones(cmd.sheetId, cmd.target);
47764
47763
  break;
@@ -47817,6 +47816,25 @@ class CellPlugin extends CorePlugin {
47817
47816
  }
47818
47817
  }
47819
47818
  }
47819
+ /**
47820
+ * Clear the styles, the format and the content of zones
47821
+ */
47822
+ clearCells(sheetId, zones) {
47823
+ for (const zone of zones) {
47824
+ for (let col = zone.left; col <= zone.right; col++) {
47825
+ for (let row = zone.top; row <= zone.bottom; row++) {
47826
+ this.dispatch("UPDATE_CELL", {
47827
+ sheetId: sheetId,
47828
+ col,
47829
+ row,
47830
+ content: "",
47831
+ style: null,
47832
+ format: "",
47833
+ });
47834
+ }
47835
+ }
47836
+ }
47837
+ }
47820
47838
  /**
47821
47839
  * Copy the style of the reference column/row to the new columns/rows.
47822
47840
  */
@@ -49228,7 +49246,10 @@ class HeaderSizePlugin extends CorePlugin {
49228
49246
  handle(cmd) {
49229
49247
  switch (cmd.type) {
49230
49248
  case "CREATE_SHEET": {
49231
- this.history.update("sizes", cmd.sheetId, { COL: [], ROW: [] });
49249
+ this.history.update("sizes", cmd.sheetId, {
49250
+ COL: Array(this.getters.getNumberCols(cmd.sheetId)).fill(undefined),
49251
+ ROW: Array(this.getters.getNumberRows(cmd.sheetId)).fill(undefined),
49252
+ });
49232
49253
  break;
49233
49254
  }
49234
49255
  case "DUPLICATE_SHEET":
@@ -51277,19 +51298,23 @@ class SheetPlugin extends CorePlugin {
51277
51298
  }
51278
51299
  }
51279
51300
  moveCellOnColumnsDeletion(sheet, deletedColumn) {
51301
+ this.dispatch("CLEAR_CELLS", {
51302
+ sheetId: sheet.id,
51303
+ target: [
51304
+ {
51305
+ left: deletedColumn,
51306
+ top: 0,
51307
+ right: deletedColumn,
51308
+ bottom: sheet.rows.length - 1,
51309
+ },
51310
+ ],
51311
+ });
51280
51312
  for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
51281
51313
  const row = sheet.rows[rowIndex];
51282
51314
  for (let i in row.cells) {
51283
51315
  const colIndex = Number(i);
51284
51316
  const cellId = row.cells[i];
51285
51317
  if (cellId) {
51286
- if (colIndex === deletedColumn) {
51287
- this.dispatch("CLEAR_CELL", {
51288
- sheetId: sheet.id,
51289
- col: colIndex,
51290
- row: rowIndex,
51291
- });
51292
- }
51293
51318
  if (colIndex > deletedColumn) {
51294
51319
  this.setNewPosition(cellId, sheet.id, colIndex - 1, rowIndex);
51295
51320
  }
@@ -51335,22 +51360,20 @@ class SheetPlugin extends CorePlugin {
51335
51360
  *
51336
51361
  */
51337
51362
  moveCellOnRowsDeletion(sheet, deleteFromRow, deleteToRow) {
51363
+ this.dispatch("CLEAR_CELLS", {
51364
+ sheetId: sheet.id,
51365
+ target: [
51366
+ {
51367
+ left: 0,
51368
+ top: deleteFromRow,
51369
+ right: this.getters.getNumberCols(sheet.id),
51370
+ bottom: deleteToRow,
51371
+ },
51372
+ ],
51373
+ });
51338
51374
  const numberRows = deleteToRow - deleteFromRow + 1;
51339
51375
  for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
51340
51376
  const row = sheet.rows[rowIndex];
51341
- if (rowIndex >= deleteFromRow && rowIndex <= deleteToRow) {
51342
- for (let i in row.cells) {
51343
- const colIndex = Number(i);
51344
- const cellId = row.cells[i];
51345
- if (cellId) {
51346
- this.dispatch("CLEAR_CELL", {
51347
- sheetId: sheet.id,
51348
- col: colIndex,
51349
- row: rowIndex,
51350
- });
51351
- }
51352
- }
51353
- }
51354
51377
  if (rowIndex > deleteToRow) {
51355
51378
  for (let i in row.cells) {
51356
51379
  const colIndex = Number(i);
@@ -55911,6 +55934,9 @@ class PivotUIPlugin extends UIPlugin {
55911
55934
  }
55912
55935
  }
55913
55936
  getPivot(pivotId) {
55937
+ if (!this.getters.isExistingPivot(pivotId)) {
55938
+ throw new Error(`pivot ${pivotId} not found`);
55939
+ }
55914
55940
  return this.pivots[pivotId];
55915
55941
  }
55916
55942
  isPivotUnused(pivotId) {
@@ -57204,7 +57230,7 @@ class Session extends EventBus {
57204
57230
  */
57205
57231
  leave(data) {
57206
57232
  if (Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
57207
- this.snapshot(data);
57233
+ this.snapshot(data());
57208
57234
  }
57209
57235
  delete this.clients[this.clientId];
57210
57236
  this.transportService.leave(this.clientId);
@@ -57626,9 +57652,7 @@ class DataCleanupPlugin extends UIPlugin {
57626
57652
  if (!data) {
57627
57653
  return;
57628
57654
  }
57629
- for (const { col, row } of positions(zone)) {
57630
- this.dispatch("CLEAR_CELL", { col, row, sheetId });
57631
- }
57655
+ this.dispatch("CLEAR_CELLS", { target: [zone], sheetId });
57632
57656
  const zonePasted = {
57633
57657
  left: zone.left,
57634
57658
  top: zone.top,
@@ -57993,7 +58017,7 @@ class InsertPivotPlugin extends UIPlugin {
57993
58017
  sheetId,
57994
58018
  col,
57995
58019
  row,
57996
- content: `=PIVOT("${pivotFormulaId}")`,
58020
+ content: `=PIVOT(${pivotFormulaId})`,
57997
58021
  });
57998
58022
  const zone = {
57999
58023
  left: col,
@@ -58301,6 +58325,9 @@ class SheetUIPlugin extends UIPlugin {
58301
58325
  if (showFormula && cell?.isFormula) {
58302
58326
  return localizeFormula(cell.content, this.getters.getLocale());
58303
58327
  }
58328
+ else if (showFormula && !cell?.content) {
58329
+ return "";
58330
+ }
58304
58331
  else {
58305
58332
  return this.getters.getEvaluatedCell(position).formattedValue;
58306
58333
  }
@@ -58799,6 +58826,7 @@ function repeatGroupHeadersCommand(getters, cmd) {
58799
58826
  const repeatCommandTransformRegistry = new Registry();
58800
58827
  repeatCommandTransformRegistry.add("UPDATE_CELL", genericRepeat);
58801
58828
  repeatCommandTransformRegistry.add("CLEAR_CELL", genericRepeat);
58829
+ repeatCommandTransformRegistry.add("CLEAR_CELLS", genericRepeat);
58802
58830
  repeatCommandTransformRegistry.add("DELETE_CONTENT", genericRepeat);
58803
58831
  repeatCommandTransformRegistry.add("ADD_MERGE", genericRepeat);
58804
58832
  repeatCommandTransformRegistry.add("REMOVE_MERGE", genericRepeat);
@@ -59380,6 +59408,7 @@ class ClipboardPlugin extends UIPlugin {
59380
59408
  this.status = "invisible";
59381
59409
  if (this._isCutOperation) {
59382
59410
  this.copiedData = undefined;
59411
+ this._isCutOperation = false;
59383
59412
  }
59384
59413
  break;
59385
59414
  }
@@ -59423,9 +59452,10 @@ class ClipboardPlugin extends UIPlugin {
59423
59452
  case "DELETE_CELL": {
59424
59453
  const { cut, paste } = this.getDeleteCellsTargets(cmd.zone, cmd.shiftDimension);
59425
59454
  if (!isZoneValid(cut[0])) {
59426
- for (const { col, row } of positions(cmd.zone)) {
59427
- this.dispatch("CLEAR_CELL", { col, row, sheetId: this.getters.getActiveSheetId() });
59428
- }
59455
+ this.dispatch("CLEAR_CELLS", {
59456
+ target: [cmd.zone],
59457
+ sheetId: this.getters.getActiveSheetId(),
59458
+ });
59429
59459
  break;
59430
59460
  }
59431
59461
  const copiedData = this.copy(cut);
@@ -59476,6 +59506,7 @@ class ClipboardPlugin extends UIPlugin {
59476
59506
  }
59477
59507
  case "ACTIVATE_PAINT_FORMAT": {
59478
59508
  const zones = this.getters.getSelectedZones();
59509
+ this._isCutOperation = false;
59479
59510
  this.copiedData = this.copy(zones);
59480
59511
  this.status = "visible";
59481
59512
  if (cmd.persistent) {
@@ -67827,7 +67858,7 @@ class Model extends EventBus {
67827
67858
  this.session.join(this.config.client);
67828
67859
  }
67829
67860
  leaveSession() {
67830
- this.session.leave(this.exportData());
67861
+ this.session.leave(lazy(() => this.exportData()));
67831
67862
  }
67832
67863
  setupUiPlugin(Plugin) {
67833
67864
  const plugin = new Plugin(this.uiPluginConfig);
@@ -68429,6 +68460,6 @@ exports.tokenColors = tokenColors;
68429
68460
  exports.tokenize = tokenize;
68430
68461
 
68431
68462
 
68432
- __info__.version = "17.4.4";
68433
- __info__.date = "2024-08-09T12:24:07.798Z";
68434
- __info__.hash = "a43e855";
68463
+ __info__.version = "17.4.6";
68464
+ __info__.date = "2024-08-26T13:50:49.623Z";
68465
+ __info__.hash = "f5648d9";