@odoo/o-spreadsheet 18.5.0-alpha.0 → 18.5.0-alpha.10

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.
@@ -1,9 +1,9 @@
1
1
  <!--
2
2
  This file is generated by o-spreadsheet build tools. Do not edit it.
3
3
  @see https://github.com/odoo/o-spreadsheet
4
- @version 18.5.0-alpha.0
5
- @date 2025-06-24T12:27:25.939Z
6
- @hash ed0f325
4
+ @version 18.5.0-alpha.10
5
+ @date 2025-08-21T06:43:00.829Z
6
+ @hash 5800d1b
7
7
  -->
8
8
  <odoo>
9
9
  <t t-name="o-spreadsheet-ValidationMessages">
@@ -215,7 +215,7 @@
215
215
  t-ref="input"
216
216
  class="os-input w-100"
217
217
  type="text"
218
- t-att-class="props.class"
218
+ t-att-class="inputClass"
219
219
  t-att-id="props.id"
220
220
  t-att-placeholder="props.placeholder"
221
221
  t-att-value="props.value"
@@ -981,6 +981,15 @@
981
981
  t-att-style="dragAndDrop.itemsStyle[col.nameWithGranularity]"
982
982
  class="pt-1">
983
983
  <PivotDimension dimension="col" onRemoved.bind="removeDimension">
984
+ <t t-set-slot="upper-right-icons">
985
+ <t t-set="errorMessage" t-value="getHugeDimensionErrorMessage(col)"/>
986
+ <i
987
+ t-if="errorMessage"
988
+ class="text-warning fa fa-exclamation-triangle"
989
+ t-att-title="errorMessage"
990
+ />
991
+ </t>
992
+
984
993
  <PivotDimensionGranularity
985
994
  t-if="isDateOrDatetimeField(col)"
986
995
  dimension="col"
@@ -989,6 +998,12 @@
989
998
  allGranularities="getGranularitiesFor(col)"
990
999
  />
991
1000
  <PivotDimensionOrder dimension="col" onUpdated.bind="this.updateOrder"/>
1001
+ <PivotCustomGroupsCollapsible
1002
+ t-if="col.isCustomField"
1003
+ pivotId="props.pivotId"
1004
+ customField="getCustomField(col)"
1005
+ onCustomFieldUpdated="props.onDimensionsUpdated"
1006
+ />
992
1007
  </PivotDimension>
993
1008
  </div>
994
1009
  </t>
@@ -1007,6 +1022,15 @@
1007
1022
  t-att-style="dragAndDrop.itemsStyle[row.nameWithGranularity]"
1008
1023
  class="pt-1">
1009
1024
  <PivotDimension dimension="row" onRemoved.bind="removeDimension">
1025
+ <t t-set-slot="upper-right-icons">
1026
+ <t t-set="errorMessage" t-value="getHugeDimensionErrorMessage(row)"/>
1027
+ <i
1028
+ t-if="errorMessage"
1029
+ class="text-warning fa fa-exclamation-triangle"
1030
+ t-att-title="errorMessage"
1031
+ />
1032
+ </t>
1033
+
1010
1034
  <PivotDimensionGranularity
1011
1035
  t-if="isDateOrDatetimeField(row)"
1012
1036
  dimension="row"
@@ -1015,6 +1039,12 @@
1015
1039
  allGranularities="getGranularitiesFor(row)"
1016
1040
  />
1017
1041
  <PivotDimensionOrder dimension="row" onUpdated.bind="this.updateOrder"/>
1042
+ <PivotCustomGroupsCollapsible
1043
+ t-if="row.isCustomField"
1044
+ pivotId="props.pivotId"
1045
+ customField="getCustomField(row)"
1046
+ onCustomFieldUpdated="props.onDimensionsUpdated"
1047
+ />
1018
1048
  </PivotDimension>
1019
1049
  </div>
1020
1050
  </t>
@@ -1243,6 +1273,42 @@
1243
1273
  </Section>
1244
1274
  </t>
1245
1275
 
1276
+ <t t-name="o-spreadsheet-PivotCustomGroupsCollapsible">
1277
+ <SidePanelCollapsible
1278
+ class="'o-pivot-custom-groups'"
1279
+ isInitiallyCollapsed="true"
1280
+ title.translate="Groups">
1281
+ <t t-set-slot="content">
1282
+ <div class="ps-4">
1283
+ <div
1284
+ t-foreach="groups"
1285
+ t-as="group"
1286
+ t-key="group_index"
1287
+ class="o-pivot-custom-group pb-1">
1288
+ <div
1289
+ class="d-flex align-items-center justify-content-between small"
1290
+ t-on-pointerdown.stop="">
1291
+ <TextInput
1292
+ value="group.name"
1293
+ onChange="(newName) => this.onRenameGroup(group_index, newName)"
1294
+ />
1295
+ <i
1296
+ class="o-button-icon ps-3 fa fa-trash"
1297
+ t-on-click="() => this.onDeleteGroup(group_index)"
1298
+ />
1299
+ </div>
1300
+ </div>
1301
+ <div
1302
+ t-if="!hasOthersGroup"
1303
+ class="o-button-link o-add-others-group small pb-1"
1304
+ t-on-click="() => this.addOthersGroup()">
1305
+ <span>+ &quot;Others&quot; group</span>
1306
+ </div>
1307
+ </div>
1308
+ </t>
1309
+ </SidePanelCollapsible>
1310
+ </t>
1311
+
1246
1312
  <t t-name="o-spreadsheet-MoreFormatsPanel">
1247
1313
  <div class="o-more-formats-panel">
1248
1314
  <div
@@ -1543,11 +1609,11 @@
1543
1609
  <div class="o-dv-list-values p-1 d-flex align-items-center">
1544
1610
  <div class="me-2">
1545
1611
  <RoundColorPicker
1546
- currentColor="props.criterion.colors?.[value] || '#E7E9ED'"
1547
- onColorPicked="(c) => this.onColorChanged(c, value)"
1612
+ currentColor="props.criterion.colors?.[value.value] || '#E7E9ED'"
1613
+ onColorPicked="(c) => this.onColorChanged(c, value.value)"
1548
1614
  />
1549
1615
  </div>
1550
- <input type="text" class="o-input" t-att-value="value" disabled="1"/>
1616
+ <input type="text" class="o-input" t-att-value="value.label" disabled="1"/>
1551
1617
  </div>
1552
1618
  </t>
1553
1619
 
@@ -1688,8 +1754,9 @@
1688
1754
  <t t-if="state.mode === 'edit'">
1689
1755
  <ConditionalFormattingEditor
