From 69257d5d6f9c757cfba4447f63336fd14fb4be49 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 8 Nov 2013 12:32:10 +0100 Subject: [REF] work in progress. reset graph view to minimal state in addon web_graph bzr revid: ged@openerp.com-20131108113210-aptz2pne05iwca82 --- addons/web_graph/static/src/css/flotr2.css | 69 ----- addons/web_graph/static/src/css/graph.css | 80 ----- addons/web_graph/static/src/js/graph.js | 412 +------------------------- addons/web_graph/static/src/xml/web_graph.xml | 39 +-- 4 files changed, 5 insertions(+), 595 deletions(-) delete mode 100644 addons/web_graph/static/src/css/flotr2.css (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/flotr2.css b/addons/web_graph/static/src/css/flotr2.css deleted file mode 100644 index fae7b033811..00000000000 --- a/addons/web_graph/static/src/css/flotr2.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Flotr Styles */ - -.flotr-datagrid-container { - border: 1px solid #999; - border-bottom: none; - background: #fff; -} -.flotr-datagrid { - border-collapse: collapse; - border-spacing: 0; -} -.flotr-datagrid td, .flotr-datagrid th { - border: 1px solid #ccc; - padding: 1px 3px; - min-width: 2em; -} -.flotr-datagrid tr:hover, .flotr-datagrid col.hover { - background: #f3f3f3; -} -.flotr-datagrid tr:hover th, .flotr-datagrid th.hover { - background: #999; - color: #fff; -} -.flotr-datagrid th { - text-align: left; - background: #e3e3e3; - border: 2px outset #fff; -} -.flotr-datagrid-toolbar { - padding: 1px; - border-bottom: 1px solid #ccc; - background: #f9f9f9; -} -.flotr-datagrid td:hover { - background: #ccc; -} -.flotr-datagrid .first-row th { - text-align: center; -} -.flotr-canvas { - margin-bottom: -3px; - padding-bottom: 1px; -} -.flotr-tabs-group { - border-top: 1px solid #999; -} -.flotr-tab { - border: 1px solid #666; - border-top: none; - margin: 0 3px; - padding: 1px 4px; - cursor: pointer; - -moz-border-radius: 0 0 4px 4px; - -webkit-border-bottom-left-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - border-radius: 0 0 4px 4px; - opacity: 0.5; - -moz-opacity: 0.5; -} -.flotr-tab.selected { - background: #ddd; - opacity: 1; - -moz-opacity: 1; -} -.flotr-tab:hover { - background: #ccc; -} - - diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index 2fd4b5953cf..e69de29bb2d 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -1,80 +0,0 @@ -.openerp a.dropdown-menu-icon { - z-index: 1; - position: absolute; - color: #4c4c4c; - right: 8px; -} -.openerp a.dropdown-menu-icon:hover { - text-decoration: none; -} -.editor-render { - position: relative; -} -#editor-render-body { - position: relative; - width: 650px; - height: 350px; -} -.openerp .graph-dropdown { - display: none; - position: absolute; - top: 32px; - right: 8px; - padding: 8px; - border: 1px solid #afafb6; - background: white; - z-index: 1; - min-width: 160px; - overflow-x: hidden; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; - -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); - -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); - -box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); -} -.openerp .graph-dropdown h3 { - margin: 8px 4px 4px 0; - color: #8786b7; - font-size: 13px; -} -.openerp .graph-menu > li > a { - position: relative; - display: block; - padding: 2px 4px 2px 20px; - line-height: 12px; - color: #4c4c4c; - text-decoration: none; -} -.openerp .graph-menu > li > a:hover { - text-decoration: none; - background: #f0f0fa; - background: -moz-linear-gradient(#f0f0fa, #eeeef6); - background: -webkit-gradient(linear, left top, left bottom, from(#f0f0fa), to(#eeeef6)); - background: -webkit-linear-gradient(#f0f0fa, #eeeef6); - -moz-box-shadow: none; - -webkit-box-shadow: none; - -box-shadow: none; -} -.openerp .open .graph-dropdown { - display: block; -} - -.openerp .graph-menu { - padding: 0; - margin: 0; -} -.openerp .graph-menu .active:before { - content: "W"; - font-family: "entypoRegular" !important; - font-size: 24px; - font-weight: 300 !important; - color: #a3a3a3; - position: absolute; - left: 4px; - top: -2px; -} -.openerp .graph-menu li { - padding: 0; - list-style-type: none; -} diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index a84bb53fc85..f0bef5d5749 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -7,15 +7,6 @@ openerp.web_graph = function (instance) { var _lt = instance.web._lt; var _t = instance.web._t; -// removed ``undefined`` values -var filter_values = function (o) { - var out = {}; - for (var k in o) { - if (!o.hasOwnProperty(k) || o[k] === undefined) { continue; } - out[k] = o[k]; - } - return out; -}; instance.web.views.add('graph', 'instance.web_graph.GraphView'); instance.web_graph.GraphView = instance.web.View.extend({ @@ -24,411 +15,16 @@ instance.web_graph.GraphView = instance.web.View.extend({ view_type: "graph", init: function(parent, dataset, view_id, options) { - var self = this; - this._super(parent); + this._super(parent, dataset, view_id, options); this.set_default_options(options); - this.dataset = dataset; - this.view_id = view_id; - - this.mode = "bar"; // line, bar, area, pie, radar - this.orientation = false; // true: horizontal, false: vertical - this.stacked = true; - - this.spreadsheet = false; // Display data grid, allows copy to CSV - this.forcehtml = false; - this.legend = "top"; // top, inside, no - - this.domain = []; - this.context = {}; - this.group_by = []; - - this.graph = null; - }, - view_loading: function(r) { - return this.load_graph(r); - }, - destroy: function () { - if (this.graph) { - this.graph.destroy(); - } - this._super(); - }, - - load_graph: function(fields_view_get) { - // TODO: move to load_view and document - var self = this; - this.fields_view = fields_view_get; - this.$el.addClass(this.fields_view.arch.attrs['class']); - - this.mode = this.fields_view.arch.attrs.type || 'bar'; - this.orientation = this.fields_view.arch.attrs.orientation == 'horizontal'; - - var width = this.$el.parent().width(); - this.$el.css("width", width); - this.container = this.$el.find("#editor-render-body").css({ - width: width, - height: Math.min(500, width * 0.8) - })[0]; - - var graph_render = this.proxy('graph_render'); - this.$el.on('click', '.oe_graph_options a', function (evt) { - var $el = $(evt.target); - - self.graph_render({data: filter_values({ - mode: $el.data('mode'), - legend: $el.data('legend'), - orientation: $el.data('orientation'), - stacked: $el.data('stacked') - })}); - }); - - this.$el.find("#graph_show_data").click(function () { - self.spreadsheet = ! self.spreadsheet; - self.graph_render(); - }); - this.$el.find("#graph_switch").click(function () { - if (self.mode != 'radar') { - self.orientation = ! self.orientation; - } - self.graph_render(); - }); - - this.$el.find("#graph_download").click(function () { - if (self.legend == "top") { self.legend = "inside"; } - self.forcehtml = true; - - self.graph_get_data().done(function (result) { - self.graph_render_all(result).download.saveImage('png'); - }).always(function () { - self.forcehtml = false; - }); - }); - this.trigger('graph_view_loaded', fields_view_get); - }, - - get_format: function (options) { - options = options || {}; - var legend = { - show: this.legend != 'no', - }; - - switch (this.legend) { - case 'top': - legend.noColumns = 4; - legend.container = this.$el.find("div.graph_header_legend")[0]; - break; - case 'inside': - legend.position = 'nw'; - legend.backgroundColor = '#D2E8FF'; - break; - } - - return _.extend({ - legend: legend, - mouse: { - track: true, - relative: true - }, - spreadsheet : { - show: this.spreadsheet, - initialTab: "data" - }, - HtmlText : (options.xaxis && options.xaxis.labelsAngle) ? false : !this.forcehtml, - }, options); - }, - - make_graph: function (mode, container, data) { - if (mode === 'area') { mode = 'line'; } - var format = this.get_format(this['options_' + mode](data)); - return Flotr.draw(container, data.data, format); - }, - - options_bar: function (data) { - var min = _(data.data).chain() - .map(function (record) { - if (record.data.length > 0){ - return _.min(record.data, function (item) { - return item[1]; - })[1]; - } - }).min().value(); - return { - bars : { - show : true, - stacked : this.stacked, - horizontal : this.orientation, - barWidth : 0.7, - lineWidth : 1 - }, - grid : { - verticalLines : this.orientation, - horizontalLines : !this.orientation, - outline : "sw", - }, - yaxis : { - ticks: this.orientation ? data.ticks : false, - min: !this.orientation ? (min < 0 ? min : 0) : null - }, - xaxis : { - labelsAngle: 45, - ticks: this.orientation ? false : data.ticks, - min: this.orientation ? (min < 0 ? min : 0) : null - } - }; - }, - - options_pie: function (data) { - return { - pie : { - show: true - }, - grid : { - verticalLines : false, - horizontalLines : false, - outline : "", - }, - xaxis : {showLabels: false}, - yaxis : {showLabels: false}, - }; - }, - - options_radar: function (data) { - return { - radar : { - show : true, - stacked : this.stacked - }, - grid : { - circular : true, - minorHorizontalLines : true - }, - xaxis : { - ticks: data.ticks - }, - }; - }, - - options_line: function (data) { - return { - lines : { - show : true, - }, - points: { - show: true, - }, - grid : { - verticalLines : this.orientation, - horizontalLines : !this.orientation, - outline : "sw", - }, - yaxis : { - ticks: this.orientation ? data.ticks : false - }, - xaxis : { - labelsAngle: 45, - ticks: this.orientation ? false : data.ticks - } - }; - }, - - graph_get_data: function () { - var model = this.dataset.model, - domain = new instance.web.CompoundDomain(this.domain || []), - context = new instance.web.CompoundContext(this.context || {}), - group_by = this.group_by || [], - view_id = this.view_id || false, - mode = this.mode || 'bar', - orientation = this.orientation || false, - stacked = this.stacked || false; - - var obj = new instance.web.Model(model); - var view_get; - var fields; - var result = []; - var ticks = {}; - - return this.alive(obj.call("fields_view_get", [view_id, 'graph', context]).then(function(tmp) { - view_get = tmp; - fields = view_get['fields']; - var toload = _.select(group_by, function(x) { return fields[x] === undefined }); - if (toload.length >= 1) - return obj.call("fields_get", [toload, context]); - else - return $.when([]); - }).then(function (fields_to_add) { - _.extend(fields, fields_to_add); - - var tree = $($.parseXML(view_get['arch'])); - - var pos = 0; - var xaxis = _.clone(group_by || []); - var yaxis = []; - tree.find("field").each(function() { - var field = $(this); - if (! field.attr("name")) - return; - if ((group_by.length == 0) && ((! pos) || instance.web.py_eval(field.attr('group') || "false"))) { - xaxis.push(field.attr('name')); - } - if (pos && ! instance.web.py_eval(field.attr('group') || "false")) { - yaxis.push(field.attr('name')); - } - pos += 1; - }); - - if (xaxis.length === 0) - throw new Error("No field for the X axis!"); - if (yaxis.length === 0) - throw new Error("No field for the Y axis!"); - - // Convert a field's data into a displayable string - - function _convert_key(field, data) { - if (fields[field]['type'] === 'many2one') - data = data && data[0]; - return data; - } - - function _convert(field, data, tick) { - tick = tick === undefined ? true : false; - try { - data = instance.web.format_value(data, fields[field]); - } catch(e) { - data = "" + data; - } - if (tick) { - if (ticks[data] === undefined) - ticks[data] = _.size(ticks); - return ticks[data]; - } - return data || 0; - } - - function _orientation(x, y) { - if (! orientation) - return [x, y] - return [y, x] - } - - if (mode === "pie") { - return obj.call("read_group", [domain, yaxis.concat([xaxis[0]]), [xaxis[0]]], {context: context}).then(function(res) { - _.each(res, function(record) { - result.push({ - 'data': [[_convert(xaxis[0], record[xaxis[0]]), record[yaxis[0]]]], - 'label': _convert(xaxis[0], record[xaxis[0]], false) - }); - }); - }); - } else if ((! stacked) || (xaxis.length < 2)) { - var defs = []; - _.each(xaxis, function(x) { - defs.push(obj.call("read_group", [domain, yaxis.concat([x]), [x]], {context: context}).then(function(res) { - return [x, res]; - })); - }); - return $.when.apply($, defs).then(function() { - _.each(_.toArray(arguments), function(res) { - var x = res[0]; - res = res[1]; - result.push({ - 'data': _.map(res, function(record) { - return _orientation(_convert(x, record[x]), record[yaxis[0]] || 0); - }), - 'label': fields[x]['string'] - }); - }); - }); - } else { - xaxis.reverse(); - return obj.call("read_group", [domain, yaxis.concat(xaxis.slice(0, 1)), xaxis.slice(0, 1)], {context: context}).then(function(axis) { - var defs = []; - _.each(axis, function(x) { - var key = x[xaxis[0]] - defs.push(obj.call("read_group", [x['__domain'], yaxis.concat(xaxis.slice(1, 2)), xaxis.slice(1, 2)], {context: context}).then(function(res) { - return [x, key, res]; - })); - }); - return $.when.apply($, defs).then(function() { - _.each(_.toArray(arguments), function(res) { - var x = res[0]; - var key = res[1]; - res = res[2]; - result.push({ - 'data': _.map(res, function(record) { - return _orientation(_convert(xaxis[1], record[xaxis[1]]), record[yaxis[0]] || 0); - }), - 'label': _convert(xaxis[0], key, false) - }) - }); - }); - }); - } - }).then(function() { - var res = { - 'data': result, - 'ticks': _.map(ticks, function(el, key) { return [el, key || _t("Undefined")] }) - }; - return res; - })); - }, - // Render the graph and update menu styles - graph_render: function (options) { - options = options || {}; - _.extend(this, options.data); - - return this.graph_get_data() - .done(this.proxy('graph_render_all')); - }, - - graph_render_all: function (data) { - var i; - if (this.mode=='area') { - for (i=0; i 1) { - $active = $active.filter('[data-stacked=' + this.stacked + ']'); - } - $active = $active.add( - this.$el.find('a:not([data-mode])[data-legend=' + this.legend + ']')); - - $active.addClass('active'); - - if (this.spreadsheet) { - this.$el.find("#graph_show_data").addClass("active"); - } - return this.graph; }, - // render the graph using the domain, context and group_by - // calls the 'graph_data_get' python controller to process all data - // TODO: check is group_by should better be in the context - do_search: function(domain, context, group_by) { - this.domain = domain; - this.context = context; - this.group_by = group_by; - - this.graph_render(); - }, - - do_show: function() { + do_show: function () { this.do_push_state({}); return this._super(); }, + + }); }; diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index e2e316b22d9..75e32ee5070 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -1,41 +1,4 @@ -- cgit v1.2.3 From 23b9f226c782e1b8290171df530dfb0465933204 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 8 Nov 2013 12:50:30 +0100 Subject: [ADD] add (custom version of) bootstrap library to graph view (addon web_graph) bzr revid: ged@openerp.com-20131108115030-0r4e4vk379mqtkzf --- addons/web_graph/static/src/css/bootstrap.css | 1560 +++++++++++++++++++++++++ addons/web_graph/static/src/css/nv.d3.css | 769 ++++++++++++ addons/web_graph/static/src/js/graph.js | 2 - 3 files changed, 2329 insertions(+), 2 deletions(-) create mode 100644 addons/web_graph/static/src/css/bootstrap.css create mode 100644 addons/web_graph/static/src/css/nv.d3.css (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/bootstrap.css b/addons/web_graph/static/src/css/bootstrap.css new file mode 100644 index 00000000000..c1b2b49f0ee --- /dev/null +++ b/addons/web_graph/static/src/css/bootstrap.css @@ -0,0 +1,1560 @@ +/*! + * Bootstrap v3.0.0 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +/*! normalize.css v2.1.3 | MIT License | git.io/normalize */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} +audio, +canvas, +video { + display: inline-block; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +a { + background: transparent; +} +a:focus { + outline: thin dotted; +} +a:active, +a:hover { + outline: 0; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +mark { + background: #ff0; + color: #000; +} +code, +kbd, +pre, +samp { + font-family: monospace, serif; + font-size: 1em; +} +pre { + white-space: pre-wrap; +} +q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 0; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +button, +input, +select, +textarea { + font-family: inherit; + font-size: 100%; + margin: 0; +} +button, +input { + line-height: normal; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +textarea { + overflow: auto; + vertical-align: top; +} +table { + border-collapse: collapse; + border-spacing: 0; +}/* +*, +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +}*/ +html { + font-size: 62.5%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.428571429; + color: #333333; + background-color: #ffffff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #428bca; + text-decoration: none; +} +a:hover, +a:focus { + color: #2a6496; + text-decoration: underline; +} +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +img { + vertical-align: middle; +} +.img-responsive { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + padding: 4px; + line-height: 1.428571429; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.428571429; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + pointer-events: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + color: #333333; + background-color: #ebebeb; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; +} +.btn-primary { + color: #ffffff; + background-color: #428bca; + border-color: #357ebd; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #3276b1; + border-color: #285e8e; +} +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #428bca; + border-color: #357ebd; +} +.btn-warning { + color: #ffffff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ed9c28; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-danger { + color: #ffffff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #d2322d; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-success { + color: #ffffff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #47a447; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #39b3d7; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-link { + color: #428bca; + font-weight: normal; + cursor: pointer; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #2a6496; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #999999; + text-decoration: none; +} +.btn-lg { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +.btn-sm, +.btn-xs { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs { + padding: 1px 5px; +} +.btn-block { + display: block; + width: 100%; + padding-left: 0; + padding-right: 0; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon:empty { + width: 1em; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid #000000; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + border-bottom: 0 dotted; +} +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.428571429; + color: #333333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #262626; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #428bca; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #999999; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.428571429; + color: #999999; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0 dotted; + border-bottom: 4px solid #000000; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } +} +.btn-default .caret { + border-top-color: #333333; +} +.btn-primary .caret, +.btn-success .caret, +.btn-warning .caret, +.btn-danger .caret, +.btn-info .caret { + border-top-color: #fff; +} +.dropup .btn-default .caret { + border-bottom-color: #333333; +} +.dropup .btn-primary .caret, +.dropup .btn-success .caret, +.dropup .btn-warning .caret, +.dropup .btn-danger .caret, +.dropup .btn-info .caret { + border-bottom-color: #fff; +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus { + outline: none; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar:before, +.btn-toolbar:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.btn-toolbar:after { + clear: both; +} +.btn-toolbar .btn-group { + float: left; +} +.btn-toolbar > .btn + .btn, +.btn-toolbar > .btn-group + .btn, +.btn-toolbar > .btn + .btn-group, +.btn-toolbar > .btn-group + .btn-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child > .btn:last-child, +.btn-group > .btn-group:first-child > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn-group:last-child > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group-xs > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; + padding: 1px 5px; +} +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after { + content: " "; + /* 1 */ + + display: table; + /* 2 */ + +} +.btn-group-vertical > .btn-group:after { + clear: both; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-bottom-left-radius: 4px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child > .btn:last-child, +.btn-group-vertical > .btn-group:first-child > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified .btn { + float: none; + display: table-cell; + width: 1%; +} +[data-toggle="buttons"] > .btn > input[type="radio"], +[data-toggle="buttons"] > .btn > input[type="checkbox"] { + display: none; +} diff --git a/addons/web_graph/static/src/css/nv.d3.css b/addons/web_graph/static/src/css/nv.d3.css new file mode 100644 index 00000000000..cae834827cc --- /dev/null +++ b/addons/web_graph/static/src/css/nv.d3.css @@ -0,0 +1,769 @@ + +/******************** + * HTML CSS + */ + + +.chartWrap { + margin: 0; + padding: 0; + overflow: hidden; +} + +/******************** + Box shadow and border radius styling +*/ +.nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip { + -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); + -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); + box-shadow: 0 5px 10px rgba(0,0,0,.2); + + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +/******************** + * TOOLTIP CSS + */ + +.nvtooltip { + position: absolute; + background-color: rgba(255,255,255,1.0); + padding: 1px; + border: 1px solid rgba(0,0,0,.2); + z-index: 10000; + + font-family: Arial; + font-size: 13px; + text-align: left; + pointer-events: none; + + white-space: nowrap; + + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +/*Give tooltips that old fade in transition by + putting a "with-transitions" class on the container div. +*/ +.nvtooltip.with-transitions, .with-transitions .nvtooltip { + transition: opacity 250ms linear; + -moz-transition: opacity 250ms linear; + -webkit-transition: opacity 250ms linear; + + transition-delay: 250ms; + -moz-transition-delay: 250ms; + -webkit-transition-delay: 250ms; +} + +.nvtooltip.x-nvtooltip, +.nvtooltip.y-nvtooltip { + padding: 8px; +} + +.nvtooltip h3 { + margin: 0; + padding: 4px 14px; + line-height: 18px; + font-weight: normal; + background-color: rgba(247,247,247,0.75); + text-align: center; + + border-bottom: 1px solid #ebebeb; + + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0; +} + +.nvtooltip p { + margin: 0; + padding: 5px 14px; + text-align: center; +} + +.nvtooltip span { + display: inline-block; + margin: 2px 0; +} + +.nvtooltip table { + margin: 6px; + border-spacing:0; +} + + +.nvtooltip table td { + padding: 2px 9px 2px 0; + vertical-align: middle; +} + +.nvtooltip table td.key { + font-weight:normal; +} +.nvtooltip table td.value { + text-align: right; + font-weight: bold; +} + +.nvtooltip table tr.highlight td { + padding: 1px 9px 1px 0; + border-bottom-style: solid; + border-bottom-width: 1px; + border-top-style: solid; + border-top-width: 1px; +} + +.nvtooltip table td.legend-color-guide div { + width: 8px; + height: 8px; + vertical-align: middle; +} + +.nvtooltip .footer { + padding: 3px; + text-align: center; +} + + +.nvtooltip-pending-removal { + position: absolute; + pointer-events: none; +} + + +/******************** + * SVG CSS + */ + + +svg { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + /* Trying to get SVG to act like a greedy block in all browsers */ + display: block; + width:100%; + height:100%; +} + + +svg text { + font: normal 12px Arial; +} + +svg .title { + font: bold 14px Arial; +} + +.nvd3 .nv-background { + fill: white; + fill-opacity: 0; + /* + pointer-events: none; + */ +} + +.nvd3.nv-noData { + font-size: 18px; + font-weight: bold; +} + + +/********** +* Brush +*/ + +.nv-brush .extent { + fill-opacity: .125; + shape-rendering: crispEdges; +} + + + +/********** +* Legend +*/ + +.nvd3 .nv-legend .nv-series { + cursor: pointer; +} + +.nvd3 .nv-legend .disabled circle { + fill-opacity: 0; +} + + + +/********** +* Axes +*/ +.nvd3 .nv-axis { + pointer-events:none; +} + +.nvd3 .nv-axis path { + fill: none; + stroke: #000; + stroke-opacity: .75; + shape-rendering: crispEdges; +} + +.nvd3 .nv-axis path.domain { + stroke-opacity: .75; +} + +.nvd3 .nv-axis.nv-x path.domain { + stroke-opacity: 0; +} + +.nvd3 .nv-axis line { + fill: none; + stroke: #e5e5e5; + shape-rendering: crispEdges; +} + +.nvd3 .nv-axis .zero line, +/*this selector may not be necessary*/ .nvd3 .nv-axis line.zero { + stroke-opacity: .75; +} + +.nvd3 .nv-axis .nv-axisMaxMin text { + font-weight: bold; +} + +.nvd3 .x .nv-axis .nv-axisMaxMin text, +.nvd3 .x2 .nv-axis .nv-axisMaxMin text, +.nvd3 .x3 .nv-axis .nv-axisMaxMin text { + text-anchor: middle +} + + + +/********** +* Brush +*/ + +.nv-brush .resize path { + fill: #eee; + stroke: #666; +} + + + +/********** +* Bars +*/ + +.nvd3 .nv-bars .negative rect { + zfill: brown; +} + +.nvd3 .nv-bars rect { + zfill: steelblue; + fill-opacity: .75; + + transition: fill-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear; +} + +.nvd3 .nv-bars rect.hover { + fill-opacity: 1; +} + +.nvd3 .nv-bars .hover rect { + fill: lightblue; +} + +.nvd3 .nv-bars text { + fill: rgba(0,0,0,0); +} + +.nvd3 .nv-bars .hover text { + fill: rgba(0,0,0,1); +} + + +/********** +* Bars +*/ + +.nvd3 .nv-multibar .nv-groups rect, +.nvd3 .nv-multibarHorizontal .nv-groups rect, +.nvd3 .nv-discretebar .nv-groups rect { + stroke-opacity: 0; + + transition: fill-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear; +} + +.nvd3 .nv-multibar .nv-groups rect:hover, +.nvd3 .nv-multibarHorizontal .nv-groups rect:hover, +.nvd3 .nv-discretebar .nv-groups rect:hover { + fill-opacity: 1; +} + +.nvd3 .nv-discretebar .nv-groups text, +.nvd3 .nv-multibarHorizontal .nv-groups text { + font-weight: bold; + fill: rgba(0,0,0,1); + stroke: rgba(0,0,0,0); +} + +/*********** +* Pie Chart +*/ + +.nvd3.nv-pie path { + stroke-opacity: 0; + transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-pie .nv-slice text { + stroke: #000; + stroke-width: 0; +} + +.nvd3.nv-pie path { + stroke: #fff; + stroke-width: 1px; + stroke-opacity: 1; +} + +.nvd3.nv-pie .hover path { + fill-opacity: .7; +} +.nvd3.nv-pie .nv-label { + pointer-events: none; +} +.nvd3.nv-pie .nv-label rect { + fill-opacity: 0; + stroke-opacity: 0; +} + +/********** +* Lines +*/ + +.nvd3 .nv-groups path.nv-line { + fill: none; + stroke-width: 1.5px; + /* + stroke-linecap: round; + shape-rendering: geometricPrecision; + + transition: stroke-width 250ms linear; + -moz-transition: stroke-width 250ms linear; + -webkit-transition: stroke-width 250ms linear; + + transition-delay: 250ms + -moz-transition-delay: 250ms; + -webkit-transition-delay: 250ms; + */ +} + +.nvd3 .nv-groups path.nv-line.nv-thin-line { + stroke-width: 1px; +} + + +.nvd3 .nv-groups path.nv-area { + stroke: none; + /* + stroke-linecap: round; + shape-rendering: geometricPrecision; + + stroke-width: 2.5px; + transition: stroke-width 250ms linear; + -moz-transition: stroke-width 250ms linear; + -webkit-transition: stroke-width 250ms linear; + + transition-delay: 250ms + -moz-transition-delay: 250ms; + -webkit-transition-delay: 250ms; + */ +} + +.nvd3 .nv-line.hover path { + stroke-width: 6px; +} + +/* +.nvd3.scatter .groups .point { + fill-opacity: 0.1; + stroke-opacity: 0.1; +} + */ + +.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point { + fill-opacity: 0; + stroke-opacity: 0; +} + +.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point { + fill-opacity: .5 !important; + stroke-opacity: .5 !important; +} + + +.with-transitions .nvd3 .nv-groups .nv-point { + transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-scatter .nv-groups .nv-point.hover, +.nvd3 .nv-groups .nv-point.hover { + stroke-width: 7px; + fill-opacity: .95 !important; + stroke-opacity: .95 !important; +} + + +.nvd3 .nv-point-paths path { + stroke: #aaa; + stroke-opacity: 0; + fill: #eee; + fill-opacity: 0; +} + + + +.nvd3 .nv-indexLine { + cursor: ew-resize; +} + + +/********** +* Distribution +*/ + +.nvd3 .nv-distribution { + pointer-events: none; +} + + + +/********** +* Scatter +*/ + +/* **Attempting to remove this for useVoronoi(false), need to see if it's required anywhere +.nvd3 .nv-groups .nv-point { + pointer-events: none; +} +*/ + +.nvd3 .nv-groups .nv-point.hover { + stroke-width: 20px; + stroke-opacity: .5; +} + +.nvd3 .nv-scatter .nv-point.hover { + fill-opacity: 1; +} + +/* +.nv-group.hover .nv-point { + fill-opacity: 1; +} +*/ + + +/********** +* Stacked Area +*/ + +.nvd3.nv-stackedarea path.nv-area { + fill-opacity: .7; + /* + stroke-opacity: .65; + fill-opacity: 1; + */ + stroke-opacity: 0; + + transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; + + /* + transition-delay: 500ms; + -moz-transition-delay: 500ms; + -webkit-transition-delay: 500ms; + */ + +} + +.nvd3.nv-stackedarea path.nv-area.hover { + fill-opacity: .9; + /* + stroke-opacity: .85; + */ +} +/* +.d3stackedarea .groups path { + stroke-opacity: 0; +} + */ + + + +.nvd3.nv-stackedarea .nv-groups .nv-point { + stroke-opacity: 0; + fill-opacity: 0; +} + +/* +.nvd3.nv-stackedarea .nv-groups .nv-point.hover { + stroke-width: 20px; + stroke-opacity: .75; + fill-opacity: 1; +}*/ + + + +/********** +* Line Plus Bar +*/ + +.nvd3.nv-linePlusBar .nv-bar rect { + fill-opacity: .75; +} + +.nvd3.nv-linePlusBar .nv-bar rect:hover { + fill-opacity: 1; +} + + +/********** +* Bullet +*/ + +.nvd3.nv-bullet { font: 10px sans-serif; } +.nvd3.nv-bullet .nv-measure { fill-opacity: .8; } +.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; } +.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; } +.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; } +.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; } +.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; } +.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; } +.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; } +.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; } +.nvd3.nv-bullet .nv-subtitle { fill: #999; } + + +.nvd3.nv-bullet .nv-range { + fill: #bababa; + fill-opacity: .4; +} +.nvd3.nv-bullet .nv-range:hover { + fill-opacity: .7; +} + + + +/********** +* Sparkline +*/ + +.nvd3.nv-sparkline path { + fill: none; +} + +.nvd3.nv-sparklineplus g.nv-hoverValue { + pointer-events: none; +} + +.nvd3.nv-sparklineplus .nv-hoverValue line { + stroke: #333; + stroke-width: 1.5px; + } + +.nvd3.nv-sparklineplus, +.nvd3.nv-sparklineplus g { + pointer-events: all; +} + +.nvd3 .nv-hoverArea { + fill-opacity: 0; + stroke-opacity: 0; +} + +.nvd3.nv-sparklineplus .nv-xValue, +.nvd3.nv-sparklineplus .nv-yValue { + /* + stroke: #666; + */ + stroke-width: 0; + font-size: .9em; + font-weight: normal; +} + +.nvd3.nv-sparklineplus .nv-yValue { + stroke: #f66; +} + +.nvd3.nv-sparklineplus .nv-maxValue { + stroke: #2ca02c; + fill: #2ca02c; +} + +.nvd3.nv-sparklineplus .nv-minValue { + stroke: #d62728; + fill: #d62728; +} + +.nvd3.nv-sparklineplus .nv-currentValue { + /* + stroke: #444; + fill: #000; + */ + font-weight: bold; + font-size: 1.1em; +} + +/********** +* historical stock +*/ + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick { + stroke-width: 2px; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover { + stroke-width: 4px; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive { + stroke: #2ca02c; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative { + stroke: #d62728; +} + +.nvd3.nv-historicalStockChart .nv-axis .nv-axislabel { + font-weight: bold; +} + +.nvd3.nv-historicalStockChart .nv-dragTarget { + fill-opacity: 0; + stroke: none; + cursor: move; +} + +.nvd3 .nv-brush .extent { + /* + cursor: ew-resize !important; + */ + fill-opacity: 0 !important; +} + +.nvd3 .nv-brushBackground rect { + stroke: #000; + stroke-width: .4; + fill: #fff; + fill-opacity: .7; +} + + + +/********** +* Indented Tree +*/ + + +/** + * TODO: the following 3 selectors are based on classes used in the example. I should either make them standard and leave them here, or move to a CSS file not included in the library + */ +.nvd3.nv-indentedtree .name { + margin-left: 5px; +} + +.nvd3.nv-indentedtree .clickable { + color: #08C; + cursor: pointer; +} + +.nvd3.nv-indentedtree span.clickable:hover { + color: #005580; + text-decoration: underline; +} + + +.nvd3.nv-indentedtree .nv-childrenCount { + display: inline-block; + margin-left: 5px; +} + +.nvd3.nv-indentedtree .nv-treeicon { + cursor: pointer; + /* + cursor: n-resize; + */ +} + +.nvd3.nv-indentedtree .nv-treeicon.nv-folded { + cursor: pointer; + /* + cursor: s-resize; + */ +} + +/********** +* Parallel Coordinates +*/ + +.nvd3 .background path { + fill: none; + stroke: #ccc; + stroke-opacity: .4; + shape-rendering: crispEdges; +} + +.nvd3 .foreground path { + fill: none; + stroke: steelblue; + stroke-opacity: .7; +} + +.nvd3 .brush .extent { + fill-opacity: .3; + stroke: #fff; + shape-rendering: crispEdges; +} + +.nvd3 .axis line, .axis path { + fill: none; + stroke: #000; + shape-rendering: crispEdges; +} + +.nvd3 .axis text { + text-shadow: 0 1px 0 #fff; +} + +/**** +Interactive Layer +*/ +.nvd3 .nv-interactiveGuideLine { + pointer-events:none; +} +.nvd3 line.nv-guideline { + stroke: #ccc; +} \ No newline at end of file diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index f0bef5d5749..af63c78cff1 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -16,8 +16,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ init: function(parent, dataset, view_id, options) { this._super(parent, dataset, view_id, options); - this.set_default_options(options); - }, do_show: function () { -- cgit v1.2.3 From 7ad9aecc13e23ce40a4b22e31ed5f7f9435adf4c Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 8 Nov 2013 14:08:06 +0100 Subject: [IMP] add widgets (chart view and pivot view) in addon web_graph bzr revid: ged@openerp.com-20131108130806-ez2a6sxdsy0bzg62 --- addons/web_graph/static/src/js/graph.js | 57 +++++++++++++++++++++++++-- addons/web_graph/static/src/xml/web_graph.xml | 35 ++++++++++++++-- 2 files changed, 85 insertions(+), 7 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index af63c78cff1..173f2e8973a 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -1,28 +1,79 @@ /*--------------------------------------------------------- * OpenERP web_graph *---------------------------------------------------------*/ +/*global openerp:true*/ +/*global $:true*/ +'use strict'; openerp.web_graph = function (instance) { var _lt = instance.web._lt; var _t = instance.web._t; - instance.web.views.add('graph', 'instance.web_graph.GraphView'); + instance.web_graph.GraphView = instance.web.View.extend({ - template: "GraphView", + template: 'GraphView', display_name: _lt('Graph'), - view_type: "graph", + view_type: 'graph', + events: { + 'click .graph_mode_selection li' : function (event) { + event.preventDefault(); + var mode = event.target.attributes['data-mode'].nodeValue; + if (mode == 'data') { + this.chart_view.hide(); + this.pivot_table.show(); + } else { + this.pivot_table.hide(); + this.chart_view.show(mode); + } + }, + }, init: function(parent, dataset, view_id, options) { this._super(parent, dataset, view_id, options); + this.pivot_table = new PivotTable(this); + this.chart_view = new ChartView(this); + }, + + view_loading: function (fields_view_get) { + this.pivot_table.appendTo('.graph_pivot'); + this.chart_view.appendTo('.graph_chart'); + this.chart_view.hide(); }, do_show: function () { this.do_push_state({}); return this._super(); }, +}); + +var PivotTable = instance.web.Widget.extend({ + template: 'pivot_table', + + show: function () { + this.$el.css('display', 'block'); + }, + + hide: function () { + this.$el.css('display', 'none'); + }, + +}); + +var ChartView = instance.web.Widget.extend({ + template: 'chart_view', + + show: function () { + this.$el.css('display', 'block'); + }, + hide: function () { + this.$el.css('display', 'none'); + }, }); + + + }; diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 75e32ee5070..f38dadc74ce 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -1,4 +1,31 @@ - + + +
+
+ + +
+ +
+
+
+
+
+
+ + +
Hello Pivot
+
+ + + + + +
-- cgit v1.2.3 From eab6a192e9413c09b67b28fbf856d3314051bc4a Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 8 Nov 2013 16:20:48 +0100 Subject: [IMP] add pie, line and bar chart to the chartview widget (addon web_graph) bzr revid: ged@openerp.com-20131108152048-0akyhf0c7lcdsqjh --- addons/web_graph/static/src/js/graph.js | 190 +++++++++++++++++++++++++- addons/web_graph/static/src/xml/web_graph.xml | 2 +- 2 files changed, 189 insertions(+), 3 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 173f2e8973a..aa4275493b6 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -12,6 +12,10 @@ var _t = instance.web._t; instance.web.views.add('graph', 'instance.web_graph.GraphView'); + /** + * GraphView view. It mostly contains two widgets (PivotTable and ChartView) + * and some data. + */ instance.web_graph.GraphView = instance.web.View.extend({ template: 'GraphView', display_name: _lt('Graph'), @@ -19,13 +23,17 @@ instance.web_graph.GraphView = instance.web.View.extend({ events: { 'click .graph_mode_selection li' : function (event) { event.preventDefault(); - var mode = event.target.attributes['data-mode'].nodeValue; + var self = this, + mode = event.target.attributes['data-mode'].nodeValue; if (mode == 'data') { this.chart_view.hide(); this.pivot_table.show(); } else { this.pivot_table.hide(); - this.chart_view.show(mode); + this.get_data().done(function (data) { + self.chart_view.draw(data, mode); + self.chart_view.show(mode); + }); } }, }, @@ -34,20 +42,56 @@ instance.web_graph.GraphView = instance.web.View.extend({ this._super(parent, dataset, view_id, options); this.pivot_table = new PivotTable(this); this.chart_view = new ChartView(this); + this.x_groups = []; + this.measure = null; + this.domain = []; + this.model = null; + }, view_loading: function (fields_view_get) { + var self = this; + this.model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}); + + // get the default groupbys and measure defined in the field view + _.each(fields_view_get.arch.children, function (field) { + if ('name' in field.attrs) { + if ('operator' in field.attrs) { + self.measure = field.attrs.name; + } else { + self.x_groups.push(field.attrs.name); + } + } + }); + + this.chart_view.set_measure(this.measure); this.pivot_table.appendTo('.graph_pivot'); this.chart_view.appendTo('.graph_chart'); this.chart_view.hide(); + this.get_data().done(this.pivot_table.draw); + }, + + get_data: function () { + var view_fields = this.x_groups.concat(this.measure); + + return query_groups(this.model, view_fields, this.domain, this.x_groups); + }, + + do_search: function (domain, context, group_by) { + this.domain = new instance.web.CompoundDomain(domain); }, do_show: function () { this.do_push_state({}); return this._super(); }, + }); + /** + * PivotTable widget. It displays the data in tabular data and allows the + * user to drill down and up in the table + */ var PivotTable = instance.web.Widget.extend({ template: 'pivot_table', @@ -59,10 +103,18 @@ var PivotTable = instance.web.Widget.extend({ this.$el.css('display', 'none'); }, + draw: function (data) { + console.log("data",data); + }, }); + /** + * ChartView widget. It displays the data in chart form, using the nvd3 + * library. Various modes include bar charts, pie charts or line charts. + */ var ChartView = instance.web.Widget.extend({ template: 'chart_view', + measure: null, show: function () { this.$el.css('display', 'block'); @@ -72,8 +124,142 @@ var ChartView = instance.web.Widget.extend({ this.$el.css('display', 'none'); }, + set_measure: function (measure) { + this.measure = measure; + }, + + draw: function (data, mode) { + // d3.select('.graph_chart_svg').remove(); + + $('.graph_chart_svg').empty(); + $('.graph_chart_svg').append(''); + + switch (mode) { + case 'bar_chart': + this.render_bar_chart(data); + break; + case 'pie_chart': + this.render_pie_chart(data); + break; + case 'line_chart': + this.render_line_chart(data); + break; + } + }, + + format_data: function (datapt) { + var val = datapt.attributes; + return { + x: datapt.attributes.value[1], + y: this.measure ? val.aggregates[this.measure] : val.length, + }; + }, + + render_bar_chart: function (data) { + var formatted_data = [{ + key: 'Bar chart', + values: _.map(data, this.format_data.bind(this)), + }]; + + nv.addGraph(function () { + var chart = nv.models.discreteBarChart() + .tooltips(false) + .showValues(true) + .staggerLabels(true) + .width(650) + .height(400); + + d3.select('.graph_chart_svg svg') + .datum(formatted_data) + .attr('width', 650) + .attr('height', 400) + .call(chart); + + nv.utils.windowResize(chart.update); + return chart; + }); + }, + + render_pie_chart: function (data) { + var formatted_data = _.map(data, this.format_data.bind(this)); + + nv.addGraph(function () { + var chart = nv.models.pieChart() + .color(d3.scale.category10().range()) + .width(650) + .height(400); + + d3.select('.graph_chart_svg svg') + .datum(formatted_data) + .transition().duration(1200) + .attr('width', 650) + .attr('height', 400) + .call(chart); + + nv.utils.windowResize(chart.update); + return chart; + }); + }, + + render_line_chart: function (data) { + var measure_label = (this.measure) ? this.measure : 'Quantity'; + + var formatted_data = [{ + key: measure_label, + values: _.map(data, this.format_data.bind(this)) + }]; + + nv.addGraph(function () { + var width = 600, + height = 300; + + var chart = nv.models.lineChart() + .x(function (d,u) { return u; }) + .width(width) + .height(height) + .margin({top: 30, right: 20, bottom: 20, left: 60}); + + d3.select('.graph_chart_svg svg') + .attr('width', width) + .attr('height', height) + .datum(formatted_data) + .call(chart); + + return chart; + }); + }, + }); +/** + * Query the server and return a deferred which will return the data + * with all the groupbys applied (this is done for now, but the goal + * is to modify read_group in order to allow eager and lazy groupbys + */ +function query_groups (model, fields, domain, groupbys) { + return model.query(fields) + .filter(domain) + .group_by(groupbys) + .then(function (results) { + var non_empty_results = _.filter(results, function (group) { + return group.attributes.length > 0; + }); + if (groupbys.length <= 1) { + return non_empty_results; + } else { + var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) { + var new_domain = result.model._domain; + var new_groupings = groupbys.slice(1); + return query_groups(model, fields,new_domain, new_groupings).then(function (subgroups) { + result.subgroups_data = subgroups; + }); + })); + return get_subgroups.then(function () { + return non_empty_results; + }); + } + }); +} }; diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index f38dadc74ce..4798e4b1c72 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -25,7 +25,7 @@ - +
-- cgit v1.2.3 From 906d5168cc29f3258dfa2899de1e8c45f88098b7 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 8 Nov 2013 16:27:17 +0100 Subject: [IMP] small cleanups to chartview widget (addon web_graph) bzr revid: ged@openerp.com-20131108152717-stbx0us8ipom67iq --- addons/web_graph/static/src/js/graph.js | 69 +++++++++++++-------------- addons/web_graph/static/src/xml/web_graph.xml | 1 - 2 files changed, 32 insertions(+), 38 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index aa4275493b6..ca704e31527 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -129,21 +129,19 @@ var ChartView = instance.web.Widget.extend({ }, draw: function (data, mode) { - // d3.select('.graph_chart_svg').remove(); - - $('.graph_chart_svg').empty(); - $('.graph_chart_svg').append(''); + $('.graph_chart').empty(); + $('.graph_chart').append(''); switch (mode) { case 'bar_chart': this.render_bar_chart(data); break; - case 'pie_chart': - this.render_pie_chart(data); - break; case 'line_chart': this.render_line_chart(data); break; + case 'pie_chart': + this.render_pie_chart(data); + break; } }, @@ -169,29 +167,8 @@ var ChartView = instance.web.Widget.extend({ .width(650) .height(400); - d3.select('.graph_chart_svg svg') - .datum(formatted_data) - .attr('width', 650) - .attr('height', 400) - .call(chart); - - nv.utils.windowResize(chart.update); - return chart; - }); - }, - - render_pie_chart: function (data) { - var formatted_data = _.map(data, this.format_data.bind(this)); - - nv.addGraph(function () { - var chart = nv.models.pieChart() - .color(d3.scale.category10().range()) - .width(650) - .height(400); - - d3.select('.graph_chart_svg svg') + d3.select('.graph_chart svg') .datum(formatted_data) - .transition().duration(1200) .attr('width', 650) .attr('height', 400) .call(chart); @@ -210,18 +187,15 @@ var ChartView = instance.web.Widget.extend({ }]; nv.addGraph(function () { - var width = 600, - height = 300; - var chart = nv.models.lineChart() .x(function (d,u) { return u; }) - .width(width) - .height(height) + .width(600) + .height(300) .margin({top: 30, right: 20, bottom: 20, left: 60}); - d3.select('.graph_chart_svg svg') - .attr('width', width) - .attr('height', height) + d3.select('.graph_chart svg') + .attr('width', 600) + .attr('height', 300) .datum(formatted_data) .call(chart); @@ -229,6 +203,27 @@ var ChartView = instance.web.Widget.extend({ }); }, + render_pie_chart: function (data) { + var formatted_data = _.map(data, this.format_data.bind(this)); + + nv.addGraph(function () { + var chart = nv.models.pieChart() + .color(d3.scale.category10().range()) + .width(650) + .height(400); + + d3.select('.graph_chart svg') + .datum(formatted_data) + .transition().duration(1200) + .attr('width', 650) + .attr('height', 400) + .call(chart); + + nv.utils.windowResize(chart.update); + return chart; + }); + }, + }); /** diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 4798e4b1c72..2a93bcfcb94 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -25,7 +25,6 @@ -
-- cgit v1.2.3 From 4dd5ac99249c3addd3806b31476a536c721b4fb6 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 8 Nov 2013 16:41:14 +0100 Subject: [FIX] fix a bug preventing hide and show method of chartview widget to function properly (addon web_graph) bzr revid: ged@openerp.com-20131108154114-25zqn3jq5u6iuibt --- addons/web_graph/static/src/js/graph.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index ca704e31527..30318a923a7 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -1,8 +1,10 @@ /*--------------------------------------------------------- * OpenERP web_graph *---------------------------------------------------------*/ -/*global openerp:true*/ +/*global openerp:true $:true*/ /*global $:true*/ +/*global _:true*/ + 'use strict'; openerp.web_graph = function (instance) { @@ -117,11 +119,11 @@ var ChartView = instance.web.Widget.extend({ measure: null, show: function () { - this.$el.css('display', 'block'); + $('.graph_chart').css('display', 'block'); }, hide: function () { - this.$el.css('display', 'none'); + $('.graph_chart').css('display', 'none'); }, set_measure: function (measure) { -- cgit v1.2.3 From 6ecbf2ef80552656b1ea065ba0fb5ae92967ab1d Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 12 Nov 2013 09:38:27 +0100 Subject: [IMP] add access to model fields description in addon web_graph bzr revid: ged@openerp.com-20131112083827-fy9i054l9mq3vynz --- addons/web_graph/static/src/js/graph.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 30318a923a7..e5e297dc2a8 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -1,11 +1,10 @@ /*--------------------------------------------------------- * OpenERP web_graph *---------------------------------------------------------*/ -/*global openerp:true $:true*/ -/*global $:true*/ -/*global _:true*/ 'use strict'; +/* jshint undef: false */ + openerp.web_graph = function (instance) { @@ -48,6 +47,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.measure = null; this.domain = []; this.model = null; + this.model_fields = []; }, @@ -71,6 +71,10 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.chart_view.appendTo('.graph_chart'); this.chart_view.hide(); this.get_data().done(this.pivot_table.draw); + + return this.model.call('fields_get', []).then(function (fields) { + self.model_fields = fields; + }); }, get_data: function () { @@ -79,6 +83,10 @@ instance.web_graph.GraphView = instance.web.View.extend({ return query_groups(this.model, view_fields, this.domain, this.x_groups); }, + get_desc: function(field_id) { + return this.model_fields[field_id].string; + }, + do_search: function (domain, context, group_by) { this.domain = new instance.web.CompoundDomain(domain); }, @@ -106,7 +114,7 @@ var PivotTable = instance.web.Widget.extend({ }, draw: function (data) { - console.log("data",data); + console.log('data',data); }, }); @@ -260,3 +268,4 @@ function query_groups (model, fields, domain, groupbys) { }; + -- cgit v1.2.3 From d947299a740b9b7f6d40097b69235d6aa004aa38 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 12 Nov 2013 09:49:55 +0100 Subject: [FIX] fix pivottable and chartview widget to use their template instead of hardcoded divs (addon web_graph) bzr revid: ged@openerp.com-20131112084955-2x8o57ndln0xx0nx --- addons/web_graph/static/src/js/graph.js | 12 ++++++------ addons/web_graph/static/src/xml/web_graph.xml | 3 +-- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index e5e297dc2a8..5cfd437d666 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -67,8 +67,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ }); this.chart_view.set_measure(this.measure); - this.pivot_table.appendTo('.graph_pivot'); - this.chart_view.appendTo('.graph_chart'); + this.pivot_table.appendTo('.graph_main_content'); + this.chart_view.appendTo('.graph_main_content'); this.chart_view.hide(); this.get_data().done(this.pivot_table.draw); @@ -127,11 +127,11 @@ var ChartView = instance.web.Widget.extend({ measure: null, show: function () { - $('.graph_chart').css('display', 'block'); + this.$el.css('display', 'block'); }, hide: function () { - $('.graph_chart').css('display', 'none'); + this.$el.css('display', 'none'); }, set_measure: function (measure) { @@ -139,8 +139,8 @@ var ChartView = instance.web.Widget.extend({ }, draw: function (data, mode) { - $('.graph_chart').empty(); - $('.graph_chart').append(''); + this.$el.empty(); + this.$el.append(''); switch (mode) { case 'bar_chart': diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 2a93bcfcb94..409a86dfc06 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -15,8 +15,6 @@
-
-
@@ -25,6 +23,7 @@ +
-- cgit v1.2.3 From 4d7150fc5895e518e313398715170020c3287eca Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 12 Nov 2013 12:31:34 +0100 Subject: [REF] large refactoring of addon web_graph (mainly add widget BasicDataView and many cleanups) bzr revid: ged@openerp.com-20131112113134-w2298fsh1va4jpm7 --- addons/web_graph/static/src/js/graph.js | 124 +++++++++++++++----------------- 1 file changed, 58 insertions(+), 66 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 5cfd437d666..a36f8f68db0 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -21,6 +21,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ template: 'GraphView', display_name: _lt('Graph'), view_type: 'graph', + events: { 'click .graph_mode_selection li' : function (event) { event.preventDefault(); @@ -31,62 +32,46 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.pivot_table.show(); } else { this.pivot_table.hide(); - this.get_data().done(function (data) { - self.chart_view.draw(data, mode); - self.chart_view.show(mode); - }); + this.chart_view.set_mode(mode); + this.chart_view.show(); } }, }, - init: function(parent, dataset, view_id, options) { - this._super(parent, dataset, view_id, options); - this.pivot_table = new PivotTable(this); - this.chart_view = new ChartView(this); - this.x_groups = []; - this.measure = null; - this.domain = []; - this.model = null; - this.model_fields = []; - - }, - view_loading: function (fields_view_get) { var self = this; - this.model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}); + var model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}); + var measure = null; + var groupbys = [] // get the default groupbys and measure defined in the field view _.each(fields_view_get.arch.children, function (field) { if ('name' in field.attrs) { if ('operator' in field.attrs) { - self.measure = field.attrs.name; + measure = field.attrs.name; } else { - self.x_groups.push(field.attrs.name); + groupbys.push(field.attrs.name); } } }); - this.chart_view.set_measure(this.measure); - this.pivot_table.appendTo('.graph_main_content'); - this.chart_view.appendTo('.graph_main_content'); - this.chart_view.hide(); - this.get_data().done(this.pivot_table.draw); - - return this.model.call('fields_get', []).then(function (fields) { - self.model_fields = fields; + return model.call('fields_get', []).then(function (fields) { + var view_fields = groupbys.concat(measure); + query_groups(model, view_fields, self.domain, groupbys).done(function (data) { + self.pivot_table = new PivotTable(data, fields, groupbys, measure); + self.chart_view = new ChartView(data, fields, groupbys, measure); + self.pivot_table.appendTo('.graph_main_content') + .done(function () { + self.pivot_table.draw(); + }); + self.chart_view.appendTo('.graph_main_content') + .done(function () { + self.chart_view.hide(); + }); + }); }); }, - get_data: function () { - var view_fields = this.x_groups.concat(this.measure); - - return query_groups(this.model, view_fields, this.domain, this.x_groups); - }, - - get_desc: function(field_id) { - return this.model_fields[field_id].string; - }, - do_search: function (domain, context, group_by) { this.domain = new instance.web.CompoundDomain(domain); }, @@ -99,11 +84,17 @@ instance.web_graph.GraphView = instance.web.View.extend({ }); /** - * PivotTable widget. It displays the data in tabular data and allows the - * user to drill down and up in the table + * BasicDataView widget. Basic widget to manage show/hide functionality + * and to initialize some attributes. It is inherited by PivotTable + * and ChartView widget. */ -var PivotTable = instance.web.Widget.extend({ - template: 'pivot_table', +var BasicDataView = instance.web.Widget.extend({ + init: function (data, fields, groupby, measure) { + this.data = data; + this.fields = fields; + this.groupby = groupby; + this.measure = measure; + }, show: function () { this.$el.css('display', 'block'); @@ -112,9 +103,17 @@ var PivotTable = instance.web.Widget.extend({ hide: function () { this.$el.css('display', 'none'); }, +}); - draw: function (data) { - console.log('data',data); + /** + * PivotTable widget. It displays the data in tabular data and allows the + * user to drill down and up in the table + */ +var PivotTable = BasicDataView.extend({ + template: 'pivot_table', + + draw: function () { + console.log('data',this.data); }, }); @@ -122,35 +121,28 @@ var PivotTable = instance.web.Widget.extend({ * ChartView widget. It displays the data in chart form, using the nvd3 * library. Various modes include bar charts, pie charts or line charts. */ -var ChartView = instance.web.Widget.extend({ +var ChartView = BasicDataView.extend({ template: 'chart_view', - measure: null, + mode: 'bar_chart', - show: function () { - this.$el.css('display', 'block'); - }, - - hide: function () { - this.$el.css('display', 'none'); - }, - - set_measure: function (measure) { - this.measure = measure; + set_mode: function (mode) { + this.mode = mode; + this.draw(); }, - draw: function (data, mode) { + draw: function () { this.$el.empty(); this.$el.append(''); - switch (mode) { + switch (this.mode) { case 'bar_chart': - this.render_bar_chart(data); + this.render_bar_chart(); break; case 'line_chart': - this.render_line_chart(data); + this.render_line_chart(); break; case 'pie_chart': - this.render_pie_chart(data); + this.render_pie_chart(); break; } }, @@ -163,10 +155,10 @@ var ChartView = instance.web.Widget.extend({ }; }, - render_bar_chart: function (data) { + render_bar_chart: function () { var formatted_data = [{ key: 'Bar chart', - values: _.map(data, this.format_data.bind(this)), + values: _.map(this.data, this.format_data.bind(this)), }]; nv.addGraph(function () { @@ -188,12 +180,12 @@ var ChartView = instance.web.Widget.extend({ }); }, - render_line_chart: function (data) { + render_line_chart: function () { var measure_label = (this.measure) ? this.measure : 'Quantity'; var formatted_data = [{ key: measure_label, - values: _.map(data, this.format_data.bind(this)) + values: _.map(this.data, this.format_data.bind(this)) }]; nv.addGraph(function () { @@ -213,8 +205,8 @@ var ChartView = instance.web.Widget.extend({ }); }, - render_pie_chart: function (data) { - var formatted_data = _.map(data, this.format_data.bind(this)); + render_pie_chart: function () { + var formatted_data = _.map(this.data, this.format_data.bind(this)); nv.addGraph(function () { var chart = nv.models.pieChart() -- cgit v1.2.3 From 298a7012bfb1ba3b66bee56d196aa52be7bb2789 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 12 Nov 2013 14:53:44 +0100 Subject: [IMP] add rendering of basic table in pivottable widget (addon web_graph) bzr revid: ged@openerp.com-20131112135344-fi7mwyd49bqnbg69 --- addons/web_graph/static/src/css/graph.css | 12 ++++++++++++ addons/web_graph/static/src/js/graph.js | 23 ++++++++++++++++++++--- addons/web_graph/static/src/xml/web_graph.xml | 2 +- 3 files changed, 33 insertions(+), 4 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index e69de29bb2d..b6412b8856c 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -0,0 +1,12 @@ + +.graph_main_content td { + border: 1px solid black; + padding: 0.5rem; + text-align: right; +} + +td.graph_border { + background-color: rgb(227, 227, 227); + text-align: left; +} + diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index a36f8f68db0..e8836604324 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -10,6 +10,7 @@ openerp.web_graph = function (instance) { var _lt = instance.web._lt; var _t = instance.web._t; +var QWeb = instance.web.qweb; instance.web.views.add('graph', 'instance.web_graph.GraphView'); @@ -94,6 +95,7 @@ var BasicDataView = instance.web.Widget.extend({ this.fields = fields; this.groupby = groupby; this.measure = measure; + this.measure_label = measure ? fields[measure].string : 'Quantity'; }, show: function () { @@ -113,7 +115,23 @@ var PivotTable = BasicDataView.extend({ template: 'pivot_table', draw: function () { - console.log('data',this.data); + var self = this; + console.log("data",this.data); + + var rows = '' + + this.fields[this.groupby[0]].string + + '' + + this.measure_label + + ''; + _.each(this.data, function (datapt) { + rows += '' + + datapt.attributes.value[1] + + '' + + datapt.attributes.aggregates[self.measure]+ + ''; + }); + + this.$el.append(rows); }, }); @@ -181,10 +199,9 @@ var ChartView = BasicDataView.extend({ }, render_line_chart: function () { - var measure_label = (this.measure) ? this.measure : 'Quantity'; var formatted_data = [{ - key: measure_label, + key: this.measure_label, values: _.map(this.data, this.format_data.bind(this)) }]; diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 409a86dfc06..4e8c3883b4e 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -19,7 +19,7 @@ -
Hello Pivot
+
-- cgit v1.2.3 From 8eeaca216d796eca53b361dfad364028ef09882e Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 12 Nov 2013 17:10:34 +0100 Subject: [REF] refactoring of addon web_graph. goal is to handle properly the switch of chart view to table view bzr revid: ged@openerp.com-20131112161034-yy80ypm39j32sazv --- addons/web_graph/static/src/js/graph.js | 114 ++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 51 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index e8836604324..44152e45372 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -22,59 +22,72 @@ instance.web_graph.GraphView = instance.web.View.extend({ template: 'GraphView', display_name: _lt('Graph'), view_type: 'graph', + mode: 'pivot', // pivot => display pivot table, chart => display chart events: { 'click .graph_mode_selection li' : function (event) { event.preventDefault(); - var self = this, - mode = event.target.attributes['data-mode'].nodeValue; - if (mode == 'data') { - this.chart_view.hide(); - this.pivot_table.show(); + var view_mode = event.target.attributes['data-mode'].nodeValue; + if (view_mode === 'data') { + this.mode = 'pivot'; } else { - this.pivot_table.hide(); - this.chart_view.set_mode(mode); - this.chart_view.show(); + this.mode = 'chart'; + this.chart_view.set_mode(view_mode); } + this.display_data(); }, }, + display_data : function () { + if (this.mode === 'pivot') { + this.chart_view.hide(); + this.pivot_table.show(); + } else { + this.pivot_table.hide(); + this.chart_view.draw(); + this.chart_view.show(); + } + }, + view_loading: function (fields_view_get) { var self = this; - var model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}); - var measure = null; - var groupbys = [] + this.model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}); + this.measure = null; + this.groupbys = []; // get the default groupbys and measure defined in the field view _.each(fields_view_get.arch.children, function (field) { if ('name' in field.attrs) { if ('operator' in field.attrs) { - measure = field.attrs.name; + self.measure = field.attrs.name; } else { - groupbys.push(field.attrs.name); + self.groupbys.push(field.attrs.name); } } }); - return model.call('fields_get', []).then(function (fields) { - var view_fields = groupbys.concat(measure); - query_groups(model, view_fields, self.domain, groupbys).done(function (data) { - self.pivot_table = new PivotTable(data, fields, groupbys, measure); - self.chart_view = new ChartView(data, fields, groupbys, measure); - self.pivot_table.appendTo('.graph_main_content') - .done(function () { - self.pivot_table.draw(); - }); - self.chart_view.appendTo('.graph_main_content') - .done(function () { - self.chart_view.hide(); - }); - }); + return this.model.call('fields_get', []).then(function (fields) { + self.pivot_table = new PivotTable(fields, self.groupbys, self.measure); + self.chart_view = new ChartView(fields, self.groupbys, self.measure); + self.pivot_table.appendTo('.graph_main_content'); + self.chart_view.appendTo('.graph_main_content'); }); }, + get_data: function () { + var view_fields = this.groupbys.concat(this.measure); + return query_groups(this.model, view_fields, this.domain, this.groupbys); + }, + do_search: function (domain, context, group_by) { + var self = this; this.domain = new instance.web.CompoundDomain(domain); + return this.get_data().done(function (data) { + self.pivot_table.set_data(data); + self.chart_view.set_data(data); + self.pivot_table.draw(); + self.display_data(); + }); }, do_show: function () { @@ -90,12 +103,16 @@ instance.web_graph.GraphView = instance.web.View.extend({ * and ChartView widget. */ var BasicDataView = instance.web.Widget.extend({ - init: function (data, fields, groupby, measure) { - this.data = data; + init: function (fields, groupby, measure) { this.fields = fields; this.groupby = groupby; this.measure = measure; this.measure_label = measure ? fields[measure].string : 'Quantity'; + this.data = []; + }, + + set_data : function (data) { + this.data = data; }, show: function () { @@ -105,6 +122,9 @@ var BasicDataView = instance.web.Widget.extend({ hide: function () { this.$el.css('display', 'none'); }, + + draw: function() { + }, }); /** @@ -115,19 +135,19 @@ var PivotTable = BasicDataView.extend({ template: 'pivot_table', draw: function () { + this.$el.empty(); var self = this; - console.log("data",this.data); - var rows = '' + + var rows = '' + this.fields[this.groupby[0]].string + - '' + + '' + this.measure_label + ''; _.each(this.data, function (datapt) { - rows += '' + + rows += '' + datapt.attributes.value[1] + - '' + - datapt.attributes.aggregates[self.measure]+ + '' + + datapt.attributes.aggregates[self.measure] + ''; }); @@ -141,28 +161,21 @@ var PivotTable = BasicDataView.extend({ */ var ChartView = BasicDataView.extend({ template: 'chart_view', - mode: 'bar_chart', set_mode: function (mode) { - this.mode = mode; - this.draw(); + var render_functions = { + 'bar_chart' : this.render_bar_chart, + 'line_chart' : this.render_line_chart, + 'pie_chart' : this.render_pie_chart, + }; + + this.render = render_functions[mode]; }, draw: function () { this.$el.empty(); this.$el.append(''); - - switch (this.mode) { - case 'bar_chart': - this.render_bar_chart(); - break; - case 'line_chart': - this.render_line_chart(); - break; - case 'pie_chart': - this.render_pie_chart(); - break; - } + this.render(); }, format_data: function (datapt) { @@ -199,7 +212,6 @@ var ChartView = BasicDataView.extend({ }, render_line_chart: function () { - var formatted_data = [{ key: this.measure_label, values: _.map(this.data, this.format_data.bind(this)) -- cgit v1.2.3 From 3c0445479bf5ceaab5bb2b6f201daa787c53bb82 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 13 Nov 2013 10:18:07 +0100 Subject: [REF] move the method displaydata to a better place in addon web_graph bzr revid: ged@openerp.com-20131113091807-cxmc4aaaswdmkfia --- addons/web_graph/static/src/js/graph.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 44152e45372..7ade3843bde 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -38,17 +38,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, }, - display_data : function () { - if (this.mode === 'pivot') { - this.chart_view.hide(); - this.pivot_table.show(); - } else { - this.pivot_table.hide(); - this.chart_view.draw(); - this.chart_view.show(); - } - }, - view_loading: function (fields_view_get) { var self = this; this.model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}); @@ -79,6 +68,17 @@ instance.web_graph.GraphView = instance.web.View.extend({ return query_groups(this.model, view_fields, this.domain, this.groupbys); }, + display_data : function () { + if (this.mode === 'pivot') { + this.chart_view.hide(); + this.pivot_table.show(); + } else { + this.pivot_table.hide(); + this.chart_view.draw(); + this.chart_view.show(); + } + }, + do_search: function (domain, context, group_by) { var self = this; this.domain = new instance.web.CompoundDomain(domain); @@ -138,7 +138,7 @@ var PivotTable = BasicDataView.extend({ this.$el.empty(); var self = this; - var rows = '' + + var rows = ' fa-sort-asc' + this.fields[this.groupby[0]].string + '' + this.measure_label + -- cgit v1.2.3 From 3be25d2c45b6869e30b7ad77413b50bd99f62822 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 13 Nov 2013 10:26:46 +0100 Subject: [IMP] add redraw flag to basicview widget in addon web_graph bzr revid: ged@openerp.com-20131113092646-182veoj027lkbdb6 --- addons/web_graph/static/src/js/graph.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 7ade3843bde..7f83d656059 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -74,7 +74,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.pivot_table.show(); } else { this.pivot_table.hide(); - this.chart_view.draw(); this.chart_view.show(); } }, @@ -85,7 +84,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ return this.get_data().done(function (data) { self.pivot_table.set_data(data); self.chart_view.set_data(data); - self.pivot_table.draw(); self.display_data(); }); }, @@ -103,6 +101,9 @@ instance.web_graph.GraphView = instance.web.View.extend({ * and ChartView widget. */ var BasicDataView = instance.web.Widget.extend({ + + need_redraw: false, + init: function (fields, groupby, measure) { this.fields = fields; this.groupby = groupby; @@ -113,9 +114,14 @@ var BasicDataView = instance.web.Widget.extend({ set_data : function (data) { this.data = data; + this.need_redraw = true; }, show: function () { + if (this.need_redraw) { + this.draw(); + this.need_redraw = false; + } this.$el.css('display', 'block'); }, @@ -170,6 +176,7 @@ var ChartView = BasicDataView.extend({ }; this.render = render_functions[mode]; + this.need_redraw = true; }, draw: function () { -- cgit v1.2.3 From b5af9d421e6aa98ea21b47416cd9dc7391a5e54b Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 13 Nov 2013 11:50:59 +0100 Subject: [IMP] add functionality to basicview widget and rearrange code in addon web_graph bzr revid: ged@openerp.com-20131113105059-1l6th5zcn5wrm3x7 --- addons/web_graph/static/src/js/graph.js | 106 +++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 35 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 7f83d656059..0361cd12e0d 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -2,11 +2,11 @@ * OpenERP web_graph *---------------------------------------------------------*/ -'use strict'; /* jshint undef: false */ openerp.web_graph = function (instance) { +'use strict'; var _lt = instance.web._lt; var _t = instance.web._t; @@ -40,32 +40,30 @@ instance.web_graph.GraphView = instance.web.View.extend({ view_loading: function (fields_view_get) { var self = this; - this.model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}); - this.measure = null; + var model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}); + var measure = null; this.groupbys = []; // get the default groupbys and measure defined in the field view _.each(fields_view_get.arch.children, function (field) { if ('name' in field.attrs) { if ('operator' in field.attrs) { - self.measure = field.attrs.name; + measure = field.attrs.name; } else { self.groupbys.push(field.attrs.name); } } }); - return this.model.call('fields_get', []).then(function (fields) { - self.pivot_table = new PivotTable(fields, self.groupbys, self.measure); - self.chart_view = new ChartView(fields, self.groupbys, self.measure); - self.pivot_table.appendTo('.graph_main_content'); - self.chart_view.appendTo('.graph_main_content'); + return model.call('fields_get', []).then(function (fields) { + self.pivot_table = new PivotTable(model, fields, [], self.groupbys, [], measure); + self.chart_view = new ChartView(model, fields, [], self.groupbys, [], measure); + return self.pivot_table.appendTo('.graph_main_content'); + }).then(function() { + return self.chart_view.appendTo('.graph_main_content'); }); - }, - get_data: function () { - var view_fields = this.groupbys.concat(this.measure); - return query_groups(this.model, view_fields, this.domain, this.groupbys); + }, display_data : function () { @@ -79,13 +77,10 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, do_search: function (domain, context, group_by) { - var self = this; this.domain = new instance.web.CompoundDomain(domain); - return this.get_data().done(function (data) { - self.pivot_table.set_data(data); - self.chart_view.set_data(data); - self.display_data(); - }); + this.pivot_table.set_domain(domain); + this.chart_view.set_domain(domain); + this.display_data(); }, do_show: function () { @@ -104,16 +99,43 @@ var BasicDataView = instance.web.Widget.extend({ need_redraw: false, - init: function (fields, groupby, measure) { + // Input parameters: + // model: model to display + // fields: dictionary returned by field_get on model (desc of model) + // domain: constraints on model records + // row_groupby: groubys on rows (so, row headers in the pivot table) + // col_groupby: idem, but on col + // measure: quantity to display. either a field from the model, or + // null, in which case we use the "count" measure + init: function (model, fields, domain, row_groupby, col_groupby, measure) { + this.model = model; this.fields = fields; - this.groupby = groupby; + this.domain = domain; + this.row_groupby = row_groupby; + this.col_groupby = col_groupby; this.measure = measure; this.measure_label = measure ? fields[measure].string : 'Quantity'; this.data = []; + this.need_redraw = true; }, - set_data : function (data) { - this.data = data; + set_domain: function (domain) { + this.domain = domain; + this.need_redraw = true; + }, + + set_row_groupby: function (row_groupby) { + this.row_groupby = row_groupby; + this.need_redraw = true; + }, + + set_col_groupby: function (col_groupby) { + this.col_groupby = col_groupby; + this.need_redraw = true; + }, + + set_measure: function (measure) { + this.measure = measure; this.need_redraw = true; }, @@ -131,6 +153,12 @@ var BasicDataView = instance.web.Widget.extend({ draw: function() { }, + + get_data: function (groupby) { + var view_fields = this.row_groupby.concat(this.measure, this.col_groupby); + return query_groups(this.model, view_fields, this.domain, groupby); + }, + }); /** @@ -141,24 +169,29 @@ var PivotTable = BasicDataView.extend({ template: 'pivot_table', draw: function () { + this.get_data(this.row_groupby).done(this._draw.bind(this)); + }, + + _draw: function (data) { + console.log("data",data); this.$el.empty(); var self = this; - var rows = ' fa-sort-asc' + - this.fields[this.groupby[0]].string + + var rows = '' + + this.fields[this.row_groupby[0]].string + '' + this.measure_label + ''; - _.each(this.data, function (datapt) { + + _.each(data, function (datapt) { rows += '' + datapt.attributes.value[1] + '' + datapt.attributes.aggregates[self.measure] + ''; }); - this.$el.append(rows); - }, + } }); /** @@ -180,9 +213,12 @@ var ChartView = BasicDataView.extend({ }, draw: function () { + var self = this; this.$el.empty(); this.$el.append(''); - this.render(); + this.get_data(this.row_groupby).done(function (data) { + self.render(data); + }); }, format_data: function (datapt) { @@ -193,10 +229,10 @@ var ChartView = BasicDataView.extend({ }; }, - render_bar_chart: function () { + render_bar_chart: function (data) { var formatted_data = [{ key: 'Bar chart', - values: _.map(this.data, this.format_data.bind(this)), + values: _.map(data, this.format_data.bind(this)), }]; nv.addGraph(function () { @@ -218,10 +254,10 @@ var ChartView = BasicDataView.extend({ }); }, - render_line_chart: function () { + render_line_chart: function (data) { var formatted_data = [{ key: this.measure_label, - values: _.map(this.data, this.format_data.bind(this)) + values: _.map(data, this.format_data.bind(this)) }]; nv.addGraph(function () { @@ -241,8 +277,8 @@ var ChartView = BasicDataView.extend({ }); }, - render_pie_chart: function () { - var formatted_data = _.map(this.data, this.format_data.bind(this)); + render_pie_chart: function (data) { + var formatted_data = _.map(data, this.format_data.bind(this)); nv.addGraph(function () { var chart = nv.models.pieChart() -- cgit v1.2.3 From cecac9a32a786a4bdb5d0e0c8a4847738c7ffc00 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 13 Nov 2013 15:44:24 +0100 Subject: [IMP] improve the rendering of the table in pivottable widget (addon web_graph) bzr revid: ged@openerp.com-20131113144424-8i4ld0fjggw6nled --- addons/web_graph/static/src/js/graph.js | 73 +++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 21 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 0361cd12e0d..f400f76d459 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -167,30 +167,67 @@ var BasicDataView = instance.web.Widget.extend({ */ var PivotTable = BasicDataView.extend({ template: 'pivot_table', + rows: null, + cols: null, draw: function () { - this.get_data(this.row_groupby).done(this._draw.bind(this)); + this.get_data(this.row_groupby) + .then(this.proxy('build_table')) + .done(this.proxy('_draw')); }, - _draw: function (data) { - console.log("data",data); + build_table: function (data) { + var self = this; + function make_cell (content, is_border) { + return '' + content + ''; + } + + this.cols = [{ + path: [], + value: this.measure_label, + expanded: false, + parent: null, + children: [], + html_tds: [], + domain: this.domain, + header: $(make_cell(this.measure_label, true)), + }]; + + this.rows = _.map(data, function (datapt) { + var row = $(''); + row.html(make_cell(datapt.attributes.value[1], true)); + row.append(make_cell(datapt.attributes.aggregates[self.measure])); + + return { + path: [datapt.attributes.grouped_on], + value: datapt.attributes.value[1], + expanded: false, + parent: null, + children: [], + html_tr: row, + domain: datapt.model._domain + }; + }); + }, + + _draw: function () { + this.$el.empty(); var self = this; - var rows = '' + + var header = '' + this.fields[this.row_groupby[0]].string + '' + this.measure_label + ''; + this.$el.append(header); - _.each(data, function (datapt) { - rows += '' + - datapt.attributes.value[1] + - '' + - datapt.attributes.aggregates[self.measure] + - ''; + _.each(this.rows, function (row) { + self.$el.append(row.html_tr); }); - this.$el.append(rows); + } }); @@ -202,13 +239,7 @@ var ChartView = BasicDataView.extend({ template: 'chart_view', set_mode: function (mode) { - var render_functions = { - 'bar_chart' : this.render_bar_chart, - 'line_chart' : this.render_line_chart, - 'pie_chart' : this.render_pie_chart, - }; - - this.render = render_functions[mode]; + this.render = this['render_' + mode]; this.need_redraw = true; }, @@ -232,7 +263,7 @@ var ChartView = BasicDataView.extend({ render_bar_chart: function (data) { var formatted_data = [{ key: 'Bar chart', - values: _.map(data, this.format_data.bind(this)), + values: _.map(data, this.proxy('format_data')), }]; nv.addGraph(function () { @@ -257,7 +288,7 @@ var ChartView = BasicDataView.extend({ render_line_chart: function (data) { var formatted_data = [{ key: this.measure_label, - values: _.map(data, this.format_data.bind(this)) + values: _.map(data, this.proxy('format_data')) }]; nv.addGraph(function () { @@ -278,7 +309,7 @@ var ChartView = BasicDataView.extend({ }, render_pie_chart: function (data) { - var formatted_data = _.map(data, this.format_data.bind(this)); + var formatted_data = _.map(data, this.proxy('format_data')); nv.addGraph(function () { var chart = nv.models.pieChart() -- cgit v1.2.3 From 26e6a496bebb3200c58e37b5e5bb7f167e0f3618 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 13 Nov 2013 16:47:31 +0100 Subject: [IMP] work in progress. goal is to allow expansion of rows/cols in pivottable (addon web_graph) bzr revid: ged@openerp.com-20131113154731-lmhcyajqcf2k4bxt --- addons/web_graph/static/src/js/graph.js | 97 +++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 22 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index f400f76d459..bc1040e9df9 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -41,29 +41,62 @@ instance.web_graph.GraphView = instance.web.View.extend({ view_loading: function (fields_view_get) { var self = this; var model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}); - var measure = null; - this.groupbys = []; + var options = {}; + options.domain = []; + options.col_groupby = []; // get the default groupbys and measure defined in the field view + options.measure = null; + options.row_groupby = []; _.each(fields_view_get.arch.children, function (field) { if ('name' in field.attrs) { if ('operator' in field.attrs) { - measure = field.attrs.name; + options.measure = field.attrs.name; } else { - self.groupbys.push(field.attrs.name); + options.row_groupby.push(field.attrs.name); } } }); - return model.call('fields_get', []).then(function (fields) { - self.pivot_table = new PivotTable(model, fields, [], self.groupbys, [], measure); - self.chart_view = new ChartView(model, fields, [], self.groupbys, [], measure); - return self.pivot_table.appendTo('.graph_main_content'); - }).then(function() { - return self.chart_view.appendTo('.graph_main_content'); + // get the most important fields (of the model) by looking at the + // groupby filters defined in the search view + options.important_fields = [] + var load_view = instance.web.fields_view_get({ + model: model, + view_type: 'search', }); + var important_fields_def = $.when(load_view).then(function (search_view) { + var groups = _.select(search_view.arch.children, function (c) { + return (c.tag == 'group') && (c.attrs.string != 'Display'); + }); + _.each(groups, function(g) { + _.each(g.children, function (g) { + if (g.attrs.context) { + var field_id = py.eval(g.attrs.context).group_by; + options.important_fields.push(field_id); + } + }); + }); + }).then + + // get the fields descriptions from the model + var field_descr_def = model.call('fields_get', []) + .then(function (fields) { options.fields = fields; }); + + + return $.when(important_fields_def, field_descr_def) + .then(function () { + self.pivot_table = new PivotTable(model, options); + self.chart_view = new ChartView(model, options); + }) + .then(function () { + return self.pivot_table.appendTo('.graph_main_content') + }) + .then(function() { + return self.chart_view.appendTo('.graph_main_content'); + }); }, display_data : function () { @@ -107,16 +140,17 @@ var BasicDataView = instance.web.Widget.extend({ // col_groupby: idem, but on col // measure: quantity to display. either a field from the model, or // null, in which case we use the "count" measure - init: function (model, fields, domain, row_groupby, col_groupby, measure) { + init: function (model, options) { this.model = model; - this.fields = fields; - this.domain = domain; - this.row_groupby = row_groupby; - this.col_groupby = col_groupby; - this.measure = measure; - this.measure_label = measure ? fields[measure].string : 'Quantity'; + this.fields = options.fields; + this.domain = options.domain; + this.row_groupby = options.row_groupby; + this.col_groupby = options.col_groupby; + this.measure = options.measure; + this.measure_label = options.measure ? options.fields[options.measure].string : 'Quantity'; this.data = []; this.need_redraw = true; + this.important_fields = options.important_fields; }, set_domain: function (domain) { @@ -169,6 +203,20 @@ var PivotTable = BasicDataView.extend({ template: 'pivot_table', rows: null, cols: null, + current_row_id : 0, + + events: { + 'click .graph_border a' : function (event) { + event.preventDefault(); + var row_id = event.target.attributes['data-row-id'].nodeValue; + console.log("clickclick on row ", row_id); + }, + }, + + generate_id: function () { + this.current_row_id += 1; + return this.current_row_id - 1; + }, draw: function () { this.get_data(this.row_groupby) @@ -196,19 +244,24 @@ var PivotTable = BasicDataView.extend({ }]; this.rows = _.map(data, function (datapt) { - var row = $(''); - row.html(make_cell(datapt.attributes.value[1], true)); - row.append(make_cell(datapt.attributes.aggregates[self.measure])); + var jquery_row = $(''); + var header = $(make_cell(datapt.attributes.value[1], true)); + var row_id = self.generate_id(); + + header.prepend('+ '); + jquery_row.html(header); + jquery_row.append(make_cell(datapt.attributes.aggregates[self.measure])); - return { + var row = { path: [datapt.attributes.grouped_on], value: datapt.attributes.value[1], expanded: false, parent: null, children: [], - html_tr: row, + html_tr: jquery_row, domain: datapt.model._domain }; + return row; }); }, -- cgit v1.2.3 From 4f448f36317eab36e332544a1463c85c3abaa740 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 14 Nov 2013 11:34:46 +0100 Subject: [IMP] work in progress. goal is to allow expansion of rows/cols in pivottable (addon web_graph) bzr revid: ged@openerp.com-20131114103446-qpqs3j0i8yhbvbg3 --- addons/web_graph/static/src/css/graph.css | 4 ++ addons/web_graph/static/src/js/graph.js | 81 ++++++++++++++++++++++----- addons/web_graph/static/src/xml/web_graph.xml | 13 +++++ 3 files changed, 84 insertions(+), 14 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index b6412b8856c..e60575096bc 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -10,3 +10,7 @@ td.graph_border { text-align: left; } +span.field-selection { + display: none; + padding: 0; +} \ No newline at end of file diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index bc1040e9df9..e1c20281bd0 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -60,7 +60,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ // get the most important fields (of the model) by looking at the // groupby filters defined in the search view - options.important_fields = [] + options.important_fields = []; var load_view = instance.web.fields_view_get({ model: model, view_type: 'search', @@ -79,7 +79,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ } }); }); - }).then + }); // get the fields descriptions from the model var field_descr_def = model.call('fields_get', []) @@ -92,7 +92,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ self.chart_view = new ChartView(model, options); }) .then(function () { - return self.pivot_table.appendTo('.graph_main_content') + return self.pivot_table.appendTo('.graph_main_content'); }) .then(function() { return self.chart_view.appendTo('.graph_main_content'); @@ -153,6 +153,10 @@ var BasicDataView = instance.web.Widget.extend({ this.important_fields = options.important_fields; }, + get_descr: function (field_id) { + return this.fields[field_id].string; + }, + set_domain: function (domain) { this.domain = domain; this.need_redraw = true; @@ -206,18 +210,70 @@ var PivotTable = BasicDataView.extend({ current_row_id : 0, events: { - 'click .graph_border a' : function (event) { + 'click .graph_border > a' : function (event) { + var self = this; event.preventDefault(); + + var dropdown_options = { + fields: _.map(this.important_fields, function (field) { + return {id: field, value: self.fields[field].string}; + }), + row_id: event.target.attributes['data-row-id'].nodeValue, + }; + + this.dropdown = $(QWeb.render('field_selection', dropdown_options)); + + $(event.target).after(this.dropdown); + $('.field-selection').next('.dropdown-menu').toggle(); + }, + 'click a.field-selection' : function (event) { + event.preventDefault(); + this.dropdown.remove(); var row_id = event.target.attributes['data-row-id'].nodeValue; - console.log("clickclick on row ", row_id); + var field_id = event.target.attributes['data-field-id'].nodeValue; + this.expand_row(row_id, field_id); }, }, + init: function (model, options) { + this._super(model, options); + }, + generate_id: function () { this.current_row_id += 1; return this.current_row_id - 1; }, + get_row: function (id) { + return _.find(this.rows, function(row) { + return (row.id == id); + }); + }, + + make_cell: function (content, is_border) { + return '' + content + ''; + }, + + expand_row: function (row_id, field_id) { + var row = this.get_row(row_id); + this.row_groupby.push(field_id); + var visible_fields = this.row_groupby.concat(this.col_groupby, this.measure); + + console.log("model",this.model); + console.log("vf",visible_fields); + console.log("domain",row.domain); + console.log("gb",this.row_groupby); + + query_groups(this.model, visible_fields, row.domain, [field_id]) + .then(function (data) { + console.log("datapt",data); + }); + + }, +// function query_groups (model, fields, domain, groupbys) { + draw: function () { this.get_data(this.row_groupby) .then(this.proxy('build_table')) @@ -226,11 +282,7 @@ var PivotTable = BasicDataView.extend({ build_table: function (data) { var self = this; - function make_cell (content, is_border) { - return '' + content + ''; - } + this.cols = [{ path: [], @@ -240,26 +292,27 @@ var PivotTable = BasicDataView.extend({ children: [], html_tds: [], domain: this.domain, - header: $(make_cell(this.measure_label, true)), + header: $(this.make_cell(this.measure_label, true)), }]; this.rows = _.map(data, function (datapt) { var jquery_row = $(''); - var header = $(make_cell(datapt.attributes.value[1], true)); + var header = $(self.make_cell(datapt.attributes.value[1], true)); var row_id = self.generate_id(); header.prepend('+ '); jquery_row.html(header); - jquery_row.append(make_cell(datapt.attributes.aggregates[self.measure])); + jquery_row.append(self.make_cell(datapt.attributes.aggregates[self.measure])); var row = { + id: row_id, path: [datapt.attributes.grouped_on], value: datapt.attributes.value[1], expanded: false, parent: null, children: [], html_tr: jquery_row, - domain: datapt.model._domain + domain: datapt.model._domain, }; return row; }); diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 4e8c3883b4e..19aa1018be8 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -26,4 +26,17 @@
+ +
+ + +
+
+ -- cgit v1.2.3 From a38ab9c56c7316dc8984fb80474339e3d7c81e89 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 14 Nov 2013 14:17:47 +0100 Subject: [IMP] work in progress. goal is to allow expansion of rows/cols in pivottable (addon web_graph) bzr revid: ged@openerp.com-20131114131747-mq8uh02iplc0xmer --- addons/web_graph/static/src/css/graph.css | 4 ++ addons/web_graph/static/src/js/graph.js | 97 ++++++++++++++++++++----------- 2 files changed, 66 insertions(+), 35 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index e60575096bc..f2d3338c385 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -13,4 +13,8 @@ td.graph_border { span.field-selection { display: none; padding: 0; +} + +span.web_graph_indent { + padding-left: 50px; } \ No newline at end of file diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index e1c20281bd0..f7670ab7b60 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -205,8 +205,8 @@ var BasicDataView = instance.web.Widget.extend({ */ var PivotTable = BasicDataView.extend({ template: 'pivot_table', - rows: null, - cols: null, + rows: [], + cols: [], current_row_id : 0, events: { @@ -250,29 +250,74 @@ var PivotTable = BasicDataView.extend({ }); }, - make_cell: function (content, is_border) { - return '' + content + ''; + make_cell: function (content, options) { + var attrs = [''); + if (options && options.indent) { + _.each(_.range(options.indent), function () { + attrs.push(''); + }); + } + return attrs.join(' ') + content + ''; + }, + + make_row: function (data, parent_id) { + var has_parent = (parent_id !== undefined); + var parent = has_parent ? this.get_row(parent_id) : null; + var path = has_parent ? parent.path.concat(data.attributes.grouped_on) + : [data.attributes.grouped_on]; + + + var indent_level = has_parent ? parent.path.length : 0; + + + var jquery_row = $(''); + var header = $(this.make_cell(data.attributes.value[1], {is_border:true, indent: indent_level})); + var row_id = this.generate_id(); + + header.prepend('+ '); + jquery_row.html(header); + jquery_row.append(this.make_cell(data.attributes.aggregates[this.measure])); + + var row = { + id: row_id, + path: path, + value: data.attributes.value[1], + expanded: false, + parent: parent_id, + children: [], + html_tr: jquery_row, + domain: data.model._domain, + }; + this.rows.push(row); // to do, insert it properly + + if (has_parent) { + parent.children.push(row); + } + return row; }, expand_row: function (row_id, field_id) { + var self = this; var row = this.get_row(row_id); this.row_groupby.push(field_id); var visible_fields = this.row_groupby.concat(this.col_groupby, this.measure); - console.log("model",this.model); - console.log("vf",visible_fields); - console.log("domain",row.domain); - console.log("gb",this.row_groupby); - query_groups(this.model, visible_fields, row.domain, [field_id]) .then(function (data) { - console.log("datapt",data); + _.each(data, function (datapt) { + + var new_row = self.make_row(datapt, row_id); + row.html_tr.after(new_row.html_tr); + }); + row.expanded = true; }); }, -// function query_groups (model, fields, domain, groupbys) { draw: function () { this.get_data(this.row_groupby) @@ -292,31 +337,13 @@ var PivotTable = BasicDataView.extend({ children: [], html_tds: [], domain: this.domain, - header: $(this.make_cell(this.measure_label, true)), + header: $(this.make_cell(this.measure_label, {is_border:true})), }]; - this.rows = _.map(data, function (datapt) { - var jquery_row = $(''); - var header = $(self.make_cell(datapt.attributes.value[1], true)); - var row_id = self.generate_id(); - - header.prepend('+ '); - jquery_row.html(header); - jquery_row.append(self.make_cell(datapt.attributes.aggregates[self.measure])); - - var row = { - id: row_id, - path: [datapt.attributes.grouped_on], - value: datapt.attributes.value[1], - expanded: false, - parent: null, - children: [], - html_tr: jquery_row, - domain: datapt.model._domain, - }; - return row; + _.each(data, function (datapt) { + self.make_row(datapt); }); - }, + }, _draw: function () { -- cgit v1.2.3 From 3c16fd11320fbc381855474116f90cddb7fb44be Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 14 Nov 2013 15:00:15 +0100 Subject: [IMP] allows expansion of rows in pivottable (addon web_graph) bzr revid: ged@openerp.com-20131114140015-h1hqzl5a70921vkq --- addons/web_graph/static/src/js/graph.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index f7670ab7b60..1c3ebd74075 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -262,6 +262,9 @@ var PivotTable = BasicDataView.extend({ attrs.push(''); }); } + if (options && options.foldable) { + attrs.push(' '); + } return attrs.join(' ') + content + ''; }, @@ -276,10 +279,9 @@ var PivotTable = BasicDataView.extend({ var jquery_row = $(''); - var header = $(this.make_cell(data.attributes.value[1], {is_border:true, indent: indent_level})); var row_id = this.generate_id(); - header.prepend('+ '); + var header = $(this.make_cell(data.attributes.value[1], {is_border:true, indent: indent_level, foldable:true, row_id: row_id})); jquery_row.html(header); jquery_row.append(this.make_cell(data.attributes.aggregates[this.measure])); @@ -315,6 +317,12 @@ var PivotTable = BasicDataView.extend({ row.html_tr.after(new_row.html_tr); }); row.expanded = true; + console.log("tr",row.html_tr); + var icon = row.html_tr.find('.icon-caret-right'); + icon.removeClass('icon-caret-right') + .addClass('icon-caret-down'); + console.log("icon",icon); + // console.log("nrst",); }); }, -- cgit v1.2.3 From 3e607e8e3c9809a4279d96727a46887eebeeb69c Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 14 Nov 2013 15:07:33 +0100 Subject: [IMP] changes triangle icon into + and - signs icon in pivot table (addon web_graph) bzr revid: ged@openerp.com-20131114140733-9jyvttydbb2gm5jv --- addons/web_graph/static/src/js/graph.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 1c3ebd74075..46c739121f9 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -263,7 +263,7 @@ var PivotTable = BasicDataView.extend({ }); } if (options && options.foldable) { - attrs.push(' '); + attrs.push(' '); } return attrs.join(' ') + content + ''; }, @@ -312,17 +312,13 @@ var PivotTable = BasicDataView.extend({ query_groups(this.model, visible_fields, row.domain, [field_id]) .then(function (data) { _.each(data, function (datapt) { - var new_row = self.make_row(datapt, row_id); row.html_tr.after(new_row.html_tr); }); row.expanded = true; - console.log("tr",row.html_tr); - var icon = row.html_tr.find('.icon-caret-right'); - icon.removeClass('icon-caret-right') - .addClass('icon-caret-down'); - console.log("icon",icon); - // console.log("nrst",); + var icon = row.html_tr.find('.icon-plus-sign'); + icon.removeClass('icon-plus-sign') + .addClass('icon-minus-sign'); }); }, -- cgit v1.2.3 From ba5de8088bf0448a6c015ccf0292decbc03c760c Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 14 Nov 2013 16:33:48 +0100 Subject: [IMP] allows the user to clear the groupbys in pivottable (addon web_graph) bzr revid: ged@openerp.com-20131114153348-bux7ldhkhe1jl29e --- addons/web_graph/static/src/js/graph.js | 69 ++++++++++++++++++++++----- addons/web_graph/static/src/xml/web_graph.xml | 2 +- 2 files changed, 57 insertions(+), 14 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 46c739121f9..ffc773f1c3e 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -36,6 +36,9 @@ instance.web_graph.GraphView = instance.web.View.extend({ } this.display_data(); }, + 'click .graph_clear_groups' : function (event) { + this.pivot_table.clear_groups(); + }, }, view_loading: function (fields_view_get) { @@ -216,7 +219,7 @@ var PivotTable = BasicDataView.extend({ var dropdown_options = { fields: _.map(this.important_fields, function (field) { - return {id: field, value: self.fields[field].string}; + return {id: field, value: self.get_descr(field)}; }), row_id: event.target.attributes['data-row-id'].nodeValue, }; @@ -235,6 +238,14 @@ var PivotTable = BasicDataView.extend({ }, }, + clear_groups: function () { + this.row_groupby = []; + this.col_groupby = []; + this.rows = []; + this.cols = []; + this.draw(); + }, + init: function (model, options) { this._super(model, options); }, @@ -271,24 +282,31 @@ var PivotTable = BasicDataView.extend({ make_row: function (data, parent_id) { var has_parent = (parent_id !== undefined); var parent = has_parent ? this.get_row(parent_id) : null; - var path = has_parent ? parent.path.concat(data.attributes.grouped_on) - : [data.attributes.grouped_on]; - + var path; + if (has_parent) { + console.log("parent",parent); + path = parent.path.concat(data.attributes.grouped_on); + } else if (data.attributes.grouped_on !== undefined) { + path = [data.attributes.grouped_on]; + } else { + path = []; + } var indent_level = has_parent ? parent.path.length : 0; + var value = (this.row_groupby.length > 0) ? data.attributes.value[1] : "Total"; var jquery_row = $(''); var row_id = this.generate_id(); - var header = $(this.make_cell(data.attributes.value[1], {is_border:true, indent: indent_level, foldable:true, row_id: row_id})); + var header = $(this.make_cell(value, {is_border:true, indent: indent_level, foldable:true, row_id: row_id})); jquery_row.html(header); jquery_row.append(this.make_cell(data.attributes.aggregates[this.measure])); var row = { id: row_id, path: path, - value: data.attributes.value[1], + value: value, expanded: false, parent: parent_id, children: [], @@ -297,6 +315,9 @@ var PivotTable = BasicDataView.extend({ }; this.rows.push(row); // to do, insert it properly + if (this.row_groupby.length === 0) { + row.remove_when_expanded = true; + } if (has_parent) { parent.children.push(row); } @@ -307,18 +328,31 @@ var PivotTable = BasicDataView.extend({ var self = this; var row = this.get_row(row_id); this.row_groupby.push(field_id); + var visible_fields = this.row_groupby.concat(this.col_groupby, this.measure); + if (row.remove_when_expanded) { + this.rows = []; + row.html_tr.remove(); + } else { + row.expanded = true; + row.html_tr.find('.icon-plus-sign') + .removeClass('icon-plus-sign') + .addClass('icon-minus-sign'); + } + query_groups(this.model, visible_fields, row.domain, [field_id]) .then(function (data) { _.each(data, function (datapt) { - var new_row = self.make_row(datapt, row_id); - row.html_tr.after(new_row.html_tr); + var new_row; + if (row.remove_when_expanded) { + new_row = self.make_row(datapt); + self.$('tr.graph_table_header').after(new_row.html_tr); + } else { + new_row = self.make_row(datapt, row_id); + row.html_tr.after(new_row.html_tr); + } }); - row.expanded = true; - var icon = row.html_tr.find('.icon-plus-sign'); - icon.removeClass('icon-plus-sign') - .addClass('icon-minus-sign'); }); }, @@ -332,6 +366,7 @@ var PivotTable = BasicDataView.extend({ build_table: function (data) { var self = this; + console.log("data",data); this.cols = [{ path: [], @@ -353,12 +388,20 @@ var PivotTable = BasicDataView.extend({ this.$el.empty(); var self = this; + var header; - var header = '' + + if (this.row_groupby.length > 0) { + header = '' + this.fields[this.row_groupby[0]].string + '' + this.measure_label + ''; + } else { + header = '' + + '' + + this.measure_label + + ''; + } this.$el.append(header); _.each(this.rows, function (row) { diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 19aa1018be8..5a56f34d84a 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -11,8 +11,8 @@
  • Line Chart
  • Pie chart
  • + -
    -- cgit v1.2.3 From 2216a699087c790182bd34227d3d1d4554131b9d Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 14 Nov 2013 17:31:07 +0100 Subject: [IMP] many usability fixes in pivottable drill down and up (addon web_graph) bzr revid: ged@openerp.com-20131114163107-pm3s3siwtzqn98jy --- addons/web_graph/static/src/js/graph.js | 43 +++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 16 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index ffc773f1c3e..3ab9b034ea1 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -216,18 +216,24 @@ var PivotTable = BasicDataView.extend({ 'click .graph_border > a' : function (event) { var self = this; event.preventDefault(); + var row_id = event.target.attributes['data-row-id'].nodeValue; - var dropdown_options = { - fields: _.map(this.important_fields, function (field) { - return {id: field, value: self.get_descr(field)}; - }), - row_id: event.target.attributes['data-row-id'].nodeValue, - }; - - this.dropdown = $(QWeb.render('field_selection', dropdown_options)); + var row = this.get_row(row_id); + if (row.expanded) { + this.fold_row(row_id) + } else { + var dropdown_options = { + fields: _.map(this.important_fields, function (field) { + return {id: field, value: self.get_descr(field)}; + }), + row_id: row_id, + }; + this.dropdown = $(QWeb.render('field_selection', dropdown_options)); + $(event.target).after(this.dropdown); + $('.field-selection').next('.dropdown-menu').toggle(); + } - $(event.target).after(this.dropdown); - $('.field-selection').next('.dropdown-menu').toggle(); + }, 'click a.field-selection' : function (event) { event.preventDefault(); @@ -284,7 +290,6 @@ var PivotTable = BasicDataView.extend({ var parent = has_parent ? this.get_row(parent_id) : null; var path; if (has_parent) { - console.log("parent",parent); path = parent.path.concat(data.attributes.grouped_on); } else if (data.attributes.grouped_on !== undefined) { path = [data.attributes.grouped_on]; @@ -293,7 +298,7 @@ var PivotTable = BasicDataView.extend({ } var indent_level = has_parent ? parent.path.length : 0; - var value = (this.row_groupby.length > 0) ? data.attributes.value[1] : "Total"; + var value = (this.row_groupby.length > 0) ? data.attributes.value[1] : 'Total'; var jquery_row = $(''); @@ -313,10 +318,12 @@ var PivotTable = BasicDataView.extend({ html_tr: jquery_row, domain: data.model._domain, }; + // rows.splice(index of parent if any,0,row); this.rows.push(row); // to do, insert it properly if (this.row_groupby.length === 0) { row.remove_when_expanded = true; + row.domain = this.domain; } if (has_parent) { parent.children.push(row); @@ -333,7 +340,6 @@ var PivotTable = BasicDataView.extend({ if (row.remove_when_expanded) { this.rows = []; - row.html_tr.remove(); } else { row.expanded = true; row.html_tr.find('.icon-plus-sign') @@ -343,7 +349,7 @@ var PivotTable = BasicDataView.extend({ query_groups(this.model, visible_fields, row.domain, [field_id]) .then(function (data) { - _.each(data, function (datapt) { + _.each(data.reverse(), function (datapt) { var new_row; if (row.remove_when_expanded) { new_row = self.make_row(datapt); @@ -353,10 +359,17 @@ var PivotTable = BasicDataView.extend({ row.html_tr.after(new_row.html_tr); } }); + if (row.remove_when_expanded) { + row.html_tr.remove(); + } }); }, + fold_row: function (row_id) { + + }, + draw: function () { this.get_data(this.row_groupby) .then(this.proxy('build_table')) @@ -366,8 +379,6 @@ var PivotTable = BasicDataView.extend({ build_table: function (data) { var self = this; - console.log("data",data); - this.cols = [{ path: [], value: this.measure_label, -- cgit v1.2.3 From 2609105d41cfd7ef798a87c161e84eaf0092e2f1 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 15 Nov 2013 09:50:37 +0100 Subject: [IMP] allow pivottable to fold rows (addon web_graph) bzr revid: ged@openerp.com-20131115085037-nhbi5x9ooa75drnk --- addons/web_graph/static/src/js/graph.js | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 3ab9b034ea1..efde4315b29 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -220,7 +220,7 @@ var PivotTable = BasicDataView.extend({ var row = this.get_row(row_id); if (row.expanded) { - this.fold_row(row_id) + this.fold_row(row_id); } else { var dropdown_options = { fields: _.map(this.important_fields, function (field) { @@ -326,7 +326,7 @@ var PivotTable = BasicDataView.extend({ row.domain = this.domain; } if (has_parent) { - parent.children.push(row); + parent.children.push(row.id); } return row; }, @@ -360,14 +360,37 @@ var PivotTable = BasicDataView.extend({ } }); if (row.remove_when_expanded) { - row.html_tr.remove(); + row.html_tr.remove(); } }); }, fold_row: function (row_id) { + var self = this; + var row = this.get_row(row_id); + + _.each(row.children, function (child_row) { + self.remove_row(child_row); + }); + row.children = []; + + row.expanded = false; + row.html_tr.find('.icon-minus-sign') + .removeClass('icon-minus-sign') + .addClass('icon-plus-sign');; + + }, + + remove_row: function (row_id) { + var self = this; + var row = this.get_row(row_id); + + _.each(row.children, function (child_row) { + self.remove_row(child_row); + }); + row.html_tr.remove(); }, draw: function () { -- cgit v1.2.3 From fecfa8e52cdaca9925c32945da0d5638a6802c1b Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 15 Nov 2013 10:24:11 +0100 Subject: [IMP] makes display smarter list of options in dropdown menu on pivottable widget (addon web_graph) bzr revid: ged@openerp.com-20131115092411-abnckphk4mn9ji3z --- addons/web_graph/static/src/js/graph.js | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index efde4315b29..875a34aa92f 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -222,15 +222,22 @@ var PivotTable = BasicDataView.extend({ if (row.expanded) { this.fold_row(row_id); } else { - var dropdown_options = { - fields: _.map(this.important_fields, function (field) { - return {id: field, value: self.get_descr(field)}; - }), - row_id: row_id, - }; - this.dropdown = $(QWeb.render('field_selection', dropdown_options)); - $(event.target).after(this.dropdown); - $('.field-selection').next('.dropdown-menu').toggle(); + if (row.path.length < this.row_groupby.length) { + var field_to_expand = this.row_groupby[row.path.length]; + this.expand_row(row_id, field_to_expand); + } else { + var already_grouped = self.row_groupby.concat(self.col_groupby); + var possible_groups = _.difference(self.important_fields, already_grouped); + var dropdown_options = { + fields: _.map(possible_groups, function (field) { + return {id: field, value: self.get_descr(field)}; + }), + row_id: row_id, + }; + this.dropdown = $(QWeb.render('field_selection', dropdown_options)); + $(event.target).after(this.dropdown); + $('.field-selection').next('.dropdown-menu').toggle(); + } } @@ -334,7 +341,10 @@ var PivotTable = BasicDataView.extend({ expand_row: function (row_id, field_id) { var self = this; var row = this.get_row(row_id); - this.row_groupby.push(field_id); + + if (row.path.length == this.row_groupby.length) { + this.row_groupby.push(field_id); + } var visible_fields = this.row_groupby.concat(this.col_groupby, this.measure); -- cgit v1.2.3 From 75caaeb1a39cea51b05e41c3f5db1fe904f64f43 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 15 Nov 2013 12:19:32 +0100 Subject: [IMP] smarter behavior when unfolding/refolding: check 'unfolding' level and do not ask what field to expand if it already knows (addon web_graph) bzr revid: ged@openerp.com-20131115111932-rdphi3w01nmein7t --- addons/web_graph/static/src/js/graph.js | 61 +++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 21 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 875a34aa92f..93e8d72cfe8 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -144,11 +144,15 @@ var BasicDataView = instance.web.Widget.extend({ // measure: quantity to display. either a field from the model, or // null, in which case we use the "count" measure init: function (model, options) { + var self = this; this.model = model; this.fields = options.fields; this.domain = options.domain; - this.row_groupby = options.row_groupby; - this.col_groupby = options.col_groupby; + this.groupby = { + row: options.row_groupby, + col: options.col_groupby, + }; + this.measure = options.measure; this.measure_label = options.measure ? options.fields[options.measure].string : 'Quantity'; this.data = []; @@ -166,12 +170,12 @@ var BasicDataView = instance.web.Widget.extend({ }, set_row_groupby: function (row_groupby) { - this.row_groupby = row_groupby; + this.groupby.row = row_groupby; this.need_redraw = true; }, set_col_groupby: function (col_groupby) { - this.col_groupby = col_groupby; + this.groupby.col = col_groupby; this.need_redraw = true; }, @@ -196,7 +200,7 @@ var BasicDataView = instance.web.Widget.extend({ }, get_data: function (groupby) { - var view_fields = this.row_groupby.concat(this.measure, this.col_groupby); + var view_fields = this.groupby.row.concat(this.measure, this.groupby.col); return query_groups(this.model, view_fields, this.domain, groupby); }, @@ -222,11 +226,11 @@ var PivotTable = BasicDataView.extend({ if (row.expanded) { this.fold_row(row_id); } else { - if (row.path.length < this.row_groupby.length) { - var field_to_expand = this.row_groupby[row.path.length]; + if (row.path.length < this.groupby.row.length) { + var field_to_expand = this.groupby.row[row.path.length]; this.expand_row(row_id, field_to_expand); } else { - var already_grouped = self.row_groupby.concat(self.col_groupby); + var already_grouped = self.groupby.row.concat(self.groupby.col); var possible_groups = _.difference(self.important_fields, already_grouped); var dropdown_options = { fields: _.map(possible_groups, function (field) { @@ -252,8 +256,8 @@ var PivotTable = BasicDataView.extend({ }, clear_groups: function () { - this.row_groupby = []; - this.col_groupby = []; + this.groupby.row = []; + this.groupby.col = []; this.rows = []; this.cols = []; this.draw(); @@ -305,7 +309,7 @@ var PivotTable = BasicDataView.extend({ } var indent_level = has_parent ? parent.path.length : 0; - var value = (this.row_groupby.length > 0) ? data.attributes.value[1] : 'Total'; + var value = (this.groupby.row.length > 0) ? data.attributes.value[1] : 'Total'; var jquery_row = $(''); @@ -328,7 +332,7 @@ var PivotTable = BasicDataView.extend({ // rows.splice(index of parent if any,0,row); this.rows.push(row); // to do, insert it properly - if (this.row_groupby.length === 0) { + if (this.groupby.row.length === 0) { row.remove_when_expanded = true; row.domain = this.domain; } @@ -342,11 +346,11 @@ var PivotTable = BasicDataView.extend({ var self = this; var row = this.get_row(row_id); - if (row.path.length == this.row_groupby.length) { - this.row_groupby.push(field_id); + if (row.path.length == this.groupby.row.length) { + this.groupby.row.push(field_id); } - var visible_fields = this.row_groupby.concat(this.col_groupby, this.measure); + var visible_fields = this.groupby.row.concat(this.groupby.col, this.measure); if (row.remove_when_expanded) { this.rows = []; @@ -381,15 +385,21 @@ var PivotTable = BasicDataView.extend({ var row = this.get_row(row_id); _.each(row.children, function (child_row) { - self.remove_row(child_row); + self.remove_row(child_row); }); row.children = []; row.expanded = false; row.html_tr.find('.icon-minus-sign') .removeClass('icon-minus-sign') - .addClass('icon-plus-sign');; + .addClass('icon-plus-sign'); + var fold_levels = _.map(self.rows, function(g) {return g.path.length;}); + var new_groupby_length = _.reduce(fold_levels, function (x, y) { + return Math.max(x,y); + }, 0); + + this.groupby.row.splice(new_groupby_length); }, remove_row: function (row_id) { @@ -401,10 +411,11 @@ var PivotTable = BasicDataView.extend({ }); row.html_tr.remove(); + removeFromArray(this.rows, row); }, draw: function () { - this.get_data(this.row_groupby) + this.get_data(this.groupby.row) .then(this.proxy('build_table')) .done(this.proxy('_draw')); }, @@ -434,9 +445,9 @@ var PivotTable = BasicDataView.extend({ var self = this; var header; - if (this.row_groupby.length > 0) { + if (this.groupby.row.length > 0) { header = '' + - this.fields[this.row_groupby[0]].string + + this.fields[this.groupby.row[0]].string + '' + this.measure_label + ''; @@ -471,7 +482,7 @@ var ChartView = BasicDataView.extend({ var self = this; this.$el.empty(); this.$el.append(''); - this.get_data(this.row_groupby).done(function (data) { + this.get_data(this.groupby.row).done(function (data) { self.render(data); }); }, @@ -555,6 +566,14 @@ var ChartView = BasicDataView.extend({ }); +// utility +function removeFromArray(array, element) { + var index = array.indexOf(element); + if (index > -1) { + array.splice(index, 1); + } +} + /** * Query the server and return a deferred which will return the data * with all the groupbys applied (this is done for now, but the goal -- cgit v1.2.3 From 776a57ef0cda65ce03f60d9f5bf3d466225dd4b2 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 15 Nov 2013 12:26:59 +0100 Subject: [FIX] fixes a bug where the view build a table without clearing the existing rows (addon web_graph) bzr revid: ged@openerp.com-20131115112659-mzb4smcr85dq60ww --- addons/web_graph/static/src/js/graph.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 93e8d72cfe8..5a4ff51f2d4 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -144,6 +144,7 @@ var BasicDataView = instance.web.Widget.extend({ // measure: quantity to display. either a field from the model, or // null, in which case we use the "count" measure init: function (model, options) { + console.log("initializing", model, options); var self = this; this.model = model; this.fields = options.fields; @@ -422,6 +423,7 @@ var PivotTable = BasicDataView.extend({ build_table: function (data) { var self = this; + this.rows = []; this.cols = [{ path: [], -- cgit v1.2.3 From ab1411aa9eaedc8ef569aaa660cf7a3584f3ef30 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 15 Nov 2013 13:13:15 +0100 Subject: [IMP] makes the text clickable in clickable cells in pivottable (addon web_graph) bzr revid: ged@openerp.com-20131115121315-2lb0mptvv44g8xjk --- addons/web_graph/static/src/css/graph.css | 4 ++++ addons/web_graph/static/src/js/graph.js | 19 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index f2d3338c385..6651ea39ae2 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -17,4 +17,8 @@ span.field-selection { span.web_graph_indent { padding-left: 50px; +} + +.web_graph_click:hover { + cursor: pointer; } \ No newline at end of file diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 5a4ff51f2d4..9f94f5eb0ee 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -144,7 +144,6 @@ var BasicDataView = instance.web.Widget.extend({ // measure: quantity to display. either a field from the model, or // null, in which case we use the "count" measure init: function (model, options) { - console.log("initializing", model, options); var self = this; this.model = model; this.fields = options.fields; @@ -218,7 +217,7 @@ var PivotTable = BasicDataView.extend({ current_row_id : 0, events: { - 'click .graph_border > a' : function (event) { + 'click .web_graph_click' : function (event) { var self = this; event.preventDefault(); var row_id = event.target.attributes['data-row-id'].nodeValue; @@ -241,6 +240,9 @@ var PivotTable = BasicDataView.extend({ }; this.dropdown = $(QWeb.render('field_selection', dropdown_options)); $(event.target).after(this.dropdown); + this.dropdown.css({position:"absolute", + left:event.pageX, + top:event.pageY}); $('.field-selection').next('.dropdown-menu').toggle(); } } @@ -292,9 +294,18 @@ var PivotTable = BasicDataView.extend({ }); } if (options && options.foldable) { - attrs.push(' '); + attrs.push(''); } - return attrs.join(' ') + content + ''; + if (content) { + attrs.push(content); + } else { + attrs.push('Undefined'); + } + if (options && options.foldable) { + attrs.push(''); + } + attrs.push(''); + return attrs.join(' '); }, make_row: function (data, parent_id) { -- cgit v1.2.3 From b08a38c5286ddca7945ed73938e53b0d7e98dbd2 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 15 Nov 2013 16:16:59 +0100 Subject: [REF] refactoring in progress. moves charts to its own file in addon web_graph bzr revid: ged@openerp.com-20131115151659-g1lc0ypd9v3cxg1p --- addons/web_graph/static/src/js/charts.js | 84 ++++++++++++++++++++ addons/web_graph/static/src/js/graph.js | 131 ++++++++----------------------- 2 files changed, 116 insertions(+), 99 deletions(-) create mode 100644 addons/web_graph/static/src/js/charts.js (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js new file mode 100644 index 00000000000..728b435dbd1 --- /dev/null +++ b/addons/web_graph/static/src/js/charts.js @@ -0,0 +1,84 @@ + +var formatter = function (measure) { + return function (datapt) { + var val = datapt.attributes; + return { + x: datapt.attributes.value[1], + y: measure ? val.aggregates[measure] : val.length, + }; + }; +}; + + +var Charts = { + bar_chart : function (groups, measure) { + var formatted_data = [{ + key: 'Bar chart', + values: _.map(groups, formatter(measure)), + }]; + + nv.addGraph(function () { + var chart = nv.models.discreteBarChart() + .tooltips(false) + .showValues(true) + .staggerLabels(true) + .width(650) + .height(400); + + d3.select('.graph_chart svg') + .datum(formatted_data) + .attr('width', 650) + .attr('height', 400) + .call(chart); + + nv.utils.windowResize(chart.update); + return chart; + }); + }, + + line_chart: function (groups, measure, measure_label) { + var formatted_data = [{ + key: measure_label, + values: _.map(groups, formatter(measure)) + }]; + + nv.addGraph(function () { + var chart = nv.models.lineChart() + .x(function (d,u) { return u; }) + .width(600) + .height(300) + .margin({top: 30, right: 20, bottom: 20, left: 60}); + + d3.select('.graph_chart svg') + .attr('width', 600) + .attr('height', 300) + .datum(formatted_data) + .call(chart); + + return chart; + }); + }, + + pie_chart: function (groups, measure) { + var formatted_data = _.map(groups, formatter(measure)); + + nv.addGraph(function () { + var chart = nv.models.pieChart() + .color(d3.scale.category10().range()) + .width(650) + .height(400); + + d3.select('.graph_chart svg') + .datum(formatted_data) + .transition().duration(1200) + .attr('width', 650) + .attr('height', 400) + .call(chart); + + nv.utils.windowResize(chart.update); + return chart; + }); + }, + + +}; \ No newline at end of file diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 9f94f5eb0ee..ccec8f03ec3 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -126,6 +126,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ }); + + /** * BasicDataView widget. Basic widget to manage show/hide functionality * and to initialize some attributes. It is inherited by PivotTable @@ -206,6 +208,35 @@ var BasicDataView = instance.web.Widget.extend({ }); + + + /** + * ChartView widget. It displays the data in chart form, using the nvd3 + * library. Various modes include bar charts, pie charts or line charts. + */ +var ChartView = BasicDataView.extend({ + template: 'chart_view', + + set_mode: function (mode) { + this.mode = mode; + console.log("mode",mode); + this.render = this['render_' + mode]; + this.need_redraw = true; + }, + + draw: function () { + var self = this; + this.$el.empty(); + console.log("measrue",self.measure); + this.$el.append(''); + this.get_data(this.groupby.row).done(function (data) { + Charts[self.mode](data, self.measure, self.measure_label); + }); + }, + + + +}); /** * PivotTable widget. It displays the data in tabular data and allows the * user to drill down and up in the table @@ -479,106 +510,8 @@ var PivotTable = BasicDataView.extend({ } }); - /** - * ChartView widget. It displays the data in chart form, using the nvd3 - * library. Various modes include bar charts, pie charts or line charts. - */ -var ChartView = BasicDataView.extend({ - template: 'chart_view', - - set_mode: function (mode) { - this.render = this['render_' + mode]; - this.need_redraw = true; - }, - - draw: function () { - var self = this; - this.$el.empty(); - this.$el.append(''); - this.get_data(this.groupby.row).done(function (data) { - self.render(data); - }); - }, - - format_data: function (datapt) { - var val = datapt.attributes; - return { - x: datapt.attributes.value[1], - y: this.measure ? val.aggregates[this.measure] : val.length, - }; - }, - - render_bar_chart: function (data) { - var formatted_data = [{ - key: 'Bar chart', - values: _.map(data, this.proxy('format_data')), - }]; - - nv.addGraph(function () { - var chart = nv.models.discreteBarChart() - .tooltips(false) - .showValues(true) - .staggerLabels(true) - .width(650) - .height(400); - - d3.select('.graph_chart svg') - .datum(formatted_data) - .attr('width', 650) - .attr('height', 400) - .call(chart); - - nv.utils.windowResize(chart.update); - return chart; - }); - }, - - render_line_chart: function (data) { - var formatted_data = [{ - key: this.measure_label, - values: _.map(data, this.proxy('format_data')) - }]; - - nv.addGraph(function () { - var chart = nv.models.lineChart() - .x(function (d,u) { return u; }) - .width(600) - .height(300) - .margin({top: 30, right: 20, bottom: 20, left: 60}); - - d3.select('.graph_chart svg') - .attr('width', 600) - .attr('height', 300) - .datum(formatted_data) - .call(chart); - - return chart; - }); - }, - - render_pie_chart: function (data) { - var formatted_data = _.map(data, this.proxy('format_data')); - - nv.addGraph(function () { - var chart = nv.models.pieChart() - .color(d3.scale.category10().range()) - .width(650) - .height(400); - - d3.select('.graph_chart svg') - .datum(formatted_data) - .transition().duration(1200) - .attr('width', 650) - .attr('height', 400) - .call(chart); - - nv.utils.windowResize(chart.update); - return chart; - }); - }, - -}); +//////////////////////////////////////////////////////////////////////////////// // utility function removeFromArray(array, element) { var index = array.indexOf(element); -- cgit v1.2.3 From 08a26f9e95ab5a432385d803679eba030fcb6673 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 15 Nov 2013 16:37:01 +0100 Subject: [REF] refactoring in progress. moves some util functions to its own file in addon web_graph bzr revid: ged@openerp.com-20131115153701-rxh1voksnu0ule4t --- addons/web_graph/static/src/js/graph.js | 40 --------------------------------- 1 file changed, 40 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index ccec8f03ec3..48fa416ba75 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -511,45 +511,5 @@ var PivotTable = BasicDataView.extend({ }); -//////////////////////////////////////////////////////////////////////////////// -// utility -function removeFromArray(array, element) { - var index = array.indexOf(element); - if (index > -1) { - array.splice(index, 1); - } -} - -/** - * Query the server and return a deferred which will return the data - * with all the groupbys applied (this is done for now, but the goal - * is to modify read_group in order to allow eager and lazy groupbys - */ -function query_groups (model, fields, domain, groupbys) { - return model.query(fields) - .filter(domain) - .group_by(groupbys) - .then(function (results) { - var non_empty_results = _.filter(results, function (group) { - return group.attributes.length > 0; - }); - if (groupbys.length <= 1) { - return non_empty_results; - } else { - var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) { - var new_domain = result.model._domain; - var new_groupings = groupbys.slice(1); - return query_groups(model, fields,new_domain, new_groupings).then(function (subgroups) { - result.subgroups_data = subgroups; - }); - })); - return get_subgroups.then(function () { - return non_empty_results; - }); - } - }); -} - - }; -- cgit v1.2.3 From 990deeebe465ae9ee992b1251b89c46683d84589 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 15 Nov 2013 17:32:09 +0100 Subject: [REF] refactoring in progress. removes widget chartview and merges basicdataview with pivottable widgets in addon web_graph bzr revid: ged@openerp.com-20131115163209-iebydq0jth2f8lee --- addons/web_graph/static/src/js/charts.js | 6 +- addons/web_graph/static/src/js/graph.js | 102 +++++++++----------------- addons/web_graph/static/src/xml/web_graph.xml | 3 +- 3 files changed, 38 insertions(+), 73 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index 728b435dbd1..f35d012b592 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -25,7 +25,7 @@ var Charts = { .width(650) .height(400); - d3.select('.graph_chart svg') + d3.select('.graph_main_content svg') .datum(formatted_data) .attr('width', 650) .attr('height', 400) @@ -49,7 +49,7 @@ var Charts = { .height(300) .margin({top: 30, right: 20, bottom: 20, left: 60}); - d3.select('.graph_chart svg') + d3.select('.graph_main_content svg') .attr('width', 600) .attr('height', 300) .datum(formatted_data) @@ -68,7 +68,7 @@ var Charts = { .width(650) .height(400); - d3.select('.graph_chart svg') + d3.select('.graph_main_content svg') .datum(formatted_data) .transition().duration(1200) .attr('width', 650) diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 48fa416ba75..3b53744d9f3 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -22,18 +22,12 @@ instance.web_graph.GraphView = instance.web.View.extend({ template: 'GraphView', display_name: _lt('Graph'), view_type: 'graph', - mode: 'pivot', // pivot => display pivot table, chart => display chart + mode: 'pivot', // pivot, bar_chart, line_chart or pie_chart events: { 'click .graph_mode_selection li' : function (event) { event.preventDefault(); - var view_mode = event.target.attributes['data-mode'].nodeValue; - if (view_mode === 'data') { - this.mode = 'pivot'; - } else { - this.mode = 'chart'; - this.chart_view.set_mode(view_mode); - } + this.mode = event.target.attributes['data-mode'].nodeValue; this.display_data(); }, 'click .graph_clear_groups' : function (event) { @@ -91,31 +85,48 @@ instance.web_graph.GraphView = instance.web.View.extend({ return $.when(important_fields_def, field_descr_def) .then(function () { + + self.data = { + model: model, + domain: options.domain, + fields: options.fields, + important_fields: options.important_fields, + measure: options.measure, + measure_label: options.fields[options.measure].string, + col_groupby: [], + row_groupby: options.row_groupby, + groups: [], + total: null, + }; self.pivot_table = new PivotTable(model, options); - self.chart_view = new ChartView(model, options); }) .then(function () { return self.pivot_table.appendTo('.graph_main_content'); - }) - .then(function() { - return self.chart_view.appendTo('.graph_main_content'); }); + }, display_data : function () { + var content = this.$el.filter('.graph_main_content'); + content.find('svg').remove(); + var self = this; if (this.mode === 'pivot') { - this.chart_view.hide(); this.pivot_table.show(); + } else { this.pivot_table.hide(); - this.chart_view.show(); + content.append(''); + var view_fields = this.data.row_groupby.concat(this.data.measure, this.data.col_groupby); + query_groups(this.data.model, view_fields, this.data.domain, this.data.row_groupby).then(function (groups) { + Charts[self.mode](groups, self.data.measure, self.data.measure_label); + }); + } }, do_search: function (domain, context, group_by) { - this.domain = new instance.web.CompoundDomain(domain); + this.data.domain = new instance.web.CompoundDomain(domain); this.pivot_table.set_domain(domain); - this.chart_view.set_domain(domain); this.display_data(); }, @@ -127,14 +138,15 @@ instance.web_graph.GraphView = instance.web.View.extend({ }); - /** - * BasicDataView widget. Basic widget to manage show/hide functionality - * and to initialize some attributes. It is inherited by PivotTable - * and ChartView widget. + * PivotTable widget. It displays the data in tabular data and allows the + * user to drill down and up in the table */ -var BasicDataView = instance.web.Widget.extend({ - +var PivotTable = instance.web.Widget.extend({ + template: 'pivot_table', + rows: [], + cols: [], + current_row_id : 0, need_redraw: false, // Input parameters: @@ -198,54 +210,12 @@ var BasicDataView = instance.web.Widget.extend({ this.$el.css('display', 'none'); }, - draw: function() { - }, get_data: function (groupby) { var view_fields = this.groupby.row.concat(this.measure, this.groupby.col); return query_groups(this.model, view_fields, this.domain, groupby); }, -}); - - - - /** - * ChartView widget. It displays the data in chart form, using the nvd3 - * library. Various modes include bar charts, pie charts or line charts. - */ -var ChartView = BasicDataView.extend({ - template: 'chart_view', - - set_mode: function (mode) { - this.mode = mode; - console.log("mode",mode); - this.render = this['render_' + mode]; - this.need_redraw = true; - }, - - draw: function () { - var self = this; - this.$el.empty(); - console.log("measrue",self.measure); - this.$el.append(''); - this.get_data(this.groupby.row).done(function (data) { - Charts[self.mode](data, self.measure, self.measure_label); - }); - }, - - - -}); - /** - * PivotTable widget. It displays the data in tabular data and allows the - * user to drill down and up in the table - */ -var PivotTable = BasicDataView.extend({ - template: 'pivot_table', - rows: [], - cols: [], - current_row_id : 0, events: { 'click .web_graph_click' : function (event) { @@ -297,10 +267,6 @@ var PivotTable = BasicDataView.extend({ this.draw(); }, - init: function (model, options) { - this._super(model, options); - }, - generate_id: function () { this.current_row_id += 1; return this.current_row_id - 1; diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 5a56f34d84a..6696260b568 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -6,12 +6,11 @@ Chart type -
    -- cgit v1.2.3 From afb1382575c2904fb40217c8cba7fee2d3de0d17 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 15 Nov 2013 17:32:47 +0100 Subject: [ADD] forgot to add utility.js file to addon web_graph bzr revid: ged@openerp.com-20131115163247-9tv5t7w9ygcmcnnm --- addons/web_graph/static/src/js/utility.js | 38 +++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 addons/web_graph/static/src/js/utility.js (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/utility.js b/addons/web_graph/static/src/js/utility.js new file mode 100644 index 00000000000..9f4ab2bb6a3 --- /dev/null +++ b/addons/web_graph/static/src/js/utility.js @@ -0,0 +1,38 @@ + +function removeFromArray(array, element) { + var index = array.indexOf(element); + if (index > -1) { + array.splice(index, 1); + } +} + +/** + * Query the server and return a deferred which will return the data + * with all the groupbys applied (this is done for now, but the goal + * is to modify read_group in order to allow eager and lazy groupbys + */ +function query_groups (model, fields, domain, groupbys) { + return model.query(fields) + .filter(domain) + .group_by(groupbys) + .then(function (results) { + var non_empty_results = _.filter(results, function (group) { + return group.attributes.length > 0; + }); + if (groupbys.length <= 1) { + return non_empty_results; + } else { + var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) { + var new_domain = result.model._domain; + var new_groupings = groupbys.slice(1); + return query_groups(model, fields,new_domain, new_groupings).then(function (subgroups) { + result.subgroups_data = subgroups; + }); + })); + return get_subgroups.then(function () { + return non_empty_results; + }); + } + }); +} + -- cgit v1.2.3 From 0b9150160c89f96388b50ad6eb39bfe9595a1c50 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 18 Nov 2013 10:07:15 +0100 Subject: [REF] refactoring in progress. removes widget chartview and merges basicdataview with pivottable widgets in addon web_graph bzr revid: ged@openerp.com-20131118090715-2e9vgt7y2ynm6nql --- addons/web_graph/static/src/js/graph.js | 34 +++++++-------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 3b53744d9f3..a0762dd5ae0 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -15,8 +15,8 @@ var QWeb = instance.web.qweb; instance.web.views.add('graph', 'instance.web_graph.GraphView'); /** - * GraphView view. It mostly contains two widgets (PivotTable and ChartView) - * and some data. + * GraphView view. It mostly contains a widget (PivotTable), some data, and + * calls to charts function. */ instance.web_graph.GraphView = instance.web.View.extend({ template: 'GraphView', @@ -111,6 +111,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ content.find('svg').remove(); var self = this; if (this.mode === 'pivot') { + this.pivot_table.draw(); this.pivot_table.show(); } else { @@ -126,7 +127,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ do_search: function (domain, context, group_by) { this.data.domain = new instance.web.CompoundDomain(domain); - this.pivot_table.set_domain(domain); + this.pivot_table.set_domain(this.data.domain); this.display_data(); }, @@ -147,7 +148,6 @@ var PivotTable = instance.web.Widget.extend({ rows: [], cols: [], current_row_id : 0, - need_redraw: false, // Input parameters: // model: model to display @@ -170,39 +170,16 @@ var PivotTable = instance.web.Widget.extend({ this.measure = options.measure; this.measure_label = options.measure ? options.fields[options.measure].string : 'Quantity'; this.data = []; - this.need_redraw = true; this.important_fields = options.important_fields; }, - get_descr: function (field_id) { - return this.fields[field_id].string; - }, set_domain: function (domain) { this.domain = domain; - this.need_redraw = true; - }, - - set_row_groupby: function (row_groupby) { - this.groupby.row = row_groupby; - this.need_redraw = true; - }, - - set_col_groupby: function (col_groupby) { - this.groupby.col = col_groupby; - this.need_redraw = true; }, - set_measure: function (measure) { - this.measure = measure; - this.need_redraw = true; - }, show: function () { - if (this.need_redraw) { - this.draw(); - this.need_redraw = false; - } this.$el.css('display', 'block'); }, @@ -210,6 +187,9 @@ var PivotTable = instance.web.Widget.extend({ this.$el.css('display', 'none'); }, + get_descr: function (field_id) { + return this.fields[field_id].string; + }, get_data: function (groupby) { var view_fields = this.groupby.row.concat(this.measure, this.groupby.col); -- cgit v1.2.3 From 06b125de40269076969232fa877ea8b8ec3c61ec Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 18 Nov 2013 13:53:20 +0100 Subject: [REF] large refactoring. removes widget chartview and merges basicdataview with pivottable widgets in addon web_graph bzr revid: ged@openerp.com-20131118125320-uhy58xmxlx4nkvbt --- addons/web_graph/static/src/css/graph.css | 4 + addons/web_graph/static/src/js/graph.js | 385 +++++++++++--------------- addons/web_graph/static/src/xml/web_graph.xml | 4 +- 3 files changed, 164 insertions(+), 229 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index 6651ea39ae2..ee9234cbdff 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -19,6 +19,10 @@ span.web_graph_indent { padding-left: 50px; } +span.web_graph_indent:first-child { + padding-left: 10px; +} + .web_graph_click:hover { cursor: pointer; } \ No newline at end of file diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index a0762dd5ae0..558e101c921 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -23,6 +23,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ display_name: _lt('Graph'), view_type: 'graph', mode: 'pivot', // pivot, bar_chart, line_chart or pie_chart + pivot_table: null, events: { 'click .graph_mode_selection li' : function (event) { @@ -30,34 +31,31 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.mode = event.target.attributes['data-mode'].nodeValue; this.display_data(); }, - 'click .graph_clear_groups' : function (event) { - this.pivot_table.clear_groups(); - }, }, view_loading: function (fields_view_get) { var self = this; var model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}); - var options = {}; - options.domain = []; - options.col_groupby = []; + var domain = []; + var col_groupby = []; + var row_groupby = []; + var measure = null; + var fields; + var important_fields = []; // get the default groupbys and measure defined in the field view - options.measure = null; - options.row_groupby = []; _.each(fields_view_get.arch.children, function (field) { if ('name' in field.attrs) { if ('operator' in field.attrs) { - options.measure = field.attrs.name; + measure = field.attrs.name; } else { - options.row_groupby.push(field.attrs.name); + row_groupby.push(field.attrs.name); } } }); // get the most important fields (of the model) by looking at the // groupby filters defined in the search view - options.important_fields = []; var load_view = instance.web.fields_view_get({ model: model, view_type: 'search', @@ -67,12 +65,11 @@ instance.web_graph.GraphView = instance.web.View.extend({ var groups = _.select(search_view.arch.children, function (c) { return (c.tag == 'group') && (c.attrs.string != 'Display'); }); - _.each(groups, function(g) { _.each(g.children, function (g) { if (g.attrs.context) { var field_id = py.eval(g.attrs.context).group_by; - options.important_fields.push(field_id); + important_fields.push(field_id); } }); }); @@ -80,30 +77,23 @@ instance.web_graph.GraphView = instance.web.View.extend({ // get the fields descriptions from the model var field_descr_def = model.call('fields_get', []) - .then(function (fields) { options.fields = fields; }); - + .then(function (fs) { fields = fs; }); return $.when(important_fields_def, field_descr_def) .then(function () { - self.data = { model: model, - domain: options.domain, - fields: options.fields, - important_fields: options.important_fields, - measure: options.measure, - measure_label: options.fields[options.measure].string, + domain: domain, + fields: fields, + important_fields: important_fields, + measure: measure, + measure_label: fields[measure].string, col_groupby: [], - row_groupby: options.row_groupby, + row_groupby: row_groupby, groups: [], total: null, }; - self.pivot_table = new PivotTable(model, options); - }) - .then(function () { - return self.pivot_table.appendTo('.graph_main_content'); }); - }, display_data : function () { @@ -111,9 +101,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ content.find('svg').remove(); var self = this; if (this.mode === 'pivot') { - this.pivot_table.draw(); this.pivot_table.show(); - } else { this.pivot_table.hide(); content.append(''); @@ -127,7 +115,13 @@ instance.web_graph.GraphView = instance.web.View.extend({ do_search: function (domain, context, group_by) { this.data.domain = new instance.web.CompoundDomain(domain); - this.pivot_table.set_domain(this.data.domain); + + if (this.pivot_table) { + this.pivot_table.draw(); + } else { + this.pivot_table = new PivotTable(this.data); + this.pivot_table.appendTo('.graph_main_content'); + } this.display_data(); }, @@ -139,64 +133,19 @@ instance.web_graph.GraphView = instance.web.View.extend({ }); + /** * PivotTable widget. It displays the data in tabular data and allows the * user to drill down and up in the table */ var PivotTable = instance.web.Widget.extend({ template: 'pivot_table', + data: null, + headers: [], rows: [], cols: [], current_row_id : 0, - // Input parameters: - // model: model to display - // fields: dictionary returned by field_get on model (desc of model) - // domain: constraints on model records - // row_groupby: groubys on rows (so, row headers in the pivot table) - // col_groupby: idem, but on col - // measure: quantity to display. either a field from the model, or - // null, in which case we use the "count" measure - init: function (model, options) { - var self = this; - this.model = model; - this.fields = options.fields; - this.domain = options.domain; - this.groupby = { - row: options.row_groupby, - col: options.col_groupby, - }; - - this.measure = options.measure; - this.measure_label = options.measure ? options.fields[options.measure].string : 'Quantity'; - this.data = []; - this.important_fields = options.important_fields; - }, - - - set_domain: function (domain) { - this.domain = domain; - }, - - - show: function () { - this.$el.css('display', 'block'); - }, - - hide: function () { - this.$el.css('display', 'none'); - }, - - get_descr: function (field_id) { - return this.fields[field_id].string; - }, - - get_data: function (groupby) { - var view_fields = this.groupby.row.concat(this.measure, this.groupby.col); - return query_groups(this.model, view_fields, this.domain, groupby); - }, - - events: { 'click .web_graph_click' : function (event) { var self = this; @@ -207,12 +156,12 @@ var PivotTable = instance.web.Widget.extend({ if (row.expanded) { this.fold_row(row_id); } else { - if (row.path.length < this.groupby.row.length) { - var field_to_expand = this.groupby.row[row.path.length]; + if (row.path.length < this.data.row_groupby.length) { + var field_to_expand = this.data.row_groupby[row.path.length]; this.expand_row(row_id, field_to_expand); } else { - var already_grouped = self.groupby.row.concat(self.groupby.col); - var possible_groups = _.difference(self.important_fields, already_grouped); + var already_grouped = self.data.row_groupby.concat(self.data.col_groupby); + var possible_groups = _.difference(self.data.important_fields, already_grouped); var dropdown_options = { fields: _.map(possible_groups, function (field) { return {id: field, value: self.get_descr(field)}; @@ -221,14 +170,13 @@ var PivotTable = instance.web.Widget.extend({ }; this.dropdown = $(QWeb.render('field_selection', dropdown_options)); $(event.target).after(this.dropdown); - this.dropdown.css({position:"absolute", - left:event.pageX, + this.dropdown.css({position:'absolute', + left:event.pageX, top:event.pageY}); $('.field-selection').next('.dropdown-menu').toggle(); } } - }, 'click a.field-selection' : function (event) { event.preventDefault(); @@ -238,133 +186,167 @@ var PivotTable = instance.web.Widget.extend({ this.expand_row(row_id, field_id); }, }, + + init: function (data) { + this.data = data; + }, - clear_groups: function () { - this.groupby.row = []; - this.groupby.col = []; - this.rows = []; - this.cols = []; - this.draw(); + start: function () { + var self = this; + this.get_groups(this.data.row_groupby) + .then(function (groups) { + self.data.groups = groups; + return self.get_groups([]); + }).then(function (total) { + self.data.total = total; + self.build_table(); + self.draw(); + }); }, - generate_id: function () { - this.current_row_id += 1; - return this.current_row_id - 1; + draw: function () { + var self = this; + this.$el.empty(); + + _.each(this.headers, function (header) { + self.$el.append(header); + }); + + _.each(this.rows, function (row) { + self.$el.append(row.html); + }); }, - get_row: function (id) { - return _.find(this.rows, function(row) { - return (row.id == id); + show: function () { + this.$el.css('display', 'block'); + }, + + hide: function () { + this.$el.css('display', 'none'); + }, + + build_table: function () { + var self = this; + + this.headers.push('' + + '' + + this.data.measure_label + + ''); + + var main_row = this.make_row(this.data.total[0]); + + _.each(this.data.groups, function (group) { + self.make_row(group, main_row.id); }); }, - make_cell: function (content, options) { - var attrs = [''); - if (options && options.indent) { - _.each(_.range(options.indent), function () { - attrs.push(''); - }); - } - if (options && options.foldable) { - attrs.push(''); - } - if (content) { - attrs.push(content); - } else { - attrs.push('Undefined'); - } - if (options && options.foldable) { - attrs.push(''); - } - attrs.push(''); - return attrs.join(' '); + get_groups: function (groupby) { + var view_fields = this.data.row_groupby.concat(this.data.measure, this.data.col_groupby); + return query_groups(this.data.model, view_fields, this.data.domain, groupby); }, - make_row: function (data, parent_id) { - var has_parent = (parent_id !== undefined); - var parent = has_parent ? this.get_row(parent_id) : null; - var path; + make_row: function (group, parent_id) { + var path, + value, + expanded, + domain, + parent, + has_parent = (parent_id !== undefined), + row_id = this.generate_id(); + if (has_parent) { - path = parent.path.concat(data.attributes.grouped_on); - } else if (data.attributes.grouped_on !== undefined) { - path = [data.attributes.grouped_on]; + parent = this.get_row(parent_id); + path = parent.path.concat(group.attributes.grouped_on); + value = group.attributes.value[1]; + expanded = false; + parent.children.push(row_id); + domain = group.model._domain; } else { + parent = null; path = []; + value = 'Total'; + expanded = true; + domain = this.data.domain; } - var indent_level = has_parent ? parent.path.length : 0; - var value = (this.groupby.row.length > 0) ? data.attributes.value[1] : 'Total'; - - var jquery_row = $(''); - var row_id = this.generate_id(); - var header = $(this.make_cell(value, {is_border:true, indent: indent_level, foldable:true, row_id: row_id})); + var header = this.make_cell(value, {is_border:true, indent: path.length, foldable:true, row_id: row_id}); jquery_row.html(header); - jquery_row.append(this.make_cell(data.attributes.aggregates[this.measure])); + jquery_row.append(this.make_cell(group.attributes.aggregates[this.data.measure])); var row = { id: row_id, path: path, value: value, - expanded: false, + expanded: expanded, parent: parent_id, children: [], - html_tr: jquery_row, - domain: data.model._domain, + html: jquery_row, + domain: domain, }; - // rows.splice(index of parent if any,0,row); - this.rows.push(row); // to do, insert it properly + this.rows.push(row); // to do, insert it properly, after all childs of parent + return row; + }, - if (this.groupby.row.length === 0) { - row.remove_when_expanded = true; - row.domain = this.domain; - } - if (has_parent) { - parent.children.push(row.id); + generate_id: function () { + this.current_row_id += 1; + return this.current_row_id - 1; + }, + + get_row: function (id) { + return _.find(this.rows, function(row) { + return (row.id == id); + }); + }, + + make_cell: function (content, options) { + options = _.extend({is_border: false, indent:0, foldable:false}, options); + content = (content) ? content : 'Undefined'; + + var cell = $(''); + if (options.is_border) cell.addClass('graph_border'); + _.each(_.range(options.indent), function () { + cell.prepend($('', {class:'web_graph_indent'})); + }); + + if (options.foldable) { + var plus = $('', {'data-row-id':options.row_id, + class:'icon-plus-sign web_graph_click', + href:'#'}); + plus.append(' '); + plus.append(content); + cell.append(plus); + } else { + cell.append(content); } - return row; + return cell; }, expand_row: function (row_id, field_id) { var self = this; var row = this.get_row(row_id); - if (row.path.length == this.groupby.row.length) { - this.groupby.row.push(field_id); + if (row.path.length == this.data.row_groupby.length) { + this.data.row_groupby.push(field_id); } + row.expanded = true; + row.html.find('.icon-plus-sign') + .removeClass('icon-plus-sign') + .addClass('icon-minus-sign'); - var visible_fields = this.groupby.row.concat(this.groupby.col, this.measure); - - if (row.remove_when_expanded) { - this.rows = []; - } else { - row.expanded = true; - row.html_tr.find('.icon-plus-sign') - .removeClass('icon-plus-sign') - .addClass('icon-minus-sign'); - } - - query_groups(this.model, visible_fields, row.domain, [field_id]) + var visible_fields = this.data.row_groupby.concat(this.data.col_groupby, this.data.measure); + query_groups(this.data.model, visible_fields, row.domain, [field_id]) .then(function (data) { _.each(data.reverse(), function (datapt) { - var new_row; - if (row.remove_when_expanded) { - new_row = self.make_row(datapt); - self.$('tr.graph_table_header').after(new_row.html_tr); - } else { - new_row = self.make_row(datapt, row_id); - row.html_tr.after(new_row.html_tr); - } + var new_row = self.make_row(datapt, row_id); + row.html.after(new_row.html); + }); - if (row.remove_when_expanded) { - row.html_tr.remove(); - } }); }, @@ -379,7 +361,7 @@ var PivotTable = instance.web.Widget.extend({ row.children = []; row.expanded = false; - row.html_tr.find('.icon-minus-sign') + row.html.find('.icon-minus-sign') .removeClass('icon-minus-sign') .addClass('icon-plus-sign'); @@ -388,7 +370,7 @@ var PivotTable = instance.web.Widget.extend({ return Math.max(x,y); }, 0); - this.groupby.row.splice(new_groupby_length); + this.data.row_groupby.splice(new_groupby_length); }, remove_row: function (row_id) { @@ -399,63 +381,10 @@ var PivotTable = instance.web.Widget.extend({ self.remove_row(child_row); }); - row.html_tr.remove(); + row.html.remove(); removeFromArray(this.rows, row); }, - draw: function () { - this.get_data(this.groupby.row) - .then(this.proxy('build_table')) - .done(this.proxy('_draw')); - }, - - build_table: function (data) { - var self = this; - this.rows = []; - - this.cols = [{ - path: [], - value: this.measure_label, - expanded: false, - parent: null, - children: [], - html_tds: [], - domain: this.domain, - header: $(this.make_cell(this.measure_label, {is_border:true})), - }]; - - _.each(data, function (datapt) { - self.make_row(datapt); - }); - }, - - _draw: function () { - - this.$el.empty(); - var self = this; - var header; - - if (this.groupby.row.length > 0) { - header = '' + - this.fields[this.groupby.row[0]].string + - '' + - this.measure_label + - ''; - } else { - header = '' + - '' + - this.measure_label + - ''; - } - this.$el.append(header); - - _.each(this.rows, function (row) { - self.$el.append(row.html_tr); - }); - - } }); - }; - diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 6696260b568..dbe544d2d2c 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -33,7 +33,9 @@
  • - + +
  • +
  • Clear groups
  • -- cgit v1.2.3 From b34a2307cd60d857d4bcbf8cec053cf6748a8dc0 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 18 Nov 2013 14:07:56 +0100 Subject: [REF] moves the loading data code from start to draw function, in widget pivottable (addon web_graph) bzr revid: ged@openerp.com-20131118130756-rx6wqcejn92j5sl4 --- addons/web_graph/static/src/js/graph.js | 45 ++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 558e101c921..a1a9ef68429 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -117,7 +117,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.data.domain = new instance.web.CompoundDomain(domain); if (this.pivot_table) { - this.pivot_table.draw(); + this.pivot_table.draw(true); } else { this.pivot_table = new PivotTable(this.data); this.pivot_table.appendTo('.graph_main_content'); @@ -133,7 +133,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ }); - /** * PivotTable widget. It displays the data in tabular data and allows the * user to drill down and up in the table @@ -186,35 +185,39 @@ var PivotTable = instance.web.Widget.extend({ this.expand_row(row_id, field_id); }, }, - + init: function (data) { this.data = data; }, start: function () { - var self = this; - this.get_groups(this.data.row_groupby) - .then(function (groups) { - self.data.groups = groups; - return self.get_groups([]); - }).then(function (total) { - self.data.total = total; - self.build_table(); - self.draw(); - }); + this.draw(true); }, - draw: function () { + draw: function (load_data) { var self = this; - this.$el.empty(); - _.each(this.headers, function (header) { - self.$el.append(header); - }); + if (load_data === true) { + this.get_groups(this.data.row_groupby) + .then(function (groups) { + self.data.groups = groups; + return self.get_groups([]); + }).then(function (total) { + self.data.total = total; + self.build_table(); + self.draw(false); + }); + } else { + this.$el.empty(); - _.each(this.rows, function (row) { - self.$el.append(row.html); - }); + _.each(this.headers, function (header) { + self.$el.append(header); + }); + + _.each(this.rows, function (row) { + self.$el.append(row.html); + }); + } }, show: function () { -- cgit v1.2.3 From a6848a195a60b9b0d2a6a65daa2716dbeece4708 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 18 Nov 2013 15:19:55 +0100 Subject: [IMP] small code cleanup in addon web_graph bzr revid: ged@openerp.com-20131118141955-00qcb19wm0gswvck --- addons/web_graph/static/src/css/graph.css | 2 +- addons/web_graph/static/src/js/graph.js | 49 ++++++++++++++++++------------- 2 files changed, 29 insertions(+), 22 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index ee9234cbdff..863829b320d 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -20,7 +20,7 @@ span.web_graph_indent { } span.web_graph_indent:first-child { - padding-left: 10px; + padding-left: 25px; } .web_graph_click:hover { diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index a1a9ef68429..4f8c579cfc3 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -147,11 +147,11 @@ var PivotTable = instance.web.Widget.extend({ events: { 'click .web_graph_click' : function (event) { - var self = this; + var row_id = event.target.attributes['data-row-id'].nodeValue, + row = this.get_row(row_id); + event.preventDefault(); - var row_id = event.target.attributes['data-row-id'].nodeValue; - var row = this.get_row(row_id); if (row.expanded) { this.fold_row(row_id); } else { @@ -159,24 +159,12 @@ var PivotTable = instance.web.Widget.extend({ var field_to_expand = this.data.row_groupby[row.path.length]; this.expand_row(row_id, field_to_expand); } else { - var already_grouped = self.data.row_groupby.concat(self.data.col_groupby); - var possible_groups = _.difference(self.data.important_fields, already_grouped); - var dropdown_options = { - fields: _.map(possible_groups, function (field) { - return {id: field, value: self.get_descr(field)}; - }), - row_id: row_id, - }; - this.dropdown = $(QWeb.render('field_selection', dropdown_options)); - $(event.target).after(this.dropdown); - this.dropdown.css({position:'absolute', - left:event.pageX, - top:event.pageY}); - $('.field-selection').next('.dropdown-menu').toggle(); + this.display_dropdown(row_id, $(event.target), event.pageY, event.pageY); } } }, + 'click a.field-selection' : function (event) { event.preventDefault(); this.dropdown.remove(); @@ -228,13 +216,32 @@ var PivotTable = instance.web.Widget.extend({ this.$el.css('display', 'none'); }, + display_dropdown: function (row_id, target, x, y) { + var self = this, + already_grouped = self.data.row_groupby.concat(self.data.col_groupby), + possible_groups = _.difference(self.data.important_fields, already_grouped), + dropdown_options = { + fields: _.map(possible_groups, function (field) { + return {id: field, value: self.get_descr(field)}; + }), + row_id: row_id, + }; + this.dropdown = $(QWeb.render('field_selection', dropdown_options)); + target.after(this.dropdown); + this.dropdown.css({position:'absolute', + left:x, + top:y}); + $('.field-selection').next('.dropdown-menu').toggle(); + }, + build_table: function () { var self = this; - this.headers.push('' + - '' + - this.data.measure_label + - ''); + var header = $(''); + header.append(this.make_cell(' ', {is_border:true})); + header.append(this.make_cell(this.data.measure_label, + {is_border:true, foldable: true})); + this.headers = [header]; var main_row = this.make_row(this.data.total[0]); -- cgit v1.2.3 From 1901b38c16648267077a3a2f5671ba1f2ad04ba3 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 18 Nov 2013 16:26:20 +0100 Subject: [IMP] preliminary work on supporting col expansion in pivottable widget (addon web_graph) bzr revid: ged@openerp.com-20131118152620-srzpkuom8rmxlik1 --- addons/web_graph/static/src/js/graph.js | 101 ++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 23 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 4f8c579cfc3..949739c7ae1 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -143,26 +143,18 @@ var PivotTable = instance.web.Widget.extend({ headers: [], rows: [], cols: [], - current_row_id : 0, + id_seed : 0, events: { 'click .web_graph_click' : function (event) { - var row_id = event.target.attributes['data-row-id'].nodeValue, - row = this.get_row(row_id); - event.preventDefault(); - if (row.expanded) { - this.fold_row(row_id); - } else { - if (row.path.length < this.data.row_groupby.length) { - var field_to_expand = this.data.row_groupby[row.path.length]; - this.expand_row(row_id, field_to_expand); - } else { - this.display_dropdown(row_id, $(event.target), event.pageY, event.pageY); - } + if (event.target.attributes['data-row-id'] !== undefined) { + this.handle_row_event(event); + } + if (event.target.attributes['data-col-id'] !== undefined) { + this.handle_col_event(event); } - }, 'click a.field-selection' : function (event) { @@ -174,6 +166,39 @@ var PivotTable = instance.web.Widget.extend({ }, }, + handle_row_event: function (event) { + var row_id = event.target.attributes['data-row-id'].nodeValue, + row = this.get_row(row_id); + + if (row.expanded) { + this.fold_row(row_id); + } else { + if (row.path.length < this.data.row_groupby.length) { + var field_to_expand = this.data.row_groupby[row.path.length]; + this.expand_row(row_id, field_to_expand); + } else { + this.display_dropdown(row_id, $(event.target), event.pageY, event.pageY); + } + } + }, + + handle_col_event: function (event) { + console.log("col expand", this.cols); + // var col_id = event.target.attributes['data-col-id'].nodeValue, + // col = this.get_row(col_id); + + // if (col.expanded) { + // this.fold_row(row_id); + // } else { + // if (col.path.length < this.data.col_groupby.length) { + // var field_to_expand = this.data.col_groupby[col.path.length]; + // this.expand_col(col_id, field_to_expand); + // } else { + // this.display_dropdown(col_id, $(event.target), event.pageY, event.pageY); + // } + // } + }, + init: function (data) { this.data = data; }, @@ -237,12 +262,24 @@ var PivotTable = instance.web.Widget.extend({ build_table: function () { var self = this; + var col_id = this.generate_id(); + var header = $(''); header.append(this.make_cell(' ', {is_border:true})); header.append(this.make_cell(this.data.measure_label, - {is_border:true, foldable: true})); + {is_border:true, foldable: true, col_id:col_id})); this.headers = [header]; + this.cols= [{ + path: [], + value: this.data.measure_label, + expanded: false, + parent: null, + children: [], + cells: [], // a cell is {td:, row_id:} + domain: this.data.domain, + }]; + var main_row = this.make_row(this.data.total[0]); _.each(this.data.groups, function (group) { @@ -286,8 +323,14 @@ var PivotTable = instance.web.Widget.extend({ var jquery_row = $(''); var header = this.make_cell(value, {is_border:true, indent: path.length, foldable:true, row_id: row_id}); + var cell = this.make_cell(group.attributes.aggregates[this.data.measure]); jquery_row.html(header); - jquery_row.append(this.make_cell(group.attributes.aggregates[this.data.measure])); + jquery_row.append(cell); + + _.each(this.cols, function (col) { + col.cells.push({row_id: row_id, td: cell }); + // insert cells into corresponding col + }); var row = { id: row_id, @@ -304,8 +347,8 @@ var PivotTable = instance.web.Widget.extend({ }, generate_id: function () { - this.current_row_id += 1; - return this.current_row_id - 1; + this.id_seed += 1; + return this.id_seed - 1; }, get_row: function (id) { @@ -314,9 +357,15 @@ var PivotTable = instance.web.Widget.extend({ }); }, + get_col: function (id) { + return _.find(this.cols, function(col) { + return (col.id == id); + }); + }, + make_cell: function (content, options) { options = _.extend({is_border: false, indent:0, foldable:false}, options); - content = (content) ? content : 'Undefined'; + content = (content !== undefined) ? content : 'Undefined'; var cell = $(''); if (options.is_border) cell.addClass('graph_border'); @@ -325,9 +374,10 @@ var PivotTable = instance.web.Widget.extend({ }); if (options.foldable) { - var plus = $('', {'data-row-id':options.row_id, - class:'icon-plus-sign web_graph_click', - href:'#'}); + var attrs = {class:'icon-plus-sign web_graph_click', href:'#'}; + if (options.row_id !== undefined) attrs['data-row-id'] = options.row_id; + if (options.col_id !== undefined) attrs['data-col-id'] = options.col_id; + var plus = $('', attrs); plus.append(' '); plus.append(content); cell.append(plus); @@ -355,7 +405,6 @@ var PivotTable = instance.web.Widget.extend({ _.each(data.reverse(), function (datapt) { var new_row = self.make_row(datapt, row_id); row.html.after(new_row.html); - }); }); @@ -393,6 +442,12 @@ var PivotTable = instance.web.Widget.extend({ row.html.remove(); removeFromArray(this.rows, row); + + _.each(this.cols, function (col) { + col.cells = _.filter(col.cells, function (cell) { + return cell.row_id !== row_id; + }); + }); }, }); -- cgit v1.2.3 From 40ededd5401624b65392c3936e739217e5f5e0a8 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 19 Nov 2013 10:20:53 +0100 Subject: [IMP] preliminary work on supporting col expansion in pivottable widget (addon web_graph) bzr revid: ged@openerp.com-20131119092053-hp1pdgckiplw8mgp --- addons/web_graph/static/src/js/graph.js | 71 +++++++++++++++++---------- addons/web_graph/static/src/xml/web_graph.xml | 11 ++++- 2 files changed, 56 insertions(+), 26 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 949739c7ae1..83b99d63b36 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -158,11 +158,18 @@ var PivotTable = instance.web.Widget.extend({ }, 'click a.field-selection' : function (event) { + var id, + field_id = event.target.attributes['data-field-id'].nodeValue; event.preventDefault(); this.dropdown.remove(); - var row_id = event.target.attributes['data-row-id'].nodeValue; - var field_id = event.target.attributes['data-field-id'].nodeValue; - this.expand_row(row_id, field_id); + if (event.target.attributes['data-row-id'] !== undefined) { + var id = event.target.attributes['data-row-id'].nodeValue; + this.expand_row(id, field_id); + } + if (event.target.attributes['data-col-id'] !== undefined) { + var id = event.target.attributes['data-col-id'].nodeValue; + this.expand_col(id, field_id); + } }, }, @@ -177,26 +184,31 @@ var PivotTable = instance.web.Widget.extend({ var field_to_expand = this.data.row_groupby[row.path.length]; this.expand_row(row_id, field_to_expand); } else { - this.display_dropdown(row_id, $(event.target), event.pageY, event.pageY); + this.display_dropdown({row_id:row_id, + target: $(event.target), + x: event.pageY, + y: event.pageY}); } } }, handle_col_event: function (event) { - console.log("col expand", this.cols); - // var col_id = event.target.attributes['data-col-id'].nodeValue, - // col = this.get_row(col_id); - - // if (col.expanded) { - // this.fold_row(row_id); - // } else { - // if (col.path.length < this.data.col_groupby.length) { - // var field_to_expand = this.data.col_groupby[col.path.length]; - // this.expand_col(col_id, field_to_expand); - // } else { - // this.display_dropdown(col_id, $(event.target), event.pageY, event.pageY); - // } - // } + var col_id = event.target.attributes['data-col-id'].nodeValue, + col = this.get_col(col_id); + + if (col.expanded) { + this.fold_col(col_id); + } else { + if (col.path.length < this.data.col_groupby.length) { + var field_to_expand = this.data.col_groupby[col.path.length]; + this.expand_col(col_id, field_to_expand); + } else { + this.display_dropdown({col_id: col_id, + target: $(event.target), + x: event.pageX, + y: event.pageY}); + } + } }, init: function (data) { @@ -241,21 +253,25 @@ var PivotTable = instance.web.Widget.extend({ this.$el.css('display', 'none'); }, - display_dropdown: function (row_id, target, x, y) { + display_dropdown: function (options) { var self = this, already_grouped = self.data.row_groupby.concat(self.data.col_groupby), possible_groups = _.difference(self.data.important_fields, already_grouped), dropdown_options = { fields: _.map(possible_groups, function (field) { return {id: field, value: self.get_descr(field)}; - }), - row_id: row_id, - }; + })}; + if (options.row_id) { + dropdown_options.row_id= options.row_id; + } else { + dropdown_options.col_id = options.col_id; + } + this.dropdown = $(QWeb.render('field_selection', dropdown_options)); - target.after(this.dropdown); + options.target.after(this.dropdown); this.dropdown.css({position:'absolute', - left:x, - top:y}); + left:options.x, + top:options.y}); $('.field-selection').next('.dropdown-menu').toggle(); }, @@ -271,6 +287,7 @@ var PivotTable = instance.web.Widget.extend({ this.headers = [header]; this.cols= [{ + id: col_id, path: [], value: this.data.measure_label, expanded: false, @@ -410,6 +427,10 @@ var PivotTable = instance.web.Widget.extend({ }, + expand_col: function (col_id, field_id) { + console.log("expandidng col",col_id, field_id); + }, + fold_row: function (row_id) { var self = this; var row = this.get_row(row_id); diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index dbe544d2d2c..8713ff9f6d5 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -31,7 +31,16 @@ -
    -
    +
    -- cgit v1.2.3 From a32018f96237b72ee2ad021987d97539ff433129 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 22 Nov 2013 10:43:22 +0100 Subject: [REF] large refactoring in progress. goal is to separate the data handling code (pivot) from the ui code (drawing, buttons, events (addon web_graph) bzr revid: ged@openerp.com-20131122094322-wn36gtmtv9pgn5su --- addons/web_graph/static/src/js/graph.js | 99 +++++++++++++-------------------- addons/web_graph/static/src/js/pivot.js | 67 ++++++++++++++++------ 2 files changed, 90 insertions(+), 76 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 3363f7cb3a8..7ad283c6810 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -125,87 +125,66 @@ instance.web_graph.GraphView = instance.web.View.extend({ draw_table: function () { this.draw_top_headers(); - _.each(this.pivot_table.rows, this.proxy('draw_row')); + this.pivot_table.iterate(this.pivot_table.rows, this.proxy('draw_row')); }, - draw_top_headers: function () { - var self = this, - pivot = this.pivot_table; + make_border_cell: function (colspan, rowspan) { + return $('').addClass('graph_border') + .attr('colspan', colspan) + .attr('rowspan', rowspan); + }, - function get_column_tree(cols, level) { - var height, - width, - children = _.map(cols[0].children, function (child) { - get_column_tree(child, level - 1); - }); - if (children.length > 0) { - height = 1; - width = _.reduce(children, function (x,y) { return x + y;}, 0); - } else { - height = level; - width = 1; - } - return {level: level, - width: width, - height: height, - col:cols[0], - children: children}; - } + make_header_title: function (header) { + return $(' ') + .addClass('web_graph_click') + .attr('href', '#') + .addClass((header.is_expanded) ? 'icon-minus-sign' : 'icon-plus-sign') + .append(header.name); + }, - function make_cell(elem) { - var title = $(' ') - .addClass('web_graph_click') - .attr('href', '#') - .attr('data-col-id', elem.col.id) - .addClass((elem.col.is_expanded) ? 'icon-minus-sign' : 'icon-plus-sign') - .append(elem.col.name); - return $('').addClass('graph_border') - .append(title) - .attr('rowspan', elem.height) - .attr('colspan', elem.width); + draw_top_headers: function () { + var self = this, + pivot = this.pivot_table, + height = pivot.get_max_path_length(pivot.cols), + header_cells = [[this.make_border_cell(1, height)]]; + + function make_col_header (col) { + var cell = self.make_border_cell(col.width, col.height); + return cell.append(self.make_header_title(col)) + .attr('data-col-id', col.id); } - var height = _.max(_.map(pivot.cols, function(g) {return g.path.length;})); - height = (height === 0) ? 1 : height; - - var col_tree = get_column_tree(pivot.cols, height); - - var header_cells = [[$('') - .attr('rowspan', height) - .addClass('graph_border')]]; - function make_cells (queue, level) { - var tree = queue.shift(); - queue = queue.concat(tree.children); - if (tree.level == level) { - _.last(header_cells).push(make_cell(tree)); + var col = queue.shift(); + queue = queue.concat(col.children); + console.log("col",col, level); + if (col.path.length == level) { + _.last(header_cells).push(make_col_header(col)); } else { - level -=1; - header_cells.push([make_cell(tree)]); + level +=1; + header_cells.push([make_col_header(col)]); } if (queue.length !== 0) { make_cells(queue, level); } } - make_cells([col_tree], height); + if (pivot.cols.children.length === 0) { + make_cells([pivot.cols], 0); + } else { + make_cells(pivot.cols.children, 1); + } + _.each(header_cells, function (cells) { - var row = $("").append(cells); - self.table.append(row); + self.table.append($("").append(cells)); }); }, draw_row: function (row) { var pivot = this.pivot_table, html_row = $(''), - name = $(' ') - .addClass('web_graph_click') - .attr('href', '#') - .attr('data-row-id', row.id) - .addClass((row.is_expanded) ? 'icon-minus-sign' : 'icon-plus-sign') - .append(row.name), row_header = $('') - .append(name) + .append(this.make_header_title(row)) .addClass('graph_border'); for (var i in _.range(row.path.length)) { @@ -214,7 +193,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ html_row.append(row_header); - _.each(pivot.cols, function (col) { + pivot.iterate(pivot.cols, function (col) { var cell = $('').append(pivot.get_value(row.id, col.id)); html_row.append(cell) }); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 3df67e188d8..dca21087ce5 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -2,8 +2,8 @@ var PivotTable = openerp.web.Class.extend({ init: function (options) { - this.rows = []; - this.cols = []; + this.rows = {}; + this.cols = {}; this.cells = []; this.row_groupby = options.row_groupby; this.col_groupby = []; @@ -20,7 +20,7 @@ var PivotTable = openerp.web.Class.extend({ // drawing the table (otherwise the data returned will be empty...) start: function () { var self = this; - var main_row = { + this.rows = { id: this.generate_id(), path: [], name: "Total", @@ -28,10 +28,11 @@ var PivotTable = openerp.web.Class.extend({ parent: null, children: [], domain: this.domain, + height: 1, + width: 1, }; - this.rows.push(main_row); - var main_col = { + this.cols = { id: this.generate_id(), path: [], name: this.measure_label, @@ -39,34 +40,37 @@ var PivotTable = openerp.web.Class.extend({ parent: null, children: [], domain: this.domain, + height: 1, + width: 1, }; - this.cols.push(main_col); // get total and create first cell var tot = query_groups (this.model, this.measure, this.domain, []) .then(function (total) { var val = total[0].attributes.aggregates[self.measure]; - self.set_value(main_row.id, main_col.id, val); + self.set_value(self.rows.id, self.cols.id, val); }); var grp = query_groups (this.model, this.visible_fields(), this.domain, this.row_groupby) .then(function (groups) { _.each(groups, function (group) { - var new_row = { - id: self.generate_id(), + var new_id = self.generate_id(); + self.rows.children.push({ + id: new_id, path: [group.attributes.value[1]], name: group.attributes.value[1], is_expanded: false, - parent: main_row, + parent: self.rows, children: [], domain: group.model._domain, - } - self.rows.push(new_row); - main_row.children.push(new_row.id); - self.set_value(new_row.id, main_col.id, + height: 1, + width: 1, + }); + self.set_value(new_id, self.cols.id, group.attributes.aggregates[self.measure]); }); - main_row.is_expanded = true; + self.rows.is_expanded = true; + self.rows.width = groups.length; }); return $.when(tot, grp); @@ -97,8 +101,39 @@ var PivotTable = openerp.web.Class.extend({ return ((c.row_id == row) && (c.col_id == col)); }); return (cell) ? cell.value : ''; - } + }, + + iterate: function (header, iterator) { + var self = this; + iterator(header); + _.each(header.children, function (child) { + self.iterate(child, iterator); + }); + }, + get_max_path_length: function (header) { + var height = 0; + this.iterate(this.cols, function (col) { + height = Math.max(height, col.path.length); + }); + return height; + }, + + // function set_dim (cols) { + // _.each(cols.children, set_dim); + // if (cols.children.length === 0) { + // cols.height = height - cols.path.length + 1; + // cols.width = 1; + // } else { + // cols.height = 1; + // cols.width = _.reduce(cols.children, function (sum,c) { return sum + c.width;}, 0); + // } + // } + + + // toArray: function (header) { + // return [header].concat(_.map(header.children), this.toArray(hea)) + // } }); -- cgit v1.2.3 From 2c5fb3b2a29aae9a27b957f4db456643c35db746 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 22 Nov 2013 14:59:27 +0100 Subject: [REF] large refactoring in progress. goal is to separate the data handling code (pivot) from the ui code (drawing, buttons, events (addon web_graph) bzr revid: ged@openerp.com-20131122135927-mfaa44juzjhp4kas --- addons/web_graph/static/src/js/graph.js | 101 ++++++++++++-- addons/web_graph/static/src/js/pivot.js | 231 +++++++++++++++++++++++++++++--- 2 files changed, 303 insertions(+), 29 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 7ad283c6810..91c794ea2ae 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -27,7 +27,34 @@ instance.web_graph.GraphView = instance.web.View.extend({ 'click .graph_mode_selection li' : function (event) { event.preventDefault(); this.mode = event.target.attributes['data-mode'].nodeValue; - console.log("change mode",this.mode); + }, + + 'click .web_graph_click' : function (event) { + event.preventDefault(); + if (event.target.attributes['data-row-id'] !== undefined) { + this.handle_header_event({type:'row', event:event}); + + } + if (event.target.attributes['data-col-id'] !== undefined) { + this.handle_header_event({type:'col', event:event}); + } + }, + + 'click a.field-selection' : function (event) { + var id, + field_id = event.target.attributes['data-field-id'].nodeValue; + event.preventDefault(); + this.dropdown.remove(); + if (event.target.attributes['data-row-id'] !== undefined) { + id = event.target.attributes['data-row-id'].nodeValue; + this.pivot_table.expand_row(id, field_id) + .then(this.proxy('draw_table')); + } + if (event.target.attributes['data-col-id'] !== undefined) { + id = event.target.attributes['data-col-id'].nodeValue; + this.pivot_table.expand_col(id, field_id) + .then(this.proxy('draw_table')); + } }, }, @@ -123,9 +150,56 @@ instance.web_graph.GraphView = instance.web.View.extend({ return this._super(); }, + + handle_header_event: function (options) { + var pivot = this.pivot_table, + id = options.event.target.attributes['data-' + options.type + '-id'].nodeValue, + header = pivot['get_' + options.type](id); + + if (header.is_expanded) { + pivot['fold_' + options.type](header); + this.draw_table(); + } else { + if (header.path.length < pivot[options.type + '_groupby'].length) { + // expand the corresponding header + var field = pivot[options.type + '_groupby'][header.path.length]; + pivot['expand_' + options.type](id, field) + .then(this.proxy('draw_table')); + } else { + // display dropdown to query field to expand + this.display_dropdown({id:header.id, + type: options.type, + target: $(event.target), + x: event.pageX, + y: event.pageY}); + } + } + + }, + + display_dropdown: function (options) { + var self = this, + pivot = this.pivot_table, + already_grouped = pivot.row_groupby.concat(pivot.col_groupby), + possible_groups = _.difference(self.data.important_fields, already_grouped), + dropdown_options = { + fields: _.map(possible_groups, function (field) { + return {id: field, value: self.data.fields[field].string}; + })}; + dropdown_options[options.type + '_id'] = options.id; + + this.dropdown = $(QWeb.render('field_selection', dropdown_options)); + options.target.after(this.dropdown); + this.dropdown.css({position:'absolute', + left:options.x, + top:options.y}); + $('.field-selection').next('.dropdown-menu').toggle(); + }, + draw_table: function () { + this.table.empty(); this.draw_top_headers(); - this.pivot_table.iterate(this.pivot_table.rows, this.proxy('draw_row')); + _.each(this.pivot_table.rows_array(), this.proxy('draw_row')); }, make_border_cell: function (colspan, rowspan) { @@ -148,16 +222,25 @@ instance.web_graph.GraphView = instance.web.View.extend({ height = pivot.get_max_path_length(pivot.cols), header_cells = [[this.make_border_cell(1, height)]]; + function set_dim (cols) { + _.each(cols.children, set_dim); + if (cols.children.length === 0) { + cols.height = height - cols.path.length + 1; + cols.width = 1; + } else { + cols.height = 1; + cols.width = _.reduce(cols.children, function (sum,c) { return sum + c.width;}, 0); + } + } + function make_col_header (col) { var cell = self.make_border_cell(col.width, col.height); - return cell.append(self.make_header_title(col)) - .attr('data-col-id', col.id); + return cell.append(self.make_header_title(col).attr('data-col-id', col.id)); } function make_cells (queue, level) { var col = queue.shift(); queue = queue.concat(col.children); - console.log("col",col, level); if (col.path.length == level) { _.last(header_cells).push(make_col_header(col)); } else { @@ -169,6 +252,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ } } + set_dim(pivot.cols); // add width and height info to columns headers + if (pivot.cols.children.length === 0) { make_cells([pivot.cols], 0); } else { @@ -183,8 +268,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ draw_row: function (row) { var pivot = this.pivot_table, html_row = $(''), - row_header = $('') - .append(this.make_header_title(row)) + row_header = this.make_border_cell(1,1) + .append(this.make_header_title(row).attr('data-row-id', row.id)) .addClass('graph_border'); for (var i in _.range(row.path.length)) { @@ -193,7 +278,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ html_row.append(row_header); - pivot.iterate(pivot.cols, function (col) { + _.each(pivot.cols_array(), function (col) { var cell = $('').append(pivot.get_value(row.id, col.id)); html_row.append(cell) }); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index dca21087ce5..9783155848b 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -28,8 +28,6 @@ var PivotTable = openerp.web.Class.extend({ parent: null, children: [], domain: this.domain, - height: 1, - width: 1, }; this.cols = { @@ -40,8 +38,6 @@ var PivotTable = openerp.web.Class.extend({ parent: null, children: [], domain: this.domain, - height: 1, - width: 1, }; // get total and create first cell @@ -63,14 +59,11 @@ var PivotTable = openerp.web.Class.extend({ parent: self.rows, children: [], domain: group.model._domain, - height: 1, - width: 1, }); self.set_value(new_id, self.cols.id, group.attributes.aggregates[self.measure]); }); self.rows.is_expanded = true; - self.rows.width = groups.length; }); return $.when(tot, grp); @@ -111,25 +104,224 @@ var PivotTable = openerp.web.Class.extend({ }); }, + iterate_rows: function (iterator) { + this.iterate(this.rows, iterator); + }, + + iterate_cols: function (iterator) { + this.iterate(this.cols, iterator); + }, + get_max_path_length: function (header) { var height = 0; - this.iterate(this.cols, function (col) { + this.iterate_cols(function (col) { height = Math.max(height, col.path.length); }); return height; }, - // function set_dim (cols) { - // _.each(cols.children, set_dim); - // if (cols.children.length === 0) { - // cols.height = height - cols.path.length + 1; - // cols.width = 1; - // } else { - // cols.height = 1; - // cols.width = _.reduce(cols.children, function (sum,c) { return sum + c.width;}, 0); - // } - // } + rows_array: function () { + var result = []; + this.iterate_rows(function (row) { result.push(row); }); + return result; + }, + + cols_array: function () { + var result = []; + this.iterate_cols(function (col) { result.push(col); }); + return result; + }, + + get_col: function (id) { + return _.find(this.cols_array(), function (col) { return col.id == id;}); + }, + + get_row: function (id) { + return _.find(this.rows_array(), function (row) { return row.id == id;}); + }, + + fold: function (header) { + header.children = []; + header.is_expanded = false; + var fold_lvls = _.map(this.rows_array(), function(g) {return g.path.length;}); + var new_groupby_length = _.max(fold_lvls); + this.row_groupby.splice(new_groupby_length); + + // to do : remove every corresponding cells + }, + + fold_row: function (row) { + this.fold(row); + }, + + fold_col: function (col) { + this.fold(col); + }, + + expand_row: function (row_id, field_id) { + var self = this, + row = this.get_row(row_id); + + if (row.path.length == this.row_groupby.length) { + this.row_groupby.push(field_id); + } + return query_groups_data(this.model, this.visible_fields(), row.domain, this.col_groupby, field_id) + .then(function (groups) { + _.each(groups, function (group) { + var new_row_id = self.make_header(group, row); + var cols_array = self.cols_array(); + _.each(group, function (data) { + var col = _.find(cols_array, function (c) { + return _.isEqual(_.rest(data.path), c.path); + }); + if (col) { + self.set_value(new_row_id, col.id, data.attributes.aggregates[self.measure]); + } + }); + }); + row.is_expanded = true; + }); + }, + + expand_col: function (col_id, field_id) { + var self = this, + col = this.get_col(col_id); + + if (col.path.length == this.col_groupby.length) { + this.col_groupby.push(field_id); + } + + console.log("cols",this.cols_array()); + console.log("dbg",this.col_groupby); + return query_groups_data(this.model, this.visible_fields(), col.domain, this.row_groupby, field_id) + .then(function (groups) { + console.log("groups",groups); + _.each(groups, function (group) { + // console.log("adding group",group); + var new_col_id = self.make_header(group, col); + // // var rows_array = self.rows_array(); + // // _.each(group, function (data) { + // // var row = _.find(rows_array, function (c) { + // // return _.isEqual(data.path.slice(1), c.path); + // // }); + // // if (row) { + // // self.set_value(row.id, new_col_id, data.attributes.aggregates[self.measure]); + // // } + // // }); + }); + // col.is_expanded = true; + // // console.log("col is now",col); + // // console.log("dbg",col.children.length); + }); + + }, + + make_header: function (groups, parent) { + + var new_header = { + id: this.generate_id(), + path: parent.path.concat(groups[0].attributes.value[1]), + name: groups[0].attributes.value[1], + is_expanded: false, + parent: parent.id, + children: [], + domain: groups[0].model._domain, + }; + parent.children.push(new_header); + return new_header.id; + }, + +// make_row: function (groups, parent_id) { +// var self = this, +// path, +// value, +// expanded, +// domain, +// parent, +// has_parent = (parent_id !== undefined), +// row_id = this.generate_id(); + +// if (has_parent) { +// parent = this.get_row(parent_id); +// path = parent.path.concat(groups[0].attributes.value[1]); +// value = groups[0].attributes.value[1]; +// expanded = false; +// parent.children.push(row_id); +// domain = groups[0].model._domain; +// } else { +// parent = null; +// path = []; +// value = 'Total'; +// expanded = true; +// domain = this.data.domain; +// } + +// var jquery_row = $(''); + +// var header = self.make_cell(value, {is_border:true, indent: path.length, foldable:true, row_id: row_id}); +// jquery_row.append(header); + +// var cell; + +// _.each(this.cols, function (col) { +// var element = _.find(groups, function (group) { +// return _.isEqual(_.rest(group.path), col.path); +// }); +// if (element === undefined) { +// cell = self.make_cell(''); +// } else { +// cell = self.make_cell(element.attributes.aggregates[self.data.measure]); +// } +// if (col.expanded) { +// cell.css('display', 'none'); +// } +// col.cells.push({td:cell, row_id:row_id}); +// jquery_row.append(cell); +// }); + +// if (!has_parent) { +// header.find('.icon-plus-sign') +// .removeClass('icon-plus-sign') +// .addClass('icon-minus-sign'); +// } + +// var row = { +// id: row_id, +// path: path, +// value: value, +// expanded: expanded, +// parent: parent_id, +// children: [], +// html: jquery_row, +// domain: domain, +// }; +// this.rows.push(row); // to do, insert it properly, after all childs of parent +// return row; +// }, + +// expand_row: function (row_id, field_id) { +// var self = this; +// var row = this.get_row(row_id); + +// if (row.path.length == this.data.row_groupby.length) { +// this.data.row_groupby.push(field_id); +// } +// row.expanded = true; +// row.html.find('.icon-plus-sign') +// .removeClass('icon-plus-sign') +// .addClass('icon-minus-sign'); + +// var visible_fields = this.data.row_groupby.concat(this.data.col_groupby, this.data.measure); +// query_groups_data(this.data.model, visible_fields, row.domain, this.data.col_groupby, field_id) +// .then(function (groups) { +// _.each(groups.reverse(), function (group) { +// var new_row = self.make_row(group, row_id); +// row.html.after(new_row.html); +// }); +// }); + +// }, // toArray: function (header) { // return [header].concat(_.map(header.children), this.toArray(hea)) @@ -147,9 +339,6 @@ var PivotTable = openerp.web.Class.extend({ // } - // function fold_row (row) { - - // } // function fold_col (col) { -- cgit v1.2.3 From 200762944abc00e5cb748af96583302237c9a669 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 22 Nov 2013 16:10:25 +0100 Subject: [REF] large refactoring in progress. goal is to separate the data handling code (pivot) from the ui code (drawing, buttons, events (addon web_graph) bzr revid: ged@openerp.com-20131122151025-8npxh5g5y2ema4tq --- addons/web_graph/static/src/js/graph.js | 26 +-- addons/web_graph/static/src/js/pivot.js | 283 +++++++++----------------------- 2 files changed, 88 insertions(+), 221 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 91c794ea2ae..7d7d575756c 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -197,9 +197,10 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, draw_table: function () { + console.log("cols",this.pivot_table.cols); this.table.empty(); this.draw_top_headers(); - _.each(this.pivot_table.rows_array(), this.proxy('draw_row')); + _.each(this.pivot_table.rows, this.proxy('draw_row')); }, make_border_cell: function (colspan, rowspan) { @@ -219,7 +220,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ draw_top_headers: function () { var self = this, pivot = this.pivot_table, - height = pivot.get_max_path_length(pivot.cols), + height = _.max(_.map(pivot.cols, function(g) {return g.path.length;})), header_cells = [[this.make_border_cell(1, height)]]; function set_dim (cols) { @@ -239,8 +240,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ } function make_cells (queue, level) { - var col = queue.shift(); - queue = queue.concat(col.children); + var col = queue[0]; + queue = _.rest(queue).concat(col.children); if (col.path.length == level) { _.last(header_cells).push(make_col_header(col)); } else { @@ -252,12 +253,11 @@ instance.web_graph.GraphView = instance.web.View.extend({ } } - set_dim(pivot.cols); // add width and height info to columns headers - - if (pivot.cols.children.length === 0) { - make_cells([pivot.cols], 0); + set_dim(pivot.cols[0]); // add width and height info to columns headers + if (pivot.cols[0].children.length === 0) { + make_cells(pivot.cols, 0); } else { - make_cells(pivot.cols.children, 1); + make_cells(pivot.cols[0].children, 1); } _.each(header_cells, function (cells) { @@ -278,9 +278,11 @@ instance.web_graph.GraphView = instance.web.View.extend({ html_row.append(row_header); - _.each(pivot.cols_array(), function (col) { - var cell = $('').append(pivot.get_value(row.id, col.id)); - html_row.append(cell) + _.each(pivot.cols, function (col) { + if (col.children.length === 0) { + var cell = $('').append(pivot.get_value(row.id, col.id)); + html_row.append(cell); + } }); this.table.append(html_row); } diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 9783155848b..081470fcb37 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -2,8 +2,8 @@ var PivotTable = openerp.web.Class.extend({ init: function (options) { - this.rows = {}; - this.cols = {}; + this.rows = []; + this.cols = []; this.cells = []; this.row_groupby = options.row_groupby; this.col_groupby = []; @@ -11,8 +11,7 @@ var PivotTable = openerp.web.Class.extend({ this.measure = options.measure; this.measure_label = options.measure_label; this.domain = options.domain; - - this.id_seed = -1; + this.id_seed = 0; }, // Load initial data into the rows, cols and cells array. @@ -20,7 +19,7 @@ var PivotTable = openerp.web.Class.extend({ // drawing the table (otherwise the data returned will be empty...) start: function () { var self = this; - this.rows = { + this.rows.push({ id: this.generate_id(), path: [], name: "Total", @@ -28,9 +27,9 @@ var PivotTable = openerp.web.Class.extend({ parent: null, children: [], domain: this.domain, - }; + }); - this.cols = { + this.cols.push({ id: this.generate_id(), path: [], name: this.measure_label, @@ -38,32 +37,35 @@ var PivotTable = openerp.web.Class.extend({ parent: null, children: [], domain: this.domain, - }; + }); // get total and create first cell var tot = query_groups (this.model, this.measure, this.domain, []) .then(function (total) { var val = total[0].attributes.aggregates[self.measure]; - self.set_value(self.rows.id, self.cols.id, val); + self.set_value(self.rows[0].id, self.cols[0].id, val); }); var grp = query_groups (this.model, this.visible_fields(), this.domain, this.row_groupby) .then(function (groups) { _.each(groups, function (group) { - var new_id = self.generate_id(); - self.rows.children.push({ + var new_id = self.generate_id(), + new_row = { id: new_id, path: [group.attributes.value[1]], name: group.attributes.value[1], is_expanded: false, - parent: self.rows, + parent: self.rows[0], children: [], domain: group.model._domain, - }); - self.set_value(new_id, self.cols.id, + }; + + self.rows[0].children.push(new_row); + self.rows.push(new_row); + self.set_value(new_id, self.cols[0].id, group.attributes.aggregates[self.measure]); }); - self.rows.is_expanded = true; + self.rows[0].is_expanded = true; }); return $.when(tot, grp); @@ -96,67 +98,42 @@ var PivotTable = openerp.web.Class.extend({ return (cell) ? cell.value : ''; }, - iterate: function (header, iterator) { - var self = this; - iterator(header); - _.each(header.children, function (child) { - self.iterate(child, iterator); - }); - }, - - iterate_rows: function (iterator) { - this.iterate(this.rows, iterator); - }, - - iterate_cols: function (iterator) { - this.iterate(this.cols, iterator); - }, - - get_max_path_length: function (header) { - var height = 0; - this.iterate_cols(function (col) { - height = Math.max(height, col.path.length); - }); - return height; - }, - - rows_array: function () { - var result = []; - this.iterate_rows(function (row) { result.push(row); }); - return result; - }, - - cols_array: function () { - var result = []; - this.iterate_cols(function (col) { result.push(col); }); - return result; - }, - get_col: function (id) { - return _.find(this.cols_array(), function (col) { return col.id == id;}); + return _.find(this.cols, function (col) { return col.id == id;}); }, get_row: function (id) { - return _.find(this.rows_array(), function (row) { return row.id == id;}); + return _.find(this.rows, function (row) { return row.id == id;}); }, - fold: function (header) { - header.children = []; - header.is_expanded = false; - var fold_lvls = _.map(this.rows_array(), function(g) {return g.path.length;}); + fold_row: function (row) { + var list = []; + function tree_traversal(tree) { + list.push(tree); + _.each(tree.children, tree_traversal); + } + tree_traversal(row); + this.rows = _.difference(this.rows, _.rest(list)); + row.is_expanded = false; + var fold_lvls = _.map(this.rows, function(g) {return g.path.length;}); var new_groupby_length = _.max(fold_lvls); - this.row_groupby.splice(new_groupby_length); - - // to do : remove every corresponding cells - }, - - fold_row: function (row) { - this.fold(row); + row.children = []; }, fold_col: function (col) { - this.fold(col); + var list = []; + function tree_traversal(tree) { + list.push(tree); + _.each(tree.children, tree_traversal); + } + tree_traversal(col); + this.cols = _.difference(this.cols, _.rest(list)); + col.is_expanded = false; + var fold_lvls = _.map(this.cols, function(g) {return g.path.length;}); + var new_groupby_length = _.max(fold_lvls); + this.col_groupby.splice(new_groupby_length); + col.children = []; }, expand_row: function (row_id, field_id) { @@ -169,10 +146,9 @@ var PivotTable = openerp.web.Class.extend({ return query_groups_data(this.model, this.visible_fields(), row.domain, this.col_groupby, field_id) .then(function (groups) { _.each(groups, function (group) { - var new_row_id = self.make_header(group, row); - var cols_array = self.cols_array(); + var new_row_id = self.make_row(group, row); _.each(group, function (data) { - var col = _.find(cols_array, function (c) { + var col = _.find(self.cols, function (c) { return _.isEqual(_.rest(data.path), c.path); }); if (col) { @@ -184,6 +160,21 @@ var PivotTable = openerp.web.Class.extend({ }); }, + make_row: function (groups, parent) { + var new_row = { + id: this.generate_id(), + path: parent.path.concat(groups[0].attributes.value[1]), + name: groups[0].attributes.value[1], + is_expanded: false, + parent: parent.id, + children: [], + domain: groups[0].model._domain, + }; + parent.children.push(new_row); + insertAfter(this.rows, parent, new_row); + return new_row.id; + }, + expand_col: function (col_id, field_id) { var self = this, col = this.get_col(col_id); @@ -192,34 +183,26 @@ var PivotTable = openerp.web.Class.extend({ this.col_groupby.push(field_id); } - console.log("cols",this.cols_array()); - console.log("dbg",this.col_groupby); return query_groups_data(this.model, this.visible_fields(), col.domain, this.row_groupby, field_id) .then(function (groups) { - console.log("groups",groups); _.each(groups, function (group) { - // console.log("adding group",group); - var new_col_id = self.make_header(group, col); - // // var rows_array = self.rows_array(); - // // _.each(group, function (data) { - // // var row = _.find(rows_array, function (c) { - // // return _.isEqual(data.path.slice(1), c.path); - // // }); - // // if (row) { - // // self.set_value(row.id, new_col_id, data.attributes.aggregates[self.measure]); - // // } - // // }); + var new_col_id = self.make_col(group, col); + _.each(group, function (data) { + var row = _.find(self.rows, function (c) { + return _.isEqual(data.path.slice(1), c.path); + }); + if (row) { + self.set_value(row.id, new_col_id, data.attributes.aggregates[self.measure]); + } + }); }); - // col.is_expanded = true; - // // console.log("col is now",col); - // // console.log("dbg",col.children.length); + col.is_expanded = true; }); }, - make_header: function (groups, parent) { - - var new_header = { + make_col: function (groups, parent) { + var new_col = { id: this.generate_id(), path: parent.path.concat(groups[0].attributes.value[1]), name: groups[0].attributes.value[1], @@ -228,129 +211,11 @@ var PivotTable = openerp.web.Class.extend({ children: [], domain: groups[0].model._domain, }; - parent.children.push(new_header); - return new_header.id; + parent.children.push(new_col); + insertAfter(this.cols, parent, new_col); + return new_col.id; }, -// make_row: function (groups, parent_id) { -// var self = this, -// path, -// value, -// expanded, -// domain, -// parent, -// has_parent = (parent_id !== undefined), -// row_id = this.generate_id(); - -// if (has_parent) { -// parent = this.get_row(parent_id); -// path = parent.path.concat(groups[0].attributes.value[1]); -// value = groups[0].attributes.value[1]; -// expanded = false; -// parent.children.push(row_id); -// domain = groups[0].model._domain; -// } else { -// parent = null; -// path = []; -// value = 'Total'; -// expanded = true; -// domain = this.data.domain; -// } - -// var jquery_row = $(''); - -// var header = self.make_cell(value, {is_border:true, indent: path.length, foldable:true, row_id: row_id}); -// jquery_row.append(header); - -// var cell; - -// _.each(this.cols, function (col) { -// var element = _.find(groups, function (group) { -// return _.isEqual(_.rest(group.path), col.path); -// }); -// if (element === undefined) { -// cell = self.make_cell(''); -// } else { -// cell = self.make_cell(element.attributes.aggregates[self.data.measure]); -// } -// if (col.expanded) { -// cell.css('display', 'none'); -// } -// col.cells.push({td:cell, row_id:row_id}); -// jquery_row.append(cell); -// }); - -// if (!has_parent) { -// header.find('.icon-plus-sign') -// .removeClass('icon-plus-sign') -// .addClass('icon-minus-sign'); -// } - -// var row = { -// id: row_id, -// path: path, -// value: value, -// expanded: expanded, -// parent: parent_id, -// children: [], -// html: jquery_row, -// domain: domain, -// }; -// this.rows.push(row); // to do, insert it properly, after all childs of parent -// return row; -// }, - -// expand_row: function (row_id, field_id) { -// var self = this; -// var row = this.get_row(row_id); - -// if (row.path.length == this.data.row_groupby.length) { -// this.data.row_groupby.push(field_id); -// } -// row.expanded = true; -// row.html.find('.icon-plus-sign') -// .removeClass('icon-plus-sign') -// .addClass('icon-minus-sign'); - -// var visible_fields = this.data.row_groupby.concat(this.data.col_groupby, this.data.measure); -// query_groups_data(this.data.model, visible_fields, row.domain, this.data.col_groupby, field_id) -// .then(function (groups) { -// _.each(groups.reverse(), function (group) { -// var new_row = self.make_row(group, row_id); -// row.html.after(new_row.html); -// }); -// }); - -// }, - - // toArray: function (header) { - // return [header].concat(_.map(header.children), this.toArray(hea)) - // } }); - - - // function expand_row (row, field) { - - // } - - // function expand_col (col, field) { - - // } - - - // function fold_col (col) { - - // } - - -// function update_values () { -// // update all cells (reload data from db) -// // return a deferred -// } - -// var id_seed = -1; - -// return init(); -// } \ No newline at end of file -- cgit v1.2.3 From 7299cde4cf2063dbccc797b6612c2b41c3564a8e Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 22 Nov 2013 17:04:49 +0100 Subject: [REF] large refactoring. it separates the data handling code (pivot) from the ui code (drawing, buttons, events (addon web_graph) bzr revid: ged@openerp.com-20131122160449-lv2t09bs67ux42m5 --- addons/web_graph/static/src/js/charts.js | 26 +- addons/web_graph/static/src/js/graph.js | 713 +------------------------------ addons/web_graph/static/src/js/pivot.js | 11 +- 3 files changed, 34 insertions(+), 716 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index f35d012b592..0ecd15d1daf 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -11,14 +11,9 @@ var formatter = function (measure) { var Charts = { - bar_chart : function (groups, measure) { - var formatted_data = [{ - key: 'Bar chart', - values: _.map(groups, formatter(measure)), - }]; - + bar_chart : function (data) { nv.addGraph(function () { - var chart = nv.models.discreteBarChart() + var chart = nv.models.discreteBarChart() .tooltips(false) .showValues(true) .staggerLabels(true) @@ -26,7 +21,7 @@ var Charts = { .height(400); d3.select('.graph_main_content svg') - .datum(formatted_data) + .datum(data) .attr('width', 650) .attr('height', 400) .call(chart); @@ -36,12 +31,7 @@ var Charts = { }); }, - line_chart: function (groups, measure, measure_label) { - var formatted_data = [{ - key: measure_label, - values: _.map(groups, formatter(measure)) - }]; - + line_chart: function (data) { nv.addGraph(function () { var chart = nv.models.lineChart() .x(function (d,u) { return u; }) @@ -52,16 +42,14 @@ var Charts = { d3.select('.graph_main_content svg') .attr('width', 600) .attr('height', 300) - .datum(formatted_data) + .datum(data) .call(chart); return chart; }); }, - pie_chart: function (groups, measure) { - var formatted_data = _.map(groups, formatter(measure)); - + pie_chart: function (data) { nv.addGraph(function () { var chart = nv.models.pieChart() .color(d3.scale.category10().range()) @@ -69,7 +57,7 @@ var Charts = { .height(400); d3.select('.graph_main_content svg') - .datum(formatted_data) + .datum(data[0].values) .transition().duration(1200) .attr('width', 650) .attr('height', 400) diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 7d7d575756c..cfabdead833 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -26,7 +26,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ events: { 'click .graph_mode_selection li' : function (event) { event.preventDefault(); - this.mode = event.target.attributes['data-mode'].nodeValue; + var mode = event.target.attributes['data-mode'].nodeValue; + this.switch_mode(mode); }, 'click .web_graph_click' : function (event) { @@ -125,7 +126,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ start: function () { this.table = $('
    '); - this.svg = $(''); + this.svg = $('
    '); this.$el.filter('.graph_main_content').append(this.table); this.$el.filter('.graph_main_content').append(this.svg); return this.load_view(); @@ -150,6 +151,21 @@ instance.web_graph.GraphView = instance.web.View.extend({ return this._super(); }, + switch_mode: function (mode) { + var self = this; + this.mode = mode; + if (mode === 'pivot') { + this.table.css('display', 'block'); + this.svg.css('display','none'); + } else { + this.table.css('display', 'none'); + this.svg.remove(); + this.svg = $('
    '); + this.$el.filter('.graph_main_content').append(this.svg); + Charts[mode](this.pivot_table.get_chart_data()); + + } + }, handle_header_event: function (options) { var pivot = this.pivot_table, @@ -174,7 +190,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ y: event.pageY}); } } - }, display_dropdown: function (options) { @@ -288,696 +303,4 @@ instance.web_graph.GraphView = instance.web.View.extend({ } }); - - -// make_top_headers : function () { -// var self = this, -// header; - -// function partition (columns) { -// return _.reduce(columns, function (partial, col) { -// if (partial.length === 0) return [[col]]; -// if (col.path.length > _.first(_.last(partial)).path.length) { -// _.last(partial).push(col); -// } else { -// partial.push([col]); -// } -// return partial; -// }, []); -// } - -// function side_by_side(blocks) { -// var result = _.zip.apply(_,blocks); -// result = _.map(result, function(line) {return _.compact(_.flatten(line))}); -// return result; -// } - -// function make_header_cell(col, span) { -// var options = { -// is_border:true, -// foldable:true, -// row_span: (span === undefined) ? 1 : span, -// col_id: col.id, -// }; -// var result = self.make_cell(col.value, options); -// if (col.expanded) { -// result.find('.icon-plus-sign') -// .removeClass('icon-plus-sign') -// .addClass('icon-minus-sign'); -// } -// return result; -// } - -// function calculate_width(cols) { -// if (cols.length === 1) { -// return 1; -// } -// var p = partition(_.rest(cols)); -// return _.reduce(p, function(x, y){ return x + calculate_width(y); }, 0); -// } - -// function make_header_cells(cols, height) { -// var p = partition(cols); -// if ((p.length === 1) && (p[0].length === 1)) { -// var result = [[make_header_cell(cols[0], height)]]; -// return result; -// } -// if ((p.length === 1) && (p[0].length > 1)) { -// var cell = make_header_cell(p[0][0]); -// cell.attr('colspan', calculate_width(cols)); -// return [[cell]].concat(make_header_cells(_.rest(cols), height - 1)); -// } -// if (p.length > 1) { -// return side_by_side(_.map(p, function (group) { -// return make_header_cells(group, height); -// })); -// } -// } - -// if (this.cols.length === 1) { -// header = $(''); -// header.append(this.make_cell('', {is_border:true})); -// header.append(this.make_cell(this.cols[0].value, -// {is_border:true, foldable:true, col_id:this.cols[0].id})); -// header.addClass('graph_top'); -// this.headers = [header]; -// } else { -// var height = _.max(_.map(self.cols, function(g) {return g.path.length;})); -// var header_rows = make_header_cells(_.rest(this.cols), height); - -// header_rows[0].splice(0,0,self.make_cell('', {is_border:true, }).attr('rowspan', height)) -// self.headers = []; -// _.each(header_rows, function (cells) { -// header = $(''); -// header.append(cells); -// header.addClass('graph_top'); -// self.headers.push(header); -// }); -// } -// }, - - - // mode: 'pivot', // pivot, bar_chart, line_chart or pie_chart - // pivot_table: null, - - // events: { - // 'click .graph_mode_selection li' : function (event) { - // event.preventDefault(); - // this.mode = event.target.attributes['data-mode'].nodeValue; - // this.display_data(); - // }, - // }, - - // display_data : function () { - // var content = this.$el.filter('.graph_main_content'); - // content.find('svg').remove(); - // var self = this; - // if (this.mode === 'pivot') { - // this.pivot_table.show(); - // } else { - // this.pivot_table.hide(); - // content.append(''); - // var view_fields = this.data.row_groupby.concat(this.data.measure, this.data.col_groupby); - // query_groups(this.data.model, view_fields, this.data.domain, this.data.row_groupby).then(function (groups) { - // Charts[self.mode](groups, self.data.measure, self.data.measure_label); - // }); - - // } - // }, - - - // if (this.pivot_table) { - // this.pivot_table.draw(true); - // } else { - - // this.pivot_table = new PivotTable(this.data); - // this.pivot_table.appendTo('.graph_main_content'); - // } - // this.display_data(); - - /** - * PivotTable widget. It displays the data in tabular data and allows the - * user to drill down and up in the table - */ -// var PivotTable = instance.web.Widget.extend({ -// template: 'pivot_table', - -// init: function (data) { -// var self = this; -// makePivotTable(this.data).done(function (table) { -// self.pivottable = table; -// }); -// }, - -// }); - -// var PivotTable = instance.web.Widget.extend({ -// template: 'pivot_table', -// data: null, -// headers: [], -// rows: [], -// cols: [], -// id_seed : 0, - -// events: { -// 'click .web_graph_click' : function (event) { -// event.preventDefault(); - -// if (event.target.attributes['data-row-id'] !== undefined) { -// this.handle_row_event(event); -// } -// if (event.target.attributes['data-col-id'] !== undefined) { -// this.handle_col_event(event); -// } -// }, - -// 'click a.field-selection' : function (event) { -// var id, -// field_id = event.target.attributes['data-field-id'].nodeValue; -// event.preventDefault(); -// this.dropdown.remove(); -// if (event.target.attributes['data-row-id'] !== undefined) { -// id = event.target.attributes['data-row-id'].nodeValue; -// this.expand_row(id, field_id); -// } -// if (event.target.attributes['data-col-id'] !== undefined) { -// id = event.target.attributes['data-col-id'].nodeValue; -// this.expand_col(id, field_id); -// } -// }, -// }, - -// handle_row_event: function (event) { -// var row_id = event.target.attributes['data-row-id'].nodeValue, -// row = this.get_row(row_id); - -// if (row.expanded) { -// this.fold_row(row_id); -// } else { -// if (row.path.length < this.data.row_groupby.length) { -// var field_to_expand = this.data.row_groupby[row.path.length]; -// this.expand_row(row_id, field_to_expand); -// } else { -// this.display_dropdown({row_id:row_id, -// target: $(event.target), -// x: event.pageX, -// y: event.pageY}); -// } -// } -// }, - -// handle_col_event: function (event) { -// var col_id = event.target.attributes['data-col-id'].nodeValue, -// col = this.get_col(col_id); - -// if (col.expanded) { -// this.fold_col(col_id); -// } else { -// if (col.path.length < this.data.col_groupby.length) { -// var field_to_expand = this.data.col_groupby[col.path.length]; -// this.expand_col(col_id, field_to_expand); -// } else { -// this.display_dropdown({col_id: col_id, -// target: $(event.target), -// x: event.pageX, -// y: event.pageY}); -// } -// } -// }, - -// init: function (data) { -// this.data = data; -// makePivotTable(this.data).done(function (table) { -// self.pivottable = table; -// }); - -// }, - -// start: function () { -// this.draw(true); -// }, - -// draw: function (load_data) { -// var self = this; - -// if (load_data) { -// var view_fields = this.data.row_groupby.concat(this.data.measure, this.data.col_groupby); -// query_groups_data(this.data.model, view_fields, this.data.domain, this.data.col_groupby, this.data.row_groupby[0]) -// .then(function (groups) { -// self.data.groups = groups; -// return self.get_groups([]); -// }).then(function (total) { -// total[0].path = []; -// self.data.total = [total]; -// self.build_table(); -// self.draw(false); -// }); -// } else { -// this.$el.empty(); - -// this.draw_top_headers(); - -// _.each(this.rows, function (row) { -// self.$el.append(row.html); -// }); -// } -// }, - -// show: function () { -// this.$el.css('display', 'block'); -// }, - -// hide: function () { -// this.$el.css('display', 'none'); -// }, - -// display_dropdown: function (options) { -// var self = this, -// already_grouped = self.data.row_groupby.concat(self.data.col_groupby), -// possible_groups = _.difference(self.data.important_fields, already_grouped), -// dropdown_options = { -// fields: _.map(possible_groups, function (field) { -// return {id: field, value: self.get_descr(field)}; -// })}; -// if (options.row_id) { -// dropdown_options.row_id= options.row_id; -// } else { -// dropdown_options.col_id = options.col_id; -// } - -// this.dropdown = $(QWeb.render('field_selection', dropdown_options)); -// options.target.after(this.dropdown); -// this.dropdown.css({position:'absolute', -// left:options.x, -// top:options.y}); -// $('.field-selection').next('.dropdown-menu').toggle(); -// }, - -// build_table: function () { -// var self = this; -// this.rows = []; - - -// var col_id = this.generate_id(); - -// this.cols= [{ -// id: col_id, -// path: [], -// value: this.data.measure_label, -// expanded: false, -// parent: null, -// children: [], -// cells: [], // a cell is {td:, row_id:} -// domain: this.data.domain, -// }]; - -// self.make_top_headers(); - -// var main_row = this.make_row(this.data.total[0]); - -// _.each(this.data.groups, function (group) { -// self.make_row(group, main_row.id); -// }); -// }, - -// get_descr: function (field_id) { -// return this.data.fields[field_id].string; -// }, - -// get_groups: function (groupby) { -// var view_fields = this.data.row_groupby.concat(this.data.measure, this.data.col_groupby); -// return query_groups(this.data.model, view_fields, this.data.domain, groupby); -// }, - -// make_top_headers : function () { -// var self = this, -// header; - -// function partition (columns) { -// return _.reduce(columns, function (partial, col) { -// if (partial.length === 0) return [[col]]; -// if (col.path.length > _.first(_.last(partial)).path.length) { -// _.last(partial).push(col); -// } else { -// partial.push([col]); -// } -// return partial; -// }, []); -// } - -// function side_by_side(blocks) { -// var result = _.zip.apply(_,blocks); -// result = _.map(result, function(line) {return _.compact(_.flatten(line))}); -// return result; -// } - -// function make_header_cell(col, span) { -// var options = { -// is_border:true, -// foldable:true, -// row_span: (span === undefined) ? 1 : span, -// col_id: col.id, -// }; -// var result = self.make_cell(col.value, options); -// if (col.expanded) { -// result.find('.icon-plus-sign') -// .removeClass('icon-plus-sign') -// .addClass('icon-minus-sign'); -// } -// return result; -// } - -// function calculate_width(cols) { -// if (cols.length === 1) { -// return 1; -// } -// var p = partition(_.rest(cols)); -// return _.reduce(p, function(x, y){ return x + calculate_width(y); }, 0); -// } - -// function make_header_cells(cols, height) { -// var p = partition(cols); -// if ((p.length === 1) && (p[0].length === 1)) { -// var result = [[make_header_cell(cols[0], height)]]; -// return result; -// } -// if ((p.length === 1) && (p[0].length > 1)) { -// var cell = make_header_cell(p[0][0]); -// cell.attr('colspan', calculate_width(cols)); -// return [[cell]].concat(make_header_cells(_.rest(cols), height - 1)); -// } -// if (p.length > 1) { -// return side_by_side(_.map(p, function (group) { -// return make_header_cells(group, height); -// })); -// } -// } - -// if (this.cols.length === 1) { -// header = $(''); -// header.append(this.make_cell('', {is_border:true})); -// header.append(this.make_cell(this.cols[0].value, -// {is_border:true, foldable:true, col_id:this.cols[0].id})); -// header.addClass('graph_top'); -// this.headers = [header]; -// } else { -// var height = _.max(_.map(self.cols, function(g) {return g.path.length;})); -// var header_rows = make_header_cells(_.rest(this.cols), height); - -// header_rows[0].splice(0,0,self.make_cell('', {is_border:true, }).attr('rowspan', height)) -// self.headers = []; -// _.each(header_rows, function (cells) { -// header = $(''); -// header.append(cells); -// header.addClass('graph_top'); -// self.headers.push(header); -// }); -// } -// }, - -// draw_top_headers: function () { -// var self = this; -// $("tr.graph_top").remove(); -// _.each(this.headers.reverse(), function (header) { -// self.$el.prepend(header); -// }); - -// }, - -// make_row: function (groups, parent_id) { -// var self = this, -// path, -// value, -// expanded, -// domain, -// parent, -// has_parent = (parent_id !== undefined), -// row_id = this.generate_id(); - -// if (has_parent) { -// parent = this.get_row(parent_id); -// path = parent.path.concat(groups[0].attributes.value[1]); -// value = groups[0].attributes.value[1]; -// expanded = false; -// parent.children.push(row_id); -// domain = groups[0].model._domain; -// } else { -// parent = null; -// path = []; -// value = 'Total'; -// expanded = true; -// domain = this.data.domain; -// } - -// var jquery_row = $(''); - -// var header = self.make_cell(value, {is_border:true, indent: path.length, foldable:true, row_id: row_id}); -// jquery_row.append(header); - -// var cell; - -// _.each(this.cols, function (col) { -// var element = _.find(groups, function (group) { -// return _.isEqual(_.rest(group.path), col.path); -// }); -// if (element === undefined) { -// cell = self.make_cell(''); -// } else { -// cell = self.make_cell(element.attributes.aggregates[self.data.measure]); -// } -// if (col.expanded) { -// cell.css('display', 'none'); -// } -// col.cells.push({td:cell, row_id:row_id}); -// jquery_row.append(cell); -// }); - -// if (!has_parent) { -// header.find('.icon-plus-sign') -// .removeClass('icon-plus-sign') -// .addClass('icon-minus-sign'); -// } - -// var row = { -// id: row_id, -// path: path, -// value: value, -// expanded: expanded, -// parent: parent_id, -// children: [], -// html: jquery_row, -// domain: domain, -// }; -// this.rows.push(row); // to do, insert it properly, after all childs of parent -// return row; -// }, - -// generate_id: function () { -// this.id_seed += 1; -// return this.id_seed - 1; -// }, - -// get_row: function (id) { -// return _.find(this.rows, function(row) { -// return (row.id == id); -// }); -// }, - -// get_col: function (id) { -// return _.find(this.cols, function(col) { -// return (col.id == id); -// }); -// }, - -// make_cell: function (content, options) { -// options = _.extend({is_border: false, indent:0, foldable:false}, options); -// content = (content !== undefined) ? content : 'Undefined'; - -// var cell = $(''); -// if (options.is_border) cell.addClass('graph_border'); -// if (options.row_span) cell.attr('rowspan', options.row_span); -// if (options.col_span) cell.attr('rowspan', options.col_span); -// _.each(_.range(options.indent), function () { -// cell.prepend($('', {class:'web_graph_indent'})); -// }); - -// if (options.foldable) { -// var attrs = {class:'icon-plus-sign web_graph_click', href:'#'}; -// if (options.row_id !== undefined) attrs['data-row-id'] = options.row_id; -// if (options.col_id !== undefined) attrs['data-col-id'] = options.col_id; -// var plus = $('', attrs); -// plus.append(' '); -// plus.append(content); -// cell.append(plus); -// } else { -// cell.append(content); -// } -// return cell; -// }, - -// expand_row: function (row_id, field_id) { -// var self = this; -// var row = this.get_row(row_id); - -// if (row.path.length == this.data.row_groupby.length) { -// this.data.row_groupby.push(field_id); -// } -// row.expanded = true; -// row.html.find('.icon-plus-sign') -// .removeClass('icon-plus-sign') -// .addClass('icon-minus-sign'); - -// var visible_fields = this.data.row_groupby.concat(this.data.col_groupby, this.data.measure); -// query_groups_data(this.data.model, visible_fields, row.domain, this.data.col_groupby, field_id) -// .then(function (groups) { -// _.each(groups.reverse(), function (group) { -// var new_row = self.make_row(group, row_id); -// row.html.after(new_row.html); -// }); -// }); - -// }, - -// expand_col: function (col_id, field_id) { -// var self = this; -// var col = this.get_col(col_id); - -// if (col.path.length == this.data.col_groupby.length) { -// this.data.col_groupby.push(field_id); -// } -// col.expanded = true; - -// var visible_fields = this.data.row_groupby.concat(this.data.col_groupby, this.data.measure); -// query_groups_data(this.data.model, visible_fields, col.domain, this.data.row_groupby, field_id) -// .then(function (groups) { -// _.each(groups, function (group) { -// var new_col = { -// id: self.generate_id(), -// path: col.path.concat(group[0].attributes.value[1]), -// value: group[0].attributes.value[1], -// expanded: false, -// parent: col_id, -// children: [], -// cells: [], // a cell is {td:, row_id:} -// domain: group[0].model._domain, -// }; -// col.children.push(new_col.id); -// insertAfter(self.cols, col, new_col) -// _.each(col.cells, function (cell) { -// var col_path = self.get_row(cell.row_id).path; - -// var datapt = _.find(group, function (g) { -// return _.isEqual(g.path.slice(1), col_path); -// }); - -// var value; -// if (datapt === undefined) { -// value = ''; -// } else { -// value = datapt.attributes.aggregates[self.data.measure]; -// } -// var new_cell = { -// row_id: cell.row_id, -// td: self.make_cell(value) -// }; -// new_col.cells.push(new_cell); -// cell.td.after(new_cell.td); -// cell.td.css('display','none'); -// }); - -// }); -// self.make_top_headers(); -// self.draw_top_headers(); -// }); -// }, - -// fold_row: function (row_id) { -// var self = this; -// var row = this.get_row(row_id); - -// _.each(row.children, function (child_row) { -// self.remove_row(child_row); -// }); -// row.children = []; - -// row.expanded = false; -// row.html.find('.icon-minus-sign') -// .removeClass('icon-minus-sign') -// .addClass('icon-plus-sign'); - -// var fold_levels = _.map(self.rows, function(g) {return g.path.length;}); -// var new_groupby_length = _.max(fold_levels); - -// this.data.row_groupby.splice(new_groupby_length); -// }, - -// remove_row: function (row_id) { -// var self = this; -// var row = this.get_row(row_id); - -// _.each(row.children, function (child_row) { -// self.remove_row(child_row); -// }); - -// row.html.remove(); -// removeFromArray(this.rows, row); - -// _.each(this.cols, function (col) { -// col.cells = _.filter(col.cells, function (cell) { -// return cell.row_id !== row_id; -// }); -// }); -// }, - -// fold_col: function (col_id) { -// var self = this; -// var col = this.get_col(col_id); - -// _.each(col.children, function (child_col) { -// self.remove_col(child_col); -// }); -// col.children = []; - -// _.each(col.cells, function (cell) { -// cell.td.css('display','table-cell'); -// }); -// col.expanded = false; -// // row.html.find('.icon-minus-sign') -// // .removeClass('icon-minus-sign') -// // .addClass('icon-plus-sign'); - -// var fold_levels = _.map(self.cols, function(g) {return g.path.length;}); -// var new_groupby_length = _.max(fold_levels); - -// this.data.col_groupby.splice(new_groupby_length); -// this.make_top_headers(); -// this.draw_top_headers(); - - -// }, - -// remove_col: function (col_id) { -// var self = this; -// var col = this.get_col(col_id); - -// _.each(col.children, function (child_col) { -// self.remove_col(child_col); -// }); - -// _.each(col.cells, function (cell) { -// cell.td.remove(); -// }); -// // row.html.remove(); -// removeFromArray(this.cols, col); - -// // _.each(this.cols, function (col) { -// // col.cells = _.filter(col.cells, function (cell) { -// // return cell.row_id !== row_id; -// // }); -// // }); -// }, - - -// }); - }; diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 081470fcb37..4ab6b637422 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -1,5 +1,4 @@ - var PivotTable = openerp.web.Class.extend({ init: function (options) { this.rows = []; @@ -198,7 +197,6 @@ var PivotTable = openerp.web.Class.extend({ }); col.is_expanded = true; }); - }, make_col: function (groups, parent) { @@ -216,6 +214,15 @@ var PivotTable = openerp.web.Class.extend({ return new_col.id; }, + get_chart_data: function () { + var self = this; + var values = _.map(this.rows[0].children, function (pt) { + var val = self.get_value(pt.id, 2); + return {x: pt.name, y: val}; + }); + return [{key: 'Bar chart', values: values}]; + + }, }); -- cgit v1.2.3 From 1e32b763f0e1da669d835b02fbf680f2deea0f65 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Sat, 23 Nov 2013 11:11:35 +0100 Subject: [IMP] add 'clear all groups' and 'swap axis' functionality to pivot table in addon web_graph bzr revid: ged@openerp.com-20131123101135-m0cx5eg0o41k7x2m --- addons/web_graph/static/src/js/graph.js | 11 +++- addons/web_graph/static/src/js/pivot.js | 75 +++++++++++---------------- addons/web_graph/static/src/xml/web_graph.xml | 2 + 3 files changed, 42 insertions(+), 46 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index cfabdead833..da3f4257b33 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -57,6 +57,16 @@ instance.web_graph.GraphView = instance.web.View.extend({ .then(this.proxy('draw_table')); } }, + + 'click label.graph_swap_axis' : function (event) { + this.pivot_table.swap_axis(); + this.draw_table(); + }, + + 'click label.graph_clear_all' : function (event) { + this.pivot_table.clear_all(); + this.draw_table(); + }, }, view_loading: function (fields_view_get) { @@ -212,7 +222,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, draw_table: function () { - console.log("cols",this.pivot_table.cols); this.table.empty(); this.draw_top_headers(); _.each(this.pivot_table.rows, this.proxy('draw_row')); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 4ab6b637422..288bd14436e 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -45,29 +45,9 @@ var PivotTable = openerp.web.Class.extend({ self.set_value(self.rows[0].id, self.cols[0].id, val); }); - var grp = query_groups (this.model, this.visible_fields(), this.domain, this.row_groupby) - .then(function (groups) { - _.each(groups, function (group) { - var new_id = self.generate_id(), - new_row = { - id: new_id, - path: [group.attributes.value[1]], - name: group.attributes.value[1], - is_expanded: false, - parent: self.rows[0], - children: [], - domain: group.model._domain, - }; - - self.rows[0].children.push(new_row); - self.rows.push(new_row); - self.set_value(new_id, self.cols[0].id, - group.attributes.aggregates[self.measure]); - }); - self.rows[0].is_expanded = true; - }); + var initial_group = this.expand_row(this.rows[0].id, this.row_groupby[0]); - return $.when(tot, grp); + return $.when(tot, initial_group); }, generate_id: function () { @@ -144,8 +124,8 @@ var PivotTable = openerp.web.Class.extend({ } return query_groups_data(this.model, this.visible_fields(), row.domain, this.col_groupby, field_id) .then(function (groups) { - _.each(groups, function (group) { - var new_row_id = self.make_row(group, row); + _.each(groups.reverse(), function (group) { + var new_row_id = self.make_header(group, row, self.rows); _.each(group, function (data) { var col = _.find(self.cols, function (c) { return _.isEqual(_.rest(data.path), c.path); @@ -159,8 +139,8 @@ var PivotTable = openerp.web.Class.extend({ }); }, - make_row: function (groups, parent) { - var new_row = { + make_header: function (groups, parent, header_list) { + var new_header = { id: this.generate_id(), path: parent.path.concat(groups[0].attributes.value[1]), name: groups[0].attributes.value[1], @@ -169,9 +149,9 @@ var PivotTable = openerp.web.Class.extend({ children: [], domain: groups[0].model._domain, }; - parent.children.push(new_row); - insertAfter(this.rows, parent, new_row); - return new_row.id; + parent.children.push(new_header); + insertAfter(header_list, parent, new_header); + return new_header.id; }, expand_col: function (col_id, field_id) { @@ -185,7 +165,7 @@ var PivotTable = openerp.web.Class.extend({ return query_groups_data(this.model, this.visible_fields(), col.domain, this.row_groupby, field_id) .then(function (groups) { _.each(groups, function (group) { - var new_col_id = self.make_col(group, col); + var new_col_id = self.make_header(group, col, self.cols); _.each(group, function (data) { var row = _.find(self.rows, function (c) { return _.isEqual(data.path.slice(1), c.path); @@ -199,21 +179,6 @@ var PivotTable = openerp.web.Class.extend({ }); }, - make_col: function (groups, parent) { - var new_col = { - id: this.generate_id(), - path: parent.path.concat(groups[0].attributes.value[1]), - name: groups[0].attributes.value[1], - is_expanded: false, - parent: parent.id, - children: [], - domain: groups[0].model._domain, - }; - parent.children.push(new_col); - insertAfter(this.cols, parent, new_col); - return new_col.id; - }, - get_chart_data: function () { var self = this; var values = _.map(this.rows[0].children, function (pt) { @@ -224,5 +189,25 @@ var PivotTable = openerp.web.Class.extend({ }, + swap_axis: function () { + var temp = this.rows; + this.rows = this.cols; + this.cols = temp; + + temp = this.row_groupby; + this.row_groupby = this.col_groupby; + this.col_groupby = temp; + + _.each(this.cells, function (cell) { + temp = cell.row_id; + cell.row_id = cell.col_id; + cell.col_id = temp; + }); + }, + + clear_all: function () { + this.fold_row(this.rows[0]); + this.fold_col(this.cols[0]); + } }); diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 5f5c002d7b4..d6d18b208ed 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -11,6 +11,8 @@
  • Line Chart
  • Pie chart
  • + +
    -- cgit v1.2.3 From ebf46e668d6f0ae9695eb693b8ffb6b1498ba6c4 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Sat, 23 Nov 2013 11:19:22 +0100 Subject: [REF] moves the data formatting for charts to the charts file (instead of pivot) in addon web_graph bzr revid: ged@openerp.com-20131123101922-xi429dmnwpqlfsiq --- addons/web_graph/static/src/js/charts.js | 27 +++++++++++++-------------- addons/web_graph/static/src/js/graph.js | 2 +- addons/web_graph/static/src/js/pivot.js | 10 ---------- 3 files changed, 14 insertions(+), 25 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index 0ecd15d1daf..2fb0cd7b380 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -1,17 +1,16 @@ -var formatter = function (measure) { - return function (datapt) { - var val = datapt.attributes; - return { - x: datapt.attributes.value[1], - y: measure ? val.aggregates[measure] : val.length, - }; - }; -}; +function format_chart_data (pivot) { + var values = _.map(pivot.rows[0].children.reverse(), function (pt) { + var val = pivot.get_value(pt.id, 2); + return {x: pt.name, y: val}; + }); + return [{key: 'Bar chart', values: values}]; +}; var Charts = { - bar_chart : function (data) { + bar_chart : function (pivot) { + var data = format_chart_data(pivot); nv.addGraph(function () { var chart = nv.models.discreteBarChart() .tooltips(false) @@ -31,7 +30,8 @@ var Charts = { }); }, - line_chart: function (data) { + line_chart: function (pivot) { + data = format_chart_data(pivot); nv.addGraph(function () { var chart = nv.models.lineChart() .x(function (d,u) { return u; }) @@ -49,7 +49,8 @@ var Charts = { }); }, - pie_chart: function (data) { + pie_chart: function (pivot) { + data = format_chart_data(pivot); nv.addGraph(function () { var chart = nv.models.pieChart() .color(d3.scale.category10().range()) @@ -67,6 +68,4 @@ var Charts = { return chart; }); }, - - }; \ No newline at end of file diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index da3f4257b33..4d74ad71121 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -172,7 +172,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.svg.remove(); this.svg = $('
    '); this.$el.filter('.graph_main_content').append(this.svg); - Charts[mode](this.pivot_table.get_chart_data()); + Charts[mode](this.pivot_table); } }, diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 288bd14436e..a5a3af78ae9 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -179,16 +179,6 @@ var PivotTable = openerp.web.Class.extend({ }); }, - get_chart_data: function () { - var self = this; - var values = _.map(this.rows[0].children, function (pt) { - var val = self.get_value(pt.id, 2); - return {x: pt.name, y: val}; - }); - return [{key: 'Bar chart', values: values}]; - - }, - swap_axis: function () { var temp = this.rows; this.rows = this.cols; -- cgit v1.2.3 From 0f995a25d5bb467dfb309a9f197a1f7e962b2445 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Sat, 23 Nov 2013 11:59:25 +0100 Subject: [REF] moves utility functions to pivot.js file and remove utility.js in addon web_graph bzr revid: ged@openerp.com-20131123105925-edix9lyw9k6tjlmw --- addons/web_graph/static/src/js/pivot.js | 59 +++++++++++++++++++++++++++++++ addons/web_graph/static/src/js/utility.js | 58 ------------------------------ 2 files changed, 59 insertions(+), 58 deletions(-) delete mode 100644 addons/web_graph/static/src/js/utility.js (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index a5a3af78ae9..e42f8f272ff 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -201,3 +201,62 @@ var PivotTable = openerp.web.Class.extend({ } }); + +function removeFromArray(array, element) { + var index = array.indexOf(element); + if (index > -1) { + array.splice(index, 1); + } +} + +function insertAfter(array, after, elem) { + array.splice(array.indexOf(after) + 1, 0, elem); +} + +/** + * Query the server and return a deferred which will return the data + * with all the groupbys applied (this is done for now, but the goal + * is to modify read_group in order to allow eager and lazy groupbys + */ +function query_groups (model, fields, domain, groupbys) { + return model.query(fields) + .filter(domain) + .group_by(groupbys) + .then(function (results) { + var non_empty_results = _.filter(results, function (group) { + return group.attributes.length > 0; + }); + if (groupbys.length <= 1) { + return non_empty_results; + } else { + var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) { + var new_domain = result.model._domain; + var new_groupings = groupbys.slice(1); + return query_groups(model, fields,new_domain, new_groupings).then(function (subgroups) { + result.subgroups_data = subgroups; + }); + })); + return get_subgroups.then(function () { + return non_empty_results; + }); + } + }); +} + +function query_groups_data(model, fields, domain, row_groupbys, col_groupby) { + return query_groups(model, fields, domain, [col_groupby].concat(row_groupbys)).then(function (groups) { + return _.map(groups, function (group) { + return format_group(group, []); + }); + }); +} + +function format_group (group, path) { + group.path = path.concat(group.attributes.value[1]); + result = [group]; + _.each(group.subgroups_data, function (subgroup) { + result = result.concat(format_group (subgroup, group.path)); + }); + return result; +} + diff --git a/addons/web_graph/static/src/js/utility.js b/addons/web_graph/static/src/js/utility.js deleted file mode 100644 index bb0f6a9835d..00000000000 --- a/addons/web_graph/static/src/js/utility.js +++ /dev/null @@ -1,58 +0,0 @@ - -function removeFromArray(array, element) { - var index = array.indexOf(element); - if (index > -1) { - array.splice(index, 1); - } -} - -function insertAfter(array, after, elem) { - array.splice(array.indexOf(after) + 1, 0, elem); -} - -/** - * Query the server and return a deferred which will return the data - * with all the groupbys applied (this is done for now, but the goal - * is to modify read_group in order to allow eager and lazy groupbys - */ -function query_groups (model, fields, domain, groupbys) { - return model.query(fields) - .filter(domain) - .group_by(groupbys) - .then(function (results) { - var non_empty_results = _.filter(results, function (group) { - return group.attributes.length > 0; - }); - if (groupbys.length <= 1) { - return non_empty_results; - } else { - var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) { - var new_domain = result.model._domain; - var new_groupings = groupbys.slice(1); - return query_groups(model, fields,new_domain, new_groupings).then(function (subgroups) { - result.subgroups_data = subgroups; - }); - })); - return get_subgroups.then(function () { - return non_empty_results; - }); - } - }); -} - -function query_groups_data(model, fields, domain, row_groupbys, col_groupby) { - return query_groups(model, fields, domain, [col_groupby].concat(row_groupbys)).then(function (groups) { - return _.map(groups, function (group) { - return format_group(group, []); - }); - }); -} - -function format_group (group, path) { - group.path = path.concat(group.attributes.value[1]); - result = [group]; - _.each(group.subgroups_data, function (subgroup) { - result = result.concat(format_group (subgroup, group.path)); - }); - return result; -} \ No newline at end of file -- cgit v1.2.3 From 42e38292b8ba13f54349203a16e9b61e33ebfe7b Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Sat, 23 Nov 2013 12:42:01 +0100 Subject: [REF] slight modifications to the underlying data structure of pivot table in addon web_graph bzr revid: ged@openerp.com-20131123114201-g6v6q9r15n9gdzg2 --- addons/web_graph/static/src/js/charts.js | 2 +- addons/web_graph/static/src/js/graph.js | 20 +++--- addons/web_graph/static/src/js/pivot.js | 117 ++++++++++++++++--------------- 3 files changed, 70 insertions(+), 69 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index 2fb0cd7b380..036299ebdfd 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -1,6 +1,6 @@ function format_chart_data (pivot) { - var values = _.map(pivot.rows[0].children.reverse(), function (pt) { + var values = _.map(pivot.rows.headers[0].children.reverse(), function (pt) { var val = pivot.get_value(pt.id, 2); return {x: pt.name, y: val}; }); diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 4d74ad71121..cd6cb44f93c 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -186,9 +186,9 @@ instance.web_graph.GraphView = instance.web.View.extend({ pivot['fold_' + options.type](header); this.draw_table(); } else { - if (header.path.length < pivot[options.type + '_groupby'].length) { + if (header.path.length < pivot[options.type + 's'].groupby.length) { // expand the corresponding header - var field = pivot[options.type + '_groupby'][header.path.length]; + var field = pivot[options.type + 's'].groupby[header.path.length]; pivot['expand_' + options.type](id, field) .then(this.proxy('draw_table')); } else { @@ -205,7 +205,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ display_dropdown: function (options) { var self = this, pivot = this.pivot_table, - already_grouped = pivot.row_groupby.concat(pivot.col_groupby), + already_grouped = pivot.rows.groupby.concat(pivot.cols.groupby), possible_groups = _.difference(self.data.important_fields, already_grouped), dropdown_options = { fields: _.map(possible_groups, function (field) { @@ -224,7 +224,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ draw_table: function () { this.table.empty(); this.draw_top_headers(); - _.each(this.pivot_table.rows, this.proxy('draw_row')); + _.each(this.pivot_table.rows.headers, this.proxy('draw_row')); }, make_border_cell: function (colspan, rowspan) { @@ -244,7 +244,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ draw_top_headers: function () { var self = this, pivot = this.pivot_table, - height = _.max(_.map(pivot.cols, function(g) {return g.path.length;})), + height = _.max(_.map(pivot.cols.headers, function(g) {return g.path.length;})), header_cells = [[this.make_border_cell(1, height)]]; function set_dim (cols) { @@ -277,11 +277,11 @@ instance.web_graph.GraphView = instance.web.View.extend({ } } - set_dim(pivot.cols[0]); // add width and height info to columns headers - if (pivot.cols[0].children.length === 0) { - make_cells(pivot.cols, 0); + set_dim(pivot.cols.main); // add width and height info to columns headers + if (pivot.cols.main.children.length === 0) { + make_cells(pivot.cols.headers, 0); } else { - make_cells(pivot.cols[0].children, 1); + make_cells(pivot.cols.main.children, 1); } _.each(header_cells, function (cells) { @@ -302,7 +302,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ html_row.append(row_header); - _.each(pivot.cols, function (col) { + _.each(pivot.cols.headers, function (col) { if (col.children.length === 0) { var cell = $('').append(pivot.get_value(row.id, col.id)); html_row.append(cell); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index e42f8f272ff..a4f8ad5246a 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -1,53 +1,58 @@ var PivotTable = openerp.web.Class.extend({ - init: function (options) { - this.rows = []; - this.cols = []; - this.cells = []; - this.row_groupby = options.row_groupby; - this.col_groupby = []; - this.model = options.model; - this.measure = options.measure; - this.measure_label = options.measure_label; - this.domain = options.domain; - this.id_seed = 0; - }, + id_seed: 0, - // Load initial data into the rows, cols and cells array. - // This function needs to be called after init and before - // drawing the table (otherwise the data returned will be empty...) - start: function () { - var self = this; - this.rows.push({ + init: function (options) { + main_row = { id: this.generate_id(), path: [], name: "Total", is_expanded: false, parent: null, children: [], - domain: this.domain, - }); - - this.cols.push({ + domain: options.domain, + }; + main_col = { id: this.generate_id(), path: [], - name: this.measure_label, + name: options.measure_label, is_expanded: false, parent: null, children: [], - domain: this.domain, - }); + domain: options.domain, + }; - // get total and create first cell - var tot = query_groups (this.model, this.measure, this.domain, []) - .then(function (total) { - var val = total[0].attributes.aggregates[self.measure]; - self.set_value(self.rows[0].id, self.cols[0].id, val); - }); + this.rows = { + groupby: options.row_groupby, + main: main_row, + headers: [main_row], + }; + this.cols = { + groupby: [], + main: main_col, + headers: [main_col], + }; - var initial_group = this.expand_row(this.rows[0].id, this.row_groupby[0]); + this.cells = []; + this.model = options.model; + this.domain = options.domain; + this.measure = options.measure; + this.measure_label = options.measure_label; + }, - return $.when(tot, initial_group); + // Load initial data into the rows, cols and cells array. + // This function needs to be called after init and before + // drawing the table (otherwise the data returned will be empty...) + start: function () { + var self = this, + initial_group = this.expand_row(this.rows.main.id, this.rows.groupby[0]), + total = query_groups(this.model, this.measure, this.domain, []) + .then(function (total) { + var val = total[0].attributes.aggregates[self.measure]; + self.set_value(self.rows.main.id, self.cols.main.id, val); + }); + + return $.when(total, initial_group); }, generate_id: function () { @@ -56,7 +61,7 @@ var PivotTable = openerp.web.Class.extend({ }, visible_fields: function () { - return this.row_groupby.concat(this.col_groupby, this.measure); + return this.rows.groupby.concat(this.cols.groupby, this.measure); }, set_value: function (row, col, value) { @@ -78,11 +83,11 @@ var PivotTable = openerp.web.Class.extend({ }, get_col: function (id) { - return _.find(this.cols, function (col) { return col.id == id;}); + return _.find(this.cols.headers, function (col) { return col.id == id;}); }, get_row: function (id) { - return _.find(this.rows, function (row) { return row.id == id;}); + return _.find(this.rows.headers, function (row) { return row.id == id;}); }, fold_row: function (row) { @@ -92,11 +97,11 @@ var PivotTable = openerp.web.Class.extend({ _.each(tree.children, tree_traversal); } tree_traversal(row); - this.rows = _.difference(this.rows, _.rest(list)); + this.rows.headers = _.difference(this.rows.headers, _.rest(list)); row.is_expanded = false; - var fold_lvls = _.map(this.rows, function(g) {return g.path.length;}); + var fold_lvls = _.map(this.rows.headers, function(g) {return g.path.length;}); var new_groupby_length = _.max(fold_lvls); - this.row_groupby.splice(new_groupby_length); + this.rows.groupby.splice(new_groupby_length); row.children = []; }, @@ -107,11 +112,11 @@ var PivotTable = openerp.web.Class.extend({ _.each(tree.children, tree_traversal); } tree_traversal(col); - this.cols = _.difference(this.cols, _.rest(list)); + this.cols.headers = _.difference(this.cols.headers, _.rest(list)); col.is_expanded = false; - var fold_lvls = _.map(this.cols, function(g) {return g.path.length;}); + var fold_lvls = _.map(this.cols.headers, function(g) {return g.path.length;}); var new_groupby_length = _.max(fold_lvls); - this.col_groupby.splice(new_groupby_length); + this.cols.groupby.splice(new_groupby_length); col.children = []; }, @@ -119,15 +124,15 @@ var PivotTable = openerp.web.Class.extend({ var self = this, row = this.get_row(row_id); - if (row.path.length == this.row_groupby.length) { - this.row_groupby.push(field_id); + if (row.path.length == this.rows.groupby.length) { + this.rows.groupby.push(field_id); } - return query_groups_data(this.model, this.visible_fields(), row.domain, this.col_groupby, field_id) + return query_groups_data(this.model, this.visible_fields(), row.domain, this.cols.groupby, field_id) .then(function (groups) { _.each(groups.reverse(), function (group) { - var new_row_id = self.make_header(group, row, self.rows); + var new_row_id = self.make_header(group, row, self.rows.headers); _.each(group, function (data) { - var col = _.find(self.cols, function (c) { + var col = _.find(self.cols.headers, function (c) { return _.isEqual(_.rest(data.path), c.path); }); if (col) { @@ -158,16 +163,16 @@ var PivotTable = openerp.web.Class.extend({ var self = this, col = this.get_col(col_id); - if (col.path.length == this.col_groupby.length) { - this.col_groupby.push(field_id); + if (col.path.length == this.cols.groupby.length) { + this.cols.groupby.push(field_id); } - return query_groups_data(this.model, this.visible_fields(), col.domain, this.row_groupby, field_id) + return query_groups_data(this.model, this.visible_fields(), col.domain, this.rows.groupby, field_id) .then(function (groups) { _.each(groups, function (group) { - var new_col_id = self.make_header(group, col, self.cols); + var new_col_id = self.make_header(group, col, self.cols.headers); _.each(group, function (data) { - var row = _.find(self.rows, function (c) { + var row = _.find(self.rows.headers, function (c) { return _.isEqual(data.path.slice(1), c.path); }); if (row) { @@ -184,10 +189,6 @@ var PivotTable = openerp.web.Class.extend({ this.rows = this.cols; this.cols = temp; - temp = this.row_groupby; - this.row_groupby = this.col_groupby; - this.col_groupby = temp; - _.each(this.cells, function (cell) { temp = cell.row_id; cell.row_id = cell.col_id; @@ -196,8 +197,8 @@ var PivotTable = openerp.web.Class.extend({ }, clear_all: function () { - this.fold_row(this.rows[0]); - this.fold_col(this.cols[0]); + this.fold_row(this.rows.main); + this.fold_col(this.cols.main); } }); -- cgit v1.2.3 From 616af47ff7a8434b6adc0dcac4a17fd8cf977496 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Sun, 24 Nov 2013 15:02:39 +0100 Subject: [IMP] change 'chart type' to 'Mode' text in button, and add a separator line (addon web_graph) bzr revid: ged@openerp.com-20131124140239-v4uf5ic1a79kc4ly --- addons/web_graph/static/src/xml/web_graph.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index d6d18b208ed..fd1929dd81c 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -3,10 +3,11 @@
    - + + +
    -- cgit v1.2.3 From 5173a56db659f91eb71255bcecb0cfe072f54cdb Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Sun, 24 Nov 2013 15:52:40 +0100 Subject: [IMP] add heat map functionality to pivot table (addon web_graph) bzr revid: ged@openerp.com-20131124145240-dn5vq5ecb598gf4e --- addons/web_graph/static/src/js/graph.js | 21 +++++++++++++++++++-- addons/web_graph/static/src/js/pivot.js | 4 +++- addons/web_graph/static/src/xml/web_graph.xml | 9 +++++---- 3 files changed, 27 insertions(+), 7 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index c0ccb80285a..037a07c60ec 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -77,6 +77,11 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.pivot_table.fold_cols(); this.draw_table(); }, + + 'click label.graph_heat_map' : function (event) { + this.heat_map_mode = !this.heat_map_mode; + this.draw_table(); + }, }, view_loading: function (fields_view_get) { @@ -90,6 +95,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ row_groupby = []; this.pivot_table = null; + this.heat_map_mode = false; // get the default groupbys and measure defined in the field view _.each(fields_view_get.arch.children, function (field) { @@ -300,7 +306,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, draw_row: function (row) { - var pivot = this.pivot_table, + var self = this, + pivot = this.pivot_table, html_row = $(''), row_header = this.make_border_cell(1,1) .append(this.make_header_title(row).attr('data-row-id', row.id)) @@ -314,7 +321,17 @@ instance.web_graph.GraphView = instance.web.View.extend({ _.each(pivot.cols.headers, function (col) { if (col.children.length === 0) { - var cell = $('').append(pivot.get_value(row.id, col.id)); + var value = pivot.get_value(row.id, col.id), + cell = $(''); + + cell.append((value === undefined) ? '' : value); + if ((self.heat_map_mode) && (value !== undefined)) { + // heat map + console.log("heat map", self.heat_map_mode, pivot.total); + var ratio = Math.floor(70 + 185*(pivot.total - value)/pivot.total); + console.log("ratio",ratio); + cell.css("background-color", "rgb(255," + ratio + "," + ratio + ")"); + } html_row.append(cell); } }); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 06b8a97a05d..99bc20b1015 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -38,6 +38,7 @@ var PivotTable = openerp.web.Class.extend({ this.domain = options.domain; this.measure = options.measure; this.measure_label = options.measure_label; + this.total = 0; }, // Load initial data into the rows, cols and cells array. @@ -50,6 +51,7 @@ var PivotTable = openerp.web.Class.extend({ .then(function (total) { var val = total[0].attributes.aggregates[self.measure]; self.set_value(self.rows.main.id, self.cols.main.id, val); + self.total = val; }); return $.when(total, initial_group); @@ -79,7 +81,7 @@ var PivotTable = openerp.web.Class.extend({ var cell = _.find(this.cells, function (c) { return ((c.row_id == row) && (c.col_id == col)); }); - return (cell) ? cell.value : ''; + return (cell === undefined) ? undefined : cell.value; }, get_col: function (id) { diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index bce35d40f9c..4881514a8a1 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -12,10 +12,11 @@
  • Line Chart
  • Pie chart
  • - - - - + + + + +
    -- cgit v1.2.3 From 40889788d3bb6cfac6a0dab0bf2d48e59409fe5a Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Sun, 24 Nov 2013 16:00:34 +0100 Subject: [REF] merge fold_row and fold_col methods into the fold method (addon web_graph) bzr revid: ged@openerp.com-20131124150034-0133mgww0nm3dfta --- addons/web_graph/static/src/js/graph.js | 4 +--- addons/web_graph/static/src/js/pivot.js | 36 +++++++++++---------------------- 2 files changed, 13 insertions(+), 27 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 037a07c60ec..5dbe4b780cb 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -199,7 +199,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ header = pivot['get_' + options.type](id); if (header.is_expanded) { - pivot['fold_' + options.type](header); + pivot.fold(header); this.draw_table(); } else { if (header.path.length < pivot[options.type + 's'].groupby.length) { @@ -327,9 +327,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ cell.append((value === undefined) ? '' : value); if ((self.heat_map_mode) && (value !== undefined)) { // heat map - console.log("heat map", self.heat_map_mode, pivot.total); var ratio = Math.floor(70 + 185*(pivot.total - value)/pivot.total); - console.log("ratio",ratio); cell.css("background-color", "rgb(255," + ratio + "," + ratio + ")"); } html_row.append(cell); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 99bc20b1015..cd1e0c550ac 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -33,6 +33,8 @@ var PivotTable = openerp.web.Class.extend({ headers: [main_col], }; + main_row.root = this.rows; + main_col.root = this.cols; this.cells = []; this.model = options.model; this.domain = options.domain; @@ -92,34 +94,19 @@ var PivotTable = openerp.web.Class.extend({ return _.find(this.rows.headers, function (row) { return row.id == id;}); }, - fold_row: function (row) { + fold: function (header) { var list = []; function tree_traversal(tree) { list.push(tree); _.each(tree.children, tree_traversal); } - tree_traversal(row); - this.rows.headers = _.difference(this.rows.headers, _.rest(list)); - row.is_expanded = false; - var fold_lvls = _.map(this.rows.headers, function(g) {return g.path.length;}); + tree_traversal(header); + header.root.headers = _.difference(header.root.headers, _.rest(list)); + header.is_expanded = false; + var fold_lvls = _.map(header.root.headers, function(g) {return g.path.length;}); var new_groupby_length = _.max(fold_lvls); - this.rows.groupby.splice(new_groupby_length); - row.children = []; - }, - - fold_col: function (col) { - var list = []; - function tree_traversal(tree) { - list.push(tree); - _.each(tree.children, tree_traversal); - } - tree_traversal(col); - this.cols.headers = _.difference(this.cols.headers, _.rest(list)); - col.is_expanded = false; - var fold_lvls = _.map(this.cols.headers, function(g) {return g.path.length;}); - var new_groupby_length = _.max(fold_lvls); - this.cols.groupby.splice(new_groupby_length); - col.children = []; + header.root.groupby.splice(new_groupby_length); + header.children = []; }, expand_row: function (row_id, field_id) { @@ -155,6 +142,7 @@ var PivotTable = openerp.web.Class.extend({ parent: parent.id, children: [], domain: groups[0].model._domain, + root: parent.root, }; parent.children.splice(0,0, new_header) insertAfter(header_list, parent, new_header); @@ -201,11 +189,11 @@ var PivotTable = openerp.web.Class.extend({ }, fold_rows: function () { - this.fold_row(this.rows.main); + this.fold(this.rows.main); }, fold_cols: function () { - this.fold_col(this.cols.main); + this.fold(this.cols.main); }, fold_all: function () { -- cgit v1.2.3 From 46ea9d29feb8d46eb5ee4d1900c955a219fca907 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Sun, 24 Nov 2013 21:10:49 +0100 Subject: [REF] better code organization for chart drawing in addon web_graph bzr revid: ged@openerp.com-20131124201049-p7cealv5p11hofr2 --- addons/web_graph/static/src/js/charts.js | 126 ++++++++++++++++--------------- addons/web_graph/static/src/js/graph.js | 8 +- 2 files changed, 67 insertions(+), 67 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index 6944aef9672..e0b41eaff41 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -1,75 +1,77 @@ -function draw_chart (svg, mode, pivot) { - Charts[mode](pivot); -} - -function format_chart_data (pivot) { - var values = _.map(pivot.rows.headers[0].children.reverse(), function (pt) { - var val = pivot.get_value(pt.id, 2); +function draw_chart (mode, pivot) { + var values = _.map(pivot.rows.main.children, function (pt) { + var val = pivot.get_value(pt.id, pivot.cols.main.id); return {x: pt.name, y: val}; }); - return [{key: 'Bar chart', values: values}]; -}; + switch (mode) { + case 'bar_chart': + bar_chart(values); + break; + case 'line_chart': + line_chart(values); + break; + case 'pie_chart': + pie_chart(values); + break; + } +} + +function bar_chart (data) { + nv.addGraph(function () { + var chart = nv.models.discreteBarChart() + .tooltips(false) + .showValues(true) + .staggerLabels(true) + .width(650) + .height(400); -var Charts = { - bar_chart : function (pivot) { - var data = format_chart_data(pivot); - nv.addGraph(function () { - var chart = nv.models.discreteBarChart() - .tooltips(false) - .showValues(true) - .staggerLabels(true) - .width(650) - .height(400); + d3.select('.graph_main_content svg') + .datum([{key: 'Bar chart', values:data}]) + .attr('width', 650) + .attr('height', 400) + .call(chart); - d3.select('.graph_main_content svg') - .datum(data) - .attr('width', 650) - .attr('height', 400) - .call(chart); + nv.utils.windowResize(chart.update); + return chart; + }); +}; - nv.utils.windowResize(chart.update); - return chart; - }); - }, +function line_chart (data) { + nv.addGraph(function () { + var chart = nv.models.lineChart() + .x(function (d,u) { return u; }) + .width(600) + .height(300) + .margin({top: 30, right: 20, bottom: 20, left: 60}); - line_chart: function (pivot) { - data = format_chart_data(pivot); - nv.addGraph(function () { - var chart = nv.models.lineChart() - .x(function (d,u) { return u; }) - .width(600) - .height(300) - .margin({top: 30, right: 20, bottom: 20, left: 60}); + d3.select('.graph_main_content svg') + .attr('width', 600) + .attr('height', 300) + .datum([{key: 'Bar chart', values: data}]) + .call(chart); - d3.select('.graph_main_content svg') - .attr('width', 600) - .attr('height', 300) - .datum(data) - .call(chart); + return chart; + }); +}; - return chart; - }); - }, +function pie_chart(data) { + nv.addGraph(function () { + var chart = nv.models.pieChart() + .color(d3.scale.category10().range()) + .width(650) + .height(400); - pie_chart: function (pivot) { - data = format_chart_data(pivot); - nv.addGraph(function () { - var chart = nv.models.pieChart() - .color(d3.scale.category10().range()) - .width(650) - .height(400); + d3.select('.graph_main_content svg') + .datum(data) + .transition().duration(1200) + .attr('width', 650) + .attr('height', 400) + .call(chart); - d3.select('.graph_main_content svg') - .datum(data[0].values) - .transition().duration(1200) - .attr('width', 650) - .attr('height', 400) - .call(chart); + nv.utils.windowResize(chart.update); + return chart; + }); +}; - nv.utils.windowResize(chart.update); - return chart; - }); - }, -}; \ No newline at end of file diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 5dbe4b780cb..0a1dcdd001b 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -178,7 +178,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, switch_mode: function (mode) { - var self = this; this.mode = mode; if (mode === 'pivot') { this.table.css('display', 'block'); @@ -188,7 +187,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.svg.remove(); this.svg = $('
    '); this.$el.filter('.graph_main_content').append(this.svg); - draw_chart(this.svg, mode, this.pivot_table); + draw_chart(mode, this.pivot_table); } }, @@ -326,9 +325,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ cell.append((value === undefined) ? '' : value); if ((self.heat_map_mode) && (value !== undefined)) { - // heat map - var ratio = Math.floor(70 + 185*(pivot.total - value)/pivot.total); - cell.css("background-color", "rgb(255," + ratio + "," + ratio + ")"); + var color = Math.floor(50 + 205*(pivot.total - value)/pivot.total); + cell.css("background-color", "rgb(255," + color + "," + color + ")"); } html_row.append(cell); } -- cgit v1.2.3 From 5227f89396de7527906e7708d3559cc6576cabfe Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Sun, 24 Nov 2013 21:58:55 +0100 Subject: [REF] merge expand_row and expand_col methods into the fold method, also some small code tweaks (addon web_graph) bzr revid: ged@openerp.com-20131124205855-eekx2gwhgl4ye9uj --- addons/web_graph/static/src/js/graph.js | 15 +++--- addons/web_graph/static/src/js/pivot.js | 95 +++++++++++++-------------------- 2 files changed, 43 insertions(+), 67 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 0a1dcdd001b..0ab02ccb51b 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -48,12 +48,12 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.dropdown.remove(); if (event.target.attributes['data-row-id'] !== undefined) { id = event.target.attributes['data-row-id'].nodeValue; - this.pivot_table.expand_row(id, field_id) + this.pivot_table.expand(id, field_id) .then(this.proxy('draw_table')); } if (event.target.attributes['data-col-id'] !== undefined) { id = event.target.attributes['data-col-id'].nodeValue; - this.pivot_table.expand_col(id, field_id) + this.pivot_table.expand(id, field_id) .then(this.proxy('draw_table')); } }, @@ -195,19 +195,16 @@ instance.web_graph.GraphView = instance.web.View.extend({ handle_header_event: function (options) { var pivot = this.pivot_table, id = options.event.target.attributes['data-' + options.type + '-id'].nodeValue, - header = pivot['get_' + options.type](id); + header = pivot.get_header(id); if (header.is_expanded) { pivot.fold(header); this.draw_table(); } else { - if (header.path.length < pivot[options.type + 's'].groupby.length) { - // expand the corresponding header - var field = pivot[options.type + 's'].groupby[header.path.length]; - pivot['expand_' + options.type](id, field) - .then(this.proxy('draw_table')); + if (header.path.length < header.root.groupby.length) { + var field = header.root.groupby[header.path.length]; + pivot.expand(id, field).then(this.proxy('draw_table')); } else { - // display dropdown to query field to expand this.display_dropdown({id:header.id, type: options.type, target: $(event.target), diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index cd1e0c550ac..f8c71e14975 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -48,7 +48,7 @@ var PivotTable = openerp.web.Class.extend({ // drawing the table (otherwise the data returned will be empty...) start: function () { var self = this, - initial_group = this.expand_row(this.rows.main.id, this.rows.groupby[0]), + initial_group = this.expand(this.rows.main.id, this.rows.groupby[0]), total = query_groups(this.model, this.measure, this.domain, []) .then(function (total) { var val = total[0].attributes.aggregates[self.measure]; @@ -68,30 +68,32 @@ var PivotTable = openerp.web.Class.extend({ return this.rows.groupby.concat(this.cols.groupby, this.measure); }, - set_value: function (row, col, value) { - var cell = _.find(this.cells, function (c) { - return ((c.row_id == row) && (c.col_id == col)); + set_value: function (id1, id2, value) { + var x = Math.min(id1, id2), + y = Math.max(id1, id2), + cell = _.find(this.cells, function (c) { + return ((c.x == x) && (c.y == y)); }); if (cell) { cell.value = value; } else { - this.cells.push({row_id: row, col_id: col, value: value}); + this.cells.push({x: x, y: y, value: value}); } }, - get_value: function (row, col) { - var cell = _.find(this.cells, function (c) { - return ((c.row_id == row) && (c.col_id == col)); + get_value: function (id1, id2) { + var x = Math.min(id1, id2), + y = Math.max(id1, id2), + cell = _.find(this.cells, function (c) { + return ((c.x == x) && (c.y == y)); }); return (cell === undefined) ? undefined : cell.value; }, - get_col: function (id) { - return _.find(this.cols.headers, function (col) { return col.id == id;}); - }, - - get_row: function (id) { - return _.find(this.rows.headers, function (row) { return row.id == id;}); + get_header: function (id) { + return _.find(this.rows.headers.concat(this.cols.headers), function (header) { + return header.id == id; + }); }, fold: function (header) { @@ -109,20 +111,26 @@ var PivotTable = openerp.web.Class.extend({ header.children = []; }, - expand_row: function (row_id, field_id) { + expand: function (row_id, field_id) { var self = this, - row = this.get_row(row_id); + row = this.get_header(row_id); - if (row.path.length == this.rows.groupby.length) { - this.rows.groupby.push(field_id); + if (row.path.length == row.root.groupby.length) { + row.root.groupby.push(field_id); } - return query_groups_data(this.model, this.visible_fields(), row.domain, this.cols.groupby, field_id) + + var otherDim = (row.root === this.cols) ? this.rows : this.cols; + return query_groups_data(this.model, this.visible_fields(), row.domain, otherDim.groupby, field_id) .then(function (groups) { _.each(groups.reverse(), function (group) { - var new_row_id = self.make_header(group, row, self.rows.headers); + var new_row_id = self.make_header(group, row); _.each(group, function (data) { - var col = _.find(self.cols.headers, function (c) { - return _.isEqual(_.rest(data.path), c.path); + var col = _.find(otherDim.headers, function (c) { + if (row.root === this.cols) { + return _.isEqual(data.path.slice(1), c.path); + } else { + return _.isEqual(_.rest(data.path), c.path); + } }); if (col) { self.set_value(new_row_id, col.id, data.attributes.aggregates[self.measure]); @@ -133,11 +141,12 @@ var PivotTable = openerp.web.Class.extend({ }); }, - make_header: function (groups, parent, header_list) { - var new_header = { + make_header: function (groups, parent) { + var name = (groups[0].attributes.value) ? groups[0].attributes.value[1] : 'Undefined', + new_header = { id: this.generate_id(), - path: parent.path.concat(groups[0].attributes.value[1]), - name: groups[0].attributes.value[1], + path: parent.path.concat(name), + name: name, is_expanded: false, parent: parent.id, children: [], @@ -145,47 +154,17 @@ var PivotTable = openerp.web.Class.extend({ root: parent.root, }; parent.children.splice(0,0, new_header) - insertAfter(header_list, parent, new_header); + insertAfter(parent.root.headers, parent, new_header); return new_header.id; }, - expand_col: function (col_id, field_id) { - var self = this, - col = this.get_col(col_id); - - if (col.path.length == this.cols.groupby.length) { - this.cols.groupby.push(field_id); - } - - return query_groups_data(this.model, this.visible_fields(), col.domain, this.rows.groupby, field_id) - .then(function (groups) { - _.each(groups.reverse(), function (group) { - var new_col_id = self.make_header(group, col, self.cols.headers); - _.each(group, function (data) { - var row = _.find(self.rows.headers, function (c) { - return _.isEqual(data.path.slice(1), c.path); - }); - if (row) { - self.set_value(row.id, new_col_id, data.attributes.aggregates[self.measure]); - } - }); - }); - col.is_expanded = true; - }); - }, - swap_axis: function () { var temp = this.rows; this.rows = this.cols; this.cols = temp; + this.rows.main.name = "Total"; this.cols.main.name = this.measure_label; - - _.each(this.cells, function (cell) { - temp = cell.row_id; - cell.row_id = cell.col_id; - cell.col_id = temp; - }); }, fold_rows: function () { -- cgit v1.2.3 From 2ff7dd16fe8446493efcb5aad6df06ce858de229 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Sun, 24 Nov 2013 22:48:09 +0100 Subject: [REF] some more simplifications, using the symetry between cols and rows in addon web_graph bzr revid: ged@openerp.com-20131124214809-k08p4x4h0wm4owmq --- addons/web_graph/static/src/js/graph.js | 38 +++++++++------------------ addons/web_graph/static/src/xml/web_graph.xml | 21 +++------------ 2 files changed, 15 insertions(+), 44 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 0ab02ccb51b..146a9d3e865 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -32,30 +32,17 @@ instance.web_graph.GraphView = instance.web.View.extend({ 'click .web_graph_click' : function (event) { event.preventDefault(); - if (event.target.attributes['data-row-id'] !== undefined) { - this.handle_header_event({type:'row', event:event}); - - } - if (event.target.attributes['data-col-id'] !== undefined) { - this.handle_header_event({type:'col', event:event}); - } + var id = event.target.attributes['data-id'].nodeValue; + this.handle_header_event({id:id, event:event}); }, 'click a.field-selection' : function (event) { - var id, + var id = event.target.attributes['data-id'].nodeValue, field_id = event.target.attributes['data-field-id'].nodeValue; event.preventDefault(); this.dropdown.remove(); - if (event.target.attributes['data-row-id'] !== undefined) { - id = event.target.attributes['data-row-id'].nodeValue; - this.pivot_table.expand(id, field_id) - .then(this.proxy('draw_table')); - } - if (event.target.attributes['data-col-id'] !== undefined) { - id = event.target.attributes['data-col-id'].nodeValue; - this.pivot_table.expand(id, field_id) - .then(this.proxy('draw_table')); - } + this.pivot_table.expand(id, field_id) + .then(this.proxy('draw_table')); }, 'click label.graph_swap_axis' : function (event) { @@ -194,7 +181,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ handle_header_event: function (options) { var pivot = this.pivot_table, - id = options.event.target.attributes['data-' + options.type + '-id'].nodeValue, + id = options.id, header = pivot.get_header(id); if (header.is_expanded) { @@ -206,10 +193,9 @@ instance.web_graph.GraphView = instance.web.View.extend({ pivot.expand(id, field).then(this.proxy('draw_table')); } else { this.display_dropdown({id:header.id, - type: options.type, - target: $(event.target), - x: event.pageX, - y: event.pageY}); + target: $(options.event.target), + x: options.event.pageX, + y: options.event.pageY}); } } }, @@ -220,10 +206,10 @@ instance.web_graph.GraphView = instance.web.View.extend({ already_grouped = pivot.rows.groupby.concat(pivot.cols.groupby), possible_groups = _.difference(self.data.important_fields, already_grouped), dropdown_options = { + header_id: options.id, fields: _.map(possible_groups, function (field) { return {id: field, value: self.data.fields[field].string}; })}; - dropdown_options[options.type + '_id'] = options.id; this.dropdown = $(QWeb.render('field_selection', dropdown_options)); options.target.after(this.dropdown); @@ -272,7 +258,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ function make_col_header (col) { var cell = self.make_border_cell(col.width, col.height); - return cell.append(self.make_header_title(col).attr('data-col-id', col.id)); + return cell.append(self.make_header_title(col).attr('data-id', col.id)); } function make_cells (queue, level) { @@ -306,7 +292,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ pivot = this.pivot_table, html_row = $(''), row_header = this.make_border_cell(1,1) - .append(this.make_header_title(row).attr('data-row-id', row.id)) + .append(this.make_header_title(row).attr('data-id', row.id)) .addClass('graph_border'); for (var i in _.range(row.path.length)) { diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 4881514a8a1..d9353778bcf 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -22,30 +22,15 @@
    - -
    -
    - - -
    -
    -
    -- cgit v1.2.3 From 7940ec40c65214a2bdcd800a1dd2291980abc25b Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 25 Nov 2013 10:04:43 +0100 Subject: [IMP] add total to each rows in pivot table view (addon web_graph) bzr revid: ged@openerp.com-20131125090443-r5dbre9wn2jymu37 --- addons/web_graph/static/src/js/graph.js | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 0a6a2fd15db..69155e7b255 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -284,6 +284,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ make_cells(pivot.cols.headers, 0); } else { make_cells(pivot.cols.main.children, 1); + header_cells[0].push(self.make_border_cell(1, height).append('Total')); } _.each(header_cells, function (cells) { @@ -322,6 +323,16 @@ instance.web_graph.GraphView = instance.web.View.extend({ html_row.append(cell); } }); + var cell = $('').append(pivot.get_value(row.id,pivot.cols.main.id)); + if (row.is_expanded && (row.path.length <= 2)) { + var color = row.path.length * 5 + 240; + cell.css("background-color", "rgb(" + [color, color, color].join() + ")"); + } + + if (pivot.cols.main.children.length > 0) { + html_row.append(cell); + } + this.table.append(html_row); } }); -- cgit v1.2.3 From d8aa7a6551ddb0b540cd14c35d4482d79f746fb5 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 25 Nov 2013 10:15:05 +0100 Subject: [IMP] improves the look of the total in each rows in pivot table view (addon web_graph) bzr revid: ged@openerp.com-20131125091505-wts1llbdexhnl8fe --- addons/web_graph/static/src/js/graph.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 69155e7b255..2c3645341d8 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -284,7 +284,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ make_cells(pivot.cols.headers, 0); } else { make_cells(pivot.cols.main.children, 1); - header_cells[0].push(self.make_border_cell(1, height).append('Total')); + header_cells[0].push(self.make_border_cell(1, height).append('Total').css('font-weight', 'bold')); } _.each(header_cells, function (cells) { @@ -323,10 +323,16 @@ instance.web_graph.GraphView = instance.web.View.extend({ html_row.append(cell); } }); - var cell = $('').append(pivot.get_value(row.id,pivot.cols.main.id)); + var total = pivot.get_value(row.id, pivot.cols.main.id); + var cell = $('') + .append(total) + .css('font-weight', 'bold'); if (row.is_expanded && (row.path.length <= 2)) { var color = row.path.length * 5 + 240; cell.css("background-color", "rgb(" + [color, color, color].join() + ")"); + } else if (self.heat_map_mode) { + var color = Math.floor(50 + 205*(pivot.total - total)/pivot.total); + cell.css("background-color", "rgb(255," + color + "," + color + ")"); } if (pivot.cols.main.children.length > 0) { -- cgit v1.2.3 From 4eef57206502a1d3201f256027d370f3cf386c5f Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 26 Nov 2013 16:19:06 +0100 Subject: [IMP] big commit: add query_all_values() method to pivot table, and uses it to add expand_all and update_values functionality to graph view (addon web_graph) bzr revid: ged@openerp.com-20131126151906-luj8ri6e4hj444h6 --- addons/web_graph/static/src/js/graph.js | 8 +- addons/web_graph/static/src/js/pivot.js | 279 +++++++++++++++++++++++--- addons/web_graph/static/src/xml/web_graph.xml | 1 + 3 files changed, 263 insertions(+), 25 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 2c3645341d8..2aeb68b9869 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -73,6 +73,10 @@ instance.web_graph.GraphView = instance.web.View.extend({ 'click label.graph_expand_all' : function (event) { this.pivot_table.expand_all().then(this.proxy('draw_table')); }, + + 'click label.graph_update_values' : function (event) { + this.pivot_table.update_values().then(this.proxy('draw_table')); + }, }, view_loading: function (fields_view_get) { @@ -157,7 +161,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ self.pivot_table = new PivotTable(self.data); self.pivot_table.start().then(self.proxy('draw_table')); } else { - this.pivot_table.update_values.done(function () { + this.pivot_table.update_values().done(function () { self.draw_table(); }); } @@ -240,7 +244,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ .addClass('web_graph_click') .attr('href', '#') .addClass((header.is_expanded) ? 'icon-minus-sign' : 'icon-plus-sign') - .append(header.name); + .append((header.title !== undefined) ? header.title : 'Undefined'); }, draw_top_headers: function () { diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 0dfacf5cb06..b918474be47 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -6,7 +6,7 @@ var PivotTable = openerp.web.Class.extend({ main_row = { id: this.generate_id(), path: [], - name: "Total", + title: "Total", is_expanded: false, parent: null, children: [], @@ -15,7 +15,7 @@ var PivotTable = openerp.web.Class.extend({ main_col = { id: this.generate_id(), path: [], - name: options.measure_label, + title: options.measure_label, is_expanded: false, parent: null, children: [], @@ -147,17 +147,17 @@ var PivotTable = openerp.web.Class.extend({ }, make_header: function (groups, parent) { - var name = (groups[0].attributes.value) ? groups[0].attributes.value[1] : 'Undefined', + var name = groups[0].attributes.value[1], new_header = { - id: this.generate_id(), - path: parent.path.concat(name), - name: name, - is_expanded: false, - parent: parent.id, - children: [], - domain: groups[0].model._domain, - root: parent.root, - }; + id: this.generate_id(), + path: parent.path.concat(name), + title: name, + is_expanded: false, + parent: parent.id, + children: [], + domain: groups[0].model._domain, + root: parent.root, + }; parent.children.splice(0,0, new_header) insertAfter(parent.root.headers, parent, new_header); return new_header.id; @@ -168,8 +168,8 @@ var PivotTable = openerp.web.Class.extend({ this.rows = this.cols; this.cols = temp; - this.rows.main.name = "Total"; - this.cols.main.name = this.measure_label; + this.rows.main.title = "Total"; + this.cols.main.title = this.measure_label; }, fold_rows: function () { @@ -187,17 +187,250 @@ var PivotTable = openerp.web.Class.extend({ expand_all: function () { var self = this; - // temporary code, to use while waiting for correct code. - // this code expands all rows/cols by doing as many db queries. - // correct code widd do that with just 1 request. - var header_to_expand = _.find(this.rows.headers.concat(this.cols.headers), function (header) { - return ((!header.is_expanded) && (header.path.length < header.root.groupby.length)) + + return this.query_all_values().then(function (result) { + self.rows.headers = result.row_headers; + self.cols.headers = result.col_headers; + self.cells = result.cells; + self.rows.main = self.rows.headers[0]; + self.cols.main = self.cols.headers[0]; + self.total = self.rows.main.total; + self.rows.main.title = "Total"; + self.cols.main.title = self.measure_label; + _.each(self.rows.headers, function (row) { + row.root = self.rows; + row.is_expanded = (row.children.length > 0) + }); + _.each(self.cols.headers, function (col) { + col.root = self.cols; + col.is_expanded = (col.children.length > 0) + }); + + }); + }, + + update_values: function () { + var self = this; + return this.query_all_values().then(function (result) { + var old_col_headers = self.cols.headers, + old_row_headers = self.rows.headers; + + // the next 30 lines replace this.cols.headers with the + // corresponding headers in result.col_headers + _.each(old_col_headers, function (header) { + var corresponding_col = _.find(result.col_headers, function (c) { + return _.isEqual(c.path, header.path); + }); + + if (corresponding_col !== undefined) { + if (header.is_expanded) { + corresponding_col.is_expanded = true; + _.each(corresponding_col.children, function (c) { + c.is_expanded = false; + }) + } else { + corresponding_col.is_expanded = false; + } + } + }); + + self.cols.headers = _.filter(result.col_headers, function (header) { + return (header.is_expanded !== undefined); + }); + + _.each(self.cols.headers, function (col) { + if (!col.is_expanded) { + col.children = []; + } + }); + self.cols.main = self.cols.headers[0]; + + // the next 30 lines replace this.rows.headers with the + // corresponding headers in result.row_headers + _.each(old_row_headers, function (header) { + var corresponding_row = _.find(result.row_headers, function (c) { + return _.isEqual(c.path, header.path); + }); + + if (corresponding_row !== undefined) { + if (header.is_expanded) { + corresponding_row.is_expanded = true; + _.each(corresponding_row.children, function (c) { + c.is_expanded = false; + }) + } else { + corresponding_row.is_expanded = false; + } + } + }); + + self.rows.headers = _.filter(result.row_headers, function (header) { + return (header.is_expanded !== undefined); + }); + + _.each(self.rows.headers, function (col) { + if (!col.is_expanded) { + col.children = []; + } + }); + self.rows.main = self.rows.headers[0]; + + + // now some more tweaks + self.total = self.rows.main.total; + _.each(self.rows.headers, function (row) { + row.root = self.rows; + }); + _.each(self.cols.headers, function (col) { + col.root = self.cols; + }); + self.cells = result.cells; + self.rows.main.title = "Total"; + self.cols.main.title = self.measure_label; + }); + }, + + // this method is a little tricky. In order to obtain all the values + // required to draw the full table, we have to do at least + // 2 + min(row.groupby.length, col.groupby.length) + // calls to readgroup. For example, if row.groupby = [r1, r2, r3] and + // col.groupby = [c1, c2, c3, c4], then a minimal set of calls is done + // with the following groupby: + // [] + // [c1, c2, c3, c4] + // [r1, c1, c2, c3, c4] + // [r1, r2, c1, c2, c3, c4] + // [r1, r2, r3, c1, c2, c3, c4] + // To simplify the code, we will always do 2 + row.groupby.length calls, + // unless col.groupby.length = 0, in which case we do 2 calls ([] and + // row_groupbys), but this can be optimized later. + query_all_values: function () { + var self = this, + cols = this.cols.groupby, + rows = this.rows.groupby, + def_array, + groupbys; + + if (cols.length > 0) { + groupbys = _.map(_.range(rows.length + 1), function (i) { + return rows.slice(0, i).concat(cols); + }); + groupbys.push([]); + } else { + groupbys = [rows, []]; + } + def_array = _.map(groupbys, function (groupby) { + return query_groups(self.model, self.visible_fields(), self.domain, groupby); }); - if (header_to_expand === undefined) { - return $.when(); + + return $.when.apply(null, def_array).then(function () { + var args = Array.prototype.slice.call(arguments), + col_data = _.first(args), + total = _.last(args)[0], + row_data = _.last(_.initial(args)), + cell_data = args; + + var result = self.format_data(total, col_data, row_data, cell_data); + console.log("result final",result); + return result; + + }); + + }, + + format_data: function (total, col_data, row_data, cell_data) { + var self = this, + dim_row = this.rows.groupby.length, + dim_col = this.cols.groupby.length, + col_headers = make_headers(col_data, dim_col), + row_headers = make_headers(row_data, dim_row); + cells = []; + + if (dim_col > 0) { + _.each(cell_data, function (data, index) { + make_cells(data, index, []); + }); // make it more functional? } else { - return this.expand(header_to_expand.id, header_to_expand.root.groupby[header_to_expand.path.length]).then(function () { - return self.expand_all(); + make_cells(cell_data[0], dim_row, []); + make_cells(cell_data[1], 0, []); + } + + return {col_headers: col_headers, + row_headers: row_headers, + cells: cells}; + + function make_headers (data, depth) { + var main = { + id: self.generate_id(), + count: total.attributes.length, + total: total.attributes.aggregates[self.measure], + path: [], + parent: null, + children: [], + title: '', + domain: self.domain, + }; + + if (depth > 0) { + main.children = _.map(data, function (data_pt) { + return make_tree_headers (data_pt, main, depth); + }); + } + + var result = [], + make_list = function (tree) { + result.push(tree); + _.each(tree.children, make_list); + }; + + make_list(main); + return result; + } + + function make_tree_headers (data_pt, parent, max_depth) { + var node = { + id: self.generate_id(), + count: data_pt.attributes.length, + total: data_pt.attributes.aggregates[self.measure], + path: parent.path.concat(data_pt.attributes.value[1]), + title: data_pt.attributes.value[1], + domain: data_pt.model._domain, + parent: parent, + children: [], + }; + if (node.path.length < max_depth) { + node.children = _.map(data_pt.subgroups_data, function (child) { + return make_tree_headers (child, node, max_depth); + }); + } + return node; + } + + function make_cells (data, index, current_path) { + _.each(data, function (group) { + var attr = group.attributes, + path = current_path, + value = attr.aggregates[self.measure]; + + if (attr.grouped_on !== undefined) { + path = path.concat(attr.value[1]); + } + var rowpath = path.slice(0, index), + colpath = path.slice(index); + + var row = _.find(row_headers, function (header) { + return _.isEqual(header.path, rowpath); + }); + var col = _.find(col_headers, function (header) { + return _.isEqual(header.path, colpath); + }); + cells.push({x: Math.min(row.id, col.id), + y: Math.max(row.id, col.id), + value: value}); + + if (attr.has_children) { + make_cells (group.subgroups_data, index, path); + } }); } }, diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 273ff90dac4..ad9dcc710fb 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -18,6 +18,7 @@ +
    -- cgit v1.2.3 From 857b48749b79bca158ddf1b5b4096dd6cf061d22 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 26 Nov 2013 16:57:06 +0100 Subject: [IMP] updates the pivot table domain when search view is activated bzr revid: ged@openerp.com-20131126155706-nqc6hgjbyty8jju2 --- addons/web_graph/static/src/js/graph.js | 1 + addons/web_graph/static/src/js/pivot.js | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 2aeb68b9869..3d218e38eba 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -161,6 +161,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ self.pivot_table = new PivotTable(self.data); self.pivot_table.start().then(self.proxy('draw_table')); } else { + this.pivot_table.domain = domain; this.pivot_table.update_values().done(function () { self.draw_table(); }); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index b918474be47..5516f5caf5c 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -330,10 +330,7 @@ var PivotTable = openerp.web.Class.extend({ row_data = _.last(_.initial(args)), cell_data = args; - var result = self.format_data(total, col_data, row_data, cell_data); - console.log("result final",result); - return result; - + return self.format_data(total, col_data, row_data, cell_data); }); }, -- cgit v1.2.3 From 99b7fa4272081ac74ce56fe534760ee40db88e17 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 26 Nov 2013 17:14:15 +0100 Subject: [FIX] gives the correct data to the charts function instead of undefined (addon web_graph) bzr revid: ged@openerp.com-20131126161415-3thwtp25wm1hvks0 --- addons/web_graph/static/src/js/charts.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index e0b41eaff41..16dfe2ed105 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -2,9 +2,11 @@ function draw_chart (mode, pivot) { var values = _.map(pivot.rows.main.children, function (pt) { var val = pivot.get_value(pt.id, pivot.cols.main.id); - return {x: pt.name, y: val}; + return {x: pt.title, y: val}; }); + console.log("values",values); + switch (mode) { case 'bar_chart': bar_chart(values); -- cgit v1.2.3 From 8ef078acb323766281f60f40796ae656343b581f Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 26 Nov 2013 17:14:24 +0100 Subject: [FIX] gives the correct data to the charts function instead of undefined (addon web_graph) bzr revid: ged@openerp.com-20131126161424-c0dlaqunv18anlw5 --- addons/web_graph/static/src/js/charts.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index 16dfe2ed105..df59e69b742 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -5,8 +5,6 @@ function draw_chart (mode, pivot) { return {x: pt.title, y: val}; }); - console.log("values",values); - switch (mode) { case 'bar_chart': bar_chart(values); -- cgit v1.2.3 From 0b5ff7efff63c791cf0e5d8abe66653973391a16 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 27 Nov 2013 10:10:53 +0100 Subject: [IMP] reorganizes all options in graph views (puts them in 4 dropdown menus) (addon web_graph) bzr revid: ged@openerp.com-20131127091053-ydbo89dj027ndm3o --- addons/web_graph/static/src/js/graph.js | 73 ++++++++++++++++----------- addons/web_graph/static/src/xml/web_graph.xml | 57 ++++++++++++++++----- 2 files changed, 89 insertions(+), 41 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 3d218e38eba..9cd2147d9fb 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -30,6 +30,43 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.switch_mode(mode); }, + 'click .graph_expand_selection li' : function (event) { + event.preventDefault(); + switch (event.target.attributes['data-choice'].nodeValue) { + case 'fold_columns': + this.pivot_table.fold_cols(); + this.draw_table(); + break; + case 'fold_rows': + this.pivot_table.fold_rows(); + this.draw_table(); + break; + case 'fold_all': + this.pivot_table.fold_all(); + this.draw_table(); + break; + case 'expand_all': + this.pivot_table.expand_all().then(this.proxy('draw_table')); + break; + } + }, + + 'click .graph_options_selection li' : function (event) { + event.preventDefault(); + switch (event.target.attributes['data-choice'].nodeValue) { + case 'swap_axis': + this.pivot_table.swap_axis(); + this.draw_table(); + break; + case 'update_values': + this.pivot_table.update_values().then(this.proxy('draw_table')); + break; + case 'export_data': + // Export code... To do... + break; + } + }, + 'click .web_graph_click' : function (event) { event.preventDefault(); var id = event.target.attributes['data-id'].nodeValue; @@ -45,38 +82,11 @@ instance.web_graph.GraphView = instance.web.View.extend({ .then(this.proxy('draw_table')); }, - 'click label.graph_swap_axis' : function (event) { - this.pivot_table.swap_axis(); - this.draw_table(); - }, - - 'click label.graph_fold_all' : function (event) { - this.pivot_table.fold_all(); - this.draw_table(); - }, - - 'click label.graph_fold_rows' : function (event) { - this.pivot_table.fold_rows(); - this.draw_table(); - }, - - 'click label.graph_fold_cols' : function (event) { - this.pivot_table.fold_cols(); - this.draw_table(); - }, 'click label.graph_heat_map' : function (event) { this.heat_map_mode = !this.heat_map_mode; this.draw_table(); }, - - 'click label.graph_expand_all' : function (event) { - this.pivot_table.expand_all().then(this.proxy('draw_table')); - }, - - 'click label.graph_update_values' : function (event) { - this.pivot_table.update_values().then(this.proxy('draw_table')); - }, }, view_loading: function (fields_view_get) { @@ -91,6 +101,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.pivot_table = null; this.heat_map_mode = false; + this.mode = 'pivot'; // get the default groupbys and measure defined in the field view _.each(fields_view_get.arch.children, function (field) { @@ -175,7 +186,9 @@ instance.web_graph.GraphView = instance.web.View.extend({ switch_mode: function (mode) { this.mode = mode; - if (mode === 'pivot') { + var table_modes = ['pivot', 'heatmap', 'row_heatmap', 'col_heatmap']; + if (_.contains(table_modes, mode)) { + this.draw_table(); this.table.css('display', 'block'); this.svg.css('display','none'); } else { @@ -317,7 +330,9 @@ instance.web_graph.GraphView = instance.web.View.extend({ cell = $(''); cell.append((value === undefined) ? '' : value); - if ((self.heat_map_mode) && (value !== undefined)) { + console.log("self.mode",self.mode); + if ((self.mode == 'heatmap') && (value !== undefined)) { + console.log("yop"); var color = Math.floor(50 + 205*(pivot.total - value)/pivot.total); cell.css("background-color", "rgb(255," + color + "," + color + ")"); } diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index ad9dcc710fb..20785a69139 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -1,25 +1,58 @@
    -
    - - +
    +
    + + +
    +
    + + +
    +
    + + +
    -- cgit v1.2.3 From 1f8b8165e8f563108eef32c30576b298fc26404f Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 27 Nov 2013 10:20:52 +0100 Subject: [REF] small code cleanups... removing old commented code, and small tweaks (addon web_graph) bzr revid: ged@openerp.com-20131127092052-n2ub66oczqrtmr33 --- addons/web_graph/static/src/js/graph.js | 29 +++++++++------------------ addons/web_graph/static/src/js/pivot.js | 21 +++++++++---------- addons/web_graph/static/src/xml/web_graph.xml | 9 +-------- 3 files changed, 21 insertions(+), 38 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 9cd2147d9fb..13a0d93c888 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -33,7 +33,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ 'click .graph_expand_selection li' : function (event) { event.preventDefault(); switch (event.target.attributes['data-choice'].nodeValue) { - case 'fold_columns': + case 'fold_columns': this.pivot_table.fold_cols(); this.draw_table(); break; @@ -54,7 +54,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ 'click .graph_options_selection li' : function (event) { event.preventDefault(); switch (event.target.attributes['data-choice'].nodeValue) { - case 'swap_axis': + case 'swap_axis': this.pivot_table.swap_axis(); this.draw_table(); break; @@ -81,12 +81,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.pivot_table.expand(id, field_id) .then(this.proxy('draw_table')); }, - - - 'click label.graph_heat_map' : function (event) { - this.heat_map_mode = !this.heat_map_mode; - this.draw_table(); - }, }, view_loading: function (fields_view_get) { @@ -96,7 +90,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ measure = null, fields, important_fields = [], - col_groupby = [], row_groupby = []; this.pivot_table = null; @@ -214,9 +207,9 @@ instance.web_graph.GraphView = instance.web.View.extend({ var field = header.root.groupby[header.path.length]; pivot.expand(id, field).then(this.proxy('draw_table')); } else { - this.display_dropdown({id:header.id, - target: $(options.event.target), - x: options.event.pageX, + this.display_dropdown({id:header.id, + target: $(options.event.target), + x: options.event.pageX, y: options.event.pageY}); } } @@ -306,7 +299,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ } _.each(header_cells, function (cells) { - self.table.append($("").append(cells)); + self.table.append($('').append(cells)); }); }, @@ -330,15 +323,13 @@ instance.web_graph.GraphView = instance.web.View.extend({ cell = $(''); cell.append((value === undefined) ? '' : value); - console.log("self.mode",self.mode); if ((self.mode == 'heatmap') && (value !== undefined)) { - console.log("yop"); var color = Math.floor(50 + 205*(pivot.total - value)/pivot.total); - cell.css("background-color", "rgb(255," + color + "," + color + ")"); + cell.css('background-color', 'rgb(255,' + color + ',' + color + ')'); } if (row.is_expanded && (row.path.length <= 2)) { var color = row.path.length * 5 + 240; - cell.css("background-color", "rgb(" + [color, color, color].join() + ")"); + cell.css('background-color', 'rgb(' + [color, color, color].join() + ')'); } html_row.append(cell); } @@ -349,10 +340,10 @@ instance.web_graph.GraphView = instance.web.View.extend({ .css('font-weight', 'bold'); if (row.is_expanded && (row.path.length <= 2)) { var color = row.path.length * 5 + 240; - cell.css("background-color", "rgb(" + [color, color, color].join() + ")"); + cell.css('background-color', 'rgb(' + [color, color, color].join() + ')'); } else if (self.heat_map_mode) { var color = Math.floor(50 + 205*(pivot.total - total)/pivot.total); - cell.css("background-color", "rgb(255," + color + "," + color + ")"); + cell.css('background-color', 'rgb(255,' + color + ',' + color + ')'); } if (pivot.cols.main.children.length > 0) { diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 5516f5caf5c..7c61cba1723 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -11,7 +11,7 @@ var PivotTable = openerp.web.Class.extend({ parent: null, children: [], domain: options.domain, - }; + }; main_col = { id: this.generate_id(), path: [], @@ -19,7 +19,7 @@ var PivotTable = openerp.web.Class.extend({ is_expanded: false, parent: null, children: [], - domain: options.domain, + domain: options.domain, }; this.rows = { @@ -93,7 +93,7 @@ var PivotTable = openerp.web.Class.extend({ get_header: function (id) { return _.find(this.rows.headers.concat(this.cols.headers), function (header) { return header.id == id; - }); + }); }, fold: function (header) { @@ -108,7 +108,7 @@ var PivotTable = openerp.web.Class.extend({ header.root.headers = _.difference(header.root.headers, _.rest(list)); header.is_expanded = false; var fold_lvls = _.map(header.root.headers, function(g) {return g.path.length;}); - var new_groupby_length = _.max(fold_lvls); + var new_groupby_length = _.max(fold_lvls); header.root.groupby.splice(new_groupby_length); header.children = []; this.cells = _.reject(this.cells, function (cell) { @@ -118,7 +118,7 @@ var PivotTable = openerp.web.Class.extend({ expand: function (row_id, field_id) { var self = this, - row = this.get_header(row_id); + row = this.get_header(row_id); if (row.path.length == row.root.groupby.length) { row.root.groupby.push(field_id); @@ -158,7 +158,7 @@ var PivotTable = openerp.web.Class.extend({ domain: groups[0].model._domain, root: parent.root, }; - parent.children.splice(0,0, new_header) + parent.children.splice(0,0, new_header); insertAfter(parent.root.headers, parent, new_header); return new_header.id; }, @@ -199,11 +199,11 @@ var PivotTable = openerp.web.Class.extend({ self.cols.main.title = self.measure_label; _.each(self.rows.headers, function (row) { row.root = self.rows; - row.is_expanded = (row.children.length > 0) + row.is_expanded = (row.children.length > 0); }); _.each(self.cols.headers, function (col) { col.root = self.cols; - col.is_expanded = (col.children.length > 0) + col.is_expanded = (col.children.length > 0); }); }); @@ -227,7 +227,7 @@ var PivotTable = openerp.web.Class.extend({ corresponding_col.is_expanded = true; _.each(corresponding_col.children, function (c) { c.is_expanded = false; - }) + }); } else { corresponding_col.is_expanded = false; } @@ -257,7 +257,7 @@ var PivotTable = openerp.web.Class.extend({ corresponding_row.is_expanded = true; _.each(corresponding_row.children, function (c) { c.is_expanded = false; - }) + }); } else { corresponding_row.is_expanded = false; } @@ -275,7 +275,6 @@ var PivotTable = openerp.web.Class.extend({ }); self.rows.main = self.rows.headers[0]; - // now some more tweaks self.total = self.rows.main.total; _.each(self.rows.headers, function (row) { diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 20785a69139..f07264ac9f1 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -35,14 +35,7 @@
  • Expand All
  • - +
    -- cgit v1.2.3 From be00aca052de10bbcfcf82ab00bac7802059e331 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 28 Nov 2013 09:45:51 +0100 Subject: [REF] removes all references to measure label in pivot table (addon web_graph) bzr revid: ged@openerp.com-20131128084551-19hc23fmw3gvtoc9 --- addons/web_graph/static/src/js/graph.js | 17 ++++++++++++++--- addons/web_graph/static/src/js/pivot.js | 14 +++++--------- 2 files changed, 19 insertions(+), 12 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 1bcb0fd98d3..119d0b12e16 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -34,7 +34,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ 'click .graph_measure_selection li' : function (event) { event.preventDefault(); var measure = event.target.attributes['data-choice'].nodeValue; - this.pivot_table.set_measure(measure) + this.measure = (measure === '__count') ? null : measure; + this.pivot_table.set_measure(this.measure) .then(this.proxy('display_data')); }, @@ -99,6 +100,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.pivot_table = null; this.heat_map_mode = false; this.mode = 'pivot'; + this.measure = null; this.measure_list = []; this.important_fields = []; }, @@ -133,6 +135,9 @@ instance.web_graph.GraphView = instance.web.View.extend({ } } }); + if (this.measure_list.length > 0) { + this.measure = this.measure_list[0]; + } // get the most important fields (of the model) by looking at the // groupby filters defined in the search view @@ -161,12 +166,12 @@ instance.web_graph.GraphView = instance.web.View.extend({ return $.when(important_fields_def, field_descr_def) .then(function () { + self.fields = fields; self.data = { model: model, domain: domain, fields: fields, - measure: self.measure_list[0], - measure_label: fields[self.measure_list[0]].string, + measure: self.measure, col_groupby: [], row_groupby: row_groupby, groups: [], @@ -261,7 +266,13 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.$('.field-selection').next('.dropdown-menu').toggle(); }, + measure_label: function () { + return (this.measure) ? this.fields[this.measure].string : 'Quantity'; + }, + draw_table: function () { + this.pivot_table.rows.main.title = 'Total'; + this.pivot_table.cols.main.title = this.measure_label(); this.draw_top_headers(); _.each(this.pivot_table.rows.headers, this.proxy('draw_row')); }, diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index d6ae2168bbf..40ee4f0acda 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -12,7 +12,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ this.model = options.model; this.domain = options.domain; this.measure = options.measure; - this.measure_label = options.measure_label; this.total = 0; this.id_seed = 0; this.no_data = true; @@ -58,7 +57,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }, set_measure: function (measure) { - this.measure = (measure === '__count') ? null : measure; + this.measure = measure; return this.update_values(); }, @@ -143,9 +142,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ var temp = this.rows; this.rows = this.cols; this.cols = temp; - - this.rows.main.title = 'Total'; - this.cols.main.title = this.measure_label; }, fold_rows: function () { @@ -173,8 +169,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ self.rows.main = self.rows.headers[0]; self.cols.main = self.cols.headers[0]; self.total = self.rows.main.total; - self.rows.main.title = 'Total'; - self.cols.main.title = self.measure_label; + self.rows.main.title = ''; + self.cols.main.title = ''; _.each(self.rows.headers, function (row) { row.root = self.rows; row.is_expanded = (row.children.length > 0); @@ -269,8 +265,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ col.root = self.cols; }); self.cells = result.cells; - self.rows.main.title = 'Total'; - self.cols.main.title = self.measure_label; + self.rows.main.title = ''; + self.cols.main.title = ''; }); }, -- cgit v1.2.3 From d790f8e96f2944ef120383d22696ec4038a56738 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 28 Nov 2013 10:17:15 +0100 Subject: [REF] removes duplicated code in update_values method in pivot class (addon web_graph) bzr revid: ged@openerp.com-20131128091715-g1f29k60a0pvy8sd --- addons/web_graph/static/src/js/pivot.js | 82 ++++++++++----------------------- 1 file changed, 25 insertions(+), 57 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 40ee4f0acda..a87dfada7d5 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -193,68 +193,38 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ return undefined; } self.no_data = false; - var old_col_headers = self.cols.headers, - old_row_headers = self.rows.headers; - - // the next 30 lines replace this.cols.headers with the - // corresponding headers in result.col_headers - _.each(old_col_headers, function (header) { - var corresponding_col = _.find(result.col_headers, function (c) { - return _.isEqual(c.path, header.path); - }); - - if (corresponding_col !== undefined) { - if (header.is_expanded) { - corresponding_col.is_expanded = true; - _.each(corresponding_col.children, function (c) { - c.is_expanded = false; - }); - } else { - corresponding_col.is_expanded = false; - } - } - }); - - self.cols.headers = _.filter(result.col_headers, function (header) { - return (header.is_expanded !== undefined); - }); - - _.each(self.cols.headers, function (col) { - if (!col.is_expanded) { - col.children = []; - } - }); + self.cols.headers = update_headers(self.cols.headers, result.col_headers); + self.rows.headers = update_headers(self.rows.headers, result.row_headers); self.cols.main = self.cols.headers[0]; + self.rows.main = self.rows.headers[0]; - // the next 30 lines replace this.rows.headers with the - // corresponding headers in result.row_headers - _.each(old_row_headers, function (header) { - var corresponding_row = _.find(result.row_headers, function (c) { - return _.isEqual(c.path, header.path); - }); - if (corresponding_row !== undefined) { - if (header.is_expanded) { - corresponding_row.is_expanded = true; - _.each(corresponding_row.children, function (c) { + function update_headers (old_headers, new_headers) { + _.each(old_headers, function (header) { + var corresponding_header = _.find(new_headers, function (h) { + return _.isEqual(h.path, header.path); + }); + if (corresponding_header && (header.is_expanded)) { + corresponding_header.is_expanded = true; + _.each(corresponding_header.children, function (c) { c.is_expanded = false; }); - } else { - corresponding_row.is_expanded = false; + } + if (corresponding_header && (!header.is_expanded)) { + corresponding_header.is_expanded = false; } - } - }); - - self.rows.headers = _.filter(result.row_headers, function (header) { - return (header.is_expanded !== undefined); - }); + }); + var updated_headers = _.filter(new_headers, function (header) { + return (header.is_expanded !== undefined); + }); + _.each(updated_headers, function (hdr) { + if (!hdr.is_expanded) { + hdr.children = []; + } + }); - _.each(self.rows.headers, function (col) { - if (!col.is_expanded) { - col.children = []; - } - }); - self.rows.main = self.rows.headers[0]; + return updated_headers; + } // now some more tweaks self.total = self.rows.main.total; @@ -265,8 +235,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ col.root = self.cols; }); self.cells = result.cells; - self.rows.main.title = ''; - self.cols.main.title = ''; }); }, -- cgit v1.2.3 From 4aa70638ef8418f18e05bd8ff7dba88724b886a6 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 28 Nov 2013 10:47:46 +0100 Subject: [REF] adds a 'get_total' method and simplify a few parts of the code using totals (addon web_graph) bzr revid: ged@openerp.com-20131128094746-mthch89zqx66flq7 --- addons/web_graph/static/src/js/graph.js | 10 +++++----- addons/web_graph/static/src/js/pivot.js | 14 +++++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 119d0b12e16..c1c2b52f4b8 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -363,8 +363,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ }); if (pivot.cols.main.children.length > 0) { - var row_total = pivot.get_value(row.id, pivot.cols.main.id), - cell = make_cell(row_total, pivot.cols.main) + var cell = make_cell(pivot.get_total(row), pivot.cols.main) .css('font-weight', 'bold'); html_row.append(cell); } @@ -384,16 +383,17 @@ instance.web_graph.GraphView = instance.web.View.extend({ } cell.append(value); if (self.mode === 'heatmap') { - color = Math.floor(50 + 205*(pivot.total - value)/pivot.total); + total = pivot.get_total(); + color = Math.floor(50 + 205*(total - value)/total); cell.css('background-color', $.Color(255, color, color)); } if (self.mode === 'row_heatmap') { - total = pivot.get_value(row.id, pivot.cols.main.id); + total = pivot.get_total(row); color = Math.floor(50 + 205*(total - value)/total); cell.css('background-color', $.Color(255, color, color)); } if (self.mode === 'col_heatmap') { - total = pivot.get_value(col.id, pivot.rows.main.id); + total = pivot.get_total(col); color = Math.floor(50 + 205*(total - value)/total); cell.css('background-color', $.Color(255, color, color)); } diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index a87dfada7d5..68c5ca43a3e 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -12,7 +12,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ this.model = options.model; this.domain = options.domain; this.measure = options.measure; - this.total = 0; this.id_seed = 0; this.no_data = true; }, @@ -168,7 +167,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ self.cells = result.cells; self.rows.main = self.rows.headers[0]; self.cols.main = self.cols.headers[0]; - self.total = self.rows.main.total; self.rows.main.title = ''; self.cols.main.title = ''; _.each(self.rows.headers, function (row) { @@ -186,6 +184,15 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }); }, + get_total: function (header) { + if (header) { + var main = (header.root === this.rows) ? this.cols.main : this.rows.main; + return this.get_value(header.id, main.id); + } else { + return this.rows.main.total; + } + }, + update_values: function () { var self = this; return this.query_all_values().then(function (result) { @@ -226,8 +233,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ return updated_headers; } - // now some more tweaks - self.total = self.rows.main.total; _.each(self.rows.headers, function (row) { row.root = self.rows; }); @@ -341,7 +346,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ function make_tree_headers (data_pt, parent, max_depth) { var node = { id: self.generate_id(), - total: data_pt.attributes.aggregates[self.measure], path: parent.path.concat(data_pt.attributes.value[1]), title: data_pt.attributes.value[1], domain: data_pt.model._domain, -- cgit v1.2.3 From e0920173a32f7889ce2b9bc49a7a83ad035ca60a Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 28 Nov 2013 11:16:25 +0100 Subject: [REF] improves the initialization process of pivot table (addon web_graph) bzr revid: ged@openerp.com-20131128101625-7ig5lftk8wv8w6tj --- addons/web_graph/static/src/js/graph.js | 21 ++++++--------------- addons/web_graph/static/src/js/pivot.js | 3 +++ 2 files changed, 9 insertions(+), 15 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index c1c2b52f4b8..5d4eade76fb 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -114,7 +114,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.dropdown = null; } }); - return this.load_view(); }, @@ -167,7 +166,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ return $.when(important_fields_def, field_descr_def) .then(function () { self.fields = fields; - self.data = { + var data = { model: model, domain: domain, fields: fields, @@ -176,6 +175,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ row_groupby: row_groupby, groups: [], }; + self.pivot_table = new openerp.web_graph.PivotTable(data); + var measure_selection = self.$('.graph_measure_selection'); _.each(self.measure_list, function (measure) { var choice = $('').attr('data-choice', measure) @@ -188,18 +189,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, do_search: function (domain, context, group_by) { - var self = this; - this.data.domain = new instance.web.CompoundDomain(domain); - - if (!this.pivot_table) { - self.pivot_table = new openerp.web_graph.PivotTable(self.data); - self.pivot_table.start().then(self.proxy('display_data')); - } else { - this.pivot_table.domain = domain; - this.pivot_table.update_values().done(function () { - self.display_data(); - }); - } + this.pivot_table.domain = domain; + this.pivot_table.update_values().done(this.proxy('display_data')); }, do_show: function () { @@ -255,7 +246,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ dropdown_options = { header_id: options.id, fields: _.map(possible_groups, function (field) { - return {id: field, value: self.data.fields[field].string}; + return {id: field, value: self.fields[field].string}; })}; this.dropdown = $(QWeb.render('field_selection', dropdown_options)); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 68c5ca43a3e..80e5e95306b 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -194,6 +194,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }, update_values: function () { + if (!this.rows.headers) { + return this.expand_all(); + } var self = this; return this.query_all_values().then(function (result) { if (!result) { -- cgit v1.2.3 From 0af9f5f053f8f1cde2b73a00c27492952539bc39 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 28 Nov 2013 11:33:17 +0100 Subject: [IMP] add a small highlighting when hovering over a line in pivot table (addon web_graph) bzr revid: ged@openerp.com-20131128103317-k60u8e22z9yus38h --- addons/web_graph/static/src/css/graph.css | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index 2a6ba6b6e9c..8a92da76605 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -19,10 +19,6 @@ span.web_graph_indent { padding-left: 30px; } -/*span.web_graph_indent:first-child { - padding-left: 25px; -} -*/ .web_graph_click:hover { cursor: pointer; } @@ -33,4 +29,9 @@ tr.graph_top td { tr.graph_top li { text-align: left; -} \ No newline at end of file +} + +.graph_main_content tr:hover { + background-color: rgb(245,245,245); +} + -- cgit v1.2.3 From 6afd98516c4d18a146570184d3b667a3438ffdfc Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 28 Nov 2013 11:49:29 +0100 Subject: [REF] removes a few useless lines in view_loading method (addon web_graph) bzr revid: ged@openerp.com-20131128104929-4ou50xebjub3bijh --- addons/web_graph/static/src/js/graph.js | 45 ++++++++++++++------------------- 1 file changed, 19 insertions(+), 26 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 5d4eade76fb..de4d40a923a 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -120,8 +120,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ view_loading: function (fields_view_get) { var self = this, model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}), - domain = [], - fields, row_groupby = []; // get the default groupbys and measure defined in the field view @@ -140,40 +138,35 @@ instance.web_graph.GraphView = instance.web.View.extend({ // get the most important fields (of the model) by looking at the // groupby filters defined in the search view - var load_view = instance.web.fields_view_get({ - model: model, - view_type: 'search', - }); - - var important_fields_def = $.when(load_view).then(function (search_view) { - var groups = _.select(search_view.arch.children, function (c) { - return (c.tag == 'group') && (c.attrs.string != 'Display'); - }); - _.each(groups, function(g) { - _.each(g.children, function (g) { - if (g.attrs.context) { - var field_id = py.eval(g.attrs.context).group_by; - self.important_fields.push(field_id); - } + var options = {model:model, view_type: 'search'}, + deferred1 = instance.web.fields_view_get(options).then(function (search_view) { + var groups = _.select(search_view.arch.children, function (c) { + return (c.tag == 'group') && (c.attrs.string != 'Display'); + }); + _.each(groups, function(g) { + _.each(g.children, function (g) { + if (g.attrs.context) { + var field_id = py.eval(g.attrs.context).group_by; + self.important_fields.push(field_id); + } + }); }); }); - }); // get the fields descriptions from the model - var field_descr_def = model.call('fields_get', []) - .then(function (fs) { fields = fs; }); + var deferred2 = model.call('fields_get', []).then(function (fs) { + self.fields = fs; + console.log("fiels",self.fields); + }); - return $.when(important_fields_def, field_descr_def) + return $.when(deferred1, deferred2) .then(function () { - self.fields = fields; var data = { model: model, - domain: domain, - fields: fields, + domain: [], measure: self.measure, col_groupby: [], row_groupby: row_groupby, - groups: [], }; self.pivot_table = new openerp.web_graph.PivotTable(data); @@ -181,7 +174,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ _.each(self.measure_list, function (measure) { var choice = $('').attr('data-choice', measure) .attr('href', '#') - .append(fields[measure].string); + .append(self.fields[measure].string); measure_selection.append($('
  • ').append(choice)); }); -- cgit v1.2.3 From 7b2109dcae11ac37afce0918390f61b348290c02 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 28 Nov 2013 11:54:02 +0100 Subject: [REF] removes a few useless lines in view_loading method (addon web_graph) bzr revid: ged@openerp.com-20131128105402-eb3pqksd5v9ixaxn --- addons/web_graph/static/src/js/graph.js | 39 +++++++++++++++------------------ 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index de4d40a923a..689cccaab14 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -156,29 +156,26 @@ instance.web_graph.GraphView = instance.web.View.extend({ // get the fields descriptions from the model var deferred2 = model.call('fields_get', []).then(function (fs) { self.fields = fs; - console.log("fiels",self.fields); - }); - - return $.when(deferred1, deferred2) - .then(function () { - var data = { - model: model, - domain: [], - measure: self.measure, - col_groupby: [], - row_groupby: row_groupby, - }; - self.pivot_table = new openerp.web_graph.PivotTable(data); - - var measure_selection = self.$('.graph_measure_selection'); - _.each(self.measure_list, function (measure) { - var choice = $('').attr('data-choice', measure) - .attr('href', '#') - .append(self.fields[measure].string); - measure_selection.append($('
  • ').append(choice)); + var measure_selection = self.$('.graph_measure_selection'); + _.each(self.measure_list, function (measure) { + var choice = $('').attr('data-choice', measure) + .attr('href', '#') + .append(self.fields[measure].string); + measure_selection.append($('
  • ').append(choice)); - }); }); + }); + + return $.when(deferred1, deferred2).then(function () { + var data = { + model: model, + domain: [], + measure: self.measure, + col_groupby: [], + row_groupby: row_groupby, + }; + self.pivot_table = new openerp.web_graph.PivotTable(data); + }); }, do_search: function (domain, context, group_by) { -- cgit v1.2.3 From 2ff2fc4c9e55934ff2caf010816849165d32eb5d Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 28 Nov 2013 13:38:30 +0100 Subject: [REF] removes a few useless lines (addon web_graph) bzr revid: ged@openerp.com-20131128123830-vaqaeoizit8x8jq9 --- addons/web_graph/static/src/js/pivot.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 80e5e95306b..5d5b70ebc45 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -167,8 +167,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ self.cells = result.cells; self.rows.main = self.rows.headers[0]; self.cols.main = self.cols.headers[0]; - self.rows.main.title = ''; - self.cols.main.title = ''; _.each(self.rows.headers, function (row) { row.root = self.rows; row.is_expanded = (row.children.length > 0); -- cgit v1.2.3 From d41ca29475074bfccf79d9206019913e0c16f5ff Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 28 Nov 2013 14:01:46 +0100 Subject: [IMP] adds some rudimentary support to the integration of search bar groupby into the graph view (addon web_graph) bzr revid: ged@openerp.com-20131128130146-33i0ydw9gbjqgc0v --- addons/web_graph/static/src/js/graph.js | 6 ++- addons/web_graph/static/src/js/pivot.js | 84 +++++++++++++++++++++------------ 2 files changed, 59 insertions(+), 31 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 689cccaab14..94c5a4011f9 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -180,7 +180,11 @@ instance.web_graph.GraphView = instance.web.View.extend({ do_search: function (domain, context, group_by) { this.pivot_table.domain = domain; - this.pivot_table.update_values().done(this.proxy('display_data')); + if (group_by.length > 0) { + this.pivot_table.set_row_groupby(group_by).done(this.proxy('display_data')); + } else { + this.pivot_table.update_values().done(this.proxy('display_data')); + } }, do_show: function () { diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 5d5b70ebc45..621d3fbeb3d 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -182,6 +182,31 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }); }, + set_row_groupby: function (groupby) { + var self = this; + this.rows.groupby = groupby; + return this.query_all_values().then(function (result) { + if (result) { + self.no_data = false; + self.rows.headers = result.row_headers; + self.cols.headers = self.update_headers(self.cols.headers, result.col_headers); + self.cells = result.cells; + self.cols.main = self.cols.headers[0]; + self.rows.main = self.rows.headers[0]; + _.each(self.rows.headers, function (row) { + row.root = self.rows; + row.is_expanded = (row.children.length > 0); + }); + _.each(self.cols.headers, function (col) { + col.root = self.cols; + }); + + } else { + self.no_data = true; + } + }); + }, + get_total: function (header) { if (header) { var main = (header.root === this.rows) ? this.cols.main : this.rows.main; @@ -191,6 +216,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } }, + update_values: function () { if (!this.rows.headers) { return this.expand_all(); @@ -201,39 +227,11 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ return undefined; } self.no_data = false; - self.cols.headers = update_headers(self.cols.headers, result.col_headers); - self.rows.headers = update_headers(self.rows.headers, result.row_headers); + self.cols.headers = self.update_headers(self.cols.headers, result.col_headers); + self.rows.headers = self.update_headers(self.rows.headers, result.row_headers); self.cols.main = self.cols.headers[0]; self.rows.main = self.rows.headers[0]; - - function update_headers (old_headers, new_headers) { - _.each(old_headers, function (header) { - var corresponding_header = _.find(new_headers, function (h) { - return _.isEqual(h.path, header.path); - }); - if (corresponding_header && (header.is_expanded)) { - corresponding_header.is_expanded = true; - _.each(corresponding_header.children, function (c) { - c.is_expanded = false; - }); - } - if (corresponding_header && (!header.is_expanded)) { - corresponding_header.is_expanded = false; - } - }); - var updated_headers = _.filter(new_headers, function (header) { - return (header.is_expanded !== undefined); - }); - _.each(updated_headers, function (hdr) { - if (!hdr.is_expanded) { - hdr.children = []; - } - }); - - return updated_headers; - } - _.each(self.rows.headers, function (row) { row.root = self.rows; }); @@ -244,6 +242,32 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }); }, + update_headers: function (old_headers, new_headers) { + _.each(old_headers, function (header) { + var corresponding_header = _.find(new_headers, function (h) { + return _.isEqual(h.path, header.path); + }); + if (corresponding_header && (header.is_expanded)) { + corresponding_header.is_expanded = true; + _.each(corresponding_header.children, function (c) { + c.is_expanded = false; + }); + } + if (corresponding_header && (!header.is_expanded)) { + corresponding_header.is_expanded = false; + } + }); + var updated_headers = _.filter(new_headers, function (header) { + return (header.is_expanded !== undefined); + }); + _.each(updated_headers, function (hdr) { + if (!hdr.is_expanded) { + hdr.children = []; + } + }); + return updated_headers; + }, + // this method is a little tricky. In order to obtain all the values // required to draw the full table, we have to do at least // 2 + min(row.groupby.length, col.groupby.length) -- cgit v1.2.3 From 2a3eb6c336a66fd27721898474b5d12d1e87c72d Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 28 Nov 2013 14:38:54 +0100 Subject: [REF] removes duplicated code in update/expand methods (addon web_graph) bzr revid: ged@openerp.com-20131128133854-28k6utrer7cdsz4z --- addons/web_graph/static/src/js/pivot.js | 59 +++++++++++---------------------- 1 file changed, 20 insertions(+), 39 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 621d3fbeb3d..a9ef922819f 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -158,23 +158,12 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ expand_all: function () { var self = this; - return this.query_all_values().then(function (result) { if (result) { self.no_data = false; - self.rows.headers = result.row_headers; - self.cols.headers = result.col_headers; + self.expand_headers(self.rows, result.row_headers); + self.expand_headers(self.cols, result.col_headers); self.cells = result.cells; - self.rows.main = self.rows.headers[0]; - self.cols.main = self.cols.headers[0]; - _.each(self.rows.headers, function (row) { - row.root = self.rows; - row.is_expanded = (row.children.length > 0); - }); - _.each(self.cols.headers, function (col) { - col.root = self.cols; - col.is_expanded = (col.children.length > 0); - }); } else { self.no_data = true; } @@ -182,25 +171,24 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }); }, + expand_headers: function (root, new_headers) { + root.headers = new_headers; + root.main = new_headers[0]; + _.each(root.headers, function (header) { + header.root = root; + header.is_expanded = (header.children.length > 0); + }); + }, + set_row_groupby: function (groupby) { var self = this; this.rows.groupby = groupby; return this.query_all_values().then(function (result) { if (result) { self.no_data = false; - self.rows.headers = result.row_headers; - self.cols.headers = self.update_headers(self.cols.headers, result.col_headers); + self.expand_headers(self.rows, result.row_headers); + self.update_headers(self.cols, result.col_headers); self.cells = result.cells; - self.cols.main = self.cols.headers[0]; - self.rows.main = self.rows.headers[0]; - _.each(self.rows.headers, function (row) { - row.root = self.rows; - row.is_expanded = (row.children.length > 0); - }); - _.each(self.cols.headers, function (col) { - col.root = self.cols; - }); - } else { self.no_data = true; } @@ -227,23 +215,14 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ return undefined; } self.no_data = false; - self.cols.headers = self.update_headers(self.cols.headers, result.col_headers); - self.rows.headers = self.update_headers(self.rows.headers, result.row_headers); - self.cols.main = self.cols.headers[0]; - self.rows.main = self.rows.headers[0]; - - _.each(self.rows.headers, function (row) { - row.root = self.rows; - }); - _.each(self.cols.headers, function (col) { - col.root = self.cols; - }); + self.update_headers(self.cols, result.col_headers); + self.update_headers(self.rows, result.row_headers); self.cells = result.cells; }); }, - update_headers: function (old_headers, new_headers) { - _.each(old_headers, function (header) { + update_headers: function (root, new_headers) { + _.each(root.headers, function (header) { var corresponding_header = _.find(new_headers, function (h) { return _.isEqual(h.path, header.path); }); @@ -264,8 +243,10 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ if (!hdr.is_expanded) { hdr.children = []; } + hdr.root = root; }); - return updated_headers; + root.headers = updated_headers; + root.main = root.headers[0]; }, // this method is a little tricky. In order to obtain all the values -- cgit v1.2.3 From 55bbabaf46cbc50e959192fdb8310a07afe77aef Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 28 Nov 2013 14:49:04 +0100 Subject: [IMP] changes the set_row_groupby method into set_groupby (more generic, works for rows and cols) (addon web_graph) bzr revid: ged@openerp.com-20131128134904-ubkxdowr29is2o86 --- addons/web_graph/static/src/js/graph.js | 3 ++- addons/web_graph/static/src/js/pivot.js | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 94c5a4011f9..450a86a470a 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -181,7 +181,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ do_search: function (domain, context, group_by) { this.pivot_table.domain = domain; if (group_by.length > 0) { - this.pivot_table.set_row_groupby(group_by).done(this.proxy('display_data')); + this.pivot_table.set_groupby(this.pivot_table.rows, group_by) + .done(this.proxy('display_data')); } else { this.pivot_table.update_values().done(this.proxy('display_data')); } diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index a9ef922819f..bca759a13e5 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -180,14 +180,24 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }); }, - set_row_groupby: function (groupby) { + set_groupby: function (root, groupby) { var self = this; - this.rows.groupby = groupby; + var other_root = (root === this.cols) ? this.rows : this.cols; + + root.groupby = groupby; return this.query_all_values().then(function (result) { if (result) { + var new_root_headers, new_other_root_headers; + if (root === this.cols) { + new_root_headers = result.col_headers; + new_other_root_headers = result.how_headers; + } else { + new_root_headers = result.row_headers; + new_other_root_headers = result.col_headers; + } self.no_data = false; - self.expand_headers(self.rows, result.row_headers); - self.update_headers(self.cols, result.col_headers); + self.expand_headers(root, new_root_headers); + self.update_headers(other_root, new_other_root_headers); self.cells = result.cells; } else { self.no_data = true; -- cgit v1.2.3 From 8013a154b80766779cbe2cbad101bc3669e0e41f Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 28 Nov 2013 15:18:03 +0100 Subject: [FIX] fixes a crash that occurred when a graph view had a starting groupby (given by the search view) (in addon web_graph) bzr revid: ged@openerp.com-20131128141803-j0ttpgedic84quvy --- addons/web_graph/static/src/js/pivot.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index bca759a13e5..38dad2c33cb 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -232,6 +232,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }, update_headers: function (root, new_headers) { + if (!root.main) { + return this.expand_headers(root, new_headers); + } _.each(root.headers, function (header) { var corresponding_header = _.find(new_headers, function (h) { return _.isEqual(h.path, header.path); -- cgit v1.2.3 From e2d2d51b7a7e9a77cb8b89e4adee35763e61201a Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 28 Nov 2013 15:51:55 +0100 Subject: [IMP] supports the attribute 'type' in the xml definition of the graph view, at least for bar_charts (addon web_graph) bzr revid: ged@openerp.com-20131128145155-b5w4fhw9vrp9txuc --- addons/web_graph/static/src/js/charts.js | 5 +++-- addons/web_graph/static/src/js/graph.js | 4 ++++ addons/web_graph/static/src/xml/web_graph.xml | 2 -- 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index 2ac84085ce1..35585c73c09 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -2,8 +2,9 @@ openerp.web_graph.draw_chart = function (mode, pivot, svg) { var data = _.map(pivot.rows.main.children, function (pt) { - var val = pivot.get_value(pt.id, pivot.cols.main.id); - return {x: pt.title, y: val}; + var value = pivot.get_value(pt.id, pivot.cols.main.id), + title = (pt.title !== undefined) ? pt.title : 'Undefined'; + return {x: title, y: value}; }); switch (mode) { diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 450a86a470a..77f444948b5 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -122,6 +122,10 @@ instance.web_graph.GraphView = instance.web.View.extend({ model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}), row_groupby = []; + if (fields_view_get.arch.attrs.type === 'bar') { + this.mode = 'bar_chart'; + } + // get the default groupbys and measure defined in the field view _.each(fields_view_get.arch.children, function (field) { if ('name' in field.attrs) { diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 33cc1a728c5..9a969a23eae 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -60,8 +60,6 @@ -
  • -
  • Clear groups
  • -- cgit v1.2.3 From 15547d9267178493a22074b20b68099eb5948abb Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 5 Dec 2013 11:07:10 +0100 Subject: [REF] refactors the event handling code and prepare the way for supporting col_groupby and groupby in the searchbar (addon web_graph) bzr revid: ged@openerp.com-20131205100710-5owdxv0m971ymwbs --- addons/web_graph/static/src/js/charts.js | 1 - addons/web_graph/static/src/js/graph.js | 248 ++++++++++++++++++++++--------- addons/web_graph/static/src/js/pivot.js | 15 ++ 3 files changed, 191 insertions(+), 73 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index 35585c73c09..5f17cce4aef 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -18,7 +18,6 @@ openerp.web_graph.draw_chart = function (mode, pivot, svg) { pie_chart(); break; } - function bar_chart () { nv.addGraph(function () { var chart = nv.models.discreteBarChart() diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 77f444948b5..f1c9b62e137 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -15,8 +15,7 @@ var QWeb = instance.web.qweb; instance.web.views.add('graph', 'instance.web_graph.GraphView'); /** - * GraphView view. It mostly contains a widget (PivotTable), some data, and - * calls to charts function. + * GraphView */ instance.web_graph.GraphView = instance.web.View.extend({ template: 'GraphView', @@ -24,72 +23,12 @@ instance.web_graph.GraphView = instance.web.View.extend({ view_type: 'graph', events: { - 'click .graph_mode_selection li' : function (event) { - event.preventDefault(); - var mode = event.target.attributes['data-mode'].nodeValue; - this.mode = mode; - this.display_data(); - }, - - 'click .graph_measure_selection li' : function (event) { - event.preventDefault(); - var measure = event.target.attributes['data-choice'].nodeValue; - this.measure = (measure === '__count') ? null : measure; - this.pivot_table.set_measure(this.measure) - .then(this.proxy('display_data')); - }, - - 'click .graph_expand_selection li' : function (event) { - event.preventDefault(); - switch (event.target.attributes['data-choice'].nodeValue) { - case 'fold_columns': - this.pivot_table.fold_cols(); - this.display_data(); - break; - case 'fold_rows': - this.pivot_table.fold_rows(); - this.display_data(); - break; - case 'fold_all': - this.pivot_table.fold_all(); - this.display_data(); - break; - case 'expand_all': - this.pivot_table.expand_all().then(this.proxy('display_data')); - break; - } - }, - - 'click .graph_options_selection li' : function (event) { - event.preventDefault(); - switch (event.target.attributes['data-choice'].nodeValue) { - case 'swap_axis': - this.pivot_table.swap_axis(); - this.display_data(); - break; - case 'update_values': - this.pivot_table.update_values().then(this.proxy('display_data')); - break; - case 'export_data': - // Export code... To do... - break; - } - }, - - 'click .web_graph_click' : function (event) { - event.preventDefault(); - event.stopPropagation(); - var id = event.target.attributes['data-id'].nodeValue; - this.handle_header_event({id:id, event:event}); - }, - - 'click a.field-selection' : function (event) { - var id = event.target.attributes['data-id'].nodeValue, - field_id = event.target.attributes['data-field-id'].nodeValue; - event.preventDefault(); - this.pivot_table.expand(id, field_id) - .then(this.proxy('display_data')); - }, + 'click .graph_mode_selection li' : 'mode_selection', + 'click .graph_measure_selection li' : 'measure_selection', + 'click .graph_expand_selection li' : 'expand_selection', + 'click .graph_options_selection li' : 'option_selection', + 'click .web_graph_click' : 'cell_click_callback', + 'click a.field-selection' : 'field_selection', }, init: function(parent, dataset, view_id, options) { @@ -103,6 +42,12 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.measure = null; this.measure_list = []; this.important_fields = []; + this.search_view = parent.searchview; + this.search_field = { + get_context: function () { }, + get_domain: function () { }, + get_groupby: function () { }, + }; }, start: function () { @@ -183,12 +128,38 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, do_search: function (domain, context, group_by) { + console.log("START DO SEARCH",group_by); + var self = this; + this.pivot_table.domain = domain; if (group_by.length > 0) { this.pivot_table.set_groupby(this.pivot_table.rows, group_by) .done(this.proxy('display_data')); } else { - this.pivot_table.update_values().done(this.proxy('display_data')); + this.pivot_table.update_values().done(this.proxy('display_data')); + } + + var colgroupby = get_search_col_groupby(); + console.log ("colgroupby", colgroupby); + console.log("pivot cbh",this.pivot_table.cols.groupby); + + if (!_.isEqual(colgroupby, this.pivot_table.cols.groupby)) { + // console.log ('yop'); + // this.pivot_table.set_groupby(this.pivot_table.cols, colgroupby) + // .done(this.proxy('display_data')); + } + // console.log("query",this.search_view.query.models); + function get_search_col_groupby() { + var colgroupby = [], + search = _.find(self.search_view.query.models, function (model) { + return model.attributes.category == 'ColGroupBy'; + }); + if (search) { + colgroupby = _.map(search.values.models, function (val) { + return val.attributes.value; + }); + } + return colgroupby; } }, @@ -198,6 +169,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, display_data: function () { + console.log('displaying data'); this.$('.graph_main_content svg').remove(); this.table.empty(); @@ -216,6 +188,11 @@ instance.web_graph.GraphView = instance.web.View.extend({ } }, + +/****************************************************************************** + * Event handling methods... + ******************************************************************************/ + handle_header_event: function (options) { var pivot = this.pivot_table, id = options.id, @@ -237,6 +214,127 @@ instance.web_graph.GraphView = instance.web.View.extend({ } }, + + mode_selection: function (event) { + event.preventDefault(); + var mode = event.target.attributes['data-mode'].nodeValue; + this.mode = mode; + this.display_data(); + // console.log('yop'); + // var self = this; + // var attr = [{label: self.fields['user_id'].string, value: 'user_id'}]; + // var attr2 = [{label: self.fields['user_id'].string, value: { + // attrs: {domain: [], context: {'group_by':'user_id'}} + // }}]; + // var groupbytest = { + // category: 'GroupBy', + // values: attr2, + // icon: 'u', + // field: self.search_view._s_groupby, + // }; + + // // console.log("rnst",self.search_view); + // var test = { + // values: attr, + // icon: 'u', + // field: self.search_field, + // category: _t("ColGroupBy"), + // }; + // self.search_view.query.add(test); + // self.search_view.query.add(groupbytest, {}); + + }, + + + measure_selection: function (event) { + event.preventDefault(); + var measure = event.target.attributes['data-choice'].nodeValue; + this.measure = (measure === '__count') ? null : measure; + this.pivot_table.set_measure(this.measure) + .then(this.proxy('display_data')); + }, + + expand_selection: function (event) { + event.preventDefault(); + switch (event.target.attributes['data-choice'].nodeValue) { + case 'fold_columns': + this.pivot_table.fold_cols(); + this.display_data(); + break; + case 'fold_rows': + this.pivot_table.fold_rows(); + this.display_data(); + break; + case 'fold_all': + this.pivot_table.fold_all(); + this.display_data(); + break; + case 'expand_all': + this.pivot_table.expand_all().then(this.proxy('display_data')); + break; + } + }, + + option_selection: function (event) { + event.preventDefault(); + switch (event.target.attributes['data-choice'].nodeValue) { + case 'swap_axis': + this.pivot_table.swap_axis(); + this.display_data(); + break; + case 'update_values': + this.pivot_table.update_values().then(this.proxy('display_data')); + break; + case 'export_data': + // Export code... To do... + break; + } + }, + + + cell_click_callback: function (event) { + event.preventDefault(); + event.stopPropagation(); + var id = event.target.attributes['data-id'].nodeValue; + this.handle_header_event({id:id, event:event}); + }, + + field_selection: function (event) { + var self = this, + id = event.target.attributes['data-id'].nodeValue, + field_id = event.target.attributes['data-field-id'].nodeValue; + event.preventDefault(); + this.pivot_table.expand(id, field_id).then(function () { + + var attr = [{label: self.fields[field_id].string, value: field_id}]; + var attr2 = [{label: self.fields[field_id].string, value: { + attrs: {domain: [], context: {'group_by':'stage_id'}} + }}]; + + var test = { + values: attr, + icon: 'u', + field: self.search_field, + category: _t("ColGroupBy"), + }; + + var groupbytest = { + category: 'GroupBy', + values: attr2, + icon: 'u', + field: self.search_view._s_groupby, + }; + + // console.log("rnst",self.search_view); + console.log('BEF ADD CGB'); + // self.search_view.query.add(test); + console.log('BEF ADD RGB'); + // self.search_view.query.add(groupbytest, {}); + console.log('AFTER ADD GB'); + self.display_data(); + }); + }, + display_dropdown: function (options) { var self = this, pivot = this.pivot_table, @@ -256,9 +354,9 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.$('.field-selection').next('.dropdown-menu').toggle(); }, - measure_label: function () { - return (this.measure) ? this.fields[this.measure].string : 'Quantity'; - }, +/****************************************************************************** + * Drawing pivot table methods... + ******************************************************************************/ draw_table: function () { this.pivot_table.rows.main.title = 'Total'; @@ -267,6 +365,10 @@ instance.web_graph.GraphView = instance.web.View.extend({ _.each(this.pivot_table.rows.headers, this.proxy('draw_row')); }, + measure_label: function () { + return (this.measure) ? this.fields[this.measure].string : 'Quantity'; + }, + make_border_cell: function (colspan, rowspan) { return $('').addClass('graph_border') .attr('colspan', colspan) @@ -392,4 +494,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, }); + + }; diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 38dad2c33cb..f412d59474b 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -1,6 +1,9 @@ /* jshint undef: false */ + +// TO DO : use _.uniqueID() + (function () { 'use strict'; @@ -60,6 +63,18 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ return this.update_values(); }, + is_row: function (id) { + return !!_.find(this.rows.headers, function (header) { + return header.id == id; + }); + }, + + is_col: function (id) { + return !!_.find(this.cols.headers, function (header) { + return header.id == id; + }); + }, + get_header: function (id) { return _.find(this.rows.headers.concat(this.cols.headers), function (header) { return header.id == id; -- cgit v1.2.3 From d3fffbff509f171fe658181891d90f0476f5145b Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 5 Dec 2013 16:19:45 +0100 Subject: [IMP] beginning of searchbar integration in graph view (addon web_graph) bzr revid: ged@openerp.com-20131205151945-8yo2vkykztvlru3g --- addons/web_graph/static/src/js/graph.js | 202 ++++++++++++++++++-------------- addons/web_graph/static/src/js/pivot.js | 145 ++++++++++++----------- 2 files changed, 194 insertions(+), 153 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index f1c9b62e137..83f9ee4e33c 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -33,12 +33,14 @@ instance.web_graph.GraphView = instance.web.View.extend({ init: function(parent, dataset, view_id, options) { this._super(parent); + + this.model = new instance.web.Model(dataset.model, {group_by_no_leaf: true}); this.dataset = dataset; + + this.pivot_table = new openerp.web_graph.PivotTable(this.model, dataset.domain); this.set_default_options(options); this.dropdown = null; - this.pivot_table = null; - this.heat_map_mode = false; - this.mode = 'pivot'; + this.mode = 'pivot'; // pivot, bar_chart, line_chart, pie_chart, heatmap, row_heatmap, col_heatmap this.measure = null; this.measure_list = []; this.important_fields = []; @@ -48,6 +50,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ get_domain: function () { }, get_groupby: function () { }, }; + this.groupby_mode = 'default'; // 'default' or 'manual' + this.default_row_groupby = []; }, start: function () { @@ -64,8 +68,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ view_loading: function (fields_view_get) { var self = this, - model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}), - row_groupby = []; + measure = null; if (fields_view_get.arch.attrs.type === 'bar') { this.mode = 'bar_chart'; @@ -77,17 +80,18 @@ instance.web_graph.GraphView = instance.web.View.extend({ if ('operator' in field.attrs) { self.measure_list.push(field.attrs.name); } else { - row_groupby.push(field.attrs.name); + self.default_row_groupby.push(field.attrs.name); } } }); if (this.measure_list.length > 0) { - this.measure = this.measure_list[0]; + measure = this.measure_list[0]; + this.pivot_table.set_measure(measure); } // get the most important fields (of the model) by looking at the // groupby filters defined in the search view - var options = {model:model, view_type: 'search'}, + var options = {model:this.model, view_type: 'search'}, deferred1 = instance.web.fields_view_get(options).then(function (search_view) { var groups = _.select(search_view.arch.children, function (c) { return (c.tag == 'group') && (c.attrs.string != 'Display'); @@ -103,8 +107,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ }); // get the fields descriptions from the model - var deferred2 = model.call('fields_get', []).then(function (fs) { - self.fields = fs; + var deferred2 = this.model.call('fields_get', []).then(function (fs) { + self.fields = fs; var measure_selection = self.$('.graph_measure_selection'); _.each(self.measure_list, function (measure) { var choice = $('').attr('data-choice', measure) @@ -115,51 +119,41 @@ instance.web_graph.GraphView = instance.web.View.extend({ }); }); - return $.when(deferred1, deferred2).then(function () { - var data = { - model: model, - domain: [], - measure: self.measure, - col_groupby: [], - row_groupby: row_groupby, - }; - self.pivot_table = new openerp.web_graph.PivotTable(data); - }); + return $.when(deferred1, deferred2); }, do_search: function (domain, context, group_by) { - console.log("START DO SEARCH",group_by); - var self = this; + var self = this, + col_groupby = get_col_groupby('ColGroupBy'); - this.pivot_table.domain = domain; - if (group_by.length > 0) { - this.pivot_table.set_groupby(this.pivot_table.rows, group_by) - .done(this.proxy('display_data')); - } else { - this.pivot_table.update_values().done(this.proxy('display_data')); + if (group_by.length || col_groupby.length) { + this.groupby_mode = 'manual'; + if (!group_by.length) { + group_by = this.default_row_groupby; + } } - var colgroupby = get_search_col_groupby(); - console.log ("colgroupby", colgroupby); - console.log("pivot cbh",this.pivot_table.cols.groupby); - - if (!_.isEqual(colgroupby, this.pivot_table.cols.groupby)) { - // console.log ('yop'); - // this.pivot_table.set_groupby(this.pivot_table.cols, colgroupby) - // .done(this.proxy('display_data')); + this.pivot_table.set_domain(domain); + if (this.groupby_mode === 'manual') { + this.pivot_table.set_row_groupby(group_by); + this.pivot_table.set_col_groupby(col_groupby); + } else { + this.pivot_table.set_row_groupby(this.default_row_groupby); + this.pivot_table.set_col_groupby([]); } - // console.log("query",this.search_view.query.models); - function get_search_col_groupby() { - var colgroupby = [], + this.display_data(); + + function get_col_groupby() { + var groupby = [], search = _.find(self.search_view.query.models, function (model) { return model.attributes.category == 'ColGroupBy'; }); if (search) { - colgroupby = _.map(search.values.models, function (val) { + groupby = _.map(search.values.models, function (val) { return val.attributes.value; }); } - return colgroupby; + return groupby; } }, @@ -169,21 +163,25 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, display_data: function () { - console.log('displaying data'); - this.$('.graph_main_content svg').remove(); - this.table.empty(); - - if (this.pivot_table.no_data) { - var msg = 'No data available. Try to remove any filter or add some data.'; - this.table.append($('' + msg + '')); + var pivot = this.pivot_table; + if (pivot.stale_data) { + pivot.update_data().done(this.proxy('display_data')); } else { - var table_modes = ['pivot', 'heatmap', 'row_heatmap', 'col_heatmap']; - if (_.contains(table_modes, this.mode)) { - this.draw_table(); + this.$('.graph_main_content svg').remove(); + this.table.empty(); + + if (pivot.no_data) { + var msg = 'No data available. Try to remove any filter or add some data.'; + this.table.append($('' + msg + '')); } else { - this.$('.graph_main_content').append($('
    ')); - var svg = this.$('.graph_main_content svg')[0]; - openerp.web_graph.draw_chart(this.mode, this.pivot_table, svg); + var table_modes = ['pivot', 'heatmap', 'row_heatmap', 'col_heatmap']; + if (_.contains(table_modes, this.mode)) { + this.draw_table(); + } else { + this.$('.graph_main_content').append($('
    ')); + var svg = this.$('.graph_main_content svg')[0]; + openerp.web_graph.draw_chart(this.mode, this.pivot_table, svg); + } } } }, @@ -221,8 +219,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.mode = mode; this.display_data(); // console.log('yop'); - // var self = this; - // var attr = [{label: self.fields['user_id'].string, value: 'user_id'}]; // var attr2 = [{label: self.fields['user_id'].string, value: { // attrs: {domain: [], context: {'group_by':'user_id'}} // }}]; @@ -234,24 +230,48 @@ instance.web_graph.GraphView = instance.web.View.extend({ // }; // // console.log("rnst",self.search_view); + // var self = this; + // var attr = [{label: self.fields['user_id'].string, value: 'user_id'}]; // var test = { // values: attr, // icon: 'u', // field: self.search_field, // category: _t("ColGroupBy"), // }; - // self.search_view.query.add(test); + // self.search_view.query.add(test); // self.search_view.query.add(groupbytest, {}); }, + register_groupby: function (category, field) { + var groupby; + if (category === 'ColGroupBy') { + groupby = { + category: 'ColGroupBy', + values: [{label: this.fields[field].string, value: field}], + icon: 'u', + field: this.search_field, + }; + this.search_view.query.add(groupby); + } + if (category === 'GroupBy') { + var value = {attrs: {domain: [], context: {'group_by':field}}}; + groupby = { + category: 'GroupBy', + values: [{label: this.fields[field].string, value: value}], + icon: 'u', + field: this.search_view._s_groupby, + }; + this.search_view.query.add(groupby); + } + }, measure_selection: function (event) { event.preventDefault(); var measure = event.target.attributes['data-choice'].nodeValue; this.measure = (measure === '__count') ? null : measure; - this.pivot_table.set_measure(this.measure) - .then(this.proxy('display_data')); + this.pivot_table.set_measure(this.measure); + this.display_data(); }, expand_selection: function (event) { @@ -270,7 +290,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.display_data(); break; case 'expand_all': - this.pivot_table.expand_all().then(this.proxy('display_data')); + this.pivot_table.invalidate_data(); + this.display_data(); break; } }, @@ -283,7 +304,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.display_data(); break; case 'update_values': - this.pivot_table.update_values().then(this.proxy('display_data')); + this.pivot_table.stale_data = true; + this.display_data(); break; case 'export_data': // Export code... To do... @@ -306,32 +328,38 @@ instance.web_graph.GraphView = instance.web.View.extend({ event.preventDefault(); this.pivot_table.expand(id, field_id).then(function () { - var attr = [{label: self.fields[field_id].string, value: field_id}]; - var attr2 = [{label: self.fields[field_id].string, value: { - attrs: {domain: [], context: {'group_by':'stage_id'}} - }}]; - - var test = { - values: attr, - icon: 'u', - field: self.search_field, - category: _t("ColGroupBy"), - }; - - var groupbytest = { - category: 'GroupBy', - values: attr2, - icon: 'u', - field: self.search_view._s_groupby, - }; - - // console.log("rnst",self.search_view); - console.log('BEF ADD CGB'); - // self.search_view.query.add(test); - console.log('BEF ADD RGB'); - // self.search_view.query.add(groupbytest, {}); - console.log('AFTER ADD GB'); - self.display_data(); + if (self.pivot_table.is_col(id)) { + self.register_groupby('ColGroupBy', field_id); + } else { + self.register_groupby('GroupBy', field_id); + // self.display_data(); + } + // var attr = [{label: self.fields[field_id].string, value: field_id}]; + // var attr2 = [{label: self.fields[field_id].string, value: { + // attrs: {domain: [], context: {'group_by':'stage_id'}} + // }}]; + + // var test = { + // values: attr, + // icon: 'u', + // field: self.search_field, + // category: _t("ColGroupBy"), + // }; + + // var groupbytest = { + // category: 'GroupBy', + // values: attr2, + // icon: 'u', + // field: self.search_view._s_groupby, + // }; + + // // console.log("rnst",self.search_view); + // console.log('BEF ADD CGB'); + // // self.search_view.query.add(test); + // console.log('BEF ADD RGB'); + // // self.search_view.query.add(groupbytest, {}); + // console.log('AFTER ADD GB'); + // self.display_data(); }); }, diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index f412d59474b..5446fd36fb3 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -8,19 +8,17 @@ 'use strict'; openerp.web_graph.PivotTable = openerp.web.Class.extend({ - init: function (options) { - this.rows = { groupby: options.row_groupby }; - this.cols = { groupby: [] }; + init: function (model, domain) { + this.rows = { groupby: [], main: null, headers: null }; + this.cols = { groupby: [], main: null, headers: null }; this.cells = []; - this.model = options.model; - this.domain = options.domain; - this.measure = options.measure; + this.model = model; + this.domain = domain; + this.measure = null; + this.id_seed = 0; this.no_data = true; - }, - - start: function () { - return this.expand_all(); + this.stale_data = true; }, generate_id: function () { @@ -36,6 +34,34 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ return result; }, + set_domain: function (domain) { + if (!_.isEqual(domain, this.domain)) { + this.domain = domain; + this.stale_data = true; + } + }, + + set_measure: function (measure) { + if (measure !== this.measure) { + this.measure = measure; + this.stale_data = true; + } + }, + + set_row_groupby: function (groupby) { + if (!_.isEqual(groupby, this.rows.groupby)) { + this.rows.groupby = groupby; + this.stale_data = true; + } + }, + + set_col_groupby: function (groupby) { + if (!_.isEqual(groupby, this.cols.groupby)) { + this.cols.groupby = groupby; + this.stale_data = true; + } + }, + set_value: function (id1, id2, value) { var x = Math.min(id1, id2), y = Math.max(id1, id2), @@ -58,11 +84,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ return (cell === undefined) ? undefined : cell.value; }, - set_measure: function (measure) { - this.measure = measure; - return this.update_values(); - }, - is_row: function (id) { return !!_.find(this.rows.headers, function (header) { return header.id == id; @@ -118,26 +139,26 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ var other = _.find(otherDim.headers, function (h) { if (header.root === self.cols) { return _.isEqual(data.path.slice(1), h.path); - } else { - return _.isEqual(_.rest(data.path), h.path); - } - }); - if (other) { - if (self.measure) { - self.set_value(new_header_id, other.id, data.attributes.aggregates[self.measure]); - } else { - self.set_value(new_header_id, other.id, data.attributes.length); - } - } - }); - }); - header.is_expanded = true; - }); + } else { + return _.isEqual(_.rest(data.path), h.path); + } + }); + if (other) { + if (self.measure) { + self.set_value(new_header_id, other.id, data.attributes.aggregates[self.measure]); + } else { + self.set_value(new_header_id, other.id, data.attributes.length); + } + } + }); + }); + header.is_expanded = true; + }); }, make_header: function (groups, parent) { var name = groups[0].attributes.value[1], - new_header = { + new_header = { id: this.generate_id(), path: parent.path.concat(name), title: name, @@ -171,21 +192,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ this.fold_cols(); }, - expand_all: function () { - var self = this; - return this.query_all_values().then(function (result) { - if (result) { - self.no_data = false; - self.expand_headers(self.rows, result.row_headers); - self.expand_headers(self.cols, result.col_headers); - self.cells = result.cells; - } else { - self.no_data = true; - } - - }); - }, - expand_headers: function (root, new_headers) { root.headers = new_headers; root.main = new_headers[0]; @@ -229,27 +235,36 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } }, + invalidate_data: function () { + this.cells = null; + this.rows.main = null; + this.cols.main = null; + this.rows.headers = null; + this.cols.headers = null; + this.stale_data = true; + }, - update_values: function () { - if (!this.rows.headers) { - return this.expand_all(); - } + update_data: function () { var self = this; return this.query_all_values().then(function (result) { - if (!result) { - return undefined; + self.stale_data = false; + if (result) { + self.no_data = false; + if (self.cols.headers) { + self.update_headers(self.cols, result.col_headers); + self.update_headers(self.rows, result.row_headers); + } else { + self.expand_headers(self.cols, result.col_headers); + self.expand_headers(self.rows, result.row_headers); + } + self.cells = result.cells; + } else { + self.no_data = true; } - self.no_data = false; - self.update_headers(self.cols, result.col_headers); - self.update_headers(self.rows, result.row_headers); - self.cells = result.cells; }); }, update_headers: function (root, new_headers) { - if (!root.main) { - return this.expand_headers(root, new_headers); - } _.each(root.headers, function (header) { var corresponding_header = _.find(new_headers, function (h) { return _.isEqual(h.path, header.path); @@ -279,7 +294,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ // this method is a little tricky. In order to obtain all the values // required to draw the full table, we have to do at least - // 2 + min(row.groupby.length, col.groupby.length) + // 2 + min(row.groupby.length, col.groupby.length) // calls to readgroup. For example, if row.groupby = [r1, r2, r3] and // col.groupby = [c1, c2, c3, c4], then a minimal set of calls is done // with the following groupby: @@ -317,10 +332,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ row_data = _.last(_.initial(args)), cell_data = args; - if (total === undefined) { self.no_data = true;} - return (total === undefined) - ? undefined - : self.format_data(total, col_data, row_data, cell_data); + return (total === undefined) ? undefined + : self.format_data(total, col_data, row_data, cell_data); }); }, @@ -343,8 +356,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } return {col_headers: col_headers, - row_headers: row_headers, - cells: cells}; + row_headers: row_headers, + cells: cells}; function make_headers (data, depth) { var main = { -- cgit v1.2.3 From d1caee2a5f04ff5919e5a6f1240a867832a480f6 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 6 Dec 2013 13:44:37 +0100 Subject: [IMP] supports search bar integration in graph view (but not everything works yet) (addon web_graph) bzr revid: ged@openerp.com-20131206124437-8m1gnhz3ill6w1eo --- addons/web_graph/static/src/js/graph.js | 164 ++++++++++++++++++-------------- addons/web_graph/static/src/js/pivot.js | 30 +----- 2 files changed, 97 insertions(+), 97 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 83f9ee4e33c..bd4842eac41 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -123,14 +123,20 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, do_search: function (domain, context, group_by) { + console.log('dgb', this.default_row_groupby); + if (this.groupby_mode === 'getting_ready') { + this.groupby_mode = 'manual'; + return; + } + var self = this, col_groupby = get_col_groupby('ColGroupBy'); if (group_by.length || col_groupby.length) { this.groupby_mode = 'manual'; - if (!group_by.length) { - group_by = this.default_row_groupby; - } + // if (!group_by.length) { + // group_by = this.default_row_groupby; + // } } this.pivot_table.set_domain(domain); @@ -138,7 +144,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.pivot_table.set_row_groupby(group_by); this.pivot_table.set_col_groupby(col_groupby); } else { - this.pivot_table.set_row_groupby(this.default_row_groupby); + this.pivot_table.set_row_groupby(_.toArray(this.default_row_groupby)); this.pivot_table.set_col_groupby([]); } this.display_data(); @@ -190,15 +196,37 @@ instance.web_graph.GraphView = instance.web.View.extend({ /****************************************************************************** * Event handling methods... ******************************************************************************/ - handle_header_event: function (options) { var pivot = this.pivot_table, id = options.id, - header = pivot.get_header(id); + header = pivot.get_header(id), + dim = header.root.groupby.length; + console.log('test'); + // debugger; if (header.is_expanded) { + this.groupby_mode = 'manual'; pivot.fold(header); - this.display_data(); + if (header.root.groupby.length < dim) { + if (pivot.is_row(header.id)) { + this.clear_groupby('GroupBy'); + if (header.root.groupby.length) { + this.register_groupby('GroupBy', header.root.groupby); + } else { + + this.display_data(); + } + } else { + this.clear_groupby('ColGroupBy'); + if (header.root.groupby.length) { + this.register_groupby('ColGroupBy', header.root.groupby); + } else { + this.display_data(); + } + } + } else { + this.display_data(); + } } else { if (header.path.length < header.root.groupby.length) { var field = header.root.groupby[header.path.length]; @@ -212,60 +240,60 @@ instance.web_graph.GraphView = instance.web.View.extend({ } }, - mode_selection: function (event) { event.preventDefault(); var mode = event.target.attributes['data-mode'].nodeValue; this.mode = mode; this.display_data(); - // console.log('yop'); - // var attr2 = [{label: self.fields['user_id'].string, value: { - // attrs: {domain: [], context: {'group_by':'user_id'}} - // }}]; - // var groupbytest = { - // category: 'GroupBy', - // values: attr2, - // icon: 'u', - // field: self.search_view._s_groupby, - // }; - - // // console.log("rnst",self.search_view); - // var self = this; - // var attr = [{label: self.fields['user_id'].string, value: 'user_id'}]; - // var test = { - // values: attr, - // icon: 'u', - // field: self.search_field, - // category: _t("ColGroupBy"), - // }; - // self.search_view.query.add(test); - // self.search_view.query.add(groupbytest, {}); }, register_groupby: function (category, field) { - var groupby; + var self = this, + values, + groupby; if (category === 'ColGroupBy') { + if (!(field instanceof Array)) { + field = [field]; + } + values = _.map(field, function (f) { + return {label: self.fields[f].string, value: f}; + }); + // values = [{label: this.fields[field].string, value: field}]; groupby = { category: 'ColGroupBy', - values: [{label: this.fields[field].string, value: field}], - icon: 'u', + values: values, + icon: 'f', field: this.search_field, }; this.search_view.query.add(groupby); } if (category === 'GroupBy') { - var value = {attrs: {domain: [], context: {'group_by':field}}}; + if (!(field instanceof Array)) { + field = [field]; + } + values = _.map(field, function (f) { + return {label: self.fields[f].string, value: {attrs:{domain: [], context: {'group_by':f}}}}; + }); + // var value = {attrs: {domain: [], context: {'group_by':field}}}; + // var value2 = {attrs: {domain: [], context: {'group_by':'user_id'}}}; [{label: this.fields[field].string, value: value}, {label: 'test', value:value2}] groupby = { category: 'GroupBy', - values: [{label: this.fields[field].string, value: value}], - icon: 'u', + values: values, + icon: 'w', field: this.search_view._s_groupby, }; this.search_view.query.add(groupby); } }, + clear_groupby: function (category) { + // debugger; + this.search_view.query.models = _.filter(this.search_view.query.models, function (model) { + return model.attributes.category !== category; + }); + }, + measure_selection: function (event) { event.preventDefault(); var measure = event.target.attributes['data-choice'].nodeValue; @@ -297,11 +325,27 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, option_selection: function (event) { + var pivot = this.pivot_table; event.preventDefault(); switch (event.target.attributes['data-choice'].nodeValue) { case 'swap_axis': this.pivot_table.swap_axis(); - this.display_data(); + this.clear_groupby('GroupBy'); + this.clear_groupby('ColGroupBy'); + if (pivot.rows.groupby.length && pivot.cols.groupby.length) { + this.groupby_mode = 'getting_ready'; + this.register_groupby('GroupBy', pivot.rows.groupby); + this.register_groupby('ColGroupBy', pivot.cols.groupby); + } else { + this.groupby_mode = 'manual'; + if (pivot.rows.groupby.length) { + this.register_groupby('GroupBy', pivot.rows.groupby); + } else { + this.register_groupby('ColGroupBy', pivot.cols.groupby); + } + } + + // this.display_data(); break; case 'update_values': this.pivot_table.stale_data = true; @@ -328,38 +372,21 @@ instance.web_graph.GraphView = instance.web.View.extend({ event.preventDefault(); this.pivot_table.expand(id, field_id).then(function () { - if (self.pivot_table.is_col(id)) { - self.register_groupby('ColGroupBy', field_id); + + if (self.pivot_table.is_row(id)) { + if (self.groupby_mode === 'default') { + self.groupby_mode = 'manual'; + self.register_groupby('GroupBy', self.default_row_groupby.concat([field_id])); + } else { + self.register_groupby('GroupBy', field_id); + } } else { - self.register_groupby('GroupBy', field_id); - // self.display_data(); + if (self.groupby_mode === 'default') { + self.groupby_mode = 'getting_ready'; + self.register_groupby('GroupBy', self.default_row_groupby); + } + self.register_groupby('ColGroupBy', field_id); } - // var attr = [{label: self.fields[field_id].string, value: field_id}]; - // var attr2 = [{label: self.fields[field_id].string, value: { - // attrs: {domain: [], context: {'group_by':'stage_id'}} - // }}]; - - // var test = { - // values: attr, - // icon: 'u', - // field: self.search_field, - // category: _t("ColGroupBy"), - // }; - - // var groupbytest = { - // category: 'GroupBy', - // values: attr2, - // icon: 'u', - // field: self.search_view._s_groupby, - // }; - - // // console.log("rnst",self.search_view); - // console.log('BEF ADD CGB'); - // // self.search_view.query.add(test); - // console.log('BEF ADD RGB'); - // // self.search_view.query.add(groupbytest, {}); - // console.log('AFTER ADD GB'); - // self.display_data(); }); }, @@ -385,7 +412,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ /****************************************************************************** * Drawing pivot table methods... ******************************************************************************/ - draw_table: function () { this.pivot_table.rows.main.title = 'Total'; this.pivot_table.cols.main.title = this.measure_label(); @@ -522,6 +548,4 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, }); - - }; diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 5446fd36fb3..8748de7dda0 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -51,14 +51,14 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ set_row_groupby: function (groupby) { if (!_.isEqual(groupby, this.rows.groupby)) { this.rows.groupby = groupby; - this.stale_data = true; + this.invalidate_data(); } }, set_col_groupby: function (groupby) { if (!_.isEqual(groupby, this.cols.groupby)) { this.cols.groupby = groupby; - this.stale_data = true; + this.invalidate_data(); } }, @@ -201,31 +201,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }); }, - set_groupby: function (root, groupby) { - var self = this; - var other_root = (root === this.cols) ? this.rows : this.cols; - - root.groupby = groupby; - return this.query_all_values().then(function (result) { - if (result) { - var new_root_headers, new_other_root_headers; - if (root === this.cols) { - new_root_headers = result.col_headers; - new_other_root_headers = result.how_headers; - } else { - new_root_headers = result.row_headers; - new_other_root_headers = result.col_headers; - } - self.no_data = false; - self.expand_headers(root, new_root_headers); - self.update_headers(other_root, new_other_root_headers); - self.cells = result.cells; - } else { - self.no_data = true; - } - }); - }, - get_total: function (header) { if (header) { var main = (header.root === this.rows) ? this.cols.main : this.rows.main; @@ -265,6 +240,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }, update_headers: function (root, new_headers) { + console.log('updateheader', root, new_headers); _.each(root.headers, function (header) { var corresponding_header = _.find(new_headers, function (h) { return _.isEqual(h.path, header.path); -- cgit v1.2.3 From 6a06f0d0eeee1efe7417d3a73eb2e4b8661d73d6 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 6 Dec 2013 16:43:19 +0100 Subject: [IMP] properly supports searchbar integration in graph view (addon web_graph) bzr revid: ged@openerp.com-20131206154319-6ci7ljmp2hd9q072 --- addons/web_graph/static/src/js/graph.js | 161 ++++++++++---------------------- addons/web_graph/static/src/js/pivot.js | 1 - 2 files changed, 47 insertions(+), 115 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index bd4842eac41..344899032d6 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -4,7 +4,6 @@ /* jshint undef: false */ - openerp.web_graph = function (instance) { 'use strict'; @@ -33,10 +32,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ init: function(parent, dataset, view_id, options) { this._super(parent); - this.model = new instance.web.Model(dataset.model, {group_by_no_leaf: true}); this.dataset = dataset; - this.pivot_table = new openerp.web_graph.PivotTable(this.model, dataset.domain); this.set_default_options(options); this.dropdown = null; @@ -45,13 +42,13 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.measure_list = []; this.important_fields = []; this.search_view = parent.searchview; - this.search_field = { - get_context: function () { }, - get_domain: function () { }, - get_groupby: function () { }, - }; this.groupby_mode = 'default'; // 'default' or 'manual' this.default_row_groupby = []; + this.search_field = { + get_context: function () { }, + get_domain: function () { }, + get_groupby: function () { }, + }; }, start: function () { @@ -123,12 +120,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, do_search: function (domain, context, group_by) { - console.log('dgb', this.default_row_groupby); - if (this.groupby_mode === 'getting_ready') { - this.groupby_mode = 'manual'; - return; - } - var self = this, col_groupby = get_col_groupby('ColGroupBy'); @@ -156,7 +147,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ }); if (search) { groupby = _.map(search.values.models, function (val) { - return val.attributes.value; + return val.attributes.value.attrs.context.col_group_by; }); } return groupby; @@ -202,35 +193,13 @@ instance.web_graph.GraphView = instance.web.View.extend({ header = pivot.get_header(id), dim = header.root.groupby.length; - console.log('test'); - // debugger; if (header.is_expanded) { - this.groupby_mode = 'manual'; pivot.fold(header); - if (header.root.groupby.length < dim) { - if (pivot.is_row(header.id)) { - this.clear_groupby('GroupBy'); - if (header.root.groupby.length) { - this.register_groupby('GroupBy', header.root.groupby); - } else { - - this.display_data(); - } - } else { - this.clear_groupby('ColGroupBy'); - if (header.root.groupby.length) { - this.register_groupby('ColGroupBy', header.root.groupby); - } else { - this.display_data(); - } - } - } else { - this.display_data(); - } + this.register_groupby(); } else { if (header.path.length < header.root.groupby.length) { var field = header.root.groupby[header.path.length]; - pivot.expand(id, field).then(this.proxy('display_data')); + pivot.expand(id, field).then(this.proxy('register_groupby')); } else { this.display_dropdown({id:header.id, target: $(options.event.target), @@ -248,52 +217,45 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, - register_groupby: function (category, field) { + register_groupby: function() { var self = this, - values, - groupby; - if (category === 'ColGroupBy') { - if (!(field instanceof Array)) { - field = [field]; - } - values = _.map(field, function (f) { - return {label: self.fields[f].string, value: f}; - }); - // values = [{label: this.fields[field].string, value: field}]; - groupby = { - category: 'ColGroupBy', - values: values, - icon: 'f', - field: this.search_field, - }; - this.search_view.query.add(groupby); - } - if (category === 'GroupBy') { - if (!(field instanceof Array)) { - field = [field]; + query = this.search_view.query; + this.groupby_mode = 'manual'; + + + var rows = _.map(this.pivot_table.rows.groupby, function (group) { + return make_facet('GroupBy', group); + }); + var cols = _.map(this.pivot_table.cols.groupby, function (group) { + return make_facet('ColGroupBy', group); + }); + + query.reset(rows.concat(cols)); + + function make_facet (category, fields) { + var values, + icon, + backbone_field, + cat_name; + if (!(fields instanceof Array)) { fields = [fields]; } + if (category === 'GroupBy') { + cat_name = 'group_by'; + icon = 'w'; + backbone_field = self.search_view._s_groupby; + } else { + cat_name = 'col_group_by'; + icon = 'f'; + backbone_field = self.search_field; } - values = _.map(field, function (f) { - return {label: self.fields[f].string, value: {attrs:{domain: [], context: {'group_by':f}}}}; + values = _.map(fields, function (field) { + var context = {}; + context[cat_name] = field; + return {label: self.fields[field].string, value: {attrs:{domain: [], context: context}}}; }); - // var value = {attrs: {domain: [], context: {'group_by':field}}}; - // var value2 = {attrs: {domain: [], context: {'group_by':'user_id'}}}; [{label: this.fields[field].string, value: value}, {label: 'test', value:value2}] - groupby = { - category: 'GroupBy', - values: values, - icon: 'w', - field: this.search_view._s_groupby, - }; - this.search_view.query.add(groupby); + return {category:category, values: values, icon:icon, field: backbone_field}; } }, - clear_groupby: function (category) { - // debugger; - this.search_view.query.models = _.filter(this.search_view.query.models, function (model) { - return model.attributes.category !== category; - }); - }, - measure_selection: function (event) { event.preventDefault(); var measure = event.target.attributes['data-choice'].nodeValue; @@ -307,15 +269,15 @@ instance.web_graph.GraphView = instance.web.View.extend({ switch (event.target.attributes['data-choice'].nodeValue) { case 'fold_columns': this.pivot_table.fold_cols(); - this.display_data(); + this.register_groupby(); break; case 'fold_rows': this.pivot_table.fold_rows(); - this.display_data(); + this.register_groupby(); break; case 'fold_all': this.pivot_table.fold_all(); - this.display_data(); + this.register_groupby(); break; case 'expand_all': this.pivot_table.invalidate_data(); @@ -330,28 +292,14 @@ instance.web_graph.GraphView = instance.web.View.extend({ switch (event.target.attributes['data-choice'].nodeValue) { case 'swap_axis': this.pivot_table.swap_axis(); - this.clear_groupby('GroupBy'); - this.clear_groupby('ColGroupBy'); - if (pivot.rows.groupby.length && pivot.cols.groupby.length) { - this.groupby_mode = 'getting_ready'; - this.register_groupby('GroupBy', pivot.rows.groupby); - this.register_groupby('ColGroupBy', pivot.cols.groupby); - } else { - this.groupby_mode = 'manual'; - if (pivot.rows.groupby.length) { - this.register_groupby('GroupBy', pivot.rows.groupby); - } else { - this.register_groupby('ColGroupBy', pivot.cols.groupby); - } - } - - // this.display_data(); + this.register_groupby(); break; case 'update_values': this.pivot_table.stale_data = true; this.display_data(); break; case 'export_data': + this.register_groupby(); // Export code... To do... break; } @@ -371,22 +319,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ field_id = event.target.attributes['data-field-id'].nodeValue; event.preventDefault(); this.pivot_table.expand(id, field_id).then(function () { - - - if (self.pivot_table.is_row(id)) { - if (self.groupby_mode === 'default') { - self.groupby_mode = 'manual'; - self.register_groupby('GroupBy', self.default_row_groupby.concat([field_id])); - } else { - self.register_groupby('GroupBy', field_id); - } - } else { - if (self.groupby_mode === 'default') { - self.groupby_mode = 'getting_ready'; - self.register_groupby('GroupBy', self.default_row_groupby); - } - self.register_groupby('ColGroupBy', field_id); - } + self.register_groupby(); }); }, diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 8748de7dda0..b334dbe32aa 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -240,7 +240,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }, update_headers: function (root, new_headers) { - console.log('updateheader', root, new_headers); _.each(root.headers, function (header) { var corresponding_header = _.find(new_headers, function (h) { return _.isEqual(h.path, header.path); -- cgit v1.2.3 From 5c04caf2ee2050bb0607f3ebf066e744b398d21f Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 6 Dec 2013 17:04:11 +0100 Subject: [REF] many small code cleanups in addon web_graph bzr revid: ged@openerp.com-20131206160411-9ajcschidssftb49 --- addons/web_graph/static/src/js/graph.js | 17 +++++------------ addons/web_graph/static/src/js/pivot.js | 19 +++---------------- 2 files changed, 8 insertions(+), 28 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 344899032d6..8cf0ffd4877 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -38,7 +38,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.set_default_options(options); this.dropdown = null; this.mode = 'pivot'; // pivot, bar_chart, line_chart, pie_chart, heatmap, row_heatmap, col_heatmap - this.measure = null; this.measure_list = []; this.important_fields = []; this.search_view = parent.searchview; @@ -125,9 +124,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ if (group_by.length || col_groupby.length) { this.groupby_mode = 'manual'; - // if (!group_by.length) { - // group_by = this.default_row_groupby; - // } } this.pivot_table.set_domain(domain); @@ -214,7 +210,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ var mode = event.target.attributes['data-mode'].nodeValue; this.mode = mode; this.display_data(); - }, register_groupby: function() { @@ -222,7 +217,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ query = this.search_view.query; this.groupby_mode = 'manual'; - var rows = _.map(this.pivot_table.rows.groupby, function (group) { return make_facet('GroupBy', group); }); @@ -259,8 +253,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ measure_selection: function (event) { event.preventDefault(); var measure = event.target.attributes['data-choice'].nodeValue; - this.measure = (measure === '__count') ? null : measure; - this.pivot_table.set_measure(this.measure); + this.pivot_table.set_measure((measure === '__count') ? null : measure); this.display_data(); }, @@ -276,7 +269,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.register_groupby(); break; case 'fold_all': - this.pivot_table.fold_all(); + this.pivot_table.fold_cols(); + this.pivot_table.fold_rows(); this.register_groupby(); break; case 'expand_all': @@ -287,7 +281,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, option_selection: function (event) { - var pivot = this.pivot_table; event.preventDefault(); switch (event.target.attributes['data-choice'].nodeValue) { case 'swap_axis': @@ -299,7 +292,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.display_data(); break; case 'export_data': - this.register_groupby(); // Export code... To do... break; } @@ -353,7 +345,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, measure_label: function () { - return (this.measure) ? this.fields[this.measure].string : 'Quantity'; + var pivot = this.pivot_table; + return (pivot.measure) ? this.fields[pivot.measure].string : 'Quantity'; }, make_border_cell: function (colspan, rowspan) { diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index b334dbe32aa..10bbf6a7240 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -1,9 +1,6 @@ /* jshint undef: false */ - -// TO DO : use _.uniqueID() - (function () { 'use strict'; @@ -21,11 +18,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ this.stale_data = true; }, - generate_id: function () { - this.id_seed += 1; - return this.id_seed; - }, - visible_fields: function () { var result = this.rows.groupby.concat(this.cols.groupby); if (this.measure) { @@ -159,7 +151,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ make_header: function (groups, parent) { var name = groups[0].attributes.value[1], new_header = { - id: this.generate_id(), + id: _.uniqueId(), path: parent.path.concat(name), title: name, is_expanded: false, @@ -187,11 +179,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ this.fold(this.cols.main); }, - fold_all: function () { - this.fold_rows(); - this.fold_cols(); - }, - expand_headers: function (root, new_headers) { root.headers = new_headers; root.main = new_headers[0]; @@ -336,7 +323,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ function make_headers (data, depth) { var main = { - id: self.generate_id(), + id: _.uniqueId(), path: [], parent: null, children: [], @@ -367,7 +354,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ function make_tree_headers (data_pt, parent, max_depth) { var node = { - id: self.generate_id(), + id: _.uniqueId(), path: parent.path.concat(data_pt.attributes.value[1]), title: data_pt.attributes.value[1], domain: data_pt.model._domain, -- cgit v1.2.3 From 476d0f4f38e597cf7479d6245d4eab4955d7a0c6 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 6 Dec 2013 17:23:01 +0100 Subject: [FIX] fixes a small bug where the columns would expand all headers when the user clears the rows groupby in the search view (addon web_graph) bzr revid: ged@openerp.com-20131206162301-fbq5mgqhg65yqi96 --- addons/web_graph/static/src/js/pivot.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 10bbf6a7240..9b1901e3817 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -41,6 +41,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }, set_row_groupby: function (groupby) { + if ((!groupby.length) && (this.rows.main)) { + this.fold(this.rows.main); + } if (!_.isEqual(groupby, this.rows.groupby)) { this.rows.groupby = groupby; this.invalidate_data(); @@ -48,6 +51,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }, set_col_groupby: function (groupby) { + if ((!groupby.length) && (this.cols.main)) { + this.fold(this.cols.main); + } if (!_.isEqual(groupby, this.cols.groupby)) { this.cols.groupby = groupby; this.invalidate_data(); -- cgit v1.2.3 From 65a0a97d67e02b5a659838bf54cd2accb892bc89 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 6 Dec 2013 17:25:49 +0100 Subject: [IMP] usability fix, makes sure that the dropdown menu displayed when expanding a field in graph view has always the same choices (addon web_graph) bzr revid: ged@openerp.com-20131206162549-08aw50z4zdelzxgc --- addons/web_graph/static/src/js/graph.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 8cf0ffd4877..7efc482f2dd 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -179,7 +179,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ } }, - /****************************************************************************** * Event handling methods... ******************************************************************************/ @@ -318,11 +317,11 @@ instance.web_graph.GraphView = instance.web.View.extend({ display_dropdown: function (options) { var self = this, pivot = this.pivot_table, - already_grouped = pivot.rows.groupby.concat(pivot.cols.groupby), - possible_groups = _.difference(self.important_fields, already_grouped), + // already_grouped = pivot.rows.groupby.concat(pivot.cols.groupby), + // possible_groups = _.difference(self.important_fields, already_grouped), dropdown_options = { header_id: options.id, - fields: _.map(possible_groups, function (field) { + fields: _.map(self.important_fields, function (field) { return {id: field, value: self.fields[field].string}; })}; -- cgit v1.2.3 From 66c8114768376670408a856a3c10bb342b40de5e Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 6 Dec 2013 17:26:41 +0100 Subject: [REF] removes two useless lines (addon web_graph) bzr revid: ged@openerp.com-20131206162641-27rerhfa56y6nf4e --- addons/web_graph/static/src/js/graph.js | 3 --- 1 file changed, 3 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 7efc482f2dd..a5de9f2dde7 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -317,14 +317,11 @@ instance.web_graph.GraphView = instance.web.View.extend({ display_dropdown: function (options) { var self = this, pivot = this.pivot_table, - // already_grouped = pivot.rows.groupby.concat(pivot.cols.groupby), - // possible_groups = _.difference(self.important_fields, already_grouped), dropdown_options = { header_id: options.id, fields: _.map(self.important_fields, function (field) { return {id: field, value: self.fields[field].string}; })}; - this.dropdown = $(QWeb.render('field_selection', dropdown_options)); options.target.after(this.dropdown); this.dropdown.css({position:'absolute', -- cgit v1.2.3 From 9f99fbdae7483ae8e73c4f6525ab8f3d23137126 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 9 Dec 2013 14:08:58 +0100 Subject: [FIX] properly writes the col group_by in the context (with the facets) which allows the filter to work correctly, in graph view (addon web_graph) bzr revid: ged@openerp.com-20131209130858-o8pqocw7otpqr8l0 --- addons/web_graph/static/src/js/graph.js | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index a5de9f2dde7..d64918aee56 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -44,12 +44,19 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.groupby_mode = 'default'; // 'default' or 'manual' this.default_row_groupby = []; this.search_field = { - get_context: function () { }, - get_domain: function () { }, + get_context: this.proxy('get_context'), + get_domain: function () {}, get_groupby: function () { }, }; }, + get_context: function (facet) { + var col_group_by = _.map(facet.values.models, function (model) { + return model.attributes.value.attrs.context.col_group_by; + }); + return {col_group_by : col_group_by}; + }, + start: function () { this.table = $('
    '); this.$('.graph_main_content').append(this.table); @@ -120,7 +127,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ do_search: function (domain, context, group_by) { var self = this, - col_groupby = get_col_groupby('ColGroupBy'); + col_groupby = context.col_group_by || []; // get_col_groupby('ColGroupBy'); if (group_by.length || col_groupby.length) { this.groupby_mode = 'manual'; @@ -135,19 +142,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.pivot_table.set_col_groupby([]); } this.display_data(); - - function get_col_groupby() { - var groupby = [], - search = _.find(self.search_view.query.models, function (model) { - return model.attributes.category == 'ColGroupBy'; - }); - if (search) { - groupby = _.map(search.values.models, function (val) { - return val.attributes.value.attrs.context.col_group_by; - }); - } - return groupby; - } }, do_show: function () { -- cgit v1.2.3 From f24a1b487a65dd0d565d536aa2708b315b5845f6 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 10 Dec 2013 10:21:25 +0100 Subject: [IMP] improves the chart code to display correct bar chart when no groupby are selected (graph view, addon web_graph) bzr revid: ged@openerp.com-20131210092125-fqv9by5xons81uo1 --- addons/web_graph/static/src/js/charts.js | 150 +++++++++++++++++-------------- 1 file changed, 85 insertions(+), 65 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index 5f17cce4aef..8ef16d92b3e 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -1,78 +1,98 @@ openerp.web_graph.draw_chart = function (mode, pivot, svg) { + openerp.web_graph[mode](pivot, svg); +}; - var data = _.map(pivot.rows.main.children, function (pt) { - var value = pivot.get_value(pt.id, pivot.cols.main.id), - title = (pt.title !== undefined) ? pt.title : 'Undefined'; - return {x: title, y: value}; - }); - - switch (mode) { - case 'bar_chart': - bar_chart(); - break; - case 'line_chart': - line_chart(); - break; - case 'pie_chart': - pie_chart(); - break; - } - function bar_chart () { - nv.addGraph(function () { - var chart = nv.models.discreteBarChart() - .tooltips(false) - .showValues(true) - .staggerLabels(true) - .width(650) - .height(400); - d3.select(svg) - .datum([{key: 'Bar chart', values:data}]) - .attr('width', 650) - .attr('height', 400) - .call(chart); +openerp.web_graph.bar_chart = function (pivot, svg) { + var dim_x = pivot.rows.groupby.length, + dim_y = pivot.cols.groupby.length, + data; - nv.utils.windowResize(chart.update); - return chart; + if ((dim_x === 0) && (dim_y === 0)) { + data = [{key: 'Expected Revenue', values:[{ + title: 'Total', + value: pivot.get_value(pivot.rows.main.id, pivot.cols.main.id), + }]}]; + // debugger; + } else if ((dim_x === 0) && (dim_y === 1)){ + + } else + { + data = _.map(pivot.rows.main.children, function (pt) { + var value = pivot.get_value(pt.id, pivot.cols.main.id), + title = (pt.title !== undefined) ? pt.title : 'Undefined'; + return {title: title, value: value}; }); - }; + data = [{key: 'Bar chart', values:data}]; + } + nv.addGraph(function () { + var chart = nv.models.discreteBarChart() + .x(function(d) { return d.title;}) + .y(function(d) { return d.value;}) + .tooltips(false) + .showValues(true) + .staggerLabels(true) + .width(650) + .height(400); + + d3.select(svg) + .datum(data) + .attr('width', 650) + .attr('height', 400) + .call(chart); + + nv.utils.windowResize(chart.update); + return chart; + }); +}; - function line_chart () { - nv.addGraph(function () { - var chart = nv.models.lineChart() - .x(function (d,u) { return u; }) - .width(600) - .height(300) - .margin({top: 30, right: 20, bottom: 20, left: 60}); - d3.select(svg) - .attr('width', 600) - .attr('height', 300) - .datum([{key: 'Bar chart', values: data}]) - .call(chart); +openerp.web_graph.line_chart = function (pivot, svg) { + var data = _.map(pivot.rows.main.children, function (pt) { + var value = pivot.get_value(pt.id, pivot.cols.main.id), + title = (pt.title !== undefined) ? pt.title : 'Undefined'; + return {x: title, y: value}; + }); - return chart; - }); - }; + nv.addGraph(function () { + var chart = nv.models.lineChart() + .x(function (d,u) { return u; }) + .width(600) + .height(300) + .margin({top: 30, right: 20, bottom: 20, left: 60}); - function pie_chart () { - nv.addGraph(function () { - var chart = nv.models.pieChart() - .color(d3.scale.category10().range()) - .width(650) - .height(400); + d3.select(svg) + .attr('width', 600) + .attr('height', 300) + .datum([{key: 'Bar chart', values: data}]) + .call(chart); - d3.select(svg) - .datum(data) - .transition().duration(1200) - .attr('width', 650) - .attr('height', 400) - .call(chart); + return chart; + }); +}; - nv.utils.windowResize(chart.update); - return chart; - }); - }; +openerp.web_graph.pie_chart = function (pivot, svg) { + var data = _.map(pivot.rows.main.children, function (pt) { + var value = pivot.get_value(pt.id, pivot.cols.main.id), + title = (pt.title !== undefined) ? pt.title : 'Undefined'; + return {x: title, y: value}; + }); + + nv.addGraph(function () { + var chart = nv.models.pieChart() + .color(d3.scale.category10().range()) + .width(650) + .height(400); -} + d3.select(svg) + .datum(data) + .transition().duration(1200) + .attr('width', 650) + .attr('height', 400) + .call(chart); + + nv.utils.windowResize(chart.update); + return chart; + }); +}; -- cgit v1.2.3 From fe5543a04335aa9a58dad3654318341776fe9e3e Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 10 Dec 2013 11:07:23 +0100 Subject: [IMP] improves the chart code to display correct bar chart when no row groupby are selected and a positive number of col groupbys are selected (graph view, addon web_graph) bzr revid: ged@openerp.com-20131210100723-0arehl16k54wln0z --- addons/web_graph/static/src/js/charts.js | 35 ++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index 8ef16d92b3e..b56f06acd9f 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -7,16 +7,43 @@ openerp.web_graph.draw_chart = function (mode, pivot, svg) { openerp.web_graph.bar_chart = function (pivot, svg) { var dim_x = pivot.rows.groupby.length, dim_y = pivot.cols.groupby.length, - data; + data = []; if ((dim_x === 0) && (dim_y === 0)) { data = [{key: 'Expected Revenue', values:[{ title: 'Total', value: pivot.get_value(pivot.rows.main.id, pivot.cols.main.id), }]}]; - // debugger; - } else if ((dim_x === 0) && (dim_y === 1)){ - + } else if ((dim_x === 0) && (dim_y >= 1)){ + _.each(pivot.cols.headers, function (header) { + if (header.path.length === 1) { + data.push({ + key: header.title, + values: [{x:header.root.main.title, y: pivot.get_total(header)}] + }); + } + }); + nv.addGraph(function() { + var chart = nv.models.multiBarChart() + .stacked(true) + .tooltips(false) + .showControls(false) + .width(400) + .height(500); + + d3.select(svg) + .datum(data) + .attr('width', 400) + .attr('height', 500) + .transition() + .duration(500) + .call(chart); + + nv.utils.windowResize(chart.update); + + return chart; + }); + return; } else { data = _.map(pivot.rows.main.children, function (pt) { -- cgit v1.2.3 From 1419b0793939de96bf67fc2e48d05a4fc55773d7 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 10 Dec 2013 12:16:46 +0100 Subject: [IMP] improves the way the chart view understands the xml descr of the view, so that nows fields after the operator = + are considered col groupbys (addon web_graph) bzr revid: ged@openerp.com-20131210111646-9d8l78npv72pqfp8 --- addons/web_graph/static/src/js/graph.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index d64918aee56..e35b8516dd4 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -43,6 +43,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.search_view = parent.searchview; this.groupby_mode = 'default'; // 'default' or 'manual' this.default_row_groupby = []; + this.default_col_groupby = []; this.search_field = { get_context: this.proxy('get_context'), get_domain: function () {}, @@ -83,7 +84,11 @@ instance.web_graph.GraphView = instance.web.View.extend({ if ('operator' in field.attrs) { self.measure_list.push(field.attrs.name); } else { - self.default_row_groupby.push(field.attrs.name); + if (self.measure_list.length) { + self.default_col_groupby.push(field.attrs.name); + } else { + self.default_row_groupby.push(field.attrs.name); + } } } }); @@ -139,7 +144,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.pivot_table.set_col_groupby(col_groupby); } else { this.pivot_table.set_row_groupby(_.toArray(this.default_row_groupby)); - this.pivot_table.set_col_groupby([]); + this.pivot_table.set_col_groupby(_.toArray(this.default_col_groupby)); } this.display_data(); }, -- cgit v1.2.3 From 28f27da6387b3f852cc2bc0408e2fd9f21b88d0a Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 10 Dec 2013 16:39:51 +0100 Subject: [IMP] makes the graph view much smarter about the way it displays bar charts depending on the various groupby compbinations (addon web_graph) bzr revid: ged@openerp.com-20131210153951-d36yymirvo09wbxd --- addons/web_graph/static/src/js/charts.js | 143 ++++++++++++++++++++++++++----- addons/web_graph/static/src/js/pivot.js | 4 +- 2 files changed, 123 insertions(+), 24 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index b56f06acd9f..b714e42392e 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -9,11 +9,32 @@ openerp.web_graph.bar_chart = function (pivot, svg) { dim_y = pivot.cols.groupby.length, data = []; + // No groupby ************************************************************** if ((dim_x === 0) && (dim_y === 0)) { - data = [{key: 'Expected Revenue', values:[{ + data = [{key: 'Total', values:[{ title: 'Total', value: pivot.get_value(pivot.rows.main.id, pivot.cols.main.id), }]}]; + nv.addGraph(function () { + var chart = nv.models.discreteBarChart() + .x(function(d) { return d.title;}) + .y(function(d) { return d.value;}) + .tooltips(false) + .showValues(true) + .staggerLabels(true) + .width(650) + .height(400); + + d3.select(svg) + .datum(data) + .attr('width', 650) + .attr('height', 400) + .call(chart); + + nv.utils.windowResize(chart.update); + return chart; + }); + // Only column groupbys **************************************************** } else if ((dim_x === 0) && (dim_y >= 1)){ _.each(pivot.cols.headers, function (header) { if (header.path.length === 1) { @@ -43,35 +64,113 @@ openerp.web_graph.bar_chart = function (pivot, svg) { return chart; }); - return; - } else - { + // Just 1 row groupby ****************************************************** + } else if ((dim_x === 1) && (dim_y === 0)) { data = _.map(pivot.rows.main.children, function (pt) { var value = pivot.get_value(pt.id, pivot.cols.main.id), title = (pt.title !== undefined) ? pt.title : 'Undefined'; return {title: title, value: value}; }); data = [{key: 'Bar chart', values:data}]; - } - nv.addGraph(function () { - var chart = nv.models.discreteBarChart() - .x(function(d) { return d.title;}) - .y(function(d) { return d.value;}) - .tooltips(false) - .showValues(true) - .staggerLabels(true) - .width(650) - .height(400); + nv.addGraph(function () { + var chart = nv.models.discreteBarChart() + .x(function(d) { return d.title;}) + .y(function(d) { return d.value;}) + .tooltips(false) + .showValues(true) + .staggerLabels(true) + .width(650) + .height(400); - d3.select(svg) - .datum(data) - .attr('width', 650) - .attr('height', 400) - .call(chart); + d3.select(svg) + .datum(data) + .attr('width', 650) + .attr('height', 400) + .call(chart); - nv.utils.windowResize(chart.update); - return chart; - }); + nv.utils.windowResize(chart.update); + return chart; + }); + // 1 row groupby and some col groupbys************************************** + } else if ((dim_x === 1) && (dim_y >= 1)) { + data = []; + _.each(pivot.cols.headers, function (colhdr) { + if (colhdr.path.length === 1) { + var values = []; + _.each(pivot.rows.headers, function (header) { + if (header.path.length === 1) { + values.push({ + x: header.title || 'Undefined', + y: pivot.get_value(header.id, colhdr.id, 0) + }); + } + }); + data.push({key: colhdr.title || 'Undefined', values: values}); + } + }); + + nv.addGraph(function () { + var chart = nv.models.multiBarChart() + .stacked(true) + .staggerLabels(true) + .tooltips(false) + .width(650) + .height(400); + + d3.select(svg) + .datum(data) + .attr('width', 650) + .attr('height', 400) + .call(chart); + + nv.utils.windowResize(chart.update); + return chart; + }); + // At least two row groupby************************************************* + } else { + data = []; + var keys = _.uniq(_.map(_.filter(pivot.rows.headers, function (hdr) { + return hdr.path.length === 2; + }), function (hdr) { + return hdr.title || 'Undefined'; + })); + data = _.map(keys, function (key) { + var values = []; + _.each(pivot.rows.headers, function (hdr) { + if (hdr.path.length === 1) { + var subhdr = _.find(hdr.children, function (child) { + return ((child.title === key) || ((child.title === undefined) && (key === 'Undefined'))); + }); + values.push({ + x: hdr.title || 'Undefined', + y: (subhdr) ? pivot.get_total(subhdr) : 0 + }); + } + }); + + return {key:key, values: values}; + }); + + nv.addGraph(function () { + var chart = nv.models.multiBarChart() + .stacked(true) + .staggerLabels(true) + .tooltips(false) + .transitionDuration(0) + .width(650) + .height(400); + + d3.select(svg) + .datum(data) + .attr('width', 650) + .attr('height', 400) + .call(chart); + debugger; + + nv.utils.windowResize(chart.update); + return chart; + }); + } }; diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 9b1901e3817..b73939193a0 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -73,13 +73,13 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } }, - get_value: function (id1, id2) { + get_value: function (id1, id2, default_value) { var x = Math.min(id1, id2), y = Math.max(id1, id2), cell = _.find(this.cells, function (c) { return ((c.x == x) && (c.y == y)); }); - return (cell === undefined) ? undefined : cell.value; + return (cell === undefined) ? default_value : cell.value; }, is_row: function (id) { -- cgit v1.2.3 From 4416acaa5391860a010a03a05d82fa7c5f6b9b57 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 11 Dec 2013 11:12:24 +0100 Subject: [IMP] makes line charts smarter when multiple columns exists, in graph view (addon web_graph) bzr revid: ged@openerp.com-20131211101224-eul3hvm0dt7kdz41 --- addons/web_graph/static/src/js/charts.js | 32 ++++++++++++++++++++------------ addons/web_graph/static/src/js/graph.js | 2 +- addons/web_graph/static/src/js/pivot.js | 14 ++++++++++++++ 3 files changed, 35 insertions(+), 13 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index b714e42392e..7478668865c 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -1,10 +1,10 @@ -openerp.web_graph.draw_chart = function (mode, pivot, svg) { - openerp.web_graph[mode](pivot, svg); +openerp.web_graph.draw_chart = function (mode, pivot, svg, measure_label) { + openerp.web_graph[mode](pivot, svg, measure_label); }; -openerp.web_graph.bar_chart = function (pivot, svg) { +openerp.web_graph.bar_chart = function (pivot, svg, measure_label) { var dim_x = pivot.rows.groupby.length, dim_y = pivot.cols.groupby.length, data = []; @@ -156,7 +156,6 @@ openerp.web_graph.bar_chart = function (pivot, svg) { .stacked(true) .staggerLabels(true) .tooltips(false) - .transitionDuration(0) .width(650) .height(400); @@ -165,7 +164,6 @@ openerp.web_graph.bar_chart = function (pivot, svg) { .attr('width', 650) .attr('height', 400) .call(chart); - debugger; nv.utils.windowResize(chart.update); return chart; @@ -174,12 +172,22 @@ openerp.web_graph.bar_chart = function (pivot, svg) { }; -openerp.web_graph.line_chart = function (pivot, svg) { - var data = _.map(pivot.rows.main.children, function (pt) { - var value = pivot.get_value(pt.id, pivot.cols.main.id), - title = (pt.title !== undefined) ? pt.title : 'Undefined'; - return {x: title, y: value}; - }); +openerp.web_graph.line_chart = function (pivot, svg, measure_label) { + var data = [], + dim_x = pivot.rows.groupby.length, + dim_y = pivot.cols.groupby.length; + + if (dim_y === 0) { + pivot.cols.main.title = measure_label; + } + _.each(pivot.cols.headers, function (col) { + if (!col.is_expanded) { + var values = _.map(pivot.get_rows_depth(dim_x), function (row) { + return {x: row.title, y: pivot.get_value(row.id,col.id, 0)}; + }); + data.push({values: values, key: col.title || 'Undefined'}); + } + }); nv.addGraph(function () { var chart = nv.models.lineChart() @@ -191,7 +199,7 @@ openerp.web_graph.line_chart = function (pivot, svg) { d3.select(svg) .attr('width', 600) .attr('height', 300) - .datum([{key: 'Bar chart', values: data}]) + .datum(data) .call(chart); return chart; diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index e35b8516dd4..07c0e578b83 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -172,7 +172,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ } else { this.$('.graph_main_content').append($('
    ')); var svg = this.$('.graph_main_content svg')[0]; - openerp.web_graph.draw_chart(this.mode, this.pivot_table, svg); + openerp.web_graph.draw_chart(this.mode, this.pivot_table, svg, this.measure_label()); } } } diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index b73939193a0..78f95548106 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -100,6 +100,20 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }); }, + // return all columns with a path length of 'depth' + get_columns_depth: function (depth) { + return _.filter(this.cols.headers, function (hdr) { + return hdr.path.length === depth; + }); + }, + + // return all rows with a path length of 'depth' + get_rows_depth: function (depth) { + return _.filter(this.rows.headers, function (hdr) { + return hdr.path.length === depth; + }); + }, + fold: function (header) { var list = []; function tree_traversal(tree) { -- cgit v1.2.3 From 2cf5049cf170f2560ce398f401adae9d7c2f1614 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 11 Dec 2013 11:22:46 +0100 Subject: [IMP] improves the way line chart format the different titles in the legend (addon web_graph) bzr revid: ged@openerp.com-20131211102246-88y7r63d6wgvz4u5 --- addons/web_graph/static/src/js/charts.js | 22 +++++++++++----------- addons/web_graph/static/src/js/pivot.js | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 11 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index 7478668865c..b4a958ded5b 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -173,20 +173,20 @@ openerp.web_graph.bar_chart = function (pivot, svg, measure_label) { openerp.web_graph.line_chart = function (pivot, svg, measure_label) { - var data = [], - dim_x = pivot.rows.groupby.length, + var dim_x = pivot.rows.groupby.length, dim_y = pivot.cols.groupby.length; - if (dim_y === 0) { - pivot.cols.main.title = measure_label; - } - _.each(pivot.cols.headers, function (col) { - if (!col.is_expanded) { - var values = _.map(pivot.get_rows_depth(dim_x), function (row) { - return {x: row.title, y: pivot.get_value(row.id,col.id, 0)}; - }); - data.push({values: values, key: col.title || 'Undefined'}); + var data = _.map(pivot.get_cols_leaves(), function (col) { + var values = _.map(pivot.get_rows_depth(dim_x), function (row) { + return {x: row.title, y: pivot.get_value(row.id,col.id, 0)}; + }); + var title = _.map(col.path, function (p) { + return p || 'Undefined'; + }).join('/'); + if (dim_y === 0) { + title = measure_label } + return {values: values, key: title}; }); nv.addGraph(function () { diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 78f95548106..cc43329e0b1 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -114,6 +114,20 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }); }, + // return all non expanded rows + get_rows_leaves: function () { + return _.filter(this.rows.headers, function (hdr) { + return !hdr.is_expanded; + }); + }, + + // return all non expanded cols + get_cols_leaves: function () { + return _.filter(this.cols.headers, function (hdr) { + return !hdr.is_expanded; + }); + }, + fold: function (header) { var list = []; function tree_traversal(tree) { -- cgit v1.2.3 From 4ab861699179e35e513c2cd6ac2c0e77c8e513bb Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 11 Dec 2013 11:30:32 +0100 Subject: [IMP] makes pie charts smarter when dealing with multiple levels of rows, in graph view (addon web_graph) bzr revid: ged@openerp.com-20131211103032-6vl1nys24zufuk5w --- addons/web_graph/static/src/js/charts.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index b4a958ded5b..f0025510f9c 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -184,7 +184,7 @@ openerp.web_graph.line_chart = function (pivot, svg, measure_label) { return p || 'Undefined'; }).join('/'); if (dim_y === 0) { - title = measure_label + title = measure_label; } return {values: values, key: title}; }); @@ -206,13 +206,20 @@ openerp.web_graph.line_chart = function (pivot, svg, measure_label) { }); }; -openerp.web_graph.pie_chart = function (pivot, svg) { - var data = _.map(pivot.rows.main.children, function (pt) { - var value = pivot.get_value(pt.id, pivot.cols.main.id), - title = (pt.title !== undefined) ? pt.title : 'Undefined'; - return {x: title, y: value}; +openerp.web_graph.pie_chart = function (pivot, svg, measure_label) { + var dim_x = pivot.rows.groupby.length, + dim_y = pivot.cols.groupby.length; + + var data = _.map(pivot.get_rows_leaves(), function (row) { + var title = _.map(row.path, function (p) { + return p || 'Undefined'; + }).join('/'); + if (dim_x === 0) { + title = measure_label; + } + return {x: title, y: pivot.get_total(row)}; }); - + nv.addGraph(function () { var chart = nv.models.pieChart() .color(d3.scale.category10().range()) -- cgit v1.2.3 From 3453d9da01dc22c704181942530e8abf7dcab95b Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 11 Dec 2013 12:08:36 +0100 Subject: [REF] improves the charting code by using get_rows_depth and get_columns_depth methods (addon web_graph) bzr revid: ged@openerp.com-20131211110836-8sq83pcksjm5sboq --- addons/web_graph/static/src/js/charts.js | 59 ++++++++++++-------------------- 1 file changed, 22 insertions(+), 37 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index f0025510f9c..42bb7599912 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -36,13 +36,11 @@ openerp.web_graph.bar_chart = function (pivot, svg, measure_label) { }); // Only column groupbys **************************************************** } else if ((dim_x === 0) && (dim_y >= 1)){ - _.each(pivot.cols.headers, function (header) { - if (header.path.length === 1) { - data.push({ - key: header.title, - values: [{x:header.root.main.title, y: pivot.get_total(header)}] - }); - } + data = _.map(pivot.get_columns_depth(1), function (header) { + return { + key: header.title, + values: [{x:header.root.main.title, y: pivot.get_total(header)}] + }; }); nv.addGraph(function() { var chart = nv.models.multiBarChart() @@ -93,20 +91,14 @@ openerp.web_graph.bar_chart = function (pivot, svg, measure_label) { }); // 1 row groupby and some col groupbys************************************** } else if ((dim_x === 1) && (dim_y >= 1)) { - data = []; - _.each(pivot.cols.headers, function (colhdr) { - if (colhdr.path.length === 1) { - var values = []; - _.each(pivot.rows.headers, function (header) { - if (header.path.length === 1) { - values.push({ - x: header.title || 'Undefined', - y: pivot.get_value(header.id, colhdr.id, 0) - }); - } - }); - data.push({key: colhdr.title || 'Undefined', values: values}); - } + data = _.map(pivot.get_columns_depth(1), function (colhdr) { + var values = _.map(pivot.get_rows_depth(1), function (header) { + return { + x: header.title || 'Undefined', + y: pivot.get_value(header.id, colhdr.id, 0) + }; + }); + return {key: colhdr.title || 'Undefined', values: values}; }); nv.addGraph(function () { @@ -128,26 +120,19 @@ openerp.web_graph.bar_chart = function (pivot, svg, measure_label) { }); // At least two row groupby************************************************* } else { - data = []; - var keys = _.uniq(_.map(_.filter(pivot.rows.headers, function (hdr) { - return hdr.path.length === 2; - }), function (hdr) { + var keys = _.uniq(_.map(pivot.get_rows_depth(2), function (hdr) { return hdr.title || 'Undefined'; })); data = _.map(keys, function (key) { - var values = []; - _.each(pivot.rows.headers, function (hdr) { - if (hdr.path.length === 1) { - var subhdr = _.find(hdr.children, function (child) { - return ((child.title === key) || ((child.title === undefined) && (key === 'Undefined'))); - }); - values.push({ - x: hdr.title || 'Undefined', - y: (subhdr) ? pivot.get_total(subhdr) : 0 - }); - } + var values = _.map(pivot.get_rows_depth(1), function (hdr) { + var subhdr = _.find(hdr.children, function (child) { + return ((child.title === key) || ((child.title === undefined) && (key === 'Undefined'))); + }); + return { + x: hdr.title || 'Undefined', + y: (subhdr) ? pivot.get_total(subhdr) : 0 + }; }); - return {key:key, values: values}; }); -- cgit v1.2.3 From 14d0a6e74c0cceb1af75377a314369122bd152c9 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 11 Dec 2013 13:43:07 +0100 Subject: [IMP] makes sure that the values displayed in the pivot table are properly formatted according to their types (addon web_graph) bzr revid: ged@openerp.com-20131211124307-z9lxbn39spahlxpw --- addons/web_graph/static/src/js/graph.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 07c0e578b83..53f0308f24c 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -407,9 +407,15 @@ instance.web_graph.GraphView = instance.web.View.extend({ }); }, + get_measure_type: function () { + var measure = this.pivot_table.measure; + return (measure) ? this.fields[measure].type : 'integer'; + }, + draw_row: function (row) { var self = this, pivot = this.pivot_table, + measure_type = this.get_measure_type(), html_row = $(''), row_header = this.make_border_cell(1,1) .append(this.make_header_title(row).attr('data-id', row.id)) @@ -448,7 +454,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ if (value === undefined) { return cell; } - cell.append(value); + cell.append(instance.web.format_value(value, {type: measure_type})); if (self.mode === 'heatmap') { total = pivot.get_total(); color = Math.floor(50 + 205*(total - value)/total); -- cgit v1.2.3 From b8a5b2d2b509bd19ef580f6c137327dbbae924f5 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 11 Dec 2013 14:11:48 +0100 Subject: [IMP] takes all integer and float field from model as possible measure (addon web_graph) bzr revid: ged@openerp.com-20131211131148-vdfhmf96fn2txvcj --- addons/web_graph/static/src/js/graph.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 53f0308f24c..8070bb152ce 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -82,9 +82,9 @@ instance.web_graph.GraphView = instance.web.View.extend({ _.each(fields_view_get.arch.children, function (field) { if ('name' in field.attrs) { if ('operator' in field.attrs) { - self.measure_list.push(field.attrs.name); + measure = field.attrs.name; } else { - if (self.measure_list.length) { + if (measure) { self.default_col_groupby.push(field.attrs.name); } else { self.default_row_groupby.push(field.attrs.name); @@ -92,10 +92,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ } } }); - if (this.measure_list.length > 0) { - measure = this.measure_list[0]; - this.pivot_table.set_measure(measure); - } + this.pivot_table.set_measure(measure); // get the most important fields (of the model) by looking at the // groupby filters defined in the search view @@ -117,6 +114,16 @@ instance.web_graph.GraphView = instance.web.View.extend({ // get the fields descriptions from the model var deferred2 = this.model.call('fields_get', []).then(function (fs) { self.fields = fs; + var temp = _.map(fs, function (field, name) { + return {name:name, type: field.type}; + }); + temp = _.filter(temp, function (field) { + return (((field.type === 'integer') || (field.type === 'float')) && (field.name !== 'id')); + }); + self.measure_list = _.map(temp, function (field) { + return field.name; + }); + var measure_selection = self.$('.graph_measure_selection'); _.each(self.measure_list, function (measure) { var choice = $('').attr('data-choice', measure) -- cgit v1.2.3 From b04f21ea12406fc28e7a74494af0397f6ce9e6d1 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 11 Dec 2013 15:01:40 +0100 Subject: [IMP] finally uses the full width and height to draw charts, instead of hardcoded numbers (in graph view) (addon web_graph) bzr revid: ged@openerp.com-20131211140140-shlpos1jt3z8wj41 --- addons/web_graph/static/src/css/graph.css | 1 - addons/web_graph/static/src/js/charts.js | 107 +++++++++++++++--------------- addons/web_graph/static/src/js/graph.js | 13 +++- 3 files changed, 66 insertions(+), 55 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index 8a92da76605..f054a553d4f 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -1,4 +1,3 @@ - .graph_main_content td { border: 1px solid black; padding: 0.5rem; diff --git a/addons/web_graph/static/src/js/charts.js b/addons/web_graph/static/src/js/charts.js index 42bb7599912..9e6c40eb866 100644 --- a/addons/web_graph/static/src/js/charts.js +++ b/addons/web_graph/static/src/js/charts.js @@ -1,11 +1,12 @@ -openerp.web_graph.draw_chart = function (mode, pivot, svg, measure_label) { - openerp.web_graph[mode](pivot, svg, measure_label); +openerp.web_graph.draw_chart = function (options) { + openerp.web_graph[options.mode](options); }; -openerp.web_graph.bar_chart = function (pivot, svg, measure_label) { - var dim_x = pivot.rows.groupby.length, +openerp.web_graph.bar_chart = function (options) { + var pivot = options.pivot, + dim_x = pivot.rows.groupby.length, dim_y = pivot.cols.groupby.length, data = []; @@ -13,7 +14,7 @@ openerp.web_graph.bar_chart = function (pivot, svg, measure_label) { if ((dim_x === 0) && (dim_y === 0)) { data = [{key: 'Total', values:[{ title: 'Total', - value: pivot.get_value(pivot.rows.main.id, pivot.cols.main.id), + value: options.pivot.get_value(pivot.rows.main.id, pivot.cols.main.id), }]}]; nv.addGraph(function () { var chart = nv.models.discreteBarChart() @@ -21,14 +22,14 @@ openerp.web_graph.bar_chart = function (pivot, svg, measure_label) { .y(function(d) { return d.value;}) .tooltips(false) .showValues(true) - .staggerLabels(true) - .width(650) - .height(400); + .width(options.width) + .height(options.height) + .staggerLabels(true); - d3.select(svg) + d3.select(options.svg) .datum(data) - .attr('width', 650) - .attr('height', 400) + .attr('width', options.width) + .attr('height', options.height) .call(chart); nv.utils.windowResize(chart.update); @@ -46,14 +47,14 @@ openerp.web_graph.bar_chart = function (pivot, svg, measure_label) { var chart = nv.models.multiBarChart() .stacked(true) .tooltips(false) - .showControls(false) - .width(400) - .height(500); + .width(options.width) + .height(options.height) + .showControls(false); - d3.select(svg) + d3.select(options.svg) .datum(data) - .attr('width', 400) - .attr('height', 500) + .attr('width', options.width) + .attr('height', options.height) .transition() .duration(500) .call(chart); @@ -69,21 +70,21 @@ openerp.web_graph.bar_chart = function (pivot, svg, measure_label) { title = (pt.title !== undefined) ? pt.title : 'Undefined'; return {title: title, value: value}; }); - data = [{key: 'Bar chart', values:data}]; + data = [{key: options.measure_label, values:data}]; nv.addGraph(function () { var chart = nv.models.discreteBarChart() .x(function(d) { return d.title;}) .y(function(d) { return d.value;}) .tooltips(false) .showValues(true) - .staggerLabels(true) - .width(650) - .height(400); + .width(options.width) + .height(options.height) + .staggerLabels(true); - d3.select(svg) + d3.select(options.svg) .datum(data) - .attr('width', 650) - .attr('height', 400) + .attr('width', options.width) + .attr('height', options.height) .call(chart); nv.utils.windowResize(chart.update); @@ -105,14 +106,14 @@ openerp.web_graph.bar_chart = function (pivot, svg, measure_label) { var chart = nv.models.multiBarChart() .stacked(true) .staggerLabels(true) - .tooltips(false) - .width(650) - .height(400); + .width(options.width) + .height(options.height) + .tooltips(false); - d3.select(svg) + d3.select(options.svg) .datum(data) - .attr('width', 650) - .attr('height', 400) + .attr('width', options.width) + .attr('height', options.height) .call(chart); nv.utils.windowResize(chart.update); @@ -140,14 +141,14 @@ openerp.web_graph.bar_chart = function (pivot, svg, measure_label) { var chart = nv.models.multiBarChart() .stacked(true) .staggerLabels(true) - .tooltips(false) - .width(650) - .height(400); + .width(options.width) + .height(options.height) + .tooltips(false); - d3.select(svg) + d3.select(options.svg) .datum(data) - .attr('width', 650) - .attr('height', 400) + .attr('width', options.width) + .attr('height', options.height) .call(chart); nv.utils.windowResize(chart.update); @@ -157,8 +158,9 @@ openerp.web_graph.bar_chart = function (pivot, svg, measure_label) { }; -openerp.web_graph.line_chart = function (pivot, svg, measure_label) { - var dim_x = pivot.rows.groupby.length, +openerp.web_graph.line_chart = function (options) { + var pivot = options.pivot, + dim_x = pivot.rows.groupby.length, dim_y = pivot.cols.groupby.length; var data = _.map(pivot.get_cols_leaves(), function (col) { @@ -169,7 +171,7 @@ openerp.web_graph.line_chart = function (pivot, svg, measure_label) { return p || 'Undefined'; }).join('/'); if (dim_y === 0) { - title = measure_label; + title = options.measure_label; } return {values: values, key: title}; }); @@ -177,13 +179,13 @@ openerp.web_graph.line_chart = function (pivot, svg, measure_label) { nv.addGraph(function () { var chart = nv.models.lineChart() .x(function (d,u) { return u; }) - .width(600) - .height(300) + .width(options.width) + .height(options.height) .margin({top: 30, right: 20, bottom: 20, left: 60}); - d3.select(svg) - .attr('width', 600) - .attr('height', 300) + d3.select(options.svg) + .attr('width', options.width) + .attr('height', options.height) .datum(data) .call(chart); @@ -191,8 +193,9 @@ openerp.web_graph.line_chart = function (pivot, svg, measure_label) { }); }; -openerp.web_graph.pie_chart = function (pivot, svg, measure_label) { - var dim_x = pivot.rows.groupby.length, +openerp.web_graph.pie_chart = function (options) { + var pivot = options.pivot, + dim_x = pivot.rows.groupby.length, dim_y = pivot.cols.groupby.length; var data = _.map(pivot.get_rows_leaves(), function (row) { @@ -200,7 +203,7 @@ openerp.web_graph.pie_chart = function (pivot, svg, measure_label) { return p || 'Undefined'; }).join('/'); if (dim_x === 0) { - title = measure_label; + title = options.measure_label; } return {x: title, y: pivot.get_total(row)}; }); @@ -208,14 +211,14 @@ openerp.web_graph.pie_chart = function (pivot, svg, measure_label) { nv.addGraph(function () { var chart = nv.models.pieChart() .color(d3.scale.category10().range()) - .width(650) - .height(400); + .width(options.width) + .height(options.height); - d3.select(svg) + d3.select(options.svg) .datum(data) .transition().duration(1200) - .attr('width', 650) - .attr('height', 400) + .attr('width', options.width) + .attr('height', options.height) .call(chart); nv.utils.windowResize(chart.update); diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 8070bb152ce..f1d08968626 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -61,6 +61,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ start: function () { this.table = $('
    '); this.$('.graph_main_content').append(this.table); + this.width = this.$el.width(); + this.height = this.$el.parent().parent().height(); // to get view manager body instance.web.bus.on('click', this, function (ev) { if (this.dropdown) { this.dropdown.remove(); @@ -178,8 +180,15 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.draw_table(); } else { this.$('.graph_main_content').append($('
    ')); - var svg = this.$('.graph_main_content svg')[0]; - openerp.web_graph.draw_chart(this.mode, this.pivot_table, svg, this.measure_label()); + var options = { + svg: this.$('.graph_main_content svg')[0], + mode: this.mode, + pivot: this.pivot_table, + width: this.width, + height: this.height - 30, + measure_label: this.measure_label() + }; + openerp.web_graph.draw_chart(options); } } } -- cgit v1.2.3 From 8da86807b6d459a7c6d010e447ea006c61790923 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 11 Dec 2013 15:50:56 +0100 Subject: [FIX] quick fix to make sure charts have a minimal height that is not too small (addon web_graph) bzr revid: ged@openerp.com-20131211145056-nzpnir06xx3q0n9y --- addons/web_graph/static/src/js/graph.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index f1d08968626..0b0078e7ff1 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -185,7 +185,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ mode: this.mode, pivot: this.pivot_table, width: this.width, - height: this.height - 30, + height: Math.max(this.height - 45, 250), measure_label: this.measure_label() }; openerp.web_graph.draw_chart(options); -- cgit v1.2.3 From 945719fb7dc9c63933dfbd0a27d557b4e0d2c3c6 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 11 Dec 2013 17:00:11 +0100 Subject: [FIX] correctly computes the height and the width of the graph view (addon web_graph) bzr revid: ged@openerp.com-20131211160011-fhv7ah63hlnyg7l0 --- addons/web_graph/static/src/js/graph.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 0b0078e7ff1..364014288c1 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -61,8 +61,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ start: function () { this.table = $('
    '); this.$('.graph_main_content').append(this.table); - this.width = this.$el.width(); - this.height = this.$el.parent().parent().height(); // to get view manager body instance.web.bus.on('click', this, function (ev) { if (this.dropdown) { this.dropdown.remove(); @@ -180,12 +178,17 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.draw_table(); } else { this.$('.graph_main_content').append($('
    ')); + // console.log('this.perentaui', this.getParent().$el); + // this.width = this.$el.width(); + // this.height = this.$el.parent().parent().height(); // to get view manager body + + // debugger; var options = { svg: this.$('.graph_main_content svg')[0], mode: this.mode, pivot: this.pivot_table, - width: this.width, - height: Math.max(this.height - 45, 250), + width: this.$el.width(), + height: Math.max(this.$el.parent().parent().height() - 45, 250), measure_label: this.measure_label() }; openerp.web_graph.draw_chart(options); -- cgit v1.2.3 From 7a672064c02d56f7c833c727e596b098caa5bf08 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 11 Dec 2013 17:28:50 +0100 Subject: [FIX] improves the handling of headers titles when the db query returns false or undefined (addon web_graph) bzr revid: ged@openerp.com-20131211162850-mgqs5csnw8wca974 --- addons/web_graph/static/src/js/graph.js | 7 +----- addons/web_graph/static/src/js/pivot.js | 41 ++++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 17 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 364014288c1..808f944c5f7 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -178,17 +178,12 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.draw_table(); } else { this.$('.graph_main_content').append($('
    ')); - // console.log('this.perentaui', this.getParent().$el); - // this.width = this.$el.width(); - // this.height = this.$el.parent().parent().height(); // to get view manager body - - // debugger; var options = { svg: this.$('.graph_main_content svg')[0], mode: this.mode, pivot: this.pivot_table, width: this.$el.width(), - height: Math.max(this.$el.parent().parent().height() - 45, 250), + height: Math.max(document.documentElement.clientHeight - 116 - 60, 250), measure_label: this.measure_label() }; openerp.web_graph.draw_chart(options); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index cc43329e0b1..243997229df 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -183,7 +183,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }, make_header: function (groups, parent) { - var name = groups[0].attributes.value[1], + var name = get_attribute_value(groups[0]), new_header = { id: _.uniqueId(), path: parent.path.concat(name), @@ -387,14 +387,15 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } function make_tree_headers (data_pt, parent, max_depth) { - var node = { - id: _.uniqueId(), - path: parent.path.concat(data_pt.attributes.value[1]), - title: data_pt.attributes.value[1], - domain: data_pt.model._domain, - parent: parent, - children: [], - }; + var value = get_attribute_value(data_pt), + node = { + id: _.uniqueId(), + path: parent.path.concat(value), + title: value, + domain: data_pt.model._domain, + parent: parent, + children: [], + }; if (self.measure) { node.total = data_pt.attributes.aggregates[self.measure]; } else { @@ -412,9 +413,14 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ function make_cells (data, index, current_path) { _.each(data, function (group) { var attr = group.attributes, + group_val = (attr.value instanceof Array) ? attr.value[1] : attr.value, path = current_path, value; + if (group_val === false) { + group_val = undefined; + } + if (self.measure) { value = attr.aggregates[self.measure]; } else { @@ -422,8 +428,14 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } if (attr.grouped_on !== undefined) { - path = path.concat(attr.value[1]); + if (attr.value === false) { + path = path.concat('undefined'); + } else { + path = path.concat(group_val); + } } + + console.log('attr', attr); var rowpath = path.slice(0, index), colpath = path.slice(index); @@ -433,6 +445,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ var col = _.find(col_headers, function (header) { return _.isEqual(header.path, colpath); }); + debugger; cells.push({x: Math.min(row.id, col.id), y: Math.max(row.id, col.id), value: value}); @@ -489,7 +502,7 @@ function query_groups_data (model, fields, domain, row_groupbys, col_groupby) { } function format_group (group, path) { - group.path = path.concat(group.attributes.value[1]); + group.path = path.concat(get_attribute_value(group)); var result = [group]; _.each(group.subgroups_data, function (subgroup) { result = result.concat(format_group (subgroup, group.path)); @@ -497,4 +510,10 @@ function format_group (group, path) { return result; } +function get_attribute_value (group) { + var value = group.attributes.value; + if (value === false) return 'undefined'; + return (value instanceof Array) ? value[1] : value; +} + })(); \ No newline at end of file -- cgit v1.2.3 From f24f38ca880754ea6d514abe4d692b263c95605b Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 12 Dec 2013 09:39:36 +0100 Subject: [FIX] removes a debugger statement (addon web_graph) bzr revid: ged@openerp.com-20131212083936-5s8xi6ays4xq9jul --- addons/web_graph/static/src/js/graph.js | 2 +- addons/web_graph/static/src/js/pivot.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 808f944c5f7..918a698e7b7 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -183,7 +183,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ mode: this.mode, pivot: this.pivot_table, width: this.$el.width(), - height: Math.max(document.documentElement.clientHeight - 116 - 60, 250), + height: Math.min(Math.max(document.documentElement.clientHeight - 116 - 60, 250), Math.round(0.8*this.$el.width())), measure_label: this.measure_label() }; openerp.web_graph.draw_chart(options); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 243997229df..a8ed2ae6ef5 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -445,7 +445,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ var col = _.find(col_headers, function (header) { return _.isEqual(header.path, colpath); }); - debugger; cells.push({x: Math.min(row.id, col.id), y: Math.max(row.id, col.id), value: value}); -- cgit v1.2.3 From e0ee9a58c547cd06d2d33018e43b02e549c10e9e Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 12 Dec 2013 11:55:33 +0100 Subject: [IMP] removes the expand/fold menu, because the search view covers the same functionality (addon web_graph) bzr revid: ged@openerp.com-20131212105533-uawad2hgqopfkygo --- addons/web_graph/static/src/css/graph.css | 21 ++++++++++++++++++++ addons/web_graph/static/src/js/graph.js | 28 ++++----------------------- addons/web_graph/static/src/xml/web_graph.xml | 15 ++------------ 3 files changed, 27 insertions(+), 37 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index f054a553d4f..12b0960277a 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -34,3 +34,24 @@ tr.graph_top li { background-color: rgb(245,245,245); } +.graph_view .dropdown-menu { + font-size: 13px; + padding: 4px 0; + background: #e8e8e8 !important; + background: #e8e8e8 !important; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + + font-color: !important black; + background-color: #e8e8e8; + text-shadow: none; + background-color: #e8e8e8; + + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; +} +.graph_view .dropdown-menu li a, .graph_view .dropdown-menu li a:hover, .graph_view .dropdown-menu li a:focus { + color: black; + text-decoration: none; +} diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 918a698e7b7..912f56e79fc 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -24,7 +24,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ events: { 'click .graph_mode_selection li' : 'mode_selection', 'click .graph_measure_selection li' : 'measure_selection', - 'click .graph_expand_selection li' : 'expand_selection', 'click .graph_options_selection li' : 'option_selection', 'click .web_graph_click' : 'cell_click_callback', 'click a.field-selection' : 'field_selection', @@ -269,36 +268,17 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.display_data(); }, - expand_selection: function (event) { + option_selection: function (event) { event.preventDefault(); switch (event.target.attributes['data-choice'].nodeValue) { - case 'fold_columns': - this.pivot_table.fold_cols(); - this.register_groupby(); - break; - case 'fold_rows': - this.pivot_table.fold_rows(); - this.register_groupby(); - break; - case 'fold_all': - this.pivot_table.fold_cols(); - this.pivot_table.fold_rows(); + case 'swap_axis': + this.pivot_table.swap_axis(); this.register_groupby(); break; case 'expand_all': this.pivot_table.invalidate_data(); this.display_data(); break; - } - }, - - option_selection: function (event) { - event.preventDefault(); - switch (event.target.attributes['data-choice'].nodeValue) { - case 'swap_axis': - this.pivot_table.swap_axis(); - this.register_groupby(); - break; case 'update_values': this.pivot_table.stale_data = true; this.display_data(); @@ -368,7 +348,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ return $(' ') .addClass('web_graph_click') .attr('href', '#') - .addClass((header.is_expanded) ? 'icon-minus-sign' : 'icon-plus-sign') + .addClass((header.is_expanded) ? 'fa fa-minus-square' : 'fa fa-plus-square') .append((header.title !== undefined) ? header.title : 'Undefined'); }, diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 9a969a23eae..8ebcecb01ce 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -1,5 +1,5 @@ -
    +
    -
    - - -
    -- cgit v1.2.3 From a22648c083e6fc9ef5170a6458bb52da5123faa6 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 16 Dec 2013 15:27:57 +0100 Subject: [REF] adds DataLoader class to graph view (addon web_graph) bzr revid: ged@openerp.com-20131216142757-anqt11ccrwswdify --- addons/web_graph/static/src/js/pivot.js | 139 +++++++++++++++++--------------- 1 file changed, 76 insertions(+), 63 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index a8ed2ae6ef5..1c7ae27fc31 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -9,10 +9,11 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ this.rows = { groupby: [], main: null, headers: null }; this.cols = { groupby: [], main: null, headers: null }; this.cells = []; - this.model = model; this.domain = domain; this.measure = null; + this.data_loader = new openerp.web_graph.DataLoader(model); + this.id_seed = 0; this.no_data = true; this.stale_data = true; @@ -157,7 +158,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } var otherDim = (header.root === this.cols) ? this.rows : this.cols; - return query_groups_data(this.model, this.visible_fields(), header.domain, otherDim.groupby, field_id) + return this.data_loader.get_groups(this.visible_fields(), header.domain, otherDim.groupby, {first_groupby:field_id, add_path:true}) .then(function (groups) { _.each(groups.reverse(), function (group) { var new_header_id = self.make_header(group, header); @@ -183,7 +184,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }, make_header: function (groups, parent) { - var name = get_attribute_value(groups[0]), + var name = groups[0].attributes.value, new_header = { id: _.uniqueId(), path: parent.path.concat(name), @@ -195,7 +196,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ root: parent.root, }; parent.children.splice(0,0, new_header); - insertAfter(parent.root.headers, parent, new_header); + parent.root.headers.splice(parent.root.headers.indexOf(parent) + 1, 0, new_header); return new_header.id; }, @@ -270,7 +271,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ _.each(corresponding_header.children, function (c) { c.is_expanded = false; }); - } + } if (corresponding_header && (!header.is_expanded)) { corresponding_header.is_expanded = false; } @@ -318,7 +319,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ groupbys = [rows, []]; } def_array = _.map(groupbys, function (groupby) { - return query_groups(self.model, self.visible_fields(), self.domain, groupby); + return self.data_loader.get_groups(self.visible_fields(), self.domain, groupby); }); return $.when.apply(null, def_array).then(function () { @@ -387,7 +388,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } function make_tree_headers (data_pt, parent, max_depth) { - var value = get_attribute_value(data_pt), + var value = data_pt.attributes.value, //get_attribute_value(data_pt), node = { id: _.uniqueId(), path: parent.path.concat(value), @@ -435,7 +436,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } } - console.log('attr', attr); var rowpath = path.slice(0, index), colpath = path.slice(index); @@ -458,61 +458,74 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }); -function insertAfter(array, after, elem) { - array.splice(array.indexOf(after) + 1, 0, elem); -} - -/** - * Query the server and return a deferred which will return the data - * with all the groupbys applied (this is done for now, but the goal - * is to modify read_group in order to allow eager and lazy groupbys - */ -function query_groups (model, fields, domain, groupbys) { - return model.query(fields) - .filter(domain) - .group_by(groupbys) - .then(function (results) { - var non_empty_results = _.filter(results, function (group) { - return group.attributes.length > 0; - }); - if (groupbys.length <= 1) { - return non_empty_results; - } else { - var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) { - var new_domain = result.model._domain; - var new_groupings = groupbys.slice(1); - return query_groups(model, fields,new_domain, new_groupings).then(function (subgroups) { - result.subgroups_data = subgroups; - }); - })); - return get_subgroups.then(function () { - return non_empty_results; - }); - } - }); -} +openerp.web_graph.DataLoader = openerp.web.Class.extend({ + init: function (model) { + this.model = model; + }, + + get_groups: function (fields, domain, groupbys, options) { + var self = this, + options = (options) ? options : {}, + groupings = (options.first_groupby) ? [options.first_groupby].concat(groupbys) : groupbys; + + return this._query_db(fields, domain, groupings).then(function (groups) { + return _.map(groups, function (group) { + return (options.add_path) ?self._add_path(group, []) : group; + }); + }); + + }, + + _query_db: function (fields, domain, groupbys) { + var self = this; + return this.model.query(fields) + .filter(domain) + .group_by(groupbys) + .then(function (results) { + var non_empty_results = _.filter(results, function (group) { + return group.attributes.length > 0; + }); + _.each(non_empty_results, self._sanitize_value); + if (groupbys.length <= 1) { + return non_empty_results; + } else { + var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) { + var new_domain = result.model._domain; + var new_groupings = groupbys.slice(1); + return self._query_db(fields,new_domain, new_groupings).then(function (subgroups) { + result.subgroups_data = subgroups; + }); + })); + return get_subgroups.then(function () { + return non_empty_results; + }); + } + }); + }, + + _sanitize_value: function (group) { + var value = group.attributes.value; + if (value === false) { + group.attributes.value = 'undefined'; + } else if (value instanceof Array) { + group.attributes.value = value[1]; + } else { + group.attributes.value = value; + } + }, + + _add_path: function (group, current_path) { + var self = this; + + group.path = current_path.concat(group.attributes.value); + var result = [group]; + _.each(group.subgroups_data, function (subgroup) { + result = result.concat(self._add_path(subgroup, group.path)); + }); + return result; + }, + +}); -function query_groups_data (model, fields, domain, row_groupbys, col_groupby) { - return query_groups(model, fields, domain, [col_groupby].concat(row_groupbys)).then(function (groups) { - return _.map(groups, function (group) { - return format_group(group, []); - }); - }); -} - -function format_group (group, path) { - group.path = path.concat(get_attribute_value(group)); - var result = [group]; - _.each(group.subgroups_data, function (subgroup) { - result = result.concat(format_group (subgroup, group.path)); - }); - return result; -} - -function get_attribute_value (group) { - var value = group.attributes.value; - if (value === false) return 'undefined'; - return (value instanceof Array) ? value[1] : value; -} })(); \ No newline at end of file -- cgit v1.2.3 From c256cd4f14d1f1cde45f5eecdd705fe758295b4d Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 16 Dec 2013 15:49:35 +0100 Subject: [REF] merges update_data and query_all_values method into load_data, to simplify code (addon web_graph) bzr revid: ged@openerp.com-20131216144935-2ur7pgk7ml2064j0 --- addons/web_graph/static/src/js/graph.js | 2 +- addons/web_graph/static/src/js/pivot.js | 108 +++++++++++++++----------------- 2 files changed, 50 insertions(+), 60 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 912f56e79fc..8433e560cfd 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -163,7 +163,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ display_data: function () { var pivot = this.pivot_table; if (pivot.stale_data) { - pivot.update_data().done(this.proxy('display_data')); + pivot.load_data().done(this.proxy('display_data')); } else { this.$('.graph_main_content svg').remove(); this.table.empty(); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 1c7ae27fc31..793c9f50454 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -214,15 +214,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ this.fold(this.cols.main); }, - expand_headers: function (root, new_headers) { - root.headers = new_headers; - root.main = new_headers[0]; - _.each(root.headers, function (header) { - header.root = root; - header.is_expanded = (header.children.length > 0); - }); - }, - get_total: function (header) { if (header) { var main = (header.root === this.rows) ? this.cols.main : this.rows.main; @@ -241,9 +232,45 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ this.stale_data = true; }, - update_data: function () { - var self = this; - return this.query_all_values().then(function (result) { + // To obtain all the values required to draw the full table, we have to do + // at least 2 + min(row.groupby.length, col.groupby.length) + // calls to readgroup. For example, if row.groupby = [r1, r2, r3] and + // col.groupby = [c1, c2, c3, c4], then a minimal set of calls is done + // with the following groupby: + // [], [c1, c2, c3, c4], r1, c1, c2, c3, c4], [r1, r2, c1, c2, c3, c4], + // [r1, r2, r3, c1, c2, c3, c4] + // To simplify the code, we will always do 2 + row.groupby.length calls, + // unless col.groupby.length = 0, in which case we do 2 calls ([] and + // row_groupbys), but this can be optimized later. + load_data: function () { + var self = this, + cols = this.cols.groupby, + rows = this.rows.groupby, + def_array, + groupbys; + + if (cols.length > 0) { + groupbys = _.map(_.range(rows.length + 1), function (i) { + return rows.slice(0, i).concat(cols); + }); + groupbys.push([]); + } else { + groupbys = [rows, []]; + } + def_array = _.map(groupbys, function (groupby) { + return self.data_loader.get_groups(self.visible_fields(), self.domain, groupby); + }); + + return $.when.apply(null, def_array).then(function () { + var args = Array.prototype.slice.call(arguments), + col_data = _.first(args), + total = _.last(args)[0], + row_data = _.last(_.initial(args)), + cell_data = args; + + return (total === undefined) ? undefined + : self.format_data(total, col_data, row_data, cell_data); + }).then(function (result) { self.stale_data = false; if (result) { self.no_data = false; @@ -261,6 +288,15 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }); }, + expand_headers: function (root, new_headers) { + root.headers = new_headers; + root.main = new_headers[0]; + _.each(root.headers, function (header) { + header.root = root; + header.is_expanded = (header.children.length > 0); + }); + }, + update_headers: function (root, new_headers) { _.each(root.headers, function (header) { var corresponding_header = _.find(new_headers, function (h) { @@ -289,52 +325,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ root.main = root.headers[0]; }, - // this method is a little tricky. In order to obtain all the values - // required to draw the full table, we have to do at least - // 2 + min(row.groupby.length, col.groupby.length) - // calls to readgroup. For example, if row.groupby = [r1, r2, r3] and - // col.groupby = [c1, c2, c3, c4], then a minimal set of calls is done - // with the following groupby: - // [] - // [c1, c2, c3, c4] - // [r1, c1, c2, c3, c4] - // [r1, r2, c1, c2, c3, c4] - // [r1, r2, r3, c1, c2, c3, c4] - // To simplify the code, we will always do 2 + row.groupby.length calls, - // unless col.groupby.length = 0, in which case we do 2 calls ([] and - // row_groupbys), but this can be optimized later. - query_all_values: function () { - var self = this, - cols = this.cols.groupby, - rows = this.rows.groupby, - def_array, - groupbys; - - if (cols.length > 0) { - groupbys = _.map(_.range(rows.length + 1), function (i) { - return rows.slice(0, i).concat(cols); - }); - groupbys.push([]); - } else { - groupbys = [rows, []]; - } - def_array = _.map(groupbys, function (groupby) { - return self.data_loader.get_groups(self.visible_fields(), self.domain, groupby); - }); - - return $.when.apply(null, def_array).then(function () { - var args = Array.prototype.slice.call(arguments), - col_data = _.first(args), - total = _.last(args)[0], - row_data = _.last(_.initial(args)), - cell_data = args; - - return (total === undefined) ? undefined - : self.format_data(total, col_data, row_data, cell_data); - }); - - }, - format_data: function (total, col_data, row_data, cell_data) { var self = this, dim_row = this.rows.groupby.length, @@ -388,7 +378,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } function make_tree_headers (data_pt, parent, max_depth) { - var value = data_pt.attributes.value, //get_attribute_value(data_pt), + var value = data_pt.attributes.value, node = { id: _.uniqueId(), path: parent.path.concat(value), -- cgit v1.2.3 From 65642c8c065c322be1cb671dbc7b1aac1a6f4e54 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 16 Dec 2013 16:24:33 +0100 Subject: [FIX] adds a 'whitespace:nowrap' line in graph.css to avoid weird display issues with the pivot table (addon web_graph) bzr revid: ged@openerp.com-20131216152433-xd5muebn30mcsnqh --- addons/web_graph/static/src/css/graph.css | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index 12b0960277a..1185961d2ae 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -7,6 +7,7 @@ td.graph_border { background-color: rgb(227, 227, 227); text-align: left; + white-space: nowrap; } span.field-selection { -- cgit v1.2.3 From de51e3c35a4ada3bc29c3de2abd371e43569f814 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 17 Dec 2013 12:15:01 +0100 Subject: [REF] moves more code to dataLoader class to simplify pivot class (clean separation between pivot code and loading code) (addon web_graph) bzr revid: ged@openerp.com-20131217111501-wu0nbid36bncy4wz --- addons/web_graph/static/src/js/graph.js | 2 +- addons/web_graph/static/src/js/pivot.js | 262 +++++++++++++++++--------------- 2 files changed, 142 insertions(+), 122 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 8433e560cfd..912f56e79fc 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -163,7 +163,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ display_data: function () { var pivot = this.pivot_table; if (pivot.stale_data) { - pivot.load_data().done(this.proxy('display_data')); + pivot.update_data().done(this.proxy('display_data')); } else { this.$('.graph_main_content svg').remove(); this.table.empty(); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 793c9f50454..b95e60509e8 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -117,15 +117,15 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ // return all non expanded rows get_rows_leaves: function () { - return _.filter(this.rows.headers, function (hdr) { - return !hdr.is_expanded; + return _.filter(this.rows.headers, function (hdr) { + return !hdr.is_expanded; }); }, // return all non expanded cols get_cols_leaves: function () { - return _.filter(this.cols.headers, function (hdr) { - return !hdr.is_expanded; + return _.filter(this.cols.headers, function (hdr) { + return !hdr.is_expanded; }); }, @@ -232,54 +232,25 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ this.stale_data = true; }, - // To obtain all the values required to draw the full table, we have to do - // at least 2 + min(row.groupby.length, col.groupby.length) - // calls to readgroup. For example, if row.groupby = [r1, r2, r3] and - // col.groupby = [c1, c2, c3, c4], then a minimal set of calls is done - // with the following groupby: - // [], [c1, c2, c3, c4], r1, c1, c2, c3, c4], [r1, r2, c1, c2, c3, c4], - // [r1, r2, r3, c1, c2, c3, c4] - // To simplify the code, we will always do 2 + row.groupby.length calls, - // unless col.groupby.length = 0, in which case we do 2 calls ([] and - // row_groupbys), but this can be optimized later. - load_data: function () { + update_data: function () { var self = this, - cols = this.cols.groupby, - rows = this.rows.groupby, - def_array, - groupbys; - - if (cols.length > 0) { - groupbys = _.map(_.range(rows.length + 1), function (i) { - return rows.slice(0, i).concat(cols); - }); - groupbys.push([]); - } else { - groupbys = [rows, []]; - } - def_array = _.map(groupbys, function (groupby) { - return self.data_loader.get_groups(self.visible_fields(), self.domain, groupby); - }); - - return $.when.apply(null, def_array).then(function () { - var args = Array.prototype.slice.call(arguments), - col_data = _.first(args), - total = _.last(args)[0], - row_data = _.last(_.initial(args)), - cell_data = args; + options = { + col_groupby: this.cols.groupby, + row_groupby: this.rows.groupby, + measure: this.measure, + domain: this.domain, + }; - return (total === undefined) ? undefined - : self.format_data(total, col_data, row_data, cell_data); - }).then(function (result) { + return this.data_loader.load_data(options).then (function (result) { self.stale_data = false; if (result) { self.no_data = false; if (self.cols.headers) { self.update_headers(self.cols, result.col_headers); - self.update_headers(self.rows, result.row_headers); + self.update_headers(self.rows, result.row_headers); } else { self.expand_headers(self.cols, result.col_headers); - self.expand_headers(self.rows, result.row_headers); + self.expand_headers(self.rows, result.row_headers); } self.cells = result.cells; } else { @@ -325,10 +296,127 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ root.main = root.headers[0]; }, - format_data: function (total, col_data, row_data, cell_data) { +}); + +openerp.web_graph.DataLoader = openerp.web.Class.extend({ + init: function (model) { + this.model = model; + }, + + get_groups: function (fields, domain, groupbys, options) { var self = this, - dim_row = this.rows.groupby.length, - dim_col = this.cols.groupby.length, + options = (options) ? options : {}, + groupings = (options.first_groupby) ? [options.first_groupby].concat(groupbys) : groupbys; + + return this.query_db(fields, domain, groupings).then(function (groups) { + return _.map(groups, function (group) { + return (options.add_path) ?self.add_path(group, []) : group; + }); + }); + + }, + + query_db: function (fields, domain, groupbys) { + var self = this; + return this.model.query(fields) + .filter(domain) + .group_by(groupbys) + .then(function (results) { + var non_empty_results = _.filter(results, function (group) { + return group.attributes.length > 0; + }); + _.each(non_empty_results, self.sanitize_value); + if (groupbys.length <= 1) { + return non_empty_results; + } else { + var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) { + var new_domain = result.model._domain; + var new_groupings = groupbys.slice(1); + return self.query_db(fields,new_domain, new_groupings).then(function (subgroups) { + result.subgroups_data = subgroups; + }); + })); + return get_subgroups.then(function () { + return non_empty_results; + }); + } + }); + }, + + sanitize_value: function (group) { + var value = group.attributes.value; + if (value === false) { + group.attributes.value = 'undefined'; + } else if (value instanceof Array) { + group.attributes.value = value[1]; + } else { + group.attributes.value = value; + } + }, + + add_path: function (group, current_path) { + var self = this; + + group.path = current_path.concat(group.attributes.value); + var result = [group]; + _.each(group.subgroups_data, function (subgroup) { + result = result.concat(self.add_path(subgroup, group.path)); + }); + return result; + }, + + // To obtain all the values required to draw the full table, we have to do + // at least 2 + min(row.groupby.length, col.groupby.length) + // calls to readgroup. For example, if row.groupby = [r1, r2, r3] and + // col.groupby = [c1, c2, c3, c4], then a minimal set of calls is done + // with the following groupby: + // [], [c1, c2, c3, c4], r1, c1, c2, c3, c4], [r1, r2, c1, c2, c3, c4], + // [r1, r2, r3, c1, c2, c3, c4] + // To simplify the code, we will always do 2 + row.groupby.length calls, + // unless col.groupby.length = 0, in which case we do 2 calls ([] and + // row_groupbys), but this can be optimized later. + load_data: function (options) { + var self = this, + cols = options.col_groupby, + rows = options.row_groupby, + measure = options.measure, + domain = options.domain, + visible_fields = rows.concat(cols), + def_array, + groupbys; + + if (measure) { visible_fields = visible_fields.concat(measure); } + + if (cols.length > 0) { + groupbys = _.map(_.range(rows.length + 1), function (i) { + return rows.slice(0, i).concat(cols); + }); + groupbys.push([]); + } else { + groupbys = [rows, []]; + } + def_array = _.map(groupbys, function (groupby) { + return self.get_groups(visible_fields, domain, groupby); + }); + + return $.when.apply(null, def_array).then(function () { + var args = Array.prototype.slice.call(arguments), + col_data = _.first(args), + total = _.last(args)[0], + row_data = _.last(_.initial(args)), + cell_data = args; + + return (total === undefined) ? undefined + : self.format_data(total, col_data, row_data, cell_data, options); + }); + }, + + + format_data: function (total, col_data, row_data, cell_data, options) { + var self = this, + dim_row = options.row_groupby.length, + dim_col = options.col_groupby.length, + measure = options.measure, col_headers = make_headers(col_data, dim_col), row_headers = make_headers(row_data, dim_row), cells = []; @@ -353,10 +441,10 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ parent: null, children: [], title: '', - domain: self.domain, + domain: options.domain, }; - if (self.measure) { - main.total = total.attributes.aggregates[self.measure]; + if (measure) { + main.total = total.attributes.aggregates[measure]; } else { main.total = total.attributes.length; } @@ -387,8 +475,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ parent: parent, children: [], }; - if (self.measure) { - node.total = data_pt.attributes.aggregates[self.measure]; + if (measure) { + node.total = data_pt.attributes.aggregates[measure]; } else { node.total = data_pt.attributes.length; } @@ -412,8 +500,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ group_val = undefined; } - if (self.measure) { - value = attr.aggregates[self.measure]; + if (measure) { + value = attr.aggregates[measure]; } else { value = attr.length; } @@ -446,74 +534,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } }, -}); - -openerp.web_graph.DataLoader = openerp.web.Class.extend({ - init: function (model) { - this.model = model; - }, - - get_groups: function (fields, domain, groupbys, options) { - var self = this, - options = (options) ? options : {}, - groupings = (options.first_groupby) ? [options.first_groupby].concat(groupbys) : groupbys; - - return this._query_db(fields, domain, groupings).then(function (groups) { - return _.map(groups, function (group) { - return (options.add_path) ?self._add_path(group, []) : group; - }); - }); - - }, - - _query_db: function (fields, domain, groupbys) { - var self = this; - return this.model.query(fields) - .filter(domain) - .group_by(groupbys) - .then(function (results) { - var non_empty_results = _.filter(results, function (group) { - return group.attributes.length > 0; - }); - _.each(non_empty_results, self._sanitize_value); - if (groupbys.length <= 1) { - return non_empty_results; - } else { - var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) { - var new_domain = result.model._domain; - var new_groupings = groupbys.slice(1); - return self._query_db(fields,new_domain, new_groupings).then(function (subgroups) { - result.subgroups_data = subgroups; - }); - })); - return get_subgroups.then(function () { - return non_empty_results; - }); - } - }); - }, - - _sanitize_value: function (group) { - var value = group.attributes.value; - if (value === false) { - group.attributes.value = 'undefined'; - } else if (value instanceof Array) { - group.attributes.value = value[1]; - } else { - group.attributes.value = value; - } - }, - - _add_path: function (group, current_path) { - var self = this; - - group.path = current_path.concat(group.attributes.value); - var result = [group]; - _.each(group.subgroups_data, function (subgroup) { - result = result.concat(self._add_path(subgroup, group.path)); - }); - return result; - }, }); -- cgit v1.2.3 From 9596340bc52235e1a835e30a2e1e02b7a92fceed Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 17 Dec 2013 12:19:41 +0100 Subject: [REF] removes useless line in addon web_graph bzr revid: ged@openerp.com-20131217111941-vlzn0ener6zjk737 --- addons/web_graph/static/src/js/pivot.js | 1 - 1 file changed, 1 deletion(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index b95e60509e8..dd675270132 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -14,7 +14,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ this.data_loader = new openerp.web_graph.DataLoader(model); - this.id_seed = 0; this.no_data = true; this.stale_data = true; }, -- cgit v1.2.3 From 79250f0c077e3c463fd2d644b5fe398f82048a3f Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 17 Dec 2013 16:32:04 +0100 Subject: [REF] adds event handling to pivot table class (triggers 'redraw_required' and 'groupby_changed' event when necessary (addon web_graph) bzr revid: ged@openerp.com-20131217153204-43la1m8eqw632j05 --- addons/web_graph/static/src/js/graph.js | 14 ++++++---- addons/web_graph/static/src/js/pivot.js | 47 +++++++++++++++------------------ 2 files changed, 31 insertions(+), 30 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 912f56e79fc..6805bce1793 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -138,20 +138,24 @@ instance.web_graph.GraphView = instance.web.View.extend({ do_search: function (domain, context, group_by) { var self = this, - col_groupby = context.col_group_by || []; // get_col_groupby('ColGroupBy'); + col_groupby = context.col_group_by || []; if (group_by.length || col_groupby.length) { this.groupby_mode = 'manual'; } this.pivot_table.set_domain(domain); + + var options; if (this.groupby_mode === 'manual') { - this.pivot_table.set_row_groupby(group_by); - this.pivot_table.set_col_groupby(col_groupby); + options = {row: group_by, col: col_groupby}; } else { - this.pivot_table.set_row_groupby(_.toArray(this.default_row_groupby)); - this.pivot_table.set_col_groupby(_.toArray(this.default_col_groupby)); + options = { + row: _.toArray(this.default_row_groupby), + col: _.toArray(this.default_col_groupby), + }; } + this.pivot_table.set_groupby(options); this.display_data(); }, diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index dd675270132..3938acb501e 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -4,8 +4,9 @@ (function () { 'use strict'; -openerp.web_graph.PivotTable = openerp.web.Class.extend({ +openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherMixin, { init: function (model, domain) { + openerp.EventDispatcherMixin.init.call(this); this.rows = { groupby: [], main: null, headers: null }; this.cols = { groupby: [], main: null, headers: null }; this.cells = []; @@ -40,23 +41,16 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } }, - set_row_groupby: function (groupby) { - if ((!groupby.length) && (this.rows.main)) { - this.fold(this.rows.main); - } - if (!_.isEqual(groupby, this.rows.groupby)) { - this.rows.groupby = groupby; - this.invalidate_data(); - } - }, + set_groupby: function (groupbys) { + var col_changed = !_.isEqual(groupbys.col, this.cols.groupby), + row_changed = !_.isEqual(groupbys.row, this.rows.groupby); - set_col_groupby: function (groupby) { - if ((!groupby.length) && (this.cols.main)) { - this.fold(this.cols.main); - } - if (!_.isEqual(groupby, this.cols.groupby)) { - this.cols.groupby = groupby; - this.invalidate_data(); + this.rows.groupby = groupbys.row; + this.cols.groupby = groupbys.col; + + if (col_changed || row_changed) { + this.invalidate_data(); + this.trigger('groupby_changed'); } }, @@ -141,11 +135,17 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ header.is_expanded = false; var fold_lvls = _.map(header.root.headers, function(g) {return g.path.length;}); var new_groupby_length = _.max(fold_lvls); + + if (new_groupby_length < header.root.groupby.length) { + this.trigger('groupby_changed'); + } + header.root.groupby.splice(new_groupby_length); header.children = []; this.cells = _.reject(this.cells, function (cell) { return (_.contains(ids_to_remove, cell.x) || _.contains(ids_to_remove, cell.y)); }); + this.trigger('redraw_required'); }, expand: function (header_id, field_id) { @@ -154,6 +154,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ if (header.path.length == header.root.groupby.length) { header.root.groupby.push(field_id); + this.trigger('groupby_changed'); } var otherDim = (header.root === this.cols) ? this.rows : this.cols; @@ -179,6 +180,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }); }); header.is_expanded = true; + self.trigger('redraw_required'); }); }, @@ -203,14 +205,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ var temp = this.rows; this.rows = this.cols; this.cols = temp; - }, - - fold_rows: function () { - this.fold(this.rows.main); - }, - - fold_cols: function () { - this.fold(this.cols.main); + this.trigger('groupby_changed'); + this.trigger('redraw_required'); }, get_total: function (header) { @@ -255,6 +251,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } else { self.no_data = true; } + self.trigger('redraw_required'); }); }, -- cgit v1.2.3 From 7bb84af05f978f02dc9a8a01d9f73bbea7784d67 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 18 Dec 2013 14:40:40 +0100 Subject: [REF] large refactoring of graphview: it separates the drawing code into a widget that can be used independently of the view (addon web_graph) bzr revid: ged@openerp.com-20131218134040-63fcm5a68gsk3hry --- addons/web_graph/static/src/css/graph.css | 4 +- addons/web_graph/static/src/js/graph.js | 373 +++++++++++++------------- addons/web_graph/static/src/js/pivot.js | 85 +++--- addons/web_graph/static/src/xml/web_graph.xml | 2 +- 4 files changed, 237 insertions(+), 227 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index 1185961d2ae..764fcdca209 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -35,7 +35,7 @@ tr.graph_top li { background-color: rgb(245,245,245); } -.graph_view .dropdown-menu { +.graph_widget .dropdown-menu { font-size: 13px; padding: 4px 0; background: #e8e8e8 !important; @@ -52,7 +52,7 @@ tr.graph_top li { -webkit-border-radius: 3px; border-radius: 3px; } -.graph_view .dropdown-menu li a, .graph_view .dropdown-menu li a:hover, .graph_view .dropdown-menu li a:focus { +.graph_widget .dropdown-menu li a, .graph_widget .dropdown-menu li a:hover, .graph_widget .dropdown-menu li a:focus { color: black; text-decoration: none; } diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 6805bce1793..f4d93305f41 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -13,32 +13,14 @@ var QWeb = instance.web.qweb; instance.web.views.add('graph', 'instance.web_graph.GraphView'); - /** - * GraphView - */ instance.web_graph.GraphView = instance.web.View.extend({ - template: 'GraphView', display_name: _lt('Graph'), view_type: 'graph', - events: { - 'click .graph_mode_selection li' : 'mode_selection', - 'click .graph_measure_selection li' : 'measure_selection', - 'click .graph_options_selection li' : 'option_selection', - 'click .web_graph_click' : 'cell_click_callback', - 'click a.field-selection' : 'field_selection', - }, - init: function(parent, dataset, view_id, options) { this._super(parent); - this.model = new instance.web.Model(dataset.model, {group_by_no_leaf: true}); this.dataset = dataset; - this.pivot_table = new openerp.web_graph.PivotTable(this.model, dataset.domain); - this.set_default_options(options); - this.dropdown = null; - this.mode = 'pivot'; // pivot, bar_chart, line_chart, pie_chart, heatmap, row_heatmap, col_heatmap - this.measure_list = []; - this.important_fields = []; + this.model = new instance.web.Model(dataset.model, {group_by_no_leaf: true}); this.search_view = parent.searchview; this.groupby_mode = 'default'; // 'default' or 'manual' this.default_row_groupby = []; @@ -58,14 +40,10 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, start: function () { - this.table = $('
    '); - this.$('.graph_main_content').append(this.table); - instance.web.bus.on('click', this, function (ev) { - if (this.dropdown) { - this.dropdown.remove(); - this.dropdown = null; - } - }); + var options = {enabled:false}; + this.graph_widget = new openerp.web_graph.Graph(this, this.model, options); + this.graph_widget.appendTo(this.$el); + this.graph_widget.pivot.on('groupby_changed', this, this.proxy('register_groupby')); return this.load_view(); }, @@ -77,7 +55,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.mode = 'bar_chart'; } - // get the default groupbys and measure defined in the field view _.each(fields_view_get.arch.children, function (field) { if ('name' in field.attrs) { if ('operator' in field.attrs) { @@ -91,8 +68,116 @@ instance.web_graph.GraphView = instance.web.View.extend({ } } }); - this.pivot_table.set_measure(measure); + this.graph_widget.pivot.config({measure:measure, update:false}); + }, + + do_search: function (domain, context, group_by) { + var self = this, + col_groupby = context.col_group_by || [], + options = {domain:domain}; + + if (group_by.length || col_groupby.length) { + this.groupby_mode = 'manual'; + } + if (!this.graph_widget.enabled) { + options.update = false; + options.silent = true; + } + + if (this.groupby_mode === 'manual') { + options.row_groupby = group_by; + options.col_groupby = col_groupby; + } else { + options.row_groupby = _.toArray(this.default_row_groupby); + options.col_groupby = _.toArray(this.default_col_groupby); + } + this.graph_widget.pivot.config(options); + + if (!this.graph_widget.enabled) { + this.graph_widget.activate_display(); + } + }, + + do_show: function () { + this.do_push_state({}); + return this._super(); + }, + + register_groupby: function() { + var self = this, + query = this.search_view.query; + this.groupby_mode = 'manual'; + + var rows = _.map(this.graph_widget.pivot.rows.groupby, function (group) { + return make_facet('GroupBy', group); + }); + var cols = _.map(this.graph_widget.pivot.cols.groupby, function (group) { + return make_facet('ColGroupBy', group); + }); + + query.reset(rows.concat(cols)); + + function make_facet (category, fields) { + var values, + icon, + backbone_field, + cat_name; + if (!(fields instanceof Array)) { fields = [fields]; } + if (category === 'GroupBy') { + cat_name = 'group_by'; + icon = 'w'; + backbone_field = self.search_view._s_groupby; + } else { + cat_name = 'col_group_by'; + icon = 'f'; + backbone_field = self.search_field; + } + values = _.map(fields, function (field) { + var context = {}; + context[cat_name] = field; + return {label: self.graph_widget.fields[field].string, value: {attrs:{domain: [], context: context}}}; + }); + return {category:category, values: values, icon:icon, field: backbone_field}; + } + }, +}); + +instance.web_graph.Graph = instance.web.Widget.extend({ + template: "GraphWidget", + + events: { + 'click .graph_mode_selection li' : 'mode_selection', + 'click .graph_measure_selection li' : 'measure_selection', + 'click .graph_options_selection li' : 'option_selection', + 'click .web_graph_click' : 'header_cell_clicked', + 'click a.field-selection' : 'field_selection', + }, + + init: function(parent, model, options) { + this._super(parent); + this.model = model; + this.mode = 'pivot'; + this.important_fields = []; + this.measure_list = []; + this.fields = []; + this.enabled = true; + this.dropdown = null; + + this.pivot = new openerp.web_graph.PivotTable(model, []); + + options = options || {}; + + // show_ui, hide ui ?, default stacked/grouped? + if (_.has(options, 'mode')) { this.mode = mode; } + if (_.has(options, 'measure')) { this.pivot.set_measure(options.measure); } + if (_.has(options, 'enabled')) { this.enabled = options.enabled; } + }, + + start: function() { + var self = this; + this.table = $('
    '); + this.$('.graph_main_content').append(this.table); // get the most important fields (of the model) by looking at the // groupby filters defined in the search view var options = {model:this.model, view_type: 'search'}, @@ -110,7 +195,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ }); }); - // get the fields descriptions from the model + // get the fields descriptions and measure list from the model var deferred2 = this.model.call('fields_get', []).then(function (fs) { self.fields = fs; var temp = _.map(fs, function (field, name) { @@ -133,89 +218,48 @@ instance.web_graph.GraphView = instance.web.View.extend({ }); }); - return $.when(deferred1, deferred2); - }, - - do_search: function (domain, context, group_by) { - var self = this, - col_groupby = context.col_group_by || []; - - if (group_by.length || col_groupby.length) { - this.groupby_mode = 'manual'; - } - - this.pivot_table.set_domain(domain); - - var options; - if (this.groupby_mode === 'manual') { - options = {row: group_by, col: col_groupby}; - } else { - options = { - row: _.toArray(this.default_row_groupby), - col: _.toArray(this.default_col_groupby), - }; - } - this.pivot_table.set_groupby(options); - this.display_data(); - }, - - do_show: function () { - this.do_push_state({}); - return this._super(); + return $.when(deferred1, deferred2).then(function () { + if (this.enabled) { + this.activate_display(); + } + }); }, - display_data: function () { - var pivot = this.pivot_table; - if (pivot.stale_data) { - pivot.update_data().done(this.proxy('display_data')); - } else { - this.$('.graph_main_content svg').remove(); - this.table.empty(); - - if (pivot.no_data) { - var msg = 'No data available. Try to remove any filter or add some data.'; - this.table.append($('' + msg + '')); - } else { - var table_modes = ['pivot', 'heatmap', 'row_heatmap', 'col_heatmap']; - if (_.contains(table_modes, this.mode)) { - this.draw_table(); - } else { - this.$('.graph_main_content').append($('
    ')); - var options = { - svg: this.$('.graph_main_content svg')[0], - mode: this.mode, - pivot: this.pivot_table, - width: this.$el.width(), - height: Math.min(Math.max(document.documentElement.clientHeight - 116 - 60, 250), Math.round(0.8*this.$el.width())), - measure_label: this.measure_label() - }; - openerp.web_graph.draw_chart(options); - } + activate_display: function () { + this.pivot.on('redraw_required', this, this.proxy('display_data')); + this.pivot.update_data(); + this.enabled = true; + instance.web.bus.on('click', this, function (ev) { + if (this.dropdown) { + this.dropdown.remove(); + this.dropdown = null; } - } + }); }, -/****************************************************************************** - * Event handling methods... - ******************************************************************************/ - handle_header_event: function (options) { - var pivot = this.pivot_table, - id = options.id, - header = pivot.get_header(id), - dim = header.root.groupby.length; + display_data: function () { + var pivot = this.pivot; + this.$('.graph_main_content svg').remove(); + this.table.empty(); - if (header.is_expanded) { - pivot.fold(header); - this.register_groupby(); + if (pivot.no_data) { + var msg = 'No data available. Try to remove any filter or add some data.'; + this.table.append($('' + msg + '')); } else { - if (header.path.length < header.root.groupby.length) { - var field = header.root.groupby[header.path.length]; - pivot.expand(id, field).then(this.proxy('register_groupby')); + var table_modes = ['pivot', 'heatmap', 'row_heatmap', 'col_heatmap']; + if (_.contains(table_modes, this.mode)) { + this.draw_table(); } else { - this.display_dropdown({id:header.id, - target: $(options.event.target), - x: options.event.pageX, - y: options.event.pageY}); + this.$('.graph_main_content').append($('
    ')); + var options = { + svg: this.$('.graph_main_content svg')[0], + mode: this.mode, + pivot: this.pivot, + width: this.$el.width(), + height: Math.min(Math.max(document.documentElement.clientHeight - 116 - 60, 250), Math.round(0.8*this.$el.width())), + measure_label: this.measure_label() + }; + openerp.web_graph.draw_chart(options); } } }, @@ -227,65 +271,26 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.display_data(); }, - register_groupby: function() { - var self = this, - query = this.search_view.query; - this.groupby_mode = 'manual'; - - var rows = _.map(this.pivot_table.rows.groupby, function (group) { - return make_facet('GroupBy', group); - }); - var cols = _.map(this.pivot_table.cols.groupby, function (group) { - return make_facet('ColGroupBy', group); - }); - - query.reset(rows.concat(cols)); - - function make_facet (category, fields) { - var values, - icon, - backbone_field, - cat_name; - if (!(fields instanceof Array)) { fields = [fields]; } - if (category === 'GroupBy') { - cat_name = 'group_by'; - icon = 'w'; - backbone_field = self.search_view._s_groupby; - } else { - cat_name = 'col_group_by'; - icon = 'f'; - backbone_field = self.search_field; - } - values = _.map(fields, function (field) { - var context = {}; - context[cat_name] = field; - return {label: self.fields[field].string, value: {attrs:{domain: [], context: context}}}; - }); - return {category:category, values: values, icon:icon, field: backbone_field}; - } - }, - measure_selection: function (event) { event.preventDefault(); var measure = event.target.attributes['data-choice'].nodeValue; - this.pivot_table.set_measure((measure === '__count') ? null : measure); - this.display_data(); + var actual_measure = (measure === '__count') ? null : measure + this.pivot.config({measure:actual_measure}); }, option_selection: function (event) { event.preventDefault(); switch (event.target.attributes['data-choice'].nodeValue) { case 'swap_axis': - this.pivot_table.swap_axis(); - this.register_groupby(); + this.pivot.swap_axis(); break; case 'expand_all': - this.pivot_table.invalidate_data(); - this.display_data(); + this.pivot.rows.headers = null; + this.pivot.cols.headers = null; + this.pivot.update_data(); break; case 'update_values': - this.pivot_table.stale_data = true; - this.display_data(); + this.pivot.update_data(); break; case 'export_data': // Export code... To do... @@ -293,12 +298,32 @@ instance.web_graph.GraphView = instance.web.View.extend({ } }, - - cell_click_callback: function (event) { + header_cell_clicked: function (event) { event.preventDefault(); event.stopPropagation(); - var id = event.target.attributes['data-id'].nodeValue; - this.handle_header_event({id:id, event:event}); + var id = event.target.attributes['data-id'].nodeValue, + header = this.pivot.get_header(id), + self = this, + dim = header.root.groupby.length; + + if (header.is_expanded) { + this.pivot.fold(header); + } else { + if (header.path.length < header.root.groupby.length) { + var field = header.root.groupby[header.path.length]; + this.pivot.expand(id, field); + } else { + var fields = _.map(this.important_fields, function (field) { + return {id: field, value: self.fields[field].string}; + }); + this.dropdown = $(QWeb.render('field_selection', {fields:fields, header_id:id})); + $(event.target).after(this.dropdown); + this.dropdown.css({position:'absolute', + left:event.pageX, + top:event.pageY}); + this.$('.field-selection').next('.dropdown-menu').toggle(); + } + } }, field_selection: function (event) { @@ -306,40 +331,21 @@ instance.web_graph.GraphView = instance.web.View.extend({ id = event.target.attributes['data-id'].nodeValue, field_id = event.target.attributes['data-field-id'].nodeValue; event.preventDefault(); - this.pivot_table.expand(id, field_id).then(function () { - self.register_groupby(); - }); - }, - - display_dropdown: function (options) { - var self = this, - pivot = this.pivot_table, - dropdown_options = { - header_id: options.id, - fields: _.map(self.important_fields, function (field) { - return {id: field, value: self.fields[field].string}; - })}; - this.dropdown = $(QWeb.render('field_selection', dropdown_options)); - options.target.after(this.dropdown); - this.dropdown.css({position:'absolute', - left:options.x, - top:options.y}); - this.$('.field-selection').next('.dropdown-menu').toggle(); + this.pivot.expand(id, field_id); }, /****************************************************************************** * Drawing pivot table methods... ******************************************************************************/ draw_table: function () { - this.pivot_table.rows.main.title = 'Total'; - this.pivot_table.cols.main.title = this.measure_label(); + this.pivot.rows.main.title = 'Total'; + this.pivot.cols.main.title = this.measure_label(); this.draw_top_headers(); - _.each(this.pivot_table.rows.headers, this.proxy('draw_row')); + _.each(this.pivot.rows.headers, this.proxy('draw_row')); }, measure_label: function () { - var pivot = this.pivot_table; - return (pivot.measure) ? this.fields[pivot.measure].string : 'Quantity'; + return (this.pivot.measure) ? this.fields[this.pivot.measure].string : 'Quantity'; }, make_border_cell: function (colspan, rowspan) { @@ -358,7 +364,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ draw_top_headers: function () { var self = this, - pivot = this.pivot_table, + pivot = this.pivot, height = _.max(_.map(pivot.cols.headers, function(g) {return g.path.length;})), header_cells = [[this.make_border_cell(1, height)]]; @@ -406,13 +412,13 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, get_measure_type: function () { - var measure = this.pivot_table.measure; + var measure = this.pivot.measure; return (measure) ? this.fields[measure].type : 'integer'; }, draw_row: function (row) { var self = this, - pivot = this.pivot_table, + pivot = this.pivot, measure_type = this.get_measure_type(), html_row = $(''), row_header = this.make_border_cell(1,1) @@ -471,6 +477,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ return cell; } }, + }); -}; +}; \ No newline at end of file diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 3938acb501e..a38ee51bc78 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -5,6 +5,9 @@ 'use strict'; openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherMixin, { + + // PivotTable require a 'update_data' after init to be ready + // to do: add an option to enable/disable update_data at the end of init init: function (model, domain) { openerp.EventDispatcherMixin.init.call(this); this.rows = { groupby: [], main: null, headers: null }; @@ -16,7 +19,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM this.data_loader = new openerp.web_graph.DataLoader(model); this.no_data = true; - this.stale_data = true; }, visible_fields: function () { @@ -27,31 +29,42 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM return result; }, - set_domain: function (domain) { - if (!_.isEqual(domain, this.domain)) { - this.domain = domain; - this.stale_data = true; - } - }, + config: function (options) { + var changed = false; + var groupby_changed = false; + var default_options = { + update:true, + domain:this.domain, + col_groupby: this.cols.groupby, + row_groupby: this.rows.groupby, + measure: this.measure, + silent:false + }; + var options = _.extend(default_options, options); - set_measure: function (measure) { - if (measure !== this.measure) { - this.measure = measure; - this.stale_data = true; + if (!_.isEqual(options.domain, this.domain)) { + this.domain = options.domain; + changed = true; } - }, - - set_groupby: function (groupbys) { - var col_changed = !_.isEqual(groupbys.col, this.cols.groupby), - row_changed = !_.isEqual(groupbys.row, this.rows.groupby); - - this.rows.groupby = groupbys.row; - this.cols.groupby = groupbys.col; - - if (col_changed || row_changed) { - this.invalidate_data(); - this.trigger('groupby_changed'); + if (options.measure !== this.measure) { + this.measure = options.measure; + changed = true; } + if (!_.isEqual(options.col_groupby, this.cols.groupby)) { + this.cols.groupby = options.col_groupby; + changed = true; + this.cols.headers = null; + groupby_changed = true; + } + if (!_.isEqual(options.row_groupby, this.rows.groupby)) { + this.rows.groupby = options.row_groupby; + this.rows.headers = null; + changed = true; + groupby_changed = true; + } + + if (!options.silent && groupby_changed) { this.trigger('groupby_changed'); } + if (options.update && changed) { this.update_data(); } }, set_value: function (id1, id2, value) { @@ -136,15 +149,14 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM var fold_lvls = _.map(header.root.headers, function(g) {return g.path.length;}); var new_groupby_length = _.max(fold_lvls); - if (new_groupby_length < header.root.groupby.length) { - this.trigger('groupby_changed'); - } - - header.root.groupby.splice(new_groupby_length); header.children = []; this.cells = _.reject(this.cells, function (cell) { return (_.contains(ids_to_remove, cell.x) || _.contains(ids_to_remove, cell.y)); }); + if (new_groupby_length < header.root.groupby.length) { + header.root.groupby.splice(new_groupby_length); + this.trigger('groupby_changed'); + } this.trigger('redraw_required'); }, @@ -218,15 +230,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM } }, - invalidate_data: function () { - this.cells = null; - this.rows.main = null; - this.cols.main = null; - this.rows.headers = null; - this.cols.headers = null; - this.stale_data = true; - }, - update_data: function () { var self = this, options = { @@ -237,14 +240,16 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM }; return this.data_loader.load_data(options).then (function (result) { - self.stale_data = false; if (result) { self.no_data = false; if (self.cols.headers) { self.update_headers(self.cols, result.col_headers); - self.update_headers(self.rows, result.row_headers); } else { self.expand_headers(self.cols, result.col_headers); + } + if (self.rows.headers) { + self.update_headers(self.rows, result.row_headers); + } else { self.expand_headers(self.rows, result.row_headers); } self.cells = result.cells; @@ -530,8 +535,6 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({ } }, - }); - })(); \ No newline at end of file diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 8ebcecb01ce..c96ce941767 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -1,5 +1,5 @@ -
    +
    +
    +

    + No data to display. +

    +

    + No data are available. Try to add some records, or make sure + that there is no active filter in the search bar. +

    +
    -- cgit v1.2.3 From 5a2ddfdf8053f2166ddcbcd04299e5788f64b786 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 26 Dec 2013 13:34:49 +0100 Subject: [FIX] forces an update when the user switches back to the graph view, to make sure the data displayed are up to date (graph view, addon web_graph) bzr revid: ged@openerp.com-20131226123449-qjm7hvkhfsdvi7pw --- addons/web_graph/static/src/js/graph.js | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 17a0721fd82..18432d9fa61 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -119,6 +119,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ if (!this.graph_widget.enabled) { this.graph_widget.activate_display(); + this.ViewManager.on('switch_mode', this, function () {this.graph_widget.pivot.update_data(); }); } }, -- cgit v1.2.3 From c44786804d289f768606c29f1dd48451370f0e32 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 26 Dec 2013 14:37:35 +0100 Subject: [IMP] adds an image when a graph view has no data to display (it uses the same image as an empty dashboard) (addon web_graph) bzr revid: ged@openerp.com-20131226133735-x2g7veg6d9p77y2d --- addons/web_graph/static/src/css/graph.css | 4 ---- addons/web_graph/static/src/js/graph.js | 2 -- addons/web_graph/static/src/xml/web_graph.xml | 14 +++++++------- 3 files changed, 7 insertions(+), 13 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index 7b3e289e548..764fcdca209 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -4,10 +4,6 @@ text-align: right; } -.graph_main_content .oe_view_nocontent_create:before { - background-image: none !important; -} - td.graph_border { background-color: rgb(227, 227, 227); text-align: left; diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 18432d9fa61..b56a2cde7a3 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -283,8 +283,6 @@ instance.web_graph.Graph = instance.web.Widget.extend({ } if (this.pivot.no_data) { this.$('.graph_main_content').append($(QWeb.render('graph_no_data'))); - // var msg = 'No data available. Try to remove any filter or add some data.'; - // this.table.append($('' + msg + '')); } else { var table_modes = ['pivot', 'heatmap', 'row_heatmap', 'col_heatmap']; if (_.contains(table_modes, this.mode)) { diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 8c1791d80d5..262e0df4c96 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -53,12 +53,12 @@
    -

    - No data to display. -

    -

    - No data are available. Try to add some records, or make sure - that there is no active filter in the search bar. -

    +
    +

    No data to display.

    +

    + No data are available. Try to add some records, or make sure + that there is no active filter in the search bar. +

    +
    -- cgit v1.2.3 From e1e676d737a2f682ed6a106e99b63a4dd377c5d5 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 26 Dec 2013 17:14:57 +0100 Subject: [FIX] correctly calls the parent of the graph view in the constructor (now, the view manager gets the correct view_id) (graph view, addon web_graph) bzr revid: ged@openerp.com-20131226161457-a4k3iflz61fiaqj4 --- addons/web_graph/static/src/js/graph.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index b56a2cde7a3..9806e7011a4 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -18,7 +18,7 @@ instance.web_graph.GraphView = instance.web.View.extend({ view_type: 'graph', init: function(parent, dataset, view_id, options) { - this._super(parent); + this._super(parent, dataset, view_id, options); this.dataset = dataset; this.model = new instance.web.Model(dataset.model, {group_by_no_leaf: true}); this.search_view = parent.searchview; -- cgit v1.2.3 From 0650d9d7380ec1885e6f9bd6627b7d14fd2eeded Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 27 Dec 2013 11:22:40 +0100 Subject: [FIX] correctly displays fields of type 'selection' in graph view. Previously, the code only displayed the key and not the value (addon web_graph) bzr revid: ged@openerp.com-20131227102240-gmgik0p5lujssm3w --- addons/web_graph/static/src/js/graph.js | 1 + addons/web_graph/static/src/js/pivot.js | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 9806e7011a4..cfac0ea02f6 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -233,6 +233,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ // get the fields descriptions and measure list from the model var deferred2 = this.model.call('fields_get', []).then(function (fs) { self.fields = fs; + self.pivot.config({fields:fs}); var temp = _.map(fs, function (field, name) { return {name:name, type: field.type}; }); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index a9a6a4f465e..e94b82df389 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -42,6 +42,10 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM }; options = _.extend(default_options, options); + if (options.fields) { + this.data_loader.fields = options.fields; + } + if (!_.isEqual(options.domain, this.domain)) { this.domain = options.domain; changed = true; @@ -302,6 +306,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM openerp.web_graph.DataLoader = openerp.web.Class.extend({ init: function (model) { this.model = model; + this.fields = null; }, get_groups: function (fields, domain, groupbys, options) { @@ -325,7 +330,7 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({ var non_empty_results = _.filter(results, function (group) { return group.attributes.length > 0; }); - _.each(non_empty_results, self.sanitize_value); + _.each(non_empty_results, self.sanitize_value.bind(self)); if (groupbys.length <= 1) { return non_empty_results; } else { @@ -345,6 +350,17 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({ sanitize_value: function (group) { var value = group.attributes.value; + + if (this.fields && + group.attributes.grouped_on && + this.fields[group.attributes.grouped_on].type === 'selection') { + var selection = this.fields[group.attributes.grouped_on].selection; + var value_lookup = _.find(selection, function (val) { + return val[0] === value; + }); + group.attributes.value = (value_lookup) ? value_lookup[1] : 'undefined'; + return; + } if (value === false) { group.attributes.value = 'undefined'; } else if (value instanceof Array) { -- cgit v1.2.3 From ed4fdc51080c88c6cc289eedb86407c0587d1648 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 27 Dec 2013 11:25:10 +0100 Subject: [REF] simplifies a for loop to make the code simpler (addon web_graph) bzr revid: ged@openerp.com-20131227102510-dwpjth4fng4ze14e --- addons/web_graph/static/src/js/graph.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index cfac0ea02f6..3a6d5e8ffed 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -460,7 +460,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ .append(this.make_header_title(row).attr('data-id', row.id)) .addClass('graph_border'); - for (var i in _.range(row.path.length)) { + for (var i = 0; i < row.path.length; i++) { row_header.prepend($('', {class:'web_graph_indent'})); } -- cgit v1.2.3 From 868be53bae50a49d86658102baa092c81e048691 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 27 Dec 2013 15:28:14 +0100 Subject: [IMP] incline the x-axis text by 15 degree when there are too many bars to display in a bar chart. Also, reduces the number of 'ticks' displayed (addon web_graph) bzr revid: ged@openerp.com-20131227142814-8ktqqxlthfa5hxe8 --- addons/web_graph/static/src/js/graph.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 3a6d5e8ffed..33d17e2b059 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -578,9 +578,15 @@ instance.web_graph.Graph = instance.web.Widget.extend({ var chart = nv.models.multiBarChart() .width(self.width) .height(self.height) + .reduceXTicks(false) .stacked(self.bar_ui === 'stack') .staggerLabels(true); + if (self.width / data[0].values.length < 100) { + chart.rotateLabels(-15); + chart.reduceXTicks(true); + chart.margin({bottom:40}); + } if (dim_x === 1 && dim_y === 0) { chart.showControls(false); } d3.select(self.svg) -- cgit v1.2.3 From 66ee322d0ff749cbbc8ba382ebb89a755bed66d4 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 27 Dec 2013 15:35:08 +0100 Subject: [FIX] fixes a crash happening when the context of some attributes does not have a 'group_by' attribute (in the group fields of the search view) bzr revid: ged@openerp.com-20131227143508-3g04fn2s5u9vxams --- addons/web_graph/static/src/js/graph.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 33d17e2b059..7dc6d261b0d 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -224,7 +224,9 @@ instance.web_graph.Graph = instance.web.Widget.extend({ _.each(g.children, function (g) { if (g.attrs.context) { var field_id = py.eval(g.attrs.context).group_by; - self.important_fields.push(field_id); + if (field_id) { + self.important_fields.push(field_id); + } } }); }); -- cgit v1.2.3 From 650d792413ebb6fa0af8783a97f7de032dd47d42 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 27 Dec 2013 15:55:01 +0100 Subject: [IMP] removes the 'group/stack' buttons from the bar chart ui and adds 'group/stack' controls in the option menu of the graph widget. It makes small graphs much cleaner (addon web_graph) bzr revid: ged@openerp.com-20131227145501-0hf21nieyl8mgomm --- addons/web_graph/static/src/js/graph.js | 14 +++++++++++++- addons/web_graph/static/src/xml/web_graph.xml | 4 ++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 7dc6d261b0d..6a70a9c4459 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -317,6 +317,18 @@ instance.web_graph.Graph = instance.web.Widget.extend({ option_selection: function (event) { event.preventDefault(); switch (event.target.attributes['data-choice'].nodeValue) { + case 'bar_grouped': + this.bar_ui = 'group'; + if (this.mode === 'bar_chart') { + this.display_data(); + } + break; + case 'bar_stacked': + this.bar_ui = 'stack'; + if (this.mode === 'bar_chart') { + this.display_data(); + } + break; case 'swap_axis': this.pivot.swap_axis(); break; @@ -582,6 +594,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ .height(self.height) .reduceXTicks(false) .stacked(self.bar_ui === 'stack') + .showControls(false) .staggerLabels(true); if (self.width / data[0].values.length < 100) { @@ -589,7 +602,6 @@ instance.web_graph.Graph = instance.web.Widget.extend({ chart.reduceXTicks(true); chart.margin({bottom:40}); } - if (dim_x === 1 && dim_y === 0) { chart.showControls(false); } d3.select(self.svg) .datum(data) diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 262e0df4c96..29e48b1b782 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -29,9 +29,13 @@ Options
    -- cgit v1.2.3 From fb63eb63ededd5dd5c747728cd0d23a3b409f77b Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 27 Dec 2013 16:07:19 +0100 Subject: [IMP] removes the stagger labels in bar charts, only uses the inclined labels when necessary (addon web_graph) bzr revid: ged@openerp.com-20131227150719-olinm65mh515quc2 --- addons/web_graph/static/src/js/graph.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 6a70a9c4459..ffc94e6dd84 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -594,10 +594,9 @@ instance.web_graph.Graph = instance.web.Widget.extend({ .height(self.height) .reduceXTicks(false) .stacked(self.bar_ui === 'stack') - .showControls(false) - .staggerLabels(true); + .showControls(false); - if (self.width / data[0].values.length < 100) { + if (self.width / data[0].values.length < 80) { chart.rotateLabels(-15); chart.reduceXTicks(true); chart.margin({bottom:40}); -- cgit v1.2.3 From e69f4d1af6180f95d22f52e735f1f716b28de45f Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 27 Dec 2013 16:20:55 +0100 Subject: [FIX] fixes a rendering bug which happened when the rowspan (or colspan) attributes were set to 0. Now, it is always set to a value >= 1 (addon web_graph) bzr revid: ged@openerp.com-20131227152055-77fvsc27mzs0x5t9 --- addons/web_graph/static/src/js/graph.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index ffc94e6dd84..80b7eb07d6c 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -399,8 +399,8 @@ instance.web_graph.Graph = instance.web.Widget.extend({ make_border_cell: function (colspan, rowspan) { return $('').addClass('graph_border') - .attr('colspan', colspan) - .attr('rowspan', rowspan); + .attr('colspan', (colspan) ? colspan : 1) + .attr('rowspan', (rowspan) ? rowspan : 1); }, make_header_title: function (header) { -- cgit v1.2.3 From 3d5b03af08409caf78f3deef263ebebb894d9e61 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 31 Dec 2013 10:02:57 +0100 Subject: [IMP] changes the css of the pivot table to make it look decent (at least, not as awful as before), (addon web_graph) bzr revid: ged@openerp.com-20131231090257-y0os22omx0pgjaqb --- addons/web_graph/static/src/css/graph.css | 45 ++++++++++++++++++++----------- addons/web_graph/static/src/js/graph.js | 19 +++++++------ 2 files changed, 38 insertions(+), 26 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index 764fcdca209..cc738bd73eb 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -1,15 +1,40 @@ .graph_main_content td { - border: 1px solid black; - padding: 0.5rem; + font-size: 12px; + background: #fff; + margin: 45px; + border-collapse: collapse; + text-align: left; + vertical-align: middle; +} + +.graph_main_content th { + font-size: 13px; + font-weight: normal; + color: #039; + padding: 10px 8px; + border-bottom: 2px solid #6678b1; + vertical-align: top; +} + +.graph_main_content td { + border-bottom: 1px solid #ccc; + padding: 6px 8px; text-align: right; + text-color: black; } td.graph_border { - background-color: rgb(227, 227, 227); - text-align: left; + color: #669; + text-align: left; + border-right: 1px solid #6678b1; white-space: nowrap; } +.graph_main_content tbody tr:hover td +{ + color: #009; +} + span.field-selection { display: none; padding: 0; @@ -23,18 +48,6 @@ span.web_graph_indent { cursor: pointer; } -tr.graph_top td { - text-align: center; -} - -tr.graph_top li { - text-align: left; -} - -.graph_main_content tr:hover { - background-color: rgb(245,245,245); -} - .graph_widget .dropdown-menu { font-size: 13px; padding: 4px 0; diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 80b7eb07d6c..9fcb7f3ea8e 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -397,8 +397,9 @@ instance.web_graph.Graph = instance.web.Widget.extend({ return (this.pivot.measure) ? this.fields[this.pivot.measure].string : 'Quantity'; }, - make_border_cell: function (colspan, rowspan) { - return $('').addClass('graph_border') + make_border_cell: function (colspan, rowspan, headercell) { + var tag = (headercell) ? $('') : $(''); + return tag.addClass('graph_border') .attr('colspan', (colspan) ? colspan : 1) .attr('rowspan', (rowspan) ? rowspan : 1); }, @@ -413,9 +414,10 @@ instance.web_graph.Graph = instance.web.Widget.extend({ draw_top_headers: function () { var self = this, + thead = $(''), pivot = this.pivot, height = _.max(_.map(pivot.cols.headers, function(g) {return g.path.length;})), - header_cells = [[this.make_border_cell(1, height)]]; + header_cells = [[this.make_border_cell(1, height, true)]]; function set_dim (cols) { _.each(cols.children, set_dim); @@ -429,7 +431,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ } function make_col_header (col) { - var cell = self.make_border_cell(col.width, col.height); + var cell = self.make_border_cell(col.width, col.height, true); return cell.append(self.make_header_title(col).attr('data-id', col.id)); } @@ -452,12 +454,13 @@ instance.web_graph.Graph = instance.web.Widget.extend({ make_cells(pivot.cols.headers, 0); } else { make_cells(pivot.cols.main.children, 1); - header_cells[0].push(self.make_border_cell(1, height).append('Total').css('font-weight', 'bold')); + header_cells[0].push(self.make_border_cell(1, height, true).append('Total').css('font-weight', 'bold')); } _.each(header_cells, function (cells) { - self.table.append($('').append(cells)); + thead.append($('').append(cells)); }); + self.table.append(thead); }, get_measure_type: function () { @@ -500,10 +503,6 @@ instance.web_graph.Graph = instance.web.Widget.extend({ var color, total, cell = $(''); - if ((self.mode === 'pivot') && (row.is_expanded) && (row.path.length <=2)) { - color = row.path.length * 5 + 240; - cell.css('background-color', $.Color(color, color, color)); - } if (value === undefined) { return cell; } -- cgit v1.2.3 From b9f9857454aa4c7db23ee366945528775f798ec9 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 31 Dec 2013 10:48:23 +0100 Subject: [IMP] small css fix to make sure the headers are displayed with the same color (addon web_graph) bzr revid: ged@openerp.com-20131231094823-cxhxdpebrmrq6jyv --- addons/web_graph/static/src/css/graph.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index cc738bd73eb..d1b80274738 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -24,7 +24,7 @@ } td.graph_border { - color: #669; + color: #039; text-align: left; border-right: 1px solid #6678b1; white-space: nowrap; -- cgit v1.2.3 From d63db7b67f817178a3698904cacdd655676ed673 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 31 Dec 2013 10:49:29 +0100 Subject: [IMP] makes sure that the graph view properly honors default mode request as described in the xml (addon web_graph) bzr revid: ged@openerp.com-20131231094929-giqkzmean1lralow --- addons/web_graph/static/src/js/graph.js | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 9fcb7f3ea8e..8c652239d2a 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -54,9 +54,28 @@ instance.web_graph.GraphView = instance.web.View.extend({ measure = null, stacked = false; - if (arch.attrs.type === 'bar' || !_.has(arch.attrs, 'type')) { + if (!_.has(arch.attrs, 'type')) { this.graph_widget.mode = 'bar_chart'; + } else { + switch (arch.attrs.type) { + case 'bar': + this.graph_widget.mode = 'bar_chart'; + break; + case 'pie': + this.graph_widget.mode = 'pie_chart'; + break; + case 'line': + this.graph_widget.mode = 'line_chart'; + break; + case 'pivot': + case 'heatmap': + case 'row_heatmap': + case 'col_heatmap': + this.graph_widget.mode = arch.attrs.type; + break; + } } + if (arch.attrs.stacked === 'True') { stacked = true; } @@ -190,7 +209,6 @@ instance.web_graph.Graph = instance.web.Widget.extend({ this.fields = []; this.pivot = new openerp.web_graph.PivotTable(model, []); this.mode = 'pivot'; - if (_.has(options, 'mode')) { this.mode = mode; } this.enabled = true; if (_.has(options, 'enabled')) { this.enabled = options.enabled; } this.visible_ui = true; @@ -200,6 +218,9 @@ instance.web_graph.Graph = instance.web.Widget.extend({ // hide ui/show, stacked/grouped config: function (options) { + // Possible modes: pivot, heatmap, row_heatmap, col_heatmap, + // bar_chart, pie_chart, line_chart + if (_.has(options, 'mode')) { this.mode = mode; } if (_.has(options, 'visible_ui')) { this.visible_ui = options.visible_ui; } @@ -509,17 +530,17 @@ instance.web_graph.Graph = instance.web.Widget.extend({ cell.append(instance.web.format_value(value, {type: measure_type})); if (self.mode === 'heatmap') { total = pivot.get_total(); - color = Math.floor(50 + 205*(total - value)/total); + color = Math.floor(90 + 165*(total - value)/total); cell.css('background-color', $.Color(255, color, color)); } if (self.mode === 'row_heatmap') { total = pivot.get_total(row); - color = Math.floor(50 + 205*(total - value)/total); + color = Math.floor(90 + 165*(total - value)/total); cell.css('background-color', $.Color(255, color, color)); } if (self.mode === 'col_heatmap') { total = pivot.get_total(col); - color = Math.floor(50 + 205*(total - value)/total); + color = Math.floor(90 + 165*(total - value)/total); cell.css('background-color', $.Color(255, color, color)); } return cell; -- cgit v1.2.3 From 9f6aad4fdd15ee65d2cb9a68e68a28bd6a279d04 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 31 Dec 2013 13:19:58 +0100 Subject: [IMP] yet another css fix to add border to tables in graph view (addon web_graph) bzr revid: ged@openerp.com-20131231121958-8bsz6d710o5xrgli --- addons/web_graph/static/src/css/graph.css | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index d1b80274738..0fc35bf4c9a 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -16,6 +16,14 @@ vertical-align: top; } +.graph_main_content thead { + border: 1px solid #6678b1; +} + +.graph_main_content tbody { + border: 1px solid #ccc; +} + .graph_main_content td { border-bottom: 1px solid #ccc; padding: 6px 8px; -- cgit v1.2.3 From 8347c44966b3718a23fc1d7867a6db0de8d09731 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 2 Jan 2014 11:01:27 +0100 Subject: [FIX] fixes a crash when the graph view receives an array of values instead of a single value describing a field (addon web_graph) bzr revid: ged@openerp.com-20140102100127-7bmviyzujjmlfg02 --- addons/web_graph/static/src/js/graph.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 8c652239d2a..cba45302050 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -246,7 +246,11 @@ instance.web_graph.Graph = instance.web.Widget.extend({ if (g.attrs.context) { var field_id = py.eval(g.attrs.context).group_by; if (field_id) { - self.important_fields.push(field_id); + if (field_id instanceof Array) { + self.important_fields.concat(field_id); + } else { + self.important_fields.push(field_id); + } } } }); -- cgit v1.2.3 From 2514343b52ecf98adb72333edcb4b8434f07d82c Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 3 Jan 2014 15:22:15 +0100 Subject: [IMP] adds support for more than one measure in graph view. (addon web_graph) bzr revid: ged@openerp.com-20140103142215-z19pnxmnla8xugx0 --- addons/web_graph/static/src/css/graph.css | 17 +++-- addons/web_graph/static/src/js/graph.js | 109 ++++++++++++++++++++++-------- addons/web_graph/static/src/js/pivot.js | 55 +++++++-------- 3 files changed, 120 insertions(+), 61 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css index 0fc35bf4c9a..6693899a0c8 100644 --- a/addons/web_graph/static/src/css/graph.css +++ b/addons/web_graph/static/src/css/graph.css @@ -1,26 +1,28 @@ .graph_main_content td { font-size: 12px; - background: #fff; + /*background: #fff;*/ margin: 45px; border-collapse: collapse; text-align: left; vertical-align: middle; } + .graph_main_content th { font-size: 13px; font-weight: normal; color: #039; padding: 10px 8px; - border-bottom: 2px solid #6678b1; vertical-align: top; } .graph_main_content thead { border: 1px solid #6678b1; + border-bottom: 2px solid #6678b1; + /*color: #039;*/ } -.graph_main_content tbody { +.graph_main_content tbody td{ border: 1px solid #ccc; } @@ -28,7 +30,6 @@ border-bottom: 1px solid #ccc; padding: 6px 8px; text-align: right; - text-color: black; } td.graph_border { @@ -77,3 +78,11 @@ span.web_graph_indent { color: black; text-decoration: none; } + +th.measure_row { + color: black; + font-size: 12px; + /*border: 0 !important;*/ + padding:0px 5px 0px 5px ; + margin:0; +} diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index cba45302050..978c893db19 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -51,7 +51,8 @@ instance.web_graph.GraphView = instance.web.View.extend({ view_loading: function (fields_view_get) { var self = this, arch = fields_view_get.arch, - measure = null, + measures = [], + title = arch.attrs.string, stacked = false; if (!_.has(arch.attrs, 'type')) { @@ -90,20 +91,24 @@ instance.web_graph.GraphView = instance.web.View.extend({ self.default_col_groupby.push(field.attrs.name); break; case 'measure': - measure = field.attrs.name; + measures.push(field.attrs.name); break; } } else { // old style, kept for backward compatibility if ('operator' in field.attrs) { - measure = (measure) ? measure : field.attrs.name; + measures.push(field.attrs.name); } else { self.default_row_groupby.push(field.attrs.name); } } }); + if (measures.length === 0) { + measures.push('__count'); + } this.graph_widget.config({ - measure:measure, + measures:measures, update:false, + title: title, bar_ui: (stacked) ? 'stack' : 'group' }); }, @@ -214,6 +219,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ this.visible_ui = true; this.bar_ui = 'group'; // group or stack this.config(options || {}); + this.title = 'Graph'; }, // hide ui/show, stacked/grouped @@ -227,6 +233,9 @@ instance.web_graph.Graph = instance.web.Widget.extend({ if (_.has(options, 'bar_ui')) { this.bar_ui = options.bar_ui; } + if (_.has(options, 'title')) { + this.title = options.title; + } this.pivot.config(options); }, @@ -335,8 +344,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ measure_selection: function (event) { event.preventDefault(); var measure = event.target.attributes['data-choice'].nodeValue; - var actual_measure = (measure === '__count') ? null : measure; - this.pivot.config({measure:actual_measure}); + this.pivot.config({measures:[measure]}); }, option_selection: function (event) { @@ -413,13 +421,13 @@ instance.web_graph.Graph = instance.web.Widget.extend({ ******************************************************************************/ draw_table: function () { this.pivot.rows.main.title = 'Total'; - this.pivot.cols.main.title = this.measure_label(); + this.pivot.cols.main.title = this.title; this.draw_top_headers(); _.each(this.pivot.rows.headers, this.proxy('draw_row')); }, - measure_label: function () { - return (this.pivot.measure) ? this.fields[this.pivot.measure].string : 'Quantity'; + measure_label: function (measure) { + return (measure !== '__count') ? this.fields[measure].string : 'Quantity'; }, make_border_cell: function (colspan, rowspan, headercell) { @@ -456,7 +464,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ } function make_col_header (col) { - var cell = self.make_border_cell(col.width, col.height, true); + var cell = self.make_border_cell(col.width*pivot.measures.length, col.height, true); return cell.append(self.make_header_title(col).attr('data-id', col.id)); } @@ -479,24 +487,62 @@ instance.web_graph.Graph = instance.web.Widget.extend({ make_cells(pivot.cols.headers, 0); } else { make_cells(pivot.cols.main.children, 1); - header_cells[0].push(self.make_border_cell(1, height, true).append('Total').css('font-weight', 'bold')); + if (pivot.get_cols_leaves().length > 1) { + header_cells[0].push(self.make_border_cell(pivot.measures.length, height, true).append('Total').css('font-weight', 'bold')); + } } _.each(header_cells, function (cells) { thead.append($('').append(cells)); }); + + if (pivot.measures.length >= 2) { + thead.append(self.make_measure_row()); + } + self.table.append(thead); }, - get_measure_type: function () { - var measure = this.pivot.measure; - return (measure) ? this.fields[measure].type : 'integer'; + make_measure_row: function() { + var self = this, + measures = this.pivot.measures, + cols = this.pivot.cols.headers, + measure_cells, + measure_row = $(''); + + measure_row.append($('')); + + _.each(cols, function (col) { + if (!col.children.length) { + for (var i = 0; i < measures.length; i++) { + measure_cells = $('').addClass('measure_row'); + measure_cells.append(self.measure_label(measures[i])); + measure_row.append(measure_cells); + } + } + }); + + if (this.pivot.get_cols_leaves().length > 1) { + for (var i = 0; i < measures.length; i++) { + measure_cells = $('').addClass('measure_row'); + measure_cells.append(self.measure_label(measures[i])); + measure_row.append(measure_cells); + } + } + return measure_row; + }, + + get_measure_types: function () { + var self = this; + return _.map(this.pivot.measures, function (measure) { + return (measure !== '__count') ? self.fields[measure].type : 'integer'; + }); }, draw_row: function (row) { var self = this, pivot = this.pivot, - measure_type = this.get_measure_type(), + measure_types = this.get_measure_types(), html_row = $(''), row_header = this.make_border_cell(1,1) .append(this.make_header_title(row).attr('data-id', row.id)) @@ -510,21 +556,24 @@ instance.web_graph.Graph = instance.web.Widget.extend({ _.each(pivot.cols.headers, function (col) { if (col.children.length === 0) { - var value = pivot.get_value(row.id, col.id), - cell = make_cell(value, col); - html_row.append(cell); + var values = pivot.get_value(row.id, col.id, new Array(measure_types.length)); + for (var i = 0; i < values.length; i++) { + html_row.append(make_cell(values[i], measure_types[i], col)); + } } }); - if (pivot.cols.main.children.length > 0) { - var cell = make_cell(pivot.get_total(row), pivot.cols.main) - .css('font-weight', 'bold'); - html_row.append(cell); + if (pivot.get_cols_leaves().length > 1) { + var total_vals = pivot.get_total(row); + for (var j = 0; j < total_vals.length; j++) { + var cell = make_cell(total_vals[j], measure_types[j], pivot.cols.main).css('font-weight', 'bold'); + html_row.append(cell); + } } this.table.append(html_row); - function make_cell (value, col) { + function make_cell (value, measure_type, col) { var color, total, cell = $(''); @@ -564,31 +613,31 @@ instance.web_graph.Graph = instance.web.Widget.extend({ if ((dim_x === 0) && (dim_y === 0)) { data = [{key: 'Total', values:[{ x: 'Total', - y: this.pivot.get_value(this.pivot.rows.main.id, this.pivot.cols.main.id), + y: this.pivot.get_value(this.pivot.rows.main.id, this.pivot.cols.main.id)[0], }]}]; // Only column groupbys **************************************************** } else if ((dim_x === 0) && (dim_y >= 1)){ data = _.map(this.pivot.get_columns_depth(1), function (header) { return { key: header.title, - values: [{x:header.root.main.title, y: self.pivot.get_total(header)}] + values: [{x:header.root.main.title, y: self.pivot.get_total(header)[0]}] }; }); // Just 1 row groupby ****************************************************** } else if ((dim_x === 1) && (dim_y === 0)) { data = _.map(this.pivot.rows.main.children, function (pt) { - var value = self.pivot.get_value(pt.id, self.pivot.cols.main.id), + var value = self.pivot.get_value(pt.id, self.pivot.cols.main.id)[0], title = (pt.title !== undefined) ? pt.title : 'Undefined'; return {x: title, y: value}; }); - data = [{key: this.measure_label(), values:data}]; + data = [{key: self.measure_label(self.pivot.measures[0]), values:data}]; // 1 row groupby and some col groupbys************************************** } else if ((dim_x === 1) && (dim_y >= 1)) { data = _.map(this.pivot.get_columns_depth(1), function (colhdr) { var values = _.map(self.pivot.get_rows_depth(1), function (header) { return { x: header.title || 'Undefined', - y: self.pivot.get_value(header.id, colhdr.id, 0) + y: self.pivot.get_value(header.id, colhdr.id, 0)[0] }; }); return {key: colhdr.title || 'Undefined', values: values}; @@ -605,7 +654,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ }); return { x: hdr.title || 'Undefined', - y: (subhdr) ? self.pivot.get_total(subhdr) : 0 + y: (subhdr) ? self.pivot.get_total(subhdr)[0] : 0 }; }); return {key:key, values: values}; @@ -651,7 +700,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ return p || 'Undefined'; }).join('/'); if (dim_y === 0) { - title = self.measure_label(); + title = self.measure_label(self.pivot.measures[0]); } return {values: values, key: title}; }); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index e94b82df389..4e1359339dd 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -14,7 +14,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM this.cols = { groupby: [], main: null, headers: null }; this.cells = []; this.domain = domain; - this.measure = null; + this.measures = ['__count']; this.data_loader = new openerp.web_graph.DataLoader(model); @@ -22,11 +22,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM }, visible_fields: function () { - var result = this.rows.groupby.concat(this.cols.groupby); - if (this.measure) { - result = result.concat(this.measure); - } - return result; + var result = this.rows.groupby.concat(this.cols.groupby, this.measures); + return _.without(result, '__count'); }, config: function (options) { @@ -37,7 +34,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM domain:this.domain, col_groupby: this.cols.groupby, row_groupby: this.rows.groupby, - measure: this.measure, + measures: this.measures, silent:false }; options = _.extend(default_options, options); @@ -50,8 +47,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM this.domain = options.domain; changed = true; } - if (options.measure !== this.measure) { - this.measure = options.measure; + if (!_.isEqual(options.measures, this.measures)) { + this.measures = options.measures; changed = true; } if (!_.isEqual(options.col_groupby, this.cols.groupby)) { @@ -71,26 +68,26 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM if (options.update && changed) { this.update_data(); } }, - set_value: function (id1, id2, value) { + set_value: function (id1, id2, values) { var x = Math.min(id1, id2), y = Math.max(id1, id2), cell = _.find(this.cells, function (c) { return ((c.x == x) && (c.y == y)); }); if (cell) { - cell.value = value; + cell.values = values; } else { - this.cells.push({x: x, y: y, value: value}); + this.cells.push({x: x, y: y, values: values}); } }, - get_value: function (id1, id2, default_value) { + get_value: function (id1, id2, default_values) { var x = Math.min(id1, id2), y = Math.max(id1, id2), cell = _.find(this.cells, function (c) { return ((c.x == x) && (c.y == y)); }); - return (cell === undefined) ? default_value : cell.value; + return (cell === undefined) ? default_values : cell.values; }, is_row: function (id) { @@ -187,11 +184,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM } }); if (other) { - if (self.measure) { - self.set_value(new_header_id, other.id, data.attributes.aggregates[self.measure]); - } else { - self.set_value(new_header_id, other.id, data.attributes.length); - } + self.set_value(new_header_id, other.id, _.map(self.measures, function (measure) { + return (measure === '__count') ? data.attributes.length : data.attributes.aggregates[measure]; + })); } }); }); @@ -239,7 +234,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM options = { col_groupby: this.cols.groupby, row_groupby: this.rows.groupby, - measure: this.measure, + measures: this.measures, domain: this.domain, }; @@ -391,9 +386,9 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({ var self = this, cols = options.col_groupby, rows = options.row_groupby, - visible_fields = rows.concat(cols); + visible_fields = _.without(rows.concat(cols, options.measures), '__count'); - if (options.measure) { visible_fields = visible_fields.concat(options.measure); } + // if (options.measure) { visible_fields = visible_fields.concat(options.measure); } var groupbys = _.map(_.range(cols.length + 1), function (i) { return cols.slice(0, i).concat(rows); @@ -416,9 +411,13 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({ }); }, - get_value: function (data, measure) { + get_value: function (data, measures) { var attr = data.attributes; - return (measure) ? attr.aggregates[measure] : attr.length; + var result = _.map(measures, function (measure) { + return (measure === '__count') ? attr.length : attr.aggregates[measure]; + }); + return result; + // return (measure) ? attr.aggregates[measure] : attr.length; }, format_data: function (total, col_data, row_data, cell_data, options) { @@ -451,7 +450,7 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({ children: [], title: (parent) ? data.attributes.value : '', domain: (parent) ? data.model._domain : options.domain, - total: this.get_value(options.total, options.measure), + total: this.get_value(options.total, options.measures), }; if (main.path.length < depth) { @@ -468,7 +467,9 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({ var attr = group.attributes, group_val = (attr.value instanceof Array) ? attr.value[1] : attr.value, path = current_path, - value = (options.measure) ? attr.aggregates[options.measure] : attr.length; + values = _.map(options.measures, function (measure) { + return (measure === '__count') ? attr.length : attr.aggregates[measure]; + }); group_val = (group_val === false) ? undefined : group_val; @@ -483,7 +484,7 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({ }); current_cells.push({x: Math.min(row.id, col.id), y: Math.max(row.id, col.id), - value: value}); + values: values}); if (attr.has_children) { self.make_cells (group.subgroups_data, index, path, current_cells, rows, cols, options); -- cgit v1.2.3 From 64775d40988ebff185a01797ac502e2ca12167bf Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 3 Jan 2014 15:32:36 +0100 Subject: [IMP] improves the rendering of heatmap modes when multiple measures are displayed (addon web_graph) bzr revid: ged@openerp.com-20140103143236-80zmxauy75b0n205 --- addons/web_graph/static/src/js/graph.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 978c893db19..93cac5146ec 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -558,7 +558,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ if (col.children.length === 0) { var values = pivot.get_value(row.id, col.id, new Array(measure_types.length)); for (var i = 0; i < values.length; i++) { - html_row.append(make_cell(values[i], measure_types[i], col)); + html_row.append(make_cell(values[i], measure_types[i], i, col)); } } }); @@ -566,14 +566,14 @@ instance.web_graph.Graph = instance.web.Widget.extend({ if (pivot.get_cols_leaves().length > 1) { var total_vals = pivot.get_total(row); for (var j = 0; j < total_vals.length; j++) { - var cell = make_cell(total_vals[j], measure_types[j], pivot.cols.main).css('font-weight', 'bold'); + var cell = make_cell(total_vals[j], measure_types[j], i, pivot.cols.main).css('font-weight', 'bold'); html_row.append(cell); } } this.table.append(html_row); - function make_cell (value, measure_type, col) { + function make_cell (value, measure_type, index, col) { var color, total, cell = $(''); @@ -582,18 +582,18 @@ instance.web_graph.Graph = instance.web.Widget.extend({ } cell.append(instance.web.format_value(value, {type: measure_type})); if (self.mode === 'heatmap') { - total = pivot.get_total(); - color = Math.floor(90 + 165*(total - value)/total); + total = pivot.get_total()[i]; + color = Math.floor(90 + 165*(total - Math.abs(value))/total); cell.css('background-color', $.Color(255, color, color)); } if (self.mode === 'row_heatmap') { - total = pivot.get_total(row); - color = Math.floor(90 + 165*(total - value)/total); + total = pivot.get_total(row)[i]; + color = Math.floor(90 + 165*(total - Math.abs(value))/total); cell.css('background-color', $.Color(255, color, color)); } if (self.mode === 'col_heatmap') { - total = pivot.get_total(col); - color = Math.floor(90 + 165*(total - value)/total); + total = pivot.get_total(col)[i]; + color = Math.floor(90 + 165*(total - Math.abs(value))/total); cell.css('background-color', $.Color(255, color, color)); } return cell; -- cgit v1.2.3 From 47762dfca2c49a8da9f9fd1b57f966a27d96f602 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 3 Jan 2014 15:44:18 +0100 Subject: [IMP] allows the selection of multiple measures in graph view (addon web_graph) bzr revid: ged@openerp.com-20140103144418-7mstnfwah6v6jkkx --- addons/web_graph/static/src/js/graph.js | 8 ++++++-- addons/web_graph/static/src/js/pivot.js | 8 ++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 93cac5146ec..e8e4e561ef4 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -344,7 +344,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ measure_selection: function (event) { event.preventDefault(); var measure = event.target.attributes['data-choice'].nodeValue; - this.pivot.config({measures:[measure]}); + this.pivot.config({toggle_measure:measure}); }, option_selection: function (event) { @@ -421,7 +421,11 @@ instance.web_graph.Graph = instance.web.Widget.extend({ ******************************************************************************/ draw_table: function () { this.pivot.rows.main.title = 'Total'; - this.pivot.cols.main.title = this.title; + if (this.pivot.measures.length == 1) { + this.pivot.cols.main.title = this.measure_label(this.pivot.measures[0]); + } else { + this.pivot.cols.main.title = this.title; + } this.draw_top_headers(); _.each(this.pivot.rows.headers, this.proxy('draw_row')); }, diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 4e1359339dd..e112082e018 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -51,6 +51,14 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM this.measures = options.measures; changed = true; } + if (options.toggle_measure) { + if (_.contains(this.measures, options.toggle_measure)) { + this.measures = _.without(this.measures, options.toggle_measure); + } else { + this.measures.push(options.toggle_measure); + } + changed = true; + } if (!_.isEqual(options.col_groupby, this.cols.groupby)) { this.cols.groupby = options.col_groupby; changed = true; -- cgit v1.2.3 From 6a422f27d7bffd8457f275e2cc3c41f58e37a66d Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 6 Jan 2014 09:37:34 +0100 Subject: [FIX] fixes the computation of the color displayed in heatmap modes in graph view. (addon web_graph) bzr revid: ged@openerp.com-20140106083734-qkrvuhe7398me2d2 --- addons/web_graph/static/src/js/graph.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index e8e4e561ef4..7973a5646bc 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -570,7 +570,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ if (pivot.get_cols_leaves().length > 1) { var total_vals = pivot.get_total(row); for (var j = 0; j < total_vals.length; j++) { - var cell = make_cell(total_vals[j], measure_types[j], i, pivot.cols.main).css('font-weight', 'bold'); + var cell = make_cell(total_vals[j], measure_types[j], j, pivot.cols.main).css('font-weight', 'bold'); html_row.append(cell); } } @@ -586,17 +586,17 @@ instance.web_graph.Graph = instance.web.Widget.extend({ } cell.append(instance.web.format_value(value, {type: measure_type})); if (self.mode === 'heatmap') { - total = pivot.get_total()[i]; + total = pivot.get_total()[index]; color = Math.floor(90 + 165*(total - Math.abs(value))/total); cell.css('background-color', $.Color(255, color, color)); } if (self.mode === 'row_heatmap') { - total = pivot.get_total(row)[i]; + total = pivot.get_total(row)[index]; color = Math.floor(90 + 165*(total - Math.abs(value))/total); cell.css('background-color', $.Color(255, color, color)); } if (self.mode === 'col_heatmap') { - total = pivot.get_total(col)[i]; + total = pivot.get_total(col)[index]; color = Math.floor(90 + 165*(total - Math.abs(value))/total); cell.css('background-color', $.Color(255, color, color)); } -- cgit v1.2.3 From 0aa0ea9e6c3dc6ba8b9e55f5fe04c762fcdabfae Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 7 Jan 2014 11:59:54 +0100 Subject: [REF] merges the dataloader and pivot table classes together, where they truly belong. (addon web_graph) bzr revid: ged@openerp.com-20140107105954-beb16wspdl6ikemw --- addons/web_graph/static/src/js/pivot.js | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index e112082e018..e7e37afc679 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -15,10 +15,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM this.cells = []; this.domain = domain; this.measures = ['__count']; - - this.data_loader = new openerp.web_graph.DataLoader(model); - this.no_data = true; + this.model = model; + this.fields = null; }, visible_fields: function () { @@ -40,7 +39,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM options = _.extend(default_options, options); if (options.fields) { - this.data_loader.fields = options.fields; + this.fields = options.fields; } if (!_.isEqual(options.domain, this.domain)) { @@ -179,7 +178,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM } var otherDim = (header.root === this.cols) ? this.rows : this.cols; - return this.data_loader.get_groups(this.visible_fields(), header.domain, otherDim.groupby, {first_groupby:field_id, add_path:true}) + return this.get_groups(this.visible_fields(), header.domain, otherDim.groupby, {first_groupby:field_id, add_path:true}) .then(function (groups) { _.each(groups.reverse(), function (group) { var new_header_id = self.make_header(group, header); @@ -246,7 +245,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM domain: this.domain, }; - return this.data_loader.load_data(options).then (function (result) { + return this.load_data(options).then (function (result) { if (result) { self.no_data = false; if (self.cols.headers) { @@ -304,14 +303,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM root.main = root.headers[0]; }, -}); - -openerp.web_graph.DataLoader = openerp.web.Class.extend({ - init: function (model) { - this.model = model; - this.fields = null; - }, - + //*************************************************************** + // Data loading code from db... + //*************************************************************** get_groups: function (fields, domain, groupbys, options) { var self = this, groupings = ((options || {}).first_groupby) ? [(options || {}).first_groupby].concat(groupbys) : groupbys; @@ -419,13 +413,12 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({ }); }, - get_value: function (data, measures) { + get_value_from_data: function (data, measures) { var attr = data.attributes; var result = _.map(measures, function (measure) { return (measure === '__count') ? attr.length : attr.aggregates[measure]; }); return result; - // return (measure) ? attr.aggregates[measure] : attr.length; }, format_data: function (total, col_data, row_data, cell_data, options) { @@ -458,7 +451,7 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({ children: [], title: (parent) ? data.attributes.value : '', domain: (parent) ? data.model._domain : options.domain, - total: this.get_value(options.total, options.measures), + total: this.get_value_from_data(options.total, options.measures), }; if (main.path.length < depth) { -- cgit v1.2.3 From f62567507929c64725e2baf28c6881d6eb657916 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 10 Jan 2014 12:35:57 +0100 Subject: [REF] large refactoring in graph view: changes the underlying data structure of Pivot class and simplifies a lot of code (addon web_graph) bzr revid: ged@openerp.com-20140110113557-6bs77dg7qcdofy40 --- addons/web_graph/static/src/js/graph.js | 448 ++++++++++++++----------- addons/web_graph/static/src/js/pivot.js | 557 +++++++++++++++++--------------- 2 files changed, 546 insertions(+), 459 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 7973a5646bc..84a7d147ac2 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -33,52 +33,39 @@ instance.web_graph.GraphView = instance.web.View.extend({ }; }, - get_context: function (facet) { - var col_group_by = _.map(facet.values.models, function (model) { - return model.attributes.value.attrs.context.col_group_by; - }); - return {col_group_by : col_group_by}; - }, - - start: function () { - var options = {enabled:false}; - this.graph_widget = new openerp.web_graph.Graph(this, this.model, options); - this.graph_widget.appendTo(this.$el); - this.graph_widget.pivot.on('groupby_changed', this, this.proxy('register_groupby')); - return this.load_view(); - }, - view_loading: function (fields_view_get) { var self = this, arch = fields_view_get.arch, measures = [], - title = arch.attrs.string, stacked = false; + this.widget_config = { title: arch.attrs.string }; + + debugger; if (!_.has(arch.attrs, 'type')) { - this.graph_widget.mode = 'bar_chart'; + this.widget_config.mode = 'bar_chart'; } else { switch (arch.attrs.type) { case 'bar': - this.graph_widget.mode = 'bar_chart'; + this.widget_config.mode = 'bar_chart'; break; case 'pie': - this.graph_widget.mode = 'pie_chart'; + this.widget_config.mode = 'pie_chart'; break; case 'line': - this.graph_widget.mode = 'line_chart'; + this.widget_config.mode = 'line_chart'; break; case 'pivot': case 'heatmap': case 'row_heatmap': case 'col_heatmap': - this.graph_widget.mode = arch.attrs.type; + this.widget_config.mode = arch.attrs.type; break; } } if (arch.attrs.stacked === 'True') { - stacked = true; + this.widget_config.stacked = true; } _.each(arch.children, function (field) { @@ -105,18 +92,32 @@ instance.web_graph.GraphView = instance.web.View.extend({ if (measures.length === 0) { measures.push('__count'); } - this.graph_widget.config({ - measures:measures, - update:false, - title: title, - bar_ui: (stacked) ? 'stack' : 'group' + this.widget_config.row_groupby = self.default_row_groupby; + this.widget_config.col_groupby = self.default_col_groupby; + this.widget_config.measures = measures; + // measures:measures, + // update:false, + // title: title, + // bar_ui: (stacked) ? 'stack' : 'group' + // }); + }, + + get_context: function (facet) { + var col_group_by = _.map(facet.values.models, function (model) { + return model.attributes.value.attrs.context.col_group_by; }); + return {col_group_by : col_group_by}; }, do_search: function (domain, context, group_by) { var col_groupby = context.col_group_by || [], options = {domain:domain}; + if (!this.graph_widget) { + this.graph_widget = new openerp.web_graph.Graph(this, this.model, domain, this.widget_config); + this.graph_widget.appendTo(this.$el); + this.graph_widget.on('groupby_changed', this, this.proxy('register_groupby')); + } this.search_view_groupby = group_by; if (group_by.length && this.groupby_mode !== 'manual') { @@ -139,7 +140,11 @@ instance.web_graph.GraphView = instance.web.View.extend({ options.row_groupby = _.toArray(this.default_row_groupby); options.col_groupby = _.toArray(this.default_col_groupby); } - this.graph_widget.pivot.config(options); + this.graph_widget.set_domain(domain); + this.graph_widget.set_col_groupby(options.col_groupby); + this.graph_widget.set_row_groupby(options.row_groupby); + + // this.graph_widget.pivot.config(options); if (!this.graph_widget.enabled) { this.graph_widget.activate_display(); @@ -153,49 +158,50 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, register_groupby: function() { - var self = this, - query = this.search_view.query; - - this.groupby_mode = 'manual'; - if (_.isEqual(this.search_view_groupby, this.graph_widget.pivot.rows.groupby) || - (!_.has(this.search_view, '_s_groupby'))) { - return; - } - var rows = _.map(this.graph_widget.pivot.rows.groupby, function (group) { - return make_facet('GroupBy', group); - }); - var cols = _.map(this.graph_widget.pivot.cols.groupby, function (group) { - return make_facet('ColGroupBy', group); - }); - - query.reset(rows.concat(cols)); - - function make_facet (category, fields) { - var values, - icon, - backbone_field, - cat_name; - if (!(fields instanceof Array)) { fields = [fields]; } - if (category === 'GroupBy') { - cat_name = 'group_by'; - icon = 'w'; - backbone_field = self.search_view._s_groupby; - } else { - cat_name = 'col_group_by'; - icon = 'f'; - backbone_field = self.search_field; - } - values = _.map(fields, function (field) { - var context = {}; - context[cat_name] = field; - return {label: self.graph_widget.fields[field].string, value: {attrs:{domain: [], context: context}}}; - }); - return {category:category, values: values, icon:icon, field: backbone_field}; - } + // var self = this, + // query = this.search_view.query; + + // this.groupby_mode = 'manual'; + // if (_.isEqual(this.search_view_groupby, this.graph_widget.pivot.rows.groupby) || + // (!_.has(this.search_view, '_s_groupby'))) { + // return; + // } + // var rows = _.map(this.graph_widget.pivot.rows.groupby, function (group) { + // return make_facet('GroupBy', group); + // }); + // var cols = _.map(this.graph_widget.pivot.cols.groupby, function (group) { + // return make_facet('ColGroupBy', group); + // }); + + // query.reset(rows.concat(cols)); + + // function make_facet (category, fields) { + // var values, + // icon, + // backbone_field, + // cat_name; + // if (!(fields instanceof Array)) { fields = [fields]; } + // if (category === 'GroupBy') { + // cat_name = 'group_by'; + // icon = 'w'; + // backbone_field = self.search_view._s_groupby; + // } else { + // cat_name = 'col_group_by'; + // icon = 'f'; + // backbone_field = self.search_field; + // } + // values = _.map(fields, function (field) { + // var context = {}; + // context[cat_name] = field; + // return {label: self.graph_widget.fields[field].string, value: {attrs:{domain: [], context: context}}}; + // }); + // return {category:category, values: values, icon:icon, field: backbone_field}; + // } }, }); -instance.web_graph.Graph = instance.web.Widget.extend({ +// important_fields = [field], field = {field: _,type: _, string: _} +instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMixin, { template: 'GraphWidget', events: { @@ -206,108 +212,181 @@ instance.web_graph.Graph = instance.web.Widget.extend({ 'click a.field-selection' : 'field_selection', }, - init: function(parent, model, options) { + init: function(parent, model, domain, options) { + var self = this; + this._super(parent); this.model = model; - this.important_fields = []; - this.measure_list = []; - this.fields = []; - this.pivot = new openerp.web_graph.PivotTable(model, []); - this.mode = 'pivot'; - this.enabled = true; - if (_.has(options, 'enabled')) { this.enabled = options.enabled; } - this.visible_ui = true; - this.bar_ui = 'group'; // group or stack - this.config(options || {}); - this.title = 'Graph'; - }, - - // hide ui/show, stacked/grouped - config: function (options) { - // Possible modes: pivot, heatmap, row_heatmap, col_heatmap, - // bar_chart, pie_chart, line_chart - if (_.has(options, 'mode')) { this.mode = mode; } - if (_.has(options, 'visible_ui')) { - this.visible_ui = options.visible_ui; - } - if (_.has(options, 'bar_ui')) { - this.bar_ui = options.bar_ui; - } - if (_.has(options, 'title')) { - this.title = options.title; - } - this.pivot.config(options); + this.domain = domain; + this.mode = options.mode || 'pivot'; + this.title = options.title || 'Graph'; + this.visible_ui = options.visible_ui || true; + this.pivot_options = options; }, start: function() { var self = this; this.table = $('
    '); this.$('.graph_main_content').append(this.table); - // get the most important fields (of the model) by looking at the - // groupby filters defined in the search view - var options = {model:this.model, view_type: 'search'}, - deferred1 = instance.web.fields_view_get(options).then(function (search_view) { - var groups = _.select(search_view.arch.children, function (c) { - return (c.tag == 'group') && (c.attrs.string != 'Display'); - }); - _.each(groups, function(g) { - _.each(g.children, function (g) { - if (g.attrs.context) { - var field_id = py.eval(g.attrs.context).group_by; - if (field_id) { - if (field_id instanceof Array) { - self.important_fields.concat(field_id); - } else { - self.important_fields.push(field_id); - } - } - } - }); - }); - }); + var def1 = this.get_search_fields().then(function (f) { + self.important_fields = f; + }); - // get the fields descriptions and measure list from the model - var deferred2 = this.model.call('fields_get', []).then(function (fs) { - self.fields = fs; - self.pivot.config({fields:fs}); - var temp = _.map(fs, function (field, name) { - return {name:name, type: field.type}; + var def2 = this.get_model_fields().then(function (f) { + self.fields = f; + self.measure_list = self.get_measures(); + self.add_measures_to_options(); + }); + + $.when(def1, def2).then(function () { + self.pivot = new openerp.web_graph.PivotTable(self.model, self.domain, self.fields, self.pivot_options); + self.pivot.on('redraw_required', self, self.proxy('display_data')); + self.pivot.on('groupby_changed', self, function () { self.trigger('groupby_changed'); }); + instance.web.bus.on('click', self, function () { + if (self.dropdown) { + self.dropdown.remove(); + self.dropdown = null; + } }); - temp = _.filter(temp, function (field) { - return (((field.type === 'integer') || (field.type === 'float')) && (field.name !== 'id')); + self.pivot.activate(); + }); + }, + + get_search_fields: function () { + var self = this, + options = {model:this.model, view_type: 'search'}, + result = []; + + return instance.web.fields_view_get(options).then(function (search_view) { + var groups = _.select(search_view.arch.children, function (c) { + return (c.tag === 'group') && (c.attrs.string != 'Display'); }); - self.measure_list = _.map(temp, function (field) { - return field.name; + _.each(groups, function(g) { + _.each(g.children, function (g) { + if (g.attrs.context) { + var field_id = py.eval(g.attrs.context).group_by; + if (field_id) { + if (field_id instanceof Array) { + result.concat(field_id); + } else { + result.push(field_id); + } + } + } + }); }); + return result; + }); + }, - var measure_selection = self.$('.graph_measure_selection'); - _.each(self.measure_list, function (measure) { - var choice = $('').attr('data-choice', measure) - .attr('href', '#') - .append(self.fields[measure].string); - measure_selection.append($('
  • ').append(choice)); - }); + get_model_fields: function () { + return this.model.call('fields_get', []).then(function (fs) { + return fs; }); + }, - return $.when(deferred1, deferred2).then(function () { - if (this.enabled) { - this.activate_display(); + get_measures: function(fields) { + var measures = []; + _.each(this.fields, function (f, id) { + if (((f.type === 'integer') || (f.type === 'float')) && (id !== 'id')) { + measures.push({field:id, type: f.type, string: f.string}); } }); + return measures; }, - activate_display: function () { - this.pivot.on('redraw_required', this, this.proxy('display_data')); - this.pivot.update_data(); - this.enabled = true; - instance.web.bus.on('click', this, function () { - if (this.dropdown) { - this.dropdown.remove(); - this.dropdown = null; - } + set_domain: function (domain) { + if (this.pivot) { + this.pivot.set_domain(domain); + } else { + this.pivot_options.domain = domain; + } + }, + + set_row_groupby: function (groupby) { + if (this.pivot) { + this.pivot.set_row_groupby(groupby); + } else { + this.pivot_options.row_groupby = groupby; + } + }, + + set_col_groupby: function (groupby) { + if (this.pivot) { + this.pivot.set_col_groupby(groupby); + } else { + this.pivot_options.col_groupby = groupby; + } + }, + + add_measures_to_options: function() { + var measure_selection = this.$('.graph_measure_selection'); + _.each(this.measure_list, function (measure) { + var choice = $('').attr('data-choice', measure.field) + .attr('href', '#') + .append(measure.string); + measure_selection.append($('
  • ').append(choice)); }); }, + // self.fields = fs; + // var temp = _.map(fs, function (field, name) { + // return {name:name, type: field.type}; + // }); + // temp = _.filter(temp, function (field) { + // return (((field.type === 'integer') || (field.type === 'float')) && (field.name !== 'id')); + // }); + // self.measure_list = _.map(temp, function (field) { + // return field.name; + // }); + + // var measure_selection = self.$('.graph_measure_selection'); + // _.each(self.measure_list, function (measure) { + // var choice = $('').attr('data-choice', measure) + // .attr('href', '#') + // .append(self.fields[measure].string); + // measure_selection.append($('
  • ').append(choice)); + // }); + // }); + // }, + + // hide ui/show, stacked/grouped + // config: function (options) { + // Possible modes: pivot, heatmap, row_heatmap, col_heatmap, + // bar_chart, pie_chart, line_chart + // if (_.has(options, 'mode')) { this.mode = mode; } + // if (_.has(options, 'visible_ui')) { + // this.visible_ui = options.visible_ui; + // } + // if (_.has(options, 'bar_ui')) { + // this.bar_ui = options.bar_ui; + // } + // if (_.has(options, 'title')) { + // this.title = options.title; + // } + // debugger; + // this.pivot.config(options); + // }, + + + // get the most important fields (of the model) by looking at the + // groupby filters defined in the search view + + // get the fields descriptions and measure list from the model + + // return $.when(deferred1, deferred2).then(function () { + // self.pivot = new openerp.web_graph.PivotTable(self.model, self.fields); + // self.activate_display(); + // }); + // }, + + set_mode: function (mode) { + + }, + + activate_display: function () { + }, + display_data: function () { this.$('.graph_main_content svg').remove(); this.$('.graph_main_content div').remove(); @@ -344,7 +423,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ measure_selection: function (event) { event.preventDefault(); var measure = event.target.attributes['data-choice'].nodeValue; - this.pivot.config({toggle_measure:measure}); + this.pivot.toggle_measure(measure); }, option_selection: function (event) { @@ -386,12 +465,11 @@ instance.web_graph.Graph = instance.web.Widget.extend({ header = this.pivot.get_header(id), self = this; - if (header.is_expanded) { + if (header.expanded) { this.pivot.fold(header); } else { if (header.path.length < header.root.groupby.length) { - var field = header.root.groupby[header.path.length]; - this.pivot.expand(id, field); + this.pivot.expand(id); } else { if (!this.important_fields.length) { return; @@ -420,20 +498,16 @@ instance.web_graph.Graph = instance.web.Widget.extend({ * Drawing pivot table methods... ******************************************************************************/ draw_table: function () { - this.pivot.rows.main.title = 'Total'; + this.pivot.main_row().title = 'Total'; if (this.pivot.measures.length == 1) { - this.pivot.cols.main.title = this.measure_label(this.pivot.measures[0]); + this.pivot.main_col().title = this.pivot.measures[0].string; } else { - this.pivot.cols.main.title = this.title; + this.pivot.main_col().title = this.title; } this.draw_top_headers(); _.each(this.pivot.rows.headers, this.proxy('draw_row')); }, - measure_label: function (measure) { - return (measure !== '__count') ? this.fields[measure].string : 'Quantity'; - }, - make_border_cell: function (colspan, rowspan, headercell) { var tag = (headercell) ? $('') : $(''); return tag.addClass('graph_border') @@ -445,7 +519,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ return $(' ') .addClass('web_graph_click') .attr('href', '#') - .addClass((header.is_expanded) ? 'fa fa-minus-square' : 'fa fa-plus-square') + .addClass((header.expanded) ? 'fa fa-minus-square' : 'fa fa-plus-square') .append((header.title !== undefined) ? header.title : 'Undefined'); }, @@ -486,11 +560,11 @@ instance.web_graph.Graph = instance.web.Widget.extend({ } } - set_dim(pivot.cols.main); // add width and height info to columns headers - if (pivot.cols.main.children.length === 0) { + set_dim(pivot.main_col()); // add width and height info to columns headers + if (pivot.main_col().children.length === 0) { make_cells(pivot.cols.headers, 0); } else { - make_cells(pivot.cols.main.children, 1); + make_cells(pivot.main_col().children, 1); if (pivot.get_cols_leaves().length > 1) { header_cells[0].push(self.make_border_cell(pivot.measures.length, height, true).append('Total').css('font-weight', 'bold')); } @@ -520,7 +594,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ if (!col.children.length) { for (var i = 0; i < measures.length; i++) { measure_cells = $('').addClass('measure_row'); - measure_cells.append(self.measure_label(measures[i])); + measure_cells.append(measures[i].string); measure_row.append(measure_cells); } } @@ -529,24 +603,17 @@ instance.web_graph.Graph = instance.web.Widget.extend({ if (this.pivot.get_cols_leaves().length > 1) { for (var i = 0; i < measures.length; i++) { measure_cells = $('').addClass('measure_row'); - measure_cells.append(self.measure_label(measures[i])); + measure_cells.append(measures[i].string); measure_row.append(measure_cells); } } return measure_row; }, - get_measure_types: function () { - var self = this; - return _.map(this.pivot.measures, function (measure) { - return (measure !== '__count') ? self.fields[measure].type : 'integer'; - }); - }, - draw_row: function (row) { var self = this, pivot = this.pivot, - measure_types = this.get_measure_types(), + measure_types = _.pluck(this.pivot.measures, 'type'), html_row = $(''), row_header = this.make_border_cell(1,1) .append(this.make_header_title(row).attr('data-id', row.id)) @@ -560,7 +627,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ _.each(pivot.cols.headers, function (col) { if (col.children.length === 0) { - var values = pivot.get_value(row.id, col.id, new Array(measure_types.length)); + var values = pivot.get_values(row.id, col.id); for (var i = 0; i < values.length; i++) { html_row.append(make_cell(values[i], measure_types[i], i, col)); } @@ -570,7 +637,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ if (pivot.get_cols_leaves().length > 1) { var total_vals = pivot.get_total(row); for (var j = 0; j < total_vals.length; j++) { - var cell = make_cell(total_vals[j], measure_types[j], j, pivot.cols.main).css('font-weight', 'bold'); + var cell = make_cell(total_vals[j], measure_types[j], j, pivot.cols[0]).css('font-weight', 'bold'); html_row.append(cell); } } @@ -596,6 +663,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ cell.css('background-color', $.Color(255, color, color)); } if (self.mode === 'col_heatmap') { + debugger; total = pivot.get_total(col)[index]; color = Math.floor(90 + 165*(total - Math.abs(value))/total); cell.css('background-color', $.Color(255, color, color)); @@ -617,42 +685,42 @@ instance.web_graph.Graph = instance.web.Widget.extend({ if ((dim_x === 0) && (dim_y === 0)) { data = [{key: 'Total', values:[{ x: 'Total', - y: this.pivot.get_value(this.pivot.rows.main.id, this.pivot.cols.main.id)[0], + y: this.pivot.get_total(), }]}]; // Only column groupbys **************************************************** } else if ((dim_x === 0) && (dim_y >= 1)){ - data = _.map(this.pivot.get_columns_depth(1), function (header) { + data = _.map(this.pivot.get_columns_with_depth(1), function (header) { return { key: header.title, - values: [{x:header.root.main.title, y: self.pivot.get_total(header)[0]}] + values: [{x:header.root[0].title, y: self.pivot.get_total(header)[0]}] }; }); // Just 1 row groupby ****************************************************** } else if ((dim_x === 1) && (dim_y === 0)) { - data = _.map(this.pivot.rows.main.children, function (pt) { - var value = self.pivot.get_value(pt.id, self.pivot.cols.main.id)[0], + data = _.map(this.pivot.main_row().children, function (pt) { + var value = self.pivot.get_total(pt), title = (pt.title !== undefined) ? pt.title : 'Undefined'; return {x: title, y: value}; }); - data = [{key: self.measure_label(self.pivot.measures[0]), values:data}]; + data = [{key: self.pivot.measures[0].string, values:data}]; // 1 row groupby and some col groupbys************************************** } else if ((dim_x === 1) && (dim_y >= 1)) { - data = _.map(this.pivot.get_columns_depth(1), function (colhdr) { - var values = _.map(self.pivot.get_rows_depth(1), function (header) { + data = _.map(this.pivot.get_cols_with_depth(1), function (colhdr) { + var values = _.map(self.pivot.get_rows_with_depth(1), function (header) { return { x: header.title || 'Undefined', - y: self.pivot.get_value(header.id, colhdr.id, 0)[0] + y: self.pivot.get_values(header.id, colhdr.id, 0)[0] }; }); return {key: colhdr.title || 'Undefined', values: values}; }); // At least two row groupby************************************************* } else { - var keys = _.uniq(_.map(this.pivot.get_rows_depth(2), function (hdr) { + var keys = _.uniq(_.map(this.pivot.get_rows_with_depth(2), function (hdr) { return hdr.title || 'Undefined'; })); data = _.map(keys, function (key) { - var values = _.map(self.pivot.get_rows_depth(1), function (hdr) { + var values = _.map(self.pivot.get_rows_with_depth(1), function (hdr) { var subhdr = _.find(hdr.children, function (child) { return ((child.title === key) || ((child.title === undefined) && (key === 'Undefined'))); }); @@ -697,14 +765,14 @@ instance.web_graph.Graph = instance.web.Widget.extend({ dim_y = this.pivot.cols.groupby.length; var data = _.map(this.pivot.get_cols_leaves(), function (col) { - var values = _.map(self.pivot.get_rows_depth(dim_x), function (row) { - return {x: row.title, y: self.pivot.get_value(row.id,col.id, 0)}; + var values = _.map(self.pivot.get_rows_with_depth(dim_x), function (row) { + return {x: row.title, y: self.pivot.get_values(row.id,col.id, 0)}; }); var title = _.map(col.path, function (p) { return p || 'Undefined'; }).join('/'); if (dim_y === 0) { - title = self.measure_label(self.pivot.measures[0]); + title = self.pivot.measures[0].string; } return {values: values, key: title}; }); @@ -729,7 +797,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({ pie_chart: function () { var self = this, dim_x = this.pivot.rows.groupby.length; - + debugger; var data = _.map(this.pivot.get_rows_leaves(), function (row) { var title = _.map(row.path, function (p) { return p || 'Undefined'; diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index e7e37afc679..49f2ff4b2d5 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -4,163 +4,245 @@ (function () { 'use strict'; +// Pivot Table +// +// Here is a short description of the way the data is organized: +// Main fields: +// cells = [cell] +// cell = {x: _, y: _, values: [value]} +// value = {type: _, value: _} +// measures = [measure] +// measure = {field: _, string: _, type: _} +// rows, cols = {groupby: [groupby], headers: [header]} +// groupby = {field: _, string: _, type: _, interval: _} (interval only if type = date/datetime) +// header = { +// id: _, +// path: _, +// title: _, +// expanded: _, +// parent: _, +// children: _, +// domain: _, +// root: _, +// } +// +// Pivot Table emits the events 'groupby_changed' and 'redraw_required' when necessary. +// PivotTable require a 'update_data' after init to be ready +// to do: add an option to enable/disable update_data at the end of init openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherMixin, { - // PivotTable require a 'update_data' after init to be ready - // to do: add an option to enable/disable update_data at the end of init - init: function (model, domain) { + init: function (model, domain, fields, options) { openerp.EventDispatcherMixin.init.call(this); - this.rows = { groupby: [], main: null, headers: null }; - this.cols = { groupby: [], main: null, headers: null }; + this.rows = { groupby: [], headers: null }; + this.cols = { groupby: [], headers: null }; this.cells = []; this.domain = domain; - this.measures = ['__count']; this.no_data = true; this.model = model; - this.fields = null; + this.fields = fields; + this.fields.__count = {type: 'integer', string:'Quantity'}; + this.measures = [{field:'__count', type: this.fields.type, string:this.fields.string}]; + this.active = false; + if (options.measures) { this.set_measures(options.measures); } + if (options.col_groupby) { this.set_col_groupby(options.col_groupby); } + if (options.row_groupby) { this.set_row_groupby(options.row_groupby); } }, - visible_fields: function () { - var result = this.rows.groupby.concat(this.cols.groupby, this.measures); - return _.without(result, '__count'); + // ---------------------------------------------------------------------- + // Configuration methods + // ---------------------------------------------------------------------- + activate: function() { + this.active = true; + this.update_data(); }, - config: function (options) { - var changed = false; - var groupby_changed = false; - var default_options = { - update:true, - domain:this.domain, - col_groupby: this.cols.groupby, - row_groupby: this.rows.groupby, - measures: this.measures, - silent:false - }; - options = _.extend(default_options, options); + set_domain: function (domain) { + this.domain = domain; + if (this.active) { this.update_data(); } + }, - if (options.fields) { - this.fields = options.fields; + set_measures: function (measures) { + var self = this; + if (!_.isEqual(measures, this.measures)) { + this.measures = []; + _.each(measures, function (m) { self._add_measure(m); }); + if (this.active) { this.update_data(); } } + }, - if (!_.isEqual(options.domain, this.domain)) { - this.domain = options.domain; - changed = true; - } - if (!_.isEqual(options.measures, this.measures)) { - this.measures = options.measures; - changed = true; - } - if (options.toggle_measure) { - if (_.contains(this.measures, options.toggle_measure)) { - this.measures = _.without(this.measures, options.toggle_measure); - } else { - this.measures.push(options.toggle_measure); - } - changed = true; + _add_measure: function (measure) { + if (measure.field && measure.string && measure.type) { + this.measures.push(measure); + } else { + this.measures.push({ + field: measure, + string: this.fields[measure].string, + type: this.fields[measure].type, + }); } - if (!_.isEqual(options.col_groupby, this.cols.groupby)) { - this.cols.groupby = options.col_groupby; - changed = true; + }, + + toggle_measure: function (field_id) { + var current_measure = _.findWhere(this.measures, {field:field_id}); + if (current_measure) { + this.measures = _.without(this.measures, current_measure); + } else { + this.measures.push({ + field: field_id, + type: this.fields[field_id].type, + string: this.fields[field_id].string + }); + } + if (this.active) { this.update_data(); } + }, + + set_col_groupby: function (groupbys) { + var self = this; + if (!_.isEqual(groupbys, this.cols.groupby)) { + this.cols.groupby = []; + _.each(groupbys, function (g) { self._add_groupby(self.cols.groupby, g); }); this.cols.headers = null; - groupby_changed = true; + if (this.active) { + this.trigger('groupby_changed'); + this.update_data(); + } } - if (!_.isEqual(options.row_groupby, this.rows.groupby)) { - this.rows.groupby = options.row_groupby; + }, + + set_row_groupby: function (groupbys) { + var self = this; + if (!_.isEqual(groupbys, this.rows.groupby)) { + this.rows.groupby = []; + _.each(groupbys, function (g) { self._add_groupby(self.rows.groupby, g); }); this.rows.headers = null; - changed = true; - groupby_changed = true; + if (this.active) { + this.trigger('groupby_changed'); + this.update_data(); + } } - - if (!options.silent && groupby_changed) { this.trigger('groupby_changed'); } - if (options.update && changed) { this.update_data(); } }, - set_value: function (id1, id2, values) { - var x = Math.min(id1, id2), - y = Math.max(id1, id2), - cell = _.find(this.cells, function (c) { - return ((c.x == x) && (c.y == y)); - }); - if (cell) { - cell.values = values; + _add_groupby: function(groupby_list, groupby) { + if (groupby.field && groupby.string && groupby.type) { + groupby_list.push(groupby); } else { - this.cells.push({x: x, y: y, values: values}); + groupby_list.push({ + field:groupby, + string: this.fields[groupby].string, + type: this.fields[groupby].type + }); } }, - get_value: function (id1, id2, default_values) { + // ---------------------------------------------------------------------- + // Cells manipulation methods + // ---------------------------------------------------------------------- + add_cell : function (id1, id2, values) { + var x = Math.min(id1, id2), + y = Math.max(id1, id2); + this.cells.push({x: x, y: y, values: values}); + }, + + get_values: function (id1, id2, default_values) { var x = Math.min(id1, id2), y = Math.max(id1, id2), cell = _.find(this.cells, function (c) { - return ((c.x == x) && (c.y == y)); - }); - return (cell === undefined) ? default_values : cell.values; + return ((c.x == x) && (c.y == y)); + }); + return (cell !== undefined) ? cell.values : (default_values || new Array(this.measures.length)); }, + // ---------------------------------------------------------------------- + // Headers/Rows/Cols manipulation methods + // ---------------------------------------------------------------------- is_row: function (id) { return !!_.find(this.rows.headers, function (header) { - return header.id == id; + return header.id === id; }); }, is_col: function (id) { return !!_.find(this.cols.headers, function (header) { - return header.id == id; + return header.id === id; }); }, get_header: function (id) { return _.find(this.rows.headers.concat(this.cols.headers), function (header) { - return header.id == id; + return header.id === id; }); }, // return all columns with a path length of 'depth' - get_columns_depth: function (depth) { - return _.filter(this.cols.headers, function (hdr) { - return hdr.path.length === depth; + get_cols_with_depth: function (depth) { + return _.filter(this.cols.headers, function (header) { + return header.path.length === depth; }); }, // return all rows with a path length of 'depth' - get_rows_depth: function (depth) { - return _.filter(this.rows.headers, function (hdr) { - return hdr.path.length === depth; + get_rows_with_depth: function (depth) { + return _.filter(this.rows.headers, function (header) { + return header.path.length === depth; }); }, // return all non expanded rows get_rows_leaves: function () { - return _.filter(this.rows.headers, function (hdr) { - return !hdr.is_expanded; + return _.filter(this.rows.headers, function (header) { + return !header.expanded; }); }, // return all non expanded cols get_cols_leaves: function () { - return _.filter(this.cols.headers, function (hdr) { - return !hdr.is_expanded; + return _.filter(this.cols.headers, function (header) { + return !header.expanded; }); }, - fold: function (header) { - var list = []; - function tree_traversal(tree) { - list.push(tree); - _.each(tree.children, tree_traversal); + get_ancestors: function (header) { + var self = this; + if (!header.children) return []; + return [].concat.apply([], _.map(header.children, function (c) {return self.get_ancestors_and_self(c); })); + }, + + get_ancestors_and_self: function (header) { + var self = this; + return [].concat.apply([header], _.map(header.children, function (c) { return self.get_ancestors_and_self(c); })); + }, + + get_total: function (header) { + if (header) { + return this.get_values(header.id, this.get_other_root(header).headers[0].id); } - tree_traversal(header); - var ids_to_remove = _.map(_.rest(list), function (h) { return h.id;}); + return this.get_values(this.rows.headers[0].id, this.cols.headers[0].id); + }, + + get_other_root: function (header) { + return (header.root === this.rows) ? this.cols : this.rows; + }, - header.root.headers = _.difference(header.root.headers, _.rest(list)); - header.is_expanded = false; - var fold_lvls = _.map(header.root.headers, function(g) {return g.path.length;}); - var new_groupby_length = _.max(fold_lvls); + main_row: function () { return this.rows.headers[0]; }, + + main_col: function () { return this.cols.headers[0]; }, + // ---------------------------------------------------------------------- + // Table manipulation methods + // ---------------------------------------------------------------------- + fold: function (header) { + var ancestors = this.get_ancestors(header), + removed_ids = _.pluck(ancestors, 'id'); + + header.root.headers = _.difference(header.root.headers, ancestors); header.children = []; + header.expanded = false; + this.cells = _.reject(this.cells, function (cell) { - return (_.contains(ids_to_remove, cell.x) || _.contains(ids_to_remove, cell.y)); + return (_.contains(removed_ids, cell.x) || _.contains(removed_ids, cell.y)); }); + + var new_groupby_length = _.max(_.map(header.root.headers, function(g) {return g.path.length;})); if (new_groupby_length < header.root.groupby.length) { header.root.groupby.splice(new_groupby_length); this.trigger('groupby_changed'); @@ -168,50 +250,54 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM this.trigger('redraw_required'); }, - expand: function (header_id, field_id) { + expand: function (header_id, groupby) { var self = this, - header = this.get_header(header_id); + header = this.get_header(header_id), + otherRoot = this.get_other_root(header), + fields = otherRoot.groupby.concat(this.measures); - if (header.path.length == header.root.groupby.length) { - header.root.groupby.push(field_id); + if (header.path.length === header.root.groupby.length) { + self._add_groupby(header.root.groupby, groupby); this.trigger('groupby_changed'); } + groupby = [header.root.groupby[header.path.length]].concat(otherRoot.groupby); - var otherDim = (header.root === this.cols) ? this.rows : this.cols; - return this.get_groups(this.visible_fields(), header.domain, otherDim.groupby, {first_groupby:field_id, add_path:true}) + return this.get_groups(groupby, fields, header.domain) .then(function (groups) { _.each(groups.reverse(), function (group) { - var new_header_id = self.make_header(group, header); - _.each(group, function (data) { - var other = _.find(otherDim.headers, function (h) { - if (header.root === self.cols) { - return _.isEqual(data.path.slice(1), h.path); + var child_id = self.make_header(group, header); + // make cells + _.each(self.get_ancestors_and_self(group), function (data) { + var values = _.map(self.measures, function (m) { + return data.attributes.aggregates[m.field]; + }); + + var other = _.find(otherRoot.headers, function (h) { + if (header.root === self.cols) { + return _.isEqual(data.path.slice(1), h.path); } else { return _.isEqual(_.rest(data.path), h.path); - } - }); + } + }); if (other) { - self.set_value(new_header_id, other.id, _.map(self.measures, function (measure) { - return (measure === '__count') ? data.attributes.length : data.attributes.aggregates[measure]; - })); + self.add_cell(child_id, other.id, values); } }); }); - header.is_expanded = true; + header.expanded = true; self.trigger('redraw_required'); }); }, - make_header: function (groups, parent) { - var name = groups[0].attributes.value, + make_header: function (group, parent) { + var title = group.attributes.value, new_header = { id: _.uniqueId(), - path: parent.path.concat(name), - title: name, - is_expanded: false, - parent: parent.id, + path: parent.path.concat(title), + title: title, + expanded: false, children: [], - domain: groups[0].model._domain, + domain: group.model._domain, root: parent.root, }; parent.children.splice(0,0, new_header); @@ -227,38 +313,17 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM this.trigger('redraw_required'); }, - get_total: function (header) { - if (header) { - var main = (header.root === this.rows) ? this.cols.main : this.rows.main; - return this.get_value(header.id, main.id); - } else { - return this.rows.main.total; - } - }, - + // ---------------------------------------------------------------------- + // Data loading methods + // ---------------------------------------------------------------------- update_data: function () { - var self = this, - options = { - col_groupby: this.cols.groupby, - row_groupby: this.rows.groupby, - measures: this.measures, - domain: this.domain, - }; + var self = this; - return this.load_data(options).then (function (result) { + return this.load_data().then (function (result) { if (result) { self.no_data = false; - if (self.cols.headers) { - self.update_headers(self.cols, result.col_headers); - } else { - self.expand_headers(self.cols, result.col_headers); - } - if (self.rows.headers) { - self.update_headers(self.rows, result.row_headers); - } else { - self.expand_headers(self.rows, result.row_headers); - } - self.cells = result.cells; + self[self.cols.headers ? 'update_headers' : 'expand_headers'](self.cols, result.col_headers); + self[self.rows.headers ? 'update_headers' : 'expand_headers'](self.rows, result.row_headers); } else { self.no_data = true; } @@ -268,10 +333,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM expand_headers: function (root, new_headers) { root.headers = new_headers; - root.main = new_headers[0]; _.each(root.headers, function (header) { header.root = root; - header.is_expanded = (header.children.length > 0); + header.expanded = (header.children.length > 0); }); }, @@ -280,102 +344,84 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM var corresponding_header = _.find(new_headers, function (h) { return _.isEqual(h.path, header.path); }); - if (corresponding_header && (header.is_expanded)) { - corresponding_header.is_expanded = true; + if (corresponding_header && header.expanded) { + corresponding_header.expanded = true; _.each(corresponding_header.children, function (c) { - c.is_expanded = false; + c.expanded = false; }); } - if (corresponding_header && (!header.is_expanded)) { - corresponding_header.is_expanded = false; + if (corresponding_header && (!header.expanded)) { + corresponding_header.expanded = false; } }); var updated_headers = _.filter(new_headers, function (header) { - return (header.is_expanded !== undefined); + return (header.expanded !== undefined); }); - _.each(updated_headers, function (hdr) { - if (!hdr.is_expanded) { - hdr.children = []; + _.each(updated_headers, function (header) { + if (!header.expanded) { + header.children = []; } - hdr.root = root; + header.root = root; }); root.headers = updated_headers; - root.main = root.headers[0]; }, - //*************************************************************** - // Data loading code from db... - //*************************************************************** - get_groups: function (fields, domain, groupbys, options) { + // options: fields: _, path_prefix: [] + get_groups: function (groupbys, fields, domain, path) { + path = path || []; var self = this, - groupings = ((options || {}).first_groupby) ? [(options || {}).first_groupby].concat(groupbys) : groupbys; + groupby = (groupbys.length) ? groupbys[0] : []; - return this.query_db(fields, domain, groupings).then(function (groups) { - return _.map(groups, function (group) { - return ((options || {}).add_path) ? self.add_path(group, []) : group; - }); + return this._query_db(groupby, fields, domain, path).then(function (groups) { + if (groupbys.length > 1) { + var get_subgroups = $.when.apply(null, _.map(groups, function (group) { + return self.get_groups(_.rest(groupbys), fields, group.model._domain, path.concat(group.attributes.value)).then(function (subgroups) { + group.children = subgroups; + }); + })); + return get_subgroups.then(function () { + return groups; + }); + } else { + return groups; + } }); }, - query_db: function (fields, domain, groupbys) { - var self = this; - return this.model.query(fields) + _query_db: function (groupby, fields, domain, path) { + var self = this, + field_ids = _.without(_.pluck(fields, 'field'), '__count'); + // To do : add code to check if groupby is date/datetime + // and in that case, add the correct code to the context + return this.model.query(field_ids) .filter(domain) - .group_by(groupbys) + .group_by(groupby.field) .then(function (results) { - var non_empty_results = _.filter(results, function (group) { + var groups = _.filter(results, function (group) { return group.attributes.length > 0; }); - _.each(non_empty_results, self.sanitize_value.bind(self)); - if (groupbys.length <= 1) { - return non_empty_results; - } else { - var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) { - var new_domain = result.model._domain; - var new_groupings = groupbys.slice(1); - return self.query_db(fields,new_domain, new_groupings).then(function (subgroups) { - result.subgroups_data = subgroups; - }); - })); - return get_subgroups.then(function () { - return non_empty_results; - }); - } + return _.map(groups, function (g) { return self.format_group(g, path); }); }); }, - sanitize_value: function (group) { - var value = group.attributes.value; + format_group: function (group, current_path) { + var value = group.attributes.value; - if (this.fields && - group.attributes.grouped_on && - this.fields[group.attributes.grouped_on].type === 'selection') { - var selection = this.fields[group.attributes.grouped_on].selection; - var value_lookup = _.find(selection, function (val) { - return val[0] === value; - }); - group.attributes.value = (value_lookup) ? value_lookup[1] : 'undefined'; - return; - } - if (value === false) { - group.attributes.value = 'undefined'; - } else if (value instanceof Array) { - group.attributes.value = value[1]; - } else { - group.attributes.value = value; - } - }, + if (group.attributes.grouped_on && this.fields[group.attributes.grouped_on].type === 'selection') { + var selection = this.fields[group.attributes.grouped_on].selection, + value_lookup = _.find(selection, function (val) { return val[0] === value; }); + group.attributes.value = value_lookup ? value_lookup[1] : 'undefined'; + } else if (value === false) { + group.attributes.value = 'undefined'; + } else if (value instanceof Array) { + group.attributes.value = value[1]; + } - add_path: function (group, current_path) { - var self = this; + group.path = value ? (current_path || []).concat(group.attributes.value) : []; + group.attributes.aggregates.__count = group.attributes.length; - group.path = current_path.concat(group.attributes.value); - var result = [group]; - _.each(group.subgroups_data, function (subgroup) { - result = result.concat(self.add_path(subgroup, group.path)); - }); - return result; + return group; }, // To obtain all the values required to draw the full table, we have to do @@ -384,13 +430,11 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM // 2 + row.groupby.length calls. For example, if row.groupby = [r1, r2, r3] // and col.groupby = [c1, c2], then we will make the call with the following // groupbys: [r1,r2,r3], [c1,r1,r2,r3], [c1,c2,r1,r2,r3], []. - load_data: function (options) { + load_data: function () { var self = this, - cols = options.col_groupby, - rows = options.row_groupby, - visible_fields = _.without(rows.concat(cols, options.measures), '__count'); - - // if (options.measure) { visible_fields = visible_fields.concat(options.measure); } + cols = this.cols.groupby, + rows = this.rows.groupby, + visible_fields = rows.concat(cols, self.measures); var groupbys = _.map(_.range(cols.length + 1), function (i) { return cols.slice(0, i).concat(rows); @@ -398,7 +442,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM groupbys.push([]); var def_array = _.map(groupbys, function (groupby) { - return self.get_groups(visible_fields, options.domain, groupby); + return self.get_groups(groupby, visible_fields, self.domain); }); return $.when.apply(null, def_array).then(function () { @@ -407,92 +451,67 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM col_data = (cols.length !== 0) ? data[data.length - 2] : [], total = data[data.length - 1][0]; - options.total = total; return (total === undefined) ? undefined - : self.format_data(total, col_data, row_data, data, options); - }); - }, - - get_value_from_data: function (data, measures) { - var attr = data.attributes; - var result = _.map(measures, function (measure) { - return (measure === '__count') ? attr.length : attr.aggregates[measure]; + : self.format_data(total, col_data, row_data, data); }); - return result; }, - format_data: function (total, col_data, row_data, cell_data, options) { + format_data: function (total, col_data, row_data, cell_data) { var self = this, - dim_row = options.row_groupby.length, - dim_col = options.col_groupby.length, - col_headers = make_list(this.make_headers(col_data, dim_col, options)), - row_headers = make_list(this.make_headers(row_data, dim_row, options)), + dim_row = this.rows.groupby.length, + dim_col = this.cols.groupby.length, + col_headers = this.get_ancestors_and_self(this.make_headers(col_data, dim_col)), + row_headers = this.get_ancestors_and_self(this.make_headers(row_data, dim_row)), cells = []; + this.cells = []; _.each(cell_data, function (data, index) { - self.make_cells(data, index, [], cells, row_headers, col_headers, options); + self.make_cells(data, index, [], row_headers, col_headers); }); // make it more functional? return {col_headers: col_headers, - row_headers: row_headers, - cells: cells}; - - function make_list (tree) { - return [].concat.apply([tree], _.map(tree.children, make_list)); - } + row_headers: row_headers}; }, - make_headers: function (data, depth, options, parent) { + make_headers: function (data, depth, parent) { var self = this, main = { id: _.uniqueId(), - path: (parent) ? parent.path.concat(data.attributes.value) : [], - parent: parent, + path: parent ? parent.path.concat(data.attributes.value) : [], children: [], - title: (parent) ? data.attributes.value : '', - domain: (parent) ? data.model._domain : options.domain, - total: this.get_value_from_data(options.total, options.measures), + title: parent ? data.attributes.value : '', + domain: parent ? data.model._domain : this.domain, }; if (main.path.length < depth) { - main.children = _.map(data.subgroups_data || data, function (data_pt) { - return self.make_headers (data_pt, depth, options, main); + main.children = _.map(data.children || data, function (data_pt) { + return self.make_headers (data_pt, depth, main); }); } return main; }, - make_cells: function (data, index, current_path, current_cells, rows, cols, options) { + make_cells: function (data, index, current_path, rows, cols) { var self = this; _.each(data, function (group) { var attr = group.attributes, - group_val = (attr.value instanceof Array) ? attr.value[1] : attr.value, - path = current_path, - values = _.map(options.measures, function (measure) { - return (measure === '__count') ? attr.length : attr.aggregates[measure]; + path = attr.grouped_on ? current_path.concat(attr.value) : current_path, + values = _.map(self.measures, function (measure) { + return (measure.field === '__count') ? attr.length : attr.aggregates[measure.field]; }); - group_val = (group_val === false) ? undefined : group_val; - - if (attr.grouped_on !== undefined) { - path = path.concat((attr.value === false) ? 'undefined' : group_val); - } - var row = _.find(rows, function (header) { - return _.isEqual(header.path, path.slice(index)); - }); - var col = _.find(cols, function (header) { - return _.isEqual(header.path, path.slice(0, index)); - }); - current_cells.push({x: Math.min(row.id, col.id), - y: Math.max(row.id, col.id), - values: values}); + var row = _.find(rows, function (header) { return _.isEqual(header.path, path.slice(index)); }); + var col = _.find(cols, function (header) { return _.isEqual(header.path, path.slice(0, index)); }); + self.add_cell(row.id, col.id, values); - if (attr.has_children) { - self.make_cells (group.subgroups_data, index, path, current_cells, rows, cols, options); + if (group.children) { + self.make_cells (group.children, index, path, rows, cols); } }); }, }); -})(); \ No newline at end of file +})(); + + -- cgit v1.2.3 From dbf064e817b3b37fa29c01ef362662ec134707d2 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 10 Jan 2014 13:01:49 +0100 Subject: [REF] removes useless comments (addon web_graph) bzr revid: ged@openerp.com-20140110120149-pi0h75eqlr2tl9n5 --- addons/web_graph/static/src/js/graph.js | 55 +-------------------------------- addons/web_graph/static/src/js/pivot.js | 5 +-- 2 files changed, 2 insertions(+), 58 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 84a7d147ac2..8cdc9a3eb0f 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -41,7 +41,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.widget_config = { title: arch.attrs.string }; - debugger; if (!_.has(arch.attrs, 'type')) { this.widget_config.mode = 'bar_chart'; } else { @@ -238,7 +237,7 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix self.add_measures_to_options(); }); - $.when(def1, def2).then(function () { + return $.when(def1, def2).then(function () { self.pivot = new openerp.web_graph.PivotTable(self.model, self.domain, self.fields, self.pivot_options); self.pivot.on('redraw_required', self, self.proxy('display_data')); self.pivot.on('groupby_changed', self, function () { self.trigger('groupby_changed'); }); @@ -329,57 +328,6 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix }); }, - // self.fields = fs; - // var temp = _.map(fs, function (field, name) { - // return {name:name, type: field.type}; - // }); - // temp = _.filter(temp, function (field) { - // return (((field.type === 'integer') || (field.type === 'float')) && (field.name !== 'id')); - // }); - // self.measure_list = _.map(temp, function (field) { - // return field.name; - // }); - - // var measure_selection = self.$('.graph_measure_selection'); - // _.each(self.measure_list, function (measure) { - // var choice = $('').attr('data-choice', measure) - // .attr('href', '#') - // .append(self.fields[measure].string); - // measure_selection.append($('
  • ').append(choice)); - // }); - // }); - // }, - - // hide ui/show, stacked/grouped - // config: function (options) { - // Possible modes: pivot, heatmap, row_heatmap, col_heatmap, - // bar_chart, pie_chart, line_chart - // if (_.has(options, 'mode')) { this.mode = mode; } - // if (_.has(options, 'visible_ui')) { - // this.visible_ui = options.visible_ui; - // } - // if (_.has(options, 'bar_ui')) { - // this.bar_ui = options.bar_ui; - // } - // if (_.has(options, 'title')) { - // this.title = options.title; - // } - // debugger; - // this.pivot.config(options); - // }, - - - // get the most important fields (of the model) by looking at the - // groupby filters defined in the search view - - // get the fields descriptions and measure list from the model - - // return $.when(deferred1, deferred2).then(function () { - // self.pivot = new openerp.web_graph.PivotTable(self.model, self.fields); - // self.activate_display(); - // }); - // }, - set_mode: function (mode) { }, @@ -797,7 +745,6 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix pie_chart: function () { var self = this, dim_x = this.pivot.rows.groupby.length; - debugger; var data = _.map(this.pivot.get_rows_leaves(), function (row) { var title = _.map(row.path, function (p) { return p || 'Undefined'; diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 49f2ff4b2d5..dcf89de1144 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -9,8 +9,7 @@ // Here is a short description of the way the data is organized: // Main fields: // cells = [cell] -// cell = {x: _, y: _, values: [value]} -// value = {type: _, value: _} +// cell = {x: _, y: _, values: [_]} // measures = [measure] // measure = {field: _, string: _, type: _} // rows, cols = {groupby: [groupby], headers: [header]} @@ -20,7 +19,6 @@ // path: _, // title: _, // expanded: _, -// parent: _, // children: _, // domain: _, // root: _, @@ -28,7 +26,6 @@ // // Pivot Table emits the events 'groupby_changed' and 'redraw_required' when necessary. // PivotTable require a 'update_data' after init to be ready -// to do: add an option to enable/disable update_data at the end of init openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherMixin, { init: function (model, domain, fields, options) { -- cgit v1.2.3 From 2b3b08160cd43f47f1ee11fa0fb6f400849f2fa1 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 10 Jan 2014 15:08:37 +0100 Subject: [REF] simplification of the way Pivot configuration is done in graph view (addon web_graph) bzr revid: ged@openerp.com-20140110140837-tl3ts6za0zr46id7 --- addons/web_graph/static/src/js/graph.js | 158 +++++++++++--------------------- addons/web_graph/static/src/js/pivot.js | 75 +++++++-------- 2 files changed, 83 insertions(+), 150 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 8cdc9a3eb0f..d92d09f3a8c 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -35,37 +35,14 @@ instance.web_graph.GraphView = instance.web.View.extend({ view_loading: function (fields_view_get) { var self = this, - arch = fields_view_get.arch, - measures = [], - stacked = false; + arch = fields_view_get.arch; - this.widget_config = { title: arch.attrs.string }; - - if (!_.has(arch.attrs, 'type')) { - this.widget_config.mode = 'bar_chart'; - } else { - switch (arch.attrs.type) { - case 'bar': - this.widget_config.mode = 'bar_chart'; - break; - case 'pie': - this.widget_config.mode = 'pie_chart'; - break; - case 'line': - this.widget_config.mode = 'line_chart'; - break; - case 'pivot': - case 'heatmap': - case 'row_heatmap': - case 'col_heatmap': - this.widget_config.mode = arch.attrs.type; - break; - } - } - - if (arch.attrs.stacked === 'True') { - this.widget_config.stacked = true; - } + this.widget_config = { + title: arch.attrs.string, + stacked : (arch.attrs.stacked === 'True'), + mode: (arch.attrs.type) ? arch.attrs.type : 'bar', + measures: [], + }; _.each(arch.children, function (field) { if (_.has(field.attrs, 'type')) { @@ -77,28 +54,22 @@ instance.web_graph.GraphView = instance.web.View.extend({ self.default_col_groupby.push(field.attrs.name); break; case 'measure': - measures.push(field.attrs.name); + self.widget_config.measures.push(field.attrs.name); break; } } else { // old style, kept for backward compatibility if ('operator' in field.attrs) { - measures.push(field.attrs.name); + self.widget_config.measures.push(field.attrs.name); } else { self.default_row_groupby.push(field.attrs.name); } } }); - if (measures.length === 0) { - measures.push('__count'); + if (self.widget_config.measures.length === 0) { + self.widget_config.measures.push('__count'); } this.widget_config.row_groupby = self.default_row_groupby; this.widget_config.col_groupby = self.default_col_groupby; - this.widget_config.measures = measures; - // measures:measures, - // update:false, - // title: title, - // bar_ui: (stacked) ? 'stack' : 'group' - // }); }, get_context: function (facet) { @@ -109,46 +80,42 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, do_search: function (domain, context, group_by) { - var col_groupby = context.col_group_by || [], - options = {domain:domain}; + // var col_groupby = context.col_group_by || [], + // options = {domain:domain}; if (!this.graph_widget) { this.graph_widget = new openerp.web_graph.Graph(this, this.model, domain, this.widget_config); this.graph_widget.appendTo(this.$el); this.graph_widget.on('groupby_changed', this, this.proxy('register_groupby')); + this.ViewManager.on('switch_mode', this, function (e) { if (e === 'graph') this.graph_widget.reload(); }); } - this.search_view_groupby = group_by; + // this.search_view_groupby = group_by; - if (group_by.length && this.groupby_mode !== 'manual') { - if (_.isEqual(col_groupby, [])) { - col_groupby = this.default_col_groupby; - } - } - if (group_by.length || col_groupby.length) { - this.groupby_mode = 'manual'; - } - if (!this.graph_widget.enabled) { - options.update = false; - options.silent = true; - } - - if (this.groupby_mode === 'manual') { - options.row_groupby = group_by; - options.col_groupby = col_groupby; - } else { - options.row_groupby = _.toArray(this.default_row_groupby); - options.col_groupby = _.toArray(this.default_col_groupby); - } - this.graph_widget.set_domain(domain); - this.graph_widget.set_col_groupby(options.col_groupby); - this.graph_widget.set_row_groupby(options.row_groupby); + // if (group_by.length && this.groupby_mode !== 'manual') { + // if (_.isEqual(col_groupby, [])) { + // col_groupby = this.default_col_groupby; + // } + // } + // if (group_by.length || col_groupby.length) { + // this.groupby_mode = 'manual'; + // } + // if (!this.graph_widget.enabled) { + // options.update = false; + // options.silent = true; + // } - // this.graph_widget.pivot.config(options); + // if (this.groupby_mode === 'manual') { + // options.row_groupby = group_by; + // options.col_groupby = col_groupby; + // } else { + // options.row_groupby = _.toArray(this.default_row_groupby); + // options.col_groupby = _.toArray(this.default_col_groupby); + // } + // this.graph_widget.set(domain, options.row_groupby, options.col_groupby); + // this.graph_widget.set_domain(domain); + // this.graph_widget.set_col_groupby(options.col_groupby); + // this.graph_widget.set_row_groupby(options.row_groupby); - if (!this.graph_widget.enabled) { - this.graph_widget.activate_display(); - this.ViewManager.on('switch_mode', this, function () {this.graph_widget.pivot.update_data(); }); - } }, do_show: function () { @@ -199,7 +166,6 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, }); -// important_fields = [field], field = {field: _,type: _, string: _} instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMixin, { template: 'GraphWidget', @@ -212,8 +178,6 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix }, init: function(parent, model, domain, options) { - var self = this; - this._super(parent); this.model = model; this.domain = domain; @@ -231,7 +195,7 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix self.important_fields = f; }); - var def2 = this.get_model_fields().then(function (f) { + var def2 = this.model.call('fields_get', []).then(function (f) { self.fields = f; self.measure_list = self.get_measures(); self.add_measures_to_options(); @@ -278,12 +242,6 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix }); }, - get_model_fields: function () { - return this.model.call('fields_get', []).then(function (fs) { - return fs; - }); - }, - get_measures: function(fields) { var measures = []; _.each(this.fields, function (f, id) { @@ -294,27 +252,14 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix return measures; }, - set_domain: function (domain) { - if (this.pivot) { - this.pivot.set_domain(domain); - } else { - this.pivot_options.domain = domain; - } - }, - set_row_groupby: function (groupby) { + set: function (domain, row_groupby, col_groupby) { if (this.pivot) { - this.pivot.set_row_groupby(groupby); + this.pivot.set(domain, row_groupby, col_groupby); } else { - this.pivot_options.row_groupby = groupby; - } - }, - - set_col_groupby: function (groupby) { - if (this.pivot) { - this.pivot.set_col_groupby(groupby); - } else { - this.pivot_options.col_groupby = groupby; + this.pivot_options.domain = domain; + this.pivot_options.row_groupby = row_groupby; + this.pivot_options.col_groupby = col_groupby; } }, @@ -329,10 +274,12 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix }, set_mode: function (mode) { - + this.mode = mode; + this.display_data(); }, - activate_display: function () { + reload: function () { + this.pivot.update_data(); }, display_data: function () { @@ -364,8 +311,7 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix mode_selection: function (event) { event.preventDefault(); var mode = event.target.attributes['data-mode'].nodeValue; - this.mode = mode; - this.display_data(); + this.set_mode(mode); }, measure_selection: function (event) { @@ -623,7 +569,7 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix /****************************************************************************** * Drawing charts methods... ******************************************************************************/ - bar_chart: function () { + bar: function () { var self = this, dim_x = this.pivot.rows.groupby.length, dim_y = this.pivot.cols.groupby.length, @@ -707,7 +653,7 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix }, - line_chart: function () { + line: function () { var self = this, dim_x = this.pivot.rows.groupby.length, dim_y = this.pivot.cols.groupby.length; @@ -742,7 +688,7 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix }); }, - pie_chart: function () { + pie: function () { var self = this, dim_x = this.pivot.rows.groupby.length; var data = _.map(this.pivot.get_rows_leaves(), function (row) { diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index dcf89de1144..10a6b3f9052 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -30,8 +30,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM init: function (model, domain, fields, options) { openerp.EventDispatcherMixin.init.call(this); - this.rows = { groupby: [], headers: null }; - this.cols = { groupby: [], headers: null }; this.cells = []; this.domain = domain; this.no_data = true; @@ -40,9 +38,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM this.fields.__count = {type: 'integer', string:'Quantity'}; this.measures = [{field:'__count', type: this.fields.type, string:this.fields.string}]; this.active = false; + this.rows = { groupby: this.create_field_values(options.row_groupby || []), headers: null }; + this.cols = { groupby: this.create_field_values(options.col_groupby || []), headers: null }; if (options.measures) { this.set_measures(options.measures); } - if (options.col_groupby) { this.set_col_groupby(options.col_groupby); } - if (options.row_groupby) { this.set_row_groupby(options.row_groupby); } }, // ---------------------------------------------------------------------- @@ -53,11 +51,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM this.update_data(); }, - set_domain: function (domain) { - this.domain = domain; - if (this.active) { this.update_data(); } - }, - set_measures: function (measures) { var self = this; if (!_.isEqual(measures, this.measures)) { @@ -93,42 +86,37 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM if (this.active) { this.update_data(); } }, - set_col_groupby: function (groupbys) { - var self = this; - if (!_.isEqual(groupbys, this.cols.groupby)) { - this.cols.groupby = []; - _.each(groupbys, function (g) { self._add_groupby(self.cols.groupby, g); }); - this.cols.headers = null; - if (this.active) { - this.trigger('groupby_changed'); - this.update_data(); - } - } - }, + set: function (domain, row_groupby, col_groupby) { + var row_gbs = this.create_field_values(row_groupby), + col_gbs = this.create_field_values(col_groupby), + dom_changed = !_.isEqual(this.domain, domain), + gb_changed = !(_.isEqual(row_gbs, this.rows.groupby) && + _.isEqual(col_gbs, this.cols.groupby)); - set_row_groupby: function (groupbys) { - var self = this; - if (!_.isEqual(groupbys, this.rows.groupby)) { - this.rows.groupby = []; - _.each(groupbys, function (g) { self._add_groupby(self.rows.groupby, g); }); - this.rows.headers = null; - if (this.active) { - this.trigger('groupby_changed'); - this.update_data(); - } - } - }, + if (dom_changed) { + this.domain = domain; + } + if (gb_changed) { + this.cols.groupby = col_gbs; + this.rows.groupby = row_gbs; + if (this.active) { this.trigger('groupby_changed'); } + } + if (this.active && (gb_changed || dom_changed)) { + this.update_data(); + } + }, + + create_field_value: function (f) { + return (f.field && f.string && f.type) ? f : {field: f, string: this.fields[f].string, type: this.fields[f].type}; + }, + + create_field_values: function (field_ids) { + var self = this; + return _.map(field_ids, function (f) { return self.create_field_value(f); }); + }, _add_groupby: function(groupby_list, groupby) { - if (groupby.field && groupby.string && groupby.type) { - groupby_list.push(groupby); - } else { - groupby_list.push({ - field:groupby, - string: this.fields[groupby].string, - type: this.fields[groupby].type - }); - } + groupby_list.push(this.create_field_value(groupby)); }, // ---------------------------------------------------------------------- @@ -413,7 +401,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM group.attributes.value = 'undefined'; } else if (value instanceof Array) { group.attributes.value = value[1]; - } + } group.path = value ? (current_path || []).concat(group.attributes.value) : []; group.attributes.aggregates.__count = group.attributes.length; @@ -508,7 +496,6 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM }, }); - })(); -- cgit v1.2.3 From bb1069ace8509959d9c1b41c2fb95f85da2d9934 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 10 Jan 2014 16:15:24 +0100 Subject: [REF] removes some code duplication when creating new headers in pivot class (addon web_graph) bzr revid: ged@openerp.com-20140110151524-i2usd1nyrfpgkody --- addons/web_graph/static/src/js/pivot.js | 38 ++++++++++++++------------------- 1 file changed, 16 insertions(+), 22 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 10a6b3f9052..69630d360a1 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -250,7 +250,11 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM return this.get_groups(groupby, fields, header.domain) .then(function (groups) { _.each(groups.reverse(), function (group) { - var child_id = self.make_header(group, header); + var child = self.make_header(group, header); + child.expanded = false; + header.children.splice(0,0, child); + header.root.headers.splice(header.root.headers.indexOf(header) + 1, 0, child); + // return new_header.id; // make cells _.each(self.get_ancestors_and_self(group), function (data) { var values = _.map(self.measures, function (m) { @@ -265,7 +269,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM } }); if (other) { - self.add_cell(child_id, other.id, values); + self.add_cell(child.id, other.id, values); } }); }); @@ -275,19 +279,15 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM }, make_header: function (group, parent) { - var title = group.attributes.value, - new_header = { - id: _.uniqueId(), - path: parent.path.concat(title), - title: title, - expanded: false, - children: [], - domain: group.model._domain, - root: parent.root, - }; - parent.children.splice(0,0, new_header); - parent.root.headers.splice(parent.root.headers.indexOf(parent) + 1, 0, new_header); - return new_header.id; + var title = parent ? group.attributes.value : ''; + return { + id: _.uniqueId(), + path: parent ? parent.path.concat(title) : [], + title: title, + children: [], + domain: parent ? group.model._domain : this.domain, + root: parent ? parent.root : undefined, + }; }, swap_axis: function () { @@ -460,13 +460,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM make_headers: function (data, depth, parent) { var self = this, - main = { - id: _.uniqueId(), - path: parent ? parent.path.concat(data.attributes.value) : [], - children: [], - title: parent ? data.attributes.value : '', - domain: parent ? data.model._domain : this.domain, - }; + main = this.make_header(data, parent); if (main.path.length < depth) { main.children = _.map(data.children || data, function (data_pt) { -- cgit v1.2.3 From 58598420fc0af5a7c8fdc6fd28b1c9ec08dae3ca Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 13 Jan 2014 10:48:58 +0100 Subject: [FIX] changes xml definition of the dropdown menu in graph view so that it nows corractly selects the chart mode (addon web_graph) bzr revid: ged@openerp.com-20140113094858-ykasko5a1i0gpyj3 --- addons/web_graph/static/src/xml/web_graph.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 29e48b1b782..0387d014d0c 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -11,9 +11,9 @@
  • Row Heatmap
  • Col Heatmap
  • -
  • Bar chart
  • -
  • Line Chart
  • -
  • Pie chart
  • +
  • Bar chart
  • +
  • Line Chart
  • +
  • Pie chart
  • -- cgit v1.2.3 From e2bb629c3c2528c26b216ff8fe21b4c4fb7634e0 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 13 Jan 2014 14:38:00 +0100 Subject: [IMP] adds support for various intervals when grouping by date in graph view (addon web_graph) bzr revid: ged@openerp.com-20140113133800-3n1hi5ajpioktr3d --- addons/web_graph/static/src/js/graph.js | 12 ++++++-- addons/web_graph/static/src/js/pivot.js | 35 +++++++++++++++++++++-- addons/web_graph/static/src/xml/web_graph.xml | 40 +++++++++++++++++++++++---- 3 files changed, 76 insertions(+), 11 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index d92d09f3a8c..abd1d41d629 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -369,7 +369,7 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix return; } var fields = _.map(this.important_fields, function (field) { - return {id: field, value: self.fields[field].string}; + return {id: field, value: self.fields[field].string, type:self.fields[field].type}; }); this.dropdown = $(QWeb.render('field_selection', {fields:fields, header_id:id})); $(event.target).after(this.dropdown); @@ -383,9 +383,15 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix field_selection: function (event) { var id = event.target.attributes['data-id'].nodeValue, - field_id = event.target.attributes['data-field-id'].nodeValue; + field_id = event.target.attributes['data-field-id'].nodeValue, + interval; event.preventDefault(); - this.pivot.expand(id, field_id); + if (this.fields[field_id].type === 'date' || this.fields[field_id].type === 'datetime') { + interval = event.target.attributes['data-interval'].nodeValue; + this.pivot.expand(id, {field: field_id, interval: interval}); + } else { + this.pivot.expand(id, field_id); + } }, /****************************************************************************** diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 69630d360a1..62d6e35b77c 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -107,6 +107,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM }, create_field_value: function (f) { + if (f.field && f.interval) { + return {field:f.field, string: this.fields[f.field].string, type:this.fields[f.field].type, interval: f.interval}; + } return (f.field && f.string && f.type) ? f : {field: f, string: this.fields[f].string, type: this.fields[f].type}; }, @@ -376,11 +379,37 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM _query_db: function (groupby, fields, domain, path) { var self = this, - field_ids = _.without(_.pluck(fields, 'field'), '__count'); - // To do : add code to check if groupby is date/datetime - // and in that case, add the correct code to the context + field_ids = _.without(_.pluck(fields, 'field'), '__count'), + context = {}; + + if (groupby.interval) { + context.datetime_format = {}; + var display_format; + switch (groupby.interval) { + case 'day': + display_format = 'dd MMMM YYYY'; + break; + case 'week': + display_format = 'w YYYY'; + break; + case 'month': + display_format = 'MMMM YYYY'; + break; + case 'quarter': + display_format = 'QQQ YYYY'; + break; + case 'year': + display_format = 'YYYY'; + break; + } + context.datetime_format[groupby.field] = { + interval: groupby.interval, + display_format: display_format + }; + } return this.model.query(field_ids) .filter(domain) + .context(context) .group_by(groupby.field) .then(function (results) { var groups = _.filter(results, function (group) { diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 0387d014d0c..27d7ec9af47 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -47,11 +47,41 @@
    -- cgit v1.2.3 From 4d550e963ea07da045bcb8f68ec4fad5fc7b591d Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 13 Jan 2014 16:23:16 +0100 Subject: [FIX] fixes some issues with chart drawing in graph view (addon web_graph) bzr revid: ged@openerp.com-20140113152316-4i3endkgu10jmxgc --- addons/web_graph/static/src/js/graph.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index abd1d41d629..f39f0574e9b 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -184,6 +184,7 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix this.mode = options.mode || 'pivot'; this.title = options.title || 'Graph'; this.visible_ui = options.visible_ui || true; + this.bar_ui = options.bar_ui || 'group'; this.pivot_options = options; }, @@ -325,13 +326,13 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix switch (event.target.attributes['data-choice'].nodeValue) { case 'bar_grouped': this.bar_ui = 'group'; - if (this.mode === 'bar_chart') { + if (this.mode === 'bar') { this.display_data(); } break; case 'bar_stacked': this.bar_ui = 'stack'; - if (this.mode === 'bar_chart') { + if (this.mode === 'bar') { this.display_data(); } break; @@ -609,7 +610,7 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix var values = _.map(self.pivot.get_rows_with_depth(1), function (header) { return { x: header.title || 'Undefined', - y: self.pivot.get_values(header.id, colhdr.id, 0)[0] + y: self.pivot.get_values(header.id, colhdr.id)[0] || 0 }; }); return {key: colhdr.title || 'Undefined', values: values}; -- cgit v1.2.3 From de85a1cefb2d62aae5a4a29295dcf36b6c545ad6 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 14 Jan 2014 10:27:24 +0100 Subject: [REF] adds comments and reorganize the functions in PivotTable class (addon web_graph) bzr revid: ged@openerp.com-20140114092724-z534vyceksc4dnr2 --- addons/web_graph/static/src/js/graph.js | 4 +- addons/web_graph/static/src/js/pivot.js | 159 +++++++++++++++++--------------- 2 files changed, 88 insertions(+), 75 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index f39f0574e9b..0259b4bcf73 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -340,9 +340,7 @@ instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMix this.pivot.swap_axis(); break; case 'expand_all': - this.pivot.rows.headers = null; - this.pivot.cols.headers = null; - this.pivot.update_data(); + this.pivot.expand_all(); break; case 'update_values': this.pivot.update_data(); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js index 62d6e35b77c..b78e8323645 100644 --- a/addons/web_graph/static/src/js/pivot.js +++ b/addons/web_graph/static/src/js/pivot.js @@ -4,28 +4,9 @@ (function () { 'use strict'; -// Pivot Table -// -// Here is a short description of the way the data is organized: -// Main fields: -// cells = [cell] -// cell = {x: _, y: _, values: [_]} -// measures = [measure] -// measure = {field: _, string: _, type: _} -// rows, cols = {groupby: [groupby], headers: [header]} -// groupby = {field: _, string: _, type: _, interval: _} (interval only if type = date/datetime) -// header = { -// id: _, -// path: _, -// title: _, -// expanded: _, -// children: _, -// domain: _, -// root: _, -// } -// // Pivot Table emits the events 'groupby_changed' and 'redraw_required' when necessary. -// PivotTable require a 'update_data' after init to be ready +// PivotTable is initialized by default 'inactive', and require a call to activate() +// after init to load initial data and start triggering events. openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherMixin, { init: function (model, domain, fields, options) { @@ -46,6 +27,12 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM // ---------------------------------------------------------------------- // Configuration methods // ---------------------------------------------------------------------- + // this.measures: list of measure [measure], measure = {field: _, string: _, type: _} + // this.rows.groupby, this.cols.groupby : list of groupbys used for describing rows (...), + // a groupby is also {field:_, string:_, type:_} but it also has a interval + // attribute if its type is date/datetime. + // this.active: If PivotTable is active then it triggers events and updates + // its values when necessary activate: function() { this.active = true; this.update_data(); @@ -108,9 +95,14 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM create_field_value: function (f) { if (f.field && f.interval) { - return {field:f.field, string: this.fields[f.field].string, type:this.fields[f.field].type, interval: f.interval}; + return { field:f.field, + string: this.fields[f.field].string, + type:this.fields[f.field].type, + interval: f.interval }; } - return (f.field && f.string && f.type) ? f : {field: f, string: this.fields[f].string, type: this.fields[f].type}; + return (f.field && f.string && f.type) ? f : { field: f, + string: this.fields[f].string, + type: this.fields[f].type }; }, create_field_values: function (field_ids) { @@ -125,17 +117,18 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM // ---------------------------------------------------------------------- // Cells manipulation methods // ---------------------------------------------------------------------- + // cells are objects {x:_, y:_, values:_} where x < y and values is an array + // of values (one for each measure). The condition x < y might look + // unnecessary, but it makes the rest of the code simpler: headers + // don't krow if they are rows or cols, they just know their id, so + // it is useful that a call get_values(id1, id2) is the same as get_values(id2, id1) add_cell : function (id1, id2, values) { - var x = Math.min(id1, id2), - y = Math.max(id1, id2); - this.cells.push({x: x, y: y, values: values}); + this.cells.push({x: Math.min(id1, id2), y: Math.max(id1, id2), values: values}); }, get_values: function (id1, id2, default_values) { - var x = Math.min(id1, id2), - y = Math.max(id1, id2), - cell = _.find(this.cells, function (c) { - return ((c.x == x) && (c.y == y)); + var cell = _.find(this.cells, function (c) { + return ((c.x == Math.min(id1, id2)) && (c.y == Math.max(id1, id2))); }); return (cell !== undefined) ? cell.values : (default_values || new Array(this.measures.length)); }, @@ -143,6 +136,17 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM // ---------------------------------------------------------------------- // Headers/Rows/Cols manipulation methods // ---------------------------------------------------------------------- + // this.rows.headers, this.cols.headers = [header] describe the tree structure + // of rows/cols. Headers are objects + // { + // id:_, (unique id obviously) + // path: [...], (array of all parents title, with its own title at the end) + // title:_, (name of the row/col) + // children:[_], (subrows or sub cols of this row/col) + // domain:_, (domain of data in this row/col) + // root:_ (ref to this.rows or this.cols corresponding to the header) + // expanded:_ (boolean, true if it has been expanded) + // } is_row: function (id) { return !!_.find(this.rows.headers, function (header) { return header.id === id; @@ -216,7 +220,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM main_col: function () { return this.cols.headers[0]; }, // ---------------------------------------------------------------------- - // Table manipulation methods + // Table manipulation methods : fold/expand/swap // ---------------------------------------------------------------------- fold: function (header) { var ancestors = this.get_ancestors(header), @@ -253,17 +257,16 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM return this.get_groups(groupby, fields, header.domain) .then(function (groups) { _.each(groups.reverse(), function (group) { + // make header var child = self.make_header(group, header); child.expanded = false; header.children.splice(0,0, child); header.root.headers.splice(header.root.headers.indexOf(header) + 1, 0, child); - // return new_header.id; // make cells _.each(self.get_ancestors_and_self(group), function (data) { var values = _.map(self.measures, function (m) { return data.attributes.aggregates[m.field]; }); - var other = _.find(otherRoot.headers, function (h) { if (header.root === self.cols) { return _.isEqual(data.path.slice(1), h.path); @@ -302,8 +305,12 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM }, // ---------------------------------------------------------------------- - // Data loading methods + // Data updating methods // ---------------------------------------------------------------------- + // Load the data from the db, using the method this.load_data + // update_data will try to preserve the expand/not expanded status of each + // column/row. If you want to expand all, then set this.cols.headers/this.rows.headers + // to null before calling update_data. update_data: function () { var self = this; @@ -354,7 +361,48 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM root.headers = updated_headers; }, - // options: fields: _, path_prefix: [] + expand_all: function () { + this.rows.headers = null; + this.cols.headers = null; + this.update_data(); + }, + + // ---------------------------------------------------------------------- + // Data loading methods + // ---------------------------------------------------------------------- + + // To obtain all the values required to draw the full table, we have to do + // at least 2 + min(row.groupby.length, col.groupby.length) + // calls to readgroup. To simplify the code, we will always do + // 2 + row.groupby.length calls. For example, if row.groupby = [r1, r2, r3] + // and col.groupby = [c1, c2], then we will make the call with the following + // groupbys: [r1,r2,r3], [c1,r1,r2,r3], [c1,c2,r1,r2,r3], []. + load_data: function () { + var self = this, + cols = this.cols.groupby, + rows = this.rows.groupby, + visible_fields = rows.concat(cols, self.measures); + + var groupbys = _.map(_.range(cols.length + 1), function (i) { + return cols.slice(0, i).concat(rows); + }); + groupbys.push([]); + + var def_array = _.map(groupbys, function (groupby) { + return self.get_groups(groupby, visible_fields, self.domain); + }); + + return $.when.apply(null, def_array).then(function () { + var data = Array.prototype.slice.call(arguments), + row_data = data[0], + col_data = (cols.length !== 0) ? data[data.length - 2] : [], + total = data[data.length - 1][0]; + + return (total === undefined) ? undefined + : self.format_data(total, col_data, row_data, data); + }); + }, + get_groups: function (groupbys, fields, domain, path) { path = path || []; var self = this, @@ -419,6 +467,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM }); }, + // add the path to the group and sanitize the value... format_group: function (group, current_path) { var value = group.attributes.value; @@ -438,53 +487,19 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM return group; }, - // To obtain all the values required to draw the full table, we have to do - // at least 2 + min(row.groupby.length, col.groupby.length) - // calls to readgroup. To simplify the code, we will always do - // 2 + row.groupby.length calls. For example, if row.groupby = [r1, r2, r3] - // and col.groupby = [c1, c2], then we will make the call with the following - // groupbys: [r1,r2,r3], [c1,r1,r2,r3], [c1,c2,r1,r2,r3], []. - load_data: function () { - var self = this, - cols = this.cols.groupby, - rows = this.rows.groupby, - visible_fields = rows.concat(cols, self.measures); - - var groupbys = _.map(_.range(cols.length + 1), function (i) { - return cols.slice(0, i).concat(rows); - }); - groupbys.push([]); - - var def_array = _.map(groupbys, function (groupby) { - return self.get_groups(groupby, visible_fields, self.domain); - }); - - return $.when.apply(null, def_array).then(function () { - var data = Array.prototype.slice.call(arguments), - row_data = data[0], - col_data = (cols.length !== 0) ? data[data.length - 2] : [], - total = data[data.length - 1][0]; - - return (total === undefined) ? undefined - : self.format_data(total, col_data, row_data, data); - }); - }, - format_data: function (total, col_data, row_data, cell_data) { var self = this, dim_row = this.rows.groupby.length, dim_col = this.cols.groupby.length, col_headers = this.get_ancestors_and_self(this.make_headers(col_data, dim_col)), - row_headers = this.get_ancestors_and_self(this.make_headers(row_data, dim_row)), - cells = []; + row_headers = this.get_ancestors_and_self(this.make_headers(row_data, dim_row)); this.cells = []; _.each(cell_data, function (data, index) { self.make_cells(data, index, [], row_headers, col_headers); - }); // make it more functional? + }); // not pretty. make it more functional? - return {col_headers: col_headers, - row_headers: row_headers}; + return {col_headers: col_headers, row_headers: row_headers}; }, make_headers: function (data, depth, parent) { -- cgit v1.2.3 From 11de0f36ed923f0222d8e1ecc603b53366eabf75 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 14 Jan 2014 13:51:42 +0100 Subject: [REF] separates graph view and graph widget into two files, and renames pivot into pivot_table.js (addon web_graph) bzr revid: ged@openerp.com-20140114125142-9qj3mvu0a1fp4sis --- addons/web_graph/static/src/js/graph.js | 737 ------------------------- addons/web_graph/static/src/js/graph_view.js | 177 ++++++ addons/web_graph/static/src/js/graph_widget.js | 567 +++++++++++++++++++ addons/web_graph/static/src/js/pivot.js | 539 ------------------ addons/web_graph/static/src/js/pivot_table.js | 539 ++++++++++++++++++ 5 files changed, 1283 insertions(+), 1276 deletions(-) delete mode 100644 addons/web_graph/static/src/js/graph.js create mode 100644 addons/web_graph/static/src/js/graph_view.js create mode 100644 addons/web_graph/static/src/js/graph_widget.js delete mode 100644 addons/web_graph/static/src/js/pivot.js create mode 100644 addons/web_graph/static/src/js/pivot_table.js (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js deleted file mode 100644 index 0259b4bcf73..00000000000 --- a/addons/web_graph/static/src/js/graph.js +++ /dev/null @@ -1,737 +0,0 @@ -/*--------------------------------------------------------- - * OpenERP web_graph - *---------------------------------------------------------*/ - -/* jshint undef: false */ - -openerp.web_graph = function (instance) { -'use strict'; - -var _lt = instance.web._lt; -var _t = instance.web._t; -var QWeb = instance.web.qweb; - -instance.web.views.add('graph', 'instance.web_graph.GraphView'); - -instance.web_graph.GraphView = instance.web.View.extend({ - display_name: _lt('Graph'), - view_type: 'graph', - - init: function(parent, dataset, view_id, options) { - this._super(parent, dataset, view_id, options); - this.dataset = dataset; - this.model = new instance.web.Model(dataset.model, {group_by_no_leaf: true}); - this.search_view = parent.searchview; - this.search_view_groupby = []; - this.groupby_mode = 'default'; // 'default' or 'manual' - this.default_row_groupby = []; - this.default_col_groupby = []; - this.search_field = { - get_context: this.proxy('get_context'), - get_domain: function () {}, - get_groupby: function () { }, - }; - }, - - view_loading: function (fields_view_get) { - var self = this, - arch = fields_view_get.arch; - - this.widget_config = { - title: arch.attrs.string, - stacked : (arch.attrs.stacked === 'True'), - mode: (arch.attrs.type) ? arch.attrs.type : 'bar', - measures: [], - }; - - _.each(arch.children, function (field) { - if (_.has(field.attrs, 'type')) { - switch (field.attrs.type) { - case 'row': - self.default_row_groupby.push(field.attrs.name); - break; - case 'col': - self.default_col_groupby.push(field.attrs.name); - break; - case 'measure': - self.widget_config.measures.push(field.attrs.name); - break; - } - } else { // old style, kept for backward compatibility - if ('operator' in field.attrs) { - self.widget_config.measures.push(field.attrs.name); - } else { - self.default_row_groupby.push(field.attrs.name); - } - } - }); - if (self.widget_config.measures.length === 0) { - self.widget_config.measures.push('__count'); - } - this.widget_config.row_groupby = self.default_row_groupby; - this.widget_config.col_groupby = self.default_col_groupby; - }, - - get_context: function (facet) { - var col_group_by = _.map(facet.values.models, function (model) { - return model.attributes.value.attrs.context.col_group_by; - }); - return {col_group_by : col_group_by}; - }, - - do_search: function (domain, context, group_by) { - // var col_groupby = context.col_group_by || [], - // options = {domain:domain}; - - if (!this.graph_widget) { - this.graph_widget = new openerp.web_graph.Graph(this, this.model, domain, this.widget_config); - this.graph_widget.appendTo(this.$el); - this.graph_widget.on('groupby_changed', this, this.proxy('register_groupby')); - this.ViewManager.on('switch_mode', this, function (e) { if (e === 'graph') this.graph_widget.reload(); }); - } - // this.search_view_groupby = group_by; - - // if (group_by.length && this.groupby_mode !== 'manual') { - // if (_.isEqual(col_groupby, [])) { - // col_groupby = this.default_col_groupby; - // } - // } - // if (group_by.length || col_groupby.length) { - // this.groupby_mode = 'manual'; - // } - // if (!this.graph_widget.enabled) { - // options.update = false; - // options.silent = true; - // } - - // if (this.groupby_mode === 'manual') { - // options.row_groupby = group_by; - // options.col_groupby = col_groupby; - // } else { - // options.row_groupby = _.toArray(this.default_row_groupby); - // options.col_groupby = _.toArray(this.default_col_groupby); - // } - // this.graph_widget.set(domain, options.row_groupby, options.col_groupby); - // this.graph_widget.set_domain(domain); - // this.graph_widget.set_col_groupby(options.col_groupby); - // this.graph_widget.set_row_groupby(options.row_groupby); - - }, - - do_show: function () { - this.do_push_state({}); - return this._super(); - }, - - register_groupby: function() { - // var self = this, - // query = this.search_view.query; - - // this.groupby_mode = 'manual'; - // if (_.isEqual(this.search_view_groupby, this.graph_widget.pivot.rows.groupby) || - // (!_.has(this.search_view, '_s_groupby'))) { - // return; - // } - // var rows = _.map(this.graph_widget.pivot.rows.groupby, function (group) { - // return make_facet('GroupBy', group); - // }); - // var cols = _.map(this.graph_widget.pivot.cols.groupby, function (group) { - // return make_facet('ColGroupBy', group); - // }); - - // query.reset(rows.concat(cols)); - - // function make_facet (category, fields) { - // var values, - // icon, - // backbone_field, - // cat_name; - // if (!(fields instanceof Array)) { fields = [fields]; } - // if (category === 'GroupBy') { - // cat_name = 'group_by'; - // icon = 'w'; - // backbone_field = self.search_view._s_groupby; - // } else { - // cat_name = 'col_group_by'; - // icon = 'f'; - // backbone_field = self.search_field; - // } - // values = _.map(fields, function (field) { - // var context = {}; - // context[cat_name] = field; - // return {label: self.graph_widget.fields[field].string, value: {attrs:{domain: [], context: context}}}; - // }); - // return {category:category, values: values, icon:icon, field: backbone_field}; - // } - }, -}); - -instance.web_graph.Graph = instance.web.Widget.extend(openerp.EventDispatcherMixin, { - template: 'GraphWidget', - - events: { - 'click .graph_mode_selection li' : 'mode_selection', - 'click .graph_measure_selection li' : 'measure_selection', - 'click .graph_options_selection li' : 'option_selection', - 'click .web_graph_click' : 'header_cell_clicked', - 'click a.field-selection' : 'field_selection', - }, - - init: function(parent, model, domain, options) { - this._super(parent); - this.model = model; - this.domain = domain; - this.mode = options.mode || 'pivot'; - this.title = options.title || 'Graph'; - this.visible_ui = options.visible_ui || true; - this.bar_ui = options.bar_ui || 'group'; - this.pivot_options = options; - }, - - start: function() { - var self = this; - this.table = $('
    '); - this.$('.graph_main_content').append(this.table); - var def1 = this.get_search_fields().then(function (f) { - self.important_fields = f; - }); - - var def2 = this.model.call('fields_get', []).then(function (f) { - self.fields = f; - self.measure_list = self.get_measures(); - self.add_measures_to_options(); - }); - - return $.when(def1, def2).then(function () { - self.pivot = new openerp.web_graph.PivotTable(self.model, self.domain, self.fields, self.pivot_options); - self.pivot.on('redraw_required', self, self.proxy('display_data')); - self.pivot.on('groupby_changed', self, function () { self.trigger('groupby_changed'); }); - instance.web.bus.on('click', self, function () { - if (self.dropdown) { - self.dropdown.remove(); - self.dropdown = null; - } - }); - self.pivot.activate(); - }); - }, - - get_search_fields: function () { - var self = this, - options = {model:this.model, view_type: 'search'}, - result = []; - - return instance.web.fields_view_get(options).then(function (search_view) { - var groups = _.select(search_view.arch.children, function (c) { - return (c.tag === 'group') && (c.attrs.string != 'Display'); - }); - _.each(groups, function(g) { - _.each(g.children, function (g) { - if (g.attrs.context) { - var field_id = py.eval(g.attrs.context).group_by; - if (field_id) { - if (field_id instanceof Array) { - result.concat(field_id); - } else { - result.push(field_id); - } - } - } - }); - }); - return result; - }); - }, - - get_measures: function(fields) { - var measures = []; - _.each(this.fields, function (f, id) { - if (((f.type === 'integer') || (f.type === 'float')) && (id !== 'id')) { - measures.push({field:id, type: f.type, string: f.string}); - } - }); - return measures; - }, - - - set: function (domain, row_groupby, col_groupby) { - if (this.pivot) { - this.pivot.set(domain, row_groupby, col_groupby); - } else { - this.pivot_options.domain = domain; - this.pivot_options.row_groupby = row_groupby; - this.pivot_options.col_groupby = col_groupby; - } - }, - - add_measures_to_options: function() { - var measure_selection = this.$('.graph_measure_selection'); - _.each(this.measure_list, function (measure) { - var choice = $('').attr('data-choice', measure.field) - .attr('href', '#') - .append(measure.string); - measure_selection.append($('
  • ').append(choice)); - }); - }, - - set_mode: function (mode) { - this.mode = mode; - this.display_data(); - }, - - reload: function () { - this.pivot.update_data(); - }, - - display_data: function () { - this.$('.graph_main_content svg').remove(); - this.$('.graph_main_content div').remove(); - this.table.empty(); - - if (this.visible_ui) { - this.$('.graph_header').css('display', 'block'); - } else { - this.$('.graph_header').css('display', 'none'); - } - if (this.pivot.no_data) { - this.$('.graph_main_content').append($(QWeb.render('graph_no_data'))); - } else { - var table_modes = ['pivot', 'heatmap', 'row_heatmap', 'col_heatmap']; - if (_.contains(table_modes, this.mode)) { - this.draw_table(); - } else { - this.$('.graph_main_content').append($('
    ')); - this.svg = this.$('.graph_main_content svg')[0]; - this.width = this.$el.width(); - this.height = Math.min(Math.max(document.documentElement.clientHeight - 116 - 60, 250), Math.round(0.8*this.$el.width())); - this[this.mode](); - } - } - }, - - mode_selection: function (event) { - event.preventDefault(); - var mode = event.target.attributes['data-mode'].nodeValue; - this.set_mode(mode); - }, - - measure_selection: function (event) { - event.preventDefault(); - var measure = event.target.attributes['data-choice'].nodeValue; - this.pivot.toggle_measure(measure); - }, - - option_selection: function (event) { - event.preventDefault(); - switch (event.target.attributes['data-choice'].nodeValue) { - case 'bar_grouped': - this.bar_ui = 'group'; - if (this.mode === 'bar') { - this.display_data(); - } - break; - case 'bar_stacked': - this.bar_ui = 'stack'; - if (this.mode === 'bar') { - this.display_data(); - } - break; - case 'swap_axis': - this.pivot.swap_axis(); - break; - case 'expand_all': - this.pivot.expand_all(); - break; - case 'update_values': - this.pivot.update_data(); - break; - case 'export_data': - // Export code... To do... - break; - } - }, - - header_cell_clicked: function (event) { - event.preventDefault(); - event.stopPropagation(); - var id = event.target.attributes['data-id'].nodeValue, - header = this.pivot.get_header(id), - self = this; - - if (header.expanded) { - this.pivot.fold(header); - } else { - if (header.path.length < header.root.groupby.length) { - this.pivot.expand(id); - } else { - if (!this.important_fields.length) { - return; - } - var fields = _.map(this.important_fields, function (field) { - return {id: field, value: self.fields[field].string, type:self.fields[field].type}; - }); - this.dropdown = $(QWeb.render('field_selection', {fields:fields, header_id:id})); - $(event.target).after(this.dropdown); - this.dropdown.css({position:'absolute', - left:event.pageX, - top:event.pageY}); - this.$('.field-selection').next('.dropdown-menu').toggle(); - } - } - }, - - field_selection: function (event) { - var id = event.target.attributes['data-id'].nodeValue, - field_id = event.target.attributes['data-field-id'].nodeValue, - interval; - event.preventDefault(); - if (this.fields[field_id].type === 'date' || this.fields[field_id].type === 'datetime') { - interval = event.target.attributes['data-interval'].nodeValue; - this.pivot.expand(id, {field: field_id, interval: interval}); - } else { - this.pivot.expand(id, field_id); - } - }, - -/****************************************************************************** - * Drawing pivot table methods... - ******************************************************************************/ - draw_table: function () { - this.pivot.main_row().title = 'Total'; - if (this.pivot.measures.length == 1) { - this.pivot.main_col().title = this.pivot.measures[0].string; - } else { - this.pivot.main_col().title = this.title; - } - this.draw_top_headers(); - _.each(this.pivot.rows.headers, this.proxy('draw_row')); - }, - - make_border_cell: function (colspan, rowspan, headercell) { - var tag = (headercell) ? $('') : $(''); - return tag.addClass('graph_border') - .attr('colspan', (colspan) ? colspan : 1) - .attr('rowspan', (rowspan) ? rowspan : 1); - }, - - make_header_title: function (header) { - return $(' ') - .addClass('web_graph_click') - .attr('href', '#') - .addClass((header.expanded) ? 'fa fa-minus-square' : 'fa fa-plus-square') - .append((header.title !== undefined) ? header.title : 'Undefined'); - }, - - draw_top_headers: function () { - var self = this, - thead = $(''), - pivot = this.pivot, - height = _.max(_.map(pivot.cols.headers, function(g) {return g.path.length;})), - header_cells = [[this.make_border_cell(1, height, true)]]; - - function set_dim (cols) { - _.each(cols.children, set_dim); - if (cols.children.length === 0) { - cols.height = height - cols.path.length + 1; - cols.width = 1; - } else { - cols.height = 1; - cols.width = _.reduce(cols.children, function (sum,c) { return sum + c.width;}, 0); - } - } - - function make_col_header (col) { - var cell = self.make_border_cell(col.width*pivot.measures.length, col.height, true); - return cell.append(self.make_header_title(col).attr('data-id', col.id)); - } - - function make_cells (queue, level) { - var col = queue[0]; - queue = _.rest(queue).concat(col.children); - if (col.path.length == level) { - _.last(header_cells).push(make_col_header(col)); - } else { - level +=1; - header_cells.push([make_col_header(col)]); - } - if (queue.length !== 0) { - make_cells(queue, level); - } - } - - set_dim(pivot.main_col()); // add width and height info to columns headers - if (pivot.main_col().children.length === 0) { - make_cells(pivot.cols.headers, 0); - } else { - make_cells(pivot.main_col().children, 1); - if (pivot.get_cols_leaves().length > 1) { - header_cells[0].push(self.make_border_cell(pivot.measures.length, height, true).append('Total').css('font-weight', 'bold')); - } - } - - _.each(header_cells, function (cells) { - thead.append($('').append(cells)); - }); - - if (pivot.measures.length >= 2) { - thead.append(self.make_measure_row()); - } - - self.table.append(thead); - }, - - make_measure_row: function() { - var self = this, - measures = this.pivot.measures, - cols = this.pivot.cols.headers, - measure_cells, - measure_row = $(''); - - measure_row.append($('')); - - _.each(cols, function (col) { - if (!col.children.length) { - for (var i = 0; i < measures.length; i++) { - measure_cells = $('').addClass('measure_row'); - measure_cells.append(measures[i].string); - measure_row.append(measure_cells); - } - } - }); - - if (this.pivot.get_cols_leaves().length > 1) { - for (var i = 0; i < measures.length; i++) { - measure_cells = $('').addClass('measure_row'); - measure_cells.append(measures[i].string); - measure_row.append(measure_cells); - } - } - return measure_row; - }, - - draw_row: function (row) { - var self = this, - pivot = this.pivot, - measure_types = _.pluck(this.pivot.measures, 'type'), - html_row = $(''), - row_header = this.make_border_cell(1,1) - .append(this.make_header_title(row).attr('data-id', row.id)) - .addClass('graph_border'); - - for (var i = 0; i < row.path.length; i++) { - row_header.prepend($('', {class:'web_graph_indent'})); - } - - html_row.append(row_header); - - _.each(pivot.cols.headers, function (col) { - if (col.children.length === 0) { - var values = pivot.get_values(row.id, col.id); - for (var i = 0; i < values.length; i++) { - html_row.append(make_cell(values[i], measure_types[i], i, col)); - } - } - }); - - if (pivot.get_cols_leaves().length > 1) { - var total_vals = pivot.get_total(row); - for (var j = 0; j < total_vals.length; j++) { - var cell = make_cell(total_vals[j], measure_types[j], j, pivot.cols[0]).css('font-weight', 'bold'); - html_row.append(cell); - } - } - - this.table.append(html_row); - - function make_cell (value, measure_type, index, col) { - var color, - total, - cell = $(''); - if (value === undefined) { - return cell; - } - cell.append(instance.web.format_value(value, {type: measure_type})); - if (self.mode === 'heatmap') { - total = pivot.get_total()[index]; - color = Math.floor(90 + 165*(total - Math.abs(value))/total); - cell.css('background-color', $.Color(255, color, color)); - } - if (self.mode === 'row_heatmap') { - total = pivot.get_total(row)[index]; - color = Math.floor(90 + 165*(total - Math.abs(value))/total); - cell.css('background-color', $.Color(255, color, color)); - } - if (self.mode === 'col_heatmap') { - debugger; - total = pivot.get_total(col)[index]; - color = Math.floor(90 + 165*(total - Math.abs(value))/total); - cell.css('background-color', $.Color(255, color, color)); - } - return cell; - } - }, - -/****************************************************************************** - * Drawing charts methods... - ******************************************************************************/ - bar: function () { - var self = this, - dim_x = this.pivot.rows.groupby.length, - dim_y = this.pivot.cols.groupby.length, - data; - - // No groupby ************************************************************** - if ((dim_x === 0) && (dim_y === 0)) { - data = [{key: 'Total', values:[{ - x: 'Total', - y: this.pivot.get_total(), - }]}]; - // Only column groupbys **************************************************** - } else if ((dim_x === 0) && (dim_y >= 1)){ - data = _.map(this.pivot.get_columns_with_depth(1), function (header) { - return { - key: header.title, - values: [{x:header.root[0].title, y: self.pivot.get_total(header)[0]}] - }; - }); - // Just 1 row groupby ****************************************************** - } else if ((dim_x === 1) && (dim_y === 0)) { - data = _.map(this.pivot.main_row().children, function (pt) { - var value = self.pivot.get_total(pt), - title = (pt.title !== undefined) ? pt.title : 'Undefined'; - return {x: title, y: value}; - }); - data = [{key: self.pivot.measures[0].string, values:data}]; - // 1 row groupby and some col groupbys************************************** - } else if ((dim_x === 1) && (dim_y >= 1)) { - data = _.map(this.pivot.get_cols_with_depth(1), function (colhdr) { - var values = _.map(self.pivot.get_rows_with_depth(1), function (header) { - return { - x: header.title || 'Undefined', - y: self.pivot.get_values(header.id, colhdr.id)[0] || 0 - }; - }); - return {key: colhdr.title || 'Undefined', values: values}; - }); - // At least two row groupby************************************************* - } else { - var keys = _.uniq(_.map(this.pivot.get_rows_with_depth(2), function (hdr) { - return hdr.title || 'Undefined'; - })); - data = _.map(keys, function (key) { - var values = _.map(self.pivot.get_rows_with_depth(1), function (hdr) { - var subhdr = _.find(hdr.children, function (child) { - return ((child.title === key) || ((child.title === undefined) && (key === 'Undefined'))); - }); - return { - x: hdr.title || 'Undefined', - y: (subhdr) ? self.pivot.get_total(subhdr)[0] : 0 - }; - }); - return {key:key, values: values}; - }); - } - - nv.addGraph(function () { - var chart = nv.models.multiBarChart() - .width(self.width) - .height(self.height) - .reduceXTicks(false) - .stacked(self.bar_ui === 'stack') - .showControls(false); - - if (self.width / data[0].values.length < 80) { - chart.rotateLabels(-15); - chart.reduceXTicks(true); - chart.margin({bottom:40}); - } - - d3.select(self.svg) - .datum(data) - .attr('width', self.width) - .attr('height', self.height) - .call(chart); - - nv.utils.windowResize(chart.update); - return chart; - }); - - }, - - line: function () { - var self = this, - dim_x = this.pivot.rows.groupby.length, - dim_y = this.pivot.cols.groupby.length; - - var data = _.map(this.pivot.get_cols_leaves(), function (col) { - var values = _.map(self.pivot.get_rows_with_depth(dim_x), function (row) { - return {x: row.title, y: self.pivot.get_values(row.id,col.id, 0)}; - }); - var title = _.map(col.path, function (p) { - return p || 'Undefined'; - }).join('/'); - if (dim_y === 0) { - title = self.pivot.measures[0].string; - } - return {values: values, key: title}; - }); - - nv.addGraph(function () { - var chart = nv.models.lineChart() - .x(function (d,u) { return u; }) - .width(self.width) - .height(self.height) - .margin({top: 30, right: 20, bottom: 20, left: 60}); - - d3.select(self.svg) - .attr('width', self.width) - .attr('height', self.height) - .datum(data) - .call(chart); - - return chart; - }); - }, - - pie: function () { - var self = this, - dim_x = this.pivot.rows.groupby.length; - var data = _.map(this.pivot.get_rows_leaves(), function (row) { - var title = _.map(row.path, function (p) { - return p || 'Undefined'; - }).join('/'); - if (dim_x === 0) { - title = self.measure_label; - } - return {x: title, y: self.pivot.get_total(row)}; - }); - - nv.addGraph(function () { - var chart = nv.models.pieChart() - .color(d3.scale.category10().range()) - .width(self.width) - .height(self.height); - - d3.select(self.svg) - .datum(data) - .transition().duration(1200) - .attr('width', self.width) - .attr('height', self.height) - .call(chart); - - nv.utils.windowResize(chart.update); - return chart; - }); - }, - -}); - -}; - - - - - - - - diff --git a/addons/web_graph/static/src/js/graph_view.js b/addons/web_graph/static/src/js/graph_view.js new file mode 100644 index 00000000000..1b940c1703a --- /dev/null +++ b/addons/web_graph/static/src/js/graph_view.js @@ -0,0 +1,177 @@ +/*--------------------------------------------------------- + * OpenERP web_graph + *---------------------------------------------------------*/ + +/* jshint undef: false */ + +openerp.web_graph = function (instance) { +'use strict'; + +var _lt = instance.web._lt; +var _t = instance.web._t; + +instance.web.views.add('graph', 'instance.web_graph.GraphView'); + +instance.web_graph.GraphView = instance.web.View.extend({ + display_name: _lt('Graph'), + view_type: 'graph', + + init: function(parent, dataset, view_id, options) { + this._super(parent, dataset, view_id, options); + this.dataset = dataset; + this.model = new instance.web.Model(dataset.model, {group_by_no_leaf: true}); + this.search_view = parent.searchview; + this.search_view_groupby = []; + this.groupby_mode = 'default'; // 'default' or 'manual' + this.default_row_groupby = []; + this.default_col_groupby = []; + this.search_field = { + get_context: this.proxy('get_context'), + get_domain: function () {}, + get_groupby: function () { }, + }; + }, + + view_loading: function (fields_view_get) { + var self = this, + arch = fields_view_get.arch; + + this.widget_config = { + title: arch.attrs.string, + stacked : (arch.attrs.stacked === 'True'), + mode: (arch.attrs.type) ? arch.attrs.type : 'bar', + measures: [], + }; + + _.each(arch.children, function (field) { + if (_.has(field.attrs, 'type')) { + switch (field.attrs.type) { + case 'row': + self.default_row_groupby.push(field.attrs.name); + break; + case 'col': + self.default_col_groupby.push(field.attrs.name); + break; + case 'measure': + self.widget_config.measures.push(field.attrs.name); + break; + } + } else { // old style, kept for backward compatibility + if ('operator' in field.attrs) { + self.widget_config.measures.push(field.attrs.name); + } else { + self.default_row_groupby.push(field.attrs.name); + } + } + }); + if (self.widget_config.measures.length === 0) { + self.widget_config.measures.push('__count'); + } + this.widget_config.row_groupby = self.default_row_groupby; + this.widget_config.col_groupby = self.default_col_groupby; + }, + + get_context: function (facet) { + var col_group_by = _.map(facet.values.models, function (model) { + return model.attributes.value.attrs.context.col_group_by; + }); + return {col_group_by : col_group_by}; + }, + + do_search: function (domain, context, group_by) { + // var col_groupby = context.col_group_by || [], + // options = {domain:domain}; + + if (!this.graph_widget) { + this.graph_widget = new openerp.web_graph.Graph(this, this.model, domain, this.widget_config); + this.graph_widget.appendTo(this.$el); + this.graph_widget.on('groupby_changed', this, this.proxy('register_groupby')); + this.ViewManager.on('switch_mode', this, function (e) { if (e === 'graph') this.graph_widget.reload(); }); + } + // this.search_view_groupby = group_by; + + // if (group_by.length && this.groupby_mode !== 'manual') { + // if (_.isEqual(col_groupby, [])) { + // col_groupby = this.default_col_groupby; + // } + // } + // if (group_by.length || col_groupby.length) { + // this.groupby_mode = 'manual'; + // } + // if (!this.graph_widget.enabled) { + // options.update = false; + // options.silent = true; + // } + + // if (this.groupby_mode === 'manual') { + // options.row_groupby = group_by; + // options.col_groupby = col_groupby; + // } else { + // options.row_groupby = _.toArray(this.default_row_groupby); + // options.col_groupby = _.toArray(this.default_col_groupby); + // } + // this.graph_widget.set(domain, options.row_groupby, options.col_groupby); + // this.graph_widget.set_domain(domain); + // this.graph_widget.set_col_groupby(options.col_groupby); + // this.graph_widget.set_row_groupby(options.row_groupby); + + }, + + do_show: function () { + this.do_push_state({}); + return this._super(); + }, + + register_groupby: function() { + // var self = this, + // query = this.search_view.query; + + // this.groupby_mode = 'manual'; + // if (_.isEqual(this.search_view_groupby, this.graph_widget.pivot.rows.groupby) || + // (!_.has(this.search_view, '_s_groupby'))) { + // return; + // } + // var rows = _.map(this.graph_widget.pivot.rows.groupby, function (group) { + // return make_facet('GroupBy', group); + // }); + // var cols = _.map(this.graph_widget.pivot.cols.groupby, function (group) { + // return make_facet('ColGroupBy', group); + // }); + + // query.reset(rows.concat(cols)); + + // function make_facet (category, fields) { + // var values, + // icon, + // backbone_field, + // cat_name; + // if (!(fields instanceof Array)) { fields = [fields]; } + // if (category === 'GroupBy') { + // cat_name = 'group_by'; + // icon = 'w'; + // backbone_field = self.search_view._s_groupby; + // } else { + // cat_name = 'col_group_by'; + // icon = 'f'; + // backbone_field = self.search_field; + // } + // values = _.map(fields, function (field) { + // var context = {}; + // context[cat_name] = field; + // return {label: self.graph_widget.fields[field].string, value: {attrs:{domain: [], context: context}}}; + // }); + // return {category:category, values: values, icon:icon, field: backbone_field}; + // } + }, +}); + + +}; + + + + + + + + diff --git a/addons/web_graph/static/src/js/graph_widget.js b/addons/web_graph/static/src/js/graph_widget.js new file mode 100644 index 00000000000..33f3caabc07 --- /dev/null +++ b/addons/web_graph/static/src/js/graph_widget.js @@ -0,0 +1,567 @@ + +/* jshint undef: false */ + +(function () { +'use strict'; +var QWeb = openerp.web.qweb; + +openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin, { + template: 'GraphWidget', + + events: { + 'click .graph_mode_selection li' : 'mode_selection', + 'click .graph_measure_selection li' : 'measure_selection', + 'click .graph_options_selection li' : 'option_selection', + 'click .web_graph_click' : 'header_cell_clicked', + 'click a.field-selection' : 'field_selection', + }, + + init: function(parent, model, domain, options) { + this._super(parent); + this.model = model; + this.domain = domain; + this.mode = options.mode || 'pivot'; + this.title = options.title || 'Graph'; + this.visible_ui = options.visible_ui || true; + this.bar_ui = options.bar_ui || 'group'; + this.pivot_options = options; + }, + + start: function() { + var self = this; + this.table = $('
    '); + this.$('.graph_main_content').append(this.table); + var def1 = this.get_search_fields().then(function (f) { + self.important_fields = f; + }); + + var def2 = this.model.call('fields_get', []).then(function (f) { + self.fields = f; + self.measure_list = self.get_measures(); + self.add_measures_to_options(); + }); + + return $.when(def1, def2).then(function () { + self.pivot = new openerp.web_graph.PivotTable(self.model, self.domain, self.fields, self.pivot_options); + self.pivot.on('redraw_required', self, self.proxy('display_data')); + self.pivot.on('groupby_changed', self, function () { self.trigger('groupby_changed'); }); + openerp.web.bus.on('click', self, function () { + if (self.dropdown) { + self.dropdown.remove(); + self.dropdown = null; + } + }); + self.pivot.activate(); + }); + }, + + get_search_fields: function () { + var self = this, + options = {model:this.model, view_type: 'search'}, + result = []; + + return openerp.web.fields_view_get(options).then(function (search_view) { + var groups = _.select(search_view.arch.children, function (c) { + return (c.tag === 'group') && (c.attrs.string != 'Display'); + }); + _.each(groups, function(g) { + _.each(g.children, function (g) { + if (g.attrs.context) { + var field_id = py.eval(g.attrs.context).group_by; + if (field_id) { + if (field_id instanceof Array) { + result.concat(field_id); + } else { + result.push(field_id); + } + } + } + }); + }); + return result; + }); + }, + + get_measures: function(fields) { + var measures = []; + _.each(this.fields, function (f, id) { + if (((f.type === 'integer') || (f.type === 'float')) && (id !== 'id')) { + measures.push({field:id, type: f.type, string: f.string}); + } + }); + return measures; + }, + + + set: function (domain, row_groupby, col_groupby) { + if (this.pivot) { + this.pivot.set(domain, row_groupby, col_groupby); + } else { + this.pivot_options.domain = domain; + this.pivot_options.row_groupby = row_groupby; + this.pivot_options.col_groupby = col_groupby; + } + }, + + add_measures_to_options: function() { + var measure_selection = this.$('.graph_measure_selection'); + _.each(this.measure_list, function (measure) { + var choice = $('').attr('data-choice', measure.field) + .attr('href', '#') + .append(measure.string); + measure_selection.append($('
  • ').append(choice)); + }); + }, + + set_mode: function (mode) { + this.mode = mode; + this.display_data(); + }, + + reload: function () { + this.pivot.update_data(); + }, + + display_data: function () { + this.$('.graph_main_content svg').remove(); + this.$('.graph_main_content div').remove(); + this.table.empty(); + + if (this.visible_ui) { + this.$('.graph_header').css('display', 'block'); + } else { + this.$('.graph_header').css('display', 'none'); + } + if (this.pivot.no_data) { + this.$('.graph_main_content').append($(QWeb.render('graph_no_data'))); + } else { + var table_modes = ['pivot', 'heatmap', 'row_heatmap', 'col_heatmap']; + if (_.contains(table_modes, this.mode)) { + this.draw_table(); + } else { + this.$('.graph_main_content').append($('
    ')); + this.svg = this.$('.graph_main_content svg')[0]; + this.width = this.$el.width(); + this.height = Math.min(Math.max(document.documentElement.clientHeight - 116 - 60, 250), Math.round(0.8*this.$el.width())); + this[this.mode](); + } + } + }, + + mode_selection: function (event) { + event.preventDefault(); + var mode = event.target.attributes['data-mode'].nodeValue; + this.set_mode(mode); + }, + + measure_selection: function (event) { + event.preventDefault(); + var measure = event.target.attributes['data-choice'].nodeValue; + this.pivot.toggle_measure(measure); + }, + + option_selection: function (event) { + event.preventDefault(); + switch (event.target.attributes['data-choice'].nodeValue) { + case 'bar_grouped': + this.bar_ui = 'group'; + if (this.mode === 'bar') { + this.display_data(); + } + break; + case 'bar_stacked': + this.bar_ui = 'stack'; + if (this.mode === 'bar') { + this.display_data(); + } + break; + case 'swap_axis': + this.pivot.swap_axis(); + break; + case 'expand_all': + this.pivot.expand_all(); + break; + case 'update_values': + this.pivot.update_data(); + break; + case 'export_data': + // Export code... To do... + break; + } + }, + + header_cell_clicked: function (event) { + event.preventDefault(); + event.stopPropagation(); + var id = event.target.attributes['data-id'].nodeValue, + header = this.pivot.get_header(id), + self = this; + + if (header.expanded) { + this.pivot.fold(header); + } else { + if (header.path.length < header.root.groupby.length) { + this.pivot.expand(id); + } else { + if (!this.important_fields.length) { + return; + } + var fields = _.map(this.important_fields, function (field) { + return {id: field, value: self.fields[field].string, type:self.fields[field].type}; + }); + this.dropdown = $(QWeb.render('field_selection', {fields:fields, header_id:id})); + $(event.target).after(this.dropdown); + this.dropdown.css({position:'absolute', + left:event.pageX, + top:event.pageY}); + this.$('.field-selection').next('.dropdown-menu').toggle(); + } + } + }, + + field_selection: function (event) { + var id = event.target.attributes['data-id'].nodeValue, + field_id = event.target.attributes['data-field-id'].nodeValue, + interval; + event.preventDefault(); + if (this.fields[field_id].type === 'date' || this.fields[field_id].type === 'datetime') { + interval = event.target.attributes['data-interval'].nodeValue; + this.pivot.expand(id, {field: field_id, interval: interval}); + } else { + this.pivot.expand(id, field_id); + } + }, + +/****************************************************************************** + * Drawing pivot table methods... + ******************************************************************************/ + draw_table: function () { + this.pivot.main_row().title = 'Total'; + if (this.pivot.measures.length == 1) { + this.pivot.main_col().title = this.pivot.measures[0].string; + } else { + this.pivot.main_col().title = this.title; + } + this.draw_top_headers(); + _.each(this.pivot.rows.headers, this.proxy('draw_row')); + }, + + make_border_cell: function (colspan, rowspan, headercell) { + var tag = (headercell) ? $('') : $(''); + return tag.addClass('graph_border') + .attr('colspan', (colspan) ? colspan : 1) + .attr('rowspan', (rowspan) ? rowspan : 1); + }, + + make_header_title: function (header) { + return $(' ') + .addClass('web_graph_click') + .attr('href', '#') + .addClass((header.expanded) ? 'fa fa-minus-square' : 'fa fa-plus-square') + .append((header.title !== undefined) ? header.title : 'Undefined'); + }, + + draw_top_headers: function () { + var self = this, + thead = $(''), + pivot = this.pivot, + height = _.max(_.map(pivot.cols.headers, function(g) {return g.path.length;})), + header_cells = [[this.make_border_cell(1, height, true)]]; + + function set_dim (cols) { + _.each(cols.children, set_dim); + if (cols.children.length === 0) { + cols.height = height - cols.path.length + 1; + cols.width = 1; + } else { + cols.height = 1; + cols.width = _.reduce(cols.children, function (sum,c) { return sum + c.width;}, 0); + } + } + + function make_col_header (col) { + var cell = self.make_border_cell(col.width*pivot.measures.length, col.height, true); + return cell.append(self.make_header_title(col).attr('data-id', col.id)); + } + + function make_cells (queue, level) { + var col = queue[0]; + queue = _.rest(queue).concat(col.children); + if (col.path.length == level) { + _.last(header_cells).push(make_col_header(col)); + } else { + level +=1; + header_cells.push([make_col_header(col)]); + } + if (queue.length !== 0) { + make_cells(queue, level); + } + } + + set_dim(pivot.main_col()); // add width and height info to columns headers + if (pivot.main_col().children.length === 0) { + make_cells(pivot.cols.headers, 0); + } else { + make_cells(pivot.main_col().children, 1); + if (pivot.get_cols_leaves().length > 1) { + header_cells[0].push(self.make_border_cell(pivot.measures.length, height, true).append('Total').css('font-weight', 'bold')); + } + } + + _.each(header_cells, function (cells) { + thead.append($('').append(cells)); + }); + + if (pivot.measures.length >= 2) { + thead.append(self.make_measure_row()); + } + + self.table.append(thead); + }, + + make_measure_row: function() { + var self = this, + measures = this.pivot.measures, + cols = this.pivot.cols.headers, + measure_cells, + measure_row = $(''); + + measure_row.append($('')); + + _.each(cols, function (col) { + if (!col.children.length) { + for (var i = 0; i < measures.length; i++) { + measure_cells = $('').addClass('measure_row'); + measure_cells.append(measures[i].string); + measure_row.append(measure_cells); + } + } + }); + + if (this.pivot.get_cols_leaves().length > 1) { + for (var i = 0; i < measures.length; i++) { + measure_cells = $('').addClass('measure_row'); + measure_cells.append(measures[i].string); + measure_row.append(measure_cells); + } + } + return measure_row; + }, + + draw_row: function (row) { + var self = this, + pivot = this.pivot, + measure_types = _.pluck(this.pivot.measures, 'type'), + html_row = $(''), + row_header = this.make_border_cell(1,1) + .append(this.make_header_title(row).attr('data-id', row.id)) + .addClass('graph_border'); + + for (var i = 0; i < row.path.length; i++) { + row_header.prepend($('', {class:'web_graph_indent'})); + } + + html_row.append(row_header); + + _.each(pivot.cols.headers, function (col) { + if (col.children.length === 0) { + var values = pivot.get_values(row.id, col.id); + for (var i = 0; i < values.length; i++) { + html_row.append(make_cell(values[i], measure_types[i], i, col)); + } + } + }); + + if (pivot.get_cols_leaves().length > 1) { + var total_vals = pivot.get_total(row); + for (var j = 0; j < total_vals.length; j++) { + var cell = make_cell(total_vals[j], measure_types[j], j, pivot.cols[0]).css('font-weight', 'bold'); + html_row.append(cell); + } + } + + this.table.append(html_row); + + function make_cell (value, measure_type, index, col) { + var color, + total, + cell = $(''); + if (value === undefined) { + return cell; + } + cell.append(openerp.web.format_value(value, {type: measure_type})); + if (self.mode === 'heatmap') { + total = pivot.get_total()[index]; + color = Math.floor(90 + 165*(total - Math.abs(value))/total); + cell.css('background-color', $.Color(255, color, color)); + } + if (self.mode === 'row_heatmap') { + total = pivot.get_total(row)[index]; + color = Math.floor(90 + 165*(total - Math.abs(value))/total); + cell.css('background-color', $.Color(255, color, color)); + } + if (self.mode === 'col_heatmap') { + debugger; + total = pivot.get_total(col)[index]; + color = Math.floor(90 + 165*(total - Math.abs(value))/total); + cell.css('background-color', $.Color(255, color, color)); + } + return cell; + } + }, + +/****************************************************************************** + * Drawing charts methods... + ******************************************************************************/ + bar: function () { + var self = this, + dim_x = this.pivot.rows.groupby.length, + dim_y = this.pivot.cols.groupby.length, + data; + + // No groupby ************************************************************** + if ((dim_x === 0) && (dim_y === 0)) { + data = [{key: 'Total', values:[{ + x: 'Total', + y: this.pivot.get_total(), + }]}]; + // Only column groupbys **************************************************** + } else if ((dim_x === 0) && (dim_y >= 1)){ + data = _.map(this.pivot.get_columns_with_depth(1), function (header) { + return { + key: header.title, + values: [{x:header.root[0].title, y: self.pivot.get_total(header)[0]}] + }; + }); + // Just 1 row groupby ****************************************************** + } else if ((dim_x === 1) && (dim_y === 0)) { + data = _.map(this.pivot.main_row().children, function (pt) { + var value = self.pivot.get_total(pt), + title = (pt.title !== undefined) ? pt.title : 'Undefined'; + return {x: title, y: value}; + }); + data = [{key: self.pivot.measures[0].string, values:data}]; + // 1 row groupby and some col groupbys************************************** + } else if ((dim_x === 1) && (dim_y >= 1)) { + data = _.map(this.pivot.get_cols_with_depth(1), function (colhdr) { + var values = _.map(self.pivot.get_rows_with_depth(1), function (header) { + return { + x: header.title || 'Undefined', + y: self.pivot.get_values(header.id, colhdr.id)[0] || 0 + }; + }); + return {key: colhdr.title || 'Undefined', values: values}; + }); + // At least two row groupby************************************************* + } else { + var keys = _.uniq(_.map(this.pivot.get_rows_with_depth(2), function (hdr) { + return hdr.title || 'Undefined'; + })); + data = _.map(keys, function (key) { + var values = _.map(self.pivot.get_rows_with_depth(1), function (hdr) { + var subhdr = _.find(hdr.children, function (child) { + return ((child.title === key) || ((child.title === undefined) && (key === 'Undefined'))); + }); + return { + x: hdr.title || 'Undefined', + y: (subhdr) ? self.pivot.get_total(subhdr)[0] : 0 + }; + }); + return {key:key, values: values}; + }); + } + + nv.addGraph(function () { + var chart = nv.models.multiBarChart() + .width(self.width) + .height(self.height) + .reduceXTicks(false) + .stacked(self.bar_ui === 'stack') + .showControls(false); + + if (self.width / data[0].values.length < 80) { + chart.rotateLabels(-15); + chart.reduceXTicks(true); + chart.margin({bottom:40}); + } + + d3.select(self.svg) + .datum(data) + .attr('width', self.width) + .attr('height', self.height) + .call(chart); + + nv.utils.windowResize(chart.update); + return chart; + }); + + }, + + line: function () { + var self = this, + dim_x = this.pivot.rows.groupby.length, + dim_y = this.pivot.cols.groupby.length; + + var data = _.map(this.pivot.get_cols_leaves(), function (col) { + var values = _.map(self.pivot.get_rows_with_depth(dim_x), function (row) { + return {x: row.title, y: self.pivot.get_values(row.id,col.id, 0)}; + }); + var title = _.map(col.path, function (p) { + return p || 'Undefined'; + }).join('/'); + if (dim_y === 0) { + title = self.pivot.measures[0].string; + } + return {values: values, key: title}; + }); + + nv.addGraph(function () { + var chart = nv.models.lineChart() + .x(function (d,u) { return u; }) + .width(self.width) + .height(self.height) + .margin({top: 30, right: 20, bottom: 20, left: 60}); + + d3.select(self.svg) + .attr('width', self.width) + .attr('height', self.height) + .datum(data) + .call(chart); + + return chart; + }); + }, + + pie: function () { + var self = this, + dim_x = this.pivot.rows.groupby.length; + var data = _.map(this.pivot.get_rows_leaves(), function (row) { + var title = _.map(row.path, function (p) { + return p || 'Undefined'; + }).join('/'); + if (dim_x === 0) { + title = self.measure_label; + } + return {x: title, y: self.pivot.get_total(row)}; + }); + + nv.addGraph(function () { + var chart = nv.models.pieChart() + .color(d3.scale.category10().range()) + .width(self.width) + .height(self.height); + + d3.select(self.svg) + .datum(data) + .transition().duration(1200) + .attr('width', self.width) + .attr('height', self.height) + .call(chart); + + nv.utils.windowResize(chart.update); + return chart; + }); + }, + +}); +})(); diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js deleted file mode 100644 index b78e8323645..00000000000 --- a/addons/web_graph/static/src/js/pivot.js +++ /dev/null @@ -1,539 +0,0 @@ - -/* jshint undef: false */ - -(function () { -'use strict'; - -// Pivot Table emits the events 'groupby_changed' and 'redraw_required' when necessary. -// PivotTable is initialized by default 'inactive', and require a call to activate() -// after init to load initial data and start triggering events. -openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherMixin, { - - init: function (model, domain, fields, options) { - openerp.EventDispatcherMixin.init.call(this); - this.cells = []; - this.domain = domain; - this.no_data = true; - this.model = model; - this.fields = fields; - this.fields.__count = {type: 'integer', string:'Quantity'}; - this.measures = [{field:'__count', type: this.fields.type, string:this.fields.string}]; - this.active = false; - this.rows = { groupby: this.create_field_values(options.row_groupby || []), headers: null }; - this.cols = { groupby: this.create_field_values(options.col_groupby || []), headers: null }; - if (options.measures) { this.set_measures(options.measures); } - }, - - // ---------------------------------------------------------------------- - // Configuration methods - // ---------------------------------------------------------------------- - // this.measures: list of measure [measure], measure = {field: _, string: _, type: _} - // this.rows.groupby, this.cols.groupby : list of groupbys used for describing rows (...), - // a groupby is also {field:_, string:_, type:_} but it also has a interval - // attribute if its type is date/datetime. - // this.active: If PivotTable is active then it triggers events and updates - // its values when necessary - activate: function() { - this.active = true; - this.update_data(); - }, - - set_measures: function (measures) { - var self = this; - if (!_.isEqual(measures, this.measures)) { - this.measures = []; - _.each(measures, function (m) { self._add_measure(m); }); - if (this.active) { this.update_data(); } - } - }, - - _add_measure: function (measure) { - if (measure.field && measure.string && measure.type) { - this.measures.push(measure); - } else { - this.measures.push({ - field: measure, - string: this.fields[measure].string, - type: this.fields[measure].type, - }); - } - }, - - toggle_measure: function (field_id) { - var current_measure = _.findWhere(this.measures, {field:field_id}); - if (current_measure) { - this.measures = _.without(this.measures, current_measure); - } else { - this.measures.push({ - field: field_id, - type: this.fields[field_id].type, - string: this.fields[field_id].string - }); - } - if (this.active) { this.update_data(); } - }, - - set: function (domain, row_groupby, col_groupby) { - var row_gbs = this.create_field_values(row_groupby), - col_gbs = this.create_field_values(col_groupby), - dom_changed = !_.isEqual(this.domain, domain), - gb_changed = !(_.isEqual(row_gbs, this.rows.groupby) && - _.isEqual(col_gbs, this.cols.groupby)); - - if (dom_changed) { - this.domain = domain; - } - if (gb_changed) { - this.cols.groupby = col_gbs; - this.rows.groupby = row_gbs; - if (this.active) { this.trigger('groupby_changed'); } - } - if (this.active && (gb_changed || dom_changed)) { - this.update_data(); - } - }, - - create_field_value: function (f) { - if (f.field && f.interval) { - return { field:f.field, - string: this.fields[f.field].string, - type:this.fields[f.field].type, - interval: f.interval }; - } - return (f.field && f.string && f.type) ? f : { field: f, - string: this.fields[f].string, - type: this.fields[f].type }; - }, - - create_field_values: function (field_ids) { - var self = this; - return _.map(field_ids, function (f) { return self.create_field_value(f); }); - }, - - _add_groupby: function(groupby_list, groupby) { - groupby_list.push(this.create_field_value(groupby)); - }, - - // ---------------------------------------------------------------------- - // Cells manipulation methods - // ---------------------------------------------------------------------- - // cells are objects {x:_, y:_, values:_} where x < y and values is an array - // of values (one for each measure). The condition x < y might look - // unnecessary, but it makes the rest of the code simpler: headers - // don't krow if they are rows or cols, they just know their id, so - // it is useful that a call get_values(id1, id2) is the same as get_values(id2, id1) - add_cell : function (id1, id2, values) { - this.cells.push({x: Math.min(id1, id2), y: Math.max(id1, id2), values: values}); - }, - - get_values: function (id1, id2, default_values) { - var cell = _.find(this.cells, function (c) { - return ((c.x == Math.min(id1, id2)) && (c.y == Math.max(id1, id2))); - }); - return (cell !== undefined) ? cell.values : (default_values || new Array(this.measures.length)); - }, - - // ---------------------------------------------------------------------- - // Headers/Rows/Cols manipulation methods - // ---------------------------------------------------------------------- - // this.rows.headers, this.cols.headers = [header] describe the tree structure - // of rows/cols. Headers are objects - // { - // id:_, (unique id obviously) - // path: [...], (array of all parents title, with its own title at the end) - // title:_, (name of the row/col) - // children:[_], (subrows or sub cols of this row/col) - // domain:_, (domain of data in this row/col) - // root:_ (ref to this.rows or this.cols corresponding to the header) - // expanded:_ (boolean, true if it has been expanded) - // } - is_row: function (id) { - return !!_.find(this.rows.headers, function (header) { - return header.id === id; - }); - }, - - is_col: function (id) { - return !!_.find(this.cols.headers, function (header) { - return header.id === id; - }); - }, - - get_header: function (id) { - return _.find(this.rows.headers.concat(this.cols.headers), function (header) { - return header.id === id; - }); - }, - - // return all columns with a path length of 'depth' - get_cols_with_depth: function (depth) { - return _.filter(this.cols.headers, function (header) { - return header.path.length === depth; - }); - }, - - // return all rows with a path length of 'depth' - get_rows_with_depth: function (depth) { - return _.filter(this.rows.headers, function (header) { - return header.path.length === depth; - }); - }, - - // return all non expanded rows - get_rows_leaves: function () { - return _.filter(this.rows.headers, function (header) { - return !header.expanded; - }); - }, - - // return all non expanded cols - get_cols_leaves: function () { - return _.filter(this.cols.headers, function (header) { - return !header.expanded; - }); - }, - - get_ancestors: function (header) { - var self = this; - if (!header.children) return []; - return [].concat.apply([], _.map(header.children, function (c) {return self.get_ancestors_and_self(c); })); - }, - - get_ancestors_and_self: function (header) { - var self = this; - return [].concat.apply([header], _.map(header.children, function (c) { return self.get_ancestors_and_self(c); })); - }, - - get_total: function (header) { - if (header) { - return this.get_values(header.id, this.get_other_root(header).headers[0].id); - } - return this.get_values(this.rows.headers[0].id, this.cols.headers[0].id); - }, - - get_other_root: function (header) { - return (header.root === this.rows) ? this.cols : this.rows; - }, - - main_row: function () { return this.rows.headers[0]; }, - - main_col: function () { return this.cols.headers[0]; }, - - // ---------------------------------------------------------------------- - // Table manipulation methods : fold/expand/swap - // ---------------------------------------------------------------------- - fold: function (header) { - var ancestors = this.get_ancestors(header), - removed_ids = _.pluck(ancestors, 'id'); - - header.root.headers = _.difference(header.root.headers, ancestors); - header.children = []; - header.expanded = false; - - this.cells = _.reject(this.cells, function (cell) { - return (_.contains(removed_ids, cell.x) || _.contains(removed_ids, cell.y)); - }); - - var new_groupby_length = _.max(_.map(header.root.headers, function(g) {return g.path.length;})); - if (new_groupby_length < header.root.groupby.length) { - header.root.groupby.splice(new_groupby_length); - this.trigger('groupby_changed'); - } - this.trigger('redraw_required'); - }, - - expand: function (header_id, groupby) { - var self = this, - header = this.get_header(header_id), - otherRoot = this.get_other_root(header), - fields = otherRoot.groupby.concat(this.measures); - - if (header.path.length === header.root.groupby.length) { - self._add_groupby(header.root.groupby, groupby); - this.trigger('groupby_changed'); - } - groupby = [header.root.groupby[header.path.length]].concat(otherRoot.groupby); - - return this.get_groups(groupby, fields, header.domain) - .then(function (groups) { - _.each(groups.reverse(), function (group) { - // make header - var child = self.make_header(group, header); - child.expanded = false; - header.children.splice(0,0, child); - header.root.headers.splice(header.root.headers.indexOf(header) + 1, 0, child); - // make cells - _.each(self.get_ancestors_and_self(group), function (data) { - var values = _.map(self.measures, function (m) { - return data.attributes.aggregates[m.field]; - }); - var other = _.find(otherRoot.headers, function (h) { - if (header.root === self.cols) { - return _.isEqual(data.path.slice(1), h.path); - } else { - return _.isEqual(_.rest(data.path), h.path); - } - }); - if (other) { - self.add_cell(child.id, other.id, values); - } - }); - }); - header.expanded = true; - self.trigger('redraw_required'); - }); - }, - - make_header: function (group, parent) { - var title = parent ? group.attributes.value : ''; - return { - id: _.uniqueId(), - path: parent ? parent.path.concat(title) : [], - title: title, - children: [], - domain: parent ? group.model._domain : this.domain, - root: parent ? parent.root : undefined, - }; - }, - - swap_axis: function () { - var temp = this.rows; - this.rows = this.cols; - this.cols = temp; - this.trigger('groupby_changed'); - this.trigger('redraw_required'); - }, - - // ---------------------------------------------------------------------- - // Data updating methods - // ---------------------------------------------------------------------- - // Load the data from the db, using the method this.load_data - // update_data will try to preserve the expand/not expanded status of each - // column/row. If you want to expand all, then set this.cols.headers/this.rows.headers - // to null before calling update_data. - update_data: function () { - var self = this; - - return this.load_data().then (function (result) { - if (result) { - self.no_data = false; - self[self.cols.headers ? 'update_headers' : 'expand_headers'](self.cols, result.col_headers); - self[self.rows.headers ? 'update_headers' : 'expand_headers'](self.rows, result.row_headers); - } else { - self.no_data = true; - } - self.trigger('redraw_required'); - }); - }, - - expand_headers: function (root, new_headers) { - root.headers = new_headers; - _.each(root.headers, function (header) { - header.root = root; - header.expanded = (header.children.length > 0); - }); - }, - - update_headers: function (root, new_headers) { - _.each(root.headers, function (header) { - var corresponding_header = _.find(new_headers, function (h) { - return _.isEqual(h.path, header.path); - }); - if (corresponding_header && header.expanded) { - corresponding_header.expanded = true; - _.each(corresponding_header.children, function (c) { - c.expanded = false; - }); - } - if (corresponding_header && (!header.expanded)) { - corresponding_header.expanded = false; - } - }); - var updated_headers = _.filter(new_headers, function (header) { - return (header.expanded !== undefined); - }); - _.each(updated_headers, function (header) { - if (!header.expanded) { - header.children = []; - } - header.root = root; - }); - root.headers = updated_headers; - }, - - expand_all: function () { - this.rows.headers = null; - this.cols.headers = null; - this.update_data(); - }, - - // ---------------------------------------------------------------------- - // Data loading methods - // ---------------------------------------------------------------------- - - // To obtain all the values required to draw the full table, we have to do - // at least 2 + min(row.groupby.length, col.groupby.length) - // calls to readgroup. To simplify the code, we will always do - // 2 + row.groupby.length calls. For example, if row.groupby = [r1, r2, r3] - // and col.groupby = [c1, c2], then we will make the call with the following - // groupbys: [r1,r2,r3], [c1,r1,r2,r3], [c1,c2,r1,r2,r3], []. - load_data: function () { - var self = this, - cols = this.cols.groupby, - rows = this.rows.groupby, - visible_fields = rows.concat(cols, self.measures); - - var groupbys = _.map(_.range(cols.length + 1), function (i) { - return cols.slice(0, i).concat(rows); - }); - groupbys.push([]); - - var def_array = _.map(groupbys, function (groupby) { - return self.get_groups(groupby, visible_fields, self.domain); - }); - - return $.when.apply(null, def_array).then(function () { - var data = Array.prototype.slice.call(arguments), - row_data = data[0], - col_data = (cols.length !== 0) ? data[data.length - 2] : [], - total = data[data.length - 1][0]; - - return (total === undefined) ? undefined - : self.format_data(total, col_data, row_data, data); - }); - }, - - get_groups: function (groupbys, fields, domain, path) { - path = path || []; - var self = this, - groupby = (groupbys.length) ? groupbys[0] : []; - - return this._query_db(groupby, fields, domain, path).then(function (groups) { - if (groupbys.length > 1) { - var get_subgroups = $.when.apply(null, _.map(groups, function (group) { - return self.get_groups(_.rest(groupbys), fields, group.model._domain, path.concat(group.attributes.value)).then(function (subgroups) { - group.children = subgroups; - }); - })); - return get_subgroups.then(function () { - return groups; - }); - } else { - return groups; - } - }); - - }, - - _query_db: function (groupby, fields, domain, path) { - var self = this, - field_ids = _.without(_.pluck(fields, 'field'), '__count'), - context = {}; - - if (groupby.interval) { - context.datetime_format = {}; - var display_format; - switch (groupby.interval) { - case 'day': - display_format = 'dd MMMM YYYY'; - break; - case 'week': - display_format = 'w YYYY'; - break; - case 'month': - display_format = 'MMMM YYYY'; - break; - case 'quarter': - display_format = 'QQQ YYYY'; - break; - case 'year': - display_format = 'YYYY'; - break; - } - context.datetime_format[groupby.field] = { - interval: groupby.interval, - display_format: display_format - }; - } - return this.model.query(field_ids) - .filter(domain) - .context(context) - .group_by(groupby.field) - .then(function (results) { - var groups = _.filter(results, function (group) { - return group.attributes.length > 0; - }); - return _.map(groups, function (g) { return self.format_group(g, path); }); - }); - }, - - // add the path to the group and sanitize the value... - format_group: function (group, current_path) { - var value = group.attributes.value; - - if (group.attributes.grouped_on && this.fields[group.attributes.grouped_on].type === 'selection') { - var selection = this.fields[group.attributes.grouped_on].selection, - value_lookup = _.find(selection, function (val) { return val[0] === value; }); - group.attributes.value = value_lookup ? value_lookup[1] : 'undefined'; - } else if (value === false) { - group.attributes.value = 'undefined'; - } else if (value instanceof Array) { - group.attributes.value = value[1]; - } - - group.path = value ? (current_path || []).concat(group.attributes.value) : []; - group.attributes.aggregates.__count = group.attributes.length; - - return group; - }, - - format_data: function (total, col_data, row_data, cell_data) { - var self = this, - dim_row = this.rows.groupby.length, - dim_col = this.cols.groupby.length, - col_headers = this.get_ancestors_and_self(this.make_headers(col_data, dim_col)), - row_headers = this.get_ancestors_and_self(this.make_headers(row_data, dim_row)); - - this.cells = []; - _.each(cell_data, function (data, index) { - self.make_cells(data, index, [], row_headers, col_headers); - }); // not pretty. make it more functional? - - return {col_headers: col_headers, row_headers: row_headers}; - }, - - make_headers: function (data, depth, parent) { - var self = this, - main = this.make_header(data, parent); - - if (main.path.length < depth) { - main.children = _.map(data.children || data, function (data_pt) { - return self.make_headers (data_pt, depth, main); - }); - } - return main; - }, - - make_cells: function (data, index, current_path, rows, cols) { - var self = this; - _.each(data, function (group) { - var attr = group.attributes, - path = attr.grouped_on ? current_path.concat(attr.value) : current_path, - values = _.map(self.measures, function (measure) { - return (measure.field === '__count') ? attr.length : attr.aggregates[measure.field]; - }); - - var row = _.find(rows, function (header) { return _.isEqual(header.path, path.slice(index)); }); - var col = _.find(cols, function (header) { return _.isEqual(header.path, path.slice(0, index)); }); - self.add_cell(row.id, col.id, values); - - if (group.children) { - self.make_cells (group.children, index, path, rows, cols); - } - }); - }, - -}); -})(); - - diff --git a/addons/web_graph/static/src/js/pivot_table.js b/addons/web_graph/static/src/js/pivot_table.js new file mode 100644 index 00000000000..9c927150f20 --- /dev/null +++ b/addons/web_graph/static/src/js/pivot_table.js @@ -0,0 +1,539 @@ + +/* jshint undef: false */ + +(function () { +'use strict'; + +// Pivot Table emits the events 'groupby_changed' and 'redraw_required' when necessary. +// PivotTable is initialized by default 'inactive', and require a call to activate() +// after init to load initial data and start triggering events. +openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherMixin, { + + init: function (model, domain, fields, options) { + openerp.EventDispatcherMixin.init.call(this); + this.cells = []; + this.domain = domain; + this.no_data = true; + this.model = model; + this.fields = fields; + this.fields.__count = {type: 'integer', string:'Quantity'}; + this.measures = [{field:'__count', type: this.fields.type, string:this.fields.string}]; + this.active = false; + this.rows = { groupby: this.create_field_values(options.row_groupby || []), headers: null }; + this.cols = { groupby: this.create_field_values(options.col_groupby || []), headers: null }; + if (options.measures) { this.set_measures(options.measures); } + }, + + // ---------------------------------------------------------------------- + // Configuration methods + // ---------------------------------------------------------------------- + // this.measures: list of measure [measure], measure = {field: _, string: _, type: _} + // this.rows.groupby, this.cols.groupby : list of groupbys used for describing rows (...), + // a groupby is also {field:_, string:_, type:_} but it also has a interval + // attribute if its type is date/datetime. + // this.active: If PivotTable is active then it triggers events and updates + // its values when necessary + activate: function() { + this.active = true; + this.update_data(); + }, + + set_measures: function (measures) { + var self = this; + if (!_.isEqual(measures, this.measures)) { + this.measures = []; + _.each(measures, function (m) { self._add_measure(m); }); + if (this.active) { this.update_data(); } + } + }, + + _add_measure: function (measure) { + if (measure.field && measure.string && measure.type) { + this.measures.push(measure); + } else { + this.measures.push({ + field: measure, + string: this.fields[measure].string, + type: this.fields[measure].type, + }); + } + }, + + toggle_measure: function (field_id) { + var current_measure = _.findWhere(this.measures, {field:field_id}); + if (current_measure) { + this.measures = _.without(this.measures, current_measure); + } else { + this.measures.push({ + field: field_id, + type: this.fields[field_id].type, + string: this.fields[field_id].string + }); + } + if (this.active) { this.update_data(); } + }, + + set: function (domain, row_groupby, col_groupby) { + var row_gbs = this.create_field_values(row_groupby), + col_gbs = this.create_field_values(col_groupby), + dom_changed = !_.isEqual(this.domain, domain), + gb_changed = !(_.isEqual(row_gbs, this.rows.groupby) && + _.isEqual(col_gbs, this.cols.groupby)); + + if (dom_changed) { + this.domain = domain; + } + if (gb_changed) { + this.cols.groupby = col_gbs; + this.rows.groupby = row_gbs; + if (this.active) { this.trigger('groupby_changed'); } + } + if (this.active && (gb_changed || dom_changed)) { + this.update_data(); + } + }, + + create_field_value: function (f) { + if (f.field && f.interval) { + return { field:f.field, + string: this.fields[f.field].string, + type:this.fields[f.field].type, + interval: f.interval }; + } + return (f.field && f.string && f.type) ? f : { field: f, + string: this.fields[f].string, + type: this.fields[f].type }; + }, + + create_field_values: function (field_ids) { + var self = this; + return _.map(field_ids, function (f) { return self.create_field_value(f); }); + }, + + _add_groupby: function(groupby_list, groupby) { + groupby_list.push(this.create_field_value(groupby)); + }, + + // ---------------------------------------------------------------------- + // Cells manipulation methods + // ---------------------------------------------------------------------- + // cells are objects {x:_, y:_, values:_} where x < y and values is an array + // of values (one for each measure). The condition x < y might look + // unnecessary, but it makes the rest of the code simpler: headers + // don't krow if they are rows or cols, they just know their id, so + // it is useful that a call get_values(id1, id2) is the same as get_values(id2, id1) + add_cell : function (id1, id2, values) { + this.cells.push({x: Math.min(id1, id2), y: Math.max(id1, id2), values: values}); + }, + + get_values: function (id1, id2, default_values) { + var cell = _.find(this.cells, function (c) { + return ((c.x == Math.min(id1, id2)) && (c.y == Math.max(id1, id2))); + }); + return (cell !== undefined) ? cell.values : (default_values || new Array(this.measures.length)); + }, + + // ---------------------------------------------------------------------- + // Headers/Rows/Cols manipulation methods + // ---------------------------------------------------------------------- + // this.rows.headers, this.cols.headers = [header] describe the tree structure + // of rows/cols. Headers are objects + // { + // id:_, (unique id obviously) + // path: [...], (array of all parents title, with its own title at the end) + // title:_, (name of the row/col) + // children:[_], (subrows or sub cols of this row/col) + // domain:_, (domain of data in this row/col) + // root:_ (ref to this.rows or this.cols corresponding to the header) + // expanded:_ (boolean, true if it has been expanded) + // } + is_row: function (id) { + return !!_.find(this.rows.headers, function (header) { + return header.id === id; + }); + }, + + is_col: function (id) { + return !!_.find(this.cols.headers, function (header) { + return header.id === id; + }); + }, + + get_header: function (id) { + return _.find(this.rows.headers.concat(this.cols.headers), function (header) { + return header.id === id; + }); + }, + + // return all columns with a path length of 'depth' + get_cols_with_depth: function (depth) { + return _.filter(this.cols.headers, function (header) { + return header.path.length === depth; + }); + }, + + // return all rows with a path length of 'depth' + get_rows_with_depth: function (depth) { + return _.filter(this.rows.headers, function (header) { + return header.path.length === depth; + }); + }, + + // return all non expanded rows + get_rows_leaves: function () { + return _.filter(this.rows.headers, function (header) { + return !header.expanded; + }); + }, + + // return all non expanded cols + get_cols_leaves: function () { + return _.filter(this.cols.headers, function (header) { + return !header.expanded; + }); + }, + + get_ancestors: function (header) { + var self = this; + if (!header.children) return []; + return [].concat.apply([], _.map(header.children, function (c) {return self.get_ancestors_and_self(c); })); + }, + + get_ancestors_and_self: function (header) { + var self = this; + return [].concat.apply([header], _.map(header.children, function (c) { return self.get_ancestors_and_self(c); })); + }, + + get_total: function (header) { + if (header) { + return this.get_values(header.id, this.get_other_root(header).headers[0].id); + } + return this.get_values(this.rows.headers[0].id, this.cols.headers[0].id); + }, + + get_other_root: function (header) { + return (header.root === this.rows) ? this.cols : this.rows; + }, + + main_row: function () { return this.rows.headers[0]; }, + + main_col: function () { return this.cols.headers[0]; }, + + // ---------------------------------------------------------------------- + // Table manipulation methods : fold/expand/swap + // ---------------------------------------------------------------------- + fold: function (header) { + var ancestors = this.get_ancestors(header), + removed_ids = _.pluck(ancestors, 'id'); + + header.root.headers = _.difference(header.root.headers, ancestors); + header.children = []; + header.expanded = false; + + this.cells = _.reject(this.cells, function (cell) { + return (_.contains(removed_ids, cell.x) || _.contains(removed_ids, cell.y)); + }); + + var new_groupby_length = _.max(_.map(header.root.headers, function(g) {return g.path.length;})); + if (new_groupby_length < header.root.groupby.length) { + header.root.groupby.splice(new_groupby_length); + this.trigger('groupby_changed'); + } + this.trigger('redraw_required'); + }, + + expand: function (header_id, groupby) { + var self = this, + header = this.get_header(header_id), + otherRoot = this.get_other_root(header), + fields = otherRoot.groupby.concat(this.measures); + + if (header.path.length === header.root.groupby.length) { + self._add_groupby(header.root.groupby, groupby); + this.trigger('groupby_changed'); + } + groupby = [header.root.groupby[header.path.length]].concat(otherRoot.groupby); + + return this.get_groups(groupby, fields, header.domain) + .then(function (groups) { + _.each(groups.reverse(), function (group) { + // make header + var child = self.make_header(group, header); + child.expanded = false; + header.children.splice(0,0, child); + header.root.headers.splice(header.root.headers.indexOf(header) + 1, 0, child); + // make cells + _.each(self.get_ancestors_and_self(group), function (data) { + var values = _.map(self.measures, function (m) { + return data.attributes.aggregates[m.field]; + }); + var other = _.find(otherRoot.headers, function (h) { + if (header.root === self.cols) { + return _.isEqual(data.path.slice(1), h.path); + } else { + return _.isEqual(_.rest(data.path), h.path); + } + }); + if (other) { + self.add_cell(child.id, other.id, values); + } + }); + }); + header.expanded = true; + self.trigger('redraw_required'); + }); + }, + + make_header: function (group, parent) { + var title = parent ? group.attributes.value : ''; + return { + id: _.uniqueId(), + path: parent ? parent.path.concat(title) : [], + title: title, + children: [], + domain: parent ? group.model._domain : this.domain, + root: parent ? parent.root : undefined, + }; + }, + + swap_axis: function () { + var temp = this.rows; + this.rows = this.cols; + this.cols = temp; + this.trigger('groupby_changed'); + this.trigger('redraw_required'); + }, + + // ---------------------------------------------------------------------- + // Data updating methods + // ---------------------------------------------------------------------- + // Load the data from the db, using the method this.load_data + // update_data will try to preserve the expand/not expanded status of each + // column/row. If you want to expand all, then set this.cols.headers/this.rows.headers + // to null before calling update_data. + update_data: function () { + var self = this; + + return this.load_data().then (function (result) { + if (result) { + self.no_data = false; + self[self.cols.headers ? 'update_headers' : 'expand_headers'](self.cols, result.col_headers); + self[self.rows.headers ? 'update_headers' : 'expand_headers'](self.rows, result.row_headers); + } else { + self.no_data = true; + } + self.trigger('redraw_required'); + }); + }, + + expand_headers: function (root, new_headers) { + root.headers = new_headers; + _.each(root.headers, function (header) { + header.root = root; + header.expanded = (header.children.length > 0); + }); + }, + + update_headers: function (root, new_headers) { + _.each(root.headers, function (header) { + var corresponding_header = _.find(new_headers, function (h) { + return _.isEqual(h.path, header.path); + }); + if (corresponding_header && header.expanded) { + corresponding_header.expanded = true; + _.each(corresponding_header.children, function (c) { + c.expanded = false; + }); + } + if (corresponding_header && (!header.expanded)) { + corresponding_header.expanded = false; + } + }); + var updated_headers = _.filter(new_headers, function (header) { + return (header.expanded !== undefined); + }); + _.each(updated_headers, function (header) { + if (!header.expanded) { + header.children = []; + } + header.root = root; + }); + root.headers = updated_headers; + }, + + expand_all: function () { + this.rows.headers = null; + this.cols.headers = null; + this.update_data(); + }, + + // ---------------------------------------------------------------------- + // Data loading methods + // ---------------------------------------------------------------------- + + // To obtain all the values required to draw the full table, we have to do + // at least 2 + min(row.groupby.length, col.groupby.length) + // calls to readgroup. To simplify the code, we will always do + // 2 + row.groupby.length calls. For example, if row.groupby = [r1, r2, r3] + // and col.groupby = [c1, c2], then we will make the call with the following + // groupbys: [r1,r2,r3], [c1,r1,r2,r3], [c1,c2,r1,r2,r3], []. + load_data: function () { + var self = this, + cols = this.cols.groupby, + rows = this.rows.groupby, + visible_fields = rows.concat(cols, self.measures); + + var groupbys = _.map(_.range(cols.length + 1), function (i) { + return cols.slice(0, i).concat(rows); + }); + groupbys.push([]); + + var def_array = _.map(groupbys, function (groupby) { + return self.get_groups(groupby, visible_fields, self.domain); + }); + + return $.when.apply(null, def_array).then(function () { + var data = Array.prototype.slice.call(arguments), + row_data = data[0], + col_data = (cols.length !== 0) ? data[data.length - 2] : [], + total = data[data.length - 1][0]; + + return (total === undefined) ? undefined + : self.format_data(total, col_data, row_data, data); + }); + }, + + get_groups: function (groupbys, fields, domain, path) { + path = path || []; + var self = this, + groupby = (groupbys.length) ? groupbys[0] : []; + + return this._query_db(groupby, fields, domain, path).then(function (groups) { + if (groupbys.length > 1) { + var get_subgroups = $.when.apply(null, _.map(groups, function (group) { + return self.get_groups(_.rest(groupbys), fields, group.model._domain, path.concat(group.attributes.value)).then(function (subgroups) { + group.children = subgroups; + }); + })); + return get_subgroups.then(function () { + return groups; + }); + } else { + return groups; + } + }); + + }, + + _query_db: function (groupby, fields, domain, path) { + var self = this, + field_ids = _.without(_.pluck(fields, 'field'), '__count'), + context = {}; + + if (groupby.interval) { + context.datetime_format = {}; + var display_format; + switch (groupby.interval) { + case 'day': + display_format = 'dd MMMM YYYY'; + break; + case 'week': + display_format = 'w YYYY'; + break; + case 'month': + display_format = 'MMMM YYYY'; + break; + case 'quarter': + display_format = 'QQQ YYYY'; + break; + case 'year': + display_format = 'YYYY'; + break; + } + context.datetime_format[groupby.field] = { + interval: groupby.interval, + display_format: display_format + }; + } + return this.model.query(field_ids) + .filter(domain) + .context(context) + .group_by(groupby.field) + .then(function (results) { + var groups = _.filter(results, function (group) { + return group.attributes.length > 0; + }); + return _.map(groups, function (g) { return self.format_group(g, path); }); + }); + }, + + // add the path to the group and sanitize the value... + format_group: function (group, current_path) { + var value = group.attributes.value; + + if (group.attributes.grouped_on && this.fields[group.attributes.grouped_on].type === 'selection') { + var selection = this.fields[group.attributes.grouped_on].selection, + value_lookup = _.find(selection, function (val) { return val[0] === value; }); + group.attributes.value = value_lookup ? value_lookup[1] : 'undefined'; + } else if (value === false) { + group.attributes.value = 'undefined'; + } else if (value instanceof Array) { + group.attributes.value = value[1]; + } + + group.path = value ? (current_path || []).concat(group.attributes.value) : []; + group.attributes.aggregates.__count = group.attributes.length; + + return group; + }, + + format_data: function (total, col_data, row_data, cell_data) { + var self = this, + dim_row = this.rows.groupby.length, + dim_col = this.cols.groupby.length, + col_headers = this.get_ancestors_and_self(this.make_headers(col_data, dim_col)), + row_headers = this.get_ancestors_and_self(this.make_headers(row_data, dim_row)); + + this.cells = []; + _.each(cell_data, function (data, index) { + self.make_cells(data, index, [], row_headers, col_headers); + }); // not pretty. make it more functional? + + return {col_headers: col_headers, row_headers: row_headers}; + }, + + make_headers: function (data, depth, parent) { + var self = this, + main = this.make_header(data, parent); + + if (main.path.length < depth) { + main.children = _.map(data.children || data, function (data_pt) { + return self.make_headers (data_pt, depth, main); + }); + } + return main; + }, + + make_cells: function (data, index, current_path, rows, cols) { + var self = this; + _.each(data, function (group) { + var attr = group.attributes, + path = attr.grouped_on ? current_path.concat(attr.value) : current_path, + values = _.map(self.measures, function (measure) { + return (measure.field === '__count') ? attr.length : attr.aggregates[measure.field]; + }); + + var row = _.find(rows, function (header) { return _.isEqual(header.path, path.slice(index)); }); + var col = _.find(cols, function (header) { return _.isEqual(header.path, path.slice(0, index)); }); + self.add_cell(row.id, col.id, values); + + if (group.children) { + self.make_cells (group.children, index, path, rows, cols); + } + }); + }, + +}); +})(); + + -- cgit v1.2.3 From b681cff77f8232d5d67f065daf278a17c3f98107 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 14 Jan 2014 14:01:41 +0100 Subject: [IMP] sets nvd3 library in production mode instead of debug mode (addon web_graph) bzr revid: ged@openerp.com-20140114130141-b41640a72gpshw1x --- addons/web_graph/static/src/js/graph_widget.js | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph_widget.js b/addons/web_graph/static/src/js/graph_widget.js index 33f3caabc07..c34603da19a 100644 --- a/addons/web_graph/static/src/js/graph_widget.js +++ b/addons/web_graph/static/src/js/graph_widget.js @@ -4,6 +4,7 @@ (function () { 'use strict'; var QWeb = openerp.web.qweb; +nv.dev = false; // sets nvd3 library in production mode openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin, { template: 'GraphWidget', -- cgit v1.2.3 From cf81efda4309f895f6777c46c39f1fe894f109cf Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 15 Jan 2014 10:37:49 +0100 Subject: [IMP] adds search view integration in graph view (addon web_graph) bzr revid: ged@openerp.com-20140115093749-t2s0306fchm2tnir --- addons/web_graph/static/src/js/graph_view.js | 140 +++++++++---------------- addons/web_graph/static/src/js/graph_widget.js | 130 +++++++++++++---------- addons/web_graph/static/src/js/pivot_table.js | 10 +- 3 files changed, 134 insertions(+), 146 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph_view.js b/addons/web_graph/static/src/js/graph_view.js index 1b940c1703a..eb901c28423 100644 --- a/addons/web_graph/static/src/js/graph_view.js +++ b/addons/web_graph/static/src/js/graph_view.js @@ -16,20 +16,14 @@ instance.web_graph.GraphView = instance.web.View.extend({ display_name: _lt('Graph'), view_type: 'graph', + // ---------------------------------------------------------------------- + // Init stuff + // ---------------------------------------------------------------------- init: function(parent, dataset, view_id, options) { this._super(parent, dataset, view_id, options); this.dataset = dataset; this.model = new instance.web.Model(dataset.model, {group_by_no_leaf: true}); this.search_view = parent.searchview; - this.search_view_groupby = []; - this.groupby_mode = 'default'; // 'default' or 'manual' - this.default_row_groupby = []; - this.default_col_groupby = []; - this.search_field = { - get_context: this.proxy('get_context'), - get_domain: function () {}, - get_groupby: function () { }, - }; }, view_loading: function (fields_view_get) { @@ -41,16 +35,18 @@ instance.web_graph.GraphView = instance.web.View.extend({ stacked : (arch.attrs.stacked === 'True'), mode: (arch.attrs.type) ? arch.attrs.type : 'bar', measures: [], + row_groupby: [], + col_groupby: [], }; _.each(arch.children, function (field) { if (_.has(field.attrs, 'type')) { switch (field.attrs.type) { case 'row': - self.default_row_groupby.push(field.attrs.name); + self.widget_config.row_groupby.push(field.attrs.name); break; case 'col': - self.default_col_groupby.push(field.attrs.name); + self.widget_config.col_groupby.push(field.attrs.name); break; case 'measure': self.widget_config.measures.push(field.attrs.name); @@ -60,61 +56,28 @@ instance.web_graph.GraphView = instance.web.View.extend({ if ('operator' in field.attrs) { self.widget_config.measures.push(field.attrs.name); } else { - self.default_row_groupby.push(field.attrs.name); + self.widet_config.row_groupby.push(field.attrs.name); } } }); if (self.widget_config.measures.length === 0) { self.widget_config.measures.push('__count'); } - this.widget_config.row_groupby = self.default_row_groupby; - this.widget_config.col_groupby = self.default_col_groupby; - }, - - get_context: function (facet) { - var col_group_by = _.map(facet.values.models, function (model) { - return model.attributes.value.attrs.context.col_group_by; - }); - return {col_group_by : col_group_by}; }, do_search: function (domain, context, group_by) { - // var col_groupby = context.col_group_by || [], - // options = {domain:domain}; - if (!this.graph_widget) { + if (group_by.length) { + this.widget_config.row_groupby = group_by; + } this.graph_widget = new openerp.web_graph.Graph(this, this.model, domain, this.widget_config); this.graph_widget.appendTo(this.$el); this.graph_widget.on('groupby_changed', this, this.proxy('register_groupby')); this.ViewManager.on('switch_mode', this, function (e) { if (e === 'graph') this.graph_widget.reload(); }); + return; } - // this.search_view_groupby = group_by; - - // if (group_by.length && this.groupby_mode !== 'manual') { - // if (_.isEqual(col_groupby, [])) { - // col_groupby = this.default_col_groupby; - // } - // } - // if (group_by.length || col_groupby.length) { - // this.groupby_mode = 'manual'; - // } - // if (!this.graph_widget.enabled) { - // options.update = false; - // options.silent = true; - // } - - // if (this.groupby_mode === 'manual') { - // options.row_groupby = group_by; - // options.col_groupby = col_groupby; - // } else { - // options.row_groupby = _.toArray(this.default_row_groupby); - // options.col_groupby = _.toArray(this.default_col_groupby); - // } - // this.graph_widget.set(domain, options.row_groupby, options.col_groupby); - // this.graph_widget.set_domain(domain); - // this.graph_widget.set_col_groupby(options.col_groupby); - // this.graph_widget.set_row_groupby(options.row_groupby); + this.graph_widget.set(domain, group_by, this.graph_widget.get_col_groupby()); }, do_show: function () { @@ -122,47 +85,46 @@ instance.web_graph.GraphView = instance.web.View.extend({ return this._super(); }, + // ---------------------------------------------------------------------- + // Search view integration + // ---------------------------------------------------------------------- + + // add groupby to the search view register_groupby: function() { - // var self = this, - // query = this.search_view.query; - - // this.groupby_mode = 'manual'; - // if (_.isEqual(this.search_view_groupby, this.graph_widget.pivot.rows.groupby) || - // (!_.has(this.search_view, '_s_groupby'))) { - // return; - // } - // var rows = _.map(this.graph_widget.pivot.rows.groupby, function (group) { - // return make_facet('GroupBy', group); - // }); - // var cols = _.map(this.graph_widget.pivot.cols.groupby, function (group) { - // return make_facet('ColGroupBy', group); - // }); - - // query.reset(rows.concat(cols)); - - // function make_facet (category, fields) { - // var values, - // icon, - // backbone_field, - // cat_name; - // if (!(fields instanceof Array)) { fields = [fields]; } - // if (category === 'GroupBy') { - // cat_name = 'group_by'; - // icon = 'w'; - // backbone_field = self.search_view._s_groupby; - // } else { - // cat_name = 'col_group_by'; - // icon = 'f'; - // backbone_field = self.search_field; - // } - // values = _.map(fields, function (field) { - // var context = {}; - // context[cat_name] = field; - // return {label: self.graph_widget.fields[field].string, value: {attrs:{domain: [], context: context}}}; - // }); - // return {category:category, values: values, icon:icon, field: backbone_field}; - // } + var query = this.search_view.query; + + if (!_.has(this.search_view, '_s_groupby')) { return; } + + var row_groupby = this.graph_widget.get_row_groupby(); + var gb_facet = this.make_groupby_facets(row_groupby); + var search_facet = query.findWhere({category:'GroupBy'}); + + if (search_facet) { + search_facet.values.reset(gb_facet.values); + } else { + if (row_groupby.length) { + query.add(gb_facet); + } + } }, + + make_groupby_facets: function(fields) { + var self = this, + values = _.map(fields, function (field) { + return { + label: self.graph_widget.fields[field].string, + value: {attrs:{domain: [], context: {group_by: field}}} + }; + }); + return {category:'GroupBy', values: values, icon:'w', field: self.search_view._s_groupby}; + }, + + search_field: { + get_context: function() {}, + get_domain: function () {}, + get_groupby: function () { }, + }, + }); diff --git a/addons/web_graph/static/src/js/graph_widget.js b/addons/web_graph/static/src/js/graph_widget.js index c34603da19a..a2f7761514a 100644 --- a/addons/web_graph/static/src/js/graph_widget.js +++ b/addons/web_graph/static/src/js/graph_widget.js @@ -9,14 +9,9 @@ nv.dev = false; // sets nvd3 library in production mode openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin, { template: 'GraphWidget', - events: { - 'click .graph_mode_selection li' : 'mode_selection', - 'click .graph_measure_selection li' : 'measure_selection', - 'click .graph_options_selection li' : 'option_selection', - 'click .web_graph_click' : 'header_cell_clicked', - 'click a.field-selection' : 'field_selection', - }, - + // ---------------------------------------------------------------------- + // Init stuff + // ---------------------------------------------------------------------- init: function(parent, model, domain, options) { this._super(parent); this.model = model; @@ -56,6 +51,8 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin }); }, + // this method gets the fields that appear in the search view, under the + // 'Groupby' heading get_search_fields: function () { var self = this, options = {model:this.model, view_type: 'search'}, @@ -83,6 +80,7 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin }); }, + // Extracts the integer/float fields which are not 'id' get_measures: function(fields) { var measures = []; _.each(this.fields, function (f, id) { @@ -93,7 +91,19 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin return measures; }, + add_measures_to_options: function() { + var measure_selection = this.$('.graph_measure_selection'); + _.each(this.measure_list, function (measure) { + var choice = $('').attr('data-choice', measure.field) + .attr('href', '#') + .append(measure.string); + measure_selection.append($('
  • ').append(choice)); + }); + }, + // ---------------------------------------------------------------------- + // Configuration methods + // ---------------------------------------------------------------------- set: function (domain, row_groupby, col_groupby) { if (this.pivot) { this.pivot.set(domain, row_groupby, col_groupby); @@ -104,49 +114,34 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin } }, - add_measures_to_options: function() { - var measure_selection = this.$('.graph_measure_selection'); - _.each(this.measure_list, function (measure) { - var choice = $('').attr('data-choice', measure.field) - .attr('href', '#') - .append(measure.string); - measure_selection.append($('
  • ').append(choice)); - }); - }, - set_mode: function (mode) { this.mode = mode; this.display_data(); }, + // returns the row groupbys as a list of fields (not the representation used + // internally by pivot table) + get_row_groupby: function () { + return _.pluck(this.pivot.rows.groupby, 'field'); + }, + + get_col_groupby: function () { + return _.pluck(this.pivot.cols.groupby, 'field'); + }, + reload: function () { this.pivot.update_data(); }, - display_data: function () { - this.$('.graph_main_content svg').remove(); - this.$('.graph_main_content div').remove(); - this.table.empty(); - - if (this.visible_ui) { - this.$('.graph_header').css('display', 'block'); - } else { - this.$('.graph_header').css('display', 'none'); - } - if (this.pivot.no_data) { - this.$('.graph_main_content').append($(QWeb.render('graph_no_data'))); - } else { - var table_modes = ['pivot', 'heatmap', 'row_heatmap', 'col_heatmap']; - if (_.contains(table_modes, this.mode)) { - this.draw_table(); - } else { - this.$('.graph_main_content').append($('
    ')); - this.svg = this.$('.graph_main_content svg')[0]; - this.width = this.$el.width(); - this.height = Math.min(Math.max(document.documentElement.clientHeight - 116 - 60, 250), Math.round(0.8*this.$el.width())); - this[this.mode](); - } - } + // ---------------------------------------------------------------------- + // UI code + // ---------------------------------------------------------------------- + events: { + 'click .graph_mode_selection li' : 'mode_selection', + 'click .graph_measure_selection li' : 'measure_selection', + 'click .graph_options_selection li' : 'option_selection', + 'click .web_graph_click' : 'header_cell_clicked', + 'click a.field-selection' : 'field_selection', }, mode_selection: function (event) { @@ -233,9 +228,38 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin } }, -/****************************************************************************** - * Drawing pivot table methods... - ******************************************************************************/ + // ---------------------------------------------------------------------- + // Main display method + // ---------------------------------------------------------------------- + display_data: function () { + this.$('.graph_main_content svg').remove(); + this.$('.graph_main_content div').remove(); + this.table.empty(); + + if (this.visible_ui) { + this.$('.graph_header').css('display', 'block'); + } else { + this.$('.graph_header').css('display', 'none'); + } + if (this.pivot.no_data) { + this.$('.graph_main_content').append($(QWeb.render('graph_no_data'))); + } else { + var table_modes = ['pivot', 'heatmap', 'row_heatmap', 'col_heatmap']; + if (_.contains(table_modes, this.mode)) { + this.draw_table(); + } else { + this.$('.graph_main_content').append($('
    ')); + this.svg = this.$('.graph_main_content svg')[0]; + this.width = this.$el.width(); + this.height = Math.min(Math.max(document.documentElement.clientHeight - 116 - 60, 250), Math.round(0.8*this.$el.width())); + this[this.mode](); + } + } + }, + + // ---------------------------------------------------------------------- + // Drawing the table + // ---------------------------------------------------------------------- draw_table: function () { this.pivot.main_row().title = 'Total'; if (this.pivot.measures.length == 1) { @@ -411,22 +435,22 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin } }, -/****************************************************************************** - * Drawing charts methods... - ******************************************************************************/ + // ---------------------------------------------------------------------- + // Drawing charts code + // ---------------------------------------------------------------------- bar: function () { var self = this, dim_x = this.pivot.rows.groupby.length, dim_y = this.pivot.cols.groupby.length, data; - // No groupby ************************************************************** + // No groupby if ((dim_x === 0) && (dim_y === 0)) { data = [{key: 'Total', values:[{ x: 'Total', y: this.pivot.get_total(), }]}]; - // Only column groupbys **************************************************** + // Only column groupbys } else if ((dim_x === 0) && (dim_y >= 1)){ data = _.map(this.pivot.get_columns_with_depth(1), function (header) { return { @@ -434,7 +458,7 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin values: [{x:header.root[0].title, y: self.pivot.get_total(header)[0]}] }; }); - // Just 1 row groupby ****************************************************** + // Just 1 row groupby } else if ((dim_x === 1) && (dim_y === 0)) { data = _.map(this.pivot.main_row().children, function (pt) { var value = self.pivot.get_total(pt), @@ -442,7 +466,7 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin return {x: title, y: value}; }); data = [{key: self.pivot.measures[0].string, values:data}]; - // 1 row groupby and some col groupbys************************************** + // 1 row groupby and some col groupbys } else if ((dim_x === 1) && (dim_y >= 1)) { data = _.map(this.pivot.get_cols_with_depth(1), function (colhdr) { var values = _.map(self.pivot.get_rows_with_depth(1), function (header) { @@ -453,7 +477,7 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin }); return {key: colhdr.title || 'Undefined', values: values}; }); - // At least two row groupby************************************************* + // At least two row groupby } else { var keys = _.uniq(_.map(this.pivot.get_rows_with_depth(2), function (hdr) { return hdr.title || 'Undefined'; diff --git a/addons/web_graph/static/src/js/pivot_table.js b/addons/web_graph/static/src/js/pivot_table.js index 9c927150f20..edd1fc68042 100644 --- a/addons/web_graph/static/src/js/pivot_table.js +++ b/addons/web_graph/static/src/js/pivot_table.js @@ -77,18 +77,20 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM var row_gbs = this.create_field_values(row_groupby), col_gbs = this.create_field_values(col_groupby), dom_changed = !_.isEqual(this.domain, domain), - gb_changed = !(_.isEqual(row_gbs, this.rows.groupby) && - _.isEqual(col_gbs, this.cols.groupby)); + row_gb_changed = !_.isEqual(row_gbs, this.rows.groupby), + col_gb_changed = !_.isEqual(col_gbs, this.cols.groupby); if (dom_changed) { this.domain = domain; } - if (gb_changed) { + if (row_gb_changed || col_gb_changed) { this.cols.groupby = col_gbs; this.rows.groupby = row_gbs; + if (row_gb_changed) {this.rows.headers = null; } + if (col_gb_changed) {this.cols.headers = null; } if (this.active) { this.trigger('groupby_changed'); } } - if (this.active && (gb_changed || dom_changed)) { + if (this.active && (row_gb_changed || col_gb_changed || dom_changed)) { this.update_data(); } }, -- cgit v1.2.3 From 4343ca278a21cd12880857736a9bf81a4cc83524 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 15 Jan 2014 11:51:04 +0100 Subject: [FIX] correctly compares groupby in pivot_table to avoid bugs/crashes (now, it ignores the 'interval' attributes) so the table can interact with the graph view (addon web_graph) bzr revid: ged@openerp.com-20140115105104-qff3t47lo1lyp5wd --- addons/web_graph/static/src/js/pivot_table.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/pivot_table.js b/addons/web_graph/static/src/js/pivot_table.js index edd1fc68042..79d351ce315 100644 --- a/addons/web_graph/static/src/js/pivot_table.js +++ b/addons/web_graph/static/src/js/pivot_table.js @@ -77,8 +77,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM var row_gbs = this.create_field_values(row_groupby), col_gbs = this.create_field_values(col_groupby), dom_changed = !_.isEqual(this.domain, domain), - row_gb_changed = !_.isEqual(row_gbs, this.rows.groupby), - col_gb_changed = !_.isEqual(col_gbs, this.cols.groupby); + row_gb_changed = !this.equal_groupby(row_gbs, this.rows.groupby), + col_gb_changed = !this.equal_groupby(col_gbs, this.cols.groupby); if (dom_changed) { this.domain = domain; @@ -95,6 +95,22 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM } }, + // compare groupby, ignoring the 'interval' attribute of dates... + // this is necessary to avoid problems with the groupby received by the + // context which do not have the interval attribute. This is ugly + // and need to be changed at some point + equal_groupby: function (groupby1, groupby2) { + if (groupby1.length !== groupby2.length) { return false; } + for (var i = 0; i < groupby1.length; i++) { + if (!this.equal_value(groupby1[i], groupby2[i])) { return false; } + } + return true; + }, + + equal_value: function (val1, val2) { + return ((val1.field === val2.field) && (val1.string === val2.string) && (val1.type === val2.type)); + }, + create_field_value: function (f) { if (f.field && f.interval) { return { field:f.field, -- cgit v1.2.3 From 74d6e75007ea089d79190e58a2579aaa8cd46060 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 15 Jan 2014 16:51:37 +0100 Subject: [IMP] supports col groupby in search view in graph view (addon web_graph) bzr revid: ged@openerp.com-20140115155137-qwy0sr49zhizgmf6 --- addons/web_graph/static/src/js/graph_view.js | 77 ++++++++++++++++++++------ addons/web_graph/static/src/js/graph_widget.js | 4 +- 2 files changed, 61 insertions(+), 20 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph_view.js b/addons/web_graph/static/src/js/graph_view.js index eb901c28423..c2b3979199f 100644 --- a/addons/web_graph/static/src/js/graph_view.js +++ b/addons/web_graph/static/src/js/graph_view.js @@ -66,10 +66,15 @@ instance.web_graph.GraphView = instance.web.View.extend({ }, do_search: function (domain, context, group_by) { + var col_group_by = this.get_col_groupbys_from_searchview(); + if (!this.graph_widget) { if (group_by.length) { this.widget_config.row_groupby = group_by; } + if (col_group_by.length) { + this.widget_config.col_groupby = group_by; + } this.graph_widget = new openerp.web_graph.Graph(this, this.model, domain, this.widget_config); this.graph_widget.appendTo(this.$el); this.graph_widget.on('groupby_changed', this, this.proxy('register_groupby')); @@ -77,7 +82,13 @@ instance.web_graph.GraphView = instance.web.View.extend({ return; } - this.graph_widget.set(domain, group_by, this.graph_widget.get_col_groupby()); + this.graph_widget.set(domain, group_by, col_group_by); + }, + + get_col_groupbys_from_searchview: function () { + var facet = this.search_view.query.findWhere({category:'ColGroupBy'}), + groupby_list = facet ? facet.attributes.values : []; + return _.map(groupby_list, function (g) { return g.value.attrs.context.col_group_by; }); }, do_show: function () { @@ -95,39 +106,69 @@ instance.web_graph.GraphView = instance.web.View.extend({ if (!_.has(this.search_view, '_s_groupby')) { return; } - var row_groupby = this.graph_widget.get_row_groupby(); - var gb_facet = this.make_groupby_facets(row_groupby); - var search_facet = query.findWhere({category:'GroupBy'}); + // add row groupbys + var row_groupby = this.graph_widget.get_row_groupby(), + row_facet = this.make_row_groupby_facets(row_groupby), + row_search_facet = query.findWhere({category:'GroupBy'}); - if (search_facet) { - search_facet.values.reset(gb_facet.values); + if (row_search_facet) { + row_search_facet.values.reset(row_facet.values); } else { if (row_groupby.length) { - query.add(gb_facet); + query.add(row_facet); + } + } + // add col groupbys + var col_groupby = this.graph_widget.get_col_groupby(), + col_facet = this.make_col_groupby_facets(col_groupby), + col_search_facet = query.findWhere({category:'ColGroupBy'}); + + if (col_search_facet) { + col_search_facet.values.reset(col_facet.values); + } else { + if (col_groupby.length) { + query.add(col_facet); } } }, - make_groupby_facets: function(fields) { - var self = this, - values = _.map(fields, function (field) { - return { - label: self.graph_widget.fields[field].string, - value: {attrs:{domain: [], context: {group_by: field}}} - }; - }); - return {category:'GroupBy', values: values, icon:'w', field: self.search_view._s_groupby}; + make_row_groupby_facets: function(groupbys) { + return { + category:'GroupBy', + values: this.make_groupby_values(groupbys, 'group_by'), + icon:'w', + field: this.search_view._s_groupby + }; + }, + + make_col_groupby_facets: function(groupbys) { + return { + category:'ColGroupBy', + values: this.make_groupby_values(groupbys, 'col_group_by'), + icon:'f', + field: this.search_field + }; + }, + + make_groupby_values: function (groupbys, category) { + return _.map(groupbys, function (groupby) { + var context = {}; + context[category] = groupby.field; + return { + label: groupby.string, + value: {attrs:{domain: [], context: context}} + }; + }); }, search_field: { get_context: function() {}, get_domain: function () {}, - get_groupby: function () { }, + get_groupby: function () {}, }, }); - }; diff --git a/addons/web_graph/static/src/js/graph_widget.js b/addons/web_graph/static/src/js/graph_widget.js index a2f7761514a..d84c8d794f4 100644 --- a/addons/web_graph/static/src/js/graph_widget.js +++ b/addons/web_graph/static/src/js/graph_widget.js @@ -122,11 +122,11 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin // returns the row groupbys as a list of fields (not the representation used // internally by pivot table) get_row_groupby: function () { - return _.pluck(this.pivot.rows.groupby, 'field'); + return this.pivot.rows.groupby; }, get_col_groupby: function () { - return _.pluck(this.pivot.cols.groupby, 'field'); + return this.pivot.cols.groupby; }, reload: function () { -- cgit v1.2.3 From 588e5413872c5c50ba9f48d4fd094ae1ba05e3c7 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 16 Jan 2014 10:55:49 +0100 Subject: [FIX] fixes some issues with the col_group_bys in searchbar (main problem was that do_search is called twice when the user swap axis) (addon web_graph) bzr revid: ged@openerp.com-20140116095549-3f2hbyzj32nuj147 --- addons/web_graph/static/src/js/graph_view.js | 15 +++++++++++++-- addons/web_graph/static/src/js/graph_widget.js | 1 + addons/web_graph/static/src/js/pivot_table.js | 4 ++-- 3 files changed, 16 insertions(+), 4 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph_view.js b/addons/web_graph/static/src/js/graph_view.js index c2b3979199f..91fcefaf1b8 100644 --- a/addons/web_graph/static/src/js/graph_view.js +++ b/addons/web_graph/static/src/js/graph_view.js @@ -78,17 +78,23 @@ instance.web_graph.GraphView = instance.web.View.extend({ this.graph_widget = new openerp.web_graph.Graph(this, this.model, domain, this.widget_config); this.graph_widget.appendTo(this.$el); this.graph_widget.on('groupby_changed', this, this.proxy('register_groupby')); + this.graph_widget.on('groupby_swapped', this, this.proxy('swap_groupby')); this.ViewManager.on('switch_mode', this, function (e) { if (e === 'graph') this.graph_widget.reload(); }); return; } + if (this.swapped) { + this.swapped = false; + return; + } + this.graph_widget.set(domain, group_by, col_group_by); }, get_col_groupbys_from_searchview: function () { var facet = this.search_view.query.findWhere({category:'ColGroupBy'}), - groupby_list = facet ? facet.attributes.values : []; - return _.map(groupby_list, function (g) { return g.value.attrs.context.col_group_by; }); + groupby_list = facet ? facet.values.models : []; + return _.map(groupby_list, function (g) { return g.attributes.value.attrs.context.col_group_by; }); }, do_show: function () { @@ -132,6 +138,11 @@ instance.web_graph.GraphView = instance.web.View.extend({ } }, + swap_groupby: function () { + this.swap = true; + this.register_groupby(); + }, + make_row_groupby_facets: function(groupbys) { return { category:'GroupBy', diff --git a/addons/web_graph/static/src/js/graph_widget.js b/addons/web_graph/static/src/js/graph_widget.js index d84c8d794f4..e9e3b4acb12 100644 --- a/addons/web_graph/static/src/js/graph_widget.js +++ b/addons/web_graph/static/src/js/graph_widget.js @@ -41,6 +41,7 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin self.pivot = new openerp.web_graph.PivotTable(self.model, self.domain, self.fields, self.pivot_options); self.pivot.on('redraw_required', self, self.proxy('display_data')); self.pivot.on('groupby_changed', self, function () { self.trigger('groupby_changed'); }); + self.pivot.on('groupby_swapped', self, function () { self.trigger('groupby_swapped'); }); openerp.web.bus.on('click', self, function () { if (self.dropdown) { self.dropdown.remove(); diff --git a/addons/web_graph/static/src/js/pivot_table.js b/addons/web_graph/static/src/js/pivot_table.js index 79d351ce315..d7a836d98b8 100644 --- a/addons/web_graph/static/src/js/pivot_table.js +++ b/addons/web_graph/static/src/js/pivot_table.js @@ -4,7 +4,7 @@ (function () { 'use strict'; -// Pivot Table emits the events 'groupby_changed' and 'redraw_required' when necessary. +// Pivot Table emits the events 'groupby_changed', 'groupby_swapped' and 'redraw_required' when necessary. // PivotTable is initialized by default 'inactive', and require a call to activate() // after init to load initial data and start triggering events. openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherMixin, { @@ -318,7 +318,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM var temp = this.rows; this.rows = this.cols; this.cols = temp; - this.trigger('groupby_changed'); + this.trigger('groupby_swapped'); this.trigger('redraw_required'); }, -- cgit v1.2.3 From 1c1a02d16630250ce981cf3411638922734d0224 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 16 Jan 2014 15:00:58 +0100 Subject: [IMP] changes the UI of the graph view: removes old dropdown buttons and adds a toolbar instead (addon web_graph) bzr revid: ged@openerp.com-20140116140058-rd6nde1mfupgnajt --- addons/web_graph/static/src/js/graph_widget.js | 63 +++++++++++++++---- addons/web_graph/static/src/xml/web_graph.xml | 84 +++++++++++++++----------- 2 files changed, 99 insertions(+), 48 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/js/graph_widget.js b/addons/web_graph/static/src/js/graph_widget.js index e9e3b4acb12..789cc54cbe3 100644 --- a/addons/web_graph/static/src/js/graph_widget.js +++ b/addons/web_graph/static/src/js/graph_widget.js @@ -16,7 +16,8 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin this._super(parent); this.model = model; this.domain = domain; - this.mode = options.mode || 'pivot'; + this.mode = options.mode || 'pivot'; // pivot, bar, pie, line + this.heatmap_mode = options.heatmap_mode || 'none'; this.title = options.title || 'Graph'; this.visible_ui = options.visible_ui || true; this.bar_ui = options.bar_ui || 'group'; @@ -27,6 +28,17 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin var self = this; this.table = $('
    '); this.$('.graph_main_content').append(this.table); + + var index = 0; + if (this.mode === 'bar') { index = 1; } + if (this.mode === 'line') { index = 2; } + if (this.mode === 'chart') { index = 3; } + this.$('.graph_mode_selection label').eq(index).addClass('active'); + + if (this.mode !== 'pivot') { + this.$('.graph_heatmap label').addClass('disabled'); + } + var def1 = this.get_search_fields().then(function (f) { self.important_fields = f; }); @@ -117,6 +129,22 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin set_mode: function (mode) { this.mode = mode; + + if (mode === 'pivot') { + this.$('.graph_heatmap label').removeClass('disabled'); + } else { + this.$('.graph_heatmap label').addClass('disabled'); + } + this.display_data(); + }, + + set_heatmap_mode: function (mode) { // none, row, col, all + debugger; + this.heatmap_mode = mode; + if (mode === 'none') { + this.$('.graph_heatmap label').removeClass('disabled'); + this.$('.graph_heatmap label').removeClass('active'); + } this.display_data(); }, @@ -138,16 +166,17 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin // UI code // ---------------------------------------------------------------------- events: { - 'click .graph_mode_selection li' : 'mode_selection', + 'click .graph_mode_selection label' : 'mode_selection', 'click .graph_measure_selection li' : 'measure_selection', - 'click .graph_options_selection li' : 'option_selection', + 'click .graph_options_selection label' : 'option_selection', + 'click .graph_heatmap label' : 'heatmap_mode_selection', 'click .web_graph_click' : 'header_cell_clicked', 'click a.field-selection' : 'field_selection', }, mode_selection: function (event) { event.preventDefault(); - var mode = event.target.attributes['data-mode'].nodeValue; + var mode = event.currentTarget.attributes['data-mode'].nodeValue; this.set_mode(mode); }, @@ -159,7 +188,7 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin option_selection: function (event) { event.preventDefault(); - switch (event.target.attributes['data-choice'].nodeValue) { + switch (event.currentTarget.attributes['data-choice'].nodeValue) { case 'bar_grouped': this.bar_ui = 'group'; if (this.mode === 'bar') { @@ -187,6 +216,17 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin } }, + heatmap_mode_selection: function (event) { + event.preventDefault(); + var mode = event.currentTarget.attributes['data-mode'].nodeValue; + if (this.heatmap_mode === mode) { + event.stopPropagation(); + this.set_heatmap_mode('none'); + } else { + this.set_heatmap_mode(mode); + } + }, + header_cell_clicked: function (event) { event.preventDefault(); event.stopPropagation(); @@ -245,8 +285,7 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin if (this.pivot.no_data) { this.$('.graph_main_content').append($(QWeb.render('graph_no_data'))); } else { - var table_modes = ['pivot', 'heatmap', 'row_heatmap', 'col_heatmap']; - if (_.contains(table_modes, this.mode)) { + if (this.mode === 'pivot') { this.draw_table(); } else { this.$('.graph_main_content').append($('
    ')); @@ -416,17 +455,17 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin return cell; } cell.append(openerp.web.format_value(value, {type: measure_type})); - if (self.mode === 'heatmap') { + if (self.heatmap_mode === 'both') { total = pivot.get_total()[index]; color = Math.floor(90 + 165*(total - Math.abs(value))/total); cell.css('background-color', $.Color(255, color, color)); } - if (self.mode === 'row_heatmap') { + if (self.heatmap_mode === 'row') { total = pivot.get_total(row)[index]; color = Math.floor(90 + 165*(total - Math.abs(value))/total); cell.css('background-color', $.Color(255, color, color)); } - if (self.mode === 'col_heatmap') { + if (self.heatmap_mode === 'col') { debugger; total = pivot.get_total(col)[index]; color = Math.floor(90 + 165*(total - Math.abs(value))/total); @@ -453,10 +492,10 @@ openerp.web_graph.Graph = openerp.web.Widget.extend(openerp.EventDispatcherMixin }]}]; // Only column groupbys } else if ((dim_x === 0) && (dim_y >= 1)){ - data = _.map(this.pivot.get_columns_with_depth(1), function (header) { + data = _.map(this.pivot.get_cols_with_depth(1), function (header) { return { key: header.title, - values: [{x:header.root[0].title, y: self.pivot.get_total(header)[0]}] + values: [{x:header.title, y: self.pivot.get_total(header)[0]}] }; }); // Just 1 row groupby diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 27d7ec9af47..48f225bf84e 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -1,45 +1,57 @@
    - -
    - + + +
    +
    +
    -- cgit v1.2.3 From 470d42df759ed313eb2075301101da203a80e93d Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 16 Jan 2014 15:27:48 +0100 Subject: [IMP] adds a 'title' attribute to the toolbar in graph view, to give some tooltips to the user (addon web_graph) bzr revid: ged@openerp.com-20140116142748-qigjrtb510flex9s --- addons/web_graph/static/src/xml/web_graph.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'addons/web_graph/static/src') diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index 48f225bf84e..1d71dbcbf9c 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -5,40 +5,40 @@