Добавил форму с предосмотром и редактированием
This commit is contained in:
25
dbapp/mainapp/templates/mainapp/objitem_confirm_delete.html
Normal file
25
dbapp/mainapp/templates/mainapp/objitem_confirm_delete.html
Normal file
@@ -0,0 +1,25 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Удалить объект{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid px-3">
|
||||
<div class="row mb-3">
|
||||
<div class="col-12">
|
||||
<h2>Удалить объект "{{ object }}"?</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<p>Вы уверены, что хотите удалить этот объект? Это действие нельзя будет отменить.</p>
|
||||
<div class="d-flex justify-content-end">
|
||||
<button type="submit" class="btn btn-danger">Удалить</button>
|
||||
<a href="{% url 'home' %}" class="btn btn-secondary ms-2">Отмена</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
513
dbapp/mainapp/templates/mainapp/objitem_form.html
Normal file
513
dbapp/mainapp/templates/mainapp/objitem_form.html
Normal file
@@ -0,0 +1,513 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
{% load static %}
|
||||
{% load static leaflet_tags %}
|
||||
|
||||
{% block title %}{% if object %}Редактировать объект: {{ object.name }}{% else %}Создать объект{% endif %}{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<style>
|
||||
.form-section { margin-bottom: 2rem; border: 1px solid #dee2e6; border-radius: 0.25rem; padding: 1rem; }
|
||||
.form-section-header { border-bottom: 1px solid #dee2e6; padding-bottom: 0.5rem; margin-bottom: 1rem; }
|
||||
.btn-action { margin-right: 0.5rem; }
|
||||
.dynamic-form { border: 1px dashed #ced4da; padding: 1rem; margin-top: 1rem; border-radius: 0.25rem; }
|
||||
.dynamic-form-header { display: flex; justify-content: space-between; align-items: center; }
|
||||
.readonly-field { background-color: #f8f9fa; padding: 0.375rem 0.75rem; border: 1px solid #ced4da; border-radius: 0.25rem; }
|
||||
.coord-group { border: 1px solid #dee2e6; padding: 0.75rem; border-radius: 0.25rem; margin-bottom: 1rem; }
|
||||
.coord-group-header { font-weight: bold; margin-bottom: 0.5rem; }
|
||||
.form-check-input { margin-top: 0.25rem; }
|
||||
.datetime-group { display: flex; gap: 1rem; }
|
||||
.datetime-group > div { flex: 1; }
|
||||
#map { height: 500px; width: 100%; margin-bottom: 1rem; }
|
||||
.map-container { margin-bottom: 1rem; }
|
||||
.coord-sync-group { border: 1px solid #dee2e6; padding: 0.75rem; border-radius: 0.25rem; }
|
||||
.map-controls {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 1rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.map-control-btn {
|
||||
padding: 0.375rem 0.75rem;
|
||||
border: 1px solid #ced4da;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 0.25rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.map-control-btn.active {
|
||||
background-color: #e9ecef;
|
||||
border-color: #dee2e6;
|
||||
}
|
||||
.map-control-btn.edit {
|
||||
background-color: #fff3cd;
|
||||
border-color: #ffeeba;
|
||||
}
|
||||
.map-control-btn.save {
|
||||
background-color: #d1ecf1;
|
||||
border-color: #bee5eb;
|
||||
}
|
||||
.map-control-btn.cancel {
|
||||
background-color: #f8d7da;
|
||||
border-color: #f5c6cb;
|
||||
}
|
||||
.leaflet-marker-icon {
|
||||
filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.3));
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid px-3">
|
||||
<div class="row mb-3">
|
||||
<div class="col-12 d-flex justify-content-between align-items-center">
|
||||
<h2>{% if object %}Редактировать объект: {{ object.name }}{% else %}Создать объект{% endif %}</h2>
|
||||
<div>
|
||||
<a href="{% url 'home' %}" class="btn btn-secondary btn-action">Назад</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
<!-- Основная информация -->
|
||||
<div class="form-section">
|
||||
<div class="form-section-header">
|
||||
<h4>Основная информация</h4>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.name.id_for_label }}" class="form-label">Имя объекта:</label>
|
||||
{{ form.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Дата создания:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.created_at %}{{ object.created_at|date:"d.m.Y H:i" }}{% else %}-{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Создан пользователем:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.created_by %}{{ object.created_by }}{% else %}-{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Дата последнего изменения:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.updated_at %}{{ object.updated_at|date:"d.m.Y H:i" }}{% else %}-{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Изменен пользователем:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.updated_by %}{{ object.updated_by }}{% else %}-{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ВЧ загрузки -->
|
||||
<div class="form-section">
|
||||
<div class="form-section-header d-flex justify-content-between align-items-center">
|
||||
<h4>ВЧ загрузки</h4>
|
||||
{% if not parameter_forms.forms.0.instance.pk %}
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" id="add-parameter">Добавить ВЧ загрузку</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div id="parameters-container">
|
||||
{% for param_form in parameter_forms %}
|
||||
<div class="dynamic-form" data-parameter-index="{{ forloop.counter0 }}">
|
||||
<div class="dynamic-form-header">
|
||||
<h5>ВЧ загрузка #{{ forloop.counter }}</h5>
|
||||
{% if parameter_forms.forms|length > 1 %}
|
||||
<button type="button" class="btn btn-sm btn-outline-danger remove-parameter">Удалить</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label for="{{ param_form.id_satellite.id_for_label }}" class="form-label">Спутник:</label>
|
||||
{{ param_form.id_satellite }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label for="{{ param_form.frequency.id_for_label }}" class="form-label">Частота, МГц:</label>
|
||||
{{ param_form.frequency }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label for="{{ param_form.freq_range.id_for_label }}" class="form-label">Полоса, МГц:</label>
|
||||
{{ param_form.freq_range }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label for="{{ param_form.polarization.id_for_label }}" class="form-label">Поляризация:</label>
|
||||
{{ param_form.polarization }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label for="{{ param_form.bod_velocity.id_for_label }}" class="form-label">Симв. скорость, БОД:</label>
|
||||
{{ param_form.bod_velocity }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label for="{{ param_form.modulation.id_for_label }}" class="form-label">Модуляция:</label>
|
||||
{{ param_form.modulation }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label for="{{ param_form.snr.id_for_label }}" class="form-label">ОСШ:</label>
|
||||
{{ param_form.snr }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label for="{{ param_form.standard.id_for_label }}" class="form-label">Стандарт:</label>
|
||||
{{ param_form.standard }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Блок с картой -->
|
||||
<div class="form-section">
|
||||
<div class="form-section-header">
|
||||
<h4>Карта</h4>
|
||||
</div>
|
||||
<div class="map-container">
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Геоданные -->
|
||||
<div class="form-section">
|
||||
<div class="form-section-header">
|
||||
<h4>Геоданные</h4>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Координаты геолокации -->
|
||||
<div class="coord-sync-group">
|
||||
<div class="coord-group-header">Координаты геолокации</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="id_geo_latitude" class="form-label">Широта:</label>
|
||||
<input type="number" step="0.000001" class="form-control"
|
||||
id="id_geo_latitude" name="geo_latitude"
|
||||
value="{% if object.geo_obj and object.geo_obj.coords %}{{ object.geo_obj.coords.y }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="id_geo_longitude" class="form-label">Долгота:</label>
|
||||
<input type="number" step="0.000001" class="form-control"
|
||||
id="id_geo_longitude" name="geo_longitude"
|
||||
value="{% if object.geo_obj and object.geo_obj.coords %}{{ object.geo_obj.coords.x }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Координаты Кубсата -->
|
||||
<div class="coord-group">
|
||||
<div class="coord-group-header">Координаты Кубсата</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="id_kupsat_longitude" class="form-label">Долгота:</label>
|
||||
<input type="number" step="0.000001" class="form-control"
|
||||
id="id_kupsat_longitude" name="kupsat_longitude"
|
||||
value="{% if object.geo_obj and object.geo_obj.coords_kupsat %}{{ object.geo_obj.coords_kupsat.x }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="id_kupsat_latitude" class="form-label">Широта:</label>
|
||||
<input type="number" step="0.000001" class="form-control"
|
||||
id="id_kupsat_latitude" name="kupsat_latitude"
|
||||
value="{% if object.geo_obj and object.geo_obj.coords_kupsat %}{{ object.geo_obj.coords_kupsat.y }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Координаты оперативников -->
|
||||
<div class="coord-group">
|
||||
<div class="coord-group-header">Координаты оперативников</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="id_valid_longitude" class="form-label">Долгота:</label>
|
||||
<input type="number" step="0.000001" class="form-control"
|
||||
id="id_valid_longitude" name="valid_longitude"
|
||||
value="{% if object.geo_obj and object.geo_obj.coords_valid %}{{ object.geo_obj.coords_valid.x }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="id_valid_latitude" class="form-label">Широта:</label>
|
||||
<input type="number" step="0.000001" class="form-control"
|
||||
id="id_valid_latitude" name="valid_latitude"
|
||||
value="{% if object.geo_obj and object.geo_obj.coords_valid %}{{ object.geo_obj.coords_valid.y }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="{{ geo_form.location.id_for_label }}" class="form-label">Местоположение:</label>
|
||||
{{ geo_form.location }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="{{ geo_form.comment.id_for_label }}" class="form-label">Комментарий:</label>
|
||||
{{ geo_form.comment }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Дата и время:</label>
|
||||
<div class="datetime-group">
|
||||
<div>
|
||||
<label for="id_timestamp_date" class="form-label">Дата:</label>
|
||||
<input type="date" class="form-control"
|
||||
id="id_timestamp_date" name="timestamp_date"
|
||||
value="{% if object.geo_obj and object.geo_obj.timestamp %}{{ object.geo_obj.timestamp|date:'Y-m-d' }}{% endif %}">
|
||||
</div>
|
||||
<div>
|
||||
<label for="id_timestamp_time" class="form-label">Время:</label>
|
||||
<input type="time" class="form-control"
|
||||
id="id_timestamp_time" name="timestamp_time"
|
||||
value="{% if object.geo_obj and object.geo_obj.timestamp %}{{ object.geo_obj.timestamp|time:'H:i' }}{% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label for="{{ geo_form.is_average.id_for_label }}" class="form-check-label">Усреднённое:</label>
|
||||
{{ geo_form.is_average }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if object.geo_obj %}
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Расстояние гео-кубсат, км:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.geo_obj.distance_coords_kup is not None %}
|
||||
{{ object.geo_obj.distance_coords_kup|floatformat:2 }}
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Расстояние гео-опер, км:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.geo_obj.distance_coords_valid is not None %}
|
||||
{{ object.geo_obj.distance_coords_valid|floatformat:2 }}
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Расстояние кубсат-опер, км:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.geo_obj.distance_kup_valid is not None %}
|
||||
{{ object.geo_obj.distance_kup_valid|floatformat:2 }}
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end mt-4">
|
||||
<button type="submit" class="btn btn-primary btn-action">Сохранить</button>
|
||||
{% if object %}
|
||||
<a href="{% url 'objitem_delete' object.id %}" class="btn btn-danger btn-action">Удалить</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
{{ block.super }}
|
||||
<!-- Подключаем Leaflet и его плагины -->
|
||||
{% leaflet_js %}
|
||||
{% leaflet_css %}
|
||||
|
||||
|
||||
<script>
|
||||
// Динамическое добавление ВЧ загрузок
|
||||
let parameterIndex = {{ parameter_forms|length }};
|
||||
|
||||
document.getElementById('add-parameter')?.addEventListener('click', function() {
|
||||
const container = document.getElementById('parameters-container');
|
||||
const template = document.querySelector('.dynamic-form');
|
||||
|
||||
if (template) {
|
||||
const clone = template.cloneNode(true);
|
||||
clone.querySelectorAll('[id]').forEach(el => {
|
||||
el.id = el.id.replace(/-\d+-/g, `-${parameterIndex}-`);
|
||||
});
|
||||
clone.querySelectorAll('[name]').forEach(el => {
|
||||
el.name = el.name.replace(/-\d+-/g, `-${parameterIndex}-`);
|
||||
});
|
||||
clone.querySelectorAll('[for]').forEach(el => {
|
||||
el.htmlFor = el.htmlFor.replace(/-\d+-/g, `-${parameterIndex}-`);
|
||||
});
|
||||
clone.querySelector('.dynamic-form-header h5').textContent = `ВЧ загрузка #${parameterIndex + 1}`;
|
||||
clone.dataset.parameterIndex = parameterIndex;
|
||||
container.appendChild(clone);
|
||||
parameterIndex++;
|
||||
}
|
||||
});
|
||||
|
||||
// Удаление ВЧ загрузок
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target.classList.contains('remove-parameter')) {
|
||||
if (document.querySelectorAll('.dynamic-form').length > 1) {
|
||||
e.target.closest('.dynamic-form').remove();
|
||||
} else {
|
||||
alert('Должна быть хотя бы одна ВЧ загрузка');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Инициализация карты
|
||||
const map = L.map('map').setView([55.75, 37.62], 5);
|
||||
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}).addTo(map);
|
||||
|
||||
// Маркеры для разных типов координат
|
||||
const markers = {
|
||||
geo: L.marker([55.75, 37.62], { draggable: true, color: 'blue' }).addTo(map),
|
||||
kupsat: L.marker([55.75, 37.61], { draggable: true, color: 'red' }).addTo(map),
|
||||
valid: L.marker([55.75, 37.63], { draggable: true, color: 'green' }).addTo(map)
|
||||
};
|
||||
|
||||
// Устанавливаем начальные координаты из полей формы
|
||||
function initMarkersFromForm() {
|
||||
const geoLat = parseFloat(document.getElementById('id_geo_latitude').value) || 55.75;
|
||||
const geoLng = parseFloat(document.getElementById('id_geo_longitude').value) || 37.62;
|
||||
markers.geo.setLatLng([geoLat, geoLng]);
|
||||
|
||||
const kupsatLat = parseFloat(document.getElementById('id_kupsat_latitude').value) || 55.75;
|
||||
const kupsatLng = parseFloat(document.getElementById('id_kupsat_longitude').value) || 37.61;
|
||||
markers.kupsat.setLatLng([kupsatLat, kupsatLng]);
|
||||
|
||||
const validLat = parseFloat(document.getElementById('id_valid_latitude').value) || 55.75;
|
||||
const validLng = parseFloat(document.getElementById('id_valid_longitude').value) || 37.63;
|
||||
markers.valid.setLatLng([validLat, validLng]);
|
||||
|
||||
// Центрируем карту на первом маркере
|
||||
map.setView(markers.geo.getLatLng(), 10);
|
||||
}
|
||||
|
||||
// Обновляем координаты в форме при перетаскивании маркеров
|
||||
function setupMarkerDrag(marker, latFieldId, lngFieldId, color) {
|
||||
marker.on('dragend', function(event) {
|
||||
const latLng = event.target.getLatLng();
|
||||
document.getElementById(latFieldId).value = latLng.lat.toFixed(6);
|
||||
document.getElementById(lngFieldId).value = latLng.lng.toFixed(6);
|
||||
});
|
||||
}
|
||||
|
||||
// Обновляем положение маркера при изменении координат в форме
|
||||
function setupFormChange(latFieldId, lngFieldId, marker) {
|
||||
const latField = document.getElementById(latFieldId);
|
||||
const lngField = document.getElementById(lngFieldId);
|
||||
|
||||
[latField, lngField].forEach(field => {
|
||||
field.addEventListener('change', function() {
|
||||
const lat = parseFloat(latField.value);
|
||||
const lng = parseFloat(lngField.value);
|
||||
|
||||
if (!isNaN(lat) && !isNaN(lng)) {
|
||||
marker.setLatLng([lat, lng]);
|
||||
map.setView(marker.getLatLng(), 10);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Инициализация
|
||||
initMarkersFromForm();
|
||||
|
||||
// Настройка маркеров
|
||||
setupMarkerDrag(markers.geo, 'id_geo_latitude', 'id_geo_longitude', 'blue');
|
||||
setupMarkerDrag(markers.kupsat, 'id_kupsat_latitude', 'id_kupsat_longitude', 'red');
|
||||
setupMarkerDrag(markers.valid, 'id_valid_latitude', 'id_valid_longitude', 'green');
|
||||
|
||||
// Настройка формы
|
||||
setupFormChange('id_geo_latitude', 'id_geo_longitude', markers.geo);
|
||||
setupFormChange('id_kupsat_latitude', 'id_kupsat_longitude', markers.kupsat);
|
||||
setupFormChange('id_valid_latitude', 'id_valid_longitude', markers.valid);
|
||||
|
||||
// Легенда
|
||||
const legend = L.control({ position: 'bottomright' });
|
||||
|
||||
legend.onAdd = function() {
|
||||
const div = L.DomUtil.create('div', 'info legend');
|
||||
div.innerHTML = `
|
||||
<h6>Легенда</h6>
|
||||
<div><span style="color: blue; font-weight: bold;">•</span> Геолокация</div>
|
||||
<div><span style="color: red; font-weight: bold;">•</span> Кубсат</div>
|
||||
<div><span style="color: green; font-weight: bold;">•</span> Оперативники</div>
|
||||
`;
|
||||
return div;
|
||||
};
|
||||
|
||||
legend.addTo(map);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -50,6 +50,116 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Column visibility toggle button -->
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle" id="columnVisibilityDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="bi bi-gear"></i> Колонки
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="columnVisibilityDropdown" style="z-index: 1050;">
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" id="select-all-columns" checked onchange="toggleAllColumns(this)"> Выбрать всё
|
||||
</label>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="0" checked onchange="toggleColumn(this)"> Выбрать
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="1" checked onchange="toggleColumn(this)"> Имя
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="2" checked onchange="toggleColumn(this)"> Спутник
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="3" checked onchange="toggleColumn(this)"> Част, МГц
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="4" checked onchange="toggleColumn(this)"> Полоса, МГц
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="5" checked onchange="toggleColumn(this)"> Поляризация
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="6" checked onchange="toggleColumn(this)"> Сим. V
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="7" checked onchange="toggleColumn(this)"> Модул
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="8" checked onchange="toggleColumn(this)"> ОСШ
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="9" checked onchange="toggleColumn(this)"> Геолокация
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="10" checked onchange="toggleColumn(this)"> Кубсат
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="11" checked onchange="toggleColumn(this)"> Опер. отд
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="12" checked onchange="toggleColumn(this)"> Гео-куб, км
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="13" checked onchange="toggleColumn(this)"> Гео-опер, км
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="14" checked onchange="toggleColumn(this)"> Куб-опер, км
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="15" checked onchange="toggleColumn(this)"> Обновлено
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="16" checked onchange="toggleColumn(this)"> Кем (обновление)
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="17" checked onchange="toggleColumn(this)"> Создано
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="18" checked onchange="toggleColumn(this)"> Кем (создание)
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Pagination moved here -->
|
||||
<div class="ms-auto">
|
||||
{% if page_obj.paginator.num_pages > 1 %}
|
||||
@@ -260,6 +370,8 @@
|
||||
<th scope="col">Куб-опер, км</th>
|
||||
<th scope="col">Обновлено</th>
|
||||
<th scope="col">Кем</th>
|
||||
<th scope="col">Создано</th>
|
||||
<th scope="col">Кем (создание)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -268,7 +380,7 @@
|
||||
<td class="text-center">
|
||||
<input type="checkbox" class="form-check-input item-checkbox" value="{{ item.id }}">
|
||||
</td>
|
||||
<td>{{ item.name }}</td>
|
||||
<td><a href="{% if item.obj.id %}{% url 'objitem_update' item.obj.id %}{% endif %}">{{ item.name }}</a></td>
|
||||
<td>{{ item.satellite_name }}</td>
|
||||
<td>{{ item.frequency }}</td>
|
||||
<td>{{ item.freq_range }}</td>
|
||||
@@ -283,11 +395,13 @@
|
||||
<td>{{ item.distance_geo_valid }}</td>
|
||||
<td>{{ item.distance_kup_valid }}</td>
|
||||
<td>{{ item.obj.updated_at|date:"d.m.Y H:i" }}</td>
|
||||
<td>{{ item.obj.updated_by }}</td>
|
||||
<td>{{ item.updated_by }}</td>
|
||||
<td>{{ item.obj.created_at|date:"d.m.Y H:i" }}</td>
|
||||
<td>{{ item.obj.created_by }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="17" class="text-center py-4">
|
||||
<td colspan="19" class="text-center py-4">
|
||||
{% if selected_satellite_id %}
|
||||
Нет данных для выбранных фильтров
|
||||
{% else %}
|
||||
@@ -307,6 +421,30 @@
|
||||
|
||||
<!-- JavaScript for checkbox functionality and filters -->
|
||||
<script>
|
||||
function toggleColumn(checkbox) {
|
||||
const columnIndex = parseInt(checkbox.getAttribute('data-column'));
|
||||
const table = document.querySelector('.table');
|
||||
const cells = table.querySelectorAll(`td:nth-child(${columnIndex + 1}), th:nth-child(${columnIndex + 1})`);
|
||||
|
||||
if (checkbox.checked) {
|
||||
cells.forEach(cell => {
|
||||
cell.style.display = '';
|
||||
});
|
||||
} else {
|
||||
cells.forEach(cell => {
|
||||
cell.style.display = 'none';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function toggleAllColumns(selectAllCheckbox) {
|
||||
const columnCheckboxes = document.querySelectorAll('.column-toggle');
|
||||
columnCheckboxes.forEach(checkbox => {
|
||||
checkbox.checked = selectAllCheckbox.checked;
|
||||
toggleColumn(checkbox);
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Select/Deselect all checkboxes
|
||||
const selectAllCheckbox = document.getElementById('select-all');
|
||||
@@ -451,6 +589,25 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
// Update URL and reload
|
||||
window.location.search = currentParams.toString();
|
||||
};
|
||||
|
||||
// Initialize column visibility - hide creation columns by default
|
||||
function initColumnVisibility() {
|
||||
const creationDateCheckbox = document.querySelector('input[data-column="17"]');
|
||||
const creationUserCheckbox = document.querySelector('input[data-column="18"]');
|
||||
|
||||
if (creationDateCheckbox) {
|
||||
creationDateCheckbox.checked = false; // Uncheck to hide by default
|
||||
toggleColumn(creationDateCheckbox);
|
||||
}
|
||||
|
||||
if (creationUserCheckbox) {
|
||||
creationUserCheckbox.checked = false; // Uncheck to hide by default
|
||||
toggleColumn(creationUserCheckbox);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize column visibility after page loads
|
||||
setTimeout(initColumnVisibility, 100); // Slight delay to ensure DOM is fully loaded
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user