-
Madjid Sadallah authoredbd539260
metrics_charts.js 19.91 KiB
document.addEventListener('DOMContentLoaded', function() {
function showAlert(message) {
document.getElementById('alertMessage').textContent = message;
$('#alertModal').modal('show');
}
function loadAndInitializeModal(taskId) {
const container = document.getElementById('detailsModalContainer');
const modalId = 'detailsModal';
// Supprime l'ancien modal s'il existe
const existingModal = container.querySelector(`#${modalId}`);
if (existingModal) {
existingModal.remove();
}
if (container.querySelector('#detailsModal')) {
$('#detailsModal').modal('show');
resetModal();
initializeModal();
return;
}
fetch(`/metric_details/${taskId}`)
.then(response => {
if (response.status === 404) {
showAlert('Aucun détail à afficher pour cette tâche.');
return; // Sortir de la fonction
}
return response.text();
})
.then(html => {
container.innerHTML = html;
$('#detailsModal').modal('show');
resetModal();
initializeModal();
})
.catch(error => console.error('Error loading modal content:', error));
}
function resetModal() {
const typeSelect = document.getElementById('typeSelect');
const chartTypeSelect = document.getElementById('chartTypeSelect');
const dataTableContainer = document.getElementById('dataTableContainer');
const chartContainer = document.getElementById('chartContainer');
const userSelect = document.getElementById('userSelect');
const timeSelect = document.getElementById('timeSelect');
const customDateRange = document.getElementById('customDateRange');
const startDate = document.getElementById('startDate');
const endDate = document.getElementById('endDate');
// Réinitialiser les sélections de type de données et de type de graphique
if (typeSelect) {
typeSelect.value = '';
}
if (chartTypeSelect) {
chartTypeSelect.style.display = 'none';
chartTypeSelect.value = ''; // Réinitialiser la sélection du type de graphique
}
// Réinitialiser les sélections d'utilisateurs
if (userSelect) {
$(userSelect).val(null).trigger('change'); // Utilise Select2 pour réinitialiser la sélection
}
// Réinitialiser la sélection de la période de temps
if (timeSelect) {
timeSelect.value = '';
}
// Réinitialiser les champs de date personnalisée
if (customDateRange) {
customDateRange.classList.add('d-none'); // Masquer les champs de date
}
if (startDate) {
startDate.value = '';
}
if (endDate) {
endDate.value = '';
}
// Réinitialiser l'affichage du tableau et du conteneur du graphique
if (dataTableContainer) {
dataTableContainer.style.display = 'none';
const dataTable = document.getElementById('dataTable');
if (dataTable) {
dataTable.style.display = 'none';
}
}
if (chartContainer) {
chartContainer.style.display = 'none';
}
}
function initializeModal() {
console.log('Modal initialized');
const typeSelect = document.getElementById('typeSelect');
const chartTypeSelect = document.getElementById('chartTypeSelect');
const userSelect = document.getElementById('userSelect');
const timeSelect = document.getElementById('timeSelect');
$('#userSelect').select2({
placeholder: "Utilisateurs",
allowClear: true,
width: '100%', // Utiliser 100% pour une largeur cohérente
closeOnSelect: false // Garder le sélecteur ouvert après une sélection
});
if (!typeSelect || !chartTypeSelect || !userSelect || !timeSelect) {
console.error('Required select elements not found');
return;
}
typeSelect.addEventListener('change', handleTypeChange);
chartTypeSelect.addEventListener('click', handleChartTypeChange );
userSelect.addEventListener('change', handleDataFilter);
timeSelect.addEventListener('change', handleDataFilter);
function handleDataFilter(){
resetModal()
filterData()
}
// Charger les données JSON
const jsonDataElement = document.getElementById('jsonDataScript');
if (!jsonDataElement) {
console.error('JSON data script not found.');
return;
}
window.data = JSON.parse(jsonDataElement.textContent);
document.getElementById('timeSelect').addEventListener('change', function() {
const selectedValue = this.value;
const customDateRange = document.getElementById('customDateRange');
if (selectedValue === 'custom') {
customDateRange.classList.remove('d-none');
} else {
customDateRange.classList.add('d-none');
}
// Appeler la fonction de filtrage pour mettre à jour les données en fonction de la période sélectionnée
filterData();
});
}
function handleTypeChange(event) {
const selectedType = event.target.value;
console.log('Selected Type:', selectedType);
const chartTypeSelect = document.getElementById('chartTypeSelect');
chartTypeSelect.innerHTML = ''; // Réinitialiser les icônes de type de graphique
if (selectedType) {
const chartOptions = getChartOptionsForType(selectedType);
chartOptions.forEach(option => {
const iconButton = document.createElement('button');
iconButton.className = 'btn btn-light'; // Utilisez les classes Bootstrap pour le style
iconButton.innerHTML = `<i class="${option.icon}"></i>`;
iconButton.value = option.value;
iconButton.onclick = () => {
// Ajoutez ici la logique pour gérer le clic sur l'icône
console.log(`Selected chart type: ${option.value}`);
};
chartTypeSelect.appendChild(iconButton);
});
chartTypeSelect.style.display = ''; // Afficher le sélecteur de type de graphique
}
// Cacher le graphique et afficher le tableau
const dataTableContainer = document.getElementById('dataTableContainer');
if (dataTableContainer) {
dataTableContainer.style.display = 'none';
const dataTable = document.getElementById('dataTable');
if (dataTable) {
dataTable.style.display = 'none';
}
}
const chartContainer = document.getElementById('chartContainer');
if (chartContainer) {
chartContainer.style.display = 'none';
}
// Filtrer les données
filterData();
}
function getChartOptionsForType(type) {
return [
{ value: 'table', label: 'Table', icon: 'bi bi-table' },
{ value: 'bar', label: 'Barres', icon: 'bi bi-bar-chart' },
{ value: 'line', label: 'Ligne', icon: 'bi bi-graph-up' },
{ value: 'pie', label: 'Camembert', icon: 'bi bi-pie-chart' },
{ value: 'doughnut', label: 'Donut', icon: 'bi bi-circle-fill' }, // Utilisation de 'circle-fill' pour le donut
{ value: 'radar', label: 'Radar', icon: 'bi bi-broadcast-pin' }, // Utilisation de 'broadcast-pin' pour le radar
{ value: 'polarArea', label: 'Zone Polaire', icon: 'bi bi-circle-half' }, // Utilisation de 'circle-half' pour la zone polaire
{ value: 'bubble', label: 'Bulle', icon: 'bi bi-chat-dots' }, // Utilisation de 'chat-dots' pour la bulle
{ value: 'scatter', label: 'Dispersion', icon: 'bi bi-grid-3x3' } // Utilisation de 'grid-3x3' pour la dispersion
];
}
function handleChartTypeChange(event) {
if (event.target.tagName === 'BUTTON' || event.target.tagName === 'I') {
const selectedButton = event.target.tagName === 'BUTTON' ? event.target : event.target.parentElement;
const selectedValue = selectedButton.value;
console.log(`Selected chart type: ${selectedValue}`);
const selectedChartType = selectedValue;
console.log('Selected Chart Type:', selectedChartType);
const chartContainer = document.getElementById('chartContainer');
const dataTableContainer = document.getElementById('dataTableContainer');
const typeSelect = document.getElementById('typeSelect').value;
if (selectedChartType === 'table') {
if (chartContainer) {
chartContainer.style.display = 'none';
}
if (dataTableContainer) {
dataTableContainer.style.display = '';
const dataTable = document.getElementById('dataTable');
if (dataTable) {
dataTable.style.display = '';
}
updateTable(); // Mettre à jour le tableau avec les données
}
} else if (selectedChartType) {
if (chartContainer) {
chartContainer.style.display = '';
}
if (dataTableContainer) {
dataTableContainer.style.display = 'none';
const dataTable = document.getElementById('dataTable');
if (dataTable) {
dataTable.style.display = 'none';
}
}
updateChart(typeSelect, selectedChartType);
} else {
if (chartContainer) {
chartContainer.style.display = 'none';
}
if (dataTableContainer) {
dataTableContainer.style.display = 'none';
}
}
}
}
function updateChart(type, chartType) {
const canvas = document.getElementById('metricsChart');
const ctx = canvas.getContext('2d');
// Détruire le graphique existant, si nécessaire
if (window.metricsChart && window.metricsChart instanceof Chart) {
window.metricsChart.destroy(); // Détruire l'ancien graphique
}
// Réinitialiser le canvas pour éviter des problèmes de contexte
canvas.width = canvas.width; // Réinitialiser le canvas
const data = filterData(); // Utiliser les données filtrées
if (data.length === 0) {
console.log('No data available for chart.');
return;
}
const formattedData = formatDataForChart(data, chartType);
window.metricsChart = new Chart(ctx, {
type: chartType,
data: {
labels: formattedData.labels,
datasets: [{
label: 'Dataset',
data: formattedData.values,
backgroundColor: getChartColors(chartType, formattedData.labels.length),
borderColor: getChartColors(chartType, formattedData.labels.length, true),
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
}
function formatDataForChart(data, chartType) {
// Regrouper les données par type
const groupedData = groupDataByValue(data);
// Formater les données selon le type de graphique
switch (chartType) {
case 'bar':
case 'horizontalBar':
return formatBarData(groupedData);
case 'line':
return formatLineData(groupedData);
case 'pie':
case 'doughnut':
return formatPieDoughnutData(groupedData);
case 'radar':
return formatRadarData(groupedData);
case 'polarArea':
return formatPolarAreaData(groupedData);
case 'bubble':
return formatBubbleData(groupedData);
case 'scatter':
return formatScatterData(groupedData);
default:
console.error(`Unsupported chart type: ${chartType}`);
return { labels: [], values: [] };
}
}
function groupDataByValue(data) {
return data.reduce((acc, item) => {
if (!acc[item.value]) {
acc[item.value] = 0;
}
acc[item.value] += 1;
return acc;
}, {});
}
function formatBarData(groupedData) {
const labels = Object.keys(groupedData);
const values = labels.map(key => groupedData[key]);
return {
labels,
values
};
}
function formatLineData(groupedData) {
const labels = Object.keys(groupedData);
const values = labels.map(key => groupedData[key]);
return {
labels,
values: values.map(value => ({ x: labels.indexOf(value.toString()) + 1, y: value }))
};
}
function formatPieDoughnutData(groupedData) {
const labels = Object.keys(groupedData);
const values = labels.map(key => groupedData[key]);
return {
labels,
values
};
}
function formatRadarData(groupedData) {
const labels = Object.keys(groupedData);
const values = labels.map(key => groupedData[key]);
return {
labels,
values
};
}
function formatPolarAreaData(groupedData) {
const labels = Object.keys(groupedData);
const values = labels.map(key => groupedData[key]);
return {
labels,
values
};
}
function formatBubbleData(groupedData) {
// Format pour les bulles : x, y, r
const labels = Object.keys(groupedData);
const values = labels.map((key, index) => ({
x: index + 1, // Position en x
y: groupedData[key],
r: groupedData[key] // Taille des bulles
}));
return {
labels,
values
};
}
function formatScatterData(groupedData) {
// Format pour les graphiques de dispersion : x, y
const labels = Object.keys(groupedData);
const values = labels.map((key, index) => ({
x: index + 1, // Position en x
y: groupedData[key]
}));
return {
labels,
values
};
}
function getChartColors(chartType, count, isBorder = false) {
const colors = {
bar: 'rgba(75, 192, 192, 0.2)',
horizontalBar: 'rgba(75, 192, 192, 0.2)',
line: 'rgba(75, 192, 192, 0.2)',
pie: 'rgba(75, 192, 192, 0.2)',
doughnut: 'rgba(75, 192, 192, 0.2)',
radar: 'rgba(75, 192, 192, 0.2)',
polarArea: 'rgba(75, 192, 192, 0.2)',
bubble: 'rgba(75, 192, 192, 0.2)',
scatter: 'rgba(75, 192, 192, 0.2)',
area: 'rgba(75, 192, 192, 0.2)'
};
const borderColor = isBorder ? 'rgba(75, 192, 192, 1)' : colors[chartType] || 'rgba(0,0,0,0.1)';
return Array(count).fill(borderColor);
}
function updateTable() {
const table = document.getElementById('dataTable');
const data = filterData(document.getElementById('typeSelect').value);
const rows = data.map(item => `<tr><td>${item.type}</td><td>${item.value}</td></tr>`).join('');
table.innerHTML = `<table class="table table-striped"><thead><tr><th>Type</th><th>Value</th></tr></thead><tbody>${rows}</tbody></table>`;
}
function filterData() {
// Récupérer la sélection multiple des utilisateurs
const userSelect = document.getElementById('userSelect');
const userFilter = $(userSelect).val() || []; // Utilise jQuery pour obtenir les valeurs sélectionnées
const timeSelect = document.getElementById('timeSelect').value || null;
const type = document.getElementById('typeSelect').value || null;
console.log('Filtering data based on DOM values.');
const jsonDataElement = document.getElementById('jsonDataScript');
if (!jsonDataElement) {
console.error('JSON data script not found.');
return [];
}
const jsonData = JSON.parse(jsonDataElement.textContent);
// Fonction utilitaire pour vérifier si une valeur est considérée comme non fournie
function isNotProvided(value) {
return value === null || value === undefined || value === '';
}
// Fonction pour obtenir la date de début et de fin en fonction de la sélection de période
function getDateRange(selection) {
const now = new Date();
let start = new Date();
let end = new Date();
switch (selection) {
case 'today':
start = end = now;
break;
case 'this_week':
start.setDate(now.getDate() - now.getDay());
end.setDate(start.getDate() + 6);
break;
case 'this_month':
start.setDate(1);
end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
break;
case 'this_year':
start = new Date(now.getFullYear(), 0, 1);
end = new Date(now.getFullYear(), 11, 31);
break;
case 'custom':
start = new Date(document.getElementById('startDate').value);
end = new Date(document.getElementById('endDate').value);
break;
default:
return { start: null, end: null };
}
return { start, end };
}
const { start, end } = getDateRange(timeSelect);
// Filtrer les données en fonction des filtres
const filteredData = jsonData.filter(item => {
let match = true;
if (!isNotProvided(type)) {
match = match && item.type === type;
}
if (userFilter.length > 0) {
if (userFilter.includes('all')) {
match = match && true; // Sélectionne tous les utilisateurs
} else {
match = match && userFilter.includes(String(item.user_id));
}
}
if (start && end) {
const itemDate = new Date(item.date);
console.log('Item date: ', itemDate, ' - start: ', start, ' - end: ', end)
match = match && itemDate >= start && itemDate <= end;
}
return match;
});
if (filteredData.length === 0) {
console.log('No data available for filtering.');
} else {
console.log('Filtered Data:', filteredData);
}
return filteredData;
}
document.querySelectorAll('.metrics-details').forEach(button => {
button.addEventListener('click', function() {
const taskId = this.dataset.task;
loadAndInitializeModal(taskId);
});
});
});