Skip to content

Commit

Permalink
[ADD] pivots: TODO
Browse files Browse the repository at this point in the history
Co-authored-by: rrahir <rar@odoo.com>
Co-authored-by: Pierre Rousseau <pro@odoo.com>
  • Loading branch information
pro-odoo and rrahir committed Apr 11, 2024
1 parent ce22ba2 commit ebed644
Show file tree
Hide file tree
Showing 50 changed files with 3,224 additions and 156 deletions.
608 changes: 608 additions & 0 deletions demo/data.js

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* The only aim of this file is to make ts-jest happy, as it does not support
* Object.groupBy and Map.groupBy at the current version (29.1.2)
* This is a workaround to make it work.
*/

interface ObjectConstructor {
/**
* Groups members of an iterable according to the return value of the passed callback.
* @param items An iterable.
* @param keySelector A callback which will be invoked for each item in items.
*/
groupBy<K extends PropertyKey, T>(
items: Iterable<T>,
keySelector: (item: T, index: number) => K
): Partial<Record<K, T[]>>;
}

interface MapConstructor {
/**
* Groups members of an iterable according to the return value of the passed callback.
* @param items An iterable.
* @param keySelector A callback which will be invoked for each item in items.
*/
groupBy<K, T>(items: Iterable<T>, keySelector: (item: T, index: number) => K): Map<K, T[]>;
}
6 changes: 6 additions & 0 deletions src/actions/insert_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ export const insertChart: ActionSpec = {
icon: "o-spreadsheet-Icon.INSERT_CHART",
};

export const insertPivot: ActionSpec = {
name: _t("Pivot table"),
execute: ACTIONS.CREATE_PIVOT,
icon: "o-spreadsheet-Icon.PIVOT",
};

export const insertImage: ActionSpec = {
name: _t("Image"),
description: "Ctrl+O",
Expand Down
13 changes: 13 additions & 0 deletions src/actions/menu_items_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,19 @@ export const CREATE_CHART = (env: SpreadsheetChildEnv) => {
}
};

//------------------------------------------------------------------------------
// Pivots
//------------------------------------------------------------------------------

export const CREATE_PIVOT = (env: SpreadsheetChildEnv) => {
const pivotId = env.model.uuidGenerator.uuidv4();
const newSheetId = env.model.uuidGenerator.uuidv4();
const result = env.model.dispatch("INSERT_NEW_PIVOT", { pivotId, newSheetId });
if (result.isSuccessful) {
env.openSidePanel("PivotSidePanel", { pivotId });
}
};

//------------------------------------------------------------------------------
// Image
//------------------------------------------------------------------------------
Expand Down
26 changes: 0 additions & 26 deletions src/components/side_panel/pivot/all_pivots_side_panel.ts

This file was deleted.

13 changes: 0 additions & 13 deletions src/components/side_panel/pivot/all_pivots_side_panel.xml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ css/* scss */ `
background-color: white;
}
}
.superPointDeLaMortPleaseRemoveMe {
cursor: pointer;
background: magenta;
}
`;

