summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/views/graph/graph_controller.js30
-rw-r--r--addons/web/static/src/js/views/graph/graph_model.js1
-rw-r--r--addons/web/static/src/js/views/graph/graph_renderer.js43
-rw-r--r--addons/web/static/src/js/views/graph/graph_view.js15
4 files changed, 88 insertions, 1 deletions
diff --git a/addons/web/static/src/js/views/graph/graph_controller.js b/addons/web/static/src/js/views/graph/graph_controller.js
index f47bfaeb5bb..eb5fd107081 100644
--- a/addons/web/static/src/js/views/graph/graph_controller.js
+++ b/addons/web/static/src/js/views/graph/graph_controller.js
@@ -23,6 +23,7 @@ class CarretDropdownMenu extends DropdownMenu {
var GraphController = AbstractController.extend({
custom_events: _.extend({}, AbstractController.prototype.custom_events, {
item_selected: '_onItemSelected',
+ open_view: '_onOpenView',
}),
/**
@@ -42,6 +43,9 @@ var GraphController = AbstractController.extend({
// button in the control panel owned by the graph view.
this.isEmbedded = params.isEmbedded;
this.withButtons = params.withButtons;
+ // views to use in the action triggered when the graph is clicked
+ this.views = params.views;
+ this.title = params.title;
// this parameter determines what is the list of fields
// that may be used within the groupby menu available when
@@ -296,6 +300,32 @@ var GraphController = AbstractController.extend({
this.measureMenu.update({ items: this.measures });
}
},
+
+ /**
+ * @private
+ * @param {OdooEvent} ev
+ * @param {Array[]} ev.data.domain
+ */
+ _onOpenView(ev) {
+ ev.stopPropagation();
+ const state = this.model.get();
+ const context = Object.assign({}, state.context);
+ Object.keys(context).forEach(x => {
+ if (x === 'group_by' || x.startsWith('search_default_')) {
+ delete context[x];
+ }
+ });
+ this.do_action({
+ context: context,
+ domain: ev.data.domain,
+ name: this.title,
+ res_model: this.modelName,
+ target: 'current',
+ type: 'ir.actions.act_window',
+ view_mode: 'list',
+ views: this.views,
+ });
+ },
});
return GraphController;
diff --git a/addons/web/static/src/js/views/graph/graph_model.js b/addons/web/static/src/js/views/graph/graph_model.js
index 21614493e3c..e1411324c77 100644
--- a/addons/web/static/src/js/views/graph/graph_model.js
+++ b/addons/web/static/src/js/views/graph/graph_model.js
@@ -244,6 +244,7 @@ return AbstractModel.extend({
self.chart.dataPoints.push({
resId: dataPt[self.chart.groupBy[0]] instanceof Array ? dataPt[self.chart.groupBy[0]][0] : -1,
count: count,
+ domain: dataPt.__domain,
value: value,
labels: labels,
originIndex: originIndex,
diff --git a/addons/web/static/src/js/views/graph/graph_renderer.js b/addons/web/static/src/js/views/graph/graph_renderer.js
index cf6dba6e4c3..35e78690528 100644
--- a/addons/web/static/src/js/views/graph/graph_renderer.js
+++ b/addons/web/static/src/js/views/graph/graph_renderer.js
@@ -68,6 +68,7 @@ return AbstractRenderer.extend({
this.isEmbedded = params.isEmbedded || false;
this.title = params.title || '';
this.fields = params.fields || {};
+ this.disableLinking = params.disableLinking;
this.chart = null;
this.chartId = _.uniqueId('chart');
@@ -134,6 +135,7 @@ return AbstractRenderer.extend({
* @param {Object} tooltipModel see chartjs documentation
*/
_customTooltip: function (tooltipModel) {
+ this.$el.css({ cursor: 'default' });
if (this.$tooltip) {
this.$tooltip.remove();
}
@@ -144,6 +146,10 @@ return AbstractRenderer.extend({
return;
}
+ if (this._isRedirectionEnabled()) {
+ this.$el.css({ cursor: 'pointer' });
+ }
+
const chartArea = this.chart.chartArea;
const chartAreaLeft = chartArea.left;
const chartAreaRight = chartArea.right;
@@ -579,6 +585,17 @@ return AbstractRenderer.extend({
return tooltipOptions;
},
/**
+ * Returns true iff the current graph can be clicked on to redirect to the
+ * list of records.
+ *
+ * @private
+ * @returns {boolean}
+ */
+ _isRedirectionEnabled: function () {
+ return !this.disableLinking &&
+ (this.state.mode === 'bar' || this.state.mode === 'pie');
+ },
+ /**
* Return the first index of the array list where label can be found
* or -1.
*
@@ -642,9 +659,11 @@ return AbstractRenderer.extend({
var newDataset = function (datasetLabel, originIndex) {
var data = new Array(self._getDatasetDataLength(originIndex, labels.length)).fill(0);
+ const domain = new Array(self._getDatasetDataLength(originIndex, labels.length)).fill([]);
return {
label: datasetLabel,
data: data,
+ domain: domain,
originIndex: originIndex,
};
};
@@ -658,6 +677,7 @@ return AbstractRenderer.extend({
}
var labelIndex = dataPt.labelIndex;
acc[datasetLabel].data[labelIndex] = dataPt.value;
+ acc[datasetLabel].domain[labelIndex] = dataPt.domain;
return acc;
},
{}
@@ -682,13 +702,17 @@ return AbstractRenderer.extend({
* @returns {Object} the chart options used for the current mode
*/
_prepareOptions: function (datasetsCount) {
- return {
+ const options = {
maintainAspectRatio: false,
scales: this._getScaleOptions(),
legend: this._getLegendOptions(datasetsCount),
tooltips: this._getTooltipOptions(),
elements: this._getElementOptions(),
};
+ if (this._isRedirectionEnabled()) {
+ options.onClick = this._onGraphClicked.bind(this);
+ }
+ return options;
},
/**
* Determine how to relabel a label according to a given origin.
@@ -988,6 +1012,23 @@ return AbstractRenderer.extend({
//--------------------------------------------------------------------------
/**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onGraphClicked: function (ev) {
+ const activeElement = this.chart.getElementAtEvent(ev);
+ if (activeElement.length === 0) {
+ return;
+ }
+ const domain = this.chart.data.datasets[activeElement[0]._datasetIndex].domain;
+ if (!domain) {
+ return; // empty dataset
+ }
+ this.trigger_up('open_view', {
+ domain: domain[activeElement[0]._index],
+ });
+ },
+ /**
* If the text of a legend item has been shortened and the user mouse over
* that item (actually the event type is mousemove), a tooltip with the item
* full text is displayed.
diff --git a/addons/web/static/src/js/views/graph/graph_view.js b/addons/web/static/src/js/views/graph/graph_view.js
index 488424536e6..5ae120343c6 100644
--- a/addons/web/static/src/js/views/graph/graph_view.js
+++ b/addons/web/static/src/js/views/graph/graph_view.js
@@ -115,8 +115,23 @@ var GraphView = AbstractView.extend({
this.controllerParams.withButtons = params.withButtons !== false;
this.controllerParams.measures = [...sortedMeasures, countMeasure];
this.controllerParams.groupableFields = groupableFields;
+ this.controllerParams.title = params.title || this.arch.attrs.string || _t("Untitled");
+ // retrieve form and list view ids from the action to open those views
+ // when the graph is clicked
+ function _findView(views, viewType) {
+ const view = views.find(view => {
+ return view.type === viewType;
+ });
+ return [view ? view.viewID : false, viewType];
+ }
+ this.controllerParams.views = [
+ _findView(params.actionViews, 'list'),
+ _findView(params.actionViews, 'form'),
+ ];
+
this.rendererParams.fields = this.fields;
this.rendererParams.title = this.arch.attrs.title; // TODO: use attrs.string instead
+ this.rendererParams.disableLinking = !!JSON.parse(this.arch.attrs.disable_linking || '0');
this.loadParams.mode = this.arch.attrs.type || 'bar';
this.loadParams.measure = measure || '__count__';