@odoo/o-spreadsheet 18.5.0-alpha.6 → 18.5.0-alpha.7

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 18.5.0-alpha.6
6
- * @date 2025-08-05T06:27:49.505Z
7
- * @hash 67e091f
5
+ * @version 18.5.0-alpha.7
6
+ * @date 2025-08-08T11:00:44.117Z
7
+ * @hash 1019d55
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -2656,6 +2656,7 @@
2656
2656
  "SET_FORMULA_VISIBILITY",
2657
2657
  "UPDATE_FILTER",
2658
2658
  "UPDATE_CHART",
2659
+ "UPDATE_CAROUSEL_ACTIVE_ITEM",
2659
2660
  ]);
2660
2661
  const coreTypes = new Set([
2661
2662
  /** CELLS */
@@ -2698,6 +2699,8 @@
2698
2699
  "CREATE_FIGURE",
2699
2700
  "DELETE_FIGURE",
2700
2701
  "UPDATE_FIGURE",
2702
+ "CREATE_CAROUSEL",
2703
+ "UPDATE_CAROUSEL",
2701
2704
  /** FORMATTING */
2702
2705
  "SET_FORMATTING",
2703
2706
  "CLEAR_FORMATTING",
@@ -2707,6 +2710,7 @@
2707
2710
  /** CHART */
2708
2711
  "CREATE_CHART",
2709
2712
  "UPDATE_CHART",
2713
+ "DELETE_CHART",
2710
2714
  /** FILTERS */
2711
2715
  "CREATE_TABLE",
2712
2716
  "REMOVE_TABLE",
@@ -2901,6 +2905,7 @@
2901
2905
  CommandResult["InvalidColor"] = "InvalidColor";
2902
2906
  CommandResult["InvalidPivotDataSet"] = "InvalidPivotDataSet";
2903
2907
  CommandResult["InvalidPivotCustomField"] = "InvalidPivotCustomField";
2908
+ CommandResult["MissingFigureArguments"] = "MissingFigureArguments";
2904
2909
  })(exports.CommandResult || (exports.CommandResult = {}));
2905
2910
 
2906
2911
  const availableConditionalFormatOperators = new Set([
@@ -9221,7 +9226,7 @@
9221
9226
  return;
9222
9227
  }
9223
9228
  const copiedFigure = { ...figure };
9224
- const chart = this.getters.getChart(data.figureId);
9229
+ const chart = this.getters.getChartFromFigureId(data.figureId);
9225
9230
  if (!chart) {
9226
9231
  throw new Error(`No chart for the given id: ${data.figureId}`);
9227
9232
  }
@@ -9257,6 +9262,7 @@
9257
9262
  }
