@ -0,0 +1,46 @@ | 
				
			|||||
 | 
					.. 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 | 
				
			||||
 | 
					========================== | 
				
			||||
 | 
					* Helps to create configurable dashboards easily. | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Configuration | 
				
			||||
 | 
					============= | 
				
			||||
 | 
					* No additional configurations needed | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					License | 
				
			||||
 | 
					------- | 
				
			||||
 | 
					General Public License, Version 3 (AGPL v3). | 
				
			||||
 | 
					(https://www.gnu.org/licenses/agpl-3.0-standalone.html) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Company | 
				
			||||
 | 
					------- | 
				
			||||
 | 
					* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Credits | 
				
			||||
 | 
					------- | 
				
			||||
 | 
					Developer: (V14) Unnimaya C O, 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. | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					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 `Our Website <https://cybrosys.com/>`__ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Further information | 
				
			||||
 | 
					=================== | 
				
			||||
 | 
					HTML Description: `<static/description/index.html>`__ | 
				
			||||
@ -0,0 +1,23 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					################################################################################ | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			||||
 | 
					#    Author: Unnimaya C O (odoo@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 controllers | 
				
			||||
 | 
					from . import models | 
				
			||||
@ -0,0 +1,50 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					################################################################################ | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			||||
 | 
					#    Author: Unnimaya C O (odoo@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/>. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					################################################################################ | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    'name': "Advanced Dynamic Dashboard", | 
				
			||||
 | 
					    'version': '14.0.1.0.0', | 
				
			||||
 | 
					    'category': 'Productivity', | 
				
			||||
 | 
					    'summary': """Helps to create configurable dashboards easily.""", | 
				
			||||
 | 
					    'description': """This module helps to 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': ['web'], | 
				
			||||
 | 
					    'data': [ | 
				
			||||
 | 
					        'security/ir.model.access.csv', | 
				
			||||
 | 
					        'views/dashboard_views.xml', | 
				
			||||
 | 
					        'views/dynamic_block_views.xml', | 
				
			||||
 | 
					        'views/dashboard_menu_views.xml', | 
				
			||||
 | 
					        'views/dynamic_dashboard_views.xml' | 
				
			||||
 | 
					    ], | 
				
			||||
 | 
					    'qweb': [ | 
				
			||||
 | 
					        'static/src/xml/dynamic_dashboard_template.xml', | 
				
			||||
 | 
					    ], | 
				
			||||
 | 
					    'images': ['static/description/banner.png'], | 
				
			||||
 | 
					    'license': "AGPL-3", | 
				
			||||
 | 
					    'installable': True, | 
				
			||||
 | 
					    'auto_install': False, | 
				
			||||
 | 
					    'application': True, | 
				
			||||
 | 
					} | 
				
			||||
@ -0,0 +1,22 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					################################################################################ | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			||||
 | 
					#    Author: Unnimaya C O (odoo@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 advanced_dynamic_dashboard | 
				
			||||
@ -0,0 +1,45 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					################################################################################ | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			||||
 | 
					#    Author: Unnimaya C O (odoo@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 http | 
				
			||||
 | 
					from odoo.http import request | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class DynamicDashboard(http.Controller): | 
				
			||||
 | 
					    """Class to search and filter values in dashboard""" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @http.route('/tile/details', type='json', auth='user') | 
				
			||||
 | 
					    def tile_details(self, **kw): | 
				
			||||
 | 
					        """Function to get tile details""" | 
				
			||||
 | 
					        tile_id = request.env['dashboard.block'].sudo().browse( | 
				
			||||
 | 
					            int(kw.get('id'))) | 
				
			||||
 | 
					        if tile_id: | 
				
			||||
 | 
					            return {'model': tile_id.model_id.model, 'filter': tile_id.filter, | 
				
			||||
 | 
					                    'model_name': tile_id.model_id.name} | 
				
			||||
 | 
					        else: | 
				
			||||
 | 
					            return False | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @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 | 
				
			||||
@ -0,0 +1,6 @@ | 
				
			|||||
 | 
					## Module <advanced_dynamic_dashboard> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#### 05.02.2024 | 
				
			||||
 | 
					#### Version 14.0.1.0.0 | 
				
			||||
 | 
					#### ADD | 
				
			||||
 | 
					- Initial commit for Advanced Dynamic Dashboard | 
				
			||||
@ -0,0 +1,24 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					################################################################################ | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			||||
 | 
					#    Author: Unnimaya C O (odoo@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_block | 
				
			||||
 | 
					from . import dashboard_menu | 
				
			||||
 | 
					from . import models | 
				
			||||
@ -0,0 +1,184 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					################################################################################ | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			||||
 | 
					#    Author: Unnimaya C O (odoo@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 ast import literal_eval | 
				
			||||
 | 
					from datetime import datetime | 
				
			||||
 | 
					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 Blocks" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    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( | 
				
			||||
 | 
					            'advanced_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") | 
				
			||||
 | 
					    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", | 
				
			||||
 | 
					        help='Tile Operation that needs to bring values for tile', | 
				
			||||
 | 
					        required=True) | 
				
			||||
 | 
					    graph_type = fields.Selection( | 
				
			||||
 | 
					        selection=[("bar", "Bar"), ("radar", "Radar"), ("pie", "Pie"), | 
				
			||||
 | 
					                   ("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="Choose the 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") | 
				
			||||
 | 
					    x_pos = fields.Integer(string="X-Position", help="Chart X-axis position") | 
				
			||||
 | 
					    y_pos = fields.Integer(string="Y-Position", help="Chart Y-axis position") | 
				
			||||
 | 
					    height = fields.Integer(string="Height", help="Chart height") | 
				
			||||
 | 
					    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') | 
				
			||||
 | 
					    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", | 
				
			||||
 | 
					                               invisible=True) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.onchange('model_id') | 
				
			||||
 | 
					    def _onchange_model_id(self): | 
				
			||||
 | 
					        self.operation = False | 
				
			||||
 | 
					        self.measured_field_id = False | 
				
			||||
 | 
					        self.group_by_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.sudo().search( | 
				
			||||
 | 
					                [('client_action_id', '=', int(action_id))]): | 
				
			||||
 | 
					            if rec.filter is False: | 
				
			||||
 | 
					                rec.filter = "[]" | 
				
			||||
 | 
					            filter_list = literal_eval(rec.filter) | 
				
			||||
 | 
					            # Remove existing date filters if any exist | 
				
			||||
 | 
					            filter_list = [filter_item for filter_item in filter_list if not ( | 
				
			||||
 | 
					                    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') | 
				
			||||
 | 
					                filter_list.append( | 
				
			||||
 | 
					                    ('create_date', '>=', start_date_obj.strftime('%Y-%m-%d'))) | 
				
			||||
 | 
					            if end_date and end_date != 'null': | 
				
			||||
 | 
					                end_date_obj = datetime.strptime(end_date, '%Y-%m-%d') | 
				
			||||
 | 
					                filter_list.append( | 
				
			||||
 | 
					                    ('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, | 
				
			||||
 | 
					                    'width': rec.width} | 
				
			||||
 | 
					            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, | 
				
			||||
 | 
					                                               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)) | 
				
			||||
 | 
					                    records = self._cr.dictfetchall() | 
				
			||||
 | 
					                    magnitude = 0 | 
				
			||||
 | 
					                    total = records[0].get('value') | 
				
			||||
 | 
					                    while abs(total) >= 1000: | 
				
			||||
 | 
					                        magnitude += 1 | 
				
			||||
 | 
					                        total /= 1000.0 | 
				
			||||
 | 
					                    # add more suffixes if you need them | 
				
			||||
 | 
					                    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, act_id, grid_data_list): | 
				
			||||
 | 
					        """Function fetch edited values while edit layout of the chart or tile | 
				
			||||
 | 
					         and save values in a database""" | 
				
			||||
 | 
					        for block in self.env['dashboard.block'].sudo().search( | 
				
			||||
 | 
					                [('client_action_id', '=', int(act_id))]): | 
				
			||||
 | 
					            for data in grid_data_list: | 
				
			||||
 | 
					                if block['id'] == data['id']: | 
				
			||||
 | 
					                    block.write({ | 
				
			||||
 | 
					                        'x_pos': int(data['x']), | 
				
			||||
 | 
					                        'y_pos': int(data['y']), | 
				
			||||
 | 
					                        'height': int(data['height']), | 
				
			||||
 | 
					                        'width': int(data['width']), | 
				
			||||
 | 
					                    }) | 
				
			||||
@ -0,0 +1,79 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					################################################################################ | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			||||
 | 
					#    Author: Unnimaya C O (odoo@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, fields, models | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class DashboardMenu(models.Model): | 
				
			||||
 | 
					    """Class to create new dashboard menu""" | 
				
			||||
 | 
					    _name = "dashboard.menu" | 
				
			||||
 | 
					    _description = "Dashboard Menu" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    name = fields.Char(string="Name", | 
				
			||||
 | 
					                       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") | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.model | 
				
			||||
 | 
					    def create(self, vals): | 
				
			||||
 | 
					        """Function to create new dashboard menu""" | 
				
			||||
 | 
					        action_id = self.env['ir.actions.client'].create({ | 
				
			||||
 | 
					            'name': vals['name'], | 
				
			||||
 | 
					            'tag': 'advanced_dynamic_dashboard', | 
				
			||||
 | 
					        }) | 
				
			||||
 | 
					        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().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().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().unlink() | 
				
			||||
@ -0,0 +1,60 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					################################################################################ | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			||||
 | 
					#    Author: Unnimaya C O (odoo@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 models | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					def get_query(self, args, operation, field, group_by=False, | 
				
			||||
 | 
					              apply_ir_rules=False): | 
				
			||||
 | 
					    """Method for creating query for fetching data to be displayed on the | 
				
			||||
 | 
					    dashboard block""" | 
				
			||||
 | 
					    query = self._where_calc(args) | 
				
			||||
 | 
					    if apply_ir_rules: | 
				
			||||
 | 
					        self._apply_ir_rules(query, 'read') | 
				
			||||
 | 
					    join = '' | 
				
			||||
 | 
					    group_by_str = '' | 
				
			||||
 | 
					    if operation and field: | 
				
			||||
 | 
					        data = 'COALESCE(%s("%s".%s),0) AS value' % (operation.upper(), | 
				
			||||
 | 
					                                                     self._table, field.name) | 
				
			||||
 | 
					        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, where_clause, where_clause_params = query.get_sql() | 
				
			||||
 | 
					    where_str = where_clause and (" WHERE %s" % where_clause) or '' | 
				
			||||
 | 
					    query_str = ('SELECT %s FROM ' % data + from_clause + join + where_str + | 
				
			||||
 | 
					                 group_by_str) | 
				
			||||
 | 
					    return query_str % tuple( | 
				
			||||
 | 
					        map(lambda x: "'" + str(x) + "'", where_clause_params)) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					models.BaseModel.get_query = get_query | 
				
			||||
		
		
			
  | 
| 
		 After Width: | Height: | Size: 3.6 KiB  | 
| 
		 After Width: | Height: | Size: 1.3 KiB  | 
| 
		 After Width: | Height: | Size: 1.4 KiB  | 
| 
		 After Width: | Height: | Size: 542 B  | 
| 
		 After Width: | Height: | Size: 576 B  | 
| 
		 After Width: | Height: | Size: 733 B  | 
| 
		 After Width: | Height: | Size: 4.3 KiB  | 
| 
		 After Width: | Height: | Size: 4.0 KiB  | 
| 
		 After Width: | Height: | Size: 911 B  | 
| 
		 After Width: | Height: | Size: 1.1 KiB  | 
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 After Width: | Height: | Size: 673 B  | 
| 
		 After Width: | Height: | Size: 878 B  | 
| 
		 After Width: | Height: | Size: 653 B  | 
| 
		 After Width: | Height: | Size: 905 B  | 
| 
		 After Width: | Height: | Size: 4.3 KiB  | 
| 
		 After Width: | Height: | Size: 839 B  | 
| 
		 After Width: | Height: | Size: 3.8 KiB  | 
| 
		 After Width: | Height: | Size: 26 KiB  | 
| 
		 After Width: | Height: | Size: 427 B  | 
| 
		 After Width: | Height: | Size: 627 B  | 
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 After Width: | Height: | Size: 988 B  | 
| 
		 After Width: | Height: | Size: 3.7 KiB  | 
| 
		 After Width: | Height: | Size: 5.0 KiB  | 
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 After Width: | Height: | Size: 1.5 KiB  | 
| 
		 After Width: | Height: | Size: 1.1 KiB  | 
| 
		 After Width: | Height: | Size: 1.9 KiB  | 
| 
		 After Width: | Height: | Size: 1.1 KiB  | 
| 
		 After Width: | Height: | Size: 2.1 KiB  | 
| 
		 After Width: | Height: | Size: 4.4 KiB  | 
| 
		 After Width: | Height: | Size: 589 B  | 
| 
		 After Width: | Height: | Size: 3.4 KiB  | 
| 
		 After Width: | Height: | Size: 1.7 KiB  | 
| 
		 After Width: | Height: | Size: 2.3 KiB  | 
| 
		 After Width: | Height: | Size: 967 B  | 
| 
		 After Width: | Height: | Size: 1.6 KiB  | 
| 
		 After Width: | Height: | Size: 3.8 KiB  | 
| 
		 After Width: | Height: | Size: 5.0 KiB  | 
| 
		 After Width: | Height: | Size: 64 KiB  | 
| 
		 After Width: | Height: | Size: 110 KiB  | 
| 
		 After Width: | Height: | Size: 1.7 MiB  | 
| 
		 After Width: | Height: | Size: 63 KiB  | 
| 
		 After Width: | Height: | Size: 71 KiB  | 
| 
		 After Width: | Height: | Size: 64 KiB  | 
| 
		 After Width: | Height: | Size: 66 KiB  | 
| 
		 After Width: | Height: | Size: 36 KiB  | 
| 
		 After Width: | Height: | Size: 178 KiB  | 
| 
		 After Width: | Height: | Size: 33 KiB  | 
| 
		 After Width: | Height: | Size: 40 KiB  | 
| 
		 After Width: | Height: | Size: 36 KiB  | 
| 
		 After Width: | Height: | Size: 61 KiB  | 
| 
		 After Width: | Height: | Size: 58 KiB  | 
| 
		 After Width: | Height: | Size: 63 KiB  | 
| 
		 After Width: | Height: | Size: 176 KiB  | 
| 
		 After Width: | Height: | Size: 179 KiB  | 
| 
		 After Width: | Height: | Size: 58 KiB  | 
| 
		 After Width: | Height: | Size: 178 KiB  | 
| 
		 After Width: | Height: | Size: 162 KiB  | 
| 
		 After Width: | Height: | Size: 413 KiB  | 
| 
		 After Width: | Height: | Size: 182 KiB  | 
| 
		 After Width: | Height: | Size: 211 KiB  | 
| 
		 After Width: | Height: | Size: 176 KiB  | 
| 
		 After Width: | Height: | Size: 22 KiB  | 
| 
		 After Width: | Height: | Size: 40 KiB  | 
| 
		 After Width: | Height: | Size: 48 KiB  | 
| 
		 After Width: | Height: | Size: 8.1 KiB  | 
@ -0,0 +1,714 @@ | 
				
			|||||
 | 
					<div style="background-color: #714B67; height: 810px; width: 100%; padding: 15px; position: relative;"> | 
				
			||||
 | 
					    <!-- TITLE BAR --> | 
				
			||||
 | 
					    <div class="d-flex align-items-center justify-content-between" | 
				
			||||
 | 
					         style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;"> | 
				
			||||
 | 
					        <img src="assets/misc/cybrosys-logo.png" width="42" height="42" | 
				
			||||
 | 
					             style="width: 42px; height: 42px;"/> | 
				
			||||
 | 
					        <div> | 
				
			||||
 | 
					            <div style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" | 
				
			||||
 | 
					                 class="mr-2"> | 
				
			||||
 | 
					                <i class="fa fa-check mr-1"></i>Enterprise | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					            <div style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" | 
				
			||||
 | 
					                 class="mr-2"> | 
				
			||||
 | 
					                <i class="fa fa-check mr-1"></i>Community | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					            <div style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" | 
				
			||||
 | 
					                 class="mr-2"> | 
				
			||||
 | 
					                <i class="fa fa-check mr-1"></i>Odoo.sh | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					    <!-- END OF TITLE BAR --> | 
				
			||||
 | 
					    <div class="container"> | 
				
			||||
 | 
					        <div class="row"> | 
				
			||||
 | 
					            <div class="col-sm-12 col-md-12 col-lg-12"> | 
				
			||||
 | 
					                <!-- APP HERO --> | 
				
			||||
 | 
					                <h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;"> | 
				
			||||
 | 
					                    Advanced Dynamic Dashboard | 
				
			||||
 | 
					                </h1> | 
				
			||||
 | 
					                <p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;"> | 
				
			||||
 | 
					                    Facilitates the Seamless Creation of Customizable | 
				
			||||
 | 
					                    Dashboards.</p> | 
				
			||||
 | 
					                <!-- END OF APP HERO --> | 
				
			||||
 | 
					                <img src="assets/screenshots/hero.gif" class="img-responsive" | 
				
			||||
 | 
					                     style="width: 100%; margin-left: auto; margin-right: auto;"/> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<!-- NAVIGATION SECTION --> | 
				
			||||
 | 
					<div class="d-flex align-items-center" | 
				
			||||
 | 
					     style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;"> | 
				
			||||
 | 
					    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			||||
 | 
					         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			||||
 | 
					        <img src="assets/misc/compass.png"/> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					    <h2 class="mt-2" | 
				
			||||
 | 
					        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			||||
 | 
					        Explore This | 
				
			||||
 | 
					        Module</h2> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<div class="row my-4" style="font-family: 'Montserrat', sans-serif;"> | 
				
			||||
 | 
					    <div class="col-sm-12 col-md-6 my-3"> | 
				
			||||
 | 
					        <a href="#overview"> | 
				
			||||
 | 
					            <div class="d-flex justify-content-between align-items-center" | 
				
			||||
 | 
					                 style="background-color: #f5f5f5; padding: 30px; width: 100%;"> | 
				
			||||
 | 
					                <div> | 
				
			||||
 | 
					                    <span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span> | 
				
			||||
 | 
					                    <span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33;  display: block;">Learn | 
				
			||||
 | 
					                      more about this | 
				
			||||
 | 
					                      module</span> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					                <img src="assets/misc/right-arrow.png" width="36" height="36"/> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </a> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					    <div class="col-sm-12 col-md-6 my-3"> | 
				
			||||
 | 
					        <a href="#features"> | 
				
			||||
 | 
					            <div class="d-flex justify-content-between align-items-center" | 
				
			||||
 | 
					                 style="background-color: #f5f5f5; padding: 30px; width: 100%;"> | 
				
			||||
 | 
					                <div> | 
				
			||||
 | 
					                    <span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span> | 
				
			||||
 | 
					                    <span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33;  display: block;">View | 
				
			||||
 | 
					                      features of this | 
				
			||||
 | 
					                      module</span> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					                <img src="assets/misc/right-arrow.png" width="36" height="36"/> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </a> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					    <div class="col-sm-12 col-md-6 my-3"> | 
				
			||||
 | 
					        <a href="#screenshots"> | 
				
			||||
 | 
					            <div class="d-flex justify-content-between align-items-center" | 
				
			||||
 | 
					                 style="background-color: #f5f5f5; padding: 30px; width: 100%;"> | 
				
			||||
 | 
					                <div> | 
				
			||||
 | 
					                    <span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span> | 
				
			||||
 | 
					                    <span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33;  display: block;">View | 
				
			||||
 | 
					                      screenshots for this | 
				
			||||
 | 
					                      module</span> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					                <img src="assets/misc/right-arrow.png" width="36" height="36"/> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </a> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<!-- END OF NAVIGATION SECTION --> | 
				
			||||
 | 
					<!-- OVERVIEW SECTION --> | 
				
			||||
 | 
					<div class="d-flex align-items-center" | 
				
			||||
 | 
					     style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="overview"> | 
				
			||||
 | 
					    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			||||
 | 
					         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			||||
 | 
					        <img src="assets/misc/pie-chart.png"/> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					    <h2 class="mt-2" | 
				
			||||
 | 
					        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			||||
 | 
					        Overview | 
				
			||||
 | 
					    </h2> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<div class="row" | 
				
			||||
 | 
					     style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> | 
				
			||||
 | 
					    <div class="col-sm-12 py-4"> | 
				
			||||
 | 
					        The Advanced Dynamic Dashboard module empowers users to | 
				
			||||
 | 
					        customize,arrange, and access real-time data relevant to their | 
				
			||||
 | 
					        business, | 
				
			||||
 | 
					        department, or specific processes, facilitating informed | 
				
			||||
 | 
					        decision-making and optimized performance. | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<!-- END OF OVERVIEW SECTION --> | 
				
			||||
 | 
					<!-- FEATURES SECTION --> | 
				
			||||
 | 
					<div class="d-flex align-items-center" | 
				
			||||
 | 
					     style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="features"> | 
				
			||||
 | 
					    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			||||
 | 
					         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			||||
 | 
					        <img src="assets/misc/features.png"/> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					    <h2 class="mt-2" | 
				
			||||
 | 
					        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			||||
 | 
					        Features | 
				
			||||
 | 
					    </h2> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<div class="row" | 
				
			||||
 | 
					     style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> | 
				
			||||
 | 
					    <div class="col-sm-12 col-md-6"> | 
				
			||||
 | 
					        <div class="d-flex align-items-center" | 
				
			||||
 | 
					             style="margin-top: 30px; margin-bottom: 30px"> | 
				
			||||
 | 
					            <img src="assets/misc/check-box.png" class="mr-2"/> | 
				
			||||
 | 
					            <span | 
				
			||||
 | 
					                    style="font-family: 'Montserrat', sans-serif; font-size:  18px; font-weight: bold;"> Effortlessly generate interactive Charts and Tiles.</span> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="d-flex align-items-center" | 
				
			||||
 | 
					             style="margin-top: 30px; margin-bottom: 30px"> | 
				
			||||
 | 
					            <img src="assets/misc/check-box.png" class="mr-2"/> | 
				
			||||
 | 
					            <span | 
				
			||||
 | 
					                    style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Available Dark mode and Light mode.</span> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="d-flex align-items-center" | 
				
			||||
 | 
					             style="margin-top: 30px; margin-bottom: 30px"> | 
				
			||||
 | 
					            <img src="assets/misc/check-box.png" class="mr-2"/> | 
				
			||||
 | 
					            <span | 
				
			||||
 | 
					                    style="font-family: 'Montserrat', sans-serif; font-size:  18px; font-weight: bold;"> Feasible to establish a Dashboard Menu in any | 
				
			||||
 | 
					                    model.</span> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="d-flex align-items-center" | 
				
			||||
 | 
					             style="margin-top: 30px; margin-bottom: 30px"> | 
				
			||||
 | 
					            <img src="assets/misc/check-box.png" class="mr-2"/> | 
				
			||||
 | 
					            <span | 
				
			||||
 | 
					                    style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Charts can be exported as Images, PDFs, and CSVs.</span> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="d-flex align-items-center" | 
				
			||||
 | 
					             style="margin-top: 30px; margin-bottom: 30px"> | 
				
			||||
 | 
					            <img src="assets/misc/check-box.png" class="mr-2"/> | 
				
			||||
 | 
					            <span | 
				
			||||
 | 
					                    style="font-family: 'Montserrat', sans-serif; font-size:  18px; font-weight: bold;">Enable dragging and resizing of Charts and Tiles for | 
				
			||||
 | 
					                    flexible layouts.</span> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="d-flex align-items-center" | 
				
			||||
 | 
					             style="margin-top: 30px; margin-bottom: 30px"> | 
				
			||||
 | 
					            <img src="assets/misc/check-box.png" class="mr-2"/> | 
				
			||||
 | 
					            <span | 
				
			||||
 | 
					                    style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Edit and configure Charts and Tiles</span> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<!-- END OF FEATURES SECTION --> | 
				
			||||
 | 
					<!-- SCREENSHOTS SECTION --> | 
				
			||||
 | 
					<div class="d-flex align-items-center" | 
				
			||||
 | 
					     style="border-bottom: 2px solid #714B67; padding: 15px 0px;" | 
				
			||||
 | 
					     id="screenshots"> | 
				
			||||
 | 
					    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			||||
 | 
					         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			||||
 | 
					        <img src="assets/misc/pictures.png"/> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					    <h2 class="mt-2" | 
				
			||||
 | 
					        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			||||
 | 
					        Screenshots | 
				
			||||
 | 
					    </h2> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<div class="row"> | 
				
			||||
 | 
					    <div class="col-sm-12"> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					                Click ADD ITEMS to add Graphs and Tiles to the Dashboard. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/1.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					                Add required details for creating a Tile. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/2.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					                New Tiles on the dashboard. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/3.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					              Create new Chart. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/4.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					                Charts added to the dashboard. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/5.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					               Dashboard based on the date filter. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/6.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					                 It is possible to Search the name of chart or tile. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/7.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					               <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					                Click the marked button for enabling Dark Mode. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/8.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					                 Dashboard in Dark Mode. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/9.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					                Click EDIT LAYOUT for editing the dashboard layout. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/s15.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					                It is possible to change size of chart and tile by clicking the | 
				
			||||
 | 
					        marked icon, also we can drag them to any position. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> | 
				
			||||
 | 
					            </p> | 
				
			||||
 | 
					            <img src="assets/screenshots/s17.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					                Click on the 3 dots icon for exporting the graphs. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/s18.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					                Graph exported as image. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/s19.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					               Graph exported as pdf. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/s20.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div>       <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					               Navigate to Dashboards menu to add the dashboard menu under any | 
				
			||||
 | 
					            menu. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/10.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					                Choose the menu name and parent menu. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/11.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					               New menu added in Inventory module. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <img src="assets/screenshots/12.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div style="display: block; margin: 30px auto;"> | 
				
			||||
 | 
					            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			||||
 | 
					                We can create new dashboard here. | 
				
			||||
 | 
					            </h3> | 
				
			||||
 | 
					            <p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> | 
				
			||||
 | 
					            </p> | 
				
			||||
 | 
					            <img src="assets/screenshots/13.png" class="img-thumbnail"> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<!-- END OF SCREENSHOTS SECTION --> | 
				
			||||
 | 
					<!-- RELATED PRODUCTS --> | 
				
			||||
 | 
					<div class="d-flex align-items-center" | 
				
			||||
 | 
					     style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> | 
				
			||||
 | 
					    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			||||
 | 
					         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			||||
 | 
					        <img src="assets/misc/categories.png"/> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					    <h2 class="mt-2" | 
				
			||||
 | 
					        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			||||
 | 
					        Related | 
				
			||||
 | 
					        Products | 
				
			||||
 | 
					    </h2> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<div class="row"> | 
				
			||||
 | 
					    <div class="col-sm-12"> | 
				
			||||
 | 
					        <div id="demo1" class="row carousel slide" data-ride="carousel"> | 
				
			||||
 | 
					            <!-- The slideshow --> | 
				
			||||
 | 
					            <div class="carousel-inner" style="padding: 30px;"> | 
				
			||||
 | 
					                <div class="carousel-item" style="min-height: 198.656px;"> | 
				
			||||
 | 
					                    <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
				
			||||
 | 
					                         style="float:left"> | 
				
			||||
 | 
					                        <a href="https://apps.odoo.com/apps/modules/14.0/project_dashboard_odoo/" | 
				
			||||
 | 
					                           target="_blank"> | 
				
			||||
 | 
					                            <div style="border-radius:10px"> | 
				
			||||
 | 
					                                <img class="img img-responsive center-block" | 
				
			||||
 | 
					                                     style="border-radius: 0px;" | 
				
			||||
 | 
					                                     src="assets/modules/1.png"> | 
				
			||||
 | 
					                            </div> | 
				
			||||
 | 
					                        </a> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                    <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
				
			||||
 | 
					                         style="float:left"> | 
				
			||||
 | 
					                        <a href="https://apps.odoo.com/apps/modules/14.0/pdf_report_with_sign/" | 
				
			||||
 | 
					                           target="_blank"> | 
				
			||||
 | 
					                            <div style="border-radius:10px"> | 
				
			||||
 | 
					                                <img class="img img-responsive center-block" | 
				
			||||
 | 
					                                     style="border-radius: 0px;" | 
				
			||||
 | 
					                                     src="assets/modules/2.png"> | 
				
			||||
 | 
					                            </div> | 
				
			||||
 | 
					                        </a> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                    <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
				
			||||
 | 
					                         style="float:left"> | 
				
			||||
 | 
					                        <a href="https://apps.odoo.com/apps/modules/14.0/magic_note/" | 
				
			||||
 | 
					                           target="_blank"> | 
				
			||||
 | 
					                            <div style="border-radius:10px"> | 
				
			||||
 | 
					                                <img class="img img-responsive center-block" | 
				
			||||
 | 
					                                     style="border-radius: 0px;" | 
				
			||||
 | 
					                                     src="assets/modules/3.png"> | 
				
			||||
 | 
					                            </div> | 
				
			||||
 | 
					                        </a> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					                <div class="carousel-item active" | 
				
			||||
 | 
					                     style="min-height: 198.656px;"> | 
				
			||||
 | 
					                    <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
				
			||||
 | 
					                         style="float:left"> | 
				
			||||
 | 
					                        <a href="https://apps.odoo.com/apps/modules/14.0/odoo11_magento2/" | 
				
			||||
 | 
					                           target="_blank"> | 
				
			||||
 | 
					                            <div style="border-radius:10px"> | 
				
			||||
 | 
					                                <img class="img img-responsive center-block" | 
				
			||||
 | 
					                                     style="border-radius: 0px;" | 
				
			||||
 | 
					                                     src="assets/modules/4.png"> | 
				
			||||
 | 
					                            </div> | 
				
			||||
 | 
					                        </a> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                    <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
				
			||||
 | 
					                         style="float:left"> | 
				
			||||
 | 
					                        <a href="https://apps.odoo.com/apps/modules/14.0/custom_gantt_view/" | 
				
			||||
 | 
					                           target="_blank"> | 
				
			||||
 | 
					                            <div style="border-radius:10px"> | 
				
			||||
 | 
					                                <img class="img img-responsive center-block" | 
				
			||||
 | 
					                                     style="border-radius: 0px;" | 
				
			||||
 | 
					                                     src="assets/modules/5.png"> | 
				
			||||
 | 
					                            </div> | 
				
			||||
 | 
					                        </a> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                    <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
				
			||||
 | 
					                         style="float:left"> | 
				
			||||
 | 
					                        <a href="https://apps.odoo.com/apps/modules/14.0/odoo_dynamic_dashboard/" | 
				
			||||
 | 
					                           target="_blank"> | 
				
			||||
 | 
					                            <div style="border-radius:10px"> | 
				
			||||
 | 
					                                <img class="img img-responsive center-block" | 
				
			||||
 | 
					                                     style="border-radius: 0px;" | 
				
			||||
 | 
					                                     src="assets/modules/6.png"> | 
				
			||||
 | 
					                            </div> | 
				
			||||
 | 
					                        </a> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					            <!-- Left and right controls --> | 
				
			||||
 | 
					            <a class="carousel-control-prev" href="#demo1" data-slide="prev" | 
				
			||||
 | 
					               style="width:35px; color:#000"> <span | 
				
			||||
 | 
					                    class="carousel-control-prev-icon"><i | 
				
			||||
 | 
					                    class="fa fa-chevron-left" | 
				
			||||
 | 
					                    style="font-size:24px"></i></span> | 
				
			||||
 | 
					            </a> <a class="carousel-control-next" href="#demo1" | 
				
			||||
 | 
					                    data-slide="next" style="width:35px; color:#000"> | 
				
			||||
 | 
					            <span class="carousel-control-next-icon"><i | 
				
			||||
 | 
					                    class="fa fa-chevron-right" | 
				
			||||
 | 
					                    style="font-size:24px"></i></span> | 
				
			||||
 | 
					        </a> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<!-- END OF RELATED PRODUCTS --> | 
				
			||||
 | 
					<!-- OUR SERVICES --> | 
				
			||||
 | 
					<div class="d-flex align-items-center" | 
				
			||||
 | 
					     style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> | 
				
			||||
 | 
					    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			||||
 | 
					         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			||||
 | 
					        <img src="assets/misc/star.png"/> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					    <h2 class="mt-2" | 
				
			||||
 | 
					        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			||||
 | 
					        Our Services | 
				
			||||
 | 
					    </h2> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<div class="container my-5"> | 
				
			||||
 | 
					    <div class="row"> | 
				
			||||
 | 
					        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
				
			||||
 | 
					            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
				
			||||
 | 
					                 style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
				
			||||
 | 
					                <img src="assets/icons/cogs.png" class="img-responsive" | 
				
			||||
 | 
					                     height="48px" width="48px"> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					            <h6 class="text-center" | 
				
			||||
 | 
					                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
				
			||||
 | 
					                Odoo | 
				
			||||
 | 
					                Customization</h6> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
				
			||||
 | 
					            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
				
			||||
 | 
					                 style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
				
			||||
 | 
					                <img src="assets/icons/wrench.png" class="img-responsive" | 
				
			||||
 | 
					                     height="48px" width="48px"> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					            <h6 class="text-center" | 
				
			||||
 | 
					                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
				
			||||
 | 
					                Odoo | 
				
			||||
 | 
					                Implementation</h6> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
				
			||||
 | 
					            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
				
			||||
 | 
					                 style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
				
			||||
 | 
					                <img src="assets/icons/lifebuoy.png" class="img-responsive" | 
				
			||||
 | 
					                     height="48px" width="48px"> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					            <h6 class="text-center" | 
				
			||||
 | 
					                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
				
			||||
 | 
					                Odoo | 
				
			||||
 | 
					                Support</h6> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
				
			||||
 | 
					            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
				
			||||
 | 
					                 style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
				
			||||
 | 
					                <img src="assets/icons/user.png" class="img-responsive" | 
				
			||||
 | 
					                     height="48px" width="48px"> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					            <h6 class="text-center" | 
				
			||||
 | 
					                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
				
			||||
 | 
					                Hire | 
				
			||||
 | 
					                Odoo | 
				
			||||
 | 
					                Developer</h6> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
				
			||||
 | 
					            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
				
			||||
 | 
					                 style="background-color: #54a0ff  !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
				
			||||
 | 
					                <img src="assets/icons/puzzle.png" class="img-responsive" | 
				
			||||
 | 
					                     height="48px" width="48px"> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					            <h6 class="text-center" | 
				
			||||
 | 
					                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
				
			||||
 | 
					                Odoo | 
				
			||||
 | 
					                Integration</h6> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
				
			||||
 | 
					            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
				
			||||
 | 
					                 style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
				
			||||
 | 
					                <img src="assets/icons/update.png" class="img-responsive" | 
				
			||||
 | 
					                     height="48px" width="48px"> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					            <h6 class="text-center" | 
				
			||||
 | 
					                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
				
			||||
 | 
					                Odoo | 
				
			||||
 | 
					                Migration</h6> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
				
			||||
 | 
					            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
				
			||||
 | 
					                 style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
				
			||||
 | 
					                <img src="assets/icons/consultation.png" class="img-responsive" | 
				
			||||
 | 
					                     height="48px" width="48px"> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					            <h6 class="text-center" | 
				
			||||
 | 
					                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
				
			||||
 | 
					                Odoo | 
				
			||||
 | 
					                Consultancy</h6> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
				
			||||
 | 
					            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
				
			||||
 | 
					                 style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
				
			||||
 | 
					                <img src="assets/icons/training.png" class="img-responsive" | 
				
			||||
 | 
					                     height="48px" width="48px"> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					            <h6 class="text-center" | 
				
			||||
 | 
					                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
				
			||||
 | 
					                Odoo | 
				
			||||
 | 
					                Implementation</h6> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
				
			||||
 | 
					            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
				
			||||
 | 
					                 style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
				
			||||
 | 
					                <img src="assets/icons/license.png" class="img-responsive" | 
				
			||||
 | 
					                     height="48px" width="48px"> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					            <h6 class="text-center" | 
				
			||||
 | 
					                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
				
			||||
 | 
					                Odoo | 
				
			||||
 | 
					                Licensing Consultancy</h6> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<!-- END OF OUR SERVICES --> | 
				
			||||
 | 
					<!-- OUR INDUSTRIES --> | 
				
			||||
 | 
					<div class="d-flex align-items-center" | 
				
			||||
 | 
					     style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> | 
				
			||||
 | 
					    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			||||
 | 
					         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			||||
 | 
					        <img src="assets/misc/corporate.png"/> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					    <h2 class="mt-2" | 
				
			||||
 | 
					        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			||||
 | 
					        Our | 
				
			||||
 | 
					        Industries | 
				
			||||
 | 
					    </h2> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<div class="container my-5"> | 
				
			||||
 | 
					    <div class="row"> | 
				
			||||
 | 
					        <div class="col-lg-3"> | 
				
			||||
 | 
					            <div class="my-4 d-flex flex-column justify-content-center" | 
				
			||||
 | 
					                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
				
			||||
 | 
					                <img src="assets/icons/trading-black.png" | 
				
			||||
 | 
					                     class="img-responsive mb-3" height="48px" width="48px"> | 
				
			||||
 | 
					                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
				
			||||
 | 
					                    Trading | 
				
			||||
 | 
					                </h5> | 
				
			||||
 | 
					                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
				
			||||
 | 
					                    Easily procure | 
				
			||||
 | 
					                    and | 
				
			||||
 | 
					                    sell your products</p> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-3"> | 
				
			||||
 | 
					            <div class="my-4 d-flex flex-column justify-content-center" | 
				
			||||
 | 
					                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
				
			||||
 | 
					                <img src="assets/icons/pos-black.png" | 
				
			||||
 | 
					                     class="img-responsive mb-3" height="48px" width="48px"> | 
				
			||||
 | 
					                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
				
			||||
 | 
					                    POS | 
				
			||||
 | 
					                </h5> | 
				
			||||
 | 
					                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
				
			||||
 | 
					                    Easy | 
				
			||||
 | 
					                    configuration | 
				
			||||
 | 
					                    and convivial experience</p> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-3"> | 
				
			||||
 | 
					            <div class="my-4 d-flex flex-column justify-content-center" | 
				
			||||
 | 
					                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
				
			||||
 | 
					                <img src="assets/icons/education-black.png" | 
				
			||||
 | 
					                     class="img-responsive mb-3" height="48px" width="48px"> | 
				
			||||
 | 
					                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
				
			||||
 | 
					                    Education | 
				
			||||
 | 
					                </h5> | 
				
			||||
 | 
					                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
				
			||||
 | 
					                    A platform for | 
				
			||||
 | 
					                    educational management</p> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-3"> | 
				
			||||
 | 
					            <div class="my-4 d-flex flex-column justify-content-center" | 
				
			||||
 | 
					                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
				
			||||
 | 
					                <img src="assets/icons/manufacturing-black.png" | 
				
			||||
 | 
					                     class="img-responsive mb-3" height="48px" width="48px"> | 
				
			||||
 | 
					                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
				
			||||
 | 
					                    Manufacturing | 
				
			||||
 | 
					                </h5> | 
				
			||||
 | 
					                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
				
			||||
 | 
					                    Plan, track and | 
				
			||||
 | 
					                    schedule your operations</p> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-3"> | 
				
			||||
 | 
					            <div class="my-4 d-flex flex-column justify-content-center" | 
				
			||||
 | 
					                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
				
			||||
 | 
					                <img src="assets/icons/ecom-black.png" | 
				
			||||
 | 
					                     class="img-responsive mb-3" height="48px" width="48px"> | 
				
			||||
 | 
					                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
				
			||||
 | 
					                    E-commerce & Website | 
				
			||||
 | 
					                </h5> | 
				
			||||
 | 
					                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
				
			||||
 | 
					                    Mobile | 
				
			||||
 | 
					                    friendly, | 
				
			||||
 | 
					                    awe-inspiring product pages</p> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-3"> | 
				
			||||
 | 
					            <div class="my-4 d-flex flex-column justify-content-center" | 
				
			||||
 | 
					                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
				
			||||
 | 
					                <img src="assets/icons/service-black.png" | 
				
			||||
 | 
					                     class="img-responsive mb-3" height="48px" width="48px"> | 
				
			||||
 | 
					                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
				
			||||
 | 
					                    Service Management | 
				
			||||
 | 
					                </h5> | 
				
			||||
 | 
					                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
				
			||||
 | 
					                    Keep track of | 
				
			||||
 | 
					                    services and invoice</p> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-3"> | 
				
			||||
 | 
					            <div class="my-4 d-flex flex-column justify-content-center" | 
				
			||||
 | 
					                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
				
			||||
 | 
					                <img src="assets/icons/restaurant-black.png" | 
				
			||||
 | 
					                     class="img-responsive mb-3" height="48px" width="48px"> | 
				
			||||
 | 
					                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
				
			||||
 | 
					                    Restaurant | 
				
			||||
 | 
					                </h5> | 
				
			||||
 | 
					                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
				
			||||
 | 
					                    Run your bar or | 
				
			||||
 | 
					                    restaurant methodically</p> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-lg-3"> | 
				
			||||
 | 
					            <div class="my-4 d-flex flex-column justify-content-center" | 
				
			||||
 | 
					                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
				
			||||
 | 
					                <img src="assets/icons/hotel-black.png" | 
				
			||||
 | 
					                     class="img-responsive mb-3" height="48px" width="48px"> | 
				
			||||
 | 
					                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
				
			||||
 | 
					                    Hotel Management | 
				
			||||
 | 
					                </h5> | 
				
			||||
 | 
					                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
				
			||||
 | 
					                    An | 
				
			||||
 | 
					                    all-inclusive | 
				
			||||
 | 
					                    hotel management application</p> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<!-- END OF OUR INDUSTRIES --> | 
				
			||||
 | 
					<!-- SUPPORT --> | 
				
			||||
 | 
					<div class="d-flex align-items-center" | 
				
			||||
 | 
					     style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> | 
				
			||||
 | 
					    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			||||
 | 
					         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			||||
 | 
					        <img src="assets/misc/customer-support.png"/> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					    <h2 class="mt-2" | 
				
			||||
 | 
					        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			||||
 | 
					        Support | 
				
			||||
 | 
					    </h2> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<div class="container mt-5"> | 
				
			||||
 | 
					    <div class="row"> | 
				
			||||
 | 
					        <div class="col-sm-12 col-md-6"> | 
				
			||||
 | 
					            <div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> | 
				
			||||
 | 
					                <div class="mr-4 d-flex justify-content-center align-items-center" | 
				
			||||
 | 
					                     style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> | 
				
			||||
 | 
					                    <img src="assets/misc/support.png" height="48" width="48" | 
				
			||||
 | 
					                         style="width: 42px; height: 42px;"/> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					                <div> | 
				
			||||
 | 
					                    <h4>Need Help?</h4> | 
				
			||||
 | 
					                    <p style="line-height: 100%;">Got questions or need help? | 
				
			||||
 | 
					                        Get in touch.</p> | 
				
			||||
 | 
					                    <a href="mailto:odoo@cybrosys.com"> | 
				
			||||
 | 
					                        <p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> | 
				
			||||
 | 
					                            odoo@cybrosys.com</p> | 
				
			||||
 | 
					                    </a> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					        <div class="col-sm-12 col-md-6"> | 
				
			||||
 | 
					            <div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> | 
				
			||||
 | 
					                <div class="mr-4 d-flex justify-content-center align-items-center" | 
				
			||||
 | 
					                     style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> | 
				
			||||
 | 
					                    <img src="assets/misc/whatsapp.png" height="52" width="52" | 
				
			||||
 | 
					                         style="width: 52px; height: 52px;"/> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					                <div> | 
				
			||||
 | 
					                    <h4>WhatsApp</h4> | 
				
			||||
 | 
					                    <p style="line-height: 100%;">Say hi to us on WhatsApp!</p> | 
				
			||||
 | 
					                    <a href="https://api.whatsapp.com/send?phone=918606827707"> | 
				
			||||
 | 
					                        <p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> | 
				
			||||
 | 
					                            +91 86068 | 
				
			||||
 | 
					                            27707</p> | 
				
			||||
 | 
					                    </a> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					    <div class="row"> | 
				
			||||
 | 
					        <div class="col-sm-12 my-5 d-flex justify-content-center align-items-center"> | 
				
			||||
 | 
					            <img src="assets/misc/logo.png" width="144" height="31" | 
				
			||||
 | 
					                 style="width:144px; height: 31px; margin-top: 40px;"/> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					<!-- END OF SUPPORT --> | 
				
			||||
@ -0,0 +1,365 @@ | 
				
			|||||
 | 
					.row { | 
				
			||||
 | 
					    margin: 1rem; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.o_dynamic_navbar { | 
				
			||||
 | 
					    margin: 1rem 0 1rem 0; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.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; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.grid-stack-item { | 
				
			||||
 | 
					    position: absolute !important; | 
				
			||||
 | 
					    font-size: 100%; | 
				
			||||
 | 
					    overflow:hidden; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.card:hover { | 
				
			||||
 | 
					    transform: scale(1.05); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.card-header { | 
				
			||||
 | 
					    border-radius: 0.5rem 0.5rem 0 0 !important; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.container { | 
				
			||||
 | 
					    max-width: 100% !important; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.tile-container { | 
				
			||||
 | 
					    padding: 0 0 0 10px; | 
				
			||||
 | 
					    border-radius: 0.5rem !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; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#search-input-chart { | 
				
			||||
 | 
					    margin-left: auto; | 
				
			||||
 | 
					    height: 2.4rem; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#searchclear { | 
				
			||||
 | 
					    position: absolute; | 
				
			||||
 | 
					    margin: 0.3rem 0 0 13.5rem; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.navbar-collapse { | 
				
			||||
 | 
					    margin-bottom: 8px !important; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					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; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.toggle-btn { | 
				
			||||
 | 
					    font-size: 15px; | 
				
			||||
 | 
					    position: absolute; | 
				
			||||
 | 
					    left: 18.2em; | 
				
			||||
 | 
					    display: inline-block; | 
				
			||||
 | 
					    padding: 4px 0 0 0; | 
				
			||||
 | 
					    border-radius: 0.5rem; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.theme-text { | 
				
			||||
 | 
					    font-family: Arial, sans-serif; | 
				
			||||
 | 
					    font-size: 1em; | 
				
			||||
 | 
					    opacity: 70%; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.search-group { | 
				
			||||
 | 
					    position: absolute; | 
				
			||||
 | 
					    right: 1.7em; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/*!* Hide default HTML checkbox *!*/ | 
				
			||||
 | 
					.toggle-btn input { | 
				
			||||
 | 
					    opacity: 0; | 
				
			||||
 | 
					    width: 0; | 
				
			||||
 | 
					    height: 0; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/*!* The slider *!*/ | 
				
			||||
 | 
					.slider { | 
				
			||||
 | 
					    position: absolute; | 
				
			||||
 | 
					    cursor: pointer; | 
				
			||||
 | 
					    top: 0; | 
				
			||||
 | 
					    left: 0; | 
				
			||||
 | 
					    right: 0; | 
				
			||||
 | 
					    bottom: 0; | 
				
			||||
 | 
					    background-color: #ccc; | 
				
			||||
 | 
					    -webkit-transition: .4s; | 
				
			||||
 | 
					    transition: .4s; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.theme_icon { | 
				
			||||
 | 
					    font-weight: bold; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.theme_icon:hover { | 
				
			||||
 | 
					    text-shadow: 2px 1px 20px #795db3; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.block_setting { | 
				
			||||
 | 
					    position: absolute; | 
				
			||||
 | 
					    top: 7px; | 
				
			||||
 | 
					    left: 10px; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.block_delete { | 
				
			||||
 | 
					    position: absolute; | 
				
			||||
 | 
					    top: 7px; | 
				
			||||
 | 
					    right: 20px; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.export_option { | 
				
			||||
 | 
					    position: absolute; | 
				
			||||
 | 
					    top: 9px; | 
				
			||||
 | 
					    right: 520px; | 
				
			||||
 | 
					    font-size: 15px; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#ExportMenu::after { | 
				
			||||
 | 
					    display: none; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.tile_edit { | 
				
			||||
 | 
					    color: #d2d2d2; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.block_edit { | 
				
			||||
 | 
					    color: #3f3f3f; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.dropdown-export { | 
				
			||||
 | 
					    right: 0; | 
				
			||||
 | 
					    top: 1em; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.block_setting, .block_delete, .block_export { | 
				
			||||
 | 
					    display: none; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.grid-stack-item:hover .block_setting, | 
				
			||||
 | 
					.grid-stack-item:hover .block_export, | 
				
			||||
 | 
					.grid-stack-item:hover .block_delete { | 
				
			||||
 | 
					    display: block; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.chart-edit { | 
				
			||||
 | 
					    position: absolute; | 
				
			||||
 | 
					    top: 0px; | 
				
			||||
 | 
					    left: 3px; | 
				
			||||
 | 
					    font-size: 16px; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.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%; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.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 { | 
				
			||||
 | 
					    padding: 1.2rem 0 2.6rem 0 !important; | 
				
			||||
 | 
					    border-bottom: 1px solid #3f3f3f1a !important; | 
				
			||||
 | 
					    color: #444444; | 
				
			||||
 | 
					    background-color: #e1e2e26e !important; | 
				
			||||
 | 
					    border-bottom: 5px solid #eef0f0 !important; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.theme_icon:hover { | 
				
			||||
 | 
					    text-shadow: 0px 0px 5px #9388ff; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.navbar-style { | 
				
			||||
 | 
					    margin-top: 1.2em; | 
				
			||||
 | 
					    border-radius: 0.5em; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.grid-stack > .grid-stack-item > .grid-stack-item-content { | 
				
			||||
 | 
					    overflow-x: unset !important; | 
				
			||||
 | 
					    overflow-y: unset !important; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.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; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    .search-group { | 
				
			||||
 | 
					        width: 50%; | 
				
			||||
 | 
					        position: absolute; | 
				
			||||
 | 
					        right: 3.7em; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    .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; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    .grid-stack-item-content { | 
				
			||||
 | 
					        cursor: move; | 
				
			||||
 | 
					        width: 211px; | 
				
			||||
 | 
					        height: 63px; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    /*    !* styles for mobile devices *!*/ | 
				
			||||
 | 
					    .grid-stack.grid-stack-one-column-mode > .grid-stack-item { | 
				
			||||
 | 
					        width: 100% !important; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    .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; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    #search-button { | 
				
			||||
 | 
					        position: relative; | 
				
			||||
 | 
					        left: 3.5em; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    .search-box { | 
				
			||||
 | 
					        top: -3em; | 
				
			||||
 | 
					        left: 7.5em; | 
				
			||||
 | 
					        margin: 0em -1.9em; | 
				
			||||
 | 
					        width: 79%; | 
				
			||||
 | 
					        position: relative; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    .navbar-toggler { | 
				
			||||
 | 
					        margin: 0.2em 1em; | 
				
			||||
 | 
					        padding: 0.25rem 0.5rem; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    .dropdown-add-items { | 
				
			||||
 | 
					        position: absolute; | 
				
			||||
 | 
					        color: #e4e4e4; | 
				
			||||
 | 
					        top: -2.6em; | 
				
			||||
 | 
					        left: 3.5em; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					} | 
				
			||||
@ -0,0 +1,598 @@ | 
				
			|||||
 | 
					odoo.define('advanced_dynamic_dashboard.Dashboard', function (require) { | 
				
			||||
 | 
					    "use strict"; | 
				
			||||
 | 
					    var AbstractAction = require('web.AbstractAction'); | 
				
			||||
 | 
					    var ajax = require('web.ajax'); | 
				
			||||
 | 
					    var core = require('web.core'); | 
				
			||||
 | 
					    var rpc = require('web.rpc'); | 
				
			||||
 | 
					    var QWeb = core.qweb; | 
				
			||||
 | 
					    var Dialog = require('web.Dialog'); | 
				
			||||
 | 
					    var DynamicDashboard = AbstractAction.extend({ | 
				
			||||
 | 
					        template: 'advanced_dynamic_dashboard', | 
				
			||||
 | 
					        events: { | 
				
			||||
 | 
					            'click .add_block': '_onClick_add_block', | 
				
			||||
 | 
					            'click .block_setting': '_onClick_block_setting', | 
				
			||||
 | 
					            'click .block_delete': '_onClick_block_delete', | 
				
			||||
 | 
					            'click #search-button': 'search_chart', | 
				
			||||
 | 
					            'click #searchclear': 'clear_search', | 
				
			||||
 | 
					            'click #dropdownNavbar': 'navbar_toggle', | 
				
			||||
 | 
					            'mouseenter #dropdownMenuButton': 'dropdown_toggle', | 
				
			||||
 | 
					            'click .chart_item_export': 'export_item', | 
				
			||||
 | 
					            'click #edit_layout': '_onClick_edit_layout', | 
				
			||||
 | 
					            'click #save_layout': '_onClick_save_layout', | 
				
			||||
 | 
					            'change #theme-toggle': 'switch_mode', | 
				
			||||
 | 
					            'change #start-date': '_onchangeFilter', | 
				
			||||
 | 
					            'change #end-date': '_onchangeFilter', | 
				
			||||
 | 
					            'mouseenter #theme-change-icon': 'show_mode_text', | 
				
			||||
 | 
					            'mouseleave #theme-change-icon': 'hide_mode_text', | 
				
			||||
 | 
					            'click .tile': '_onClick_tile' | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function to Initializes all the values while loading the file
 | 
				
			||||
 | 
					        init: function (parent, context) { | 
				
			||||
 | 
					            this.action_id = context['id']; | 
				
			||||
 | 
					            this._super(parent, context); | 
				
			||||
 | 
					            this.block_ids = []; | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Returns the function fetch_data when page load.
 | 
				
			||||
 | 
					        willStart: function () { | 
				
			||||
 | 
					            var self = this; | 
				
			||||
 | 
					            return $.when(this._super()).then(function () { | 
				
			||||
 | 
					                return self.fetch_data(); | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function return render_dashboards() and gridstack_init()
 | 
				
			||||
 | 
					        start: function () { | 
				
			||||
 | 
					            self = this; | 
				
			||||
 | 
					            this.set("title", 'Dashboard'); | 
				
			||||
 | 
					            return this._super().then(function () { | 
				
			||||
 | 
					                self.render_dashboards(); | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Fetch data and call rpc query to create chart or tile. return block_ids
 | 
				
			||||
 | 
					        fetch_data: function () { | 
				
			||||
 | 
					            self = this; | 
				
			||||
 | 
					            var def1 = this._rpc({ | 
				
			||||
 | 
					                model: 'dashboard.block', | 
				
			||||
 | 
					                method: 'get_dashboard_vals', | 
				
			||||
 | 
					                args: [[], this.action_id] | 
				
			||||
 | 
					            }).then(function (result) { | 
				
			||||
 | 
					                self.block_ids = result; | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					            return $.when(def1); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function change text of dark and light mode while clicking the dark and light button.
 | 
				
			||||
 | 
					        show_mode_text: function () { | 
				
			||||
 | 
					            this.$el.find('.theme_icon').next(this.el.querySelector('.theme-text')).remove(); | 
				
			||||
 | 
					            if ( this.$el.find('#theme-toggle').is(':checked')) {//Set text "Light Mode"
 | 
				
			||||
 | 
					                this.$el.find('.theme_icon').after('<span style="color: #d6e7ff" class="theme-text">⠀Light Mode</span>'); | 
				
			||||
 | 
					            } else { | 
				
			||||
 | 
					            //Set text "Dark Mode"
 | 
				
			||||
 | 
					                this.$el.find('.theme_icon').after('<span style="color: #000000" class="theme-text">⠀Dark Mode</span>'); | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            this.$el.find('.theme_icon').next(this.el.querySelector('.theme-text')).fadeIn(); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //While click button, hide the mode icon and text
 | 
				
			||||
 | 
					        hide_mode_text: function () { | 
				
			||||
 | 
					            this.$el.find('.theme_icon').next(this.el.querySelector('.theme-text')).fadeOut(function () { | 
				
			||||
 | 
					                $(this).remove(); | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function to change dashboard theme dark and light mode.
 | 
				
			||||
 | 
					        switch_mode: function (ev) { | 
				
			||||
 | 
					            this.$el.find('.theme_icon').next('.theme-text').remove(); | 
				
			||||
 | 
					            const isDarkTheme = this.$el.find('#theme-toggle').is(':checked'); | 
				
			||||
 | 
					            $(this.el.parentElement).toggleClass('dark-theme', isDarkTheme); | 
				
			||||
 | 
					            this.$el.find('.theme_icon').toggleClass('bi-sun-fill', isDarkTheme); | 
				
			||||
 | 
					            this.$el.find('.theme_icon').toggleClass('bi-moon-stars-fill', !isDarkTheme); | 
				
			||||
 | 
					            this.$el.find('.dropdown-export').toggleClass('dropdown-menu-dark', isDarkTheme); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function for applying filter
 | 
				
			||||
 | 
					        _onchangeFilter: function() { | 
				
			||||
 | 
					            var start_date = this.$('#start-date').val(); | 
				
			||||
 | 
					            var end_date = this.$('#end-date').val(); | 
				
			||||
 | 
					            if (!start_date) { | 
				
			||||
 | 
					                start_date = "null"; | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            if (!end_date) { | 
				
			||||
 | 
					                end_date = "null"; | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            this._rpc({ | 
				
			||||
 | 
					                model: 'dashboard.block', | 
				
			||||
 | 
					                method: 'get_dashboard_vals', | 
				
			||||
 | 
					                args: [[], this.action_id, start_date, end_date], | 
				
			||||
 | 
					            }).then(function (result) { | 
				
			||||
 | 
					                self.block_ids = result; | 
				
			||||
 | 
					                // Reinitialize gridstack layout after updating data
 | 
				
			||||
 | 
					                self.gridstack_init(self); | 
				
			||||
 | 
					                self.$('.o_dynamic_dashboard').empty(); | 
				
			||||
 | 
					                self.render_dashboards(); | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function fetch random color values and set chart color
 | 
				
			||||
 | 
					        get_colors: function (x_axis) { | 
				
			||||
 | 
					            return x_axis.map(() => `rgb(${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)})`); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Set bar chart label, color, data and options. And return data and options
 | 
				
			||||
 | 
					        get_values_bar: function (block) { | 
				
			||||
 | 
					            var data = { | 
				
			||||
 | 
					                labels: block.x_axis, | 
				
			||||
 | 
					                datasets: [{ | 
				
			||||
 | 
					                    data: block.y_axis, | 
				
			||||
 | 
					                    backgroundColor: this.get_colors(block.x_axis), | 
				
			||||
 | 
					                    borderColor: 'rgba(200, 200, 200, 0.75)', | 
				
			||||
 | 
					                    borderWidth: 1 | 
				
			||||
 | 
					                }] | 
				
			||||
 | 
					            }; | 
				
			||||
 | 
					            var options = { | 
				
			||||
 | 
					                scales: { | 
				
			||||
 | 
					                    y: { | 
				
			||||
 | 
					                        beginAtZero: true | 
				
			||||
 | 
					                    } | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					            }; | 
				
			||||
 | 
					            return [data, options]; | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Set pie chart data and options. And return data and options.
 | 
				
			||||
 | 
					        get_values_pie: function (block) { | 
				
			||||
 | 
					            var data = { | 
				
			||||
 | 
					                labels: block['x_axis'], | 
				
			||||
 | 
					                datasets: [{ | 
				
			||||
 | 
					                    label: '', | 
				
			||||
 | 
					                    data: block['y_axis'], | 
				
			||||
 | 
					                    backgroundColor: this.get_colors(block['x_axis']), | 
				
			||||
 | 
					                    hoverOffset: 4 | 
				
			||||
 | 
					                }] | 
				
			||||
 | 
					            }; | 
				
			||||
 | 
					            return [data, {}]; | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Set line chart label, data and options. And return data and options.
 | 
				
			||||
 | 
					        get_values_line: function (block) { | 
				
			||||
 | 
					            var data = { | 
				
			||||
 | 
					                labels: block['x_axis'], | 
				
			||||
 | 
					                datasets: [{ | 
				
			||||
 | 
					                    label: '', | 
				
			||||
 | 
					                    data: block['y_axis'], | 
				
			||||
 | 
					                    fill: false, | 
				
			||||
 | 
					                    borderColor: 'rgb(75, 192, 192)', | 
				
			||||
 | 
					                    tension: 0.1 | 
				
			||||
 | 
					                }] | 
				
			||||
 | 
					            }; | 
				
			||||
 | 
					            return [data, {}]; | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        // Set doughnut chart data and options. And return data and options.
 | 
				
			||||
 | 
					        get_values_doughnut: function (block) { | 
				
			||||
 | 
					            var data = { | 
				
			||||
 | 
					                labels: block['x_axis'], | 
				
			||||
 | 
					                datasets: [{ | 
				
			||||
 | 
					                    label: '', | 
				
			||||
 | 
					                    data: block['y_axis'], | 
				
			||||
 | 
					                    backgroundColor: this.get_colors(block['x_axis']), | 
				
			||||
 | 
					                    hoverOffset: 4 | 
				
			||||
 | 
					                }] | 
				
			||||
 | 
					            }; | 
				
			||||
 | 
					            return [data, {}]; | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        // Set radar chart data and options. And return data and options.
 | 
				
			||||
 | 
					        get_values_radar: function (block) { | 
				
			||||
 | 
					            var data = { | 
				
			||||
 | 
					                labels: block['x_axis'], | 
				
			||||
 | 
					                datasets: [{ | 
				
			||||
 | 
					                    label: '', | 
				
			||||
 | 
					                    data: block['y_axis'], | 
				
			||||
 | 
					                    fill: true, | 
				
			||||
 | 
					                    backgroundColor: 'rgba(255, 99, 132, 0.2)', | 
				
			||||
 | 
					                    borderColor: 'rgb(255, 99, 132)', | 
				
			||||
 | 
					                    pointBackgroundColor: 'rgb(255, 99, 132)', | 
				
			||||
 | 
					                    pointBorderColor: '#fff', | 
				
			||||
 | 
					                    pointHoverBackgroundColor: '#fff', | 
				
			||||
 | 
					                    pointHoverBorderColor: 'rgb(255, 99, 132)' | 
				
			||||
 | 
					                }] | 
				
			||||
 | 
					            }; | 
				
			||||
 | 
					            var options = { | 
				
			||||
 | 
					                    elements: { | 
				
			||||
 | 
					                        line: { | 
				
			||||
 | 
					                            borderWidth: 3 | 
				
			||||
 | 
					                        } | 
				
			||||
 | 
					                    } | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					            return [data, options]; | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        // Used gridstack to drag and resize chart and tile.
 | 
				
			||||
 | 
					        gridstack_init: function (self) {// Used gridstack to drag and resize chart and tile.
 | 
				
			||||
 | 
					            self.$('.grid-stack').gridstack({ | 
				
			||||
 | 
					                animate: true, | 
				
			||||
 | 
					                duration: 200, | 
				
			||||
 | 
					                handle: '.grid-stack-item-content', | 
				
			||||
 | 
					                draggable: { | 
				
			||||
 | 
					                    handle: '.grid-stack-item-content', | 
				
			||||
 | 
					                    scroll: true | 
				
			||||
 | 
					                }, | 
				
			||||
 | 
					                resizable:{ | 
				
			||||
 | 
					                aspectRatio:20/18, | 
				
			||||
 | 
					                }, | 
				
			||||
 | 
					                alwaysShowResizeHandle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent), | 
				
			||||
 | 
					                float: true | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					            self.gridstack_off(self); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        // Enable move and resize functionality
 | 
				
			||||
 | 
					        gridstack_on: function (self) { | 
				
			||||
 | 
					            var gridstack = self.$('.grid-stack').data('gridstack'); | 
				
			||||
 | 
					            gridstack.enableMove(true); | 
				
			||||
 | 
					            gridstack.enableResize(true); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        // Disable move and resize functionality
 | 
				
			||||
 | 
					        gridstack_off: function (self) { | 
				
			||||
 | 
					            var gridstack = self.$('.grid-stack').data('gridstack'); | 
				
			||||
 | 
					            gridstack.enableMove(false); | 
				
			||||
 | 
					            gridstack.enableResize(false); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function for rendering dashboards
 | 
				
			||||
 | 
					        render_dashboards: function () { | 
				
			||||
 | 
					            self.$("#save_layout").hide();//Hide save_layout button
 | 
				
			||||
 | 
					            _.each(this.block_ids, function (block) { | 
				
			||||
 | 
					                if (block['type'] == 'tile') { | 
				
			||||
 | 
					                    self.$('.o_dynamic_dashboard').append(QWeb.render('DynamicDashboardTile', {widget: block})); | 
				
			||||
 | 
					                    // Add the new tile to the Gridstack layout with correct position and size
 | 
				
			||||
 | 
					                    var newTile = self.$('.o_dynamic_dashboard').children().last(); | 
				
			||||
 | 
					                    // Check if the Gridstack element is initialized
 | 
				
			||||
 | 
					                    var gridstack = self.$('.grid-stack').data('gridstack'); | 
				
			||||
 | 
					                    if (gridstack) { | 
				
			||||
 | 
					                        gridstack.addWidget(newTile, block.x, block.y, block.width, block.height, block.autoPosition); | 
				
			||||
 | 
					                    } | 
				
			||||
 | 
					                } else { | 
				
			||||
 | 
					                    // Block type = 'chart'
 | 
				
			||||
 | 
					                    self.$('.o_dynamic_dashboard').append(QWeb.render('DynamicDashboardChart', {widget: block})); | 
				
			||||
 | 
					                    if (!('x_axis' in block)) { | 
				
			||||
 | 
					                        return false; | 
				
			||||
 | 
					                    } | 
				
			||||
 | 
					                    var type = block['graph_type']; | 
				
			||||
 | 
					                    var chart_type = 'self.get_values_' + `${type}(block)`; | 
				
			||||
 | 
					                    // Set up and render the chart using Chart.js
 | 
				
			||||
 | 
					                    var newChartContainer = self.$('.o_dynamic_dashboard').children().last(); | 
				
			||||
 | 
					                    new Chart(self.$('.chart_graphs').last(), { | 
				
			||||
 | 
					                        type: block['graph_type'], | 
				
			||||
 | 
					                        data: eval(chart_type)[0], | 
				
			||||
 | 
					                        options: eval(chart_type)[1] | 
				
			||||
 | 
					                    }); | 
				
			||||
 | 
					                    // Check if the Gridstack element is initialized
 | 
				
			||||
 | 
					                    var gridstack = self.$('.grid-stack').data('gridstack'); | 
				
			||||
 | 
					                    if (gridstack) { | 
				
			||||
 | 
					                        // Add the new chart container to the Gridstack layout at the original position
 | 
				
			||||
 | 
					                        gridstack.addWidget(newChartContainer, block.x, block.y, block.width, block.height, block.autoPosition); | 
				
			||||
 | 
					                    } | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					            // Toggling dropdown for exporting, clicked item, closing all others
 | 
				
			||||
 | 
					            // When clicked on one, also when mouse leaves parent.
 | 
				
			||||
 | 
					            self.$(".block_export").on({ | 
				
			||||
 | 
					                click: function () {//Show the export dropdown.
 | 
				
			||||
 | 
					                    if ($(this).next(".dropdown-export").is(':visible')) { | 
				
			||||
 | 
					                        $(this).next(".dropdown-export").hide(); | 
				
			||||
 | 
					                    } else { | 
				
			||||
 | 
					                        $(this).next('.dropdown-export').hide(); | 
				
			||||
 | 
					                        $(this).next(".dropdown-export").show(); | 
				
			||||
 | 
					                    } | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					            //Function to hide dropdown-export list while mouse leave the block.
 | 
				
			||||
 | 
					            self.$(".grid-stack-item").on({ | 
				
			||||
 | 
					                mouseleave: function () { | 
				
			||||
 | 
					                   self.$('.dropdown-export').hide(); | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					            //Function to hide dropdown-addblock list if mouse leave dropdown
 | 
				
			||||
 | 
					            //list.
 | 
				
			||||
 | 
					            self.$(".dropdown-addblock").on({ | 
				
			||||
 | 
					                mouseleave: function () { | 
				
			||||
 | 
					                    self.$(".dropdown-addblock").hide(); | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					            self.gridstack_init(self); | 
				
			||||
 | 
					            if (localStorage.getItem("toggleState") == 'true') { | 
				
			||||
 | 
					                self.$(".toggle").prop('checked', true) | 
				
			||||
 | 
					                $(self.el.parentElement).addClass('dark-theme'); | 
				
			||||
 | 
					                self.$(".theme_icon").removeClass('bi-moon-stars-fill'); | 
				
			||||
 | 
					                self.$(".theme_icon").addClass('bi-sun-fill'); | 
				
			||||
 | 
					                self.$(".dropdown-export").addClass('dropdown-menu-dark'); | 
				
			||||
 | 
					            } else { | 
				
			||||
 | 
					                $(self.el.parentElement).removeClass('dark-theme'); | 
				
			||||
 | 
					                self.$(".theme_icon").removeClass('bi-sun-fill'); | 
				
			||||
 | 
					                self.$(".theme_icon").addClass('bi-moon-stars-fill'); | 
				
			||||
 | 
					                self.$(".dropdown-export").removeClass('dropdown-menu-dark'); | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function to toggle the navbar.
 | 
				
			||||
 | 
					        navbar_toggle: function () { | 
				
			||||
 | 
					            this.$('.navbar-collapse').toggle(); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function to export chart into jpg, png or csv formate.
 | 
				
			||||
 | 
					        export_item: function (e) { | 
				
			||||
 | 
					            var type = $(e.currentTarget).attr('data-type'); | 
				
			||||
 | 
					            var canvas = $(e.currentTarget).closest('.export_option').siblings('.row').find('#canvas')[0]; | 
				
			||||
 | 
					            var dataTitle = canvas.getAttribute("data-title"); | 
				
			||||
 | 
					            // Create a new canvas with a white background
 | 
				
			||||
 | 
					            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); | 
				
			||||
 | 
					            // Draw the chart onto the new canvas
 | 
				
			||||
 | 
					            bgCtx.drawImage(canvas, 0, 0); | 
				
			||||
 | 
					            // Export the new canvas as an image
 | 
				
			||||
 | 
					            var imgData = bgCanvas.toDataURL("image/png"); | 
				
			||||
 | 
					            if (type === 'png') { | 
				
			||||
 | 
					                this.$el.find('.chart_png_export').attr({ | 
				
			||||
 | 
					                    href: imgData, | 
				
			||||
 | 
					                    download: `${dataTitle}.png` | 
				
			||||
 | 
					                }); | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            if (type === 'pdf') { | 
				
			||||
 | 
					                var pdf = new jsPDF(); | 
				
			||||
 | 
					                pdf.addImage(bgCanvas.toDataURL("image/png"), 'PNG', 0, 0); | 
				
			||||
 | 
					                pdf.save(`${dataTitle}.pdf`); | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            if (type === 'csv') { | 
				
			||||
 | 
					                var rows = []; | 
				
			||||
 | 
					                // Check if the id inside the object is equal to this id
 | 
				
			||||
 | 
					                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); | 
				
			||||
 | 
					                    } | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					                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); // Required for FF
 | 
				
			||||
 | 
					                link.click(); | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function to toggle the button Add Items.
 | 
				
			||||
 | 
					        dropdown_toggle: function () { | 
				
			||||
 | 
					            this.$el.find('.dropdown-addblock').show(); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function return all block in exact position.
 | 
				
			||||
 | 
					        on_reverse_breadcrumb: function () { | 
				
			||||
 | 
					            this.fetch_data().then(function () {//Fetch all datas
 | 
				
			||||
 | 
					                self.render_dashboards(); | 
				
			||||
 | 
					                self.gridstack_init(self); | 
				
			||||
 | 
					                location.reload(); | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        // Fetch search input value and filter the chart and tile.
 | 
				
			||||
 | 
					        search_chart: function (e) { | 
				
			||||
 | 
					            e.stopPropagation(); | 
				
			||||
 | 
					            var self = this; | 
				
			||||
 | 
					            // Hide certain elements
 | 
				
			||||
 | 
					            self.$(this).next("#theme-change-icon").hide(); | 
				
			||||
 | 
					            self.$("#edit_layout").hide(); | 
				
			||||
 | 
					            self.$("#save_layout").hide(); | 
				
			||||
 | 
					            self.$(".date-inputs").hide(); | 
				
			||||
 | 
					            // Clear existing Gridstack layout
 | 
				
			||||
 | 
					            self.$('.grid-stack').data('gridstack').removeAll(); | 
				
			||||
 | 
					            // Empty the dynamic dashboard container
 | 
				
			||||
 | 
					            self.$('.o_dynamic_dashboard').empty(); | 
				
			||||
 | 
					            // Fetch filtered data using Ajax
 | 
				
			||||
 | 
					            ajax.jsonRpc("/custom_dashboard/search_input_chart", 'call', { | 
				
			||||
 | 
					                'search_input': self.$("#search-input-chart").val() | 
				
			||||
 | 
					            }).then(function (res) { | 
				
			||||
 | 
					                // Iterate through block_ids
 | 
				
			||||
 | 
					                _.each(self.block_ids, function (block) { | 
				
			||||
 | 
					                    if (res.includes(block['id'])) { | 
				
			||||
 | 
					                        // Check block type and render accordingly
 | 
				
			||||
 | 
					                        if (block['type'] == 'tile') { | 
				
			||||
 | 
					                            self.$('.o_dynamic_dashboard').append(QWeb.render('DynamicDashboardTile', {widget: block})); | 
				
			||||
 | 
					                            // Add the new tile to the Gridstack layout
 | 
				
			||||
 | 
					                            var newTile = self.$('.o_dynamic_dashboard').children().last(); | 
				
			||||
 | 
					                            self.$('.grid-stack').data('gridstack').addWidget(newTile, block.x, block.y, block.width, block.height, block.autoPosition); | 
				
			||||
 | 
					                        } else {  // Block type = 'chart'
 | 
				
			||||
 | 
					                            self.$('.o_dynamic_dashboard').append(QWeb.render('DynamicDashboardChart', {widget: block})); | 
				
			||||
 | 
					                            // Check if 'x_axis' is present in block
 | 
				
			||||
 | 
					                            if (!('x_axis' in block)) { | 
				
			||||
 | 
					                                return false; | 
				
			||||
 | 
					                            } | 
				
			||||
 | 
					                            // Set up and render the chart using Chart.js
 | 
				
			||||
 | 
					                            var type = block['graph_type']; | 
				
			||||
 | 
					                            var newChartContainer = self.$('.o_dynamic_dashboard').children().last(); | 
				
			||||
 | 
					                            var chart_type = 'self.get_values_' + `${block['graph_type']}(block)` | 
				
			||||
 | 
					                            new Chart(self.$('.chart_graphs').last(), { | 
				
			||||
 | 
					                                type: block['graph_type'], | 
				
			||||
 | 
					                                data: eval(chart_type)[0], | 
				
			||||
 | 
					                                options: eval(chart_type)[1] | 
				
			||||
 | 
					                            }); | 
				
			||||
 | 
					                            // Add the new chart container to the Gridstack layout at the original position
 | 
				
			||||
 | 
					                            self.$('.grid-stack').data('gridstack').addWidget(newChartContainer, block.x, block.y, block.width, block.height, block.autoPosition); | 
				
			||||
 | 
					                        } | 
				
			||||
 | 
					                    } | 
				
			||||
 | 
					                }); | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					            // Initialize Gridstack
 | 
				
			||||
 | 
					            self.gridstack_init(self); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function to clear search box and call the functon on_reverse_breadcrumb().
 | 
				
			||||
 | 
					        clear_search: function () { | 
				
			||||
 | 
					            self.$("#search-input-chart").val(""); | 
				
			||||
 | 
					            self.$("#theme-change-icon").show(); | 
				
			||||
 | 
					            self.$("#edit_layout").show(); | 
				
			||||
 | 
					            self.$("#save_layout").hide(); | 
				
			||||
 | 
					            self.$(".date-inputs").show(); | 
				
			||||
 | 
					            self.block_ids = []; | 
				
			||||
 | 
					            self.on_reverse_breadcrumb(); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function to edit blocks and redirect to the model dashboard.block
 | 
				
			||||
 | 
					        _onClick_block_setting: function (event) { | 
				
			||||
 | 
					            event.stopPropagation(); | 
				
			||||
 | 
					            this.do_action({ | 
				
			||||
 | 
					                type: 'ir.actions.act_window', | 
				
			||||
 | 
					                res_model: 'dashboard.block', | 
				
			||||
 | 
					                view_mode: 'form', | 
				
			||||
 | 
					                res_id: parseInt($(event.currentTarget).closest('.block').attr('data-id')), | 
				
			||||
 | 
					                views: [[false, 'form']], | 
				
			||||
 | 
					                context: {'form_view_initial_mode': 'edit'}, | 
				
			||||
 | 
					            }, {on_reverse_breadcrumb: self.on_reverse_breadcrumb}) | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //While click on cross icon, the block will be deleted.
 | 
				
			||||
 | 
					        _onClick_block_delete: function (event) { | 
				
			||||
 | 
					            event.stopPropagation(); | 
				
			||||
 | 
					            bootbox.confirm({//Popup to conform delete
 | 
				
			||||
 | 
					                message: "Are you sure you want to delete this item?", | 
				
			||||
 | 
					                title: "Delete confirmation", | 
				
			||||
 | 
					                buttons: { | 
				
			||||
 | 
					                    cancel: { | 
				
			||||
 | 
					                        label: 'NO, GO BACK', | 
				
			||||
 | 
					                        className: 'btn-primary' | 
				
			||||
 | 
					                    }, | 
				
			||||
 | 
					                    confirm: { | 
				
			||||
 | 
					                        label: 'YES, I\'M SURE', | 
				
			||||
 | 
					                        className: 'btn-danger' | 
				
			||||
 | 
					                    } | 
				
			||||
 | 
					                }, | 
				
			||||
 | 
					                //Function to unlink block
 | 
				
			||||
 | 
					                callback: function (result) { | 
				
			||||
 | 
					                    if (result) { | 
				
			||||
 | 
					                        rpc.query({ | 
				
			||||
 | 
					                            model: 'dashboard.block', | 
				
			||||
 | 
					                            method: 'unlink', | 
				
			||||
 | 
					                            args: [parseInt($(event.currentTarget).closest('.block').attr('data-id'))], // ID of the record to unlink
 | 
				
			||||
 | 
					                        }).then(function (result) { | 
				
			||||
 | 
					                             location.reload() | 
				
			||||
 | 
					                            self.on_reverse_breadcrumb(); | 
				
			||||
 | 
					                        }).catch(function (error) { | 
				
			||||
 | 
					                        }); | 
				
			||||
 | 
					                    } else { | 
				
			||||
 | 
					                        // Do nothing
 | 
				
			||||
 | 
					                    } | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        // Method for converting to camel case
 | 
				
			||||
 | 
					        convertToCamelCase: function (chartType) { | 
				
			||||
 | 
					            switch (chartType) { | 
				
			||||
 | 
					                case "bar": | 
				
			||||
 | 
					                    return "Bar"; | 
				
			||||
 | 
					                case "radar": | 
				
			||||
 | 
					                    return "Radar"; | 
				
			||||
 | 
					                case "pie": | 
				
			||||
 | 
					                    return "Pie"; | 
				
			||||
 | 
					                case "line": | 
				
			||||
 | 
					                    return "Line"; | 
				
			||||
 | 
					                case "doughnut": | 
				
			||||
 | 
					                    return "Doughnut"; | 
				
			||||
 | 
					                default: | 
				
			||||
 | 
					                    // If the chart type is not recognized, you can handle it accordingly
 | 
				
			||||
 | 
					                    return chartType; | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Fetch data and create chart or tile
 | 
				
			||||
 | 
					        _onClick_add_block: function (e) { | 
				
			||||
 | 
					            var type = $(e.currentTarget).attr('data-type'); | 
				
			||||
 | 
					            if (type == 'graph') { | 
				
			||||
 | 
					                var chart_type = $(e.currentTarget).attr('data-chart_type'); | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            if (type === 'tile') { | 
				
			||||
 | 
					                var randomColor = '#' + ('000000' + Math.floor(Math.random() * 16777216).toString(16)).slice(-6); | 
				
			||||
 | 
					                this.do_action({// Redirect to dashboard.block
 | 
				
			||||
 | 
					                    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': 2, | 
				
			||||
 | 
					                        'default_width': 2, | 
				
			||||
 | 
					                        'default_tile_color': randomColor, | 
				
			||||
 | 
					                        '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(); | 
				
			||||
 | 
					                    } | 
				
			||||
 | 
					                }); | 
				
			||||
 | 
					            } else { | 
				
			||||
 | 
					                this.do_action({ | 
				
			||||
 | 
					                    type: 'ir.actions.act_window', | 
				
			||||
 | 
					                    res_model: 'dashboard.block', | 
				
			||||
 | 
					                    view_mode: 'form', | 
				
			||||
 | 
					                    views: [[false, 'form']], | 
				
			||||
 | 
					                    context: { | 
				
			||||
 | 
					                        'form_view_initial_mode': 'edit', | 
				
			||||
 | 
					                        'default_name': 'New ' + self.convertToCamelCase(chart_type), | 
				
			||||
 | 
					                        'default_type': type, | 
				
			||||
 | 
					                        '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(); | 
				
			||||
 | 
					                    } | 
				
			||||
 | 
					                }); | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            // Fetching saved layout from localstorage memory.
 | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        // Function to hide edit_layout button and show save_layout button. and also work the function gridstack_on(self)
 | 
				
			||||
 | 
					        _onClick_edit_layout: function (e) { | 
				
			||||
 | 
					            e.stopPropagation(); | 
				
			||||
 | 
					            self.$(".date-inputs").hide(); | 
				
			||||
 | 
					            self.$("#edit_layout").hide(); | 
				
			||||
 | 
					            self.$("#save_layout").show(); | 
				
			||||
 | 
					            self.gridstack_on(self); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        //Function to save the edited value
 | 
				
			||||
 | 
					        _onClick_save_layout: function (e) { | 
				
			||||
 | 
					            e.stopPropagation(); | 
				
			||||
 | 
					            self.$(".date-inputs").show(); | 
				
			||||
 | 
					            self.$("#edit_layout").show(); | 
				
			||||
 | 
					            self.$("#save_layout").hide(); | 
				
			||||
 | 
					            var grid_data_list = []; | 
				
			||||
 | 
					            this.$el.find('.grid-stack-item').each(function () { | 
				
			||||
 | 
					                grid_data_list.push({ | 
				
			||||
 | 
					                    'id': $(this).data('id'), | 
				
			||||
 | 
					                    'x': $(this).data('gs-x'), | 
				
			||||
 | 
					                    'y': $(this).data('gs-y'), | 
				
			||||
 | 
					                    'width': $(this).data('gs-width'), | 
				
			||||
 | 
					                    'height': $(this).data('gs-height') | 
				
			||||
 | 
					                }) | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					            this._rpc({ | 
				
			||||
 | 
					                model: 'dashboard.block', | 
				
			||||
 | 
					                method: 'get_save_layout', | 
				
			||||
 | 
					                args: [[], this.action_id, grid_data_list] | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					            self.gridstack_off(self); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        // Function to view the tree view of the tile.
 | 
				
			||||
 | 
					        _onClick_tile: function (e) { | 
				
			||||
 | 
					            e.stopPropagation(); | 
				
			||||
 | 
					            ajax.jsonRpc('/tile/details', 'call', { | 
				
			||||
 | 
					                'id': $(e.currentTarget).attr('data-id') | 
				
			||||
 | 
					            }).then(function (result) { | 
				
			||||
 | 
					                if (result['model_name']) { | 
				
			||||
 | 
					                    self.do_action({ | 
				
			||||
 | 
					                        name: result['model_name'], | 
				
			||||
 | 
					                        type: 'ir.actions.act_window', | 
				
			||||
 | 
					                        res_model: result['model'], | 
				
			||||
 | 
					                        view_mode: 'tree,form', | 
				
			||||
 | 
					                        views: [[false, 'list'], [false, 'form']], | 
				
			||||
 | 
					                        domain: result['filter'] | 
				
			||||
 | 
					                    }); | 
				
			||||
 | 
					                } else { | 
				
			||||
 | 
					                    Dialog.alert(this, "Configure the tile's model and parameters."); | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					            }); | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					    }); | 
				
			||||
 | 
					    core.action_registry.add('advanced_dynamic_dashboard', DynamicDashboard); | 
				
			||||
 | 
					    return DynamicDashboard; | 
				
			||||
 | 
					}); | 
				
			||||
@ -0,0 +1,171 @@ | 
				
			|||||
 | 
					
 | 
				
			||||
 | 
					: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; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.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; | 
				
			||||
 | 
					  right: 1rem; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					 .dark-theme { | 
				
			||||
 | 
					  /* Add dark theme styles here */ | 
				
			||||
 | 
					  .block_edit { | 
				
			||||
 | 
					    color: #b7b7b7 !important; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  .navbar { | 
				
			||||
 | 
					    padding: 1.2rem 0 2.6rem 0 !important; | 
				
			||||
 | 
					    border-bottom: 1px solid #3f3f3f1a !important; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  .theme_icon:hover { | 
				
			||||
 | 
					    text-shadow: 0px 0px 5px #9388ff; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					.add_block{ | 
				
			||||
 | 
					  color: #dfdfdf; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					  #ExportMenu { | 
				
			||||
 | 
					    color: #626262; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  .dropdown-export { | 
				
			||||
 | 
					    background-color: #2a2a2a; | 
				
			||||
 | 
					    color: #dfdfdf; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  .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_renderer { | 
				
			||||
 | 
					    background-color: #e8e8e8 !important; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  background-color: #1C1B1B; | 
				
			||||
 | 
					  @media (max-width: 767px) { | 
				
			||||
 | 
					    .navbar-light .navbar-toggler { | 
				
			||||
 | 
					      color: #A7A7A72D; | 
				
			||||
 | 
					      border-color: #F6F6F621; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					} | 
				
			||||
@ -0,0 +1,196 @@ | 
				
			|||||
 | 
					<?xml version="1.0" encoding="UTF-8"?> | 
				
			||||
 | 
					<templates id="template" xml:space="preserve"> | 
				
			||||
 | 
					    <!--Dashboard view with navigation bar and grid stack template--> | 
				
			||||
 | 
					    <t t-name="advanced_dynamic_dashboard"> | 
				
			||||
 | 
					        <div class="container mx-auto"> | 
				
			||||
 | 
					            <div class="navbar navbar-expand-md navbar-light bg-light mb-4 navbar-style border-bottom" | 
				
			||||
 | 
					                 role="navigation"> | 
				
			||||
 | 
					                <button class="navbar-toggler" id="dropdownNavbar" type="button" | 
				
			||||
 | 
					                        data-toggle="collapse" | 
				
			||||
 | 
					                        data-target="#navbarCollapse" | 
				
			||||
 | 
					                        aria-controls="navbarCollapse" aria-expanded="false" | 
				
			||||
 | 
					                        aria-label="Toggle navigation"> | 
				
			||||
 | 
					                    <span class="navbar-toggler-icon"/> | 
				
			||||
 | 
					                </button> | 
				
			||||
 | 
					                <div class="collapse navbar-collapse" | 
				
			||||
 | 
					                     aria-labelledby="dropdownNavbar"> | 
				
			||||
 | 
					                    <ul class="navbar-nav mr-auto"> | 
				
			||||
 | 
					                        <label class="navbar-items dropdown drop-down-add"> | 
				
			||||
 | 
					                            <button class="btn dropdown-add-items dropdown-toggle" | 
				
			||||
 | 
					                                    type="button" id="dropdownMenuButton" | 
				
			||||
 | 
					                                    data-toggle="dropdown" aria-haspopup="true" | 
				
			||||
 | 
					                                    aria-expanded="false"> | 
				
			||||
 | 
					                                <i class="bi bi-plus-circle-fill"/> | 
				
			||||
 | 
					                                <span>⠀Add Items</span> | 
				
			||||
 | 
					                            </button> | 
				
			||||
 | 
					                            <div class="dropdown-menu dropdown-addblock" | 
				
			||||
 | 
					                                 aria-labelledby="dropdownMenuButton"> | 
				
			||||
 | 
					                                <a class="dropdown-item add_block" | 
				
			||||
 | 
					                                   data-type="tile">Tile</a> | 
				
			||||
 | 
					                                <a class="dropdown-item add_block" | 
				
			||||
 | 
					                                   data-type="graph" data-chart_type="bar">Bar Chart</a> | 
				
			||||
 | 
					                                <a class="dropdown-item add_block" | 
				
			||||
 | 
					                                   data-type="graph" data-chart_type="doughnut">Doughnut Chart</a> | 
				
			||||
 | 
					                                <a class="dropdown-item add_block" | 
				
			||||
 | 
					                                   data-type="graph" | 
				
			||||
 | 
					                                   data-chart_type="line">Line Chart</a> | 
				
			||||
 | 
					                                <a class="dropdown-item add_block" | 
				
			||||
 | 
					                                   data-type="graph" data-chart_type="pie">Pie Chart</a> | 
				
			||||
 | 
					                                <a class="dropdown-item add_block" | 
				
			||||
 | 
					                                   data-type="graph" | 
				
			||||
 | 
					                                   data-chart_type="radar">Radar Chart</a> | 
				
			||||
 | 
					                            </div> | 
				
			||||
 | 
					                        </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 navbar-items btn-group" | 
				
			||||
 | 
					                             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; border-radius: 5px;  margin-right: 10px;"/> | 
				
			||||
 | 
					                            <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; border-radius: 5px;"/> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					                    </ul> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					            <div class="o_dynamic_dashboard row m-2 grid-stack" | 
				
			||||
 | 
					                 name="gridstack"> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    </t> | 
				
			||||
 | 
					    <t t-name="DynamicDashboardTile"> | 
				
			||||
 | 
					        <!--Tile building template--> | 
				
			||||
 | 
					        <div t-att-class="'grid-stack-item ' + widget.name" | 
				
			||||
 | 
					             t-att-data-gs-y="widget.y_pos" | 
				
			||||
 | 
					             t-att-data-gs-x="widget.x_pos" t-att-data-gs-width="widget.width" | 
				
			||||
 | 
					             t-att-data-gs-height="widget.height" | 
				
			||||
 | 
					             t-att-data-id="widget.id"> | 
				
			||||
 | 
					            <div class="grid-stack-item-content tile block" | 
				
			||||
 | 
					                 t-att-data-id="widget.id" | 
				
			||||
 | 
					                 t-att-style="widget.color+widget.text_color"> | 
				
			||||
 | 
					                <div t-att-style="widget.color+widget.text_color" | 
				
			||||
 | 
					                     class="tile-container d-flex  align-items-center  w-100  my-3"> | 
				
			||||
 | 
					                    <a class="block_setting tile_edit tile-container__setting-icon"> | 
				
			||||
 | 
					                        <i class="fa fa-edit"/> | 
				
			||||
 | 
					                    </a> | 
				
			||||
 | 
					                    <a class="block_delete tile_edit tile-container__delete-icon"> | 
				
			||||
 | 
					                        <i class="fa fa-times"/> | 
				
			||||
 | 
					                    </a> | 
				
			||||
 | 
					                    <div> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                    <div t-att-style="widget.icon_color" | 
				
			||||
 | 
					                         class="tile-container__icon-container bg-white d-flex justify-content-center align-items-center"> | 
				
			||||
 | 
					                        <i t-att-class="widget.icon"/> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                    <div t-att-style="widget.text_color" | 
				
			||||
 | 
					                         class="tile-container__status-container"> | 
				
			||||
 | 
					                        <h2 t-att-style="widget.text_color" | 
				
			||||
 | 
					                            class="status-container__title"> | 
				
			||||
 | 
					                            <t t-esc="widget.name"/> | 
				
			||||
 | 
					                        </h2> | 
				
			||||
 | 
					                        <div class="status-container__figures d-flex flex-wrap align-items-baseline"> | 
				
			||||
 | 
					                            <h3 class="mb-0 mb-md-1 mb-lg-0 mr-1" | 
				
			||||
 | 
					                                t-att-style="widget.val_color"> | 
				
			||||
 | 
					                                <t t-esc="widget.value"/> | 
				
			||||
 | 
					                            </h3> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    </t> | 
				
			||||
 | 
					    <t t-name="DynamicDashboardChart"> | 
				
			||||
 | 
					        <!-- Chart building template--> | 
				
			||||
 | 
					        <div t-att-class="'grid-stack-item ' + widget.name" | 
				
			||||
 | 
					             t-att-data-gs-x="widget.x_pos" | 
				
			||||
 | 
					             t-att-data-gs-y="widget.y_pos" t-att-data-gs-width="widget.width" | 
				
			||||
 | 
					             t-att-data-gs-height="widget.height" | 
				
			||||
 | 
					             t-att-data-id="widget.id"> | 
				
			||||
 | 
					            <div class="grid-stack-item-content block card" | 
				
			||||
 | 
					                 t-att-data-id="widget.id"> | 
				
			||||
 | 
					                <div class="card-body mt-1" id="in_ex_body_hide"> | 
				
			||||
 | 
					                    <div class="block_edit block_setting"> | 
				
			||||
 | 
					                        <i title="Configuration" | 
				
			||||
 | 
					                           class="fa fa-pencil block_setting chart-edit"/> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                    <div class="dropdown export_option"> | 
				
			||||
 | 
					                        <div class="block_edit fa fa-ellipsis-v block_export dropdown-toggle" | 
				
			||||
 | 
					                             type="button" | 
				
			||||
 | 
					                             id="ExportMenu" data-toggle="dropdown" | 
				
			||||
 | 
					                             aria-haspopup="true" aria-expanded="false"> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					                        <div class="dropdown-menu dropdown-export" | 
				
			||||
 | 
					                             aria-labelledby="ExportMenu"> | 
				
			||||
 | 
					                            <div class="m-2 chart_export_menu_header"> | 
				
			||||
 | 
					                                <span>Export</span> | 
				
			||||
 | 
					                            </div> | 
				
			||||
 | 
					                            <a class="dropdown-item chart_item_export chart_png_export" | 
				
			||||
 | 
					                               data-type="png"> | 
				
			||||
 | 
					                                <i class="fa fa-file-image-o"/> | 
				
			||||
 | 
					                                <span>Save as Image</span> | 
				
			||||
 | 
					                            </a> | 
				
			||||
 | 
					                            <button class="dropdown-item chart_pdf_export chart_item_export" | 
				
			||||
 | 
					                                    data-type="pdf"> | 
				
			||||
 | 
					                                <i class="fa fa-file-pdf-o"/> | 
				
			||||
 | 
					                                <span>Save as PDF</span> | 
				
			||||
 | 
					                            </button> | 
				
			||||
 | 
					                            <button class="dropdown-item chart_csv_export chart_item_export" | 
				
			||||
 | 
					                                    data-type="csv" | 
				
			||||
 | 
					                                    t-att-data-id="widget.id"> | 
				
			||||
 | 
					                                <i class="fa fa-file-code-o"/> | 
				
			||||
 | 
					                                <span>Export to CSV</span> | 
				
			||||
 | 
					                            </button> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                    <div class="block_edit block_delete"> | 
				
			||||
 | 
					                        <i title="Delete" | 
				
			||||
 | 
					                           class="fa fa-times block_delete chart-setting"/> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                    <h3 class="chart_title"> | 
				
			||||
 | 
					                        <t t-esc="widget.name"/> | 
				
			||||
 | 
					                    </h3> | 
				
			||||
 | 
					                    <div class="row"> | 
				
			||||
 | 
					                        <div class="col-md-12 chart_canvas" id="chart_canvas" | 
				
			||||
 | 
					                             t-att-data-id="widget.id"> | 
				
			||||
 | 
					                            <canvas id="canvas" class="chart_graphs" | 
				
			||||
 | 
					                                    t-att-data-title="widget.name"/> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    </t> | 
				
			||||
 | 
					</templates> | 
				
			||||
@ -0,0 +1,63 @@ | 
				
			|||||
 | 
					<?xml version="1.0" encoding="utf-8"?> | 
				
			||||
 | 
					<odoo> | 
				
			||||
 | 
					    <!--Kanban view of the dashboard menu--> | 
				
			||||
 | 
					    <record id="dashboard_menu_view_kanban" model="ir.ui.view"> | 
				
			||||
 | 
					        <field name="name">dashboard.menu.view.kanban</field> | 
				
			||||
 | 
					        <field name="model">dashboard.menu</field> | 
				
			||||
 | 
					        <field name="arch" type="xml"> | 
				
			||||
 | 
					            <kanban> | 
				
			||||
 | 
					                <field name="name"/> | 
				
			||||
 | 
					                <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> | 
				
			||||
 | 
					                            <div class="row"> | 
				
			||||
 | 
					                                <hr class="mt4 mb4"/> | 
				
			||||
 | 
					                                <div class="col-6 text-center"> | 
				
			||||
 | 
					                                    <strong>Parent:</strong> | 
				
			||||
 | 
					                                </div> | 
				
			||||
 | 
					                                <div class="col-6 text-center"> | 
				
			||||
 | 
					                                    <field name="menu_id"/> | 
				
			||||
 | 
					                                </div> | 
				
			||||
 | 
					                            </div> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					                    </t> | 
				
			||||
 | 
					                </templates> | 
				
			||||
 | 
					            </kanban> | 
				
			||||
 | 
					        </field> | 
				
			||||
 | 
					    </record> | 
				
			||||
 | 
					    <!--Form view of the dashboard menu--> | 
				
			||||
 | 
					    <record id="dashboard_menu_view_form" model="ir.ui.view"> | 
				
			||||
 | 
					        <field name="name">dashboard.menu.view.form</field> | 
				
			||||
 | 
					        <field name="model">dashboard.menu</field> | 
				
			||||
 | 
					        <field name="arch" type="xml"> | 
				
			||||
 | 
					            <form> | 
				
			||||
 | 
					                <sheet> | 
				
			||||
 | 
					                    <group> | 
				
			||||
 | 
					                        <group> | 
				
			||||
 | 
					                            <field name="name" class="oe_inline"/> | 
				
			||||
 | 
					                            <field name="menu_id" class="oe_inline"/> | 
				
			||||
 | 
					                            <field name="group_ids" widget="many2many_tags" | 
				
			||||
 | 
					                                   invisible="1"/> | 
				
			||||
 | 
					                            <field name="client_action_id" invisible="1"/> | 
				
			||||
 | 
					                        </group> | 
				
			||||
 | 
					                    </group> | 
				
			||||
 | 
					                </sheet> | 
				
			||||
 | 
					            </form> | 
				
			||||
 | 
					        </field> | 
				
			||||
 | 
					    </record> | 
				
			||||
 | 
					    <!--    Action specified for the dashboard menu--> | 
				
			||||
 | 
					    <record id="dashboard_menu_action" model="ir.actions.act_window"> | 
				
			||||
 | 
					        <field name="name">Dashboards Menu</field> | 
				
			||||
 | 
					        <field name="type">ir.actions.act_window</field> | 
				
			||||
 | 
					        <field name="res_model">dashboard.menu</field> | 
				
			||||
 | 
					        <field name="view_mode">kanban,form</field> | 
				
			||||
 | 
					    </record> | 
				
			||||
 | 
					    <!--    Dashboards Menu--> | 
				
			||||
 | 
					    <menuitem id="dashboard_menu_menu" name="Dashboards" | 
				
			||||
 | 
					              parent="advanced_dynamic_dashboard.dashboard_menu_root" | 
				
			||||
 | 
					              sequence="0" action="dashboard_menu_action"/> | 
				
			||||
 | 
					</odoo> | 
				
			||||
@ -0,0 +1,13 @@ | 
				
			|||||
 | 
					<?xml version="1.0" encoding="utf-8"?> | 
				
			||||
 | 
					<odoo> | 
				
			||||
 | 
					    <!--    The client action record to view the Dashboard--> | 
				
			||||
 | 
					    <record id="dashboard_menu_root_action" model="ir.actions.client"> | 
				
			||||
 | 
					        <field name="name">Dashboard</field> | 
				
			||||
 | 
					        <field name="tag">advanced_dynamic_dashboard</field> | 
				
			||||
 | 
					    </record> | 
				
			||||
 | 
					    <!--    Dynamic Dashboards menu--> | 
				
			||||
 | 
					    <menuitem id="dashboard_menu_root" name="Dynamic Dashboards" | 
				
			||||
 | 
					              action="dashboard_menu_root_action" | 
				
			||||
 | 
					              web_icon="advanced_dynamic_dashboard,static/description/icon.png" | 
				
			||||
 | 
					              sequence="-1"/> | 
				
			||||
 | 
					</odoo> | 
				
			||||
@ -0,0 +1,74 @@ | 
				
			|||||
 | 
					<?xml version="1.0" encoding="utf-8"?> | 
				
			||||
 | 
					<odoo> | 
				
			||||
 | 
					    <!--Form view of the dashboard block--> | 
				
			||||
 | 
					    <record id="dashboard_block_view_form" model="ir.ui.view"> | 
				
			||||
 | 
					        <field name="name">dashboard.block.view.form</field> | 
				
			||||
 | 
					        <field name="model">dashboard.block</field> | 
				
			||||
 | 
					        <field name="arch" type="xml"> | 
				
			||||
 | 
					            <form> | 
				
			||||
 | 
					                <sheet> | 
				
			||||
 | 
					                    <group> | 
				
			||||
 | 
					                        <group> | 
				
			||||
 | 
					                            <div> | 
				
			||||
 | 
					                                <field name="name" class="oe_inline" | 
				
			||||
 | 
					                                       style="font-size: 30px;" | 
				
			||||
 | 
					                                       placeholder="Block Name" required="1"/> | 
				
			||||
 | 
					                            </div> | 
				
			||||
 | 
					                        </group> | 
				
			||||
 | 
					                    </group> | 
				
			||||
 | 
					                    <group> | 
				
			||||
 | 
					                        <group> | 
				
			||||
 | 
					                            <field name="model_id" | 
				
			||||
 | 
					                                   attrs="{'required':[('edit_mode','=', True)]}"/> | 
				
			||||
 | 
					                            <field name="client_action_id" invisible="1"/> | 
				
			||||
 | 
					                            <field name="model_name" invisible="1"/> | 
				
			||||
 | 
					                            <field name="edit_mode" invisible="1"/> | 
				
			||||
 | 
					                            <field name="operation" | 
				
			||||
 | 
					                                   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)]}"/> | 
				
			||||
 | 
					                            <field name="filter" widget="domain" | 
				
			||||
 | 
					                                   options="{'model': 'model_name'}"/> | 
				
			||||
 | 
					                        </group> | 
				
			||||
 | 
					                    </group> | 
				
			||||
 | 
					                    <group string="Block Information"> | 
				
			||||
 | 
					                        <group> | 
				
			||||
 | 
					                            <field name="type" required="1"/> | 
				
			||||
 | 
					                            <field name="graph_type" | 
				
			||||
 | 
					                                   attrs="{'invisible': [('type','!=', 'graph')]}"/> | 
				
			||||
 | 
					                            <field name="graph_size" | 
				
			||||
 | 
					                                   attrs="{'invisible': [('type','!=', 'graph')]}"/> | 
				
			||||
 | 
					                            <field name="fa_icon" | 
				
			||||
 | 
					                                   attrs="{'invisible': [('type','!=', 'tile')]}"/> | 
				
			||||
 | 
					                            <field name="group_by_id" | 
				
			||||
 | 
					                                   attrs="{'invisible': [('type','!=', 'graph')], 'required':[('type','=','graph')]}" | 
				
			||||
 | 
					                                   domain="[('model_id','=',model_id),('relation','!=','res.users'), ('ttype','not in',['one2many','many2many']), ('store', '=', True)]"/> | 
				
			||||
 | 
					                            <field name="tile_color" | 
				
			||||
 | 
					                                   attrs="{'invisible': [('type','!=', 'tile')]}" | 
				
			||||
 | 
					                                   widget="color" class="mb-4 o_im_livechat_field_widget_color"/> | 
				
			||||
 | 
					                            <field name="val_color" | 
				
			||||
 | 
					                                   attrs="{'invisible': [('type','!=', 'tile')]}" | 
				
			||||
 | 
					                                   widget="color"/> | 
				
			||||
 | 
					                            <field name="text_color" | 
				
			||||
 | 
					                                   attrs="{'invisible': [('type','!=', 'tile')]}" | 
				
			||||
 | 
					                                   widget="color"/> | 
				
			||||
 | 
					                        </group> | 
				
			||||
 | 
					                    </group> | 
				
			||||
 | 
					                </sheet> | 
				
			||||
 | 
					            </form> | 
				
			||||
 | 
					        </field> | 
				
			||||
 | 
					    </record> | 
				
			||||
 | 
					    <!--Tree view of the dashboard block--> | 
				
			||||
 | 
					    <record id="dashboard_block_view_tree" model="ir.ui.view"> | 
				
			||||
 | 
					        <field name="name">dashboard.block.view.tree</field> | 
				
			||||
 | 
					        <field name="model">dashboard.block</field> | 
				
			||||
 | 
					        <field name="arch" type="xml"> | 
				
			||||
 | 
					            <tree> | 
				
			||||
 | 
					                <field name="name"/> | 
				
			||||
 | 
					                <field name="model_id"/> | 
				
			||||
 | 
					                <field name="type"/> | 
				
			||||
 | 
					            </tree> | 
				
			||||
 | 
					        </field> | 
				
			||||
 | 
					    </record> | 
				
			||||
 | 
					</odoo> | 
				
			||||
@ -0,0 +1,30 @@ | 
				
			|||||
 | 
					<?xml version="1.0" encoding="utf-8"?> | 
				
			||||
 | 
					<odoo> | 
				
			||||
 | 
					    <template id="assets_backend" name="advanced dynamic dashboard assets" | 
				
			||||
 | 
					              inherit_id="web.assets_backend"> | 
				
			||||
 | 
					        <xpath expr="." position="inside"> | 
				
			||||
 | 
					            <link rel="stylesheet" | 
				
			||||
 | 
					                  href="advanced_dynamic_dashboard/static/src/css/dynamic_dashboard.css"/> | 
				
			||||
 | 
					            <link rel="stylesheet" | 
				
			||||
 | 
					                  href='advanced_dynamic_dashboard/static/lib/css/gridstack.min.css'/> | 
				
			||||
 | 
					            <link rel="stylesheet" | 
				
			||||
 | 
					                  href='advanced_dynamic_dashboard/static/src/scss/dynamic_dashboard.scss'/> | 
				
			||||
 | 
					            <link rel="stylesheet" | 
				
			||||
 | 
					                  href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css"/> | 
				
			||||
 | 
					            <script type="text/javascript" | 
				
			||||
 | 
					                    src="/advanced_dynamic_dashboard/static/src/js/dynamic_dashboard.js"/> | 
				
			||||
 | 
					            <script type="text/javascript" | 
				
			||||
 | 
					                    src='https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.2.6/gridstack.min.js'/> | 
				
			||||
 | 
					            <script type="text/javascript" | 
				
			||||
 | 
					                    src='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js'/> | 
				
			||||
 | 
					            <script type="text/javascript" | 
				
			||||
 | 
					                    src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js"/> | 
				
			||||
 | 
					            <script type="text/javascript" | 
				
			||||
 | 
					                    src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"/> | 
				
			||||
 | 
					            <script type="text/javascript" | 
				
			||||
 | 
					                    src='https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js'/> | 
				
			||||
 | 
					            <script type="text/javascript" | 
				
			||||
 | 
					                    src='https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js'/> | 
				
			||||
 | 
					        </xpath> | 
				
			||||
 | 
					    </template> | 
				
			||||
 | 
					</odoo> | 
				
			||||