export class PivotDimension extends Component<Props, SpreadsheetChildEnv> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
<templates>
<t t-name="o-spreadsheet-PivotDimension">
<div class="border py-1 px-2 d-flex flex-column shadow-sm pivot-dimension">
<div
class="border py-1 px-2 d-flex flex-column shadow-sm pivot-dimension"
t-att-class="{'bg-danger': !props.dimension.isValid}">
<div class="d-flex flex-row justify-content-between align-items-center">
<span class="fw-bold" t-esc="props.dimension.displayName"/>
<i
class="btn fa fa-times pe-0"
<span
class="pe-0 superPointDeLaMortPleaseRemoveMe"
t-if="props.onRemoved"
t-on-click="() => props.onRemoved(props.dimension)"
/>
t-on-click="() => props.onRemoved(props.dimension)">
</span>
<!-- TODO Should use an icon-->
</div>
<t t-slot="default"/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ export class PivotDimensionGranularity extends Component<Props, SpreadsheetChild
availableGranularities: Set,
};
periods = PERIODS;
allGranularities = ["year", "quarter", "month", "week", "day"];
allGranularities = Object.keys(PERIODS);
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export class PivotDimensions extends Component<Props, SpreadsheetChildEnv> {
isDateField = isDateField;

startDragAndDrop(dimension: PivotDimensionType, event: MouseEvent) {
if (event.button !== 0) {
if (event.button !== 0 || (event.target as HTMLElement).tagName === "SELECT") {
return;
}

Expand Down Expand Up @@ -88,7 +88,7 @@ export class PivotDimensions extends Component<Props, SpreadsheetChildEnv> {
}

startDragAndDropMeasures(measure: PivotMeasure, event: MouseEvent) {
if (event.button !== 0) {
if (event.button !== 0 || (event.target as HTMLElement).tagName === "SELECT") {
return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<templates>
<t t-name="o-spreadsheet-PivotDimensions">
<div class="o_side_panel_section pivot-dimensions" t-ref="pivot-dimensions">
<div class="fw-bold py-1 d-flex flex-row justify-content-between align-items-center">
<div class="o_side_panel_section pivot-dimensions o-section" t-ref="pivot-dimensions">
<div
class="fw-bold py-1 d-flex flex-row justify-content-between align-items-center o-section-title">
Columns
<AddDimensionButton
onFieldPicked.bind="addColumnDimension"
Expand All @@ -25,7 +26,7 @@
</div>
</t>
<div
class="fw-bold pt-4 pb-1 d-flex flex-row justify-content-between align-items-center"
class="fw-bold pt-4 pb-1 d-flex flex-row justify-content-between align-items-center o-section-title"
t-att-style="dragAndDrop.itemsStyle['__rows_title__']">
Rows
<AddDimensionButton
Expand All @@ -49,7 +50,8 @@
</PivotDimension>
</div>
</t>
<div class="fw-bold pt-4 pb-1 d-flex flex-row justify-content-between align-items-center">
<div
class="fw-bold pt-4 pb-1 d-flex flex-row justify-content-between align-items-center o-section-title">
Measures
<AddDimensionButton
onFieldPicked.bind="addMeasureDimension"
Expand Down
30 changes: 30 additions & 0 deletions src/components/side_panel/pivot/pivot_preview/pivot_preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Component, useRef } from "@odoo/owl";
import { getPivotHighlights } from "../../../../helpers/pivot/pivot_highlight";
import { css } from "../../../helpers";
import { useHighlightsOnHover } from "../../../helpers/highlight_hook";

css/* scss */ `
.o_pivot_preview {
cursor: pointer;
&:hover {
background-color: #f1f3f4;
}
}
`;

export class PivotPreview extends Component {
static template = "o-spreadsheet-PivotPreview";
static props = { pivotId: String };
setup() {
const previewRef = useRef("pivotPreview");
useHighlightsOnHover(previewRef, this);
}

selectPivot() {
this.env.openSidePanel("PivotSidePanel", { pivotId: this.props.pivotId });
}

get highlights() {
return getPivotHighlights(this.env.model.getters, this.props.pivotId);
}
}
10 changes: 10 additions & 0 deletions src/components/side_panel/pivot/pivot_preview/pivot_preview.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<templates>
<t t-name="o-spreadsheet-PivotPreview">
<div
class="o_pivot_preview p-4 border-bottom"
t-ref="pivotPreview"
t-on-click="this.selectPivot">
<span t-esc="env.model.getters.getPivotDisplayName(props.pivotId)"/>
</div>
</t>
</templates>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Component } from "@odoo/owl";
import { SpreadsheetChildEnv, UID } from "../../../..";
import { pivotSidePanelRegistry } from "../../../../helpers/pivot/pivot_side_panel_registry";
import { Section } from "../../components/section/section";
import { PivotDimensions } from "../pivot_dimensions/pivot_dimensions";
import { PivotPreview } from "../pivot_preview/pivot_preview";

interface Props {
pivotId?: UID;
onCloseSidePanel: () => void;
}

export class PivotSidePanel extends Component<Props, SpreadsheetChildEnv> {
static template = "o-spreadsheet-PivotSidePanel";
static props = {
pivotId: { type: String, optional: true },
onCloseSidePanel: Function,
};
static components = {
PivotDimensions,
Section,
PivotPreview,
};

get sidePanelEditor() {
if (!this.props.pivotId) {
throw new Error("pivotId is required to call this function.");
}
const pivot = this.env.model.getters.getPivotCoreDefinition(this.props.pivotId);
if (!pivot) {
throw new Error("pivotId does not correspond to a pivot.");
}
return pivotSidePanelRegistry.get(pivot.type).editor;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<templates>
<t t-name="o-spreadsheet-PivotSidePanel">
<t t-if="props.pivotId" t-component="sidePanelEditor" t-props="props"/>
<t t-else="">
<t t-foreach="env.model.getters.getPivotIds()" t-as="pivotId" t-key="pivotId">
<PivotPreview pivotId="pivotId"/>
</t>
</t>
</t>
</templates>
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Component, useState } from "@odoo/owl";
import { SpreadsheetChildEnv } from "../../../../..";
import { splitReference, toZone } from "../../../../../helpers";
import { SpreadsheetPivotRuntimeDefinition } from "../../../../../helpers/pivot/spreadsheet_pivot";
import { Store, useLocalStore } from "../../../../../store_engine";
import { PivotSidePanelStore } from "../../../../../stores/pivot_side_panel_store";
import { _t } from "../../../../../translation";
import { UID } from "../../../../../types";
import { SpreadsheetPivotCoreDefinition } from "../../../../../types/pivot";
import { SelectionInput } from "../../../../selection_input/selection_input";
import { Section } from "../../../components/section/section";
import { EditableName } from "../../editable_name/editable_name";
import { PivotDimensions } from "../../pivot_dimensions/pivot_dimensions";

interface Props {
pivotId: UID;
onCloseSidePanel: () => void;
}

export class PivotSpreadsheetSidePanel extends Component<Props, SpreadsheetChildEnv> {
static template = "o-spreadsheet-PivotSpreadsheetSidePanel";
static props = {
pivotId: String,
onCloseSidePanel: Function,
};
static components = {
PivotDimensions,
Section,
SelectionInput,
EditableName,
};
store!: Store<PivotSidePanelStore>;

state!: { range: string };

setup() {
this.store = useLocalStore(PivotSidePanelStore, this.props.pivotId);
this.pivot.loadSync(); //TODOPRO Should be different IMO
this.state = useState({
range: this.env.model.getters.getRangeString(this.definition.range, "forceSheetReference"),
});
// this.range = zoneToXc(this.definition.range.zone);
}
get pivot() {
return this.env.model.getters.getPivot(this.props.pivotId);
}

get name() {
return this.env.model.getters.getPivotName(this.props.pivotId);
}

get displayName() {
return this.env.model.getters.getPivotDisplayName(this.props.pivotId);
}

get definition(): SpreadsheetPivotRuntimeDefinition {
return this.pivot.definition as SpreadsheetPivotRuntimeDefinition;
}

onSelectionChanged(ranges: string[]) {
this.state.range = ranges[0];
}

onSelectionConfirmed() {
if (this.state.range) {
const { sheetName, xc } = splitReference(this.state.range);
const sheetId = sheetName
? this.env.model.getters.getSheetIdByName(sheetName)
: this.env.model.getters.getActiveSheetId();
const zone = toZone(xc);
this.store.update({ sheetId, zone });
}
}

duplicatePivot() {
const newPivotId = this.env.model.uuidGenerator.uuidv4();
const result = this.env.model.dispatch("DUPLICATE_PIVOT", {
pivotId: this.props.pivotId,
newPivotId,
});
const text = result.isSuccessful
? _t('Pivot duplicated. Use the "Re-insert pivot" menu item to insert it in a sheet.')
: _t("Pivot duplication failed");
const type = result.isSuccessful ? "success" : "danger";
this.env.notifyUser({
text,
sticky: false,
type,
});
if (result.isSuccessful) {
this.env.openSidePanel("PivotSidePanel", { pivotId: newPivotId });
}
}

onNameChanged(name: string) {
this.store.update({ name });
}

onDimensionsUpdated(definition: Partial<SpreadsheetPivotCoreDefinition>) {
this.store.update(definition);
}

back() {
this.env.openSidePanel("PivotSidePanel", {});
}
}

0 comments on commit ebed644

Please sign in to comment.