Browse Source

Apr 8 [UPDT] : Updated 'advanced_dynamic_dashboard'

pull/278/merge
AjmalCybro 1 year ago
parent
commit
1f9e200cce
  1. 24
      advanced_dynamic_dashboard/README.rst
  2. 11
      advanced_dynamic_dashboard/__init__.py
  3. 28
      advanced_dynamic_dashboard/__manifest__.py
  4. 8
      advanced_dynamic_dashboard/controllers/__init__.py
  5. 8
      advanced_dynamic_dashboard/controllers/advanced_dynamic_dashboard.py
  6. 2
      advanced_dynamic_dashboard/doc/RELEASE_NOTES.md
  7. 27
      advanced_dynamic_dashboard/hooks.py
  8. 8
      advanced_dynamic_dashboard/models/__init__.py
  9. 54
      advanced_dynamic_dashboard/models/dashboard_block.py
  10. 18
      advanced_dynamic_dashboard/models/dashboard_menu.py
  11. 48
      advanced_dynamic_dashboard/models/domain_to_sql.py
  12. 1
      advanced_dynamic_dashboard/security/ir.model.access.csv
  13. BIN
      advanced_dynamic_dashboard/static/description/assets/hero.gif
  14. BIN
      advanced_dynamic_dashboard/static/description/assets/icons/notes.png
  15. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/1.png
  16. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/10.png
  17. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/11.png
  18. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/12.png
  19. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/13.png
  20. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/14.png
  21. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/15.png
  22. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/16.png
  23. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/17.png
  24. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/18.png
  25. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/2.png
  26. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/3.png
  27. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/4.png
  28. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/5.png
  29. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/6.png
  30. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/7.png
  31. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/8.png
  32. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/9.png
  33. BIN
      advanced_dynamic_dashboard/static/description/assets/screenshots/hero.png
  34. 916
      advanced_dynamic_dashboard/static/description/index.html
  35. 16
      advanced_dynamic_dashboard/static/src/css/dynamic_dashboard.css
  36. 157
      advanced_dynamic_dashboard/static/src/js/dynamic_dashboard.js
  37. 59
      advanced_dynamic_dashboard/static/src/xml/dynamic_dashboard_template.xml
  38. 16
      advanced_dynamic_dashboard/views/dashboard_menu_views.xml
  39. 9
      advanced_dynamic_dashboard/views/dashboard_views.xml
  40. 15
      advanced_dynamic_dashboard/views/dynamic_block_views.xml
  41. 22
      advanced_dynamic_dashboard/wizard/__init__.py
  42. 75
      advanced_dynamic_dashboard/wizard/dashboard_mail.py
  43. 22
      advanced_dynamic_dashboard/wizard/dashboard_mail_views.xml

24
advanced_dynamic_dashboard/README.rst

