{% extends "@UVDeskCoreFramework//Templates//layout.html.twig" %}
{% block title %}Dashboard{% endblock %}
{% block pageContent %}
<style>
.btn{
border: 1px solid #1a1a1a;
display: inline-block;
padding: 10px;
position: relative;
text-align: center;
transition: background 600ms ease, color 600ms ease;
margin-right: 0px !important;
}
input[type="radio"].toggle {
display: none;
}
input[type=radio]:checked + label {
background: blue;
color:white;
}
.uv-action-bar .uv-field-block.date {
display: inline-block;
margin-right: 8px;
}
.uv-action-bar label {
font-size: 16px;
vertical-align: middle;
margin-right: 10px;
}
.uv-inner-section .uv-action-bar label{
font-size: 15px;
}
@media screen and (min-width: 1100px) and (max-width: 1260px) {
.uv-inner-section .uv-action-bar .uv-action-bar-col-lt, .uv-inner-section .uv-action-bar .uv-action-bar-col-rt {
width: 55% !important;
}
}
.graficosTortaBarra{
font-size:11px;width: 520px;border:1px solid #d3d3d3;height: 300px;padding:10px;
}
.graficosTortaBarra label{
line-height: 2;
padding: 0 8px;
display: inline-block;
}
.boch {
display:inline-block;
height: 10px;
width: 10px;
margin-right: 3px;
border-radius: 50%;
}
.box-graficos {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.uv-activity-wrapper {
margin-top: 60px;
}
.uv-activity-wrapper .uv-activity-chart-col-lt {
width: 80%;
float: left;
}
ul.uv-activity-brick-wrapper {
list-style: none;
margin: 0;
padding: 0;
width: 100%;
display: inline-block;
}
ul.uv-activity-brick-wrapper li {
width: 25%;
display: inline-block;
float: left;
padding-left: 10px;
padding-right: 10px;
color: #fff;
}
ul.uv-activity-brick-wrapper .uv-activity-brick {
border-radius: 3px;
padding: 10px;
text-align: center;
}
ul.uv-activity-brick-wrapper li a {
color: #fff;
font-size: 45px;
width: 100%;
display: inline-block;
}
ul.uv-activity-brick-wrapper li label {
font-size: 18px;
width: 100%;
display: inline-block;
}
.uv-activity-chart-bottom-row .uv-pannel-body {
height: 450px;
}
.kudos-overview {
width: 40%;
float: left;
padding-right: 10px;
}
.recent-notification {
width: 30%;
float: left;
padding-left: 10px;
}
.completion-chart {
width: 300px;
margin: 0 auto;
}
.progress-meter .background {
fill: #EFEFEF;
}
.progress-meter text {
font-size: 30px;
}
.kudos-overview .uv-pannel-body {
text-align: center;
padding-top: 50px;
}
.kudos-overview .uv-pannel-body label {
margin-top: 10px;
display: inline-block;
}
.recent-notification ul {
list-style: none;
padding: 0;
margin: 0;
overflow-y: auto;
max-height: 400px !important;
}
.recent-notification .uv-pannel-body {
padding: 0;
}
.recent-notification ul li {
color: #333333;
border-bottom: solid 1px #D3D3D3;
padding: 15px 20px;
}
.recent-notification ul li:first-child {
border-top: none;
}
.recent-notification ul li:last-child {
border-bottom: none;
}
.recent-notification ul li * {
display: inline-block !important;
}
.recent-notification ul li .timeago {
color: #9E9E9E;
margin-top: 5px;
font-size: 13px;
}
.recent-notification label {
text-align: center;
display: inline-block;
width: 100%;
padding-top: 15px;
border-top: 1px solid #d3d3d3;
}
.recent-notification span.uv-notification-message {
float: left;
width: 100%;
}
.kudos-count {
width: 30%;
float: left;
padding-right: 10px;
padding-left: 10px;
}
.kudos-count .uv-pannel-body {
padding-top: 50px;
overflow-y: auto;
}
.kudos-count ul {
list-style: none;
padding: 0;
margin: 0;
}
.kudos-count ul li {
width: 100%;
display: inline-block;
padding: 15px 0;
}
.kudos-count ul li .uv-icon-kudos {
vertical-align: middle;
margin-right: 10px;
}
.uv-activity-wrapper .uv-activity-chart-col-rt {
width: 20%;
float: left;
}
.uv-activity-chart-col-rt ul {
padding: 0;
margin: 0;
list-style: none;
}
.uv-activity-chart-col-rt ul li {
margin-bottom: 10px
}
.uv-activity-chart-col-rt ul li span {
width: 100%;
display: inline-block;
color: #6f6f6f;
}
.uv-middle {
margin: 0 auto;
display: inline-block;
margin-top: 200px;
text-align: center;
width: 100%;
}
@media screen and (max-width: 1024px) {
.uv-activity-wrapper .uv-activity-chart-col-lt {
width: 100%;
padding: 0;
}
.uv-activity-wrapper .uv-activity-chart-col-rt {
width: 100%;
}
.kudos-overview {
width: 100%;
padding: 0;
}
.kudos-count {
width: 100%;
padding: 0;
}
.recent-notification {
width: 100%;
padding: 0;
}
ul.uv-activity-brick-wrapper li {
width: 50%;
margin: 10px 0;
}
}
@media screen and (max-width: 768px) {
ul.uv-activity-brick-wrapper li {
width: 100%;
}
}
@media screen and (max-width: 467px) {
.completion-chart {
width: 100%;
}
}
span.uv-notification-message a:link, span.uv-notification-message a:visited, label a:link, label a:visited {
color: #2750C4;
font-size: 15px;
}
.uv-mob-aside {
display: none;
}
{# .uv-copyright {
text-align: center;
} #}
</style>
<div class="uv-area">
<div>
<div class="uv-action-bar">
<div class="uv-action-bar-col-lt">
<label>{{ 'From'|trans }}</label>
<div class="uv-field-block date">
<input type="text" class="uv-field uv-date-picker date date-from" id="from" value="">
</div>
<label>{{ 'To'|trans }}</label>
<div class="uv-field-block date">
<input type="text" class="uv-field uv-date-picker date date-to" id="to" value="">
</div>
<input value="year" type="radio" class="toggle " name="options" id="year" autocomplete="off" >
<label class="btn" for="year">Last Year</label>
<input value="month" type="radio" class="toggle " name="options" id="month" autocomplete="off">
<label class="btn" for="month">Last Month</label>
<input value="week" type="radio" class="toggle " name="options" id="week" autocomplete="off" >
<label class="btn" for="week">Last Week</label>
<input value="day" type="radio" class="toggle " name="options" id="day" autocomplete="off" >
<label class="btn" for="day">Last Day</label>
</div>
{# <input value="year" type="radio" class="toggle " name="options" id="year" autocomplete="off" >
<label class="btn" for="year">Last Year</label>
<input value="month" type="radio" class="toggle " name="options" id="month" autocomplete="off">
<label class="btn" for="month">Last Month</label>
<input value="week" type="radio" class="toggle " name="options" id="week" autocomplete="off" >
<label class="btn" for="week">Last Week</label>
<input value="day" type="radio" class="toggle " name="options" id="day" autocomplete="off" >
<label class="btn" for="day">Last Day</label>#}
</div>
<div class="box-graficos">
<div>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bar-chart" viewBox="0 0 16 16">
<path d="M4 11H2v3h2v-3zm5-4H7v7h2V7zm5-5v12h-2V2h2zm-2-1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1h-2zM6 7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7zm-5 4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-3z"/>
</svg>
<b>{{ 'Tickets by Status' |trans }}</b><br><br>
<div class="graficosTortaBarra" >
<span id="contenidoticketsByStatus">
{% for tStatus in report_service.ticketsByStatus %}
<label>
<span class='boch' style="background: {{ tStatus.Color }}"> </span>
({{ tStatus.Cantidad }}) - {{ tStatus.Nombre }}
</label>
{% endfor %}
</span>
<div style="padding:25px;" >
<canvas id="ticketsByStatus" width="700" height="350"></canvas>
</div>
</div>
</div>
<div>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bar-chart" viewBox="0 0 16 16">
<path d="M4 11H2v3h2v-3zm5-4H7v7h2V7zm5-5v12h-2V2h2zm-2-1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1h-2zM6 7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7zm-5 4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-3z"/>
</svg>
<b>{{ 'Tickets by Type' |trans }}</b><br><br>
<div class="graficosTortaBarra" >
<span id="contenidoticketsByType">
{% for tStatus in report_service.ticketsByType %}
<label>
<span class='boch' style="background: {{ tStatus.Color }}"> </span>
({{ tStatus.Cantidad }}) - {{ tStatus.Nombre }}
</label>
{% endfor %}
</span>
<div style="width: 220px; margin: 0 auto;padding:25px;">
<canvas id="ticketsByType" ></canvas>
</div>
</div>
</div>
<div>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bar-chart" viewBox="0 0 16 16">
<path d="M4 11H2v3h2v-3zm5-4H7v7h2V7zm5-5v12h-2V2h2zm-2-1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1h-2zM6 7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7zm-5 4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-3z"/>
</svg>
<b>{{ 'Tickets by Priority' |trans }}</b><br><br>
<div class="graficosTortaBarra" >
<span id="contenidoticketsByPriority">
{% for tPriority in report_service.ticketsByPriority %}
<label>
<span class='boch' style="background: {{ tPriority.Color }}"> </span>
({{ tPriority.Cantidad }}) - {{ tPriority.Nombre }}
</label>
{% endfor %}
</span>
<div style="padding:25px;">
<canvas id="ticketsByPriority" width="700" height="350" ></canvas>
</div>
</div>
</div>
<div>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bar-chart" viewBox="0 0 16 16">
<path d="M4 11H2v3h2v-3zm5-4H7v7h2V7zm5-5v12h-2V2h2zm-2-1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1h-2zM6 7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7zm-5 4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-3z"/>
</svg>
<b>{{ 'Tickets per Agent' |trans }}</b><br><br>
<div class="graficosTortaBarra" >
<span id="contenidoticketsPerAgent">
{% for tAgent in report_service.ticketsPerAgent %}
<label>
<span class='boch' style="background: {{ tAgent.Color }}"> </span>
({{ tAgent.Cantidad }}) - {{ tAgent.Nombre }}
</label>
{% endfor %}
</span>
<div style="padding:25px;width: 220px; margin: 0 auto;">
<canvas id="ticketsPerAgent" ></canvas>
</div>
</div>
</div>
<div>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bar-chart" viewBox="0 0 16 16">
<path d="M4 11H2v3h2v-3zm5-4H7v7h2V7zm5-5v12h-2V2h2zm-2-1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1h-2zM6 7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7zm-5 4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-3z"/>
</svg>
<b>{{ 'Tickets per Team' |trans }}</b><br><br>
<div class="graficosTortaBarra" >
<span id="contenidoticketsPerTeam">
{% for tTeam in report_service.ticketsPerTeam %}
<label>
<span class='boch' style="background: {{ tTeam.Color }}"> </span>
({{ tTeam.Cantidad }}) - {{ tTeam.Nombre }}
</label>
{% endfor %}
</span>
<div style="padding:25px;width: 220px; margin: 0 auto;">
<canvas id="ticketsPerTeam" ></canvas>
</div>
</div>
</div>
<div>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bar-chart" viewBox="0 0 16 16">
<path d="M4 11H2v3h2v-3zm5-4H7v7h2V7zm5-5v12h-2V2h2zm-2-1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1h-2zM6 7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7zm-5 4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-3z"/>
</svg>
<b>{{ 'Kudos' |trans }}</b><br><br>
<div class="graficosTortaBarra" >
<span id="contenidokudos">
{% for tKudos in report_service.Kudos %}
<label>
<span class='boch' style="background: {{ tKudos.Color }}"> </span>
({{ tKudos.Cantidad }}) - {{ tKudos.Nombre }}
</label>
{% endfor %}
</span>
<div style="padding:25px;">
<canvas id="kudos" width="700" height="350" ></canvas>
</div>
</div>
</div>
</div>
</div>
<div class="uv-copyright">
<span class="uv-credit-text">Powered by <a href="https://www.uvdesk.com" target="_blank">UVdesk</a></span>
</div>
</div>
{% endblock %}
{% block footer %}
{{ parent() }}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<script>
let startGlobalDate = "";
let endGlobalDate = "";
let date = new Date();
let currentMonth = date.getMonth();
let currentDate = date.getDate();
let currentYear = date.getFullYear();
//Filtros año, mes, semana, dia
$("input[type='radio']").click(function(){
currentDate = new Date();
start = new Date();
end = new Date();
$('.uv-action-bar .date').find("#to").val(currentDate.getFullYear() + "-" + (currentDate.getMonth()+1) + "-" + currentDate.getDate());
var hasta = new Date($('.uv-action-bar .date').find("#to").val());
switch ($('input[name="options"]:checked').val()) {
case "year":
start.setFullYear(currentDate.getFullYear() - 1);
start.setMonth(0);
start.setDate(1);
start.setHours(0, 0, 0, 0);
end.setFullYear(currentDate.getFullYear() - 1);
end.setMonth(11);
end.setDate(new Date(currentDate.getFullYear() - 1, 12, 0).getDate())
end.setHours(0, 0, 0, 0);
datestringStart = start.getFullYear() + "-" + (start.getMonth()+1) + "-" + start.getDate();
datestringEnd = end.getFullYear() + "-" + (end.getMonth()+1) + "-" + end.getDate();
$('.uv-action-bar .date').find("#from").val(datestringStart)
$('.uv-action-bar .date').find("#to").val(datestringEnd).trigger('change');
break;
case "month":
start.setMonth(currentDate.getMonth() - 1);
start.setDate(1);
start.setHours(0, 0, 0, 0);
end.setMonth(currentDate.getMonth() - 1);
end.setDate(new Date(end.getFullYear(), end.getMonth(), 0).getDate())
end.setHours(0, 0, 0, 0);
datestringStart = start.getFullYear() + "-" + (start.getMonth()+1) + "-" + start.getDate();
datestringEnd = end.getFullYear() + "-" + (end.getMonth()+1) + "-" + end.getDate();
$('.uv-action-bar .date').find("#from").val(datestringStart);
$('.uv-action-bar .date').find("#to").val(datestringEnd).trigger('change');
break;
case "week":
var beforeOneWeek = new Date(new Date().getTime() - 60 * 60 * 24 * 7 * 1000)
var beforeOneWeek2 = new Date(beforeOneWeek);
day = beforeOneWeek.getDay()
diffToMonday = beforeOneWeek.getDate() - day + (day === 0 ? -6 : 1)
lastMonday = new Date(beforeOneWeek.setDate(diffToMonday))
lastSunday = new Date(beforeOneWeek2.setDate(diffToMonday + 6));
datestringStart = lastMonday.getFullYear() + "-" + (lastMonday.getMonth()+1) + "-" + lastMonday.getDate();
datestringEnd = lastSunday.getFullYear() + "-" + (lastSunday.getMonth()+1) + "-" + lastSunday.getDate();
$('.uv-action-bar .date').find("#from").val(datestringStart);
$('.uv-action-bar .date').find("#to").val(datestringEnd).trigger('change');
break;
case "day":
start.setFullYear(hasta.getFullYear());
start.setMonth(hasta.getMonth());
start.setDate(hasta.getDate());
start.setHours(0, 0, 0, 0);
datestring = start.getFullYear() + "-" + (start.getMonth()+1) + "-" + start.getDate();
$('.uv-action-bar .date').find("#from").val(datestring);
$('.uv-action-bar .date').find("#to").val(datestring).trigger('change');
break;
}
})
let ticketsByStatus = {{report_service.ticketsByStatus|json_encode|raw}};
let ticketsByType = {{report_service.ticketsByType|json_encode|raw}};
let ticketsByPriority = {{report_service.ticketsByPriority|json_encode|raw}};
let ticketsPerAgent = {{report_service.ticketsPerAgent|json_encode|raw}};
let ticketsPerTeam = {{report_service.ticketsPerTeam|json_encode|raw}};
let kudos = {{report_service.kudos|json_encode|raw}};
$('.uv-action-bar .date #from').datetimepicker({
maxDate: new Date(currentYear, currentMonth, currentDate),
format: 'YYYY-MM-DD',
}).on('dp.change', function(e) {
filtroFechas();
});
$('.uv-action-bar .date #to').datetimepicker({
maxDate: new Date(currentYear, currentMonth, currentDate),
format: 'YYYY-MM-DD',
}).on('dp.change', function(e) {
filtroFechas();
});
const filtroFechas = () => {
//Filtro fechas
$.ajax({
type: "POST",
url: "{{ path('helpdesk_member_report_charts_xhr') }}",
data: {
'from': $('.uv-action-bar .date').find("#from").val(),
'to': $('.uv-action-bar .date').find("#to").val()
},
dataType: "json",
success: function(msg){
ticketsByStatus = msg['ticketsByStatus']
ticketsByType = msg['ticketsByType']
ticketsByPriority = msg['ticketsByPriority']
ticketsPerAgent = msg['ticketsPerAgent']
ticketsPerTeam = msg['ticketsPerTeam']
kudos = msg['kudos']
actualizarGraficos();
//actualizarGraficos(new Date($('.uv-action-bar .date').find("#from").val()),new Date($('.uv-action-bar .date').find("#to").val()))
}
});
}
const capitalizeFirstLetter = (string) => {
return string.charAt(0).toUpperCase() + string.slice(1);
}
const crearGrafico = (tickets, nombre) => {
let tipo = 'pie'
let labels = Object.values(tickets).map(function (el) {return el.Nombre })
let label = ''
switch(nombre) {
case 'kudos':
tipo = 'horizontalBar';
break;
case 'ticketsByStatus':
tipo = 'horizontalBar';
break;
case 'ticketsByPriority':
tipo = 'horizontalBar';
break;
}
return new Chart(
document.getElementById(nombre),
{
type: tipo,
data: {
labels: labels,
datasets: [{
label: label,
data: Object.values(tickets).map(function (el) { return el.Cantidad }),
backgroundColor: Object.values(tickets).map(function (el) { return el.Color }),
hoverOffset: 4
}]
},options: {
legend: { display: false }
}
}
)
}
const actualizaGrafico = (grafico, tickets, nombre) => {
let labels = Object.values(tickets).map(function (el) {return el.Nombre })
const data = {
labels: labels,
datasets: [
{
label: '',
data: Object.values(tickets).map(function (el) { return el.Cantidad }),
backgroundColor: Object.values(tickets).map(function (el) { return el.Color }),
hoverOffset: 4
}
]
};
grafico.data.labels = data.labels;
grafico.data.datasets = data.datasets;
grafico.update();
let html = '';
$.each(tickets, function (key, value) {
let Color = value.Color;
let Cantidad = value.Cantidad;
let Nombre = value.Nombre;
html += '<label><span class="boch" style="background: '+ Color +'"></span> '+ Cantidad +' - '+ Nombre +' </label>';
});
$('#'+nombre).html(html);
}
//Tickets by Status
let graficoTicketByStatus = crearGrafico(ticketsByStatus, 'ticketsByStatus')
//Tickets by type
let graficoTicketByType = crearGrafico(ticketsByType, 'ticketsByType')
//Tickets by priority
let graficoTicketByPriority = crearGrafico(ticketsByPriority, 'ticketsByPriority')
//Tickets per agent
let graficoPerAgent = crearGrafico(ticketsPerAgent, 'ticketsPerAgent')
//Tickets per team
let graficoPerTeam = crearGrafico(ticketsPerTeam, 'ticketsPerTeam')
//Kudos
let graficoKudos = crearGrafico(kudos, 'kudos')
const actualizarGraficos = () => {
actualizaGrafico(graficoTicketByStatus, ticketsByStatus, 'contenidoticketsByStatus');
actualizaGrafico(graficoTicketByType, ticketsByType, 'contenidoticketsByType');
actualizaGrafico(graficoTicketByPriority, ticketsByPriority, 'contenidoticketsByPriority');
actualizaGrafico(graficoPerAgent, ticketsPerAgent, 'contenidoticketsPerAgent');
actualizaGrafico(graficoPerTeam, ticketsPerTeam, 'contenidoticketsPerTeam');
actualizaGrafico(graficoKudos, kudos, 'contenidokudos');
}
</script>
{% endblock %}