@odoo/o-spreadsheet 17.3.0-alpha.7 → 17.3.0

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 17.3.0-alpha.7
5
- @date 2024-05-07T10:43:31.043Z
6
- @hash 853c266
4
+ @version 17.3.0
5
+ @date 2024-05-31T14:22:11.907Z
6
+ @hash 271202e
7
7
  -->
8
8
  <odoo>
9
9
  <t t-name="o-spreadsheet-ActionButton">
@@ -585,11 +585,7 @@
585
585
  </t>
586
586
 
587
587
  <t t-name="o-spreadsheet-SpreadsheetDashboard">
588
- <div
589
- class="o-grid o-two-columns"
590
- tabindex="-1"
591
- t-on-wheel="onMouseWheel"
592
- t-on-pointerdown="onClosePopover">
588
+ <div class="o-grid o-two-columns" tabindex="-1" t-on-wheel="onMouseWheel">
593
589
  <div class="mx-auto h-100 position-relative" t-ref="grid" t-att-style="gridContainer">
594
590
  <GridOverlay
595
591
  onCellHovered.bind="onCellHovered"
@@ -818,16 +814,14 @@
818
814
  </t>
819
815
 
820
816
  <t t-name="o-spreadsheet-FilterIconsOverlay">
821
- <div t-on-pointerdown.stop="this.props.onMouseDown">
822
- <t
823
- t-foreach="getFilterHeadersPositions()"
824
- t-as="position"
825
- t-key="'filter'+position.col + '_' + position.row">
826
- <GridCellIcon cellPosition="position" horizontalAlign="'right'">
827
- <FilterIcon cellPosition="position"/>
828
- </GridCellIcon>
829
- </t>
830
- </div>
817
+ <t
818
+ t-foreach="getFilterHeadersPositions()"
819
+ t-as="position"
820
+ t-key="'filter'+position.col + '_' + position.row">
821
+ <GridCellIcon cellPosition="position" horizontalAlign="'right'">
822
+ <FilterIcon cellPosition="position"/>
823
+ </GridCellIcon>
824
+ </t>
831
825
  </t>
832
826
 
833
827
  <t t-name="o-spreadsheet-FilterMenu">
@@ -956,7 +950,7 @@
956
950
  tabindex="-1"
957
951
  t-on-click="focusDefaultElement"
958
952
  t-on-keydown="onKeydown"
959
- t-on-wheel="onMouseWheel"
953
+ t-on-wheel.prevent="onMouseWheel"
960
954
  t-ref="grid">
961
955
  <GridOverlay
962
956
  onCellClicked.bind="onCellClicked"
@@ -1062,7 +1056,7 @@
1062
1056
  t-on-contextmenu.stop.prevent="onContextMenu">
1063
1057
  <FiguresContainer onFigureDeleted="props.onFigureDeleted"/>
1064
1058
  <DataValidationOverlay/>
1065
- <FilterIconsOverlay onMouseDown="(ev) => this.onMouseDown(ev, {closePopover: false})"/>
1059
+ <FilterIconsOverlay/>
1066
1060
  <GridAddRowsFooter
1067
1061
  t-if="!env.model.getters.isReadonly()"
1068
1062
  t-key="env.model.getters.getActiveSheetId()"
@@ -2541,55 +2535,41 @@
2541
2535
  </div>
2542
2536
  </t>
2543
2537
 
2544
- <t t-name="o-spreadsheet-BarChartDesignPanel">
2545
- <div>
2546
- <Section class="'o-chart-background-color'">
2547
- <t t-set-slot="title">Background color</t>
2548
- <div class="d-flex align-items-center">
2549
- <span class="me-2">Select a color...</span>
2550
- <RoundColorPicker
2551
- currentColor="props.definition.background"
2552
- onColorPicked.bind="updateBackgroundColor"
2553
- title="backgroundColorTitle"
2538
+ <t t-name="o-spreadsheet-AxisDesignEditor">
2539
+ <t t-set="editor_label">Axis title</t>
2540
+ <Section class="'py-0'">
2541
+ <select class="o-input o-axis-selector" t-on-change="this.updateAxisEditor">
2542
+ <t t-foreach="props.axesList" t-as="axis" t-key="axis.id">
2543
+ <option
2544
+ t-att-value="axis.id"
2545
+ t-att-selected="state.currentAxis === axis.id"
2546
+ t-esc="axis.name"
2554
2547
  />
2555
- </div>
2556
- </Section>
2557
- <ChartTitle title="title" update.bind="updateTitle"/>
2558
- <Section>
2559
- <t t-set-slot="title">Vertical axis position</t>
2560
- <select
2561
- t-att-value="props.definition.verticalAxisPosition"
2562
- class="o-input"
2563
- t-on-change="(ev) => this.updateSelect('verticalAxisPosition', ev)">
2564
- <option value="left">Left</option>
2565
- <option value="right">Right</option>
2566
- </select>
2567
- </Section>
2568
- <Section>
2569
- <t t-set-slot="title">Legend position</t>
2570
- <select
2571
- t-att-value="props.definition.legendPosition"
2572
- class="o-input"
2573
- t-on-change="(ev) => this.updateSelect('legendPosition', ev)">
2574
- <option value="none">None</option>
2575
- <option value="top">Top</option>
2576
- <option value="bottom">Bottom</option>
2577
- <option value="left">Left</option>
2578
- <option value="right">Right</option>
2579
- </select>
2580
- </Section>
2581
- </div>
2548
+ </t>
2549
+ </select>
2550
+ </Section>
2551
+ <ChartTitle
2552
+ title="this.getAxisTitle()"
2553
+ updateTitle.bind="updateAxisTitle"
2554
+ name="editor_label"
2555
+ toggleItalic.bind="toggleItalicAxisTitle"
2556
+ toggleBold.bind="toggleBoldAxisTitle"
2557
+ updateAlignment.bind="updateAxisTitleAlignment"
2558
+ updateColor.bind="updateAxisTitleColor"
2559
+ style="axisTitleStyle"
2560
+ />
2582
2561
  </t>
2583
2562
 
2584
2563
  <t t-name="o-spreadsheet.ChartDataSeries">
2585
2564
  <Section class="'o-data-series'">
2586
2565
  <t t-set-slot="title" t-esc="title"/>
2587
2566
  <SelectionInput
2588
- ranges="props.ranges"
2567
+ ranges="ranges"
2589
2568
  required="true"
2590
2569
  hasSingleRange="props.hasSingleRange"
2591
2570
  onSelectionChanged="(ranges) => props.onSelectionChanged(ranges)"
2592
2571
  onSelectionConfirmed="() => props.onSelectionConfirmed()"
2572
+ colors="colors"
2593
2573
  />
2594
2574
  </Section>
2595
2575
  </t>
@@ -2600,6 +2580,62 @@
2600
2580
  </Section>
2601
2581
  </t>
2602
2582
 