1690
1756
  editedCf="editedCF"
1691
- onSave.bind="switchToList"
1757
+ onExit.bind="switchToList"
1692
1758
  onCancel.bind="cancelEdition"
1759
+ isNewCf="originalEditedCf === undefined"
1693
1760
  />
1694
1761
  </t>
1695
1762
  </div>
@@ -1912,7 +1979,7 @@
1912
1979
  <div class="o-cf-data-bar-editor">
1913
1980
  <div class="o-section-subtitle">Color</div>
1914
1981
  <RoundColorPicker
1915
- currentColor="colorNumberString(rule.color)"
1982
+ currentColor="colorNumberToHex(rule.color)"
1916
1983
  onColorPicked.bind="updateDataBarColor"
1917
1984
  disableNoColor="true"
1918
1985
  />
@@ -2053,7 +2120,7 @@
2053
2120
  </Section>
2054
2121
  <Section class="'pt-1'">
2055
2122
  <div class="o-sidePanelButtons">
2056
- <button t-on-click="props.onCancel" class="o-button o-cf-cancel">Cancel</button>
2123
+ <button t-on-click="onCancel" class="o-button o-cf-cancel">Cancel</button>
2057
2124
  <button
2058
2125
  t-on-click="onSave"
2059
2126
  class="o-button primary o-cf-save"
@@ -2212,11 +2279,12 @@
2212
2279
 
2213
2280
  <t t-name="o-spreadsheet-SidePanelCollapsible">
2214
2281
  <div class="" t-att-class="props.class">
2215
- <div class="o_side_panel_collapsible_title o-fw-bold d-flex align-items-center">
2282
+ <div
2283
+ class="o_side_panel_collapsible_title o-fw-bold d-flex align-items-center"
2284
+ t-on-click="() => this.toggle()">
2216
2285
  <div
2217
2286
  class="collapsor w-100 d-flex align-items-center ps-1"
2218
- t-att-class="state.isCollapsed ? 'collapsed' : ''"
2219
- t-on-click="() => this.toggle()">
2287
+ t-att-class="state.isCollapsed ? 'collapsed' : ''">
2220
2288
  <span class="collapsor-arrow">
2221
2289
  <t t-call="o-spreadsheet-Icon.ANGLE_DOWN"/>
2222
2290
  </span>
@@ -2273,6 +2341,30 @@
2273
2341
  </label>
2274
2342
  </t>
2275
2343
 
2344
+ <t t-name="o-spreadsheet-CarouselItemTitleCollapsible">
2345
+ <SidePanelCollapsible
2346
+ class="'o-carousel-item-title'"
2347
+ isInitiallyCollapsed="true"
2348
+ title.translate="Carousel Title">
2349
+ <t t-set-slot="content">
2350
+ <div class="ps-4">
2351
+ <TextInput
2352
+ value="title"
2353
+ onChange.bind="updateTitle"
2354
+ placeholder.translate="Title"
2355
+ alwaysShowBorder="true"
2356
+ />
2357
+ <TextStyler
2358
+ style="style"
2359
+ updateStyle.bind="updateStyle"
2360
+ defaultStyle="defaultStyle"
2361
+ hasHorizontalAlign="false"
2362
+ />
2363
+ </div>
2364
+ </t>
2365
+ </SidePanelCollapsible>
2366
+ </t>
2367
+
2276
2368
  <t t-name="o-spreadsheet.BadgeSelection">
2277
2369
  <div class="d-flex w-100 o-badge-selection">
2278
2370
  <t t-foreach="props.choices" t-as="choice" t-key="choice.value">
@@ -2287,6 +2379,37 @@
2287
2379
  </div>
2288
2380
  </t>
2289
2381
 
2382
+ <t t-name="o-spreadsheet-GenericZoomableChartDesignPanel">
2383
+ <GeneralDesignEditor t-props="props">
2384
+ <t t-set-slot="general-extension">
2385
+ <ChartLegend t-props="props"/>
2386
+ <Section class="'pt-0'" title.translate="Values">
2387
+ <ChartShowValues t-props="props"/>
2388
+ </Section>
2389
+ <Section class="'pt-0'" title.translate="Zoom">
2390
+ <Checkbox
2391
+ name="'zoomable'"
2392
+ label.translate="Show slicer"
2393
+ value="props.definition.zoomable"
2394
+ onChange.bind="onToggleZoom"
2395
+ className="'mb-2'"
2396
+ />
2397
+ </Section>
2398
+ </t>
2399
+ </GeneralDesignEditor>
2400
+ <SeriesWithAxisDesignEditor t-props="props"/>
2401
+ <SidePanelCollapsible isInitiallyCollapsed="true" title.translate="Axes">
2402
+ <t t-set-slot="content">
2403
+ <AxisDesignEditor
2404
+ axesList="axesList"
2405
+ chartId="props.chartId"
2406
+ definition="props.definition"
2407
+ updateChart="props.updateChart"
2408
+ />
2409
+ </t>
2410
+ </SidePanelCollapsible>
2411
+ </t>
2412
+
2290
2413
  <t t-name="o-spreadsheet-WaterfallChartDesignPanel">
2291
2414
  <GeneralDesignEditor t-props="props">
2292
2415
  <t t-set-slot="general-extension">
@@ -2302,6 +2425,18 @@
2302
2425
  <Section class="'pt-0'" title.translate="Values">
2303
2426
  <ChartShowValues t-props="props"/>
2304
2427
  </Section>
2428
+ <Section class="'pt-0'" title.translate="Zoom">
2429
+ <Checkbox
2430
+ name="'zoomable'"
2431
+ label.translate="Show slicer"
2432
+ value="props.definition.zoomable"
2433
+ onChange.bind="onToggleZoom"
2434
+ className="'mb-2'"
2435
+ />
2436
+ </Section>
2437
+ <Section class="'pt-1'" title.translate="Number formatting">
2438
+ <ChartHumanizeNumbers t-props="props"/>
2439
+ </Section>
2305
2440
  </t>
2306
2441
  </GeneralDesignEditor>
2307
2442
  <SidePanelCollapsible isInitiallyCollapsed="true" title.translate="Waterfall design">
@@ -2360,7 +2495,7 @@
2360
2495
  <t t-set-slot="content">
2361
2496
  <AxisDesignEditor
2362
2497
  axesList="axesList"
2363
- figureId="props.figureId"
2498
+ chartId="props.chartId"
2364
2499
  definition="props.definition"
2365
2500
  updateChart="props.updateChart"
2366
2501
  />
@@ -2382,14 +2517,14 @@
2382
2517
 
2383
2518
  <t t-if="coloringOptions.type === 'categoryColor'">
