Перевести дашборд на layout в стиле Virtualizor

Этот коммит содержится в:
Виктор
2026-05-07 03:53:36 +09:00
родитель 165f1cc7db
Коммит 44836474c5
+169 -181
Просмотреть файл
@@ -7,209 +7,197 @@
<link rel="stylesheet" href="/static/app.css"> <link rel="stylesheet" href="/static/app.css">
</head> </head>
<body> <body>
<div class="shell"> <div class="v-layout">
<header class="topbar"> <aside class="v-sidebar">
<div> <div class="v-logo">
<div class="brand">Virtuality</div> <strong>Virtuality</strong>
<div class="muted">Лёгкая панель управления виртуализацией</div> <span>control panel</span>
</div> </div>
<div class="top-meta"> <nav class="v-nav">
<span>{{ system.hostname }}</span> <a class="active" href="/">Обзор</a>
<span>{{ system.ip }}</span> <a href="/vm/create">Создать VM</a>
<span>{{ system.time }}</span> <a href="/iso">ISO</a>
<span>user: {{ user }}</span> <a href="/disk-images">Диски</a>
<a class="link-pill" href="/network">Сеть</a> <a href="/network">Сеть</a>
<a class="link-pill" href="/operations">Операции</a> <a href="/operations">Операции</a>
<a class="link-pill" href="/iso">ISO</a> <a href="/logs">Журналы</a>
<a class="link-pill" href="/disk-images">Диски</a> <a href="/update">Обновления</a>
<a class="link-pill {{ 'accent' if update_notice and update_notice.has_update else '' }}" href="/update">Обновления{% if update_notice and update_notice.has_update %} · доступно{% endif %}</a> <a href="/host">Хост</a>
<a class="link-pill accent" href="/vm/create">+ Создать VM</a> </nav>
<form method="post" action="/logout" class="logout-form"><button class="ghost">Выйти</button></form> </aside>
</div>
</header>
{% if update_notice and update_notice.has_update %} <main class="v-main">
<section class="card update-banner"> <header class="v-topbar">
<div> <div>
<div class="label">Доступно обновление Virtuality</div> <div class="v-title">Обзор</div>
<div class="value small">{{ update_notice.current_version }} {{ update_notice.latest_version }}</div> <div class="v-subtitle">{{ system.hostname }} · {{ system.ip }} · {{ system.time }}</div>
<div class="muted small-note"> </div>
Пропущено версий: {{ update_notice.missing_count }} · новых коммитов: {{ update_notice.commit_count }} <div class="top-meta">
<span>user: {{ user }}</span>
<a class="link-pill accent" href="/vm/create">+ Создать VM</a>
<form method="post" action="/logout" class="logout-form"><button class="ghost">Выйти</button></form>
</div>
</header>
{% if update_notice and update_notice.has_update %}
<section class="card update-banner">
<div>
<div class="label">Доступно обновление Virtuality</div>
<div class="value small">{{ update_notice.current_version }} → {{ update_notice.latest_version }}</div>
<div class="muted small-note">Пропущено версий: {{ update_notice.missing_count }} · новых коммитов: {{ update_notice.commit_count }}</div>
</div> </div>
</div> <div class="actions">
<div class="actions"> <a class="link-pill accent" href="/update">Посмотреть изменения</a>
<a class="link-pill accent" href="/update">Посмотреть изменения</a> </div>
</div> </section>
{% endif %}
<section class="grid stats">
<article class="card stat">
<div class="label">Uptime</div>
<div class="value">{{ system.uptime }}</div>
</article>
<article class="card stat">
<div class="label">Load</div>
<div class="value">{{ system.load }}</div>
</article>
<article class="card stat">
<div class="label">Kernel</div>
<div class="value small">{{ system.kernel }}</div>
</article>
<article class="card stat">
<div class="label">VM</div>
<div class="value">{{ vms|length }}</div>
</article>
</section> </section>
{% endif %}
<section class="grid stats"> <section class="card">
<article class="card stat">
<div class="label">Uptime</div>
<div class="value">{{ system.uptime }}</div>
</article>
<article class="card stat">
<div class="label">Load</div>
<div class="value">{{ system.load }}</div>
</article>
<article class="card stat">
<div class="label">Kernel</div>
<div class="value small">{{ system.kernel }}</div>
</article>
<article class="card stat">
<div class="label">VM</div>
<div class="value">{{ vms|length }}</div>
</article>
</section>
<section class="grid two">
<article class="card">
<div class="card-head"> <div class="card-head">
<h2>Сервисы</h2> <h2>Виртуальные машины</h2>
<span class="pill">systemd</span> <div class="actions">
</div> <a class="link-pill" href="/operations">Операции</a>
<div class="services"> <a class="link-pill" href="/logs">Журналы</a>
{% for name, state in services.items() %} <a class="link-pill accent" href="/vm/create">+ Создать VM</a>
<div class="service-row">
<span>{{ name }}</span>
<span class="status {{ 'ok' if state == 'active' else 'warn' }}">{{ state }}</span>
</div> </div>
{% endfor %}
</div>
</article>
<article class="card">
<div class="card-head">
<h2>Последние операции</h2>
<a class="link-pill" href="/operations">Журнал</a>
</div>
<div class="services">
{% for operation in operations %}
<a class="service-row service-link" href="/operations/{{ operation.id }}">
<span>
<strong>{{ operation.title }}</strong>
<small>{{ operation.created_at }} · {{ operation.message }}</small>
</span>
<span class="status {{ operation_css(operation.status) }}">{{ operation.status }}</span>
</a>
{% else %}
<div class="muted">Операций пока нет. Чистый лист — редкость, почти музей.</div>
{% endfor %}
</div>
</article>
</section>
<section class="grid two">
<article class="card">
<div class="card-head">
<h2>Storage pools</h2>
<span class="pill">libvirt</span>
</div> </div>
<table> <table>
<thead> <thead>
<tr><th>Name</th><th>State</th><th>Autostart</th></tr> <tr><th>ID</th><th>Name</th><th>State</th><th>Actions</th></tr>
</thead> </thead>
<tbody> <tbody>
{% for pool in pools %} {% for vm in vms %}
<tr> <tr>
<td>{{ pool.name }}</td> <td>{{ vm.id }}</td>
<td><span class="status {{ 'ok' if pool.state == 'active' else 'warn' }}">{{ pool.state }}</span></td> <td class="strong"><a class="table-link" href="/vm/{{ vm.name }}">{{ vm.name }}</a></td>
<td>{{ pool.autostart }}</td> <td><span class="status {{ 'ok' if 'running' in vm.state else 'warn' }}">{{ vm.state }}</span></td>
<td class="actions">
<a class="link-pill" href="/vm/{{ vm.name }}">Подробнее</a>
<form method="post" action="/vm/{{ vm.name }}/start"><button>Start</button></form>
<form method="post" action="/vm/{{ vm.name }}/shutdown"><button>Shutdown</button></form>
<form method="post" action="/vm/{{ vm.name }}/reboot"><button>Reboot</button></form>
<form method="post" action="/vm/{{ vm.name }}/destroy"><button class="danger">Power off</button></form>
</td>
</tr> </tr>
{% else %} {% else %}
<tr><td colspan="3" class="muted">Storage pools не найдены</td></tr> <tr><td colspan="4" class="muted">Виртуальных машин пока нет</td></tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</article> </section>
<article class="card"> <section class="grid two">
<div class="card-head"> <article class="card">
<h2>Быстрые действия</h2> <div class="card-head">
<span class="pill">control plane</span> <h2>Сервисы</h2>
</div> <span class="pill">systemd</span>
<div class="quick-actions"> </div>
<a class="big-action" href="/vm/create"> <div class="services">
<strong>Создать VM</strong> {% for name, state in services.items() %}
<span>Запуск мастера с ISO, RAM, CPU, диском, архитектурой и выбором Bridge/NAT</span> <div class="service-row">
</a> <span>{{ name }}</span>
<a class="big-action" href="/network"> <span class="status {{ 'ok' if state == 'active' else 'warn' }}">{{ state }}</span>
<strong>Сеть</strong> </div>
<span>NAT Router для VPS, DHCP leases, nftables и проброс портов</span> {% endfor %}
</a> </div>
<a class="big-action" href="/iso"> </article>
<strong>ISO-менеджер</strong>
<span>Загрузка, удаление и refresh ISO storage pool</span>
</a>
<a class="big-action" href="/disk-images">
<strong>Диски</strong>
<span>Загрузка .img/.raw/.qcow2 и импорт готовых системных образов</span>
</a>
<a class="big-action" href="/operations">
<strong>Журнал операций</strong>
<span>Прогресс, stdout/stderr virt-install и причины ошибок</span>
</a>
<a class="big-action" href="/update">
<strong>Обновления</strong>
<span>Проверка GitHub, список пропущенных версий и установка обновления</span>
</a>
</div>
</article>
</section>
<section class="card"> <article class="card">
<div class="card-head"> <div class="card-head">
<h2>Виртуальные машины</h2> <h2>Последние операции</h2>
<div class="actions"> <a class="link-pill" href="/operations">Все операции</a>
<a class="link-pill" href="/network">Сеть</a> </div>
<a class="link-pill" href="/operations">Операции</a> <div class="services">
<a class="link-pill" href="/iso">ISO</a> {% for operation in operations %}
<a class="link-pill" href="/disk-images">Диски</a> <a class="service-row service-link" href="/operations/{{ operation.id }}">
<a class="link-pill" href="/update">Обновления</a> <span>
<a class="link-pill accent" href="/vm/create">+ Создать VM</a> <strong>{{ operation.title }}</strong>
</div> <small>{{ operation.created_at }} · {{ operation.message }}</small>
</div> </span>
<table> <span class="status {{ operation_css(operation.status) }}">{{ operation.status }}</span>
<thead> </a>
<tr><th>ID</th><th>Name</th><th>State</th><th>Actions</th></tr> {% else %}
</thead> <div class="muted">Операций пока нет.</div>
<tbody> {% endfor %}
{% for vm in vms %} </div>
<tr> </article>
<td>{{ vm.id }}</td> </section>
<td class="strong"><a class="table-link" href="/vm/{{ vm.name }}">{{ vm.name }}</a></td>
<td><span class="status {{ 'ok' if 'running' in vm.state else 'warn' }}">{{ vm.state }}</span></td>
<td class="actions">
<a class="link-pill" href="/vm/{{ vm.name }}">Подробнее</a>
<form method="post" action="/vm/{{ vm.name }}/start"><button>Start</button></form>
<form method="post" action="/vm/{{ vm.name }}/shutdown"><button>Shutdown</button></form>
<form method="post" action="/vm/{{ vm.name }}/reboot"><button>Reboot</button></form>
<form method="post" action="/vm/{{ vm.name }}/destroy"><button class="danger">Power off</button></form>
</td>
</tr>
{% else %}
<tr><td colspan="4" class="muted">Виртуальных машин пока нет</td></tr>
{% endfor %}
</tbody>
</table>
</section>
<section class="grid two"> <section class="grid two">
<article class="card"> <article class="card">
<div class="card-head"> <div class="card-head">
<h2>Интерфейсы</h2> <h2>Storage pools</h2>
<span class="pill">ip -br a</span> <span class="pill">libvirt</span>
</div> </div>
<pre>{{ network.interfaces }}</pre> <table>
</article> <thead>
<article class="card"> <tr><th>Name</th><th>State</th><th>Autostart</th></tr>
<div class="card-head"> </thead>
<h2>Маршруты</h2> <tbody>
<span class="pill">ip route</span> {% for pool in pools %}
</div> <tr>
<pre>{{ network.routes }}</pre> <td>{{ pool.name }}</td>
</article> <td><span class="status {{ 'ok' if pool.state == 'active' else 'warn' }}">{{ pool.state }}</span></td>
</section> <td>{{ pool.autostart }}</td>
</tr>
{% else %}
<tr><td colspan="3" class="muted">Storage pools не найдены</td></tr>
{% endfor %}
</tbody>
</table>
</article>
<article class="card">
<div class="card-head">
<h2>Быстрые действия</h2>
<span class="pill">control plane</span>
</div>
<div class="quick-actions">
<a class="big-action" href="/vm/create"><strong>Создать VM</strong><span>Мастер создания виртуальной машины</span></a>
<a class="big-action" href="/network"><strong>Сеть</strong><span>NAT, DHCP leases, проброс портов</span></a>
<a class="big-action" href="/iso"><strong>ISO</strong><span>Установочные .iso образы</span></a>
<a class="big-action" href="/disk-images"><strong>Диски</strong><span>.img/.raw/.qcow2 и архивы</span></a>
<a class="big-action" href="/logs"><strong>Журналы</strong><span>Web, update, libvirt, операции</span></a>
</div>
</article>
</section>
<section class="grid two">
<article class="card">
<div class="card-head">
<h2>Интерфейсы</h2>
<span class="pill">ip -br a</span>
</div>
<pre>{{ network.interfaces }}</pre>
</article>
<article class="card">
<div class="card-head">
<h2>Маршруты</h2>
<span class="pill">ip route</span>
</div>
<pre>{{ network.routes }}</pre>
</article>
</section>
</main>
</div> </div>
</body> </body>
</html> </html>