Files
DevOpsLab/app/templates/pages/roles/list.html
Сергей Антропов 1fbf9185a2 feat: добавлена пометка типа операции (Build/Push) в истории сборок Dockerfile
- Добавлена колонка 'Тип' во все таблицы истории сборок
- Для push операций отображается registry вместо платформ
- Сохранение пользователя при создании push лога
- Исправлена ошибка с logger в push_docker_image endpoint
- Улучшено отображение истории сборок с визуальными индикаторами
2026-02-15 22:59:02 +03:00

249 lines
12 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends "base.html" %}
{% block title %}Роли - DevOpsLab{% endblock %}
{% block page_title %}Роли Ansible{% endblock %}
{% block header_actions %}
<a href="/roles/create" class="btn btn-primary btn-sm">
<i class="fas fa-plus me-2"></i>
Создать роль
</a>
{% endblock %}
{% block content %}
<!-- Поиск и фильтры -->
<div class="card mb-3">
<div class="card-body">
<form method="get" action="/roles" class="row g-3">
<div class="col-12 col-md-8">
<input
type="text"
name="search"
value="{{ search }}"
placeholder="Поиск по имени или описанию..."
class="form-control"
>
</div>
<div class="col-12 col-md-4">
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">
<i class="fas fa-search me-1"></i>
Поиск
</button>
{% if search %}
<a href="/roles" class="btn btn-outline-secondary">
<i class="fas fa-times me-1"></i>
Сброс
</a>
{% endif %}
</div>
</div>
</form>
</div>
</div>
<!-- Таблица ролей -->
<div class="card mb-3">
<div class="card-header">
<div class="d-flex justify-content-between align-items-center">
<h5 class="mb-0">Список ролей</h5>
<span class="text-muted small">
Всего: <strong>{{ total }}</strong>
</span>
</div>
</div>
<div class="card-body p-0">
{% if roles %}
<div class="table-responsive">
<table class="table table-hover mb-0 align-middle">
<thead class="table-light">
<tr>
<th style="width: 20%;">Имя роли</th>
<th style="width: 30%;">Описание</th>
<th style="width: 20%;">Компоненты</th>
<th style="width: 20%;">Платформы</th>
<th style="width: auto; min-width: 140px;">Действия</th>
</tr>
</thead>
<tbody>
{% for role in roles %}
<tr>
<td>
<a href="/roles/{{ role.name }}" class="text-decoration-none fw-semibold text-primary">
<i class="fas fa-cube me-1"></i>
{{ role.name }}
</a>
</td>
<td>
<span class="text-muted small">
{% if role.description %}
{{ role.description[:80] }}{% if role.description|length > 80 %}...{% endif %}
{% else %}
<span class="text-muted fst-italic">Нет описания</span>
{% endif %}
</span>
</td>
<td>
<div class="d-flex flex-wrap gap-1">
{% if role.has_tasks %}
<span class="badge bg-success" title="Tasks - задачи роли">
<i class="fas fa-tasks me-1"></i>Tasks
</span>
{% endif %}
{% if role.has_defaults %}
<span class="badge bg-info" title="Defaults - значения по умолчанию">
<i class="fas fa-sliders-h me-1"></i>Defaults
</span>
{% endif %}
{% if role.has_handlers %}
<span class="badge bg-warning text-dark" title="Handlers - обработчики">
<i class="fas fa-bell me-1"></i>Handlers
</span>
{% endif %}
{% if role.has_meta %}
<span class="badge bg-primary" title="Meta - метаданные роли">
<i class="fas fa-info-circle me-1"></i>Meta
</span>
{% endif %}
{% if not role.has_tasks and not role.has_defaults and not role.has_handlers and not role.has_meta %}
<span class="badge bg-secondary">Пустая роль</span>
{% endif %}
</div>
</td>
<td>
{% if role.platforms and role.platforms|length > 0 %}
<div class="d-flex flex-wrap gap-1">
{% for platform in role.platforms[:4] %}
<span class="badge bg-dark" title="{{ platform.name }}{% if platform.versions %} ({{ platform.versions|join(', ') }}){% endif %}">
<i class="fab fa-linux me-1"></i>
{{ platform.name }}
</span>
{% endfor %}
{% if role.platforms|length > 4 %}
<span class="badge bg-secondary" title="Ещё {{ role.platforms|length - 4 }} платформ">
+{{ role.platforms|length - 4 }}
</span>
{% endif %}
</div>
{% else %}
<span class="text-muted small fst-italic">Не указаны</span>
{% endif %}
</td>
<td>
<div class="btn-group btn-group-sm" role="group">
<a
href="/roles/{{ role.name }}/test"
class="btn btn-outline-success"
title="Запустить тест"
>
<i class="fas fa-vial"></i>
</a>
<a
href="/roles/{{ role.name }}/edit"
class="btn btn-outline-primary"
title="Редактировать"
>
<i class="fas fa-edit"></i>
</a>
<a
href="/roles/{{ role.name }}"
class="btn btn-outline-secondary"
title="Детали"
>
<i class="fas fa-info-circle"></i>
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-5">
<i class="fas fa-inbox fa-3x text-muted mb-3"></i>
<p class="text-muted mb-3">Роли не найдены</p>
<a href="/roles/create" class="btn btn-primary">
<i class="fas fa-plus me-2"></i>
Создать первую роль
</a>
</div>
{% endif %}
</div>
{% if roles and total_pages > 1 %}
<div class="card-footer">
<div class="d-flex justify-content-between align-items-center flex-wrap gap-3">
<!-- Пагинация -->
<nav aria-label="Навигация по страницам">
<ul class="pagination mb-0">
{% if page > 1 %}
<li class="page-item">
<a class="page-link" href="?page={{ page - 1 }}{% if search %}&search={{ search }}{% endif %}">
<i class="fas fa-chevron-left"></i>
</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link">
<i class="fas fa-chevron-left"></i>
</span>
</li>
{% endif %}
{% for p in range(1, total_pages + 1) %}
{% if p == page %}
<li class="page-item active">
<span class="page-link">{{ p }}</span>
</li>
{% elif p == 1 or p == total_pages or (p >= page - 2 and p <= page + 2) %}
<li class="page-item">
<a class="page-link" href="?page={{ p }}{% if search %}&search={{ search }}{% endif %}">{{ p }}</a>
</li>
{% elif p == page - 3 or p == page + 3 %}
<li class="page-item disabled">
<span class="page-link">...</span>
</li>
{% endif %}
{% endfor %}
{% if page < total_pages %}
<li class="page-item">
<a class="page-link" href="?page={{ page + 1 }}{% if search %}&search={{ search }}{% endif %}">
<i class="fas fa-chevron-right"></i>
</a>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link">
<i class="fas fa-chevron-right"></i>
</span>
</li>
{% endif %}
</ul>
</nav>
<!-- Выбор количества на странице -->
<div class="d-flex align-items-center gap-2">
<span class="text-muted small">На странице:</span>
<select
class="form-select form-select-sm pagination-per-page-select"
style="width: auto;"
onchange="window.location.href = '?page=1&per_page=' + this.value + '{% if search %}&search={{ search }}{% endif %}'"
>
<option value="10" {% if per_page == 10 %}selected{% endif %}>10</option>
<option value="25" {% if per_page == 25 %}selected{% endif %}>25</option>
<option value="50" {% if per_page == 50 %}selected{% endif %}>50</option>
<option value="100" {% if per_page == 100 %}selected{% endif %}>100</option>
</select>
</div>
<!-- Информация о странице -->
<div class="text-muted small">
Показано {{ ((page - 1) * per_page) + 1 }} - {{ [page * per_page, total]|min }} из {{ total }}
</div>
</div>
</div>
{% endif %}
</div>
{% endblock %}