2384
2519
  <TreeMapCategoryColors
2385
- figureId="props.figureId"
2520
+ chartId="props.chartId"
2386
2521
  definition="props.definition"
2387
2522
  onColorChanged.bind="onCategoryColorChange"
2388
2523
  />
2389
2524
  </t>
2390
2525
  <t t-else="">
2391
2526
  <TreeMapColorScale
2392
- figureId="props.figureId"
2527
+ chartId="props.chartId"
2393
2528
  definition="props.definition"
2394
2529
  onColorChanged.bind="onColorScaleChange"
2395
2530
  />
@@ -2405,13 +2540,13 @@
2405
2540
  name="'showHeaders'"
2406
2541
  label.translate="Show headers"
2407
2542
  value="showHeaders"
2408
- onChange="(showHeaders) => props.updateChart(this.props.figureId, { showHeaders })"
2543
+ onChange="(showHeaders) => props.updateChart(this.props.chartId, { showHeaders })"
2409
2544
  />
2410
2545
  </Section>
2411
2546
  <Section class="'pt-0'" t-if="showHeaders">
2412
2547
  <TextStyler
2413
2548
  class="'pt-0 o-header-style'"
2414
- updateStyle="(headerDesign) => props.updateChart(this.props.figureId, { headerDesign })"
2549
+ updateStyle="(headerDesign) => props.updateChart(this.props.chartId, { headerDesign })"
2415
2550
  style="props.definition.headerDesign || {}"
2416
2551
  defaultStyle="defaults.headerDesign"
2417
2552
  hasBackgroundColor="true"
@@ -2424,7 +2559,7 @@
2424
2559
  name="'showLabels'"
2425
2560
  label.translate="Show labels"
2426
2561
  value="showLabels"
2427
- onChange="(showLabels) => props.updateChart(this.props.figureId, { showLabels })"
2562
+ onChange="(showLabels) => props.updateChart(this.props.chartId, { showLabels })"
2428
2563
  />
2429
2564
  <ChartShowValues t-props="props" defaultValue="defaults.showValues"/>
2430
2565
  </div>
@@ -2432,7 +2567,7 @@
2432
2567
  <Section class="'pt-0'" t-if="showValues || showLabels">
2433
2568
  <TextStyler
2434
2569
  class="'pt-0 o-values-style'"
2435
- updateStyle="(valuesDesign) => props.updateChart(this.props.figureId, { valuesDesign })"
2570
+ updateStyle="(valuesDesign) => props.updateChart(this.props.chartId, { valuesDesign })"
2436
2571
  style="props.definition.valuesDesign || {}"
2437
2572
  defaultStyle="defaults.valuesDesign"
2438
2573
  hasVerticalAlign="true"
@@ -2523,7 +2658,7 @@
2523
2658
  name="'showLabels'"
2524
2659
  label.translate="Show labels"
2525
2660
  value="showLabels"
2526
- onChange="(showLabels) => props.updateChart(this.props.figureId, { showLabels })"
2661
+ onChange="(showLabels) => props.updateChart(this.props.chartId, { showLabels })"
2527
2662
  />
2528
2663
  <ChartShowValues t-props="props" defaultValue="defaults.showValues"/>
2529
2664
  </div>
@@ -2531,7 +2666,7 @@
2531
2666
  <Section class="'pt-0'" t-if="showValues || showLabels">
2532
2667
  <TextStyler
2533
2668
  class="'o-values-style'"
2534
- updateStyle="(valuesDesign) => props.updateChart(this.props.figureId, { valuesDesign })"
2669
+ updateStyle="(valuesDesign) => props.updateChart(this.props.chartId, { valuesDesign })"
2535
2670
  style="props.definition.valuesDesign || {}"
2536
2671
  defaultStyle="defaults.valuesDesign"
2537
2672
  />
@@ -2550,12 +2685,7 @@
2550
2685
  <GeneralDesignEditor t-props="props" defaultChartTitleFontSize="defaultScorecardTitleFontSize">
2551
2686
  <t t-set-slot="general-extension">
2552
2687
  <Section class="'pt-1'" title.translate="Number formatting">
2553
- <Checkbox
2554
- name="'humanizeNumbers'"
2555
- label="humanizeNumbersLabel"
2556
- value="props.definition.humanize"
2557
- onChange.bind="updateHumanizeNumbers"
2558
- />
2688
+ <ChartHumanizeNumbers t-props="props"/>
2559
2689
  </Section>
2560
2690
  </t>
2561
2691
  </GeneralDesignEditor>
@@ -2668,6 +2798,9 @@
2668
2798
  <ChartShowValues t-props="props"/>
2669
2799
  <ChartShowDataMarkers t-props="props"/>
2670
2800
  </Section>
2801
+ <Section class="'pt-1'" title.translate="Number formatting">
2802
+ <ChartHumanizeNumbers t-props="props"/>
2803
+ </Section>
2671
2804
  </t>
2672
2805
  </GeneralDesignEditor>
2673
2806
  <SeriesDesignEditor t-props="props"/>
@@ -2680,9 +2813,12 @@
2680
2813
  <Section class="'pt-0'" title.translate="Values">
2681
2814
  <ChartShowValues t-props="props"/>
2682
2815
  </Section>
2816
+ <Section class="'pt-1'" title.translate="Number formatting">
2817
+ <ChartHumanizeNumbers t-props="props"/>
2818
+ </Section>
2683
2819
  <PieHoleSize
2684
2820
  t-if="props.definition.isDoughnut"
2685
- value="props.definition.pieHolePercentage ?? 50"
2821
+ value="props.definition.pieHolePercentage ?? this.defaultHoleSize"
2686
2822
  onValueChange.bind="onPieHoleSizeChange"
2687
2823
  />
2688
2824
  </t>
@@ -2690,46 +2826,48 @@
2690
2826
  </t>
2691
2827
 
2692
2828
  <t t-name="o-spreadsheet-ChartPanel">
2693
- <div class="o-chart" t-if="figureId">
2829
+ <div class="o-chart d-flex flex-column h-100" t-if="chartId">
2694
2830
  <div class="o-panel">
2695
2831
  <div
2696
2832
  class="o-panel-element o-panel-configuration"
2697
2833
  t-att-class="store.panel !== 'configuration' ? 'inactive' : ''"
2698
- t-on-click="() => this.store.activatePanel('configuration')">
2834
+ t-on-click="switchPanel.bind(this, 'configuration')">
2699
2835
  <i class="fa fa-sliders"/>
2700
2836
  Configuration
2701
2837
  </div>
2702
2838
  <div
