From f2bace651832903d6b34d51c396d2ee5a849ff98 Mon Sep 17 00:00:00 2001 From: jpr-odoo Date: Mon, 1 Jun 2020 12:08:09 +0000 Subject: [PATCH] [IMP] website: add min & max option for chart axis value This commit introduces min & max input options for the chart values of the axis. It will be visible only for the line and bar chart. - When min and max values are same, we fix this by changing the min value to zero and multiply provided value by 2 to set max value. - When min value greater than max value, we swap the values. - When the min value is given and the max value is not: - If the min value is smaller than greatest value of the chart, then the max value is set to the greatest value of the chart. - Otherwise, the given minimum value is used as maximum value and the minimum is set to 0. - When only the max value is given then the minimum value is set to 0. task-2250766 closes odoo/odoo#52221 Signed-off-by: Quentin Smetz (qsm) Co-authored-by: dwa-odoo --- .../static/src/snippets/s_chart/000.js | 14 +++++++ .../static/src/snippets/s_chart/options.js | 41 +++++++++++++++++++ addons/website/views/snippets/s_chart.xml | 4 +- 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/addons/website/static/src/snippets/s_chart/000.js b/addons/website/static/src/snippets/s_chart/000.js index 2c67bd03612..eb32dbc119e 100644 --- a/addons/website/static/src/snippets/s_chart/000.js +++ b/addons/website/static/src/snippets/s_chart/000.js @@ -48,6 +48,7 @@ const ChartWidget = publicWidget.Widget.extend({ }, tooltips: { enabled: this.el.dataset.tooltipDisplay === 'true', + position: 'custom', }, title: { display: !!this.el.dataset.title, @@ -80,18 +81,30 @@ const ChartWidget = publicWidget.Widget.extend({ }, }; } else { + // For extending the range of the axis while maintaining the auto + // fit behavior + const beforeBuildTicks = (scale) => { + scale.min = parseInt(this.el.dataset.ticksMin) || scale.min; + scale.max = parseInt(this.el.dataset.ticksMax) || scale.max; + }; chartData.options.scales = { xAxes: [{ stacked: this.el.dataset.stacked === 'true', ticks: { beginAtZero: true }, + // Maintaining the gap between two values on + // vertical/horizontally axis + beforeBuildTicks: beforeBuildTicks, }], yAxes: [{ stacked: this.el.dataset.stacked === 'true', ticks: { beginAtZero: true }, + // Maintaining the gap between two values on + // vertical/horizontally axis + beforeBuildTicks: beforeBuildTicks, }], }; } @@ -104,6 +117,7 @@ const ChartWidget = publicWidget.Widget.extend({ } const canvas = this.el.querySelector('canvas'); + window.Chart.Tooltip.positioners.custom = (elements, eventPosition) => eventPosition; this.chart = new window.Chart(canvas, chartData); return this._super.apply(this, arguments); }, diff --git a/addons/website/static/src/snippets/s_chart/options.js b/addons/website/static/src/snippets/s_chart/options.js index 49f4789861b..bcce637a661 100644 --- a/addons/website/static/src/snippets/s_chart/options.js +++ b/addons/website/static/src/snippets/s_chart/options.js @@ -118,6 +118,9 @@ options.registry.InnerChart = options.Class.extend({ this._setDefaultSelectedInput(); await this._reloadGraph(); } + if (params.attributeName === 'minValue' || params.attributeName === 'maxValue') { + this._computeTicksMinMaxValue(); + } }, //-------------------------------------------------------------------------- @@ -148,6 +151,44 @@ options.registry.InnerChart = options.Class.extend({ } return this._super(...arguments); }, + /** + * Maintains the gap between the scale axis for the auto fit behavior if we + * used min/max config. + * + * @private + */ + _computeTicksMinMaxValue() { + const dataset = this.$target[0].dataset; + let minValue = parseInt(dataset.minValue); + let maxValue = parseInt(dataset.maxValue); + if (!isNaN(maxValue)) { + // Reverse min max values when min value is greater than max value + if (maxValue < minValue) { + maxValue = minValue; + minValue = parseInt(dataset.maxValue); + } else if (maxValue === minValue) { + // If min value and max value are same for positive and negative + // number + minValue < 0 ? (maxValue = 0, minValue = 2 * minValue) : (minValue = 0, maxValue = 2 * maxValue); + } + } else { + // Find max value from each row/column data + const datasets = JSON.parse(dataset.data).datasets || []; + const dataValue = _.flatten(datasets.map(el => el.data.map(data => { + return !isNaN(parseInt(data)) ? parseInt(data) : 0; + }))); + // When max value is not given and min value is greater than chart + // data values + if (minValue >= Math.max(...dataValue)) { + maxValue = minValue; + minValue = 0; + } + } + this.$target.attr({ + 'data-ticks-min': minValue, + 'data-ticks-max': maxValue, + }); + }, /** * Sets and reloads the data on the canvas if it has changed. * Used in matrix related method. diff --git a/addons/website/views/snippets/s_chart.xml b/addons/website/views/snippets/s_chart.xml index 42852be1466..379d8552587 100644 --- a/addons/website/views/snippets/s_chart.xml +++ b/addons/website/views/snippets/s_chart.xml @@ -28,7 +28,7 @@ Bar Vertical Bar Horizontal - Line + Line Pie Doughnut Radar @@ -53,6 +53,8 @@ + +