- Добавлена колонка 'Тип' во все таблицы истории сборок - Для push операций отображается registry вместо платформ - Сохранение пользователя при создании push лога - Исправлена ошибка с logger в push_docker_image endpoint - Улучшено отображение истории сборок с визуальными индикаторами
3772 lines
92 KiB
CSS
3772 lines
92 KiB
CSS
/* Основные стили для Resource Planner */
|
||
/* Автор: Сергей Антропов - https://devops.org.ru */
|
||
|
||
:root {
|
||
--primary-color: #0d6efd;
|
||
--secondary-color: #6c757d;
|
||
--success-color: #198754;
|
||
--danger-color: #dc3545;
|
||
--warning-color: #ffc107;
|
||
--info-color: #0dcaf0;
|
||
--light-color: #f8f9fa;
|
||
--dark-color: #212529;
|
||
--border-radius: 0.5rem;
|
||
--box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||
--box-shadow-lg: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
--sidebar-width: 260px;
|
||
--sidebar-bg: linear-gradient(180deg, #1e293b 0%, #0f172a 100%);
|
||
--sidebar-text: #e2e8f0;
|
||
--sidebar-hover: rgba(255, 255, 255, 0.1);
|
||
--sidebar-active: rgba(102, 126, 234, 0.2);
|
||
}
|
||
|
||
* {
|
||
box-sizing: border-box;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||
line-height: 1.6;
|
||
color: #1f2937;
|
||
background: #f8f9fa;
|
||
min-height: 100vh;
|
||
display: flex;
|
||
overflow-x: hidden;
|
||
}
|
||
|
||
/* Утилита для flex: позволяет flex-потомкам сжиматься и корректно распределять высоту */
|
||
.min-h-0 {
|
||
min-height: 0;
|
||
}
|
||
|
||
/* Кнопка «Добавить» в форме расписания — та же высота, что у полей ввода (form-control) */
|
||
.sync-add-btn {
|
||
height: calc(2.5rem + 0.75rem + 2px) !important;
|
||
}
|
||
|
||
/* Карточка «Использование ресурсов» в карточке сервера — на 5rem ниже по высоте */
|
||
.server-usage-card {
|
||
max-height: calc(100% - 1.6rem);
|
||
}
|
||
|
||
/* Переключатель «Включено» в расписании синхронизации — крупнее, ровно по середине ячейки по высоте и ширине */
|
||
.sync-schedule-toggle-cell {
|
||
text-align: center !important;
|
||
vertical-align: middle !important;
|
||
display: table-cell !important;
|
||
}
|
||
.sync-schedule-toggle-cell .sync-schedule-toggle-form {
|
||
display: flex !important;
|
||
justify-content: center !important;
|
||
align-items: center !important;
|
||
width: 100% !important;
|
||
min-height: 100% !important;
|
||
margin: 0 !important;
|
||
}
|
||
.sync-schedule-toggle-wrap.form-switch .form-check-input {
|
||
width: 2.75rem;
|
||
height: 1.4rem;
|
||
cursor: pointer;
|
||
}
|
||
.sync-schedule-toggle-wrap.form-switch {
|
||
padding-left: 0.5rem;
|
||
min-height: 1.4rem;
|
||
margin-top: 0rem !important;
|
||
}
|
||
.sync-schedule-toggle-wrap.form-switch .form-check-input:checked {
|
||
background-position: right 0.35rem center;
|
||
}
|
||
|
||
/* Переключатель «Логи» в расписании — ровно по середине ячейки по высоте и ширине */
|
||
.sync-schedule-savelog-cell {
|
||
text-align: center !important;
|
||
vertical-align: middle !important;
|
||
display: table-cell !important;
|
||
}
|
||
.sync-schedule-savelog-cell .sync-schedule-savelog-form {
|
||
display: flex !important;
|
||
justify-content: center !important;
|
||
align-items: center !important;
|
||
width: 100% !important;
|
||
min-height: 100% !important;
|
||
margin: 0 !important;
|
||
}
|
||
.sync-schedule-savelog-cell .sync-schedule-savelog-wrap.form-switch .form-check-input {
|
||
width: 2.75rem;
|
||
height: 1.4rem;
|
||
cursor: pointer;
|
||
}
|
||
.sync-schedule-savelog-cell .sync-schedule-savelog-wrap.form-switch {
|
||
padding-left: 0.5rem;
|
||
min-height: 1.4rem;
|
||
margin-top: 0 !important;
|
||
margin-bottom: 0 !important;
|
||
}
|
||
.sync-schedule-savelog-cell .sync-schedule-savelog-wrap.form-switch .form-check-input:checked {
|
||
background-position: right 0.35rem center;
|
||
}
|
||
|
||
/* Форма редактирования интервала в таблице расписания — уменьшенная по высоте (~вдвое) */
|
||
.sync-interval-form-compact .form-control,
|
||
.sync-interval-form-compact .form-select,
|
||
.sync-interval-form-compact .btn {
|
||
min-height: 1.15rem;
|
||
height: 1.5rem;
|
||
padding: 0.05rem 0.25rem;
|
||
font-size: 1rem;
|
||
line-height: 1.1;
|
||
}
|
||
.sync-interval-form-compact .form-select {
|
||
padding-right: 1.25rem;
|
||
}
|
||
|
||
/* Sidebar */
|
||
.sidebar {
|
||
width: var(--sidebar-width);
|
||
background: var(--sidebar-bg);
|
||
color: var(--sidebar-text);
|
||
position: fixed;
|
||
left: 0;
|
||
top: 0;
|
||
height: 100vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
z-index: 1000;
|
||
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
|
||
overflow-y: auto;
|
||
overflow-x: hidden;
|
||
transition: width 0.25s ease;
|
||
}
|
||
|
||
/* Хэндл для изменения ширины сайдбара (только на десктопе, когда развёрнут) */
|
||
.sidebar-resize-handle {
|
||
display: none;
|
||
position: absolute;
|
||
right: 0;
|
||
top: 0;
|
||
bottom: 0;
|
||
width: 6px;
|
||
cursor: col-resize;
|
||
z-index: 10;
|
||
background: transparent;
|
||
}
|
||
.sidebar-resize-handle:hover,
|
||
.sidebar-resize-handle.dragging {
|
||
background: rgba(102, 126, 234, 0.3);
|
||
}
|
||
@media (min-width: 992px) {
|
||
.sidebar:not(.collapsed) .sidebar-resize-handle {
|
||
display: block;
|
||
}
|
||
}
|
||
@media (max-width: 991.98px) {
|
||
.sidebar-resize-handle {
|
||
display: none !important;
|
||
}
|
||
}
|
||
|
||
/* Кнопка сворачивания сайдбара (только на десктопе) */
|
||
.sidebar-collapse-btn {
|
||
display: none;
|
||
position: absolute;
|
||
right: 0.5rem;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
width: 1.75rem;
|
||
height: 1.75rem;
|
||
padding: 0;
|
||
border: none;
|
||
border-radius: 0.25rem;
|
||
background: rgba(255, 255, 255, 0.1);
|
||
color: var(--sidebar-text);
|
||
cursor: pointer;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: background 0.2s, color 0.2s;
|
||
}
|
||
.sidebar-collapse-btn:hover {
|
||
background: rgba(255, 255, 255, 0.2);
|
||
color: #fff;
|
||
}
|
||
.sidebar-collapse-icon {
|
||
font-size: 0.75rem;
|
||
transition: transform 0.25s ease;
|
||
}
|
||
.sidebar.collapsed .sidebar-collapse-icon {
|
||
transform: rotate(180deg);
|
||
}
|
||
@media (min-width: 992px) {
|
||
.sidebar-collapse-btn {
|
||
display: flex;
|
||
}
|
||
}
|
||
@media (max-width: 991.98px) {
|
||
.sidebar-collapse-btn {
|
||
display: none !important;
|
||
}
|
||
}
|
||
|
||
/* Свёрнутое состояние: только иконки с title при наведении */
|
||
.sidebar.collapsed {
|
||
width: 64px !important;
|
||
}
|
||
.sidebar.collapsed .brand-text,
|
||
.sidebar.collapsed .menu-text,
|
||
.sidebar.collapsed .dropdown-arrow {
|
||
opacity: 0;
|
||
width: 0;
|
||
overflow: hidden;
|
||
padding: 0;
|
||
margin: 0;
|
||
pointer-events: none;
|
||
}
|
||
/* Скрываем выпадающее меню по умолчанию в свернутом виде */
|
||
.sidebar.collapsed .sidebar-dropdown-menu {
|
||
opacity: 0;
|
||
max-height: 0;
|
||
overflow: hidden;
|
||
padding: 0;
|
||
margin: 0;
|
||
pointer-events: none;
|
||
}
|
||
/* Показываем выпадающее меню при раскрытии — иконки с title */
|
||
.sidebar.collapsed .sidebar-dropdown-item.open .sidebar-dropdown-menu {
|
||
opacity: 1;
|
||
max-height: 500px;
|
||
overflow: visible;
|
||
padding: 0.25rem 0;
|
||
margin: 0.25rem 0;
|
||
pointer-events: auto;
|
||
}
|
||
.sidebar.collapsed .sidebar-dropdown-menu .sidebar-menu-link {
|
||
justify-content: center;
|
||
padding: 0.6rem 0.75rem;
|
||
padding-left: 0.75rem;
|
||
}
|
||
.sidebar.collapsed .sidebar-brand {
|
||
justify-content: center;
|
||
padding: 0.5rem;
|
||
}
|
||
.sidebar.collapsed .sidebar-menu-link {
|
||
justify-content: center;
|
||
padding: 0.75rem;
|
||
}
|
||
.sidebar.collapsed .sidebar-dropdown-toggle {
|
||
justify-content: center;
|
||
}
|
||
.sidebar.collapsed .sidebar-menu-divider {
|
||
margin: 0.5rem 0.75rem;
|
||
}
|
||
/* Кнопка выхода: только иконка по центру */
|
||
.sidebar.collapsed .btn-logout-sidebar .menu-text {
|
||
opacity: 0;
|
||
width: 0;
|
||
overflow: hidden;
|
||
padding: 0;
|
||
margin: 0;
|
||
}
|
||
.sidebar.collapsed .btn-logout-sidebar {
|
||
justify-content: center;
|
||
width: 2.5rem;
|
||
min-width: 2.5rem;
|
||
padding: 0.875rem 0;
|
||
margin: 0 auto;
|
||
gap: 0;
|
||
}
|
||
.sidebar.collapsed .btn-logout-sidebar .menu-icon {
|
||
margin: 0;
|
||
}
|
||
.sidebar.collapsed .sidebar-footer {
|
||
display: flex;
|
||
justify-content: center;
|
||
padding: 1rem 0.5rem;
|
||
}
|
||
.sidebar.collapsed .sidebar-logout {
|
||
margin: 0;
|
||
}
|
||
.sidebar.collapsed .sidebar-header {
|
||
padding: 1rem 0.5rem;
|
||
}
|
||
.sidebar.collapsed .sidebar-collapse-btn {
|
||
right: 50%;
|
||
transform: translate(50%, -50%);
|
||
display: flex !important; /* Всегда видна кнопка, даже когда sidebar свернут */
|
||
z-index: 10; /* Поверх других элементов */
|
||
}
|
||
|
||
.sidebar-header {
|
||
padding: 1.75rem 1.25rem;
|
||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||
background: linear-gradient(180deg, rgba(102, 126, 234, 0.15) 0%, transparent 100%);
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* Колонка с бейджем версии и текстом ЦИСМ.ЦОД: бейдж ровно над надписью, прижат вправо по букве Д */
|
||
/* Колонка высотой как иконка (2rem); по центру по вертикали только надпись — её центр совпадает с центром логотипа */
|
||
.sidebar-brand-text-column {
|
||
position: relative;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-end;
|
||
justify-content: center;
|
||
width: fit-content;
|
||
height: 2rem;
|
||
}
|
||
|
||
/* Контейнер бейджей в шапке: логин слева, версия справа, тот же размер */
|
||
.sidebar-header-badges {
|
||
position: absolute;
|
||
right: 0;
|
||
bottom: 100%;
|
||
margin-bottom: -0.2rem;
|
||
display: inline-flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
gap: 0.25rem;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.sidebar.collapsed .sidebar-header-badges {
|
||
display: none;
|
||
}
|
||
|
||
/* Бейдж логина админа: красный, тот же размер что и версия */
|
||
.sidebar-user-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
padding: 0.1rem 0.25rem;
|
||
font-size: 0.375rem;
|
||
font-weight: 500;
|
||
color: #fff;
|
||
background: #c0392b;
|
||
border: 1px solid #a93226;
|
||
border-radius: 0.125rem;
|
||
white-space: nowrap;
|
||
max-width: 6rem;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
/* Бейдж версии: тот же размер, прижат к правому краю */
|
||
.sidebar-version-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
padding: 0.1rem 0.25rem;
|
||
font-size: 0.375rem;
|
||
font-weight: 500;
|
||
color: rgba(255, 255, 255, 0.75);
|
||
background: rgba(255, 255, 255, 0.08);
|
||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||
border-radius: 0.125rem;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.sidebar-header::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 2px;
|
||
background: linear-gradient(90deg, transparent, #667eea, #764ba2, transparent);
|
||
animation: shimmer 3s ease-in-out infinite;
|
||
}
|
||
|
||
@keyframes shimmer {
|
||
0%, 100% { opacity: 0.5; }
|
||
50% { opacity: 1; }
|
||
}
|
||
|
||
.sidebar-brand {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 1rem;
|
||
font-size: 1.1rem;
|
||
font-weight: 700;
|
||
color: #fff;
|
||
text-decoration: none;
|
||
position: relative;
|
||
transition: transform 0.3s ease;
|
||
padding: 0.5rem;
|
||
border-radius: 0.5rem;
|
||
margin: -0.5rem;
|
||
}
|
||
|
||
.sidebar-brand:hover {
|
||
transform: translateX(2px);
|
||
background: rgba(255, 255, 255, 0.05);
|
||
text-decoration: none;
|
||
}
|
||
|
||
.brand-icon {
|
||
font-size: 2rem;
|
||
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.4));
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
display: inline-block;
|
||
animation: pulse 2s ease-in-out infinite;
|
||
position: relative;
|
||
width: 1.2em;
|
||
text-align: center;
|
||
}
|
||
|
||
.brand-icon::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
width: 120%;
|
||
height: 120%;
|
||
background: radial-gradient(circle, rgba(102, 126, 234, 0.3) 0%, transparent 70%);
|
||
border-radius: 50%;
|
||
z-index: -1;
|
||
animation: glow 2s ease-in-out infinite;
|
||
}
|
||
|
||
@keyframes pulse {
|
||
0%, 100% { transform: scale(1); }
|
||
50% { transform: scale(1.05); }
|
||
}
|
||
|
||
@keyframes glow {
|
||
0%, 100% { opacity: 0.5; transform: translate(-50%, -50%) scale(1); }
|
||
50% { opacity: 0.8; transform: translate(-50%, -50%) scale(1.1); }
|
||
}
|
||
|
||
.brand-text {
|
||
background: linear-gradient(135deg, #ffffff 0%, #e0e7ff 50%, #c7d2fe 100%);
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
letter-spacing: 0.02em;
|
||
line-height: 1.3;
|
||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.sidebar-nav {
|
||
flex: 1;
|
||
padding: 1rem 0;
|
||
overflow-y: auto;
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-height: 0;
|
||
}
|
||
|
||
.sidebar-menu {
|
||
list-style: none;
|
||
padding: 0;
|
||
flex: 1 1 auto;
|
||
margin: 0;
|
||
}
|
||
|
||
.sidebar-menu-item {
|
||
margin: 0.25rem 0;
|
||
}
|
||
|
||
.sidebar-menu-divider {
|
||
height: 1px;
|
||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
|
||
margin: 0.75rem 1.25rem;
|
||
border: none;
|
||
list-style: none;
|
||
}
|
||
|
||
.sidebar-menu-link {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
padding: 0.875rem 1.25rem;
|
||
color: var(--sidebar-text);
|
||
text-decoration: none;
|
||
transition: var(--transition);
|
||
border-left: 3px solid rgba(102, 126, 234, 0.3);
|
||
font-weight: 500;
|
||
font-size: 0.9375rem;
|
||
background: rgba(0, 0, 0, 0.15);
|
||
border-radius: 0.375rem;
|
||
margin: 0 0.5rem;
|
||
}
|
||
|
||
.sidebar-menu-link:hover {
|
||
background: rgba(0, 0, 0, 0.25);
|
||
border-left-color: #667eea;
|
||
color: #fff;
|
||
transform: translateX(2px);
|
||
}
|
||
|
||
.sidebar-menu-link.active {
|
||
background: var(--sidebar-active);
|
||
border-left-color: #667eea;
|
||
color: #fff;
|
||
}
|
||
|
||
.menu-icon {
|
||
font-size: 1.25rem;
|
||
width: 24px;
|
||
text-align: center;
|
||
color: rgba(255, 255, 255, 0.5);
|
||
opacity: 0.7;
|
||
display: inline-block;
|
||
transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
|
||
position: relative;
|
||
}
|
||
|
||
.menu-icon.fas,
|
||
.menu-icon.far {
|
||
width: 1.2em;
|
||
}
|
||
|
||
.sidebar-menu-link:hover .menu-icon {
|
||
color: rgba(255, 255, 255, 0.8);
|
||
opacity: 0.9;
|
||
transform: scale(1.05);
|
||
}
|
||
|
||
.sidebar-menu-link.active .menu-icon {
|
||
color: rgba(255, 255, 255, 0.95);
|
||
opacity: 1;
|
||
}
|
||
|
||
.menu-text {
|
||
flex: 1;
|
||
}
|
||
|
||
.dropdown-arrow {
|
||
font-size: 0.75rem;
|
||
opacity: 0.7;
|
||
transition: transform 0.3s ease;
|
||
margin-left: auto;
|
||
}
|
||
|
||
.sidebar-dropdown-item {
|
||
position: relative;
|
||
margin: 0.25rem 0;
|
||
}
|
||
|
||
.sidebar-dropdown-item .sidebar-dropdown-toggle {
|
||
/* Стили наследуются от .sidebar-menu-link */
|
||
}
|
||
|
||
.sidebar-dropdown-item .sidebar-dropdown-toggle:hover {
|
||
/* Стили наследуются от .sidebar-menu-link:hover */
|
||
}
|
||
|
||
.sidebar-dropdown-item.open .dropdown-arrow {
|
||
transform: rotate(180deg);
|
||
}
|
||
|
||
.sidebar-dropdown-menu {
|
||
list-style: none;
|
||
padding: 0;
|
||
/* margin: 0.25rem 0.5rem 0; */
|
||
max-height: 0;
|
||
overflow: hidden;
|
||
transition: max-height 0.3s ease, padding 0.3s ease, background 0.3s ease, border 0.3s ease, box-shadow 0.3s ease;
|
||
background: transparent;
|
||
border-radius: 0.375rem;
|
||
border: 1px solid transparent;
|
||
box-shadow: none;
|
||
}
|
||
|
||
.sidebar-dropdown-item.open .sidebar-dropdown-menu {
|
||
max-height: 500px;
|
||
padding: 0.5rem 0;
|
||
background: rgba(0, 0, 0, 0.3);
|
||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
.sidebar-dropdown-menu .sidebar-menu-link {
|
||
padding-left: 1.75rem;
|
||
padding-right: 1rem;
|
||
font-size: 0.875rem;
|
||
padding-top: 0.625rem;
|
||
padding-bottom: 0.625rem;
|
||
margin: 0.125rem 0.5rem;
|
||
border-radius: 0.25rem;
|
||
background: transparent;
|
||
}
|
||
|
||
.sidebar-dropdown-menu .sidebar-menu-link:hover {
|
||
background: rgba(102, 126, 234, 0.15);
|
||
transform: translateX(2px);
|
||
}
|
||
|
||
.sidebar-dropdown-menu .sidebar-menu-link.active {
|
||
background: rgba(102, 126, 234, 0.25);
|
||
border-left-color: #667eea;
|
||
}
|
||
|
||
.sidebar-dropdown-menu .sidebar-menu-link .menu-icon {
|
||
font-size: 1rem;
|
||
width: 20px;
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.sidebar-dropdown-menu .sidebar-menu-link:hover .menu-icon,
|
||
.sidebar-dropdown-menu .sidebar-menu-link.active .menu-icon {
|
||
opacity: 1;
|
||
color: rgba(255, 255, 255, 0.95);
|
||
}
|
||
|
||
.sidebar-dropdown-toggle {
|
||
cursor: pointer;
|
||
}
|
||
|
||
.sidebar-dropdown-item:has(.sidebar-menu-link.active) .sidebar-dropdown-toggle {
|
||
background: var(--sidebar-active);
|
||
border-left-color: #667eea;
|
||
color: #fff;
|
||
}
|
||
|
||
.sidebar-dropdown-item:has(.sidebar-menu-link.active) .sidebar-dropdown-toggle .menu-icon {
|
||
color: rgba(255, 255, 255, 0.95);
|
||
opacity: 1;
|
||
}
|
||
|
||
.sidebar-dropdown-link {
|
||
display: block;
|
||
padding: 0.625rem 1.25rem 0.625rem 1.75rem;
|
||
color: var(--sidebar-text);
|
||
text-decoration: none;
|
||
font-size: 0.875rem;
|
||
transition: var(--transition);
|
||
border-left: 3px solid transparent;
|
||
}
|
||
|
||
.sidebar-dropdown-link:hover {
|
||
background: var(--sidebar-hover);
|
||
border-left-color: #667eea;
|
||
color: #fff;
|
||
padding-left: 1.875rem;
|
||
}
|
||
|
||
.sidebar-dropdown-link:active,
|
||
.sidebar-dropdown-link.active {
|
||
background: var(--sidebar-active);
|
||
border-left-color: #667eea;
|
||
color: #fff;
|
||
}
|
||
|
||
.sidebar-footer {
|
||
padding: 1.25rem;
|
||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||
background: rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
/* Бейджи в самом низу sidebar-nav: пользователь и версия, в одну строку, приглушённые под цвет menu-text */
|
||
.sidebar-nav-badges {
|
||
display: flex;
|
||
flex-wrap: nowrap;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 0.5rem;
|
||
margin-top: auto;
|
||
padding: 0.75rem 0.5rem 0;
|
||
min-height: 1.5rem;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.sidebar-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
padding: 0.2rem 0.5rem;
|
||
font-size: 0.75rem;
|
||
font-weight: 500;
|
||
color: rgba(255, 255, 255, 0.75);
|
||
background: rgba(255, 255, 255, 0.08);
|
||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||
border-radius: 0.25rem;
|
||
white-space: nowrap;
|
||
max-width: 50%;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.sidebar.collapsed .sidebar-nav-badges {
|
||
display: none;
|
||
}
|
||
|
||
.sidebar-export-import {
|
||
display: flex;
|
||
gap: 0.5rem;
|
||
margin-bottom: 0.75rem;
|
||
}
|
||
|
||
.sidebar-export-import .btn {
|
||
flex: 1;
|
||
padding: 0.625rem 0.75rem;
|
||
border-radius: 0.5rem;
|
||
font-weight: 500;
|
||
font-size: 0.875rem;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 0.5rem;
|
||
text-decoration: none;
|
||
transition: var(--transition);
|
||
border: 1px solid;
|
||
}
|
||
|
||
.btn-export-sidebar {
|
||
background: rgba(13, 110, 253, 0.2);
|
||
border-color: rgba(13, 110, 253, 0.3);
|
||
color: #93c5fd;
|
||
}
|
||
|
||
.btn-export-sidebar:hover {
|
||
background: rgba(13, 110, 253, 0.3);
|
||
border-color: rgba(13, 110, 253, 0.5);
|
||
color: #fff;
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
.btn-import-sidebar {
|
||
background: rgba(25, 135, 84, 0.2);
|
||
border-color: rgba(25, 135, 84, 0.3);
|
||
color: #86efac;
|
||
}
|
||
|
||
.btn-import-sidebar:hover {
|
||
background: rgba(25, 135, 84, 0.3);
|
||
border-color: rgba(25, 135, 84, 0.5);
|
||
color: #fff;
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
.sidebar-user {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
margin-bottom: 1rem;
|
||
padding: 0.75rem;
|
||
background: rgba(255, 255, 255, 0.05);
|
||
border-radius: 0.5rem;
|
||
}
|
||
|
||
.user-icon {
|
||
font-size: 1.25rem;
|
||
}
|
||
|
||
.user-name {
|
||
font-weight: 600;
|
||
color: #fff;
|
||
font-size: 0.9375rem;
|
||
}
|
||
|
||
.sidebar-logout {
|
||
width: 100%;
|
||
padding: 0 0.5rem;
|
||
}
|
||
|
||
/* Кнопка выхода в стиле пунктов меню */
|
||
.btn-logout-sidebar {
|
||
/* Наследует стили от .sidebar-menu-link */
|
||
background: rgba(220, 53, 69, 0.15) !important;
|
||
border-left-color: rgba(220, 53, 69, 0.4) !important;
|
||
color: #fca5a5 !important;
|
||
}
|
||
|
||
.btn-logout-sidebar:hover {
|
||
background: rgba(220, 53, 69, 0.25) !important;
|
||
border-left-color: #dc3545 !important;
|
||
color: #fff !important;
|
||
transform: translateX(2px);
|
||
}
|
||
|
||
.btn-logout-sidebar .menu-icon {
|
||
color: rgba(252, 165, 165, 0.7);
|
||
}
|
||
|
||
.btn-logout-sidebar:hover .menu-icon {
|
||
color: #fff;
|
||
opacity: 1;
|
||
}
|
||
|
||
/* Main wrapper */
|
||
.main-wrapper {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-height: 100vh;
|
||
transition: var(--transition);
|
||
}
|
||
|
||
body.with-sidebar .main-wrapper {
|
||
margin-left: var(--sidebar-width);
|
||
transition: margin-left 0.25s ease;
|
||
}
|
||
|
||
/* Content header */
|
||
.content-header {
|
||
background: #fff;
|
||
border-bottom: 1px solid #e5e7eb;
|
||
padding: 1rem 1.5rem;
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 100;
|
||
}
|
||
|
||
.content-header-inner {
|
||
max-width: 100%;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
gap: 1rem;
|
||
}
|
||
|
||
.header-actions {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 0.5rem;
|
||
align-items: center;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.header-actions .btn {
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* Адаптивность для header-actions на мобильных устройствах */
|
||
@media (max-width: 576px) {
|
||
.header-actions {
|
||
width: 100%;
|
||
justify-content: flex-start;
|
||
}
|
||
|
||
.header-actions .btn {
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
}
|
||
}
|
||
|
||
.page-title {
|
||
font-size: 1.5rem;
|
||
font-weight: 700;
|
||
color: #1f2937;
|
||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||
margin: 0;
|
||
}
|
||
|
||
/* Main content */
|
||
.main-content {
|
||
flex: 1;
|
||
min-width: 0; /* чтобы широкий контент (логи, pre) не растягивал страницу */
|
||
padding: 1rem 1.5rem;
|
||
width: 100%;
|
||
max-width: 100%;
|
||
overflow-x: auto;
|
||
background: transparent;
|
||
}
|
||
|
||
/* Стили для блоков с кодом Dockerfile - предотвращение выхода за границы */
|
||
.dockerfile-code-wrapper {
|
||
width: 100%;
|
||
max-width: 100%;
|
||
overflow-x: auto;
|
||
overflow-y: hidden;
|
||
}
|
||
|
||
.dockerfile-code-wrapper pre {
|
||
width: 100%;
|
||
max-width: 100%;
|
||
overflow-x: auto;
|
||
overflow-y: hidden;
|
||
word-wrap: break-word;
|
||
white-space: pre-wrap;
|
||
word-break: break-all;
|
||
margin: 0;
|
||
}
|
||
|
||
.dockerfile-code-wrapper code {
|
||
display: block;
|
||
width: 100%;
|
||
max-width: 100%;
|
||
overflow-x: auto;
|
||
word-wrap: break-word;
|
||
white-space: pre-wrap;
|
||
word-break: break-all;
|
||
font-family: 'Courier New', Courier, monospace;
|
||
font-size: 0.875rem;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
/* Стили для модального окна сообщений */
|
||
#messageModal .modal-dialog-centered {
|
||
display: flex;
|
||
align-items: center;
|
||
min-height: calc(100% - 1rem);
|
||
}
|
||
|
||
#messageModal .modal-content {
|
||
border-radius: 0.5rem;
|
||
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||
}
|
||
|
||
#messageModal .modal-header {
|
||
border-radius: 0.5rem 0.5rem 0 0;
|
||
border-bottom: none;
|
||
padding: 1rem 1.5rem;
|
||
}
|
||
|
||
#messageModal .modal-body {
|
||
padding: 1.5rem;
|
||
font-size: 1rem;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
#messageModal .modal-footer {
|
||
border-top: 1px solid #dee2e6;
|
||
padding: 0.75rem 1.5rem;
|
||
}
|
||
|
||
#messageModal .modal-header.bg-success,
|
||
#messageModal .modal-header.bg-danger,
|
||
#messageModal .modal-header.bg-warning,
|
||
#messageModal .modal-header.bg-info {
|
||
color: white;
|
||
}
|
||
|
||
#messageModal .modal-header.bg-warning {
|
||
color: #212529;
|
||
}
|
||
|
||
/* Стили для модального окна подтверждения */
|
||
#confirmModal .modal-dialog-centered {
|
||
display: flex;
|
||
align-items: center;
|
||
min-height: calc(100% - 1rem);
|
||
}
|
||
|
||
#confirmModal .modal-content {
|
||
border-radius: 0.5rem;
|
||
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||
}
|
||
|
||
#confirmModal .modal-header {
|
||
border-radius: 0.5rem 0.5rem 0 0;
|
||
border-bottom: none;
|
||
padding: 1rem 1.5rem;
|
||
background-color: #ffc107 !important;
|
||
color: #212529;
|
||
}
|
||
|
||
#confirmModal .modal-body {
|
||
padding: 1.5rem;
|
||
font-size: 1rem;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
#confirmModal .modal-footer {
|
||
border-top: 1px solid #dee2e6;
|
||
padding: 0.75rem 1.5rem;
|
||
gap: 0.5rem;
|
||
}
|
||
|
||
#confirmModal .modal-footer .btn {
|
||
min-width: 120px;
|
||
}
|
||
|
||
/* Убираем контейнеры для максимального использования пространства */
|
||
.container-xl,
|
||
.container-lg,
|
||
.container-md,
|
||
.container-sm,
|
||
.container {
|
||
max-width: 100% !important;
|
||
padding-left: 0 !important;
|
||
padding-right: 0 !important;
|
||
}
|
||
|
||
/* Страница лога синхронизации: окно лога на всю высоту экрана, отступ снизу 2rem, без отступа у card-header */
|
||
.sync-run-log-page .sync-run-log-card {
|
||
display: flex;
|
||
flex-direction: column;
|
||
/* Высота: весь экран минус шапка страницы, card-header и 2rem отступ снизу */
|
||
height: calc(100vh - 7rem);
|
||
margin-bottom: 0 !important;
|
||
}
|
||
.sync-run-log-page .sync-run-log-card-header {
|
||
margin-bottom: 0 !important;
|
||
padding-bottom: 0.5rem !important;
|
||
flex-shrink: 0;
|
||
}
|
||
.sync-run-log-page .sync-run-log-card .card-body {
|
||
flex: 1;
|
||
min-height: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.sync-run-log-page .sync-log-scroll-wrapper {
|
||
overflow-x: auto !important;
|
||
overflow-y: auto !important;
|
||
-webkit-overflow-scrolling: touch;
|
||
flex: 1;
|
||
min-height: 0;
|
||
}
|
||
.sync-run-log-page .sync-run-log-pre {
|
||
white-space: pre !important;
|
||
width: max-content !important;
|
||
min-width: 100% !important;
|
||
display: block !important;
|
||
}
|
||
|
||
/* Карточки */
|
||
.card {
|
||
border: none;
|
||
border-radius: var(--border-radius);
|
||
box-shadow: var(--box-shadow);
|
||
transition: var(--transition);
|
||
margin-bottom: 1rem;
|
||
background: #fff;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.card-header {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||
padding: 0.875rem 1rem;
|
||
font-weight: 600;
|
||
font-size: 0.9375rem;
|
||
border-radius: var(--border-radius) var(--border-radius) 0 0;
|
||
color: #fff;
|
||
}
|
||
|
||
/* Белый цвет для всех заголовков в card-header */
|
||
.card-header h1,
|
||
.card-header h2,
|
||
.card-header h3,
|
||
.card-header h4,
|
||
.card-header h5,
|
||
.card-header h6,
|
||
.card-header .h1,
|
||
.card-header .h2,
|
||
.card-header .h3,
|
||
.card-header .h4,
|
||
.card-header .h5,
|
||
.card-header .h6 {
|
||
color: #fff !important;
|
||
margin: 0;
|
||
}
|
||
|
||
.card-body {
|
||
padding: 1rem;
|
||
}
|
||
|
||
/* Единый стиль форм Planning UI — выравнивание, группы, фоны */
|
||
.planning-modal-form .modal-body {
|
||
padding: 1rem 1.25rem;
|
||
}
|
||
.planning-modal-form .form-label {
|
||
margin-bottom: 0.35rem;
|
||
}
|
||
.planning-modal-form .form-text {
|
||
font-size: 0.8rem;
|
||
margin-top: 0.25rem;
|
||
}
|
||
/* Группа с фоном — для ресурсов, параметров */
|
||
.planning-form-group {
|
||
background: #f8fafc;
|
||
border: 1px solid #e2e8f0;
|
||
border-radius: 0.5rem;
|
||
padding: 1rem 1.25rem;
|
||
margin-bottom: 1rem;
|
||
}
|
||
.planning-form-group:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
/* Подсказка в модальном окне — карточка с пояснением */
|
||
.planning-modal-hint {
|
||
background: #f8fafc;
|
||
border: 1px solid #e2e8f0;
|
||
border-radius: 0.5rem;
|
||
margin-bottom: 1rem;
|
||
}
|
||
.planning-modal-hint .card-body {
|
||
padding: 0.75rem 1rem;
|
||
}
|
||
.planning-modal-hint .card-text {
|
||
font-size: 0.875rem;
|
||
margin-bottom: 0;
|
||
}
|
||
.planning-form-group-title {
|
||
font-size: 0.75rem;
|
||
font-weight: 600;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.05em;
|
||
color: #64748b;
|
||
margin-bottom: 0.75rem;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
}
|
||
/* Имя/название — на всю ширину */
|
||
.planning-form-field-full {
|
||
width: 100%;
|
||
}
|
||
.planning-modal-form .row.g-3 {
|
||
--bs-gutter-x: 1rem;
|
||
--bs-gutter-y: 0.75rem;
|
||
}
|
||
|
||
/* Формы добавления/редактирования сервера в Planning UI */
|
||
.planning-server-form-section {
|
||
padding-bottom: 0.5rem;
|
||
}
|
||
.planning-server-form-section.planning-form-group {
|
||
background: #f8fafc;
|
||
border: 1px solid #e2e8f0;
|
||
border-radius: 0.5rem;
|
||
padding: 1rem 1.25rem;
|
||
}
|
||
.planning-server-form-section h6 {
|
||
letter-spacing: 0.05em;
|
||
padding-bottom: 0.25rem;
|
||
border-bottom: 1px solid #e9ecef;
|
||
}
|
||
|
||
/* Карточки кластеров Ceph в Planning UI */
|
||
.planning-ceph-cluster-card {
|
||
transition: box-shadow 0.2s ease, border-color 0.2s ease;
|
||
}
|
||
.planning-ceph-cluster-card:hover {
|
||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15) !important;
|
||
border-color: rgba(102, 126, 234, 0.4) !important;
|
||
}
|
||
.planning-ceph-pools-list .d-flex.align-items-center {
|
||
transition: background 0.15s ease;
|
||
}
|
||
.planning-ceph-pools-list .d-flex.align-items-center:hover {
|
||
background: rgba(102, 126, 234, 0.08) !important;
|
||
}
|
||
|
||
/* Планирование: компактные заголовки карточек и более широкие строки таблиц */
|
||
.planning-workspace .card-header.d-flex.justify-content-between.align-items-center {
|
||
margin-bottom: 0;
|
||
}
|
||
.planning-workspace .card-header {
|
||
margin-bottom: 0;
|
||
}
|
||
.planning-workspace .table td,
|
||
.planning-workspace .table th {
|
||
padding: 0.65rem 0.75rem;
|
||
vertical-align: middle;
|
||
}
|
||
.planning-workspace .table tbody tr {
|
||
min-height: 2.5rem;
|
||
}
|
||
|
||
/* Диски и GPU в инвентаре серверов — выделение, количество отдельно, add-кнопки внизу */
|
||
.planning-inv-disks-col,
|
||
.planning-inv-gpus-col {
|
||
min-width: 0;
|
||
}
|
||
.planning-inv-item {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
flex-wrap: wrap;
|
||
padding: 0.25rem 0.5rem;
|
||
border-radius: 0.35rem;
|
||
font-size: 0.8rem;
|
||
gap: 0.15rem;
|
||
}
|
||
.planning-inv-disk {
|
||
background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
|
||
border: 1px solid #86efac;
|
||
color: #166534;
|
||
}
|
||
.planning-inv-pool {
|
||
background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
|
||
border: 1px solid #93c5fd;
|
||
color: #1e40af;
|
||
}
|
||
.planning-inv-gpu {
|
||
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
|
||
border: 1px solid #fcd34d;
|
||
color: #92400e;
|
||
}
|
||
.planning-inv-item-count {
|
||
font-weight: 700;
|
||
font-size: 0.85em;
|
||
color: inherit;
|
||
opacity: 0.95;
|
||
padding: 0 0.2rem;
|
||
}
|
||
/* Сворачивание дисков/GPU при количестве > 1 — native details/summary */
|
||
.planning-inv-collapse-details {
|
||
list-style: none;
|
||
}
|
||
.planning-inv-collapse-details summary {
|
||
list-style: none;
|
||
cursor: pointer;
|
||
}
|
||
.planning-inv-collapse-details summary::-webkit-details-marker {
|
||
display: none;
|
||
}
|
||
.planning-inv-collapse-btn {
|
||
color: var(--bs-secondary);
|
||
text-decoration: none;
|
||
}
|
||
.planning-inv-collapse-btn:hover {
|
||
color: var(--bs-primary);
|
||
}
|
||
.planning-inv-chevron {
|
||
display: inline-block;
|
||
transition: transform 0.2s ease;
|
||
}
|
||
.planning-inv-collapse-details[open] .planning-inv-chevron {
|
||
transform: rotate(180deg);
|
||
}
|
||
/* Каждая запись в развёрнутом списке — на новой строке */
|
||
.planning-inv-collapse-content .planning-inv-item {
|
||
align-self: flex-start;
|
||
width: 100%;
|
||
max-width: 100%;
|
||
}
|
||
/* Модалки дисков — на 30% шире (500px * 1.3 ≈ 650px) */
|
||
.modal-dialog-disk {
|
||
max-width: 650px;
|
||
}
|
||
.planning-inv-add-btns {
|
||
padding-top: 0.25rem;
|
||
border-top: 1px dashed #e2e8f0;
|
||
}
|
||
.planning-inv-add-btns .btn-link {
|
||
opacity: 0.8;
|
||
}
|
||
.planning-inv-add-btns .btn-link:hover {
|
||
opacity: 1;
|
||
}
|
||
|
||
/* Иконки действий в планировании — с бордерами */
|
||
.planning-workspace .planning-action-btn,
|
||
.planning-workspace .col-actions .btn-link,
|
||
.planning-workspace .col-actions .btn,
|
||
.planning-workspace .planning-inv-add-btns .btn-link,
|
||
.planning-workspace .planning-inv-item .btn-link {
|
||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||
border-radius: 0.35rem;
|
||
padding: 0.2rem 0.35rem !important;
|
||
}
|
||
.planning-workspace .col-actions .btn-link:hover,
|
||
.planning-workspace .planning-inv-add-btns .btn-link:hover,
|
||
.planning-workspace .planning-inv-item .btn-link:hover {
|
||
border-color: rgba(0, 0, 0, 0.25);
|
||
background: rgba(0, 0, 0, 0.04);
|
||
}
|
||
|
||
/* Заголовок карточки Ceph кластера — имя слева, кнопки прижаты вправо */
|
||
.planning-ceph-cluster-card .card-header {
|
||
flex-wrap: nowrap;
|
||
overflow: hidden;
|
||
gap: 0.5rem;
|
||
}
|
||
.planning-ceph-cluster-card .card-header strong {
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.planning-ceph-cluster-card .card-header .col-actions {
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* Кнопки в заголовке карточки Ceph кластера — видимы и с обрамлением */
|
||
.planning-ceph-cluster-card .card-header .col-actions .btn-link,
|
||
.planning-ceph-cluster-card .card-header .col-actions button {
|
||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||
border-radius: 0.35rem;
|
||
padding: 0.35rem 0.5rem !important;
|
||
min-width: 1.75rem;
|
||
min-height: 1.75rem;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: #fff;
|
||
text-decoration: none !important;
|
||
}
|
||
.planning-ceph-cluster-card .card-header .col-actions .btn-link:hover,
|
||
.planning-ceph-cluster-card .card-header .col-actions button:hover {
|
||
background: #f8f9fa;
|
||
border-color: rgba(0, 0, 0, 0.3);
|
||
}
|
||
.planning-ceph-cluster-card .card-header .col-actions .fa-stack {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* Мини-карточки статистики Ceph кластера (replication, reserved, fast, bulk) */
|
||
.planning-ceph-stats-row {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 0.5rem;
|
||
}
|
||
.planning-ceph-stat-card {
|
||
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
||
border: 1px solid #e2e8f0;
|
||
border-radius: 0.4rem;
|
||
padding: 0.4rem 0.6rem;
|
||
font-size: 0.8rem;
|
||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||
}
|
||
.planning-ceph-stat-card.planning-ceph-stat-fast {
|
||
border-left: 3px solid #eab308;
|
||
background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%);
|
||
color: #92400e;
|
||
}
|
||
.planning-ceph-stat-card.planning-ceph-stat-bulk {
|
||
border-left: 3px solid #64748b;
|
||
background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%);
|
||
color: #475569;
|
||
}
|
||
/* Мини-карточки в Ceph кластере: слева — инфо, справа — пулы */
|
||
.planning-ceph-info-card .planning-ceph-stat-card,
|
||
.planning-ceph-pools-card .planning-ceph-stat-card {
|
||
padding: 0.35rem 0.5rem;
|
||
}
|
||
|
||
/* Мини-карточки Ceph пулов */
|
||
.planning-ceph-pool-card {
|
||
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
||
border: 1px solid #e2e8f0;
|
||
border-radius: 0.5rem;
|
||
padding: 0.6rem 0.75rem;
|
||
margin-bottom: 0.5rem;
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||
transition: box-shadow 0.2s;
|
||
}
|
||
.planning-ceph-pool-card:hover {
|
||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
|
||
}
|
||
.planning-ceph-pool-card.fast {
|
||
border-left: 3px solid #eab308;
|
||
background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%);
|
||
}
|
||
.planning-ceph-pool-card.bulk {
|
||
border-left: 3px solid #64748b;
|
||
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
||
}
|
||
|
||
/* Колонка Действия: 12% ширины для кнопок */
|
||
.col-actions {
|
||
width: 12%;
|
||
white-space: nowrap;
|
||
}
|
||
.col-actions .btn-link {
|
||
padding: 0 0.2rem;
|
||
}
|
||
|
||
/* Таблицы */
|
||
.table {
|
||
background-color: #fff;
|
||
border-radius: var(--border-radius);
|
||
overflow: hidden;
|
||
margin-bottom: 0;
|
||
font-size: 0.875rem;
|
||
}
|
||
|
||
.table thead {
|
||
background-color: #f8f9fa;
|
||
}
|
||
|
||
.table th {
|
||
font-weight: 600;
|
||
border-bottom: 2px solid #dee2e6;
|
||
padding: 0 0.5rem 0.5rem;
|
||
font-size: 0.8125rem;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.table td {
|
||
padding: 0 0.5rem 0.5rem;
|
||
vertical-align: middle;
|
||
font-size: 0.875rem;
|
||
}
|
||
|
||
/* Столбец Контент в списке хранилищ: перенос слов */
|
||
.storage-content-cell {
|
||
white-space: normal;
|
||
word-break: normal;
|
||
overflow-wrap: break-word;
|
||
max-width: 12rem;
|
||
}
|
||
|
||
.table tbody tr {
|
||
transition: var(--transition);
|
||
}
|
||
|
||
.table tbody tr:hover {
|
||
background-color: #f8f9fa;
|
||
}
|
||
|
||
/* Формы на страницах */
|
||
.form-page {
|
||
padding: 0;
|
||
}
|
||
|
||
.form-page .card {
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
/* Убираем большие отступы */
|
||
.row {
|
||
margin-left: -0.5rem;
|
||
margin-right: -0.5rem;
|
||
}
|
||
|
||
.row > * {
|
||
padding-left: 0.5rem;
|
||
padding-right: 0.5rem;
|
||
}
|
||
|
||
.mb-3 {
|
||
margin-bottom: 1rem !important;
|
||
}
|
||
|
||
.mt-3 {
|
||
margin-top: 1rem !important;
|
||
}
|
||
|
||
.py-3,
|
||
.pt-3,
|
||
.pb-3 {
|
||
padding-top: 1rem !important;
|
||
padding-bottom: 1rem !important;
|
||
}
|
||
|
||
/* Кнопки в заголовках */
|
||
.d-flex.justify-content-between.align-items-center {
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.d-flex.justify-content-between.align-items-center h2 {
|
||
margin: 0;
|
||
font-size: 1.5rem;
|
||
color: #1f2937;
|
||
font-weight: 700;
|
||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
/* Заголовки в контенте */
|
||
.main-content h1,
|
||
.main-content h2,
|
||
.main-content h3,
|
||
.main-content h4,
|
||
.main-content h5,
|
||
.main-content h6 {
|
||
color: #1f2937;
|
||
font-weight: 600;
|
||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.main-content h2 {
|
||
font-size: 1.5rem;
|
||
margin-bottom: 1rem;
|
||
padding-bottom: 0.5rem;
|
||
border-bottom: 2px solid #e9ecef;
|
||
}
|
||
|
||
.main-content h3 {
|
||
font-size: 1.25rem;
|
||
margin-bottom: 0.75rem;
|
||
}
|
||
|
||
.main-content h4 {
|
||
font-size: 1.125rem;
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
|
||
/* Оверлей при открытом сайдбаре на мобильных */
|
||
.sidebar-overlay {
|
||
display: none;
|
||
position: fixed;
|
||
inset: 0;
|
||
background: rgba(0, 0, 0, 0.4);
|
||
z-index: 999;
|
||
opacity: 0;
|
||
transition: opacity 0.3s ease;
|
||
}
|
||
.sidebar-overlay.visible {
|
||
display: block;
|
||
opacity: 1;
|
||
}
|
||
@media (min-width: 992px) {
|
||
.sidebar-overlay {
|
||
display: none !important;
|
||
}
|
||
}
|
||
|
||
/* Кнопка гамбургера для открытия сайдбара (только на узких экранах) */
|
||
.sidebar-toggle-btn {
|
||
display: none;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 2.5rem;
|
||
height: 2.5rem;
|
||
padding: 0;
|
||
border: 1px solid #e5e7eb;
|
||
border-radius: 0.375rem;
|
||
background: #fff;
|
||
color: #374151;
|
||
cursor: pointer;
|
||
transition: background 0.2s, color 0.2s;
|
||
}
|
||
.sidebar-toggle-btn:hover {
|
||
background: #f3f4f6;
|
||
color: #1f2937;
|
||
}
|
||
@media (max-width: 991.98px) {
|
||
.sidebar-toggle-btn {
|
||
display: inline-flex;
|
||
}
|
||
}
|
||
@media (min-width: 992px) {
|
||
.sidebar-toggle-btn {
|
||
display: none !important;
|
||
}
|
||
}
|
||
|
||
/* Адаптивность: сайдбар сворачивается влево, открывается по кнопке */
|
||
@media (max-width: 991.98px) {
|
||
.sidebar {
|
||
transform: translateX(-100%);
|
||
transition: transform 0.3s ease;
|
||
z-index: 1001;
|
||
box-shadow: none;
|
||
}
|
||
|
||
.sidebar.open {
|
||
transform: translateX(0);
|
||
box-shadow: 4px 0 20px rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
body.with-sidebar .main-wrapper {
|
||
margin-left: 0;
|
||
}
|
||
|
||
.main-content {
|
||
padding: 0.75rem 1rem;
|
||
}
|
||
|
||
.content-header {
|
||
padding: 0.75rem 1rem;
|
||
}
|
||
}
|
||
|
||
@media (min-width: 992px) {
|
||
.main-content {
|
||
padding: 1rem 2rem;
|
||
}
|
||
|
||
.content-header {
|
||
padding: 1rem 2rem;
|
||
}
|
||
}
|
||
|
||
/* Группы кнопок */
|
||
.btn-group {
|
||
display: inline-flex;
|
||
gap: 0.25rem;
|
||
align-items: center;
|
||
}
|
||
|
||
.btn-group .btn {
|
||
margin: 0;
|
||
padding: 0.375rem 0.5rem;
|
||
font-size: 0.875rem;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* Утилиты */
|
||
.shadow-sm {
|
||
box-shadow: var(--box-shadow);
|
||
}
|
||
|
||
.shadow {
|
||
box-shadow: var(--box-shadow-lg);
|
||
}
|
||
|
||
.rounded {
|
||
border-radius: var(--border-radius);
|
||
}
|
||
|
||
/* Анимации */
|
||
@keyframes fadeIn {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(-10px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
.fade-in {
|
||
animation: fadeIn 0.3s ease;
|
||
}
|
||
|
||
/* Скроллбар для sidebar */
|
||
.sidebar::-webkit-scrollbar {
|
||
width: 6px;
|
||
}
|
||
|
||
.sidebar::-webkit-scrollbar-track {
|
||
background: rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.sidebar::-webkit-scrollbar-thumb {
|
||
background: rgba(255, 255, 255, 0.2);
|
||
border-radius: 3px;
|
||
}
|
||
|
||
.sidebar::-webkit-scrollbar-thumb:hover {
|
||
background: rgba(255, 255, 255, 0.3);
|
||
}
|
||
|
||
/* Заголовки таблиц с сортировкой: перенос по пробелам (FP32 TFLOPs → FP32 / TFLOPs) */
|
||
th.sortable,
|
||
th.text-center.sortable {
|
||
white-space: normal;
|
||
word-break: normal;
|
||
overflow-wrap: break-word;
|
||
min-width: 0;
|
||
}
|
||
th.sortable a,
|
||
th.text-center.sortable a {
|
||
white-space: normal;
|
||
word-break: normal;
|
||
overflow-wrap: break-word;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
text-align: center;
|
||
max-width: 100%;
|
||
}
|
||
|
||
/* Sticky header для таблиц */
|
||
.table-responsive .sticky-top {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 10;
|
||
}
|
||
|
||
/* Навигация для сводок */
|
||
.summary-nav .card {
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.summary-nav .btn {
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* Таблицы в полную ширину */
|
||
.table-responsive {
|
||
width: 100%;
|
||
}
|
||
|
||
.table {
|
||
width: 100%;
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
/* Центрирование всех таблиц по умолчанию */
|
||
.table th,
|
||
.table td {
|
||
text-align: center;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
/* Исключения для текстовых полей (если нужно) */
|
||
.table th.text-start,
|
||
.table td.text-start {
|
||
text-align: left;
|
||
}
|
||
|
||
.table th.text-end,
|
||
.table td.text-end {
|
||
text-align: right;
|
||
}
|
||
|
||
/* Колонка Cluster в листинге VM: разрешаем перенос строк */
|
||
.vm-cluster-cell {
|
||
white-space: normal;
|
||
word-wrap: break-word;
|
||
overflow-wrap: break-word;
|
||
max-width: 12rem;
|
||
}
|
||
|
||
/* Report Cards Styles */
|
||
.report-card {
|
||
border-radius: 1rem;
|
||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||
background: #ffffff;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.report-card::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 4px;
|
||
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
|
||
transform: scaleX(0);
|
||
transform-origin: left;
|
||
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||
}
|
||
|
||
.report-card:hover {
|
||
transform: translateY(-8px);
|
||
box-shadow: 0 12px 40px rgba(102, 126, 234, 0.25) !important;
|
||
}
|
||
|
||
.report-card:hover::before {
|
||
transform: scaleX(1);
|
||
}
|
||
|
||
.report-card-header {
|
||
height: 120px;
|
||
position: relative;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.report-card-header::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
opacity: 0.1;
|
||
background: radial-gradient(circle at 30% 50%, rgba(255, 255, 255, 0.3) 0%, transparent 70%);
|
||
}
|
||
|
||
.report-card-header::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: -50%;
|
||
right: -50%;
|
||
width: 200%;
|
||
height: 200%;
|
||
background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%);
|
||
animation: rotate 20s linear infinite;
|
||
}
|
||
|
||
@keyframes rotate {
|
||
from {
|
||
transform: rotate(0deg);
|
||
}
|
||
to {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
|
||
.report-icon-wrapper {
|
||
position: relative;
|
||
z-index: 1;
|
||
width: 80px;
|
||
height: 80px;
|
||
border-radius: 20px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
backdrop-filter: blur(10px);
|
||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||
background: rgba(255, 255, 255, 0.2);
|
||
}
|
||
|
||
.report-card:hover .report-icon-wrapper {
|
||
transform: scale(1.1) rotate(5deg);
|
||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
.report-icon-large {
|
||
font-size: 2.5rem;
|
||
color: #ffffff;
|
||
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.2));
|
||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||
}
|
||
|
||
.report-card:hover .report-icon-large {
|
||
transform: scale(1.1);
|
||
}
|
||
|
||
/* Color variants for report cards */
|
||
.report-card-primary {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
}
|
||
|
||
.report-card-info {
|
||
background: linear-gradient(135deg, #0dcaf0 0%, #0aa2c0 100%);
|
||
}
|
||
|
||
.report-card-success {
|
||
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
||
}
|
||
|
||
.report-card-warning {
|
||
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
||
}
|
||
|
||
.report-card-danger {
|
||
background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
|
||
}
|
||
|
||
/* Report card buttons */
|
||
.btn-report-action {
|
||
border: none;
|
||
border-radius: 0.75rem;
|
||
padding: 0.75rem 1.5rem;
|
||
font-weight: 600;
|
||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.btn-report-action::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
width: 0;
|
||
height: 0;
|
||
border-radius: 50%;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
transform: translate(-50%, -50%);
|
||
transition: width 0.6s, height 0.6s;
|
||
}
|
||
|
||
.btn-report-action:hover::before {
|
||
width: 300px;
|
||
height: 300px;
|
||
}
|
||
|
||
.btn-report-action span,
|
||
.btn-report-action i {
|
||
position: relative;
|
||
z-index: 1;
|
||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
}
|
||
|
||
.btn-report-action:hover span {
|
||
transform: translateX(-4px);
|
||
}
|
||
|
||
.btn-report-action:hover i {
|
||
transform: translateX(4px);
|
||
}
|
||
|
||
.report-btn-primary {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
.report-btn-primary:hover {
|
||
background: linear-gradient(135deg, #5568d3 0%, #6a3d8f 100%);
|
||
color: #ffffff;
|
||
box-shadow: 0 8px 24px rgba(102, 126, 234, 0.4);
|
||
}
|
||
|
||
.report-btn-info {
|
||
background: linear-gradient(135deg, #0dcaf0 0%, #0aa2c0 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
.report-btn-info:hover {
|
||
background: linear-gradient(135deg, #0bb6d8 0%, #0891b2 100%);
|
||
color: #ffffff;
|
||
box-shadow: 0 8px 24px rgba(13, 202, 240, 0.4);
|
||
}
|
||
|
||
.report-btn-success {
|
||
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
.report-btn-success:hover {
|
||
background: linear-gradient(135deg, #059669 0%, #047857 100%);
|
||
color: #ffffff;
|
||
box-shadow: 0 8px 24px rgba(16, 185, 129, 0.4);
|
||
}
|
||
|
||
.report-btn-warning {
|
||
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
.report-btn-warning:hover {
|
||
background: linear-gradient(135deg, #d97706 0%, #b45309 100%);
|
||
color: #ffffff;
|
||
box-shadow: 0 8px 24px rgba(245, 158, 11, 0.4);
|
||
}
|
||
|
||
.report-btn-danger {
|
||
background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
.report-btn-danger:hover {
|
||
background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);
|
||
color: #ffffff;
|
||
box-shadow: 0 8px 24px rgba(239, 68, 68, 0.4);
|
||
}
|
||
|
||
/* Stat Cards Styles */
|
||
.stat-card {
|
||
background: #ffffff;
|
||
border: 2px solid #e5e7eb;
|
||
border-radius: 0.75rem;
|
||
padding: 1rem;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 1rem;
|
||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
height: 100%;
|
||
min-height: 100px;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.stat-card:hover {
|
||
transform: translateY(-4px);
|
||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||
border-color: #667eea;
|
||
}
|
||
|
||
.stat-card-icon {
|
||
width: 48px;
|
||
height: 48px;
|
||
border-radius: 0.5rem;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 1.5rem;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.stat-card-content {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.stat-card-label {
|
||
font-size: 0.75rem;
|
||
color: #6b7280;
|
||
text-transform: uppercase;
|
||
font-weight: 600;
|
||
letter-spacing: 0.5px;
|
||
margin-bottom: 0.25rem;
|
||
}
|
||
|
||
.stat-card-value {
|
||
font-size: 1.25rem;
|
||
font-weight: 700;
|
||
color: #1f2937;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
.stat-card-subvalue {
|
||
font-size: 0.875rem;
|
||
color: #6b7280;
|
||
margin-top: 0.25rem;
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* Stat Card Color Variants */
|
||
.stat-card-cpu .stat-card-icon {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
.stat-card-ram .stat-card-icon {
|
||
background: linear-gradient(135deg, #0dcaf0 0%, #0aa2c0 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
.stat-card-hdd .stat-card-icon {
|
||
background: linear-gradient(135deg, #6c757d 0%, #5a6268 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
.stat-card-ssd .stat-card-icon {
|
||
background: linear-gradient(135deg, #ffc107 0%, #ffb300 100%);
|
||
color: #212529;
|
||
}
|
||
|
||
.stat-card-nvme .stat-card-icon {
|
||
background: linear-gradient(135deg, #198754 0%, #157347 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
.stat-card-gpu .stat-card-icon {
|
||
background: linear-gradient(135deg, #dc3545 0%, #bb2d3b 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
/* Endpoint Selector Styles */
|
||
.endpoint-selector-wrapper {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 1rem;
|
||
padding: 0.75rem 1rem;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
border-radius: 0.75rem;
|
||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2);
|
||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
}
|
||
|
||
.endpoint-selector-wrapper:hover {
|
||
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.3);
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
.endpoint-selector-label {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
color: #ffffff;
|
||
font-weight: 600;
|
||
font-size: 0.9rem;
|
||
margin: 0;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.endpoint-selector-label i {
|
||
font-size: 1.1rem;
|
||
opacity: 0.9;
|
||
}
|
||
|
||
.endpoint-selector {
|
||
flex: 1;
|
||
min-width: 200px;
|
||
padding: 0.5rem 1rem;
|
||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||
border-radius: 0.5rem;
|
||
background: rgba(255, 255, 255, 0.95);
|
||
color: #1f2937;
|
||
font-weight: 500;
|
||
font-size: 0.95rem;
|
||
transition: all 0.3s ease;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.endpoint-selector:hover {
|
||
border-color: rgba(255, 255, 255, 0.5);
|
||
background: #ffffff;
|
||
}
|
||
|
||
.endpoint-selector:focus {
|
||
outline: none;
|
||
border-color: rgba(255, 255, 255, 0.8);
|
||
background: #ffffff;
|
||
box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.2);
|
||
}
|
||
|
||
/* Pagination Styles */
|
||
/* Автор: Сергей Антропов - https://devops.org.ru */
|
||
.pagination {
|
||
display: flex;
|
||
list-style: none;
|
||
padding: 0;
|
||
margin: 0;
|
||
gap: 0.5rem;
|
||
}
|
||
|
||
.pagination .page-item {
|
||
margin: 0;
|
||
}
|
||
|
||
.pagination .page-link {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-width: 2.5rem;
|
||
height: 2.5rem;
|
||
padding: 0.5rem 0.75rem;
|
||
border: 2px solid #e5e7eb;
|
||
border-radius: 0.5rem;
|
||
background: #ffffff;
|
||
color: #4b5563;
|
||
text-decoration: none;
|
||
font-weight: 600;
|
||
font-size: 0.875rem;
|
||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.pagination .page-link:hover {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: #ffffff;
|
||
border-color: #667eea;
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
|
||
text-decoration: none;
|
||
}
|
||
|
||
.pagination .page-item.active .page-link {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: #ffffff;
|
||
border-color: #667eea;
|
||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
||
font-weight: 700;
|
||
}
|
||
|
||
.pagination .page-item.active .page-link:hover {
|
||
background: linear-gradient(135deg, #5568d3 0%, #6a3d8f 100%);
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
|
||
}
|
||
|
||
.pagination .page-item.disabled .page-link {
|
||
background: #f3f4f6;
|
||
color: #9ca3af;
|
||
border-color: #e5e7eb;
|
||
cursor: not-allowed;
|
||
opacity: 0.6;
|
||
box-shadow: none;
|
||
}
|
||
|
||
.pagination .page-item.disabled .page-link:hover {
|
||
background: #f3f4f6;
|
||
color: #9ca3af;
|
||
border-color: #e5e7eb;
|
||
transform: none;
|
||
box-shadow: none;
|
||
}
|
||
|
||
.pagination.pagination-sm .page-link {
|
||
min-width: 2rem;
|
||
height: 2rem;
|
||
padding: 0.375rem 0.625rem;
|
||
font-size: 0.8125rem;
|
||
}
|
||
|
||
/* Pagination Per Page Select Styles */
|
||
/* Автор: Сергей Антропов - https://devops.org.ru */
|
||
.pagination-per-page-wrapper {
|
||
position: relative;
|
||
display: inline-block;
|
||
}
|
||
|
||
.pagination-per-page-select {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-width: 4rem;
|
||
height: 2rem;
|
||
padding: 0.375rem 0.75rem 0.375rem 0.5rem;
|
||
border: 2px solid #e5e7eb;
|
||
border-radius: 0.5rem;
|
||
background: #ffffff;
|
||
color: #4b5563;
|
||
font-weight: 600;
|
||
font-size: 0.8125rem;
|
||
cursor: pointer;
|
||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||
appearance: none;
|
||
-webkit-appearance: none;
|
||
-moz-appearance: none;
|
||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%234b5563' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
|
||
background-repeat: no-repeat;
|
||
background-position: right 0.5rem center;
|
||
background-size: 0.75rem;
|
||
padding-right: 2rem;
|
||
}
|
||
|
||
.pagination-per-page-select:hover {
|
||
background-color: #f9fafb;
|
||
border-color: #667eea;
|
||
color: #667eea;
|
||
transform: translateY(-1px);
|
||
box-shadow: 0 4px 8px rgba(102, 126, 234, 0.2);
|
||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23667eea' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
|
||
}
|
||
|
||
.pagination-per-page-select:focus {
|
||
outline: none;
|
||
border-color: #667eea;
|
||
background-color: #ffffff;
|
||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1), 0 4px 12px rgba(102, 126, 234, 0.2);
|
||
color: #667eea;
|
||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23667eea' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
|
||
}
|
||
|
||
.pagination-per-page-select:active {
|
||
transform: translateY(0);
|
||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.pagination-per-page-select option {
|
||
padding: 0.5rem;
|
||
background: #ffffff;
|
||
color: #4b5563;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.pagination-per-page-select option:hover {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
.pagination-per-page-select option:checked {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: #ffffff;
|
||
}
|
||
|
||
/* Endpoint Status Toggle Buttons */
|
||
/* Автор: Сергей Антропов - https://devops.org.ru */
|
||
.endpoint-status-toggle {
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.endpoint-status-toggle .btn-group-toggle {
|
||
display: flex;
|
||
gap: 0.5rem;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.endpoint-status-btn {
|
||
flex: 1;
|
||
min-width: 140px;
|
||
padding: 0.75rem 1.25rem;
|
||
border: 2px solid #e5e7eb;
|
||
border-radius: 0.5rem;
|
||
background: #ffffff;
|
||
color: #4b5563;
|
||
font-weight: 600;
|
||
font-size: 0.875rem;
|
||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 0.5rem;
|
||
}
|
||
|
||
.endpoint-status-btn:hover {
|
||
border-color: #667eea;
|
||
color: #667eea;
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2);
|
||
background: #f9fafb;
|
||
}
|
||
|
||
.endpoint-status-btn.active {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: #ffffff;
|
||
border-color: #667eea;
|
||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
||
font-weight: 700;
|
||
}
|
||
|
||
.endpoint-status-btn.active:hover {
|
||
background: linear-gradient(135deg, #5568d3 0%, #6a3d8f 100%);
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
|
||
}
|
||
|
||
.endpoint-status-btn i {
|
||
font-size: 1rem;
|
||
}
|
||
|
||
/* Специальные цвета для разных статусов */
|
||
.endpoint-status-btn[data-status="planned"]:not(.active) {
|
||
border-color: #f59e0b;
|
||
color: #f59e0b;
|
||
}
|
||
|
||
.endpoint-status-btn[data-status="planned"]:not(.active):hover {
|
||
background: #fef3c7;
|
||
border-color: #f59e0b;
|
||
}
|
||
|
||
.endpoint-status-btn[data-status="planned"].active {
|
||
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
||
border-color: #f59e0b;
|
||
}
|
||
|
||
.endpoint-status-btn[data-status="disabled"]:not(.active) {
|
||
border-color: #ef4444;
|
||
color: #ef4444;
|
||
}
|
||
|
||
.endpoint-status-btn[data-status="disabled"]:not(.active):hover {
|
||
background: #fee2e2;
|
||
border-color: #ef4444;
|
||
}
|
||
|
||
.endpoint-status-btn[data-status="disabled"].active {
|
||
background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
|
||
border-color: #ef4444;
|
||
}
|
||
|
||
.endpoint-status-btn[data-status="enabled"]:not(.active) {
|
||
border-color: #10b981;
|
||
color: #10b981;
|
||
}
|
||
|
||
.endpoint-status-btn[data-status="enabled"]:not(.active):hover {
|
||
background: #d1fae5;
|
||
border-color: #10b981;
|
||
}
|
||
|
||
.endpoint-status-btn[data-status="enabled"].active {
|
||
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
||
border-color: #10b981;
|
||
}
|
||
|
||
/* Responsive pagination */
|
||
@media (max-width: 768px) {
|
||
.pagination {
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
}
|
||
|
||
.pagination .page-link {
|
||
min-width: 2rem;
|
||
height: 2rem;
|
||
padding: 0.375rem 0.5rem;
|
||
font-size: 0.8125rem;
|
||
}
|
||
|
||
.pagination-per-page-select {
|
||
min-width: 3.5rem;
|
||
height: 1.875rem;
|
||
font-size: 0.75rem;
|
||
padding: 0.25rem 1.75rem 0.25rem 0.375rem;
|
||
}
|
||
|
||
.endpoint-status-btn {
|
||
min-width: 100%;
|
||
flex: none;
|
||
}
|
||
}
|
||
|
||
/* HTMX Spinner Styles */
|
||
.htmx-indicator {
|
||
display: none;
|
||
opacity: 0;
|
||
transition: opacity 0.3s ease-in-out;
|
||
}
|
||
|
||
.htmx-request .htmx-indicator,
|
||
.htmx-request.htmx-indicator {
|
||
display: inline-block;
|
||
opacity: 1;
|
||
}
|
||
|
||
.htmx-request button {
|
||
opacity: 0.7;
|
||
cursor: wait;
|
||
}
|
||
|
||
/* Скрываем иконку во время загрузки, когда показывается спиннер */
|
||
.htmx-request .htmx-indicator-opposite {
|
||
display: none;
|
||
}
|
||
|
||
.spinner-border-sm {
|
||
width: 1rem;
|
||
height: 1rem;
|
||
border-width: 0.15em;
|
||
}
|
||
|
||
/* Модальный overlay для синхронизации */
|
||
.sync-overlay {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background-color: rgba(0, 0, 0, 0.75);
|
||
z-index: 9999;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
backdrop-filter: blur(2px);
|
||
-webkit-backdrop-filter: blur(2px);
|
||
}
|
||
|
||
.sync-modal {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
border-radius: 1rem;
|
||
padding: 2.5rem 3rem;
|
||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
|
||
min-width: 300px;
|
||
max-width: 90%;
|
||
text-align: center;
|
||
animation: fadeInScale 0.3s ease-out;
|
||
}
|
||
|
||
@keyframes fadeInScale {
|
||
from {
|
||
opacity: 0;
|
||
transform: scale(0.9);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: scale(1);
|
||
}
|
||
}
|
||
|
||
.sync-modal .spinner-border {
|
||
border-width: 0.25em;
|
||
}
|
||
|
||
.sync-modal .spinner-border.text-primary {
|
||
border-color: rgba(255, 255, 255, 0.3);
|
||
border-right-color: #ffffff;
|
||
}
|
||
|
||
/* Индикатор прогресса при общей синхронизации */
|
||
.sync-progress-indicator {
|
||
max-width: 280px;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
}
|
||
|
||
.sync-progress-bar-indeterminate {
|
||
height: 4px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
border-radius: 2px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.sync-progress-bar-indeterminate::after {
|
||
content: '';
|
||
display: block;
|
||
height: 100%;
|
||
width: 40%;
|
||
background: rgba(255, 255, 255, 0.9);
|
||
border-radius: 2px;
|
||
animation: syncProgressIndeterminate 1.5s ease-in-out infinite;
|
||
}
|
||
|
||
@keyframes syncProgressIndeterminate {
|
||
0% { transform: translateX(-100%); }
|
||
50% { transform: translateX(250%); }
|
||
100% { transform: translateX(-100%); }
|
||
}
|
||
|
||
/* Карточки результатов синхронизации по кластерам */
|
||
.sync-results-list {
|
||
text-align: left;
|
||
}
|
||
|
||
.sync-results-cards {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 0.5rem;
|
||
max-height: 280px;
|
||
overflow-y: auto;
|
||
padding-right: 0.25rem;
|
||
}
|
||
|
||
.sync-results-cards::-webkit-scrollbar {
|
||
width: 6px;
|
||
}
|
||
|
||
.sync-results-cards::-webkit-scrollbar-track {
|
||
background: rgba(255, 255, 255, 0.1);
|
||
border-radius: 3px;
|
||
}
|
||
|
||
.sync-results-cards::-webkit-scrollbar-thumb {
|
||
background: rgba(255, 255, 255, 0.3);
|
||
border-radius: 3px;
|
||
}
|
||
|
||
.sync-result-card {
|
||
background: rgba(255, 255, 255, 0.12);
|
||
border-radius: 0.5rem;
|
||
padding: 0.75rem 1rem;
|
||
border-left: 4px solid transparent;
|
||
}
|
||
|
||
.sync-result-card-ok {
|
||
border-left-color: rgba(255, 255, 255, 0.6);
|
||
background: rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
.sync-result-card-err {
|
||
border-left-color: rgba(255, 200, 200, 0.9);
|
||
background: rgba(255, 100, 100, 0.15);
|
||
}
|
||
|
||
.sync-result-card-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
margin-bottom: 0.35rem;
|
||
}
|
||
|
||
.sync-result-card-icon {
|
||
font-size: 0.85rem;
|
||
opacity: 0.9;
|
||
}
|
||
|
||
.sync-result-card-ok .sync-result-card-icon {
|
||
color: rgba(255, 255, 255, 0.9);
|
||
}
|
||
|
||
.sync-result-card-err .sync-result-card-icon {
|
||
color: rgba(255, 220, 220, 0.95);
|
||
}
|
||
|
||
.sync-result-card-name {
|
||
font-weight: 600;
|
||
color: rgba(255, 255, 255, 0.95);
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.sync-result-card-body {
|
||
font-size: 0.85rem;
|
||
color: rgba(255, 255, 255, 0.85);
|
||
line-height: 1.4;
|
||
padding-left: 1.4rem;
|
||
}
|
||
|
||
.sync-result-icon-ok {
|
||
color: rgba(255, 255, 255, 0.9) !important;
|
||
}
|
||
|
||
.sync-result-icon-err {
|
||
color: rgba(255, 220, 220, 0.95) !important;
|
||
}
|
||
|
||
.sync-modal h5 {
|
||
font-weight: 600;
|
||
font-size: 1.25rem;
|
||
}
|
||
|
||
/* Стили для секций дашборда */
|
||
.dashboard-section {
|
||
margin-bottom: 3rem;
|
||
}
|
||
|
||
.dashboard-section:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.dashboard-section h4 {
|
||
font-weight: 600;
|
||
font-size: 1.125rem;
|
||
color: #495057;
|
||
margin-bottom: 1rem;
|
||
padding-bottom: 0.5rem;
|
||
border-bottom: 2px solid #e9ecef;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
}
|
||
|
||
/* CodeMirror стили для ошибок */
|
||
.cm-error-line {
|
||
background-color: #ffe6e6 !important;
|
||
}
|
||
|
||
.cm-error-marker {
|
||
color: #dc3545;
|
||
font-weight: bold;
|
||
cursor: help;
|
||
}
|
||
|
||
/* CodeMirror общие стили */
|
||
.CodeMirror {
|
||
border: 1px solid #dee2e6;
|
||
border-radius: 0.375rem;
|
||
font-family: 'Courier New', monospace;
|
||
font-size: 14px;
|
||
height: auto;
|
||
min-height: 300px;
|
||
}
|
||
|
||
.CodeMirror-focused {
|
||
border-color: #86b7fe;
|
||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||
}
|
||
|
||
.dashboard-section h4 i {
|
||
color: #6c757d;
|
||
font-size: 1rem;
|
||
}
|
||
|
||
/* Страница настроек подкруток дашборда (в стиле проекта) */
|
||
.dashboard-settings-page .dashboard-tweak-table th {
|
||
font-weight: 600;
|
||
color: #495057;
|
||
}
|
||
.dashboard-settings-page .dashboard-tweak-table .tweak-input {
|
||
max-width: 6rem;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
text-align: center;
|
||
}
|
||
.dashboard-settings-page .dashboard-tweak-datacenter-cell {
|
||
font-weight: 500;
|
||
}
|
||
.dashboard-settings-page .dashboard-tweak-datacenter-icon {
|
||
width: 2rem;
|
||
height: 2rem;
|
||
border-radius: var(--border-radius);
|
||
background: linear-gradient(135deg, var(--primary-color) 0%, #0a58ca 100%);
|
||
color: #fff;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.sync-modal p {
|
||
font-size: 0.9rem;
|
||
opacity: 0.9;
|
||
}
|
||
|
||
/* Карточки ресурсов сервера - одинаковый размер */
|
||
.resource-card {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.resource-card > .card {
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-height: 180px;
|
||
}
|
||
|
||
.resource-card > .card > .card-body {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* Одинаковая высота для карточек основной информации и использования ресурсов */
|
||
.row.align-items-stretch > [class*="col-"] > .card.h-100,
|
||
.row > [class*="col-"] > .card.h-100 {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.row.align-items-stretch > [class*="col-"] > .card.h-100 > .card-body,
|
||
.row > [class*="col-"] > .card.h-100 > .card-body {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* Карточка CEPH пула */
|
||
.ceph-pool-hero { position: relative; }
|
||
.ceph-pool-hero-bg {
|
||
position: absolute;
|
||
inset: 0;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
opacity: 0.95;
|
||
}
|
||
.ceph-pool-hero .card-body { position: relative; z-index: 1; }
|
||
.ceph-pool-icon {
|
||
width: 56px;
|
||
height: 56px;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
border-radius: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 1.5rem;
|
||
color: #fff;
|
||
}
|
||
.ceph-pool-stats-mini {
|
||
display: flex;
|
||
gap: 1.5rem;
|
||
justify-content: flex-end;
|
||
flex-wrap: wrap;
|
||
}
|
||
.ceph-pool-stats-mini .stat-item { text-align: center; }
|
||
.ceph-pool-stats-mini .stat-value {
|
||
display: block;
|
||
font-size: 1.25rem;
|
||
font-weight: 600;
|
||
color: #fff;
|
||
}
|
||
.ceph-pool-stats-mini .stat-label {
|
||
font-size: 0.75rem;
|
||
color: rgba(255, 255, 255, 0.8);
|
||
}
|
||
.ceph-pool-progress {
|
||
background: rgba(255, 255, 255, 0.2);
|
||
border-radius: 4px;
|
||
}
|
||
.ceph-stat-card {
|
||
padding: 0.75rem;
|
||
border-radius: 8px;
|
||
text-align: center;
|
||
background: #f8f9fa;
|
||
border-left: 4px solid #dee2e6;
|
||
}
|
||
.ceph-stat-card-raw { border-left-color: #667eea; }
|
||
.ceph-stat-card-usable { border-left-color: #38ef7d; }
|
||
.ceph-stat-card-used { border-left-color: #ff9a9e; }
|
||
.ceph-stat-card-free { border-left-color: #a1c4fd; }
|
||
.ceph-stat-card-full { border-left-color: #4facfe; }
|
||
.ceph-stat-card-overhead { border-left-color: #fcb69f; }
|
||
.ceph-stat-value {
|
||
display: block;
|
||
font-weight: 600;
|
||
font-size: 1rem;
|
||
}
|
||
.ceph-stat-label {
|
||
font-size: 0.7rem;
|
||
color: #6c757d;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.05em;
|
||
}
|
||
|
||
/* Карточки дополнительной информации в CEPH пуле */
|
||
.ceph-info-card {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
padding: 0.75rem 1rem;
|
||
background: #f8f9fa;
|
||
border-radius: 0.5rem;
|
||
border: 1px solid #e9ecef;
|
||
transition: all 0.2s ease;
|
||
}
|
||
.ceph-info-card:hover {
|
||
background: #fff;
|
||
border-color: #667eea;
|
||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.15);
|
||
}
|
||
a:hover .ceph-info-card { color: inherit; }
|
||
.ceph-info-card-icon {
|
||
width: 40px;
|
||
height: 40px;
|
||
min-width: 40px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: #fff;
|
||
border-radius: 0.375rem;
|
||
font-size: 1rem;
|
||
}
|
||
.ceph-info-card-icon-rbd {
|
||
background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
|
||
}
|
||
.ceph-info-card-icon-vm {
|
||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||
}
|
||
.ceph-info-card-body { flex: 1; min-width: 0; }
|
||
.ceph-info-card-title {
|
||
font-weight: 600;
|
||
color: #212529;
|
||
margin-bottom: 0.25rem;
|
||
}
|
||
.ceph-info-card-stats {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 0.5rem 1rem;
|
||
font-size: 0.8rem;
|
||
color: #6c757d;
|
||
}
|
||
.ceph-info-stat { white-space: nowrap; }
|
||
.ceph-info-card-meta {
|
||
font-size: 0.75rem;
|
||
}
|
||
.ceph-info-card-arrow {
|
||
color: #adb5bd;
|
||
font-size: 0.75rem;
|
||
flex-shrink: 0;
|
||
}
|
||
.ceph-info-card:hover .ceph-info-card-arrow {
|
||
color: #667eea;
|
||
}
|
||
.ceph-info-card-storage .ceph-info-card-arrow { margin-left: auto; }
|
||
.ceph-info-card-empty {
|
||
padding: 1rem;
|
||
justify-content: center;
|
||
background: #f8f9fa;
|
||
border-style: dashed;
|
||
}
|
||
.ceph-info-card-clickable {
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* --- Страница экспорта данных --- */
|
||
/* Общие стили для страниц экспорта, импорта и очистки */
|
||
.page-export .export-hero,
|
||
.page-import .import-hero,
|
||
.page-clear .clear-hero {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: #fff;
|
||
border-radius: var(--border-radius);
|
||
padding: 1.5rem 1.75rem;
|
||
margin-bottom: 1.5rem;
|
||
box-shadow: var(--box-shadow-lg);
|
||
}
|
||
.page-export .export-hero .export-hero-title,
|
||
.page-import .import-hero .import-hero-title,
|
||
.page-clear .clear-hero .clear-hero-title {
|
||
font-size: 1.25rem;
|
||
font-weight: 600;
|
||
margin-bottom: 0.35rem;
|
||
}
|
||
.page-export .export-hero .export-hero-desc,
|
||
.page-import .import-hero .import-hero-desc,
|
||
.page-clear .clear-hero .clear-hero-desc {
|
||
font-size: 0.9rem;
|
||
opacity: 0.95;
|
||
}
|
||
.page-export .export-section-card,
|
||
.page-import .import-section-card,
|
||
.page-clear .clear-section-card {
|
||
background: #fff;
|
||
border-radius: var(--border-radius);
|
||
border: 1px solid rgba(0, 0, 0, 0.08);
|
||
box-shadow: var(--box-shadow);
|
||
overflow: hidden;
|
||
height: 100%;
|
||
}
|
||
.page-export .export-section-card .card-header-export,
|
||
.page-import .import-section-card .card-header-import,
|
||
.page-clear .clear-section-card .card-header-export {
|
||
font-weight: 600;
|
||
font-size: 0.95rem;
|
||
padding: 1rem 1.25rem;
|
||
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
}
|
||
.page-export .export-section-card .card-header-export.on-default,
|
||
.page-import .import-section-card .card-header-import.on-default,
|
||
.page-clear .clear-section-card .card-header-export.on-default {
|
||
background: linear-gradient(180deg, rgba(34, 197, 94, 0.08) 0%, transparent 100%);
|
||
color: #15803d;
|
||
}
|
||
.page-export .export-section-card .card-header-export.off-default,
|
||
.page-import .import-section-card .card-header-import.off-default,
|
||
.page-clear .clear-section-card .card-header-export.off-default {
|
||
background: linear-gradient(180deg, rgba(99, 102, 241, 0.08) 0%, transparent 100%);
|
||
color: #4338ca;
|
||
}
|
||
.page-export .export-section-card .card-body,
|
||
.page-import .import-section-card .card-body,
|
||
.page-clear .clear-section-card .card-body {
|
||
padding: 1.25rem 1.25rem;
|
||
}
|
||
.page-export .export-section-card .form-check,
|
||
.page-import .import-section-card .form-check,
|
||
.page-clear .clear-section-card .form-check {
|
||
padding-left: 2.5rem;
|
||
min-height: 1.75rem;
|
||
align-items: center;
|
||
}
|
||
.page-export .export-section-card .form-check-input,
|
||
.page-import .import-section-card .form-check-input,
|
||
.page-clear .clear-section-card .form-check-input {
|
||
width: 2.25rem;
|
||
height: 1.15rem;
|
||
margin-top: 0;
|
||
cursor: pointer;
|
||
}
|
||
.page-export .export-section-card .form-check-label,
|
||
.page-import .import-section-card .form-check-label,
|
||
.page-clear .clear-section-card .form-check-label {
|
||
cursor: pointer;
|
||
font-size: 0.9rem;
|
||
}
|
||
.page-export .export-section-card .export-sub-option,
|
||
.page-import .import-section-card .import-sub-option,
|
||
.page-clear .clear-section-card .export-sub-option {
|
||
margin-left: 2.75rem;
|
||
padding-left: 0.75rem;
|
||
border-left: 2px solid rgba(0, 0, 0, 0.12);
|
||
}
|
||
.page-export .export-actions,
|
||
.page-import .import-actions,
|
||
.page-clear .clear-actions {
|
||
margin-top: 1.75rem;
|
||
padding-top: 1.25rem;
|
||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 0.75rem;
|
||
align-items: center;
|
||
}
|
||
.page-export .export-actions .btn-download,
|
||
.page-import .import-actions .btn-upload {
|
||
padding: 0.6rem 1.25rem;
|
||
font-weight: 600;
|
||
box-shadow: var(--box-shadow);
|
||
}
|
||
.page-export .export-actions .btn-download:hover,
|
||
.page-import .import-actions .btn-upload:hover {
|
||
box-shadow: 0 0.35rem 0.6rem rgba(13, 110, 253, 0.35);
|
||
}
|
||
.page-clear .clear-actions .btn-clear {
|
||
padding: 0.6rem 1.25rem;
|
||
font-weight: 600;
|
||
box-shadow: var(--box-shadow);
|
||
}
|
||
.page-clear .clear-actions .btn-clear:hover {
|
||
box-shadow: 0 0.35rem 0.6rem rgba(220, 53, 69, 0.35);
|
||
}
|
||
.page-export .alert-danger,
|
||
.page-import .alert-danger,
|
||
.page-clear .alert-danger {
|
||
border-radius: var(--border-radius);
|
||
}
|
||
.page-export .export-section-card .form-check-switch-row,
|
||
.page-import .import-section-card .form-check-switch-row,
|
||
.page-clear .clear-section-card .form-check-switch-row {
|
||
margin-bottom: 0.85rem;
|
||
}
|
||
.page-export .export-section-card .form-check-switch-row:last-child,
|
||
.page-import .import-section-card .form-check-switch-row:last-child,
|
||
.page-clear .clear-section-card .form-check-switch-row:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
.page-import .import-section-card .form-label {
|
||
font-weight: 500;
|
||
color: #374151;
|
||
}
|
||
.page-import .import-section-card .form-text {
|
||
font-size: 0.85rem;
|
||
margin-top: 0.25rem;
|
||
}
|
||
.page-import .import-warning-card {
|
||
background: linear-gradient(180deg, rgba(245, 158, 11, 0.08) 0%, transparent 100%);
|
||
border: 1px solid rgba(245, 158, 11, 0.3);
|
||
border-radius: var(--border-radius);
|
||
padding: 1rem 1.25rem;
|
||
margin-bottom: 1.25rem;
|
||
}
|
||
.page-import .import-warning-card .alert-warning {
|
||
margin-bottom: 0;
|
||
border: none;
|
||
background: transparent;
|
||
padding: 0;
|
||
}
|
||
.page-import .import-stats-summary ul li {
|
||
padding-left: 0;
|
||
}
|
||
.page-import .import-stats-summary .alert-info {
|
||
border-radius: var(--border-radius);
|
||
}
|
||
.page-clear .clear-warning-card {
|
||
background: linear-gradient(180deg, rgba(220, 53, 69, 0.08) 0%, transparent 100%);
|
||
border: 1px solid rgba(220, 53, 69, 0.3);
|
||
border-radius: var(--border-radius);
|
||
padding: 1rem 1.25rem;
|
||
margin-bottom: 1.25rem;
|
||
}
|
||
.page-clear .clear-stats-summary ul li {
|
||
padding-left: 0;
|
||
}
|
||
|
||
/* Строка фильтра и поиска справочника оборудования — одна высота и вид */
|
||
.equipment-filter-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
}
|
||
.equipment-filter-row .equipment-filter-select {
|
||
width: 180px;
|
||
min-height: 31px;
|
||
flex-shrink: 0;
|
||
}
|
||
.equipment-filter-row .equipment-filter-search {
|
||
width: 280px;
|
||
}
|
||
.equipment-filter-row .equipment-filter-search .form-control,
|
||
.equipment-filter-row .equipment-filter-search .input-group-text {
|
||
min-height: 31px;
|
||
}
|
||
.equipment-filter-row .form-select-sm {
|
||
padding-top: 0.25rem;
|
||
padding-bottom: 0.25rem;
|
||
}
|
||
|
||
/* Цвет типа оборудования (swatch в списке типов) */
|
||
.equipment-type-color-swatch {
|
||
display: inline-block;
|
||
width: 1.25rem;
|
||
height: 1.25rem;
|
||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||
border-radius: 0.25rem;
|
||
vertical-align: middle;
|
||
margin-right: 0.35rem;
|
||
}
|
||
|
||
/* ——— ЦОДы в помещении: современный список (Автор: Сергей Антропов - https://devops.org.ru) ——— */
|
||
/* Одинаковая высота заголовков карточек «Стойки» и «ЦОДы в помещении» */
|
||
.dc-racks-card-header,
|
||
.dc-endpoints-in-room-card .dc-endpoints-card-header {
|
||
min-height: 3.5rem;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.dc-endpoints-in-room-card .card-header {
|
||
border-bottom: 1px solid #e9ecef;
|
||
}
|
||
|
||
.dc-endpoints-add-form {
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.dc-endpoints-add-form:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
/* Высота выпадающего списка и кнопки «Добавить ЦОД» как у селектора помещений (.endpoint-selector) */
|
||
.dc-endpoints-add-form .dc-endpoints-add-select,
|
||
.dc-endpoints-add-form .btn {
|
||
min-height: 2.5rem;
|
||
padding-top: 0.5rem;
|
||
padding-bottom: 0.5rem;
|
||
}
|
||
|
||
.dc-endpoints-add-form .dc-endpoints-add-select {
|
||
padding-left: 1rem;
|
||
padding-right: 1rem;
|
||
font-size: 0.95rem;
|
||
}
|
||
|
||
.dc-endpoints-add-select {
|
||
min-width: 10rem;
|
||
max-width: 14rem;
|
||
}
|
||
|
||
.dc-endpoints-in-room-body {
|
||
padding: 0.75rem 1rem;
|
||
}
|
||
|
||
.dc-endpoint-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
padding: 0.6rem 0.75rem;
|
||
margin-bottom: 0.5rem;
|
||
background: #f8fafc;
|
||
border: 1px solid #e2e8f0;
|
||
border-radius: 0.5rem;
|
||
transition: background 0.2s, border-color 0.2s, box-shadow 0.2s;
|
||
}
|
||
|
||
.dc-endpoint-item:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.dc-endpoint-item:hover {
|
||
background: #f1f5f9;
|
||
border-color: #cbd5e1;
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
|
||
}
|
||
|
||
.dc-endpoint-item-icon {
|
||
width: 2.25rem;
|
||
height: 2.25rem;
|
||
border-radius: 0.5rem;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 0.875rem;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.dc-endpoint-item-name {
|
||
flex: 1;
|
||
min-width: 0;
|
||
font-weight: 500;
|
||
color: #334155;
|
||
font-size: 0.9375rem;
|
||
}
|
||
|
||
.dc-endpoint-item-remove {
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.dc-endpoint-item-remove .btn-link {
|
||
opacity: 0.6;
|
||
transition: opacity 0.2s;
|
||
}
|
||
|
||
.dc-endpoint-item-remove .btn-link:hover {
|
||
opacity: 1;
|
||
}
|
||
|
||
.dc-endpoints-empty {
|
||
text-align: center;
|
||
padding: 1.5rem 1rem;
|
||
background: linear-gradient(180deg, #f8fafc 0%, #f1f5f9 100%);
|
||
border-radius: 0.5rem;
|
||
border: 1px dashed #cbd5e1;
|
||
}
|
||
|
||
.dc-endpoints-empty-icon {
|
||
width: 3rem;
|
||
height: 3rem;
|
||
margin: 0 auto 0.75rem;
|
||
border-radius: 50%;
|
||
background: #e2e8f0;
|
||
color: #64748b;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 1.25rem;
|
||
}
|
||
|
||
.dc-endpoints-empty-text {
|
||
font-size: 0.9375rem;
|
||
color: #475569;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.dc-endpoints-empty-hint {
|
||
font-size: 0.8125rem;
|
||
color: #94a3b8;
|
||
margin-top: 0.25rem;
|
||
}
|
||
|
||
/* Таблица размещения в стойке */
|
||
.rack-layout-card-header {
|
||
padding: 0;
|
||
margin-bottom: 0rem !important;
|
||
}
|
||
.rack-layout-table td.rack-cell-content {
|
||
vertical-align: middle;
|
||
min-height: 2rem;
|
||
}
|
||
/* Название строго по центру ячейки независимо от кнопок */
|
||
.rack-cell-inner {
|
||
position: relative;
|
||
min-height: 2rem;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
align-items: center;
|
||
}
|
||
.rack-placement-name-center {
|
||
position: absolute;
|
||
left: 0;
|
||
right: 0;
|
||
top: 0;
|
||
bottom: 0;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
.rack-placement-actions-pos {
|
||
position: relative;
|
||
z-index: 2;
|
||
}
|
||
.rack-placement-badge.rack-placement-server,
|
||
.rack-placement-badge.rack-placement-equipment,
|
||
.rack-placement-badge.rack-placement-label {
|
||
display: inline-block;
|
||
padding: 0.35rem 0.6rem;
|
||
background-color: #e9ecef;
|
||
color: #495057;
|
||
border-radius: 0.25rem;
|
||
font-weight: 500;
|
||
}
|
||
.rack-placement-server,
|
||
.rack-placement-equipment,
|
||
.rack-placement-label {
|
||
padding: 0.25rem 0;
|
||
}
|
||
.rack-placement-server a:hover {
|
||
text-decoration: underline;
|
||
}
|
||
.rack-placement-vms {
|
||
border-left: 2px solid #e2e8f0;
|
||
padding-left: 0.5rem;
|
||
}
|
||
.rack-placement-vms .badge {
|
||
font-size: 0.7rem;
|
||
}
|
||
|
||
/* Кнопки на размещении: не сливаются с цветным фоном ячейки */
|
||
.rack-placement-actions {
|
||
background: rgba(255, 255, 255, 0.95);
|
||
border: 1px solid rgba(0, 0, 0, 0.12);
|
||
border-radius: 0.35rem;
|
||
padding: 0.2rem 0.35rem;
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||
}
|
||
.rack-placement-actions .btn {
|
||
border-width: 1px;
|
||
}
|
||
.rack-placement-actions .btn:hover {
|
||
background: rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
/* Ручка перетаскивания размещения */
|
||
.rack-drag-handle {
|
||
cursor: grab;
|
||
}
|
||
.rack-drag-handle:active {
|
||
cursor: grabbing;
|
||
}
|
||
|
||
/* Подсветка ячейки при перетаскивании (валидная зона сброса) */
|
||
.rack-drop-cell.rack-drop-valid {
|
||
outline: 2px dashed var(--bs-primary, #0d6efd);
|
||
outline-offset: -2px;
|
||
background-color: rgba(13, 110, 253, 0.12) !important;
|
||
}
|
||
|
||
/* Карта стоек */
|
||
/* Форма настройки сетки: компактная высота (~на 30% ниже стандартной) */
|
||
.rack-map-size-form .form-control {
|
||
padding-top: 0.15rem;
|
||
padding-bottom: 0.15rem;
|
||
line-height: 1.25;
|
||
font-size: 0.8rem;
|
||
min-height: 1.5rem;
|
||
}
|
||
.rack-map-size-form .btn {
|
||
padding-top: 0.15rem;
|
||
padding-bottom: 0.15rem;
|
||
line-height: 1.25;
|
||
font-size: 0.8rem;
|
||
min-height: 1.5rem;
|
||
}
|
||
.rack-map-size-form label {
|
||
font-size: 0.8rem;
|
||
}
|
||
.rack-map-grid-wrapper {
|
||
overflow-x: auto;
|
||
}
|
||
.rack-map-table {
|
||
table-layout: fixed;
|
||
}
|
||
.rack-map-cell {
|
||
width: 2.5rem;
|
||
min-width: 2.5rem;
|
||
max-width: 8rem;
|
||
height: 2.5rem;
|
||
cursor: pointer;
|
||
font-size: 0.75rem;
|
||
}
|
||
.rack-map-cell:hover {
|
||
background-color: rgba(0, 0, 0, 0.05) !important;
|
||
}
|
||
.rack-map-cell-filled {
|
||
font-weight: 500;
|
||
}
|
||
.rack-map-cell-rack {
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
max-width: 100%;
|
||
display: inline-block;
|
||
}
|
||
.rack-map-cell-zone {
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
max-width: 100%;
|
||
display: inline-block;
|
||
}
|
||
.rack-map-zone-cold_corridor {
|
||
background-color: rgba(13, 202, 240, 0.2);
|
||
color: #0aa2c0;
|
||
}
|
||
.rack-map-zone-hot_corridor {
|
||
background-color: rgba(220, 53, 69, 0.2);
|
||
color: #b02a37;
|
||
}
|
||
.rack-map-zone-other {
|
||
background-color: rgba(108, 117, 125, 0.2);
|
||
color: #495057;
|
||
}
|
||
.rack-map-cell-selected {
|
||
outline: 2px solid var(--bs-primary);
|
||
outline-offset: -2px;
|
||
background-color: rgba(13, 110, 253, 0.2) !important;
|
||
}
|
||
|
||
/* ========== Обзор ЦОД: карта 60%, метрики 40%, по 2 карточки в ряд ========== */
|
||
.rack-overview-intro {
|
||
max-width: 36rem;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
}
|
||
.rack-overview-intro .rack-overview-intro-icon {
|
||
line-height: 1;
|
||
}
|
||
.rack-overview-layout {
|
||
align-items: stretch;
|
||
}
|
||
@media (min-width: 992px) {
|
||
.rack-overview-col-map {
|
||
flex: 0 0 70%;
|
||
max-width: 70%;
|
||
min-width: 0;
|
||
}
|
||
.rack-overview-col-metrics {
|
||
flex: 0 0 30%;
|
||
max-width: 30%;
|
||
min-width: 0;
|
||
}
|
||
}
|
||
.rack-overview-col-map {
|
||
min-width: 0;
|
||
}
|
||
/* Сетка миникарточек: 2 столбца, 4 строки одинаковой высоты, карточки растягиваются по ширине и высоте ячейки */
|
||
.rack-overview-metrics-sidebar {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
grid-template-rows: repeat(4, minmax(4.5rem, 1fr));
|
||
gap: 0.35rem;
|
||
}
|
||
/* Обёртки карточек: на всю ширину ячейки сетки (Bootstrap .col-6 даёт 50%, переопределяем только здесь) */
|
||
.rack-overview-metrics-sidebar > * {
|
||
width: 100% !important;
|
||
min-width: 0;
|
||
min-height: 0;
|
||
display: flex;
|
||
}
|
||
.rack-overview-metrics-sidebar .rack-overview-metric-mini {
|
||
flex: 1;
|
||
width: 100%;
|
||
min-height: 0;
|
||
padding: 0.5rem 0.65rem;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
gap: 0.6rem;
|
||
}
|
||
.rack-overview-metric-mini .stat-card-icon {
|
||
width: 34px;
|
||
height: 34px;
|
||
min-width: 34px;
|
||
min-height: 34px;
|
||
font-size: 1rem;
|
||
}
|
||
.rack-overview-metric-mini .stat-card-content {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
.rack-overview-metric-mini .stat-card-label {
|
||
font-size: 0.7rem;
|
||
margin-bottom: 0.15rem;
|
||
}
|
||
.rack-overview-metric-mini .stat-card-value {
|
||
font-size: 1rem;
|
||
font-weight: 700;
|
||
}
|
||
.rack-overview-metric-mini .stat-card-subvalue {
|
||
font-size: 0.7rem;
|
||
margin-top: 0.05rem;
|
||
}
|
||
|
||
.rack-overview-grid-wrapper {
|
||
overflow: auto;
|
||
min-height: 200px;
|
||
flex: 1 1 0;
|
||
min-width: 0;
|
||
width: 100%;
|
||
}
|
||
.rack-overview-table {
|
||
table-layout: fixed;
|
||
font-size: 0.8rem;
|
||
height: 100%;
|
||
width: 100%;
|
||
margin-bottom: 0 !important;
|
||
}
|
||
.rack-overview-table tbody {
|
||
height: 100%;
|
||
}
|
||
.rack-overview-table tr {
|
||
height: calc(100% / var(--map-rows, 10));
|
||
}
|
||
.rack-overview-table td {
|
||
padding: 0.25rem !important;
|
||
vertical-align: middle;
|
||
text-align: center;
|
||
width: calc(100% / var(--map-cols, 10));
|
||
transition: background-color 0.15s ease, box-shadow 0.15s ease;
|
||
}
|
||
.rack-overview-cell {
|
||
cursor: default;
|
||
min-height: 2rem;
|
||
}
|
||
/* Лёгкое выделение при наведении (без агрессивной синей обводки) */
|
||
.rack-overview-cell:hover {
|
||
background-color: rgba(0, 0, 0, 0.04) !important;
|
||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
|
||
}
|
||
/* Светлый фон ячейки: холодный и горячий коридор */
|
||
.rack-overview-cell.rack-overview-cell-zone-cold_corridor {
|
||
background-color: #e0f4fc;
|
||
}
|
||
.rack-overview-cell.rack-overview-cell-zone-hot_corridor {
|
||
background-color: #ffebee;
|
||
}
|
||
.rack-overview-cell.rack-overview-cell-zone-cold_corridor:hover {
|
||
background-color: #ccebf7 !important;
|
||
}
|
||
.rack-overview-cell.rack-overview-cell-zone-hot_corridor:hover {
|
||
background-color: #ffcdd2 !important;
|
||
}
|
||
/* Вся ячейка стойки кликабельна — открывает модалку */
|
||
.rack-overview-cell-clickable {
|
||
cursor: pointer;
|
||
}
|
||
.rack-overview-cell-clickable:hover {
|
||
background-color: rgba(13, 110, 253, 0.12) !important;
|
||
box-shadow: inset 0 0 0 1px rgba(13, 110, 253, 0.25);
|
||
}
|
||
.rack-overview-cell-filled .rack-overview-cell-rack {
|
||
padding: 0.15rem 0.35rem;
|
||
border-radius: 0.35rem;
|
||
transition: background 0.2s;
|
||
}
|
||
.rack-overview-cell-clickable .rack-overview-cell-rack:hover {
|
||
background: rgba(13, 110, 253, 0.15);
|
||
}
|
||
.rack-overview-cell-rack i {
|
||
margin-right: 0.2rem;
|
||
}
|
||
.rack-overview-cell-zone {
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
font-size: 0.7rem;
|
||
padding: 0.1rem 0.25rem;
|
||
border-radius: 0.25rem;
|
||
}
|
||
.rack-overview-zone-cold_corridor {
|
||
color: #0d7ea4;
|
||
}
|
||
.rack-overview-zone-hot_corridor {
|
||
color: #b02a37;
|
||
}
|
||
|
||
/* Модалка содержимого стойки — крупнее, с переворотом спереди/сзади */
|
||
.rack-overview-modal .modal-dialog {
|
||
max-width: 640px;
|
||
}
|
||
.rack-overview-modal-content {
|
||
border: 2px solid #e5e7eb;
|
||
border-radius: 0.75rem;
|
||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||
}
|
||
.rack-overview-modal-body {
|
||
max-height: 75vh;
|
||
overflow-y: auto;
|
||
}
|
||
.rack-overview-modal-placeholder {
|
||
padding: 2rem !important;
|
||
}
|
||
|
||
/* 3D-переворот стойки: спереди ↔ сзади */
|
||
.rack-overview-flip-wrapper {
|
||
perspective: 1200px;
|
||
min-height: 200px;
|
||
}
|
||
.rack-overview-flip-inner {
|
||
position: relative;
|
||
width: 100%;
|
||
min-height: 180px;
|
||
transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
|
||
transform-style: preserve-3d;
|
||
}
|
||
.rack-overview-flip-wrapper.rack-overview-flip-flipped .rack-overview-flip-inner {
|
||
transform: rotateY(180deg);
|
||
}
|
||
.rack-overview-face {
|
||
backface-visibility: hidden;
|
||
-webkit-backface-visibility: hidden;
|
||
padding: 1rem 2.25rem;
|
||
padding-bottom: 1.5rem;
|
||
}
|
||
.rack-overview-face-front {
|
||
position: relative;
|
||
transform: rotateY(0deg);
|
||
}
|
||
.rack-overview-face-back {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
transform: rotateY(180deg);
|
||
}
|
||
/* Кнопки разворота в шапке модалки справа */
|
||
.rack-overview-modal-header-actions {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.25rem;
|
||
margin-left: auto;
|
||
margin-right: 0.25rem;
|
||
}
|
||
.rack-overview-face-header {
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
.rack-overview-face-header .rack-overview-rack-title {
|
||
margin-bottom: 0.75rem;
|
||
}
|
||
.rack-overview-flip-btn {
|
||
flex-shrink: 0;
|
||
}
|
||
.rack-overview-face-label {
|
||
font-size: 0.75rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
/* Крупный бадж «Спереди» / «Сзади» по центру */
|
||
.rack-overview-side-badge {
|
||
display: inline-block;
|
||
padding: 0.45rem 1.1rem;
|
||
font-size: 1rem;
|
||
font-weight: 700;
|
||
letter-spacing: 0.04em;
|
||
border-radius: 2rem;
|
||
text-transform: uppercase;
|
||
}
|
||
.rack-overview-side-badge.rack-overview-flip-trigger {
|
||
cursor: pointer;
|
||
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
||
}
|
||
.rack-overview-side-badge.rack-overview-flip-trigger:hover {
|
||
transform: scale(1.05);
|
||
box-shadow: 0 4px 14px rgba(224, 168, 0, 0.5);
|
||
}
|
||
.rack-overview-side-badge-front,
|
||
.rack-overview-side-badge-back {
|
||
background: linear-gradient(135deg, #ffc107 0%, #e0a800 100%);
|
||
color: #1f2937;
|
||
box-shadow: 0 2px 10px rgba(224, 168, 0, 0.4);
|
||
}
|
||
|
||
/* Компактные цветные полоски U в модалке */
|
||
.rack-overview-rack-contents {
|
||
padding: 0;
|
||
}
|
||
.rack-overview-rack-title-main {
|
||
font-size: 1.2rem;
|
||
font-weight: 700;
|
||
color: #1f2937;
|
||
letter-spacing: -0.02em;
|
||
}
|
||
.rack-overview-rack-subtitle {
|
||
font-size: 0.9rem;
|
||
font-weight: 500;
|
||
color: #6b7280;
|
||
}
|
||
.rack-overview-rack-title h6 {
|
||
font-weight: 600;
|
||
color: #1f2937;
|
||
}
|
||
|
||
/* Схематичная стойка: рамка (контур), левая/правая «рейки» с юнитами, середина — слоты */
|
||
.rack-overview-rack-frame {
|
||
margin-top: 0.75rem;
|
||
border: 3px solid #4b5563;
|
||
border-radius: 8px;
|
||
background: #374151;
|
||
box-shadow: inset 0 0 0 1px #1f2937, 0 4px 12px rgba(0, 0, 0, 0.2);
|
||
overflow: hidden;
|
||
}
|
||
.rack-overview-rack-frame .rack-overview-u-grid {
|
||
background: #1f2937;
|
||
margin-top: 0;
|
||
border-radius: 0;
|
||
}
|
||
|
||
/* Сетка: слева юниты | полоски размещений | справа юниты */
|
||
.rack-overview-u-grid {
|
||
display: grid;
|
||
grid-template-columns: auto 1fr auto;
|
||
grid-template-rows: repeat(var(--rack-units, 42), 22px);
|
||
gap: 1px 0;
|
||
align-items: stretch;
|
||
}
|
||
/* Левая и правая колонки — «рейки» стойки с номерами U */
|
||
.rack-overview-u-label {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 0.65rem;
|
||
font-weight: 700;
|
||
color: #9ca3af;
|
||
min-width: 2rem;
|
||
background: #374151;
|
||
border-right: 1px solid #1f2937;
|
||
}
|
||
.rack-overview-u-label-left {
|
||
padding-left: 0.35rem;
|
||
padding-right: 0.25rem;
|
||
border-right: 2px solid #4b5563;
|
||
}
|
||
.rack-overview-u-label-right {
|
||
border-right: none;
|
||
border-left: 2px solid #4b5563;
|
||
padding-left: 0.25rem;
|
||
padding-right: 0.35rem;
|
||
}
|
||
.rack-overview-u-strip-wrapper {
|
||
grid-column: 2;
|
||
min-height: 0;
|
||
height: 100%;
|
||
background: #1f2937;
|
||
}
|
||
.rack-overview-u-strip {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
height: 100%;
|
||
padding: 0 0.6rem;
|
||
border-radius: 0.4rem;
|
||
font-size: 0.85rem;
|
||
font-weight: 500;
|
||
text-decoration: none;
|
||
color: #fff;
|
||
transition: filter 0.2s, box-shadow 0.2s;
|
||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||
}
|
||
.rack-overview-u-strip:hover {
|
||
filter: brightness(1.1);
|
||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
|
||
}
|
||
.rack-overview-u-strip-no-link {
|
||
cursor: default;
|
||
pointer-events: none;
|
||
}
|
||
.rack-overview-u-strip-u {
|
||
flex-shrink: 0;
|
||
font-size: 0.75rem;
|
||
opacity: 0.95;
|
||
}
|
||
.rack-overview-u-strip-label {
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* Спиннер обновления метрик в реальном времени (карточки ВМ): HTMX добавляет .htmx-request к индикатору */
|
||
.realtime-metrics-spinner {
|
||
display: none;
|
||
z-index: 5;
|
||
}
|
||
.realtime-metrics-spinner.htmx-request {
|
||
display: inline-block;
|
||
}
|
||
|
||
/* Спиннер обновления realtime-метрик на дашборде (раз в 3 мин) */
|
||
.dashboard-realtime-spinner {
|
||
display: none;
|
||
z-index: 5;
|
||
}
|
||
.dashboard-realtime-spinner.htmx-request {
|
||
display: inline-block;
|
||
}
|
||
/* Логи для DevOpsLab */
|
||
.log-container {
|
||
background: #1f2937;
|
||
color: #10b981;
|
||
padding: 1rem;
|
||
border-radius: 0.5rem;
|
||
font-family: 'Courier New', monospace;
|
||
font-size: 0.875rem;
|
||
max-height: 500px;
|
||
overflow-y: auto;
|
||
}
|
||
.log-line {
|
||
margin-bottom: 0.25rem;
|
||
line-height: 1.5;
|
||
}
|
||
.log-error {
|
||
color: #ef4444;
|
||
}
|
||
.log-warning {
|
||
color: #f59e0b;
|
||
}
|
||
.log-info {
|
||
color: #3b82f6;
|
||
}
|
||
|
||
/* Profile page styles */
|
||
/* Автор: Сергей Антропов - https://devops.org.ru */
|
||
.avatar-circle {
|
||
width: 100px;
|
||
height: 100px;
|
||
border-radius: 50%;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: white;
|
||
font-size: 2.5rem;
|
||
font-weight: bold;
|
||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
/* Tab navigation styles */
|
||
.nav-tabs .nav-link {
|
||
color: #667eea;
|
||
border: none;
|
||
border-bottom: 2px solid transparent;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.nav-tabs .nav-link:hover {
|
||
border-bottom-color: #667eea;
|
||
color: #764ba2;
|
||
background: rgba(102, 126, 234, 0.05);
|
||
}
|
||
|
||
.nav-tabs .nav-link.active {
|
||
color: #667eea;
|
||
border-bottom-color: #667eea;
|
||
background: transparent;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.card-header-tabs {
|
||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.card-header-tabs .nav-link {
|
||
color: rgba(255, 255, 255, 0.8);
|
||
border-bottom-color: transparent;
|
||
}
|
||
|
||
.card-header-tabs .nav-link:hover {
|
||
color: #fff;
|
||
border-bottom-color: rgba(255, 255, 255, 0.5);
|
||
background: rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
.card-header-tabs .nav-link.active {
|
||
color: #fff;
|
||
border-bottom-color: #fff;
|
||
background: rgba(255, 255, 255, 0.15);
|
||
}
|