2703
2839
  class="o-panel-element o-panel-design"
2704
2840
  t-att-class="store.panel !== 'design' ? 'inactive' : ''"
2705
- t-on-click="() => this.store.activatePanel('design')">
2841
+ t-on-click="switchPanel.bind(this, 'design')">
2706
2842
  <i class="fa fa-paint-brush"/>
2707
2843
  Design
2708
2844
  </div>
2709
2845
  </div>
2710
2846
 
2711
- <t t-set="definition" t-value="getChartDefinition(this.figureId)"/>
2712
- <t t-if="store.panel === 'configuration'">
2713
- <ChartTypePicker figureId="props.figureId" chartPanelStore="store"/>
2714
- <t
2715
- t-component="chartPanel.configuration"
2716
- definition="definition"
2717
- figureId="figureId"
2718
- updateChart.bind="updateChart"
2719
- canUpdateChart.bind="canUpdateChart"
2720
- t-key="figureId + definition.type"
2721
- />
2722
- </t>
2723
- <t t-else="">
2724
- <t
2725
- t-component="chartPanel.design"
2726
- definition="definition"
2727
- figureId="figureId"
2728
- updateChart.bind="updateChart"
2729
- canUpdateChart.bind="canUpdateChart"
2730
- t-key="figureId + definition.type"
2731
- />
2732
- </t>
2847
+ <t t-set="definition" t-value="getChartDefinition(this.chartId)"/>
2848
+ <div class="o-panel-content overflow-y-auto" t-ref="panelContent">
2849
+ <div t-att-class="store.panel !== 'configuration' ? 'd-none' : ''">
2850
+ <ChartTypePicker chartId="chartId" chartPanelStore="store"/>
2851
+ <t
2852
+ t-component="chartPanel.configuration"
2853
+ definition="definition"
2854
+ chartId="chartId"
2855
+ updateChart.bind="updateChart"
2856
+ canUpdateChart.bind="canUpdateChart"
2857
+ t-key="chartId + definition.type"
2858
+ />
2859
+ </div>
2860
+ <div t-att-class="store.panel !== 'design' ? 'd-none' : ''">
2861
+ <t
2862
+ t-component="chartPanel.design"
2863
+ definition="definition"
2864
+ chartId="chartId"
2865
+ updateChart.bind="updateChart"
2866
+ canUpdateChart.bind="canUpdateChart"
2867
+ t-key="chartId + definition.type"
2868
+ />
2869
+ </div>
2870
+ </div>
2733
2871
  </div>
2734
2872
  </t>
2735
2873
 
@@ -2741,6 +2879,18 @@
2741
2879
  <ChartShowValues t-props="props"/>
2742
2880
  <ChartShowDataMarkers t-props="props"/>
2743
2881
  </Section>
2882
+ <Section class="'pt-0'" title.translate="Zoom">
2883
+ <Checkbox
2884
+ name="'zoomable'"
2885
+ label.translate="Show slicer"
2886
+ value="props.definition.zoomable"
2887
+ onChange.bind="onToggleZoom"
2888
+ className="'mb-2'"
2889
+ />
2890
+ </Section>
2891
+ <Section class="'pt-1'" title.translate="Number formatting">
2892
+ <ChartHumanizeNumbers t-props="props"/>
2893
+ </Section>
2744
2894
  </t>
2745
2895
  </GeneralDesignEditor>
2746
2896
  <SeriesWithAxisDesignEditor t-props="props"/>
@@ -2748,7 +2898,7 @@
2748
2898
  <t t-set-slot="content">
2749
2899
  <AxisDesignEditor
2750
2900
  axesList="axesList"
2751
- figureId="props.figureId"
2901
+ chartId="props.chartId"
2752
2902
  definition="props.definition"
2753
2903
  updateChart="props.updateChart"
2754
2904
  />
@@ -2847,6 +2997,9 @@
2847
2997
  <option value="left">Bottom left</option>
2848
2998
  </select>
2849
2999
  </Section>
3000
+ <Section class="'pt-1'" title.translate="Number formatting">
3001
+ <ChartHumanizeNumbers t-props="props"/>
3002
+ </Section>
2850
3003
  </t>
2851
3004
  </GeneralDesignEditor>
2852
3005
 
@@ -2905,7 +3058,7 @@
2905
3058
  <t t-name="o-spreadsheet-GeoChartConfigPanel">
2906
3059
  <div>
2907
3060
  <GeoChartRegionSelectSection
2908
- figureId="props.figureId"
3061
+ chartId="props.chartId"
2909
3062
  definition="props.definition"
2910
3063
  updateChart="props.updateChart"
2911
3064
  />
@@ -2935,7 +3088,13 @@
2935
3088
  </t>
2936
3089
 
2937
3090
  <t t-name="o-spreadsheet-GaugeChartDesignPanel">
2938
- <GeneralDesignEditor t-props="props"/>
3091
+ <GeneralDesignEditor t-props="props">
3092
+ <t t-set-slot="general-extension">
3093
+ <Section class="'pt-1'" title.translate="Number formatting">
3094
+ <ChartHumanizeNumbers t-props="props"/>
3095
+ </Section>
3096
+ </t>
3097
+ </GeneralDesignEditor>
2939
3098
  <SidePanelCollapsible isInitiallyCollapsed="false" title.translate="Gauge Design">
2940
3099
  <t t-set-slot="content">
2941
3100
  <Section class="'pt-0'" title.translate="Range">
@@ -3077,6 +3236,9 @@
3077
3236
  <Section class="'pt-0'" title.translate="Values">
3078
3237
  <ChartShowValues t-props="props"/>
3079
3238
  </Section>
3239
+ <Section class="'pt-1'" title.translate="Number formatting">
3240
+ <ChartHumanizeNumbers t-props="props"/>
3241
+ </Section>
3080
3242
  </t>
3081
3243
  </GeneralDesignEditor>
3082
3244
 
@@ -3105,6 +3267,18 @@
3105
3267
  <ChartShowValues t-props="props"/>
3106
3268
  <ChartShowDataMarkers t-props="props"/>
3107
3269
  </Section>
3270
+ <Section class="'pt-0'" title.translate="Zoom">
3271
+ <Checkbox
3272
+ name="'zoomable'"
3273
+ label.translate="Show slicer"
3274
+ value="props.definition.zoomable"
3275
+ onChange.bind="onToggleZoom"
3276
+ className="'mb-2'"
3277
+ />
3278
+ </Section>
3279
+ <Section class="'pt-1'" title.translate="Number formatting">
3280
+ <ChartHumanizeNumbers t-props="props"/>
3281
+ </Section>
3108
3282
  </t>
