Настроил сеелери, начал привязку lyngsat
This commit is contained in:
@@ -1,60 +1,60 @@
|
||||
{% extends "mapsapp/map2d_base.html" %}
|
||||
{% load static %}
|
||||
{% block title %}Вынос точек{% endblock title %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
// Цвета для стандартных маркеров (из leaflet-color-markers)
|
||||
var markerColors = ['red', 'green', 'orange', 'violet', 'grey', 'black', 'blue'];
|
||||
var getColorIcon = function(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]
|
||||
});
|
||||
};
|
||||
|
||||
var overlays = [];
|
||||
|
||||
{% for group in groups %}
|
||||
var groupIndex = {{ forloop.counter0 }};
|
||||
var colorName = markerColors[groupIndex % markerColors.length];
|
||||
var groupIcon = getColorIcon(colorName);
|
||||
|
||||
var groupLayer = L.layerGroup();
|
||||
|
||||
var subgroup = [];
|
||||
{% for point_data in group.points %}
|
||||
var pointName = "{{ group.name|escapejs }}";
|
||||
|
||||
var marker = L.marker([{{ point_data.point.1|safe }}, {{ point_data.point.0|safe }}], {
|
||||
icon: groupIcon
|
||||
}).bindPopup(pointName);
|
||||
|
||||
groupLayer.addLayer(marker);
|
||||
|
||||
subgroup.push({
|
||||
label: "{{ forloop.counter }} - {{ point_data.frequency }}",
|
||||
layer: marker
|
||||
});
|
||||
{% endfor %}
|
||||
|
||||
overlays.push({
|
||||
label: '{{ group.name|escapejs }}',
|
||||
selectAllCheckbox: true,
|
||||
children: subgroup,
|
||||
layer: groupLayer
|
||||
});
|
||||
{% endfor %}
|
||||
|
||||
|
||||
// Используем именно tree-контрол
|
||||
L.control.layers.tree(baseLayers, overlays, {
|
||||
collapsed: false,
|
||||
autoZIndex: true
|
||||
}).addTo(map);
|
||||
</script>
|
||||
{% extends "mapsapp/map2d_base.html" %}
|
||||
{% load static %}
|
||||
{% block title %}Вынос точек{% endblock title %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
// Цвета для стандартных маркеров (из leaflet-color-markers)
|
||||
var markerColors = ['red', 'green', 'orange', 'violet', 'grey', 'black', 'blue'];
|
||||
var getColorIcon = function(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]
|
||||
});
|
||||
};
|
||||
|
||||
var overlays = [];
|
||||
|
||||
{% for group in groups %}
|
||||
var groupIndex = {{ forloop.counter0 }};
|
||||
var colorName = markerColors[groupIndex % markerColors.length];
|
||||
var groupIcon = getColorIcon(colorName);
|
||||
|
||||
var groupLayer = L.layerGroup();
|
||||
|
||||
var subgroup = [];
|
||||
{% for point_data in group.points %}
|
||||
var pointName = "{{ group.name|escapejs }}";
|
||||
|
||||
var marker = L.marker([{{ point_data.point.1|safe }}, {{ point_data.point.0|safe }}], {
|
||||
icon: groupIcon
|
||||
}).bindPopup(pointName);
|
||||
|
||||
groupLayer.addLayer(marker);
|
||||
|
||||
subgroup.push({
|
||||
label: "{{ forloop.counter }} - {{ point_data.frequency }}",
|
||||
layer: marker
|
||||
});
|
||||
{% endfor %}
|
||||
|
||||
overlays.push({
|
||||
label: '{{ group.name|escapejs }}',
|
||||
selectAllCheckbox: true,
|
||||
children: subgroup,
|
||||
layer: groupLayer
|
||||
});
|
||||
{% endfor %}
|
||||
|
||||
|
||||
// Используем именно tree-контрол
|
||||
L.control.layers.tree(baseLayers, overlays, {
|
||||
collapsed: false,
|
||||
autoZIndex: true
|
||||
}).addTo(map);
|
||||
</script>
|
||||
{% endblock extra_js %}
|
||||
@@ -1,189 +1,189 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Действия{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="text-center mb-5">
|
||||
<h1 class="display-4 fw-bold">Действия</h1>
|
||||
<p class="lead">Управление данными спутников</p>
|
||||
</div>
|
||||
|
||||
<!-- Alert messages -->
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
|
||||
<!-- Main feature cards -->
|
||||
<div class="row g-4">
|
||||
<!-- Excel Data Upload Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-primary bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-file-earmark-excel text-primary" viewBox="0 0 16 16">
|
||||
<path d="M5.884 6.68a.5.5 0 1 0-.768.64L7.349 10l-2.233 2.68a.5.5 0 0 0 .768.64L8 10.781l2.116 2.54a.5.5 0 0 0 .768-.641L8.651 10l2.233-2.68a.5.5 0 0 0-.768-.64L8 9.219z"/>
|
||||
<path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2M9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Загрузка данных из Excel</h3>
|
||||
</div>
|
||||
<p class="card-text">Загрузите данные из Excel-файла в базу данных. Поддерживается выбор спутника и ограничение количества записей.</p>
|
||||
<a href="{% url 'mainapp:load_excel_data' %}" class="btn btn-primary">
|
||||
Перейти к загрузке данных
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CSV Data Upload Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-success bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-file-earmark-text text-success" viewBox="0 0 16 16">
|
||||
<path d="M5.5 7a.5.5 0 0 0 0 1h5a.5.5 0 0 0 0-1zm0 2a.5.5 0 0 0 0 1h2a.5.5 0 0 0 0-1z"/>
|
||||
<path d="M9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4.5L9.5 0m0 1v2A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Загрузка данных из CSV</h3>
|
||||
</div>
|
||||
<p class="card-text">Загрузите данные из CSV-файла в базу данных. Простая загрузка с возможностью указания пути к файлу.</p>
|
||||
<a href="{% url 'mainapp:load_csv_data' %}" class="btn btn-success">
|
||||
Перейти к загрузке данных
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Satellite List Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-info bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-satellite text-info" viewBox="0 0 16 16">
|
||||
<path d="M13.37 1.37c-2.75 0-5.4 1.13-7.29 3.02C4.13 6.33 3 8.98 3 11.73c0 2.75 1.13 5.4 3.02 7.29 1.94 1.94 4.54 3.02 7.29 3.02 2.75 0 5.4-1.13 7.29-3.02 1.94-1.94 3.02-4.54 3.02-7.29 0-2.75-1.13-5.4-3.02-7.29C18.77 2.5-2.75 1.37-5.5 1.37m-5.5 8.26c0-1.52.62-3.02 1.73-4.13 1.11-1.11 2.61-1.73 4.13-1.73 1.52 0 3.02.62 4.13 1.73 1.11 1.11 1.73 2.61 1.73 4.13 0 1.52-.62 3.02-1.73 4.13-1.11 1.11-2.61 1.73-4.13 1.73-1.52 0-3.02-.62-4.13-1.73-1.11-1.11-1.73-2.61-1.73-4.13"/>
|
||||
<path d="M6.63 6.63c.62-.62 1.45-.98 2.27-.98.82 0 1.65.36 2.27.98.62.62.98 1.45.98 2.27 0 .82-.36 1.65-.98 2.27-.62.62-1.45.98-2.27.98-.82 0-1.65-.36-2.27-.98-.62-.62-.98-1.45-.98-2.27 0-.82.36-1.65.98-2.27m2.27 1.02c-.26 0-.52.1-.71.29-.2.2-.29.46-.29.71 0 .26.1.52.29.71.2.2.46.29.71.29.26 0 .52-.1.71-.29.2-.2.29-.46.29-.71 0-.26-.1-.52-.29-.71-.19-.19-.45-.29-.71-.29"/>
|
||||
<path d="M5.13 5.13c.46-.46 1.08-.73 1.73-.73.65 0 1.27.27 1.73.73.46.46.73 1.08.73 1.73 0 .65-.27 1.27-.73 1.73-.46.46-1.08.73-1.73.73-.65 0-1.27-.27-1.73-.73-.46-.46-.73-1.08-.73-1.73 0-.65.27-1.27.73-1.73m1.73.58c-.15 0-.3.06-.42.18-.12.12-.18.27-.18.42 0 .15.06.3.18.42.12.12.27.18.42.18.15 0 .3-.06.42-.18.12-.12.18-.27.18-.42 0-.15-.06-.3-.18-.42-.12-.12-.27-.18-.42-.18"/>
|
||||
<path d="M8 3.5c.28 0 .5.22.5.5v1c0 .28-.22.5-.5.5s-.5-.22-.5-.5v-1c0-.28.22-.5.5-.5"/>
|
||||
<path d="M10.5 8c0-.28.22-.5.5-.5h1c.28 0 .5.22.5.5s-.22.5-.5.5h-1c-.28 0-.5-.22-.5-.5"/>
|
||||
<path d="M8 12.5c-.28 0-.5.22-.5.5v1c0 .28.22.5.5.5s.5-.22.5-.5v-1c0-.28-.22-.5-.5-.5"/>
|
||||
<path d="M3.5 8c0 .28-.22.5-.5.5h-1c-.28 0-.5-.22-.5-.5s.22-.5.5-.5h1c.28 0 .5.22.5.5"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Добавление списка спутников</h3>
|
||||
</div>
|
||||
<p class="card-text">Добавьте новый список спутников в базу данных для последующего использования в загрузке данных.</p>
|
||||
<a href="{% url 'mainapp:add_sats' %}" class="btn btn-info">
|
||||
Добавить список спутников
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Transponders Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-warning bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-wifi text-warning" viewBox="0 0 16 16">
|
||||
<path d="M6.002 3.5a5.5 5.5 0 1 1 3.996 9.5H10A5.5 5.5 0 0 1 6.002 3.5M6.002 5.5a3.5 3.5 0 1 0 3.996 5.5H10A3.5 3.5 0 0 0 6.002 5.5"/>
|
||||
<path d="M10.5 12.5a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5.5.5 0 0 0-1 0 .5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5.5.5 0 0 0-1 0 .5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5 3.5 3.5 0 0 1 7 0"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Добавление транспондеров</h3>
|
||||
</div>
|
||||
<p class="card-text">Добавьте список транспондеров из JSON-файла в базу данных. Требуется наличие файла transponders.json.</p>
|
||||
<a href="{% url 'mainapp:add_trans' %}" class="btn btn-warning">
|
||||
Добавить транспондеры
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- VCH Load Data Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-danger bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-upload text-danger" viewBox="0 0 16 16">
|
||||
<path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5"/>
|
||||
<path d="M7.646 1.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V11.5a.5.5 0 0 1-1 0V2.707L5.354 4.854a.5.5 0 1 1-.708-.708z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Добавление данных ВЧ загрузки</h3>
|
||||
</div>
|
||||
<p class="card-text">Загрузите данные ВЧ загрузки из HTML-файла с таблицами. Поддерживается выбор спутника для привязки данных.</p>
|
||||
<a href="{% url 'mainapp:vch_load' %}" class="btn btn-danger">
|
||||
Добавить данные ВЧ загрузки
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lyngsat Data Fill Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-secondary bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-cloud-download text-secondary" viewBox="0 0 16 16">
|
||||
<path d="M4.406 1.342A5.53 5.53 0 0 1 8 0c2.69 0 4.923 2 5.166 4.579C14.758 4.804 16 6.137 16 7.773 16 9.569 14.502 11 12.687 11H10a.5.5 0 0 1 0-1h2.688C13.979 10 15 8.988 15 7.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 2.825 10.328 1 8 1a4.53 4.53 0 0 0-2.941 1.1c-.757.652-1.153 1.438-1.153 2.055v.448l-.445.049C2.064 4.805 1 5.952 1 7.318 1 8.785 2.23 10 3.781 10H6a.5.5 0 0 1 0 1H3.781C1.708 11 0 9.366 0 7.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383"/>
|
||||
<path d="M7.646 15.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 14.293V5.5a.5.5 0 0 0-1 0v8.793l-2.146-2.147a.5.5 0 0 0-.708.708z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Заполнение данных Lyngsat</h3>
|
||||
</div>
|
||||
<p class="card-text">Загрузите данные о транспондерах спутников с сайта Lyngsat. Выберите спутники и регионы для парсинга данных.</p>
|
||||
<a href="{% url 'mainapp:fill_lyngsat_data' %}" class="btn btn-secondary">
|
||||
Заполнить данные Lyngsat
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Calculation Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-info bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-calculator text-info" viewBox="0 0 16 16">
|
||||
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v4h2V2a1 1 0 0 0-1-1M5 6v1h1V6zm2 0v1h1V6zm2 0v1h1V6zm2 0v1h1V6zm1 2v1h1V8zm0 2v1h1v-1zm0 2v1h1v-1zm-8-6v8H3V8zm2 0v8h1V8zm2 0v8h1V8zm2 0v8h1V8z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Привязка ВЧ загрузки</h3>
|
||||
</div>
|
||||
<p class="card-text">Привязка ВЧ загрузки с sigma</p>
|
||||
<a href="{% url 'mainapp:link_vch_sigma' %}" class="btn btn-info">
|
||||
Открыть форму
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- New Event Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-success bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-plus-circle text-success" viewBox="0 0 16 16">
|
||||
<path d="M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0M4.5 7.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5M7.5 4.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 0 1h-1a.5.5 0 0 1-.5-.5m1 3a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-1 0v-3a.5.5 0 0 1 .5-.5"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Формирование таблицы для Кубсатов</h3>
|
||||
</div>
|
||||
<p class="card-text">Добавьте новое событие с помощью выбора спутника и загрузки файла данных.</p>
|
||||
<a href="{% url 'mainapp:kubsat_excel' %}" class="btn btn-success">
|
||||
Добавить событие
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Действия{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="text-center mb-5">
|
||||
<h1 class="display-4 fw-bold">Действия</h1>
|
||||
<p class="lead">Управление данными спутников</p>
|
||||
</div>
|
||||
|
||||
<!-- Alert messages -->
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
|
||||
<!-- Main feature cards -->
|
||||
<div class="row g-4">
|
||||
<!-- Excel Data Upload Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-primary bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-file-earmark-excel text-primary" viewBox="0 0 16 16">
|
||||
<path d="M5.884 6.68a.5.5 0 1 0-.768.64L7.349 10l-2.233 2.68a.5.5 0 0 0 .768.64L8 10.781l2.116 2.54a.5.5 0 0 0 .768-.641L8.651 10l2.233-2.68a.5.5 0 0 0-.768-.64L8 9.219z"/>
|
||||
<path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2M9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Загрузка данных из Excel</h3>
|
||||
</div>
|
||||
<p class="card-text">Загрузите данные из Excel-файла в базу данных. Поддерживается выбор спутника и ограничение количества записей.</p>
|
||||
<a href="{% url 'mainapp:load_excel_data' %}" class="btn btn-primary">
|
||||
Перейти к загрузке данных
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CSV Data Upload Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-success bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-file-earmark-text text-success" viewBox="0 0 16 16">
|
||||
<path d="M5.5 7a.5.5 0 0 0 0 1h5a.5.5 0 0 0 0-1zm0 2a.5.5 0 0 0 0 1h2a.5.5 0 0 0 0-1z"/>
|
||||
<path d="M9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4.5L9.5 0m0 1v2A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Загрузка данных из CSV</h3>
|
||||
</div>
|
||||
<p class="card-text">Загрузите данные из CSV-файла в базу данных. Простая загрузка с возможностью указания пути к файлу.</p>
|
||||
<a href="{% url 'mainapp:load_csv_data' %}" class="btn btn-success">
|
||||
Перейти к загрузке данных
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Satellite List Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-info bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-satellite text-info" viewBox="0 0 16 16">
|
||||
<path d="M13.37 1.37c-2.75 0-5.4 1.13-7.29 3.02C4.13 6.33 3 8.98 3 11.73c0 2.75 1.13 5.4 3.02 7.29 1.94 1.94 4.54 3.02 7.29 3.02 2.75 0 5.4-1.13 7.29-3.02 1.94-1.94 3.02-4.54 3.02-7.29 0-2.75-1.13-5.4-3.02-7.29C18.77 2.5-2.75 1.37-5.5 1.37m-5.5 8.26c0-1.52.62-3.02 1.73-4.13 1.11-1.11 2.61-1.73 4.13-1.73 1.52 0 3.02.62 4.13 1.73 1.11 1.11 1.73 2.61 1.73 4.13 0 1.52-.62 3.02-1.73 4.13-1.11 1.11-2.61 1.73-4.13 1.73-1.52 0-3.02-.62-4.13-1.73-1.11-1.11-1.73-2.61-1.73-4.13"/>
|
||||
<path d="M6.63 6.63c.62-.62 1.45-.98 2.27-.98.82 0 1.65.36 2.27.98.62.62.98 1.45.98 2.27 0 .82-.36 1.65-.98 2.27-.62.62-1.45.98-2.27.98-.82 0-1.65-.36-2.27-.98-.62-.62-.98-1.45-.98-2.27 0-.82.36-1.65.98-2.27m2.27 1.02c-.26 0-.52.1-.71.29-.2.2-.29.46-.29.71 0 .26.1.52.29.71.2.2.46.29.71.29.26 0 .52-.1.71-.29.2-.2.29-.46.29-.71 0-.26-.1-.52-.29-.71-.19-.19-.45-.29-.71-.29"/>
|
||||
<path d="M5.13 5.13c.46-.46 1.08-.73 1.73-.73.65 0 1.27.27 1.73.73.46.46.73 1.08.73 1.73 0 .65-.27 1.27-.73 1.73-.46.46-1.08.73-1.73.73-.65 0-1.27-.27-1.73-.73-.46-.46-.73-1.08-.73-1.73 0-.65.27-1.27.73-1.73m1.73.58c-.15 0-.3.06-.42.18-.12.12-.18.27-.18.42 0 .15.06.3.18.42.12.12.27.18.42.18.15 0 .3-.06.42-.18.12-.12.18-.27.18-.42 0-.15-.06-.3-.18-.42-.12-.12-.27-.18-.42-.18"/>
|
||||
<path d="M8 3.5c.28 0 .5.22.5.5v1c0 .28-.22.5-.5.5s-.5-.22-.5-.5v-1c0-.28.22-.5.5-.5"/>
|
||||
<path d="M10.5 8c0-.28.22-.5.5-.5h1c.28 0 .5.22.5.5s-.22.5-.5.5h-1c-.28 0-.5-.22-.5-.5"/>
|
||||
<path d="M8 12.5c-.28 0-.5.22-.5.5v1c0 .28.22.5.5.5s.5-.22.5-.5v-1c0-.28-.22-.5-.5-.5"/>
|
||||
<path d="M3.5 8c0 .28-.22.5-.5.5h-1c-.28 0-.5-.22-.5-.5s.22-.5.5-.5h1c.28 0 .5.22.5.5"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Добавление списка спутников</h3>
|
||||
</div>
|
||||
<p class="card-text">Добавьте новый список спутников в базу данных для последующего использования в загрузке данных.</p>
|
||||
<a href="{% url 'mainapp:add_sats' %}" class="btn btn-info">
|
||||
Добавить список спутников
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Transponders Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-warning bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-wifi text-warning" viewBox="0 0 16 16">
|
||||
<path d="M6.002 3.5a5.5 5.5 0 1 1 3.996 9.5H10A5.5 5.5 0 0 1 6.002 3.5M6.002 5.5a3.5 3.5 0 1 0 3.996 5.5H10A3.5 3.5 0 0 0 6.002 5.5"/>
|
||||
<path d="M10.5 12.5a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5.5.5 0 0 0-1 0 .5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5.5.5 0 0 0-1 0 .5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5 3.5 3.5 0 0 1 7 0"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Добавление транспондеров</h3>
|
||||
</div>
|
||||
<p class="card-text">Добавьте список транспондеров из JSON-файла в базу данных. Требуется наличие файла transponders.json.</p>
|
||||
<a href="{% url 'mainapp:add_trans' %}" class="btn btn-warning">
|
||||
Добавить транспондеры
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- VCH Load Data Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-danger bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-upload text-danger" viewBox="0 0 16 16">
|
||||
<path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5"/>
|
||||
<path d="M7.646 1.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V11.5a.5.5 0 0 1-1 0V2.707L5.354 4.854a.5.5 0 1 1-.708-.708z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Добавление данных ВЧ загрузки</h3>
|
||||
</div>
|
||||
<p class="card-text">Загрузите данные ВЧ загрузки из HTML-файла с таблицами. Поддерживается выбор спутника для привязки данных.</p>
|
||||
<a href="{% url 'mainapp:vch_load' %}" class="btn btn-danger">
|
||||
Добавить данные ВЧ загрузки
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lyngsat Data Fill Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-secondary bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-cloud-download text-secondary" viewBox="0 0 16 16">
|
||||
<path d="M4.406 1.342A5.53 5.53 0 0 1 8 0c2.69 0 4.923 2 5.166 4.579C14.758 4.804 16 6.137 16 7.773 16 9.569 14.502 11 12.687 11H10a.5.5 0 0 1 0-1h2.688C13.979 10 15 8.988 15 7.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 2.825 10.328 1 8 1a4.53 4.53 0 0 0-2.941 1.1c-.757.652-1.153 1.438-1.153 2.055v.448l-.445.049C2.064 4.805 1 5.952 1 7.318 1 8.785 2.23 10 3.781 10H6a.5.5 0 0 1 0 1H3.781C1.708 11 0 9.366 0 7.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383"/>
|
||||
<path d="M7.646 15.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 14.293V5.5a.5.5 0 0 0-1 0v8.793l-2.146-2.147a.5.5 0 0 0-.708.708z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Заполнение данных Lyngsat</h3>
|
||||
</div>
|
||||
<p class="card-text">Загрузите данные о транспондерах спутников с сайта Lyngsat. Выберите спутники и регионы для парсинга данных.</p>
|
||||
<a href="{% url 'mainapp:fill_lyngsat_data' %}" class="btn btn-secondary">
|
||||
Заполнить данные Lyngsat
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Calculation Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-info bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-calculator text-info" viewBox="0 0 16 16">
|
||||
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v4h2V2a1 1 0 0 0-1-1M5 6v1h1V6zm2 0v1h1V6zm2 0v1h1V6zm2 0v1h1V6zm1 2v1h1V8zm0 2v1h1v-1zm0 2v1h1v-1zm-8-6v8H3V8zm2 0v8h1V8zm2 0v8h1V8zm2 0v8h1V8z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Привязка ВЧ загрузки</h3>
|
||||
</div>
|
||||
<p class="card-text">Привязка ВЧ загрузки с sigma</p>
|
||||
<a href="{% url 'mainapp:link_vch_sigma' %}" class="btn btn-info">
|
||||
Открыть форму
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- New Event Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-success bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-plus-circle text-success" viewBox="0 0 16 16">
|
||||
<path d="M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0M4.5 7.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5M7.5 4.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 0 1h-1a.5.5 0 0 1-.5-.5m1 3a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-1 0v-3a.5.5 0 0 1 .5-.5"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Формирование таблицы для Кубсатов</h3>
|
||||
</div>
|
||||
<p class="card-text">Добавьте новое событие с помощью выбора спутника и загрузки файла данных.</p>
|
||||
<a href="{% url 'mainapp:kubsat_excel' %}" class="btn btn-success">
|
||||
Добавить событие
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,34 +1,34 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Загрузка данных из CSV{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-success text-white">
|
||||
<h2 class="mb-0">Загрузка данных из CSV</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
|
||||
<p class="card-text">Загрузите CSV-файл для загрузки данных в базу.</p>
|
||||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
|
||||
<!-- Form fields with Bootstrap styling -->
|
||||
{% include 'mainapp/components/_form_field.html' with field=form.file %}
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<a href="{% url 'mainapp:home' %}" class="btn btn-secondary me-md-2">Назад</a>
|
||||
<button type="submit" class="btn btn-success">Добавить в базу</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Загрузка данных из CSV{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-success text-white">
|
||||
<h2 class="mb-0">Загрузка данных из CSV</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
|
||||
<p class="card-text">Загрузите CSV-файл для загрузки данных в базу.</p>
|
||||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
|
||||
<!-- Form fields with Bootstrap styling -->
|
||||
{% include 'mainapp/components/_form_field.html' with field=form.file %}
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<a href="{% url 'mainapp:home' %}" class="btn btn-secondary me-md-2">Назад</a>
|
||||
<button type="submit" class="btn btn-success">Добавить в базу</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,36 +1,36 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Загрузка данных из Excel{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h2 class="mb-0">Загрузка данных из Excel</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
|
||||
<p class="card-text">Загрузите Excel-файл и выберите спутник для загрузки данных в базу.</p>
|
||||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
|
||||
<!-- Form fields with Bootstrap styling -->
|
||||
{% include 'mainapp/components/_form_field.html' with field=form.file %}
|
||||
{% include 'mainapp/components/_form_field.html' with field=form.sat_choice %}
|
||||
{% include 'mainapp/components/_form_field.html' with field=form.number_input %}
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<a href="{% url 'mainapp:home' %}" class="btn btn-secondary me-md-2">Назад</a>
|
||||
<button type="submit" class="btn btn-primary">Добавить в базу</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Загрузка данных из Excel{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h2 class="mb-0">Загрузка данных из Excel</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
|
||||
<p class="card-text">Загрузите Excel-файл и выберите спутник для загрузки данных в базу.</p>
|
||||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
|
||||
<!-- Form fields with Bootstrap styling -->
|
||||
{% include 'mainapp/components/_form_field.html' with field=form.file %}
|
||||
{% include 'mainapp/components/_form_field.html' with field=form.sat_choice %}
|
||||
{% include 'mainapp/components/_form_field.html' with field=form.number_input %}
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<a href="{% url 'mainapp:home' %}" class="btn btn-secondary me-md-2">Назад</a>
|
||||
<button type="submit" class="btn btn-primary">Добавить в базу</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,42 +1,42 @@
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<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>
|
||||
|
||||
<!-- Bootstrap Icons -->
|
||||
<link href="{% static 'bootstrap-icons/bootstrap-icons.css' %}" rel="stylesheet">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="{% static 'bootstrap/bootstrap.min.css' %}" rel="stylesheet">
|
||||
|
||||
<!-- Дополнительные стили -->
|
||||
{% block extra_css %}{% endblock %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Навигационная панель -->
|
||||
{% include 'mainapp/components/_navbar.html' %}
|
||||
|
||||
<!-- Сообщения -->
|
||||
<div class="container mt-3">
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
</div>
|
||||
|
||||
<!-- Основной контент -->
|
||||
<main class="{% if full_width_page %}container-fluid p-0{% else %}container mt-4{% endif %}">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="{% static 'bootstrap/bootstrap.bundle.min.js' %}" defer></script>
|
||||
|
||||
<!-- Дополнительные скрипты -->
|
||||
{% block extra_js %}{% endblock %}
|
||||
</body>
|
||||
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<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>
|
||||
|
||||
<!-- Bootstrap Icons -->
|
||||
<link href="{% static 'bootstrap-icons/bootstrap-icons.css' %}" rel="stylesheet">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="{% static 'bootstrap/bootstrap.min.css' %}" rel="stylesheet">
|
||||
|
||||
<!-- Дополнительные стили -->
|
||||
{% block extra_css %}{% endblock %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Навигационная панель -->
|
||||
{% include 'mainapp/components/_navbar.html' %}
|
||||
|
||||
<!-- Сообщения -->
|
||||
<div class="container mt-3">
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
</div>
|
||||
|
||||
<!-- Основной контент -->
|
||||
<main class="{% if full_width_page %}container-fluid p-0{% else %}container mt-4{% endif %}">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="{% static 'bootstrap/bootstrap.bundle.min.js' %}" defer></script>
|
||||
|
||||
<!-- Дополнительные скрипты -->
|
||||
{% block extra_js %}{% endblock %}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,33 +1,33 @@
|
||||
{% comment %}
|
||||
Переиспользуемый компонент для отображения полей формы
|
||||
Использование:
|
||||
{% include 'mainapp/components/_form_field.html' with field=form.field_name %}
|
||||
{% include 'mainapp/components/_form_field.html' with field=form.field_name label_class="custom-label" %}
|
||||
{% endcomment %}
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ field.id_for_label }}" class="form-label {% if label_class %}{{ label_class }}{% endif %}">
|
||||
{{ field.label }}
|
||||
{% if field.field.required %}<span class="text-danger">*</span>{% endif %}
|
||||
</label>
|
||||
|
||||
{% if field.field.widget.input_type == 'checkbox' %}
|
||||
<div class="form-check">
|
||||
{{ field }}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ field }}
|
||||
{% endif %}
|
||||
|
||||
{% if field.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{% for error in field.errors %}
|
||||
{{ error }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if field.help_text %}
|
||||
<small class="form-text text-muted">{{ field.help_text }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% comment %}
|
||||
Переиспользуемый компонент для отображения полей формы
|
||||
Использование:
|
||||
{% include 'mainapp/components/_form_field.html' with field=form.field_name %}
|
||||
{% include 'mainapp/components/_form_field.html' with field=form.field_name label_class="custom-label" %}
|
||||
{% endcomment %}
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ field.id_for_label }}" class="form-label {% if label_class %}{{ label_class }}{% endif %}">
|
||||
{{ field.label }}
|
||||
{% if field.field.required %}<span class="text-danger">*</span>{% endif %}
|
||||
</label>
|
||||
|
||||
{% if field.field.widget.input_type == 'checkbox' %}
|
||||
<div class="form-check">
|
||||
{{ field }}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ field }}
|
||||
{% endif %}
|
||||
|
||||
{% if field.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{% for error in field.errors %}
|
||||
{{ error }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if field.help_text %}
|
||||
<small class="form-text text-muted">{{ field.help_text }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
{% comment %}
|
||||
Переиспользуемый компонент для отображения сообщений Django
|
||||
Использование:
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
{% endcomment %}
|
||||
|
||||
{% if messages %}
|
||||
<div class="messages-container">
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{% if message.tags == 'error' %}
|
||||
<i class="bi bi-exclamation-triangle-fill me-2"></i>
|
||||
{% elif message.tags == 'success' %}
|
||||
<i class="bi bi-check-circle-fill me-2"></i>
|
||||
{% elif message.tags == 'warning' %}
|
||||
<i class="bi bi-exclamation-circle-fill me-2"></i>
|
||||
{% elif message.tags == 'info' %}
|
||||
<i class="bi bi-info-circle-fill me-2"></i>
|
||||
{% endif %}
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% comment %}
|
||||
Переиспользуемый компонент для отображения сообщений Django
|
||||
Использование:
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
{% endcomment %}
|
||||
|
||||
{% if messages %}
|
||||
<div class="messages-container">
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{% if message.tags == 'error' %}
|
||||
<i class="bi bi-exclamation-triangle-fill me-2"></i>
|
||||
{% elif message.tags == 'success' %}
|
||||
<i class="bi bi-check-circle-fill me-2"></i>
|
||||
{% elif message.tags == 'warning' %}
|
||||
<i class="bi bi-exclamation-circle-fill me-2"></i>
|
||||
{% elif message.tags == 'info' %}
|
||||
<i class="bi bi-info-circle-fill me-2"></i>
|
||||
{% endif %}
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -1,57 +1,57 @@
|
||||
{% comment %}
|
||||
Переиспользуемый компонент навигационной панели
|
||||
Использование:
|
||||
{% include 'mainapp/components/_navbar.html' %}
|
||||
{% endcomment %}
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="{% url 'mainapp:home' %}">Геолокация</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
{% if user.is_authenticated %}
|
||||
<ul class="navbar-nav me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'mainapp:home' %}">Объекты</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'mainapp:actions' %}">Действия</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'mapsapp:3dmap' %}">3D карта</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'mapsapp:2dmap' %}">2D карта</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'admin:index' %}">Админ панель</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown">
|
||||
{% if user.first_name and user.last_name %}
|
||||
{{ user.first_name }} {{ user.last_name }}
|
||||
{% elif user.get_full_name %}
|
||||
{{ user.get_full_name }}
|
||||
{% else %}
|
||||
{{ user.username }}
|
||||
{% endif %}
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end">
|
||||
<li><a class="dropdown-item" href="{% url 'logout' %}">Выйти</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
{% else %}
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'login' %}">Войти</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{% comment %}
|
||||
Переиспользуемый компонент навигационной панели
|
||||
Использование:
|
||||
{% include 'mainapp/components/_navbar.html' %}
|
||||
{% endcomment %}
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="{% url 'mainapp:home' %}">Геолокация</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
{% if user.is_authenticated %}
|
||||
<ul class="navbar-nav me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'mainapp:home' %}">Объекты</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'mainapp:actions' %}">Действия</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'mapsapp:3dmap' %}">3D карта</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'mapsapp:2dmap' %}">2D карта</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'admin:index' %}">Админ панель</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown">
|
||||
{% if user.first_name and user.last_name %}
|
||||
{{ user.first_name }} {{ user.last_name }}
|
||||
{% elif user.get_full_name %}
|
||||
{{ user.get_full_name }}
|
||||
{% else %}
|
||||
{{ user.username }}
|
||||
{% endif %}
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end">
|
||||
<li><a class="dropdown-item" href="{% url 'logout' %}">Выйти</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
{% else %}
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'login' %}">Войти</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
{% comment %}
|
||||
Переиспользуемый компонент для заголовков таблиц с сортировкой
|
||||
Использование:
|
||||
{% include 'mainapp/components/_table_header.html' with label="Имя" field="name" sort=sort %}
|
||||
{% include 'mainapp/components/_table_header.html' with label="Частота" field="frequency" sort=sort sortable=False %}
|
||||
{% endcomment %}
|
||||
|
||||
<th scope="col">
|
||||
{% if sortable != False %}
|
||||
<a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}sort={% if sort == field %}-{{ field }}{% elif sort == '-'|add:field %}{{ field }}{% else %}{{ field }}{% endif %}"
|
||||
class="text-white text-decoration-none d-inline-flex align-items-center">
|
||||
{{ label }}
|
||||
{% if sort == field %}
|
||||
<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" title="Сбросить сортировку">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</a>
|
||||
{% elif sort == '-'|add:field %}
|
||||
<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" title="Сбросить сортировку">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</a>
|
||||
{% else %}
|
||||
<i class="bi bi-arrow-down-up ms-1"></i>
|
||||
{% endif %}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ label }}
|
||||
{% endif %}
|
||||
</th>
|
||||
{% comment %}
|
||||
Переиспользуемый компонент для заголовков таблиц с сортировкой
|
||||
Использование:
|
||||
{% include 'mainapp/components/_table_header.html' with label="Имя" field="name" sort=sort %}
|
||||
{% include 'mainapp/components/_table_header.html' with label="Частота" field="frequency" sort=sort sortable=False %}
|
||||
{% endcomment %}
|
||||
|
||||
<th scope="col">
|
||||
{% if sortable != False %}
|
||||
<a href="?{% for key, value in request.GET.items %}{% if key != 'page' and key != 'sort' %}{{ key }}={{ value }}&{% endif %}{% endfor %}sort={% if sort == field %}-{{ field }}{% elif sort == '-'|add:field %}{{ field }}{% else %}{{ field }}{% endif %}"
|
||||
class="text-white text-decoration-none d-inline-flex align-items-center">
|
||||
{{ label }}
|
||||
{% if sort == field %}
|
||||
<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" title="Сбросить сортировку">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</a>
|
||||
{% elif sort == '-'|add:field %}
|
||||
<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" title="Сбросить сортировку">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</a>
|
||||
{% else %}
|
||||
<i class="bi bi-arrow-down-up ms-1"></i>
|
||||
{% endif %}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ label }}
|
||||
{% endif %}
|
||||
</th>
|
||||
|
||||
@@ -1,118 +1,118 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Заполнение данных Lyngsat{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h3 class="mb-0">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-cloud-download me-2" viewBox="0 0 16 16">
|
||||
<path d="M4.406 1.342A5.53 5.53 0 0 1 8 0c2.69 0 4.923 2 5.166 4.579C14.758 4.804 16 6.137 16 7.773 16 9.569 14.502 11 12.687 11H10a.5.5 0 0 1 0-1h2.688C13.979 10 15 8.988 15 7.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 2.825 10.328 1 8 1a4.53 4.53 0 0 0-2.941 1.1c-.757.652-1.153 1.438-1.153 2.055v.448l-.445.049C2.064 4.805 1 5.952 1 7.318 1 8.785 2.23 10 3.781 10H6a.5.5 0 0 1 0 1H3.781C1.708 11 0 9.366 0 7.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383"/>
|
||||
<path d="M7.646 15.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 14.293V5.5a.5.5 0 0 0-1 0v8.793l-2.146-2.147a.5.5 0 0 0-.708.708z"/>
|
||||
</svg>
|
||||
Заполнение данных из Lyngsat
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- Alert messages -->
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
|
||||
<div class="alert alert-info" role="alert">
|
||||
<strong>Внимание!</strong> Процесс заполнения данных может занять продолжительное время,
|
||||
так как выполняются запросы к внешнему сайту Lyngsat. Пожалуйста, дождитесь завершения операции.
|
||||
</div>
|
||||
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
|
||||
<!-- Satellites Selection -->
|
||||
<div class="mb-4">
|
||||
<label for="{{ form.satellites.id_for_label }}" class="form-label fw-bold">
|
||||
{{ form.satellites.label }}
|
||||
</label>
|
||||
{{ form.satellites }}
|
||||
{% if form.satellites.help_text %}
|
||||
<div class="form-text">{{ form.satellites.help_text }}</div>
|
||||
{% endif %}
|
||||
{% if form.satellites.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.satellites.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Regions Selection -->
|
||||
<div class="mb-4">
|
||||
<label for="{{ form.regions.id_for_label }}" class="form-label fw-bold">
|
||||
{{ form.regions.label }}
|
||||
</label>
|
||||
{{ form.regions }}
|
||||
{% if form.regions.help_text %}
|
||||
<div class="form-text">{{ form.regions.help_text }}</div>
|
||||
{% endif %}
|
||||
{% if form.regions.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.regions.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Buttons -->
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-between">
|
||||
<a href="{% url 'mainapp:actions' %}" class="btn btn-secondary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left me-1" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8"/>
|
||||
</svg>
|
||||
Назад
|
||||
</a>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-download me-1" viewBox="0 0 16 16">
|
||||
<path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5"/>
|
||||
<path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708z"/>
|
||||
</svg>
|
||||
Заполнить данные
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info Card -->
|
||||
<div class="card mt-4 shadow-sm">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Информация</h5>
|
||||
<p class="card-text">
|
||||
Эта форма позволяет загрузить данные о транспондерах спутников с сайта Lyngsat.
|
||||
Выберите один или несколько спутников и регионы для парсинга данных.
|
||||
</p>
|
||||
<ul>
|
||||
<li>Данные включают частоты, поляризацию, модуляцию, стандарты и другие параметры</li>
|
||||
<li>Процесс может занять несколько минут в зависимости от количества выбранных спутников</li>
|
||||
<li>Существующие записи будут обновлены, новые - созданы</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Form validation
|
||||
(function() {
|
||||
'use strict';
|
||||
var forms = document.querySelectorAll('.needs-validation');
|
||||
Array.prototype.slice.call(forms).forEach(function(form) {
|
||||
form.addEventListener('submit', function(event) {
|
||||
if (!form.checkValidity()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
form.classList.add('was-validated');
|
||||
}, false);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Заполнение данных Lyngsat{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h3 class="mb-0">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-cloud-download me-2" viewBox="0 0 16 16">
|
||||
<path d="M4.406 1.342A5.53 5.53 0 0 1 8 0c2.69 0 4.923 2 5.166 4.579C14.758 4.804 16 6.137 16 7.773 16 9.569 14.502 11 12.687 11H10a.5.5 0 0 1 0-1h2.688C13.979 10 15 8.988 15 7.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 2.825 10.328 1 8 1a4.53 4.53 0 0 0-2.941 1.1c-.757.652-1.153 1.438-1.153 2.055v.448l-.445.049C2.064 4.805 1 5.952 1 7.318 1 8.785 2.23 10 3.781 10H6a.5.5 0 0 1 0 1H3.781C1.708 11 0 9.366 0 7.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383"/>
|
||||
<path d="M7.646 15.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 14.293V5.5a.5.5 0 0 0-1 0v8.793l-2.146-2.147a.5.5 0 0 0-.708.708z"/>
|
||||
</svg>
|
||||
Заполнение данных из Lyngsat
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- Alert messages -->
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
|
||||
<div class="alert alert-info" role="alert">
|
||||
<strong>Внимание!</strong> Процесс заполнения данных может занять продолжительное время,
|
||||
так как выполняются запросы к внешнему сайту Lyngsat. Пожалуйста, дождитесь завершения операции.
|
||||
</div>
|
||||
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
|
||||
<!-- Satellites Selection -->
|
||||
<div class="mb-4">
|
||||
<label for="{{ form.satellites.id_for_label }}" class="form-label fw-bold">
|
||||
{{ form.satellites.label }}
|
||||
</label>
|
||||
{{ form.satellites }}
|
||||
{% if form.satellites.help_text %}
|
||||
<div class="form-text">{{ form.satellites.help_text }}</div>
|
||||
{% endif %}
|
||||
{% if form.satellites.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.satellites.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Regions Selection -->
|
||||
<div class="mb-4">
|
||||
<label for="{{ form.regions.id_for_label }}" class="form-label fw-bold">
|
||||
{{ form.regions.label }}
|
||||
</label>
|
||||
{{ form.regions }}
|
||||
{% if form.regions.help_text %}
|
||||
<div class="form-text">{{ form.regions.help_text }}</div>
|
||||
{% endif %}
|
||||
{% if form.regions.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.regions.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Buttons -->
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-between">
|
||||
<a href="{% url 'mainapp:actions' %}" class="btn btn-secondary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left me-1" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8"/>
|
||||
</svg>
|
||||
Назад
|
||||
</a>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-download me-1" viewBox="0 0 16 16">
|
||||
<path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5"/>
|
||||
<path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708z"/>
|
||||
</svg>
|
||||
Заполнить данные
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info Card -->
|
||||
<div class="card mt-4 shadow-sm">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Информация</h5>
|
||||
<p class="card-text">
|
||||
Эта форма позволяет загрузить данные о транспондерах спутников с сайта Lyngsat.
|
||||
Выберите один или несколько спутников и регионы для парсинга данных.
|
||||
</p>
|
||||
<ul>
|
||||
<li>Данные включают частоты, поляризацию, модуляцию, стандарты и другие параметры</li>
|
||||
<li>Процесс может занять несколько минут в зависимости от количества выбранных спутников</li>
|
||||
<li>Существующие записи будут обновлены, новые - созданы</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Form validation
|
||||
(function() {
|
||||
'use strict';
|
||||
var forms = document.querySelectorAll('.needs-validation');
|
||||
Array.prototype.slice.call(forms).forEach(function(form) {
|
||||
form.addEventListener('submit', function(event) {
|
||||
if (!form.checkValidity()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
form.classList.add('was-validated');
|
||||
}, false);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Привязка ВЧ{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-info text-white">
|
||||
<h2 class="mb-0">Привязка ВЧ загрузки</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert {{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<p class="card-text">Введите допустимый разброс для частоты и полосы</p>
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.sat_choice.id_for_label }}" class="form-label">Выберите спутник:</label>
|
||||
{{ form.sat_choice }}
|
||||
{% if form.sat_choice.errors %}
|
||||
<div class="text-danger mt-1">{{ form.sat_choice.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% comment %} <div class="mb-3">
|
||||
<label for="{{ form.ku_range.id_for_label }}" class="form-label">Выберите перенос по частоте(МГц):</label>
|
||||
{{ form.ku_range }}
|
||||
{% if form.ku_range.errors %}
|
||||
<div class="text-danger mt-1">{{ form.ku_range.errors }}</div>
|
||||
{% endif %}
|
||||
</div> {% endcomment %}
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.value1.id_for_label }}" class="form-label">Разброс по частоте(в МГц)</label>
|
||||
{{ form.value1 }}
|
||||
{% if form.value1.errors %}
|
||||
<div class="text-danger mt-1">{{ form.value1.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.value2.id_for_label }}" class="form-label">Разброс по полосе(в %)</label>
|
||||
{{ form.value2 }}
|
||||
{% if form.value2.errors %}
|
||||
<div class="text-danger mt-1">{{ form.value2.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<a href="{% url 'mainapp:home' %}" class="btn btn-secondary me-md-2">Назад</a>
|
||||
{% comment %} <a href="{% url 'mainapp:home' %}" class="btn btn-danger me-md-2">Сбросить привязку</a> {% endcomment %}
|
||||
<button type="submit" class="btn btn-info">Выполнить привязку</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Привязка ВЧ{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-info text-white">
|
||||
<h2 class="mb-0">Привязка ВЧ загрузки</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert {{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<p class="card-text">Введите допустимый разброс для частоты и полосы</p>
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.sat_choice.id_for_label }}" class="form-label">Выберите спутник:</label>
|
||||
{{ form.sat_choice }}
|
||||
{% if form.sat_choice.errors %}
|
||||
<div class="text-danger mt-1">{{ form.sat_choice.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% comment %} <div class="mb-3">
|
||||
<label for="{{ form.ku_range.id_for_label }}" class="form-label">Выберите перенос по частоте(МГц):</label>
|
||||
{{ form.ku_range }}
|
||||
{% if form.ku_range.errors %}
|
||||
<div class="text-danger mt-1">{{ form.ku_range.errors }}</div>
|
||||
{% endif %}
|
||||
</div> {% endcomment %}
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.value1.id_for_label }}" class="form-label">Разброс по частоте(в МГц)</label>
|
||||
{{ form.value1 }}
|
||||
{% if form.value1.errors %}
|
||||
<div class="text-danger mt-1">{{ form.value1.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.value2.id_for_label }}" class="form-label">Разброс по полосе(в %)</label>
|
||||
{{ form.value2 }}
|
||||
{% if form.value2.errors %}
|
||||
<div class="text-danger mt-1">{{ form.value2.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<a href="{% url 'mainapp:home' %}" class="btn btn-secondary me-md-2">Назад</a>
|
||||
{% comment %} <a href="{% url 'mainapp:home' %}" class="btn btn-danger me-md-2">Сбросить привязку</a> {% endcomment %}
|
||||
<button type="submit" class="btn btn-info">Выполнить привязку</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,241 +1,241 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Статус задачи Lyngsat{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h3 class="mb-0">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-hourglass-split me-2" viewBox="0 0 16 16">
|
||||
<path d="M2.5 15a.5.5 0 1 1 0-1h1v-1a4.5 4.5 0 0 1 2.557-4.06c.29-.139.443-.377.443-.59v-.7c0-.213-.154-.451-.443-.59A4.5 4.5 0 0 1 3.5 3V2h-1a.5.5 0 0 1 0-1h11a.5.5 0 0 1 0 1h-1v1a4.5 4.5 0 0 1-2.557 4.06c-.29.139-.443.377-.443.59v.7c0 .213.154.451.443.59A4.5 4.5 0 0 1 12.5 13v1h1a.5.5 0 0 1 0 1zm2-13v1c0 .537.12 1.045.337 1.5h6.326c.216-.455.337-.963.337-1.5V2zm3 6.35c0 .701-.478 1.236-1.011 1.492A3.5 3.5 0 0 0 4.5 13s.866-1.299 3-1.48zm1 0v3.17c2.134.181 3 1.48 3 1.48a3.5 3.5 0 0 0-1.989-3.158C8.978 9.586 8.5 9.052 8.5 8.351z"/>
|
||||
</svg>
|
||||
Статус задачи заполнения данных Lyngsat
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if task_id %}
|
||||
<div class="mb-3">
|
||||
<strong>ID задачи:</strong> <code id="task-id">{{ task_id }}</code>
|
||||
</div>
|
||||
|
||||
<!-- Progress Bar -->
|
||||
<div class="mb-4">
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<span id="status-text">Загрузка статуса...</span>
|
||||
<span id="progress-percent">0%</span>
|
||||
</div>
|
||||
<div class="progress" style="height: 25px;">
|
||||
<div id="progress-bar" class="progress-bar progress-bar-striped progress-bar-animated"
|
||||
role="progressbar" style="width: 0%;"
|
||||
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
|
||||
<span id="progress-text">0%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Task State -->
|
||||
<div id="task-state-container" class="alert alert-info" role="alert">
|
||||
<strong>Состояние:</strong> <span id="task-state">Проверка...</span>
|
||||
</div>
|
||||
|
||||
<!-- Results Container (hidden by default) -->
|
||||
<div id="results-container" class="d-none">
|
||||
<h5 class="mt-4">Результаты обработки</h5>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h6 class="card-subtitle mb-2 text-muted">Обработано спутников</h6>
|
||||
<h3 class="card-title" id="result-satellites">-</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h6 class="card-subtitle mb-2 text-muted">Обработано источников</h6>
|
||||
<h3 class="card-title" id="result-sources">-</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3 border-success">
|
||||
<div class="card-body">
|
||||
<h6 class="card-subtitle mb-2 text-success">Создано записей</h6>
|
||||
<h3 class="card-title text-success" id="result-created">-</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3 border-info">
|
||||
<div class="card-body">
|
||||
<h6 class="card-subtitle mb-2 text-info">Обновлено записей</h6>
|
||||
<h3 class="card-title text-info" id="result-updated">-</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Errors -->
|
||||
<div id="errors-container" class="d-none">
|
||||
<h6 class="text-danger">Ошибки при обработке:</h6>
|
||||
<div class="alert alert-warning">
|
||||
<ul id="errors-list" class="mb-0"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Error Container (hidden by default) -->
|
||||
<div id="error-container" class="alert alert-danger d-none" role="alert">
|
||||
<strong>Ошибка:</strong> <span id="error-text"></span>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-between mt-4">
|
||||
<a href="{% url 'mainapp:fill_lyngsat_data' %}" class="btn btn-secondary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left me-1" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8"/>
|
||||
</svg>
|
||||
Назад к форме
|
||||
</a>
|
||||
<a href="{% url 'mainapp:actions' %}" class="btn btn-outline-primary" id="actions-btn">
|
||||
Перейти к действиям
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
ID задачи не указан. Пожалуйста, запустите задачу через форму заполнения данных.
|
||||
</div>
|
||||
<a href="{% url 'mainapp:fill_lyngsat_data' %}" class="btn btn-primary">
|
||||
Перейти к форме
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if task_id %}
|
||||
<script>
|
||||
let taskId = '{{ task_id }}';
|
||||
let pollInterval;
|
||||
let isCompleted = false;
|
||||
|
||||
function updateProgress(data) {
|
||||
const statusText = document.getElementById('status-text');
|
||||
const progressBar = document.getElementById('progress-bar');
|
||||
const progressText = document.getElementById('progress-text');
|
||||
const progressPercent = document.getElementById('progress-percent');
|
||||
const taskState = document.getElementById('task-state');
|
||||
const taskStateContainer = document.getElementById('task-state-container');
|
||||
|
||||
// Update state
|
||||
taskState.textContent = data.state;
|
||||
|
||||
if (data.state === 'PENDING') {
|
||||
statusText.textContent = 'Задача в очереди...';
|
||||
taskStateContainer.className = 'alert alert-info';
|
||||
} else if (data.state === 'PROGRESS') {
|
||||
const percent = data.percent || 0;
|
||||
statusText.textContent = data.status || 'Обработка...';
|
||||
progressBar.style.width = percent + '%';
|
||||
progressBar.setAttribute('aria-valuenow', percent);
|
||||
progressText.textContent = percent + '%';
|
||||
progressPercent.textContent = percent + '%';
|
||||
taskStateContainer.className = 'alert alert-info';
|
||||
} else if (data.state === 'SUCCESS') {
|
||||
statusText.textContent = 'Задача завершена успешно!';
|
||||
progressBar.style.width = '100%';
|
||||
progressBar.setAttribute('aria-valuenow', 100);
|
||||
progressText.textContent = '100%';
|
||||
progressPercent.textContent = '100%';
|
||||
progressBar.classList.remove('progress-bar-animated');
|
||||
progressBar.classList.add('bg-success');
|
||||
taskStateContainer.className = 'alert alert-success';
|
||||
|
||||
// Show results
|
||||
if (data.result) {
|
||||
showResults(data.result);
|
||||
}
|
||||
|
||||
isCompleted = true;
|
||||
clearInterval(pollInterval);
|
||||
} else if (data.state === 'FAILURE') {
|
||||
statusText.textContent = 'Ошибка при выполнении задачи';
|
||||
progressBar.classList.remove('progress-bar-animated');
|
||||
progressBar.classList.add('bg-danger');
|
||||
taskStateContainer.className = 'alert alert-danger';
|
||||
|
||||
// Show error
|
||||
const errorContainer = document.getElementById('error-container');
|
||||
const errorText = document.getElementById('error-text');
|
||||
errorText.textContent = data.error || 'Неизвестная ошибка';
|
||||
errorContainer.classList.remove('d-none');
|
||||
|
||||
isCompleted = true;
|
||||
clearInterval(pollInterval);
|
||||
}
|
||||
}
|
||||
|
||||
function showResults(result) {
|
||||
const resultsContainer = document.getElementById('results-container');
|
||||
resultsContainer.classList.remove('d-none');
|
||||
|
||||
document.getElementById('result-satellites').textContent = result.total_satellites || 0;
|
||||
document.getElementById('result-sources').textContent = result.total_sources || 0;
|
||||
document.getElementById('result-created').textContent = result.created || 0;
|
||||
document.getElementById('result-updated').textContent = result.updated || 0;
|
||||
|
||||
// Show errors if any
|
||||
if (result.errors && result.errors.length > 0) {
|
||||
const errorsContainer = document.getElementById('errors-container');
|
||||
const errorsList = document.getElementById('errors-list');
|
||||
errorsContainer.classList.remove('d-none');
|
||||
|
||||
errorsList.innerHTML = '';
|
||||
result.errors.slice(0, 10).forEach(error => {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = error;
|
||||
errorsList.appendChild(li);
|
||||
});
|
||||
|
||||
if (result.errors.length > 10) {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = `И еще ${result.errors.length - 10} ошибок...`;
|
||||
li.className = 'text-muted';
|
||||
errorsList.appendChild(li);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkTaskStatus() {
|
||||
fetch(`/api/lyngsat-task-status/${taskId}/`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
updateProgress(data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error checking task status:', error);
|
||||
});
|
||||
}
|
||||
|
||||
// Start polling
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
checkTaskStatus();
|
||||
pollInterval = setInterval(checkTaskStatus, 2000); // Poll every 2 seconds
|
||||
|
||||
// Stop polling after 30 minutes
|
||||
setTimeout(() => {
|
||||
if (!isCompleted) {
|
||||
clearInterval(pollInterval);
|
||||
document.getElementById('status-text').textContent = 'Превышено время ожидания. Обновите страницу для проверки статуса.';
|
||||
}
|
||||
}, 30 * 60 * 1000);
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Статус задачи Lyngsat{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h3 class="mb-0">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-hourglass-split me-2" viewBox="0 0 16 16">
|
||||
<path d="M2.5 15a.5.5 0 1 1 0-1h1v-1a4.5 4.5 0 0 1 2.557-4.06c.29-.139.443-.377.443-.59v-.7c0-.213-.154-.451-.443-.59A4.5 4.5 0 0 1 3.5 3V2h-1a.5.5 0 0 1 0-1h11a.5.5 0 0 1 0 1h-1v1a4.5 4.5 0 0 1-2.557 4.06c-.29.139-.443.377-.443.59v.7c0 .213.154.451.443.59A4.5 4.5 0 0 1 12.5 13v1h1a.5.5 0 0 1 0 1zm2-13v1c0 .537.12 1.045.337 1.5h6.326c.216-.455.337-.963.337-1.5V2zm3 6.35c0 .701-.478 1.236-1.011 1.492A3.5 3.5 0 0 0 4.5 13s.866-1.299 3-1.48zm1 0v3.17c2.134.181 3 1.48 3 1.48a3.5 3.5 0 0 0-1.989-3.158C8.978 9.586 8.5 9.052 8.5 8.351z"/>
|
||||
</svg>
|
||||
Статус задачи заполнения данных Lyngsat
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if task_id %}
|
||||
<div class="mb-3">
|
||||
<strong>ID задачи:</strong> <code id="task-id">{{ task_id }}</code>
|
||||
</div>
|
||||
|
||||
<!-- Progress Bar -->
|
||||
<div class="mb-4">
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<span id="status-text">Загрузка статуса...</span>
|
||||
<span id="progress-percent">0%</span>
|
||||
</div>
|
||||
<div class="progress" style="height: 25px;">
|
||||
<div id="progress-bar" class="progress-bar progress-bar-striped progress-bar-animated"
|
||||
role="progressbar" style="width: 0%;"
|
||||
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
|
||||
<span id="progress-text">0%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Task State -->
|
||||
<div id="task-state-container" class="alert alert-info" role="alert">
|
||||
<strong>Состояние:</strong> <span id="task-state">Проверка...</span>
|
||||
</div>
|
||||
|
||||
<!-- Results Container (hidden by default) -->
|
||||
<div id="results-container" class="d-none">
|
||||
<h5 class="mt-4">Результаты обработки</h5>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h6 class="card-subtitle mb-2 text-muted">Обработано спутников</h6>
|
||||
<h3 class="card-title" id="result-satellites">-</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h6 class="card-subtitle mb-2 text-muted">Обработано источников</h6>
|
||||
<h3 class="card-title" id="result-sources">-</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3 border-success">
|
||||
<div class="card-body">
|
||||
<h6 class="card-subtitle mb-2 text-success">Создано записей</h6>
|
||||
<h3 class="card-title text-success" id="result-created">-</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3 border-info">
|
||||
<div class="card-body">
|
||||
<h6 class="card-subtitle mb-2 text-info">Обновлено записей</h6>
|
||||
<h3 class="card-title text-info" id="result-updated">-</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Errors -->
|
||||
<div id="errors-container" class="d-none">
|
||||
<h6 class="text-danger">Ошибки при обработке:</h6>
|
||||
<div class="alert alert-warning">
|
||||
<ul id="errors-list" class="mb-0"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Error Container (hidden by default) -->
|
||||
<div id="error-container" class="alert alert-danger d-none" role="alert">
|
||||
<strong>Ошибка:</strong> <span id="error-text"></span>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-between mt-4">
|
||||
<a href="{% url 'mainapp:fill_lyngsat_data' %}" class="btn btn-secondary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left me-1" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8"/>
|
||||
</svg>
|
||||
Назад к форме
|
||||
</a>
|
||||
<a href="{% url 'mainapp:actions' %}" class="btn btn-outline-primary" id="actions-btn">
|
||||
Перейти к действиям
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
ID задачи не указан. Пожалуйста, запустите задачу через форму заполнения данных.
|
||||
</div>
|
||||
<a href="{% url 'mainapp:fill_lyngsat_data' %}" class="btn btn-primary">
|
||||
Перейти к форме
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if task_id %}
|
||||
<script>
|
||||
let taskId = '{{ task_id }}';
|
||||
let pollInterval;
|
||||
let isCompleted = false;
|
||||
|
||||
function updateProgress(data) {
|
||||
const statusText = document.getElementById('status-text');
|
||||
const progressBar = document.getElementById('progress-bar');
|
||||
const progressText = document.getElementById('progress-text');
|
||||
const progressPercent = document.getElementById('progress-percent');
|
||||
const taskState = document.getElementById('task-state');
|
||||
const taskStateContainer = document.getElementById('task-state-container');
|
||||
|
||||
// Update state
|
||||
taskState.textContent = data.state;
|
||||
|
||||
if (data.state === 'PENDING') {
|
||||
statusText.textContent = 'Задача в очереди...';
|
||||
taskStateContainer.className = 'alert alert-info';
|
||||
} else if (data.state === 'PROGRESS') {
|
||||
const percent = data.percent || 0;
|
||||
statusText.textContent = data.status || 'Обработка...';
|
||||
progressBar.style.width = percent + '%';
|
||||
progressBar.setAttribute('aria-valuenow', percent);
|
||||
progressText.textContent = percent + '%';
|
||||
progressPercent.textContent = percent + '%';
|
||||
taskStateContainer.className = 'alert alert-info';
|
||||
} else if (data.state === 'SUCCESS') {
|
||||
statusText.textContent = 'Задача завершена успешно!';
|
||||
progressBar.style.width = '100%';
|
||||
progressBar.setAttribute('aria-valuenow', 100);
|
||||
progressText.textContent = '100%';
|
||||
progressPercent.textContent = '100%';
|
||||
progressBar.classList.remove('progress-bar-animated');
|
||||
progressBar.classList.add('bg-success');
|
||||
taskStateContainer.className = 'alert alert-success';
|
||||
|
||||
// Show results
|
||||
if (data.result) {
|
||||
showResults(data.result);
|
||||
}
|
||||
|
||||
isCompleted = true;
|
||||
clearInterval(pollInterval);
|
||||
} else if (data.state === 'FAILURE') {
|
||||
statusText.textContent = 'Ошибка при выполнении задачи';
|
||||
progressBar.classList.remove('progress-bar-animated');
|
||||
progressBar.classList.add('bg-danger');
|
||||
taskStateContainer.className = 'alert alert-danger';
|
||||
|
||||
// Show error
|
||||
const errorContainer = document.getElementById('error-container');
|
||||
const errorText = document.getElementById('error-text');
|
||||
errorText.textContent = data.error || 'Неизвестная ошибка';
|
||||
errorContainer.classList.remove('d-none');
|
||||
|
||||
isCompleted = true;
|
||||
clearInterval(pollInterval);
|
||||
}
|
||||
}
|
||||
|
||||
function showResults(result) {
|
||||
const resultsContainer = document.getElementById('results-container');
|
||||
resultsContainer.classList.remove('d-none');
|
||||
|
||||
document.getElementById('result-satellites').textContent = result.total_satellites || 0;
|
||||
document.getElementById('result-sources').textContent = result.total_sources || 0;
|
||||
document.getElementById('result-created').textContent = result.created || 0;
|
||||
document.getElementById('result-updated').textContent = result.updated || 0;
|
||||
|
||||
// Show errors if any
|
||||
if (result.errors && result.errors.length > 0) {
|
||||
const errorsContainer = document.getElementById('errors-container');
|
||||
const errorsList = document.getElementById('errors-list');
|
||||
errorsContainer.classList.remove('d-none');
|
||||
|
||||
errorsList.innerHTML = '';
|
||||
result.errors.slice(0, 10).forEach(error => {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = error;
|
||||
errorsList.appendChild(li);
|
||||
});
|
||||
|
||||
if (result.errors.length > 10) {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = `И еще ${result.errors.length - 10} ошибок...`;
|
||||
li.className = 'text-muted';
|
||||
errorsList.appendChild(li);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkTaskStatus() {
|
||||
fetch(`/api/lyngsat-task-status/${taskId}/`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
updateProgress(data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error checking task status:', error);
|
||||
});
|
||||
}
|
||||
|
||||
// Start polling
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
checkTaskStatus();
|
||||
pollInterval = setInterval(checkTaskStatus, 2000); // Poll every 2 seconds
|
||||
|
||||
// Stop polling after 30 minutes
|
||||
setTimeout(() => {
|
||||
if (!isCompleted) {
|
||||
clearInterval(pollInterval);
|
||||
document.getElementById('status-text').textContent = 'Превышено время ожидания. Обновите страницу для проверки статуса.';
|
||||
}
|
||||
}, 30 * 60 * 1000);
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,25 +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 'mainapp:home' %}" class="btn btn-secondary ms-2">Отмена</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% 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 'mainapp:home' %}" class="btn btn-secondary ms-2">Отмена</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,473 +1,473 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
{% load static %}
|
||||
{% load static leaflet_tags %}
|
||||
{% load l10n %}
|
||||
|
||||
{% block title %}Просмотр объекта: {{ object.name }}{% 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; }
|
||||
.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>Просмотр объекта: {{ object.name }}</h2>
|
||||
<div>
|
||||
<a href="{% url 'mainapp:objitem_list' %}{% if request.GET.urlencode %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-secondary btn-action">Назад</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Основная информация -->
|
||||
<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 class="form-label">Название:</label>
|
||||
<div class="readonly-field">{{ object.name|default:"-" }}</div>
|
||||
</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">
|
||||
<h4>ВЧ загрузка</h4>
|
||||
</div>
|
||||
|
||||
{% if object.parameter_obj %}
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Спутник:</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.id_satellite.name|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Частота (МГц):</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.frequency|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Полоса (МГц):</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.freq_range|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Поляризация:</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.polarization.name|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Символьная скорость:</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.bod_velocity|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Модуляция:</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.modulation.name|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">ОСШ:</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.snr|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Стандарт:</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.standard.name|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="mb-3">
|
||||
<p>Нет данных о ВЧ загрузке</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</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>
|
||||
|
||||
{% if object.geo_obj %}
|
||||
<!-- Координаты геолокации -->
|
||||
<div class="coord-sync-group">
|
||||
<div class="coord-group-header">Координаты геолокации</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Широта:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.geo_obj.coords %}{{ object.geo_obj.coords.y|floatformat:6 }}{% else %}-{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Долгота:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.geo_obj.coords %}{{ object.geo_obj.coords.x|floatformat:6 }}{% else %}-{% 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 class="form-label">Долгота:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.geo_obj.coords_kupsat %}{{ object.geo_obj.coords_kupsat.x|floatformat:6 }}{% 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.geo_obj.coords_kupsat %}{{ object.geo_obj.coords_kupsat.y|floatformat:6 }}{% else %}-{% endif %}
|
||||
</div>
|
||||
</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 class="form-label">Долгота:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.geo_obj.coords_valid %}{{ object.geo_obj.coords_valid.x|floatformat:6 }}{% 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.geo_obj.coords_valid %}{{ object.geo_obj.coords_valid.y|floatformat:6 }}{% else %}-{% endif %}
|
||||
</div>
|
||||
</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">{{ object.geo_obj.location|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Комментарий:</label>
|
||||
<div class="readonly-field">{{ object.geo_obj.comment|default:"-" }}</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.geo_obj.timestamp %}{{ object.geo_obj.timestamp|date:"d.m.Y H:i" }}{% else %}-{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-check-label">Усредненное значение:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.geo_obj.is_average %}Да{% else %}Нет{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
{% else %}
|
||||
<p>Нет данных о геолокации</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end mt-4">
|
||||
{% if user.customuser.role == 'admin' or user.customuser.role == 'moderator' %}
|
||||
<a href="{% url 'mainapp:objitem_update' object.id %}{% if request.GET.urlencode %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-primary btn-action">Редактировать</a>
|
||||
{% endif %}
|
||||
<a href="{% url 'mainapp:objitem_list' %}{% if request.GET.urlencode %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-secondary btn-action">Назад</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
{{ block.super }}
|
||||
<!-- Подключаем Leaflet и его плагины -->
|
||||
{% leaflet_js %}
|
||||
{% leaflet_css %}
|
||||
<script src="{% static 'leaflet-markers/js/leaflet-color-markers.js' %}"></script>
|
||||
|
||||
<script>
|
||||
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 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 markers = {};
|
||||
function createMarker(position, color, name) {
|
||||
const marker = L.marker(position, {
|
||||
draggable: false,
|
||||
icon: createMarkerIcon(color),
|
||||
title: name
|
||||
}).addTo(map);
|
||||
marker.bindPopup(name);
|
||||
return marker;
|
||||
}
|
||||
|
||||
// Получаем координаты из данных объекта
|
||||
{% if object.geo_obj and object.geo_obj.coords %}
|
||||
const geoLat = {{ object.geo_obj.coords.y|unlocalize }};
|
||||
const geoLng = {{ object.geo_obj.coords.x|unlocalize }};
|
||||
{% else %}
|
||||
const geoLat = 55.75;
|
||||
const geoLng = 37.62;
|
||||
{% endif %}
|
||||
|
||||
{% if object.geo_obj and object.geo_obj.coords_kupsat %}
|
||||
const kupsatLat = {{ object.geo_obj.coords_kupsat.y|unlocalize }};
|
||||
const kupsatLng = {{ object.geo_obj.coords_kupsat.x|unlocalize }};
|
||||
{% else %}
|
||||
const kupsatLat = 55.75;
|
||||
const kupsatLng = 37.61;
|
||||
{% endif %}
|
||||
|
||||
{% if object.geo_obj and object.geo_obj.coords_valid %}
|
||||
const validLat = {{ object.geo_obj.coords_valid.y|unlocalize }};
|
||||
const validLng = {{ object.geo_obj.coords_valid.x|unlocalize }};
|
||||
{% else %}
|
||||
const validLat = 55.75;
|
||||
const validLng = 37.63;
|
||||
{% endif %}
|
||||
|
||||
// Создаем маркеры
|
||||
markers.geo = createMarker(
|
||||
[geoLat, geoLng],
|
||||
colors.geo,
|
||||
'Геолокация'
|
||||
);
|
||||
|
||||
markers.kupsat = createMarker(
|
||||
[kupsatLat, kupsatLng],
|
||||
colors.kupsat,
|
||||
'Кубсат'
|
||||
);
|
||||
|
||||
markers.valid = createMarker(
|
||||
[validLat, validLng],
|
||||
colors.valid,
|
||||
'Оперативник'
|
||||
);
|
||||
|
||||
// Центрируем карту на первом маркере
|
||||
if (map.hasLayer(markers.geo)) {
|
||||
map.setView(markers.geo.getLatLng(), 10);
|
||||
}
|
||||
|
||||
// Легенда
|
||||
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 = `
|
||||
<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>
|
||||
`;
|
||||
return div;
|
||||
};
|
||||
|
||||
legend.addTo(map);
|
||||
});
|
||||
</script>
|
||||
{% extends 'mainapp/base.html' %}
|
||||
{% load static %}
|
||||
{% load static leaflet_tags %}
|
||||
{% load l10n %}
|
||||
|
||||
{% block title %}Просмотр объекта: {{ object.name }}{% 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; }
|
||||
.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>Просмотр объекта: {{ object.name }}</h2>
|
||||
<div>
|
||||
<a href="{% url 'mainapp:objitem_list' %}{% if request.GET.urlencode %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-secondary btn-action">Назад</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Основная информация -->
|
||||
<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 class="form-label">Название:</label>
|
||||
<div class="readonly-field">{{ object.name|default:"-" }}</div>
|
||||
</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">
|
||||
<h4>ВЧ загрузка</h4>
|
||||
</div>
|
||||
|
||||
{% if object.parameter_obj %}
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Спутник:</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.id_satellite.name|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Частота (МГц):</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.frequency|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Полоса (МГц):</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.freq_range|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Поляризация:</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.polarization.name|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Символьная скорость:</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.bod_velocity|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Модуляция:</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.modulation.name|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">ОСШ:</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.snr|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Стандарт:</label>
|
||||
<div class="readonly-field">{{ object.parameter_obj.standard.name|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="mb-3">
|
||||
<p>Нет данных о ВЧ загрузке</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</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>
|
||||
|
||||
{% if object.geo_obj %}
|
||||
<!-- Координаты геолокации -->
|
||||
<div class="coord-sync-group">
|
||||
<div class="coord-group-header">Координаты геолокации</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Широта:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.geo_obj.coords %}{{ object.geo_obj.coords.y|floatformat:6 }}{% else %}-{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Долгота:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.geo_obj.coords %}{{ object.geo_obj.coords.x|floatformat:6 }}{% else %}-{% 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 class="form-label">Долгота:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.geo_obj.coords_kupsat %}{{ object.geo_obj.coords_kupsat.x|floatformat:6 }}{% 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.geo_obj.coords_kupsat %}{{ object.geo_obj.coords_kupsat.y|floatformat:6 }}{% else %}-{% endif %}
|
||||
</div>
|
||||
</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 class="form-label">Долгота:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.geo_obj.coords_valid %}{{ object.geo_obj.coords_valid.x|floatformat:6 }}{% 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.geo_obj.coords_valid %}{{ object.geo_obj.coords_valid.y|floatformat:6 }}{% else %}-{% endif %}
|
||||
</div>
|
||||
</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">{{ object.geo_obj.location|default:"-" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Комментарий:</label>
|
||||
<div class="readonly-field">{{ object.geo_obj.comment|default:"-" }}</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.geo_obj.timestamp %}{{ object.geo_obj.timestamp|date:"d.m.Y H:i" }}{% else %}-{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-check-label">Усредненное значение:</label>
|
||||
<div class="readonly-field">
|
||||
{% if object.geo_obj.is_average %}Да{% else %}Нет{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
{% else %}
|
||||
<p>Нет данных о геолокации</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end mt-4">
|
||||
{% if user.customuser.role == 'admin' or user.customuser.role == 'moderator' %}
|
||||
<a href="{% url 'mainapp:objitem_update' object.id %}{% if request.GET.urlencode %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-primary btn-action">Редактировать</a>
|
||||
{% endif %}
|
||||
<a href="{% url 'mainapp:objitem_list' %}{% if request.GET.urlencode %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-secondary btn-action">Назад</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
{{ block.super }}
|
||||
<!-- Подключаем Leaflet и его плагины -->
|
||||
{% leaflet_js %}
|
||||
{% leaflet_css %}
|
||||
<script src="{% static 'leaflet-markers/js/leaflet-color-markers.js' %}"></script>
|
||||
|
||||
<script>
|
||||
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 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 markers = {};
|
||||
function createMarker(position, color, name) {
|
||||
const marker = L.marker(position, {
|
||||
draggable: false,
|
||||
icon: createMarkerIcon(color),
|
||||
title: name
|
||||
}).addTo(map);
|
||||
marker.bindPopup(name);
|
||||
return marker;
|
||||
}
|
||||
|
||||
// Получаем координаты из данных объекта
|
||||
{% if object.geo_obj and object.geo_obj.coords %}
|
||||
const geoLat = {{ object.geo_obj.coords.y|unlocalize }};
|
||||
const geoLng = {{ object.geo_obj.coords.x|unlocalize }};
|
||||
{% else %}
|
||||
const geoLat = 55.75;
|
||||
const geoLng = 37.62;
|
||||
{% endif %}
|
||||
|
||||
{% if object.geo_obj and object.geo_obj.coords_kupsat %}
|
||||
const kupsatLat = {{ object.geo_obj.coords_kupsat.y|unlocalize }};
|
||||
const kupsatLng = {{ object.geo_obj.coords_kupsat.x|unlocalize }};
|
||||
{% else %}
|
||||
const kupsatLat = 55.75;
|
||||
const kupsatLng = 37.61;
|
||||
{% endif %}
|
||||
|
||||
{% if object.geo_obj and object.geo_obj.coords_valid %}
|
||||
const validLat = {{ object.geo_obj.coords_valid.y|unlocalize }};
|
||||
const validLng = {{ object.geo_obj.coords_valid.x|unlocalize }};
|
||||
{% else %}
|
||||
const validLat = 55.75;
|
||||
const validLng = 37.63;
|
||||
{% endif %}
|
||||
|
||||
// Создаем маркеры
|
||||
markers.geo = createMarker(
|
||||
[geoLat, geoLng],
|
||||
colors.geo,
|
||||
'Геолокация'
|
||||
);
|
||||
|
||||
markers.kupsat = createMarker(
|
||||
[kupsatLat, kupsatLng],
|
||||
colors.kupsat,
|
||||
'Кубсат'
|
||||
);
|
||||
|
||||
markers.valid = createMarker(
|
||||
[validLat, validLng],
|
||||
colors.valid,
|
||||
'Оперативник'
|
||||
);
|
||||
|
||||
// Центрируем карту на первом маркере
|
||||
if (map.hasLayer(markers.geo)) {
|
||||
map.setView(markers.geo.getLatLng(), 10);
|
||||
}
|
||||
|
||||
// Легенда
|
||||
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 = `
|
||||
<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>
|
||||
`;
|
||||
return div;
|
||||
};
|
||||
|
||||
legend.addTo(map);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,52 +1,52 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Новое событие{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-header bg-success text-white">
|
||||
<h2 class="mb-0">Формирование таблицы Кубсат</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{% comment%}
|
||||
<div class="mb-4">
|
||||
<label for="{{ form.sat_choice.id_for_label }}" class="form-label">{{ form.sat_choice.label }}</label>
|
||||
{{ form.sat_choice }}
|
||||
{% if form.sat_choice.errors %}
|
||||
<div class="text-danger mt-1">{{ form.sat_choice.errors }}</div>
|
||||
{% endif %}
|
||||
</div>{% endcomment %}
|
||||
|
||||
{% comment %} <div class="mb-4">
|
||||
<label for="{{ form.pol_choice.id_for_label }}" class="form-label">{{ form.pol_choice.label }}</label>
|
||||
{{ form.pol_choice }}
|
||||
{% if form.pol_choice.errors %}
|
||||
<div class="text-danger mt-1">{{ form.pol_choice.errors }}</div>
|
||||
{% endif %}
|
||||
</div> {% endcomment %}
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="{{ form.file.id_for_label }}" class="form-label">{{ form.file.label }}</label>
|
||||
{{ form.file }}
|
||||
{% if form.file.errors %}
|
||||
<div class="text-danger mt-1">{{ form.file.errors }}</div>
|
||||
{% endif %}
|
||||
<div class="form-text">Выберите файл для загрузки</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<a href="{% url 'mainapp:home' %}" class="btn btn-secondary">Назад</a>
|
||||
<button type="submit" class="btn btn-success">Выполнить</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Новое событие{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-header bg-success text-white">
|
||||
<h2 class="mb-0">Формирование таблицы Кубсат</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{% comment%}
|
||||
<div class="mb-4">
|
||||
<label for="{{ form.sat_choice.id_for_label }}" class="form-label">{{ form.sat_choice.label }}</label>
|
||||
{{ form.sat_choice }}
|
||||
{% if form.sat_choice.errors %}
|
||||
<div class="text-danger mt-1">{{ form.sat_choice.errors }}</div>
|
||||
{% endif %}
|
||||
</div>{% endcomment %}
|
||||
|
||||
{% comment %} <div class="mb-4">
|
||||
<label for="{{ form.pol_choice.id_for_label }}" class="form-label">{{ form.pol_choice.label }}</label>
|
||||
{{ form.pol_choice }}
|
||||
{% if form.pol_choice.errors %}
|
||||
<div class="text-danger mt-1">{{ form.pol_choice.errors }}</div>
|
||||
{% endif %}
|
||||
</div> {% endcomment %}
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="{{ form.file.id_for_label }}" class="form-label">{{ form.file.label }}</label>
|
||||
{{ form.file }}
|
||||
{% if form.file.errors %}
|
||||
<div class="text-danger mt-1">{{ form.file.errors }}</div>
|
||||
{% endif %}
|
||||
<div class="form-text">Выберите файл для загрузки</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<a href="{% url 'mainapp:home' %}" class="btn btn-secondary">Назад</a>
|
||||
<button type="submit" class="btn btn-success">Выполнить</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,53 +1,53 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Загрузка данных транспондеров{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-warning text-white">
|
||||
<h2 class="mb-0">Загрузка данных транспондеров из CellNet</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert {{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<p class="card-text">Загрузите xml-файл и выберите спутник для загрузки данных в базу.</p>
|
||||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.file.id_for_label }}" class="form-label">Выберите xml файл:</label>
|
||||
{{ form.file }}
|
||||
{% if form.file.errors %}
|
||||
<div class="text-danger mt-1">{{ form.file.errors }}</div>
|
||||
{% endif %}
|
||||
<div class="form-text">Загрузите xml-файл (.xml) с данными для обработки</div>
|
||||
</div>
|
||||
|
||||
{% comment %} <div class="mb-3">
|
||||
<label for="{{ form.sat_choice.id_for_label }}" class="form-label">Выберите спутник:</label>
|
||||
{{ form.sat_choice }}
|
||||
{% if form.sat_choice.errors %}
|
||||
<div class="text-danger mt-1">{{ form.sat_choice.errors }}</div>
|
||||
{% endif %}
|
||||
</div> {% endcomment %}
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<a href="{% url 'mainapp:home' %}" class="btn btn-secondary me-md-2">Назад</a>
|
||||
<button type="submit" class="btn btn-warning">Добавить в базу</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Загрузка данных транспондеров{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-warning text-white">
|
||||
<h2 class="mb-0">Загрузка данных транспондеров из CellNet</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert {{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<p class="card-text">Загрузите xml-файл и выберите спутник для загрузки данных в базу.</p>
|
||||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.file.id_for_label }}" class="form-label">Выберите xml файл:</label>
|
||||
{{ form.file }}
|
||||
{% if form.file.errors %}
|
||||
<div class="text-danger mt-1">{{ form.file.errors }}</div>
|
||||
{% endif %}
|
||||
<div class="form-text">Загрузите xml-файл (.xml) с данными для обработки</div>
|
||||
</div>
|
||||
|
||||
{% comment %} <div class="mb-3">
|
||||
<label for="{{ form.sat_choice.id_for_label }}" class="form-label">Выберите спутник:</label>
|
||||
{{ form.sat_choice }}
|
||||
{% if form.sat_choice.errors %}
|
||||
<div class="text-danger mt-1">{{ form.sat_choice.errors }}</div>
|
||||
{% endif %}
|
||||
</div> {% endcomment %}
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<a href="{% url 'mainapp:home' %}" class="btn btn-secondary me-md-2">Назад</a>
|
||||
<button type="submit" class="btn btn-warning">Добавить в базу</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,56 +1,56 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Загрузка данных ВЧ загрузки{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-danger text-white">
|
||||
<h2 class="mb-0">Загрузка данных ВЧ загрузки</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert {{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<p class="card-text">Загрузите HTML-файл с таблицами данных ВЧ загрузки и выберите спутник для привязки данных.</p>
|
||||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
|
||||
<!-- Form fields with Bootstrap styling -->
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.file.id_for_label }}" class="form-label">Выберите HTML файл:</label>
|
||||
{{ form.file }}
|
||||
{% if form.file.errors %}
|
||||
<div class="text-danger mt-1">{{ form.file.errors }}</div>
|
||||
{% endif %}
|
||||
<div class="form-text">Загрузите HTML-файл, содержащий таблицы с данными ВЧ загрузки</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.sat_choice.id_for_label }}" class="form-label">Выберите спутник:</label>
|
||||
{{ form.sat_choice }}
|
||||
{% if form.sat_choice.errors %}
|
||||
<div class="text-danger mt-1">{{ form.sat_choice.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<a href="{% url 'mainapp:home' %}" class="btn btn-secondary me-md-2">Назад</a>
|
||||
<button type="submit" class="btn btn-danger">Обработать файл</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Загрузка данных ВЧ загрузки{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-danger text-white">
|
||||
<h2 class="mb-0">Загрузка данных ВЧ загрузки</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert {{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<p class="card-text">Загрузите HTML-файл с таблицами данных ВЧ загрузки и выберите спутник для привязки данных.</p>
|
||||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
|
||||
<!-- Form fields with Bootstrap styling -->
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.file.id_for_label }}" class="form-label">Выберите HTML файл:</label>
|
||||
{{ form.file }}
|
||||
{% if form.file.errors %}
|
||||
<div class="text-danger mt-1">{{ form.file.errors }}</div>
|
||||
{% endif %}
|
||||
<div class="form-text">Загрузите HTML-файл, содержащий таблицы с данными ВЧ загрузки</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.sat_choice.id_for_label }}" class="form-label">Выберите спутник:</label>
|
||||
{{ form.sat_choice }}
|
||||
{% if form.sat_choice.errors %}
|
||||
<div class="text-danger mt-1">{{ form.sat_choice.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<a href="{% url 'mainapp:home' %}" class="btn btn-secondary me-md-2">Назад</a>
|
||||
<button type="submit" class="btn btn-danger">Обработать файл</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user