Веб-интерфейс: страница /clusters, навигация и крошки для кластеров
- Выделена страница списка кластеров, панель упрощена; nav_active и крошки ведут в раздел Кластеры; theme.js синхронизирует активную пилюлю по URL. - Доработки дашборда, аддонов, журнала, стилей и API-документации. - Поддержка Podman: docker-compose.podman.yml, скрипты сокета; Makefile и env.
This commit is contained in:
+296
-47
@@ -440,6 +440,16 @@ html[data-theme="light"] .nav-link.nav-pill.nav-pill--active:not(.nav-pill--ext)
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
/* Отдельная карточка на панели: донаты + список кластеров (GET /stats) */
|
||||
.home-resources-summary-inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
.home-resources-summary-card .donuts-card-title {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
/* Пояснение: узлы kind и метрики идут через Docker или Podman (CONTAINER_CLI) */
|
||||
.stats-engine-hint {
|
||||
margin: 0;
|
||||
@@ -460,10 +470,10 @@ html[data-theme="light"] .nav-link.nav-pill.nav-pill--active:not(.nav-pill--ext)
|
||||
padding: 0.85rem 0.65rem;
|
||||
}
|
||||
|
||||
/* Среда: Docker API · Kind · Kubectl · Каталогов — один ряд, 4 колонки */
|
||||
/* Среда: Docker API · Kind · Kubectl (3 в ряд); число каталогов — в сетке метрик под ними */
|
||||
.stats-env-cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 0.65rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -513,10 +523,10 @@ html[data-theme="light"] .stats-env-card--metric {
|
||||
background: rgba(59, 130, 246, 0.07);
|
||||
}
|
||||
|
||||
/* Метрики: по 4 карточки в ряд (4 метрики — один ряд) */
|
||||
/* Метрики панели: по 3 карточки в ряд */
|
||||
.stats-metrics-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 0.65rem;
|
||||
flex: 1 1 auto;
|
||||
align-content: start;
|
||||
@@ -524,7 +534,7 @@ html[data-theme="light"] .stats-env-card--metric {
|
||||
|
||||
@media (max-width: 520px) {
|
||||
.stats-metrics-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -909,6 +919,46 @@ html[data-theme="light"] .cluster-node-res-card__bar-track {
|
||||
background: rgba(239, 68, 68, 0.12);
|
||||
}
|
||||
|
||||
/* Страница «Кластеры»: заголовок слева, кнопка «Создать кластер» справа */
|
||||
.clusters-page-hero-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 1rem 1.5rem;
|
||||
}
|
||||
.clusters-page-hero-text {
|
||||
flex: 1 1 14rem;
|
||||
min-width: 0;
|
||||
}
|
||||
.clusters-page-hero-lead {
|
||||
margin: 0;
|
||||
}
|
||||
.clusters-page-hero-actions {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-top: 0.15rem;
|
||||
}
|
||||
.clusters-page-create-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.6rem 1.35rem;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 650;
|
||||
border-radius: 10px;
|
||||
text-decoration: none;
|
||||
border: 1px solid transparent;
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.14);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.clusters-page-create-btn:hover {
|
||||
filter: brightness(1.08);
|
||||
}
|
||||
|
||||
/* Прогресс создания кластера */
|
||||
.create-progress-wrap {
|
||||
margin-top: 1rem;
|
||||
@@ -2170,6 +2220,31 @@ html[data-theme="light"] .cluster-kube-hint.cluster-kube-hint--info {
|
||||
margin: 0 0 0.55rem;
|
||||
font-size: 1.02rem;
|
||||
}
|
||||
/* Заголовок карточки K8s + выпадающий фильтр namespace справа */
|
||||
.cluster-k8s-card-header {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 0.5rem 1rem;
|
||||
margin-bottom: 0.55rem;
|
||||
}
|
||||
.cluster-k8s-card-header .cluster-detail-section-title {
|
||||
margin: 0;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
.cluster-k8s-ns-filter-wrap {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.cluster-k8s-ns-select {
|
||||
width: auto;
|
||||
min-width: 10rem;
|
||||
max-width: min(18rem, 100%);
|
||||
margin: 0;
|
||||
padding: 0.35rem 0.5rem;
|
||||
font-size: 0.88rem;
|
||||
}
|
||||
|
||||
/* Сетка карточек узлов на странице кластера: не более 3 карточек в ряд */
|
||||
.cluster-page-node-cards--wide.cluster-nodes-resources__cards-row {
|
||||
@@ -2769,69 +2844,199 @@ html[data-theme="light"] .cluster-edit-yaml-preview-head {
|
||||
flex: 1 1 14rem;
|
||||
max-width: 28rem;
|
||||
}
|
||||
.cluster-addons-hint {
|
||||
margin: 0.35rem 0 0;
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
.cluster-addons-status-bar {
|
||||
margin-top: 0.65rem;
|
||||
font-size: 0.85rem;
|
||||
margin-top: 0.85rem;
|
||||
}
|
||||
.cluster-addons-status-bar--message .cluster-addons-status-msg {
|
||||
margin: 0;
|
||||
font-size: 0.88rem;
|
||||
line-height: 1.45;
|
||||
}
|
||||
.cluster-addons-status-cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr));
|
||||
gap: 0.65rem;
|
||||
}
|
||||
.cluster-addons-status-card {
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.65rem 0.75rem;
|
||||
background: rgba(0, 0, 0, 0.14);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.35rem;
|
||||
min-height: 3.5rem;
|
||||
justify-content: center;
|
||||
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
||||
}
|
||||
html[data-theme="light"] .cluster-addons-status-card {
|
||||
background: rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
.cluster-addons-status-card--on {
|
||||
border-color: rgba(34, 197, 94, 0.45);
|
||||
box-shadow: 0 0 0 1px rgba(34, 197, 94, 0.12);
|
||||
}
|
||||
.cluster-addons-status-card--off {
|
||||
border-color: var(--border);
|
||||
opacity: 0.92;
|
||||
}
|
||||
.cluster-addons-status-card__label {
|
||||
font-size: 0.78rem;
|
||||
font-weight: 600;
|
||||
color: var(--muted);
|
||||
line-height: 1.25;
|
||||
word-break: break-word;
|
||||
}
|
||||
.cluster-addons-status-card__value {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
.cluster-addons-status-card--on .cluster-addons-status-card__value {
|
||||
color: rgb(34, 197, 94);
|
||||
}
|
||||
.cluster-addons-status-card--off .cluster-addons-status-card__value {
|
||||
color: var(--muted);
|
||||
}
|
||||
.cluster-addons-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: 1rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
@media (min-width: 52rem) {
|
||||
.cluster-addons-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
/* Шапка карточки аддона: заголовок + бейдж «установлен» справа */
|
||||
.cluster-addon-card__header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 0.65rem;
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
.cluster-addon-card__title {
|
||||
margin: 0 0 0.35rem;
|
||||
.cluster-addon-card__header .cluster-addon-card__title {
|
||||
margin: 0;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.3;
|
||||
}
|
||||
.cluster-addon-card__badge {
|
||||
flex: 0 0 auto;
|
||||
font-size: 0.68rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.03em;
|
||||
text-transform: uppercase;
|
||||
padding: 0.28rem 0.5rem;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--border);
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.cluster-addon-card__badge--on {
|
||||
border-color: rgba(34, 197, 94, 0.5);
|
||||
color: rgb(34, 197, 94);
|
||||
background: rgba(34, 197, 94, 0.1);
|
||||
}
|
||||
.cluster-addon-card__badge--off {
|
||||
color: var(--muted);
|
||||
background: rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
html[data-theme="light"] .cluster-addon-card__badge--off {
|
||||
background: rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
.cluster-addon-card__values-details {
|
||||
margin: 0.75rem 0 0;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.5rem 0.65rem;
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
html[data-theme="light"] .cluster-addon-card__values-details {
|
||||
background: rgba(15, 23, 42, 0.03);
|
||||
}
|
||||
.cluster-addon-card__values-summary {
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
font-size: 0.88rem;
|
||||
list-style-position: outside;
|
||||
padding: 0.15rem 0;
|
||||
}
|
||||
.cluster-addon-card__values-hint {
|
||||
margin: 0.5rem 0 0.45rem;
|
||||
font-size: 0.78rem;
|
||||
line-height: 1.45;
|
||||
}
|
||||
.cluster-addon-card__values-subhead {
|
||||
margin: 0.65rem 0 0.35rem;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
}
|
||||
.cluster-addon-card__values-details .cluster-addon-card__values-subhead:first-of-type {
|
||||
margin-top: 0.35rem;
|
||||
}
|
||||
.cluster-addon-card__values-textarea {
|
||||
display: block;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
min-height: 6rem;
|
||||
padding: 0.5rem 0.6rem;
|
||||
font-size: 0.78rem;
|
||||
line-height: 1.4;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--border);
|
||||
background: rgba(0, 0, 0, 0.18);
|
||||
color: inherit;
|
||||
resize: vertical;
|
||||
}
|
||||
html[data-theme="light"] .cluster-addon-card__values-textarea {
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
.cluster-addon-card__desc {
|
||||
margin: 0 0 0.75rem;
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.45;
|
||||
}
|
||||
.cluster-addon-card__actions {
|
||||
.cluster-addon-card__actions--equal {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
width: 100%;
|
||||
margin-top: 0.85rem;
|
||||
gap: 0.5rem;
|
||||
align-items: stretch;
|
||||
}
|
||||
.cluster-addon-card__actions--equal .btn-addon-install,
|
||||
.cluster-addon-card__actions--equal .btn-addon-remove {
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
min-height: 2.65rem;
|
||||
margin-top: 0;
|
||||
box-sizing: border-box;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.cluster-addon-card--wide {
|
||||
grid-column: 1 / -1;
|
||||
grid-column: 1;
|
||||
}
|
||||
.cluster-addon-istio-grid {
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
.cluster-addons-log-card {
|
||||
/* Карточка хода Helm на странице аддонов (разметка как у create-progress-wrap + job-log-panel) */
|
||||
.cluster-addons-helm-progress {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.cluster-addons-log-pre {
|
||||
.cluster-addons-helm-progress .job-log-panel {
|
||||
max-height: min(55vh, 420px);
|
||||
}
|
||||
.cluster-addons-bootstrap-msg {
|
||||
margin: 0.5rem 0 0;
|
||||
max-height: min(50vh, 22rem);
|
||||
overflow: auto;
|
||||
padding: 0.65rem 0.75rem;
|
||||
font-size: 0.78rem;
|
||||
line-height: 1.4;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--border);
|
||||
background: rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
html[data-theme="light"] .cluster-addons-log-pre {
|
||||
background: rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
.cluster-addons-busy-overlay {
|
||||
z-index: 9995;
|
||||
}
|
||||
body.cluster-addons-busy {
|
||||
overflow: hidden;
|
||||
font-size: 0.88rem;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
/* Версии чартов на странице аддонов */
|
||||
@@ -2930,8 +3135,58 @@ html[data-theme="light"] .journal-details-cell {
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.journal-page-size-hint {
|
||||
/* Три сегмента на странице журнала — шире блок переключателя */
|
||||
.journal-toolbar-card .cluster-edit-segmented {
|
||||
max-width: 100%;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
@media (min-width: 960px) {
|
||||
.journal-toolbar-card .cluster-edit-segmented {
|
||||
flex-wrap: nowrap;
|
||||
max-width: 56rem;
|
||||
}
|
||||
}
|
||||
.journal-view-fieldset {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
.journal-cluster-picker {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.journal-cluster-picker.hidden {
|
||||
display: none;
|
||||
}
|
||||
.journal-cluster-picker-label {
|
||||
display: block;
|
||||
font-size: 0.88rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
.journal-cluster-select {
|
||||
width: 100%;
|
||||
max-width: 24rem;
|
||||
padding: 0.45rem 0.65rem;
|
||||
font-size: 0.9rem;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--surface);
|
||||
color: var(--text);
|
||||
}
|
||||
.journal-cluster-picker-hint {
|
||||
margin: 0.45rem 0 0;
|
||||
font-size: 0.84rem;
|
||||
max-width: 40rem;
|
||||
}
|
||||
.journal-toolbar-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.75rem 1rem;
|
||||
margin-top: 0.65rem;
|
||||
}
|
||||
.journal-cell-kind {
|
||||
word-break: break-word;
|
||||
max-width: 12rem;
|
||||
}
|
||||
|
||||
/* Пагинация журнала */
|
||||
@@ -3000,12 +3255,6 @@ html[data-theme="light"] .journal-details-cell {
|
||||
font-size: 0.9rem;
|
||||
user-select: none;
|
||||
}
|
||||
.journal-pagination-summary {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin: 0.85rem 0 0;
|
||||
font-size: 0.84rem;
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
.journal-pagination-inner {
|
||||
flex-direction: column;
|
||||
|
||||
Reference in New Issue
Block a user