3109
3283
  </GeneralDesignEditor>
3110
3284
  <SeriesWithAxisDesignEditor t-props="props">
@@ -3124,7 +3298,7 @@
3124
3298
  <t t-set-slot="content">
3125
3299
  <AxisDesignEditor
3126
3300
  axesList="axesList"
3127
- figureId="props.figureId"
3301
+ chartId="props.chartId"
3128
3302
  definition="props.definition"
3129
3303
  updateChart="props.updateChart"
3130
3304
  />
@@ -3139,6 +3313,9 @@
3139
3313
  <Section class="'pt-0'" title.translate="Values">
3140
3314
  <ChartShowValues t-props="props"/>
3141
3315
  </Section>
3316
+ <Section class="'pt-1'" title.translate="Number formatting">
3317
+ <ChartHumanizeNumbers t-props="props"/>
3318
+ </Section>
3142
3319
  </t>
3143
3320
  </GeneralDesignEditor>
3144
3321
  <SeriesWithAxisDesignEditor t-props="props"/>
@@ -3146,7 +3323,7 @@
3146
3323
  <t t-set-slot="content">
3147
3324
  <AxisDesignEditor
3148
3325
  axesList="axesList"
3149
- figureId="props.figureId"
3326
+ chartId="props.chartId"
3150
3327
  definition="props.definition"
3151
3328
  updateChart="props.updateChart"
3152
3329
  />
@@ -3580,7 +3757,7 @@
3580
3757
  name="'showValues'"
3581
3758
  label.translate="Show values"
3582
3759
  value="props.definition.showValues ?? props.defaultValue"
3583
- onChange="(showValues) => props.updateChart(this.props.figureId, { showValues })"
3760
+ onChange="(showValues) => props.updateChart(this.props.chartId, { showValues })"
3584
3761
  />
3585
3762
  </t>
3586
3763
 
@@ -3589,7 +3766,7 @@
3589
3766
  name="'showDataMarkers'"
3590
3767
  label.translate="Show data markers"
3591
3768
  value="!props.definition.hideDataMarkers"
3592
- onChange="(showDataMarkers) => props.updateChart(this.props.figureId, { hideDataMarkers: !showDataMarkers })"
3769
+ onChange="(showDataMarkers) => props.updateChart(this.props.chartId, { hideDataMarkers: !showDataMarkers })"
3593
3770
  />
3594
3771
  </t>
3595
3772
 
@@ -3776,6 +3953,15 @@
3776
3953
  </Section>
3777
3954
  </t>
3778
3955
 
3956
+ <t t-name="o-spreadsheet-ChartHumanizeNumbers">
3957
+ <Checkbox
3958
+ name="'humanizeNumbers'"
3959
+ label.translate="Make numbers human-readable"
3960
+ value="props.definition.humanize ?? true"
3961
+ onChange="(humanize) => props.updateChart(this.props.chartId, { humanize })"
3962
+ />
3963
+ </t>
3964
+
3779
3965
  <t t-name="o-spreadsheet-GenericChartConfigPanel">
3780
3966
  <div>
3781
3967
  <ChartDataSeries
@@ -3937,6 +4123,73 @@
3937
4123
  </div>
3938
4124
  </t>
3939
4125
 
4126
+ <t t-name="o-spreadsheet-CarouselPanel">
4127
+ <div class="o-carousel-panel h-100 overflow-auto">
4128
+ <div class="o-carousel-preview-list overflow-auto" t-ref="previewList">
4129
+ <div
4130
+ t-foreach="carouselItems"
4131
+ t-as="item"
4132
+ t-key="getItemId(item)"
4133
+ class="o-carousel-preview position-relative d-flex align-items-center border-bottom ps-1 pe-2 pt-3 pb-2 w-100"
4134
+ t-att-class="{ 'o-dragging': dragAndDrop.draggedItemId === getItemId(item) }"
4135
+ t-att-style="getPreviewDivStyle(item)">
4136
+ <div
4137
+ class="o-drag-handle position-absolute ps-1 flex-shrink-0"
4138
+ t-on-pointerdown.stop.prevent="(ev) => this.onDragHandleMouseDown(item, ev)">
4139
+ <t t-call="o-spreadsheet-Icon.THIN_DRAG_HANDLE"/>
4140
+ </div>
4141
+ <div class="flex-grow-1">
4142
+ <div class="d-flex align-items-center">
4143
+ <div
4144
+ class="o-carousel-preview-icon ms-3 flex-shrink-0 d-flex align-items-center justify-content-center">
4145
+ <t t-call="{{getItemPreview(item)}}"/>
4146
+ </div>
4147
+ <div class="o-carousel-preview-title text-truncate ms-2">
4148
+ <TextInput
4149
+ value="getItemTitle(item)"
4150
+ onChange="(newName) => this.renameCarouselItem(item, newName)"
4151
+ />
4152
+ </div>
4153
+ <div class="ms-auto"/>
4154
+ <div
4155
+ t-if="item.type === 'chart'"
4156
+ class="o-edit-button o-button-icon pe-2 ps-1 flex-shrink-0 fa fa-pencil"
4157
+ t-on-click.stop="(ev) => this.editCarouselItem(item, ev)"
4158
+ title="Edit chart"
4159
+ />
4160
+ <div
4161
+ class="o-delete-button o-button-icon pe-2 ps-1 flex-shrink-0"
4162
+ t-on-click.stop="(ev) => this.deleteCarouselItem(item, ev)"
4163
+ title="Remove chart">
4164
+ <t t-call="o-spreadsheet-Icon.TRASH_FILLED"/>
4165
+ </div>
4166
+ </div>
4167
+ <div class="ms-3">
4168
+ <CarouselItemTitleCollapsible
4169
+ carouselTitle="item.carouselTitle"
4170
+ onUpdateCarouselTitle="(style) => this.onUpdateCarouselTitle(item_index, style)"
4171
+ />
4172
+ </div>
4173
+ </div>
4174
+ </div>
4175
+ </div>
4176
+ <div
4177
+ class="o-button-link o-carousel-add-chart float-end d-flex align-items-center pt-4 pe-4 gap-2"
4178
+ t-on-click="addNewChartToCarousel">
4179
+ + Add chart
4180
+ <span t-att-title="carouselAddChartInfoMessage">
4181
+ <t t-call="o-spreadsheet-Icon.CIRCLE_INFO"/>
4182
+ </span>
4183
+ </div>
4184
+ <div
4185
+ t-if="!hasDataView"
4186
+ class="o-button-link o-carousel-add-data-view float-end pt-4 pe-4"
4187
+ t-on-click="addDataViewToCarousel">
4188
+ + Add data view
4189
+ </div>
4190
+ </div>
4191
+ </t>
4192
+
3940
4193
  <t t-name="o-spreadsheet-SelectionInput">
