diff --git a/odoo_dynamic_dashboard/README.rst b/odoo_dynamic_dashboard/README.rst new file mode 100644 index 000000000..7d8825003 --- /dev/null +++ b/odoo_dynamic_dashboard/README.rst @@ -0,0 +1,45 @@ +.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg + :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +Odoo Dynamic Dashboard +========================== +* Dynamically Arrange the dashboard to get the information that are relevant to your business, department, or a specific process or need. + +Configuration +============= +- No configuration needed + +License +======= +Affero General Public License v3.0 (AGPL v3) +(https://www.gnu.org/licenses/agpl-3.0-standalone.html) + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developers: (V18) Bhagyadev KP, +* Contact: odoo@cybrosys.com + +Contacts +-------- +* Mail Contact : odoo@cybrosys.com +* Website : http://www.cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com +This module is maintained by Cybrosys Technologies. +For support and more information, please visit https://www.cybrosys.com + +Further information +=================== +HTML Description: ``__ diff --git a/odoo_dynamic_dashboard/__init__.py b/odoo_dynamic_dashboard/__init__.py new file mode 100644 index 000000000..d15228aa8 --- /dev/null +++ b/odoo_dynamic_dashboard/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) 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 controllers +from . import models +from . import wizard diff --git a/odoo_dynamic_dashboard/__manifest__.py b/odoo_dynamic_dashboard/__manifest__.py new file mode 100644 index 000000000..449287620 --- /dev/null +++ b/odoo_dynamic_dashboard/__manifest__.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) 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': "Odoo Dynamic Dashboard", + 'version': '18.0.1.0.0', + 'category': 'Productivity', + 'summary': """Create Configurable Dashboards Easily""", + 'description': """Create Configurable Odoo Dynamic Dashboard to get the + information that are relevant to your business, department, or a specific + process or need""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': "https://www.cybrosys.com", + 'depends': ['web'], + 'data': [ + 'security/ir.model.access.csv', + 'data/dashboard_theme_data.xml', + 'views/dashboard_views.xml', + 'views/dynamic_block_views.xml', + 'views/dashboard_menu_views.xml', + 'views/dashboard_theme_views.xml', + 'wizard/dashboard_mail_views.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js', + 'odoo_dynamic_dashboard/static/src/css/**/*.css', + 'odoo_dynamic_dashboard/static/src/scss/**/*.scss', + 'odoo_dynamic_dashboard/static/src/js/**/*.js', + 'odoo_dynamic_dashboard/static/src/xml/**/*.xml', + 'https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css', + 'odoo_dynamic_dashboard/static/lib/js/interactjs.js', + ], + }, + 'images': ['static/description/banner.gif'], + 'license': "AGPL-3", + 'installable': True, + 'auto_install': False, + 'application': True, +} + + + diff --git a/odoo_dynamic_dashboard/controllers/__init__.py b/odoo_dynamic_dashboard/controllers/__init__.py new file mode 100644 index 000000000..2ebeccd86 --- /dev/null +++ b/odoo_dynamic_dashboard/controllers/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) 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 odoo_dynamic_dashboard diff --git a/odoo_dynamic_dashboard/controllers/odoo_dynamic_dashboard.py b/odoo_dynamic_dashboard/controllers/odoo_dynamic_dashboard.py new file mode 100644 index 000000000..16bc55032 --- /dev/null +++ b/odoo_dynamic_dashboard/controllers/odoo_dynamic_dashboard.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) 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 odoo import http +from odoo.http import request + + +class DynamicDashboard(http.Controller): + """Class to search and filter values in dashboard""" + + @http.route('/custom_dashboard/search_input_chart', type='json', + auth="public", website=True) + def dashboard_search_input_chart(self, search_input): + """Function to filter search input in dashboard""" + return request.env['dashboard.block'].search([ + ('name', 'ilike', search_input)]).ids diff --git a/odoo_dynamic_dashboard/data/dashboard_theme_data.xml b/odoo_dynamic_dashboard/data/dashboard_theme_data.xml new file mode 100644 index 000000000..29c052ae3 --- /dev/null +++ b/odoo_dynamic_dashboard/data/dashboard_theme_data.xml @@ -0,0 +1,12 @@ + + + + + + Demo + #4158D0 + #C850C0 + #FFCC70 + + + \ No newline at end of file diff --git a/odoo_dynamic_dashboard/doc/RELEASE_NOTES.md b/odoo_dynamic_dashboard/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..5e0d4c368 --- /dev/null +++ b/odoo_dynamic_dashboard/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 15.10.2024 +#### Version 18.0.1.0.0 +##### ADD +- Initial commit for Odoo Dynamic Dashboard \ No newline at end of file diff --git a/odoo_dynamic_dashboard/models/__init__.py b/odoo_dynamic_dashboard/models/__init__.py new file mode 100644 index 000000000..7fb6dab76 --- /dev/null +++ b/odoo_dynamic_dashboard/models/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) 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 dashboard_block +from . import dashboard_menu +from . import dashboard_theme +from . import domain_to_sql diff --git a/odoo_dynamic_dashboard/models/dashboard_block.py b/odoo_dynamic_dashboard/models/dashboard_block.py new file mode 100644 index 000000000..592cfd7d2 --- /dev/null +++ b/odoo_dynamic_dashboard/models/dashboard_block.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) 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 ast import literal_eval +from odoo import api, fields, models +from odoo.osv import expression + + +class DashboardBlock(models.Model): + """Class is used to create charts and tiles in dashboard""" + _name = "dashboard.block" + _description = "Dashboard Block" + + def get_default_action(self): + """Function to get values from dashboard if action_id is true return + id else return false""" + action_id = self.env.ref( + 'odoo_dynamic_dashboard.dashboard_view_action') + if action_id: + return action_id.id + return False + + name = fields.Char(string="Name", help='Name of the block') + fa_icon = fields.Char(string="Icon", help="Add icon for tile") + operation = fields.Selection( + selection=[("sum", "Sum"), ("avg", "Average"), ("count", "Count")], + string="Operation", + help='Tile Operation that needs to bring values for tile', + required=True) + graph_type = fields.Selection( + selection=[("bar", "Bar"), ("radar", "Radar"), ("pie", "Pie"), + ("polarArea", "polarArea"), ("line", "Line"), + ("doughnut", "Doughnut")], + string="Chart Type", help='Type of Chart') + measured_field_id = fields.Many2one("ir.model.fields", + string="Measured Field", + help="Select the Measured") + client_action_id = fields.Many2one('ir.actions.client', + string="Client action", + default=get_default_action, + help="Client action") + type = fields.Selection( + selection=[("graph", "Chart"), ("tile", "Tile")], + string="Type", help='Type of Block ie, Chart or Tile') + x_axis = fields.Char(string="X-Axis", help="Chart X-axis") + y_axis = fields.Char(string="Y-Axis", help="Chart Y-axis") + height = fields.Char(string="Height ", help="Height of the block") + width = fields.Char(string="Width", help="Width of the block") + translate_x = fields.Char(string="Translate_X", + help="x value for the style transform translate") + translate_y = fields.Char(string="Translate_Y", + help="y value for the style transform translate") + data_x = fields.Char(string="Data_X", help="Data x value for resize") + data_y = fields.Char(string="Data_Y", help="Data y value for resize") + group_by_id = fields.Many2one("ir.model.fields", + string="Group by(Y-Axis)", + help='Field value for Y-Axis') + tile_color = fields.Char(string="Tile Color", help='Primary Color of Tile') + text_color = fields.Char(string="Text Color", help='Text Color of Tile') + val_color = fields.Char(string="Value Color", help='Value Color of Tile') + fa_color = fields.Char(string="Icon Color", help='Icon Color of Tile') + filter = fields.Char(string="Filter", help="Add filter") + model_id = fields.Many2one('ir.model', string='Model', + help="Select the module name") + model_name = fields.Char(related='model_id.model', string="Model Name", + help="Added model_id model") + edit_mode = fields.Boolean(string="Edit Mode", + help="Enable to edit chart and tile",) + + @api.onchange('model_id') + def _onchange_model_id(self): + if self.operation or self.measured_field_id: + self.operation = False + self.measured_field_id = False + + def get_dashboard_vals(self, action_id, start_date=None, end_date=None): + """Fetch block values from js and create chart""" + block_id = [] + for rec in self.env['dashboard.block'].sudo().search( + [('client_action_id', '=', int(action_id))]): + if rec.filter is False: + rec.filter = "[]" + filter_list = literal_eval(rec.filter) + filter_list = [filter_item for filter_item in filter_list if not ( + isinstance(filter_item, tuple) and filter_item[ + 0] == 'create_date')] + rec.filter = repr(filter_list) + vals = {'id': rec.id, 'name': rec.name, 'type': rec.type, + 'graph_type': rec.graph_type, 'icon': rec.fa_icon, + 'model_name': rec.model_name, + 'color': f'background-color: {rec.tile_color};' if rec.tile_color else '#1f6abb;', + 'text_color': f'color: {rec.text_color};' if rec.text_color else '#FFFFFF;', + 'val_color': f'color: {rec.val_color};' if rec.val_color else '#FFFFFF;', + 'icon_color': f'color: {rec.tile_color};' if rec.tile_color else '#1f6abb;', + 'height': rec.height, + 'width': rec.width, + 'translate_x': rec.translate_x, + 'translate_y': rec.translate_y, + 'data_x': rec.data_x, + 'data_y': rec.data_y, + 'domain': filter_list, + } + domain = [] + if rec.filter: + domain = expression.AND([literal_eval(rec.filter)]) + if rec.model_name: + if rec.type == 'graph': + self._cr.execute(self.env[rec.model_name].get_query(domain, + rec.operation, + rec.measured_field_id, + start_date, + end_date, + group_by=rec.group_by_id)) + records = self._cr.dictfetchall() + x_axis = [] + for record in records: + if record.get('name') and type( + record.get('name')) == dict: + x_axis.append(record.get('name')[self._context.get( + 'lang') or 'en_US']) + else: + x_axis.append(record.get(rec.group_by_id.name)) + y_axis = [] + for record in records: + y_axis.append(record.get('value')) + vals.update({'x_axis': x_axis, 'y_axis': y_axis}) + else: + self._cr.execute(self.env[rec.model_name].get_query(domain, + rec.operation, + rec.measured_field_id, + start_date, + end_date)) + records = self._cr.dictfetchall() + magnitude = 0 + total = records[0].get('value') + while abs(total) >= 1000: + magnitude += 1 + total /= 1000.0 + val = '%.2f%s' % ( + total, ['', 'K', 'M', 'G', 'T', 'P'][magnitude]) + records[0]['value'] = val + vals.update(records[0]) + block_id.append(vals) + return block_id + + def get_save_layout(self, grid_data_list): + """Function fetch edited values while edit layout of the chart or tile + and save values in a database""" + for data in grid_data_list: + block = self.browse(int(data['id'])) + if data.get('data-x'): + block.write({ + 'translate_x': f"{data['data-x']}px", + 'translate_y': f"{data['data-y']}px", + 'data_x': data['data-x'], + 'data_y': data['data-y'], + }) + if data.get('height'): + block.write({ + 'height': f"{data['height']}px", + 'width': f"{data['width']}px", + }) + return True diff --git a/odoo_dynamic_dashboard/models/dashboard_menu.py b/odoo_dynamic_dashboard/models/dashboard_menu.py new file mode 100644 index 000000000..ba009b1b0 --- /dev/null +++ b/odoo_dynamic_dashboard/models/dashboard_menu.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) 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 odoo import api, fields, models + + +class DashboardMenu(models.Model): + """Class to create new dashboard menu""" + _name = "dashboard.menu" + _description = "Dashboard Menu" + + name = fields.Char(string="Name", ondelete='cascade', + help="Enter a name for the dashboard menu") + menu_id = fields.Many2one('ir.ui.menu', string="Parent Menu", + help="Parent Menu Location of New Dashboard", + ondelete='cascade') + group_ids = fields.Many2many('res.groups', string='Groups', + related='menu_id.groups_id', + help="User need to be at least in one of " + "these groups to see the menu") + client_action_id = fields.Many2one('ir.actions.client', + string="Client Action", + help="Client action of the " + "corresponding dashboard menu") + + @api.model + def create(self, vals): + """Function to create new dashboard menu""" + action_id = self.env['ir.actions.client'].create([{ + 'name': vals['name'], + 'tag': 'OdooDynamicDashboard', + }]) + vals['client_action_id'] = action_id.id + self.env['ir.ui.menu'].create([{ + 'name': vals['name'], + 'parent_id': vals['menu_id'], + 'action': 'ir.actions.client,%d' % (action_id.id,) + }]) + return super(DashboardMenu, self).create(vals) + + def write(self, vals): + """Function to save edited data in dashboard menu""" + for rec in self: + client_act_id = rec['client_action_id'].id + self.env['ir.ui.menu'].search( + [('parent_id', '=', rec['menu_id'].id), + ('action', '=', f'ir.actions.client,{client_act_id}')]).write({ + 'name': vals['name'] if 'name' in vals.keys() else rec['name'], + 'parent_id': vals['menu_id'] if 'menu_id' in vals.keys() else + rec['menu_id'], + 'action': f'ir.actions.client,{client_act_id}' + }) + return super(DashboardMenu, self).write(vals) + + def unlink(self): + """Delete dashboard along with menu item""" + for rec in self: + self.env['ir.ui.menu'].search( + [('parent_id', '=', rec['menu_id'].id), + ('action', '=', + f'ir.actions.client,{rec["client_action_id"].id}')]).unlink() + return super(DashboardMenu, self).unlink() diff --git a/odoo_dynamic_dashboard/models/dashboard_theme.py b/odoo_dynamic_dashboard/models/dashboard_theme.py new file mode 100644 index 000000000..dd5179e54 --- /dev/null +++ b/odoo_dynamic_dashboard/models/dashboard_theme.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) 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 odoo import api, fields, models + + +class DashboardTheme(models.Model): + _name = 'dashboard.theme' + _description = 'Dashboard Theme' + + name = fields.Char(string='Theme Name', help='Name of the theme') + color_x = fields.Char(string='Color X', help='Select the color_x for theme', + default='#4158D0') + color_y = fields.Char(string='Color Y', help='Select the color_y for theme', + default='#C850C0') + color_z = fields.Char(string='Color Z', help='Select the color_z for theme', + default='#FFCC70') + body = fields.Html(string='Body', help='Preview of the theme will be shown') + style = fields.Char(string='Style', + help='It store the style of the gradient') + + @api.constrains('name', 'color_x', 'color_y', 'color_z') + def save_record(self): + """ + Function for saving the datas including body and style + """ + self.body = f"
" + self.style = f"background-image: linear-gradient(50deg, {self.color_x} 0%, {self.color_y} 46%, {self.color_z} 100%);" + + def get_records(self): + """ + Function for returning all records with fields name and style + """ + records = self.search_read([], ['name', 'style']) + return records diff --git a/odoo_dynamic_dashboard/models/domain_to_sql.py b/odoo_dynamic_dashboard/models/domain_to_sql.py new file mode 100644 index 000000000..766fd269e --- /dev/null +++ b/odoo_dynamic_dashboard/models/domain_to_sql.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) 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 odoo import models + + +def get_query(self, args, operation, field, start_date=None, end_date=None, + group_by=False, apply_ir_rules=False): + """ Dashboard block Query Creation """ + query = self._where_calc(args) + if apply_ir_rules: + self._apply_ir_rules(query, 'read') + if operation and field: + data = 'COALESCE(%s("%s".%s),0) AS value' % ( + operation.upper(), self._table, field.name) + join = '' + group_by_str = '' + if group_by: + if group_by.ttype == 'many2one': + relation_model = group_by.relation.replace('.', '_') + join = ' INNER JOIN %s on "%s".id = "%s".%s' % ( + relation_model, relation_model, self._table, group_by.name) + rec_name = self.env[group_by.relation]._rec_name_fallback() + data = data + ',"%s".%s AS %s' % ( + relation_model, rec_name, group_by.name) + group_by_str = ' Group by "%s".%s' % (relation_model, rec_name) + else: + data = data + ',"%s".%s' % (self._table, group_by.name) + group_by_str = ' Group by "%s".%s' % ( + self._table, str(group_by.name)) + else: + data = '"%s".id' % (self._table) + from_clause, from_params = query.from_clause + where_clause, where_clause_params = query.where_clause + where_str = where_clause and (" WHERE %s" % where_clause) or '' + if start_date and start_date != 'null': + start_date_query = f' AND ({from_clause}."create_date" >= \'{start_date}\')' + else: + start_date_query = '' + if end_date and end_date != 'null': + end_date_query = f' AND ({from_clause}."create_date" <= \'{end_date}\')' + else: + end_date_query = '' + query_str = 'SELECT %s FROM ' % data + from_clause + join + where_str + start_date_query + end_date_query + group_by_str + def format_param(x): + if not isinstance(x, tuple): + return "'" + str(x) + "'" + elif isinstance(x, tuple) and len(x) == 1: + return "(" + str(x[0]) + ")" + else: + return str(x) + exact_query = query_str % tuple(map(format_param, where_clause_params)) + return exact_query +models.BaseModel.get_query = get_query diff --git a/odoo_dynamic_dashboard/security/ir.model.access.csv b/odoo_dynamic_dashboard/security/ir.model.access.csv new file mode 100644 index 000000000..e2bf6b1f6 --- /dev/null +++ b/odoo_dynamic_dashboard/security/ir.model.access.csv @@ -0,0 +1,5 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_dashboard_block_user,access.dashboard.block.user,model_dashboard_block,base.group_user,1,1,1,1 +access_dashboard_menu_user,access.dashboard.menu.user,model_dashboard_menu,base.group_user,1,1,1,1 +access_dashboard_theme_user,access.dashboard.theme.user,model_dashboard_theme,base.group_user,1,1,1,1 +access_dashboard_mail_user,access.dashboard.mail.user,model_dashboard_mail,base.group_user,1,1,1,1 diff --git a/odoo_dynamic_dashboard/static/description/assets/cybro-icon.png b/odoo_dynamic_dashboard/static/description/assets/cybro-icon.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/cybro-odoo.png b/odoo_dynamic_dashboard/static/description/assets/cybro-odoo.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/h2.png b/odoo_dynamic_dashboard/static/description/assets/h2.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/arrows-repeat.svg b/odoo_dynamic_dashboard/static/description/assets/icons/arrows-repeat.svg new file mode 100644 index 000000000..1d7efabc5 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/arrows-repeat.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/banner-1.png b/odoo_dynamic_dashboard/static/description/assets/icons/banner-1.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/banner-2.svg b/odoo_dynamic_dashboard/static/description/assets/icons/banner-2.svg new file mode 100644 index 000000000..e606d97d9 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/banner-2.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/banner-bg.png b/odoo_dynamic_dashboard/static/description/assets/icons/banner-bg.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/banner-bg.svg b/odoo_dynamic_dashboard/static/description/assets/icons/banner-bg.svg new file mode 100644 index 000000000..b1378103e --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/banner-bg.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/banner-call.svg b/odoo_dynamic_dashboard/static/description/assets/icons/banner-call.svg new file mode 100644 index 000000000..96c687e81 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/banner-call.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/banner-mail.svg b/odoo_dynamic_dashboard/static/description/assets/icons/banner-mail.svg new file mode 100644 index 000000000..cbf0d158d --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/banner-mail.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/banner-pattern.svg b/odoo_dynamic_dashboard/static/description/assets/icons/banner-pattern.svg new file mode 100644 index 000000000..9c1c7e101 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/banner-pattern.svg @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/banner-promo.svg b/odoo_dynamic_dashboard/static/description/assets/icons/banner-promo.svg new file mode 100644 index 000000000..d52791b11 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/banner-promo.svg @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/brand-pair.svg b/odoo_dynamic_dashboard/static/description/assets/icons/brand-pair.svg new file mode 100644 index 000000000..d8db7fc1e --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/brand-pair.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/check.png b/odoo_dynamic_dashboard/static/description/assets/icons/check.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/chevron.png b/odoo_dynamic_dashboard/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/close-icon.svg b/odoo_dynamic_dashboard/static/description/assets/icons/close-icon.svg new file mode 100644 index 000000000..df8cce37a --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/close-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/cogs.png b/odoo_dynamic_dashboard/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/collabarate-icon.svg b/odoo_dynamic_dashboard/static/description/assets/icons/collabarate-icon.svg new file mode 100644 index 000000000..dd4e10518 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/collabarate-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/consultation.png b/odoo_dynamic_dashboard/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/cybro-logo.png b/odoo_dynamic_dashboard/static/description/assets/icons/cybro-logo.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/down.svg b/odoo_dynamic_dashboard/static/description/assets/icons/down.svg new file mode 100644 index 000000000..f21c36271 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/ecom-black.png b/odoo_dynamic_dashboard/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/education-black.png b/odoo_dynamic_dashboard/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/faq.png b/odoo_dynamic_dashboard/static/description/assets/icons/faq.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/feature-icon.svg b/odoo_dynamic_dashboard/static/description/assets/icons/feature-icon.svg new file mode 100644 index 000000000..fa0ea6850 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/feature-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/feature.png b/odoo_dynamic_dashboard/static/description/assets/icons/feature.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/gear.svg b/odoo_dynamic_dashboard/static/description/assets/icons/gear.svg new file mode 100644 index 000000000..0cc66b6ea --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/gear.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/hero.gif b/odoo_dynamic_dashboard/static/description/assets/icons/hero.gif new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/hire-odoo.svg b/odoo_dynamic_dashboard/static/description/assets/icons/hire-odoo.svg new file mode 100644 index 000000000..e1ac089b0 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/hire-odoo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/hotel-black.png b/odoo_dynamic_dashboard/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/license.png b/odoo_dynamic_dashboard/static/description/assets/icons/license.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/life-ring-icon.svg b/odoo_dynamic_dashboard/static/description/assets/icons/life-ring-icon.svg new file mode 100644 index 000000000..3ae6e1d89 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/life-ring-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/lifebuoy.png b/odoo_dynamic_dashboard/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/mail.svg b/odoo_dynamic_dashboard/static/description/assets/icons/mail.svg new file mode 100644 index 000000000..1eedde695 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/mail.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/manufacturing-black.png b/odoo_dynamic_dashboard/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/notes.png b/odoo_dynamic_dashboard/static/description/assets/icons/notes.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/notification icon.svg b/odoo_dynamic_dashboard/static/description/assets/icons/notification icon.svg new file mode 100644 index 000000000..053189973 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/notification icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/odoo-consultancy.svg b/odoo_dynamic_dashboard/static/description/assets/icons/odoo-consultancy.svg new file mode 100644 index 000000000..e05f65bde --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/odoo-consultancy.svg @@ -0,0 +1,4 @@ + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/odoo-licencing.svg b/odoo_dynamic_dashboard/static/description/assets/icons/odoo-licencing.svg new file mode 100644 index 000000000..2606c88b0 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/odoo-licencing.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/odoo-logo.png b/odoo_dynamic_dashboard/static/description/assets/icons/odoo-logo.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/patter.svg b/odoo_dynamic_dashboard/static/description/assets/icons/patter.svg new file mode 100644 index 000000000..25c9c0a8f --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/patter.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/pattern1.png b/odoo_dynamic_dashboard/static/description/assets/icons/pattern1.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/pos-black.png b/odoo_dynamic_dashboard/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/puzzle-piece-icon.svg b/odoo_dynamic_dashboard/static/description/assets/icons/puzzle-piece-icon.svg new file mode 100644 index 000000000..3e9ad9373 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/puzzle-piece-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/puzzle.png b/odoo_dynamic_dashboard/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/replace-icon.svg b/odoo_dynamic_dashboard/static/description/assets/icons/replace-icon.svg new file mode 100644 index 000000000..d0e3a7af1 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/replace-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/restaurant-black.png b/odoo_dynamic_dashboard/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/screenshot-main.png b/odoo_dynamic_dashboard/static/description/assets/icons/screenshot-main.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/screenshot.png b/odoo_dynamic_dashboard/static/description/assets/icons/screenshot.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/service-black.png b/odoo_dynamic_dashboard/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/skype-fill.svg b/odoo_dynamic_dashboard/static/description/assets/icons/skype-fill.svg new file mode 100644 index 000000000..c17423639 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/skype-fill.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/skype.png b/odoo_dynamic_dashboard/static/description/assets/icons/skype.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/skype.svg b/odoo_dynamic_dashboard/static/description/assets/icons/skype.svg new file mode 100644 index 000000000..df3dad39b --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/skype.svg @@ -0,0 +1,3 @@ + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/star-1.svg b/odoo_dynamic_dashboard/static/description/assets/icons/star-1.svg new file mode 100644 index 000000000..7e55ab162 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/star-1.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/star-2.svg b/odoo_dynamic_dashboard/static/description/assets/icons/star-2.svg new file mode 100644 index 000000000..5ae9f507a --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/star-2.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/support.png b/odoo_dynamic_dashboard/static/description/assets/icons/support.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/test-1 - Copy.png b/odoo_dynamic_dashboard/static/description/assets/icons/test-1 - Copy.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/test-1.png b/odoo_dynamic_dashboard/static/description/assets/icons/test-1.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/test-2.png b/odoo_dynamic_dashboard/static/description/assets/icons/test-2.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/trading-black.png b/odoo_dynamic_dashboard/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/training.png b/odoo_dynamic_dashboard/static/description/assets/icons/training.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/translate.svg b/odoo_dynamic_dashboard/static/description/assets/icons/translate.svg new file mode 100644 index 000000000..af9c8a1aa --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/translate.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/update.png b/odoo_dynamic_dashboard/static/description/assets/icons/update.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/user.png b/odoo_dynamic_dashboard/static/description/assets/icons/user.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/video.png b/odoo_dynamic_dashboard/static/description/assets/icons/video.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/whatsapp.png b/odoo_dynamic_dashboard/static/description/assets/icons/whatsapp.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/wrench-icon.svg b/odoo_dynamic_dashboard/static/description/assets/icons/wrench-icon.svg new file mode 100644 index 000000000..174b5a465 --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/assets/icons/wrench-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/odoo_dynamic_dashboard/static/description/assets/icons/wrench.png b/odoo_dynamic_dashboard/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/modules/1.gif b/odoo_dynamic_dashboard/static/description/assets/modules/1.gif new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/modules/2.gif b/odoo_dynamic_dashboard/static/description/assets/modules/2.gif new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/modules/3.png b/odoo_dynamic_dashboard/static/description/assets/modules/3.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/modules/4.png b/odoo_dynamic_dashboard/static/description/assets/modules/4.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/modules/5.png b/odoo_dynamic_dashboard/static/description/assets/modules/5.png new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/modules/6.jpg b/odoo_dynamic_dashboard/static/description/assets/modules/6.jpg new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/Tiles.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/Tiles.png new file mode 100644 index 000000000..840ca3952 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/Tiles.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/additems.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/additems.png new file mode 100644 index 000000000..4d14bbaa3 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/additems.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/blocks.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/blocks.png new file mode 100644 index 000000000..4faac43c8 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/blocks.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/charts.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/charts.png new file mode 100644 index 000000000..12cec0141 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/charts.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/darkmode.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/darkmode.png new file mode 100644 index 000000000..07152ceef Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/darkmode.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/dashboard_create.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/dashboard_create.png new file mode 100644 index 000000000..f57a3343f Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/dashboard_create.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/delete.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/delete.png new file mode 100644 index 000000000..315c6fc9e Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/delete.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/editlayout.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/editlayout.png new file mode 100644 index 000000000..bf566acf4 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/editlayout.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/email.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/email.png new file mode 100644 index 000000000..00f2f0d96 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/email.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/email_report.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/email_report.png new file mode 100644 index 000000000..e8a7442d6 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/email_report.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/hero.gif b/odoo_dynamic_dashboard/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..d507e8d96 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/hero.gif differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/mainpage.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/mainpage.png new file mode 100644 index 000000000..19508c10a Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/mainpage.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/newbar.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/newbar.png new file mode 100644 index 000000000..f645291ad Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/newbar.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/newtile.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/newtile.png new file mode 100644 index 000000000..e1b51dc80 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/newtile.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/pdf.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/pdf.png new file mode 100644 index 000000000..5fce57032 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/pdf.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/pdf_and_mail.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/pdf_and_mail.png new file mode 100644 index 000000000..5944d04ea Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/pdf_and_mail.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/redirect.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/redirect.png new file mode 100644 index 000000000..481e80450 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/redirect.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/sales_dashboard.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/sales_dashboard.png new file mode 100644 index 000000000..1cc77c546 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/sales_dashboard.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/savetypes.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/savetypes.png new file mode 100644 index 000000000..8ab132751 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/savetypes.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/themes.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/themes.png new file mode 100644 index 000000000..47905fb23 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/themes.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/screenshots/themeselect.png b/odoo_dynamic_dashboard/static/description/assets/screenshots/themeselect.png new file mode 100644 index 000000000..86d3437c3 Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/assets/screenshots/themeselect.png differ diff --git a/odoo_dynamic_dashboard/static/description/assets/y18.jpg b/odoo_dynamic_dashboard/static/description/assets/y18.jpg new file mode 100644 index 000000000..e69de29bb diff --git a/odoo_dynamic_dashboard/static/description/banner.gif b/odoo_dynamic_dashboard/static/description/banner.gif new file mode 100644 index 000000000..a35ece8df Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/banner.gif differ diff --git a/odoo_dynamic_dashboard/static/description/icon.png b/odoo_dynamic_dashboard/static/description/icon.png new file mode 100644 index 000000000..72141ec9d Binary files /dev/null and b/odoo_dynamic_dashboard/static/description/icon.png differ diff --git a/odoo_dynamic_dashboard/static/description/index.html b/odoo_dynamic_dashboard/static/description/index.html new file mode 100644 index 000000000..2a5c93b6c --- /dev/null +++ b/odoo_dynamic_dashboard/static/description/index.html @@ -0,0 +1,1307 @@ + + + + + + Odoo Dynamic Dashboard + + + + + + + + + + +
+
+ + + +
+
+ Community +
+
+ Enterprise +
+ + + + +
+
+ +
+
+
+
+

+ This Module Helps To Create Configurable Dashboards Easily. +

+

Odoo Dynamic Dashboard +

+
+
+ +
+ +
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+

Key + Heighlights

+
+
+
+
+ +
+
+ Easily Create Dynamic Charts And Tiles +
+
+
+
+
+
+ +
+
+ Create A Dynamic Dashboard Menu In Any Model +
+
+
+
+
+
+ +
+
+ Charts Can Export Into Image, PDF, XLSX And CSV +
+
+
+
+
+
+ +
+
+ Edit And Configure Charts And Tiles. +
+
+
+
+
+ +
+
+
+ Odoo Dynamic Dashboard +

+ Are you ready to make your business more + organized? +
Improve now! +

+ +
+
+ +
+
+
+ + + + +
+
+ +
+
+
+
+ acc_bg +
+ +
+
+
+
+

+ Odoo Dynamic Dashboard + + View +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ Create New Dashboard Tiles View. + +

+
+
+

The tiled view of the records in Odoo is also clickable; when you click on a record, you will be directed to the records tree view. +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ Dashboard Charts View + +

+
+
+

The chart view of the records in Odoo is provided in the dashboard based on the filtering. +

+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+

Clicking on various icons generates different types of chart data, which can be exported as image, PDF, CSV, and XLSX formats. +

+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+

By clicking cross icon you can delete the chart and also the same for tile. +

+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+

Select Type Of The Item. +

+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+

+ When choosing the "Tile" option, input a name for the tile, select a model, operation type, and measured field. Additionally, customize the tile with an icon and color. +

+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+

When opting for "Charts," provide a name for the chart, select a model, operation type, and measured field, along with filters. Additionally, choose the chart type, set its size, and specify the grouping for the Y-axis. +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ Edit Layout +

+
+
+

You can change the position of the item and resize the item.

+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+

By double-clicking the tile, it will redirect to the corresponding tree view.

+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+

Dark mode.

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ Dashboard Menu +

+
+
+

You can add dashboard menu in any module. Add a name for the menu and select the parent menu also.

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ Dashboard Block +

+
+
+

You can see all the tiles and charts created in the Dashboard Block menu.

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ Dashboard Theme +

+
+
+

Customize the Dashboard Theme via Configuration > Dashboard Theme. Then, choose the configured theme for your dashboard.

+
+
+
+ + +
+
+
+
+
+
+
+
+
+

+ Print PDF +

+
+
+

Print & Mail whole dashboard in PDF format by clicking the PDF or Mail icon.

+
+
+
+ + +
+
+
+
+
+
+
+
+
+

+ Send Mail +

+
+
+

Clicking the Mail icon brings up a wizard, where you can select users and then click the SEND button.

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ Demo Mail +

+
+
+

Clicking the Mail icon brings up a wizard, where you can select users and then click the SEND button.

+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+

+ Interactive User Interface.

+
+ +
+
+
+
+
+
+ +
+

Easily Create Dynamic Charts And Tiles

+
+
+
+
+
+
+
+ +
+

Create A Dynamic Dashboard Menu In Any Model

+
+
+
+
+
+
+
+ +
+

Charts Can Export Into Image, PDF, XLSX And CSV.

+
+
+
+
+
+
+
+ +
+

Edit And Configure Charts And Tiles.

+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+

Yes you can use. +

+
+
+ +
+ +
+

You can. +

+
+
+
+
+
+
+
+
+
+ +
+
+

+ Latest Release 18.0.1.0.0 +

+ + 15th October, 2024 + +
+
+
+
+
+ Add +
+
+
+
    +
  • + Initial Commit +
  • + +
+
+
+
+
+
+
+
+
+
+ + + + + + +
+

+ Our Services

+ +
+ +
+
+ .... +
+
+ +
+ + +
+
+ + + + + + diff --git a/odoo_dynamic_dashboard/static/src/css/dynamic_dashboard.css b/odoo_dynamic_dashboard/static/src/css/dynamic_dashboard.css new file mode 100644 index 000000000..3447b9dd6 --- /dev/null +++ b/odoo_dynamic_dashboard/static/src/css/dynamic_dashboard.css @@ -0,0 +1,344 @@ +.row { + margin: 1rem; +} +.resize-drag { + border-radius: 8px; + padding: 20px; + margin: 1rem; + color: white; + font-size: 20px; + font-family: sans-serif; + + touch-action: none; + box-sizing: border-box; +} + +.theme { + position: absolute; + right: 60.5em; + padding-top:inherit; +} + +.card { + background-color: transparent !important; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + border-radius: 5px !important; + cursor: pointer; + transition: transform 0.2s; +} + +.dashboard_pdf{ + position: absolute; + right: 26.5em; + padding-top:inherit; +} + +.dashboard_mail{ + position: absolute; + right: 24.5em; + padding-top:inherit; +} + +.resize-drag { + position: relative !important; + font-size: 100%; + overflow:hidden; +} + +h2, h3 { + font-size: 150% !important; +} + +.container { + max-width: 100% !important; +} + +.tile { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + border-radius: 5px; + cursor: pointer; + transition: transform 0.2s; +} + +div.card-header { + color: #383838; + background-color: #70659647 !important; +} + +/* The toggle-btn - the box around the slider */ +.layout-switch { + font-size: 15px; + position: absolute; + left: 10.5em; + display: inline-block; + padding: 0 0 0 0; + border-radius: 0.5rem; +} + +.modal-header .btn-close { + display: none; +} + +.modal-title{ + margin-inline-end: auto; +} + +.theme-text { + font-family: Arial, sans-serif; + font-size: 1em; + opacity: 70%; +} + +.search-group { + position: absolute; + right: 1.7em; +} + +.block_setting { + position: absolute; + top: 7px; + left: 10px; +} + +.block_delete { + position: absolute; + top: 7px; + right: 10px; +} + +.tile_edit { + color: #d2d2d2; +} + +.block_edit { + color: #3f3f3f; +} + +.block_setting, .block_delete, .block_image, .block_pdf, .block_xlsx, .block_csv, .block_export { + display: none; +} + +.resize-drag:hover .block_setting, +.resize-drag:hover .block_xlsx, +.resize-drag:hover .block_csv, +.resize-drag:hover .block_image, +.resize-drag:hover .block_pdf, +.resize-drag:hover .block_export, +.resize-drag:hover .block_delete { + display: block; +} + +.chart-edit { + position: absolute; + top: 0px; + left: 3px; + font-size: 16px; +} + +.chart-image { + position: absolute; + top: 3px; + right: 106px; + font-size: 16px; +} + +.chart-pdf { + position: absolute; + top: 3px; + right: 82px; + font-size: 16px; +} + +.chart-csv { + position: absolute; + top: 3px; + right: 58px; + font-size: 16px; +} + +.chart-xlsx { + position: absolute; + top: 6px; + right: 34px; + font-size: 15px; +} + +.chart-setting { + position: absolute; + top: 0px; + right: 3px; + font-size: 16px; +} + +.chart_title { + padding-top: 0.7em; + text-align: center; + font-size: 16px; +} + +input:checked + .slider:before { + -webkit-transform: translateX(26px); + -ms-transform: translateX(26px); + transform: translateX(26px); +} + +.move_slider { + -webkit-transform: translateX(26px); + -ms-transform: translateX(26px); + transform: translateX(26px); +} + +/* Rounded sliders */ +.slider.round { + border-radius: 34px; + margin: -1px 6px 11px 0; +} + +.slider.round:before { + border-radius: 50%; +} + +.o_kanban_record { + background-color: #e8e8e8 !important; +} + +.oe_module_name { + background-color: #ffffff !important; +} + +.bootbox .modal-footer .btn-danger:hover { + background-color: #ff595c; +} + +.bootbox .modal-footer .btn-danger { + box-shadow: none; + margin-left: 0.5rem; +} + +.bootbox .modal-header { + text-shadow: -1px 3px 5px #b4b4b4; +} + +.bootbox .modal-body { + font-size: 14px; + text-shadow: -1px 3px 5px #b4b4b4; + color: #000000; +} + +.dropdown-addblock, .o-dropdown-menu { + left: 2.5em; + top: 2.5em; +} + +.navbar { + top:10px; + padding: 1.2rem 0 2.6rem 0 !important; + border-bottom: 1px solid #3f3f3f1a !important; + color: #444444; + background-color: #ffffff !important; +} + +.theme_icon:hover { + text-shadow: 0px 0px 5px #9388ff; +} + +.navbar-style { + margin-top: 1.2em; + border-radius: 0.5em; +} + +.dropdown-add-items { + position: absolute; + color: #e4e4e4; + left: 2em; + font-size: 16px; + text-transform: uppercase; + background-color: #71639e; + border: 1px solid transparent; + padding: 0.375rem 0.75rem; + font-size: 1.08333333rem; + border-radius: 0.25rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +.dropdown-add-items:hover { + color: white; + background-color: #59507b; +} + +@media (max-width: 767px) { + .navbar { + padding: 1.2rem 0 1.2rem 0; + } + + .navbar:focus, .navbar:active { + padding: 1.2rem 0 2rem 0; + } + + .o_web_client.o_touch_device .btn, .o_web_client.o_touch_device .btn .btn-sm, .o_web_client.o_touch_device .btn .btn-group-sm > .btn { + font-size: 1.08333333rem; + padding: 6px 8px; + margin-top: 39px; + margin-left: -39px; + } + + .dropdown-item { + font-size: 1.08333333rem; + font-weight: 500; + } + + .dropdown-addblock, .o-dropdown-menu { + left: -3.5em; + padding: 0em 7em; + margin-top: 38px; + width: 276px; + } + + .toggle-btn { + position: absolute; + margin-top: -16px; + margin-left: 56px; + left: 1.2em; + top: 2.3em; + height: 10px; + } + + #edit_layout { + display: none; + border-radius: inherit; + } + + #search-button { + position: relative; + left: 3.5em; + } + + #searchclear { + position: absolute; + margin: 0.3rem 0 0 9.9rem; + } + + .search-box { + top: -3em; + left: 7.5em; + margin: 0em -1.9em; + width: 79%; + } + + + .navbar-toggler { + margin: 0.2em 1em; + padding: 0.25rem 0.5rem; + } + + .dropdown-add-items { + position: absolute; + color: #e4e4e4; + top: -2.6em; + left: 3.5em; + } +} diff --git a/odoo_dynamic_dashboard/static/src/js/dynamic_dashboard.js b/odoo_dynamic_dashboard/static/src/js/dynamic_dashboard.js new file mode 100644 index 000000000..68f016423 --- /dev/null +++ b/odoo_dynamic_dashboard/static/src/js/dynamic_dashboard.js @@ -0,0 +1,391 @@ +/** @odoo-module **/ +import { registry } from "@web/core/registry"; +import { loadJS } from '@web/core/assets'; +import { DynamicDashboardTile} from './dynamic_dashboard_tile'; +import { DynamicDashboardChart} from './dynamic_dashboard_chart'; +import { useService } from "@web/core/utils/hooks"; +const { Component, useRef, mount, onWillStart, onMounted} = owl; +import { rpc } from "@web/core/network/rpc"; + +export class OdooDynamicDashboard extends Component { + // Setup function to run when the template of the class OdooDynamicDashboard renders + setup() { + this.ThemeSelector = useRef('ThemeSelector'); + this.action = useService("action"); + this.orm = useService("orm"); + this.dialog = useService("dialog"); + this.actionId = this.props.actionId + this.rpc = rpc; + onWillStart(async () => { + await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js") + await loadJS("https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js") + await loadJS("https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.9.3/html2pdf.bundle.min.js") + }) + onMounted(()=>{ + this.renderDashboard(); + }) + } + + onChangeTheme(){ + /* Function for changing color of the theme of the dashboard */ + $(".container").attr('style', this.ThemeSelector.el.value + 'min-height:-webkit-fill-available;') + } + + ResizeDrag() { + /* Function for resizing and dragging the div resize-drag */ + $('.items .resize-drag').each(function(index, element) { + interact(element).resizable({ + edges: { left: true, right: true, bottom: true, top: true }, + listeners: { + move (event) { + var target = event.target + var x = (parseFloat(target.getAttribute('data-x')) || 0) + var y = (parseFloat(target.getAttribute('data-y')) || 0) + // update the element's style + target.style.width = event.rect.width + 'px' + target.style.height = event.rect.height + 'px' + // translate when resizing from top or left edges + x += event.deltaRect.left + y += event.deltaRect.top + } + }, + modifiers: [ + // keep the edges inside the parent + interact.modifiers.restrictEdges({ + outer: 'parent' + }), + // minimum size + interact.modifiers.restrictSize({ + min: { width: 100, height: 50 } + }) + ], + inertia: true + }).draggable({ + listeners: {move: dragMoveListener}, + inertia: true, + modifiers: [ + interact.modifiers.restrictRect({ + restriction: 'parent', + endOnly: true + }) + ] + }) + + function dragMoveListener (event) { + var target = event.target + // keep the dragged position in the data-x/data-y attributes + var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx + var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy + // translate the element + target.style.transform = 'translate(' + x + 'px, ' + y + 'px)' + // update the posiion attributes + target.setAttribute('data-x', x) + target.setAttribute('data-y', y) + } + // this function is used later in the resizing + window.dragMoveListener = dragMoveListener + }); + } + + async renderDashboard(){ + /* Function for rendering the dashboard */ + var self = this; + $("#save_layout").hide(); + await this.orm.call('dashboard.theme', 'get_records', [[]]).then(function (response) { + response.forEach((ev) => { + const options = document.createElement("option"); + options.value = ev.style; + options.text = ev.name; + self.ThemeSelector.el.append(options) + }); + }) + await this.orm.call("dashboard.block", "get_dashboard_vals", [[], this.actionId]).then( function (response){ + for (let i = 0; i < response.length; i++) { + if (response[i].type === 'tile'){ + mount(DynamicDashboardTile, $('.items')[0], { props: { + widget: response[i], doAction: self.action, dialog:self.dialog, orm: self.orm + }}); + } + else{ + mount(DynamicDashboardChart, $('.items')[0], { props: { + widget: response[i], doAction: self.action, rpc: self.rpc, dialog:self.dialog, orm: self.orm + }}); + } + } + }) + } + + editLayout(ev) { + /* Function for editing the layout , it enables resizing and dragging functionality */ + $('.items .resize-drag').each(function(index, element) { + interact(element).draggable(true) + interact(element).resizable(true) + }); + ev.stopPropagation(); + ev.preventDefault(); + $("#edit_layout").hide(); + $("#save_layout").show(); + this.ResizeDrag() + } + + saveLayout(ev){ + /* Function for saving the layout */ + var self = this; + ev.stopPropagation(); + ev.preventDefault(); + $("#edit_layout").show(); + $("#save_layout").hide(); + var data_list = [] + $('.items .resize-drag').each(function(index, element) { + interact(element).draggable(false) + interact(element).resizable(false) + data_list.push({ + 'id' : element.dataset['id'], + 'data-x': element.dataset['x'], + 'data-y': element.dataset['y'], + 'height': element.clientHeight, + 'width': element.clientWidth, + }) + }); + self.orm.call('dashboard.block','get_save_layout', [[], data_list]).then( function (response){ + window.location.reload(); + }); + } + + changeViewMode(ev){ + /* Function for changing the mode of the view */ + ev.stopPropagation(); + ev.preventDefault(); + const currentMode = $(".mode").attr("mode"); + if (currentMode == "light"){ + $('.theme').attr('style','display: none;') + $(".container").attr('style', 'background-color: #383E45;min-height:-webkit-fill-available; !important') + $(".mode").attr("mode", "dark") + $(".bi-moon-stars-fill").attr('class', 'bi bi-cloud-sun-fill view-mode-icon') + $(".bi-cloud-sun-fill").attr('style', 'color:black;margin-left:10px;') + $(".mode").attr('style','display: none !important'); + $("#search-input-chart").attr('style', 'background-color: white; !important') + $("#search-button").attr('style', 'background-color: #BB86FC; !important') + $("#dropdownMenuButton").attr('style', 'background-color: #03DAC5;margin-top:-4px; !important') + $("#text_add").attr('style', 'color: black; !important') + $(".date-label").attr('style', 'color: black;font-family:monospace; !important') + $(".block_setting").attr('style', 'color: white; !important') + $(".block_delete").attr('style', 'color: white; !important') + $(".block_image").attr('style', 'color: #03DAC5; !important') + $(".block_pdf").attr('style', 'color: #03DAC5; !important') + $(".block_csv").attr('style', 'color: #03DAC5; !important') + $(".block_xlsx").attr('style', 'color: #03DAC5; !important') + } + else { + $('.theme').attr('style','display: block;') + $(".container").attr('style', this.ThemeSelector.el.value + 'min-height:-webkit-fill-available;') + $(".mode").attr("mode", "light") + $(".bi-cloud-sun-fill").attr('class', 'bi bi-moon-stars-fill view-mode-icon') + $(".view-mode-icon").attr('style', 'color:black;margin-left:10px; !important') + $(".mode").attr('style','display: none !important'); + $(".mode").attr('style','color: white !important'); + $("#search-input-chart").attr('style', 'background-color: none; !important') + $("#search-button").attr('style', 'background-color: none; !important') + $("#dropdownMenuButton").attr('style', 'background-color: none;margin-top:-4px; !important') + $("#text_add").attr('style', 'color: white; !important') + $(".date-label").attr('style', 'color: black; !important;font-family:monospace; !important') + $(".block_setting").attr('style', 'color: black; !important') + $(".block_delete").attr('style', 'color: black; !important') + $(".block_image").attr('style', 'color: black; !important') + $(".block_pdf").attr('style', 'color: black; !important') + $(".block_csv").attr('style', 'color: black; !important') + $(".block_xlsx").attr('style', 'color: black; !important') + } + } + onClickAdd(event){ + /* For enabling the toggle button */ + event.stopPropagation(); + event.preventDefault(); + $(".dropdown-addblock").toggle() + } + onClickAddItem(event){ + /* Function for adding tiles and charts */ + event.stopPropagation(); + event.preventDefault(); + self = this; + var type = event.target.getAttribute('data-type'); + if (type == 'graph'){ + var chart_type = event.target.getAttribute('data-chart_type'); + } + if (type == 'tile'){ + var randomColor = '#' + ('000000' + Math.floor(Math.random() * 16777216).toString(16)).slice(-6); + this.action.doAction({ + type: 'ir.actions.act_window', + res_model: 'dashboard.block', + view_mode: 'form', + views: [[false, 'form']], + context: { + 'form_view_initial_mode': 'edit', + 'default_name': 'New Tile', + 'default_type': type, + 'default_height': '155px', + 'default_width': '300px', + 'default_tile_color': randomColor, + 'default_text_color': '#FFFFFF', + 'default_val_color': '#F3F3F3', + 'default_fa_icon': 'fa fa-bar-chart', + 'default_client_action_id': parseInt(self.actionId) + } + }) + } + else{ + this.action.doAction({ + type: 'ir.actions.act_window', + res_model: 'dashboard.block', + view_mode: 'form', + views: [[false, 'form']], + context: { + 'form_view_initial_mode': 'edit', + 'default_name': 'New ' + chart_type, + 'default_type': type, + 'default_height': '565px', + 'default_width': '588px', + 'default_graph_type': chart_type, + 'default_fa_icon': 'fa fa-bar-chart', + 'default_client_action_id': parseInt(self.actionId) + }, + }) + } + } + + dateFilter(){ + /* Function for filtering the data based on the creation date */ + $(".items").empty(); + var start_date = $("#start-date").val(); + var end_date = $("#end-date").val(); + var self = this; + if (!start_date){ + start_date = "null" + } + if (!end_date){ + end_date = "null" + } + this.orm.call("dashboard.block", "get_dashboard_vals", [[], this.actionId, start_date, end_date]).then( function (response){ + for (let i = 0; i < response.length; i++) { + if (response[i].type === 'tile'){ + mount(DynamicDashboardTile, $('.items')[0], { props: { + widget: response[i], doAction: self.action, dialog:self.dialog, orm: self.orm + }}); + } + else{ + mount(DynamicDashboardChart, $('.items')[0], { props: { + widget: response[i], doAction: self.action, rpc: self.rpc, dialog:self.dialog, orm: self.orm + }}); + } + } + }) + } + + async clickSearch(){ + /* Function for searching the blocks with their names */ + var input = $("#search-input-chart").val(); + await this.rpc('/custom_dashboard/search_input_chart', {'search_input': input}).then(function (response) { + var blocks = $(".items .resize-drag"); + blocks.each(function(index, element){ + var dataId = $(element).data('id'); + if (response.includes(dataId)){ + $(element).css("visibility", "visible"); + } + else{ + $(element).css("visibility", "hidden"); + } + }) + }) + } + + showViewMode(ev){ + /* Function for showing the mode text */ + const currentMode = $(".mode").attr("mode"); + if (currentMode == "light"){ + $(".mode").text("Dark Mode") + $(".mode").attr('style','display: inline-block !important; color: black !important'); + } + else{ + $(".mode").text("Light Mode") + $(".mode").attr('style','display: inline-block !important; color: black !important'); + } + } + hideViewMode(ev){ + /* Function for hiding the mode text */ + $(".mode").fadeOut(2000); + } + clearSearch(){ + /* Function for clearing the search input */ + $("#search-input-chart").val(''); + var blocks = $(".items .resize-drag"); + blocks.each(function(index, element){ + $(element).css("visibility", "visible"); + }) + } + + async printPdf() { + /* Function for printing whole dashboard in pdf format */ + var elements = $('.items .resize-drag') + var newElement = document.createElement('div'); + newElement.className = 'pdf'; + elements.each(function(index, elem){ + newElement.appendChild(elem); + }); + for (var x=0; x< $(newElement)[0].children.length; x++){ + $($(newElement)[0].children[x])[0].style.transform = "" + } + var opt = { + margin: 0.3, + filename: 'Dashboard.pdf', + image: { type: 'jpeg', quality: 1 }, + html2canvas: { scale: 1 }, + jsPDF: { unit: 'mm', format: 'a3', orientation: 'portrait' } + }; + html2pdf().set(opt).from(newElement).save().then(()=>{ + window.location.reload() + }) + } + + async createPDF(){ + /* Function for getting pdf data in string format */ + var elements = $('.items .resize-drag') + var newElement = document.createElement('div'); + newElement.className = 'pdf'; + elements.each(function(index, elem){ + newElement.appendChild(elem); + }); + for (var x=0; x< $(newElement)[0].children.length; x++){ + $($(newElement)[0].children[x])[0].style.transform = "" + } + var opt = { + margin: 0.3, + filename: 'Dashboard.pdf', + image: { type: 'jpeg', quality: 1 }, + html2canvas: { scale: 1 }, + jsPDF: { unit: 'mm', format: 'a3', orientation: 'portrait' } + }; + var pdf = html2pdf().set(opt).from(newElement).toPdf() + var pdfOutput = await pdf.output('datauristring'); + return pdfOutput + } + + async sendMail(){ + /* Function for creating pdf and sending mail to the selected users */ + /* This function calls the createPDF() function and returns the pdf datas */ + var created_pdf = await this.createPDF(); + var base64code = created_pdf.split(',')[1]; + this.action.doAction({ + type: 'ir.actions.act_window', + name: 'SEND MAIL', + res_model: 'dashboard.mail', + view_mode: 'form', + views: [[false, 'form']], + target: 'new', + context: { + 'default_base64code': base64code, + } + }) + } +} +OdooDynamicDashboard.template = "owl.OdooDynamicDashboard" +registry.category("actions").add("OdooDynamicDashboard", OdooDynamicDashboard) diff --git a/odoo_dynamic_dashboard/static/src/js/dynamic_dashboard_chart.js b/odoo_dynamic_dashboard/static/src/js/dynamic_dashboard_chart.js new file mode 100644 index 000000000..246a39300 --- /dev/null +++ b/odoo_dynamic_dashboard/static/src/js/dynamic_dashboard_chart.js @@ -0,0 +1,221 @@ +/** @odoo-module **/ +import { loadJS } from '@web/core/assets'; +import { getColor } from "@web/core/colors/colors"; +import { _t } from "@web/core/l10n/translation"; +import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog"; +const { Component, xml, onWillStart, useRef, onMounted } = owl + +export class DynamicDashboardChart extends Component { + // Setup function of the class DynamicDashboardChart + setup() { + this.doAction = this.props.doAction.doAction; + this.chartRef = useRef("chart"); + this.dialog = this.props.dialog; + onWillStart(async () => { + await loadJS("https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.0/chart.umd.min.js") + await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js") + await loadJS("https://cdn.jsdelivr.net/npm/exceljs@4.4.0/dist/exceljs.min.js") + }) + onMounted(()=> this.renderChart()) + } + // Function to export the chart in pdf, image, xlsx and csv format + exportItem(ev){ + ev.stopPropagation(); + ev.preventDefault(); + var type = $(ev.currentTarget).attr('data-type'); + var canvas = $($($(ev.currentTarget)[0].offsetParent)[0].children[0].lastChild).find("#canvas")[0] + var dataTitle = $(canvas).attr('data-title') + var bgCanvas = document.createElement("canvas"); + bgCanvas.width = canvas.width; + bgCanvas.height = canvas.height; + var bgCtx = bgCanvas.getContext("2d"); + bgCtx.fillStyle = "white"; + bgCtx.fillRect(0, 0, canvas.width, canvas.height); + bgCtx.drawImage(canvas, 0, 0); + var imgData = bgCanvas.toDataURL("image/png"); + if (type === 'png') { + var downloadLink = document.createElement('a'); + downloadLink.href = imgData; + downloadLink.download = `${dataTitle}.png`; + document.body.appendChild(downloadLink); + downloadLink.click(); + document.body.removeChild(downloadLink); + } + if (type === 'pdf') { + var pdf = new jsPDF(); + pdf.addImage(imgData, 'PNG', 0, 0); + pdf.save(`${dataTitle}.pdf`); + } + if (type === 'xlsx'){ + var rows = []; + var items = $('.resize-drag'); + for (let i = 0; i < items.length; i++) { + if ($(items[i]).attr('data-id') === $(ev.currentTarget).attr('data-id')) { + rows.push(this.props.widget.x_axis); + rows.push(this.props.widget.y_axis); + } + } + // Prepare the workbook + const workbook = new ExcelJS.Workbook(); + const worksheet = workbook.addWorksheet('My Sheet'); + for(let i = 0; i < rows.length; i++){ + worksheet.addRow(rows[i]); + } + const image = workbook.addImage({ + base64: imgData, + extension: 'png', + }); + worksheet.addImage(image, { + tl: { col: 0, row: 4 }, + ext: { width: canvas.width, height: canvas.height } + }); + // Save workbook to a file + workbook.xlsx.writeBuffer() + .then((buffer) => { + // Create a Blob object from the buffer + let blob = new Blob([buffer], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}); + let link = document.createElement('a'); + link.href = window.URL.createObjectURL(blob); + link.setAttribute("download", `${dataTitle}.xlsx`); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }) + } + if (type === 'csv') { + var rows = []; + var items = $('.resize-drag') + for (let i = 0; i < items.length; i++) { + if ($(items[i]).attr('data-id') === $(ev.currentTarget).attr('data-id')) { + rows.push(this.props.widget.x_axis); + rows.push(this.props.widget.y_axis); + } + } + let csvContent = "data:text/csv;charset=utf-8,"; + rows.forEach(function (rowArray) { + let row = rowArray.join(","); + csvContent += row + "\r\n"; + }); + var link = document.createElement("a"); + link.setAttribute("href", encodeURI(csvContent)); + link.setAttribute("download", `${dataTitle}.csv`); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } + } + // Function to get the configuration of the chart + async getConfiguration(ev){ + ev.stopPropagation(); + ev.preventDefault(); + var id = this.props.widget.id + await this.doAction({ + type: 'ir.actions.act_window', + res_model: 'dashboard.block', + res_id: id, + view_mode: 'form', + views: [[false, "form"]] + }); + } + // Function to remove the chart + async removeTile(ev){ + ev.stopPropagation(); + ev.preventDefault(); + this.dialog.add(ConfirmationDialog, { + title: _t("Delete Confirmation"), + body: _t("Are you sure you want to delete this item?"), + confirmLabel: _t("YES, I'M SURE"), + cancelLabel: _t("NO, GO BACK"), + confirm: async () => { + await this.props.orm.unlink("dashboard.block", [this.props.widget.id]); + location.reload(); + }, + cancel: () => {}, + }); + } + // Function to render the chart + renderChart(){ + if (this.props.widget.graph_type){ + const x_axis = this.props.widget.x_axis + const y_axis = this.props.widget.y_axis + const data = [] + for (let i = 0; i < x_axis.length; i++) { + var key; + if(x_axis[i] && typeof(x_axis[i]) === 'object'){ + key = x_axis[i].en_US + } else { + key = x_axis[i] + } + const value = { key: key, value: y_axis[i] } + data.push(value); + } + new Chart( + this.chartRef.el, + { + type: this.props.widget.graph_type || 'bar', + data: { + labels: data.map(row => row.key), + datasets: [ + { + label: this.props.widget.measured_field || 'Data', + data: data.map(row => row.value), + backgroundColor: data.map((_, index) => getColor(index)), + hoverOffset : 4 + } + ] + }, + } + ); + } + } +} + +DynamicDashboardChart.template = xml` +
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+

+ +

+
+
+ +
+
+
+
+ ` diff --git a/odoo_dynamic_dashboard/static/src/js/dynamic_dashboard_tile.js b/odoo_dynamic_dashboard/static/src/js/dynamic_dashboard_tile.js new file mode 100644 index 000000000..eb5d6025c --- /dev/null +++ b/odoo_dynamic_dashboard/static/src/js/dynamic_dashboard_tile.js @@ -0,0 +1,90 @@ +/** @odoo-module **/ +import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog"; +import { _t } from "@web/core/l10n/translation"; +const { Component, xml } = owl; +import { rpc } from "@web/core/network/rpc"; + +export class DynamicDashboardTile extends Component { + // Setup function of the class DynamicDashboardTile + setup() { + this.doAction = this.props.doAction.doAction; + this.dialog = this.props.dialog; + this.orm = this.props.orm; + } + // Function to get the configuration of the tile + async getConfiguration(ev){ + ev.stopPropagation(); + ev.preventDefault(); + var id = this.props.widget.id + await this.doAction({ + type: 'ir.actions.act_window', + res_model: 'dashboard.block', + res_id: id, + view_mode: 'form', + views: [[false, "form"]] + }); + } + // Function to remove the tile + async removeTile(ev){ + ev.stopPropagation(); + ev.preventDefault(); + this.dialog.add(ConfirmationDialog, { + title: _t("Delete Confirmation"), + body: _t("Are you sure you want to delete this item?"), + confirmLabel: _t("YES, I'M SURE"), + cancelLabel: _t("NO, GO BACK"), + confirm: async () => { + await this.orm.unlink("dashboard.block", [this.props.widget.id]); + location.reload(); + }, + cancel: () => {}, + }); + } + // Function for getting records by double click + async getRecords(){ + var model_name = this.props.widget.model_name; + if (model_name){ + await this.doAction({ + type: 'ir.actions.act_window', + res_model: model_name, + view_mode: 'list', + views: [[false, "list"]], + domain: this.props.widget.domain, + }); + } + } +} +DynamicDashboardTile.template = xml ` +
+
+ + + + + + +
+ +
+
+

+ +

+
+

+ +

+
+
+
+
` \ No newline at end of file diff --git a/odoo_dynamic_dashboard/static/src/scss/dynamic_dashboard.scss b/odoo_dynamic_dashboard/static/src/scss/dynamic_dashboard.scss new file mode 100644 index 000000000..051245037 --- /dev/null +++ b/odoo_dynamic_dashboard/static/src/scss/dynamic_dashboard.scss @@ -0,0 +1,208 @@ + +:root { + /* Colors */ + --green: #00C689; + --blue: #3DA5F4; + --red: #F1536E; + --yellow: #FDA006; + /*Fonts*/ + --primary-font: 'Roboto', sans-serif; +} + +html .o_web_client > .o_action_manager { + overflow: auto; +} + +.bg-green { + background-color: var(--green); +} + +.bg-blue { + background-color: var(--blue); +} + +.bg-red { + background-color: var(--red); +} + +.bg-yellow { + background-color: var(--yellow); +} + +.text-color-yellow { + color: var(--yellow); +} + +.text-color-green { + color: var(--green); +} + +.text-color-blue { + color: var(--blue); +} + +.text-color-red { + color: var(--red); +} + +.text-color-yellow { + color: var(--yellow); +} + +.tile-container__icon-container { + border-radius: 50%; + width: 4.75rem; + height: 4.75rem; + font-size: 28px; + margin-left: 15px; +} + +.tile-container__status-container { + margin-left: 2em; +} + +.status-container__title { + font-family: var(--primary-font); + font-weight: 500; + font-size: 1.5rem; + line-height: 1.5rem; +} + +.status-container__figures { + font-family: var(--primary-font); +} + +.status-container__figures > h3 { + font-weight: 700; + font-size: 1.5rem; + line-height: 1.813rem; +} + +.tile-container__setting-icon { + top: 0.638rem; +} + +.dark-theme { + /* Add dark theme styles here */ + .block_edit { + color: #b7b7b7 !important; +} + +.theme_icon:hover { +text-shadow: 0px 0px 5px #9388ff; +} +.add_block{ + color: #dfdfdf; +} + #ExportMenu { + color: #626262; + } + + .chart_title { + color: #dfdfdf; + margin: -0.5em 0 2em 0; + } + + .btn-search_edit, { + color: #313131; + border: none; + background-color: #979797 !important; + } + + #search-input-chart { + color: #ffffff; + border: 1px solid #4e4e4e; + background-color: #2A2A2A !important; + } + + #search-clear { + color: #1f1f1f !important; + } + + div.navbar { + color: #909090; + background-color: #2A2A2A !important; + } + + .navbar-collapse { + margin-bottom: 12px !important; + } + + h3 { + color: #909090; + } + + div.dropdown-addblock { + color: #909090; + background-color: #2A2A2A !important; + } + + #dropdownMenuButton { + color: #313131; + background-color: #979797 !important; + } + + div.card-body { + border-radius: 0.5em !important; + background-color: #2a2a2a !important; + } + + .o_kanban_record { + background-color: #e8e8e8 !important; + } + + .o_kanban_renderer { + background-color: #e8e8e8 !important; + } + + .oe_module_name { + background-color: #ffffff !important; + } + + background-color: #1C1B1B; + @media (max-width: 767px) { + .navbar-light .navbar-toggler { + color: #A7A7A72D; + border-color: #F6F6F621; + } + } +} +.btn-align-items{ + width: 134px; + font-size: small; + border-radius: revert; + height: 33px; +} +#edit_layout{ + background-color: #0c8444; +} +#save_layout{ + background-color: #b53c5d; + width: 134px; + height: 33px; + font-size: small; + border-radius: revert; +} +#search-button{ + width: 69px; + margin-left: 5px; +} +#search-input-chart{ + width: 206px; + height: 34px; + border: 1px solid black; +} +.search-clear{ + margin-left: -80px; +} +label input{ + appearance: none; +} +.mode{ + padding-left: 7px; + font-family: 'odoo_ui_icons'; + display: none; +} +.view-mode-icon{ + font-size: x-large; +} \ No newline at end of file diff --git a/odoo_dynamic_dashboard/static/src/xml/dynamic_dashboard_template.xml b/odoo_dynamic_dashboard/static/src/xml/dynamic_dashboard_template.xml new file mode 100644 index 000000000..079723614 --- /dev/null +++ b/odoo_dynamic_dashboard/static/src/xml/dynamic_dashboard_template.xml @@ -0,0 +1,129 @@ + + + + +
+ +
+
+
+ +
+ + diff --git a/odoo_dynamic_dashboard/views/dashboard_menu_views.xml b/odoo_dynamic_dashboard/views/dashboard_menu_views.xml new file mode 100644 index 000000000..72d6ce90e --- /dev/null +++ b/odoo_dynamic_dashboard/views/dashboard_menu_views.xml @@ -0,0 +1,66 @@ + + + + + dashboard.menu.view.kanban + dashboard.menu + + + + + +
+
+

+ Name: + +

+
+
+
+
+ Parent: +
+
+ +
+
+
+
+
+
+
+
+ + + dashboard.menu.view.form + dashboard.menu + +
+ + + + + + + + + + +
+
+
+ + + + Dashboards Menu + ir.actions.act_window + dashboard.menu + kanban,form + + + +
diff --git a/odoo_dynamic_dashboard/views/dashboard_theme_views.xml b/odoo_dynamic_dashboard/views/dashboard_theme_views.xml new file mode 100644 index 000000000..bb1f46d64 --- /dev/null +++ b/odoo_dynamic_dashboard/views/dashboard_theme_views.xml @@ -0,0 +1,56 @@ + + + + + dashboard.theme.view.form + dashboard.theme + +
+ + +
+ +
+
+ + + + + + + + + + + +
+
+
+
+ + + + dashboard.theme.view.list + dashboard.theme + + + + + + + + + Dashboard Theme + ir.actions.act_window + dashboard.theme + list,form + + + + +
diff --git a/odoo_dynamic_dashboard/views/dashboard_views.xml b/odoo_dynamic_dashboard/views/dashboard_views.xml new file mode 100644 index 000000000..182b7f7da --- /dev/null +++ b/odoo_dynamic_dashboard/views/dashboard_views.xml @@ -0,0 +1,14 @@ + + + + + Dashboard + OdooDynamicDashboard + + + + diff --git a/odoo_dynamic_dashboard/views/dynamic_block_views.xml b/odoo_dynamic_dashboard/views/dynamic_block_views.xml new file mode 100644 index 000000000..f16f567e5 --- /dev/null +++ b/odoo_dynamic_dashboard/views/dynamic_block_views.xml @@ -0,0 +1,87 @@ + + + + + dashboard.block.view.form + dashboard.block + +
+ + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + dashboard.block.view.list + dashboard.block + + + + + + + + + + + Dashboard Block + ir.actions.act_window + dashboard.block + list,form + {'default_edit_mode' : True} + + + +
diff --git a/odoo_dynamic_dashboard/wizard/__init__.py b/odoo_dynamic_dashboard/wizard/__init__.py new file mode 100644 index 000000000..294ad3c78 --- /dev/null +++ b/odoo_dynamic_dashboard/wizard/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) 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 dashboard_mail diff --git a/odoo_dynamic_dashboard/wizard/dashboard_mail.py b/odoo_dynamic_dashboard/wizard/dashboard_mail.py new file mode 100644 index 000000000..fe85897bf --- /dev/null +++ b/odoo_dynamic_dashboard/wizard/dashboard_mail.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) 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 odoo import fields, models + + +class DashboardMail(models.TransientModel): + _name = 'dashboard.mail' + _description = 'Dashboard Mail' + + user_ids = fields.Many2many('res.users', string="Users", + domain="[('id','!=', uid)]", + help="Select User") + base64code = fields.Char(string='Base 64', help='Base64 Code of the pdf') + + def send_mail(self): + """ + Function for sending mail to the selected users + """ + for user in self.user_ids: + mail_content = ( + 'Hi %s,
' + 'I hope this mail finds you well. I am pleased to share the Dashboard Report with you.
' + 'Please find the attachment
') % user.name + mail_values = { + 'subject': 'Dashboard Report', + 'author_id': self.env.user.partner_id.id, + 'body_html': mail_content, + 'email_to': user.email, + } + mail_id = self.env['mail.mail'].create(mail_values) + attachment_values = { + 'name': 'Dashboard.pdf', + 'datas': self.base64code, + 'type': 'binary', + 'res_model': 'mail.mail', + 'res_id': mail_id.id, + } + attachment_id = self.env['ir.attachment'].create(attachment_values) + mail_id.write({ + 'attachment_ids': [(4, attachment_id.id)] + }) + mail_id.send() + + return { + 'type': 'ir.actions.client', + 'tag': 'reload', + } + + def cancel_mail(self): + """ + Function for refreshing the page while clicking cancel + """ + return { + 'type': 'ir.actions.client', + 'tag': 'reload', + } diff --git a/odoo_dynamic_dashboard/wizard/dashboard_mail_views.xml b/odoo_dynamic_dashboard/wizard/dashboard_mail_views.xml new file mode 100644 index 000000000..f58b57d4e --- /dev/null +++ b/odoo_dynamic_dashboard/wizard/dashboard_mail_views.xml @@ -0,0 +1,22 @@ + + + + + dashboard.mail.view.form + dashboard.mail + +
+ + + + + +
+
+
+
\ No newline at end of file