[IMP] web: add cumulative line chart

The cumulative option on line chart is useful for displaying
cumulative information graphically.

closes odoo/odoo#97394

Task-id: 2146487
Signed-off-by: FrancoisGe <fge@odoo.com>
This commit is contained in:
Dardenne Florent (dafl)
2022-08-10 12:07:19 +02:00
parent cef8cf87b4
commit 22133a01be
7 changed files with 72 additions and 2 deletions
@@ -22,6 +22,9 @@ export class GraphArchParser extends XMLParser {
if (node.hasAttribute("stacked")) {
archInfo.stacked = archParseBoolean(node.getAttribute("stacked"));
}
if (node.hasAttribute("cumulated")) {
archInfo.cumulated = archParseBoolean(node.getAttribute("cumulated"));
}
const mode = node.getAttribute("type");
if (mode && MODES.includes(mode)) {
archInfo.mode = mode;
@@ -112,6 +112,11 @@ export class GraphController extends Component {
const { stacked } = this.model.metaData;
this.model.updateMetaData({ stacked: !stacked });
}
toggleCumulated() {
const { cumulated } = this.model.metaData;
this.model.updateMetaData({ cumulated: !cumulated });
}
}
GraphController.template = "web.GraphView";
@@ -38,6 +38,10 @@
t-on-click="toggleStacked"
t-att-class="{ active: model.metaData.stacked }"
/>
<button class="btn btn-secondary fa fa-signal o_graph_button" data-tooltip="Cumulative" aria-label="Cumulative"
t-on-click="toggleCumulated"
t-att-class="{ active: model.metaData.cumulated }"
/>
</div>
<div t-if="model.metaData.mode !== 'pie' and model.metaData.domains.length === 1" class="btn-group" role="toolbar" aria-label="Sort graph" name="toggleOrderToolbar">
<button class="btn btn-secondary fa fa-sort-amount-desc o_graph_button" data-tooltip="Descending" aria-label="Descending"
@@ -125,7 +125,7 @@ export class GraphModel extends Model {
/**
* Only supposed to be called to change one or several parameters among
* "measure", "mode", "order", and "stacked".
* "measure", "mode", "order", "stacked" and "cumulated".
* @param {Object} params
*/
async updateMetaData(params) {
@@ -318,7 +318,7 @@ export class GraphRenderer extends Component {
* @returns {Object}
*/
getLineChartData() {
const { groupBy, domains, stacked } = this.model.metaData;
const { groupBy, domains, stacked, cumulated } = this.model.metaData;
const data = this.model.data;
for (let index = 0; index < data.datasets.length; ++index) {
const dataset = data.datasets[index];
@@ -348,6 +348,13 @@ export class GraphRenderer extends Component {
if (stacked) {
dataset.backgroundColor = hexToRGBA(dataset.borderColor, 0.4);
}
if (cumulated) {
let accumulator = 0;
dataset.data = dataset.data.map((value) => {
accumulator += value;
return accumulator;
});
}
}
if (data.datasets.length === 1 && data.datasets[0].originIndex === 0) {
const dataset = data.datasets[0];
@@ -43,6 +43,7 @@ export const graphView = {
order: archInfo.order || null,
resModel: resModel,
stacked: "stacked" in archInfo ? archInfo.stacked : true,
cumulated: archInfo.cumulated || false,
title: archInfo.title || _lt("Untitled"),
};
}
@@ -1024,6 +1024,56 @@ QUnit.module("Views", (hooks) => {
checkDatasets(assert, graph, keysToEvaluate, expectedDatasets);
});
QUnit.test("Cumulative prop and default line chart", async function (assert) {
const graph = await makeView({
serverData,
type: "graph",
resModel: "foo",
arch: `
<graph type="line" stacked="0">
<field name="bar"/>
<field name="product_id"/>
</graph>
`,
});
assert.strictEqual(graph.model.metaData.mode, "line", "should be in line chart mode.");
assert.strictEqual(
graph.model.metaData.cumulated,
false,
"should not be cumulative by default."
);
await click(target, '[data-tooltip="Cumulative"]');
assert.strictEqual(graph.model.metaData.cumulated, true, "should be in cumulative");
const expectedDatasets = [
{
data: [1, 4],
},
{
data: [4, 4],
},
];
checkDatasets(assert, graph, ["data"], expectedDatasets);
});
QUnit.test("Default cumulative prop", async function (assert) {
const graph = await makeView({
serverData,
type: "graph",
resModel: "foo",
arch: `
<graph type="line" stacked="0" cumulated="1">
<field name="bar"/>
<field name="product_id"/>
</graph>
`,
});
assert.strictEqual(graph.model.metaData.mode, "line", "should be in line chart mode.");
assert.strictEqual(graph.model.metaData.cumulated, true, "should be in cumulative");
});
QUnit.test("line chart rendering (no groupBy, several domains)", async function (assert) {
assert.expect(7);
const graph = await makeView({