3941
4194
  <div class="o-selection" t-ref="o-selection">
3942
4195
  <div
@@ -5099,12 +5352,26 @@
5099
5352
  </svg>
5100
5353
  </t>
5101
5354
  <t t-name="o-spreadsheet-Icon.PLUS_IN_BOX">
5102
- <svg
5103
- class="o-icon"
5104
- width="18"
5105
- height="18"
5106
- style="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5">
5107
- <path stroke="currentColor" d="M1.5,1.5h15v15h-15v-15M9,5v8M5,9h8"/>
5355
+ <svg class="o-icon" width="18" height="18" style="">
5356
+ <path
5357
+ fill="currentColor"
5358
+ d="
5359
+ M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v14h14V2H2
5360
+ M4,9.5 h10 v-1.5 h-10
5361
+ M8.25,3.75 v10 h1.5 v-10
5362
+ "
5363
+ />
5364
+ </svg>
5365
+ </t>
5366
+ <t t-name="o-spreadsheet-Icon.MINUS_IN_BOX">
5367
+ <svg class="o-icon" width="18" height="18" style="">
5368
+ <path
5369
+ fill="currentColor"
5370
+ d="
5371
+ M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v14h14V2H2
5372
+ M4,9.5 h10 v-1.5 h-10
5373
+ "
5374
+ />
5108
5375
  </svg>
5109
5376
  </t>
5110
5377
  <t t-name="o-spreadsheet-Icon.GROUP_ROWS">
@@ -5279,6 +5546,14 @@
5279
5546
  <i class="fa fa-download"/>
5280
5547
  </div>
5281
5548
  </t>
5549
+ <t t-name="o-spreadsheet-Icon.CAROUSEL">
5550
+ <svg class="o-icon" viewBox="0 0 122.88 99.75">
5551
+ <path
5552
+ fill="currentColor"
5553
+ d="M29.09,0h64.7A5.21,5.21,0,0,1,99,5.18v89.4a5.19,5.19,0,0,1-5.18,5.17H29.09a5.19,5.19,0,0,1-5.17-5.18V5.18A5.21,5.21,0,0,1,29.09,0Zm78.52,12.46,10.59-1.52a4.71,4.71,0,0,1,4.68,4.69v68.5a4.71,4.71,0,0,1-4.68,4.68L107.77,88a1.35,1.35,0,0,1-1.31-1.34V83.14a1.34,1.34,0,0,1,1.44-1.23l8.91.73V17.22l-9,1.34a1.34,1.34,0,0,1-1.34-1.34V13.78a1.34,1.34,0,0,1,1.15-1.32ZM5,11l10.31,1.49a1.33,1.33,0,0,1,1.14,1.32v3.44a1.34,1.34,0,0,1-1.34,1.34l-9-1.34V82.64L15,81.91a1.33,1.33,0,0,1,1.43,1.23v3.49A1.35,1.35,0,0,1,15.11,88l-10.43.84A4.71,4.71,0,0,1,0,84.13V15.63a4.73,4.73,0,0,1,4.68-4.69L5,11Zm87.93-4.9H30v87.6h62.9V6.07Z"
5554
+ />
5555
+ </svg>
5556
+ </t>
5282
5557
 
5283
5558
  <t t-name="o-spreadsheet-IconPicker">
5284
5559
  <div class="o-icon-picker">
@@ -5759,7 +6034,7 @@
5759
6034
  <t t-name="o-spreadsheet-FullScreenChart">
5760
6035
  <div
5761
6036
  class="position-absolute o-fullscreen-chart-overlay w-100 h-100 d-flex"
5762
- t-if="figureUI"
6037
+ t-if="chartId"
5763
6038
  t-on-click="exitFullScreen">
5764
6039
  <button
5765
6040
  class="o-exit top-0 end-0 position-absolute o-button primary m-1"
@@ -5773,14 +6048,9 @@
5773
6048
  t-ref="fullScreenChart"
5774
6049
  t-on-click.stop=""
5775
6050
  t-on-keydown="(ev) => this.onKeyDown(ev)">
5776
- <t
5777
- t-component="chartComponent"
5778
- figureUI="this.figureUI"
5779
- isFullScreen="true"
5780
- t-key="this.figureUI.id"
5781
- />
6051
+ <t t-component="chartComponent" chartId="chartId" isFullScreen="true" t-key="chartId"/>
5782
6052
  <div class="position-absolute top-0 end-0">
5783
- <ChartDashboardMenu figureUI="figureUI"/>
6053
+ <ChartDashboardMenu chartId="chartId"/>
5784
6054
  </div>
5785
6055
  </div>
5786
6056
  </div>
@@ -5981,6 +6251,7 @@
5981
6251
  onFigureDeleted="this.props.onFigureDeleted"
5982
6252
  figureUI="figureUI"
5983
6253
  style="getFigureStyle(figureUI)"
6254
+ class="getFigureClass(figureUI)"
5984
6255
  onMouseDown="(ev) => this.startDraggingFigure(figureUI, ev)"
5985
6256
  onClickAnchor="(dirX, dirY, ev) => this.startResize(figureUI, dirX, dirY, ev)"
5986
6257
  />
@@ -6007,21 +6278,60 @@
6007
6278
 
6008
6279
  <t t-name="o-spreadsheet-ChartFigure">
6009
6280
  <div class="o-chart-container w-100 h-100" t-on-dblclick="onDoubleClick">
6010
- <t
6011
- t-component="chartComponent"
6012
- figureUI="this.props.figureUI"
6013
- t-key="this.props.figureUI.id"
6014
- />
6281
+ <t t-component="chartComponent" chartId="chartId" t-key="chartId"/>
6015
6282
  </div>
6016
6283
  <div t-if="env.isDashboard()" class="position-absolute top-0 end-0">
