v1.4.0: fix #43, #31, #29, #49, #33 + shared templating

This commit is contained in:
2026-05-20 20:08:25 +03:00
parent ca4d00c895
commit 64991f0228
63 changed files with 5005 additions and 45 deletions
@@ -0,0 +1,55 @@
{% extends "page.html" %}
{% block page_content %}
<div class="card">
<div class="card-header"><h2>Инциденты</h2>
{% if user.role in ['owner','engineer'] %}
<button class="btn btn-primary btn-sm" onclick="document.getElementById('modal-incident').classList.add('open')">+ Создать</button>
{% endif %}
</div>
<form method="get" class="filter-bar">
<select name="severity" onchange="this.form.submit()"><option value="">Все важности</option><option value="P1" {% if severity == 'P1' %}selected{% endif %}>P1 — Критичный</option><option value="P2" {% if severity == 'P2' %}selected{% endif %}>P2 — Высокий</option><option value="P3" {% if severity == 'P3' %}selected{% endif %}>P3 — Средний</option></select>
<select name="status_filter" onchange="this.form.submit()"><option value="">Все статусы</option><option value="open" {% if status_filter == 'open' %}selected{% endif %}>Открыт</option><option value="in_progress" {% if status_filter == 'in_progress' %}selected{% endif %}>В работе</option><option value="resolved" {% if status_filter == 'resolved' %}selected{% endif %}>Решён</option></select>
</form>
<div class="table-wrap"><table><thead><tr><th>Важность</th><th>Название</th><th>Объект</th><th>Исполнитель</th><th>Статус</th><th>Создан</th><th class="actions"></th></tr></thead>
<tbody>{% for i in incidents %}<tr>
<td><span class="badge badge-{{ {'P1':'critical','P2':'high','P3':'medium'}[i.severity] }}">{{ i.severity }}</span></td>
<td>{{ i.title }}</td><td>{{ i.object.name if i.object else '' }}</td>
<td>{{ i.assignee.full_name if i.assignee else '' }}</td>
<td><span class="badge badge-{{ i.status }}">{{ {'open':'Открыт','in_progress':'В работе','resolved':'Решён','closed':'Закрыт'}[i.status] }}</span></td>
<td><small>{{ i.created_at.strftime('%d.%m.%Y') if i.created_at else '' }}</small></td>
<td class="actions">{% if i.status in ['open','in_progress'] %}
<button class="btn btn-success btn-sm" onclick="resolveIncident({{ i.id }})">✓ Решить</button>
{% endif %}
</td>
</tr>{% endfor %}</tbody></table>
</div>
</div>
<div class="modal-overlay" id="modal-incident"><div class="modal">
<button type="button" class="modal-close" onclick="this.closest('.modal-overlay').classList.remove('open')"></button>
<h2>Новый инцидент</h2>
<form method="post" action="/service/incidents/create">
<div class="form-group"><label>Название</label><input type="text" name="title" required></div>
<div class="form-group"><label>Описание</label><textarea name="description"></textarea></div>
<div class="form-row">
<div class="form-group"><label>Объект</label><select name="object_id" required>{% for o in objects %}<option value="{{ o.id }}">{{ o.name }}</option>{% endfor %}</select></div>
<div class="form-group"><label>Исполнитель</label><select name="assigned_to"><option value=""></option>{% for u in users %}<option value="{{ u.id }}">{{ u.full_name }}</option>{% endfor %}</select></div>
</div>
<div class="form-group"><label>Важность</label><select name="severity"><option value="P3">P3 — Средний</option><option value="P1">P1 — Критичный</option><option value="P2">P2 — Высокий</option></select></div>
<div class="form-actions"><button type="submit" class="btn btn-primary">Создать</button>
<button type="button" class="btn btn-secondary" onclick="this.closest('.modal-overlay').classList.remove('open')">Отмена</button></div>
</form>
</div></div>
<div class="modal-overlay" id="modal-resolve"><div class="modal">
<button type="button" class="modal-close" onclick="this.closest('.modal-overlay').classList.remove('open')"></button>
<h2>Решение инцидента</h2>
<form method="post" action="/service/incidents/resolve">
<input type="hidden" name="id" id="resolve-id">
<div class="form-group"><label>Описание решения</label><textarea name="resolution" required></textarea></div>
<div class="form-actions"><button type="submit" class="btn btn-success">Подтвердить</button>
<button type="button" class="btn btn-secondary" onclick="this.closest('.modal-overlay').classList.remove('open')">Отмена</button></div>
</form>
</div></div>
<script>
function resolveIncident(id){ document.getElementById('resolve-id').value = id; document.getElementById('modal-resolve').classList.add('open'); }
</script>
{% endblock %}