@ -0,0 +1,61 @@ |
|||
.. image:: https://img.shields.io/badge/license-LGPL--3-blue.svg |
|||
:target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html |
|||
:alt: License: LGPL-3 |
|||
|
|||
Website HelpDesk Dashboard |
|||
========================== |
|||
Website HelpDesk Dashboard Module Brings a Multipurpose Graphical Dashboard |
|||
for Website HelpDesk module |
|||
|
|||
Depends |
|||
======= |
|||
[odoo_website_helpdesk] Custom addon by Cybrosys. |
|||
|
|||
Tech |
|||
==== |
|||
* [Python] - Models |
|||
* [XML] - Odoo views |
|||
|
|||
Installation |
|||
============ |
|||
- www.odoo.com/documentation/18.0/setup/install.html |
|||
- Install our custom addon |
|||
|
|||
Company |
|||
------- |
|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
|||
|
|||
License |
|||
======= |
|||
General Public License, Version 3 (LGPL-3 v3). |
|||
(https://www.gnu.org/licenses/lgpl-3.0-standalone.html) |
|||
|
|||
Credits |
|||
======= |
|||
Developers: (V16) Robin K , |
|||
(V17) Fathima Mazlin AM, |
|||
(V18) Akhil Ashok, |
|||
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: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from . import controllers |
|||
from . import models |
@ -0,0 +1,52 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
{ |
|||
'name': "Website HelpDesk Dashboard", |
|||
'version': '18.0.1.0.0', |
|||
'category': 'Website', |
|||
'summary': """Helpdesk Support Ticket Management Dashboard""", |
|||
'description': """Website HelpDesk Dashboard Module Brings a Multipurpose""" |
|||
"""Graphical Dashboard for Website HelpDesk module""", |
|||
'author': "Cybrosys Techno Solutions", |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'maintainer': 'Cybrosys Techno Solutions', |
|||
'website': "https://www.openhrms.com", |
|||
'depends': ['odoo_website_helpdesk', 'base'], |
|||
'data': [ |
|||
'views/menu_item.xml', |
|||
'views/dashboard_templates.xml', |
|||
], |
|||
'assets': { |
|||
'web.assets_backend': [ |
|||
'odoo_website_helpdesk_dashboard/static/src/css/dashboard.css', |
|||
'odoo_website_helpdesk_dashboard/static/src/js/lib/Chart.bundle.js', |
|||
'odoo_website_helpdesk_dashboard/static/src/js/dashboard_view.js', |
|||
'odoo_website_helpdesk_dashboard/static/src/xml/dashboard_view.xml', |
|||
'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js' |
|||
], |
|||
}, |
|||
'images': ['static/description/banner.png'], |
|||
'license': 'LGPL-3', |
|||
'auto_install': False, |
|||
'installable': True, |
|||
'application': False, |
|||
} |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from . import odoo_website_helpdesk_dashboard |
@ -0,0 +1,41 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from odoo import http |
|||
from odoo.http import request |
|||
|
|||
|
|||
class HelpDeskTickets(http.Controller): |
|||
@http.route(['/help/tickets'], type="json", auth="user") |
|||
def elearning_snippet(self): |
|||
tickets = [] |
|||
help_tickets = request.env['ticket.helpdesk'].sudo().search( |
|||
[('stage_id.name', '=', 'Inbox')]) |
|||
for i in help_tickets: |
|||
tickets.append( |
|||
{'name': i.name, 'subject': i.subject, 'id': i.id}) |
|||
values = { |
|||
'h_tickets': tickets |
|||
} |
|||
response = http.Response( |
|||
template='odoo_website_helpdesk_dashboard.dashboard_tickets', |
|||
qcontext=values) |
|||
return response.render() |
@ -0,0 +1,7 @@ |
|||
## Module <odoo_website_helpdesk_dashboard> |
|||
|
|||
#### 09.12.2024 |
|||
#### Version 18.0.1.0.0 |
|||
#### ADD |
|||
|
|||
- Initial commit for Website HelpDesk Dashboard |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from . import ticket_helpdesk |
@ -0,0 +1,176 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
import calendar |
|||
from odoo import api, models |
|||
|
|||
|
|||
class TicketHelpdesk(models.Model): |
|||
""" Inherited class to get help desk ticket details....""" |
|||
_inherit = 'ticket.helpdesk' |
|||
|
|||
@api.model |
|||
def check_user_group(self): |
|||
"""Checking user group""" |
|||
user = self.env.user |
|||
if user.has_group('base.group_user'): |
|||
return True |
|||
return False |
|||
|
|||
@api.model |
|||
def get_tickets_count(self): |
|||
""" Function To Get The Ticket Count""" |
|||
ticket_details = self.search([]) |
|||
ticket_data = [ |
|||
{ |
|||
'ticket_name': ticket.name, |
|||
'customer_name': ticket.customer_id.name, |
|||
'subject': ticket.subject, |
|||
'priority': ticket.priority, |
|||
'assigned_to': ticket.assigned_user_id.name, |
|||
'assigned_image': ticket.assigned_user_id.image_1920, |
|||
} |
|||
for ticket in ticket_details |
|||
] |
|||
tickets_new_count = self.search_count( |
|||
[('stage_id.name', 'in', ['Inbox', 'Draft'])]) |
|||
tickets_in_progress_count = self.search_count( |
|||
[('stage_id.name', '=', 'In Progress')]) |
|||
tickets_closed_count = self.search_count( |
|||
[('stage_id.name', '=', 'Done')]) |
|||
very_low_count = self.search_count([ |
|||
('priority', '=', '0')]) |
|||
very_low_count1 = very_low_count * 10 |
|||
low_count = self.search_count([ |
|||
('priority', '=', '1')]) |
|||
low_count1 = low_count * 10 |
|||
normal_count = self.search_count([ |
|||
('priority', '=', '2')]) |
|||
normal_count1 = normal_count * 10 |
|||
high_count = self.search_count([ |
|||
('priority', '=', '3')]) |
|||
high_count1 = high_count * 10 |
|||
very_high_count = self.search_count([ |
|||
('priority', '=', '4')]) |
|||
very_high_count1 = very_high_count * 10 |
|||
response = self.search_count([ |
|||
('review', '!=', None)]) |
|||
teams_count = self.env['team.helpdesk'].search_count([]) |
|||
tickets = self.search( |
|||
[('stage_id.name', 'in', ['Inbox', 'Draft'])]) |
|||
p_tickets = [ticket.name for ticket in tickets] |
|||
values = { |
|||
'inbox_count': tickets_new_count, |
|||
'progress_count': tickets_in_progress_count, |
|||
'done_count': tickets_closed_count, |
|||
'team_count': teams_count, |
|||
'p_tickets': p_tickets, |
|||
'very_low_count1': very_low_count1, |
|||
'low_count1': low_count1, |
|||
'normal_count1': normal_count1, |
|||
'high_count1': high_count1, |
|||
'very_high_count1': very_high_count1, |
|||
'response': response, |
|||
'ticket_details': ticket_data, |
|||
} |
|||
return values |
|||
|
|||
@api.model |
|||
def get_tickets_view(self): |
|||
""" Function To Get The Ticket View""" |
|||
tickets_new_count = self.search_count( |
|||
[('stage_id.name', 'in', ['Inbox', 'Draft'])]) |
|||
tickets_in_progress_count = self.search_count( |
|||
[('stage_id.name', '=', 'In Progress')]) |
|||
tickets_closed_count = self.search_count( |
|||
[('stage_id.name', '=', 'Done')]) |
|||
teams_count = self.search_count([]) |
|||
tickets_new = self.search( |
|||
[('stage_id.name', 'in', ['Inbox', 'Draft'])]) |
|||
tickets_in_progress = self.search( |
|||
[('stage_id.name', '=', 'In Progress')]) |
|||
tickets_closed = self.search( |
|||
[('stage_id.name', '=', 'Done')]) |
|||
teams = self.env['team.helpdesk'].search([]) |
|||
new_list = [f"{new.name} : {new.subject}" for new in tickets_new] |
|||
progress_list = [f"{progress.name} : {progress.subject}" for progress in |
|||
tickets_in_progress] |
|||
done_list = [f"{done.name} : {done.subject}" for done in tickets_closed] |
|||
teams_list = [team.name for team in teams] |
|||
|
|||
tickets = self.search( |
|||
[('stage_id.name', 'in', ['Inbox', 'Draft'])]) |
|||
p_tickets = [ticket.name for ticket in tickets] |
|||
values = { |
|||
'inbox_count': tickets_new_count, |
|||
'progress_count': tickets_in_progress_count, |
|||
'done_count': tickets_closed_count, |
|||
'team_count': teams_count, |
|||
'new_tkts': new_list, |
|||
'progress': progress_list, |
|||
'done': done_list, |
|||
'teams': teams_list, |
|||
'p_tickets': p_tickets |
|||
} |
|||
return values |
|||
|
|||
@api.model |
|||
def get_ticket_month_pie(self): |
|||
"""For pie chart""" |
|||
month_count = [] |
|||
month_value = [] |
|||
tickets = self.search([]) |
|||
for rec in tickets: |
|||
month = rec.create_date.month |
|||
if month not in month_value: |
|||
month_value.append(month) |
|||
month_count.append(month) |
|||
month_val = [] |
|||
for index in range(len(month_value)): |
|||
value = month_count.count(month_value[index]) |
|||
month_name = calendar.month_name[month_value[index]] |
|||
month_val.append({'label': month_name, 'value': value}) |
|||
name = [record.get('label') for record in month_val] |
|||
count = [record.get('value') for record in month_val] |
|||
month = [count, name] |
|||
return month |
|||
|
|||
@api.model |
|||
def get_team_ticket_count_pie(self): |
|||
"""For bar chart""" |
|||
ticket_count = [] |
|||
team_list = [] |
|||
tickets = self.search([]) |
|||
for rec in tickets: |
|||
if rec.team_id: |
|||
team = rec.team_id.name |
|||
if team not in team_list: |
|||
team_list.append(team) |
|||
ticket_count.append(team) |
|||
team_val = [] |
|||
for index in range(len(team_list)): |
|||
value = ticket_count.count(team_list[index]) |
|||
team_name = team_list[index] |
|||
team_val.append({'label': team_name, 'value': value}) |
|||
name = [record.get('label') for record in team_val] |
|||
count = [record.get('value') for record in team_val] |
|||
team = [count, name] |
|||
return team |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 628 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 210 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 929 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 17 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: 1.2 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 294 KiB |
After Width: | Height: | Size: 2.2 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: 1.2 KiB |
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 462 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 926 B |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 189 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.1 KiB |
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: 875 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 767 KiB |
After Width: | Height: | Size: 138 KiB |
After Width: | Height: | Size: 760 KiB |
After Width: | Height: | Size: 92 KiB |
After Width: | Height: | Size: 697 KiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 103 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 880 KiB |
After Width: | Height: | Size: 91 KiB |
After Width: | Height: | Size: 9.0 KiB |
@ -0,0 +1,267 @@ |
|||
|
|||
.o_action_manager { |
|||
overflow: auto !important; |
|||
} |
|||
|
|||
.help_dashboards { |
|||
padding-top: 10px; |
|||
background-color: #f8faff !important; |
|||
} |
|||
|
|||
.dashboard_card h4 { |
|||
font-size: 1.1rem; |
|||
} |
|||
|
|||
.main-section { |
|||
margin-left: 6px; |
|||
} |
|||
|
|||
.breadcrumbs { |
|||
margin-top: 0; |
|||
} |
|||
|
|||
/* Widget One |
|||
---------------------------*/ |
|||
.stat-content { |
|||
display: inline-block; |
|||
width: 66%; |
|||
} |
|||
|
|||
.stat-icon { |
|||
display: inline-block; |
|||
} |
|||
|
|||
.stat-widget-one .stat-icon { |
|||
vertical-align: top; |
|||
margin: auto; |
|||
width: 100%; |
|||
color: #01c490; |
|||
} |
|||
|
|||
.stat-widget-one .stat-icon i { |
|||
font-size: 30px; |
|||
font-weight: 900; |
|||
display: inline-block; |
|||
color: #01c490; |
|||
} |
|||
|
|||
.stat-widget-one .stat-text { |
|||
font-size: 11px; |
|||
color: #868e96; |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.stat-widget-one .stat-digit { |
|||
font-size: 24px; |
|||
color: #02448b; |
|||
} |
|||
|
|||
.stat-count { |
|||
font-size: 20px; |
|||
text-align: center; |
|||
color: #00438b; |
|||
} |
|||
|
|||
.stat-title { |
|||
font-size: 17px; |
|||
text-align: center; |
|||
color: #00438b; |
|||
} |
|||
|
|||
/*=====================Dashboard===========================*/ |
|||
|
|||
.dashboard_card { |
|||
padding: 0px; |
|||
margin-bottom: 1.5rem; |
|||
border-radius: 0px; |
|||
box-shadow: none; |
|||
background: none; |
|||
transition: transform 0.2s ease, box-shadow 0.2s ease; |
|||
will-change: transform, box-shadow; |
|||
} |
|||
|
|||
.dashboard_card:hover { |
|||
transform: translateY(-2px) translateZ(0) !important; |
|||
box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; |
|||
} |
|||
|
|||
.helpdesk { |
|||
margin-top: 3%; |
|||
margin-bottom: 2%; |
|||
} |
|||
|
|||
.helpdesk .stat-icon { |
|||
border-radius: 15px 0 0 15px; |
|||
width: 30%; |
|||
height: 100px; |
|||
text-align: center; |
|||
padding-top: 11%; |
|||
background: #4a5c9a; |
|||
color: #fff; |
|||
} |
|||
|
|||
#team_ico { |
|||
-webkit-text-stroke: 1px #8e8e8e; |
|||
} |
|||
|
|||
.helpdesk .dashboard_card { |
|||
border-radius: 15px; |
|||
transition: transform 0.2s ease, box-shadow 0.2s ease; |
|||
will-change: transform, box-shadow; |
|||
box-shadow: 0 10px 40px 0 rgba(62, 57, 107, 0.07), |
|||
0 2px 9px 0 rgba(62, 57, 107, 0.06); |
|||
} |
|||
|
|||
.stat-widget-one .stat-text { |
|||
font-size: 14px; |
|||
color: #314384ff; |
|||
margin: 2rem 0rem 1rem 0rem; |
|||
text-align: center; |
|||
} |
|||
|
|||
.stat-widget-one .stat-digit { |
|||
font-size: 20px; |
|||
font-weight: bolder; |
|||
padding: 1px 10px 2px 0; |
|||
color: #8061a9; |
|||
text-shadow: 0px 0px 20px #000000; |
|||
text-align: center; |
|||
} |
|||
|
|||
.stat-widget-one .stat-icon i { |
|||
font-size: 25px; |
|||
font-weight: 900; |
|||
display: inline-block; |
|||
color: #fff; |
|||
} |
|||
|
|||
.stat-widget-one { |
|||
border-radius: 15px; |
|||
background-color: white; |
|||
text-align: inherit !important; |
|||
} |
|||
|
|||
.stat-widget-one { |
|||
width: 100%; |
|||
} |
|||
|
|||
|
|||
.inbox_tickets .stat-widget-one .stat-text { |
|||
color: #706F8E; |
|||
} |
|||
|
|||
.inbox_tickets .stat-icon { |
|||
background: #706F8E !important; |
|||
} |
|||
|
|||
.inprogress_tickets .stat-widget-one .stat-text { |
|||
color: #9AA8A8; |
|||
} |
|||
|
|||
.inprogress_tickets .stat-icon { |
|||
background: #9AA8A8 !important; |
|||
} |
|||
|
|||
.done_tickets .stat-icon { |
|||
background: #847A9F !important; |
|||
} |
|||
|
|||
.done_tickets .stat-widget-one .stat-text { |
|||
color: #847A9F; |
|||
} |
|||
|
|||
.team_card .stat-icon { |
|||
background: #66719a !important; |
|||
} |
|||
|
|||
.team_card .stat-widget-one .stat-text { |
|||
color: #66719a; |
|||
} |
|||
|
|||
.dashboard_card-body { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
} |
|||
|
|||
.pending_detail { |
|||
width: 75%; |
|||
padding: 0 0 0 40px; |
|||
margin: 0 0 0 4px; |
|||
} |
|||
|
|||
.ticket_box { |
|||
height: 32rem; |
|||
overflow-y: auto; |
|||
} |
|||
|
|||
.ticket_box_head { |
|||
text-align: center; |
|||
padding: 12px 0; |
|||
color: rgb(73 80 87 / 76%); |
|||
font-weight: bold; |
|||
font-size: 20px; |
|||
background: #b1cccc; |
|||
margin-bottom: 9px; |
|||
} |
|||
|
|||
.tickets_head { |
|||
margin-left: 10px; |
|||
} |
|||
|
|||
.pending_tickets { |
|||
padding-left: 0 ! important; |
|||
} |
|||
|
|||
.tickets_list { |
|||
font-weight: 500; |
|||
font-size: 14px; |
|||
margin: 10px; |
|||
list-style-type: none; |
|||
border-radius: 5px; |
|||
border: 1px solid rgba(69, 72, 103, 0.71); |
|||
background: #f3f3f3bd; |
|||
padding: 10px !important; |
|||
} |
|||
|
|||
.half_chart.chart-container.card-shadow { |
|||
height: 32rem; |
|||
} |
|||
.chart-container.card-shadow { |
|||
height: 32rem; |
|||
} |
|||
.row { |
|||
/* Define your styles here */ |
|||
font-weight: bold; |
|||
margin-bottom: 20px; |
|||
/* Add more styles as needed */ |
|||
transition: background-color 0.3s ease-in-out; |
|||
} |
|||
.td{ |
|||
width:20%; |
|||
padding:15px; |
|||
transition: background-color 0.3s ease-in-out; /* Add a transition for background-color */ |
|||
|
|||
} |
|||
.td:hover { |
|||
background-color: #e0e0e0; /* Change the background color on hover */ |
|||
} |
|||
.custom-tr{ |
|||
width:10%; |
|||
|
|||
} |
|||
.custom-tr:hover { |
|||
background-color: #ff8080; /* Change the background color on hover */ |
|||
color: white; /* Change the text color on hover */ |
|||
font-size: 18px; /* Change the font size on hover */ |
|||
font-weight: normal; /* Change the font weight on hover */ |
|||
border: 2px solid #ff8080; /* Add a border on hover */ |
|||
/* Add more hover styles as needed */ |
|||
} |
|||
.user-image{ |
|||
width: 10%; |
|||
height: auto; /* Let the height adjust proportionally to maintain aspect ratio */ |
|||
border-radius: 50%; /* This will create a circular shape */ |
|||
display: block; /* Ensures it's a block element for proper centering */ |
|||
margin: 0 auto; /* Centers the circular image horizontally */ |
|||
} |
@ -0,0 +1,290 @@ |
|||
/** @odoo-module **/ |
|||
import { registry } from "@web/core/registry"; |
|||
import { rpc } from '@web/core/network/rpc'; |
|||
import { _t } from "@web/core/l10n/translation"; |
|||
import { Component } from "@odoo/owl"; |
|||
import { onMounted, useRef } from "@odoo/owl"; |
|||
import { useService } from "@web/core/utils/hooks"; |
|||
/** Initializes the HelpDeskDashBoard component**/ |
|||
class HelpDeskDashBoard extends Component{ |
|||
/**Set up function**/ |
|||
setup() { |
|||
super.setup(); |
|||
var self = this; |
|||
this.ref = useRef("helpDeskDashboard") |
|||
this.actionService = useService("action"); |
|||
onMounted(this.onMounted); |
|||
} |
|||
/**Function for onMounted**/ |
|||
onMounted(){ |
|||
this.render_dashboards(); |
|||
this.render_graphs(); |
|||
} |
|||
/**To render the charts**/ |
|||
render_graphs() { |
|||
var self = this; |
|||
self.render_tickets_month_graph(); |
|||
self.render_team_ticket_count_graph(); |
|||
} |
|||
/**Doughnut chart: TICKET STATUS**/ |
|||
render_tickets_month_graph() { |
|||
var self = this; |
|||
var ctx = this.ref.el.querySelector('#ticket_month') |
|||
rpc('/web/dataset/call_kw/ticket.helpdesk/get_tickets_count', { |
|||
model: "ticket.helpdesk", |
|||
method: "get_tickets_view", |
|||
args: [], |
|||
kwargs: {}, |
|||
}).then(function (values) { |
|||
var data = { |
|||
labels: ['New', 'In Progress', 'Solved'], |
|||
datasets: [{ |
|||
data: [values.inbox_count, values.progress_count, values.done_count], |
|||
backgroundColor: [ |
|||
"#665191", |
|||
"#ff7c43", |
|||
"#ffa600" |
|||
], |
|||
borderColor: [ |
|||
"#003f5c", |
|||
"#2f4b7c", |
|||
"#f95d6a" |
|||
], |
|||
borderWidth: 1 |
|||
}] |
|||
}; |
|||
/** Options **/ |
|||
var options = { |
|||
responsive: true, |
|||
title: false, |
|||
legend: { |
|||
display: true, |
|||
position: "right", |
|||
labels: { |
|||
fontColor: "#333", |
|||
fontSize: 16 |
|||
} |
|||
}, |
|||
scales: { |
|||
yAxes: [{ |
|||
gridLines: { |
|||
color: "rgba(0, 0, 0, 0)", |
|||
display: false, |
|||
}, |
|||
ticks: { |
|||
min: 0, |
|||
display: false, |
|||
} |
|||
}] |
|||
} |
|||
}; |
|||
/** Create Chart class object **/ |
|||
var chart = new Chart(ctx, { |
|||
type: "doughnut", |
|||
data: data, |
|||
options: options |
|||
}); |
|||
}); |
|||
} |
|||
/** Bar chart: Team - Tickets Count Ratio **/ |
|||
render_team_ticket_count_graph() { |
|||
var self = this |
|||
var ctx = this.ref.el.querySelector('.team_ticket_count'); |
|||
rpc('/web/dataset/call_kw/ticket.helpdesk/get_tickets_count', { |
|||
model: "ticket.helpdesk", |
|||
method: "get_team_ticket_count_pie", |
|||
args: [], |
|||
kwargs: {}, |
|||
}).then(function (arrays) { |
|||
var data = { |
|||
labels: arrays[1], |
|||
datasets: [{ |
|||
label: "", |
|||
data: arrays[0], |
|||
backgroundColor: [ |
|||
'rgba(255, 99, 132, 0.2)', |
|||
'rgba(255, 159, 64, 0.2)', |
|||
'rgba(255, 205, 86, 0.2)', |
|||
'rgba(75, 192, 192, 0.2)', |
|||
'rgba(54, 162, 235, 0.2)', |
|||
'rgba(153, rpc102, 255, 0.2)', |
|||
'rgba(201, 203, 207, 0.2)' |
|||
], |
|||
borderColor: ['rgb(255, 99, 132)', |
|||
'rgb(255, 159, 64)', |
|||
'rgb(255, 205, 86)', |
|||
'rgb(75, 192, 192)', |
|||
'rgb(54, 162, 235)', |
|||
'rgb(153, 102, 255)', |
|||
'rgb(201, 203, 207)' |
|||
], |
|||
borderWidth: 1 |
|||
},] |
|||
}; |
|||
/** Options **/ |
|||
var options = { |
|||
responsive: true, |
|||
title: false, |
|||
maintainAspectRatio: true, |
|||
legend: { |
|||
display: false |
|||
}, |
|||
scales: { |
|||
yAxes: [{ |
|||
display: true, |
|||
ticks: { |
|||
beginAtZero: true, |
|||
steps: 10, |
|||
stepValue: 5, |
|||
// max: 100
|
|||
} |
|||
}] |
|||
} |
|||
}; |
|||
/** Create Chart class object **/ |
|||
var chart = new Chart(ctx, { |
|||
type: "bar", |
|||
data: data, |
|||
options: options |
|||
}); |
|||
}); |
|||
} |
|||
/** List view of tickets in dashboard **/ |
|||
render_dashboards() { |
|||
var self = this; |
|||
rpc('/web/dataset/call_kw/ticket.helpdesk/get_tickets_count', { |
|||
model: 'ticket.helpdesk', |
|||
method: 'get_tickets_count', |
|||
args: [], |
|||
kwargs: {}, |
|||
}).then(function(result) { |
|||
var inbox_count_span = document.createElement("span"); |
|||
inbox_count_span.textContent = result.inbox_count |
|||
self.ref.el.querySelector('#inbox_count').appendChild(inbox_count_span); |
|||
var progress_count_span = document.createElement("span"); |
|||
progress_count_span.textContent = result.progress_count |
|||
self.ref.el.querySelector('#inprogress_count').appendChild(progress_count_span); |
|||
var done_count_span = document.createElement("span"); |
|||
done_count_span.textContent = result.done_count |
|||
self.ref.el.querySelector('#done_count').appendChild(done_count_span); |
|||
var team_count_span = document.createElement("span"); |
|||
team_count_span.textContent = result.team_count |
|||
self.ref.el.querySelector('#team_count').appendChild(team_count_span); |
|||
var priorityCounts = { |
|||
very_low: result.very_low_count1, |
|||
low: result.low_count1, |
|||
normal: result.normal_count1, |
|||
high: result.high_count1, |
|||
very_high : result.very_high_count1 |
|||
}; |
|||
/**Loop through the priorities and create progress bars**/ |
|||
for (var priority in priorityCounts) { |
|||
var progressBarWidth = priorityCounts[priority] + "%"; |
|||
var progressBar = $("<div class='progress-bar'></div>").css("width", progressBarWidth); |
|||
var progressBarContainer = $("<div class='progress'></div>").append(progressBar); |
|||
var progressValue = $("<div class='progress-value'></div>").text(priorityCounts[priority] + "%"); |
|||
// Append the progress bar container to elements with class corresponding to the priority
|
|||
$("." + priority + "_count").append(progressBarContainer); |
|||
$("." + priority + "_count .progress-value").append(progressValue); |
|||
} |
|||
var tbody = $(".ticket-details"); |
|||
var ticket_details = result.ticket_details; |
|||
for (var i = 0; i < ticket_details.length; i++) { |
|||
/** Get the current ticket object **/ |
|||
var ticket = ticket_details[i]; |
|||
var row = $("<tr></tr>"); |
|||
/** Assuming you have the Base64-encoded image data in a |
|||
variable called ticket.assigned_image **/ |
|||
var base64Image = ticket.assigned_image; |
|||
var assignedUserCell = $("<td class='td'></td>"); |
|||
var imgElement = $("<img>"); |
|||
/** Set the image source **/ |
|||
imgElement.attr("src", "data:image/png;base64," + base64Image); |
|||
/** Set an alt attribute for accessibility **/ |
|||
imgElement.attr("alt", "User Image"); |
|||
/** Add the 'oe-avatar' class to the <img> element **/ |
|||
imgElement.addClass("user-image"); |
|||
|
|||
/** Append the img element to the assignedUserCell **/ |
|||
assignedUserCell.append(imgElement); |
|||
/** Append the assignedUserCell to the row **/ |
|||
row.append(assignedUserCell); |
|||
row.append("<td class='td'>" + ticket.customer_name + "</td>"); |
|||
row.append("<td class='td'>" + ticket.ticket_name + "</td>"); |
|||
row.append(assignedUserCell); |
|||
row.append("<td>" + ticket.assigned_to + "</td>"); |
|||
row.append("<td>" + ticket.subject + "</td>"); |
|||
row.append("<td>" + ticket.priority + "</td>"); |
|||
tbody.append(row); |
|||
} |
|||
$(".response").append(result.response); |
|||
rpc('/help/tickets', {}).then((values) => { |
|||
$('.pending_tickets').append(values); |
|||
}); |
|||
}); |
|||
} |
|||
/** To show new tickets **/ |
|||
tickets_inbox(ev) { |
|||
var self = this; |
|||
ev.stopPropagation(); |
|||
ev.preventDefault(); |
|||
self.actionService.doAction({ |
|||
name: _t("Inbox"), |
|||
type: 'ir.actions.act_window', |
|||
res_model: 'ticket.helpdesk', |
|||
view_mode: 'tree,form', |
|||
views: [[false, 'list'], [false, 'form']], |
|||
domain: [['stage_id.name', 'in', ['Inbox', 'Draft']]], |
|||
context: {default_stage_id_name: 'Draft'}, |
|||
target: 'current' |
|||
}); |
|||
} |
|||
/** To show in progress tickets **/ |
|||
tickets_inprogress(ev) { |
|||
var self = this; |
|||
ev.stopPropagation(); |
|||
ev.preventDefault(); |
|||
self.actionService.doAction({ |
|||
name: _t("In Progress"), |
|||
type: 'ir.actions.act_window', |
|||
res_model: 'ticket.helpdesk', |
|||
view_mode: 'tree,form', |
|||
views: [[false, 'list'], [false, 'form']], |
|||
domain: [['stage_id.name', '=', 'In Progress']], |
|||
context: {create: false}, |
|||
target: 'current' |
|||
}); |
|||
} |
|||
/** To show done tickets **/ |
|||
tickets_done(ev) { |
|||
var self = this; |
|||
ev.stopPropagation(); |
|||
ev.preventDefault(); |
|||
self.actionService.doAction({ |
|||
name: _t("Done"), |
|||
type: 'ir.actions.act_window', |
|||
res_model: 'ticket.helpdesk', |
|||
view_mode: 'tree,form', |
|||
views: [[false, 'list'], [false, 'form']], |
|||
domain: [['stage_id.name', '=', 'Done']], |
|||
context: {create: false}, |
|||
target: 'current' |
|||
}); |
|||
} |
|||
/** To show the helpdesk teams**/ |
|||
helpdesk_teams(ev) { |
|||
var self = this; |
|||
ev.stopPropagation(); |
|||
ev.preventDefault(); |
|||
self.actionService.doAction({ |
|||
name: _t("Teams"), |
|||
type: 'ir.actions.act_window', |
|||
res_model: 'team.helpdesk', |
|||
view_mode: 'tree,form', |
|||
views: [[false, 'list'], [false, 'form']], |
|||
target: 'current' |
|||
}); |
|||
} |
|||
} |
|||
HelpDeskDashBoard.template = 'DashBoardHelpDesk' |
|||
registry.category("actions").add("helpdesk_dashboard", HelpDeskDashBoard) |
@ -0,0 +1,224 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<templates id="template" xml:space="preserve"> |
|||
<t t-name="HelpDesk_Dashboard" owl="1"> |
|||
<div class="helpdesk_dashboards"> |
|||
<div class="container-fluid helpdesk_dashboard_main"/> |
|||
</div> |
|||
</t> |
|||
<t t-name="DashBoardHelpDesk"> |
|||
<link rel="stylesheet" |
|||
href="/odoo_website_helpdesk_dashboard/static/src/css/dashboard.css"/> |
|||
<div class="row main-section mt-5" t-ref="helpDeskDashboard"> |
|||
<h2 class="section-header" style="font-size: 2em; color:#4a5c9a;">HelpDesk Dashboard</h2> |
|||
<div class="col-sm-6 col-md-3-12 col-md-6 col-lg-3 helpdesk inbox_tickets" |
|||
t-on-click="tickets_inbox"> |
|||
<div class="dashboard_card" data-toggle="collapse"> |
|||
<div class="dashboard_card-body panel panel-new"> |
|||
<div class="stat-widget-one" style="background-color:pink"> |
|||
<div class="stat-icon"> |
|||
<i class="fa fa-inbox"/> |
|||
</div> |
|||
<div class="stat-content"> |
|||
<div class="stat-text" style="color:black">New Tickets</div> |
|||
<div class="stat-digit" id="inbox_count"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="panel-new-collapse collapse"> |
|||
<div id="help_new_tickets" |
|||
style="border:none; font-size:8px; padding:0 8px 8px 8px;"> |
|||
<br/> |
|||
<br/> |
|||
<p style="border:none; font-size:14px; padding:0 15px 15px 15px;"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-sm-6 col-md-3-12 col-md-6 col-lg-3 salon_spa_orders helpdesk inprogress_tickets" |
|||
t-on-click="tickets_inprogress"> |
|||
<div class="dashboard_card" data-toggle="collapse"> |
|||
<div class="dashboard_card-body panel panel-progress"> |
|||
<div class="stat-widget-one" style="background-color:orange"> |
|||
<div class="stat-icon"> |
|||
<i class="fa fa-spinner"/> |
|||
</div> |
|||
<div class="stat-content"> |
|||
<div class="stat-text" |
|||
style="color:black">Tickets In Progress</div> |
|||
<div class="stat-digit" id="inprogress_count"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="panel-progress-collapse collapse"> |
|||
<div id="help_progress_tickets" |
|||
style="border:none; font-size:8px; padding:0 8px 8px 8px;"> |
|||
<br/> |
|||
<br/> |
|||
<p style="border:none; font-size:14px; padding:0 15px 15px 15px;"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-sm-6 col-md-3-12 col-md-6 col-lg-3 helpdesk done_tickets" |
|||
t-on-click="tickets_done"> |
|||
<div class="dashboard_card" data-toggle="collapse"> |
|||
<div class="dashboard_card-body panel panel-done"> |
|||
<div class="stat-widget-one" style="background-color:pink"> |
|||
<div class="stat-icon"> |
|||
<i class="fa fa-check"/> |
|||
</div> |
|||
<div class="stat-content"> |
|||
<div class="stat-text" style="color:black">Done Tickets</div> |
|||
<div class="stat-digit" id="done_count"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="panel-done-collapse collapse"> |
|||
<div id="help_done_tickets" |
|||
style="border:none; font-size:14px; padding:0 15px 15px 15px;"> |
|||
<br/> |
|||
<br/> |
|||
<p style="font-style:italic; font-weight:100;"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-sm-6 col-md-3-12 col-md-6 col-lg-3 helpdesk team_card" |
|||
t-on-click="helpdesk_teams"> |
|||
<div class="dashboard_card" data-toggle="collapse"> |
|||
<div class="dashboard_card-body panel panel-team"> |
|||
<div class="stat-widget-one" style="background-color:white"> |
|||
<div class="stat-icon"> |
|||
<i class="fa fa-group" id="team_ico"/> |
|||
</div> |
|||
<div class="stat-content"> |
|||
<div class="stat-text" style="color:black">HelpDesk Teams</div> |
|||
<div class="stat-digit" id="team_count"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="panel-team-collapse collapse"> |
|||
<div id="help_teams" |
|||
style="border:none; font-size:14px; padding:0 15px 15px 15px;"> |
|||
<br/> |
|||
<br/> |
|||
<p style="font-style:italic; font-weight:100;"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="dashboard_card" |
|||
style="display: flex; justify-content: center; align-items: center;"> |
|||
<div style="color: black; font-weight: bold; height: 60px; width: 700px; text-align: center;"> |
|||
<span>CUSTOMER SATISFACTION:</span> |
|||
<div style="display: flex; justify-content: center; align-items: center;"> |
|||
<span>😃</span> |
|||
<span>Response Received:</span> |
|||
<div style="width: 10px;"/> <!-- Using width for spacing --> |
|||
<div class="response"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="row ticket-section"> |
|||
<div class="col-12 col-sm-12 col-md-4 ticket_box chart-container card-shadow"> |
|||
<h2 class="tickets_head">Ticket Priority</h2> |
|||
<hr/> |
|||
<div class="col-xs-12 text-align"> |
|||
<div class="text-color"> |
|||
<div class="line"> |
|||
Very low : |
|||
<div class="very_low_count" widget="progressbar"> |
|||
<div class="progress-value"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-xs-12 text-align"> |
|||
<div class="text-color"> |
|||
<div class="line"> |
|||
Low : |
|||
<div class="low_count" widget="progressbar"> |
|||
<div class="progress-value"/> |
|||
</div> |
|||
</div></div> |
|||
</div> |
|||
<div class="col-xs-12 text-align"> |
|||
<div class="text-color"> |
|||
<div class="line"> |
|||
Normal : |
|||
<div class="normal_count" widget="progressbar"> |
|||
<div class="progress-value"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-xs-12 text-align"> |
|||
<div class="text-color"> |
|||
<div class="line"> |
|||
High : |
|||
<div class="high_count" widget="progressbar"> |
|||
<div class="progress-value"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-xs-12 text-align"> |
|||
<div class="text-color"> |
|||
<div class="line"> |
|||
Very High : |
|||
<div class="very_high_count" widget="progressbar"> |
|||
<div class="progress-value"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-12 col-sm-12 col-md-4"> |
|||
<div class="leads_month_pie_div half_chart chart-container card-shadow"> |
|||
<h2>TICKET STATUS</h2> |
|||
<hr/> |
|||
<div class="graph_canvas"> |
|||
<canvas id="ticket_month" width="200" height="120"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-12 col-sm-12 col-md-4"> |
|||
<div class="team_ticket_div half_chart chart-container card-shadow"> |
|||
<h2>Team - Tickets Count Ratio</h2> |
|||
<hr/> |
|||
<div class="graph_canvas"> |
|||
<canvas class="team_ticket_count"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-100 col-sm-100 col-md-20"> |
|||
<div class="leads_month_pie_div half_chart chart-container card-shadow"> |
|||
<h2>ISSUE</h2> |
|||
<hr/> |
|||
<!-- Add a table to display ticket details --> |
|||
<table class="ticket-table"> |
|||
<thead> |
|||
<tr style="font-size: 16px; font-weight: bold; background-color: pink; color: black;height:50%" |
|||
class="custom-tr"> |
|||
<th style="width: 20%; min-width: 20px; font-size: 13px;">Customer Name</th> |
|||
<th style="width: 20%; min-width: 10px; font-size: 13px;">Ticket</th> |
|||
<th style="width: 20%; min-width: 20px; font-size: 13px;"> </th> |
|||
<th style="width: 20%; min-width: 20px; font-size: 13px;">Assigned to</th> |
|||
<th style="width: 20%; min-width: 20px; font-size: 13px;">Subject</th> |
|||
<th style="width: 20%; min-width: 20px; font-size: 13px;">Priority</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody class="ticket-details"> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
</templates> |
@ -0,0 +1,47 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!-- Template for view all tickets in list view--> |
|||
<template id="dashboard_tickets" name="Pending Tickets template"> |
|||
<t t-foreach="h_tickets" t-as="ticket"> |
|||
<div class="tickets_list" t-att-id="ticket['id']" |
|||
t-att-value="ticket['id']"> |
|||
<t t-esc="ticket['name']+' | '+ticket['subject']"/> |
|||
</div> |
|||
</t> |
|||
</template> |
|||
<!-- Table for ticket in dashboard--> |
|||
<template id="dashboard_ticket_detailed" name="Tickets template"> |
|||
<t t-foreach="h_tickets" t-as="ticket"> |
|||
<div class="col-xs-12 " style="padding:0;"> |
|||
<div class="ticket_box_head"> |
|||
<t t-esc="ticket['name']+' - ('+ticket['create_date'].strftime('%d-%b-%y')"/> |
|||
) |
|||
</div> |
|||
</div> |
|||
<div class="row m-4 pt-3 w-75"> |
|||
<div class="col-sm-6 col-md-3-12 col-md-6 col-lg-6 "> |
|||
<h3 class="ticket_name"> |
|||
Ticket Name : |
|||
<t t-esc="ticket['name']"/> |
|||
</h3> |
|||
<h3 class="ticket_subject"> |
|||
Ticket Issue : |
|||
<t t-esc="ticket['subject']"/> |
|||
</h3> |
|||
</div> |
|||
<div class="col-sm-6 col-md-3-12 col-md-6 col-lg-3"> |
|||
<h4 class="ticket_customer"> |
|||
<t t-if="ticket['customer_name']"> |
|||
Customer : |
|||
<t t-esc="ticket['customer_name']"/> |
|||
</t> |
|||
</h4> |
|||
<h4 class="ticket_subject"> |
|||
Description : |
|||
<t t-esc="ticket['description']"/> |
|||
</h4> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,13 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<record id="action_website_helpdesk_dashboard" model="ir.actions.client"> |
|||
<field name="name">HelpDesk</field> |
|||
<field name="tag">helpdesk_dashboard</field> |
|||
</record> |
|||
<menuitem id="odoo_website_helpdesk.menu_helpdesk" name="Helpdesk" |
|||
action="action_website_helpdesk_dashboard" |
|||
sequence="5"/> |
|||
<menuitem name="Dashboard" id="menu_helpdesk_dashboard_new" |
|||
parent="odoo_website_helpdesk.menu_helpdesk" sequence="0" |
|||
action="action_website_helpdesk_dashboard"/> |
|||
</odoo> |