|
<!DOCTYPE html> |
|
<html lang="es"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Boston Scientific Dashboard</title> |
|
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css"/> |
|
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script> |
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> |
|
<style> |
|
|
|
:root { |
|
--primary-blue: #0057b8; |
|
--secondary-blue: #003f7f; |
|
--light-gray: #f4f4f4; |
|
--dark-gray: #333; |
|
--highlight-yellow: #FFD700; |
|
--danger-red: #FF0000; |
|
--success-green: #008000; |
|
} |
|
|
|
|
|
body { |
|
font-family: Arial, sans-serif; |
|
background-color: var(--light-gray); |
|
color: var(--dark-gray); |
|
margin: 0; |
|
padding: 0; |
|
} |
|
|
|
h1 { |
|
text-align: center; |
|
color: var(--primary-blue); |
|
margin: 20px 0; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
.dashboard { |
|
display: grid; |
|
grid-template-columns: 1fr 2fr 1fr; |
|
grid-template-rows: auto auto auto; |
|
gap: 20px; |
|
padding: 20px; |
|
} |
|
|
|
|
|
#controls { |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
background: white; |
|
padding: 10px; |
|
border-radius: 10px; |
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); |
|
} |
|
|
|
select { |
|
padding: 8px; |
|
font-size: 16px; |
|
border: 2px solid var(--primary-blue); |
|
border-radius: 5px; |
|
background: white; |
|
color: var(--dark-gray); |
|
cursor: pointer; |
|
} |
|
|
|
|
|
#map { |
|
height: 500px; |
|
width: 100%; |
|
border-radius: 10px; |
|
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2); |
|
} |
|
|
|
|
|
.chart-container { |
|
display: grid; |
|
grid-template-columns: repeat(2, 1fr); |
|
gap: 20px; |
|
} |
|
|
|
.chart-box { |
|
background: white; |
|
padding: 20px; |
|
border-radius: 10px; |
|
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
canvas { |
|
width: 100%; |
|
height: 300px; |
|
} |
|
|
|
|
|
@media (max-width: 768px) { |
|
.chart-container { |
|
grid-template-columns: 1fr; |
|
} |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
|
|
<h1>Matrix - Dashboard</h1> |
|
<div id="controls"> |
|
<label for="category">Status:</label> |
|
<select id="category" onchange="updateMarkers()"> |
|
<option value="all">All</option> |
|
<option value="assessment">Assessment</option> |
|
<option value="deployment">In Deployment</option> |
|
<option value="operative">Operative</option> |
|
<option value="paused">Paused</option> |
|
<option value="maintenance">Maintenance</option> |
|
<option value="removed">Removed</option> |
|
</select> |
|
</div> |
|
<div class="dashboard"> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="chart-box"> |
|
<canvas id="connectionsChart"></canvas> |
|
<canvas id="webinarChart"></canvas> |
|
<canvas id="recordingChart"></canvas> |
|
</div> |
|
|
|
|
|
<div id="map"></div> |
|
|
|
<div class="chart-box"> |
|
<canvas id="supportTimeChart"></canvas> |
|
<canvas id="webinarTime"></canvas> |
|
<canvas id="recordingTime"></canvas> |
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
<script> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var locations = [ |
|
{ name: "Ragusa", coords: [36.9257, 14.7244], category: "operative", connections: 12, avgSupportTime: 12, webinars: 4, avgWebinarTime: 1 , recordings: 0, avgRecordingTime: 0}, |
|
{ name: "Seville", coords: [37.3886, -5.9823], category: "operative", connections: 6, avgSupportTime: 2, webinars: 7, avgWebinarTime: 1 , recordings: 0, avgRecordingTime: 0}, |
|
{ name: "Groningen", coords: [53.2194, 6.5665], category: "operative", connections: 6, avgSupportTime: 3, webinars: 0, avgWebinarTime: 0 , recordings: 0, avgRecordingTime: 0}, |
|
{ name: "Cape Town", coords: [-33.9249, 18.4241], category: "operative", connections: 5, avgSupportTime: 0.5, webinars: 13, avgWebinarTime: 1 , recordings: 0, avgRecordingTime: 0}, |
|
{ name: "Bern", coords: [46.9481, 7.4474], category: "operative", connections: 1, avgSupportTime: 0, webinars: 0, avgWebinarTime: 0 , recordings: 0, avgRecordingTime: 0}, |
|
{ name: "Kiel", coords: [54.3233, 10.1228], category: "removed", connections: 0, avgSupportTime: 0, webinars: 0, avgWebinarTime: 0 , recordings: 0, avgRecordingTime: 0}, |
|
|
|
{ name: "Le Mans", coords: [48.0077, 0.1996], category: "assessment", connections: 0, avgSupportTime: 0, webinars: 0, avgWebinarTime: 0 , recordings: 0, avgRecordingTime: 0}, |
|
{ name: "Gdansk", coords: [54.3520, 18.6466], category: "assessment", connections: 0, avgSupportTime: 0, webinars: 0, avgWebinarTime: 0 , recordings: 0, avgRecordingTime: 0}, |
|
{ name: "Prague", coords: [50.0755, 14.4378], category: "assessment", connections: 0, avgSupportTime: 0, webinars: 0, avgWebinarTime: 0 , recordings: 0, avgRecordingTime: 0}, |
|
{ name: "Kuwait", coords: [29.3759, 47.9774], category: "assessment", connections: 0, avgSupportTime: 0, webinars: 0, avgWebinarTime: 0 , recordings: 0, avgRecordingTime: 0} |
|
]; |
|
var map = L.map('map').setView([50.0755, 14.4378], 3); |
|
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { |
|
attribution: 'Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' |
|
}).addTo(map); |
|
|
|
var categoryColors = { |
|
"assessment": "#0057b8", |
|
"deployment": "#008000", |
|
"operative": "#008000", |
|
"paused": "#FFD700", |
|
"maintenance": "#FFA500", |
|
"removed": "#FF0000" |
|
}; |
|
|
|
var markers = []; |
|
var chart1 = null; |
|
var chart2 = null; |
|
var chart3 = null; |
|
var chart4 = null; |
|
var chart5 = null; |
|
var chart6 = null; |
|
|
|
function updateMarkers() { |
|
var selectedCategory = document.getElementById("category").value; |
|
|
|
markers.forEach(marker => map.removeLayer(marker)); |
|
markers = []; |
|
|
|
var filteredLocations = locations.filter(location => selectedCategory === "all" || location.category === selectedCategory); |
|
|
|
filteredLocations.forEach(location => { |
|
var marker = L.circleMarker(location.coords, { |
|
color: categoryColors[location.category], |
|
fillColor: categoryColors[location.category], |
|
fillOpacity: 0.8, |
|
radius: 8 |
|
}).bindPopup(`<b>${location.name}</b><br>Categoría: ${location.category}<br>Conexiones: ${location.connections}<br>Soporte: ${location.avgSupportTime} hrs`); |
|
|
|
marker.addTo(map); |
|
markers.push(marker); |
|
}); |
|
|
|
if (markers.length > 1) { |
|
var group = new L.featureGroup(markers); |
|
map.fitBounds(group.getBounds()); |
|
} else if (markers.length === 1) { |
|
map.setView(markers[0].getLatLng(), 6); |
|
} else { |
|
map.setView([45, 10], 3); |
|
} |
|
|
|
updateCharts(filteredLocations); |
|
} |
|
|
|
|
|
|
|
|
|
function updateCharts(filteredLocations) { |
|
var cityNames = filteredLocations.map(location => location.name); |
|
|
|
var connectionsData = filteredLocations.map(location => location.connections); |
|
var avgSupportTimeData = filteredLocations.map(location => location.avgSupportTime); |
|
var webinarData = filteredLocations.map(location => location.webinars); |
|
var avgWebinarTimeData = filteredLocations.map(location => location.avgWebinarTime); |
|
var recordingData = filteredLocations.map(location => location.recordings); |
|
var avgRecordingTimeData = filteredLocations.map(location => location.avgRecordingTime); |
|
|
|
var categoryColorsData = filteredLocations.map(location => categoryColors[location.category]); |
|
|
|
if (chart1) chart1.destroy(); |
|
if (chart2) chart2.destroy(); |
|
if (chart3) chart3.destroy(); |
|
if (chart4) chart4.destroy(); |
|
if (chart5) chart3.destroy(); |
|
if (chart6) chart4.destroy(); |
|
|
|
var ctx1 = document.getElementById('connectionsChart').getContext('2d'); |
|
chart1 = new Chart(ctx1, { |
|
type: 'bar', |
|
data: { |
|
labels: cityNames, |
|
datasets: [{ |
|
label: 'Monthly Remote Connections', |
|
data: connectionsData, |
|
backgroundColor: categoryColorsData, |
|
borderColor: '#333', |
|
borderWidth: 1, |
|
borderRadius: 5, |
|
hoverBackgroundColor: 'rgba(0, 0, 0, 0.2)' |
|
}] |
|
}, |
|
options: { |
|
plugins: { |
|
legend: { display: false }, |
|
title: { |
|
display: true, |
|
text: 'Monthly Remote connections', |
|
font: { |
|
size: 12 |
|
}, |
|
color: '#333' |
|
} |
|
}, |
|
scales: { |
|
x: { |
|
ticks: { color: '#333' }, |
|
grid: { display: false } |
|
}, |
|
y: { |
|
ticks: { color: '#333' }, |
|
grid: { color: 'rgba(0,0,0,0.1)' } |
|
} |
|
}, |
|
animation: { |
|
duration: 1000, |
|
easing: 'easeInOutBounce' |
|
} |
|
|
|
} |
|
}); |
|
|
|
var ctx2 = document.getElementById('supportTimeChart').getContext('2d'); |
|
chart2 = new Chart(ctx2, { |
|
type: 'bar', |
|
data: { |
|
labels: cityNames, |
|
datasets: [{ |
|
label: 'Average Monthly Support Time (hrs)', |
|
data: avgSupportTimeData, |
|
backgroundColor: categoryColorsData, |
|
borderColor: '#333', |
|
borderWidth: 1, |
|
borderRadius: 5, |
|
hoverBackgroundColor: 'rgba(0, 0, 0, 0.2)' |
|
}] |
|
}, |
|
options: { |
|
plugins: { |
|
legend: { display: false }, |
|
title: { |
|
display: true, |
|
text: 'Average Monthly Support Time (hrs)', |
|
font: { |
|
size: 12 |
|
}, |
|
color: '#333' |
|
} |
|
}, |
|
scales: { |
|
x: { |
|
ticks: { color: '#333' }, |
|
grid: { display: false } |
|
}, |
|
y: { |
|
ticks: { color: '#333' }, |
|
grid: { color: 'rgba(0,0,0,0.1)' } |
|
} |
|
}, |
|
animation: { |
|
duration: 1000, |
|
easing: 'easeInOutBounce' |
|
} |
|
} |
|
}); |
|
|
|
var ctx3 = document.getElementById('webinarChart').getContext('2d'); |
|
chart3 = new Chart(ctx3, { |
|
type: 'bar', |
|
data: { |
|
labels: cityNames, |
|
datasets: [{ |
|
label: 'Average Monthly Webinar Connections', |
|
data: webinarData, |
|
backgroundColor: categoryColorsData, |
|
borderColor: '#333', |
|
borderWidth: 1, |
|
borderRadius: 5, |
|
hoverBackgroundColor: 'rgba(0, 0, 0, 0.2)' |
|
}] |
|
}, |
|
options: { |
|
plugins: { |
|
legend: { display: false }, |
|
title: { |
|
display: true, |
|
text: 'Monthly Webinar Connections', |
|
font: { |
|
size: 12 |
|
}, |
|
color: '#333' |
|
} |
|
}, |
|
scales: { |
|
x: { |
|
ticks: { color: '#333' }, |
|
grid: { display: false } |
|
}, |
|
y: { |
|
ticks: { color: '#333' }, |
|
grid: { color: 'rgba(0,0,0,0.1)' } |
|
} |
|
}, |
|
animation: { |
|
duration: 1000, |
|
easing: 'easeInOutBounce' |
|
} |
|
} |
|
}); |
|
|
|
var ctx4 = document.getElementById('webinarTime').getContext('2d'); |
|
chart4 = new Chart(ctx4, { |
|
type: 'bar', |
|
data: { |
|
labels: cityNames, |
|
datasets: [{ |
|
label: 'Average Monthly Webinar Time (hrs/session)', |
|
data: avgWebinarTimeData, |
|
backgroundColor: categoryColorsData, |
|
borderColor: '#333', |
|
borderWidth: 1, |
|
borderRadius: 5, |
|
hoverBackgroundColor: 'rgba(0, 0, 0, 0.2)' |
|
}] |
|
}, |
|
options: { |
|
plugins: { |
|
legend: { display: false }, |
|
title: { |
|
display: true, |
|
text: 'Average Monthly Webinar Time (hrs/session)', |
|
font: { |
|
size: 12 |
|
}, |
|
color: '#333' |
|
} |
|
}, |
|
scales: { |
|
x: { |
|
ticks: { color: '#333' }, |
|
grid: { display: false } |
|
}, |
|
y: { |
|
ticks: { color: '#333' }, |
|
grid: { color: 'rgba(0,0,0,0.1)' } |
|
} |
|
}, |
|
animation: { |
|
duration: 1000, |
|
easing: 'easeInOutBounce' |
|
} |
|
} |
|
}); |
|
|
|
|
|
|
|
|
|
|
|
var ctx5 = document.getElementById('recordingChart').getContext('2d'); |
|
chart5 = new Chart(ctx5, { |
|
type: 'bar', |
|
data: { |
|
labels: cityNames, |
|
datasets: [{ |
|
label: 'Average Monthly Recordings', |
|
data: recordingData, |
|
backgroundColor: categoryColorsData, |
|
borderColor: '#333', |
|
borderWidth: 1, |
|
borderRadius: 5, |
|
hoverBackgroundColor: 'rgba(0, 0, 0, 0.2)' |
|
}] |
|
}, |
|
options: { |
|
plugins: { |
|
legend: { display: false }, |
|
title: { |
|
display: true, |
|
text: 'Monthly Recordings', |
|
font: { |
|
size: 12 |
|
}, |
|
color: '#333' |
|
} |
|
}, |
|
scales: { |
|
x: { |
|
ticks: { color: '#333' }, |
|
grid: { display: false } |
|
}, |
|
y: { |
|
ticks: { color: '#333' }, |
|
grid: { color: 'rgba(0,0,0,0.1)' } |
|
} |
|
}, |
|
animation: { |
|
duration: 1000, |
|
easing: 'easeInOutBounce' |
|
} |
|
} |
|
}); |
|
|
|
var ctx6 = document.getElementById('recordingTime').getContext('2d'); |
|
chart6 = new Chart(ctx6, { |
|
type: 'bar', |
|
data: { |
|
labels: cityNames, |
|
datasets: [{ |
|
label: 'Average Monthly Recording Time (hrs)', |
|
data: avgRecordingTimeData, |
|
backgroundColor: categoryColorsData, |
|
borderColor: '#333', |
|
borderWidth: 1, |
|
borderRadius: 5, |
|
hoverBackgroundColor: 'rgba(0, 0, 0, 0.2)' |
|
}] |
|
}, |
|
options: { |
|
plugins: { |
|
legend: { display: false }, |
|
title: { |
|
display: true, |
|
text: 'Average Monthly Recording Time (hrs)', |
|
font: { |
|
size: 12 |
|
}, |
|
color: '#333' |
|
} |
|
}, |
|
scales: { |
|
x: { |
|
ticks: { color: '#333' }, |
|
grid: { display: false } |
|
}, |
|
y: { |
|
ticks: { color: '#333' }, |
|
grid: { color: 'rgba(0,0,0,0.1)' } |
|
} |
|
}, |
|
animation: { |
|
duration: 1000, |
|
easing: 'easeInOutBounce' |
|
} |
|
} |
|
}); |
|
|
|
} |
|
|
|
updateMarkers(); |
|
</script> |
|
|
|
</body> |
|
</html> |
|
|
|
|
|
|
|
|