6017
- <ChartDashboardMenu figureUI="props.figureUI"/>
6284
+ <ChartDashboardMenu chartId="chartId"/>
6285
+ </div>
6286
+ </t>
6287
+
6288
+ <t t-name="o-spreadsheet-CarouselFigure">
6289
+ <div class="o-carousel w-100 h-100 d-flex flex-column" t-on-dblclick="onCarouselDoubleClick">
6290
+ <t t-set="selectedItem" t-value="selectedCarouselItem"/>
6291
+ <div
6292
+ class="o-carousel-header d-flex flex-shrink-0 pe-1 rounded pe-auto"
6293
+ t-att-class="{
6294
+ 'o-carousel-header-floating': !env.isDashboard() and selectedItem?.type === 'carouselDataView',
6295
+ }"
6296
+ t-att-style="headerStyle">
6297
+ <div
6298
+ class="o-carousel-title d-flex align-items-center"
6299
+ t-esc="title"
6300
+ t-att-style="titleStyle"
6301
+ />
6302
+ <div class="ms-auto d-flex">
6303
+ <t t-foreach="carousel.items" t-as="item" t-key="item_index">
6304
+ <div
6305
+ class="o-carousel-tab text-truncate px-2 mt-1 mb-1 flex-shrink-0"
6306
+ t-att-class="{ 'selected': isItemSelected(item) }"
6307
+ t-esc="getItemTitle(item)"
6308
+ t-on-click.stop="() => this.onCarouselTabClick(item)"
6309
+ />
6310
+ </t>
6311
+ </div>
6312
+ </div>
6313
+ <div
6314
+ t-if="!selectedItem"
6315
+ class="o-carousel-empty w-100 flex-fill d-flex align-items-center justify-content-center">
6316
+ <t t-call="o-spreadsheet-Icon.CAROUSEL"/>
6317
+ </div>
6318
+ <div t-elif="selectedItem.type === 'chart'" class="o-carousel-content w-100 flex-fill">
6319
+ <div class="o-chart-container w-100 h-100">
6320
+ <t
6321
+ t-component="chartComponent"
6322
+ chartId="selectedItem.chartId"
6323
+ t-key="selectedItem.chartId"
6324
+ />
6325
+ </div>
6326
+ </div>
6018
6327
  </div>
6019
6328
  </t>
6020
6329
 
6021
6330
  <t t-name="o-spreadsheet-FigureComponent">
6022
- <div class="o-figure-wrapper pe-auto" t-att-style="wrapperStyle">
6331
+ <div class="o-figure-wrapper" t-att-style="wrapperStyle" t-ref="figureWrapper">
6023
6332
  <div
6024
6333
  class="o-figure w-100 h-100"
6334
+ t-att-class="props.class"
6025
6335
  t-on-pointerdown.stop="(ev) => this.onMouseDown(ev)"
6026
6336
  t-on-click="onClick"
6027
6337
  t-on-contextmenu.prevent.stop="(ev) => !env.model.getters.isReadonly() and this.onContextMenu(ev)"
@@ -6036,11 +6346,12 @@
6036
6346
  t-key="props.figureUI.id"
6037
6347
  onFigureDeleted="props.onFigureDeleted"
6038
6348
  figureUI="props.figureUI"
6349
+ editFigureStyle.bind="editWrapperStyle"
6039
6350
  />
6040
6351
  <div class="o-figure-menu position-absolute m-2" t-if="!env.isDashboard()">
6041
6352
  <div
6042
6353
  class="o-figure-menu-item"
6043
- t-if="!env.model.getters.isReadonly()"
6354
+ t-if="!env.model.getters.isReadonly() and props.figureUI.tag !== 'carousel'"
6044
6355
  t-on-click="showMenu"
6045
6356
  t-ref="menuButton"
6046
6357
  t-on-contextmenu.prevent.stop="showMenu">
@@ -6053,46 +6364,63 @@
6053
6364
  onClose="() => this.menuState.isOpen=false"
6054
6365
  />
6055
6366
  </div>
6367
+ <div t-if="!env.isDashboard()" class="position-absolute top-0 start-0 pe-none w-100 h-100">
6368
+ <div
6369
+ class="o-figure-border pe-auto w-100 h-0 position-absolute pb-2"
6370
+ t-att-style="getBorderStyle('top')"
6371
+ />
6372
+ <div
6373
+ class="o-figure-border pe-auto h-100 position-absolute start-0 ps-2"
6374
+ t-att-style="getBorderStyle('left')"
6375
+ />
6376
+ <div
6377
+ class="o-figure-border pe-auto w-100 position-absolute bottom-0 pt-2"
6378
+ t-att-style="getBorderStyle('bottom')"
6379
+ />
6380
+ <div
6381
+ class="o-figure-border pe-auto h-100 position-absolute end-0 pe-2"
6382
+ t-att-style="getBorderStyle('right')"
6383
+ />
6384
+ </div>
6056
6385
  </div>
6057
- <div class="o-figure-border w-100 h-100 position-absolute pe-none" t-att-style="borderStyle"/>
6058
6386
  <t t-if="isSelected and !env.isMobile()">
6059
6387
  <div
6060
- class="o-fig-anchor o-top"
6388
+ class="o-fig-anchor o-top pe-auto"
6061
6389
  t-att-style="this.getResizerPosition('top')"
6062
6390
  t-on-pointerdown="(ev) => this.clickAnchor(0,-1, ev)"
6063
6391
  />
6064
6392
  <div
6065
- class="o-fig-anchor o-topRight"
6393
+ class="o-fig-anchor o-topRight pe-auto"
6066
6394
  t-att-style="this.getResizerPosition('top right')"
6067
6395
  t-on-pointerdown="(ev) => this.clickAnchor(1,-1, ev)"
6068
6396
  />
6069
6397
  <div
6070
- class="o-fig-anchor o-right"
6398
+ class="o-fig-anchor o-right pe-auto"
6071
6399
  t-att-style="this.getResizerPosition('right')"
6072
6400
  t-on-pointerdown="(ev) => this.clickAnchor(1,0, ev)"
6073
6401
  />
6074
6402
  <div
6075
- class="o-fig-anchor o-bottomRight"
6403
+ class="o-fig-anchor o-bottomRight pe-auto"
6076
6404
  t-att-style="this.getResizerPosition('bottom right')"
6077
6405
  t-on-pointerdown="(ev) => this.clickAnchor(1,1, ev)"
6078
6406
  />
6079
6407
  <div
6080
- class="o-fig-anchor o-bottom"
6408
+ class="o-fig-anchor o-bottom pe-auto"
6081
6409
  t-att-style="this.getResizerPosition('bottom')"
6082
6410
  t-on-pointerdown="(ev) => this.clickAnchor(0,1, ev)"
6083
6411
  />
6084
6412
  <div
6085
- class="o-fig-anchor o-bottomLeft"
6413
+ class="o-fig-anchor o-bottomLeft pe-auto"
6086
6414
  t-att-style="this.getResizerPosition('bottom left')"
6087
6415
  t-on-pointerdown="(ev) => this.clickAnchor(-1,1, ev)"
6088
6416
  />
6089
6417
  <div
