diff options
Diffstat (limited to 'addons/web/static/src/js/views/graph/graph_view.js')
| -rw-r--r-- | addons/web/static/src/js/views/graph/graph_view.js | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/addons/web/static/src/js/views/graph/graph_view.js b/addons/web/static/src/js/views/graph/graph_view.js new file mode 100644 index 00000000..759817c8 --- /dev/null +++ b/addons/web/static/src/js/views/graph/graph_view.js @@ -0,0 +1,162 @@ +odoo.define('web.GraphView', function (require) { +"use strict"; + +/** + * The Graph View is responsible to display a graphical (meaning: chart) + * representation of the current dataset. As of now, it is currently able to + * display data in three types of chart: bar chart, line chart and pie chart. + */ + +var AbstractView = require('web.AbstractView'); +var core = require('web.core'); +var GraphModel = require('web.GraphModel'); +var Controller = require('web.GraphController'); +var GraphRenderer = require('web.GraphRenderer'); + +var _t = core._t; +var _lt = core._lt; + +var searchUtils = require('web.searchUtils'); +var GROUPABLE_TYPES = searchUtils.GROUPABLE_TYPES; + +var GraphView = AbstractView.extend({ + display_name: _lt('Graph'), + icon: 'fa-bar-chart', + jsLibs: [ + '/web/static/lib/Chart/Chart.js', + ], + config: _.extend({}, AbstractView.prototype.config, { + Model: GraphModel, + Controller: Controller, + Renderer: GraphRenderer, + }), + viewType: 'graph', + searchMenuTypes: ['filter', 'groupBy', 'comparison', 'favorite'], + + /** + * @override + */ + init: function (viewInfo, params) { + this._super.apply(this, arguments); + + const additionalMeasures = params.additionalMeasures || []; + let measure; + const measures = {}; + const measureStrings = {}; + let groupBys = []; + const groupableFields = {}; + this.fields.__count__ = { string: _t("Count"), type: 'integer' }; + + this.arch.children.forEach(field => { + let fieldName = field.attrs.name; + if (fieldName === "id") { + return; + } + const interval = field.attrs.interval; + if (interval) { + fieldName = fieldName + ':' + interval; + } + if (field.attrs.type === 'measure') { + const { string } = this.fields[fieldName]; + measure = fieldName; + measures[fieldName] = { + description: string, + fieldName, + groupNumber: 0, + isActive: false, + itemType: 'measure', + }; + } else { + groupBys.push(fieldName); + } + if (field.attrs.string) { + measureStrings[fieldName] = field.attrs.string; + } + }); + + for (const name in this.fields) { + const field = this.fields[name]; + if (name !== 'id' && field.store === true) { + if ( + ['integer', 'float', 'monetary'].includes(field.type) || + additionalMeasures.includes(name) + ) { + measures[name] = { + description: field.string, + fieldName: name, + groupNumber: 0, + isActive: false, + itemType: 'measure', + }; + } + if (GROUPABLE_TYPES.includes(field.type)) { + groupableFields[name] = field; + } + } + } + for (const name in measureStrings) { + if (measures[name]) { + measures[name].description = measureStrings[name]; + } + } + + // Remove invisible fields from the measures + this.arch.children.forEach(field => { + let fieldName = field.attrs.name; + if (field.attrs.invisible && py.eval(field.attrs.invisible)) { + groupBys = groupBys.filter(groupBy => groupBy !== fieldName); + if (fieldName in groupableFields) { + delete groupableFields[fieldName]; + } + if (!additionalMeasures.includes(fieldName)) { + delete measures[fieldName]; + } + } + }); + + const sortedMeasures = Object.values(measures).sort((a, b) => { + const descA = a.description.toLowerCase(); + const descB = b.description.toLowerCase(); + return descA > descB ? 1 : descA < descB ? -1 : 0; + }); + const countMeasure = { + description: _t("Count"), + fieldName: '__count__', + groupNumber: 1, + isActive: false, + itemType: 'measure', + }; + 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.orderBy = this.arch.attrs.order; + this.loadParams.measure = measure || '__count__'; + this.loadParams.groupBys = groupBys; + this.loadParams.fields = this.fields; + this.loadParams.comparisonDomain = params.comparisonDomain; + this.loadParams.stacked = this.arch.attrs.stacked !== "False"; + }, +}); + +return GraphView; + +}); |