2583
+ <t t-name="o-spreadsheet-GeneralDesignEditor">
2584
+ <t t-set="chart_title">Chart title</t>
2585
+ <SidePanelCollapsible collapsedAtInit="false">
2586
+ <t t-set-slot="title">General</t>
2587
+ <t t-set-slot="content">
2588
+ <Section class="'o-chart-background-color pt-0 pb-0'">
2589
+ <div class="d-flex align-items-center mt-0">
2590
+ <span class="o-section-title mb-0 pe-2">Background color</span>
2591
+ <RoundColorPicker
2592
+ currentColor="props.definition.background"
2593
+ onColorPicked.bind="updateBackgroundColor"
2594
+ />
2595
+ </div>
2596
+ </Section>
2597
+ <ChartTitle
2598
+ title="title.text"
2599
+ updateTitle.bind="updateTitle"
2600
+ name="chart_title"
2601
+ toggleItalic.bind="toggleItalicChartTitle"
2602
+ toggleBold.bind="toggleBoldChartTitle"
2603
+ updateAlignment.bind="updateChartTitleAlignment"
2604
+ updateColor.bind="updateChartTitleColor"
2605
+ style="titleStyle"
2606
+ />
2607
+ <t t-slot="general-extension"/>
2608
+ </t>
2609
+ </SidePanelCollapsible>
2610
+ </t>
2611
+
2612
+ <t t-name="o-spreadsheet-GenericChartConfigPanel">
2613
+ <div>
2614
+ <ChartDataSeries
2615
+ ranges="this.getDataSeriesRanges()"
2616
+ onSelectionChanged="(ranges) => this.onDataSeriesRangesChanged(ranges)"
2617
+ onSelectionConfirmed="() => this.onDataSeriesConfirmed()"
2618
+ />
2619
+ <ChartLabelRange
2620
+ range="this.getLabelRange()"
2621
+ isInvalid="isLabelInvalid"
2622
+ onSelectionChanged="(ranges) => this.onLabelRangeChanged(ranges)"
2623
+ onSelectionConfirmed="() => this.onLabelRangeConfirmed()"
2624
+ options="this.getLabelRangeOptions()"
2625
+ />
2626
+ <Section class="'o-use-row-as-headers'" t-if="calculateHeaderPosition()">
2627
+ <Checkbox
2628
+ name="'dataSetsHaveTitle'"
2629
+ label="dataSetsHaveTitleLabel"
2630
+ value="props.definition.dataSetsHaveTitle"
2631
+ onChange.bind="onUpdateDataSetsHaveTitle"
2632
+ />
2633
+ </Section>
2634
+
2635
+ <ChartErrorSection t-if="errorMessages.length" messages="errorMessages"/>
2636
+ </div>
2637
+ </t>
2638
+
2603
2639
  <t t-name="o-spreadsheet.ChartLabelRange">
2604
2640
  <Section class="'o-data-labels'">
2605
2641
  <t t-set-slot="title" t-esc="props.title"/>
@@ -2623,9 +2659,12 @@
2623
2659
  </t>
2624
2660
 
2625
2661
  <t t-name="o-spreadsheet.ChartTitle">
2626
- <t t-set="placeholder">New Chart</t>
2627
- <Section class="'o-chart-title'">
2628
- <t t-set-slot="title">Title</t>
2662
+ <t t-set="placeholder">Add a title</t>
2663
+ <Section class="'o-chart-title pb-0'">
2664
+ <t t-set-slot="title">
2665
+ <t t-if="props.name" t-esc="props.name"/>
2666
+ <t t-else="">Title</t>
2667
+ </t>
2629
2668
  <input
2630
2669
  type="text"
2631
2670
  class="o-input o-optional"
@@ -2633,9 +2672,165 @@
2633
2672
  t-on-change="updateTitle"
2634
2673
  t-att-placeholder="placeholder"
2635
2674
  />
2675
+ <Section class="'pt-0 px-0'">
2676
+ <div class="o-chart-title-designer position-relative d-flex align-items-center">
2677
+ <span
2678
+ class="o-menu-item-button o-hoverable-button"
2679
+ title="Bold"
2680
+ t-att-class="{active: props.style.bold}"
2681
+ t-on-click="(ev) => this.props.toggleBold()">
2682
+ <span>
2683
+ <t t-call="o-spreadsheet-Icon.BOLD"/>
2684
+ </span>
2685
+ </span>
2686
+ <span
2687
+ class="o-menu-item-button o-hoverable-button"
2688
+ title="Italic"
2689
+ t-att-class="{active: props.style.italic}"
2690
+ t-on-click="(ev) => this.props.toggleItalic()">
2691
+ <span>
2692
+ <t t-call="o-spreadsheet-Icon.ITALIC"/>
2693
+ </span>
2694
+ </span>
2695
+ <span
2696
+ class="o-menu-item-button o-hoverable-button"
2697
+ title="Horizontal alignment"
2698
+ t-on-click="(ev) => this.toggleDropdownTool('horizontalChartAlignTool', ev)">
2699
+ <span>
2700
+ <t t-if="props.style.align === 'center'" t-call="o-spreadsheet-Icon.ALIGN_CENTER"/>
2701
+ <t t-elif="props.style.align === 'right'" t-call="o-spreadsheet-Icon.ALIGN_RIGHT"/>
2702
+ <t t-else="" t-call="o-spreadsheet-Icon.ALIGN_LEFT"/>
2703
+ </span>
2704
+ <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
2705
+ </span>
2706
+ <div
2707
+ class="o-dropdown-content position-absolute top-100 start-0 bg-white"
2708
+ t-if="state.activeTool === 'horizontalChartAlignTool'"
2709
+ t-on-click.stop="">
2710
+ <div class="o-dropdown-line d-flex">
2711
+ <span
2712
+ class="o-menu-item-button o-hoverable-button"
2713
+ t-att-class="{active: props.style.align === 'left'}"
2714
+ title="Left"
2715
+ t-on-click="(ev) => this.updateAlignment('left')">
2716
+ <span>
2717
+ <t t-call="o-spreadsheet-Icon.ALIGN_LEFT"/>
2718
+ </span>
2719
+ </span>
2720
+ <span
2721
+ class="o-menu-item-button o-hoverable-button"
2722
+ t-att-class="{active: props.style.align === 'center'}"
2723
+ title="Center"
2724
+ t-on-click="(ev) => this.updateAlignment('center')">
2725
+ <span>
2726
+ <t t-call="o-spreadsheet-Icon.ALIGN_CENTER"/>
2727
+ </span>
2728
+ </span>
2729
+ <span
2730
+ class="o-menu-item-button o-hoverable-button"
2731
+ t-att-class="{active: props.style.align === 'right'}"
2732
+ title="Right"
2733
+ t-on-click="(ev) => this.updateAlignment('right')">
2734
+ <span>
2735
+ <t t-call="o-spreadsheet-Icon.ALIGN_RIGHT"/>
2736
+ </span>
2737
+ </span>
2738
+ </div>
2739
+ </div>
2740
+ <ColorPickerWidget
2741
+ currentColor="props.style.color"
2742
+ toggleColorPicker="(ev) => this.toggleDropdownTool('fillChartColorTool', ev)"
2743
+ showColorPicker="state.activeTool === 'fillChartColorTool'"
2744
+ onColorPicked.bind="onColorPicked"
2745
+ title="fill_color"
2746
+ icon="'o-spreadsheet-Icon.TEXT_COLOR'"
2747
+ class="'o-hoverable-button o-menu-item-button'"
2748
+ />
2749
+ </div>
2750
+ </Section>
2636
2751
  </Section>
