summaryrefslogtreecommitdiff
path: root/addons/web_graph/static/src
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web_graph/static/src')
-rw-r--r--addons/web_graph/static/src/css/graph.css165
-rw-r--r--addons/web_graph/static/src/css/nv.d3.css769
-rw-r--r--addons/web_graph/static/src/js/graph_view.js297
-rw-r--r--addons/web_graph/static/src/js/graph_widget.js875
-rw-r--r--addons/web_graph/static/src/js/pivot_table.js468
-rw-r--r--addons/web_graph/static/src/xml/web_graph.xml65
6 files changed, 0 insertions, 2639 deletions
diff --git a/addons/web_graph/static/src/css/graph.css b/addons/web_graph/static/src/css/graph.css
deleted file mode 100644
index fd6735961e1..00000000000
--- a/addons/web_graph/static/src/css/graph.css
+++ /dev/null
@@ -1,165 +0,0 @@
- /*
- This is a hack for IE9 ...
- Attrs : width and height are not take in consideration
- */
-.openerp svg:not(:root) {
- overflow: visible;
-}
-
-.graph_pivot_mode {
- position:initial;
-}
-
-.graph_chart_mode {
- position:relative;
-}
-
-.graph_main_content td {
- font-size: 12px;
- margin: 45px;
- border-collapse: collapse;
- vertical-align: middle;
- border-bottom: 1px solid #ccc;
- padding: 6px 8px;
- text-align: right;
- color: black;
-}
-
-.graph_main_content td:first-child {
- background-color: rgb(240, 238, 238);
-}
-
-.graph_main_content table {
- margin-top: 10px;
-}
-
-.graph_measure_selection .oe_selected {
- padding-left: 0;
-}
-
-.graph_measure_selection .oe_selected:before {
- content: "\f00c";
- width: 20px;
- display: inline-block;
- font-family: FontAwesome;
-}
-
-.graph_measure_selection li {
- margin-left: 5px;
-}
-
-.graph_main_content th {
- font-size: 13px;
- font-weight: normal;
- padding: 10px 8px;
- vertical-align: top;
- color: black;
-}
-
-.graph_main_content tbody td{
- border: 1px solid #b8b8b8;
-}
-
-.graph_main_content tbody {
- border-top: 1px solid black;
-}
-
-.graph_main_content thead {
- background-color: rgb(240, 238, 238);
- border: 1px solid #b8b8b8;
-}
-
-.graph_main_content thead th {
- border-left: 1px solid #b8b8b8;
-}
-
-div.graph_widget {
- padding:10px;
-}
-
-.oe_dashboard div.graph_widget {
- padding:0;
-}
-
-td.graph_border {
- text-align: left;
- white-space: nowrap;
-}
-
-.graph_main_content table:not(.heatmap) tr:hover td:not(:first-child)
-{
- background-color: rgb(245, 245, 245);
-}
-
-span.field-selection {
- display: none;
- padding: 0;
-}
-
-.web_graph_click:hover {
- cursor: pointer;
-}
-
-.graph_widget .dropdown-menu {
- font-size: 13px;
- padding: 4px 0;
- background: #e8e8e8 !important;
- border: 1px solid rgba(0, 0, 0, 0.15);
- font-color: !important black;
- text-shadow: none;
- background-color: #e8e8e8;
- -moz-border-radius: 3px;
- -webkit-border-radius: 3px;
- border-radius: 3px;
-}
-
-
-.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;
-}
-
-th.measure_row {
- color: black;
- font-size: 12px;
- padding:0px 5px 0px 5px ;
- margin:0;
-}
-
-
-.graph-dropdown-submenu {
- position: relative;
-}
-
-.graph-dropdown-submenu>.dropdown-menu {
- top: 0;
- left: 100%;
- margin-top: -6px;
- margin-left: -1px;
- -webkit-border-radius: 0 6px 6px 6px;
- -moz-border-radius: 0 6px 6px;
- border-radius: 0 6px 6px 6px;
-}
-
-.graph-dropdown-submenu:hover>.dropdown-menu {
- display: block;
-}
-
-.graph-dropdown-submenu>a:after {
- display: block;
- content: " ";
- float: right;
- width: 0;
- height: 0;
- border-color: transparent;
- border-style: solid;
- border-width: 5px 0 5px 5px;
- border-left-color: #ccc;
- margin-top: 5px;
- margin-right: -10px;
-}
-
-.graph-dropdown-submenu:hover>a:after {
- border-left-color: #fff;
-}
-
diff --git a/addons/web_graph/static/src/css/nv.d3.css b/addons/web_graph/static/src/css/nv.d3.css
deleted file mode 100644
index cae834827cc..00000000000
--- a/addons/web_graph/static/src/css/nv.d3.css
+++ /dev/null
@@ -1,769 +0,0 @@
-
-/********************
- * 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_view.js b/addons/web_graph/static/src/js/graph_view.js
deleted file mode 100644
index acd075dcc73..00000000000
--- a/addons/web_graph/static/src/js/graph_view.js
+++ /dev/null
@@ -1,297 +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;
-
-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 stuff
- // ----------------------------------------------------------------------
- init: function(parent, dataset, view_id, options) {
- var self = this;
- 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.col_search_field = {
- get_context: function() { return { col_group_by: self.graph_widget.get_col_groupbys(),
- measures: self.graph_widget.get_current_measures()};},
- get_domain: function () {},
- get_groupby: function () {},
- };
- this.$buttons = options.$buttons;
- this.view_loaded = $.Deferred();
- },
-
- start: function() {
- var $buttons = instance.web.qweb.render("graph-view-buttons");
- this.$buttons.html($buttons);
- return this._super();
- },
-
- 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 || 'bar',
- measures: [],
- row_groupby: [],
- col_groupby: [],
- graph_view: this,
- $buttons: this.$buttons
- };
-
- _.each(arch.children, function (field) {
- var field_name = field.attrs.name;
- if (_.has(field.attrs, 'interval')) {
- field_name = field.attrs.name + ':' + field.attrs.interval;
- }
- //noinspection FallThroughInSwitchStatementJS
- switch (field.attrs.type) {
- case 'measure':
- self.widget_config.measures.push(field_name);
- break;
- case 'col':
- self.widget_config.col_groupby.push(field_name);
- break;
- default:
- if ('operator' in field.attrs) {
- self.widget_config.measures.push(field_name);
- break;
- }
- case 'row':
- self.widget_config.row_groupby.push(field_name);
- }
- });
- if (self.widget_config.measures.length === 0) {
- self.widget_config.measures.push('__count');
- }
- this.view_loaded.resolve();
- },
-
- do_search: function (domain, context, group_by) {
- var self = this;
- this.view_loaded.done(function () {
- self._do_search(domain, context, group_by);
- });
- },
-
- _do_search: function (domain, context, group_by) {
- if (this.ignore_do_search) {
- this.ignore_do_search = false;
- return;
- }
- var self = this,
- groupbys = this.get_groupbys_from_searchview(),
- col_group_by = groupbys.col_group_by,
- measures = groupbys.measures;
-
- if (!this.graph_widget) {
- this.widget_config.context = _.clone(context);
- this.widget_config.context.group_by_no_leaf = true;
- if (group_by.length) {
- this.widget_config.row_groupby = group_by;
- }
- if (col_group_by.length) {
- this.widget_config.col_groupby = col_group_by;
- }
- if (measures.length) {
- this.widget_config.measures = measures;
- }
- this.graph_widget = new openerp.web_graph.Graph(this, this.model, domain, this.widget_config);
- this.graph_widget.appendTo(this.$el).done(function () {
-
- });
- return;
- }
-
- this.graph_widget.set(domain, group_by, col_group_by, measures);
- },
-
- get_groupbys_from_searchview: function () {
- var result = { group_by: [], col_group_by: [], measures: []},
- searchdata = this.search_view.build_search_data();
-
- _.each(searchdata.groupbys, function (data) {
- data = (_.isString(data)) ? py.eval(data) : data;
- result.group_by = result.group_by.concat(data.group_by);
- if (data.col_group_by) {
- result.col_group_by = result.col_group_by.concat(data.col_group_by);
- }
- if (data.measures) {
- result.measures = result.measures.concat(data.measures);
- }
- });
-
- if (result.col_group_by.length) {
- return result;
- }
- _.each(searchdata.contexts, function (context) {
- if (context.col_group_by) {
- result.col_group_by = result.col_group_by.concat(context.col_group_by);
- }
- if (context.measures) {
- result.measures = result.measures.concat(context.measures);
- }
- });
- return result;
- },
-
- do_show: function () {
- this.do_push_state({});
- return this._super();
- },
-
- // ----------------------------------------------------------------------
- // Search view integration
- // ----------------------------------------------------------------------
-
- // add groupby to the search view
- register_groupby: function(row_groupby, col_groupby) {
- var query = this.search_view.query,
- groupbys = this.get_groupbys_from_searchview(),
- search_row_groupby = groupbys.group_by,
- search_col_groupby = groupbys.col_group_by,
- search_measures = groupbys.measures,
- row_gb_changed = !_.isEqual(_.pluck(row_groupby, 'field'), search_row_groupby),
- col_gb_changed = !_.isEqual(_.pluck(col_groupby, 'field'), search_col_groupby),
- measures_gb_changed = !_.isEqual(_.pluck(col_groupby, 'field'), search_col_groupby);
- if (!_.has(this.search_view, '_s_groupby')) { return; }
-
- if (!row_gb_changed && !col_gb_changed) {
- return;
- }
-
- var custom_groups = this.get_custom_filter_groupbys();
- row_groupby = row_groupby.slice(custom_groups.groupby.length);
- col_groupby = col_groupby.slice(custom_groups.col_groupby.length);
-
- if (row_gb_changed && col_gb_changed) {
- // when two changes to the search view will be done, the method do_search
- // will be called twice, once with the correct groupby and incorrect col_groupby,
- // and once with correct informations. This flag is necessary to prevent the
- // incorrect informations to propagate and trigger useless queries
- this.ignore_do_search = true;
- }
-
- if (row_gb_changed) {
- // add row groupbys
- var row_facet = this.make_row_groupby_facets(row_groupby),
- row_search_facet = query.findWhere({category:'GroupBy'});
-
- if (row_search_facet) {
- row_search_facet.values.reset(row_facet.values, {focus_input:false});
- } else {
- if (row_groupby.length) {
- query.add(row_facet);
- }
- }
- }
-
- if (col_gb_changed) {
- // add col groupbys
- var 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, {focus_input:false});
- } else {
- if (col_groupby.length) {
- query.add(col_facet);
- }
- }
- }
- },
-
- make_row_groupby_facets: function(groupbys) {
- return {
- category:'GroupBy',
- values: this.make_groupby_values(groupbys, 'group_by'),
- icon:'fa fa-bars',
- 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:'fa fa-level-down',
- field: this.col_search_field
- };
- },
-
- make_groupby_values: function (groupbys, category) {
- return _.map(groupbys, function (groupby) {
- var context = {};
- context[category] = groupby.field;
- var value;
- if (category === 'group_by' && groupby.type !== 'date' && groupby.type !== 'datetime') {
- value = groupby.filter || {attrs: {domain: [], context: context}};
- } else {
- value = {attrs: {domain: [], context: context}};
- }
- return {
- label: groupby.string,
- value: value
- };
- });
- },
-
- get_custom_filter_groupbys: function () {
- var gb = [],
- col_gb = [];
-
- var facet = this.search_view.query.at(0);
- if (facet) {
- if (facet.get('category') !== 'GroupBy' && facet.get('category') !== 'ColGroupBy') {
- gb = get_groupby(facet);
- col_gb = get_col_groupby(facet);
- }
- }
- return {
- groupby: gb,
- col_groupby: col_gb,
- }
- }
-
-});
-
-function get_groupby(facet) {
- var field = facet.get('field'),
- result = [];
- if ('get_groupby' in field) {
- result = instance.web.pyeval.sync_eval_domains_and_contexts({
- group_by_seq: field.get_groupby(facet)
- }).group_by;
- }
- return result;
-}
-function get_col_groupby(facet) {
- var field = facet.get('field'),
- result = [];
- if ('get_context' in field) {
- result = instance.web.pyeval.sync_eval_domains_and_contexts({
- contexts: field.get_context(facet)
- }).context.col_group_by || [];
- }
- return result;
-}
-
-
-};
diff --git a/addons/web_graph/static/src/js/graph_widget.js b/addons/web_graph/static/src/js/graph_widget.js
deleted file mode 100644
index afb691e4790..00000000000
--- a/addons/web_graph/static/src/js/graph_widget.js
+++ /dev/null
@@ -1,875 +0,0 @@
-
-/* jshint undef: false */
-
-(function () {
-'use strict';
-var QWeb = openerp.web.qweb;
-var _lt = openerp.web._lt;
-var _t = openerp.web._t;
-
-nv.dev = false; // sets nvd3 library in production mode
-
-openerp.web_graph.Graph = openerp.web.Widget.extend({
- template: 'GraphWidget',
-
- // ----------------------------------------------------------------------
- // Init stuff
- // ----------------------------------------------------------------------
- init: function(parent, model, domain, options) {
- this._super(parent);
- this.model = model;
- this.domain = domain;
- this.mode = options.mode || 'pivot'; // pivot, bar, pie, line
- this.visible_ui = options.visible_ui || true;
- this.bar_ui = options.bar_ui || 'group';
- this.graph_view = options.graph_view || null;
- this.pivot_options = options;
- this.title = options.title || 'Data';
- this.$buttons = options.$buttons;
- },
-
- start: function() {
- var self = this;
- this.table = $('<table>');
- this.$('.graph_main_content').append(this.table);
-
- this.$buttons.find('.oe-pivot-mode').click(function () {
- self.set_mode.bind(self)('pivot');
- });
- this.$measure_list = this.$buttons.find('.oe-measure-list');
-
- this.$buttons.find('.oe-bar-mode').click(function () {
- self.set_mode.bind(self)('bar');
- });
- this.$buttons.find('.oe-line-mode').click(function () {
- self.set_mode.bind(self)('line');
- });
- this.$buttons.find('.oe-pie-mode').click(function () {
- self.set_mode.bind(self)('pie');
- });
- this.$buttons.find('.fa-expand').click(this.swap_axis.bind(this));
- this.$buttons.find('.fa-arrows-alt').click(function () {
- self.pivot.expand_all().then(self.proxy('display_data'));
- });
- this.$buttons.find('.fa-download').click(this.export_xls.bind(this));
-
- var indexes = {'pivot': 0, 'bar': 1, 'line': 2, 'chart': 3};
- this.$('.graph_mode_selection label').eq(indexes[this.mode]).addClass('selected');
-
- if (this.mode !== 'pivot') {
- this.$('.graph_heatmap label').addClass('disabled');
- this.$('.graph_main_content').addClass('graph_chart_mode');
- } else {
- this.$('.graph_main_content').addClass('graph_pivot_mode');
- }
- // get search view
- var parent = this.getParent();
- while (!(parent instanceof openerp.web.ViewManager)) {
- parent = parent.getParent();
- }
- this.search_view = parent.searchview;
-
- openerp.session.rpc('/web_graph/check_xlwt').then(function (result) {
- self.$('.graph_options_selection label').last().toggle(result);
- });
-
- this.$buttons.find('button').tooltip();
-
- return this.model.call('fields_get', {
- context: this.graph_view.dataset.context
- }).then(function (f) {
- self.fields = f;
- self.fields.__count = {field:'__count', type: 'integer', string:_t('Count')};
- self.groupby_fields = self.get_groupby_fields();
- self.measure_list = self.get_measures();
- self.add_measures_to_options();
- self.pivot_options.row_groupby = self.create_field_values(self.pivot_options.row_groupby || []);
- self.pivot_options.col_groupby = self.create_field_values(self.pivot_options.col_groupby || []);
- self.pivot_options.measures = self.create_field_values(self.pivot_options.measures || [{field:'__count', type: 'integer', string:'Count'}]);
- self.pivot = new openerp.web_graph.PivotTable(self.model, self.domain, self.fields, self.pivot_options);
- self.pivot.update_data().then(function () {
- self.display_data();
- if (self.graph_view) {
- self.graph_view.register_groupby(self.pivot.rows.groupby, self.pivot.cols.groupby);
- }
- });
- openerp.web.bus.on('click', self, function (event) {
- if (self.dropdown) {
- self.$row_clicked = $(event.target).closest('tr');
- self.dropdown.remove();
- self.dropdown = null;
- }
- });
- self.put_measure_checkmarks();
- });
- },
-
- get_groupby_fields: function () {
- var search_fields = this.get_search_fields(),
- search_field_names = _.pluck(search_fields, 'field'),
- other_fields = [],
- groupable_types = ['many2one', 'char', 'boolean', 'selection', 'date', 'datetime'];
-
- _.each(this.fields, function (val, key) {
- if (!_.contains(search_field_names, key) &&
- _.contains(groupable_types, val.type) &&
- val.store === true) {
- other_fields.push({
- field: key,
- string: val.string,
- });
- }
- });
- return search_fields.concat(other_fields);
- },
-
- // this method gets the fields that appear in the search view, under the
- // 'Groupby' heading
- get_search_fields: function () {
- // this method is disabled for now. This requires extensive changes because the
- // search view works quite differently: But the graph view is going to be split
- // soon in pivot view and graph view. The pivot view will then properly handle
- // groupbys.
- return [];
- var self = this;
-
- var groupbygroups = _(this.search_view.drawer.inputs).select(function (g) {
- return g instanceof openerp.web.search.GroupbyGroup;
- });
-
- var filters = _.flatten(_.pluck(groupbygroups, 'filters'), true),
- groupbys = _.flatten(_.map(filters, function (filter) {
- var groupby = py.eval(filter.attrs.context).group_by;
- if (!(groupby instanceof Array)) { groupby = [groupby]; }
- return _.map(groupby, function(g) {
- return {field: g, filter: filter};
- });
- }));
-
- return _.uniq(_.map(groupbys, function (groupby) {
- var field = groupby.field,
- filter = groupby.filter,
- raw_field = field.split(':')[0],
- string = (field === raw_field) ? filter.attrs.string : self.fields[raw_field].string;
-
- filter = (field === raw_field) ? filter : undefined;
-
- return { field: raw_field, string: string, filter: filter };
- }), false, function (filter) {return filter.field;});
- },
-
- // Extracts the integer/float fields which are not 'id'
- get_measures: function() {
- return _.compact(_.map(this.fields, function (f, id) {
- if (((f.type === 'integer') || (f.type === 'float')) &&
- (id !== 'id') &&
- (f.store !== false)) {
- return {field:id, type: f.type, string: f.string};
- }
- }));
- },
-
- add_measures_to_options: function() {
- this.$measure_list.append(
- _.map(this.measure_list, function (measure) {
- return $('<li>').append($('<a>').attr('data-choice', measure.field)
- .attr('href', '#')
- .text(measure.string));
- }));
- this.$measure_list.find('li').click(this.measure_selection.bind(this));
- },
-
- // ----------------------------------------------------------------------
- // Configuration methods
- // ----------------------------------------------------------------------
- set: function (domain, row_groupby, col_groupby, measures_groupby) {
- if (!this.pivot) {
- this.pivot_options.domain = domain;
- this.pivot_options.row_groupby = row_groupby;
- this.pivot_options.col_groupby = col_groupby;
- this.pivot_options.measures_groupby = measures_groupby;
- return;
- }
- var row_gbs = this.create_field_values(row_groupby),
- col_gbs = this.create_field_values(col_groupby),
- measures_gbs = this.create_field_values(measures_groupby),
- dom_changed = !_.isEqual(this.pivot.domain, domain),
- row_gb_changed = !_.isEqual(row_gbs, this.pivot.rows.groupby),
- col_gb_changed = !_.isEqual(col_gbs, this.pivot.cols.groupby),
- measures_gb_changed = !_.isEqual(measures_gbs, this.pivot.measures),
- row_reduced = is_strict_beginning_of(row_gbs, this.pivot.rows.groupby),
- col_reduced = is_strict_beginning_of(col_gbs, this.pivot.cols.groupby),
- measures_reduced = is_strict_beginning_of(measures_gbs, this.pivot.measures);
-
- if (!dom_changed && row_reduced && !col_gb_changed && !measures_gb_changed) {
- this.pivot.fold_with_depth(this.pivot.rows, row_gbs.length);
- this.display_data();
- return;
- }
- if (!dom_changed && col_reduced && !row_gb_changed && !measures_gb_changed) {
- this.pivot.fold_with_depth(this.pivot.cols, col_gbs.length);
- this.display_data();
- return;
- }
-
- if (!dom_changed && col_reduced && row_reduced && !measures_gb_changed) {
- this.pivot.fold_with_depth(this.pivot.rows, row_gbs.length);
- this.pivot.fold_with_depth(this.pivot.cols, col_gbs.length);
- this.display_data();
- return;
- }
-
- if (dom_changed || row_gb_changed || col_gb_changed || measures_gb_changed) {
- this.pivot.set(domain, row_gbs, col_gbs, measures_gbs).then(this.proxy('display_data'));
- }
-
- if (measures_gb_changed) {
- this.put_measure_checkmarks();
- }
- },
-
- set_mode: function (mode) {
- this.mode = mode;
-
- if (mode === 'pivot') {
- this.$('.graph_heatmap label').removeClass('disabled');
- this.$('.graph_main_content').removeClass('graph_chart_mode').addClass('graph_pivot_mode');
- } else {
- this.$('.graph_heatmap label').addClass('disabled');
- this.$('.graph_main_content').removeClass('graph_pivot_mode').addClass('graph_chart_mode');
- }
- this.display_data();
- },
-
- create_field_value: function (f) {
- var field = (_.contains(f, ':')) ? f.split(':')[0] : f,
- groupby_field = _.findWhere(this.groupby_fields, {field:field}),
- string = groupby_field ? groupby_field.string : this.fields[field].string,
- result = {field: f, string: string, type: this.fields[field].type };
-
- if (groupby_field) {
- result.filter = groupby_field.filter;
- }
-
- return result;
- },
-
- create_field_values: function (field_ids) {
- return _.map(field_ids, this.proxy('create_field_value'));
- },
-
-
- get_col_groupbys: function () {
- return _.pluck(this.pivot.cols.groupby, 'field');
- },
-
- get_current_measures: function () {
- return _.pluck(this.pivot.measures, 'field');
- },
-
- // ----------------------------------------------------------------------
- // UI code
- // ----------------------------------------------------------------------
- events: {
- 'click .graph_mode_selection label' : 'mode_selection',
- 'click .graph_measure_selection li' : 'measure_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.currentTarget.getAttribute('data-mode');
- this.set_mode(mode);
- },
-
- measure_selection: function (event) {
- event.preventDefault();
- event.stopPropagation();
- var measure_field = event.target.getAttribute('data-choice');
- var measure = {
- field: measure_field,
- type: this.fields[measure_field].type,
- string: this.fields[measure_field].string
- };
-
- this.pivot.toggle_measure(measure).then(this.proxy('display_data'));
- this.put_measure_checkmarks();
- },
-
- put_measure_checkmarks: function () {
- var self = this,
- measures_li = this.$measure_list.find('li');
- measures_li.removeClass('selected');
- _.each(this.measure_list, function (measure, index) {
- if (_.findWhere(self.pivot.measures, measure)) {
- measures_li.eq(index).addClass('selected');
- }
- });
-
- },
-
- option_selection: function (event) {
- event.preventDefault();
- switch (event.currentTarget.getAttribute('data-choice')) {
- case 'swap_axis':
- this.swap_axis();
- break;
- case 'expand_all':
- this.pivot.expand_all().then(this.proxy('display_data'));
- break;
- case 'update_values':
- this.pivot.update_data().then(this.proxy('display_data'));
- break;
- case 'export_data':
- this.export_xls();
- break;
- }
- },
-
- header_cell_clicked: function (event) {
- event.preventDefault();
- event.stopPropagation();
- var id = event.target.getAttribute('data-id'),
- header = this.pivot.get_header(id),
- self = this;
-
- if (header.expanded) {
- if (header.root === this.pivot.rows) {
- this.fold_row(header, event);
- } else {
- this.fold_col(header);
- }
- return;
- }
- if (header.path.length < header.root.groupby.length) {
- this.$row_clicked = $(event.target).closest('tr');
- this.expand(id);
- return;
- }
- if (!this.groupby_fields.length) {
- return;
- }
-
- var fields = _.map(this.groupby_fields, function (field) {
- return {id: field.field, value: field.string, type:self.fields[field.field.split(':')[0]].type};
- });
- if (this.dropdown) {
- this.dropdown.remove();
- }
- this.dropdown = $(QWeb.render('field_selection', {fields:fields, header_id:id}));
- $(event.target).after(this.dropdown);
- this.dropdown.css({
- position:'absolute',
- left:event.originalEvent.layerX,
- });
- this.$('.field-selection').next('.dropdown-menu').first().toggle();
- },
-
- field_selection: function (event) {
- var id = event.target.getAttribute('data-id'),
- field_id = event.target.getAttribute('data-field-id'),
- interval,
- groupby = this.create_field_value(field_id);
- event.preventDefault();
- if (this.fields[field_id].type === 'date' || this.fields[field_id].type === 'datetime') {
- interval = event.target.getAttribute('data-interval');
- groupby.field = groupby.field + ':' + interval;
- }
- this.expand(id, groupby);
- },
-
- // ----------------------------------------------------------------------
- // Pivot Table integration
- // ----------------------------------------------------------------------
- expand: function (header_id, groupby) {
- var self = this,
- header = this.pivot.get_header(header_id),
- update_groupby = !!groupby;
-
- groupby = groupby || header.root.groupby[header.path.length];
-
- this.pivot.expand(header_id, groupby).then(function () {
- if (header.root === self.pivot.rows) {
- // expanding rows can be done by only inserting in the dom
- // console.log(event.target);
- var rows = self.build_rows(header.children);
- var doc_fragment = $(document.createDocumentFragment());
- rows.map(function (row) {
- doc_fragment.append(self.draw_row(row, 0));
- });
- self.$row_clicked.after(doc_fragment);
- } else {
- // expanding cols will redraw the full table
- self.display_data();
- }
- if (update_groupby && self.graph_view) {
- self.graph_view.register_groupby(self.pivot.rows.groupby, self.pivot.cols.groupby);
- }
- });
-
- },
-
- fold_row: function (header, event) {
- var rows_before = this.pivot.rows.headers.length,
- update_groupby = this.pivot.fold(header),
- rows_after = this.pivot.rows.headers.length,
- rows_removed = rows_before - rows_after;
-
- if (rows_after === 1) {
- // probably faster to redraw the unique row instead of removing everything
- this.display_data();
- } else {
- var $row = $(event.target).parent().parent();
- $row.nextAll().slice(0,rows_removed).remove();
- }
- if (update_groupby && this.graph_view) {
- this.graph_view.register_groupby(this.pivot.rows.groupby, this.pivot.cols.groupby);
- }
- },
-
- fold_col: function (header) {
- var update_groupby = this.pivot.fold(header);
-
- this.display_data();
- if (update_groupby && this.graph_view) {
- this.graph_view.register_groupby(this.pivot.rows.groupby, this.pivot.cols.groupby);
- }
- },
-
- swap_axis: function () {
- this.pivot.swap_axis();
- this.display_data();
- this.graph_view.register_groupby(this.pivot.rows.groupby, this.pivot.cols.groupby);
- },
-
- // ----------------------------------------------------------------------
- // Convert Pivot data structure into table structure :
- // compute rows, cols, colors, cell width, cell height, ...
- // ----------------------------------------------------------------------
- build_table: function(raw) {
- return {
- headers: this.build_headers(),
- measure_row: this.build_measure_row(),
- rows: this.build_rows(this.pivot.rows.headers,raw),
- nbr_measures: this.pivot.measures.length,
- title: this.title,
- };
- },
-
- build_headers: function () {
- var pivot = this.pivot,
- nbr_measures = pivot.measures.length,
- height = _.max(_.map(pivot.cols.headers, function(g) {return g.path.length;})) + 1,
- rows = [];
-
- _.each(pivot.cols.headers, function (col) {
- var cell_width = nbr_measures * (col.expanded ? pivot.get_ancestor_leaves(col).length : 1),
- cell_height = col.expanded ? 1 : height - col.path.length,
- cell = {width: cell_width, height: cell_height, title: col.title, id: col.id, expanded: col.expanded};
- if (rows[col.path.length]) {
- rows[col.path.length].push(cell);
- } else {
- rows[col.path.length] = [cell];
- }
- });
-
- if (pivot.get_cols_leaves().length > 1) {
- rows[0].push({width: nbr_measures, height: height, title: ' ', id: pivot.main_col().id });
- }
- if (pivot.cols.headers.length === 1) {
- rows = [[{width: nbr_measures, height: 1, title: _t('Total'), id: pivot.main_col().id, expanded: false}]];
- }
- return rows;
- },
-
- build_measure_row: function () {
- var nbr_leaves = this.pivot.get_cols_leaves().length,
- nbr_cols = nbr_leaves + ((nbr_leaves > 1) ? 1 : 0),
- result = [],
- add_total = this.pivot.get_cols_leaves().length > 1,
- i, m;
- for (i = 0; i < nbr_cols; i++) {
- for (m = 0; m < this.pivot.measures.length; m++) {
- result.push({
- text:this.pivot.measures[m].string,
- is_bold: add_total && (i === nbr_cols - 1)
- });
- }
- }
- return result;
- },
-
- make_cell: function (row, col, value, index, raw) {
- var formatted_value = raw && !_.isUndefined(value) ? value : openerp.web.format_value(value, {type:this.pivot.measures[index].type}),
- cell = {value:formatted_value};
-
- return cell;
- },
-
- build_rows: function (headers, raw) {
- var self = this,
- pivot = this.pivot,
- m, i, j, k, cell, row;
-
- var rows = [];
- var cells, pivot_cells, values;
-
- var nbr_of_rows = headers.length;
- var col_headers = pivot.get_cols_leaves();
-
- for (i = 0; i < nbr_of_rows; i++) {
- row = headers[i];
- cells = [];
- pivot_cells = [];
- for (j = 0; j < pivot.cells.length; j++) {
- if (pivot.cells[j].x == row.id || pivot.cells[j].y == row.id) {
- pivot_cells.push(pivot.cells[j]);
- }
- }
-
- for (j = 0; j < col_headers.length; j++) {
- values = undefined;
- for (k = 0; k < pivot_cells.length; k++) {
- if (pivot_cells[k].x == col_headers[j].id || pivot_cells[k].y == col_headers[j].id) {
- values = pivot_cells[k].values;
- break;
- }
- }
- if (!values) { values = new Array(pivot.measures.length);}
- for (m = 0; m < pivot.measures.length; m++) {
- cells.push(self.make_cell(row,col_headers[j],values[m], m, raw));
- }
- }
- if (col_headers.length > 1) {
- var totals = pivot.get_total(row);
- for (m = 0; m < pivot.measures.length; m++) {
- cell = self.make_cell(row, pivot.cols.headers[0], totals[m], m, raw);
- cell.is_bold = 'true';
- cells.push(cell);
- }
- }
- rows.push({
- id: row.id,
- indent: row.path.length,
- title: row.title,
- expanded: row.expanded,
- cells: cells,
- });
- }
-
- return rows;
- },
-
- // ----------------------------------------------------------------------
- // Main display method
- // ----------------------------------------------------------------------
- display_data: function () {
- var scroll = $(window).scrollTop();
- this.$('.graph_main_content svg').remove();
- this.$('.graph_main_content div').remove();
- this.table.empty();
- this.$('.graph_options_selection label').last().toggleClass('disabled', this.pivot.no_data);
- 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.$('.graph_header').toggle(this.visible_ui);
- if (this.pivot.no_data) {
- this.$('.graph_main_content').append($(QWeb.render('graph_no_data')));
- } else {
- if (this.mode === 'pivot') {
- this.draw_table();
- $(window).scrollTop(scroll);
- } else {
- this.$('.graph_main_content').append($('<div><svg>'));
- this.svg = this.$('.graph_main_content svg')[0];
- this[this.mode]();
- }
- }
- },
-
- // ----------------------------------------------------------------------
- // Drawing the table
- // ----------------------------------------------------------------------
- draw_table: function () {
- var custom_gbs = this.graph_view.get_custom_filter_groupbys(),
- frozen_rows = custom_gbs.groupby.length,
- frozen_cols = custom_gbs.col_groupby.length;
-
- var table = this.build_table();
- var doc_fragment = $(document.createDocumentFragment());
- this.draw_headers(table.headers, doc_fragment, frozen_cols);
- this.draw_measure_row(table.measure_row, doc_fragment);
- this.draw_rows(table.rows, doc_fragment, frozen_rows);
- this.table.append(doc_fragment);
- },
-
- make_header_cell: function (header, frozen) {
- var cell = (_.has(header, 'cells') ? $('<td>') : $('<th>'))
- .addClass('graph_border')
- .attr('rowspan', header.height)
- .attr('colspan', header.width);
- var $content = $('<span>').attr('href','#')
- .text(' ' + (header.title || _t('Undefined')))
- .css('margin-left', header.indent*30 + 'px')
- .attr('data-id', header.id);
- if (_.has(header, 'expanded')) {
- if (('indent' in header) && header.indent >= frozen) {
- $content.addClass(header.expanded ? 'fa fa-minus-square' : 'fa fa-plus-square');
- $content.addClass('web_graph_click');
- }
- if (!('indent' in header) && header.lvl >= frozen) {
- $content.addClass(header.expanded ? 'fa fa-minus-square' : 'fa fa-plus-square');
- $content.addClass('web_graph_click');
- }
- } else {
- $content.css('font-weight', 'bold');
- }
- return cell.append($content);
- },
-
- draw_headers: function (headers, doc_fragment, frozen_cols) {
- var make_cell = this.make_header_cell,
- $empty_cell = $('<th>').attr('rowspan', headers.length),
- $thead = $('<thead>');
-
- _.each(headers, function (row, lvl) {
- var $row = $('<tr>');
- _.each(row, function (header) {
- header.lvl = lvl;
- $row.append(make_cell(header, frozen_cols));
- });
- $thead.append($row);
- });
- $thead.children(':first').prepend($empty_cell);
- doc_fragment.append($thead);
- this.$thead = $thead;
- },
-
- draw_measure_row: function (measure_row) {
- var $row = $('<tr>').append('<th>');
- _.each(measure_row, function (cell) {
- var $cell = $('<th>').addClass('measure_row').text(cell.text);
- if (cell.is_bold) {$cell.css('font-weight', 'bold');}
- $row.append($cell);
- });
- this.$thead.append($row);
- },
-
- draw_row: function (row, frozen_rows) {
- var $row = $('<tr>')
- .attr('data-indent', row.indent)
- .append(this.make_header_cell(row, frozen_rows));
-
- var cells_length = row.cells.length;
- var cells_list = [];
- var cell, hcell;
-
- for (var j = 0; j < cells_length; j++) {
- cell = row.cells[j];
- hcell = '<td';
- if (cell.is_bold || cell.color) {
- hcell += ' style="';
- if (cell.is_bold) hcell += 'font-weight: bold;';
- if (cell.color) hcell += 'background-color:' + $.Color(255, cell.color, cell.color) + ';';
- hcell += '"';
- }
- hcell += '>' + cell.value + '</td>';
- cells_list[j] = hcell;
- }
- return $row.append(cells_list.join(''));
- },
-
- draw_rows: function (rows, doc_fragment, frozen_rows) {
- var rows_length = rows.length,
- $tbody = $('<tbody>');
-
- doc_fragment.append($tbody);
- for (var i = 0; i < rows_length; i++) {
- $tbody.append(this.draw_row(rows[i], frozen_rows));
- }
- },
-
- // ----------------------------------------------------------------------
- // Drawing charts code
- // ----------------------------------------------------------------------
- bar: function () {
- var self = this,
- dim_x = this.pivot.rows.groupby.length,
- dim_y = this.pivot.cols.groupby.length,
- show_controls = (this.width > 400 && this.height > 300 && dim_x + dim_y >=2),
- data;
-
- // No groupby
- if ((dim_x === 0) && (dim_y === 0)) {
- data = [{key: _t('Total'), values:[{
- x: _t('Total'),
- y: this.pivot.get_total()[0],
- }]}];
- // Only column groupbys
- } else if ((dim_x === 0) && (dim_y >= 1)){
- data = _.map(this.pivot.get_cols_with_depth(1), function (header) {
- return {
- key: header.title,
- values: [{x:header.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)[0],
- title = (pt.title !== undefined) ? pt.title : _t('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 || _t('Undefined'),
- y: self.pivot.get_values(header.id, colhdr.id)[0] || 0
- };
- });
- return {key: colhdr.title || _t('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 || _t('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 === _t('Undefined'))));
- });
- return {
- x: hdr.title || _t('Undefined'),
- y: (subhdr) ? self.pivot.get_total(subhdr)[0] : 0
- };
- });
- return {key:key, values: values};
- });
- }
-
- nv.addGraph(function () {
- var chart = nv.models.multiBarChart()
- .reduceXTicks(false)
- .stacked(self.bar_ui === 'stack')
- .showControls(show_controls);
-
- 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 rows = this.pivot.get_rows_with_depth(dim_x),
- labels = _.pluck(rows, 'title');
-
- var data = _.map(this.pivot.get_cols_leaves(), function (col) {
- var values = _.map(rows, function (row, index) {
- return {x: index, y: self.pivot.get_values(row.id,col.id)[0] || 0};
- });
- var title = _.map(col.path, function (p) {
- return p || _t('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; });
-
- chart.xAxis.tickFormat(function (d,u) {return labels[d];});
-
- 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 || _t('Undefined');
- }).join('/');
- if (dim_x === 0) {
- title = self.measure_label;
- }
- return {x: title, y: self.pivot.get_total(row)[0]};
- });
-
- nv.addGraph(function () {
- var chart = nv.models.pieChart()
- .width(self.width)
- .height(self.height)
- .color(d3.scale.category10().range());
-
- 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;
- });
- },
-
- // ----------------------------------------------------------------------
- // Controller stuff...
- // ----------------------------------------------------------------------
- export_xls: function() {
- var c = openerp.webclient.crashmanager;
- openerp.web.blockUI();
- this.session.get_file({
- url: '/web_graph/export_xls',
- data: {data: JSON.stringify(this.build_table(true))},
- complete: openerp.web.unblockUI,
- error: c.rpc_error.bind(c)
- });
- },
-
-});
-
-// Utility function: returns true if the beginning of array2 is array1 and
-// if array1 is not array2
-function is_strict_beginning_of (array1, array2) {
- if (array1.length >= array2.length) { return false; }
- var result = true;
- for (var i = 0; i < array1.length; i++) {
- if (!_.isEqual(array1[i], array2[i])) { return false;}
- }
- return result;
-}
-})();
diff --git a/addons/web_graph/static/src/js/pivot_table.js b/addons/web_graph/static/src/js/pivot_table.js
deleted file mode 100644
index a99bae1756f..00000000000
--- a/addons/web_graph/static/src/js/pivot_table.js
+++ /dev/null
@@ -1,468 +0,0 @@
-
-/* jshint undef: false */
-
-(function () {
-'use strict';
-
-var _lt = openerp.web._lt;
-var _t = openerp.web._t;
-
-// PivotTable requires a call to update_data after initialization
-openerp.web_graph.PivotTable = openerp.web.Class.extend({
-
- init: function (model, domain, fields, options) {
- this.cells = [];
- this.domain = domain;
- this.context = options.context;
- this.no_data = true;
- this.updating = false;
- this.model = model;
- this.fields = fields;
- this.fields.__count = {type: 'integer', string:_t('Count')};
- this.measures = options.measures || [];
- this.rows = { groupby: options.row_groupby, headers: null };
- this.cols = { groupby: options.col_groupby, headers: null };
- },
-
- // ----------------------------------------------------------------------
- // 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:_}
- // If its type is date/datetime, field can have the corresponding interval in its description,
- // for example 'create_date:week'.
- set_measures: function (measures) {
- this.measures = measures;
- return this.update_data();
- },
-
- toggle_measure: function (measure) {
- var current_measure = _.findWhere(this.measures, measure);
- if (current_measure) { // remove current_measure
- var index = this.measures.indexOf(current_measure);
- this.measures = _.without(this.measures, current_measure);
- if (this.measures.length === 0) {
- this.no_data = true;
- } else {
- _.each(this.cells, function (cell) {
- cell.values.splice(index, 1);
- });
- }
- return $.Deferred().resolve();
- } else { // add a new measure
- this.measures.push(measure);
- return this.update_data();
- }
- },
-
- set: function (domain, row_groupby, col_groupby, measures_groupby) {
- var self = this;
- if (this.updating) {
- return this.updating.then(function () {
- self.updating = false;
- return self.set(domain, row_groupby, col_groupby, measures_groupby);
- });
- }
- var row_gb_changed = !_.isEqual(row_groupby, this.rows.groupby),
- col_gb_changed = !_.isEqual(col_groupby, this.cols.groupby),
- measures_gb_changed = !_.isEqual(measures_groupby, this.measures);
-
- this.domain = domain;
- this.rows.groupby = row_groupby;
- this.cols.groupby = col_groupby;
-
- if (measures_groupby.length) { this.measures = measures_groupby; }
-
- if (row_gb_changed) { this.rows.headers = null; }
- if (col_gb_changed) { this.cols.headers = null; }
- if (measures_gb_changed && measures_groupby.length) { this.set_measures(measures_groupby); }
-
- return this.update_data();
- },
-
- // ----------------------------------------------------------------------
- // 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 cells = this.cells,
- x = Math.min(id1, id2),
- y = Math.max(id1, id2);
- for (var i = 0; i < cells.length; i++) {
- if (cells[i].x == x && cells[i].y == y) {
- return cells[i].values;
- }
- }
- return (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 !!_.findWhere(this.rows.headers, {id:id});
- },
-
- is_col: function (id) {
- return !!_.findWhere(this.cols.headers, {id:id});
- },
-
- get_header: function (id) {
- return _.findWhere(this.rows.headers.concat(this.cols.headers), {id:id});
- },
-
- _get_headers_with_depth: function (headers, depth) {
- return _.filter(headers, function (header) {
- return header.path.length === depth;
- });
- },
-
- // return all columns with a path length of 'depth'
- get_cols_with_depth: function (depth) {
- return this._get_headers_with_depth(this.cols.headers, depth);
- },
-
- // return all rows with a path length of 'depth'
- get_rows_with_depth: function (depth) {
- return this._get_headers_with_depth(this.rows.headers, depth);
- },
-
- get_ancestor_leaves: function (header) {
- return _.where(this.get_ancestors_and_self(header), {expanded:false});
- },
-
- // return all non expanded rows
- get_rows_leaves: function () {
- return _.where(this.rows.headers, {expanded:false});
- },
-
- // return all non expanded cols
- get_cols_leaves: function () {
- return _.where(this.cols.headers, {expanded:false});
- },
-
- 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) {
- return (header) ? this.get_values(header.id, this.get_other_root(header).headers[0].id)
- : 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
- // ----------------------------------------------------------------------
- // return true if the folding changed the groupbys, false if not
- 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(_.pluck(_.pluck(header.root.headers, 'path'), 'length'));
- if (new_groupby_length < header.root.groupby.length) {
- header.root.groupby.splice(new_groupby_length);
- return true;
- }
- return false;
- },
-
- fold_with_depth: function (root, depth) {
- var self = this;
- _.each(this._get_headers_with_depth(root.headers, depth), function (header) {
- self.fold(header);
- });
- },
-
- expand_all: function () {
- this.rows.headers = null;
- this.cols.headers = null;
- return this.update_data();
- },
-
- expand: function (header_id, groupby) {
- var self = this,
- header = this.get_header(header_id),
- other_root = this.get_other_root(header),
- this_gb = [groupby.field],
- other_gbs = _.pluck(other_root.groupby, 'field');
-
- if (header.path.length === header.root.groupby.length) {
- header.root.groupby.push(groupby);
- }
- return this.perform_requests(this_gb, other_gbs, header.domain).then(function () {
- var data = Array.prototype.slice.call(arguments).slice(other_gbs.length + 1);
- _.each(data, function (data_pt) {
- self.make_headers_and_cell(
- data_pt, header.root.headers, other_root.headers, 1, header.path, true);
- });
- header.expanded = true;
- header.children.forEach(function (child) {
- child.expanded = false;
- child.root = header.root;
- });
- });
- },
-
- swap_axis: function () {
- var temp = this.rows;
- this.rows = this.cols;
- this.cols = temp;
- },
-
- // ----------------------------------------------------------------------
- // Data updating methods
- // ----------------------------------------------------------------------
- // 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;
- this.updating = this.perform_requests().then (function () {
- var data = Array.prototype.slice.call(arguments);
- self.no_data = !data[0].length;
- if (self.no_data) {
- return;
- }
- var row_headers = [],
- col_headers = [];
- self.cells = [];
-
- var dim_col = self.cols.groupby.length,
- i, j, index;
-
- for (i = 0; i < self.rows.groupby.length + 1; i++) {
- for (j = 0; j < dim_col + 1; j++) {
- index = i*(dim_col + 1) + j;
- self.make_headers_and_cell(data[index], row_headers, col_headers, i);
- }
- }
- self.set_headers(row_headers, self.rows);
- self.set_headers(col_headers, self.cols);
- });
- return this.updating;
- },
-
- make_headers_and_cell: function (data_pts, row_headers, col_headers, index, prefix, expand) {
- var self = this;
- data_pts.forEach(function (data_pt) {
- var row_value = (prefix || []).concat(data_pt.attributes.value.slice(0,index));
- var col_value = data_pt.attributes.value.slice(index);
-
- if (expand && !_.find(col_headers, function (hdr) {return self.isEqual(col_value, hdr.path);})) {
- return;
- }
- var row = self.find_or_create_header(row_headers, row_value, data_pt);
- var col = self.find_or_create_header(col_headers, col_value, data_pt);
-
- var cell_value = _.map(self.measures, function (m) {
- return data_pt.attributes.aggregates[m.field];
- });
- self.cells.push({
- x: Math.min(row.id, col.id),
- y: Math.max(row.id, col.id),
- values: cell_value
- });
- });
- },
-
- make_header: function (values) {
- return _.extend({
- children: [],
- domain: this.domain,
- expanded: undefined,
- id: _.uniqueId(),
- path: [],
- root: undefined,
- title: undefined
- }, values || {});
- },
-
- find_or_create_header: function (headers, path, data_pt) {
- var self = this;
- var hdr = _.find(headers, function (header) {
- return self.isEqual(path, header.path);
- });
- if (hdr) {
- return hdr;
- }
- if (!path.length) {
- hdr = this.make_header({title: _t('Total')});
- headers.push(hdr);
- return hdr;
- }
- hdr = this.make_header({
- path:path,
- domain:data_pt.model._domain,
- title: _t(_.last(path))
- });
- var parent = _.find(headers, function (header) {
- return self.isEqual(header.path, _.initial(path, 1));
- });
-
- var previous = parent.children.length ? _.last(parent.children) : parent;
- headers.splice(headers.indexOf(previous) + 1, 0, hdr);
- parent.children.push(hdr);
- return hdr;
- },
-
- perform_requests: function (group1, group2, domain) {
- var self = this,
- requests = [],
- row_gbs = _.pluck(this.rows.groupby, 'field'),
- col_gbs = _.pluck(this.cols.groupby, 'field'),
- field_list = row_gbs.concat(col_gbs, _.pluck(this.measures, 'field')),
- fields = field_list.map(function (f) { return self.raw_field(f); });
-
- group1 = group1 || row_gbs;
- group2 = group2 || col_gbs;
-
- var i,j, groupbys;
- for (i = 0; i < group1.length + 1; i++) {
- for (j = 0; j < group2.length + 1; j++) {
- groupbys = group1.slice(0,i).concat(group2.slice(0,j));
- requests.push(self.get_groups(groupbys, fields, domain || self.domain));
- }
- }
- return $.when.apply(null, requests);
- },
-
- // set the 'expanded' status of new_headers more or less like root.headers, with root as root
- set_headers: function(new_headers, root) {
- var self = this;
- if (root.headers) {
- _.each(root.headers, function (header) {
- var corresponding_header = _.find(new_headers, function (h) {
- return self.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;
- corresponding_header.children = [];
- }
- });
- var updated_headers = _.filter(new_headers, function (header) {
- return (header.expanded !== undefined);
- });
- _.each(updated_headers, function (header) {
- header.root = root;
- });
- root.headers = updated_headers;
- } else {
- root.headers = new_headers;
- _.each(root.headers, function (header) {
- header.root = root;
- header.expanded = (header.children.length > 0);
- });
- }
- return new_headers;
- },
-
- get_groups: function (groupbys, fields, domain) {
- var self = this;
- return this.model.query(_.without(fields, '__count'))
- .filter(domain)
- .context(this.context)
- .lazy(false)
- .group_by(groupbys)
- .then(function (groups) {
- return groups.filter(function (group) {
- return group.attributes.length > 0;
- }).map(function (group) {
- var attrs = group.attributes,
- grouped_on = attrs.grouped_on instanceof Array ? attrs.grouped_on : [attrs.grouped_on],
- raw_grouped_on = grouped_on.map(function (f) {
- return self.raw_field(f);
- });
- if (grouped_on.length === 1) {
- attrs.value = [attrs.value];
- }
- attrs.value = _.range(grouped_on.length).map(function (i) {
- var grp = grouped_on[i],
- field = self.fields[grp];
- if (attrs.value[i] === false) {
- return _t('Undefined');
- } else if (attrs.value[i] instanceof Array) {
- return attrs.value[i][1];
- } else if (field && field.type === 'selection') {
- var selected = _.where(field.selection, {0: attrs.value[i]})[0];
- return selected ? selected[1] : attrs.value[i];
- }
- return attrs.value[i];
- });
- attrs.aggregates.__count = group.attributes.length;
- attrs.grouped_on = raw_grouped_on;
- return group;
- });
- });
- },
-
- // if field is a fieldname, returns field, if field is field_id:interval, retuns field_id
- raw_field: function (field) {
- return field.split(':')[0];
- },
-
- isEqual: function (path1, path2) {
- if (path1.length !== path2.length) { return false; }
- for (var i = 0; i < path1.length; i++) {
- if (path1[i] !== path2[i]) {
- return false;
- }
- }
- return true;
- },
-
-});
-
-})();
diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml
deleted file mode 100644
index 70bcf328d68..00000000000
--- a/addons/web_graph/static/src/xml/web_graph.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<templates>
-
- <t t-name="graph-view-buttons">
- <div class="btn-group btn-group-sm">
- <button class="btn btn-default fa fa-table oe-pivot-mode" title="Pivot Table"></button>
- <button class="btn btn-default fa fa-bar-chart-o oe-bar-mode" title="Bar Chart"></button>
- <button class="btn btn-default fa fa-line-chart oe-line-mode" title="Line Chart"></button>
- <button class="btn btn-default fa fa-pie-chart oe-pie-mode" title="Pie Chart"></button>
- </div>
- <div class="btn-group btn-group-sm">
- <button class="btn btn-default fa fa-expand oe-pivot" title="Flip columns and rows"></button>
- <button class="btn btn-default fa fa-arrows-alt oe-pivot" title="Expand"></button>
- <button class="btn btn-default fa fa-download oe-pivot" title="Download Data"></button>
- </div>
- <div class="btn-group btn-group-sm">
- <button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
- Measures <span class="caret"/>
- </button>
- <ul class="oe-measure-list dropdown-menu"/>
- </div>
- </t>
- <div t-name="GraphWidget" class="graph_widget">
- <div class="graph_main_content"></div>
- </div>
-
- <div t-name="field_selection" class="dropdown">
- <span class="btn btn-default field-selection dropdown-toggle" data-toggle="dropdown"></span>
- <ul class="dropdown-menu multi-level" role="menu">
- <t t-foreach="fields" t-as="field">
- <t t-if="(field.type === 'date') || (field.type === 'datetime')">
- <li class="graph-dropdown-submenu">
- <a class="field-selection" t-att-data-field-id="field.id" t-att-data-id="header_id" t-att-data-interval="'month'" href="#">
- <t t-esc="field.value"/>
- </a>
- <ul class="dropdown-menu">
- <li><a href="#" class="field-selection" t-att-data-field-id="field.id" t-att-data-id="header_id" t-att-data-interval="'day'">Day</a></li>
- <li><a href="#" class="field-selection" t-att-data-field-id="field.id" t-att-data-id="header_id" t-att-data-interval="'week'">Week</a></li>
- <li><a href="#" class="field-selection" t-att-data-field-id="field.id" t-att-data-id="header_id" t-att-data-interval="'month'">Month</a></li>
- <li><a href="#" class="field-selection" t-att-data-field-id="field.id" t-att-data-id="header_id" t-att-data-interval="'quarter'">Quarter</a></li>
- <li><a href="#" class="field-selection" t-att-data-field-id="field.id" t-att-data-id="header_id" t-att-data-interval="'year'">Year</a></li>
- </ul>
- </li>
- </t>
-
- <t t-if="(field.type !== 'date') &amp;&amp; (field.type !== 'datetime')">
- <li>
- <a class="field-selection" t-att-data-field-id="field.id" t-att-data-id="header_id" href="#">
- <t t-esc="field.value"/>
- </a>
- </li>
- </t>
- </t>
- </ul>
- </div>
-
- <div t-name="graph_no_data" class="oe_view_nocontent" >
- <div class="oe_empty_custom_dashboard">
- <p><b>No data to display.</b></p>
- <p>
- No data available for this graph. Try to add some records, or make sure
- that there is at least one measure and no active filter in the search bar.
- </p>
- </div>
- </div>
-</templates>