Веб-UI: темы, навигация API, статистика и доработки API
- Шапка: логотип Kubernetes, ссылка на главную, выпадающее меню API (Swagger/ReDoc/Health), переключатель светлой/тёмной темы (localStorage). - Светлая тема в синей гамме; выравнивание кнопки темы в ряду с пилюлями. - Дашборд: единая карточка ошибки health/stats, подсказка Docker/Podman, поле container_cli в GET /stats, total_workers_from_meta всегда число (0 без meta). - Правки кластеров, job_store, compose, документация и частичные шаблоны.
This commit is contained in:
+160
-15
@@ -6,29 +6,127 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{% block page_title %}{{ app_title }}{% endblock %} — kind</title>
|
||||
{# Тема до первой отрисовки: localStorage kind_k8s_theme или prefers-color-scheme #}
|
||||
<script>
|
||||
(function () {
|
||||
try {
|
||||
var k = "kind_k8s_theme";
|
||||
var v = localStorage.getItem(k);
|
||||
var t =
|
||||
v === "light" || v === "dark"
|
||||
? v
|
||||
: window.matchMedia("(prefers-color-scheme: light)").matches
|
||||
? "light"
|
||||
: "dark";
|
||||
document.documentElement.setAttribute("data-theme", t);
|
||||
} catch (e) {
|
||||
document.documentElement.setAttribute("data-theme", "dark");
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<link rel="stylesheet" href="/static/style.css" />
|
||||
<script src="/static/js/theme.js" defer></script>
|
||||
{% block head_extra %}{% endblock %}
|
||||
</head>
|
||||
<body
|
||||
class="app-body"
|
||||
class="app-body{% block body_extra_class %}{% endblock %}"
|
||||
data-api-base="/api/v1"
|
||||
data-app-title="{{ app_title | e }}"
|
||||
{% block body_attrs %}{% endblock %}
|
||||
>
|
||||
<a class="skip-link" href="#main-content">К основному содержимому</a>
|
||||
|
||||
<header class="top-nav" role="banner">
|
||||
<div class="top-nav-inner">
|
||||
<div class="nav-brand">
|
||||
<span class="nav-logo" aria-hidden="true">◈</span>
|
||||
{# Логотип Kubernetes (SVG из набора Simple Icons, CC0) + название — одна ссылка на главную. #}
|
||||
<a href="/" class="nav-brand nav-brand-link">
|
||||
<img
|
||||
src="/static/icons/kubernetes.svg"
|
||||
alt=""
|
||||
class="nav-logo-img"
|
||||
width="28"
|
||||
height="28"
|
||||
decoding="async"
|
||||
/>
|
||||
<span class="nav-title">{{ app_title }}</span>
|
||||
</div>
|
||||
<nav class="nav-links" aria-label="Разделы">
|
||||
{# Панель подсвечивается только на дашборде; на странице документации — обычная пилюля, как Swagger/ReDoc. #}
|
||||
</a>
|
||||
{# Один ряд flex: Панель, Документация, API, тема — общий align-items: center #}
|
||||
<nav class="nav-links top-nav-actions" aria-label="Разделы и оформление">
|
||||
<a href="/" class="nav-link nav-pill{% if nav_active|default('') == 'panel' %} nav-pill--active{% endif %}">Панель</a>
|
||||
<a href="/documentation" class="nav-link nav-pill{% if nav_active|default('') == 'documentation' %} nav-pill--active{% endif %}">Документация</a>
|
||||
<a href="/docs" class="nav-link nav-pill nav-pill--ext" data-open-window="kind_swagger">Swagger</a>
|
||||
<a href="/redoc" class="nav-link nav-pill nav-pill--ext" data-open-window="kind_redoc">ReDoc</a>
|
||||
<a href="/api/v1/health" class="nav-link nav-pill nav-pill--ext" data-open-window="kind_health">Health</a>
|
||||
<div class="nav-dropdown">
|
||||
<button
|
||||
type="button"
|
||||
class="nav-link nav-pill nav-dropdown__trigger"
|
||||
id="nav-api-trigger"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-controls="nav-api-menu"
|
||||
>
|
||||
API
|
||||
</button>
|
||||
<ul class="nav-dropdown__menu" id="nav-api-menu" role="menu" hidden>
|
||||
<li role="none">
|
||||
<a
|
||||
role="menuitem"
|
||||
href="/docs"
|
||||
class="nav-dropdown__link nav-pill--ext"
|
||||
data-open-window="kind_swagger"
|
||||
>Swagger</a>
|
||||
</li>
|
||||
<li role="none">
|
||||
<a
|
||||
role="menuitem"
|
||||
href="/redoc"
|
||||
class="nav-dropdown__link nav-pill--ext"
|
||||
data-open-window="kind_redoc"
|
||||
>ReDoc</a>
|
||||
</li>
|
||||
<li role="none">
|
||||
<a
|
||||
role="menuitem"
|
||||
href="/api/v1/health"
|
||||
class="nav-dropdown__link nav-pill--ext"
|
||||
data-open-window="kind_health"
|
||||
>Health</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<button type="button" id="theme-toggle" class="theme-toggle theme-toggle--nav-end">
|
||||
<svg
|
||||
class="theme-toggle__icon theme-toggle__icon--sun"
|
||||
viewBox="0 0 24 24"
|
||||
width="18"
|
||||
height="18"
|
||||
aria-hidden="true"
|
||||
focusable="false"
|
||||
>
|
||||
<circle cx="12" cy="12" r="4" fill="none" stroke="currentColor" stroke-width="2" />
|
||||
<path
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
d="M12 2v2M12 20v2M2 12h2M20 12h2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M19.07 4.93l-1.41 1.41M6.34 17.66l-1.41 1.41"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
class="theme-toggle__icon theme-toggle__icon--moon"
|
||||
viewBox="0 0 24 24"
|
||||
width="18"
|
||||
height="18"
|
||||
aria-hidden="true"
|
||||
focusable="false"
|
||||
>
|
||||
<path
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linejoin="round"
|
||||
d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
@@ -53,16 +151,63 @@
|
||||
{% endblock %}
|
||||
</footer>
|
||||
|
||||
{# Отдельное окно браузера для документации и health (не вкладка). #}
|
||||
{# Отдельное окно для Swagger/ReDoc/Health; выпадающее меню API. #}
|
||||
<script>
|
||||
(function () {
|
||||
var opts = "noopener,noreferrer,width=1240,height=840,scrollbars=yes,resizable=yes";
|
||||
document.querySelectorAll(".nav-link[data-open-window]").forEach(function (a) {
|
||||
a.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
var name = a.getAttribute("data-open-window") || "kind_ext";
|
||||
window.open(a.getAttribute("href"), name, opts);
|
||||
function bindOpenWindow(scope) {
|
||||
(scope || document).querySelectorAll("[data-open-window]").forEach(function (a) {
|
||||
if (a.tagName !== "A") return;
|
||||
a.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
var name = a.getAttribute("data-open-window") || "kind_ext";
|
||||
window.open(a.getAttribute("href"), name, opts);
|
||||
});
|
||||
});
|
||||
}
|
||||
bindOpenWindow();
|
||||
|
||||
var dd = document.querySelector(".nav-dropdown");
|
||||
if (!dd) return;
|
||||
var btn = document.getElementById("nav-api-trigger");
|
||||
var menu = document.getElementById("nav-api-menu");
|
||||
if (!btn || !menu) return;
|
||||
|
||||
function closeApiMenu() {
|
||||
dd.classList.remove("nav-dropdown--open");
|
||||
btn.setAttribute("aria-expanded", "false");
|
||||
menu.setAttribute("hidden", "");
|
||||
}
|
||||
function openApiMenu() {
|
||||
dd.classList.add("nav-dropdown--open");
|
||||
btn.setAttribute("aria-expanded", "true");
|
||||
menu.removeAttribute("hidden");
|
||||
}
|
||||
function toggleApiMenu() {
|
||||
if (menu.hasAttribute("hidden")) openApiMenu();
|
||||
else closeApiMenu();
|
||||
}
|
||||
|
||||
btn.addEventListener("click", function (e) {
|
||||
e.stopPropagation();
|
||||
toggleApiMenu();
|
||||
});
|
||||
|
||||
menu.querySelectorAll("a[role='menuitem']").forEach(function (a) {
|
||||
a.addEventListener("click", function () {
|
||||
closeApiMenu();
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener("click", function () {
|
||||
closeApiMenu();
|
||||
});
|
||||
dd.addEventListener("click", function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Escape") closeApiMenu();
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
{# Создание кластера, журнал задания и последние задания.
|
||||
Автор: Сергей Антропов — https://devops.org.ru #}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block body_attrs %}data-dashboard-mode="create"{% endblock %}
|
||||
|
||||
{% 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 %}
|
||||
<section class="card hero-panel cluster-create-hero" aria-labelledby="create-hero-title">
|
||||
<h1 class="page-title" id="create-hero-title">Создание кластера</h1>
|
||||
<p class="muted page-lead">
|
||||
Укажите имя, версию образа kindest/node и число worker-нод. Операция выполняется в фоне; ход смотрите в журнале ниже.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<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-ноды (0–20)</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 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>
|
||||
|
||||
{% include "partials/dashboard_modals.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="/static/js/dashboard.js" defer></script>
|
||||
{% endblock %}
|
||||
+20
-181
@@ -1,8 +1,9 @@
|
||||
{# Главная панель: кластеры, задания, создание.
|
||||
Расширяет base.html; логика в /static/js/dashboard.js.
|
||||
{# Главная: создание (CTA), статистика, донаты, таблица кластеров.
|
||||
Автор: Сергей Антропов — https://devops.org.ru #}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block body_attrs %}data-dashboard-mode="home"{% endblock %}
|
||||
|
||||
{% block footer %}
|
||||
<div class="footer-inner">
|
||||
<p class="footer-copyright">
|
||||
@@ -14,119 +15,34 @@
|
||||
|
||||
{% 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 внутри контейнера.
|
||||
Данные обновляются автоматически.
|
||||
<section class="card cta-hero-card" aria-labelledby="cta-hero-title">
|
||||
<div class="cta-hero-inner">
|
||||
<h1 class="page-title" id="cta-hero-title">Создать кластер</h1>
|
||||
<p class="muted page-lead cta-hero-lead">
|
||||
Кластеры kind, kubeconfig и kubectl — ниже на странице. Данные обновляются автоматически.
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
id="status-banner"
|
||||
class="hero-panel-status muted"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
>
|
||||
Проверка среды…
|
||||
<a href="/cluster-create" class="btn btn-cta-large">Перейти к форме создания</a>
|
||||
</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>
|
||||
<p id="stats-engine-hint" class="stats-engine-hint muted hidden" aria-live="polite"></p>
|
||||
<div id="stats-failure-wrap" class="stats-failure-wrap hidden" role="alert" aria-live="polite"></div>
|
||||
<div id="stats-env" class="stats-env-cards" role="status" aria-live="polite">
|
||||
<p class="stats-env-placeholder muted">Проверка среды…</p>
|
||||
</div>
|
||||
<div id="stats-grid" class="stats-metrics-grid" aria-label="Сводка по кластерам и заданиям"></div>
|
||||
</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-ноды (0–20)</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 id="aggregate-donuts-section" class="card aggregate-donuts-card" aria-labelledby="donuts-heading">
|
||||
<h2 id="donuts-heading" class="donuts-card-title">Ресурсы узлов (сводка)</h2>
|
||||
<div id="aggregate-donuts" class="aggregate-donuts" aria-live="polite"></div>
|
||||
</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>
|
||||
@@ -136,6 +52,7 @@
|
||||
<th>kubeconfig</th>
|
||||
<th>Версия</th>
|
||||
<th>Workers</th>
|
||||
<th>Состояние</th>
|
||||
<th class="col-actions">Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -145,85 +62,7 @@
|
||||
<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>
|
||||
{% include "partials/dashboard_modals.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
Автор: Сергей Антропов — https://devops.org.ru #}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{# Полная ширина контента и подвала — см. .doc-layout-full в style.css #}
|
||||
{% block body_extra_class %} doc-layout-full{% endblock %}
|
||||
|
||||
{% block page_title %}Документация{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
{# Модалки kubectl и подтверждения — общие для главной и страницы создания кластера.
|
||||
Автор: Сергей Антропов — https://devops.org.ru #}
|
||||
<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 modal-head--cluster">
|
||||
<h3 id="modal-title" class="modal-title-text modal-title-text--center">Состояние кластера</h3>
|
||||
<div class="modal-toolbar" role="toolbar" aria-label="Действия в окне">
|
||||
<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>
|
||||
<button type="button" class="modal-close btn-secondary" id="modal-close">Закрыть</button>
|
||||
</div>
|
||||
</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>
|
||||
|
||||
<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">
|
||||
<button type="button" class="btn-secondary" id="confirm-modal-cancel">Отмена</button>
|
||||
<button type="button" id="confirm-modal-ok">Подтвердить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user