2637
2752
  </t>
2638
2753
 
2754
+ <t t-name="o-spreadsheet-ChartWithAxisDesignPanel">
2755
+ <GeneralDesignEditor
2756
+ figureId="props.figureId"
2757
+ definition="props.definition"
2758
+ updateChart="props.updateChart">
2759
+ <t t-set-slot="general-extension">
2760
+ <Section class="'pt-0'">
2761
+ <t t-set-slot="title">Legend position</t>
2762
+ <select
2763
+ t-att-value="props.definition.legendPosition ?? 'top'"
2764
+ class="o-input"
2765
+ t-on-change="this.updateLegendPosition">
2766
+ <option value="none">None</option>
2767
+ <option value="top">Top</option>
2768
+ <option value="bottom">Bottom</option>
2769
+ <option value="left">Left</option>
2770
+ <option value="right">Right</option>
2771
+ </select>
2772
+ </Section>
2773
+ </t>
2774
+ </GeneralDesignEditor>
2775
+ <SidePanelCollapsible collapsedAtInit="true">
2776
+ <t t-set-slot="title">Data series</t>
2777
+ <t t-set-slot="content">
2778
+ <Section class="'pt-0 pb-0'">
2779
+ <select
2780
+ class="o-input data-series-selector"
2781
+ t-model="state.label"
2782
+ t-on-change="(ev) => this.updateSerieEditor(ev)">
2783
+ <t t-foreach="getDataSeries()" t-as="serie" t-key="serie" t-index="index">
2784
+ <option
2785
+ t-att-value="serie"
2786
+ t-att-selected="state.index === serie_index"
2787
+ t-esc="serie"
2788
+ />
2789
+ </t>
2790
+ </select>
2791
+ <Section class="'px-0'">
2792
+ <div class="d-flex align-items-center">
2793
+ <span class="o-section-title mb-0 pe-2">Series color</span>
2794
+ <RoundColorPicker
2795
+ currentColor="getDataSerieColor()"
2796
+ onColorPicked.bind="updateDataSeriesColor"
2797
+ />
2798
+ </div>
2799
+ </Section>
2800
+ <Section class="'pt-0 px-0'">
2801
+ <t t-set-slot="title">Vertical axis</t>
2802
+ <select
2803
+ t-att-value="getDataSerieAxis()"
2804
+ class="o-input o-vertical-axis-selection"
2805
+ t-on-change="(ev) => this.updateDataSeriesAxis(ev)">
2806
+ <option value="left">Left</option>
2807
+ <option value="right">Right</option>
2808
+ </select>
2809
+ </Section>
2810
+ <Section class="'pt-0 px-0'">
2811
+ <t t-set-slot="title">Series name</t>
2812
+ <input
2813
+ class="o-input o-serie-label-editor"
2814
+ t-att-value="getDataSerieLabel()"
2815
+ t-on-change="(ev) => this.updateDataSeriesLabel(ev)"
2816
+ />
2817
+ </Section>
2818
+ </Section>
2819
+ </t>
2820
+ </SidePanelCollapsible>
2821
+ <SidePanelCollapsible collapsedAtInit="true">
2822
+ <t t-set-slot="title">Axis</t>
2823
+ <t t-set-slot="content">
2824
+ <AxisDesignEditor
2825
+ axesList="axesList"
2826
+ figureId="props.figureId"
2827
+ definition="props.definition"
2828
+ updateChart="props.updateChart"
2829
+ />
2830
+ </t>
2831
+ </SidePanelCollapsible>
2832
+ </t>
2833
+
2639
2834
  <t t-name="o-spreadsheet-ComboChartConfigPanel">
2640
2835
  <div>
2641
2836
  <ChartDataSeries
@@ -2650,14 +2845,6 @@
2650
2845
  onSelectionConfirmed="() => this.onLabelRangeConfirmed()"
2651
2846
  options="this.getLabelRangeOptions()"
2652
2847
  />
2653
- <Section class="'o-use-right-axis py-0'">
2654
- <Checkbox
2655
- name="'shouldUseRightAxis'"
2656
- label="shouldUseRightAxis"
2657
- value="props.definition.useBothYAxis"
2658
- onChange.bind="onUpdateUseRightAxis"
2659
- />
2660
- </Section>
2661
2848
  <Section class="'o-use-row-as-headers py-0'" t-if="calculateHeaderPosition()">
2662
2849
  <Checkbox
2663
2850
  name="'dataSetsHaveTitle'"
@@ -2671,46 +2858,6 @@
2671
2858
  </div>
2672
2859
  </t>
2673
2860
 
2674
- <t t-name="o-spreadsheet-ComboChartDesignPanel">
2675
- <div>
2676
- <Section class="'o-chart-background-color'">
2677
- <t t-set-slot="title">Background color</t>
2678
- <div class="d-flex align-items-center">
2679
- <span class="me-2">Select a color...</span>
2680
- <RoundColorPicker
2681
- currentColor="props.definition.background"
2682
- onColorPicked.bind="updateBackgroundColor"
2683
- title="backgroundColorTitle"
2684
- />
2685
- </div>
2686
- </Section>
2687
- <ChartTitle title="title" update.bind="updateTitle"/>
2688
- <Section t-if="!props.definition.useBothYAxis">
2689
- <t t-set-slot="title">Vertical axis position</t>
2690
- <select
2691
- t-att-value="props.definition.verticalAxisPosition"
2692
- class="o-input"
2693
- t-on-change="(ev) => this.updateSelect('verticalAxisPosition', ev)">
2694
- <option value="left">Left</option>
2695
- <option value="right">Right</option>
2696
- </select>
2697
- </Section>
2698
- <Section>
2699
- <t t-set-slot="title">Legend position</t>
2700
- <select
2701
- t-att-value="props.definition.legendPosition"
2702
- class="o-input"
2703
- t-on-change="(ev) => this.updateSelect('legendPosition', ev)">
2704
- <option value="none">None</option>
2705
- <option value="top">Top</option>
2706
- <option value="bottom">Bottom</option>
2707
- <option value="left">Left</option>
2708
- <option value="right">Right</option>
2709
- </select>
2710
- </Section>
2711
- </div>
2712
- </t>
2713
-
2714
2861
  <t t-name="o-spreadsheet-GaugeChartConfigPanel">
2715
2862
  <div>
2716
2863
  <ChartDataSeries
@@ -2728,52 +2875,48 @@
2728
2875
  </t>
2729
2876
 
2730
2877
  <t t-name="o-spreadsheet-GaugeChartDesignPanel">
