[MIG] kpi_dashboard: migration to 13.0
parent
de5a435343
commit
c708de0679
|
@ -5,11 +5,11 @@
|
||||||
"name": "Kpi Dashboard",
|
"name": "Kpi Dashboard",
|
||||||
"summary": """
|
"summary": """
|
||||||
Create Dashboards using kpis""",
|
Create Dashboards using kpis""",
|
||||||
"version": "12.0.1.3.0",
|
"version": "13.0.1.0.0",
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"author": "Creu Blanca,Odoo Community Association (OCA)",
|
"author": "Creu Blanca,Odoo Community Association (OCA)",
|
||||||
"website": "https://github.com/OCA/reporting-engine",
|
"website": "https://github.com/OCA/reporting-engine",
|
||||||
"depends": ["bus", "board", "base_sparse_field", "web_widget_color"],
|
"depends": ["bus", "board", "base_sparse_field"],
|
||||||
"qweb": ["static/src/xml/dashboard.xml"],
|
"qweb": ["static/src/xml/dashboard.xml"],
|
||||||
"data": [
|
"data": [
|
||||||
"wizards/kpi_dashboard_menu.xml",
|
"wizards/kpi_dashboard_menu.xml",
|
||||||
|
|
|
@ -134,7 +134,6 @@ class KpiKpi(models.Model):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
self.cron_id = self.env["ir.cron"].create(self._cron_vals())
|
self.cron_id = self.env["ir.cron"].create(self._cron_vals())
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def write(self, vals):
|
def write(self, vals):
|
||||||
if "value" in vals:
|
if "value" in vals:
|
||||||
vals["value_last_update"] = fields.Datetime.now()
|
vals["value_last_update"] = fields.Datetime.now()
|
||||||
|
@ -165,8 +164,10 @@ class KpiKpi(models.Model):
|
||||||
)
|
)
|
||||||
results = self._get_code_input_dict()
|
results = self._get_code_input_dict()
|
||||||
savepoint = "kpi_formula_%s" % self.id
|
savepoint = "kpi_formula_%s" % self.id
|
||||||
|
# pylint: disable=E8103
|
||||||
self.env.cr.execute("savepoint %s" % savepoint)
|
self.env.cr.execute("savepoint %s" % savepoint)
|
||||||
safe_eval(self.code or "", results, mode="exec", nocopy=True)
|
safe_eval(self.code or "", results, mode="exec", nocopy=True)
|
||||||
|
# pylint: disable=E8103
|
||||||
self.env.cr.execute("rollback to %s" % savepoint)
|
self.env.cr.execute("rollback to %s" % savepoint)
|
||||||
return results.get("result", {})
|
return results.get("result", {})
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,427 @@
|
||||||
|
/* nvd3 version 1.8.2-dev (https://github.com/novus/nvd3) 2016-02-08 */
|
||||||
|
.nvd3 .nv-axis {
|
||||||
|
pointer-events:none;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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
|
||||||
|
}
|
||||||
|
|
||||||
|
.nvd3 .nv-axis.nv-disabled {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* scatter */
|
||||||
|
.nvd3 .nv-groups .nv-point.hover {
|
||||||
|
stroke-width: 20px;
|
||||||
|
stroke-opacity: .5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nvd3 .nv-scatter .nv-point.hover {
|
||||||
|
fill-opacity: 1;
|
||||||
|
}
|
||||||
|
.nv-noninteractive {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nv-distx, .nv-disty {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.nvtooltip {
|
||||||
|
position: absolute;
|
||||||
|
background-color: rgba(255,255,255,1.0);
|
||||||
|
color: rgba(0,0,0,1.0);
|
||||||
|
padding: 1px;
|
||||||
|
border: 1px solid rgba(0,0,0,.2);
|
||||||
|
z-index: 10000;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nvtooltip {
|
||||||
|
background: rgba(255,255,255, 0.8);
|
||||||
|
border: 1px solid rgba(0,0,0,0.5);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*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 50ms linear;
|
||||||
|
-moz-transition: opacity 50ms linear;
|
||||||
|
-webkit-transition: opacity 50ms linear;
|
||||||
|
|
||||||
|
transition-delay: 200ms;
|
||||||
|
-moz-transition-delay: 200ms;
|
||||||
|
-webkit-transition-delay: 200ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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);
|
||||||
|
color: rgba(0,0,0,1.0);
|
||||||
|
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.key.total {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.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 table td.legend-color-guide div {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border: 1px solid #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nvtooltip .footer {
|
||||||
|
padding: 3px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nvtooltip-pending-removal {
|
||||||
|
pointer-events: none;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****
|
||||||
|
Interactive Layer
|
||||||
|
*/
|
||||||
|
.nvd3 .nv-interactiveGuideLine {
|
||||||
|
pointer-events:none;
|
||||||
|
}
|
||||||
|
.nvd3 line.nv-guideline {
|
||||||
|
stroke: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nvd3 .nv-bars rect {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.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-candlestickBar .nv-ticks 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nvd3 .nv-groups path.nv-line {
|
||||||
|
fill: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nvd3 .nv-groups path.nv-area {
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************
|
||||||
|
* SVG CSS
|
||||||
|
*/
|
||||||
|
|
||||||
|
/********************
|
||||||
|
Default CSS for an svg element nvd3 used
|
||||||
|
*/
|
||||||
|
svg.nvd3-svg {
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
display: block;
|
||||||
|
width:100%;
|
||||||
|
height:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************
|
||||||
|
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: 5px;
|
||||||
|
-moz-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.nvd3 text {
|
||||||
|
font: normal 12px Arial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nvd3 .title {
|
||||||
|
font: bold 14px Arial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nvd3 .nv-background {
|
||||||
|
fill: white;
|
||||||
|
fill-opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nvd3.nv-noData {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********
|
||||||
|
* Brush
|
||||||
|
*/
|
||||||
|
|
||||||
|
.nv-brush .extent {
|
||||||
|
fill-opacity: .125;
|
||||||
|
shape-rendering: crispEdges;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nv-brush .resize path {
|
||||||
|
fill: #eee;
|
||||||
|
stroke: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********
|
||||||
|
* Legend
|
||||||
|
*/
|
||||||
|
|
||||||
|
.nvd3 .nv-legend .nv-series {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nvd3 .nv-legend .nv-disabled circle {
|
||||||
|
fill-opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* focus */
|
||||||
|
.nvd3 .nv-brush .extent {
|
||||||
|
fill-opacity: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nvd3 .nv-brushBackground rect {
|
||||||
|
stroke: #000;
|
||||||
|
stroke-width: .4;
|
||||||
|
fill: #fff;
|
||||||
|
fill-opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.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-pie-title {
|
||||||
|
font-size: 24px;
|
||||||
|
fill: rgba(19, 196, 249, 0.59);
|
||||||
|
}
|
||||||
|
|
||||||
|
.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 path {
|
||||||
|
fill-opacity: .7;
|
||||||
|
}
|
||||||
|
.nvd3.nv-pie .hover path {
|
||||||
|
fill-opacity: 1;
|
||||||
|
}
|
||||||
|
.nvd3.nv-pie .nv-label {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.nvd3.nv-pie .nv-label rect {
|
||||||
|
fill-opacity: 0;
|
||||||
|
stroke-opacity: 0;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,6 @@
|
||||||
|
/*
|
||||||
|
global py
|
||||||
|
*/
|
||||||
odoo.define("kpi_dashboard.DashboardController", function(require) {
|
odoo.define("kpi_dashboard.DashboardController", function(require) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
@ -20,7 +23,7 @@ odoo.define("kpi_dashboard.DashboardController", function(require) {
|
||||||
add_modify_color: "_addModifyColor",
|
add_modify_color: "_addModifyColor",
|
||||||
refresh_colors: "_refreshColors",
|
refresh_colors: "_refreshColors",
|
||||||
}),
|
}),
|
||||||
_refreshOnFly: function(event) {
|
_refreshOnFly: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
this._rpc({
|
this._rpc({
|
||||||
model: this.modelName,
|
model: this.modelName,
|
||||||
|
@ -37,12 +40,14 @@ odoo.define("kpi_dashboard.DashboardController", function(require) {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
renderPager: function($node, options) {
|
renderPager: function($node, options) {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
options = _.extend({}, options, {
|
options = _.extend({}, options, {
|
||||||
validate: this.canBeDiscarded.bind(this),
|
validate: this.canBeDiscarded.bind(this),
|
||||||
});
|
});
|
||||||
this._super($node, options);
|
this._super($node, options);
|
||||||
},
|
},
|
||||||
_pushState: function(state) {
|
_pushState: function(state) {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
state = state || {};
|
state = state || {};
|
||||||
var env = this.model.get(this.handle, {env: true});
|
var env = this.model.get(this.handle, {env: true});
|
||||||
state.id = env.currentId;
|
state.id = env.currentId;
|
||||||
|
|
|
@ -4,7 +4,7 @@ odoo.define("kpi_dashboard.DashboardModel", function(require) {
|
||||||
var BasicModel = require("web.BasicModel");
|
var BasicModel = require("web.BasicModel");
|
||||||
|
|
||||||
var DashboardModel = BasicModel.extend({
|
var DashboardModel = BasicModel.extend({
|
||||||
_fetchRecord: function(record, options) {
|
_fetchRecord: function(record) {
|
||||||
return this._rpc({
|
return this._rpc({
|
||||||
model: record.model,
|
model: record.model,
|
||||||
method: "read_dashboard",
|
method: "read_dashboard",
|
||||||
|
|
|
@ -4,7 +4,6 @@ odoo.define("kpi_dashboard.DashboardRenderer", function(require) {
|
||||||
var BasicRenderer = require("web.BasicRenderer");
|
var BasicRenderer = require("web.BasicRenderer");
|
||||||
var core = require("web.core");
|
var core = require("web.core");
|
||||||
var registry = require("kpi_dashboard.widget_registry");
|
var registry = require("kpi_dashboard.widget_registry");
|
||||||
var BusService = require("bus.BusService");
|
|
||||||
var qweb = core.qweb;
|
var qweb = core.qweb;
|
||||||
|
|
||||||
var DashboardRenderer = BasicRenderer.extend({
|
var DashboardRenderer = BasicRenderer.extend({
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
global nv
|
||||||
|
*/
|
||||||
|
odoo.define("web.nvd3.extensions", function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The nvd3 library extensions and fixes should be done here to avoid patching
|
||||||
|
* in place.
|
||||||
|
*/
|
||||||
|
|
||||||
|
nv.dev = false;
|
||||||
|
// Sets nvd3 library in production mode
|
||||||
|
|
||||||
|
// monkey patch nvd3 to allow removing eventhandler on windowresize events
|
||||||
|
// see https://github.com/novus/nvd3/pull/396 for more details
|
||||||
|
|
||||||
|
// Adds a resize listener to the window.
|
||||||
|
nv.utils.onWindowResize = function(fun) {
|
||||||
|
if (fun === null) return;
|
||||||
|
window.addEventListener("resize", fun);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Backwards compatibility with current API.
|
||||||
|
nv.utils.windowResize = nv.utils.onWindowResize;
|
||||||
|
|
||||||
|
// Removes a resize listener from the window.
|
||||||
|
nv.utils.offWindowResize = function(fun) {
|
||||||
|
if (fun === null) return;
|
||||||
|
window.removeEventListener("resize", fun);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Monkey patch nvd3 to prevent crashes when user changes view and nvd3
|
||||||
|
// tries to remove tooltips after 500 ms... seriously nvd3, what were you
|
||||||
|
// thinking?
|
||||||
|
nv.tooltip.cleanup = function() {
|
||||||
|
$(".nvtooltip").remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Monkey patch nvd3 to prevent it to display a tooltip (position: absolute)
|
||||||
|
// with a negative `top`; with this patch the highest tooltip's position is
|
||||||
|
// still in the graph
|
||||||
|
var originalCalcTooltipPosition = nv.tooltip.calcTooltipPosition;
|
||||||
|
nv.tooltip.calcTooltipPosition = function() {
|
||||||
|
var container = originalCalcTooltipPosition.apply(this, arguments);
|
||||||
|
container.style.top =
|
||||||
|
container.style.top.split("px")[0] < 0 ? 0 + "px" : container.style.top;
|
||||||
|
return container;
|
||||||
|
};
|
||||||
|
});
|
|
@ -7,9 +7,12 @@ odoo.define("kpi_dashboard.AbstractWidget", function(require) {
|
||||||
var registry = require("kpi_dashboard.widget_registry");
|
var registry = require("kpi_dashboard.widget_registry");
|
||||||
|
|
||||||
var AbstractWidget = Widget.extend({
|
var AbstractWidget = Widget.extend({
|
||||||
template: "kpi_dashboard.base_widget", // Template used by the widget
|
// Template used by the widget
|
||||||
cssLibs: [], // Specific css of the widget
|
template: "kpi_dashboard.base_widget",
|
||||||
jsLibs: [], // Specific Javascript libraries of the widget
|
// Specific css of the widget
|
||||||
|
cssLibs: [],
|
||||||
|
// Specific Javascript libraries of the widget
|
||||||
|
jsLibs: [],
|
||||||
events: {
|
events: {
|
||||||
"click .o_kpi_dashboard_toggle_button": "_onClickToggleButton",
|
"click .o_kpi_dashboard_toggle_button": "_onClickToggleButton",
|
||||||
"click .direct_action": "_onClickDirectAction",
|
"click .direct_action": "_onClickDirectAction",
|
||||||
|
|
|
@ -3,7 +3,6 @@ odoo.define("kpi_dashboard.CounterWidget", function(require) {
|
||||||
|
|
||||||
var IntegerWidget = require("kpi_dashboard.IntegerWidget");
|
var IntegerWidget = require("kpi_dashboard.IntegerWidget");
|
||||||
var registry = require("kpi_dashboard.widget_registry");
|
var registry = require("kpi_dashboard.widget_registry");
|
||||||
var field_utils = require("web.field_utils");
|
|
||||||
|
|
||||||
var CounterWidget = IntegerWidget.extend({
|
var CounterWidget = IntegerWidget.extend({
|
||||||
shortList: [],
|
shortList: [],
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/*
|
||||||
|
global nv, d3
|
||||||
|
*/
|
||||||
odoo.define("kpi_dashboard.GraphWidget", function(require) {
|
odoo.define("kpi_dashboard.GraphWidget", function(require) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
@ -9,11 +12,11 @@ odoo.define("kpi_dashboard.GraphWidget", function(require) {
|
||||||
var GraphWidget = AbstractWidget.extend({
|
var GraphWidget = AbstractWidget.extend({
|
||||||
template: "kpi_dashboard.graph",
|
template: "kpi_dashboard.graph",
|
||||||
jsLibs: [
|
jsLibs: [
|
||||||
"/web/static/lib/nvd3/d3.v3.js",
|
"/kpi_dashboard/static/lib/nvd3/d3.v3.js",
|
||||||
"/web/static/lib/nvd3/nv.d3.js",
|
"/kpi_dashboard/static/lib/nvd3/nv.d3.js",
|
||||||
"/web/static/src/js/libs/nvd3.js",
|
"/kpi_dashboard/static/src/js/lib/nvd3.js",
|
||||||
],
|
],
|
||||||
cssLibs: ["/web/static/lib/nvd3/nv.d3.css"],
|
cssLibs: ["/kpi_dashboard/static/lib/nvd3/nv.d3.css"],
|
||||||
start: function() {
|
start: function() {
|
||||||
this._onResize = this._onResize.bind(this);
|
this._onResize = this._onResize.bind(this);
|
||||||
nv.utils.windowResize(this._onResize);
|
nv.utils.windowResize(this._onResize);
|
||||||
|
@ -28,7 +31,7 @@ odoo.define("kpi_dashboard.GraphWidget", function(require) {
|
||||||
}
|
}
|
||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
},
|
},
|
||||||
_getChartOptions: function(values) {
|
_getChartOptions: function() {
|
||||||
return {
|
return {
|
||||||
x: function(d, u) {
|
x: function(d, u) {
|
||||||
return u;
|
return u;
|
||||||
|
|
|
@ -18,16 +18,17 @@ odoo.define("kpi_dashboard.IntegerWidget", function(require) {
|
||||||
var suffix = "";
|
var suffix = "";
|
||||||
var shortened = false;
|
var shortened = false;
|
||||||
var digits = this.digits;
|
var digits = this.digits;
|
||||||
|
var result = num;
|
||||||
_.each(this.shortList, function(shortItem) {
|
_.each(this.shortList, function(shortItem) {
|
||||||
if (!shortened && Math.abs(num) >= shortItem[0]) {
|
if (!shortened && Math.abs(num) >= shortItem[0]) {
|
||||||
shortened = true;
|
shortened = true;
|
||||||
suffix = shortItem[1];
|
suffix = shortItem[1];
|
||||||
num /= shortItem[0];
|
result /= shortItem[0];
|
||||||
digits = shortItem[2];
|
digits = shortItem[2];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
field_utils.format.float(num, false, {
|
field_utils.format.float(result, false, {
|
||||||
digits: digits,
|
digits: digits,
|
||||||
}) + suffix
|
}) + suffix
|
||||||
);
|
);
|
||||||
|
|
|
@ -21,8 +21,8 @@ odoo.define("kpi_dashboard.MeterWidget", function(require) {
|
||||||
style: "Arch",
|
style: "Arch",
|
||||||
width: 10,
|
width: 10,
|
||||||
size: size,
|
size: size,
|
||||||
prepend: values.prefix !== undefined ? values.prefix : "",
|
prepend: values.prefix === undefined ? "" : values.prefix,
|
||||||
append: values.suffix !== undefined ? values.suffix : "",
|
append: values.suffix === undefined ? "" : values.suffix,
|
||||||
color: values.font_color,
|
color: values.font_color,
|
||||||
animate_text_colors: true,
|
animate_text_colors: true,
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,7 @@ class TestFormula(TransactionCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.kpi = self.env["kpi.kpi"].create(
|
self.kpi = self.env["kpi.kpi"].create(
|
||||||
{"name": "DEMO KPI", "widget": "number", "computation_method": "code",}
|
{"name": "DEMO KPI", "widget": "number", "computation_method": "code"}
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_forbidden_words_01(self):
|
def test_forbidden_words_01(self):
|
||||||
|
@ -45,8 +45,7 @@ result = {{}}
|
||||||
result['value'] = len(model.search([('id', '=', {})]))
|
result['value'] = len(model.search([('id', '=', {})]))
|
||||||
result['previous'] = len(model.search([('id', '!=', {})]))
|
result['previous'] = len(model.search([('id', '!=', {})]))
|
||||||
""".format(
|
""".format(
|
||||||
self.kpi.id,
|
self.kpi.id, self.kpi.id,
|
||||||
self.kpi.id,
|
|
||||||
)
|
)
|
||||||
self.kpi.compute()
|
self.kpi.compute()
|
||||||
value = self.kpi.value
|
value = self.kpi.value
|
||||||
|
@ -66,8 +65,7 @@ result = {{}}
|
||||||
result['value'] = len(model.search([('id', '=', {})]))
|
result['value'] = len(model.search([('id', '=', {})]))
|
||||||
result['previous'] = len(model.search([('id', '!=', {})]))
|
result['previous'] = len(model.search([('id', '!=', {})]))
|
||||||
""".format(
|
""".format(
|
||||||
self.kpi.id,
|
self.kpi.id, self.kpi.id,
|
||||||
self.kpi.id,
|
|
||||||
)
|
)
|
||||||
self.kpi.compute()
|
self.kpi.compute()
|
||||||
value = self.kpi.value
|
value = self.kpi.value
|
||||||
|
|
|
@ -53,16 +53,18 @@ class TestKpiDashboard(TransactionCase):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.env["kpi.dashboard.item"].create(
|
self.env["kpi.dashboard.item"].create(
|
||||||
{"dashboard_id": self.dashboard.id, "name": "TITLE", "row": 2, "column": 1,}
|
{"dashboard_id": self.dashboard.id, "name": "TITLE", "row": 2, "column": 1}
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_constrains_01(self):
|
def test_constrains_01(self):
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
self.kpi_01.dashboard_item_ids.write({"size_x": 2})
|
self.kpi_01.dashboard_item_ids.write({"size_x": 2})
|
||||||
|
self.kpi_01.flush()
|
||||||
|
|
||||||
def test_constrains_02(self):
|
def test_constrains_02(self):
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
self.kpi_02.dashboard_item_ids.write({"size_x": 4})
|
self.kpi_02.dashboard_item_ids.write({"size_x": 4})
|
||||||
|
self.kpi_01.flush()
|
||||||
|
|
||||||
def test_constrains_03(self):
|
def test_constrains_03(self):
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Copyright 2020 Creu Blanca
|
# Copyright 2020 Creu Blanca
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from odoo import api, fields, models
|
from odoo import fields, models
|
||||||
|
|
||||||
|
|
||||||
class KpiDashboardMenu(models.TransientModel):
|
class KpiDashboardMenu(models.TransientModel):
|
||||||
|
@ -12,6 +12,5 @@ class KpiDashboardMenu(models.TransientModel):
|
||||||
dashboard_id = fields.Many2one("kpi.dashboard", required=True)
|
dashboard_id = fields.Many2one("kpi.dashboard", required=True)
|
||||||
menu_id = fields.Many2one("ir.ui.menu")
|
menu_id = fields.Many2one("ir.ui.menu")
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def generate_menu(self):
|
def generate_menu(self):
|
||||||
self.dashboard_id._generate_menu(self.menu_id)
|
self.dashboard_id._generate_menu(self.menu_id)
|
||||||
|
|
Loading…
Reference in New Issue