Files
KindClustersDashboard/app/templates/dashboard.html
T
Sergey Antropoff 8bd44adbb0 Панель: журнал заданий, pull --progress plain, PTY/EIO, старт/стоп в фоне, очистка jobs
- Фоновые stop/start с job_id и poll; отмена с kill; docker pull plain + снятие ANSI
- Лимиты журнала API/буфера; список jobs без progress_log; DELETE /jobs
- UI: опрос чаще, подсказка при пустом логе, кнопка очистки завершённых
2026-04-04 07:04:46 +03:00

232 lines
8.8 KiB
HTML
Raw 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.
{# Главная панель: кластеры, задания, создание.
Расширяет base.html; логика в /static/js/dashboard.js.
Автор: Сергей Антропов — https://devops.org.ru #}
{% extends "base.html" %}
{% block footer %}
<div class="footer-inner">
<p class="footer-copyright">
© {{ app_title }} ·
<a href="https://devops.org.ru" target="_blank" rel="noopener">devops.org.ru</a>
</p>
</div>
{% endblock %}
{% block content %}
<div class="top-dashboard-row">
<section class="card hero-panel" id="hero-panel" aria-labelledby="hero-title">
<div class="hero-panel-main">
<h1 class="page-title" id="hero-title">Панель управления</h1>
<p class="muted page-lead">
Создание и удаление кластеров kind, kubeconfig и просмотр узлов/подов через kubectl внутри контейнера.
Данные обновляются автоматически.
</p>
</div>
<div
id="status-banner"
class="hero-panel-status muted"
role="status"
aria-live="polite"
>
Проверка среды…
</div>
</section>
<aside class="card stats-side-card" aria-labelledby="stats-heading">
<h2 id="stats-heading">Статистика</h2>
<dl id="stats-dl" class="stats-dl stats-dl--compact" aria-label="Сводка по кластерам и заданиям"></dl>
<div id="stats-resources" class="stats-resources" aria-live="polite"></div>
<p id="stats-err" class="msg hidden" role="alert"></p>
</aside>
</div>
<section class="card create-cluster-card">
<h2>Создать кластер</h2>
<form id="form-create" novalidate>
<div class="create-form-grid">
<div class="create-form-col">
<label for="fld-name">Имя (a-z0-9-)</label>
<input
id="fld-name"
name="name"
required
pattern="[a-z0-9]([-a-z0-9]*[a-z0-9])?"
maxlength="63"
placeholder="dev"
autocomplete="off"
/>
<label for="fld-workers">Worker-ноды (020)</label>
<input id="fld-workers" name="workers" type="number" min="0" max="20" value="2" />
</div>
<div class="create-form-col">
<label for="version-select">Тег образа kindest/node (подсказка) или введите версию вручную ниже</label>
<div class="row">
<select id="version-select" name="kubernetes_version_preset" aria-describedby="ver-hint">
<option value="">— загрузить список —</option>
</select>
</div>
<label for="kubernetes_version">Версия Kubernetes / тег node</label>
<input
name="kubernetes_version"
id="kubernetes_version"
required
placeholder="1.29.4 или v1.29.4"
autocomplete="off"
/>
</div>
<div class="create-form-span">
<div class="row create-actions">
<button type="submit">Создать кластер</button>
</div>
</div>
</div>
<div id="create-progress-wrap" class="create-progress-wrap hidden" aria-hidden="true">
<p class="create-progress-hint muted" id="create-progress-hint">
Идёт операция — шаг <code>kind create</code> может занять несколько минут при первом pull образов.
Ниже выводится журнал (скачивание образов и подъём нод).
</p>
<div
class="progress-track"
role="progressbar"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="0"
aria-labelledby="create-progress-label"
id="create-progress-track"
>
<div class="progress-bar" id="create-progress-bar" style="width:0%"></div>
</div>
<p class="progress-label" id="create-progress-label"></p>
<div class="job-log-panel-wrap">
<label for="job-log-panel" class="job-log-label muted">Журнал задания</label>
<pre
id="job-log-panel"
class="mono job-log-panel"
role="log"
aria-live="polite"
aria-relevant="additions"
></pre>
</div>
<button type="button" id="btn-cancel-create" class="btn-secondary">Отменить</button>
</div>
<p id="create-msg" class="msg" aria-live="polite"></p>
<details id="job-details" class="job-details hidden">
<summary>Технические детали (JSON)</summary>
<pre id="job-json" class="mono job-json-pre" tabindex="0"></pre>
</details>
</form>
</section>
<section class="card clusters-card">
<h2>Кластеры</h2>
<p class="muted git-hint">
Каталог <code>clusters/</code> в Git не коммитится — только локальные kubeconfig и meta.
</p>
<div class="table-wrap">
<table id="tbl-clusters" aria-label="Список кластеров">
<thead>
<tr>
<th>Имя</th>
<th>kind</th>
<th>kubeconfig</th>
<th>Версия</th>
<th>Workers</th>
<th class="col-actions">Действия</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<p id="list-msg" class="msg muted"></p>
</section>
<section class="card jobs-card">
<div class="row spread jobs-card-toolbar">
<h2 id="jobs-heading" class="jobs-card-title">Последние задания</h2>
<button type="button" id="btn-jobs-clear" class="btn-secondary">Очистить завершённые</button>
</div>
<div class="table-wrap">
<table id="tbl-jobs" aria-label="Последние задания создания">
<thead>
<tr>
<th>Дата, время <span class="th-hint">(UTC)</span></th>
<th>Кластер</th>
<th>Статус</th>
<th>Сообщение</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<p id="jobs-msg" class="msg muted"></p>
</section>
<div
id="modal-overlay"
class="modal-overlay hidden"
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
>
<div class="modal-box">
<div class="modal-head row spread">
<h3 id="modal-title" class="modal-title-text">Состояние кластера</h3>
<button type="button" class="modal-close btn-secondary" id="modal-close">Закрыть</button>
</div>
<div id="modal-dl-wrap" class="modal-dl-wrap hidden">
<span
class="icon-tooltip-host"
data-tooltip="Скачать kubeconfig для использования с kubectl на хосте"
>
<button
type="button"
class="icon-btn"
id="modal-btn-kubeconfig"
aria-label="Скачать kubeconfig для kubectl на хосте"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
</button>
</span>
<span class="muted modal-dl-hint">kubeconfig</span>
</div>
<div id="modal-spinner" class="modal-spinner hidden" aria-hidden="true">
<span class="spinner" aria-label="Загрузка"></span>
<span class="muted">Запрос kubectl…</span>
</div>
<p id="modal-sub" class="muted modal-sub"></p>
<h4 class="modal-section-title muted">Узлы</h4>
<pre id="modal-nodes" class="mono" role="region" aria-label="Вывод kubectl get nodes"></pre>
<h4 class="modal-section-title muted">Поды (все namespace)</h4>
<pre id="modal-pods" class="mono" role="region" aria-label="Вывод kubectl get pods"></pre>
</div>
</div>
{# Модальное подтверждение вместо window.confirm (удаление, остановка узлов). #}
<div
id="confirm-modal-overlay"
class="modal-overlay confirm-modal-overlay hidden"
role="alertdialog"
aria-modal="true"
aria-labelledby="confirm-modal-title"
aria-describedby="confirm-modal-message"
>
<div class="modal-box modal-box--confirm">
<h3 id="confirm-modal-title" class="modal-title-text confirm-modal-title">Подтвердите действие</h3>
<p id="confirm-modal-message" class="modal-sub confirm-modal-message"></p>
<div class="confirm-modal-actions row spread">
<button type="button" class="btn-secondary" id="confirm-modal-cancel">Отмена</button>
<button type="button" id="confirm-modal-ok">Подтвердить</button>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script src="/static/js/dashboard.js" defer></script>
{% endblock %}