{% extends 'base.html.twig' %}
{% set bodyClass = 'reporting_dashboard' %}
{% set menuItem = 'reporting_dashboard' %}
{% block body_head %}
<h1>
{{ 'reporting.dashboard.title.index'|trans }}
<small>{{ app.user.collectivity }}</small>
</h1>
{% endblock %}
{% block breadcrumb %}
{% set breadcrumb = [] %}
{% include '_breadcrumb.html.twig' with {'breadcrumb': breadcrumb} %}
{% endblock %}
{% block body %}
<div class="tdb">
<div class="row">
{# LEFT #}
<div class="col-md-6">
<div class="row">
{# DETAIL : CONTRACTOR #}
<div class="col-md-6">
<div class="box box-solid">
<div class="box-header with-border"><h3 class="box-title">Sous-traitants</h3></div>
<div class="box-body">
{% if 0 == data.contractor.all %}
Aucune donnée à afficher
{% else %}
<div class="col-sm-6 col-sm-offset-0 col-xs-4 col-xs-offset-1 text-center">
<canvas id="contractor-clauses" width="400" height="400"></canvas>
<p>{{ 'reporting.dashboard.contractor.contractual_clauses_verified.title'|trans }}</p>
</div>
<div class="col-sm-6 col-sm-offset-0 col-xs-4 col-xs-offset-1 text-center">
<canvas id="contractor-adopted-security-features" width="400" height="400"></canvas>
<p>{{ 'reporting.dashboard.contractor.adopted_security_features.title'|trans }}</p>
</div>
<div class="col-sm-6 col-sm-offset-0 col-xs-4 col-xs-offset-1 text-center">
<canvas id="contractor-maintains-treatment-register" width="400" height="400"></canvas>
<p>{{ 'reporting.dashboard.contractor.maintains_treatment_register.title'|trans }}</p>
</div>
<div class="col-sm-6 col-sm-offset-0 col-xs-4 col-xs-offset-1 text-center">
<canvas id="contractor-sending-data-outside-eu" width="400" height="400"></canvas>
<p>{{ 'reporting.dashboard.contractor.sending_data_outside_eu.title'|trans }}</p>
</div>
{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
{# REQUEST #}
<div class="small-box bg-yellow">
<div class="inner">
<h3>{{ data.request.value.status.toProcess }}</h3>
<p>Demandes à traiter</p>
</div>
<div class="icon">
<i class="fa fa-users"></i>
</div>
<a aria-label="Plus d'informations" href="{{ path('registry_request_list') }}" class="small-box-footer">
Plus d'informations <i class="fa fa-arrow-circle-right"></i>
</a>
</div>
<div class="box box-solid">
<div class="box-header with-border"><h3 class="box-title">Demandes</h3></div>
<div class="box-body">
{% if 0 == data.request.value.all %}
Aucune donnée à afficher
{% else %}
<div class="col-sm-6 col-sm-offset-0 col-xs-4 col-xs-offset-1 text-center" style="padding-left: 0; padding-right: 0;">
<canvas id="request-type" width="500" height="500"></canvas>
<p>{{ 'reporting.dashboard.request.type.title'|trans }}</p>
</div>
<div class="col-sm-6 col-sm-offset-0 col-xs-4 col-xs-offset-1 text-center" style="padding-left: 0; padding-right: 0;">
<canvas id="request-status" width="500" height="500"></canvas>
<p>{{ 'reporting.dashboard.request.status.title'|trans }}</p>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
{# DETAIL : MATURITY #}
<div class="box box-solid">
<div class="box-header with-border"><h3 class="box-title">Indice de maturité</h3></div>
<div class="box-body">
<style>
.dropdown.bootstrap-select {
width: 100% !important;
}
</style>
<select class="selectpicker" id="referentiel-chooser">
{% for ref in referentiels %}
<option value="{{ ref.id }}" {% if ref.id == selected_ref.id %}selected{% endif %}>{{ ref.name }}</option>
{% endfor %}
</select>
<div style="margin-top: 1em">
{% if data.maturity is empty %}
Aucun indice à afficher
{% else %}
{% if data.maturity.new is defined and data.maturity.new.data is defined and data.maturity.new.data|length >= 3 %}
<canvas id="maturity-radar"></canvas>
{% else %}
Le référentiel contient moins de trois sections
{% endif %}
{% endif %}
</div>
</div>
</div>
{# DETAIL : TREATMENTS #}
<div class="box box-solid">
<div class="box-header with-border"><h3 class="box-title">Mesures de sécurité</h3></div>
<div class="box-body">
{% if 0 == data.treatment.value.numeric %}
Aucun traitement utilisable pour ce graphe
{% else %}
<canvas id="treatment-bar"></canvas>
{% endif %}
</div>
</div>
</div>
</div>
{% if app.user.collectivity.hasModuleConformiteTraitement == true or
app.user.collectivity.hasModuleConformiteOrganisation == true %}
<div class="row">
<div class="col-md-12">
{# DETAIL : CONFORMITE TRAITEMENT #}
{% if app.user.collectivity.hasModuleConformiteTraitement == true %}
<div class="box box-solid">
<div class="box-header with-border"><h3 class="box-title">Conformité des traitements</h3></div>
<div class="box-body">
{% if data.conformiteTraitement.data is empty %}
Aucune donnée à afficher
{% else %}
<canvas id="conformiteTraitement-pie"></canvas>
{% endif %}
</div>
</div>
{% endif %}
</div>
</div>
{% endif %}
</div>
{# RIGHT #}
<div class="col-md-6">
<div class="row">
{# AIPD #}
<div class="col-sm-6 col-xs-12">
{% if app.user.collectivity.hasModuleConformiteTraitement == true %}
<div class="small-box bg-light-blue">
<div class="inner">
<h3>{{ data.aipd.toDo }}</h3>
<p>AIPD à réaliser</p>
</div>
<div class="icon">
<i class="fa fa-clipboard-list"></i>
</div>
<a aria-label="Plus d'informations" href="{{ path('registry_conformite_traitement_list') }}" class="small-box-footer">
Plus d'informations <i class="fa fa-arrow-circle-right"></i>
</a>
</div>
{% endif %}
</div>
{# Action to realize #}
<div class="col-sm-6 col-xs-12">
<div class="small-box bg-aqua">
<div class="inner">
<h3>{{ data.mesurement.value.planified }}</h3>
<p>Actions planifiées</p>
</div>
<div class="icon">
<i class="fa fa-bullseye"></i>
</div>
<a aria-label="Plus d'informations" href="{{ path('registry_mesurement_action_plan') }}" class="small-box-footer">
Plus d'informations <i class="fa fa-arrow-circle-right"></i>
</a>
</div>
</div>
</div>
<div class="row">
{# VIOLATION #}
<div class="col-sm-6 col-xs-12">
<div class="small-box bg-red">
<div class="inner">
<h3>{{ data.violation.value.all }}</h3>
<p>Violations</p>
</div>
<div class="icon">
<i class="fa fa-exclamation-circle"></i>
</div>
<a aria-label="Plus d'informations" href="{{ path('registry_violation_list') }}" class="small-box-footer">
Plus d'informations <i class="fa fa-arrow-circle-right"></i>
</a>
</div>
</div>
{# MESUREMENT : applied #}
<div class="col-sm-6 col-xs-12">
<div class="small-box bg-green">
<div class="inner">
<h3>{{ data.mesurement.value.applied }}</h3>
<p>Actions mises en place</p>
</div>
<div class="icon">
<i class="fa fa-adjust"></i>
</div>
<a aria-label="Plus d'informations" href="{{ path('registry_mesurement_list') }}" class="small-box-footer">
Plus d'informations <i class="fa fa-arrow-circle-right"></i>
</a>
</div>
</div>
{# <div class="col-sm-12">#}
{# {% if app_activate_notifications and app_notification_dashboard_shown == 'true' %}#}
{# #}{# {{app_notification_max_shown}} #}
{# <div id="notifications" class="box box-solid">#}
{# {{ block("body", "Notification/Notification/box.html.twig") }}#}
{# </div>#}
{# {% endif %}#}
{# </div>#}
</div>
<div class="row">
<div class="col-md-12">
<div class="box box-warning">
<div class="box-header with-border"><h3 class="box-title">Plan d'actions <small>{{ app_user_dashboard_action_plan_limit }} prochaines</small></h3></div>
<div class="box-body">
<table role="presentation" class="table table-striped table-bordered">
<thead>
<tr>
<th scope="col">{{ 'registry.mesurement.list.name'|trans }}</th>
<th scope="col">{{ 'registry.mesurement.list.planification_date'|trans }}</th>
<th scope="col">{{ 'registry.mesurement.list.priority'|trans }}</th>
<th scope="col">{{ 'registry.mesurement.list.manager'|trans }}</th>
<th scope="col">{{ 'label.action_link'|trans }}</th>
</tr>
</thead>
<tbody>
{% if not actions|length %}
<tr>
<td colspan="5" style="text-align: center">
Aucune action planifiée
</td>
</tr>
{% endif %}
{% for action in actions %}
<tr>
<td>{{ action.name }}</td>
<td>{{ action.planificationDate|date('d/m/Y') }}</td>
<td>
{% set key = action.priority %}
{% if key is not null %}
{% if key is same as ('low') %}
<span class="badge bg-blue">{{ dictionary('registry_mesurement_priority')[key] }}</span>
{% elseif key is same as ('normal') %}
<span class="badge bg-yellow">{{ dictionary('registry_mesurement_priority')[key] }}</span>
{% elseif key is same as ('high') %}
<span class="badge bg-red">{{ dictionary('registry_mesurement_priority')[key] }}</span>
{% endif %}
{% endif %}
</td>
<td>{{ action.manager }}</td>
<td>
<a aria-label="Chercher" href="/actions-de-protection/visualiser/{{ action.id }}" ><i class="fas fa-search"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="row">
{% if app.user.collectivity.hasModuleConformiteOrganisation == true %}
<div class="col-md-12">
{# DETAIL : CONFORMITE ORGANISATION #}
<div class="box box-solid">
<div class="box-header with-border"><h3 class="box-title">Conformité de la structure</h3></div>
{% if data.conformiteOrganisation is empty %}
<div class="box-body">
Aucune donnée à afficher
</div>
{% else %}
<div class="box-body no-padding">
<table role="presentation" class="table table-striped">
<thead>
<tr>
<th scope="col">Processus</th>
<th scope="col">Progression</th>
<th style="width: 40px" scope="col">Conformité</th>
</tr>
</thead>
<tbody>
{% for conformite in data.conformiteOrganisation %}
{% set score = (conformite['conformite'] / 5 * 100) %}
{% if score < 50 %}
{% set color = 'red' %}
{% elseif score < 70 %}
{% set color = 'yellow' %}
{% else %}
{% set color = 'green' %}
{% endif %}
<tr>
<td>{{ conformite['processus'] }}</td>
<td>
<div class="progress progress-xs">
<div class="progress-bar progress-bar-{{ color }}" style="width: {{ score }}%"></div>
</div>
</td>
<td>
<span style="min-width: 100%" class="badge bg-{{ color }}">{{ score }}%</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
</div>
{% endif %}
</div>
</div>
</div>
{# JOURNALISATION #}
<div class="row">
<div class="col-md-12">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Journalisation <small>{{ app_user_dashboard_journalisation_limit }} dernières actions</small></h3>
</div>
<div class="box-body no-padding">
<table role="presentation" class="table">
<thead>
<tr>
<th scope="col">Nom utilisateur</th>
<th scope="col">Email utilisateur</th>
<th scope="col">Date</th>
<th scope="col">Sujet</th>
<th scope="col">Action</th>
<th scope="col">Nom</th>
<th scope="col">Lien</th>
</tr>
</thead>
<tbody>
{% for logJournal in data.logJournal %}
{% set logJournalLink = getLogJournalLink(logJournal) %}
<tr>
<td>{{ logJournal.userFullName }}</td>
<td>{{ logJournal.userEmail }}</td>
<td>{{ logJournal.date|date('d/m/Y') }}</td>
<td>{{ logJournal.subjectType ? logJournal.subjectType|dictionary('reporting_log_journal_subject') : '' }}</td>
<td>{{ logJournal.action ? logJournal.action|dictionary('reporting_log_journal_action') : '' }}</td>
<td>{{ logJournal.subjectName }}</td>
<td>
{% if logJournal.isDeleted %}
{{ logJournalLink }}
{% elseif logJournalLink is not null %}
<a aria-label="Lien" href="{{ logJournalLink }}">Lien</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block javascripts %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
{# DEFINE DATA #}
<script>
let labelYes = '{{ 'label.yes'|trans }}';
let labelNo = '{{ 'label.no'|trans }}';
let colorBlue = 'rgba(54, 162, 235, 1)';
let colorBlueOpacity = 'rgba(54, 162, 235, 0.5)';
let colorGreen = ' rgba(48, 183, 44, 1)';
let colorGreenOpacity = ' rgba(48, 183, 44, 0.5)';
let colorPurple = 'rgba(153, 51, 204, 1)';
let colorPurpleOpacity = 'rgba(153, 51, 204, 0.5)';
let colorRed = 'rgba(255, 99, 132, 1)';
let colorRedOpacity = 'rgba(255, 99, 132, 0.5)';
let colorTeal = 'rgba(0, 105, 92, 1)';
let colorTealOpacity = 'rgba(0, 105, 92, 0.5)';
let colorOrange = 'rgb(255, 136, 0, 1)';
let colorOrangeOpacity = 'rgb(255, 136, 0, 0.5)';
let labelYesNo = [labelYes, labelNo];
// CONTRACTOR
let contractorClausesData = [{{ data.contractor.clauses.yes }}, {{ data.contractor.clauses.no }}];
let contractorAdoptedSecurityFeaturesData = [{{ data.contractor.adoptedSecurityFeatures.yes }}, {{ data.contractor.adoptedSecurityFeatures.no }}];
let contractorMaintainsTreatmentRegisterData = [{{ data.contractor.maintainsTreatmentRegister.yes }}, {{ data.contractor.maintainsTreatmentRegister.no }}];
let contractorSendingDataOutsideEuData = [{{ data.contractor.sendingDataOutsideEu.yes }}, {{ data.contractor.sendingDataOutsideEu.no }}];
// MESUREMENT
let mesurementStatusData = [{{ data.mesurement.value.applied }}, {{ data.mesurement.value.planified }}, {{ data.mesurement.value.notApplied }}];
// MATURITY
let maturityLabels = [];
let maturitySerieLabel = [];
let maturityData = [];
{% if data.maturity.new is defined %}
let tmpData1 = [];
maturitySerieLabel.push('{{ data.maturity.new.name }}');
{% for position, info in data.maturity.new.data %}
maturityLabels.push('{{ info.name }}');
tmpData1.push('{{ info.score }}');
{% endfor %}
maturityData.push(tmpData1);
{% endif %}
{% if data.maturity.old is defined %}
let tmpData2 = [];
maturitySerieLabel.push('{{ data.maturity.old.name }}');
{% for position, info in data.maturity.old.data %}
tmpData2.push('{{ info.score }}');
{% endfor %}
maturityData.push(tmpData2);
{% endif %}
// REQUEST
let requestTypeLabel = [
'Rectifier des données',
'Supprimer des données',
'Retirer le consentement',
'Accéder à des données',
'Portabilité des données',
'Limiter le traitement',
'Autre',
];
let requestTypeData = [];
{% if data.request.value.type.correct %}
requestTypeData.push({{ data.request.value.type.correct }});
{% elseif data.request.value.type.delete %}
requestTypeData.push({{ data.request.value.type.delete }});
{% elseif data.request.value.type.withdrawConsent %}
requestTypeData.push({{ data.request.value.type.withdrawConsent }});
{% elseif data.request.value.type.access %}
requestTypeData.push({{ data.request.value.type.access }});
{% elseif data.request.value.type.dataPortability %}
requestTypeData.push({{ data.request.value.type.dataPortability }});
{% elseif data.request.value.type.limitTreatment %}
requestTypeData.push({{ data.request.value.type.limitTreatment }});
{% elseif data.request.value.type.other %}
requestTypeData.push({{ data.request.value.type.other }});
{% endif %}
let requestStatusLabel = [
'Traité',
'À traiter',
'Non-recevable',
];
let requestStatusData = [];
{% if data.request.value.status.processed %}
requestStatusData.push({{ data.request.value.status.processed }});
{% elseif data.request.value.status.toProcess %}
requestStatusData.push({{ data.request.value.status.toProcess }});
{% elseif data.request.value.status.incomplete %}
requestStatusData.push({{ data.request.value.status.incomplete }});
{% endif %}
// TREATMENT
let treatmentLabels = [
'Contrôle d\'accès',
'Traçabilité',
'Sauvegarde',
'Mises à jour',
];
let treatmentDatasetYes = [];
let treatmentDatasetNo = [];
{% for key, item in data.treatment.value.data %}
{% set yesItem = attribute(item, 'yes') %}
{% set noItem = attribute(item, 'no') %}
{% if yesItem > 0 or noItem > 0 %}
treatmentDatasetYes.push('{{ attribute(item, 'yes') }}');
treatmentDatasetNo.push('{{ attribute(item, 'no') }}');
{% endif %}
{% endfor %}
// CONFORMITE TRAITEMENT
let conformiteTraitementLabels = {{ data.conformiteTraitement.labels|json_encode|raw }};
let conformiteTraitementData = [];
{% if data.conformiteTraitement.data %}
conformiteTraitementData = {{ data.conformiteTraitement.data|json_encode|raw }};
{% endif %}
let conformiteTraitementColors = {{ data.conformiteTraitement.colors|json_encode|raw }};
</script>
{# USE DATA & DEFINE GRAPH #}
{{ encore_entry_script_tags('js/dashboard') }}
<script>
$(document).ready(function() {
$('body').on('change', '#referentiel-chooser', function() {
console.log('change', $(this).val());
window.location.href = "{{ app.request.pathinfo }}?referentiel=" + $(this).val();
})
})
</script>
{% endblock %}