2731
- <div>
2732
- <Section class="'o-chart-background-color'">
2733
- <t t-set-slot="title">Background color</t>
2734
- <div class="d-flex align-items-center">
2735
- <span class="me-2">Select a color...</span>
2736
- <RoundColorPicker
2737
- currentColor="props.definition.background"
2738
- onColorPicked.bind="updateBackgroundColor"
2739
- title="backgroundColorTitle"
2740
- />
2741
- </div>
2742
- </Section>
2743
- <ChartTitle title="title" update.bind="updateTitle"/>
2744
- <Section>
2745
- <t t-set-slot="title">Range</t>
2746
- <div class="o-subsection-left">
2747
- <input
2748
- type="text"
2749
- t-model="state.sectionRule.rangeMin"
2750
- t-on-change="() => this.updateSectionRule(state.sectionRule)"
2751
- t-on-input="() => this.canUpdateSectionRule(state.sectionRule)"
2752
- class="o-input o-data-range-min"
2753
- t-att-class="{ 'o-invalid': isRangeMinInvalid() }"
2754
- />
2755
- </div>
2756
- <div class="o-subsection-right">
2757
- <input
2758
- type="text"
2759
- t-model="state.sectionRule.rangeMax"
2760
- t-on-change="() => this.updateSectionRule(state.sectionRule)"
2761
- t-on-input="() => this.canUpdateSectionRule(state.sectionRule)"
2762
- class="o-input o-data-range-max"
2763
- t-att-class="{ 'o-invalid': isRangeMaxInvalid() }"
2764
- />
2765
- </div>
2766
- </Section>
2878
+ <GeneralDesignEditor
2879
+ figureId="props.figureId"
2880
+ definition="props.definition"
2881
+ updateChart="props.updateChart"
2882
+ />
2883
+ <SidePanelCollapsible collapsedAtInit="true">
2884
+ <t t-set-slot="title">Gauge Design</t>
2885
+ <t t-set-slot="content">
2886
+ <Section class="'pt-0'">
2887
+ <t t-set-slot="title">Range</t>
2888
+ <div class="o-subsection-left">
2889
+ <input
2890
+ type="text"
2891
+ t-model="state.sectionRule.rangeMin"
2892
+ t-on-change="() => this.updateSectionRule(state.sectionRule)"
2893
+ t-on-input="() => this.canUpdateSectionRule(state.sectionRule)"
2894
+ class="o-input o-data-range-min"
2895
+ t-att-class="{ 'o-invalid': isRangeMinInvalid() }"
2896
+ />
2897
+ </div>
2898
+ <div class="o-subsection-right">
2899
+ <input
2900
+ type="text"
2901
+ t-model="state.sectionRule.rangeMax"
2902
+ t-on-change="() => this.updateSectionRule(state.sectionRule)"
2903
+ t-on-input="() => this.canUpdateSectionRule(state.sectionRule)"
2904
+ class="o-input o-data-range-max"
2905
+ t-att-class="{ 'o-invalid': isRangeMaxInvalid() }"
2906
+ />
2907
+ </div>
2908
+ </Section>
2767
2909
 
2768
- <Section>
2769
- <t t-set-slot="title">Thresholds</t>
2770
- <t t-call="o-spreadsheet-GaugeChartColorSectionTemplate">
2771
- <t t-set="sectionRule" t-value="state.sectionRule"/>
2772
- </t>
2773
- </Section>
2910
+ <Section>
2911
+ <t t-set-slot="title">Thresholds</t>
2912
+ <t t-call="o-spreadsheet-GaugeChartColorSectionTemplate">
2913
+ <t t-set="sectionRule" t-value="state.sectionRule"/>
2914
+ </t>
2915
+ </Section>
2774
2916
 
2775
- <ChartErrorSection t-if="designErrorMessages.length" messages="designErrorMessages"/>
2776
- </div>
2917
+ <ChartErrorSection t-if="designErrorMessages.length" messages="designErrorMessages"/>
2918
+ </t>
2919
+ </SidePanelCollapsible>
2777
2920
  </t>
2778
2921
 
2779
2922
  <t t-name="o-spreadsheet-GaugeChartColorSectionTemplate">
@@ -2851,63 +2994,6 @@
2851
2994
  </tr>
2852
2995
  </t>
2853
2996
 
2854
- <t t-name="o-spreadsheet-GenericChartConfigPanel">
2855
- <div>
2856
- <ChartDataSeries
2857
- ranges="this.getDataSeriesRanges()"
2858
- onSelectionChanged="(ranges) => this.onDataSeriesRangesChanged(ranges)"
2859
- onSelectionConfirmed="() => this.onDataSeriesConfirmed()"
2860
- />
2861
- <ChartLabelRange
2862
- range="this.getLabelRange()"
2863
- isInvalid="isLabelInvalid"
2864
- onSelectionChanged="(ranges) => this.onLabelRangeChanged(ranges)"
2865
- onSelectionConfirmed="() => this.onLabelRangeConfirmed()"
2866
- options="this.getLabelRangeOptions()"
2867
- />
2868
- <Section class="'o-use-row-as-headers'" t-if="calculateHeaderPosition()">
2869
- <Checkbox
2870
- name="'dataSetsHaveTitle'"
2871
- label="dataSetsHaveTitleLabel"
2872
- value="props.definition.dataSetsHaveTitle"
2873
- onChange.bind="onUpdateDataSetsHaveTitle"
2874
- />
2875
- </Section>
2876
-
2877
- <ChartErrorSection t-if="errorMessages.length" messages="errorMessages"/>
2878
- </div>
2879
- </t>
2880
-
2881
- <t t-name="o-spreadsheet-GenericChartDesignPanel">
2882
- <div>
2883
- <Section class="'o-chart-background-color'">
2884
- <t t-set-slot="title">Background color</t>
2885
- <div class="d-flex align-items-center">
2886
- <span class="me-2">Select a color...</span>
2887
- <RoundColorPicker
2888
- currentColor="props.definition.background"
2889
- onColorPicked.bind="updateBackgroundColor"
2890
- title="backgroundColorTitle"
2891
- />
2892
- </div>
2893
- </Section>
2894
- <ChartTitle title="title" update.bind="updateTitle"/>
2895
- <Section>
2896
- <t t-set-slot="title">Legend position</t>
2897
- <select
2898
- t-att-value="props.definition.legendPosition"
2899
- class="o-input"
2900
- t-on-change="(ev) => this.updateSelect('legendPosition', ev)">
2901
- <option value="none">None</option>
2902
- <option value="top">Top</option>
2903
- <option value="bottom">Bottom</option>
2904
- <option value="left">Left</option>
2905
- <option value="right">Right</option>
2906
- </select>
2907
- </Section>
2908
- </div>
2909
- </t>
2910
-
2911
2997
  <t t-name="o-spreadsheet-LineConfigPanel">
2912
2998
  <div>
2913
2999
  <Section class="'pt-0'">
@@ -2949,46 +3035,6 @@
2949
3035
  </div>
2950
3036
  </t>
2951
3037
 
