@odoo/o-spreadsheet 16.3.0 → 16.3.2

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.
@@ -16869,6 +16869,7 @@ const unFreezePane = {
16869
16869
  execute: (env) => env.model.dispatch("UNFREEZE_COLUMNS_ROWS", {
16870
16870
  sheetId: env.model.getters.getActiveSheetId(),
16871
16871
  }),
16872
+ icon: "o-spreadsheet-Icon.UNFREEZE",
16872
16873
  };
16873
16874
  const freezePane = {
16874
16875
  name: _lt("Freeze"),
@@ -17839,7 +17840,7 @@ class LineBarPieConfigPanel extends Component {
17839
17840
  return !!this.state.labelsDispatchResult?.isCancelledBecause(33 /* CommandResult.InvalidLabelRange */);
17840
17841
  }
17841
17842
  onUpdateDataSetsHaveTitle(ev) {
17842
- this.props.updateChart({
17843
+ this.props.updateChart(this.props.figureId, {
17843
17844
  dataSetsHaveTitle: ev.target.checked,
17844
17845
  });
17845
17846
  }
@@ -17851,7 +17852,7 @@ class LineBarPieConfigPanel extends Component {
17851
17852
  this.dataSeriesRanges = ranges;
17852
17853
  }
17853
17854
  onDataSeriesConfirmed() {
17854
- this.state.datasetDispatchResult = this.props.updateChart({
17855
+ this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
17855
17856
  dataSets: this.dataSeriesRanges,
17856
17857
  });
17857
17858
  }
@@ -17863,12 +17864,12 @@ class LineBarPieConfigPanel extends Component {
17863
17864
  this.labelRange = ranges[0];
17864
17865
  }
17865
17866
  onLabelRangeConfirmed() {
17866
- this.state.labelsDispatchResult = this.props.updateChart({
17867
+ this.state.labelsDispatchResult = this.props.updateChart(this.props.figureId, {
17867
17868
  labelRange: this.labelRange,
17868
17869
  });
17869
17870
  }
17870
17871
  onUpdateAggregated(ev) {
17871
- this.props.updateChart({
17872
+ this.props.updateChart(this.props.figureId, {
17872
17873
  aggregated: ev.target.checked,
17873
17874
  });
17874
17875
  }
@@ -17898,12 +17899,12 @@ LineBarPieConfigPanel.props = {
17898
17899
  class BarConfigPanel extends LineBarPieConfigPanel {
17899
17900
  static template = "o-spreadsheet-BarConfigPanel";
17900
17901
  onUpdateStacked(ev) {
17901
- this.props.updateChart({
17902
+ this.props.updateChart(this.props.figureId, {
17902
17903
  stacked: ev.target.checked,
17903
17904
  });
17904
17905
  }
17905
17906
  onUpdateAggregated(ev) {
17906
- this.props.updateChart({
17907
+ this.props.updateChart(this.props.figureId, {
17907
17908
  aggregated: ev.target.checked,
17908
17909
  });
17909
17910
  }
@@ -17940,6 +17941,18 @@ css /* scss */ `
17940
17941
  grid-template-columns: repeat(${ITEMS_PER_LINE}, 1fr);
17941
17942
  grid-gap: ${ITEM_HORIZONTAL_MARGIN * 2}px;
17942
17943
  }
17944
+ .o-color-picker-toggler-button {
17945
+ display: flex;
17946
+ .o-color-picker-toggler-sign {
17947
+ margin: auto auto;
17948
+ width: 55%;
17949
+ height: 55%;
17950
+ .o-icon {
17951
+ width: 100%;
17952
+ height: 100%;
17953
+ }
17954
+ }
17955
+ }
17943
17956
  .o-color-picker-line-item {
17944
17957
  width: ${ITEM_EDGE_LENGTH}px;
17945
17958
  height: ${ITEM_EDGE_LENGTH}px;
@@ -18228,17 +18241,17 @@ class LineBarPieDesignPanel extends Component {
18228
18241
  this.state.fillColorTool = !this.state.fillColorTool;
18229
18242
  }
18230
18243
  updateBackgroundColor(color) {
18231
- this.props.updateChart({
18244
+ this.props.updateChart(this.props.figureId, {
18232
18245
  background: color,
18233
18246
  });
18234
18247
  }
18235
18248
  updateTitle(ev) {
18236
- this.props.updateChart({
18249
+ this.props.updateChart(this.props.figureId, {
18237
18250
  title: ev.target.value,
18238
18251
  });
18239
18252
  }
18240
18253
  updateSelect(attr, ev) {
18241
- this.props.updateChart({
18254
+ this.props.updateChart(this.props.figureId, {
18242
18255
  [attr]: ev.target.value,
18243
18256
  });
18244
18257
  }
@@ -18271,7 +18284,7 @@ class GaugeChartConfigPanel extends Component {
18271
18284
  this.dataRange = ranges[0];
18272
18285
  }
18273
18286
  updateDataRange() {
18274
- this.state.dataRangeDispatchResult = this.props.updateChart({
18287
+ this.state.dataRangeDispatchResult = this.props.updateChart(this.props.figureId, {
18275
18288
  dataRange: this.dataRange,
18276
18289
  });
18277
18290
  }
@@ -18329,12 +18342,12 @@ class GaugeChartDesignPanel extends Component {
18329
18342
  }
18330
18343
  updateBackgroundColor(color) {
18331
18344
  this.state.openedMenu = undefined;
18332
- this.props.updateChart({
18345
+ this.props.updateChart(this.props.figureId, {
18333
18346
  background: color,
18334
18347
  });
18335
18348
  }
18336
18349
  updateTitle(ev) {
18337
- this.props.updateChart({
18350
+ this.props.updateChart(this.props.figureId, {
18338
18351
  title: ev.target.value,
18339
18352
  });
18340
18353
  }
@@ -18399,7 +18412,7 @@ class GaugeChartDesignPanel extends Component {
18399
18412
  }
18400
18413
  }
18401
18414
  updateSectionRule(sectionRule) {
18402
- this.state.sectionRuleDispatchResult = this.props.updateChart({
18415
+ this.state.sectionRuleDispatchResult = this.props.updateChart(this.props.figureId, {
18403
18416
  sectionRule,
18404
18417
  });
18405
18418
  }
@@ -18423,17 +18436,17 @@ class LineConfigPanel extends LineBarPieConfigPanel {
18423
18436
  return false;
18424
18437
  }
18425
18438
  onUpdateLabelsAsText(ev) {
18426
- this.props.updateChart({
18439
+ this.props.updateChart(this.props.figureId, {
18427
18440
  labelsAsText: ev.target.checked,
18428
18441
  });
18429
18442
  }
18430
18443
  onUpdateStacked(ev) {
18431
- this.props.updateChart({
18444
+ this.props.updateChart(this.props.figureId, {
18432
18445
  stacked: ev.target.checked,
18433
18446
  });
18434
18447
  }
18435
18448
  onUpdateAggregated(ev) {
18436
- this.props.updateChart({
18449
+ this.props.updateChart(this.props.figureId, {
18437
18450
  aggregated: ev.target.checked,
18438
18451
  });
18439
18452
  }
@@ -18469,7 +18482,7 @@ class ScorecardChartConfigPanel extends Component {
18469
18482
  this.keyValue = ranges[0];
18470
18483
  }
18471
18484
  updateKeyValueRange() {
18472
- this.state.keyValueDispatchResult = this.props.updateChart({
18485
+ this.state.keyValueDispatchResult = this.props.updateChart(this.props.figureId, {
18473
18486
  keyValue: this.keyValue,
18474
18487
  });
18475
18488
  }
@@ -18477,12 +18490,12 @@ class ScorecardChartConfigPanel extends Component {
18477
18490
  this.baseline = ranges[0];
18478
18491
  }
18479
18492
  updateBaselineRange() {
18480
- this.state.baselineDispatchResult = this.props.updateChart({
18493
+ this.state.baselineDispatchResult = this.props.updateChart(this.props.figureId, {
18481
18494
  baseline: this.baseline,
18482
18495
  });
18483
18496
  }
18484
18497
  updateBaselineMode(ev) {
18485
- this.props.updateChart({ baselineMode: ev.target.value });
18498
+ this.props.updateChart(this.props.figureId, { baselineMode: ev.target.value });
18486
18499
  }
18487
18500
  }
18488
18501
  ScorecardChartConfigPanel.props = {
@@ -18501,12 +18514,12 @@ class ScorecardChartDesignPanel extends Component {
18501
18514
  useExternalListener(window, "click", this.closeMenus);
18502
18515
  }
18503
18516
  updateTitle(ev) {
18504
- this.props.updateChart({
18517
+ this.props.updateChart(this.props.figureId, {
18505
18518
  title: ev.target.value,
18506
18519
  });
18507
18520
  }
18508
18521
  updateBaselineDescr(ev) {
18509
- this.props.updateChart({ baselineDescr: ev.target.value });
18522
+ this.props.updateChart(this.props.figureId, { baselineDescr: ev.target.value });
18510
18523
  }
18511
18524
  toggleColorPicker(colorPickerId) {
18512
18525
  if (this.state.openedColorPicker === colorPickerId) {
@@ -18519,13 +18532,13 @@ class ScorecardChartDesignPanel extends Component {
18519
18532
  setColor(color, colorPickerId) {
18520
18533
  switch (colorPickerId) {
18521
18534
  case "backgroundColor":
18522
- this.props.updateChart({ background: color });
18535
+ this.props.updateChart(this.props.figureId, { background: color });
18523
18536
  break;
18524
18537
  case "baselineColorDown":
18525
- this.props.updateChart({ baselineColorDown: color });
18538
+ this.props.updateChart(this.props.figureId, { baselineColorDown: color });
18526
18539
  break;
18527
18540
  case "baselineColorUp":
18528
- this.props.updateChart({ baselineColorUp: color });
18541
+ this.props.updateChart(this.props.figureId, { baselineColorUp: color });
18529
18542
  break;
18530
18543
  }
18531
18544
  this.closeMenus();
@@ -18590,13 +18603,9 @@ css /* scss */ `
18590
18603
  class ChartPanel extends Component {
18591
18604
  static template = "o-spreadsheet-ChartPanel";
18592
18605
  state;
18593
- shouldUpdateChart = true;
18594
18606
  get figureId() {
18595
18607
  return this.state.figureId;
18596
18608
  }
18597
- get sheetId() {
18598
- return this.state.sheetId;
18599
- }
18600
18609
  setup() {
18601
18610
  const selectedFigureId = this.env.model.getters.getSelectedFigureId();
18602
18611
  if (!selectedFigureId) {
@@ -18606,17 +18615,11 @@ class ChartPanel extends Component {
18606
18615
  this.state = useState({
18607
18616
  panel: "configuration",
18608
18617
  figureId: selectedFigureId,
18609
- sheetId: this.env.model.getters.getActiveSheetId(),
18610
18618
  });
18611
18619
  onWillUpdateProps(() => {
18612
18620
  const selectedFigureId = this.env.model.getters.getSelectedFigureId();
18613
18621
  if (selectedFigureId && selectedFigureId !== this.state.figureId) {
18614
18622
  this.state.figureId = selectedFigureId;
18615
- this.state.sheetId = this.env.model.getters.getActiveSheetId();
18616
- this.shouldUpdateChart = false;
18617
- }
18618
- else {
18619
- this.shouldUpdateChart = true;
18620
18623
  }
18621
18624
  if (!this.env.model.getters.isChartDefined(this.figureId)) {
18622
18625
  this.props.onCloseSidePanel();
@@ -18624,8 +18627,8 @@ class ChartPanel extends Component {
18624
18627
  }
18625
18628
  });
18626
18629
  }
18627
- updateChart(updateDefinition) {
18628
- if (!this.shouldUpdateChart) {
18630
+ updateChart(figureId, updateDefinition) {
18631
+ if (figureId !== this.figureId) {
18629
18632
  return;
18630
18633
  }
18631
18634
  const definition = {
@@ -18634,8 +18637,8 @@ class ChartPanel extends Component {
18634
18637
  };
18635
18638
  return this.env.model.dispatch("UPDATE_CHART", {
18636
18639
  definition,
18637
- id: this.figureId,
18638
- sheetId: this.sheetId,
18640
+ id: figureId,
18641
+ sheetId: this.env.model.getters.getFigureSheetId(figureId),
18639
18642
  });
18640
18643
  }
18641
18644
  onTypeChange(type) {
@@ -18647,7 +18650,7 @@ class ChartPanel extends Component {
18647
18650
  this.env.model.dispatch("UPDATE_CHART", {
18648
18651
  definition,
18649
18652
  id: this.figureId,
18650
- sheetId: this.sheetId,
18653
+ sheetId: this.env.model.getters.getFigureSheetId(this.figureId),
18651
18654
  });
18652
18655
  }
18653
18656
  get chartPanel() {
@@ -20612,7 +20615,14 @@ class ContentEditableHelper {
20612
20615
  current = it.next();
20613
20616
  }
20614
20617
  if (current.value !== nodeToFind) {
20615
- throw new Error("Cannot find the node in the children of the element");
20618
+ /** This situation can happen if the code is called while the selection is not currently on the ContentEditableHelper.
20619
+ * In this case, we return 0 because we don't know the size of the text before the selection.
20620
+ *
20621
+ * A known occurence is triggered since the introduction of commit d4663158 (PR #2038).
20622
+ *
20623
+ * FIXME: find a way to test eventhough the selection API is not available in jsDOM.
20624
+ */
20625
+ return 0;
20616
20626
  }
20617
20627
  else {
20618
20628
  if (!current.value.hasChildNodes()) {
@@ -24461,6 +24471,16 @@ const XLSX_INDEXED_COLORS = {
24461
24471
  63: "333333",
24462
24472
  64: "000000",
24463
24473
  65: "FFFFFF", // system background
24474
+ };
24475
+ const IMAGE_MIMETYPE_EXTENSION_MAPPING = {
24476
+ "image/avif": "avif",
24477
+ "image/bmp": "bmp",
24478
+ "image/gif": "gif",
24479
+ "image/vnd.microsoft.icon": "ico",
24480
+ "image/jpeg": "jpeg",
24481
+ "image/png": "png",
24482
+ "image/tiff": "tiff",
24483
+ "image/webp": "webp",
24464
24484
  };
24465
24485
 
24466
24486
  /**
@@ -26942,6 +26962,11 @@ function createOverride(partName, contentType) {
26942
26962
  <Override ContentType="${contentType}" PartName="${partName}" />
26943
26963
  `;
26944
26964
  }
26965
+ function createDefaultXMLElement(extension, contentType) {
26966
+ return escapeXml /*xml*/ `
26967
+ <Default Extension="${extension}" ContentType="${contentType}" />
26968
+ `;
26969
+ }
26945
26970
  function joinXmlNodes(xmlNodes) {
26946
26971
  return new XMLString(xmlNodes.join("\n"));
26947
26972
  }
@@ -38664,7 +38689,8 @@ class SheetUIPlugin extends UIPlugin {
38664
38689
  getCellWidth(position) {
38665
38690
  const text = this.getCellText(position);
38666
38691
  const style = this.getters.getCellComputedStyle(position);
38667
- let contentWidth = this.getTextWidth(text, style);
38692
+ const multiLineText = text.split(NEWLINE);
38693
+ let contentWidth = Math.max(...multiLineText.map((line) => this.getTextWidth(line, style)));
38668
38694
  const icon = this.getters.getConditionalIcon(position);
38669
38695
  if (icon) {
38670
38696
  contentWidth += computeIconWidth(this.getters.getCellStyle(position));
@@ -41708,7 +41734,7 @@ class ImageProvider {
41708
41734
  const file = await this.getImageFromUser();
41709
41735
  const path = await this.fileStore.upload(file);
41710
41736
  const size = await this.getImageSize(path);
41711
- return { path, size };
41737
+ return { path, size, mimetype: file.type };
41712
41738
  }
41713
41739
  getImageFromUser() {
41714
41740
  return new Promise((resolve, reject) => {
@@ -43793,6 +43819,10 @@ class Spreadsheet extends Component {
43793
43819
  }
43794
43820
  checkViewportSize() {
43795
43821
  const { xRatio, yRatio } = this.env.model.getters.getFrozenSheetViewRatio(this.env.model.getters.getActiveSheetId());
43822
+ if (!isFinite(xRatio) || !isFinite(yRatio)) {
43823
+ // before mounting, the ratios can be NaN or Infinity if the viewport size is 0
43824
+ return;
43825
+ }
43796
43826
  if (yRatio > MAXIMAL_FREEZABLE_RATIO || xRatio > MAXIMAL_FREEZABLE_RATIO) {
43797
43827
  if (this.isViewportTooSmall) {
43798
43828
  return;
@@ -46785,8 +46815,7 @@ function createWorksheets(data, construct) {
46785
46815
  // Figures and Charts
46786
46816
  let drawingNode = escapeXml ``;
46787
46817
  const drawingRelIds = [];
46788
- const charts = sheet.charts;
46789
- for (const chart of charts) {
46818
+ for (const chart of sheet.charts) {
46790
46819
  const xlsxChartId = convertChartId(chart.id);
46791
46820
  const chartRelId = addRelsToFile(construct.relsFiles, `xl/drawings/_rels/drawing${sheetIndex}.xml.rels`, {
46792
46821
  target: `../charts/chart${xlsxChartId}.xml`,
@@ -46795,20 +46824,27 @@ function createWorksheets(data, construct) {
46795
46824
  drawingRelIds.push(chartRelId);
46796
46825
  files.push(createXMLFile(createChart(chart, sheetIndex, data), `xl/charts/chart${xlsxChartId}.xml`, "chart"));
46797
46826
  }
46798
- const images = sheet.images;
46799
- for (const image of images) {
46827
+ for (const image of sheet.images) {
46828
+ const mimeType = image.data.mimetype;
46829
+ if (mimeType === undefined)
46830
+ continue;
46831
+ const extension = IMAGE_MIMETYPE_EXTENSION_MAPPING[mimeType];
46832
+ // only support exporting images with mimetypes specified in the mapping
46833
+ if (extension === undefined)
46834
+ continue;
46800
46835
  const xlsxImageId = convertImageId(image.id);
46836
+ let imageFileName = `image${xlsxImageId}.${extension}`;
46801
46837
  const imageRelId = addRelsToFile(construct.relsFiles, `xl/drawings/_rels/drawing${sheetIndex}.xml.rels`, {
46802
- target: `../media/image${xlsxImageId}`,
46838
+ target: `../media/${imageFileName}`,
46803
46839
  type: XLSX_RELATION_TYPE.image,
46804
46840
  });
46805
46841
  drawingRelIds.push(imageRelId);
46806
46842
  files.push({
46807
- path: `xl/media/image${xlsxImageId}`,
46808
- imagePath: image.data.path,
46843
+ path: `xl/media/${imageFileName}`,
46844
+ imageSrc: image.data.path,
46809
46845
  });
46810
46846
  }
46811
- const drawings = [...charts, ...images];
46847
+ const drawings = [...sheet.charts, ...sheet.images];
46812
46848
  if (drawings.length) {
46813
46849
  const drawingRelId = addRelsToFile(construct.relsFiles, `xl/worksheets/_rels/sheet${sheetIndex}.xml.rels`, {
46814
46850
  target: `../drawings/drawing${sheetIndex}.xml`,
@@ -46927,6 +46963,8 @@ function createRelsFiles(relsFiles) {
46927
46963
  }
46928
46964
  function createContentTypes(files) {
46929
46965
  const overrideNodes = [];
46966
+ // hard-code supported image mimetypes
46967
+ const imageDefaultNodes = Object.entries(IMAGE_MIMETYPE_EXTENSION_MAPPING).map(([mimetype, extension]) => createDefaultXMLElement(extension, mimetype));
46930
46968
  for (const file of files) {
46931
46969
  if ("contentType" in file && file.contentType) {
46932
46970
  overrideNodes.push(createOverride("/" + file.path, CONTENT_TYPES[file.contentType]));
@@ -46942,6 +46980,7 @@ function createContentTypes(files) {
46942
46980
  ];
46943
46981
  const xml = escapeXml /*xml*/ `
46944
46982
  <Types xmlns="${NAMESPACE["Types"]}">
46983
+ ${joinXmlNodes(Object.values(imageDefaultNodes))}
46945
46984
  <Default ${formatAttributes(relsAttributes)} />
46946
46985
  <Default ${formatAttributes(xmlAttributes)} />
46947
46986
  ${joinXmlNodes(overrideNodes)}
@@ -47526,6 +47565,6 @@ function addFunction(functionName, functionDescription) {
47526
47565
  export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
47527
47566
 
47528
47567
 
47529
- __info__.version = '16.3.0';
47530
- __info__.date = '2023-05-17T14:44:57.860Z';
47531
- __info__.hash = '33b37e4';
47568
+ __info__.version = '16.3.2';
47569
+ __info__.date = '2023-06-02T10:13:46.734Z';
47570
+ __info__.hash = '69a4378';