@odoo/o-spreadsheet 17.4.12 → 17.4.14

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.12
6
- * @date 2024-11-13T15:06:56.109Z
7
- * @hash 5cde4be
5
+ * @version 17.4.14
6
+ * @date 2024-11-28T09:08:12.462Z
7
+ * @hash 81bf386
8
8
  */
9
9
 
10
10
  'use strict';
@@ -3136,7 +3136,9 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
3136
3136
  return reverseSearch ? numberOfValues - i - 1 : i;
3137
3137
  }
3138
3138
  }
3139
- return reverseSearch ? numberOfValues - closestMatchIndex - 1 : closestMatchIndex;
3139
+ return reverseSearch && closestMatchIndex !== -1
3140
+ ? numberOfValues - closestMatchIndex - 1
3141
+ : closestMatchIndex;
3140
3142
  }
3141
3143
  /**
3142
3144
  * Normalize a value.
@@ -25181,9 +25183,12 @@ function createPyramidChartRuntime(chart, getters) {
25181
25183
  if (datasets && datasets[1]) {
25182
25184
  datasets[1].data = datasets[1].data.map((value) => (value > 0 ? -value : 0));
25183
25185
  }
25186
+ const maxValue = Math.max(...config.data?.datasets.map((dataSet) => Math.max(...dataSet.data.map(Math.abs))));
25184
25187
  const scales = config.options.scales;
25185
25188
  const scalesXCallback = scales.x.ticks.callback;
25186
25189
  scales.x.ticks.callback = (value) => scalesXCallback(Math.abs(value));
25190
+ scales.x.suggestedMin = -maxValue;
25191
+ scales.x.suggestedMax = maxValue;
25187
25192
  const tooltipLabelCallback = config.options.plugins.tooltip.callbacks.label;
25188
25193
  config.options.plugins.tooltip.callbacks.label = (item) => {
25189
25194
  const tooltipItem = { ...item, parsed: { y: item.parsed.y, x: Math.abs(item.parsed.x) } };
@@ -54281,6 +54286,9 @@ class Evaluator {
54281
54286
  }
54282
54287
  for (let i = 0; i < positions.length; ++i) {
54283
54288
  const position = positions[i];
54289
+ if (this.nextPositionsToUpdate.has(position)) {
54290
+ continue;
54291
+ }
54284
54292
  const evaluatedCell = this.computeCell(position);
54285
54293
  if (evaluatedCell !== EMPTY_CELL) {
54286
54294
  this.evaluatedCells.set(position, evaluatedCell);
@@ -54288,6 +54296,9 @@ class Evaluator {
54288
54296
  }
54289
54297
  onIterationEndEvaluationRegistry.getAll().forEach((callback) => callback(this.getters));
54290
54298
  }
54299
+ if (currentIteration >= MAX_ITERATION) {
54300
+ console.warn("Maximum iteration reached while evaluating cells");
54301
+ }
54291
54302
  }
54292
54303
  computeCell(position) {
54293
54304
  const evaluation = this.evaluatedCells.get(position);
@@ -54322,7 +54333,6 @@ class Evaluator {
54322
54333
  }
54323
54334
  finally {
54324
54335
  this.cellsBeingComputed.delete(cellId);
54325
- this.nextPositionsToUpdate.delete(position);
54326
54336
  }
54327
54337
  }
54328
54338
  computeAndSave(position) {
@@ -54373,6 +54383,7 @@ class Evaluator {
54373
54383
  { sheetId, zone: rightPartZone },
54374
54384
  { sheetId, zone: leftColumnZone },
54375
54385
  ]);
54386
+ invalidatedPositions.delete(arrayFormulaPosition);
54376
54387
  this.nextPositionsToUpdate.addMany(invalidatedPositions);
54377
54388
  }
54378
54389
  assertSheetHasEnoughSpaceToSpreadFormulaResult({ sheetId, col, row }, matrixResult) {
@@ -54451,6 +54462,8 @@ class Evaluator {
54451
54462
  }
54452
54463
  this.nextPositionsToUpdate.addMany(this.getCellsDependingOn(invalidated));
54453
54464
  this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedBy(invalidated));
54465
+ [...invalidated].forEach((inv) => this.spreadingRelations.removeNode(inv));
54466
+ this.spreadingRelations.removeNode(position);
54454
54467
  }
54455
54468
  // ----------------------------------------------------------
54456
54469
  // COMMON FUNCTIONALITY
@@ -55431,25 +55444,11 @@ class EvaluationDataValidationPlugin extends UIPlugin {
55431
55444
  }
55432
55445
  switch (cmd.type) {
55433
55446
  case "ADD_DATA_VALIDATION_RULE":
55434
- const ranges = cmd.ranges.map((range) => this.getters.getRangeFromRangeData(range));
55435
- if (cmd.rule.criterion.type === "isBoolean") {
55436
- this.setContentToBooleanCells({ ...cmd.rule, ranges });
55437
- }
55438
- delete this.validationResults[cmd.sheetId];
55439
- break;
55440
55447
  case "REMOVE_DATA_VALIDATION_RULE":
55441
55448
  delete this.validationResults[cmd.sheetId];
55442
55449
  break;
55443
55450
  }
55444
55451
  }
55445
- setContentToBooleanCells(rule) {
55446
- for (const position of getCellPositionsInRanges(rule.ranges)) {
55447
- const evaluatedCell = this.getters.getEvaluatedCell(position);
55448
- if (evaluatedCell.type !== CellValueType.boolean) {
55449
- this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
55450
- }
55451
- }
55452
- }
55453
55452
  isDataValidationInvalid(cellPosition) {
55454
55453
  return !this.getValidationResultForCell(cellPosition).isValid;
55455
55454
  }
@@ -57381,7 +57380,7 @@ class Session extends EventBus {
57381
57380
  * Notify the server that the user client left the collaborative session
57382
57381
  */