2952
- <t t-name="o-spreadsheet-LineChartDesignPanel">
2953
- <div>
2954
- <Section class="'o-chart-background-color'">
2955
- <t t-set-slot="title">Background color</t>
2956
- <div class="d-flex align-items-center">
2957
- <span class="me-2">Select a color...</span>
2958
- <RoundColorPicker
2959
- currentColor="props.definition.background"
2960
- onColorPicked.bind="updateBackgroundColor"
2961
- title="backgroundColorTitle"
2962
- />
2963
- </div>
2964
- </Section>
2965
- <ChartTitle title="title" update.bind="updateTitle"/>
2966
- <Section>
2967
- <t t-set-slot="title">Vertical axis position</t>
2968
- <select
2969
- t-att-value="props.definition.verticalAxisPosition"
2970
- class="o-input"
2971
- t-on-change="(ev) => this.updateSelect('verticalAxisPosition', ev)">
2972
- <option value="left">Left</option>
2973
- <option value="right">Right</option>
2974
- </select>
2975
- </Section>
2976
- <Section>
2977
- <t t-set-slot="title">Legend position</t>
2978
- <select
2979
- t-att-value="props.definition.legendPosition"
2980
- class="o-input"
2981
- t-on-change="(ev) => this.updateSelect('legendPosition', ev)">
2982
- <option value="none">None</option>
2983
- <option value="top">Top</option>
2984
- <option value="bottom">Bottom</option>
2985
- <option value="left">Left</option>
2986
- <option value="right">Right</option>
2987
- </select>
2988
- </Section>
2989
- </div>
2990
- </t>
2991
-
2992
3038
  <t t-name="o-spreadsheet-ChartPanel">
2993
3039
  <div class="o-chart" t-if="figureId">
2994
3040
  <div class="o-panel">
@@ -3048,6 +3094,29 @@
3048
3094
  </div>
3049
3095
  </t>
3050
3096
 
3097
+ <t t-name="o-spreadsheet-PieChartDesignPanel">
3098
+ <GeneralDesignEditor
3099
+ figureId="props.figureId"
3100
+ definition="props.definition"
3101
+ updateChart="props.updateChart">
3102
+ <t t-set-slot="general-extension">
3103
+ <Section class="'pt-0'">
3104
+ <t t-set-slot="title">Legend position</t>
3105
+ <select
3106
+ t-att-value="props.definition.legendPosition ?? 'top'"
3107
+ class="o-input"
3108
+ t-on-change="(ev) => this.updateLegendPosition(ev)">
3109
+ <option value="none">None</option>
3110
+ <option value="top">Top</option>
3111
+ <option value="bottom">Bottom</option>
3112
+ <option value="left">Left</option>
3113
+ <option value="right">Right</option>
3114
+ </select>
3115
+ </Section>
3116
+ </t>
3117
+ </GeneralDesignEditor>
3118
+ </t>
3119
+
3051
3120
  <t t-name="o-spreadsheet-ScatterConfigPanel">
3052
3121
  <div>
3053
3122
  <ChartDataSeries
@@ -3118,144 +3187,152 @@
3118
3187
  <t t-name="o-spreadsheet-ScorecardChartDesignPanel">
3119
3188
  <t t-set="color_up">Color Up</t>
3120
3189
  <t t-set="color_down">Color Down</t>
3121
- <div>
3122
- <Section class="'o-chart-background-color'">
3123
- <t t-set-slot="title">Background color</t>
3124
- <div class="d-flex align-items-center">
3125
- <span class="me-2">Select a color...</span>
3126
- <RoundColorPicker
3127
- currentColor="props.definition.background"
3128
- onColorPicked="(color) => this.setColor(color, 'backgroundColor')"
3129
- title="backgroundColorTitle"
3190
+ <GeneralDesignEditor
3191
+ figureId="props.figureId"
3192
+ definition="props.definition"
3193
+ updateChart="props.updateChart">
3194
+ <t t-set-slot="general-extension">
3195
+ <Section class="'pt-1'">
3196
+ <t t-set-slot="title">Number formatting</t>
3197
+ <Checkbox
3198
+ name="'humanizeNumbers'"
3199
+ label="humanizeNumbersLabel"
3200
+ value="props.definition.humanize"
3201
+ onChange.bind="updateHumanizeNumbers"
3130
3202
  />
3131
- </div>
3132
- </Section>
3133
- <ChartTitle title="title" update.bind="updateTitle"/>
3134
- <Section>
3135
- <t t-set-slot="title">Baseline description</t>
3136
- <input
3137
- type="text"
3138
- t-att-value="translate(props.definition.baselineDescr)"
3139
- t-on-change="updateBaselineDescr"
3140
- class="o-input o-optional"
3141
- />
3142
- </Section>
3143
- </div>
3144
- <Section class="'o-chart-baseline-color'">
3145
- <t t-set-slot="title" t-esc="colorsSectionTitle"/>
3146
- <div class="d-flex align-items-center mb-2">
3147
- <RoundColorPicker
3148
- currentColor="props.definition.baselineColorUp"
3149
- onColorPicked="(color) => this.setColor(color, 'baselineColorUp')"
3150
- title="color_up"
3151
- />
3152
- <span class="ps-2">Color on value increase</span>
3153
- </div>
3154
- <div class="d-flex align-items-center">
3155
- <RoundColorPicker
3156
- currentColor="props.definition.baselineColorDown"
3157
- onColorPicked="(color) => this.setColor(color, 'baselineColorDown')"
3158
- title="color_down"
3159
- />
3160
- <span class="ps-2">Color on value decrease</span>
3161
- </div>
3162
- </Section>
3163
- <Section class="'pt-1'">
3164
- <t t-set-slot="title">Number formatting</t>
3165
- <Checkbox
3166
- name="'humanizeNumbers'"
3167
- label="humanizeNumbersLabel"
3168
- value="props.definition.humanize"
3169
- onChange.bind="updateHumanizeNumbers"
3170
- />
3171
- </Section>
3203
+ </Section>
3204
+ </t>
3205
+ </GeneralDesignEditor>
3206
+ <SidePanelCollapsible collapsedAtInit="true">
3207
+ <t t-set-slot="title">Baseline</t>
3208
+ <t t-set-slot="content">
3209
+ <Section>
3210
+ <t t-set-slot="title">Baseline description</t>
3211
+ <input
3212
+ type="text"
3213
+ t-att-value="translate(props.definition.baselineDescr)"
3214
+ t-on-change="updateBaselineDescr"
3215
+ class="o-input o-optional"
3216
+ />
3217
+ </Section>
3218
+ <Section class="'o-chart-baseline-color'">
3219
+ <t t-set-slot="title" t-esc="colorsSectionTitle"/>
3220
+ <div class="d-flex align-items-center mb-2">
3221
+ <RoundColorPicker
3222
+ currentColor="props.definition.baselineColorUp"
3223
+ onColorPicked="(color) => this.setColor(color, 'baselineColorUp')"
3224
+ title="color_up"
3225
+ />
3226
+ <span class="ps-2">Color on value increase</span>
3227
+ </div>
3228
+ <div class="d-flex align-items-center">
3229
+ <RoundColorPicker
3230
+ currentColor="props.definition.baselineColorDown"
3231
+ onColorPicked="(color) => this.setColor(color, 'baselineColorDown')"
3232
+ title="color_down"
3233
+ />
3234
+ <span class="ps-2">Color on value decrease</span>
3235
+ </div>
3236
+ </Section>
3237
+ </t>
3238
+ </SidePanelCollapsible>
3172
3239
  </t>
