Добавил информацию о типе объекта. Просто фиксы

This commit is contained in:
2025-11-17 15:54:27 +03:00
parent f438e74946
commit b889fb29a3
20 changed files with 1086 additions and 134 deletions

View File

@@ -42,7 +42,7 @@
<!-- Search bar -->
<div style="min-width: 200px; flex-grow: 1; max-width: 400px;">
<div class="input-group">
<input type="text" id="toolbar-search" class="form-control" placeholder="Поиск по ID..."
<input type="text" id="toolbar-search" class="form-control" placeholder="Поиск по ID или имени..."
value="{{ search_query|default:'' }}">
<button type="button" class="btn btn-outline-primary"
onclick="performSearch()">Найти</button>
@@ -67,6 +67,12 @@
<!-- Action buttons -->
<div class="d-flex gap-2">
<a href="{% url 'mainapp:load_excel_data' %}" class="btn btn-primary btn-sm" title="Загрузка данных из Excel">
<i class="bi bi-file-earmark-excel"></i> Excel
</a>
<a href="{% url 'mainapp:load_csv_data' %}" class="btn btn-success btn-sm" title="Загрузка данных из CSV">
<i class="bi bi-file-earmark-text"></i> CSV
</a>
{% if user.customuser.role == 'admin' or user.customuser.role == 'moderator' %}
<button type="button" class="btn btn-danger btn-sm" title="Удалить"
onclick="deleteSelectedSources()">
@@ -194,7 +200,7 @@
<!-- LyngSat Filter -->
<div class="mb-2">
<label class="form-label">Тип объекта (ТВ):</label>
<label class="form-label">ТВ или нет:</label>
<div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="has_lyngsat" id="has_lyngsat_1"
@@ -209,6 +215,24 @@
</div>
</div>
<!-- ObjectInfo Filter -->
<div class="mb-2">
<label class="form-label">Тип объекта:</label>
<div class="d-flex justify-content-between mb-1">
<button type="button" class="btn btn-sm btn-outline-secondary"
onclick="selectAllOptions('info_id', true)">Выбрать</button>
<button type="button" class="btn btn-sm btn-outline-secondary"
onclick="selectAllOptions('info_id', false)">Снять</button>
</div>
<select name="info_id" class="form-select form-select-sm mb-2" multiple size="4">
{% for info in object_infos %}
<option value="{{ info.id }}" {% if info.id in selected_info %}selected{% endif %}>
{{ info.name }}
</option>
{% endfor %}
</select>
</div>
<!-- Point Count Filter -->
<div class="mb-2">
<label class="form-label">Количество точек:</label>
@@ -227,6 +251,35 @@
placeholder="До" value="{{ date_to|default:'' }}">
</div>
<!-- Signal Mark Filter -->
<div class="mb-2">
<label class="form-label">Наличие сигнала:</label>
<div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="has_signal_mark" id="has_signal_mark_1"
value="1" {% if has_signal_mark == '1' %}checked{% endif %}>
<label class="form-check-label" for="has_signal_mark_1">Есть</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="has_signal_mark" id="has_signal_mark_0"
value="0" {% if has_signal_mark == '0' %}checked{% endif %}>
<label class="form-check-label" for="has_signal_mark_0">Нет</label>
</div>
</div>
</div>
<!-- Mark Date Filter -->
<div class="mb-2">
<label class="form-label">Дата отметки сигнала:</label>
<input type="date" name="mark_date_from" id="mark_date_from" class="form-control form-control-sm mb-1"
placeholder="От" value="{{ mark_date_from|default:'' }}">
<input type="date" name="mark_date_to" id="mark_date_to" class="form-control form-control-sm"
placeholder="До" value="{{ mark_date_to|default:'' }}">
</div>
<hr class="my-3">
<h6 class="text-muted mb-2"><i class="bi bi-sliders"></i> Фильтры по параметрам точек</h6>
<!-- Geo Timestamp Filter -->
<div class="mb-2">
<label class="form-label">Дата ГЛ:</label>
@@ -236,6 +289,96 @@
placeholder="До" value="{{ geo_date_to|default:'' }}">
</div>
<!-- Polarization Selection - Multi-select -->
<div class="mb-2">
<label class="form-label">Поляризация:</label>
<div class="d-flex justify-content-between mb-1">
<button type="button" class="btn btn-sm btn-outline-secondary"
onclick="selectAllOptions('polarization_id', true)">Выбрать</button>
<button type="button" class="btn btn-sm btn-outline-secondary"
onclick="selectAllOptions('polarization_id', false)">Снять</button>
</div>
<select name="polarization_id" class="form-select form-select-sm mb-2" multiple size="4">
{% for polarization in polarizations %}
<option value="{{ polarization.id }}" {% if polarization.id in selected_polarizations %}selected{% endif %}>
{{ polarization.name }}
</option>
{% endfor %}
</select>
</div>
<!-- Modulation Selection - Multi-select -->
<div class="mb-2">
<label class="form-label">Модуляция:</label>
<div class="d-flex justify-content-between mb-1">
<button type="button" class="btn btn-sm btn-outline-secondary"
onclick="selectAllOptions('modulation_id', true)">Выбрать</button>
<button type="button" class="btn btn-sm btn-outline-secondary"
onclick="selectAllOptions('modulation_id', false)">Снять</button>
</div>
<select name="modulation_id" class="form-select form-select-sm mb-2" multiple size="4">
{% for modulation in modulations %}
<option value="{{ modulation.id }}" {% if modulation.id in selected_modulations %}selected{% endif %}>
{{ modulation.name }}
</option>
{% endfor %}
</select>
</div>
<!-- Frequency Filter -->
<div class="mb-2">
<label class="form-label">Частота, МГц:</label>
<input type="number" step="0.001" name="freq_min" class="form-control form-control-sm mb-1"
placeholder="От" value="{{ freq_min|default:'' }}">
<input type="number" step="0.001" name="freq_max" class="form-control form-control-sm"
placeholder="До" value="{{ freq_max|default:'' }}">
</div>
<!-- Frequency Range (Bandwidth) Filter -->
<div class="mb-2">
<label class="form-label">Полоса, МГц:</label>
<input type="number" step="0.001" name="freq_range_min" class="form-control form-control-sm mb-1"
placeholder="От" value="{{ freq_range_min|default:'' }}">
<input type="number" step="0.001" name="freq_range_max" class="form-control form-control-sm"
placeholder="До" value="{{ freq_range_max|default:'' }}">
</div>
<!-- Symbol Rate Filter -->
<div class="mb-2">
<label class="form-label">Символьная скорость, БОД:</label>
<input type="number" step="0.001" name="bod_velocity_min" class="form-control form-control-sm mb-1"
placeholder="От" value="{{ bod_velocity_min|default:'' }}">
<input type="number" step="0.001" name="bod_velocity_max" class="form-control form-control-sm"
placeholder="До" value="{{ bod_velocity_max|default:'' }}">
</div>
<!-- SNR Filter -->
<div class="mb-2">
<label class="form-label">ОСШ, дБ:</label>
<input type="number" step="0.1" name="snr_min" class="form-control form-control-sm mb-1"
placeholder="От" value="{{ snr_min|default:'' }}">
<input type="number" step="0.1" name="snr_max" class="form-control form-control-sm"
placeholder="До" value="{{ snr_max|default:'' }}">
</div>
<!-- Mirrors Selection - Multi-select -->
<div class="mb-2">
<label class="form-label">Зеркала:</label>
<div class="d-flex justify-content-between mb-1">
<button type="button" class="btn btn-sm btn-outline-secondary"
onclick="selectAllOptions('mirror_id', true)">Выбрать</button>
<button type="button" class="btn btn-sm btn-outline-secondary"
onclick="selectAllOptions('mirror_id', false)">Снять</button>
</div>
<select name="mirror_id" class="form-select form-select-sm mb-2" multiple size="4">
{% for mirror in mirrors %}
<option value="{{ mirror.id }}" {% if mirror.id in selected_mirrors %}selected{% endif %}>
{{ mirror.name }}
</option>
{% endfor %}
</select>
</div>
<!-- Apply Filters and Reset Buttons -->
<div class="d-grid gap-2 mt-2">
<button type="submit" class="btn btn-primary btn-sm">Применить</button>
@@ -267,15 +410,15 @@
{% endif %}
</a>
</th>
<th scope="col" style="min-width: 150px;">Имя</th>
<th scope="col" style="min-width: 120px;">Спутник</th>
<th scope="col" style="min-width: 120px;">Тип объекта</th>
<th scope="col" style="min-width: 150px;">Усредненные координаты</th>
<th scope="col" style="min-width: 150px;">Координаты Кубсата</th>
<th scope="col" style="min-width: 150px;">Координаты оперативников</th>
<th scope="col" style="min-width: 150px;">Координаты справочные</th>
<th scope="col" style="min-width: 180px;">Наличие сигнала</th>
{% if has_any_lyngsat %}
<th scope="col" class="text-center" style="min-width: 80px;">Тип объекта</th>
{% endif %}
<th scope="col" class="text-center" style="min-width: 80px;">ТВ или нет</th>
<th scope="col" class="text-center" style="min-width: 100px;">
<a href="javascript:void(0)" onclick="updateSort('objitem_count')" class="text-white text-decoration-none">
Кол-во точек
@@ -317,7 +460,18 @@
value="{{ source.id }}">
</td>
<td class="text-center">{{ source.id }}</td>
<td>{{ source.satellite }}</td>
<td>{{ source.name }}</td>
<td>
{% if source.satellite_id %}
<a href="#" class="text-decoration-underline"
onclick="showSatelliteModal({{ source.satellite_id }}); return false;">
{{ source.satellite }}
</a>
{% else %}
{{ source.satellite }}
{% endif %}
</td>
<td>{{ source.info }}</td>
<td>{{ source.coords_average }}</td>
<td>{{ source.coords_kupsat }}</td>
<td>{{ source.coords_valid }}</td>
@@ -345,7 +499,6 @@
<span class="text-muted">-</span>
{% endif %}
</td>
{% if has_any_lyngsat %}
<td class="text-center">
{% if source.has_lyngsat %}
<a href="#" class="text-primary text-decoration-none"
@@ -356,7 +509,6 @@
-
{% endif %}
</td>
{% endif %}
<td class="text-center">{{ source.objitem_count }}</td>
<td>{{ source.created_at|date:"d.m.Y H:i" }}</td>
<td>{{ source.updated_at|date:"d.m.Y H:i" }}</td>
@@ -411,7 +563,7 @@
</tr>
{% empty %}
<tr>
<td colspan="12" class="text-center text-muted">Нет данных для отображения</td>
<td colspan="14" class="text-center text-muted">Нет данных для отображения</td>
</tr>
{% endfor %}
</tbody>
@@ -775,6 +927,7 @@ document.addEventListener('DOMContentLoaded', function() {
setupRadioLikeCheckboxes('has_coords_valid');
setupRadioLikeCheckboxes('has_coords_reference');
setupRadioLikeCheckboxes('has_lyngsat');
setupRadioLikeCheckboxes('has_signal_mark');
// Update filter counter on page load
updateFilterCounter();
@@ -896,10 +1049,10 @@ function showSourceDetails(sourceId) {
// Build transponder cell
let transponderCell = '-';
if (objitem.has_transponder) {
transponderCell = '<a href="#" class="text-success text-decoration-none" ' +
transponderCell = '<a href="#" class="text-decoration-underline" ' +
'onclick="showTransponderModal(' + objitem.transponder_id + '); return false;" ' +
'title="Показать данные транспондера">' +
'<i class="bi bi-broadcast"></i> ' + objitem.transponder_info +
objitem.transponder_info +
'</a>';
}
@@ -922,12 +1075,21 @@ function showSourceDetails(sourceId) {
'</a>';
}
// Build satellite cell with link
let satelliteCell = objitem.satellite_name;
if (objitem.satellite_id) {
satelliteCell = '<a href="#" class="text-decoration-underline" ' +
'onclick="showSatelliteModal(' + objitem.satellite_id + '); return false;">' +
objitem.satellite_name +
'</a>';
}
row.innerHTML = '<td class="text-center">' +
'<input type="checkbox" class="form-check-input modal-item-checkbox" value="' + objitem.id + '">' +
'</td>' +
'<td class="text-center">' + objitem.id + '</td>' +
'<td>' + objitem.name + '</td>' +
'<td>' + objitem.satellite_name + '</td>' +
'<td>' + satelliteCell + '</td>' +
'<td>' + transponderCell + '</td>' +
'<td>' + objitem.frequency + '</td>' +
'<td>' + objitem.freq_range + '</td>' +
@@ -954,8 +1116,13 @@ function showSourceDetails(sourceId) {
// Setup modal select-all checkbox
setupModalSelectAll();
// Initialize column visibility
initModalColumnVisibility();
// Initialize column visibility after DOM update
// Use requestAnimationFrame to ensure DOM is rendered
requestAnimationFrame(() => {
setTimeout(() => {
initModalColumnVisibility();
}, 50);
});
} else {
// Show no data message
document.getElementById('modalNoData').style.display = 'block';
@@ -1002,21 +1169,27 @@ function setupModalSelectAll() {
// Function to toggle modal column visibility
function toggleModalColumn(checkbox) {
const columnIndex = parseInt(checkbox.getAttribute('data-column'));
const modal = document.getElementById('sourceDetailsModal');
const table = modal.querySelector('.table');
// Get the specific tbody for objitems
const tbody = document.getElementById('objitemTableBody');
if (!tbody) return;
// Get the parent table
const table = tbody.closest('table');
if (!table) return;
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';
});
}
// Get all rows and toggle specific cell in each
const rows = table.querySelectorAll('tr');
rows.forEach(row => {
const cells = row.children;
if (cells[columnIndex]) {
if (checkbox.checked) {
cells[columnIndex].style.removeProperty('display');
} else {
cells[columnIndex].style.setProperty('display', 'none', 'important');
}
}
});
}
// Function to toggle all modal columns
@@ -1032,11 +1205,31 @@ function toggleAllModalColumns(selectAllCheckbox) {
function initModalColumnVisibility() {
// Hide columns by default: Создано (16), Кем(созд) (17), Комментарий (18), Усреднённое (19), Стандарт (20), Sigma (22)
const columnsToHide = [16, 17, 18, 19, 20, 22];
// Get the specific tbody for objitems
const tbody = document.getElementById('objitemTableBody');
if (!tbody) {
console.log('objitemTableBody not found');
return;
}
// Get the parent table
const table = tbody.closest('table');
if (!table) {
console.log('Table not found');
return;
}
// Hide columns that should be hidden by default
columnsToHide.forEach(columnIndex => {
const checkbox = document.querySelector('.modal-column-toggle[data-column="' + columnIndex + '"]');
if (checkbox && !checkbox.checked) {
toggleModalColumn(checkbox);
}
// Get all rows in the table (including thead and tbody)
const rows = table.querySelectorAll('tr');
rows.forEach(row => {
const cells = row.children;
if (cells[columnIndex]) {
cells[columnIndex].style.setProperty('display', 'none', 'important');
}
});
});
}
@@ -1190,4 +1383,7 @@ function showTransponderModal(transponderId) {
<!-- Include the sigma parameter modal component -->
{% include 'mainapp/components/_sigma_parameter_modal.html' %}
<!-- Include the satellite modal component -->
{% include 'mainapp/components/_satellite_modal.html' %}
{% endblock %}