57383
57382
  async leave(data) {
57384
- if (Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
57383
+ if (data && Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
57385
57384
  await this.snapshot(data());
57386
57385
  }
57387
57386
  delete this.clients[this.clientId];
@@ -58852,6 +58851,42 @@ class CellComputedStylePlugin extends UIPlugin {
58852
58851
  }
58853
58852
  }
58854
58853
 
58854
+ class DataValidationInsertionPlugin extends UIPlugin {
58855
+ handle(cmd) {
58856
+ switch (cmd.type) {
58857
+ case "ADD_DATA_VALIDATION_RULE":
58858
+ if (cmd.rule.criterion.type === "isBoolean") {
58859
+ const ranges = cmd.ranges.map((range) => this.getters.getRangeFromRangeData(range));
58860
+ for (const position of getCellPositionsInRanges(ranges)) {
58861
+ const cell = this.getters.getCell(position);
58862
+ const evaluatedCell = this.getters.getEvaluatedCell(position);
58863
+ if (!cell?.content) {
58864
+ this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
58865
+ // In this case, a cell has been updated in the core plugin but
58866
+ // not yet evaluated. This can occur after a paste operation.
58867
+ }
58868
+ else if (cell?.content && evaluatedCell.type === CellValueType.empty) {
58869
+ let value;
58870
+ if (cell.content.startsWith("=")) {
58871
+ const result = this.getters.evaluateFormula(position.sheetId, cell.content);
58872
+ value = (isMatrix(result) ? result[0][0] : result)?.toString();
58873
+ }
58874
+ else {
58875
+ value = cell.content;
58876
+ }
58877
+ if (!value || !isBoolean(value)) {
58878
+ this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
58879
+ }
58880
+ }
58881
+ else if (evaluatedCell.type !== CellValueType.boolean) {
58882
+ this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
58883
+ }
58884
+ }
58885
+ }
58886
+ }
58887
+ }
58888
+ }
58889
+
58855
58890
  const genericRepeatsTransforms = [
58856
58891
  repeatSheetDependantCommand,
58857
58892
  repeatTargetDependantCommand,
@@ -61917,7 +61952,8 @@ const featurePluginRegistry = new Registry()
61917
61952
  .add("history", HistoryPlugin)
61918
61953
  .add("data_cleanup", DataCleanupPlugin)
61919
61954
  .add("table_autofill", TableAutofillPlugin)
61920
- .add("table_ui_resize", TableResizeUI);
61955
+ .add("table_ui_resize", TableResizeUI)
61956
+ .add("datavalidation_insert", DataValidationInsertionPlugin);
61921
61957
  // Plugins which have a state, but which should not be shared in collaborative
61922
61958
  const statefulUIPluginRegistry = new Registry()
61923
61959
  .add("selection", GridSelectionPlugin)
@@ -68079,7 +68115,8 @@ class Model extends EventBus {
68079
68115
  this.session.join(this.config.client);
68080
68116
  }
68081
68117
  async leaveSession() {
68082
- await this.session.leave(lazy(() => this.exportData()));
68118
+ const snapshot = this.getters.isReadonly() ? undefined : lazy(() => this.exportData());
68119
+ await this.session.leave(snapshot);
68083
68120
  }
68084
68121
  setupUiPlugin(Plugin) {
68085
68122
  const plugin = new Plugin(this.uiPluginConfig);
@@ -68682,6 +68719,6 @@ exports.tokenColors = tokenColors;
68682
68719
  exports.tokenize = tokenize;
68683
68720
 
68684
68721
 
68685
- __info__.version = "17.4.12";
68686
- __info__.date = "2024-11-13T15:06:56.109Z";
68687
- __info__.hash = "5cde4be";
68722
+ __info__.version = "17.4.14";
68723
+ __info__.date = "2024-11-28T09:08:12.462Z";
68724
+ __info__.hash = "81bf386";
@@ -3868,7 +3868,7 @@ declare class Session extends EventBus<CollaborativeEvent> {
3868
3868
  /**
3869
3869
  * Notify the server that the user client left the collaborative session
3870
3870
  */
3871
- leave(data: Lazy<WorkbookData>): Promise<void>;
3871
+ leave(data?: Lazy<WorkbookData>): Promise<void>;
3872
3872
  /**
3873
3873
  * Send a snapshot of the spreadsheet to the collaboration server
3874
3874
  */
@@ -4128,7 +4128,6 @@ declare class EvaluationDataValidationPlugin extends UIPlugin {
4128
4128
  static getters: readonly ["getDataValidationInvalidCriterionValueMessage", "getInvalidDataValidationMessage", "getValidationResultForCellValue", "isCellValidCheckbox", "isDataValidationInvalid"];
4129
4129
  validationResults: Record<UID, SheetValidationResult>;
4130
4130
  handle(cmd: CoreViewCommand): void;
4131
- private setContentToBooleanCells;
4132
4131
  isDataValidationInvalid(cellPosition: CellPosition): boolean;
4133
4132
  getInvalidDataValidationMessage(cellPosition: CellPosition): string | undefined;
4134
4133
  /**
@@ -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.12
6
- * @date 2024-11-13T15:06:56.109Z
7
- * @hash 5cde4be
5
+ * @version 17.4.14
6
+ * @date 2024-11-28T09:08:12.462Z
7
+ * @hash 81bf386
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -3134,7 +3134,9 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
3134
3134
  return reverseSearch ? numberOfValues - i - 1 : i;
3135
3135
  }
3136
3136
  }
3137
- return reverseSearch ? numberOfValues - closestMatchIndex - 1 : closestMatchIndex;
3137
+ return reverseSearch && closestMatchIndex !== -1
3138
+ ? numberOfValues - closestMatchIndex - 1
3139
+ : closestMatchIndex;
3138
3140
  }
3139
3141
  /**
3140
3142
  * Normalize a value.
@@ -25179,9 +25181,12 @@ function createPyramidChartRuntime(chart, getters) {
25179
25181
  if (datasets && datasets[1]) {
25180
25182
  datasets[1].data = datasets[1].data.map((value) => (value > 0 ? -value : 0));
25181
25183
  }
25184
+ const maxValue = Math.max(...config.data?.datasets.map((dataSet) => Math.max(...dataSet.data.map(Math.abs))));
25182
25185
  const scales = config.options.scales;
25183
25186
  const scalesXCallback = scales.x.ticks.callback;
25184
25187
  scales.x.ticks.callback = (value) => scalesXCallback(Math.abs(value));
25188
+ scales.x.suggestedMin = -maxValue;
25189
+ scales.x.suggestedMax = maxValue;
25185
25190
  const tooltipLabelCallback = config.options.plugins.tooltip.callbacks.label;
25186
25191
  config.options.plugins.tooltip.callbacks.label = (item) => {
25187
25192
  const tooltipItem = { ...item, parsed: { y: item.parsed.y, x: Math.abs(item.parsed.x) } };
@@ -54279,6 +54284,9 @@ class Evaluator {
54279
54284
  }
54280
54285
  for (let i = 0; i < positions.length; ++i) {
54281
54286
  const position = positions[i];
54287
+ if (this.nextPositionsToUpdate.has(position)) {
54288
+ continue;
54289
+ }
54282
54290
  const evaluatedCell = this.computeCell(position);
54283
54291
  if (evaluatedCell !== EMPTY_CELL) {
54284
54292
  this.evaluatedCells.set(position, evaluatedCell);
@@ -54286,6 +54294,9 @@ class Evaluator {
54286
54294
  }
54287
54295
  onIterationEndEvaluationRegistry.getAll().forEach((callback) => callback(this.getters));
54288
54296
  }
54297
+ if (currentIteration >= MAX_ITERATION) {
54298
+ console.warn("Maximum iteration reached while evaluating cells");
54299
+ }
54289
54300
  }
54290
54301
  computeCell(position) {
54291
54302
  const evaluation = this.evaluatedCells.get(position);
@@ -54320,7 +54331,6 @@ class Evaluator {
54320
54331
  }
54321
54332
  finally {
54322
54333
  this.cellsBeingComputed.delete(cellId);
54323
- this.nextPositionsToUpdate.delete(position);
54324
54334
  }
54325
54335
  }
54326
54336
  computeAndSave(position) {
@@ -54371,6 +54381,7 @@ class Evaluator {
54371
54381
  { sheetId, zone: rightPartZone },
54372
54382
  { sheetId, zone: leftColumnZone },
54373
54383
  ]);
54384
+ invalidatedPositions.delete(arrayFormulaPosition);
54374
54385
  this.nextPositionsToUpdate.addMany(invalidatedPositions);
54375
54386
  }
54376
54387
  assertSheetHasEnoughSpaceToSpreadFormulaResult({ sheetId, col, row }, matrixResult) {
@@ -54449,6 +54460,8 @@ class Evaluator {
54449
54460
  }
54450
54461
  this.nextPositionsToUpdate.addMany(this.getCellsDependingOn(invalidated));
54451
54462
  this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedBy(invalidated));
54463
+ [...invalidated].forEach((inv) => this.spreadingRelations.removeNode(inv));
54464
+ this.spreadingRelations.removeNode(position);
54452
54465
  }
54453
54466
  // ----------------------------------------------------------
54454
54467
  // COMMON FUNCTIONALITY
@@ -55429,25 +55442,11 @@ class EvaluationDataValidationPlugin extends UIPlugin {
55429
55442
  }
55430
55443
  switch (cmd.type) {
55431
55444
  case "ADD_DATA_VALIDATION_RULE":
55432
- const ranges = cmd.ranges.map((range) => this.getters.getRangeFromRangeData(range));
55433
- if (cmd.rule.criterion.type === "isBoolean") {
55434
- this.setContentToBooleanCells({ ...cmd.rule, ranges });
55435
- }
55436
- delete this.validationResults[cmd.sheetId];
55437
- break;
55438
55445
  case "REMOVE_DATA_VALIDATION_RULE":
55439
55446
  delete this.validationResults[cmd.sheetId];
55440
55447
  break;
55441
55448
  }
55442
55449
  }
55443
- setContentToBooleanCells(rule) {
55444
- for (const position of getCellPositionsInRanges(rule.ranges)) {
55445
- const evaluatedCell = this.getters.getEvaluatedCell(position);
55446
- if (evaluatedCell.type !== CellValueType.boolean) {
55447
- this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
55448
- }
55449
- }
55450
- }
55451
55450
  isDataValidationInvalid(cellPosition) {
55452
55451
  return !this.getValidationResultForCell(cellPosition).isValid;
55453
55452
  }
@@ -57379,7 +57378,7 @@ class Session extends EventBus {
57379
57378
  * Notify the server that the user client left the collaborative session
57380
57379
  */
57381
57380
  async leave(data) {
57382
- if (Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
57381
+ if (data && Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
57383
57382
  await this.snapshot(data());
57384
57383
  }
57385
57384
  delete this.clients[this.clientId];
@@ -58850,6 +58849,42 @@ class CellComputedStylePlugin extends UIPlugin {
58850
58849
  }
58851
58850
  }
58852
58851
 
58852
+ class DataValidationInsertionPlugin extends UIPlugin {
58853
+ handle(cmd) {
58854
+ switch (cmd.type) {
58855
+ case "ADD_DATA_VALIDATION_RULE":
58856
+ if (cmd.rule.criterion.type === "isBoolean") {
58857
+ const ranges = cmd.ranges.map((range) => this.getters.getRangeFromRangeData(range));
58858
+ for (const position of getCellPositionsInRanges(ranges)) {
58859
+ const cell = this.getters.getCell(position);
58860
+ const evaluatedCell = this.getters.getEvaluatedCell(position);
58861
+ if (!cell?.content) {
58862
+ this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
58863
+ // In this case, a cell has been updated in the core plugin but
58864
+ // not yet evaluated. This can occur after a paste operation.
58865
+ }
58866
+ else if (cell?.content && evaluatedCell.type === CellValueType.empty) {
58867
+ let value;
58868
+ if (cell.content.startsWith("=")) {
58869
+ const result = this.getters.evaluateFormula(position.sheetId, cell.content);
58870
+ value = (isMatrix(result) ? result[0][0] : result)?.toString();
58871
+ }
58872
+ else {
58873
+ value = cell.content;
58874
+ }
58875
+ if (!value || !isBoolean(value)) {
58876
+ this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
58877
+ }
58878
+ }
58879
+ else if (evaluatedCell.type !== CellValueType.boolean) {
58880
+ this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
58881
+ }
58882
+ }
58883
+ }
58884
+ }
58885
+ }
58886
+ }
58887
+
58853
58888
  const genericRepeatsTransforms = [
58854
58889
  repeatSheetDependantCommand,
58855
58890
  repeatTargetDependantCommand,
@@ -61915,7 +61950,8 @@ const featurePluginRegistry = new Registry()
61915
61950
  .add("history", HistoryPlugin)
61916
61951
  .add("data_cleanup", DataCleanupPlugin)
61917
61952
  .add("table_autofill", TableAutofillPlugin)
61918
- .add("table_ui_resize", TableResizeUI);
61953
+ .add("table_ui_resize", TableResizeUI)
61954
+ .add("datavalidation_insert", DataValidationInsertionPlugin);
61919
61955
  // Plugins which have a state, but which should not be shared in collaborative
61920
61956
  const statefulUIPluginRegistry = new Registry()
61921
61957
  .add("selection", GridSelectionPlugin)
@@ -68077,7 +68113,8 @@ class Model extends EventBus {
68077
68113
  this.session.join(this.config.client);
68078
68114
  }
68079
68115
  async leaveSession() {
68080
- await this.session.leave(lazy(() => this.exportData()));
68116
+ const snapshot = this.getters.isReadonly() ? undefined : lazy(() => this.exportData());
68117
+ await this.session.leave(snapshot);
68081
68118
  }
68082
68119
  setupUiPlugin(Plugin) {
68083
68120
  const plugin = new Plugin(this.uiPluginConfig);
@@ -68637,6 +68674,6 @@ const constants = {
68637
68674
  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 };
68638
68675
 
68639
68676
 
68640
- __info__.version = "17.4.12";
68641
- __info__.date = "2024-11-13T15:06:56.109Z";
68642
- __info__.hash = "5cde4be";
68677
+ __info__.version = "17.4.14";
68678
+ __info__.date = "2024-11-28T09:08:12.462Z";
68679
+ __info__.hash = "81bf386";
@@ -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.12
6
- * @date 2024-11-13T15:06:56.109Z
7
- * @hash 5cde4be
5
+ * @version 17.4.14
6
+ * @date 2024-11-28T09:08:12.462Z
7
+ * @hash 81bf386
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -3135,7 +3135,9 @@
3135
3135
  return reverseSearch ? numberOfValues - i - 1 : i;
3136
3136
  }
3137
3137
  }
3138
- return reverseSearch ? numberOfValues - closestMatchIndex - 1 : closestMatchIndex;
3138
+ return reverseSearch && closestMatchIndex !== -1
3139
+ ? numberOfValues - closestMatchIndex - 1
3140
+ : closestMatchIndex;
3139
3141
  }
3140
3142
  /**
3141
3143
  * Normalize a value.
@@ -25180,9 +25182,12 @@ stores.inject(MyMetaStore, storeInstance);
25180
25182
  if (datasets && datasets[1]) {
25181
25183
  datasets[1].data = datasets[1].data.map((value) => (value > 0 ? -value : 0));
25182
25184
  }
25185
+ const maxValue = Math.max(...config.data?.datasets.map((dataSet) => Math.max(...dataSet.data.map(Math.abs))));
25183
25186
  const scales = config.options.scales;
25184
25187
  const scalesXCallback = scales.x.ticks.callback;
25185
25188
  scales.x.ticks.callback = (value) => scalesXCallback(Math.abs(value));
25189
+ scales.x.suggestedMin = -maxValue;
25190
+ scales.x.suggestedMax = maxValue;
25186
25191
  const tooltipLabelCallback = config.options.plugins.tooltip.callbacks.label;
25187
25192
  config.options.plugins.tooltip.callbacks.label = (item) => {
25188
25193
  const tooltipItem = { ...item, parsed: { y: item.parsed.y, x: Math.abs(item.parsed.x) } };
@@ -54280,6 +54285,9 @@ stores.inject(MyMetaStore, storeInstance);
54280
54285
  }
54281
54286
  for (let i = 0; i < positions.length; ++i) {
54282
54287
  const position = positions[i];
54288
+ if (this.nextPositionsToUpdate.has(position)) {
54289
+ continue;
54290
+ }
54283
54291
  const evaluatedCell = this.computeCell(position);
54284
54292
  if (evaluatedCell !== EMPTY_CELL) {
54285
54293
  this.evaluatedCells.set(position, evaluatedCell);
@@ -54287,6 +54295,9 @@ stores.inject(MyMetaStore, storeInstance);
54287
54295
  }
54288
54296
  onIterationEndEvaluationRegistry.getAll().forEach((callback) => callback(this.getters));
54289
54297
  }
54298
+ if (currentIteration >= MAX_ITERATION) {
54299
+ console.warn("Maximum iteration reached while evaluating cells");
54300
+ }
54290
54301
  }
54291
54302
  computeCell(position) {
54292
54303
  const evaluation = this.evaluatedCells.get(position);
@@ -54321,7 +54332,6 @@ stores.inject(MyMetaStore, storeInstance);
54321
54332
  }
54322
54333
  finally {
54323
54334
  this.cellsBeingComputed.delete(cellId);
54324
- this.nextPositionsToUpdate.delete(position);
54325
54335
  }
54326
54336
  }
54327
54337
  computeAndSave(position) {
@@ -54372,6 +54382,7 @@ stores.inject(MyMetaStore, storeInstance);
54372
54382
  { sheetId, zone: rightPartZone },
54373
54383
  { sheetId, zone: leftColumnZone },
54374
54384
  ]);
54385
+ invalidatedPositions.delete(arrayFormulaPosition);
54375
54386
  this.nextPositionsToUpdate.addMany(invalidatedPositions);
54376
54387
  }
54377
54388
  assertSheetHasEnoughSpaceToSpreadFormulaResult({ sheetId, col, row }, matrixResult) {
@@ -54450,6 +54461,8 @@ stores.inject(MyMetaStore, storeInstance);
54450
54461
  }
54451
54462
  this.nextPositionsToUpdate.addMany(this.getCellsDependingOn(invalidated));
54452
54463
  this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedBy(invalidated));
54464
+ [...invalidated].forEach((inv) => this.spreadingRelations.removeNode(inv));
54465
+ this.spreadingRelations.removeNode(position);
54453
54466
  }
54454
54467
  // ----------------------------------------------------------
54455
54468
  // COMMON FUNCTIONALITY
@@ -55430,25 +55443,11 @@ stores.inject(MyMetaStore, storeInstance);
55430
55443
  }
55431
55444
  switch (cmd.type) {
55432
55445
  case "ADD_DATA_VALIDATION_RULE":
55433
- const ranges = cmd.ranges.map((range) => this.getters.getRangeFromRangeData(range));
55434
- if (cmd.rule.criterion.type === "isBoolean") {
55435
- this.setContentToBooleanCells({ ...cmd.rule, ranges });
55436
- }
55437
- delete this.validationResults[cmd.sheetId];
55438
- break;
55439
55446
  case "REMOVE_DATA_VALIDATION_RULE":
55440
55447
  delete this.validationResults[cmd.sheetId];
55441
55448
  break;
55442
55449
  }
55443
55450
  }
55444
- setContentToBooleanCells(rule) {
55445
- for (const position of getCellPositionsInRanges(rule.ranges)) {
55446
- const evaluatedCell = this.getters.getEvaluatedCell(position);
55447
- if (evaluatedCell.type !== CellValueType.boolean) {
55448
- this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
55449
- }
55450
- }
55451
- }
55452
55451
  isDataValidationInvalid(cellPosition) {
55453
55452
  return !this.getValidationResultForCell(cellPosition).isValid;
55454
55453
  }
@@ -57380,7 +57379,7 @@ stores.inject(MyMetaStore, storeInstance);
57380
57379
  * Notify the server that the user client left the collaborative session
57381
57380
  */
57382
57381
  async leave(data) {
57383
- if (Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
57382
+ if (data && Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
57384
57383
  await this.snapshot(data());
57385
57384
  }
57386
57385
  delete this.clients[this.clientId];
@@ -58851,6 +58850,42 @@ stores.inject(MyMetaStore, storeInstance);
58851
58850
  }
58852
58851
  }
58853
58852
 
58853
+ class DataValidationInsertionPlugin extends UIPlugin {
58854
+ handle(cmd) {
58855
+ switch (cmd.type) {
58856
+ case "ADD_DATA_VALIDATION_RULE":
58857
+ if (cmd.rule.criterion.type === "isBoolean") {
58858
+ const ranges = cmd.ranges.map((range) => this.getters.getRangeFromRangeData(range));
58859
+ for (const position of getCellPositionsInRanges(ranges)) {
58860
+ const cell = this.getters.getCell(position);
58861
+ const evaluatedCell = this.getters.getEvaluatedCell(position);
58862
+ if (!cell?.content) {
58863
+ this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
58864
+ // In this case, a cell has been updated in the core plugin but
58865
+ // not yet evaluated. This can occur after a paste operation.
58866
+ }
58867
+ else if (cell?.content && evaluatedCell.type === CellValueType.empty) {
58868
+ let value;
58869
+ if (cell.content.startsWith("=")) {
58870
+ const result = this.getters.evaluateFormula(position.sheetId, cell.content);
58871
+ value = (isMatrix(result) ? result[0][0] : result)?.toString();
58872
+ }
58873
+ else {
58874
+ value = cell.content;
58875
+ }
58876
+ if (!value || !isBoolean(value)) {
58877
+ this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
58878
+ }
58879
+ }
58880
+ else if (evaluatedCell.type !== CellValueType.boolean) {
58881
+ this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
58882
+ }
58883
+ }
58884
+ }
58885
+ }
58886
+ }
58887
+ }
58888
+
58854
58889
  const genericRepeatsTransforms = [
58855
58890
  repeatSheetDependantCommand,
58856
58891
  repeatTargetDependantCommand,
@@ -61916,7 +61951,8 @@ stores.inject(MyMetaStore, storeInstance);
61916
61951
  .add("history", HistoryPlugin)
61917
61952
  .add("data_cleanup", DataCleanupPlugin)
61918
61953
  .add("table_autofill", TableAutofillPlugin)
61919
- .add("table_ui_resize", TableResizeUI);
61954
+ .add("table_ui_resize", TableResizeUI)
61955
+ .add("datavalidation_insert", DataValidationInsertionPlugin);
61920
61956
  // Plugins which have a state, but which should not be shared in collaborative
61921
61957
  const statefulUIPluginRegistry = new Registry()
61922
61958
  .add("selection", GridSelectionPlugin)
@@ -68078,7 +68114,8 @@ stores.inject(MyMetaStore, storeInstance);
68078
68114
  this.session.join(this.config.client);
68079
68115
  }
68080
68116
  async leaveSession() {
68081
- await this.session.leave(lazy(() => this.exportData()));
68117
+ const snapshot = this.getters.isReadonly() ? undefined : lazy(() => this.exportData());
68118
+ await this.session.leave(snapshot);
68082
68119
  }
68083
68120
  setupUiPlugin(Plugin) {
68084
68121
  const plugin = new Plugin(this.uiPluginConfig);
@@ -68681,9 +68718,9 @@ stores.inject(MyMetaStore, storeInstance);
68681
68718
  exports.tokenize = tokenize;
68682
68719
 
68683
68720
 
68684
- __info__.version = "17.4.12";
68685
- __info__.date = "2024-11-13T15:06:56.109Z";
68686
- __info__.hash = "5cde4be";
68721
+ __info__.version = "17.4.14";
68722
+ __info__.date = "2024-11-28T09:08:12.462Z";
68723
+ __info__.hash = "81bf386";
68687
68724
 
68688
68725
 
68689
68726
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);