Доделал страницу со всеми объектами
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="{% static 'favicon.ico' %}" type="image/x-icon">
|
||||
<title>{% block title %}Геолокация{% endblock %}</title>
|
||||
|
||||
<link href="{% static 'bootstrap-icons/bootstrap-icons.css' %}" rel="stylesheet">
|
||||
<link href="{% static 'bootstrap/bootstrap.min.css' %}" rel="stylesheet">
|
||||
|
||||
<!-- Дополнительные стили (если нужно) -->
|
||||
|
||||
@@ -381,6 +381,7 @@
|
||||
<!-- Подключаем Leaflet и его плагины -->
|
||||
{% leaflet_js %}
|
||||
{% leaflet_css %}
|
||||
<script src="{% static 'leaflet-markers/js/leaflet-color-markers.js' %}"></script>
|
||||
|
||||
|
||||
<script>
|
||||
@@ -428,13 +429,94 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
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)
|
||||
// Определяем цвета для маркеров
|
||||
const colors = {
|
||||
geo: 'blue',
|
||||
kupsat: 'red',
|
||||
valid: 'green'
|
||||
};
|
||||
|
||||
// Функция для создания иконки маркера
|
||||
function createMarkerIcon(color) {
|
||||
return L.icon({
|
||||
iconUrl: '{% static "leaflet-markers/img/marker-icon-" %}' + color + '.png',
|
||||
shadowUrl: `{% static 'leaflet-markers/img/marker-shadow.png' %}`,
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41],
|
||||
popupAnchor: [1, -34],
|
||||
shadowSize: [41, 41]
|
||||
});
|
||||
}
|
||||
const editableLayerGroup = new L.FeatureGroup();
|
||||
map.addLayer(editableLayerGroup);
|
||||
|
||||
// Маркеры
|
||||
const markers = {};
|
||||
function createMarker(latFieldId, lngFieldId, position, color, name) {
|
||||
const marker = L.marker(position, {
|
||||
draggable: false,
|
||||
icon: createMarkerIcon(color),
|
||||
title: name
|
||||
}).addTo(editableLayerGroup);
|
||||
marker.bindPopup(name);
|
||||
|
||||
// Синхронизация при изменении формы
|
||||
function syncFromForm() {
|
||||
const lat = parseFloat(document.getElementById(latFieldId).value);
|
||||
const lng = parseFloat(document.getElementById(lngFieldId).value);
|
||||
if (!isNaN(lat) && !isNaN(lng)) {
|
||||
marker.setLatLng([lat, lng]);
|
||||
}
|
||||
}
|
||||
|
||||
// Синхронизация при перетаскивании (только если активировано)
|
||||
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);
|
||||
});
|
||||
|
||||
// Добавляем методы для управления
|
||||
marker.enableEditing = function() {
|
||||
this.dragging.enable();
|
||||
this.openPopup();
|
||||
};
|
||||
|
||||
marker.disableEditing = function() {
|
||||
this.dragging.disable();
|
||||
this.closePopup();
|
||||
};
|
||||
|
||||
marker.syncFromForm = syncFromForm;
|
||||
|
||||
return marker;
|
||||
}
|
||||
|
||||
// Создаем маркеры
|
||||
markers.geo = createMarker(
|
||||
'id_geo_latitude',
|
||||
'id_geo_longitude',
|
||||
[55.75, 37.62],
|
||||
colors.geo,
|
||||
'Геолокация'
|
||||
);
|
||||
|
||||
markers.kupsat = createMarker(
|
||||
'id_kupsat_latitude',
|
||||
'id_kupsat_longitude',
|
||||
[55.75, 37.61],
|
||||
colors.kupsat,
|
||||
'Кубсат'
|
||||
);
|
||||
|
||||
markers.valid = createMarker(
|
||||
'id_valid_latitude',
|
||||
'id_valid_longitude',
|
||||
[55.75, 37.63],
|
||||
colors.valid,
|
||||
'Оперативник'
|
||||
);
|
||||
|
||||
// Устанавливаем начальные координаты из полей формы
|
||||
function initMarkersFromForm() {
|
||||
const geoLat = parseFloat(document.getElementById('id_geo_latitude').value) || 55.75;
|
||||
@@ -453,16 +535,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
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);
|
||||
@@ -482,24 +555,126 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// Инициализация
|
||||
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 editControlsDiv = L.DomUtil.create('div', 'map-controls');
|
||||
editControlsDiv.style.position = 'absolute';
|
||||
editControlsDiv.style.top = '10px';
|
||||
editControlsDiv.style.right = '10px';
|
||||
editControlsDiv.style.zIndex = '1000';
|
||||
editControlsDiv.style.background = 'white';
|
||||
editControlsDiv.style.padding = '10px';
|
||||
editControlsDiv.style.borderRadius = '4px';
|
||||
editControlsDiv.style.boxShadow = '0 0 10px rgba(0,0,0,0.2)';
|
||||
editControlsDiv.innerHTML = `
|
||||
<div class="map-controls">
|
||||
<button type="button" id="edit-btn" class="map-control-btn edit">Редактировать</button>
|
||||
<button type="button" id="save-btn" class="map-control-btn save" disabled>Сохранить</button>
|
||||
<button type="button" id="cancel-btn" class="map-control-btn cancel" disabled>Отмена</button>
|
||||
</div>
|
||||
`;
|
||||
map.getContainer().appendChild(editControlsDiv);
|
||||
|
||||
let isEditing = false;
|
||||
|
||||
// Сохраняем начальные координаты для отмены
|
||||
const initialPositions = {
|
||||
geo: markers.geo.getLatLng(),
|
||||
kupsat: markers.kupsat.getLatLng(),
|
||||
valid: markers.valid.getLatLng()
|
||||
};
|
||||
|
||||
// Включение редактирования
|
||||
document.getElementById('edit-btn').addEventListener('click', function() {
|
||||
if (isEditing) return;
|
||||
|
||||
isEditing = true;
|
||||
document.getElementById('edit-btn').classList.add('active');
|
||||
document.getElementById('save-btn').disabled = false;
|
||||
document.getElementById('cancel-btn').disabled = false;
|
||||
|
||||
// Включаем drag для всех маркеров
|
||||
Object.values(markers).forEach(marker => {
|
||||
marker.enableEditing();
|
||||
});
|
||||
|
||||
// Показываем подсказку
|
||||
L.popup()
|
||||
.setLatLng(map.getCenter())
|
||||
.setContent('Перетаскивайте маркеры. Нажмите "Сохранить" или "Отмена".')
|
||||
.openOn(map);
|
||||
});
|
||||
|
||||
// Сохранение изменений
|
||||
document.getElementById('save-btn').addEventListener('click', function() {
|
||||
if (!isEditing) return;
|
||||
|
||||
isEditing = false;
|
||||
document.getElementById('edit-btn').classList.remove('active');
|
||||
document.getElementById('save-btn').disabled = true;
|
||||
document.getElementById('cancel-btn').disabled = true;
|
||||
|
||||
// Отключаем редактирование
|
||||
Object.values(markers).forEach(marker => {
|
||||
marker.disableEditing();
|
||||
});
|
||||
|
||||
// Обновляем начальные позиции
|
||||
initialPositions.geo = markers.geo.getLatLng();
|
||||
initialPositions.kupsat = markers.kupsat.getLatLng();
|
||||
initialPositions.valid = markers.valid.getLatLng();
|
||||
|
||||
// Убираем попап подсказки
|
||||
map.closePopup();
|
||||
});
|
||||
|
||||
// Отмена изменений
|
||||
document.getElementById('cancel-btn').addEventListener('click', function() {
|
||||
if (!isEditing) return;
|
||||
|
||||
isEditing = false;
|
||||
document.getElementById('edit-btn').classList.remove('active');
|
||||
document.getElementById('save-btn').disabled = true;
|
||||
document.getElementById('cancel-btn').disabled = true;
|
||||
|
||||
// Возвращаем маркеры на исходные позиции
|
||||
markers.geo.setLatLng(initialPositions.geo);
|
||||
markers.kupsat.setLatLng(initialPositions.kupsat);
|
||||
markers.valid.setLatLng(initialPositions.valid);
|
||||
|
||||
// Отключаем редактирование
|
||||
Object.values(markers).forEach(marker => {
|
||||
marker.disableEditing();
|
||||
});
|
||||
|
||||
// Синхронизируем форму с исходными значениями
|
||||
document.getElementById('id_geo_latitude').value = initialPositions.geo.lat.toFixed(6);
|
||||
document.getElementById('id_geo_longitude').value = initialPositions.geo.lng.toFixed(6);
|
||||
|
||||
document.getElementById('id_kupsat_latitude').value = initialPositions.kupsat.lat.toFixed(6);
|
||||
document.getElementById('id_kupsat_longitude').value = initialPositions.kupsat.lng.toFixed(6);
|
||||
|
||||
document.getElementById('id_valid_latitude').value = initialPositions.valid.lat.toFixed(6);
|
||||
document.getElementById('id_valid_longitude').value = initialPositions.valid.lng.toFixed(6);
|
||||
map.closePopup();
|
||||
});
|
||||
|
||||
// Легенда
|
||||
const legend = L.control({ position: 'bottomright' });
|
||||
|
||||
legend.onAdd = function() {
|
||||
const div = L.DomUtil.create('div', 'info legend');
|
||||
div.style.fontSize = '14px';
|
||||
div.style.backgroundColor = 'white';
|
||||
div.style.padding = '10px';
|
||||
div.style.borderRadius = '4px';
|
||||
div.style.boxShadow = '0 0 10px rgba(0,0,0,0.2)';
|
||||
div.innerHTML = `
|
||||
<h6>Легенда</h6>
|
||||
<h5>Легенда</h5>
|
||||
<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>
|
||||
@@ -510,4 +685,4 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
legend.addTo(map);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
@@ -109,52 +109,57 @@
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="9" checked onchange="toggleColumn(this)"> Геолокация
|
||||
<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)"> Кубсат
|
||||
<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)"> Опер. отд
|
||||
<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)"> Гео-куб, км
|
||||
<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)"> Гео-опер, км
|
||||
<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)"> Куб-опер, км
|
||||
<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)"> Обновлено
|
||||
<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)"> Кем (обновление)
|
||||
<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)"> Создано
|
||||
<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)"> Кем (создание)
|
||||
<input type="checkbox" class="column-toggle" data-column="18" checked onchange="toggleColumn(this)"> Создано
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="19" checked onchange="toggleColumn(this)"> Кем (создание)
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -354,24 +359,118 @@
|
||||
<th scope="col" class="text-center" style="width: 3%;">
|
||||
<input type="checkbox" id="select-all" class="form-check-input">
|
||||
</th>
|
||||
<th scope="col">Имя</th>
|
||||
<th scope="col">Спутник</th>
|
||||
<th scope="col">Част, МГц</th>
|
||||
<th scope="col">Полоса, МГц</th>
|
||||
<th scope="col">Поляризация</th>
|
||||
<th scope="col">Сим. V</th>
|
||||
<th scope="col">Модул</th>
|
||||
<th scope="col">ОСШ</th>
|
||||
|
||||
<!-- Столбец "Имя" -->
|
||||
<th scope="col">
|
||||
<a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}sort={% if sort == 'name' %}-name{% elif sort == '-name' %}name{% else %}name{% endif %}" class="text-white text-decoration-none d-inline-flex align-items-center">
|
||||
Имя
|
||||
{% if sort == 'name' %} <i class="bi bi-sort-up ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% elif sort == '-name' %} <i class="bi bi-sort-down ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% else %} <i class="bi bi-arrow-down-up ms-1"></i> {% endif %}
|
||||
</a>
|
||||
</th>
|
||||
|
||||
<!-- Столбец "Спутник" -->
|
||||
<th scope="col">
|
||||
<a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}sort={% if sort == 'satellite' %}-satellite{% elif sort == '-satellite' %}satellite{% else %}satellite{% endif %}" class="text-white text-decoration-none d-inline-flex align-items-center">
|
||||
Спутник
|
||||
{% if sort == 'satellite' %} <i class="bi bi-sort-up ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% elif sort == '-satellite' %} <i class="bi bi-sort-down ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% else %} <i class="bi bi-arrow-down-up ms-1"></i> {% endif %}
|
||||
</a>
|
||||
</th>
|
||||
|
||||
<!-- Столбец "Част, МГц" -->
|
||||
<th scope="col">
|
||||
<a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}sort={% if sort == 'frequency' %}-frequency{% elif sort == '-frequency' %}frequency{% else %}frequency{% endif %}" class="text-white text-decoration-none d-inline-flex align-items-center">
|
||||
Част, МГц
|
||||
{% if sort == 'frequency' %} <i class="bi bi-sort-up ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% elif sort == '-frequency' %} <i class="bi bi-sort-down ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% else %} <i class="bi bi-arrow-down-up ms-1"></i> {% endif %}
|
||||
</a>
|
||||
</th>
|
||||
|
||||
<!-- Столбец "Полоса, МГц" -->
|
||||
<th scope="col">
|
||||
<a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}sort={% if sort == 'freq_range' %}-freq_range{% elif sort == '-freq_range' %}freq_range{% else %}freq_range{% endif %}" class="text-white text-decoration-none d-inline-flex align-items-center">
|
||||
Полоса, МГц
|
||||
{% if sort == 'freq_range' %} <i class="bi bi-sort-up ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% elif sort == '-freq_range' %} <i class="bi bi-sort-down ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% else %} <i class="bi bi-arrow-down-up ms-1"></i> {% endif %}
|
||||
</a>
|
||||
</th>
|
||||
|
||||
<!-- Столбец "Поляризация" -->
|
||||
<th scope="col">
|
||||
<a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}sort={% if sort == 'polarization' %}-polarization{% elif sort == '-polarization' %}polarization{% else %}polarization{% endif %}" class="text-white text-decoration-none d-inline-flex align-items-center">
|
||||
Поляризация
|
||||
{% if sort == 'polarization' %} <i class="bi bi-sort-up ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% elif sort == '-polarization' %} <i class="bi bi-sort-down ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% else %} <i class="bi bi-arrow-down-up ms-1"></i> {% endif %}
|
||||
</a>
|
||||
</th>
|
||||
|
||||
<!-- Столбец "Сим. V" -->
|
||||
<th scope="col">
|
||||
<a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}sort={% if sort == 'bod_velocity' %}-bod_velocity{% elif sort == '-bod_velocity' %}bod_velocity{% else %}bod_velocity{% endif %}" class="text-white text-decoration-none d-inline-flex align-items-center">
|
||||
Сим. V
|
||||
{% if sort == 'bod_velocity' %} <i class="bi bi-sort-up ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% elif sort == '-bod_velocity' %} <i class="bi bi-sort-down ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% else %} <i class="bi bi-arrow-down-up ms-1"></i> {% endif %}
|
||||
</a>
|
||||
</th>
|
||||
|
||||
<!-- Столбец "Модул" -->
|
||||
<th scope="col">
|
||||
<a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}sort={% if sort == 'modulation' %}-modulation{% elif sort == '-modulation' %}modulation{% else %}modulation{% endif %}" class="text-white text-decoration-none d-inline-flex align-items-center">
|
||||
Модул
|
||||
{% if sort == 'modulation' %} <i class="bi bi-sort-up ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% elif sort == '-modulation' %} <i class="bi bi-sort-down ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% else %} <i class="bi bi-arrow-down-up ms-1"></i> {% endif %}
|
||||
</a>
|
||||
</th>
|
||||
|
||||
<!-- Столбец "ОСШ" -->
|
||||
<th scope="col">
|
||||
<a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}sort={% if sort == 'snr' %}-snr{% elif sort == '-snr' %}snr{% else %}snr{% endif %}" class="text-white text-decoration-none d-inline-flex align-items-center">
|
||||
ОСШ
|
||||
{% if sort == 'snr' %} <i class="bi bi-sort-up ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% elif sort == '-snr' %} <i class="bi bi-sort-down ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% else %} <i class="bi bi-arrow-down-up ms-1"></i> {% endif %}
|
||||
</a>
|
||||
</th>
|
||||
|
||||
<!-- Столбец "Время ГЛ" -->
|
||||
<th scope="col">
|
||||
<a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}sort={% if sort == 'geo_timestamp' %}-geo_timestamp{% elif sort == '-geo_timestamp' %}geo_timestamp{% else %}geo_timestamp{% endif %}" class="text-white text-decoration-none d-inline-flex align-items-center">
|
||||
Время ГЛ
|
||||
{% if sort == 'geo_timestamp' %} <i class="bi bi-sort-up ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% elif sort == '-geo_timestamp' %} <i class="bi bi-sort-down ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% else %} <i class="bi bi-arrow-down-up ms-1"></i> {% endif %}
|
||||
</a>
|
||||
</th>
|
||||
|
||||
<!-- Столбец "Геолокация" - без сортировки -->
|
||||
<th scope="col">Геолокация</th>
|
||||
|
||||
<!-- Столбец "Кубсат" - без сортировки -->
|
||||
<th scope="col">Кубсат</th>
|
||||
|
||||
<!-- Столбец "Опер. отд" - без сортировки -->
|
||||
<th scope="col">Опер. отд</th>
|
||||
|
||||
<!-- Столбец "Гео-куб, км" - без сортировки -->
|
||||
<th scope="col">Гео-куб, км</th>
|
||||
|
||||
<!-- Столбец "Гео-опер, км" - без сортировки -->
|
||||
<th scope="col">Гео-опер, км</th>
|
||||
|
||||
<!-- Столбец "Куб-опер, км" - без сортировки -->
|
||||
<th scope="col">Куб-опер, км</th>
|
||||
<th scope="col">Обновлено</th>
|
||||
<th scope="col">Кем</th>
|
||||
<th scope="col">Создано</th>
|
||||
<th scope="col">Кем (создание)</th>
|
||||
|
||||
<!-- Столбец "Обновлено" -->
|
||||
<th scope="col">
|
||||
<a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}sort={% if sort == 'updated_at' %}-updated_at{% elif sort == '-updated_at' %}updated_at{% else %}updated_at{% endif %}" class="text-white text-decoration-none d-inline-flex align-items-center">
|
||||
Обновлено
|
||||
{% if sort == 'updated_at' %} <i class="bi bi-sort-up ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% elif sort == '-updated_at' %} <i class="bi bi-sort-down ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% else %} <i class="bi bi-arrow-down-up ms-1"></i> {% endif %}
|
||||
</a>
|
||||
</th>
|
||||
|
||||
<!-- Столбец "Кем (обновление)" - без сортировки -->
|
||||
<th scope="col">Кем(обн)</th>
|
||||
|
||||
<!-- Столбец "Создано" -->
|
||||
<th scope="col">
|
||||
<a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}sort={% if sort == 'created_at' %}-created_at{% elif sort == '-created_at' %}created_at{% else %}created_at{% endif %}" class="text-white text-decoration-none d-inline-flex align-items-center">
|
||||
Создано
|
||||
{% if sort == 'created_at' %} <i class="bi bi-sort-up ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% elif sort == '-created_at' %} <i class="bi bi-sort-down ms-1"></i> <a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}" class="text-white ms-1"><i class="bi bi-x-lg"></i></a> {% else %} <i class="bi bi-arrow-down-up ms-1"></i> {% endif %}
|
||||
</a>
|
||||
</th>
|
||||
|
||||
<!-- Столбец "Кем (создание)" - без сортировки -->
|
||||
<th scope="col">Кем(созд)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -388,6 +487,7 @@
|
||||
<td>{{ item.bod_velocity }}</td>
|
||||
<td>{{ item.modulation }}</td>
|
||||
<td>{{ item.snr }}</td>
|
||||
<td>{{ item.geo_timestamp|date:"d.m.Y H:i" }}</td>
|
||||
<td>{{ item.geo_coords }}</td>
|
||||
<td>{{ item.kupsat_coords }}</td>
|
||||
<td>{{ item.valid_coords }}</td>
|
||||
@@ -419,7 +519,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- JavaScript for checkbox functionality and filters -->
|
||||
|
||||
<script>
|
||||
function toggleColumn(checkbox) {
|
||||
const columnIndex = parseInt(checkbox.getAttribute('data-column'));
|
||||
@@ -446,7 +546,6 @@ function toggleAllColumns(selectAllCheckbox) {
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Select/Deselect all checkboxes
|
||||
const selectAllCheckbox = document.getElementById('select-all');
|
||||
const itemCheckboxes = document.querySelectorAll('.item-checkbox');
|
||||
|
||||
@@ -457,7 +556,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
});
|
||||
});
|
||||
|
||||
// Update select all checkbox state based on individual selections
|
||||
itemCheckboxes.forEach(checkbox => {
|
||||
checkbox.addEventListener('change', function() {
|
||||
const allChecked = Array.from(itemCheckboxes).every(cb => cb.checked);
|
||||
@@ -592,16 +690,28 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// 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"]');
|
||||
const creationDateCheckbox = document.querySelector('input[data-column="18"]');
|
||||
const creationUserCheckbox = document.querySelector('input[data-column="19"]');
|
||||
const creationDistanceGOpCheckbox = document.querySelector('input[data-column="14"]');
|
||||
const creationDistanceKubOpCheckbox = document.querySelector('input[data-column="15"]');
|
||||
|
||||
if (creationDistanceGOpCheckbox) {
|
||||
creationDistanceGOpCheckbox.checked = false;
|
||||
toggleColumn(creationDistanceGOpCheckbox);
|
||||
}
|
||||
|
||||
if (creationDistanceKubOpCheckbox) {
|
||||
creationDistanceKubOpCheckbox.checked = false;
|
||||
toggleColumn(creationDistanceKubOpCheckbox);
|
||||
}
|
||||
|
||||
if (creationDateCheckbox) {
|
||||
creationDateCheckbox.checked = false; // Uncheck to hide by default
|
||||
creationDateCheckbox.checked = false;
|
||||
toggleColumn(creationDateCheckbox);
|
||||
}
|
||||
|
||||
if (creationUserCheckbox) {
|
||||
creationUserCheckbox.checked = false; // Uncheck to hide by default
|
||||
creationUserCheckbox.checked = false;
|
||||
toggleColumn(creationUserCheckbox);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ from django.contrib.admin.views.decorators import staff_member_required
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views import View
|
||||
from django.db.models import OuterRef, Subquery
|
||||
from django.views.generic import TemplateView, FormView, UpdateView, DeleteView, CreateView
|
||||
from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin
|
||||
from django.contrib.auth import logout
|
||||
@@ -34,7 +35,7 @@ from .forms import (
|
||||
ParameterForm,
|
||||
GeoForm
|
||||
)
|
||||
from .models import ObjItem
|
||||
from .models import ObjItem, Modulation, Polarization
|
||||
from .clusters import get_clusters
|
||||
from io import BytesIO
|
||||
from datetime import datetime
|
||||
@@ -320,13 +321,12 @@ from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
class ObjItemListView(LoginRequiredMixin, View):
|
||||
def get(self, request):
|
||||
satellites = Satellite.objects.filter(parameters__objitems__isnull=False).distinct().order_by('name')
|
||||
|
||||
# Get selected satellite from query parameters
|
||||
|
||||
selected_sat_id = request.GET.get('satellite_id')
|
||||
page_number = request.GET.get('page', 1)
|
||||
items_per_page = request.GET.get('items_per_page', '50')
|
||||
|
||||
# Get filter parameters
|
||||
sort_param = request.GET.get('sort', '')
|
||||
|
||||
freq_min = request.GET.get('freq_min')
|
||||
freq_max = request.GET.get('freq_max')
|
||||
range_min = request.GET.get('range_min')
|
||||
@@ -341,28 +341,23 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
selected_satellites = request.GET.getlist('satellite_id')
|
||||
has_kupsat = request.GET.get('has_kupsat')
|
||||
has_valid = request.GET.get('has_valid')
|
||||
|
||||
|
||||
try:
|
||||
items_per_page = int(items_per_page)
|
||||
except ValueError:
|
||||
items_per_page = 50
|
||||
|
||||
# Only filter objects by selected satellite if provided (no data shown by default)
|
||||
objects = ObjItem.objects.none() # Initially empty
|
||||
|
||||
|
||||
objects = ObjItem.objects.none()
|
||||
|
||||
if selected_satellites or selected_sat_id:
|
||||
# Handle single satellite from old parameter or multiple from new parameter
|
||||
if selected_sat_id and not selected_satellites:
|
||||
# For backward compatibility - if only single satellite parameter is provided
|
||||
try:
|
||||
selected_sat_id_single = int(selected_sat_id)
|
||||
selected_satellites = [selected_sat_id_single]
|
||||
except ValueError:
|
||||
selected_satellites = []
|
||||
|
||||
# Start with the basic filter if any satellites are selected
|
||||
|
||||
if selected_satellites:
|
||||
# Start with the basic filter - optimized with prefetch_related for all related objects
|
||||
objects = ObjItem.objects.select_related(
|
||||
'geo_obj',
|
||||
'updated_by__user',
|
||||
@@ -374,7 +369,6 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
'parameters_obj__standard'
|
||||
).filter(parameters_obj__id_satellite_id__in=selected_satellites)
|
||||
else:
|
||||
# If no satellites are selected, start with all objects
|
||||
objects = ObjItem.objects.select_related(
|
||||
'geo_obj',
|
||||
'updated_by__user',
|
||||
@@ -385,9 +379,7 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
'parameters_obj__modulation',
|
||||
'parameters_obj__standard'
|
||||
)
|
||||
|
||||
# Apply additional filters
|
||||
# Frequency filter
|
||||
|
||||
if freq_min is not None and freq_min.strip() != '':
|
||||
try:
|
||||
freq_min_val = float(freq_min)
|
||||
@@ -400,8 +392,7 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
objects = objects.filter(parameters_obj__frequency__lte=freq_max_val)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Range filter
|
||||
|
||||
if range_min is not None and range_min.strip() != '':
|
||||
try:
|
||||
range_min_val = float(range_min)
|
||||
@@ -414,8 +405,7 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
objects = objects.filter(parameters_obj__freq_range__lte=range_max_val)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# SNR filter
|
||||
|
||||
if snr_min is not None and snr_min.strip() != '':
|
||||
try:
|
||||
snr_min_val = float(snr_min)
|
||||
@@ -428,8 +418,7 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
objects = objects.filter(parameters_obj__snr__lte=snr_max_val)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Symbol rate filter
|
||||
|
||||
if bod_min is not None and bod_min.strip() != '':
|
||||
try:
|
||||
bod_min_val = float(bod_min)
|
||||
@@ -442,72 +431,110 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
objects = objects.filter(parameters_obj__bod_velocity__lte=bod_max_val)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Modulation filter
|
||||
|
||||
if selected_modulations:
|
||||
objects = objects.filter(parameters_obj__modulation__id__in=selected_modulations)
|
||||
|
||||
# Polarization filter
|
||||
|
||||
if selected_polarizations:
|
||||
objects = objects.filter(parameters_obj__polarization__id__in=selected_polarizations)
|
||||
|
||||
# Kupsat coords filter
|
||||
if has_kupsat == '1': # has coords
|
||||
|
||||
if has_kupsat == '1':
|
||||
objects = objects.filter(geo_obj__coords_kupsat__isnull=False)
|
||||
elif has_kupsat == '0': # no coords
|
||||
elif has_kupsat == '0':
|
||||
objects = objects.filter(geo_obj__coords_kupsat__isnull=True)
|
||||
|
||||
# Valid coords filter
|
||||
if has_valid == '1': # has coords
|
||||
|
||||
if has_valid == '1':
|
||||
objects = objects.filter(geo_obj__coords_valid__isnull=False)
|
||||
elif has_valid == '0': # no coords
|
||||
elif has_valid == '0':
|
||||
objects = objects.filter(geo_obj__coords_valid__isnull=True)
|
||||
|
||||
# Add search functionality - search only in name and location fields to avoid spatial lookup errors
|
||||
|
||||
if search_query:
|
||||
search_query = search_query.strip()
|
||||
if search_query:
|
||||
# Search in name and location fields to match displayed text
|
||||
objects = objects.filter(
|
||||
models.Q(name__icontains=search_query) |
|
||||
models.Q(geo_obj__location__icontains=search_query)
|
||||
)
|
||||
else:
|
||||
selected_sat_id = None
|
||||
|
||||
# Add pagination
|
||||
|
||||
first_param_freq_subq = self.get_first_param_subquery('frequency')
|
||||
first_param_range_subq = self.get_first_param_subquery('freq_range')
|
||||
first_param_snr_subq = self.get_first_param_subquery('snr')
|
||||
first_param_bod_subq = self.get_first_param_subquery('bod_velocity')
|
||||
first_param_sat_name_subq = self.get_first_param_subquery('id_satellite__name')
|
||||
first_param_pol_name_subq = self.get_first_param_subquery('polarization__name')
|
||||
first_param_mod_name_subq = self.get_first_param_subquery('modulation__name')
|
||||
|
||||
objects = objects.annotate(
|
||||
first_param_freq=Subquery(first_param_freq_subq),
|
||||
first_param_range=Subquery(first_param_range_subq),
|
||||
first_param_snr=Subquery(first_param_snr_subq),
|
||||
first_param_bod=Subquery(first_param_bod_subq),
|
||||
first_param_sat_name=Subquery(first_param_sat_name_subq),
|
||||
first_param_pol_name=Subquery(first_param_pol_name_subq),
|
||||
first_param_mod_name=Subquery(first_param_mod_name_subq),
|
||||
)
|
||||
|
||||
valid_sort_fields = {
|
||||
'name': 'name',
|
||||
'-name': '-name',
|
||||
'updated_at': 'updated_at',
|
||||
'-updated_at': '-updated_at',
|
||||
'created_at': 'created_at',
|
||||
'-created_at': '-created_at',
|
||||
'updated_by': 'updated_by__user__username',
|
||||
'-updated_by': '-updated_by__user__username',
|
||||
'created_by': 'created_by__user__username',
|
||||
'-created_by': '-created_by__user__username',
|
||||
'geo_timestamp': 'geo_obj__timestamp',
|
||||
'-geo_timestamp': '-geo_obj__timestamp',
|
||||
'frequency': 'first_param_freq',
|
||||
'-frequency': '-first_param_freq',
|
||||
'freq_range': 'first_param_range',
|
||||
'-freq_range': '-first_param_range',
|
||||
'snr': 'first_param_snr',
|
||||
'-snr': '-first_param_snr',
|
||||
'bod_velocity': 'first_param_bod',
|
||||
'-bod_velocity': '-first_param_bod',
|
||||
'satellite': 'first_param_sat_name',
|
||||
'-satellite': '-first_param_sat_name',
|
||||
'polarization': 'first_param_pol_name',
|
||||
'-polarization': '-first_param_pol_name',
|
||||
'modulation': 'first_param_mod_name',
|
||||
'-modulation': '-first_param_mod_name',
|
||||
}
|
||||
|
||||
if sort_param in valid_sort_fields:
|
||||
objects = objects.order_by(valid_sort_fields[sort_param])
|
||||
|
||||
paginator = Paginator(objects, items_per_page)
|
||||
page_obj = paginator.get_page(page_number)
|
||||
|
||||
# Prepare the data to include calculated fields for the template
|
||||
|
||||
processed_objects = []
|
||||
for obj in page_obj:
|
||||
# Get the first parameter using the prefetched relation to avoid additional queries
|
||||
param = None
|
||||
if hasattr(obj, 'parameters_obj') and obj.parameters_obj.all():
|
||||
# Get parameters from the prefetched queryset without triggering new query
|
||||
param_list = list(obj.parameters_obj.all())
|
||||
if param_list:
|
||||
param = param_list[0] # Get first parameter without additional query
|
||||
|
||||
# Process geo coordinates
|
||||
param = param_list[0]
|
||||
|
||||
geo_coords = "-"
|
||||
kupsat_coords = "-"
|
||||
valid_coords = "-"
|
||||
distance_geo_kup = "-"
|
||||
distance_geo_valid = "-"
|
||||
distance_kup_valid = "-"
|
||||
|
||||
|
||||
if obj.geo_obj:
|
||||
# Format geo coordinates
|
||||
geo_timestamp = obj.geo_obj.timestamp
|
||||
if obj.geo_obj.coords:
|
||||
longitude = obj.geo_obj.coords.coords[0]
|
||||
latitude = obj.geo_obj.coords.coords[1]
|
||||
lon = f"{longitude}E" if longitude > 0 else f"{abs(longitude)}W"
|
||||
lat = f"{latitude}N" if latitude > 0 else f"{abs(latitude)}S"
|
||||
geo_coords = f"{lat} {lon}"
|
||||
|
||||
# Format kupsat coordinates
|
||||
|
||||
if obj.geo_obj.coords_kupsat:
|
||||
longitude = obj.geo_obj.coords_kupsat.coords[0]
|
||||
latitude = obj.geo_obj.coords_kupsat.coords[1]
|
||||
@@ -516,8 +543,7 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
kupsat_coords = f"{lat} {lon}"
|
||||
elif obj.geo_obj.coords_kupsat is not None:
|
||||
kupsat_coords = "-"
|
||||
|
||||
# Format valid coordinates
|
||||
|
||||
if obj.geo_obj.coords_valid:
|
||||
longitude = obj.geo_obj.coords_valid.coords[0]
|
||||
latitude = obj.geo_obj.coords_valid.coords[1]
|
||||
@@ -526,18 +552,16 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
valid_coords = f"{lat} {lon}"
|
||||
elif obj.geo_obj.coords_valid is not None:
|
||||
valid_coords = "-"
|
||||
|
||||
# Format distances
|
||||
|
||||
if obj.geo_obj.distance_coords_kup is not None:
|
||||
distance_geo_kup = f"{obj.geo_obj.distance_coords_kup:.3f}"
|
||||
|
||||
|
||||
if obj.geo_obj.distance_coords_valid is not None:
|
||||
distance_geo_valid = f"{obj.geo_obj.distance_coords_valid:.3f}"
|
||||
|
||||
|
||||
if obj.geo_obj.distance_kup_valid is not None:
|
||||
distance_kup_valid = f"{obj.geo_obj.distance_kup_valid:.3f}"
|
||||
|
||||
# Extract related object data to avoid additional queries in template
|
||||
|
||||
satellite_name = "-"
|
||||
frequency = "-"
|
||||
freq_range = "-"
|
||||
@@ -545,26 +569,22 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
bod_velocity = "-"
|
||||
modulation_name = "-"
|
||||
snr = "-"
|
||||
|
||||
|
||||
if param:
|
||||
# Get satellite data directly to avoid additional query
|
||||
if hasattr(param, 'id_satellite') and param.id_satellite:
|
||||
satellite_name = param.id_satellite.name if hasattr(param.id_satellite, 'name') else "-"
|
||||
|
||||
# Get parameter values directly
|
||||
|
||||
frequency = f"{param.frequency:.3f}" if param.frequency is not None else "-"
|
||||
freq_range = f"{param.freq_range:.3f}" if param.freq_range is not None else "-"
|
||||
bod_velocity = f"{param.bod_velocity:.0f}" if param.bod_velocity is not None else "-"
|
||||
snr = f"{param.snr:.0f}" if param.snr is not None else "-"
|
||||
|
||||
# Get polarization name directly to avoid additional query
|
||||
|
||||
if hasattr(param, 'polarization') and param.polarization:
|
||||
polarization_name = param.polarization.name if hasattr(param.polarization, 'name') else "-"
|
||||
|
||||
# Get modulation name directly to avoid additional query
|
||||
|
||||
if hasattr(param, 'modulation') and param.modulation:
|
||||
modulation_name = param.modulation.name if hasattr(param.modulation, 'name') else "-"
|
||||
|
||||
|
||||
processed_objects.append({
|
||||
'id': obj.id,
|
||||
'name': obj.name or "-",
|
||||
@@ -575,6 +595,7 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
'bod_velocity': bod_velocity,
|
||||
'modulation': modulation_name,
|
||||
'snr': snr,
|
||||
'geo_timestamp': geo_timestamp,
|
||||
'geo_coords': geo_coords,
|
||||
'kupsat_coords': kupsat_coords,
|
||||
'valid_coords': valid_coords,
|
||||
@@ -584,12 +605,10 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
'updated_by': obj.updated_by if obj.updated_by else '-',
|
||||
'obj': obj
|
||||
})
|
||||
|
||||
# Get all modulations and polarizations for filter dropdowns
|
||||
from .models import Modulation, Polarization
|
||||
|
||||
modulations = Modulation.objects.all()
|
||||
polarizations = Polarization.objects.all()
|
||||
|
||||
|
||||
context = {
|
||||
'satellites': satellites,
|
||||
'selected_satellite_id': selected_sat_id,
|
||||
@@ -597,7 +616,6 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
'processed_objects': processed_objects,
|
||||
'items_per_page': items_per_page,
|
||||
'available_items_per_page': [50, 100, 500, 1000],
|
||||
# Filter values
|
||||
'freq_min': freq_min,
|
||||
'freq_max': freq_max,
|
||||
'range_min': range_min,
|
||||
@@ -612,14 +630,18 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
'selected_satellites': [int(x) for x in selected_satellites if x.isdigit()],
|
||||
'has_kupsat': has_kupsat,
|
||||
'has_valid': has_valid,
|
||||
# For filter dropdowns
|
||||
'modulations': modulations,
|
||||
'polarizations': polarizations,
|
||||
# Enable full width layout
|
||||
'full_width_page': True,
|
||||
'sort': sort_param,
|
||||
}
|
||||
|
||||
|
||||
return render(request, 'mainapp/objitem_list.html', context)
|
||||
|
||||
def get_first_param_subquery(self, field_name):
|
||||
return Parameter.objects.filter(
|
||||
objitems=OuterRef('pk')
|
||||
).order_by('id').values(field_name)[:1]
|
||||
|
||||
class ObjItemUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
|
||||
model = ObjItem
|
||||
@@ -632,14 +654,10 @@ class ObjItemUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
# Добавляем контекст для карты
|
||||
context['LEAFLET_CONFIG'] = {
|
||||
'DEFAULT_CENTER': (55.75, 37.62),
|
||||
'DEFAULT_ZOOM': 5,
|
||||
}
|
||||
|
||||
# Остальной контекст остается без изменений
|
||||
ParameterFormSet = modelformset_factory(
|
||||
Parameter,
|
||||
form=ParameterForm,
|
||||
@@ -703,19 +721,19 @@ class ObjItemUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
|
||||
geo_longitude = self.request.POST.get('geo_longitude')
|
||||
geo_latitude = self.request.POST.get('geo_latitude')
|
||||
if geo_longitude and geo_latitude:
|
||||
geo_instance.coords = Point(float(geo_longitude), float(geo_latitude))
|
||||
geo_instance.coords = Point(float(geo_longitude), float(geo_latitude), srid=4326)
|
||||
|
||||
# Обрабатываем координаты Кубсата
|
||||
kupsat_longitude = self.request.POST.get('kupsat_longitude')
|
||||
kupsat_latitude = self.request.POST.get('kupsat_latitude')
|
||||
if kupsat_longitude and kupsat_latitude:
|
||||
geo_instance.coords_kupsat = Point(float(kupsat_longitude), float(kupsat_latitude))
|
||||
geo_instance.coords_kupsat = Point(float(kupsat_longitude), float(kupsat_latitude), srid=4326)
|
||||
|
||||
# Обрабатываем координаты оперативников
|
||||
valid_longitude = self.request.POST.get('valid_longitude')
|
||||
valid_latitude = self.request.POST.get('valid_latitude')
|
||||
if valid_longitude and valid_latitude:
|
||||
geo_instance.coords_valid = Point(float(valid_longitude), float(valid_latitude))
|
||||
geo_instance.coords_valid = Point(float(valid_longitude), float(valid_latitude), srid=4326)
|
||||
|
||||
# Обрабатываем дату/время
|
||||
timestamp_date = self.request.POST.get('timestamp_date')
|
||||
@@ -788,19 +806,19 @@ class ObjItemCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
|
||||
geo_longitude = self.request.POST.get('geo_longitude')
|
||||
geo_latitude = self.request.POST.get('geo_latitude')
|
||||
if geo_longitude and geo_latitude:
|
||||
geo_instance.coords = Point(float(geo_longitude), float(geo_latitude))
|
||||
geo_instance.coords = Point(float(geo_longitude), float(geo_latitude), srid=4326)
|
||||
|
||||
# Обрабатываем координаты Кубсата
|
||||
kupsat_longitude = self.request.POST.get('kupsat_longitude')
|
||||
kupsat_latitude = self.request.POST.get('kupsat_latitude')
|
||||
if kupsat_longitude and kupsat_latitude:
|
||||
geo_instance.coords_kupsat = Point(float(kupsat_longitude), float(kupsat_latitude))
|
||||
geo_instance.coords_kupsat = Point(float(kupsat_longitude), float(kupsat_latitude), srid=4326)
|
||||
|
||||
# Обрабатываем координаты оперативников
|
||||
valid_longitude = self.request.POST.get('valid_longitude')
|
||||
valid_latitude = self.request.POST.get('valid_latitude')
|
||||
if valid_longitude and valid_latitude:
|
||||
geo_instance.coords_valid = Point(float(valid_longitude), float(valid_latitude))
|
||||
geo_instance.coords_valid = Point(float(valid_longitude), float(valid_latitude), srid=4326)
|
||||
|
||||
# Обрабатываем дату/время
|
||||
timestamp_date = self.request.POST.get('timestamp_date')
|
||||
|
||||
Reference in New Issue
Block a user