3173
3240
 
3174
3241
  <t t-name="o-spreadsheet-WaterfallChartDesignPanel">
3175
- <div>
3176
- <Section class="'o-chart-background-color'">
3177
- <t t-set-slot="title">Background color</t>
3178
- <div class="d-flex align-items-center">
3179
- <span class="me-2">Select a color...</span>
3180
- <RoundColorPicker
3181
- currentColor="props.definition.background"
3182
- onColorPicked="(color) => this.updateColor('background', color)"
3183
- />
3184
- </div>
3185
- </Section>
3186
- <ChartTitle title="title" update.bind="updateTitle"/>
3187
- <Section>
3188
- <t t-set-slot="title">Vertical axis position</t>
3189
- <select
3190
- t-att-value="props.definition.verticalAxisPosition"
3191
- class="o-input o-chart-vertical-axis-position"
3192
- t-on-change="(ev) => this.updateSelect('verticalAxisPosition', ev)">
3193
- <option value="left">Left</option>
3194
- <option value="right">Right</option>
3195
- </select>
3196
- </Section>
3197
- <Section>
3198
- <t t-set-slot="title">Legend position</t>
3199
- <select
3200
- t-att-value="props.definition.legendPosition"
3201
- class="o-input o-chart-legend-position"
3202
- t-on-change="(ev) => this.updateSelect('legendPosition', ev)">
3203
- <option value="none">None</option>
3204
- <option value="top">Top</option>
3205
- <option value="bottom">Bottom</option>
3206
- <option value="left">Left</option>
3207
- <option value="right">Right</option>
3208
- </select>
3209
- </Section>
3210
- <Section>
3211
- <t t-set-slot="title">Waterfall options</t>
3212
- <t t-set="firstValueAsSubtotal">Use first value as subtotal</t>
3213
- <Checkbox
3214
- name="'firstValueAsSubtotal'"
3215
- label="firstValueAsSubtotal"
3216
- value="props.definition.firstValueAsSubtotal"
3217
- onChange.bind="onUpdateFirstValueAsSubtotal"
3218
- />
3219
- <t t-set="showSubTotalsLabel">Show subtotals at the end of series</t>
3220
- <Checkbox
3221
- name="'showSubTotals'"
3222
- label="showSubTotalsLabel"
3223
- value="props.definition.showSubTotals"
3224
- onChange.bind="onUpdateShowSubTotals"
3225
- />
3226
- <t t-set="showConnectorLinesLabel">Show connector lines</t>
3227
- <Checkbox
3228
- name="'showConnectorLines'"
3229
- label="showConnectorLinesLabel"
3230
- value="props.definition.showConnectorLines"
3231
- onChange.bind="onUpdateShowConnectorLines"
3232
- />
3233
- </Section>
3234
- <Section>
3235
- <t t-set-slot="title">Waterfall colors</t>
3236
- <div class="o-waterfall-positive-color d-flex align-items-center mb-1">
3237
- <RoundColorPicker
3238
- currentColor="positiveValuesColor"
3239
- onColorPicked="(color) => this.updateColor('positiveValuesColor', color)"
3242
+ <GeneralDesignEditor
3243
+ figureId="props.figureId"
3244
+ definition="props.definition"
3245
+ updateChart="props.updateChart">
3246
+ <t t-set-slot="general-extension">
3247
+ <Section>
3248
+ <t t-set-slot="title">Vertical axis position</t>
3249
+ <select
3250
+ t-att-value="props.definition.verticalAxisPosition"
3251
+ class="o-input o-chart-vertical-axis-position"
3252
+ t-on-change="(ev) => this.updateVerticalAxisPosition(ev)">
3253
+ <option value="left">Left</option>
3254
+ <option value="right">Right</option>
3255
+ </select>
3256
+ </Section>
3257
+ <Section>
3258
+ <t t-set-slot="title">Legend position</t>
3259
+ <select
3260
+ t-att-value="props.definition.legendPosition"
3261
+ class="o-input o-chart-legend-position"
3262
+ t-on-change="(ev) => this.updateLegendPosition(ev)">
3263
+ <option value="none">None</option>
3264
+ <option value="top">Top</option>
3265
+ <option value="bottom">Bottom</option>
3266
+ <option value="left">Left</option>
3267
+ <option value="right">Right</option>
3268
+ </select>
3269
+ </Section>
3270
+ </t>
3271
+ </GeneralDesignEditor>
3272
+ <SidePanelCollapsible collapsedAtInit="true">
3273
+ <t t-set-slot="title">Waterfall design</t>
3274
+ <t t-set-slot="content">
3275
+ <Section class="'pt-0'">
3276
+ <t t-set-slot="title">Waterfall options</t>
3277
+ <t t-set="firstValueAsSubtotal">Use first value as subtotal</t>
3278
+ <Checkbox
3279
+ name="'firstValueAsSubtotal'"
3280
+ label="firstValueAsSubtotal"
3281
+ value="props.definition.firstValueAsSubtotal"
3282
+ onChange.bind="onUpdateFirstValueAsSubtotal"
3240
3283
  />
3241
- <span class="ps-2">Color of positive values</span>
3242
- </div>
3243
- <div class="o-waterfall-negative-color d-flex align-items-center mb-1">
3244
- <RoundColorPicker
3245
- currentColor="negativeValuesColor"
3246
- onColorPicked="(color) => this.updateColor('negativeValuesColor', color)"
3284
+ <t t-set="showSubTotalsLabel">Show subtotals at the end of series</t>
3285
+ <Checkbox
3286
+ name="'showSubTotals'"
3287
+ label="showSubTotalsLabel"
3288
+ value="props.definition.showSubTotals"
3289
+ onChange.bind="onUpdateShowSubTotals"
3247
3290
  />
3248
- <span class="ps-2">Color of negative values</span>
3249
- </div>
3250
- <div class="o-waterfall-subtotal-color d-flex align-items-center">
3251
- <RoundColorPicker
3252
- currentColor="subTotalValuesColor"
3253
- onColorPicked="(color) => this.updateColor('subTotalValuesColor', color)"
3291
+ <t t-set="showConnectorLinesLabel">Show connector lines</t>
3292
+ <Checkbox
3293
+ name="'showConnectorLines'"
3294
+ label="showConnectorLinesLabel"
3295
+ value="props.definition.showConnectorLines"
3296
+ onChange.bind="onUpdateShowConnectorLines"
3254
3297
  />
