From 13ea439bb202e805155d4fa3d828eab9b720fb8c Mon Sep 17 00:00:00 2001 From: Nicolas Mac Rouillon Date: Tue, 13 Dec 2016 15:04:14 -0300 Subject: [PATCH] FIX --- web_dashboard_tile/README.rst | 50 ++--- web_dashboard_tile/__init__.py | 27 +-- web_dashboard_tile/__openerp__.py | 14 +- web_dashboard_tile/models/__init__.py | 24 +-- web_dashboard_tile/models/tile_tile.py | 175 ++---------------- web_dashboard_tile/static/src/css/tile.css | 39 +--- web_dashboard_tile/static/src/js/custom_js.js | 8 +- .../static/src/xml/custom_xml.xml | 4 +- web_dashboard_tile/views/templates.xml | 2 +- web_dashboard_tile/views/tile.xml | 6 +- 10 files changed, 63 insertions(+), 286 deletions(-) diff --git a/web_dashboard_tile/README.rst b/web_dashboard_tile/README.rst index 0337037b..523dcadb 100644 --- a/web_dashboard_tile/README.rst +++ b/web_dashboard_tile/README.rst @@ -1,19 +1,6 @@ -Add Tiles to Dashboard -====================== - -<<<<<<< HEAD -module to give you a dashboard where you can configure tile from any view -and add them as short cut. - -* Tile can be: - * displayed only for a user; - * global for all users (In that case, some tiles will be hidden if - the current user doesn't have access to the given model); -* The tile displays items count of a given model restricted to a given domain; -* Optionnaly, the tile can display the result of a function of a field; - * Function is one of sum/avg/min/max/median; - * Field must be integer or float; -======= +Dashboard Tiles +=============== + Adds a dashboard where you can configure tiles from any view and add them as short cut. By default, the tile displays items count of a given model restricted to a given domain. @@ -30,28 +17,18 @@ Tile can be: - Restricted to some groups. *Note: The tile will be hidden if the current user doesn't have access to the given model.* ->>>>>>> 3ab676d... [IMP][8.0][web_dashboard_tile] Refactor (see changes in description) (#476) Usage ===== * Dashboad sample, displaying Sale Orders to invoice: -.. image:: /web_dashboard_tile/static/src/img/screenshot_dashboard.png + +.. image:: ./static/src/img/screenshot_dashboard.png + * Tree view displayed when user click on the tile: -.. image:: /web_dashboard_tile/static/src/img/screenshot_action_click.png - -Known issues / Roadmap -====================== - -<<<<<<< HEAD -* Can not edit tile from dashboard (color, sequence, function, ...); -* Context are ignored; -* Date filter can not be relative; -* Combine domain of menue and filter so can not restore origin filter; -* Support context_today; -* Add icons; -* Support client side action (like inbox); -======= + +.. image:: ./static/src/img/screenshot_action_click.png + Known issues ============ * Can not edit tile from dashboard (color, sequence, function, ...). @@ -66,7 +43,6 @@ Roadmap * Restore original Domain + Filter when an action is set. * Posibility to hide the tile based on a field expression. * Posibility to set the background color based on a field expression. ->>>>>>> 3ab676d... [IMP][8.0][web_dashboard_tile] Refactor (see changes in description) (#476) Bug Tracker =========== @@ -74,10 +50,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed feedback -`here `_. +`here `_. Credits @@ -88,6 +61,7 @@ Contributors * Markus Schneider * Sylvain Le Gal (https://twitter.com/legalsylvain) +* Iván Todorovich Maintainer ---------- @@ -100,4 +74,4 @@ This module is maintained by the OCA. OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -To contribute to this module, please visit http://odoo-community.org. +To contribute to this module, please visit http://odoo-community.org. \ No newline at end of file diff --git a/web_dashboard_tile/__init__.py b/web_dashboard_tile/__init__.py index 35d8f47b..1d098b58 100644 --- a/web_dashboard_tile/__init__.py +++ b/web_dashboard_tile/__init__.py @@ -1,26 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2010-2013 OpenERP s.a. (). -# Copyright (C) 2014 initOS GmbH & Co. KG (). -# Copyright (C) 2015-Today GRAP -# Author Markus Schneider -# @author Sylvain LE GAL (https://twitter.com/legalsylvain) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2010-2013 OpenERP s.a. (). +# © 2014 initOS GmbH & Co. KG (). +# © 2015-Today GRAP +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html from . import models diff --git a/web_dashboard_tile/__openerp__.py b/web_dashboard_tile/__openerp__.py index f84fd1b3..bcba4eb5 100644 --- a/web_dashboard_tile/__openerp__.py +++ b/web_dashboard_tile/__openerp__.py @@ -20,6 +20,10 @@ # along with this program. If not, see . # ############################################################################## +# -*- coding: utf-8 -*- +# © 2010-2013 OpenERP s.a. (). +# © 2014 initOS GmbH & Co. KG (). +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html { "name": "Dashboard Tile", "summary": "Add Tiles to Dashboard", @@ -30,9 +34,16 @@ 'mail', 'web_widget_color', ], - 'author': "initOS GmbH & Co. KG,GRAP,Odoo Community Association (OCA)", + 'author': 'initOS GmbH & Co. KG, ' + 'GRAP, ' + 'Odoo Community Association (OCA)', "category": "web", 'license': 'AGPL-3', + 'contributors': [ + 'initOS GmbH & Co. KG', + 'GRAP', + 'Iván Todorovich ' + ], 'data': [ 'views/tile.xml', 'views/templates.xml', @@ -46,5 +57,4 @@ 'qweb': [ 'static/src/xml/custom_xml.xml', ], - 'installable': True, } diff --git a/web_dashboard_tile/models/__init__.py b/web_dashboard_tile/models/__init__.py index fc23e732..97fec216 100644 --- a/web_dashboard_tile/models/__init__.py +++ b/web_dashboard_tile/models/__init__.py @@ -1,23 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2015-Today GRAP -# @author Sylvain LE GAL (https://twitter.com/legalsylvain) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2010-2013 OpenERP s.a. (). +# © 2014 initOS GmbH & Co. KG (). +# © 2015-Today GRAP +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html from . import tile_tile diff --git a/web_dashboard_tile/models/tile_tile.py b/web_dashboard_tile/models/tile_tile.py index 498d365b..bc304b69 100644 --- a/web_dashboard_tile/models/tile_tile.py +++ b/web_dashboard_tile/models/tile_tile.py @@ -1,33 +1,4 @@ # -*- coding: utf-8 -*- -<<<<<<< HEAD -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2010-2013 OpenERP s.a. (). -# Copyright (C) 2014 initOS GmbH & Co. KG (). -# Copyright (C) 2015-Today GRAP -# Author Markus Schneider -# @author Sylvain LE GAL (https://twitter.com/legalsylvain) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp import api, fields -from openerp.models import Model -from openerp.exceptions import except_orm -======= # © 2010-2013 OpenERP s.a. (). # © 2014 initOS GmbH & Co. KG (). # © 2015-Today GRAP @@ -40,13 +11,10 @@ from collections import OrderedDict from openerp import api, fields, models from openerp.tools.safe_eval import safe_eval as eval ->>>>>>> 3ab676d... [IMP][8.0][web_dashboard_tile] Refactor (see changes in description) (#476) from openerp.tools.translate import _ +from openerp.exceptions import ValidationError, except_orm -<<<<<<< HEAD -class TileTile(Model): -======= def median(vals): # https://docs.python.org/3/library/statistics.html#statistics.median # TODO : refactor, using statistics.median when Odoo will be available @@ -75,7 +43,7 @@ FIELD_FUNCTIONS = OrderedDict([ 'help': _("Total value of '%s'")}), ('avg', { 'name': 'Average', - 'func': lambda vals: sum(vals)/len(vals), + 'func': lambda vals: sum(vals) / len(vals), 'help': _("Minimum value of '%s'")}), ('median', { 'name': 'Median', @@ -89,56 +57,10 @@ FIELD_FUNCTION_SELECTION = [ class TileTile(models.Model): ->>>>>>> 3ab676d... [IMP][8.0][web_dashboard_tile] Refactor (see changes in description) (#476) _name = 'tile.tile' _description = 'Dashboard Tile' _order = 'sequence, name' -<<<<<<< HEAD - def median(self, aList): - # https://docs.python.org/3/library/statistics.html#statistics.median - # TODO : refactor, using statistics.median when Odoo will be available - # in Python 3.4 - even = (0 if len(aList) % 2 else 1) + 1 - half = (len(aList) - 1) / 2 - return sum(sorted(aList)[half:half + even]) / float(even) - - def _get_tile_info(self): - ima_obj = self.env['ir.model.access'] - res = {} - for r in self: - r.active = False - r.count = 0 - r.computed_value = 0 - r.helper = '' - if ima_obj.check(r.model_id.model, 'read', False): - # Compute count item - model = self.env[r.model_id.model] - r.count = model.search_count(eval(r.domain)) - r.active = True - - # Compute datas for field_id depending of field_function - if r.field_function and r.field_id and r.count != 0: - records = model.search(eval(r.domain)) - vals = [x[r.field_id.name] for x in records] - desc = r.field_id.field_description - if r.field_function == 'min': - r.computed_value = min(vals) - r.helper = _("Minimum value of '%s'") % desc - elif r.field_function == 'max': - r.computed_value = max(vals) - r.helper = _("Maximum value of '%s'") % desc - elif r.field_function == 'sum': - r.computed_value = sum(vals) - r.helper = _("Total value of '%s'") % desc - elif r.field_function == 'avg': - r.computed_value = sum(vals) / len(vals) - r.helper = _("Average value of '%s'") % desc - elif r.field_function == 'median': - r.computed_value = self.median(vals) - r.helper = _("Median value of '%s'") % desc - return res -======= def _get_eval_context(self): def _context_today(): return fields.Date.from_string(fields.Date.context_today(self)) @@ -238,13 +160,13 @@ class TileTile(models.Model): self.primary_function != 'count', self.secondary_function and self.secondary_function != 'count' - ]): - records = model.search(eval(domain, eval_context)) + ]): + records = model.search(eval(domain, eval_context)) for f in ['primary_', 'secondary_']: - f_function = f+'function' - f_field_id = f+'field_id' - f_format = f+'format' - f_value = f+'value' + f_function = f + 'function' + f_field_id = f + 'field_id' + f_format = f + 'format' + f_value = f + 'value' value = 0 if self[f_function] == 'count': value = count @@ -268,9 +190,9 @@ class TileTile(models.Model): 'secondary_function', 'secondary_field_id') def _compute_helper(self): for f in ['primary_', 'secondary_']: - f_function = f+'function' - f_field_id = f+'field_id' - f_helper = f+'helper' + f_function = f + 'function' + f_field_id = f + 'field_id' + f_helper = f + 'helper' self[f_helper] = '' field_func = FIELD_FUNCTIONS.get(self[f_function], {}) help = field_func.get('help', False) @@ -285,15 +207,13 @@ class TileTile(models.Model): def _compute_active(self): ima = self.env['ir.model.access'] self.active = ima.check(self.model_id.model, 'read', False) ->>>>>>> 3ab676d... [IMP][8.0][web_dashboard_tile] Refactor (see changes in description) (#476) def _search_active(self, operator, value): cr = self.env.cr if operator != '=': raise except_orm( - 'Unimplemented Feature', - 'Search on Active field disabled.') - ima_obj = self.env['ir.model.access'] + _('Unimplemented Feature. Search on Active field disabled.')) + ima = self.env['ir.model.access'] ids = [] cr.execute(""" SELECT tt.id, im.model @@ -301,40 +221,10 @@ class TileTile(models.Model): INNER JOIN ir_model im ON tt.model_id = im.id""") for result in cr.fetchall(): - if (ima_obj.check(result[1], 'read', False) == value): + if (ima.check(result[1], 'read', False) == value): ids.append(result[0]) return [('id', 'in', ids)] -<<<<<<< HEAD - # Column Section - name = fields.Char(required=True) - model_id = fields.Many2one( - comodel_name='ir.model', string='Model', required=True) - user_id = fields.Many2one( - comodel_name='res.users', string='User') - domain = fields.Text(default='[]') - action_id = fields.Many2one( - comodel_name='ir.actions.act_window', string='Action') - count = fields.Integer(compute='_get_tile_info') - computed_value = fields.Float(compute='_get_tile_info') - helper = fields.Char(compute='_get_tile_info') - field_function = fields.Selection(selection=[ - ('min', 'Minimum'), - ('max', 'Maximum'), - ('sum', 'Sum'), - ('avg', 'Average'), - ('median', 'Median'), - ], string='Function') - field_id = fields.Many2one( - comodel_name='ir.model.fields', string='Field', - domain="[('model_id', '=', model_id)," - " ('ttype', 'in', ['float', 'int'])]") - active = fields.Boolean( - compute='_get_tile_info', readonly=True, search='_search_active') - background_color = fields.Char(default='#0E6C7E', oldname='color') - font_color = fields.Char(default='#FFFFFF') - sequence = fields.Integer(default=0, required=True) -======= # Constraints and onchanges @api.one @api.constrains('model_id', 'primary_field_id', 'secondary_field_id') @@ -344,9 +234,9 @@ class TileTile(models.Model): self.primary_field_id.model_id.id != self.model_id.id, self.secondary_field_id and self.secondary_field_id.model_id.id != self.model_id.id - ]): - raise ValidationError( - _("Please select a field from the selected model.")) + ]): + raise ValidationError( + _("Please select a field from the selected model.")) @api.onchange('model_id') def _onchange_model_id(self): @@ -359,34 +249,8 @@ class TileTile(models.Model): self.primary_field_id = False if self.secondary_function in [False, 'count']: self.secondary_field_id = False ->>>>>>> 3ab676d... [IMP][8.0][web_dashboard_tile] Refactor (see changes in description) (#476) - - # Constraint Section - def _check_model_id_field_id(self, cr, uid, ids, context=None): - for t in self.browse(cr, uid, ids, context=context): - if t.field_id and t.field_id.model_id.id != t.model_id.id: - return False - return True - - def _check_field_id_field_function(self, cr, uid, ids, context=None): - for t in self.browse(cr, uid, ids, context=context): - if t.field_id and not t.field_function or\ - t.field_function and not t.field_id: - return False - return True - - _constraints = [ - ( - _check_model_id_field_id, - "Error ! Please select a field of the selected model.", - ['model_id', 'field_id']), - ( - _check_field_id_field_function, - "Error ! Please set both fields: 'Field' and 'Function'.", - ['field_id', 'field_function']), - ] - # View / action Section + # Action methods @api.multi def open_link(self): res = { @@ -403,8 +267,7 @@ class TileTile(models.Model): } if self.action_id: res.update(self.action_id.read( - ['view_type', 'view_mode', 'view_id', 'type'])[0]) - # FIXME: restore original Domain + Filter would be better + ['view_type', 'view_mode', 'type'])[0]) return res @api.model diff --git a/web_dashboard_tile/static/src/css/tile.css b/web_dashboard_tile/static/src/css/tile.css index 4ec483d7..73b811d3 100644 --- a/web_dashboard_tile/static/src/css/tile.css +++ b/web_dashboard_tile/static/src/css/tile.css @@ -1,17 +1,10 @@ -.openerp .oe_kanban_view .oe_dashbaord_tile{ +.openerp .oe_kanban_view .oe_dashboard_tile { width: 150px; height: 150px; border: 0; border-radius: 0; } -<<<<<<< HEAD -.openerp .oe_kanban_view .oe_dashbaord_tile .tile_label, -.openerp .oe_kanban_view .oe_dashbaord_tile .tile_count_without_computed_value, -.openerp .oe_kanban_view .oe_dashbaord_tile .tile_count_with_computed_value, -.openerp .oe_kanban_view .oe_dashbaord_tile .tile_computed_value { - width: 140px; -======= /* Disable default kanban style */ .openerp .oe_kanban_view .oe_dashboard_tile .oe_kanban_content div:first-child { margin-right: inherit!important; @@ -20,44 +13,27 @@ .openerp .oe_kanban_view .oe_dashboard_tile .tile_label, .openerp .oe_kanban_view .oe_dashboard_tile .tile_primary_value, .openerp .oe_kanban_view .oe_dashboard_tile .tile_secondary_value { ->>>>>>> 3ab676d... [IMP][8.0][web_dashboard_tile] Refactor (see changes in description) (#476) text-align: center; font-weight: bold; } -<<<<<<< HEAD -.openerp .oe_kanban_view .oe_dashbaord_tile .tile_label{ -======= .openerp .oe_kanban_view .oe_dashboard_tile .tile_label { ->>>>>>> 3ab676d... [IMP][8.0][web_dashboard_tile] Refactor (see changes in description) (#476) padding: 5px; font-size: 15px; } -<<<<<<< HEAD -.openerp .oe_kanban_view .oe_dashbaord_tile .tile_count_without_computed_value{ - font-size: 52px; - font-weight: bold; -======= .openerp .oe_kanban_view .oe_dashboard_tile .tile_primary_value{ font-size: 54px; ->>>>>>> 3ab676d... [IMP][8.0][web_dashboard_tile] Refactor (see changes in description) (#476) position: absolute; left: 5px; right: 5px; bottom: 5px; } -<<<<<<< HEAD -.openerp .oe_kanban_view .oe_dashbaord_tile .tile_count_with_computed_value{ - font-size: 38px; - font-weight: bold; -======= .openerp .oe_kanban_view .oe_dashboard_tile .tile_secondary_value{ display: none; font-size: 18px; font-style: italic; ->>>>>>> 3ab676d... [IMP][8.0][web_dashboard_tile] Refactor (see changes in description) (#476) position: absolute; left: 5px; right: 5px; @@ -69,16 +45,6 @@ bottom: 30px; } -<<<<<<< HEAD -.openerp .oe_kanban_view .oe_dashbaord_tile .tile_computed_value{ - font-size: 18px; - font-weight: bold; - position: absolute; - right: 10px; - bottom: 5px; - font-style: italic; -} -======= .openerp .oe_kanban_view .oe_dashboard_tile .with_secondary .tile_secondary_value{ display: block; } @@ -90,5 +56,4 @@ .openerp .oe_searchview_drawer .oe_opened .oe_dashboard_tile_form { display: block; -} ->>>>>>> 3ab676d... [IMP][8.0][web_dashboard_tile] Refactor (see changes in description) (#476) +} \ No newline at end of file diff --git a/web_dashboard_tile/static/src/js/custom_js.js b/web_dashboard_tile/static/src/js/custom_js.js index c192ef29..9015f9a9 100644 --- a/web_dashboard_tile/static/src/js/custom_js.js +++ b/web_dashboard_tile/static/src/js/custom_js.js @@ -19,7 +19,7 @@ // //############################################################################# -openerp.web_dashboard_tile = function (instance) +odoo.web_dashboard_tile = function (instance) { var QWeb = instance.web.qweb, _t = instance.web._t, @@ -35,13 +35,13 @@ _.mixin({ var self = this; this.$('#add_dashboard_tile').on('click', this, function (){ self.save_tile(); - }) + }); }, render_data: function(dashboard_choices){ var selection = instance.web.qweb.render( "SearchView.addtodashboard.selection", { selections: dashboard_choices}); - this.$("form input").before(selection) + this.$("form input").before(selection); }, save_tile: function () { var self = this; @@ -97,4 +97,4 @@ _.mixin({ } }); -} +}; diff --git a/web_dashboard_tile/static/src/xml/custom_xml.xml b/web_dashboard_tile/static/src/xml/custom_xml.xml index 3e0c2316..11ecb179 100644 --- a/web_dashboard_tile/static/src/xml/custom_xml.xml +++ b/web_dashboard_tile/static/src/xml/custom_xml.xml @@ -2,11 +2,11 @@ -
+
- + \ No newline at end of file diff --git a/web_dashboard_tile/views/templates.xml b/web_dashboard_tile/views/templates.xml index e7a68b21..1fe51f0d 100644 --- a/web_dashboard_tile/views/templates.xml +++ b/web_dashboard_tile/views/templates.xml @@ -30,4 +30,4 @@ - + \ No newline at end of file diff --git a/web_dashboard_tile/views/tile.xml b/web_dashboard_tile/views/tile.xml index cf9a003f..a42d952f 100644 --- a/web_dashboard_tile/views/tile.xml +++ b/web_dashboard_tile/views/tile.xml @@ -103,7 +103,7 @@ -