diff --git a/dbapp/mainapp/templates/mainapp/statistics.html b/dbapp/mainapp/templates/mainapp/statistics.html
index 3a9a105..cf8eae1 100644
--- a/dbapp/mainapp/templates/mainapp/statistics.html
+++ b/dbapp/mainapp/templates/mainapp/statistics.html
@@ -113,6 +113,19 @@
.card-body canvas:active {
cursor: grabbing;
}
+
+ /* Summary rows in satellite table */
+ .table-warning.fw-bold td {
+ border-bottom: 2px solid #ffc107 !important;
+ }
+
+ .table-info.fw-bold td {
+ border-bottom: 2px solid #0dcaf0 !important;
+ }
+
+ .satellite-stat-row:hover {
+ background-color: #f8f9fa !important;
+ }
{% endblock %}
@@ -326,6 +339,17 @@
+
+
+ | Всего |
+
+ {{ total_points }}
+ |
+
+ {{ total_sources }}
+ |
+
+
{% for stat in satellite_stats %}
| {{ stat.parameter_obj__id_satellite__name }} |
@@ -373,6 +397,30 @@
+
+
+
+
+
+
+
+
+
+
@@ -588,7 +650,9 @@ document.addEventListener('DOMContentLoaded', function() {
const dailyLabels = dailyData.map(d => {
if (d.date) {
const date = new Date(d.date);
- return date.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year:"2-digit" });
+ const dateStr = date.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year:"2-digit" });
+ const dayStr = date.toLocaleDateString('ru-RU', { weekday: 'short' });
+ return dateStr + ' (' + dayStr + ')';
}
return '';
});
@@ -743,6 +807,9 @@ document.addEventListener('DOMContentLoaded', function() {
barChart.data.datasets[0].backgroundColor = barColors;
barChart.update();
}
+
+ // Update source charts
+ updateSourceCharts();
}
// Initialize charts
@@ -829,10 +896,12 @@ document.addEventListener('DOMContentLoaded', function() {
color: '#333',
font: {
weight: 'bold',
- size: 11
+ size: 12
},
- formatter: function(value) {
- return value;
+ formatter: function(value, context) {
+ const total = context.dataset.data.reduce((a, b) => a + b, 0);
+ const percentage = ((value / total) * 100).toFixed(1);
+ return percentage + '%\n(' + value + ')';
}
}
},
@@ -890,10 +959,149 @@ document.addEventListener('DOMContentLoaded', function() {
}
}
+ // Source object charts (similar to satellite charts but for sources count)
+ let sourcePieChart = null;
+ let sourceBarChart = null;
+
+ // Initialize source charts
+ function initSourceCharts() {
+ const filteredStats = getFilteredSatelliteData();
+
+ // Source Pie Chart
+ if (filteredStats.length > 0) {
+ const sourcePieLabels = filteredStats.map(s => s.parameter_obj__id_satellite__name);
+ const sourcePieData = filteredStats.map(s => s.sources_count);
+ const sourcePieColors = filteredStats.map((s, i) => colors[satelliteStats.indexOf(s) % colors.length]);
+
+ sourcePieChart = new Chart(document.getElementById('sourcePieChart'), {
+ type: 'doughnut',
+ data: {
+ labels: sourcePieLabels,
+ datasets: [{
+ data: sourcePieData,
+ backgroundColor: sourcePieColors
+ }]
+ },
+ options: {
+ responsive: true,
+ plugins: {
+ legend: {
+ position: 'right',
+ labels: {
+ boxWidth: 12,
+ font: {
+ size: 11
+ }
+ }
+ },
+ datalabels: {
+ color: '#fff',
+ font: {
+ weight: 'bold',
+ size: 10
+ },
+ formatter: function(value, context) {
+ const total = context.dataset.data.reduce((a, b) => a + b, 0);
+ const percentage = ((value / total) * 100).toFixed(1);
+ if (percentage < 3) return '';
+ return value + '\n(' + percentage + '%)';
+ },
+ textAlign: 'center'
+ }
+ }
+ }
+ });
+ }
+
+ // Source Bar Chart (top 15)
+ if (filteredStats.length > 0) {
+ const topSourceStats = filteredStats.slice(0, 15);
+ const sourceBarLabels = topSourceStats.map(s => s.parameter_obj__id_satellite__name);
+ const sourceBarData = topSourceStats.map(s => s.sources_count);
+ const sourceBarColors = topSourceStats.map((s, i) => colors[satelliteStats.indexOf(s) % colors.length]);
+
+ sourceBarChart = new Chart(document.getElementById('sourceBarChart'), {
+ type: 'bar',
+ data: {
+ labels: sourceBarLabels,
+ datasets: [{
+ label: 'Количество объектов',
+ data: sourceBarData,
+ backgroundColor: sourceBarColors
+ }]
+ },
+ options: {
+ responsive: true,
+ indexAxis: 'y',
+ interaction: {
+ intersect: false,
+ mode: 'index'
+ },
+ plugins: {
+ legend: {
+ display: false
+ },
+ datalabels: {
+ anchor: 'end',
+ align: 'end',
+ color: '#333',
+ font: {
+ weight: 'bold',
+ size: 12
+ },
+ formatter: function(value, context) {
+ const total = context.dataset.data.reduce((a, b) => a + b, 0);
+ const percentage = ((value / total) * 100).toFixed(1);
+ return percentage + '%\n(' + value + ')';
+ }
+ }
+ },
+ scales: {
+ x: {
+ beginAtZero: true,
+ grace: '10%'
+ }
+ }
+ }
+ });
+ }
+ }
+
+ // Update source charts based on satellite selection
+ function updateSourceCharts() {
+ const filteredStats = getFilteredSatelliteData();
+
+ // Update source pie chart
+ if (sourcePieChart) {
+ const sourcePieLabels = filteredStats.map(s => s.parameter_obj__id_satellite__name);
+ const sourcePieData = filteredStats.map(s => s.sources_count);
+ const sourcePieColors = filteredStats.map((s, i) => colors[satelliteStats.indexOf(s) % colors.length]);
+
+ sourcePieChart.data.labels = sourcePieLabels;
+ sourcePieChart.data.datasets[0].data = sourcePieData;
+ sourcePieChart.data.datasets[0].backgroundColor = sourcePieColors;
+ sourcePieChart.update();
+ }
+
+ // Update source bar chart (limit to top 15 for readability)
+ if (sourceBarChart) {
+ const topSourceStats = filteredStats.slice(0, 15);
+ const sourceBarLabels = topSourceStats.map(s => s.parameter_obj__id_satellite__name);
+ const sourceBarData = topSourceStats.map(s => s.sources_count);
+ const sourceBarColors = topSourceStats.map((s, i) => colors[satelliteStats.indexOf(s) % colors.length]);
+
+ sourceBarChart.data.labels = sourceBarLabels;
+ sourceBarChart.data.datasets[0].data = sourceBarData;
+ sourceBarChart.data.datasets[0].backgroundColor = sourceBarColors;
+ sourceBarChart.update();
+ }
+ }
+
// Initialize satellite functionality
initSatelliteCheckboxes();
initSatelliteButtons();
initCharts();
+ initSourceCharts();
// Note: Zoom functionality temporarily disabled due to plugin loading issues
// Can be re-enabled when zoom plugin is properly configured
@@ -913,9 +1121,13 @@ document.addEventListener('DOMContentLoaded', function() {
'show-daily-chart': 'daily-chart-block',
'show-satellite-table': 'satellite-table-block',
- // Individual charts
+ // Satellite charts
'show-pie-chart': 'pie-chart-block',
- 'show-bar-chart': 'bar-chart-block'
+ 'show-bar-chart': 'bar-chart-block',
+
+ // Source object charts
+ 'show-source-pie-chart': 'source-pie-chart-block',
+ 'show-source-bar-chart': 'source-bar-chart-block'
};
// Load settings from localStorage
@@ -997,6 +1209,18 @@ document.addEventListener('DOMContentLoaded', function() {
satelliteChartsBlock.classList.add('hidden');
}
}
+
+ // Source charts block
+ const sourceChartsVisible = ['show-source-pie-chart', 'show-source-bar-chart']
+ .some(id => !document.getElementById(blockSettings[id])?.classList.contains('hidden'));
+ const sourceChartsBlock = document.getElementById('source-charts-block');
+ if (sourceChartsBlock) {
+ if (sourceChartsVisible) {
+ sourceChartsBlock.classList.remove('hidden');
+ } else {
+ sourceChartsBlock.classList.add('hidden');
+ }
+ }
}
// Initialize settings
@@ -1044,7 +1268,7 @@ document.addEventListener('DOMContentLoaded', function() {
if (selectChartsOnlyBtn) {
selectChartsOnlyBtn.addEventListener('click', function() {
- const chartKeys = ['show-daily-chart', 'show-satellite-table', 'show-pie-chart', 'show-bar-chart'];
+ const chartKeys = ['show-daily-chart', 'show-satellite-table', 'show-pie-chart', 'show-bar-chart', 'show-source-pie-chart', 'show-source-bar-chart'];
Object.keys(blockSettings).forEach(key => {
currentSettings[key] = chartKeys.includes(key);
});