3255
- <span class="ps-2">Color of subtotals</span>
3256
- </div>
3257
- </Section>
3258
- </div>
3298
+ </Section>
3299
+ <Section>
3300
+ <t t-set-slot="title">Waterfall colors</t>
3301
+ <div class="o-waterfall-positive-color d-flex align-items-center mb-1">
3302
+ <RoundColorPicker
3303
+ currentColor="positiveValuesColor"
3304
+ onColorPicked="(color) => this.updateColor('positiveValuesColor', color)"
3305
+ />
3306
+ <span class="ps-2">Color of positive values</span>
3307
+ </div>
3308
+ <div class="o-waterfall-negative-color d-flex align-items-center mb-1">
3309
+ <RoundColorPicker
3310
+ currentColor="negativeValuesColor"
3311
+ onColorPicked="(color) => this.updateColor('negativeValuesColor', color)"
3312
+ />
3313
+ <span class="ps-2">Color of negative values</span>
3314
+ </div>
3315
+ <div class="o-waterfall-subtotal-color d-flex align-items-center">
3316
+ <RoundColorPicker
3317
+ currentColor="subTotalValuesColor"
3318
+ onColorPicked="(color) => this.updateColor('subTotalValuesColor', color)"
3319
+ />
3320
+ <span class="ps-2">Color of subtotals</span>
3321
+ </div>
3322
+ </Section>
3323
+ </t>
3324
+ </SidePanelCollapsible>
3325
+ <SidePanelCollapsible collapsedAtInit="true">
3326
+ <t t-set-slot="title">Axis title</t>
3327
+ <t t-set-slot="content">
3328
+ <AxisDesignEditor
3329
+ axesList="axesList"
3330
+ figureId="props.figureId"
3331
+ definition="props.definition"
3332
+ updateChart="props.updateChart"
3333
+ />
3334
+ </t>
3335
+ </SidePanelCollapsible>
3259
3336
  </t>
3260
3337
 
3261
3338
  <t t-name="o-spreadsheet.Checkbox">
@@ -3276,6 +3353,27 @@
3276
3353
  </label>
3277
3354
  </t>
3278
3355
 
3356
+ <t t-name="o-spreadsheet-SidePanelCollapsible">
3357
+ <div class="p-1 m-1" t-att-class="props.class">
3358
+ <div class="o_side_panel_collapsible_title d-flex align-items-center">
3359
+ <span
3360
+ t-att-id="'btn-collapse-'+currentId"
3361
+ t-att-class="{ 'collapsed': props.collapsedAtInit }"
3362
+ class="collapsor w-100"
3363
+ data-bs-toggle="collapse"
3364
+ t-att-data-bs-target="'#box-collapse-'+currentId">
3365
+ <t t-slot="title"/>
3366
+ </span>
3367
+ </div>
3368
+ <div
3369
+ t-att-id="'box-collapse-'+currentId"
3370
+ t-att-class="{'show': !props.collapsedAtInit}"
3371
+ class="collapsible_section collapse">
3372
+ <t t-slot="content"/>
3373
+ </div>
3374
+ </div>
3375
+ </t>
3376
+
3279
3377
  <t t-name="o-spreadsheet.RoundColorPicker">
3280
3378
  <div
3281
3379
  class="o-round-color-picker-button rounded-circle"
@@ -4170,18 +4268,6 @@
4170
4268
  </div>
4171
4269
  </t>
4172
4270
 
4173
- <div t-name="o-spreadsheet-AllPivotsSidePanel" class="o_spreadsheet_pivot_side_panel">
4174
- <t t-foreach="env.model.getters.getPivotIds()" t-as="pivotId" t-key="pivotId">
4175
- <PivotPreview pivotId="pivotId"/>
4176
- </t>
4177
- </div>
4178
-
4179
- <t t-name="o-spreadsheet-PivotPreview">
4180
- <div class="o_side_panel_select" t-ref="pivotPreview" t-on-click="this.selectPivot">
4181
- <span t-esc="env.model.getters.getPivotDisplayName(props.pivotId)"/>
4182
- </div>
4183
- </t>
4184
-
4185
4271
  <t t-name="o-spreadsheet-EditableName">
4186
4272
  <t t-if="state.isEditing">
4187
4273
  <div>
@@ -4205,32 +4291,31 @@
4205
4291
  Add
4206
4292
  </span>
4207
4293
  <Popover t-if="popover.isOpen" t-props="popoverProps">
4208
- <div class="p-2 bg-white border-bottom d-flex align-items-baseline pivot-dimension-search">
4294
+ <div
4295
+ class="p-2 bg-white border-bottom d-flex sticky-top align-items-baseline pivot-dimension-search">
4209
4296
  <i class="pe-1 pivot-dimension-search-field-icon">
4210
4297
  <t t-call="o-spreadsheet-Icon.SEARCH"/>
4211
4298
  </i>
4212
4299
  <input
4213
- t-model="search.input"
4300
+ t-on-input="(ev) => this.updateSearch(ev.target.value)"
4214
4301
  t-on-keydown="onKeyDown"
4215
4302
  class="border-0 w-100 pivot-dimension-search-field"
4216
- autofocus="1"
4303
+ t-ref="autofocus"
4217
4304
  />
4218
4305
  </div>
4219
- <div
4220
- t-foreach="filteredFields"
4221
- t-as="field"
4222
- t-key="field.name"
4223
- t-esc="field.string"
4224
- t-att-title="field.help"
4225
- t-on-click="() => this.pickField(field)"
4226
- class="p-1 px-2 pivot-dimension-field"
4227
- role="button"
4306
+ <TextValueProvider
4307
+ proposals="autoComplete.provider.proposals"
4308
+ selectedIndex="autoComplete.selectedIndex"
4309
+ onValueSelected="autoComplete.provider.selectProposal"
4310
+ onValueHovered="() => {}"
4228
4311
  />
4229
4312
  </Popover>
4230
4313
  </t>
4231
4314
 
4232
4315
  <t t-name="o-spreadsheet-PivotDimension">
4233
- <div class="border py-1 px-2 d-flex flex-column shadow-sm pivot-dimension">
4316
+ <div
4317
+ class="border py-1 px-2 d-flex flex-column shadow-sm pivot-dimension"
4318
+ t-att-class="{'bg-danger': !props.dimension.isValid}">
4234
4319
  <div class="d-flex flex-row justify-content-between align-items-center">
4235
4320
  <span class="fw-bold" t-esc="props.dimension.displayName"/>
4236
4321
  <i
@@ -4252,7 +4337,7 @@
4252
4337
  class="o_input flex-basis-50"
4253
4338
  t-on-change="(ev) => props.onUpdated(props.dimension, ev.target.value)">
4254
4339
  <option
4255
- t-foreach="allGranularities"
4340
+ t-foreach="props.allGranularities"
4256
4341
  t-as="granularity"
4257
4342
  t-key="granularity"
4258
4343
  t-if="props.availableGranularities.has(granularity) || granularity === props.dimension.granularity"
@@ -4272,17 +4357,23 @@
4272
4357
  <select
4273
4358
  class="o_input flex-basis-50"
4274
4359
  t-on-change="(ev) => props.onUpdated(props.dimension, ev.target.value)">
4275
- <option value="" t-att-selected="props.dimension.order === undefined">Automatic</option>
4276
4360
  <option value="asc" t-att-selected="props.dimension.order === 'asc'">Ascending</option>
4277
4361
  <option value="desc" t-att-selected="props.dimension.order === 'desc'">Descending</option>
4362
+ <option
4363
+ t-if="props.dimension.type !== 'date'"
4364
+ value=""
4365
+ t-att-selected="props.dimension.order === undefined">
4366
+ Unsorted
4367
+ </option>
4278
4368
  </select>
