diff --git a/web_dashboard_tile/README.rst b/web_dashboard_tile/README.rst new file mode 100644 index 000000000..c19bcdfac --- /dev/null +++ b/web_dashboard_tile/README.rst @@ -0,0 +1,66 @@ +Add Tiles to Dashboard +====================== + +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; + +Usage +===== + +* Dashboad sample, displaying Sale Orders to invoice: +.. image:: web_dashboard_tile/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 + +Kown issues/limits +================== +* 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; + +possible future improvments +=========================== +* support context_today; +* add icons; +* support client side action (like inbox); + +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 `_. + + +Credits +======= + +Contributors +------------ + +* Markus Schneider +* Sylvain Le Gal (https://twitter.com/legalsylvain) + +Maintainer +---------- + +.. image:: http://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: http://odoo-community.org + +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. diff --git a/web_dashboard_tile/__init__.py b/web_dashboard_tile/__init__.py new file mode 100644 index 000000000..35d8f47b1 --- /dev/null +++ b/web_dashboard_tile/__init__.py @@ -0,0 +1,26 @@ +# -*- 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 . +# +############################################################################## + +from . import models diff --git a/web_dashboard_tile/__openerp__.py b/web_dashboard_tile/__openerp__.py new file mode 100644 index 000000000..66cc75448 --- /dev/null +++ b/web_dashboard_tile/__openerp__.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2010-2013 OpenERP s.a. (). +# Copyright (C) 2014 initOS GmbH & Co. KG (). +# Author Markus Schneider +# +# 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 . +# +############################################################################## +{ + "name": "Dashboard Tile", + "summary": "Add Tiles to Dashboard", + "version": "1.0", + "depends": [ + 'web', + 'board', + 'mail', + 'web_widget_color', + ], + 'author': "initOS GmbH & Co. KG,GRAP,Odoo Community Association (OCA)", + "category": "web", + 'license': 'AGPL-3', + 'data': [ + 'views/tile.xml', + 'views/templates.xml', + 'security/ir.model.access.csv', + 'security/rules.xml', + ], + 'demo': [ + 'demo/res_groups.yml', + 'demo/tile_tile.yml', + ], + 'qweb': [ + 'static/src/xml/custom_xml.xml', + ], +} diff --git a/web_dashboard_tile/demo/res_groups.yml b/web_dashboard_tile/demo/res_groups.yml new file mode 100644 index 000000000..735437c5c --- /dev/null +++ b/web_dashboard_tile/demo/res_groups.yml @@ -0,0 +1,25 @@ +# -*- 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 . +# +############################################################################## + +- !record {model: res.groups, id: base.group_no_one}: + users: + - base.user_root diff --git a/web_dashboard_tile/demo/tile_tile.yml b/web_dashboard_tile/demo/tile_tile.yml new file mode 100644 index 000000000..6b23b71bd --- /dev/null +++ b/web_dashboard_tile/demo/tile_tile.yml @@ -0,0 +1,40 @@ +# -*- 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 . +# +############################################################################## + +- !record {model: tile.tile, id: installed_modules}: + name: Installed Modules + model_id: base.model_ir_module_module + domain: [['state', 'in', ['installed', 'to upgrade', 'to remove']]] + action_id: base.open_module_tree + +- !record {model: tile.tile, id: installed_OCA_modules}: + name: Installed OCA Modules + model_id: base.model_ir_module_module + domain: [['state', 'in', ['installed', 'to upgrade', 'to remove']], ['author', 'ilike', 'Odoo Community Association (OCA)']] + action_id: base.open_module_tree + +- !record {model: tile.tile, id: all_currency_with_rate}: + name: Currencies (Max Rate) + model_id: base.model_res_currency + domain: [] + field_function: max + field_id: base.field_res_currency_rate diff --git a/web_dashboard_tile/i18n/fr.po b/web_dashboard_tile/i18n/fr.po new file mode 100644 index 000000000..6bb700fa3 --- /dev/null +++ b/web_dashboard_tile/i18n/fr.po @@ -0,0 +1,220 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * web_dashboard_tile +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-04-10 01:04+0000\n" +"PO-Revision-Date: 2015-04-10 01:04+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: web_dashboard_tile +#: field:tile.tile,action_id:0 +msgid "Action" +msgstr "Action" + +#. module: web_dashboard_tile +#: field:tile.tile,active:0 +msgid "Active" +msgstr "Actif" + +#. module: web_dashboard_tile +#: selection:tile.tile,field_function:0 +msgid "Average" +msgstr "Moyenne" + +#. module: web_dashboard_tile +#: code:addons/web_dashboard_tile/tile.py:82 +#, python-format +msgid "Average value of '%s'" +msgstr "Valeur moyenne du champ '%s'" + +#. module: web_dashboard_tile +#: field:tile.tile,color:0 +msgid "Background color" +msgstr "Couleur de fond" + +#. module: web_dashboard_tile +#: field:tile.tile,computed_value:0 +msgid "Computed Value" +msgstr "Valeur calculée" + +#. module: web_dashboard_tile +#: field:tile.tile,count:0 +msgid "Count" +msgstr "Quantité" + +#. module: web_dashboard_tile +#. openerp-web +#: code:addons/web_dashboard_tile/static/src/xml/custom_xml.xml:8 +#, python-format +msgid "Create" +msgstr "Créer" + +#. module: web_dashboard_tile +#: model:ir.actions.act_window,name:web_dashboard_tile.action_kanban_dashboard_tile +#: model:ir.actions.act_window,name:web_dashboard_tile.action_tree_dashboard_tile +#: model:ir.ui.menu,name:web_dashboard_tile.mail_dashboard +msgid "Dashboard" +msgstr "Tableau de bord" + +#. module: web_dashboard_tile +#: model:ir.ui.menu,name:web_dashboard_tile.menue_dashboard_tile +msgid "Dashboard Tile" +msgstr "Indicateur de tableau de bord" + +#. module: web_dashboard_tile +#: view:tile.tile:0 +msgid "Dashboard tiles" +msgstr "Indicateurs de tableau de bord" + +#. module: web_dashboard_tile +#: view:tile.tile:0 +msgid "Delete" +msgstr "Supprimer" + +#. module: web_dashboard_tile +#: field:tile.tile,domain:0 +msgid "Domain" +msgstr "Domaine" + +#. module: web_dashboard_tile +#: view:tile.tile:0 +msgid "Edit..." +msgstr "Editer..." + +#. module: web_dashboard_tile +#. openerp-web +#: code:addons/web_dashboard_tile/static/src/js/custom_js.js:61 +#, python-format +msgid "Error" +msgstr "Erreur" + +#. module: web_dashboard_tile +#: constraint:tile.tile:0 +msgid "Error ! Please select a field of the selected model." +msgstr "Erreur ! Veuillez sélectioner un champ qui correspond au modèle." + +#. module: web_dashboard_tile +#: constraint:tile.tile:0 +msgid "Error ! Please set both fields: 'Field' and 'Function'." +msgstr "Erreur ! Veuillez renseigner les deux champs : 'Champ' et 'Fonction'." + +#. module: web_dashboard_tile +#: field:tile.tile,field_id:0 +msgid "Field" +msgstr "Champ" + +#. module: web_dashboard_tile +#. openerp-web +#: code:addons/web_dashboard_tile/static/src/js/custom_js.js:61 +#, python-format +msgid "Filter name is required." +msgstr "Le nom du filtre est requis." + +#. module: web_dashboard_tile +#: field:tile.tile,font_color:0 +msgid "Font Color" +msgstr "Couleur du texte" + +#. module: web_dashboard_tile +#: field:tile.tile,field_function:0 +msgid "Function" +msgstr "Fonction" + +#. module: web_dashboard_tile +#: field:tile.tile,helper:0 +msgid "Helper Text" +msgstr "Texte Descriptif" + +#. module: web_dashboard_tile +#: selection:tile.tile,field_function:0 +msgid "Maximum" +msgstr "Maximum" + +#. module: web_dashboard_tile +#: code:addons/web_dashboard_tile/tile.py:76 +#, python-format +msgid "Maximum value of '%s'" +msgstr "Valeur maximale du champ '%s'" + +#. module: web_dashboard_tile +#: selection:tile.tile,field_function:0 +msgid "Median" +msgstr "Médiane" + +#. module: web_dashboard_tile +#: code:addons/web_dashboard_tile/tile.py:85 +#, python-format +msgid "Median value of '%s'" +msgstr "Valeur médian du champ '%s'" + +#. module: web_dashboard_tile +#: selection:tile.tile,field_function:0 +msgid "Minimum" +msgstr "Minimum" + +#. module: web_dashboard_tile +#: code:addons/web_dashboard_tile/tile.py:73 +#, python-format +msgid "Minimum value of '%s'" +msgstr "Valeur minimale du champ '%s'" + +#. module: web_dashboard_tile +#: field:tile.tile,model_id:0 +msgid "Model" +msgstr "Modèle" + +#. module: web_dashboard_tile +#: field:tile.tile,sequence:0 +msgid "Sequence" +msgstr "Séquence" + +#. module: web_dashboard_tile +#. openerp-web +#: code:addons/web_dashboard_tile/static/src/js/custom_js.js:100 +#, python-format +msgid "Success" +msgstr "Succès" + +#. module: web_dashboard_tile +#: selection:tile.tile,field_function:0 +msgid "Sum" +msgstr "Somme" + +#. module: web_dashboard_tile +#: field:tile.tile,name:0 +msgid "Tile Name" +msgstr "Nom de l'indicateur" + +#. module: web_dashboard_tile +#. openerp-web +#: code:addons/web_dashboard_tile/static/src/js/custom_js.js:100 +#, python-format +msgid "Tile is created" +msgstr "L'indicateur a été créé" + +#. module: web_dashboard_tile +#. openerp-web +#: code:addons/web_dashboard_tile/static/src/xml/custom_xml.xml:6 +#, python-format +msgid "Tile:" +msgstr "Indicateur :" + +#. module: web_dashboard_tile +#: code:addons/web_dashboard_tile/tile.py:79 +#, python-format +msgid "Total value of '%s'" +msgstr "Somme du champ '%s'" + +#. module: web_dashboard_tile +#: field:tile.tile,user_id:0 +msgid "User" +msgstr "Utilisateur" diff --git a/web_dashboard_tile/i18n/web_dashboard_tile.pot b/web_dashboard_tile/i18n/web_dashboard_tile.pot new file mode 100644 index 000000000..0e89f8cae --- /dev/null +++ b/web_dashboard_tile/i18n/web_dashboard_tile.pot @@ -0,0 +1,232 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * web_dashboard_tile +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-04-10 01:03+0000\n" +"PO-Revision-Date: 2015-04-10 01:03+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: web_dashboard_tile +#: field:tile.tile,action_id:0 +msgid "Action" +msgstr "" + +#. module: web_dashboard_tile +#: field:tile.tile,active:0 +msgid "Active" +msgstr "" + +#. module: web_dashboard_tile +#: selection:tile.tile,field_function:0 +msgid "Average" +msgstr "" + +#. module: web_dashboard_tile +#: code:addons/web_dashboard_tile/tile.py:82 +#, python-format +msgid "Average value of '%s'" +msgstr "" + +#. module: web_dashboard_tile +#: field:tile.tile,color:0 +msgid "Background color" +msgstr "" + +#. module: web_dashboard_tile +#: field:tile.tile,computed_value:0 +msgid "Computed Value" +msgstr "" + +#. module: web_dashboard_tile +#: field:tile.tile,count:0 +msgid "Count" +msgstr "" + +#. module: web_dashboard_tile +#. openerp-web +#: code:addons/web_dashboard_tile/static/src/xml/custom_xml.xml:8 +#, python-format +msgid "Create" +msgstr "" + +#. module: web_dashboard_tile +#: model:ir.actions.act_window,name:web_dashboard_tile.action_kanban_dashboard_tile +#: model:ir.actions.act_window,name:web_dashboard_tile.action_tree_dashboard_tile +#: model:ir.ui.menu,name:web_dashboard_tile.mail_dashboard +msgid "Dashboard" +msgstr "" + +#. module: web_dashboard_tile +#: model:ir.ui.menu,name:web_dashboard_tile.menue_dashboard_tile +msgid "Dashboard Tile" +msgstr "" + +#. module: web_dashboard_tile +#: view:tile.tile:0 +msgid "Dashboard tiles" +msgstr "" + +#. module: web_dashboard_tile +#: view:tile.tile:0 +msgid "Delete" +msgstr "" + +#. module: web_dashboard_tile +#: field:tile.tile,domain:0 +msgid "Domain" +msgstr "" + +#. module: web_dashboard_tile +#: view:tile.tile:0 +msgid "Edit..." +msgstr "" + +#. module: web_dashboard_tile +#. openerp-web +#: code:addons/web_dashboard_tile/static/src/js/custom_js.js:61 +#, python-format +msgid "Error" +msgstr "" + +#. module: web_dashboard_tile +#: constraint:tile.tile:0 +msgid "Error ! Please select a field of the selected model." +msgstr "" + +#. module: web_dashboard_tile +#: constraint:tile.tile:0 +msgid "Error ! Please set both fields: 'Field' and 'Function'." +msgstr "" + +#. module: web_dashboard_tile +#: field:tile.tile,field_id:0 +msgid "Field" +msgstr "" + +#. module: web_dashboard_tile +#. openerp-web +#: code:addons/web_dashboard_tile/static/src/js/custom_js.js:61 +#, python-format +msgid "Filter name is required." +msgstr "" + +#. module: web_dashboard_tile +#: field:tile.tile,font_color:0 +msgid "Font Color" +msgstr "" + +#. module: web_dashboard_tile +#: field:tile.tile,field_function:0 +msgid "Function" +msgstr "" + +#. module: web_dashboard_tile +#: field:tile.tile,helper:0 +msgid "Helper Text" +msgstr "" + +#. module: web_dashboard_tile +#: selection:tile.tile,field_function:0 +msgid "Maximum" +msgstr "" + +#. module: web_dashboard_tile +#: code:addons/web_dashboard_tile/tile.py:76 +#, python-format +msgid "Maximum value of '%s'" +msgstr "" + +#. module: web_dashboard_tile +#: selection:tile.tile,field_function:0 +msgid "Median" +msgstr "" + +#. module: web_dashboard_tile +#: code:addons/web_dashboard_tile/tile.py:85 +#, python-format +msgid "Median value of '%s'" +msgstr "" + +#. module: web_dashboard_tile +#: selection:tile.tile,field_function:0 +msgid "Minimum" +msgstr "" + +#. module: web_dashboard_tile +#: code:addons/web_dashboard_tile/tile.py:73 +#, python-format +msgid "Minimum value of '%s'" +msgstr "" + +#. module: web_dashboard_tile +#: field:tile.tile,model_id:0 +msgid "Model" +msgstr "" + +#. module: web_dashboard_tile +#: field:tile.tile,sequence:0 +msgid "Sequence" +msgstr "" + +#. module: web_dashboard_tile +#. openerp-web +#: code:addons/web_dashboard_tile/static/src/js/custom_js.js:100 +#, python-format +msgid "Success" +msgstr "" + +#. module: web_dashboard_tile +#: selection:tile.tile,field_function:0 +msgid "Sum" +msgstr "" + +#. module: web_dashboard_tile +#: field:tile.tile,name:0 +msgid "Tile Name" +msgstr "" + +#. module: web_dashboard_tile +#. openerp-web +#: code:addons/web_dashboard_tile/static/src/js/custom_js.js:100 +#, python-format +msgid "Tile is created" +msgstr "" + +#. module: web_dashboard_tile +#. openerp-web +#: code:addons/web_dashboard_tile/static/src/xml/custom_xml.xml:6 +#, python-format +msgid "Tile:" +msgstr "" + +#. module: web_dashboard_tile +#: code:addons/web_dashboard_tile/tile.py:79 +#, python-format +msgid "Total value of '%s'" +msgstr "" + +#. module: web_dashboard_tile +#: field:tile.tile,user_id:0 +msgid "User" +msgstr "" + +#. module: web_dashboard_tile +#: code:_description:0 +#: model:ir.model,name:web_dashboard_tile.model_tile_tile +#, python-format +msgid "tile.tile" +msgstr "" + +#. module: web_dashboard_tile +#: view:tile.tile:0 +msgid "í" +msgstr "" diff --git a/web_dashboard_tile/models/__init__.py b/web_dashboard_tile/models/__init__.py new file mode 100644 index 000000000..fc23e732e --- /dev/null +++ b/web_dashboard_tile/models/__init__.py @@ -0,0 +1,23 @@ +# -*- 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 . +# +############################################################################## + +from . import tile_tile diff --git a/web_dashboard_tile/models/tile_tile.py b/web_dashboard_tile/models/tile_tile.py new file mode 100644 index 000000000..4743afcb5 --- /dev/null +++ b/web_dashboard_tile/models/tile_tile.py @@ -0,0 +1,179 @@ +# -*- 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 . +# +############################################################################## + +from openerp import api, fields +from openerp.models import Model +from openerp.exceptions import except_orm +from openerp.tools.translate import _ + + +class TileTile(Model): + _name = 'tile.tile' + _order = 'sequence, name' + + 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 _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'] + ids = [] + cr.execute(""" + SELECT tt.id, im.model + FROM tile_tile tt + 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): + ids.append(result[0]) + return [('id', 'in', ids)] + + # 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) + + # 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 + @api.multi + def open_link(self): + res = { + 'name': self.name, + 'view_type': 'form', + 'view_mode': 'tree', + 'view_id': [False], + 'res_model': self.model_id.model, + 'type': 'ir.actions.act_window', + 'context': self.env.context, + 'nodestroy': True, + 'target': 'current', + 'domain': self.domain, + } + 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 + return res + + @api.model + def add(self, vals): + if 'model_id' in vals and not vals['model_id'].isdigit(): + # need to replace model_name with its id + vals['model_id'] = self.env['ir.model'].search( + [('model', '=', vals['model_id'])]).id + self.create(vals) diff --git a/web_dashboard_tile/security/ir.model.access.csv b/web_dashboard_tile/security/ir.model.access.csv new file mode 100644 index 000000000..3229b4ea2 --- /dev/null +++ b/web_dashboard_tile/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +tile_user,tile_user,model_tile_tile,base.group_user,1,1,1,1 diff --git a/web_dashboard_tile/security/rules.xml b/web_dashboard_tile/security/rules.xml new file mode 100644 index 000000000..8d653b70c --- /dev/null +++ b/web_dashboard_tile/security/rules.xml @@ -0,0 +1,13 @@ + + + + + + tile.owner + + + [('user_id','in',[False,user.id])] + + + + diff --git a/web_dashboard_tile/static/description/icon.png b/web_dashboard_tile/static/description/icon.png new file mode 100644 index 000000000..fb6b1b298 Binary files /dev/null and b/web_dashboard_tile/static/description/icon.png differ diff --git a/web_dashboard_tile/static/src/css/tile.css b/web_dashboard_tile/static/src/css/tile.css new file mode 100644 index 000000000..1d057ceea --- /dev/null +++ b/web_dashboard_tile/static/src/css/tile.css @@ -0,0 +1,44 @@ +.openerp .oe_kanban_view .oe_dashbaord_tile{ + width: 150px; + height: 150px; + border: 0; + border-radius: 0; +} + +.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; + text-align: center; +} + +.openerp .oe_kanban_view .oe_dashbaord_tile .tile_label{ + padding: 5px; + font-size: 15px; +} + +.openerp .oe_kanban_view .oe_dashbaord_tile .tile_count_without_computed_value{ + font-size: 52px; + font-weight: bold; + position: absolute; + left: 5px; + bottom: 5px; +} + +.openerp .oe_kanban_view .oe_dashbaord_tile .tile_count_with_computed_value{ + font-size: 38px; + font-weight: bold; + position: absolute; + left: 5px; + bottom: 30px; +} + +.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; +} diff --git a/web_dashboard_tile/static/src/img/avg.png b/web_dashboard_tile/static/src/img/avg.png new file mode 100644 index 000000000..2f534e932 Binary files /dev/null and b/web_dashboard_tile/static/src/img/avg.png differ diff --git a/web_dashboard_tile/static/src/img/max.png b/web_dashboard_tile/static/src/img/max.png new file mode 100644 index 000000000..ff33ee437 Binary files /dev/null and b/web_dashboard_tile/static/src/img/max.png differ diff --git a/web_dashboard_tile/static/src/img/median.png b/web_dashboard_tile/static/src/img/median.png new file mode 100644 index 000000000..61d5dd7c2 Binary files /dev/null and b/web_dashboard_tile/static/src/img/median.png differ diff --git a/web_dashboard_tile/static/src/img/min.png b/web_dashboard_tile/static/src/img/min.png new file mode 100644 index 000000000..de7c3fd02 Binary files /dev/null and b/web_dashboard_tile/static/src/img/min.png differ diff --git a/web_dashboard_tile/static/src/img/screenshot_action_click.png b/web_dashboard_tile/static/src/img/screenshot_action_click.png new file mode 100644 index 000000000..3fd41f99d Binary files /dev/null and b/web_dashboard_tile/static/src/img/screenshot_action_click.png differ diff --git a/web_dashboard_tile/static/src/img/screenshot_dashboard.png b/web_dashboard_tile/static/src/img/screenshot_dashboard.png new file mode 100644 index 000000000..9cbdeecd3 Binary files /dev/null and b/web_dashboard_tile/static/src/img/screenshot_dashboard.png differ diff --git a/web_dashboard_tile/static/src/img/sum.png b/web_dashboard_tile/static/src/img/sum.png new file mode 100644 index 000000000..90908e8bb Binary files /dev/null and b/web_dashboard_tile/static/src/img/sum.png differ diff --git a/web_dashboard_tile/static/src/js/custom_js.js b/web_dashboard_tile/static/src/js/custom_js.js new file mode 100644 index 000000000..c192ef293 --- /dev/null +++ b/web_dashboard_tile/static/src/js/custom_js.js @@ -0,0 +1,100 @@ +// @@@ web_dashboard_tile custom JS @@@ +//############################################################################# +// +// Copyright (C) 2010-2013 OpenERP s.a. () +// Copyright (C) 2014 initOS GmbH & Co. KG () +// +// 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 . +// +//############################################################################# + +openerp.web_dashboard_tile = function (instance) +{ +var QWeb = instance.web.qweb, + _t = instance.web._t, + _lt = instance.web._lt; +_.mixin({ + sum: function (obj) { return _.reduce(obj, function (a, b) { return a + b; }, 0); } +}); + var module = instance.board.AddToDashboard; + + module.include({ + start: function () { + this._super(); + 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) + }, + save_tile: function () { + var self = this; + var view_parent = this.getParent().getParent(); + + var $name = this.$('#dashboard_tile_new_name'); + + this.tile = new instance.web.Model('tile.tile'); + + var private_filter = !this.$('#oe_searchview_custom_public').prop('checked'); + if (_.isEmpty($name.val())){ + this.do_warn(_t("Error"), _t("Filter name is required.")); + return false; + } + var search = this.view.build_search_data(); + var context = new instance.web.CompoundContext(view_parent.dataset.get_context() || []); + var domain = new instance.web.CompoundDomain(view_parent.dataset.get_domain() || []); + _.each(search.contexts, context.add, context); + _.each(search.domains, domain.add, domain); + + var c = instance.web.pyeval.eval('context', context); + for(var k in c) { + if (c.hasOwnProperty(k) && /^search_default_/.test(k)) { + delete c[k]; + } + } + // TODO: replace this 6.1 workaround by attribute on + c.dashboard_merge_domains_contexts = false; + var d = instance.web.pyeval.eval('domain', domain); + + context.add({ + group_by: instance.web.pyeval.eval('groupbys', search.groupbys || []) + }); + // Don't save user_context keys in the custom filter, otherwise end + // up with e.g. wrong uid or lang stored *and used in subsequent + // reqs* + var ctx = context; + _(_.keys(instance.session.user_context)).each(function (key) { + delete ctx[key]; + }); + var filter = { + name: $name.val(), + user_id: private_filter ? instance.session.uid : false, + model_id: self.view.model, + //context: context, + domain: d, + action_id: view_parent.action.id, + }; + // FIXME: current context? + return self.tile.call('add', [filter]).done(function (id) { + self.do_warn(_t("Success"), _t("Tile is created")); + }); + + } + }); +} diff --git a/web_dashboard_tile/static/src/xml/custom_xml.xml b/web_dashboard_tile/static/src/xml/custom_xml.xml new file mode 100644 index 000000000..3e0c23167 --- /dev/null +++ b/web_dashboard_tile/static/src/xml/custom_xml.xml @@ -0,0 +1,12 @@ + + + + +
+ + + +
+
+
+
diff --git a/web_dashboard_tile/views/templates.xml b/web_dashboard_tile/views/templates.xml new file mode 100644 index 000000000..e7a68b213 --- /dev/null +++ b/web_dashboard_tile/views/templates.xml @@ -0,0 +1,33 @@ + + + + + + + + diff --git a/web_dashboard_tile/views/tile.xml b/web_dashboard_tile/views/tile.xml new file mode 100644 index 000000000..36411ad84 --- /dev/null +++ b/web_dashboard_tile/views/tile.xml @@ -0,0 +1,126 @@ + + + + + tile.tile + + + + + + + + + + + + + + + + tile.tile + +
+ +

+ +

+ + + + + + + + + + + + + + +
+
+
+
+ + + + tile.tile + + + + + + + + + + + + + + + + + + + + + + + Dashboard + tile.tile + form + tree,kanban,form + + + + + + + Dashboard + tile.tile + form + kanban + ['|',('user_id','=',False),('user_id','=',uid)] + + + + + Dashboard + + + + + +
+