@ -1,20 +1,19 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
.. 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
Advanced Dynamic Dashboard
================================================
==========================
* Dynamically Arrange the dashboard to get the information that are relevant to your business, department, or a specific process or need.
Installation
============
- www.odoo.com/documentation/16.0/setup/install.html
- Install our custom addon
Configuration
=============
- No configuration needed
License
-------
GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (AGPL v3)
(https://www.odoo.com/documentation/user/16.0/legal/licenses/licenses.html)
AFFERO GENERAL PUBLIC LICENSE, Version 3 (AGPL v3)
(https://www.gnu.org/licenses/agpl-3.0-standalone.html)
Company
-------
@ -22,16 +21,17 @@ Company
Credits
-------
* Developer:
(V16) Robin @Cybrosys, Afra MP @Cybrosys
* Developer: (V16) Robin, Afra MP, Contact: odoo@cybrosys.com
Contacts
--------
* Mail Contact : odoo@cybrosys.com
* Website : https://cybrosys.com
Bug Tracker
-----------
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported.
Bugs are tracked on GitHub Issues. In case of trouble, please check there if
your issue has already been reported.
Maintainer
==========

11
advanced_dynamic_dashboard/__init__.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
################################################################################
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Robin, Afra MP (odoo@cybrosys.com)
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
@ -18,7 +18,8 @@
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
#############################################################################
from . import controllers
from . import models
from . import wizard
from .hooks import uninstall_hook

28
advanced_dynamic_dashboard/__manifest__.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
################################################################################
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Robin, Afra MP (odoo@cybrosys.com)
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
@ -18,41 +18,44 @@
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
#############################################################################
{
'name': "Advanced Dynamic Dashboard",
'version': '16.0.2.0.1',
'version': '16.0.2.1.2',
'category': 'Productivity',
'summary': """Create Configurable Dashboards Easily""",
'summary': """Odoo Dynamic Dashboard, Dynamic Dashboard, Odoo Dashboard, Dynamic Dashbaord, AI Dashboard, Odoo17 Dashboard, Dashboard, Odoo17, Configurable Dashboard""",
'description': """Create Configurable Advanced Dynamic Dashboard to get the
information that are relevant to your
business, department, or a specific process or need""",
'author': 'Cybrosys Techno Solutions',
'website': "https://www.cybrosys.com",
'company': 'Cybrosys Techno Solutions',
'maintainer': 'Cybrosys Techno Solutions',
'depends': ['base', 'web'],
'website': "https://www.cybrosys.com",
'depends': ['web'],
'data': [
'security/ir.model.access.csv',
'views/dashboard_views.xml',
'views/dynamic_block_views.xml',
'views/dashboard_menu_views.xml',
'wizard/dashboard_mail_views.xml',
],
'assets': {
'web.assets_backend': [
'advanced_dynamic_dashboard/static/lib/css/gridstack.min.css',
'advanced_dynamic_dashboard/static/src/css/dynamic_dashboard.css',
'advanced_dynamic_dashboard/static/src/scss/dynamic_dashboard.scss',
"https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css",
'https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css',
'https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.2.6/gridstack.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js',
"https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js",
'https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.9.3/html2pdf.bundle.min.js',
'https://cdn.jsdelivr.net/npm/exceljs@4.4.0/dist/exceljs.min.js',
'advanced_dynamic_dashboard/static/src/js/dynamic_dashboard.js',
'advanced_dynamic_dashboard/static/src/xml/dynamic_dashboard_template.xml',
'https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700'
'https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700',
],
},
'images': ['static/description/banner.png'],
@ -60,4 +63,5 @@
'installable': True,
'auto_install': False,
'application': True,
'uninstall_hook': 'uninstall_hook',
}

8
advanced_dynamic_dashboard/controllers/__init__.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
################################################################################
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Robin, Afra MP (odoo@cybrosys.com)
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
@ -18,5 +18,5 @@
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
#############################################################################
from . import advanced_dynamic_dashboard

8
advanced_dynamic_dashboard/controllers/advanced_dynamic_dashboard.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
################################################################################
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Robin, Afra MP (odoo@cybrosys.com)
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
@ -18,7 +18,7 @@
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
#############################################################################
from odoo import http
from odoo.http import request

2
advanced_dynamic_dashboard/doc/RELEASE_NOTES.md

@ -1,6 +1,6 @@
## Module <advanced_dynamic_dashboard>
#### 15.07.2023
#### 22.03.2024
#### Version 16.0.1.0.0
#### ADD
- Initial commit for Advanced Dynamic Dashboard

27
advanced_dynamic_dashboard/hooks.py

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# 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 (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
from odoo import api, SUPERUSER_ID
def uninstall_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
env['dashboard.menu'].search([]).unlink()

8
advanced_dynamic_dashboard/models/__init__.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
################################################################################
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Robin, Afra MP (odoo@cybrosys.com)
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
@ -18,7 +18,7 @@
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
#############################################################################
from . import dashboard_block
from . import dashboard_menu
from . import domain_to_sql

54
advanced_dynamic_dashboard/models/dashboard_block.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
################################################################################
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Robin, Afra MP (odoo@cybrosys.com)
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
@ -18,11 +18,10 @@
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
#############################################################################
from ast import literal_eval
from datetime import datetime
from odoo import fields, models
from odoo import fields, models, api
from odoo.osv import expression
@ -43,10 +42,6 @@ class DashboardBlock(models.Model):
name = fields.Char(string="Name", help='Name of the block')
fa_icon = fields.Char(string="Icon", help="Add icon for tile")
graph_size = fields.Selection(
selection=[("col-lg-4", "Small"), ("col-lg-6", "Medium"),
("col-lg-12", "Large")],
string="Graph Size", default='col-lg-4', help="Select the graph size")
operation = fields.Selection(
selection=[("sum", "Sum"), ("avg", "Average"), ("count", "Count")],
string="Operation",
@ -59,7 +54,8 @@ class DashboardBlock(models.Model):
string="Chart Type", help='Type of Chart')
measured_field_id = fields.Many2one("ir.model.fields",
string="Measured Field",
help="Select the Measured")
help="Select the Measured",
create=False, edit=False)
client_action_id = fields.Many2one('ir.actions.client',
string="Client action",
default=get_default_action,
@ -75,10 +71,13 @@ class DashboardBlock(models.Model):
width = fields.Integer(string="width", help="Chart width")
group_by_id = fields.Many2one("ir.model.fields", store=True,
string="Group by(Y-Axis)",
help='Field value for Y-Axis')
help='Field value for Y-Axis', create=False,
edit=False)
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')
text_color = fields.Char(string="Text Color", help='Text Color of Tile',
default='#FFFFFF')
val_color = fields.Char(string="Value Color", help='Value Color of Tile',
default='#FFFFFF')
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',
@ -93,7 +92,7 @@ class DashboardBlock(models.Model):
"""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))]):
[('client_action_id', '=', int(action_id))]):
if rec.filter is False:
rec.filter = "[]"
@ -101,8 +100,7 @@ class DashboardBlock(models.Model):
# Remove existing date filters if they exist
filter_list = [filter_item for filter_item in filter_list if not (
isinstance(filter_item, tuple) and filter_item[
0] == 'create_date')]
isinstance(filter_item, tuple) and filter_item[0] == 'create_date')]
if start_date and start_date != 'null':
start_date_obj = datetime.strptime(start_date, '%Y-%m-%d')
@ -115,15 +113,14 @@ class DashboardBlock(models.Model):
('create_date', '<=', end_date_obj.strftime('%Y-%m-%d')))
rec.filter = repr(filter_list)
vals = {'id': rec.id, 'name': rec.name, 'type': rec.type,
'graph_type': rec.graph_type, 'icon': rec.fa_icon,
'cols': rec.graph_size,
'color': 'background-color: %s;' % rec.tile_color if rec.tile_color else '#1f6abb;',
'text_color': 'color: %s;' % rec.text_color if rec.text_color else '#FFFFFF;',
'val_color': 'color: %s;' % rec.val_color if rec.val_color else '#FFFFFF;',
'icon_color': 'color: %s;' % rec.tile_color if rec.tile_color else '#1f6abb;',
'x_pos': rec.x_pos,'y_pos': rec.y_pos, 'height': rec.height,
'x_pos': rec.x_pos, 'y_pos': rec.y_pos,
'height': rec.height,
'width': rec.width}
domain = []
if rec.filter:
@ -131,15 +128,16 @@ class DashboardBlock(models.Model):
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,
group_by=rec.group_by_id))
rec.operation,
rec.measured_field_id,
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'])
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 = []
@ -148,8 +146,8 @@ class DashboardBlock(models.Model):
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))
rec.operation,
rec.measured_field_id))
records = self._cr.dictfetchall()
magnitude = 0
total = records[0].get('value')
@ -164,6 +162,10 @@ class DashboardBlock(models.Model):
block_id.append(vals)
return block_id
@api.onchange('model_id')
def _onchange_model_id(self):
self.group_by_id = self.measured_field_id = self.filter = self.operation = ''
def get_save_layout(self, act_id, grid_data_list):
"""Function fetch edited values while edit layout of the chart or tile
and save values in a database"""

18
advanced_dynamic_dashboard/models/dashboard_menu.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
################################################################################
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Robin, Afra MP (odoo@cybrosys.com)
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
@ -18,7 +18,7 @@
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
#############################################################################
from odoo import api, fields, models
@ -61,11 +61,11 @@ class DashboardMenu(models.Model):
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}'
})
'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):

48
advanced_dynamic_dashboard/models/domain_to_sql.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
################################################################################
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Robin, Afra MP (odoo@cybrosys.com)
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
@ -18,17 +18,19 @@
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
#############################################################################
from odoo import models
def get_query(self, args, operation, field, group_by=False, apply_ir_rules=False):
def get_query(self, args, operation, field, 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)
data = 'COALESCE(%s("%s".%s),0) AS value' % (
operation.upper(), self._table, field.name)
join = ''
group_by_str = ''
if group_by:
@ -37,32 +39,30 @@ def get_query(self, args, operation, field, group_by=False, apply_ir_rules=False
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)
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))
group_by_str = ' Group by "%s".%s' % (
self._table, str(group_by.name))
else:
data = '"%s".id' % (self._table)
data = '"%s".id' % self._table
from_clause, where_clause, where_clause_params = query.get_sql()
where_str = where_clause and (" WHERE %s" % where_clause) or ''
if 'company_id' in self._fields:
if len(self.env.companies.ids) > 1:
operator = 'in'
company = str(tuple(self.env.companies.ids))
else:
operator = '='
company = self.env.companies.ids[0]
if where_str == '':
add = ' where'
query_str = 'SELECT %s FROM ' % data + from_clause + join + where_str + 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:
add = ' and'
multicompany_condition = '%s "%s".company_id %s %s' % (add, self._table, operator, company)
else:
multicompany_condition = ''
query_str = 'SELECT %s FROM ' % data + from_clause + join + where_str + multicompany_condition + group_by_str
return query_str % tuple(map(lambda x: "'" + str(x) + "'", where_clause_params))
return str(x)
exact_query = query_str % tuple(map(format_param, where_clause_params))
return exact_query
models.BaseModel.get_query = get_query

1
advanced_dynamic_dashboard/security/ir.model.access.csv

@ -1,3 +1,4 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_dashboard_block,access.dashboard.block,model_dashboard_block,base.group_user,1,1,1,1
access_dashboard_menu,access.dashboard.menu,model_dashboard_menu,base.group_user,1,1,1,1
access_dashboard_mail,access.dashboard.mail,model_dashboard_mail,base.group_user,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_dashboard_block access.dashboard.block model_dashboard_block base.group_user 1 1 1 1
3 access_dashboard_menu access.dashboard.menu model_dashboard_menu base.group_user 1 1 1 1
4 access_dashboard_mail access.dashboard.mail model_dashboard_mail base.group_user 1 1 1 1

BIN
advanced_dynamic_dashboard/static/description/assets/hero.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 MiB

BIN
advanced_dynamic_dashboard/static/description/assets/icons/notes.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 KiB

After

Width:  |  Height:  |  Size: 150 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/10.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 KiB

After

Width:  |  Height:  |  Size: 150 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/11.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 81 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/12.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 KiB

After

Width:  |  Height:  |  Size: 53 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/13.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 KiB

After

Width:  |  Height:  |  Size: 78 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/14.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 KiB

After

Width:  |  Height:  |  Size: 150 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/15.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 KiB

After

Width:  |  Height:  |  Size: 81 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/17.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 261 KiB

After

Width:  |  Height:  |  Size: 41 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/18.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

After

Width:  |  Height:  |  Size: 33 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 KiB

After

Width:  |  Height:  |  Size: 157 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/3.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 140 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/4.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 KiB

After

Width:  |  Height:  |  Size: 204 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/5.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 288 KiB

After

Width:  |  Height:  |  Size: 64 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/6.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 60 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/7.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/8.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 201 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/9.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 288 KiB

After

Width:  |  Height:  |  Size: 68 KiB

BIN
advanced_dynamic_dashboard/static/description/assets/screenshots/hero.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

916
advanced_dynamic_dashboard/static/description/index.html

File diff suppressed because it is too large

16
advanced_dynamic_dashboard/static/src/css/dynamic_dashboard.css

@ -14,6 +14,10 @@
transition: transform 0.2s;
}
.bootbox-close-button{
display:none;
}
.grid-stack-item {
position: absolute !important;
font-size: 100%;
@ -24,10 +28,6 @@ h2, h3 {
font-size: 150% !important;
}
.card:hover {
transform: scale(1.05);
}
.card-header {
border-radius: 0.5rem 0.5rem 0 0 !important;
}
@ -133,6 +133,14 @@ div.card-header {
text-shadow: 2px 1px 20px #795db3;
}
.modal-header .btn-close {
display: none;
}
.modal-title{
margin-inline-end: auto;
}
.block_setting {
position: absolute;
top: 7px;

157
advanced_dynamic_dashboard/static/src/js/dynamic_dashboard.js

@ -11,6 +11,8 @@ odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) {
events: {
'click .add_block': '_onClick_add_block',
'click .block_setting': '_onClick_block_setting',
'click .dashboard_pdf': '_onClick_dashboard_pdf',
'click .dashboard_mail': '_onClick_create_pdf',
'click .block_delete': '_onClick_block_delete',
'click #search-button': 'search_chart',
'click #searchclear': 'clear_search',
@ -42,7 +44,6 @@ odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) {
this.set("title", 'Dashboard');
return this._super().then(function () {
self.render_dashboards();
// self.gridstack_init(self);
});
},
fetch_data: function () {//Fetch data and call rpc query to create chart or tile. return block_ids
@ -79,6 +80,7 @@ odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) {
this.$el.find('.dropdown-export').toggleClass('dropdown-menu-dark', isDarkTheme);
},
_onchangeFilter: function() {
// Function for changing the filter
this.$('#edit_layout').show();
var start_date = $('#start-date').val();
var end_date = $('#end-date').val();
@ -89,24 +91,14 @@ odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) {
if (!end_date) {
end_date = "null";
}
console.log(start_date,"start")
console.log(end_date,"end")
this._rpc({
model: 'dashboard.block',
method: 'get_dashboard_vals',
args: [[], this.action_id, start_date, end_date],
}).then(function (result) {
console.log(result,"res")
self.block_ids = result;
self.$('.o_dynamic_dashboard').empty(); // Clear existing blocks before rendering
self.render_dashboards(); // Re-render the dashboard with updated data
// var gridstack = self.$('.grid-stack').data('gridstack');
// gridstack.enableMove(true);
// gridstack.enableResize(true);
// console.log(gridstack,"selffffffff")
// self.gridstack_init(self);
// self.gridstack_on(self);
// self.gridstack_init(self); // Reinitialize gridstack after rendering
});
},
get_colors: function (x_axis) {//Function fetch random color values and set chart color
@ -206,7 +198,6 @@ odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) {
return [data, options];
},
gridstack_init: function (self) {// Used gridstack to drag and resize chart and tile.
console.log(self,"selfselfselfselfself")
self.$('.grid-stack').gridstack({
animate: true,
duration: 200,
@ -215,22 +206,15 @@ odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) {
handle: '.grid-stack-item-content',
scroll: true
},
resizable:{
aspectRatio:20/18,
// autoHide: false,
},
alwaysShowResizeHandle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
float: true
});
self.gridstack_off(self);
},
gridstack_on: function (self) {// Enable move and resize functionality
console.log(self,"---")
var gridstack = self.$('.grid-stack').data('gridstack');
console.log(gridstack,"gridddddd")
gridstack.enableMove(true);
gridstack.enableResize(true);
console.log(gridstack,"selffffffff")
},
gridstack_off: function (self) {// Disable move and resize functionality
var gridstack = self.$('.grid-stack').data('gridstack');
@ -238,7 +222,6 @@ odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) {
gridstack.enableResize(false);
},
render_dashboards: function () {
console.log(this.block_ids,"prefghj")
self = this;
self.$("#save_layout").hide();//Hide save_layout button
_.each(this.block_ids, function (block) {//Loop all chart and tile
@ -322,7 +305,6 @@ odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) {
var pdf = new jsPDF();
pdf.addImage(bgCanvas.toDataURL("image/png"), 'PNG', 0, 0);
pdf.save(`${dataTitle}.pdf`);
}
if (type === 'csv') {
var rows = [];
@ -341,9 +323,44 @@ odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) {
var link = document.createElement("a");
link.setAttribute("href", encodeURI(csvContent));
link.setAttribute("download", `${dataTitle}.csv`);
document.body.appendChild(link); // Required for FF
document.body.appendChild(link);
link.click();
}
if (type === 'xlsx'){
var rows = [];
for (var obj of this.block_ids) {
if (obj.id == $(e.currentTarget).attr('data-id')) {
rows.push(obj.x_axis);
rows.push(obj.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);
})
}
},
dropdown_toggle: function () {//Function to toggle the button Add Items.
this.$el.find('.dropdown-addblock').toggle();
@ -434,7 +451,6 @@ odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) {
location.reload()
self.on_reverse_breadcrumb();
}).catch(function (error) {
console.log('Error unlinking record: ', error);
});
} else {
// Do nothing
@ -465,10 +481,8 @@ odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) {
'default_text_color': '#FFFFFF',
'default_fa_icon': 'fa fa-bar-chart',
'default_client_action_id': parseInt(self.action_id)
},
on_close: function () {
window.location.reload();
}
}},{
on_reverse_breadcrumb: this.on_reverse_breadcrumb
});
} else {
this.do_action({
@ -483,26 +497,94 @@ odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) {
'default_height': 5,
'default_width': 4,
'default_graph_type': chart_type,
'default_graph_size': 'col-lg-4',
'default_fa_icon': 'fa fa-bar-chart',
'default_client_action_id': parseInt(self.action_id)
},
on_close: function(){
window.location.reload();
}
},
{
on_reverse_breadcrumb: this.on_reverse_breadcrumb
});
}
});
}
// FETCHING SAVED LAYOUT FROM LOCAL STORAGE MEMORY
},
_onClick_edit_layout: function (e) {// Function to hide edit_layout button and show save_layout button. and also work the function gridstack_on(self)
console.log(e,"oooo")
_onClick_dashboard_pdf: function (e){
// Function for printing the pdf of the dashboard
var newElement = document.createElement('div');
newElement.className = 'pdf';
var parentElements = $('.grid-stack-item')
parentElements.each(function(index, parent){
var parentWidth = $(parent).width();
var parentHeight = $(parent).height();
$(parent).children().first().css('width', parentWidth);
$(parent).children().first().css('height', parentHeight);
$(parent).children().first().css('margin', '10px');
newElement.appendChild($(parent)[0].children[0]);
})
var opt = {
margin: 8,
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()
})
},
_onClick_create_pdf: function(e){
// Function for creating pdf in datauristring format
self = this;
var newElement = document.createElement('div');
newElement.className = 'pdf';
var parentElements = $('.grid-stack-item')
parentElements.each(function(index, parent){
var parentWidth = $(parent).width();
var parentHeight = $(parent).height();
$(parent).children().first().css('width', parentWidth);
$(parent).children().first().css('height', parentHeight);
$(parent).children().first().css('margin', '10px');
newElement.appendChild($(parent)[0].children[0]);
})
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().output('datauristring')
.then(function(pdfOutput) {
self.dashboard_mail(pdfOutput)
})
},
dashboard_mail: function(pdfData){
// Function for sending mail to the selected users
var base64code = pdfData.split(',')[1];
self.do_action({
type: 'ir.actions.act_window',
name: 'SEND MAIL',
res_model: 'dashboard.mail',
view_mode: 'form',
views: [[false, 'form']],
target: 'new',
context: {
'default_base64code': base64code,
}
});
},
_onClick_edit_layout: function (e) {
// Function to hide edit_layout button and show save_layout button. and also work the function gridstack_on(self)
e.stopPropagation();
self = this;
self.$("#edit_layout").hide();
self.$("#save_layout").show();
self.gridstack_on(self);
},
_onClick_save_layout: function (e) {//Function to save the edited value
_onClick_save_layout: function (e) {
//Function to save the edited value
e.stopPropagation();
self = this;
self.$("#edit_layout").show();
@ -524,7 +606,8 @@ odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) {
});
self.gridstack_off(self);
},
_onClick_tile: function (e) {// Function to view the tree view of the tile.
_onClick_tile: function (e) {
// Function to view the tree view of the tile.
e.stopPropagation();
self = this;
ajax.jsonRpc('/tile/details', 'call', {

59
advanced_dynamic_dashboard/static/src/xml/dynamic_dashboard_template.xml

@ -22,7 +22,6 @@
aria-expanded="false">
<i class="bi bi-plus-circle-fill"/>
<span>⠀Add Items</span>
</button>
<div class="dropdown-menu dropdown-addblock"
aria-labelledby="dropdownMenuButton">
@ -45,31 +44,39 @@
data-chart_type="radar">Radar Chart</a>
</div>
</label>
<label class="navbar-items layout-switch" id="edit-layout-label">
<label class="navbar-items layout-switch" id="edit-layout-label">
<button class="navbar-items btn-search_edit btn btn-primary my-2 mx-2 my-sm-0" type="button" id="edit_layout">Edit Layout</button>
<button class="navbar-items btn-search_edit btn btn-primary my-2 mx-2 my-sm-0" type="button" id="save_layout">Save Layout</button>
</label>
<label class="navbar-items toggle-btn" id="theme-change-icon">
<input type="checkbox" class="toggle" id="theme-toggle" />
<i class="theme_icon bi bi-moon-stars-fill" />
</label>
<div class="search-group" style="margin-right: 30px;">
<!-- Search Bar -->
<div class="navbar-items btn-group search-box">
<input class="form-control mr-sm-2" type="text" placeholder="Search" id="search-input-chart" aria-label="Search" />
<span id="searchclear">
<i class='fa fa-times search-clear' />
</span>
</div>
<button class="navbar-items btn-search_edit btn btn-outline-primary my-2 my-sm-0 search-btn" type="button" id="search-button">Search</button>
</div>
<!-- Date Inputs -->
<div class="date-inputs" style="position: absolute; right: 50.5em;">
<label for="start-date" style="color: black; margin-right: 5px;">Start Date:</label>
<input type="date" id="start-date" name="start-date" style="color: black; border: 1px solid #4e4e4e; background-color: white; padding: 5px 10px; border-radius: 5px;"/>
<label for="end-date" style="color: black; margin-right: 5px;">End Date:</label>
<input type="date" id="end-date" name="end-date" style="color: black; border: 1px solid #4e4e4e; background-color: white; padding: 5px 10px; border-radius: 5px;"/>
</div>
<label class="navbar-items toggle-btn" id="theme-change-icon">
<input type="checkbox" class="toggle" id="theme-toggle" />
<i class="theme_icon bi bi-moon-stars-fill" />
</label>
<div class="search-group" style="margin-right: 30px;">
<!-- Search Bar -->
<div class="navbar-items btn-group search-box">
<input class="form-control mr-sm-2" type="text" placeholder="Search" id="search-input-chart" aria-label="Search" />
<span id="searchclear">
<i class='fa fa-times search-clear' />
</span>
</div>
<button class="navbar-items btn-search_edit btn btn-outline-primary my-2 my-sm-0 search-btn" type="button" id="search-button">Search</button>
</div>
<div class="dashboard_pdf"
style="position:absolute;right:26.5em;">
<i class="bi bi-file-pdf-fill" style="font-size:24px;"/>
</div>
<div class="dashboard_mail"
style="position:absolute;right:29.5em;">
<i class="bi bi-send-check" style="font-size:24px;"/>
</div>
<!-- Date Inputs -->
<div class="date-inputs" style="position: absolute; right: 50.5em;">
<label for="start-date" style="color: black; margin-right: 5px;">Start Date:</label>
<input type="date" id="start-date" name="start-date" style="color: black; border: 1px solid #4e4e4e; background-color: white; padding: 5px 10px; border-radius: 5px;"/>
<label for="end-date" style="color: black; margin-right: 5px;">End Date:</label>
<input type="date" id="end-date" name="end-date" style="color: black; border: 1px solid #4e4e4e; background-color: white; padding: 5px 10px; border-radius: 5px;"/>
</div>
</ul>
</div>
</div>
@ -168,6 +175,12 @@
<i class="fa fa-file-code-o"/>
<span>Export to CSV</span>
</button>
<button class="dropdown-item chart_xlsx_export chart_item_export"
data-type="xlsx"
t-att-data-id="widget.id">
<i class="bi bi-filetype-xlsx"/>
<span>Export to XLSX</span>
</button>
</div>
</div>
<h3 class="chart_title">

16
advanced_dynamic_dashboard/views/dashboard_menu_views.xml

@ -17,10 +17,12 @@
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_global_click">
<h3 class="my-2 ms-3">
Name:
<field name="name"/>
</h3>
<center>
<h3 class="my-2 ms-3">
Name:
<field name="name"/>
</h3>
</center>
<div class="row">
<hr class="mt4 mb4"/>
<div class="col-6 text-center">
@ -56,7 +58,7 @@
</form>
</field>
</record>
<menuitem name="Dashboards" id="dashboard_menu_view_menu_action"
parent="advanced_dynamic_dashboard.dashboard_menu_action"
sequence="0" action="dashboard_menu_view_action"/>
<menuitem name="Dashboard Menu" id="dashboard_menu_view_menu"
parent="advanced_dynamic_dashboard.dynamic_dashboard_menu"
sequence="10" action="dashboard_menu_view_action"/>
</odoo>

9
advanced_dynamic_dashboard/views/dashboard_views.xml

@ -5,8 +5,13 @@
<field name="name">Dashboard</field>
<field name="tag">advanced_dynamic_dashboard</field>
</record>
<menuitem name="Dynamic Dashboards" action="dashboard_view_action"
id="dashboard_menu_action"
<menuitem name="Dynamic Dashboards"
id="dynamic_dashboard_menu"
web_icon="advanced_dynamic_dashboard,static/description/icon.png"
sequence="-1"/>
<menuitem name="Dashboards"
id="dashboard_menu"
parent="advanced_dynamic_dashboard.dynamic_dashboard_menu"
action="dashboard_view_action"
sequence="0"/>
</odoo>

15
advanced_dynamic_dashboard/views/dynamic_block_views.xml

@ -19,7 +19,8 @@
<group>
<group>
<field name="model_id"
attrs="{'required':[('edit_mode','=', True)]}"/>
attrs="{'required':[('edit_mode','=', True)]}"
options="{'no_create_edit': True, 'no_create': True,}"/>
<field name="client_action_id" invisible="1"/>
<field name="model_name" invisible="1"/>
<field name="edit_mode" invisible="1"/>
@ -27,7 +28,8 @@
attrs="{'required':[('edit_mode','=', True)]}"/>
<field name="measured_field_id" required="1"
domain="[('model_id','=',model_id), ('ttype','in',['float','integer','monetary']), ('store', '=', True)]"
attrs="{'required':[('edit_mode','=', True)]}"/>
attrs="{'required':[('edit_mode','=', True)]}"
options="{'no_create_edit': True, 'no_create': True,}"/>
<field name="filter" widget="domain"
options="{'model': 'model_name'}"/>
</group>
@ -37,13 +39,12 @@
<field name="type" required="1"/>
<field name="graph_type"
attrs="{'invisible': [('type','not in', 'graph')]}"/>
<field name="graph_size"
attrs="{'invisible': [('type','not in', 'graph')]}"/>
<field name="fa_icon"
attrs="{'invisible': [('type','not in', 'tile')]}"/>
<field name="group_by_id"
attrs="{'invisible': [('type','not in', 'graph')], 'required':[('edit_mode','=', True),('type','=','graph')]}"
domain="[('model_id','=',model_id), ('ttype','!=','one2many'), ('store', '=', True)]"/>
domain="[('model_id','=',model_id), ('ttype','!=','one2many'), ('store', '=', True)]"
options="{'no_create_edit': True, 'no_create': True,}"/>
<field name="tile_color"
attrs="{'invisible': [('type','not in', 'tile')]}"
widget="color"/>
@ -79,4 +80,8 @@
<field name="view_mode">tree,form</field>
<field name="context">{'default_edit_mode' : True}</field>
</record>
<!-- Menu for Dashboard Blocks -->
<menuitem name="Dashboard Blocks" id="dashboard_block_view_menu"
parent="advanced_dynamic_dashboard.dynamic_dashboard_menu"
sequence="0" action="dashboard_block_action"/>
</odoo>

22
advanced_dynamic_dashboard/wizard/__init__.py

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# 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 (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
from . import dashboard_mail

75
advanced_dynamic_dashboard/wizard/dashboard_mail.py

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# 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 (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
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, <br/> '
'I hope this mail finds you well. I am pleased to share the <b>Dashboard Report</b> with you.<br/>'
'Please find the attachment<br/>') % 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',
}

22
advanced_dynamic_dashboard/wizard/dashboard_mail_views.xml

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- Sending dashboard pdf to users -->
<record id="dashboard_mail_view_form" model="ir.ui.view">
<field name="name">dashboard.mail.view.form</field>
<field name="model">dashboard.mail</field>
<field name="arch" type="xml">
<form string="Sent Mail">
<group>
<field name="user_ids" widget="many2many_tags"/>
<field name="base64code" invisible="1"/>
</group>
<footer>
<button name="send_mail" string="SEND"
class="btn-primary" type="object"/>
<button string="Cancel" class="btn-secondary"
name="cancel_mail" type="object"/>
</footer>
</form>
</field>
</record>
</odoo>
Loading…
Cancel
Save