4279
4369
  </div>
4280
4370
  </div>
4281
4371
  </t>
4282
4372
 
4283
- <t t-name="o-spreadsheet-PivotDimensions">
4284
- <div class="o_side_panel_section pivot-dimensions" t-ref="pivot-dimensions">
4285
- <div class="fw-bold py-1 d-flex flex-row justify-content-between align-items-center">
4373
+ <t t-name="o-spreadsheet-PivotLayoutConfigurator">
4374
+ <div class="o_side_panel_section pivot-dimensions o-section" t-ref="pivot-dimensions">
4375
+ <div
4376
+ class="fw-bold py-1 d-flex flex-row justify-content-between align-items-center o-section-title">
4286
4377
  Columns
4287
4378
  <AddDimensionButton
4288
4379
  onFieldPicked.bind="addColumnDimension"
@@ -4300,13 +4391,14 @@
4300
4391
  dimension="col"
4301
4392
  onUpdated.bind="this.updateGranularity"
4302
4393
  availableGranularities="props.unusedDateTimeGranularities[col.name]"
4394
+ allGranularities="props.allGranularities"
4303
4395
  />
4304
4396
  <PivotDimensionOrder dimension="col" onUpdated.bind="this.updateOrder"/>
4305
4397
  </PivotDimension>
4306
4398
  </div>
4307
4399
  </t>
4308
4400
  <div
4309
- class="fw-bold pt-4 pb-1 d-flex flex-row justify-content-between align-items-center"
4401
+ class="fw-bold pt-4 pb-1 d-flex flex-row justify-content-between align-items-center o-section-title"
4310
4402
  t-att-style="dragAndDrop.itemsStyle['__rows_title__']">
4311
4403
  Rows
4312
4404
  <AddDimensionButton
@@ -4325,12 +4417,14 @@
4325
4417
  dimension="row"
4326
4418
  onUpdated.bind="this.updateGranularity"
4327
4419
  availableGranularities="props.unusedDateTimeGranularities[row.name]"
4420
+ allGranularities="props.allGranularities"
4328
4421
  />
4329
4422
  <PivotDimensionOrder dimension="row" onUpdated.bind="this.updateOrder"/>
4330
4423
  </PivotDimension>
4331
4424
  </div>
4332
4425
  </t>
4333
- <div class="fw-bold pt-4 pb-1 d-flex flex-row justify-content-between align-items-center">
4426
+ <div
4427
+ class="fw-bold pt-4 pb-1 d-flex flex-row justify-content-between align-items-center o-section-title">
4334
4428
  Measures
4335
4429
  <AddDimensionButton
4336
4430
  onFieldPicked.bind="addMeasureDimension"
@@ -4366,6 +4460,93 @@
4366
4460
  </div>
4367
4461
  </t>
4368
4462
 
4463
+ <t t-name="o-spreadsheet-PivotListItem">
4464
+ <div
4465
+ class="o_pivot_list_item p-4 border-bottom"
4466
+ t-ref="pivotListItem"
4467
+ t-on-click="this.selectPivot">
4468
+ <span t-esc="env.model.getters.getPivotDisplayName(props.pivotId)"/>
4469
+ </div>
4470
+ </t>
4471
+
4472
+ <t t-name="o-spreadsheet-PivotSidePanel">
4473
+ <t t-if="props.pivotId" t-component="sidePanelEditor" t-props="props"/>
4474
+ <t t-else="">
4475
+ <t t-foreach="env.model.getters.getPivotIds()" t-as="pivotId" t-key="pivotId">
4476
+ <PivotListItem pivotId="pivotId"/>
4477
+ </t>
4478
+ </t>
4479
+ </t>
4480
+
4481
+ <t t-name="o-spreadsheet-PivotSpreadsheetSidePanel">
4482
+ <div class="d-flex flex-column h-100 justify-content-between overflow-hidden">
4483
+ <div class="h-100 overflow-auto">
4484
+ <Section>
4485
+ <t t-set-slot="title">Name</t>
4486
+ <EditableName name="name" displayName="displayName" onChanged.bind="onNameChanged"/>
4487
+ <div class="btn btn-link o_duplicate_pivot" t-on-click="duplicatePivot">
4488
+ <i class="fa fa-solid fa-copy me-1"/>
4489
+ Duplicate Pivot
4490
+ </div>
4491
+ </Section>
4492
+ <Section>
4493
+ <t t-set-slot="title">Range</t>
4494
+ <SelectionInput
4495
+ ranges="ranges"
4496
+ required="true"
4497
+ isInvalid="shouldDisplayInvalidRangeError"
4498
+ hasSingleRange="true"
4499
+ onSelectionChanged="(ranges) => this.onSelectionChanged(ranges)"
4500
+ onSelectionConfirmed="() => this.onSelectionConfirmed()"
4501
+ />
4502
+ <span
4503
+ class="text-danger sp_range_error_message"
4504
+ t-if="shouldDisplayInvalidRangeError"
4505
+ t-esc="pivot.invalidRangeMessage"
4506
+ />
4507
+ </Section>
4508
+
4509
+ <PivotLayoutConfigurator
4510
+ t-if="!pivot.isInvalidRange"
4511
+ unusedGroupableFields="store.unusedGroupableFields"
4512
+ unusedMeasureFields="store.unusedMeasureFields"
4513
+ unusedDateTimeGranularities="store.unusedDateTimeGranularities"
4514
+ allGranularities="store.allGranularities"
4515
+ definition="definition"
4516
+ onDimensionsUpdated.bind="onDimensionsUpdated"
4517
+ />
4518
+ <Section>
4519
+ <button class="btn btn-link sp_back" t-on-click="back">Back</button>
4520
+ <button class="btn btn-link sp_delete" t-on-click="delete">Delete</button>
4521
+ </Section>
4522
+ </div>
4523
+ <Section
4524
+ class="'align-items-center border-top d-flex flex-row justify-content-between py-1 pivot-defer-update'">
4525
+ <Checkbox
4526
+ label="deferUpdatesLabel"
4527
+ title="deferUpdatesTooltip"
4528
+ value="store.updatesAreDeferred"
4529
+ onChange="(value) => store.deferUpdates(value)"
4530
+ />
4531
+ <div>
4532
+ <i
4533
+ t-if="store.isDirty"
4534
+ class="btn btn-sm pe-0 fa fa-undo"
4535
+ title="Discard all changes"
4536
+ t-on-click="() => store.discardPendingUpdate()"
4537
+ />
4538
+ <span
4539
+ t-if="store.isDirty"
4540
+ class="btn btm-sm btn-link sp_apply_update"
4541
+ title="Apply all changes"
4542
+ t-on-click="() => store.applyUpdate()">
4543
+ Update
4544
+ </span>
4545
+ </div>
4546
+ </Section>
4547
+ </div>
4548
+ </t>
4549
+
4369
4550
  <t t-name="o-spreadsheet-RemoveDuplicatesPanel">
4370
4551
  <div class="o-remove-duplicates">
4371
4552
  <Section>