Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Master pivot spreadsheet pro rar #4025

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
610 changes: 610 additions & 0 deletions demo/data.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions demo/main.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Don't remove unused import
// organize-imports-ignore
import { demoData, makeLargeDataset } from "./data.js";
import { makePivotDataset } from "./pivot.js";
import { currenciesData } from "./currencies.js";
import { WebsocketTransport } from "./transport.js";
import { FileStore } from "./file_store.js";
Expand Down Expand Up @@ -257,6 +258,7 @@ class Demo extends Component {
this.stateUpdateMessages = [];
}
this.createModel(data || demoData);
// this.createModel(makePivotDataset(10_000));
// this.createModel(makeLargeDataset(26, 10_000, ["numbers"]));
// this.createModel({});
}
Expand Down
138 changes: 138 additions & 0 deletions demo/pivot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
const salesperson = [
"Perceval",
"Arthur",
"Dame Séli",
"Léodagan",
"Karadoc",
"Lancelot du Lac",
"Guenièvre",
"Bohort",
"Père Blaise",
"Yvain",
"Merlin",
"Gauvin",
"Mevanwi",
"Roi Loth",
"Uther Pendragon",
"Goustan le Cruel",
"Ygeme de Tintagel",
];

const stages = ["New", "Qualified", "Proposal", "Negotiation", "Won", "Lost"];

const sources = ["Web", "Phone", "Email", "In person", "Other"];

const customers = Array(30)
.fill(0)
.map((_, i) => `Customer ${i + 1}`);

const columns = [
"Salesperson",
"Stage",
"Customer",
"Email",
"Amount",
"Probability",
"Created on",
"Source",
"Active",
];

function randomIntFromInterval(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}

