1305 lines
56 KiB
HTML
1305 lines
56 KiB
HTML
{% extends 'mainapp/base.html' %}
|
||
{% load static %}
|
||
|
||
{% block title %}Статистика{% endblock %}
|
||
|
||
{% block extra_css %}
|
||
<link href="{% static 'css/checkbox-select-multiple.css' %}" rel="stylesheet">
|
||
<style>
|
||
.stat-card {
|
||
transition: transform 0.2s;
|
||
}
|
||
.stat-card:hover {
|
||
transform: translateY(-2px);
|
||
}
|
||
.stat-value {
|
||
font-size: 2.5rem;
|
||
font-weight: bold;
|
||
line-height: 1.2;
|
||
}
|
||
.stat-label {
|
||
font-size: 0.9rem;
|
||
color: #6c757d;
|
||
}
|
||
.satellite-stat-row:hover {
|
||
background-color: #f8f9fa;
|
||
}
|
||
.preset-btn.active {
|
||
background-color: #0d6efd;
|
||
color: white;
|
||
}
|
||
#dailyChart {
|
||
min-height: 300px;
|
||
}
|
||
.new-emission-badge {
|
||
font-size: 0.75rem;
|
||
margin: 2px;
|
||
}
|
||
|
||
/* Floating settings button */
|
||
.floating-settings {
|
||
position: fixed;
|
||
bottom: 20px;
|
||
right: 20px;
|
||
z-index: 1050;
|
||
opacity: 0.7;
|
||
transition: opacity 0.3s ease;
|
||
}
|
||
|
||
.floating-settings:hover {
|
||
opacity: 1;
|
||
}
|
||
|
||
.settings-btn {
|
||
width: 50px;
|
||
height: 50px;
|
||
border-radius: 50%;
|
||
background: #6c757d;
|
||
border: none;
|
||
color: white;
|
||
font-size: 18px;
|
||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.settings-btn:hover {
|
||
background: #5a6268;
|
||
transform: rotate(90deg);
|
||
box-shadow: 0 6px 20px rgba(0,0,0,0.25);
|
||
}
|
||
|
||
.settings-btn:focus {
|
||
box-shadow: 0 0 0 3px rgba(108, 117, 125, 0.25);
|
||
}
|
||
|
||
/* Block visibility classes */
|
||
.stats-block {
|
||
transition: opacity 0.3s ease, transform 0.3s ease;
|
||
}
|
||
|
||
.stats-block.hidden {
|
||
display: none !important;
|
||
}
|
||
|
||
/* Satellite selection styles */
|
||
.satellite-selection-container {
|
||
background-color: #f8f9fa;
|
||
}
|
||
|
||
.satellite-selection-container .form-check {
|
||
padding: 0.25rem 0.5rem;
|
||
margin: 0;
|
||
border-radius: 0.25rem;
|
||
transition: background-color 0.2s;
|
||
}
|
||
|
||
.satellite-selection-container .form-check:hover {
|
||
background-color: #e9ecef;
|
||
}
|
||
|
||
.satellite-selection-container .form-check-label {
|
||
font-size: 0.875rem;
|
||
cursor: pointer;
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
/* Chart zoom hint */
|
||
.card-body canvas {
|
||
cursor: grab;
|
||
}
|
||
|
||
.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;
|
||
}
|
||
</style>
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="container-fluid px-3">
|
||
<!-- Header -->
|
||
<div class="row mb-3">
|
||
<div class="col-12 d-flex justify-content-between align-items-center">
|
||
<h2><i class="bi bi-bar-chart-line"></i> Статистика</h2>
|
||
<a href="{% url 'mainapp:source_list' %}" class="btn btn-outline-secondary">
|
||
<i class="bi bi-arrow-left"></i> К списку объектов
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Filters -->
|
||
<div class="row mb-4">
|
||
<div class="col-12">
|
||
<div class="card">
|
||
<div class="card-body">
|
||
<form method="get" id="filter-form">
|
||
<div class="row g-3 align-items-end">
|
||
<!-- Date presets -->
|
||
<div class="col-auto">
|
||
<label class="form-label">Период:</label>
|
||
<div class="btn-group" role="group">
|
||
<button type="button" class="btn btn-outline-primary preset-btn {% if preset == 'week' %}active{% endif %}"
|
||
data-preset="week">Неделя</button>
|
||
<button type="button" class="btn btn-outline-primary preset-btn {% if preset == 'month' %}active{% endif %}"
|
||
data-preset="month">Месяц</button>
|
||
<button type="button" class="btn btn-outline-primary preset-btn {% if preset == '3months' %}active{% endif %}"
|
||
data-preset="3months">3 месяца</button>
|
||
<button type="button" class="btn btn-outline-primary preset-btn {% if preset == '6months' %}active{% endif %}"
|
||
data-preset="6months">Полгода</button>
|
||
<button type="button" class="btn btn-outline-primary preset-btn {% if preset == 'all' or not preset and not date_from %}active{% endif %}"
|
||
data-preset="all">Всё время</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Custom date range -->
|
||
<div class="col-auto">
|
||
<label for="date_from" class="form-label">С:</label>
|
||
<input type="date" class="form-control" id="date_from" name="date_from"
|
||
value="{{ date_from }}">
|
||
</div>
|
||
<div class="col-auto">
|
||
<label for="date_to" class="form-label">По:</label>
|
||
<input type="date" class="form-control" id="date_to" name="date_to"
|
||
value="{{ date_to }}">
|
||
</div>
|
||
|
||
<!-- Location Place filter -->
|
||
<div class="col-auto">
|
||
<label class="form-label">Комплекс:</label>
|
||
<select name="location_place" class="form-select" multiple size="2">
|
||
{% for value, label in location_places %}
|
||
<option value="{{ value }}" {% if value in selected_location_places %}selected{% endif %}>
|
||
{{ label }}
|
||
</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
|
||
<!-- Satellite filter with custom widget -->
|
||
<div class="col-md-3">
|
||
<label class="form-label">Спутники:</label>
|
||
<div class="checkbox-multiselect-wrapper" data-widget-id="satellite_id">
|
||
<div class="multiselect-input-container">
|
||
<div class="multiselect-tags" id="satellite_id_tags"></div>
|
||
<input type="text"
|
||
class="multiselect-search form-control"
|
||
placeholder="Выберите спутники..."
|
||
id="satellite_id_search"
|
||
autocomplete="off">
|
||
<button type="button" class="multiselect-clear" id="satellite_id_clear" title="Очистить все">×</button>
|
||
</div>
|
||
<div class="multiselect-dropdown" id="satellite_id_dropdown">
|
||
<div class="multiselect-options">
|
||
{% for satellite in satellites %}
|
||
<label class="multiselect-option">
|
||
<input type="checkbox"
|
||
name="satellite_id"
|
||
value="{{ satellite.id }}"
|
||
{% if satellite.id in selected_satellites %}checked{% endif %}
|
||
data-label="{{ satellite.name }}">
|
||
<span class="option-label">{{ satellite.name }}</span>
|
||
</label>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Submit -->
|
||
<div class="col-auto">
|
||
<button type="submit" class="btn btn-primary">
|
||
Применить
|
||
</button>
|
||
<a href="{% url 'mainapp:statistics' %}" class="btn btn-secondary">
|
||
Сбросить
|
||
</a>
|
||
</div>
|
||
</div>
|
||
<input type="hidden" name="preset" id="preset-input" value="{{ preset }}">
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Main Statistics Cards -->
|
||
<div class="row mb-4 stats-block" id="main-stats-block">
|
||
<!-- Total Points -->
|
||
<div class="col-md-4 stats-block" id="total-points-card">
|
||
<div class="card stat-card h-100 border-primary">
|
||
<div class="card-body text-center">
|
||
<div class="stat-value text-primary">{{ total_points }}</div>
|
||
<div class="stat-label">Точек геолокации</div>
|
||
<small class="text-muted">по {{ total_sources }} объектам</small>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- New Emissions -->
|
||
<div class="col-md-4 stats-block" id="new-emissions-card">
|
||
<div class="card stat-card h-100 border-success">
|
||
<div class="card-body text-center">
|
||
<div class="stat-value text-success">{{ new_emissions_count }}</div>
|
||
<div class="stat-label">Новых уникальных излучений</div>
|
||
<small class="text-muted">впервые появившихся за период</small>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Satellites Count -->
|
||
<div class="col-md-4 stats-block" id="satellites-count-card">
|
||
<div class="card stat-card h-100 border-info">
|
||
<div class="card-body text-center">
|
||
<div class="stat-value text-info">{{ satellite_stats|length }}</div>
|
||
<div class="stat-label">Спутников с данными</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- New Emissions Table -->
|
||
{% if new_emission_objects %}
|
||
<div class="row mb-4 stats-block" id="new-emissions-block">
|
||
<div class="col-12">
|
||
<div class="card">
|
||
<div class="card-header bg-light">
|
||
<i class="bi bi-stars"></i> Новые излучения (уникальные имена, появившиеся впервые в выбранном периоде)
|
||
</div>
|
||
<div class="card-body p-0">
|
||
<div class="table-responsive" style="max-height: 320px; overflow-y: auto;">
|
||
<table class="table table-sm table-hover table-striped mb-0">
|
||
<thead class="table-light sticky-top">
|
||
<tr>
|
||
<th style="width: 5%;" class="text-center">№</th>
|
||
<th style="width: 45%;">Имя объекта</th>
|
||
<th style="width: 25%;">Тип объекта</th>
|
||
<th style="width: 25%;">Принадлежность</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for obj in new_emission_objects %}
|
||
<tr>
|
||
<td class="text-center">{{ forloop.counter }}</td>
|
||
<td>{{ obj.name }}</td>
|
||
<td>{{ obj.info }}</td>
|
||
<td>{{ obj.ownership }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
|
||
<div class="row stats-block" id="charts-row-block">
|
||
<!-- Daily Chart -->
|
||
<div class="col-md-8 mb-4 stats-block" id="daily-chart-block">
|
||
<div class="card h-100">
|
||
<div class="card-header">
|
||
<i class="bi bi-graph-up"></i> Динамика по дням
|
||
</div>
|
||
<div class="card-body">
|
||
<canvas id="dailyChart"></canvas>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Satellite Statistics -->
|
||
<div class="col-md-4 mb-4 stats-block" id="satellite-table-block">
|
||
<div class="card h-100">
|
||
<div class="card-header">
|
||
<i class="bi bi-broadcast"></i> Статистика по спутникам
|
||
</div>
|
||
<div class="card-body p-0">
|
||
<div class="table-responsive" style="max-height: 400px; overflow-y: auto;">
|
||
<table class="table table-sm table-hover mb-0">
|
||
<thead class="table-light sticky-top">
|
||
<tr>
|
||
<th>Спутник</th>
|
||
<th class="text-center">Точек</th>
|
||
<th class="text-center">Объектов</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<!-- Total summary rows -->
|
||
<tr class="table-info">
|
||
<td class="text-left"><strong>Всего </strong></td>
|
||
<td class="text-center">
|
||
<span class="badge bg-warning text-dark fs-6">{{ total_points }}</span>
|
||
</td>
|
||
<td class="text-center">
|
||
<span class="badge bg-warning text-dark fs-6">{{ total_sources }}</span>
|
||
</td>
|
||
</tr>
|
||
<!-- Individual satellite stats -->
|
||
{% for stat in satellite_stats %}
|
||
<tr class="satellite-stat-row">
|
||
<td>{{ stat.parameter_obj__id_satellite__name }}</td>
|
||
<td class="text-center">
|
||
<span class="badge bg-primary">{{ stat.points_count }}</span>
|
||
</td>
|
||
<td class="text-center">
|
||
<span class="badge bg-secondary">{{ stat.sources_count }}</span>
|
||
</td>
|
||
</tr>
|
||
{% empty %}
|
||
<tr>
|
||
<td colspan="3" class="text-center text-muted">Нет данных</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Satellite Charts -->
|
||
<div class="row mb-4 stats-block" id="satellite-charts-block">
|
||
<div class="col-md-6 stats-block" id="pie-chart-block">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<i class="bi bi-pie-chart"></i> Распределение точек по спутникам
|
||
</div>
|
||
<div class="card-body">
|
||
<canvas id="satellitePieChart"></canvas>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6 stats-block" id="bar-chart-block">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<i class="bi bi-bar-chart"></i> Выбранные спутники по количеству точек
|
||
</div>
|
||
<div class="card-body">
|
||
<canvas id="satelliteBarChart"></canvas>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Source Objects Charts -->
|
||
<div class="row mb-4 stats-block" id="source-charts-block">
|
||
<div class="col-md-6 stats-block" id="source-pie-chart-block">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<i class="bi bi-pie-chart"></i> Распределение объектов по спутникам
|
||
</div>
|
||
<div class="card-body">
|
||
<canvas id="sourcePieChart"></canvas>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6 stats-block" id="source-bar-chart-block">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<i class="bi bi-bar-chart"></i> Выбранные спутники по количеству объектов
|
||
</div>
|
||
<div class="card-body">
|
||
<canvas id="sourceBarChart"></canvas>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Floating Settings Button -->
|
||
<div class="floating-settings">
|
||
<button type="button" class="btn settings-btn" data-bs-toggle="modal" data-bs-target="#settingsModal" title="Настройки отображения">
|
||
<i class="bi bi-gear"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Settings Modal -->
|
||
<div class="modal fade" id="settingsModal" tabindex="-1" aria-labelledby="settingsModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog modal-dialog-centered">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="settingsModalLabel">
|
||
<i class="bi bi-gear"></i> Настройки отображения
|
||
</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p class="text-muted mb-3">Выберите элементы для отображения на странице:</p>
|
||
|
||
<!-- Main Statistics Section -->
|
||
<div class="mb-4">
|
||
<h6 class="text-primary mb-2">
|
||
<i class="bi bi-bar-chart-line"></i> Основная статистика
|
||
</h6>
|
||
<div class="ps-3">
|
||
<div class="form-check mb-2">
|
||
<input class="form-check-input" type="checkbox" id="show-total-points" checked>
|
||
<label class="form-check-label" for="show-total-points">
|
||
<i class="bi bi-geo-alt text-primary"></i>
|
||
Карточка "Точки геолокации"
|
||
</label>
|
||
</div>
|
||
<div class="form-check mb-2">
|
||
<input class="form-check-input" type="checkbox" id="show-new-emissions-card" checked>
|
||
<label class="form-check-label" for="show-new-emissions-card">
|
||
<i class="bi bi-star text-success"></i>
|
||
Карточка "Новые излучения"
|
||
</label>
|
||
</div>
|
||
<div class="form-check mb-2">
|
||
<input class="form-check-input" type="checkbox" id="show-satellites-count" checked>
|
||
<label class="form-check-label" for="show-satellites-count">
|
||
<i class="bi bi-broadcast text-info"></i>
|
||
Карточка "Спутники с данными"
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- New Emissions Table -->
|
||
{% if new_emission_objects %}
|
||
<div class="mb-4">
|
||
<div class="form-check">
|
||
<input class="form-check-input" type="checkbox" id="show-new-emissions-table" checked>
|
||
<label class="form-check-label" for="show-new-emissions-table">
|
||
<i class="bi bi-stars text-success"></i>
|
||
<strong>Таблица новых излучений</strong>
|
||
<small class="d-block text-muted">Детальная таблица новых уникальных излучений</small>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
|
||
<!-- Charts Section -->
|
||
<div class="mb-4">
|
||
<h6 class="text-info mb-2">
|
||
<i class="bi bi-graph-up"></i> Графики и диаграммы
|
||
</h6>
|
||
<div class="ps-3">
|
||
<div class="form-check mb-2">
|
||
<input class="form-check-input" type="checkbox" id="show-daily-chart" checked>
|
||
<label class="form-check-label" for="show-daily-chart">
|
||
<i class="bi bi-graph-up text-info"></i>
|
||
График динамики по дням
|
||
</label>
|
||
</div>
|
||
<div class="form-check mb-2">
|
||
<input class="form-check-input" type="checkbox" id="show-satellite-table" checked>
|
||
<label class="form-check-label" for="show-satellite-table">
|
||
<i class="bi bi-table text-warning"></i>
|
||
Таблица статистики по спутникам
|
||
</label>
|
||
</div>
|
||
<div class="form-check mb-2">
|
||
<input class="form-check-input" type="checkbox" id="show-pie-chart" checked>
|
||
<label class="form-check-label" for="show-pie-chart">
|
||
<i class="bi bi-pie-chart text-danger"></i>
|
||
Круговая диаграмма распределения
|
||
</label>
|
||
</div>
|
||
<div class="form-check mb-2">
|
||
<input class="form-check-input" type="checkbox" id="show-bar-chart" checked>
|
||
<label class="form-check-label" for="show-bar-chart">
|
||
<i class="bi bi-bar-chart text-secondary"></i>
|
||
Столбчатая диаграмма точек по спутникам
|
||
</label>
|
||
</div>
|
||
<div class="form-check mb-2">
|
||
<input class="form-check-input" type="checkbox" id="show-source-pie-chart" checked>
|
||
<label class="form-check-label" for="show-source-pie-chart">
|
||
<i class="bi bi-pie-chart text-success"></i>
|
||
Круговая диаграмма объектов по спутникам
|
||
</label>
|
||
</div>
|
||
<div class="form-check mb-2">
|
||
<input class="form-check-input" type="checkbox" id="show-source-bar-chart" checked>
|
||
<label class="form-check-label" for="show-source-bar-chart">
|
||
<i class="bi bi-bar-chart text-warning"></i>
|
||
Столбчатая диаграмма объектов по спутникам
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Satellite Selection for Charts -->
|
||
<div class="mb-4">
|
||
<h6 class="text-warning mb-2">
|
||
<i class="bi bi-broadcast"></i> Спутники для диаграмм
|
||
</h6>
|
||
<div class="ps-3">
|
||
<div class="mb-3">
|
||
<div class="btn-group w-100 mb-2" role="group">
|
||
<button type="button" class="btn btn-outline-success btn-sm" id="select-all-satellites">
|
||
<i class="bi bi-check-all"></i> Все спутники
|
||
</button>
|
||
<button type="button" class="btn btn-outline-warning btn-sm" id="select-top10-satellites">
|
||
<i class="bi bi-trophy"></i> Топ-10
|
||
</button>
|
||
<button type="button" class="btn btn-outline-danger btn-sm" id="clear-satellites">
|
||
<i class="bi bi-x-circle"></i> Очистить
|
||
</button>
|
||
</div>
|
||
<div class="satellite-selection-container" style="max-height: 200px; overflow-y: auto; border: 1px solid #dee2e6; border-radius: 0.375rem; padding: 1.4rem;">
|
||
<div id="satellite-checkboxes">
|
||
<!-- Будет заполнено JavaScript -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Quick Actions -->
|
||
<div class="mb-3">
|
||
<h6 class="text-secondary mb-2">
|
||
<i class="bi bi-lightning"></i> Быстрые действия
|
||
</h6>
|
||
<div class="btn-group w-100" role="group">
|
||
<button type="button" class="btn btn-outline-success btn-sm" id="select-all">
|
||
<i class="bi bi-check-all"></i> Все
|
||
</button>
|
||
<button type="button" class="btn btn-outline-warning btn-sm" id="select-cards-only">
|
||
<i class="bi bi-card-text"></i> Только карточки
|
||
</button>
|
||
<button type="button" class="btn btn-outline-info btn-sm" id="select-charts-only">
|
||
<i class="bi bi-graph-up"></i> Только графики
|
||
</button>
|
||
<button type="button" class="btn btn-outline-danger btn-sm" id="select-none">
|
||
<i class="bi bi-x-circle"></i> Ничего
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-outline-secondary" id="reset-settings">
|
||
<i class="bi bi-arrow-clockwise"></i> Сбросить
|
||
</button>
|
||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">
|
||
<i class="bi bi-check-lg"></i> Применить
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block extra_js %}
|
||
<!-- <script type="module" src="{% static 'chartjs/color.esm.js' %}"></script> -->
|
||
<script src="{% static 'chartjs/chart.js' %}"></script>
|
||
<script src="{% static 'chartjs/chart-datalabels.js' %}"></script>
|
||
<script src="{% static 'js/checkbox-select-multiple.js' %}"></script>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
// Initialize multiselect widget
|
||
const wrapper = document.querySelector('.checkbox-multiselect-wrapper[data-widget-id="satellite_id"]');
|
||
if (wrapper) {
|
||
initCheckboxMultiselect(wrapper);
|
||
}
|
||
|
||
// Preset buttons handling
|
||
const presetBtns = document.querySelectorAll('.preset-btn');
|
||
const presetInput = document.getElementById('preset-input');
|
||
const dateFromInput = document.getElementById('date_from');
|
||
const dateToInput = document.getElementById('date_to');
|
||
|
||
presetBtns.forEach(btn => {
|
||
btn.addEventListener('click', function() {
|
||
presetBtns.forEach(b => b.classList.remove('active'));
|
||
this.classList.add('active');
|
||
presetInput.value = this.dataset.preset;
|
||
|
||
// Clear custom dates when using preset
|
||
dateFromInput.value = '';
|
||
dateToInput.value = '';
|
||
|
||
// Submit form
|
||
document.getElementById('filter-form').submit();
|
||
});
|
||
});
|
||
|
||
// Clear preset when custom dates are entered
|
||
dateFromInput.addEventListener('change', function() {
|
||
presetInput.value = '';
|
||
presetBtns.forEach(b => b.classList.remove('active'));
|
||
});
|
||
dateToInput.addEventListener('change', function() {
|
||
presetInput.value = '';
|
||
presetBtns.forEach(b => b.classList.remove('active'));
|
||
});
|
||
|
||
// Register plugins
|
||
Chart.register(ChartDataLabels);
|
||
|
||
// Daily Chart with zoom
|
||
const dailyData = {{ daily_data|safe }};
|
||
const dailyLabels = dailyData.map(d => {
|
||
if (d.date) {
|
||
const date = new Date(d.date);
|
||
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 '';
|
||
});
|
||
const dailyPoints = dailyData.map(d => d.points);
|
||
const dailySources = dailyData.map(d => d.sources);
|
||
|
||
let dailyChart = null;
|
||
if (dailyData.length > 0) {
|
||
dailyChart = new Chart(document.getElementById('dailyChart'), {
|
||
type: 'line',
|
||
data: {
|
||
labels: dailyLabels,
|
||
datasets: [{
|
||
label: 'Точки ГЛ',
|
||
data: dailyPoints,
|
||
borderColor: 'rgb(13, 110, 253)',
|
||
backgroundColor: 'rgba(13, 110, 253, 0.1)',
|
||
fill: false,
|
||
// tension: 0.3
|
||
}, {
|
||
label: 'Объекты',
|
||
data: dailySources,
|
||
borderColor: 'rgb(25, 135, 84)',
|
||
backgroundColor: 'rgba(25, 135, 84, 0.1)',
|
||
fill: false,
|
||
// tension: 0.3
|
||
}]
|
||
},
|
||
options: {
|
||
responsive: true,
|
||
maintainAspectRatio: false,
|
||
interaction: {
|
||
intersect: false,
|
||
mode: 'index'
|
||
},
|
||
plugins: {
|
||
legend: {
|
||
position: 'top',
|
||
},
|
||
datalabels: {
|
||
display: false
|
||
}
|
||
},
|
||
scales: {
|
||
y: {
|
||
beginAtZero: true
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// Satellite Statistics with selection
|
||
const satelliteStats = {{ satellite_stats_json|safe }};
|
||
const satelliteSettingsKey = 'statistics_satellite_selection';
|
||
|
||
const colors = [
|
||
'#0d6efd', '#198754', '#dc3545', '#ffc107', '#0dcaf0',
|
||
'#6f42c1', '#fd7e14', '#20c997', '#6c757d', '#d63384', '#adb5bd'
|
||
];
|
||
|
||
let pieChart = null;
|
||
let barChart = null;
|
||
|
||
// Load satellite selection settings
|
||
function loadSatelliteSettings() {
|
||
const saved = localStorage.getItem(satelliteSettingsKey);
|
||
if (saved) {
|
||
try {
|
||
return JSON.parse(saved);
|
||
} catch (e) {
|
||
console.warn('Failed to parse satellite settings:', e);
|
||
}
|
||
}
|
||
// Default: all satellites selected
|
||
return satelliteStats.reduce((acc, stat) => {
|
||
acc[stat.parameter_obj__id_satellite__name] = true;
|
||
return acc;
|
||
}, {});
|
||
}
|
||
|
||
// Save satellite selection settings
|
||
function saveSatelliteSettings(settings) {
|
||
localStorage.setItem(satelliteSettingsKey, JSON.stringify(settings));
|
||
}
|
||
|
||
// Initialize satellite checkboxes
|
||
function initSatelliteCheckboxes() {
|
||
const container = document.getElementById('satellite-checkboxes');
|
||
const settings = loadSatelliteSettings();
|
||
|
||
container.innerHTML = '';
|
||
satelliteStats.forEach((stat, index) => {
|
||
const satelliteName = stat.parameter_obj__id_satellite__name;
|
||
const isChecked = settings[satelliteName] !== false;
|
||
|
||
const checkboxHtml = `
|
||
<div class="form-check mb-1">
|
||
<input class="form-check-input satellite-checkbox" type="checkbox"
|
||
id="sat-${index}" value="${satelliteName}" ${isChecked ? 'checked' : ''}>
|
||
<label class="form-check-label" for="sat-${index}">
|
||
<span class="badge" style="background-color: ${colors[index % colors.length]}; width: 12px; height: 12px; display: inline-block; margin-right: 5px;"></span>
|
||
${satelliteName} (${stat.points_count})
|
||
</label>
|
||
</div>
|
||
`;
|
||
container.insertAdjacentHTML('beforeend', checkboxHtml);
|
||
});
|
||
|
||
// Add event listeners
|
||
container.querySelectorAll('.satellite-checkbox').forEach(checkbox => {
|
||
checkbox.addEventListener('change', function() {
|
||
const settings = loadSatelliteSettings();
|
||
settings[this.value] = this.checked;
|
||
saveSatelliteSettings(settings);
|
||
updateCharts();
|
||
});
|
||
});
|
||
}
|
||
|
||
// Get filtered satellite data based on selection
|
||
function getFilteredSatelliteData() {
|
||
const settings = loadSatelliteSettings();
|
||
return satelliteStats.filter(stat => settings[stat.parameter_obj__id_satellite__name] !== false);
|
||
}
|
||
|
||
// Update charts based on satellite selection
|
||
function updateCharts() {
|
||
const filteredStats = getFilteredSatelliteData();
|
||
|
||
// Update pie chart
|
||
if (pieChart) {
|
||
const pieLabels = filteredStats.map(s => s.parameter_obj__id_satellite__name);
|
||
const pieData = filteredStats.map(s => s.points_count);
|
||
const pieColors = filteredStats.map((s, i) => colors[satelliteStats.indexOf(s) % colors.length]);
|
||
|
||
pieChart.data.labels = pieLabels;
|
||
pieChart.data.datasets[0].data = pieData;
|
||
pieChart.data.datasets[0].backgroundColor = pieColors;
|
||
pieChart.update();
|
||
}
|
||
|
||
// Update bar chart (limit to top 15 for readability)
|
||
if (barChart) {
|
||
const topStats = filteredStats.slice(0, 15);
|
||
const barLabels = topStats.map(s => s.parameter_obj__id_satellite__name);
|
||
const barData = topStats.map(s => s.points_count);
|
||
const barColors = topStats.map((s, i) => colors[satelliteStats.indexOf(s) % colors.length]);
|
||
|
||
barChart.data.labels = barLabels;
|
||
barChart.data.datasets[0].data = barData;
|
||
barChart.data.datasets[0].backgroundColor = barColors;
|
||
barChart.update();
|
||
}
|
||
|
||
// Update source charts
|
||
updateSourceCharts();
|
||
}
|
||
|
||
// Initialize charts
|
||
function initCharts() {
|
||
const filteredStats = getFilteredSatelliteData();
|
||
|
||
// Pie Chart
|
||
if (filteredStats.length > 0) {
|
||
const pieLabels = filteredStats.map(s => s.parameter_obj__id_satellite__name);
|
||
const pieData = filteredStats.map(s => s.points_count);
|
||
const pieColors = filteredStats.map((s, i) => colors[satelliteStats.indexOf(s) % colors.length]);
|
||
|
||
pieChart = new Chart(document.getElementById('satellitePieChart'), {
|
||
type: 'doughnut',
|
||
data: {
|
||
labels: pieLabels,
|
||
datasets: [{
|
||
data: pieData,
|
||
backgroundColor: pieColors
|
||
}]
|
||
},
|
||
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'
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// Bar Chart (top 15)
|
||
if (filteredStats.length > 0) {
|
||
const topStats = filteredStats.slice(0, 15);
|
||
const barLabels = topStats.map(s => s.parameter_obj__id_satellite__name);
|
||
const barData = topStats.map(s => s.points_count);
|
||
const barColors = topStats.map((s, i) => colors[satelliteStats.indexOf(s) % colors.length]);
|
||
|
||
barChart = new Chart(document.getElementById('satelliteBarChart'), {
|
||
type: 'bar',
|
||
data: {
|
||
labels: barLabels,
|
||
datasets: [{
|
||
label: 'Количество точек',
|
||
data: barData,
|
||
backgroundColor: barColors
|
||
}]
|
||
},
|
||
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%'
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
// Satellite selection buttons
|
||
function initSatelliteButtons() {
|
||
const selectAllSatBtn = document.getElementById('select-all-satellites');
|
||
const selectTop10Btn = document.getElementById('select-top10-satellites');
|
||
const clearSatBtn = document.getElementById('clear-satellites');
|
||
|
||
if (selectAllSatBtn) {
|
||
selectAllSatBtn.addEventListener('click', function() {
|
||
const settings = {};
|
||
satelliteStats.forEach(stat => {
|
||
settings[stat.parameter_obj__id_satellite__name] = true;
|
||
});
|
||
saveSatelliteSettings(settings);
|
||
initSatelliteCheckboxes();
|
||
updateCharts();
|
||
});
|
||
}
|
||
|
||
if (selectTop10Btn) {
|
||
selectTop10Btn.addEventListener('click', function() {
|
||
const settings = {};
|
||
satelliteStats.forEach((stat, index) => {
|
||
settings[stat.parameter_obj__id_satellite__name] = index < 10;
|
||
});
|
||
saveSatelliteSettings(settings);
|
||
initSatelliteCheckboxes();
|
||
updateCharts();
|
||
});
|
||
}
|
||
|
||
if (clearSatBtn) {
|
||
clearSatBtn.addEventListener('click', function() {
|
||
const settings = {};
|
||
satelliteStats.forEach(stat => {
|
||
settings[stat.parameter_obj__id_satellite__name] = false;
|
||
});
|
||
saveSatelliteSettings(settings);
|
||
initSatelliteCheckboxes();
|
||
updateCharts();
|
||
});
|
||
}
|
||
}
|
||
|
||
// 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
|
||
|
||
// Settings functionality
|
||
const settingsKey = 'statistics_display_settings_detailed';
|
||
|
||
// Detailed block visibility mapping
|
||
const blockSettings = {
|
||
// Main statistics cards
|
||
'show-total-points': 'total-points-card',
|
||
'show-new-emissions-card': 'new-emissions-card',
|
||
'show-satellites-count': 'satellites-count-card',
|
||
|
||
// Tables and detailed views
|
||
'show-new-emissions-table': 'new-emissions-block',
|
||
'show-daily-chart': 'daily-chart-block',
|
||
'show-satellite-table': 'satellite-table-block',
|
||
|
||
// Satellite charts
|
||
'show-pie-chart': 'pie-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
|
||
function loadSettings() {
|
||
const saved = localStorage.getItem(settingsKey);
|
||
if (saved) {
|
||
try {
|
||
return JSON.parse(saved);
|
||
} catch (e) {
|
||
console.warn('Failed to parse settings:', e);
|
||
}
|
||
}
|
||
// Default: all visible
|
||
return Object.keys(blockSettings).reduce((acc, key) => {
|
||
acc[key] = true;
|
||
return acc;
|
||
}, {});
|
||
}
|
||
|
||
// Save settings to localStorage
|
||
function saveSettings(settings) {
|
||
localStorage.setItem(settingsKey, JSON.stringify(settings));
|
||
}
|
||
|
||
// Apply visibility settings
|
||
function applySettings(settings) {
|
||
Object.entries(blockSettings).forEach(([checkboxId, blockId]) => {
|
||
const checkbox = document.getElementById(checkboxId);
|
||
const block = document.getElementById(blockId);
|
||
|
||
if (checkbox && block) {
|
||
checkbox.checked = settings[checkboxId] !== false;
|
||
if (settings[checkboxId] === false) {
|
||
block.classList.add('hidden');
|
||
} else {
|
||
block.classList.remove('hidden');
|
||
}
|
||
}
|
||
});
|
||
|
||
// Handle parent containers visibility
|
||
updateParentContainers();
|
||
}
|
||
|
||
// Update parent container visibility based on children
|
||
function updateParentContainers() {
|
||
// Main stats block
|
||
const mainStatsVisible = ['show-total-points', 'show-new-emissions-card', 'show-satellites-count']
|
||
.some(id => !document.getElementById(blockSettings[id])?.classList.contains('hidden'));
|
||
const mainStatsBlock = document.getElementById('main-stats-block');
|
||
if (mainStatsBlock) {
|
||
if (mainStatsVisible) {
|
||
mainStatsBlock.classList.remove('hidden');
|
||
} else {
|
||
mainStatsBlock.classList.add('hidden');
|
||
}
|
||
}
|
||
|
||
// Charts row block
|
||
const chartsRowVisible = ['show-daily-chart', 'show-satellite-table']
|
||
.some(id => !document.getElementById(blockSettings[id])?.classList.contains('hidden'));
|
||
const chartsRowBlock = document.getElementById('charts-row-block');
|
||
if (chartsRowBlock) {
|
||
if (chartsRowVisible) {
|
||
chartsRowBlock.classList.remove('hidden');
|
||
} else {
|
||
chartsRowBlock.classList.add('hidden');
|
||
}
|
||
}
|
||
|
||
// Satellite charts block
|
||
const satelliteChartsVisible = ['show-pie-chart', 'show-bar-chart']
|
||
.some(id => !document.getElementById(blockSettings[id])?.classList.contains('hidden'));
|
||
const satelliteChartsBlock = document.getElementById('satellite-charts-block');
|
||
if (satelliteChartsBlock) {
|
||
if (satelliteChartsVisible) {
|
||
satelliteChartsBlock.classList.remove('hidden');
|
||
} else {
|
||
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
|
||
let currentSettings = loadSettings();
|
||
applySettings(currentSettings);
|
||
|
||
// Handle checkbox changes
|
||
Object.keys(blockSettings).forEach(checkboxId => {
|
||
const checkbox = document.getElementById(checkboxId);
|
||
if (checkbox) {
|
||
checkbox.addEventListener('change', function() {
|
||
currentSettings[checkboxId] = this.checked;
|
||
saveSettings(currentSettings);
|
||
applySettings(currentSettings);
|
||
});
|
||
}
|
||
});
|
||
|
||
// Quick action buttons
|
||
const selectAllBtn = document.getElementById('select-all');
|
||
const selectCardsOnlyBtn = document.getElementById('select-cards-only');
|
||
const selectChartsOnlyBtn = document.getElementById('select-charts-only');
|
||
const selectNoneBtn = document.getElementById('select-none');
|
||
|
||
if (selectAllBtn) {
|
||
selectAllBtn.addEventListener('click', function() {
|
||
Object.keys(blockSettings).forEach(key => {
|
||
currentSettings[key] = true;
|
||
});
|
||
saveSettings(currentSettings);
|
||
applySettings(currentSettings);
|
||
});
|
||
}
|
||
|
||
if (selectCardsOnlyBtn) {
|
||
selectCardsOnlyBtn.addEventListener('click', function() {
|
||
const cardKeys = ['show-total-points', 'show-new-emissions-card', 'show-satellites-count'];
|
||
Object.keys(blockSettings).forEach(key => {
|
||
currentSettings[key] = cardKeys.includes(key);
|
||
});
|
||
saveSettings(currentSettings);
|
||
applySettings(currentSettings);
|
||
});
|
||
}
|
||
|
||
if (selectChartsOnlyBtn) {
|
||
selectChartsOnlyBtn.addEventListener('click', function() {
|
||
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);
|
||
});
|
||
saveSettings(currentSettings);
|
||
applySettings(currentSettings);
|
||
});
|
||
}
|
||
|
||
if (selectNoneBtn) {
|
||
selectNoneBtn.addEventListener('click', function() {
|
||
Object.keys(blockSettings).forEach(key => {
|
||
currentSettings[key] = false;
|
||
});
|
||
saveSettings(currentSettings);
|
||
applySettings(currentSettings);
|
||
});
|
||
}
|
||
|
||
// Reset settings button
|
||
const resetBtn = document.getElementById('reset-settings');
|
||
if (resetBtn) {
|
||
resetBtn.addEventListener('click', function() {
|
||
currentSettings = Object.keys(blockSettings).reduce((acc, key) => {
|
||
acc[key] = true;
|
||
return acc;
|
||
}, {});
|
||
saveSettings(currentSettings);
|
||
applySettings(currentSettings);
|
||
});
|
||
}
|
||
});
|
||
</script>
|
||
{% endblock %}
|