6090
- class="o-fig-anchor o-left"
6418
+ class="o-fig-anchor o-left pe-auto"
6091
6419
  t-att-style="this.getResizerPosition('left')"
6092
6420
  t-on-pointerdown="(ev) => this.clickAnchor(-1,0, ev)"
6093
6421
  />
6094
6422
  <div
6095
- class="o-fig-anchor o-topLeft"
6423
+ class="o-fig-anchor o-topLeft pe-auto"
6096
6424
  t-att-style="this.getResizerPosition('top left')"
6097
6425
  t-on-pointerdown="(ev) => this.clickAnchor(-1,-1, ev)"
6098
6426
  />
@@ -6112,7 +6440,7 @@
6112
6440
  <canvas class="o-figure-canvas o-gauge-chart w-100 h-100 d-block" t-ref="chartContainer"/>
6113
6441
  </t>
6114
6442
 
6115
- <t t-name="spreadsheet.ChartDashboardMenu">
6443
+ <t t-name="o-spreadsheet-ChartDashboardMenu">
6116
6444
  <div class="o-dashboard-chart-select position-absolute top-0 end-0" t-on-click.stop="">
6117
6445
  <div class="d-flex flex-row px-1" t-att-style="backgroundColor">
6118
6446
  <t t-foreach="getMenuItems()" t-as="item" t-key="item.id">
@@ -6142,6 +6470,24 @@
6142
6470
  <canvas class="o-figure-canvas w-100 h-100" t-att-style="canvasStyle" t-ref="graphContainer"/>
6143
6471
  </t>
6144
6472
 
6473
+ <t t-name="o-spreadsheet-ZoomableChartJsComponent">
6474
+ <div class="w-100 h-100" t-att-style="canvasStyle">
6475
+ <div t-att-style="containerStyle">
6476
+ <canvas class="o-figure-canvas w-100 h-100" t-ref="graphContainer"/>
6477
+ </div>
6478
+ <div t-if="sliceable" class="o-master-chart-container m-0">
6479
+ <canvas
6480
+ class="o-figure-canvas o-master-chart-canvas w-100 h-100"
6481
+ t-ref="masterChartCanvas"
6482
+ t-on-dblclick="onDoubleClickInMasterChart"
6483
+ t-on-pointerdown="onPointerDownInMasterChart"
6484
+ t-on-pointermove="onPointerMoveInMasterChart"
6485
+ t-on-mouseleave="onMouseLeaveMasterChart"
6486
+ />
6487
+ </div>
6488
+ </div>
6489
+ </t>
6490
+
6145
6491
  <t t-name="o-spreadsheet-ErrorToolTip">
6146
6492
  <div class="o-error-tooltip">
6147
6493
  <t t-if="evaluationError">
@@ -6280,11 +6626,14 @@
6280
6626
  </t>
6281
6627
  )
6282
6628
  </div>
6283
- <i
6284
- class="fa fa-caret-up px-2 align-self-start"
6629
+ <div
6630
+ class="collapsor px-2 d-flex align-items-center rounded"
6285
6631
  t-att-class="state.isCollapsed ? 'collapsed' : ''"
6286
- t-on-click="() => this.toggle()"
6287
- />
6632
+ t-on-click="() => this.toggle()">
6633
+ <span class="collapsor-arrow d-inline-block">
6634
+ <t t-call="o-spreadsheet-Icon.ANGLE_DOWN"/>
6635
+ </span>
6636
+ </div>
6288
6637
  </div>
6289
6638
 
6290
6639
  <Collapse isCollapsed="state.isCollapsed">
@@ -6321,13 +6670,14 @@
6321
6670
  <t t-name="o-spreadsheet-Composer">
6322
6671
  <div class="o-composer-container w-100 h-100">
6323
6672
  <t t-set="autoCompleteProposals" t-value="props.composerStore.autoCompleteProposals"/>
6673
+ <t t-set="canBeToggled" t-value="props.composerStore.canBeToggled"/>
6324
6674
  <t
6325
6675
  t-set="assistantIsAvailable"
6326
6676
  t-value="props.showAssistant and (autoCompleteProposals.length or functionDescriptionState.showDescription)"
6327
6677
  />
6328
6678
  <div class="d-flex flex-row position-relative">
6329
6679
  <span
6330
- t-if="props.focus !== 'inactive' and assistantIsAvailable and assistant.forcedClosed"
6680
+ t-if="props.focus !== 'inactive' and assistantIsAvailable and canBeToggled and assistant.forcedClosed"
6331
6681
  role="button"
6332
6682
  title="Show formula help"
6333
6683
  t-on-click="openAssistant"
@@ -6344,7 +6694,7 @@
6344
6694
  t-att-style="props.inputStyle"
6345
6695
  t-ref="o_composer"
6346
6696
  tabindex="1"
6347
- t-att-contenteditable="env.model.getters.isReadonly() ? 'false' : 'true'"
6697
+ t-att-contenteditable="env.model.getters.isReadonly() ? 'false' : 'plaintext-only'"
6348
6698
  t-att-placeHolder="props.placeholder"
6349
6699
  t-att-inputmode="props.inputMode"
6350
6700
  spellcheck="false"
@@ -6367,12 +6717,13 @@
6367
6717
  <div
6368
6718
  class="o-composer-assistant-container shadow position-absolute z-1"
6369
6719
  t-att-style="assistantContainerStyle"
6370
- t-if="props.focus !== 'inactive' and !assistant.forcedClosed and assistantIsAvailable"
6720
+ t-if="props.focus !== 'inactive' and assistantIsAvailable and !(canBeToggled and assistant.forcedClosed)"
6371
6721
  t-on-wheel.stop=""
6372
6722
  t-on-pointerdown.prevent.stop=""
6373
6723
  t-on-pointerup.prevent.stop=""
6374
6724
  t-on-click.prevent.stop="">
6375
6725
  <span
6726
+ t-if="canBeToggled and !assistant.forcedClosed"
6376
6727
  role="button"
6377
6728
  t-on-click="closeAssistant"
6378
6729
  class="fa-stack position-absolute top-0 start-100 translate-middle fs-4">
@@ -6693,7 +7044,7 @@
6693
7044
  t-on-dblclick="() => this.onDblClick()"
6694
7045
  t-on-focusout="() => this.onFocusOut()"
6695
7046
  t-on-keydown="(ev) => this.onKeyDown(ev)"
6696
- t-att-contenteditable="state.isEditing ? 'true': 'false'"
7047
+ t-att-contenteditable="state.isEditing ? 'plaintext-only': 'false'"
6697
7048
  />
6698
7049
  <span
6699
7050
  class="o-sheet-icon ms-1"