export function makePivotDataset(rowsNumber = 10_000) {
const cells = {
A1: { content: "Salesperson" },
B1: { content: "Stage" },
C1: { content: "Customer" },
D1: { content: "Email" },
E1: { content: "Amount" },
F1: { content: "Probability" },
G1: { content: "Created on" },
H1: { content: "Source" },
I1: { content: "Active" },
};
let rowIndex = 2;
const data = [];
for (let i = 0; i < rowsNumber; i++) {
const customer = customers[randomIntFromInterval(0, customers.length - 1)];
cells[`A${rowIndex}`] = {
content: salesperson[randomIntFromInterval(0, salesperson.length - 1)],
};
cells[`B${rowIndex}`] = { content: stages[randomIntFromInterval(0, stages.length - 1)] };
cells[`C${rowIndex}`] = { content: customer };
cells[`D${rowIndex}`] = {
content: `${customer.replace(/\s/g, "").toLowerCase()}@example.com}`,
};
cells[`E${rowIndex}`] = { content: `${randomIntFromInterval(0, 100000)}`, format: 2 };
cells[`F${rowIndex}`] = { content: `${randomIntFromInterval(0, 100)}`, format: 3 };
cells[`G${rowIndex}`] = { content: `${randomIntFromInterval(40179, 45657)}`, format: 1 }; //random date between 1/1/2010 and 31/12/2024
cells[`H${rowIndex}`] = { content: sources[randomIntFromInterval(0, sources.length - 1)] };
cells[`I${rowIndex}`] = { content: Math.random() > 0.5 ? "true" : "false" };
rowIndex++;
}
return {
sheets: [
{
name: "Pivot",
id: "pivot",
colNumber: 256,
rowNumber: rowsNumber + 1,
cells: {
A1: {
content: `=PIVOT("1")`,
},
},
},
{
name: "Data",
id: "data",
colNumber: columns.length,
rowNumber: rowsNumber + 1,
cells,
},
],
formats: {
1: "d/m/yyyy",
2: "[$$]#,##0.00",
3: "0.00%",
},
pivotNextId: 2,
pivots: {
1: {
type: "SPREADSHEET",
columns: [
{
name: "Stage",
},
],
rows: [
{
name: "Created on",
granularity: "year_number",
order: "asc",
},
],
measures: [
{
name: "Amount",
aggregator: "sum",
},
],
name: "My pivot",
dataSet: {
zone: {
top: 0,
bottom: rowsNumber,
left: 0,
right: 8,
},
sheetId: "data",
},
formulaId: "1",
},
},
};
}
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
50 changes: 48 additions & 2 deletions src/collaborative/ot/ot_specific.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { otRegistry } from "../../registries";
import {
AddColumnsRowsCommand,
AddMergeCommand,
AddPivotCommand,
CreateChartCommand,
CreateSheetCommand,
CreateTableCommand,
Expand Down Expand Up @@ -91,10 +92,55 @@ otRegistry.addTransformation(
otRegistry.addTransformation(
"REMOVE_PIVOT",
["RENAME_PIVOT", "DUPLICATE_PIVOT", "INSERT_PIVOT", "UPDATE_PIVOT"],
pivotTransformation
pivotRemovedTransformation
);

function pivotTransformation(
otRegistry.addTransformation(
"DELETE_SHEET",
["ADD_PIVOT", "UPDATE_PIVOT"],
pivotDeletedSheetTransformation
);

otRegistry.addTransformation(
"ADD_COLUMNS_ROWS",
["ADD_PIVOT", "UPDATE_PIVOT"],
pivotZoneTransformation
);
otRegistry.addTransformation(
"REMOVE_COLUMNS_ROWS",
["ADD_PIVOT", "UPDATE_PIVOT"],
pivotZoneTransformation
);

function pivotZoneTransformation(
toTransform: AddPivotCommand | UpdatePivotCommand,
executed: AddColumnsRowsCommand | RemoveColumnsRowsCommand
): AddPivotCommand | UpdatePivotCommand | undefined {
if (toTransform.pivot.type !== "SPREADSHEET") {
return toTransform;
}
if (toTransform.pivot.dataSet?.sheetId !== executed.sheetId) {
return toTransform;
}
const newZone = transformZone(toTransform.pivot.dataSet.zone, executed);
const dataSet = newZone ? { ...toTransform.pivot.dataSet, zone: newZone } : undefined;
return { ...toTransform, pivot: { ...toTransform.pivot, dataSet } };
}

function pivotDeletedSheetTransformation(
toTransform: AddPivotCommand | UpdatePivotCommand,
executed: DeleteSheetCommand
): AddPivotCommand | UpdatePivotCommand | undefined {
if (toTransform.pivot.type !== "SPREADSHEET") {
return toTransform;
}
if (toTransform.pivot.dataSet?.sheetId === executed.sheetId) {
return { ...toTransform, pivot: { ...toTransform.pivot, dataSet: undefined } };
}
return toTransform;
}

function pivotRemovedTransformation(
toTransform: RenamePivotCommand | DuplicatePivotCommand | InsertPivotCommand | UpdatePivotCommand,
executed: RemovePivotCommand
) {
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 @@ -28,13 +28,6 @@ css/* scss */ `
.pivot-dimension-search {
background-color: white;
}
.pivot-dimension-field {
background-color: white;

&:hover {
background-color: #f0f0f0;
}
}
`;

export class AddDimensionButton extends Component<Props, SpreadsheetChildEnv> {
Expand Down Expand Up @@ -98,8 +91,9 @@ export class AddDimensionButton extends Component<Props, SpreadsheetChildEnv> {
}

get popoverProps() {
const { x, y, width, height } = this.buttonRef.el!.getBoundingClientRect();
return {
anchorRect: this.buttonRef.el!.getBoundingClientRect(),
anchorRect: { x, y, width, height },
positioning: "BottomLeft",
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Component } from "@odoo/owl";
import { SpreadsheetChildEnv } from "../../../../..";
import { PERIODS } from "../../../../../helpers/pivot/pivot_helpers";
import { ALL_PERIODS } from "../../../../../helpers/pivot/pivot_helpers";
import { PivotDimension } from "../../../../../types/pivot";

interface Props {
dimension: PivotDimension;
onUpdated: (dimension: PivotDimension, ev: InputEvent) => void;
availableGranularities: Set<string>;
allGranularities: string[];
}

export class PivotDimensionGranularity extends Component<Props, SpreadsheetChildEnv> {
Expand All @@ -15,7 +16,7 @@ export class PivotDimensionGranularity extends Component<Props, SpreadsheetChild
dimension: Object,
onUpdated: Function,
availableGranularities: Set,
allGranularities: Array,
};
periods = PERIODS;
allGranularities = Object.keys(PERIODS);
periods = ALL_PERIODS;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
class="o_input flex-basis-50"
t-on-change="(ev) => props.onUpdated(props.dimension, ev.target.value)">
<option
t-foreach="allGranularities"
t-foreach="props.allGranularities"
t-as="granularity"
t-key="granularity"
t-if="props.availableGranularities.has(granularity) || granularity === props.dimension.granularity"
Expand Down