9258
9263
  this.dispatch("CREATE_CHART", {
9259
9264
  figureId,
9265
+ chartId: figureId,
9260
9266
  sheetId,
9261
9267
  definition: copy.getDefinition(),
9262
9268
  col,
@@ -22997,7 +23003,7 @@ stores.inject(MyMetaStore, storeInstance);
22997
23003
  class ChartJsComponent extends owl.Component {
22998
23004
  static template = "o-spreadsheet-ChartJsComponent";
22999
23005
  static props = {
23000
- figureUI: Object,
23006
+ chartId: String,
23001
23007
  isFullScreen: { type: Boolean, optional: true },
23002
23008
  };
23003
23009
  canvas = owl.useRef("graphContainer");
@@ -23012,7 +23018,7 @@ stores.inject(MyMetaStore, storeInstance);
23012
23018
  return `background-color: ${this.background}`;
23013
23019
  }
23014
23020
  get chartRuntime() {
23015
- const runtime = this.env.model.getters.getChartRuntime(this.props.figureUI.id);
23021
+ const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
23016
23022
  if (!("chartJsConfig" in runtime)) {
23017
23023
  throw new Error("Unsupported chart runtime");
23018
23024
  }
@@ -23050,7 +23056,7 @@ stores.inject(MyMetaStore, storeInstance);
23050
23056
  }
23051
23057
  createChart(chartData) {
23052
23058
  if (this.env.model.getters.isDashboard() && this.animationStore) {
23053
- const chartType = this.env.model.getters.getChart(this.props.figureUI.id)?.type;
23059
+ const chartType = this.env.model.getters.getChart(this.props.chartId)?.type;
23054
23060
  if (chartType && this.animationStore.animationPlayed[this.animationFigureId] !== chartType) {
23055
23061
  chartData = this.enableAnimationInChartData(chartData);
23056
23062
  this.animationStore.disableAnimationForChart(this.animationFigureId, chartType);
@@ -23062,7 +23068,7 @@ stores.inject(MyMetaStore, storeInstance);
23062
23068
  }
23063
23069
  updateChartJs(chartData) {
23064
23070
  if (this.env.model.getters.isDashboard()) {
23065
- const chartType = this.env.model.getters.getChart(this.props.figureUI.id)?.type;
23071
+ const chartType = this.env.model.getters.getChart(this.props.chartId)?.type;
23066
23072
  if (chartType && this.hasChartDataChanged() && this.animationStore) {
23067
23073
  chartData = this.enableAnimationInChartData(chartData);
23068
23074
  this.animationStore.disableAnimationForChart(this.animationFigureId, chartType);
@@ -23090,9 +23096,7 @@ stores.inject(MyMetaStore, storeInstance);
23090
23096
  };
23091
23097
  }
23092
23098
  get animationFigureId() {
23093
- return this.props.isFullScreen
23094
- ? this.props.figureUI.id + "-fullscreen"
23095
- : this.props.figureUI.id;
23099
+ return this.props.isFullScreen ? this.props.chartId + "-fullscreen" : this.props.chartId;
23096
23100
  }
23097
23101
  }
23098
23102
 
@@ -23757,14 +23761,14 @@ stores.inject(MyMetaStore, storeInstance);
23757
23761
  class ScorecardChart extends owl.Component {
23758
23762
  static template = "o-spreadsheet-ScorecardChart";
23759
23763
  static props = {
23760
- figureUI: Object,
23764
+ chartId: String,
23761
23765
  };
23762
23766
  canvas = owl.useRef("chartContainer");
23763
23767
  get runtime() {
23764
- return this.env.model.getters.getChartRuntime(this.props.figureUI.id);
23768
+ return this.env.model.getters.getChartRuntime(this.props.chartId);
23765
23769
  }
23766
23770
  get title() {
23767
- const title = this.env.model.getters.getChartDefinition(this.props.figureUI.id).title.text ?? "";
23771
+ const title = this.env.model.getters.getChartDefinition(this.props.chartId).title.text ?? "";
23768
23772
  // chart titles are extracted from .json files and they are translated at runtime here
23769
23773
  return _t(title);
23770
23774
  }
@@ -27086,13 +27090,13 @@ stores.inject(MyMetaStore, storeInstance);
27086
27090
  class GaugeChartComponent extends owl.Component {
27087
27091
  static template = "o-spreadsheet-GaugeChartComponent";
27088
27092
  static props = {
27089
- figureUI: Object,
27093
+ chartId: String,
27090
27094
  isFullScreen: { type: Boolean, optional: true },
27091
27095
  };
27092
27096
  canvas = owl.useRef("chartContainer");
27093
27097
  animationStore;
27094
27098
  get runtime() {
27095
- return this.env.model.getters.getChartRuntime(this.props.figureUI.id);
27099
+ return this.env.model.getters.getChartRuntime(this.props.chartId);
27096
27100
  }
27097
27101
  setup() {
27098
27102
  if (this.env.model.getters.isDashboard()) {
@@ -27140,9 +27144,7 @@ stores.inject(MyMetaStore, storeInstance);
27140
27144
  return this.canvas.el;
27141
27145
  }
27142
27146
  get animationFigureId() {
27143
- return this.props.isFullScreen
27144
- ? this.props.figureUI.id + "-fullscreen"
27145
- : this.props.figureUI.id;
27147
+ return this.props.isFullScreen ? this.props.chartId + "-fullscreen" : this.props.chartId;
27146
27148
  }
27147
27149
  }
27148
27150
  /**
@@ -29431,7 +29433,7 @@ stores.inject(MyMetaStore, storeInstance);
29431
29433
  */
29432
29434
  function chartFactory(getters) {
29433
29435
  const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
29434
- function createChart(id, definition, sheetId) {
29436
+ function createChart(figureId, definition, sheetId) {
29435
29437
  const builder = builders.find((builder) => builder.match(definition.type));
29436
29438
  if (!builder) {
29437
29439
  throw new Error(`No builder for this chart: ${definition.type}`);
@@ -29782,6 +29784,8 @@ stores.inject(MyMetaStore, storeInstance);
29782
29784
  return {
29783
29785
  relsFiles: [],
29784
29786
  sharedStrings: [],
29787
+ chartIds: [],
29788
+ imageIds: [],
29785
29789
  // default Values that will always be part of the style sheet
29786
29790
  styles: [
29787
29791
  {
@@ -29859,6 +29863,10 @@ stores.inject(MyMetaStore, storeInstance);
29859
29863
  }
29860
29864
 
29861
29865
  function getChartMenuActions(figureId, onFigureDeleted, env) {
29866
+ const chartId = env.model.getters.getChartIdFromFigureId(figureId);
29867
+ if (!chartId) {
29868
+ return [];
29869
+ }
29862
29870
  const menuItemSpecs = [
29863
29871
  {
29864
29872
  id: "edit",
@@ -29881,8 +29889,8 @@ stores.inject(MyMetaStore, storeInstance);
29881
29889
  execute: async () => {
29882
29890
  const figureSheetId = env.model.getters.getFigureSheetId(figureId);
29883
29891
  const figure = env.model.getters.getFigure(figureSheetId, figureId);
29884
- const chartType = env.model.getters.getChartType(figureId);
29885
- const runtime = env.model.getters.getChartRuntime(figureId);
29892
+ const chartType = env.model.getters.getChartType(chartId);
29893
+ const runtime = env.model.getters.getChartRuntime(chartId);
29886
29894
  const imageUrl = chartToImageUrl(runtime, figure, chartType);
29887
29895
  const innerHTML = `<img src="${xmlEscape(imageUrl)}" />`;
29888
29896
  const blob = await chartToImageFile(runtime, figure, chartType);
@@ -29902,8 +29910,8 @@ stores.inject(MyMetaStore, storeInstance);
29902
29910
  execute: async () => {
29903
29911
  const figureSheetId = env.model.getters.getFigureSheetId(figureId);
29904
29912
  const figure = env.model.getters.getFigure(figureSheetId, figureId);
29905
- const chartType = env.model.getters.getChartType(figureId);
29906
- const runtime = env.model.getters.getChartRuntime(figureId);
29913
+ const chartType = env.model.getters.getChartType(chartId);
29914
+ const runtime = env.model.getters.getChartRuntime(chartId);
29907
29915
  const url = chartToImageUrl(runtime, figure, chartType);
29908
29916
  downloadFile(url, "chart");
29909
29917
  },
@@ -29962,6 +29970,35 @@ stores.inject(MyMetaStore, storeInstance);
29962
29970
  ];
29963
29971
  return createActions(menuItemSpecs);
29964
29972
  }
29973
+ function getCarouselMenuActions(figureId, onFigureDeleted, env) {
29974
+ const menuItemSpecs = [
29975
+ {
29976
+ id: "edit_carousel",
29977
+ name: _t("Edit carousel"),
29978
+ sequence: 1,
29979
+ execute: () => {
29980
+ env.model.dispatch("SELECT_FIGURE", { figureId });
29981
+ env.openSidePanel("CarouselPanel", { figureId });
29982
+ },
29983
+ icon: "o-spreadsheet-Icon.EDIT",
29984
+ isEnabled: (env) => !env.isSmall,
29985
+ },
29986
+ {
29987
+ id: "edit_chart",
29988
+ name: _t("Edit chart"),
29989
+ sequence: 1,
29990
+ execute: () => {
29991
+ env.model.dispatch("SELECT_FIGURE", { figureId });
29992
+ env.openSidePanel("ChartPanel", {});
29993
+ },
29994
+ icon: "o-spreadsheet-Icon.EDIT",
29995
+ isEnabled: (env) => !env.isSmall,
29996
+ isVisible: (env) => env.model.getters.getSelectedCarouselItem(figureId)?.type === "chart",
29997
+ },
29998
+ getDeleteMenuItem(figureId, onFigureDeleted, env),
29999
+ ];
30000
+ return createActions(menuItemSpecs).filter((action) => env.model.getters.isReadonly() ? action.isReadonlyAllowed : true);
30001
+ }
29965
30002
  function getCopyMenuItem(figureId, env, copiedNotificationMessage) {
29966
30003
  return {
29967
30004
  id: "copy",
@@ -30010,6 +30047,103 @@ stores.inject(MyMetaStore, storeInstance);
30010
30047
  };
30011
30048
  }
30012
30049
 
30050
+ const CAROUSEL_DEFAULT_CHART_DEFINITION = {
30051
+ type: "bar",
30052
+ title: {},
30053
+ stacked: false,
30054
+ dataSetsHaveTitle: false,
30055
+ dataSets: [],
30056
+ legendPosition: "top",
30057
+ };
30058
+ function getCarouselItemPreview(getters, item) {
30059
+ if (item.type === "carouselDataView") {
30060
+ return "o-spreadsheet-Icon.LIST";
30061
+ }
30062
+ const definition = getters.getChartDefinition(item.chartId);
30063
+ const matchedChart = chartSubtypeRegistry.getAll().find((c) => c.matcher?.(definition)) ||
30064
+ chartSubtypeRegistry.get(definition.type);
30065
+ return matchedChart.preview;
30066
+ }
30067
+ function getCarouselItemTitle(getters, item) {
30068
+ if (item.title) {
30069
+ return item.title;
30070
+ }
30071
+ if (item.type === "carouselDataView") {
30072
+ return _t("Data");
30073
+ }
30074
+ const definition = getters.getChartDefinition(item.chartId);
30075
+ const matchedChart = chartSubtypeRegistry.getAll().find((c) => c.matcher?.(definition)) ||
30076
+ chartSubtypeRegistry.get(definition.type);
30077
+ return matchedChart.displayName;
30078
+ }
30079
+
30080
+ class CarouselFigure extends owl.Component {
30081
+ static template = "o-spreadsheet-CarouselFigure";
30082
+ static props = {
30083
+ figureUI: Object,
30084
+ onFigureDeleted: Function,
30085
+ editFigureStyle: { type: Function, optional: true },
30086
+ };
30087
+ static components = {};
30088
+ setup() {
30089
+ owl.useEffect(() => {
30090
+ if (this.selectedCarouselItem?.type === "carouselDataView") {
30091
+ this.props.editFigureStyle?.({ "pointer-events": "none" });
30092
+ }
30093
+ else {
30094
+ this.props.editFigureStyle?.({ "pointer-events": "auto" });
30095
+ }
30096
+ });
30097
+ }
30098
+ get carousel() {
30099
+ return this.env.model.getters.getCarousel(this.props.figureUI.id);
30100
+ }
30101
+ get selectedCarouselItem() {
30102
+ return this.env.model.getters.getSelectedCarouselItem(this.props.figureUI.id);
30103
+ }
30104
+ get chartComponent() {
30105
+ const selectedItem = this.selectedCarouselItem;
30106
+ if (selectedItem?.type !== "chart") {
30107
+ throw new Error("Selected item is not a chart");
30108
+ }
30109
+ const type = this.env.model.getters.getChartType(selectedItem.chartId);
30110
+ const component = chartComponentRegistry.get(type);
30111
+ if (!component) {
30112
+ throw new Error(`Component is not defined for type ${type}`);
30113
+ }
30114
+ return component;
30115
+ }
30116
+ onCarouselDoubleClick() {
30117
+ this.env.model.dispatch("SELECT_FIGURE", { figureId: this.props.figureUI.id });
30118
+ this.env.openSidePanel("CarouselPanel", { figureId: this.props.figureUI.id });
30119
+ }
30120
+ isItemSelected(item) {
30121
+ const selectedItem = this.selectedCarouselItem;
30122
+ return deepEquals(selectedItem, item);
30123
+ }
30124
+ getItemTitle(item) {
30125
+ return getCarouselItemTitle(this.env.model.getters, item);
30126
+ }
30127
+ onCarouselTabClick(item) {
30128
+ this.env.model.dispatch("UPDATE_CAROUSEL_ACTIVE_ITEM", {
30129
+ figureId: this.props.figureUI.id,
30130
+ sheetId: this.env.model.getters.getActiveSheetId(),
30131
+ item,
30132
+ });
30133
+ if (item.type === "carouselDataView" &&
30134
+ this.env.model.getters.getSelectedFigureId() === this.props.figureUI.id) {
30135
+ this.env.model.dispatch("SELECT_FIGURE", { figureId: null });
30136
+ }
30137
+ }
30138
+ get headerStyle() {
30139
+ const cssProperties = {};
30140
+ if (this.selectedCarouselItem?.type === "carouselDataView") {
30141
+ cssProperties["background-color"] = "#ffffff";
30142
+ }
30143
+ return cssPropertiesToCss(cssProperties);
30144
+ }
30145
+ }
30146
+
30013
30147
  class FullScreenChartStore extends SpreadsheetStore {
30014
30148
  mutators = ["toggleFullScreenChart"];
30015
30149
  fullScreenFigure = undefined;
@@ -30794,9 +30928,9 @@ stores.inject(MyMetaStore, storeInstance);
30794
30928
  this.originalChartDefinition = this.getters.getChartDefinition(chartId);
30795
30929
  }
30796
30930
  updateType(type) {
30797
- const figureId = this.chartId;
30798
- const currentDefinition = this.getters.getChartDefinition(figureId);
30799
- if (currentDefinition.type === type) {
30931
+ const chartId = this.chartId;
30932
+ const currentDefinition = this.getters.getChartDefinition(chartId);
30933
+ if (currentDefinition?.type === type) {
30800
30934
  return;
30801
30935
  }
30802
30936
  let definition;
@@ -30806,7 +30940,7 @@ stores.inject(MyMetaStore, storeInstance);
30806
30940
  else {
30807
30941
  const newChartInfo = chartSubtypeRegistry.get(type);
30808
30942
  const ChartClass = chartRegistry.get(newChartInfo.chartType);
30809
- const chartCreationContext = this.getters.getContextCreationChart(figureId);
30943
+ const chartCreationContext = this.getters.getContextCreationChart(chartId);
30810
30944
  if (!chartCreationContext)
30811
30945
  return;
30812
30946
  definition = {
@@ -30816,7 +30950,8 @@ stores.inject(MyMetaStore, storeInstance);
30816
30950
  }
30817
30951
  this.model.dispatch("UPDATE_CHART", {
30818
30952
  definition,
30819
- figureId,
30953
+ chartId,
30954
+ figureId: this.getters.getFigureIdFromChartId(chartId),
30820
30955
  sheetId: this.getters.getActiveSheetId(),
30821
30956
  });
30822
30957
  }
@@ -30837,17 +30972,17 @@ stores.inject(MyMetaStore, storeInstance);
30837
30972
  class ChartDashboardMenu extends owl.Component {
30838
30973
  static template = "o-spreadsheet-ChartDashboardMenu";
30839
30974
  static components = { MenuPopover };
30840
- static props = { figureUI: Object };
30975
+ static props = { chartId: String };
30841
30976
  fullScreenFigureStore;
30842
30977
  store;
30843
30978
  menuState = owl.useState({ isOpen: false, anchorRect: null, menuItems: [] });
30844
30979
  setup() {
30845
30980
  super.setup();
30846
- this.store = useLocalStore(ChartDashboardMenuStore, this.props.figureUI.id);
30981
+ this.store = useLocalStore(ChartDashboardMenuStore, this.props.chartId);
30847
30982
  this.fullScreenFigureStore = useStore(FullScreenChartStore);
30848
- owl.onWillUpdateProps(({ figureUI }) => {
30849
- if (figureUI.id !== this.props.figureUI.id) {
30850
- this.store.reset(figureUI.id);
30983
+ owl.onWillUpdateProps(({ chartId }) => {
30984
+ if (chartId !== this.props.chartId) {
30985
+ this.store.reset(chartId);
30851
30986
  }
30852
30987
  });
30853
30988
  }
@@ -30855,26 +30990,28 @@ stores.inject(MyMetaStore, storeInstance);
30855
30990
  return [this.fullScreenMenuItem, ...this.store.changeChartTypeMenuItems].filter(isDefined);
30856
30991
  }
30857
30992
  get backgroundColor() {
30858
- const color = this.env.model.getters.getChartDefinition(this.props.figureUI.id).background;
30993
+ const color = this.env.model.getters.getChartDefinition(this.props.chartId).background;
30859
30994
  return "background-color: " + (color || BACKGROUND_CHART_COLOR);
30860
30995
  }
30861
30996
  openContextMenu(ev) {
30862
30997
  this.menuState.isOpen = true;
30863
30998
  this.menuState.anchorRect = { x: ev.clientX, y: ev.clientY, width: 0, height: 0 };
30864
- this.menuState.menuItems = getChartMenuActions(this.props.figureUI.id, () => { }, this.env);
30999
+ const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
31000
+ this.menuState.menuItems = getChartMenuActions(figureId, () => { }, this.env);
30865
31001
  }
30866
31002
  get fullScreenMenuItem() {
30867
- const definition = this.env.model.getters.getChartDefinition(this.props.figureUI.id);
31003
+ const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
31004
+ const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
30868
31005
  if (definition.type === "scorecard") {
30869
31006
  return undefined;
30870
31007
  }
30871
- if (this.props.figureUI.id === this.fullScreenFigureStore.fullScreenFigure?.id) {
31008
+ if (this.props.chartId === this.fullScreenFigureStore.fullScreenFigure?.id) {
30872
31009
  return {
30873
31010
  id: "fullScreenChart",
30874
31011
  label: _t("Exit Full Screen"),
30875
31012
  iconClass: "fa fa-compress",
30876
31013
  onClick: () => {
30877
- this.fullScreenFigureStore.toggleFullScreenChart(this.props.figureUI.id);
31014
+ this.fullScreenFigureStore.toggleFullScreenChart(figureId);
30878
31015
  },
30879
31016
  };
30880
31017
  }
@@ -30883,7 +31020,7 @@ stores.inject(MyMetaStore, storeInstance);
30883
31020
  label: _t("Full Screen"),
30884
31021
  iconClass: "fa fa-expand",
30885
31022
  onClick: () => {
30886
- this.fullScreenFigureStore.toggleFullScreenChart(this.props.figureUI.id);
31023
+ this.fullScreenFigureStore.toggleFullScreenChart(figureId);
30887
31024
  },
30888
31025
  };
30889
31026
  }
@@ -30904,6 +31041,7 @@ stores.inject(MyMetaStore, storeInstance);
30904
31041
  static props = {
30905
31042
  figureUI: Object,
30906
31043
  onFigureDeleted: Function,
31044
+ editFigureStyle: { type: Function, optional: true },
30907
31045
  };
30908
31046
  static components = { ChartDashboardMenu };
30909
31047
  onDoubleClick() {
@@ -30911,7 +31049,14 @@ stores.inject(MyMetaStore, storeInstance);
30911
31049
  this.env.openSidePanel("ChartPanel");
30912
31050
  }
30913
31051
  get chartType() {
30914
- return this.env.model.getters.getChartType(this.props.figureUI.id);
31052
+ return this.env.model.getters.getChartType(this.chartId);
31053
+ }
31054
+ get chartId() {
31055
+ const chartId = this.env.model.getters.getChartIdFromFigureId(this.props.figureUI.id);
31056
+ if (!chartId) {
31057
+ throw new Error(`No chart found for figure ID: ${this.props.figureUI.id}`);
31058
+ }
31059
+ return chartId;
30915
31060
  }
30916
31061
  get chartComponent() {
30917
31062
  const type = this.chartType;
@@ -30928,6 +31073,7 @@ stores.inject(MyMetaStore, storeInstance);
30928
31073
  static props = {
30929
31074
  figureUI: Object,
30930
31075
  onFigureDeleted: Function,
31076
+ editFigureStyle: { type: Function, optional: true },
30931
31077
  };
30932
31078
  static components = {};
30933
31079
  // ---------------------------------------------------------------------------
@@ -30954,6 +31100,10 @@ stores.inject(MyMetaStore, storeInstance);
30954
31100
  borderWidth: 0,
30955
31101
  menuBuilder: getImageMenuActions,
30956
31102
  });
31103
+ figureRegistry.add("carousel", {
31104
+ Component: CarouselFigure,
31105
+ menuBuilder: getCarouselMenuActions,
31106
+ });
30957
31107
 
30958
31108
  // -----------------------------------------------------------------------------
30959
31109
  // STYLE
@@ -30980,6 +31130,7 @@ stores.inject(MyMetaStore, storeInstance);
30980
31130
  .o-figure-wrapper {
30981
31131
  position: absolute;
30982
31132
  box-sizing: content-box;
31133
+ pointer-events: auto;
30983
31134
 
30984
31135
  .o-fig-anchor {
30985
31136
  z-index: ${ComponentsImportance.FigureAnchor};
@@ -31038,6 +31189,7 @@ stores.inject(MyMetaStore, storeInstance);
31038
31189
  static props = {
31039
31190
  figureUI: Object,
31040
31191
  style: { type: String, optional: true },
31192
+ class: { type: String, optional: true },
31041
31193
  onFigureDeleted: { type: Function, optional: true },
31042
31194
  onMouseDown: { type: Function, optional: true },
31043
31195
  onClickAnchor: { type: Function, optional: true },
@@ -31050,6 +31202,7 @@ stores.inject(MyMetaStore, storeInstance);
31050
31202
  };
31051
31203
  menuState = owl.useState({ isOpen: false, anchorRect: null, menuItems: [] });
31052
31204
  figureRef = owl.useRef("figure");
31205
+ figureWrapperRef = owl.useRef("figureWrapper");
31053
31206
  menuButtonRef = owl.useRef("menuButton");
31054
31207
  borderWidth;
31055
31208
  get isSelected() {
@@ -31242,6 +31395,13 @@ stores.inject(MyMetaStore, storeInstance);
31242
31395
  .get(this.props.figureUI.tag)
31243
31396
  .menuBuilder(this.props.figureUI.id, this.props.onFigureDeleted, this.env);
31244
31397
  }
31398
+ editWrapperStyle(properties) {
31399
+ if (this.figureWrapperRef.el) {
31400
+ for (const property in properties) {
31401
+ this.figureWrapperRef.el.style.setProperty(property, properties[property] || null);
31402
+ }
31403
+ }
31404
+ }
31245
31405
  }
31246
31406
 
31247
31407
  class DelayedHoveredCellStore extends SpreadsheetStore {
@@ -38774,16 +38934,15 @@ stores.inject(MyMetaStore, storeInstance);
38774
38934
  reverseLookup.set(canonical, maxId);
38775
38935
  return maxId;
38776
38936
  }
38777
- const chartIds = [];
38778
38937
  /**
38779
38938
  * Convert a chart o-spreadsheet id to a xlsx id which
38780
38939
  * are unsigned integers (starting from 1).
38781
38940
  */
38782
- function convertChartId(chartId) {
38783
- const xlsxId = chartIds.findIndex((id) => id === chartId);
38941
+ function convertChartId(chartId, construct) {
38942
+ const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
38784
38943
  if (xlsxId === -1) {
38785
- chartIds.push(chartId);
38786
- return chartIds.length;
38944
+ construct.chartIds.push(chartId);
38945
+ return construct.chartIds.length;
38787
38946
  }
38788
38947
  return xlsxId + 1;
38789
38948
  }
@@ -41178,6 +41337,8 @@ stores.inject(MyMetaStore, storeInstance);
41178
41337
  sheets: sheets,
41179
41338
  sharedStrings,
41180
41339
  externalBooks,
41340
+ chartIds: [],
41341
+ imageIds: [],
41181
41342
  };
41182
41343
  }
41183
41344
  buildXlsxFileStructure() {
@@ -41855,6 +42016,18 @@ stores.inject(MyMetaStore, storeInstance);
41855
42016
  }
41856
42017
  return data;
41857
42018
  },
42019
+ })
42020
+ .add("18.5.1", {
42021
+ migrate(data) {
42022
+ for (const sheet of data.sheets || []) {
42023
+ for (const figure of sheet.figures || []) {
42024
+ if (figure.tag === "chart") {
42025
+ figure.data.chartId = figure.id;
42026
+ }
42027
+ }
42028
+ }
42029
+ return data;
42030
+ },
41858
42031
  });
41859
42032
  function fixOverlappingFilters(data) {
41860
42033
  for (const sheet of data.sheets || []) {
@@ -42108,7 +42281,12 @@ stores.inject(MyMetaStore, storeInstance);
42108
42281
  sheet.figures?.forEach((figure) => {
42109
42282
  if (figure.tag === "chart") {
42110
42283
  // chart definition
42111
- map[figure.id] = figure.data;
42284
+ if (data.version && compareVersions(String(data.version), "18.5.1") <= 0) {
42285
+ map[figure.data.chartId] = figure.data;
42286
+ }
42287
+ else {
42288
+ map[figure.id] = figure.data;
42289
+ }
42112
42290
  }
42113
42291
  });
42114
42292
  }
@@ -42119,20 +42297,20 @@ stores.inject(MyMetaStore, storeInstance);
42119
42297
  let command = cmd;
42120
42298
  switch (cmd.type) {
42121
42299
  case "CREATE_CHART":
42122
- map[cmd.figureId] = cmd.definition;
42300
+ map[cmd.chartId] = cmd.definition;
42123
42301
  break;
42124
42302
  case "UPDATE_CHART":
42125
- if (!map[cmd.figureId]) {
42303
+ if (!map[cmd.chartId]) {
42126
42304
  /** the chart does not exist on the map, it might have been created after a duplicate sheet.
42127
42305
  * We don't have access to the definition, so we skip the command.
42128
42306
  */
42129
- console.log(`Fix chart definition: chart with id ${cmd.figureId} not found.`);
42307
+ console.log(`Fix chart definition: chart with id ${cmd.chartId} not found.`);
42130
42308
  continue;
42131
42309
  }
42132
- const definition = map[cmd.figureId];
42310
+ const definition = map[cmd.chartId];
42133
42311
  const newDefinition = { ...definition, ...cmd.definition };
42134
42312
  command = { ...cmd, definition: newDefinition };
42135
- map[cmd.figureId] = newDefinition;
42313
+ map[cmd.chartId] = newDefinition;
42136
42314
  break;
42137
42315
  }
42138
42316
  commands.push(command);
@@ -42705,6 +42883,7 @@ stores.inject(MyMetaStore, storeInstance);
42705
42883
  const result = env.model.dispatch("CREATE_CHART", {
42706
42884
  sheetId,
42707
42885
  figureId,
42886
+ chartId: figureId,
42708
42887
  col,
42709
42888
  row,
42710
42889
  offset,
@@ -42716,6 +42895,26 @@ stores.inject(MyMetaStore, storeInstance);
42716
42895
  env.openSidePanel("ChartPanel");
42717
42896
  }
42718
42897
  };
42898
+ const CREATE_CAROUSEL = (env) => {
42899
+ const getters = env.model.getters;
42900
+ const figureId = env.model.uuidGenerator.smallUuid();
42901
+ const sheetId = getters.getActiveSheetId();
42902
+ const size = { width: DEFAULT_FIGURE_WIDTH, height: DEFAULT_FIGURE_HEIGHT };
42903
+ const { col, row, offset } = centerFigurePosition(getters, size);
42904
+ const result = env.model.dispatch("CREATE_CAROUSEL", {
42905
+ sheetId,
42906
+ figureId,
42907
+ col,
42908
+ row,
42909
+ offset,
42910
+ size,
42911
+ definition: { items: [] },
42912
+ });
42913
+ if (result.isSuccessful) {
42914
+ env.model.dispatch("SELECT_FIGURE", { figureId });
42915
+ env.openSidePanel("CarouselPanel", { figureId });
42916
+ }
42917
+ };
42719
42918
  //------------------------------------------------------------------------------
42720
42919
  // Pivots
42721
42920
  //------------------------------------------------------------------------------
@@ -43967,6 +44166,12 @@ stores.inject(MyMetaStore, storeInstance);
43967
44166
  isEnabled: (env) => !env.isSmall,
43968
44167
  icon: "o-spreadsheet-Icon.INSERT_CHART",
43969
44168
  };
44169
+ const insertCarousel = {
44170
+ name: _t("Carousel"),
44171
+ execute: CREATE_CAROUSEL,
44172
+ isEnabled: (env) => !env.isSmall,
44173
+ icon: "o-spreadsheet-Icon.CAROUSEL",
44174
+ };
43970
44175
  const insertPivot = {
43971
44176
  name: _t("Pivot table"),
43972
44177
  execute: CREATE_PIVOT,
@@ -48057,6 +48262,7 @@ stores.inject(MyMetaStore, storeInstance);
48057
48262
  horizontalSnap: undefined,
48058
48263
  verticalSnap: undefined,
48059
48264
  cancelDnd: undefined,
48265
+ overlappingCarousel: undefined,
48060
48266
  });
48061
48267
  setup() {
48062
48268
  owl.onMounted(() => {
@@ -48079,6 +48285,7 @@ stores.inject(MyMetaStore, storeInstance);
48079
48285
  this.dnd.draggedFigure = undefined;
48080
48286
  this.dnd.horizontalSnap = undefined;
48081
48287
  this.dnd.verticalSnap = undefined;
48288
+ this.dnd.overlappingCarousel = undefined;
48082
48289
  this.dnd.cancelDnd = undefined;
48083
48290
  }
48084
48291
  });
@@ -48217,26 +48424,46 @@ stores.inject(MyMetaStore, storeInstance);
48217
48424
  const currentMousePosition = { x: ev.clientX, y: ev.clientY };
48218
48425
  const draggedFigure = dragFigureForMove(currentMousePosition, initialMousePosition, initialFigure, maxDimensions, initialScrollPosition, getters.getActiveSheetScrollInfo());
48219
48426
  const otherFigures = this.getOtherFigures(initialFigure.id);
48220
- const snapResult = snapForMove(getters, draggedFigure, otherFigures);
48221
- this.dnd.draggedFigure = snapResult.snappedFigure;
48222
- this.dnd.horizontalSnap = this.getSnap(snapResult.horizontalSnapLine);
48223
- this.dnd.verticalSnap = this.getSnap(snapResult.verticalSnapLine);
48427
+ const overlappingCarousel = this.getCarouselOverlappingChart(draggedFigure, otherFigures);
48428
+ this.dnd.overlappingCarousel = overlappingCarousel;
48429
+ if (!overlappingCarousel) {
48430
+ const snapResult = snapForMove(getters, draggedFigure, otherFigures);
48431
+ this.dnd.draggedFigure = snapResult.snappedFigure;
48432
+ this.dnd.horizontalSnap = this.getSnap(snapResult.horizontalSnapLine);
48433
+ this.dnd.verticalSnap = this.getSnap(snapResult.verticalSnapLine);
48434
+ }
48435
+ else {
48436
+ this.dnd.draggedFigure = draggedFigure;
48437
+ this.dnd.horizontalSnap = undefined;
48438
+ this.dnd.verticalSnap = undefined;
48439
+ }
48224
48440
  };
48225
48441
  const onMouseUp = (ev) => {
48226
48442
  if (!this.dnd.draggedFigure) {
48227
48443
  return;
48228
48444
  }
48229
48445
  const { col, row, offset } = this.env.model.getters.getPositionAnchorOffset(this.dnd.draggedFigure);
48446
+ if (!this.dnd.overlappingCarousel) {
48447
+ this.env.model.dispatch("UPDATE_FIGURE", {
48448
+ sheetId,
48449
+ figureId: figureUI.id,
48450
+ offset,
48451
+ col,
48452
+ row,
48453
+ });
48454
+ }
48455
+ else {
48456
+ this.env.model.dispatch("ADD_FIGURE_CHART_TO_CAROUSEL", {
48457
+ sheetId,
48458
+ carouselFigureId: this.dnd.overlappingCarousel.id,
48459
+ chartFigureId: figureUI.id,
48460
+ });
48461
+ this.props.onFigureDeleted();
48462
+ }
48230
48463
  this.dnd.draggedFigure = undefined;
48231
48464
  this.dnd.horizontalSnap = undefined;
48232
48465
  this.dnd.verticalSnap = undefined;
48233
- this.env.model.dispatch("UPDATE_FIGURE", {
48234
- sheetId,
48235
- figureId: figureUI.id,
48236
- offset,
48237
- col,
48238
- row,
48239
- });
48466
+ this.dnd.overlappingCarousel = undefined;
48240
48467
  };
48241
48468
  this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
48242
48469
  }
@@ -48288,6 +48515,7 @@ stores.inject(MyMetaStore, storeInstance);
48288
48515
  this.dnd.draggedFigure = undefined;
48289
48516
  this.dnd.horizontalSnap = undefined;
48290
48517
  this.dnd.verticalSnap = undefined;
48518
+ this.dnd.overlappingCarousel = undefined;
48291
48519
  };
48292
48520
  this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
48293
48521
  }
@@ -48304,10 +48532,15 @@ stores.inject(MyMetaStore, storeInstance);
48304
48532
  if (figureUI.id !== this.dnd.draggedFigure?.id)
48305
48533
  return "";
48306
48534
  return cssPropertiesToCss({
48307
- opacity: "0.9",
48535
+ opacity: this.dnd.overlappingCarousel?.id ? "0.6" : "0.9",
48308
48536
  cursor: "grabbing",
48309
48537
  });
48310
48538
  }
48539
+ getFigureClass(figureUI) {
48540
+ if (figureUI.id !== this.dnd.overlappingCarousel?.id)
48541
+ return "";
48542
+ return "o-add-to-carousel";
48543
+ }
48311
48544
  getSnap(snapLine) {
48312
48545
  if (!snapLine || !this.dnd.draggedFigure)
48313
48546
  return undefined;
@@ -48354,6 +48587,20 @@ stores.inject(MyMetaStore, storeInstance);
48354
48587
  });
48355
48588
  }
48356
48589
  }
48590
+ getCarouselOverlappingChart(figureUI, otherFigures) {
48591
+ if (figureUI.tag !== "chart") {
48592
+ return undefined;
48593
+ }
48594
+ const minimumOverlap = 20; // Minimum overlap in pixels to consider a carousel overlapping
48595
+ const carousels = otherFigures.filter((f) => f.tag === "carousel");
48596
+ return carousels.find((carousel) => {
48597
+ const xOverlap = Math.max(0, Math.min(figureUI.x + figureUI.width, carousel.x + carousel.width) -
48598
+ Math.max(figureUI.x, carousel.x));
48599
+ const yOverlap = Math.max(0, Math.min(figureUI.y + figureUI.height, carousel.y + carousel.height) -
48600
+ Math.max(figureUI.y, carousel.y));
48601
+ return xOverlap >= minimumOverlap && yOverlap >= minimumOverlap;
48602
+ });
48603
+ }
48357
48604
  }
48358
48605
 
48359
48606
  css /* scss */ `
@@ -51036,6 +51283,226 @@ stores.inject(MyMetaStore, storeInstance);
51036
51283
  }
51037
51284
  }
51038
51285
 
51286
+ function useAutofocus({ refName }) {
51287
+ const ref = owl.useRef(refName);
51288
+ owl.useEffect((el) => {
51289
+ el?.focus();
51290
+ }, () => [ref.el]);
51291
+ }
51292
+
51293
+ css /* scss */ `
51294
+ .o-spreadsheet {
51295
+ .os-input {
51296
+ border-width: 0 0 1px 0;
51297
+ border-color: transparent;
51298
+ outline: none;
51299
+ text-overflow: ellipsis;
51300
+ color: ${TEXT_BODY};
51301
+ }
51302
+ .os-input:hover,
51303
+ .os-input:focus {
51304
+ border-color: ${GRAY_300};
51305
+ }
51306
+ }
51307
+ `;
51308
+ class TextInput extends owl.Component {
51309
+ static template = "o-spreadsheet-TextInput";
51310
+ static props = {
51311
+ value: String,
51312
+ onChange: Function,
51313
+ class: {
51314
+ type: String,
51315
+ optional: true,
51316
+ },
51317
+ id: {
51318
+ type: String,
51319
+ optional: true,
51320
+ },
51321
+ placeholder: {
51322
+ type: String,
51323
+ optional: true,
51324
+ },
51325
+ autofocus: {
51326
+ type: Boolean,
51327
+ optional: true,
51328
+ },
51329
+ };
51330
+ inputRef = owl.useRef("input");
51331
+ setup() {
51332
+ owl.useExternalListener(window, "click", (ev) => {
51333
+ if (ev.target !== this.inputRef.el && this.inputRef.el?.value !== this.props.value) {
51334
+ this.save();
51335
+ }
51336
+ }, { capture: true });
51337
+ if (this.props.autofocus) {
51338
+ useAutofocus({ refName: "input" });
51339
+ }
51340
+ }
51341
+ onKeyDown(ev) {
51342
+ switch (ev.key) {
51343
+ case "Enter":
51344
+ this.save();
51345
+ ev.preventDefault();
51346
+ ev.stopPropagation();
51347
+ break;
51348
+ case "Escape":
51349
+ if (this.inputRef.el) {
51350
+ this.inputRef.el.value = this.props.value;
51351
+ this.inputRef.el.blur();
51352
+ }
51353
+ ev.preventDefault();
51354
+ ev.stopPropagation();
51355
+ break;
51356
+ }
51357
+ }
51358
+ save() {
51359
+ const currentValue = (this.inputRef.el?.value || "").trim();
51360
+ if (currentValue !== this.props.value) {
51361
+ this.props.onChange(currentValue);
51362
+ }
51363
+ this.inputRef.el?.blur();
51364
+ }
51365
+ onMouseDown(ev) {
51366
+ // Stop the event if the input is not focused, we handle everything in onMouseUp
51367
+ if (ev.target !== document.activeElement) {
51368
+ ev.preventDefault();
51369
+ ev.stopPropagation();
51370
+ }
51371
+ }
51372
+ onMouseUp(ev) {
51373
+ const target = ev.target;
51374
+ if (target !== document.activeElement) {
51375
+ target.focus();
51376
+ target.select();
51377
+ ev.preventDefault();
51378
+ ev.stopPropagation();
51379
+ }
51380
+ }
51381
+ }
51382
+
51383
+ class CarouselPanel extends owl.Component {
51384
+ static template = "o-spreadsheet-CarouselPanel";
51385
+ static props = { onCloseSidePanel: Function, figureId: String };
51386
+ static components = { TextInput };
51387
+ dragAndDrop = useDragAndDropListItems();
51388
+ previewListRef = owl.useRef("previewList");
51389
+ setup() {
51390
+ let lastCarouselItems = [...this.carouselItems];
51391
+ owl.onWillUpdateProps(() => {
51392
+ if (!deepEquals(this.carouselItems, lastCarouselItems)) {
51393
+ this.dragAndDrop.cancel();
51394
+ }
51395
+ lastCarouselItems = [...this.carouselItems];
51396
+ });
51397
+ }
51398
+ get carouselItems() {
51399
+ return this.env.model.getters.getCarousel(this.props.figureId).items;
51400
+ }
51401
+ getPreviewDivStyle(item) {
51402
+ return this.dragAndDrop.itemsStyle[this.getItemId(item)] || "";
51403
+ }
51404
+ getItemId(item) {
51405
+ return item.type === "chart" ? item.chartId : "transparent-carousel";
51406
+ }
51407
+ addNewChartToCarousel() {
51408
+ this.env.model.dispatch("ADD_NEW_CHART_TO_CAROUSEL", {
51409
+ figureId: this.props.figureId,
51410
+ sheetId: this.env.model.getters.getActiveSheetId(),
51411
+ });
51412
+ }
51413
+ get hasDataView() {
51414
+ return this.carouselItems.some((item) => item.type === "carouselDataView");
51415
+ }
51416
+ addDataViewToCarousel() {
51417
+ const carousel = this.env.model.getters.getCarousel(this.props.figureId);
51418
+ this.env.model.dispatch("UPDATE_CAROUSEL", {
51419
+ figureId: this.props.figureId,
51420
+ sheetId: this.env.model.getters.getActiveSheetId(),
51421
+ definition: { items: [...carousel.items, { type: "carouselDataView" }] },
51422
+ });
51423
+ }
51424
+ activateCarouselItem(item) {
51425
+ this.env.model.dispatch("UPDATE_CAROUSEL_ACTIVE_ITEM", {
51426
+ figureId: this.props.figureId,
51427
+ sheetId: this.env.model.getters.getActiveSheetId(),
51428
+ item,
51429
+ });
51430
+ }
51431
+ editCarouselItem(item) {
51432
+ if (item.type === "chart") {
51433
+ this.activateCarouselItem(item);
51434
+ this.env.model.dispatch("SELECT_FIGURE", { figureId: this.props.figureId });
51435
+ this.env.openSidePanel("ChartPanel", { chartId: item.chartId });
51436
+ }
51437
+ }
51438
+ renameCarouselItem(item, newName) {
51439
+ const trimmedName = newName.trim();
51440
+ if (!trimmedName || trimmedName === this.getItemTitle(item).toString()) {
51441
+ return;
51442
+ }
51443
+ const items = [...this.carouselItems];
51444
+ const itemIndex = this.carouselItems.findIndex((itm) => deepEquals(itm, item));
51445
+ if (itemIndex !== -1) {
51446
+ items[itemIndex] = { ...item, title: trimmedName };
51447
+ this.env.model.dispatch("UPDATE_CAROUSEL", {
51448
+ figureId: this.props.figureId,
51449
+ sheetId: this.env.model.getters.getActiveSheetId(),
51450
+ definition: { items },
51451
+ });
51452
+ }
51453
+ }
51454
+ deleteCarouselItem(item) {
51455
+ const carousel = this.env.model.getters.getCarousel(this.props.figureId);
51456
+ const items = carousel.items.filter((itm) => !deepEquals(itm, item));
51457
+ this.env.model.dispatch("UPDATE_CAROUSEL", {
51458
+ figureId: this.props.figureId,
51459
+ sheetId: this.env.model.getters.getActiveSheetId(),
51460
+ definition: { items },
51461
+ });
51462
+ }
51463
+ onDragHandleMouseDown(item, event) {
51464
+ if (event.button !== 0)
51465
+ return;
51466
+ const previewRects = Array.from(this.previewListRef.el.children).map((previewEl) => getBoundingRectAsPOJO(previewEl));
51467
+ const items = this.carouselItems.map((item, index) => ({
51468
+ id: this.getItemId(item),
51469
+ size: previewRects[index].height,
51470
+ position: previewRects[index].y,
51471
+ }));
51472
+ this.dragAndDrop.start("vertical", {
51473
+ draggedItemId: this.getItemId(item),
51474
+ initialMousePosition: event.clientY,
51475
+ items: items,
51476
+ scrollableContainerEl: this.previewListRef.el,
51477
+ onDragEnd: (itemId, finalIndex) => this.onDragEnd(item, finalIndex),
51478
+ });
51479
+ }
51480
+ onDragEnd(item, finalIndex) {
51481
+ const originalIndex = this.carouselItems.findIndex((itm) => deepEquals(itm, item));
51482
+ if (originalIndex === -1 || originalIndex === finalIndex) {
51483
+ return;
51484
+ }
51485
+ const carousel = this.env.model.getters.getCarousel(this.props.figureId);
51486
+ const items = [...carousel.items];
51487
+ items.splice(originalIndex, 1);
51488
+ items.splice(finalIndex, 0, item);
51489
+ this.env.model.dispatch("UPDATE_CAROUSEL", {
51490
+ figureId: this.props.figureId,
51491
+ sheetId: this.env.model.getters.getActiveSheetId(),
51492
+ definition: { items },
51493
+ });
51494
+ }
51495
+ getItemTitle(item) {
51496
+ return getCarouselItemTitle(this.env.model.getters, item);
51497
+ }
51498
+ getItemPreview(item) {
51499
+ return getCarouselItemPreview(this.env.model.getters, item);
51500
+ }
51501
+ get carouselAddChartInfoMessage() {
51502
+ return _t("Add a chart to the carousel. You can also add a chart by dragging and dropping it over the carousel figure.");
51503
+ }
51504
+ }
51505
+
51039
51506
  class ChartDataSeries extends owl.Component {
51040
51507
  static template = "o-spreadsheet.ChartDataSeries";
51041
51508
  static components = { SelectionInput, Section };
@@ -51102,7 +51569,7 @@ stores.inject(MyMetaStore, storeInstance);
51102
51569
  ChartErrorSection,
51103
51570
  };
51104
51571
  static props = {
51105
- figureId: String,
51572
+ chartId: String,
51106
51573
  definition: Object,
51107
51574
  updateChart: Function,
51108
51575
  canUpdateChart: Function,
@@ -51160,7 +51627,7 @@ stores.inject(MyMetaStore, storeInstance);
51160
51627
  ];
51161
51628
  }
51162
51629
  onUpdateDataSetsHaveTitle(dataSetsHaveTitle) {
51163
- this.props.updateChart(this.props.figureId, {
51630
+ this.props.updateChart(this.props.chartId, {
51164
51631
  dataSetsHaveTitle,
51165
51632
  });
51166
51633
  }
@@ -51232,7 +51699,7 @@ stores.inject(MyMetaStore, storeInstance);
51232
51699
  return;
51233
51700
  }
51234
51701
  const labelRange = dataSets.length > 1 ? dataSets.shift().dataRange : "";
51235
- this.props.updateChart(this.props.figureId, {
51702
+ this.props.updateChart(this.props.chartId, {
51236
51703
  labelRange,
51237
51704
  dataSets,
51238
51705
  });
@@ -51249,7 +51716,7 @@ stores.inject(MyMetaStore, storeInstance);
51249
51716
  ...this.dataSets?.[i],
51250
51717
  dataRange,
51251
51718
  }));
51252
- this.state.datasetDispatchResult = this.props.canUpdateChart(this.props.figureId, {
51719
+ this.state.datasetDispatchResult = this.props.canUpdateChart(this.props.chartId, {
51253
51720
  dataSets: this.dataSets,
51254
51721
  });
51255
51722
  }
@@ -51261,7 +51728,7 @@ stores.inject(MyMetaStore, storeInstance);
51261
51728
  backgroundColor: colors[i],
51262
51729
  ...this.dataSets[i],
51263
51730
  }));
51264
- this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
51731
+ this.state.datasetDispatchResult = this.props.updateChart(this.props.chartId, {
51265
51732
  dataSets: this.dataSets,
51266
51733
  });
51267
51734
  }
@@ -51274,18 +51741,18 @@ stores.inject(MyMetaStore, storeInstance);
51274
51741
  ...ds,
51275
51742
  }))
51276
51743
  .filter((_, i) => i !== index);
51277
- this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
51744
+ this.state.datasetDispatchResult = this.props.updateChart(this.props.chartId, {
51278
51745
  dataSets: this.dataSets,
51279
51746
  });
51280
51747
  }
51281
51748
  onDataSeriesConfirmed() {
51282
51749
  this.dataSets = this.splitRanges;
51283
51750
  this.datasetOrientation = this.computeDatasetOrientation();
51284
- this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
51751
+ this.state.datasetDispatchResult = this.props.updateChart(this.props.chartId, {
51285
51752
  dataSets: this.dataSets,
51286
51753
  });
51287
51754
  if (this.state.datasetDispatchResult.isSuccessful) {
51288
- this.dataSets = this.env.model.getters.getChartDefinition(this.props.figureId).dataSets;
51755
+ this.dataSets = this.env.model.getters.getChartDefinition(this.props.chartId).dataSets;
51289
51756
  }
51290
51757
  }
51291
51758
  get splitRanges() {
@@ -51376,12 +51843,12 @@ stores.inject(MyMetaStore, storeInstance);
51376
51843
  */
51377
51844
  onLabelRangeChanged(ranges) {
51378
51845
  this.labelRange = ranges[0];
51379
- this.state.labelsDispatchResult = this.props.canUpdateChart(this.props.figureId, {
51846
+ this.state.labelsDispatchResult = this.props.canUpdateChart(this.props.chartId, {
51380
51847
  labelRange: this.labelRange,
51381
51848
  });
51382
51849
  }
51383
51850
  onLabelRangeConfirmed() {
51384
- this.state.labelsDispatchResult = this.props.updateChart(this.props.figureId, {
51851
+ this.state.labelsDispatchResult = this.props.updateChart(this.props.chartId, {
51385
51852
  labelRange: this.labelRange,
51386
51853
  });
51387
51854
  }
@@ -51389,7 +51856,7 @@ stores.inject(MyMetaStore, storeInstance);
51389
51856
  return this.labelRange || "";
51390
51857
  }
51391
51858
  onUpdateAggregated(aggregated) {
51392
- this.props.updateChart(this.props.figureId, {
51859
+ this.props.updateChart(this.props.chartId, {
51393
51860
  aggregated,
51394
51861
  });
51395
51862
  }
@@ -51421,7 +51888,8 @@ stores.inject(MyMetaStore, storeInstance);
51421
51888
  }
51422
51889
  const zonesBySheetName = {};
51423
51890
  const transposedDatasets = [];
51424
- const figureSheetId = getters.getFigureSheetId(this.props.figureId);
51891
+ const figureId = getters.getFigureIdFromChartId(this.props.chartId);
51892
+ const figureSheetId = getters.getFigureSheetId(figureId);
51425
51893
  let name = getters.getActiveSheet().name;
51426
51894
  if (figureSheetId) {
51427
51895
  name = getters.getSheet(figureSheetId).name;
@@ -51481,7 +51949,7 @@ stores.inject(MyMetaStore, storeInstance);
51481
51949
  : this.chartTerms.StackedColumnChart;
51482
51950
  }
51483
51951
  onUpdateStacked(stacked) {
51484
- this.props.updateChart(this.props.figureId, {
51952
+ this.props.updateChart(this.props.chartId, {
51485
51953
  stacked,
51486
51954
  });
51487
51955
  }
@@ -51975,7 +52443,7 @@ stores.inject(MyMetaStore, storeInstance);
51975
52443
  class AxisDesignEditor extends owl.Component {
51976
52444
  static template = "o-spreadsheet-AxisDesignEditor";
51977
52445
  static components = { Section, ChartTitle, BadgeSelection };
51978
- static props = { figureId: String, definition: Object, updateChart: Function, axesList: Array };
52446
+ static props = { chartId: String, definition: Object, updateChart: Function, axesList: Array };
51979
52447
  state = owl.useState({ currentAxis: "x" });
51980
52448
  defaultFontSize = CHART_AXIS_TITLE_FONT_SIZE;
51981
52449
  get axisTitleStyle() {
@@ -52000,7 +52468,7 @@ stores.inject(MyMetaStore, storeInstance);
52000
52468
  text,
52001
52469
  },
52002
52470
  };
52003
- this.props.updateChart(this.props.figureId, { axesDesign });
52471
+ this.props.updateChart(this.props.chartId, { axesDesign });
52004
52472
  }
52005
52473
  updateAxisTitleStyle(style) {
52006
52474
  const axesDesign = deepCopy(this.props.definition.axesDesign) ?? {};
@@ -52008,7 +52476,7 @@ stores.inject(MyMetaStore, storeInstance);
52008
52476
  ...axesDesign[this.state.currentAxis],
52009
52477
  title: style,
52010
52478
  };
52011
- this.props.updateChart(this.props.figureId, { axesDesign });
52479
+ this.props.updateChart(this.props.chartId, { axesDesign });
52012
52480
  }
52013
52481
  }
52014
52482
 
@@ -52061,7 +52529,7 @@ stores.inject(MyMetaStore, storeInstance);
52061
52529
  RadioSelection,
52062
52530
  };
52063
52531
  static props = {
52064
- figureId: String,
52532
+ chartId: String,
52065
52533
  definition: Object,
52066
52534
  updateChart: Function,
52067
52535
  canUpdateChart: Function,
@@ -52085,17 +52553,17 @@ stores.inject(MyMetaStore, storeInstance);
52085
52553
  this.state.activeTool = isOpen ? "" : tool;
52086
52554
  }
52087
52555
  updateBackgroundColor(color) {
52088
- this.props.updateChart(this.props.figureId, {
52556
+ this.props.updateChart(this.props.chartId, {
52089
52557
  background: color,
52090
52558
  });
52091
52559
  }
52092
52560
  updateTitle(newTitle) {
52093
52561
  const title = { ...this.title, text: newTitle };
52094
- this.props.updateChart(this.props.figureId, { title });
52562
+ this.props.updateChart(this.props.chartId, { title });
52095
52563
  }
52096
52564
  updateChartTitleStyle(style) {
52097
52565
  const title = { ...this.title, ...style };
52098
- this.props.updateChart(this.props.figureId, { title });
52566
+ this.props.updateChart(this.props.chartId, { title });
52099
52567
  this.state.activeTool = "";
52100
52568
  }
52101
52569
  }
@@ -52106,13 +52574,13 @@ stores.inject(MyMetaStore, storeInstance);
52106
52574
  Section,
52107
52575
  };
52108
52576
  static props = {
52109
- figureId: String,
52577
+ chartId: String,
52110
52578
  definition: Object,
52111
52579
  updateChart: Function,
52112
52580
  canUpdateChart: Function,
52113
52581
  };
52114
52582
  updateLegendPosition(ev) {
52115
- this.props.updateChart(this.props.figureId, {
52583
+ this.props.updateChart(this.props.chartId, {
52116
52584
  legendPosition: ev.target.value,
52117
52585
  });
52118
52586
  }
@@ -52126,7 +52594,7 @@ stores.inject(MyMetaStore, storeInstance);
52126
52594
  RoundColorPicker,
52127
52595
  };
52128
52596
  static props = {
52129
- figureId: String,
52597
+ chartId: String,
52130
52598
  definition: Object,
52131
52599
  updateChart: Function,
52132
52600
  canUpdateChart: Function,
@@ -52134,7 +52602,7 @@ stores.inject(MyMetaStore, storeInstance);
52134
52602
  };
52135
52603
  state = owl.useState({ index: 0 });
52136
52604
  getDataSeries() {
52137
- const runtime = this.env.model.getters.getChartRuntime(this.props.figureId);
52605
+ const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
52138
52606
  if (!runtime || !("chartJsConfig" in runtime)) {
52139
52607
  return [];
52140
52608
  }
@@ -52153,7 +52621,7 @@ stores.inject(MyMetaStore, storeInstance);
52153
52621
  ...dataSets[this.state.index],
52154
52622
  backgroundColor: color,
52155
52623
  };
52156
- this.props.updateChart(this.props.figureId, { dataSets });
52624
+ this.props.updateChart(this.props.chartId, { dataSets });
52157
52625
  }
52158
52626
  getDataSeriesColor() {
52159
52627
  const dataSets = this.props.definition.dataSets;
@@ -52173,7 +52641,7 @@ stores.inject(MyMetaStore, storeInstance);
52173
52641
  ...dataSets[this.state.index],
52174
52642
  label,
52175
52643
  };
52176
- this.props.updateChart(this.props.figureId, { dataSets });
52644
+ this.props.updateChart(this.props.chartId, { dataSets });
52177
52645
  }
52178
52646
  getDataSeriesLabel() {
52179
52647
  const dataSets = this.props.definition.dataSets;
@@ -52191,7 +52659,7 @@ stores.inject(MyMetaStore, storeInstance);
52191
52659
  RoundColorPicker,
52192
52660
  };
52193
52661
  static props = {
52194
- figureId: String,
52662
+ chartId: String,
52195
52663
  definition: Object,
52196
52664
  canUpdateChart: Function,
52197
52665
  updateChart: Function,
@@ -52207,7 +52675,7 @@ stores.inject(MyMetaStore, storeInstance);
52207
52675
  ...dataSets[index],
52208
52676
  yAxisId: axis === "left" ? "y" : "y1",
52209
52677
  };
52210
- this.props.updateChart(this.props.figureId, { dataSets });
52678
+ this.props.updateChart(this.props.chartId, { dataSets });
52211
52679
  }
52212
52680
  getDataSerieAxis(index) {
52213
52681
  const dataSets = this.props.definition.dataSets;
@@ -52233,7 +52701,7 @@ stores.inject(MyMetaStore, storeInstance);
52233
52701
  display,
52234
52702
  },
52235
52703
  };
52236
- this.props.updateChart(this.props.figureId, { dataSets });
52704
+ this.props.updateChart(this.props.chartId, { dataSets });
52237
52705
  }
52238
52706
  getTrendLineConfiguration(index) {
52239
52707
  const dataSets = this.props.definition.dataSets;
@@ -52274,7 +52742,7 @@ stores.inject(MyMetaStore, storeInstance);
52274
52742
  this.updateTrendLineValue(index, { order: parseInt(element.value) });
52275
52743
  }
52276
52744
  getMaxPolynomialDegree(index) {
52277
- const runtime = this.env.model.getters.getChartRuntime(this.props.figureId);
52745
+ const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
52278
52746
  return Math.min(10, runtime.chartJsConfig.data.datasets[index].data.length - 1);
52279
52747
  }
52280
52748
  get defaultWindowSize() {
@@ -52316,7 +52784,7 @@ stores.inject(MyMetaStore, storeInstance);
52316
52784
  ...config,
52317
52785
  },
52318
52786
  };
52319
- this.props.updateChart(this.props.figureId, { dataSets });
52787
+ this.props.updateChart(this.props.chartId, { dataSets });
52320
52788
  }
52321
52789
  }
52322
52790
 
@@ -52326,7 +52794,7 @@ stores.inject(MyMetaStore, storeInstance);
52326
52794
  Checkbox,
52327
52795
  };
52328
52796
  static props = {
52329
- figureId: String,
52797
+ chartId: String,
52330
52798
  definition: Object,
52331
52799
  updateChart: Function,
52332
52800
  canUpdateChart: Function,
@@ -52346,7 +52814,7 @@ stores.inject(MyMetaStore, storeInstance);
52346
52814
  ChartShowValues,
52347
52815
  };
52348
52816
  static props = {
52349
- figureId: String,
52817
+ chartId: String,
52350
52818
  definition: Object,
52351
52819
  canUpdateChart: Function,
52352
52820
  updateChart: Function,
@@ -52370,7 +52838,7 @@ stores.inject(MyMetaStore, storeInstance);
52370
52838
  Checkbox,
52371
52839
  };
52372
52840
  static props = {
52373
- figureId: String,
52841
+ chartId: String,
52374
52842
  definition: Object,
52375
52843
  updateChart: Function,
52376
52844
  canUpdateChart: Function,
@@ -52397,7 +52865,7 @@ stores.inject(MyMetaStore, storeInstance);
52397
52865
  ...dataSets[index],
52398
52866
  type,
52399
52867
  };
52400
- this.props.updateChart(this.props.figureId, { dataSets });
52868
+ this.props.updateChart(this.props.chartId, { dataSets });
52401
52869
  }
52402
52870
  getDataSeriesType(index) {
52403
52871
  const dataSets = this.props.definition.dataSets;
@@ -52433,7 +52901,7 @@ stores.inject(MyMetaStore, storeInstance);
52433
52901
  ];
52434
52902
  }
52435
52903
  onUpdateCumulative(cumulative) {
52436
- this.props.updateChart(this.props.figureId, {
52904
+ this.props.updateChart(this.props.chartId, {
52437
52905
  cumulative,
52438
52906
  });
52439
52907
  }
@@ -52449,13 +52917,13 @@ stores.inject(MyMetaStore, storeInstance);
52449
52917
  Section,
52450
52918
  };
52451
52919
  static props = {
52452
- figureId: String,
52920
+ chartId: String,
52453
52921
  definition: Object,
52454
52922
  updateChart: Function,
52455
52923
  canUpdateChart: Function,
52456
52924
  };
52457
52925
  getFunnelColorItems() {
52458
- const runtime = this.env.model.getters.getChartRuntime(this.props.figureId);
52926
+ const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
52459
52927
  const labels = (runtime.chartJsConfig.data.labels || []);
52460
52928
  const colors = getFunnelLabelColors(labels, this.props.definition.funnelColors);
52461
52929
  return labels.map((label, index) => ({
@@ -52465,7 +52933,7 @@ stores.inject(MyMetaStore, storeInstance);
52465
52933
  }
52466
52934
  updateFunnelItemColor(index, color) {
52467
52935
  const funnelColors = replaceItemAtIndex(this.props.definition.funnelColors || [], color, index);
52468
- this.props.updateChart(this.props.figureId, { funnelColors });
52936
+ this.props.updateChart(this.props.chartId, { funnelColors });
52469
52937
  }
52470
52938
  }
52471
52939
 
@@ -52473,7 +52941,7 @@ stores.inject(MyMetaStore, storeInstance);
52473
52941
  static template = "o-spreadsheet-GaugeChartConfigPanel";
52474
52942
  static components = { ChartErrorSection, ChartDataSeries };
52475
52943
  static props = {
52476
- figureId: String,
52944
+ chartId: String,
52477
52945
  definition: Object,
52478
52946
  updateChart: Function,
52479
52947
  canUpdateChart: Function,
@@ -52491,12 +52959,12 @@ stores.inject(MyMetaStore, storeInstance);
52491
52959
  }
52492
52960
  onDataRangeChanged(ranges) {
52493
52961
  this.dataRange = ranges[0];
52494
- this.state.dataRangeDispatchResult = this.props.canUpdateChart(this.props.figureId, {
52962
+ this.state.dataRangeDispatchResult = this.props.canUpdateChart(this.props.chartId, {
52495
52963
  dataRange: this.dataRange,
52496
52964
  });
52497
52965
  }
52498
52966
  updateDataRange() {
52499
- this.state.dataRangeDispatchResult = this.props.updateChart(this.props.figureId, {
52967
+ this.state.dataRangeDispatchResult = this.props.updateChart(this.props.chartId, {
52500
52968
  dataRange: this.dataRange,
52501
52969
  });
52502
52970
  }
@@ -52555,7 +53023,7 @@ stores.inject(MyMetaStore, storeInstance);
52555
53023
  StandaloneComposer,
52556
53024
  };
52557
53025
  static props = {
52558
- figureId: String,
53026
+ chartId: String,
52559
53027
  definition: Object,
52560
53028
  updateChart: Function,
52561
53029
  canUpdateChart: { type: Function, optional: true },
@@ -52596,7 +53064,7 @@ stores.inject(MyMetaStore, storeInstance);
52596
53064
  updateSectionRule(sectionRule) {
52597
53065
  this.state.sectionRuleCancelledReasons = [];
52598
53066
  this.state.sectionRuleCancelledReasons.push(...this.checkSectionRuleFormulasAreValid(this.state.sectionRule));
52599
- const dispatchResult = this.props.updateChart(this.props.figureId, {
53067
+ const dispatchResult = this.props.updateChart(this.props.chartId, {
52600
53068
  sectionRule,
52601
53069
  });
52602
53070
  if (dispatchResult.isSuccessful) {
@@ -52659,9 +53127,9 @@ stores.inject(MyMetaStore, storeInstance);
52659
53127
  return tryToNumber(toScalar(evaluatedValue), locale) !== undefined;
52660
53128
  }
52661
53129
  get sheetId() {
52662
- const chart = this.env.model.getters.getChart(this.props.figureId);
53130
+ const chart = this.env.model.getters.getChart(this.props.chartId);
52663
53131
  if (!chart) {
52664
- throw new Error("Chart not found with id " + this.props.figureId);
53132
+ throw new Error("Chart not found with id " + this.props.chartId);
52665
53133
  }
52666
53134
  return chart.sheetId;
52667
53135
  }
@@ -52671,13 +53139,13 @@ stores.inject(MyMetaStore, storeInstance);
52671
53139
  static template = "o-spreadsheet-GeoChartRegionSelectSection";
52672
53140
  static components = { Section };
52673
53141
  static props = {
52674
- figureId: String,
53142
+ chartId: String,
52675
53143
  definition: Object,
52676
53144
  updateChart: Function,
52677
53145
  };
52678
53146
  updateSelectedRegion(ev) {
52679
53147
  const value = ev.target.value;
52680
- this.props.updateChart(this.props.figureId, { region: value });
53148
+ this.props.updateChart(this.props.chartId, { region: value });
52681
53149
  }
52682
53150
  get availableRegions() {
52683
53151
  return this.env.model.getters.getGeoChartAvailableRegions();
@@ -52727,14 +53195,14 @@ stores.inject(MyMetaStore, storeInstance);
52727
53195
  : this.updateColorScale(value);
52728
53196
  }
52729
53197
  updateColorScale(colorScale) {
52730
- this.props.updateChart(this.props.figureId, { colorScale });
53198
+ this.props.updateChart(this.props.chartId, { colorScale });
52731
53199
  }
52732
53200
  updateMissingValueColor(color) {
52733
- this.props.updateChart(this.props.figureId, { missingValueColor: color });
53201
+ this.props.updateChart(this.props.chartId, { missingValueColor: color });
52734
53202
  }
52735
53203
  updateLegendPosition(ev) {
52736
53204
  const value = ev.target.value;
52737
- this.props.updateChart(this.props.figureId, { legendPosition: value });
53205
+ this.props.updateChart(this.props.chartId, { legendPosition: value });
52738
53206
  }
52739
53207
  get selectedColorScale() {
52740
53208
  return typeof this.props.definition.colorScale === "object"
@@ -52783,7 +53251,7 @@ stores.inject(MyMetaStore, storeInstance);
52783
53251
  class LineConfigPanel extends GenericChartConfigPanel {
52784
53252
  static template = "o-spreadsheet-LineConfigPanel";
52785
53253
  get canTreatLabelsAsText() {
52786
- const chart = this.env.model.getters.getChart(this.props.figureId);
53254
+ const chart = this.env.model.getters.getChart(this.props.chartId);
52787
53255
  if (chart && chart instanceof LineChart) {
52788
53256
  return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
52789
53257
  }
@@ -52808,17 +53276,17 @@ stores.inject(MyMetaStore, storeInstance);
52808
53276
  return options;
52809
53277
  }
52810
53278
  onUpdateLabelsAsText(labelsAsText) {
52811
- this.props.updateChart(this.props.figureId, {
53279
+ this.props.updateChart(this.props.chartId, {
52812
53280
  labelsAsText,
52813
53281
  });
52814
53282
  }
52815
53283
  onUpdateStacked(stacked) {
52816
- this.props.updateChart(this.props.figureId, {
53284
+ this.props.updateChart(this.props.chartId, {
52817
53285
  stacked,
52818
53286
  });
52819
53287
  }
52820
53288
  onUpdateCumulative(cumulative) {
52821
- this.props.updateChart(this.props.figureId, {
53289
+ this.props.updateChart(this.props.chartId, {
52822
53290
  cumulative,
52823
53291
  });
52824
53292
  }
@@ -52855,13 +53323,13 @@ stores.inject(MyMetaStore, storeInstance);
52855
53323
  PieHoleSize,
52856
53324
  };
52857
53325
  static props = {
52858
- figureId: String,
53326
+ chartId: String,
52859
53327
  definition: Object,
52860
53328
  updateChart: Function,
52861
53329
  canUpdateChart: { type: Function, optional: true },
52862
53330
  };
52863
53331
  onPieHoleSizeChange(pieHolePercentage) {
52864
- this.props.updateChart(this.props.figureId, {
53332
+ this.props.updateChart(this.props.chartId, {
52865
53333
  ...this.props.definition,
52866
53334
  pieHolePercentage,
52867
53335
  });
@@ -52882,7 +53350,7 @@ stores.inject(MyMetaStore, storeInstance);
52882
53350
  ChartShowDataMarkers,
52883
53351
  };
52884
53352
  static props = {
52885
- figureId: String,
53353
+ chartId: String,
52886
53354
  definition: Object,
52887
53355
  canUpdateChart: Function,
52888
53356
  updateChart: Function,
@@ -52892,14 +53360,14 @@ stores.inject(MyMetaStore, storeInstance);
52892
53360
  class ScatterConfigPanel extends GenericChartConfigPanel {
52893
53361
  static template = "o-spreadsheet-ScatterConfigPanel";
52894
53362
  get canTreatLabelsAsText() {
52895
- const chart = this.env.model.getters.getChart(this.props.figureId);
53363
+ const chart = this.env.model.getters.getChart(this.props.chartId);
52896
53364
  if (chart && chart instanceof ScatterChart) {
52897
53365
  return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
52898
53366
  }
52899
53367
  return false;
52900
53368
  }
52901
53369
  onUpdateLabelsAsText(labelsAsText) {
52902
- this.props.updateChart(this.props.figureId, {
53370
+ this.props.updateChart(this.props.chartId, {
52903
53371
  labelsAsText,
52904
53372
  });
52905
53373
  }
@@ -52921,7 +53389,7 @@ stores.inject(MyMetaStore, storeInstance);
52921
53389
  static template = "o-spreadsheet-ScorecardChartConfigPanel";
52922
53390
  static components = { SelectionInput, ChartErrorSection, Section };
52923
53391
  static props = {
52924
- figureId: String,
53392
+ chartId: String,
52925
53393
  definition: Object,
52926
53394
  updateChart: Function,
52927
53395
  canUpdateChart: Function,
@@ -52947,12 +53415,12 @@ stores.inject(MyMetaStore, storeInstance);
52947
53415
  }
52948
53416
  onKeyValueRangeChanged(ranges) {
52949
53417
  this.keyValue = ranges[0];
52950
- this.state.keyValueDispatchResult = this.props.canUpdateChart(this.props.figureId, {
53418
+ this.state.keyValueDispatchResult = this.props.canUpdateChart(this.props.chartId, {
52951
53419
  keyValue: this.keyValue,
52952
53420
  });
52953
53421
  }
52954
53422
  updateKeyValueRange() {
52955
- this.state.keyValueDispatchResult = this.props.updateChart(this.props.figureId, {
53423
+ this.state.keyValueDispatchResult = this.props.updateChart(this.props.chartId, {
52956
53424
  keyValue: this.keyValue,
52957
53425
  });
52958
53426
  }
@@ -52961,12 +53429,12 @@ stores.inject(MyMetaStore, storeInstance);
52961
53429
  }
52962
53430
  onBaselineRangeChanged(ranges) {
52963
53431
  this.baseline = ranges[0];
52964
- this.state.baselineDispatchResult = this.props.canUpdateChart(this.props.figureId, {
53432
+ this.state.baselineDispatchResult = this.props.canUpdateChart(this.props.chartId, {
52965
53433
  baseline: this.baseline,
52966
53434
  });
52967
53435
  }
52968
53436
  updateBaselineRange() {
52969
- this.state.baselineDispatchResult = this.props.updateChart(this.props.figureId, {
53437
+ this.state.baselineDispatchResult = this.props.updateChart(this.props.chartId, {
52970
53438
  baseline: this.baseline,
52971
53439
  });
52972
53440
  }
@@ -52974,7 +53442,7 @@ stores.inject(MyMetaStore, storeInstance);
52974
53442
  return this.baseline || "";
52975
53443
  }
52976
53444
  updateBaselineMode(ev) {
52977
- this.props.updateChart(this.props.figureId, { baselineMode: ev.target.value });
53445
+ this.props.updateChart(this.props.chartId, { baselineMode: ev.target.value });
52978
53446
  }
52979
53447
  }
52980
53448
 
@@ -52989,7 +53457,7 @@ stores.inject(MyMetaStore, storeInstance);
52989
53457
  ChartTitle,
52990
53458
  };
52991
53459
  static props = {
52992
- figureId: String,
53460
+ chartId: String,
52993
53461
  definition: Object,
52994
53462
  updateChart: Function,
52995
53463
  canUpdateChart: { type: Function, optional: true },
@@ -53006,7 +53474,7 @@ stores.inject(MyMetaStore, storeInstance);
53006
53474
  return SCORECARD_CHART_TITLE_FONT_SIZE;
53007
53475
  }
53008
53476
  updateHumanizeNumbers(humanize) {
53009
- this.props.updateChart(this.props.figureId, { humanize });
53477
+ this.props.updateChart(this.props.chartId, { humanize });
53010
53478
  }
53011
53479
  translate(term) {
53012
53480
  return _t(term);
@@ -53014,13 +53482,13 @@ stores.inject(MyMetaStore, storeInstance);
53014
53482
  setColor(color, colorPickerId) {
53015
53483
  switch (colorPickerId) {
53016
53484
  case "backgroundColor":
53017
- this.props.updateChart(this.props.figureId, { background: color });
53485
+ this.props.updateChart(this.props.chartId, { background: color });
53018
53486
  break;
53019
53487
  case "baselineColorDown":
53020
- this.props.updateChart(this.props.figureId, { baselineColorDown: color });
53488
+ this.props.updateChart(this.props.chartId, { baselineColorDown: color });
53021
53489
  break;
53022
53490
  case "baselineColorUp":
53023
- this.props.updateChart(this.props.figureId, { baselineColorUp: color });
53491
+ this.props.updateChart(this.props.chartId, { baselineColorUp: color });
53024
53492
  break;
53025
53493
  }
53026
53494
  }
@@ -53039,22 +53507,22 @@ stores.inject(MyMetaStore, storeInstance);
53039
53507
  };
53040
53508
  }
53041
53509
  setKeyText(text) {
53042
- this.props.updateChart(this.props.figureId, {
53510
+ this.props.updateChart(this.props.chartId, {
53043
53511
  keyDescr: { ...this.props.definition.keyDescr, text },
53044
53512
  });
53045
53513
  }
53046
53514
  updateKeyStyle(style) {
53047
53515
  const keyDescr = { ...this.keyStyle, ...style };
53048
- this.props.updateChart(this.props.figureId, { keyDescr });
53516
+ this.props.updateChart(this.props.chartId, { keyDescr });
53049
53517
  }
53050
53518
  setBaselineText(text) {
53051
- this.props.updateChart(this.props.figureId, {
53519
+ this.props.updateChart(this.props.chartId, {
53052
53520
  baselineDescr: { ...this.props.definition.baselineDescr, text },
53053
53521
  });
53054
53522
  }
53055
53523
  updateBaselineStyle(style) {
53056
53524
  const baselineDescr = { ...this.baselineStyle, ...style };
53057
- this.props.updateChart(this.props.figureId, { baselineDescr });
53525
+ this.props.updateChart(this.props.chartId, { baselineDescr });
53058
53526
  }
53059
53527
  }
53060
53528
 
@@ -53072,7 +53540,7 @@ stores.inject(MyMetaStore, storeInstance);
53072
53540
  PieHoleSize,
53073
53541
  };
53074
53542
  static props = {
53075
- figureId: String,
53543
+ chartId: String,
53076
53544
  definition: Object,
53077
53545
  updateChart: Function,
53078
53546
  canUpdateChart: { type: Function, optional: true },
@@ -53085,18 +53553,18 @@ stores.inject(MyMetaStore, storeInstance);
53085
53553
  return this.props.definition.showLabels ?? SunburstChartDefaults.showLabels;
53086
53554
  }
53087
53555
  get groupColors() {
53088
- const figureId = this.props.figureId;
53089
- const runtime = this.env.model.getters.getChartRuntime(figureId);
53556
+ const chartId = this.props.chartId;
53557
+ const runtime = this.env.model.getters.getChartRuntime(chartId);
53090
53558
  const dataset = runtime.chartJsConfig.data.datasets[0];
53091
53559
  return dataset?.groupColors || [];
53092
53560
  }
53093
53561
  onGroupColorChanged(index, color) {
53094
53562
  const colors = deepCopy(this.props.definition.groupColors) ?? [];
53095
53563
  colors[index] = color;
53096
- this.props.updateChart(this.props.figureId, { groupColors: colors });
53564
+ this.props.updateChart(this.props.chartId, { groupColors: colors });
53097
53565
  }
53098
53566
  onPieHoleSizeChange(pieHolePercentage) {
53099
- this.props.updateChart(this.props.figureId, {
53567
+ this.props.updateChart(this.props.chartId, {
53100
53568
  ...this.props.definition,
53101
53569
  pieHolePercentage,
53102
53570
  });
@@ -53110,7 +53578,7 @@ stores.inject(MyMetaStore, storeInstance);
53110
53578
  RoundColorPicker,
53111
53579
  };
53112
53580
  static props = {
53113
- figureId: String,
53581
+ chartId: String,
53114
53582
  definition: Object,
53115
53583
  onColorChanged: Function,
53116
53584
  };
@@ -53122,7 +53590,7 @@ stores.inject(MyMetaStore, storeInstance);
53122
53590
  return coloringOptions;
53123
53591
  }
53124
53592
  getTreeGroupAndColors() {
53125
- const runtime = this.env.model.getters.getChartRuntime(this.props.figureId);
53593
+ const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
53126
53594
  const config = runtime.chartJsConfig;
53127
53595
  return config.data.datasets[0]?.groupColors || [];
53128
53596
  }
@@ -53143,7 +53611,7 @@ stores.inject(MyMetaStore, storeInstance);
53143
53611
  static template = "o-spreadsheet-TreeMapColorScale";
53144
53612
  static components = { RoundColorPicker };
53145
53613
  static props = {
53146
- figureId: String,
53614
+ chartId: String,
53147
53615
  definition: Object,
53148
53616
  onColorChanged: Function,
53149
53617
  };
@@ -53185,7 +53653,7 @@ stores.inject(MyMetaStore, storeInstance);
53185
53653
  TreeMapColorScale,
53186
53654
  };
53187
53655
  static props = {
53188
- figureId: String,
53656
+ chartId: String,
53189
53657
  definition: Object,
53190
53658
  updateChart: Function,
53191
53659
  canUpdateChart: { type: Function, optional: true },
@@ -53209,15 +53677,15 @@ stores.inject(MyMetaStore, storeInstance);
53209
53677
  }
53210
53678
  changeColoringOption(option) {
53211
53679
  const coloringOptions = option === "categoryColor" ? this.savedColors.categoryColors : this.savedColors.colorScale;
53212
- this.props.updateChart(this.props.figureId, { coloringOptions });
53680
+ this.props.updateChart(this.props.chartId, { coloringOptions });
53213
53681
  }
53214
53682
  onCategoryColorChange(coloringOptions) {
53215
53683
  this.savedColors.categoryColors = coloringOptions;
53216
- this.props.updateChart(this.props.figureId, { coloringOptions });
53684
+ this.props.updateChart(this.props.chartId, { coloringOptions });
53217
53685
  }
53218
53686
  onColorScaleChange(coloringOptions) {
53219
53687
  this.savedColors.colorScale = coloringOptions;
53220
- this.props.updateChart(this.props.figureId, { coloringOptions });
53688
+ this.props.updateChart(this.props.chartId, { coloringOptions });
53221
53689
  }
53222
53690
  get coloringOptionChoices() {
53223
53691
  return [
@@ -53241,23 +53709,23 @@ stores.inject(MyMetaStore, storeInstance);
53241
53709
  ChartLegend,
53242
53710
  };
53243
53711
  static props = {
53244
- figureId: String,
53712
+ chartId: String,
53245
53713
  definition: Object,
53246
53714
  updateChart: Function,
53247
53715
  canUpdateChart: { type: Function, optional: true },
53248
53716
  };
53249
53717
  axisChoices = CHART_AXIS_CHOICES;
53250
53718
  onUpdateShowSubTotals(showSubTotals) {
53251
- this.props.updateChart(this.props.figureId, { showSubTotals });
53719
+ this.props.updateChart(this.props.chartId, { showSubTotals });
53252
53720
  }
53253
53721
  onUpdateShowConnectorLines(showConnectorLines) {
53254
- this.props.updateChart(this.props.figureId, { showConnectorLines });
53722
+ this.props.updateChart(this.props.chartId, { showConnectorLines });
53255
53723
  }
53256
53724
  onUpdateFirstValueAsSubtotal(firstValueAsSubtotal) {
53257
- this.props.updateChart(this.props.figureId, { firstValueAsSubtotal });
53725
+ this.props.updateChart(this.props.chartId, { firstValueAsSubtotal });
53258
53726
  }
53259
53727
  updateColor(colorName, color) {
53260
- this.props.updateChart(this.props.figureId, { [colorName]: color });
53728
+ this.props.updateChart(this.props.chartId, { [colorName]: color });
53261
53729
  }
53262
53730
  get axesList() {
53263
53731
  return [
@@ -53278,7 +53746,7 @@ stores.inject(MyMetaStore, storeInstance);
53278
53746
  CHART_WATERFALL_SUBTOTAL_COLOR);
53279
53747
  }
53280
53748
  updateVerticalAxisPosition(value) {
53281
- this.props.updateChart(this.props.figureId, {
53749
+ this.props.updateChart(this.props.chartId, {
53282
53750
  verticalAxisPosition: value,
53283
53751
  });
53284
53752
  }
@@ -53380,7 +53848,7 @@ stores.inject(MyMetaStore, storeInstance);
53380
53848
  class ChartTypePicker extends owl.Component {
53381
53849
  static template = "o-spreadsheet-ChartTypePicker";
53382
53850
  static components = { Section, Popover };
53383
- static props = { figureId: String, chartPanelStore: Object };
53851
+ static props = { chartId: String, chartPanelStore: Object };
53384
53852
  categories = chartCategories;
53385
53853
  chartTypeByCategories = {};
53386
53854
  popoverRef = owl.useRef("popoverRef");
@@ -53405,14 +53873,14 @@ stores.inject(MyMetaStore, storeInstance);
53405
53873
  this.closePopover();
53406
53874
  }
53407
53875
  onTypeChange(type) {
53408
- this.props.chartPanelStore.changeChartType(this.props.figureId, type);
53876
+ this.props.chartPanelStore.changeChartType(this.props.chartId, type);
53409
53877
  this.closePopover();
53410
53878
  }
53411
- getChartDefinition(figureId) {
53412
- return this.env.model.getters.getChartDefinition(figureId);
53879
+ getChartDefinition(chartId) {
53880
+ return this.env.model.getters.getChartDefinition(chartId);
53413
53881
  }
53414
53882
  getSelectedChartSubtypeProperties() {
53415
- const definition = this.getChartDefinition(this.props.figureId);
53883
+ const definition = this.getChartDefinition(this.props.chartId);
53416
53884
  const matchedChart = chartSubtypeRegistry
53417
53885
  .getAll()
53418
53886
  .find((c) => c.matcher?.(definition) || false);
@@ -53444,34 +53912,36 @@ stores.inject(MyMetaStore, storeInstance);
53444
53912
  activatePanel(panel) {
53445
53913
  this.panel = panel;
53446
53914
  }
53447
- changeChartType(figureId, newDisplayType) {
53448
- const currentCreationContext = this.getters.getContextCreationChart(figureId);
53449
- const savedCreationContext = this.creationContexts[figureId] || {};
53915
+ changeChartType(chartId, newDisplayType) {
53916
+ const currentCreationContext = this.getters.getContextCreationChart(chartId);
53917
+ const savedCreationContext = this.creationContexts[chartId] || {};
53450
53918
  let newRanges = currentCreationContext?.range;
53451
53919
  if (newRanges?.every((range, i) => deepEquals(range, savedCreationContext.range?.[i]))) {
53452
53920
  newRanges = Object.assign([], savedCreationContext.range, currentCreationContext?.range);
53453
53921
  }
53454
- this.creationContexts[figureId] = {
53922
+ this.creationContexts[chartId] = {
53455
53923
  ...savedCreationContext,
53456
53924
  ...currentCreationContext,
53457
53925
  range: newRanges,
53458
53926
  };
53927
+ const figureId = this.getters.getFigureIdFromChartId(chartId);
53459
53928
  const sheetId = this.getters.getFigureSheetId(figureId);
53460
53929
  if (!sheetId) {
53461
53930
  return;
53462
53931
  }
53463
- const definition = this.getChartDefinitionFromContextCreation(figureId, newDisplayType);
53932
+ const definition = this.getChartDefinitionFromContextCreation(chartId, newDisplayType);
53464
53933
  this.model.dispatch("UPDATE_CHART", {
53465
53934
  definition,
53935
+ chartId,
53466
53936
  figureId,
53467
53937
  sheetId,
53468
53938
  });
53469
53939
  }
53470
- getChartDefinitionFromContextCreation(figureId, newDisplayType) {
53940
+ getChartDefinitionFromContextCreation(chartId, newDisplayType) {
53471
53941
  const newChartInfo = chartSubtypeRegistry.get(newDisplayType);
53472
53942
  const ChartClass = chartRegistry.get(newChartInfo.chartType);
53473
53943
  return {
53474
- ...ChartClass.getChartDefinitionFromContextCreation(this.creationContexts[figureId]),
53944
+ ...ChartClass.getChartDefinitionFromContextCreation(this.creationContexts[chartId]),
53475
53945
  ...newChartInfo.subtypeDefinition,
53476
53946
  };
53477
53947
  }
@@ -53512,15 +53982,15 @@ stores.inject(MyMetaStore, storeInstance);
53512
53982
  class ChartPanel extends owl.Component {
53513
53983
  static template = "o-spreadsheet-ChartPanel";
53514
53984
  static components = { Section, ChartTypePicker };
53515
- static props = { onCloseSidePanel: Function, figureId: String };
53985
+ static props = { onCloseSidePanel: Function, chartId: String };
53516
53986
  panelContentRef;
53517
53987
  scrollPositions = {
53518
53988
  configuration: 0,
53519
53989
  design: 0,
53520
53990
  };
53521
53991
  store;
53522
- get figureId() {
53523
- return this.props.figureId;
53992
+ get chartId() {
53993
+ return this.props.chartId;
53524
53994
  }
53525
53995
  setup() {
53526
53996
  this.store = useLocalStore(MainChartPanelStore);
@@ -53540,45 +54010,49 @@ stores.inject(MyMetaStore, storeInstance);
53540
54010
  }
53541
54011
  this.store.activatePanel(panel);
53542
54012
  }
53543
- updateChart(figureId, updateDefinition) {
53544
- if (figureId !== this.figureId) {
54013
+ updateChart(chartId, updateDefinition) {
54014
+ const figureId = this.env.model.getters.getFigureIdFromChartId(chartId);
54015
+ if (chartId !== this.chartId) {
53545
54016
  return;
53546
54017
  }
53547
54018
  const definition = {
53548
- ...this.getChartDefinition(this.figureId),
54019
+ ...this.getChartDefinition(this.chartId),
53549
54020
  ...updateDefinition,
53550
54021
  };
53551
54022
  return this.env.model.dispatch("UPDATE_CHART", {
53552
54023
  definition,
54024
+ chartId,
53553
54025
  figureId,
53554
54026
  sheetId: this.env.model.getters.getFigureSheetId(figureId),
53555
54027
  });
53556
54028
  }
53557
- canUpdateChart(figureId, updateDefinition) {
53558
- if (figureId !== this.figureId || !this.env.model.getters.isChartDefined(figureId)) {
54029
+ canUpdateChart(chartId, updateDefinition) {
54030
+ const figureId = this.env.model.getters.getFigureIdFromChartId(chartId);
54031
+ if (chartId !== this.chartId || !this.env.model.getters.isChartDefined(chartId)) {
53559
54032
  return;
53560
54033
  }
53561
54034
  const definition = {
53562
- ...this.getChartDefinition(this.figureId),
54035
+ ...this.getChartDefinition(this.chartId),
53563
54036
  ...updateDefinition,
53564
54037
  };
53565
54038
  return this.env.model.canDispatch("UPDATE_CHART", {
53566
54039
  definition,
54040
+ chartId,
53567
54041
  figureId,
53568
54042
  sheetId: this.env.model.getters.getFigureSheetId(figureId),
53569
54043
  });
53570
54044
  }
53571
54045
  onTypeChange(type) {
53572
- if (!this.figureId) {
54046
+ if (!this.chartId) {
53573
54047
  return;
53574
54048
  }
53575
- this.store.changeChartType(this.figureId, type);
54049
+ this.store.changeChartType(this.chartId, type);
53576
54050
  }
53577
54051
  get chartPanel() {
53578
- if (!this.figureId) {
54052
+ if (!this.chartId) {
53579
54053
  throw new Error("Chart not defined.");
53580
54054
  }
53581
- const type = this.env.model.getters.getChartType(this.figureId);
54055
+ const type = this.env.model.getters.getChartType(this.chartId);
53582
54056
  if (!type) {
53583
54057
  throw new Error("Chart not defined.");
53584
54058
  }
@@ -53588,8 +54062,8 @@ stores.inject(MyMetaStore, storeInstance);
53588
54062
  }
53589
54063
  return chartPanel;
53590
54064
  }
53591
- getChartDefinition(figureId) {
53592
- return this.env.model.getters.getChartDefinition(figureId);
54065
+ getChartDefinition(chartId) {
54066
+ return this.env.model.getters.getChartDefinition(chartId);
53593
54067
  }
53594
54068
  }
53595
54069
 
@@ -55591,103 +56065,6 @@ stores.inject(MyMetaStore, storeInstance);
55591
56065
  }
55592
56066
  }
55593
56067
 
55594
- function useAutofocus({ refName }) {
55595
- const ref = owl.useRef(refName);
55596
- owl.useEffect((el) => {
55597
- el?.focus();
55598
- }, () => [ref.el]);
55599
- }
55600
-
55601
- css /* scss */ `
55602
- .o-spreadsheet {
55603
- .os-input {
55604
- border-width: 0 0 1px 0;
55605
- border-color: transparent;
55606
- outline: none;
55607
- text-overflow: ellipsis;
55608
- color: ${TEXT_BODY};
55609
- }
55610
- .os-input:hover,
55611
- .os-input:focus {
55612
- border-color: ${GRAY_300};
55613
- }
55614
- }
55615
- `;
55616
- class TextInput extends owl.Component {
55617
- static template = "o-spreadsheet-TextInput";
55618
- static props = {
55619
- value: String,
55620
- onChange: Function,
55621
- class: {
55622
- type: String,
55623
- optional: true,
55624
- },
55625
- id: {
55626
- type: String,
55627
- optional: true,
55628
- },
55629
- placeholder: {
55630
- type: String,
55631
- optional: true,
55632
- },
55633
- autofocus: {
55634
- type: Boolean,
55635
- optional: true,
55636
- },
55637
- };
55638
- inputRef = owl.useRef("input");
55639
- setup() {
55640
- owl.useExternalListener(window, "click", (ev) => {
55641
- if (ev.target !== this.inputRef.el && this.inputRef.el?.value !== this.props.value) {
55642
- this.save();
55643
- }
55644
- }, { capture: true });
55645
- if (this.props.autofocus) {
55646
- useAutofocus({ refName: "input" });
55647
- }
55648
- }
55649
- onKeyDown(ev) {
55650
- switch (ev.key) {
55651
- case "Enter":
55652
- this.save();
55653
- ev.preventDefault();
55654
- ev.stopPropagation();
55655
- break;
55656
- case "Escape":
55657
- if (this.inputRef.el) {
55658
- this.inputRef.el.value = this.props.value;
55659
- this.inputRef.el.blur();
55660
- }
55661
- ev.preventDefault();
55662
- ev.stopPropagation();
55663
- break;
55664
- }
55665
- }
55666
- save() {
55667
- const currentValue = (this.inputRef.el?.value || "").trim();
55668
- if (currentValue !== this.props.value) {
55669
- this.props.onChange(currentValue);
55670
- }
55671
- this.inputRef.el?.blur();
55672
- }
55673
- onMouseDown(ev) {
55674
- // Stop the event if the input is not focused, we handle everything in onMouseUp
55675
- if (ev.target !== document.activeElement) {
55676
- ev.preventDefault();
55677
- ev.stopPropagation();
55678
- }
55679
- }
55680
- onMouseUp(ev) {
55681
- const target = ev.target;
55682
- if (target !== document.activeElement) {
55683
- target.focus();
55684
- target.select();
55685
- ev.preventDefault();
55686
- ev.stopPropagation();
55687
- }
55688
- }
55689
- }
55690
-
55691
56068
  class PivotCustomGroupsCollapsible extends owl.Component {
55692
56069
  static template = "o-spreadsheet-PivotCustomGroupsCollapsible";
55693
56070
  static props = {
@@ -57802,11 +58179,12 @@ stores.inject(MyMetaStore, storeInstance);
57802
58179
  title: _t("Chart"),
57803
58180
  Body: ChartPanel,
57804
58181
  computeState: (getters, initialProps) => {
57805
- const figureId = getters.getSelectedFigureId() ?? initialProps.figureId;
57806
- if (!getters.isChartDefined(figureId)) {
58182
+ const figureId = getters.getSelectedFigureId();
58183
+ const chartId = figureId ? getters.getChartIdFromFigureId(figureId) : initialProps.chartId;
58184
+ if (!chartId || !getters.isChartDefined(chartId)) {
57807
58185
  return { isOpen: false };
57808
58186
  }
57809
- return { isOpen: true, props: { figureId } };
58187
+ return { isOpen: true, props: { chartId } };
57810
58188
  },
57811
58189
  });
57812
58190
  sidePanelRegistry.add("FindAndReplace", {
@@ -57894,6 +58272,17 @@ stores.inject(MyMetaStore, storeInstance);
57894
58272
  }
57895
58273
  },
57896
58274
  });
58275
+ sidePanelRegistry.add("CarouselPanel", {
58276
+ title: _t("Carousel"),
58277
+ Body: CarouselPanel,
58278
+ computeState: (getters, initialProps) => {
58279
+ const figureId = initialProps.figureId || getters.getSelectedFigureId();
58280
+ if (!figureId || !getters.doesCarouselExist(figureId)) {
58281
+ return { isOpen: false };
58282
+ }
58283
+ return { isOpen: true, props: { figureId } };
58284
+ },
58285
+ });
57897
58286
 
57898
58287
  class ScreenWidthStore {
57899
58288
  mutators = ["setSmallThreshhold"];
@@ -58855,7 +59244,7 @@ stores.inject(MyMetaStore, storeInstance);
58855
59244
  let lastFigureId = undefined;
58856
59245
  owl.onWillUpdateProps(() => {
58857
59246
  if (lastFigureId !== this.figureUI?.id) {
58858
- animationStore.enableAnimationForChart(this.figureUI?.id + "-fullscreen");
59247
+ animationStore.enableAnimationForChart(this.chartId + "-fullscreen");
58859
59248
  }
58860
59249
  lastFigureId = this.figureUI?.id;
58861
59250
  });
@@ -58864,6 +59253,11 @@ stores.inject(MyMetaStore, storeInstance);
58864
59253
  get figureUI() {
58865
59254
  return this.fullScreenChartStore.fullScreenFigure;
58866
59255
  }
59256
+ get chartId() {
59257
+ if (!this.figureUI)
59258
+ return undefined;
59259
+ return this.env.model.getters.getChartIdFromFigureId(this.figureUI?.id);
59260
+ }
58867
59261
  exitFullScreen() {
58868
59262
  if (this.figureUI) {
58869
59263
  this.fullScreenChartStore.toggleFullScreenChart(this.figureUI.id);
@@ -58875,9 +59269,9 @@ stores.inject(MyMetaStore, storeInstance);
58875
59269
  }
58876
59270
  }
58877
59271
  get chartComponent() {
58878
- if (!this.figureUI)
59272
+ if (!this.chartId)
58879
59273
  return undefined;
58880
- const type = this.env.model.getters.getChartType(this.figureUI.id);
59274
+ const type = this.env.model.getters.getChartType(this.chartId);
58881
59275
  const component = chartComponentRegistry.get(type);
58882
59276
  if (!component) {
58883
59277
  throw new Error(`Component is not defined for type ${type}`);
@@ -60536,6 +60930,7 @@ stores.inject(MyMetaStore, storeInstance);
60536
60930
  "getChartType",
60537
60931
  "getChartIds",
60538
60932
  "getChart",
60933
+ "getFigureIdFromChartId",
60539
60934
  "getContextCreationChart",
60540
60935
  ];
60541
60936
  charts = {};
@@ -60543,7 +60938,11 @@ stores.inject(MyMetaStore, storeInstance);
60543
60938
  validateChartDefinition = (cmd) => validateChartDefinition(this, cmd.definition);
60544
60939
  adaptRanges(applyChange) {
60545
60940
  for (const [chartId, chart] of Object.entries(this.charts)) {
60546
- this.history.update("charts", chartId, chart?.updateRanges(applyChange));
60941
+ if (!chart) {
60942
+ continue;
60943
+ }
60944
+ const newChart = chart.chart.updateRanges(applyChange);
60945
+ this.history.update("charts", chartId, newChart ? { figureId: chart.figureId, chart: newChart } : undefined);
60547
60946
  }
60548
60947
  }
60549
60948
  // ---------------------------------------------------------------------------
@@ -60552,9 +60951,11 @@ stores.inject(MyMetaStore, storeInstance);
60552
60951
  allowDispatch(cmd) {
60553
60952
  switch (cmd.type) {
60554
60953
  case "CREATE_CHART":
60555
- return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartDuplicate));
60954
+ return this.checkValidations(cmd, this.chainValidations(this.checkFigureArguments, this.validateChartDefinition, this.checkChartDuplicate));
60556
60955
  case "UPDATE_CHART":
60557
60956
  return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartExists, this.checkChartChanged));
60957
+ case "DELETE_CHART":
60958
+ return this.checkChartExists(cmd);
60558
60959
  default:
60559
60960
  return "Success" /* CommandResult.Success */;
60560
60961
  }
@@ -60562,37 +60963,61 @@ stores.inject(MyMetaStore, storeInstance);
60562
60963
  handle(cmd) {
60563
60964
  switch (cmd.type) {
60564
60965
  case "CREATE_CHART":
60565
- this.addFigure(cmd.figureId, cmd.sheetId, cmd.col, cmd.row, cmd.offset, cmd.size);
60566
- this.addChart(cmd.figureId, cmd.definition);
60966
+ const { col, row, offset, size, sheetId, figureId } = cmd;
60967
+ // If figure position is not defined, it means that the figure already exist (see allowDispatch)
60968
+ if (!this.getters.getFigure(sheetId, figureId) &&
60969
+ offset !== undefined &&
60970
+ col !== undefined &&
60971
+ row !== undefined) {
60972
+ this.addFigure(figureId, sheetId, col, row, offset, size);
60973
+ }
60974
+ this.addChart(cmd.figureId, cmd.chartId, cmd.definition);
60567
60975
  break;
60568
60976
  case "UPDATE_CHART": {
60569
- this.addChart(cmd.figureId, cmd.definition);
60977
+ this.addChart(cmd.figureId, cmd.chartId, cmd.definition);
60570
60978
  break;
60571
60979
  }
60572
60980
  case "DUPLICATE_SHEET": {
60573
- const sheetFiguresFrom = this.getters.getFigures(cmd.sheetId);
60574
- for (const fig of sheetFiguresFrom) {
60575
- if (fig.tag === "chart") {
60576
- const figureIdBase = fig.id.split(FIGURE_ID_SPLITTER).pop();
60577
- const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
60578
- const chart = this.charts[fig.id]?.duplicateInDuplicatedSheet(cmd.sheetIdTo);
60579
- if (chart) {
60580
- this.dispatch("CREATE_CHART", {
60581
- figureId: duplicatedFigureId,
60582
- col: fig.col,
60583
- row: fig.row,
60584
- offset: fig.offset,
60585
- size: { width: fig.width, height: fig.height },
60586
- definition: chart.getDefinition(),
60587
- sheetId: cmd.sheetIdTo,
60588
- });
60589
- }
60981
+ for (const chartId of this.getChartIds(cmd.sheetId)) {
60982
+ const { chart, figureId } = this.charts[chartId] || {};
60983
+ if (!chart || !figureId) {
60984
+ continue;
60985
+ }
60986
+ const fig = this.getters.getFigure(cmd.sheetId, figureId);
60987
+ if (!fig) {
60988
+ continue;
60989
+ }
60990
+ const figureIdBase = figureId.split(FIGURE_ID_SPLITTER).pop();
60991
+ const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
60992
+ const chartIdBase = chartId.split(FIGURE_ID_SPLITTER).pop();
60993
+ const duplicatedChartId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${chartIdBase}`;
60994
+ const newChart = chart.duplicateInDuplicatedSheet(cmd.sheetIdTo);
60995
+ if (newChart) {
60996
+ this.dispatch("CREATE_CHART", {
60997
+ figureId: duplicatedFigureId,
60998
+ chartId: duplicatedChartId,
60999
+ col: fig.col,
61000
+ row: fig.row,
61001
+ offset: fig.offset,
61002
+ size: { width: fig.width, height: fig.height },
61003
+ definition: newChart.getDefinition(),
61004
+ sheetId: cmd.sheetIdTo,
61005
+ });
60590
61006
  }
60591
61007
  }
60592
61008
  break;
60593
61009
  }
60594
61010
  case "DELETE_FIGURE":
60595
- this.history.update("charts", cmd.figureId, undefined);
61011
+ for (const chartId in this.charts) {
61012
+ if (this.charts[chartId]?.figureId === cmd.figureId) {
61013
+ this.dispatch("DELETE_CHART", { chartId, sheetId: cmd.sheetId });
61014
+ }
61015
+ }
61016
+ break;
61017
+ case "DELETE_CHART":
61018
+ if (this.isChartDefined(cmd.chartId)) {
61019
+ this.history.update("charts", cmd.chartId, undefined);
61020
+ }
60596
61021
  break;
60597
61022
  case "DELETE_SHEET":
60598
61023
  for (const id of this.getChartIds(cmd.sheetId)) {
@@ -60604,31 +61029,37 @@ stores.inject(MyMetaStore, storeInstance);
60604
61029
  // ---------------------------------------------------------------------------
60605
61030
  // Getters
60606
61031
  // ---------------------------------------------------------------------------
60607
- getContextCreationChart(figureId) {
60608
- return this.charts[figureId]?.getContextCreation();
61032
+ getContextCreationChart(chartId) {
61033
+ return this.charts[chartId]?.chart.getContextCreation();
60609
61034
  }
60610
- getChart(figureId) {
60611
- return this.charts[figureId];
61035
+ getChart(chartId) {
61036
+ return this.charts[chartId]?.chart;
60612
61037
  }
60613
- getChartType(figureId) {
60614
- const type = this.charts[figureId]?.type;
61038
+ getFigureIdFromChartId(chartId) {
61039
+ if (!this.charts[chartId]) {
61040
+ throw new Error(`Chart with id ${chartId} does not exist.`);
61041
+ }
61042
+ return this.charts[chartId].figureId;
61043
+ }
61044
+ getChartType(chartId) {
61045
+ const type = this.charts[chartId]?.chart.type;
60615
61046
  if (!type) {
60616
61047
  throw new Error("Chart not defined.");
60617
61048
  }
60618
61049
  return type;
60619
61050
  }
60620
- isChartDefined(figureId) {
60621
- return figureId in this.charts && this.charts !== undefined;
61051
+ isChartDefined(chartId) {
61052
+ return chartId in this.charts && this.charts !== undefined;
60622
61053
  }
60623
61054
  getChartIds(sheetId) {
60624
61055
  return Object.entries(this.charts)
60625
- .filter(([, chart]) => chart?.sheetId === sheetId)
61056
+ .filter(([, chart]) => chart?.chart.sheetId === sheetId)
60626
61057
  .map(([id]) => id);
60627
61058
  }
60628
- getChartDefinition(figureId) {
60629
- const definition = this.charts[figureId]?.getDefinition();
61059
+ getChartDefinition(chartId) {
61060
+ const definition = this.charts[chartId]?.chart.getDefinition();
60630
61061
  if (!definition) {
60631
- throw new Error(`There is no chart with the given figureId: ${figureId}`);
61062
+ throw new Error(`There is no chart with the given id: ${chartId}`);
60632
61063
  }
60633
61064
  return definition;
60634
61065
  }
@@ -60643,7 +61074,16 @@ stores.inject(MyMetaStore, storeInstance);
60643
61074
  // figure data should be external IMO => chart should be in sheet.chart
60644
61075
  // instead of in figure.data
60645
61076
  if (figure.tag === "chart") {
60646
- this.charts[figure.id] = this.createChart(figure.id, figure.data, sheet.id);
61077
+ const chartId = figure.data.chartId;
61078
+ const chart = this.createChart(figure.id, figure.data, sheet.id);
61079
+ this.charts[chartId] = { chart, figureId: figure.id };
61080
+ }
61081
+ else if (figure.tag === "carousel") {
61082
+ for (const chartId in figure.data.chartDefinitions || {}) {
61083
+ const chartDefinition = figure.data.chartDefinitions[chartId];
61084
+ const chart = this.createChart(figure.id, chartDefinition, sheet.id);
61085
+ this.charts[chartId] = { chart, figureId: figure.id };
61086
+ }
60647
61087
  }
60648
61088
  }
60649
61089
  }
@@ -60657,13 +61097,23 @@ stores.inject(MyMetaStore, storeInstance);
60657
61097
  const figures = [];
60658
61098
  for (const sheetFigure of sheetFigures) {
60659
61099
  const figure = sheetFigure;
60660
- if (figure && figure.tag === "chart") {
60661
- const data = this.charts[figure.id]?.getDefinition();
61100
+ const chartId = Object.keys(this.charts).find((chartId) => this.charts[chartId]?.figureId === sheetFigure.id);
61101
+ if (figure && figure.tag === "chart" && chartId) {
61102
+ const data = this.charts[chartId]?.chart.getDefinition();
60662
61103
  if (data) {
60663
- figure.data = data;
61104
+ figure.data = { ...data, chartId };
60664
61105
  figures.push(figure);
60665
61106
  }
60666
61107
  }
61108
+ else if (figure && figure.tag === "carousel") {
61109
+ const chartIds = Object.keys(this.charts).filter((chartId) => this.charts[chartId]?.figureId === sheetFigure.id);
61110
+ const data = {};
61111
+ for (const chartId of chartIds) {
61112
+ data[chartId] = this.charts[chartId]?.chart.getDefinition();
61113
+ }
61114
+ figure.data = { chartDefinitions: data };
61115
+ figures.push(figure);
61116
+ }
60667
61117
  else {
60668
61118
  figures.push(figure);
60669
61119
  }
@@ -60696,27 +61146,40 @@ stores.inject(MyMetaStore, storeInstance);
60696
61146
  * Add a chart in the local state. If a chart already exists, this chart is
60697
61147
  * replaced
60698
61148
  */
60699
- addChart(id, definition) {
60700
- const sheetId = this.getters.getFigureSheetId(id);
61149
+ addChart(figureId, chartId, definition) {
61150
+ const sheetId = this.getters.getFigureSheetId(figureId);
60701
61151
  if (sheetId) {
60702
- this.history.update("charts", id, this.createChart(id, definition, sheetId));
61152
+ const chart = this.createChart(figureId, definition, sheetId);
61153
+ this.history.update("charts", chartId, { figureId, chart });
60703
61154
  }
60704
61155
  }
60705
61156
  checkChartDuplicate(cmd) {
60706
- return this.getters.getFigureSheetId(cmd.figureId)
61157
+ return this.isChartDefined(cmd.chartId)
60707
61158
  ? "DuplicatedChartId" /* CommandResult.DuplicatedChartId */
60708
61159
  : "Success" /* CommandResult.Success */;
60709
61160
  }
60710
61161
  checkChartExists(cmd) {
60711
- return this.isChartDefined(cmd.figureId)
61162
+ return this.isChartDefined(cmd.chartId)
60712
61163
  ? "Success" /* CommandResult.Success */
60713
61164
  : "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
60714
61165
  }
60715
61166
  checkChartChanged(cmd) {
60716
- return deepEquals(this.getChartDefinition(cmd.figureId), cmd.definition)
61167
+ if (cmd.figureId !== this.charts[cmd.chartId]?.figureId) {
61168
+ return "Success" /* CommandResult.Success */;
61169
+ }
61170
+ return deepEquals(this.getChartDefinition(cmd.chartId), cmd.definition)
60717
61171
  ? "NoChanges" /* CommandResult.NoChanges */
60718
61172
  : "Success" /* CommandResult.Success */;
60719
61173
  }
61174
+ /** If the command would create a new figure, there need to be a position & offset defined in the command */
61175
+ checkFigureArguments(cmd) {
61176
+ if (this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
61177
+ return "Success" /* CommandResult.Success */;
61178
+ }
61179
+ return cmd.offset !== undefined && cmd.col !== undefined && cmd.row !== undefined
61180
+ ? "Success" /* CommandResult.Success */
61181
+ : "MissingFigureArguments" /* CommandResult.MissingFigureArguments */;
61182
+ }
60720
61183
  }
60721
61184
 
60722
61185
  // -----------------------------------------------------------------------------
@@ -61570,6 +62033,23 @@ stores.inject(MyMetaStore, storeInstance);
61570
62033
  this.onRowRemove(cmd.sheetId);
61571
62034
  }
61572
62035
  break;
62036
+ case "DUPLICATE_SHEET": {
62037
+ for (const figureId in this.figures[cmd.sheetId]) {
62038
+ const fig = this.figures[cmd.sheetId]?.[figureId];
62039
+ if (!fig) {
62040
+ continue;
62041
+ }
62042
+ const figureIdBase = figureId.split(FIGURE_ID_SPLITTER).pop();
62043
+ const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
62044
+ this.dispatch("CREATE_FIGURE", {
62045
+ figureId: duplicatedFigureId,
62046
+ ...fig,
62047
+ size: { width: fig.width, height: fig.height },
62048
+ sheetId: cmd.sheetIdTo,
62049
+ });
62050
+ }
62051
+ break;
62052
+ }
61573
62053
  }
61574
62054
  }
61575
62055
  onColRemove(sheetId) {
@@ -61681,6 +62161,9 @@ stores.inject(MyMetaStore, storeInstance);
61681
62161
  const figure = { ...this.getFigure(sheetId, figureId), ...update };
61682
62162
  for (const [key, value] of Object.entries(update)) {
61683
62163
  switch (key) {
62164
+ case "tag":
62165
+ this.history.update("figures", sheetId, figure.id, key, value);
62166
+ break;
61684
62167
  case "offset":
61685
62168
  this.history.update("figures", sheetId, figure.id, key, value);
61686
62169
  break;
@@ -62108,7 +62591,9 @@ stores.inject(MyMetaStore, storeInstance);
62108
62591
  handle(cmd) {
62109
62592
  switch (cmd.type) {
62110
62593
  case "CREATE_IMAGE":
62111
- this.addFigure(cmd.figureId, cmd.sheetId, cmd.col, cmd.row, cmd.offset, cmd.size);
62594
+ if (!this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
62595
+ this.addFigure(cmd.figureId, cmd.sheetId, cmd.col, cmd.row, cmd.offset, cmd.size);
62596
+ }
62112
62597
  this.history.update("images", cmd.sheetId, cmd.figureId, cmd.definition);
62113
62598
  this.syncedImages.add(cmd.definition.path);
62114
62599
  break;
@@ -64246,6 +64731,122 @@ stores.inject(MyMetaStore, storeInstance);
64246
64731
  }
64247
64732
  }
64248
64733
 
64734
+ class CarouselPlugin extends CorePlugin {
64735
+ static getters = ["getCarousel", "doesCarouselExist"];
64736
+ carousels = {};
64737
+ allowDispatch(cmd) {
64738
+ switch (cmd.type) {
64739
+ case "CREATE_CAROUSEL": {
64740
+ if (this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
64741
+ return "DuplicatedFigureId" /* CommandResult.DuplicatedFigureId */;
64742
+ }
64743
+ return "Success" /* CommandResult.Success */;
64744
+ }
64745
+ case "UPDATE_CAROUSEL": {
64746
+ if (!this.carousels[cmd.sheetId]?.[cmd.figureId]) {
64747
+ return "InvalidFigureId" /* CommandResult.InvalidFigureId */;
64748
+ }
64749
+ return "Success" /* CommandResult.Success */;
64750
+ }
64751
+ }
64752
+ return "Success" /* CommandResult.Success */;
64753
+ }
64754
+ handle(cmd) {
64755
+ switch (cmd.type) {
64756
+ case "CREATE_CAROUSEL":
64757
+ if (!this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
64758
+ this.dispatch("CREATE_FIGURE", { ...cmd, tag: "carousel" });
64759
+ }
64760
+ this.history.update("carousels", cmd.sheetId, cmd.figureId, cmd.definition);
64761
+ break;
64762
+ case "UPDATE_CAROUSEL":
64763
+ this.removeDeletedCharts(cmd, this.getters.getCarousel(cmd.figureId).items);
64764
+ this.history.update("carousels", cmd.sheetId, cmd.figureId, cmd.definition);
64765
+ break;
64766
+ case "DUPLICATE_SHEET": {
64767
+ const sheetFiguresFrom = this.getters.getFigures(cmd.sheetId);
64768
+ for (const fig of sheetFiguresFrom) {
64769
+ if (fig.tag === "carousel") {
64770
+ const figureIdBase = fig.id.split(FIGURE_ID_SPLITTER).pop();
64771
+ const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
64772
+ const carousel = this.getCarousel(fig.id);
64773
+ if (carousel) {
64774
+ const size = { width: fig.width, height: fig.height };
64775
+ this.dispatch("CREATE_CAROUSEL", {
64776
+ sheetId: cmd.sheetIdTo,
64777
+ figureId: duplicatedFigureId,
64778
+ offset: fig.offset,
64779
+ col: fig.col,
64780
+ row: fig.row,
64781
+ size,
64782
+ definition: {
64783
+ items: carousel.items.map((item) => {
64784
+ if (item.type === "carouselDataView") {
64785
+ return { type: "carouselDataView" };
64786
+ }
64787
+ const chartIdBase = item.chartId.split(FIGURE_ID_SPLITTER).pop();
64788
+ const newChartId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${chartIdBase}`;
64789
+ return { type: "chart", chartId: newChartId };
64790
+ }),
64791
+ },
64792
+ });
64793
+ }
64794
+ }
64795
+ }
64796
+ break;
64797
+ }
64798
+ case "DELETE_FIGURE":
64799
+ this.history.update("carousels", cmd.sheetId, cmd.figureId, undefined);
64800
+ break;
64801
+ case "DELETE_SHEET":
64802
+ this.history.update("carousels", cmd.sheetId, undefined);
64803
+ break;
64804
+ }
64805
+ }
64806
+ doesCarouselExist(figureId) {
64807
+ for (const sheetId in this.carousels) {
64808
+ if (this.carousels[sheetId]?.[figureId]) {
64809
+ return true;
64810
+ }
64811
+ }
64812
+ throw false;
64813
+ }
64814
+ getCarousel(figureId) {
64815
+ for (const sheetId in this.carousels) {
64816
+ if (this.carousels[sheetId]?.[figureId]) {
64817
+ return this.carousels[sheetId][figureId];
64818
+ }
64819
+ }
64820
+ throw new Error(`There is no carousel with the given figureId: ${figureId}`);
64821
+ }
64822
+ removeDeletedCharts(cmd, oldItems) {
64823
+ const newChartIds = new Set(cmd.definition.items.filter((item) => item.type === "chart").map((item) => item.chartId));
64824
+ for (const item of oldItems) {
64825
+ if (item.type === "chart" && !newChartIds.has(item.chartId)) {
64826
+ this.dispatch("DELETE_CHART", { chartId: item.chartId, sheetId: cmd.sheetId });
64827
+ }
64828
+ }
64829
+ }
64830
+ import(data) {
64831
+ for (const sheet of data.sheets) {
64832
+ const carousels = (sheet.figures || []).filter((figure) => figure.tag === "carousel");
64833
+ for (const carousel of carousels) {
64834
+ this.history.update("carousels", sheet.id, carousel.id, { items: carousel.data.items });
64835
+ }
64836
+ }
64837
+ }
64838
+ export(data) {
64839
+ for (const sheet of data.sheets) {
64840
+ const carousels = sheet.figures.filter((figure) => figure.tag === "carousel");
64841
+ for (const carousel of carousels) {
64842
+ if (this.carousels[sheet.id]?.[carousel.id]) {
64843
+ carousel.data = { ...carousel.data, ...this.carousels[sheet.id]?.[carousel.id] };
64844
+ }
64845
+ }
64846
+ }
64847
+ }
64848
+ }
64849
+
64249
64850
  class HeaderGroupingPlugin extends CorePlugin {
64250
64851
  static getters = [
64251
64852
  "getHeaderGroups",
@@ -67201,7 +67802,7 @@ stores.inject(MyMetaStore, storeInstance);
67201
67802
  break;
67202
67803
  case "UPDATE_CHART":
67203
67804
  case "CREATE_CHART":
67204
- this.tryToAddColors(this.getChartColors(cmd.figureId));
67805
+ this.tryToAddColors(this.getChartColors(cmd.chartId));
67205
67806
  break;
67206
67807
  case "UPDATE_CELL":
67207
67808
  case "ADD_CONDITIONAL_FORMAT":
@@ -67333,8 +67934,10 @@ stores.inject(MyMetaStore, storeInstance);
67333
67934
  switch (cmd.type) {
67334
67935
  case "UPDATE_CHART":
67335
67936
  case "CREATE_CHART":
67336
- case "DELETE_FIGURE":
67337
- this.charts[cmd.figureId] = undefined;
67937
+ this.charts[cmd.chartId] = undefined;
67938
+ break;
67939
+ case "DELETE_CHART":
67940
+ this.charts[cmd.chartId] = undefined;
67338
67941
  break;
67339
67942
  case "DELETE_SHEET":
67340
67943
  for (const chartId in this.charts) {
@@ -67345,15 +67948,15 @@ stores.inject(MyMetaStore, storeInstance);
67345
67948
  break;
67346
67949
  }
67347
67950
  }
67348
- getChartRuntime(figureId) {
67349
- if (!this.charts[figureId]) {
67350
- const chart = this.getters.getChart(figureId);
67951
+ getChartRuntime(chartId) {
67952
+ if (!this.charts[chartId]) {
67953
+ const chart = this.getters.getChart(chartId);
67351
67954
  if (!chart) {
67352
- throw new Error(`No chart for the given id: ${figureId}`);
67955
+ throw new Error(`No chart for the given id: ${chartId}`);
67353
67956
  }
67354
- this.charts[figureId] = this.createRuntimeChart(chart);
67957
+ this.charts[chartId] = this.createRuntimeChart(chart);
67355
67958
  }
67356
- return this.charts[figureId];
67959
+ return this.charts[chartId];
67357
67960
  }
67358
67961
  /**
67359
67962
  * Get the background and textColor of a chart based on the color of the first cell of the main range of the chart.
@@ -67388,8 +67991,14 @@ stores.inject(MyMetaStore, storeInstance);
67388
67991
  if (!figure || figure.tag !== "chart") {
67389
67992
  continue;
67390
67993
  }
67391
- const figureId = figure.id;
67392
- const figureData = this.getters.getChart(figureId)?.getDefinitionForExcel(this.getters);
67994
+ const chartId = this.getters
67995
+ .getChartIds(sheet.id)
67996
+ .find((chartId) => this.getters.getFigureIdFromChartId(chartId) === figure.id);
67997
+ if (!chartId) {
67998
+ continue;
67999
+ }
68000
+ const chart = this.getters.getChart(chartId);
68001
+ const figureData = chart?.getDefinitionForExcel(this.getters);
67393
68002
  if (figureData) {
67394
68003
  figures.push({
67395
68004
  ...figure,
@@ -67397,12 +68006,11 @@ stores.inject(MyMetaStore, storeInstance);
67397
68006
  });
67398
68007
  }
67399
68008
  else {
67400
- const chart = this.getters.getChart(figureId);
67401
68009
  if (!chart) {
67402
68010
  continue;
67403
68011
  }
67404
- const type = this.getters.getChartType(figureId);
67405
- const runtime = this.getters.getChartRuntime(figureId);
68012
+ const type = this.getters.getChartType(chartId);
68013
+ const runtime = this.getters.getChartRuntime(chartId);
67406
68014
  const img = chartToImageUrl(runtime, figure, type);
67407
68015
  if (img) {
67408
68016
  sheet.images.push({
@@ -70536,7 +71144,9 @@ stores.inject(MyMetaStore, storeInstance);
70536
71144
  otRegistry.addTransformation("ADD_COLUMNS_ROWS", ["ADD_COLUMNS_ROWS"], addHeadersTransformation);
70537
71145
  otRegistry.addTransformation("REMOVE_COLUMNS_ROWS", ["ADD_COLUMNS_ROWS"], addHeadersTransformation);
70538
71146
  otRegistry.addTransformation("DELETE_SHEET", ["MOVE_RANGES"], transformTargetSheetId);
70539
- otRegistry.addTransformation("DELETE_FIGURE", ["UPDATE_FIGURE", "UPDATE_CHART"], updateChartFigure);
71147
+ otRegistry.addTransformation("DELETE_FIGURE", ["UPDATE_FIGURE", "UPDATE_CHART", "UPDATE_CAROUSEL"], updateChartFigure);
71148
+ otRegistry.addTransformation("DELETE_CHART", ["UPDATE_CHART"], updateChartOnChartDelete);
71149
+ otRegistry.addTransformation("DELETE_CHART", ["UPDATE_CAROUSEL"], updateCarouselOnChartDelete);
70540
71150
  otRegistry.addTransformation("CREATE_SHEET", ["CREATE_SHEET"], createSheetTransformation);
70541
71151
  otRegistry.addTransformation("ADD_MERGE", ["ADD_MERGE", "REMOVE_MERGE"], mergeTransformation);
70542
71152
  otRegistry.addTransformation("ADD_COLUMNS_ROWS", ["FREEZE_COLUMNS", "FREEZE_ROWS"], freezeTransformation);
@@ -70589,6 +71199,21 @@ stores.inject(MyMetaStore, storeInstance);
70589
71199
  }
70590
71200
  return toTransform;
70591
71201
  }
71202
+ function updateChartOnChartDelete(toTransform, executed) {
71203
+ if (toTransform.chartId === executed.chartId) {
71204
+ return undefined;
71205
+ }
71206
+ return toTransform;
71207
+ }
71208
+ function updateCarouselOnChartDelete(toTransform, executed) {
71209
+ return {
71210
+ ...toTransform,
71211
+ definition: {
71212
+ ...toTransform.definition,
71213
+ items: toTransform.definition.items.filter((item) => !(item.type === "chart" && item.chartId === executed.chartId)),
71214
+ },
71215
+ };
71216
+ }
70592
71217
  function createSheetTransformation(toTransform, executed) {
70593
71218
  if (toTransform.sheetId === executed.sheetId) {
70594
71219
  toTransform = { ...toTransform, sheetId: `${toTransform.sheetId}~` };
@@ -72983,9 +73608,11 @@ stores.inject(MyMetaStore, storeInstance);
72983
73608
 
72984
73609
  const uuidGenerator = new UuidGenerator();
72985
73610
  function repeatCreateChartCommand(getters, cmd) {
73611
+ const id = uuidGenerator.smallUuid();
72986
73612
  return {
72987
73613
  ...repeatSheetDependantCommand(getters, cmd),
72988
- figureId: uuidGenerator.smallUuid(),
73614
+ figureId: id,
73615
+ chartId: id,
72989
73616
  };
72990
73617
  }
72991
73618
  function repeatCreateImageCommand(getters, cmd) {
@@ -76195,6 +76822,123 @@ stores.inject(MyMetaStore, storeInstance);
76195
76822
  }
76196
76823
  }
76197
76824
 
76825
+ class CarouselUIPlugin extends UIPlugin {
76826
+ static getters = [
76827
+ "getSelectedCarouselItem",
76828
+ "getChartFromFigureId",
76829
+ "getChartIdFromFigureId",
76830
+ ];
76831
+ uuidGenerator = new UuidGenerator();
76832
+ carouselStates = {};
76833
+ handle(cmd) {
76834
+ switch (cmd.type) {
76835
+ case "ADD_NEW_CHART_TO_CAROUSEL":
76836
+ this.addNewChartToCarousel(cmd.figureId, cmd.sheetId);
76837
+ break;
76838
+ case "ADD_FIGURE_CHART_TO_CAROUSEL":
76839
+ this.addFigureChartToCarousel(cmd.carouselFigureId, cmd.chartFigureId, cmd.sheetId);
76840
+ break;
76841
+ case "UPDATE_CAROUSEL_ACTIVE_ITEM":
76842
+ this.carouselStates[cmd.figureId] = cmd.item;
76843
+ break;
76844
+ case "DELETE_FIGURE":
76845
+ delete this.carouselStates[cmd.figureId];
76846
+ break;
76847
+ case "UPDATE_CAROUSEL":
76848
+ this.fixWrongCarouselState(cmd.figureId);
76849
+ break;
76850
+ case "DELETE_CHART":
76851
+ case "UNDO":
76852
+ case "REDO":
76853
+ case "DELETE_SHEET":
76854
+ for (const figureId in this.carouselStates) {
76855
+ this.fixWrongCarouselState(figureId);
76856
+ }
76857
+ break;
76858
+ }
76859
+ }
76860
+ getSelectedCarouselItem(figureId) {
76861
+ const carousel = this.getters.getCarousel(figureId);
76862
+ if (!carousel.items.length) {
76863
+ return undefined;
76864
+ }
76865
+ return this.carouselStates[figureId] ? this.carouselStates[figureId] : carousel.items[0];
76866
+ }
76867
+ getChartFromFigureId(figureId) {
76868
+ const sheetId = this.getters.getFigureSheetId(figureId);
76869
+ if (!sheetId) {
76870
+ return undefined;
76871
+ }
76872
+ const chartId = this.getChartIdFromFigureId(figureId);
76873
+ return chartId ? this.getters.getChart(chartId) : undefined;
76874
+ }
76875
+ getChartIdFromFigureId(figureId) {
76876
+ const sheetId = this.getters.getFigureSheetId(figureId);
76877
+ if (!sheetId) {
76878
+ return undefined;
76879
+ }
76880
+ const figure = this.getters.getFigure(sheetId, figureId);
76881
+ if (!figure || (figure.tag !== "chart" && figure.tag !== "carousel")) {
76882
+ return undefined;
76883
+ }
76884
+ if (figure.tag === "carousel") {
76885
+ const carouselItem = this.getSelectedCarouselItem(figureId);
76886
+ return carouselItem?.type === "chart" ? carouselItem.chartId : undefined;
76887
+ }
76888
+ return this.getters
76889
+ .getChartIds(sheetId)
76890
+ .find((chartId) => this.getters.getFigureIdFromChartId(chartId) === figureId);
76891
+ }
76892
+ fixWrongCarouselState(figureId) {
76893
+ if (!this.getters.doesCarouselExist(figureId)) {
76894
+ delete this.carouselStates[figureId];
76895
+ return;
76896
+ }
76897
+ const carousel = this.getters.getCarousel(figureId);
76898
+ if (!carousel) {
76899
+ delete this.carouselStates[figureId];
76900
+ return;
76901
+ }
76902
+ if (!this.carouselStates[figureId]) {
76903
+ this.carouselStates[figureId] = carousel.items[0];
76904
+ }
76905
+ else if (carousel.items.length === 0) {
76906
+ delete this.carouselStates[figureId];
76907
+ }
76908
+ else if (!carousel.items.some((item) => deepEquals(item, this.carouselStates[figureId]))) {
76909
+ this.carouselStates[figureId] = carousel.items[0];
76910
+ }
76911
+ }
76912
+ addNewChartToCarousel(figureId, sheetId) {
76913
+ const carousel = this.getters.getCarousel(figureId);
76914
+ const chartId = this.uuidGenerator.smallUuid();
76915
+ this.dispatch("CREATE_CHART", {
76916
+ chartId,
76917
+ figureId,
76918
+ sheetId,
76919
+ definition: CAROUSEL_DEFAULT_CHART_DEFINITION,
76920
+ });
76921
+ const definition = { items: [...carousel.items, { type: "chart", chartId }] };
76922
+ this.dispatch("UPDATE_CAROUSEL", { sheetId, figureId, definition });
76923
+ }
76924
+ addFigureChartToCarousel(figureId, chartFigureId, sheetId) {
76925
+ const chartId = this.getChartIdFromFigureId(chartFigureId);
76926
+ if (!chartId) {
76927
+ return;
76928
+ }
76929
+ const carousel = this.getters.getCarousel(figureId);
76930
+ const definition = { items: [...carousel.items, { type: "chart", chartId }] };
76931
+ this.dispatch("UPDATE_CAROUSEL", { sheetId, figureId, definition });
76932
+ this.dispatch("UPDATE_CHART", {
76933
+ sheetId,
76934
+ chartId,
76935
+ figureId,
76936
+ definition: this.getters.getChartDefinition(chartId),
76937
+ });
76938
+ this.dispatch("DELETE_FIGURE", { sheetId, figureId: chartFigureId });
76939
+ }
76940
+ }
76941
+
76198
76942
  class HeaderPositionsUIPlugin extends UIPlugin {
76199
76943
  static getters = ["getColDimensions", "getRowDimensions", "getColRowOffset"];
76200
76944
  headerPositions = {};
@@ -76326,6 +77070,7 @@ stores.inject(MyMetaStore, storeInstance);
76326
77070
  .add("conditional formatting", ConditionalFormatPlugin)
76327
77071
  .add("figures", FigurePlugin)
76328
77072
  .add("chart", ChartPlugin)
77073
+ .add("carousel", CarouselPlugin)
76329
77074
  .add("image", ImagePlugin)
76330
77075
  .add("pivot_core", PivotCorePlugin)
76331
77076
  .add("spreadsheet_pivot_core", SpreadsheetPivotCorePlugin)
@@ -76358,7 +77103,8 @@ stores.inject(MyMetaStore, storeInstance);
76358
77103
  .add("table_computed_style", TableComputedStylePlugin)
76359
77104
  .add("header_positions", HeaderPositionsUIPlugin)
76360
77105
  .add("viewport", SheetViewPlugin)
76361
- .add("clipboard", ClipboardPlugin);
77106
+ .add("clipboard", ClipboardPlugin)
77107
+ .add("carousel_ui", CarouselUIPlugin);
76362
77108
  // Plugins which have a derived state from core data
76363
77109
  const coreViewsPluginRegistry = new Registry()
76364
77110
  .add("evaluation", EvaluationPlugin)
@@ -77311,6 +78057,10 @@ stores.inject(MyMetaStore, storeInstance);
77311
78057
  .addChild("insert_chart", ["insert"], {
77312
78058
  ...insertChart,
77313
78059
  sequence: 50,
78060
+ })
78061
+ .addChild("insert_carousel", ["insert"], {
78062
+ ...insertCarousel,
78063
+ sequence: 51,
77314
78064
  })
77315
78065
  .addChild("insert_pivot", ["insert"], {
77316
78066
  ...insertPivot,
@@ -83693,7 +84443,7 @@ stores.inject(MyMetaStore, storeInstance);
83693
84443
  ];
83694
84444
  }
83695
84445
 
83696
- function createDrawing(drawingRelIds, sheet, figures) {
84446
+ function createDrawing(drawingRelIds, sheet, figures, construct) {
83697
84447
  const namespaces = [
83698
84448
  ["xmlns:xdr", NAMESPACE.drawing],
83699
84449
  ["xmlns:r", RELATIONSHIP_NSR],
@@ -83704,7 +84454,7 @@ stores.inject(MyMetaStore, storeInstance);
83704
84454
  for (const [figureIndex, figure] of Object.entries(figures)) {
83705
84455
  switch (figure?.tag) {
83706
84456
  case "chart":
83707
- figuresNodes.push(createChartDrawing(figure, sheet, drawingRelIds[figureIndex]));
84457
+ figuresNodes.push(createChartDrawing(figure, sheet, drawingRelIds[figureIndex], construct));
83708
84458
  break;
83709
84459
  case "image":
83710
84460
  figuresNodes.push(createImageDrawing(figure, sheet, drawingRelIds[figureIndex]));
@@ -83766,10 +84516,10 @@ stores.inject(MyMetaStore, storeInstance);
83766
84516
  offset: convertDotValueToEMU(offset - currentPosition + FIGURE_BORDER_WIDTH),
83767
84517
  };
83768
84518
  }
83769
- function createChartDrawing(figure, sheet, chartRelId) {
84519
+ function createChartDrawing(figure, sheet, chartRelId, construct) {
83770
84520
  // position
83771
84521
  const { from, to } = convertFigureData(figure, sheet);
83772
- const chartId = convertChartId(figure.id);
84522
+ const chartId = convertChartId(figure.id, construct);
83773
84523
  const cNvPrAttrs = [
83774
84524
  ["id", chartId],
83775
84525
  ["name", `Chart ${chartId}`],
@@ -84432,7 +85182,7 @@ stores.inject(MyMetaStore, storeInstance);
84432
85182
  let drawingNode = escapeXml ``;
84433
85183
  const drawingRelIds = [];
84434
85184
  for (const chart of sheet.charts) {
84435
- const xlsxChartId = convertChartId(chart.id);
85185
+ const xlsxChartId = convertChartId(chart.id, construct);
84436
85186
  const chartRelId = addRelsToFile(construct.relsFiles, `xl/drawings/_rels/drawing${sheetIndex}.xml.rels`, {
84437
85187
  target: `../charts/chart${xlsxChartId}.xml`,
84438
85188
  type: XLSX_RELATION_TYPE.chart,
@@ -84466,7 +85216,7 @@ stores.inject(MyMetaStore, storeInstance);
84466
85216
  target: `../drawings/drawing${sheetIndex}.xml`,
84467
85217
  type: XLSX_RELATION_TYPE.drawing,
84468
85218
  });
84469
- files.push(createXMLFile(createDrawing(drawingRelIds, sheet, drawings), `xl/drawings/drawing${sheetIndex}.xml`, "drawing"));
85219
+ files.push(createXMLFile(createDrawing(drawingRelIds, sheet, drawings, construct), `xl/drawings/drawing${sheetIndex}.xml`, "drawing"));
84470
85220
  drawingNode = escapeXml /*xml*/ `<drawing r:id="${drawingRelId}" />`;
84471
85221
  }
84472
85222
  const sheetXml = escapeXml /*xml*/ `
@@ -85449,6 +86199,7 @@ stores.inject(MyMetaStore, storeInstance);
85449
86199
  HIGHLIGHT_COLOR,
85450
86200
  PIVOT_TABLE_CONFIG,
85451
86201
  ChartTerms,
86202
+ FIGURE_ID_SPLITTER,
85452
86203
  };
85453
86204
  const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
85454
86205
 
@@ -85503,9 +86254,9 @@ stores.inject(MyMetaStore, storeInstance);
85503
86254
  exports.tokenize = tokenize;
85504
86255
 
85505
86256
 
85506
- __info__.version = "18.5.0-alpha.6";
85507
- __info__.date = "2025-08-05T06:27:49.505Z";
85508
- __info__.hash = "67e091f";
86257
+ __info__.version = "18.5.0-alpha.7";
86258
+ __info__.date = "2025-08-08T11:00:44.117Z";
86259
+ __info__.hash = "1019d55";
85509
86260
 
85510
86261
 
85511
86262
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);