diff --git a/internal/api/static/style.css b/internal/api/static/style.css deleted file mode 100644 index 104c68a..0000000 --- a/internal/api/static/style.css +++ /dev/null @@ -1,1306 +0,0 @@ -/* - * Copyright 2026 Safronov Grigorii - * - * Licensed under the CDDL, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * https://opensource.org/licenses/CDDL-1.0 - */ - - /* Файл: internal/api/static/style.css */ -/* Стили для веб-интерфейса Futriis DB Dashboard */ - -:root { - --primary-color: #00bfff; - --primary-dark: #0099cc; - --secondary-color: #6c757d; - --success-color: #28a745; - --danger-color: #dc3545; - --warning-color: #ffc107; - --info-color: #17a2b8; - - --bg-dark: #1a1a2e; - --bg-sidebar: #005385; - --bg-card: #0f3460; - --bg-hover: #1a1f3a; - --text-primary: #ffffff; - --text-secondary: #b8c6db; - --border-color: #2d3a5e; - - --shadow-sm: 0 2px 4px rgba(0,0,0,0.1); - --shadow-md: 0 4px 8px rgba(0,0,0,0.15); - --shadow-lg: 0 8px 16px rgba(0,0,0,0.2); - - --transition: all 0.3s ease; -} - -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; - background: var(--bg-dark); - color: var(--text-primary); - overflow: hidden; -} - -/* Dashboard Container */ -.dashboard-container { - display: flex; - height: 100vh; - width: 100%; -} - -/* Sidebar - Вертикальное меню */ -.sidebar { - width: 280px; - background: var(--bg-sidebar); - display: flex; - flex-direction: column; - transition: var(--transition); - box-shadow: var(--shadow-lg); - z-index: 100; - overflow-y: auto; - overflow-x: hidden; -} - -.sidebar-header { - padding: 24px 20px; - border-bottom: 1px solid var(--border-color); - display: flex; - align-items: center; - justify-content: space-between; -} - -.logo { - display: flex; - align-items: center; - gap: 12px; - font-size: 1.5rem; - font-weight: 700; -} - -.logo img { - width: 225px; - height: 107px; - object-fit: contain; -} - -.logo span { - background: linear-gradient(135deg, var(--primary-color), #00ffcc); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; -} - -.menu-toggle { - display: none; - background: none; - border: none; - color: var(--text-primary); - font-size: 1.2rem; - cursor: pointer; - padding: 8px; -} - -/* Navigation Menu */ -.nav-menu { - flex: 1; - list-style: none; - padding: 20px 0; -} - -.nav-item { - margin-bottom: 4px; -} - -.nav-link { - display: flex; - align-items: center; - gap: 12px; - padding: 12px 20px; - color: var(--text-secondary); - text-decoration: none; - transition: var(--transition); - border-radius: 8px; - margin: 0 8px; -} - -.nav-link:hover { - background: var(--bg-hover); - color: var(--text-primary); -} - -.nav-link.active { - background: var(--primary-color); - color: white; -} - -.nav-link i { - width: 24px; - font-size: 1.1rem; -} - -.nav-link span { - flex: 1; -} - -/* Submenu */ -.has-submenu > .nav-link { - position: relative; -} - -.has-submenu > .nav-link .fa-chevron-down { - margin-left: auto; - transition: var(--transition); -} - -.has-submenu.open > .nav-link .fa-chevron-down { - transform: rotate(180deg); -} - -.submenu { - list-style: none; - padding-left: 56px; - max-height: 0; - overflow: hidden; - transition: max-height 0.3s ease; -} - -.has-submenu.open .submenu { - max-height: 500px; -} - -.submenu li a { - display: flex; - align-items: center; - gap: 12px; - padding: 10px 16px; - color: var(--text-secondary); - text-decoration: none; - font-size: 0.9rem; - transition: var(--transition); - border-radius: 6px; - margin: 2px 8px; -} - -.submenu li a:hover { - background: var(--bg-hover); - color: var(--text-primary); -} - -.submenu li a i { - width: 20px; - font-size: 0.9rem; -} - -/* Sidebar Footer */ -.sidebar-footer { - padding: 20px; - border-top: 1px solid var(--border-color); -} - -.user-info { - display: flex; - align-items: center; - gap: 12px; - padding: 12px; - background: var(--bg-dark); - border-radius: 8px; - margin-bottom: 12px; -} - -.user-info i { - font-size: 1.2rem; - color: var(--primary-color); -} - -.logout-btn { - width: 100%; - display: flex; - align-items: center; - gap: 12px; - padding: 10px 16px; - background: var(--danger-color); - border: none; - color: white; - border-radius: 8px; - cursor: pointer; - font-size: 1rem; - transition: var(--transition); -} - -.logout-btn:hover { - background: #c82333; - transform: translateY(-1px); -} - -/* Main Content */ -.main-content { - flex: 1; - display: flex; - flex-direction: column; - overflow: hidden; -} - -.top-bar { - background: #1a1a2e; - padding: 16px 24px; - display: flex; - justify-content: space-between; - align-items: center; - border-bottom: 1px solid var(--border-color); -} - -.top-bar h1 { - font-size: 1.5rem; - font-weight: 600; -} - -.connection-status { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 16px; - background: var(--bg-dark); - border-radius: 24px; - font-size: 0.9rem; - font-weight: 500; -} - -.connection-status i { - font-size: 0.8rem; - display: none; -} - -.connection-status.online { - color: #00ff88; - background: rgba(0, 255, 136, 0.15); - text-shadow: 0 0 8px rgba(0, 255, 136, 0.5); -} - -.connection-status.offline { - color: var(--danger-color); - background: rgba(220, 53, 69, 0.1); -} - -.connection-status.online i { - display: none; -} - -.connection-status.offline i { - display: none; -} - -.connection-status::before { - content: "●"; - margin-right: 8px; - font-size: 12px; - animation: pulse 2s infinite; -} - -@keyframes pulse { - 0% { - opacity: 0.6; - text-shadow: 0 0 2px currentColor; - } - 50% { - opacity: 1; - text-shadow: 0 0 10px currentColor; - } - 100% { - opacity: 0.6; - text-shadow: 0 0 2px currentColor; - } -} - -.connection-status.online::before { - color: #00ff88; -} - -.connection-status.offline::before { - color: var(--danger-color); - animation: none; -} - -.content-area { - flex: 1; - overflow-y: auto; - padding: 24px; -} - -/* Dashboard Cards */ -.dashboard-stats { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); - gap: 20px; - margin-bottom: 30px; -} - -.stat-card { - background: var(--bg-card); - border-radius: 12px; - padding: 20px; - display: flex; - align-items: center; - gap: 16px; - transition: var(--transition); -} - -.stat-card:hover { - transform: translateY(-2px); - box-shadow: var(--shadow-md); -} - -.stat-icon { - width: 60px; - height: 60px; - background: rgba(0, 191, 255, 0.1); - border-radius: 12px; - display: flex; - align-items: center; - justify-content: center; -} - -.stat-icon i { - font-size: 2rem; - color: var(--primary-color); -} - -.stat-info h3 { - font-size: 1.8rem; - font-weight: 700; -} - -.stat-info p { - color: var(--text-secondary); - font-size: 0.85rem; -} - -/* Tables */ -.data-table { - width: 100%; - background: var(--bg-card); - border-radius: 12px; - overflow-x: auto; -} - -.data-table table { - width: 100%; - border-collapse: collapse; -} - -.data-table th, -.data-table td { - padding: 12px 16px; - text-align: left; - border-bottom: 1px solid var(--border-color); -} - -.data-table th { - background: var(--bg-sidebar); - font-weight: 600; - color: var(--primary-color); -} - -.data-table tr:hover { - background: var(--bg-hover); -} - -/* Forms */ -.form-group { - margin-bottom: 20px; -} - -.form-group label { - display: block; - margin-bottom: 8px; - font-weight: 500; -} - -.form-control { - width: 100%; - padding: 10px 12px; - background: #1a1a2e; - border: 1px solid var(--border-color); - border-radius: 8px; - color: var(--text-primary); - font-size: 0.95rem; - transition: var(--transition); -} - -.form-control:focus { - outline: none; - border-color: var(--primary-color); - box-shadow: 0 0 0 2px rgba(0, 191, 255, 0.2); - background: #1a1a2e; -} - -/* Подсветка полей ввода при наведении мыши - только рамка */ -.form-control:hover { - border-color: var(--primary-color); - background: #1a1a2e; -} - -textarea.form-control { - min-height: 120px; - font-family: monospace; - resize: vertical; -} - -/* Buttons - общие стили для всех кнопок */ -.btn { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 8px; - padding: 10px 20px; - border: none; - border-radius: 8px; - cursor: pointer; - font-size: 0.95rem; - font-weight: 500; - transition: var(--transition); - text-decoration: none; - width: auto; - min-width: 80px; -} - -/* Стили для кнопки "Войти" (primary) */ -.btn-primary { - background: #1a1a2e; - color: white; -} - -.btn-primary:hover { - background: #2a2a4e; - transform: translateY(-1px); -} - -/* Стили для кнопки "Отмена" (secondary) - полностью идентичны кнопке "Войти" */ -.btn-secondary { - background: #1a1a2e; - color: white; -} - -.btn-secondary:hover { - background: #2a2a4e; - transform: translateY(-1px); -} - -.btn-danger { - background: var(--danger-color); - color: white; -} - -.btn-danger:hover { - background: #c82333; -} - -.btn-sm { - padding: 6px 12px; - font-size: 0.85rem; -} - -/* Modal */ -.modal { - display: none; - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.7); - z-index: 1000; - align-items: center; - justify-content: center; -} - -.modal.show { - display: flex; -} - -.modal-content { - background: #005385; - border-radius: 16px; - width: 90%; - max-width: 500px; - max-height: 80vh; - display: flex; - flex-direction: column; - animation: modalSlideIn 0.3s ease; - position: relative; -} - -@keyframes modalSlideIn { - from { - transform: translateY(-50px); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} - -.modal-header { - padding: 20px 24px; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); - display: flex; - justify-content: space-between; - align-items: center; -} - -.modal-header h2 { - font-size: 1.5rem; - font-weight: 600; - color: var(--text-primary); - margin: 0; -} - -.modal-close { - background: none; - border: none; - font-size: 1.5rem; - cursor: pointer; - color: var(--text-secondary); - padding: 0; - /* width: 32px; */ - /* height: 32px; */ - display: flex; - align-items: center; - justify-content: center; - border-radius: 8px; - transition: var(--transition); -} - -.modal-close:hover { - background: rgba(255, 255, 255, 0.1); - color: var(--text-primary); -} - -.modal-body { - padding: 24px; - overflow-y: auto; - flex: 1; -} - -.modal-footer { - padding: 16px 24px; - border-top: 1px solid rgba(255, 255, 255, 0.1); - display: flex; - justify-content: flex-end; - gap: 12px; - flex-direction: row-reverse; -} - -/* Стили для кнопок в модальном окне - обе кнопки имеют одинаковый фон на всю площадь */ -.modal-footer .btn { - font-size: 0.9rem; - padding: 10px 24px; - border-radius: 8px; - width: auto; - min-width: 100px; -} - -/* Кнопка "Войти" в модальном окне */ -.modal-footer .btn-primary { - background: #1a1a2e; - color: white; - border: none; -} - -.modal-footer .btn-primary:hover { - background: #2a2a4e; - transform: translateY(-1px); -} - -/* Кнопка "Отмена" в модальном окне - полностью идентична кнопке "Войти" */ -.modal-footer .btn-secondary { - background: #1a1a2e; - color: white; - border: none; -} - -.modal-footer .btn-secondary:hover { - background: #2a2a4e; - transform: translateY(-1px); -} - -/* Notifications */ -.notification-container { - position: fixed; - top: 20px; - right: 20px; - z-index: 1100; -} - -.notification { - background: var(--bg-card); - border-radius: 8px; - padding: 12px 20px; - margin-bottom: 10px; - display: flex; - align-items: center; - gap: 12px; - box-shadow: var(--shadow-lg); - animation: slideInRight 0.3s ease; -} - -@keyframes slideInRight { - from { - transform: translateX(100%); - opacity: 0; - } - to { - transform: translateX(0); - opacity: 1; - } -} - -.notification.success { - border-left: 4px solid var(--success-color); -} - -.notification.error { - border-left: 4px solid var(--danger-color); -} - -.notification.warning { - border-left: 4px solid var(--warning-color); -} - -.notification.info { - border-left: 4px solid var(--info-color); -} - -/* Loading Spinner */ -.loading-spinner { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - min-height: 200px; -} - -.loading-spinner i { - font-size: 3rem; - color: var(--primary-color); -} - -.loading-spinner p { - margin-top: 16px; - color: var(--text-secondary); -} - -/* Tabs */ -.tabs { - display: flex; - gap: 8px; - margin-bottom: 20px; - border-bottom: 1px solid var(--border-color); - padding-bottom: 8px; -} - -.tab-btn { - padding: 8px 16px; - background: none; - border: none; - color: var(--text-secondary); - cursor: pointer; - border-radius: 6px; - transition: var(--transition); -} - -.tab-btn.active { - background: var(--primary-color); - color: white; -} - -.tab-content { - display: none; -} - -.tab-content.active { - display: block; -} - -/* Responsive Design */ -@media (max-width: 768px) { - .sidebar { - position: fixed; - left: -280px; - height: 100%; - transition: left 0.3s ease; - } - - .sidebar.open { - left: 0; - } - - .menu-toggle { - display: block; - } - - .main-content { - margin-left: 0; - } - - .dashboard-stats { - grid-template-columns: 1fr; - } - - .data-table { - font-size: 0.85rem; - } - - .data-table th, - .data-table td { - padding: 8px 12px; - } - - .modal-content { - width: 95%; - margin: 20px; - } - - .logo img { - width: 180px; - height: 86px; - } -} - -@media (max-width: 480px) { - .top-bar h1 { - font-size: 1.2rem; - } - - .stat-card { - padding: 16px; - } - - .stat-icon { - width: 50px; - height: 50px; - } - - .stat-info h3 { - font-size: 1.4rem; - } - - .logo img { - width: 150px; - height: 71px; - } - - .connection-status { - padding: 4px 10px; - font-size: 0.75rem; - } - - .connection-status::before { - font-size: 8px; - margin-right: 4px; - } -} - -/* Scrollbar Styling */ -::-webkit-scrollbar { - width: 8px; - height: 8px; -} - -::-webkit-scrollbar-track { - background: var(--bg-dark); -} - -::-webkit-scrollbar-thumb { - background: var(--border-color); - border-radius: 4px; -} - -::-webkit-scrollbar-thumb:hover { - background: var(--primary-color); -} - -/* ==================== Дополнительные стили для новых компонентов ==================== */ - -/* Badges and status indicators */ -.badge { - display: inline-block; - padding: 4px 8px; - background: var(--primary-color); - color: white; - border-radius: 4px; - font-size: 0.75rem; - margin: 2px; -} - -.status-badge { - display: inline-block; - padding: 4px 12px; - border-radius: 20px; - font-size: 0.75rem; - font-weight: 500; -} - -.status-badge.status-active { - background: rgba(40, 167, 69, 0.2); - color: #28a745; - border: 1px solid rgba(40, 167, 69, 0.3); -} - -.status-badge.status-inactive { - background: rgba(220, 53, 69, 0.2); - color: #dc3545; - border: 1px solid rgba(220, 53, 69, 0.3); -} - -/* Success and error messages */ -.success-message { - background: rgba(40, 167, 69, 0.1); - border: 1px solid rgba(40, 167, 69, 0.3); - border-radius: 8px; - padding: 16px; - text-align: center; -} - -.success-message i { - font-size: 2rem; - color: #28a745; - margin-bottom: 8px; -} - -.error-message { - background: rgba(220, 53, 69, 0.1); - border: 1px solid rgba(220, 53, 69, 0.3); - border-radius: 8px; - padding: 16px; - text-align: center; - color: #dc3545; -} - -/* Code styling */ -code { - font-family: 'Courier New', monospace; - background: var(--bg-dark); - padding: 2px 6px; - border-radius: 4px; - font-size: 0.85rem; -} - -/* Select dropdown styling */ -select.form-control { - cursor: pointer; - appearance: none; - background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3e%3cpath d='M7 10l5 5 5-5z'/%3e%3c/svg%3e"); - background-repeat: no-repeat; - background-position: right 12px center; - background-size: 16px; -} - -/* Better table styling */ -.data-table table { - font-size: 0.85rem; -} - -.data-table td code { - word-break: break-all; - max-width: 300px; - display: inline-block; -} - -/* Button variants */ -.btn-warning { - background: #ffc107; - color: #1a1a2e; -} - -.btn-warning:hover { - background: #e0a800; - transform: translateY(-1px); -} - -.btn-success { - background: #28a745; - color: white; -} - -.btn-success:hover { - background: #218838; - transform: translateY(-1px); -} - -/* Animation for notifications */ -@keyframes slideOutRight { - from { - transform: translateX(0); - opacity: 1; - } - to { - transform: translateX(100%); - opacity: 0; - } -} - -/* Responsive adjustments for new components */ -@media (max-width: 768px) { - .data-table td code { - max-width: 150px; - font-size: 0.7rem; - } - - .badge { - font-size: 0.65rem; - padding: 2px 6px; - } - - .btn-sm { - padding: 4px 8px; - font-size: 0.75rem; - } -} - -/* Submenu open state */ -.has-submenu.open .submenu { - max-height: 500px; -} - -/* Transaction status indicators */ -.transaction-status { - display: inline-block; - width: 10px; - height: 10px; - border-radius: 50%; - margin-right: 8px; -} - -.transaction-status.active { - background: #28a745; - box-shadow: 0 0 5px #28a745; -} - -.transaction-status.pending { - background: #ffc107; - box-shadow: 0 0 5px #ffc107; -} - -/* File input styling */ -input[type="file"].form-control { - padding: 8px; - cursor: pointer; -} - -input[type="file"].form-control::file-selector-button { - background: var(--primary-color); - color: white; - border: none; - padding: 6px 12px; - border-radius: 4px; - cursor: pointer; - margin-right: 12px; -} - -input[type="file"].form-control::file-selector-button:hover { - background: var(--primary-dark); -} - -/* ==================== Стили для триггеров ==================== */ - -/* Trigger status badges */ -.status-badge.status-enabled { - background: rgba(40, 167, 69, 0.2); - color: #28a745; - border: 1px solid rgba(40, 167, 69, 0.3); -} - -.status-badge.status-disabled { - background: rgba(108, 117, 125, 0.2); - color: #6c757d; - border: 1px solid rgba(108, 117, 125, 0.3); -} - -/* Trigger event badges */ -.event-badge { - display: inline-block; - padding: 2px 8px; - border-radius: 4px; - font-size: 0.7rem; - font-weight: 500; -} - -.event-before { - background: rgba(255, 193, 7, 0.2); - color: #ffc107; -} - -.event-after { - background: rgba(23, 162, 184, 0.2); - color: #17a2b8; -} - -/* Trigger actions styling */ -.trigger-action { - font-family: monospace; - font-size: 0.8rem; -} - -/* ==================== Стили для ограничений (Constraints) ==================== */ - -/* Constraint sections */ -.constraint-section { - background: var(--bg-card); - border-radius: 12px; - padding: 20px; - margin-bottom: 24px; -} - -.constraint-section h4 { - margin-bottom: 16px; - display: flex; - align-items: center; - gap: 8px; - color: var(--primary-color); -} - -.constraint-section h4 i { - font-size: 1.1rem; -} - -.constraint-section .data-table { - background: transparent; -} - -.constraint-section .data-table th { - background: rgba(0, 0, 0, 0.2); -} - -/* Constraint badges */ -.constraint-badge { - display: inline-block; - padding: 2px 8px; - border-radius: 4px; - font-size: 0.7rem; - font-weight: 500; - margin-right: 6px; -} - -.constraint-badge-required { - background: rgba(255, 193, 7, 0.2); - color: #ffc107; -} - -.constraint-badge-unique { - background: rgba(40, 167, 69, 0.2); - color: #28a745; -} - -.constraint-badge-min { - background: rgba(23, 162, 184, 0.2); - color: #17a2b8; -} - -.constraint-badge-max { - background: rgba(23, 162, 184, 0.2); - color: #17a2b8; -} - -.constraint-badge-enum { - background: rgba(111, 66, 193, 0.2); - color: #6f42c1; -} - -.constraint-badge-regex { - background: rgba(220, 53, 69, 0.2); - color: #dc3545; -} - -/* Constraint value display */ -.constraint-value { - font-family: monospace; - background: var(--bg-dark); - padding: 2px 6px; - border-radius: 4px; - font-size: 0.8rem; -} - -.enum-values { - display: flex; - flex-wrap: wrap; - gap: 4px; -} - -.enum-values .badge { - background: var(--primary-color); - color: white; - font-size: 0.7rem; - padding: 2px 8px; -} - -/* Constraint form styles */ -.constraint-form-row { - display: flex; - gap: 12px; - align-items: flex-end; - margin-bottom: 16px; -} - -.constraint-form-row .form-group { - flex: 1; - margin-bottom: 0; -} - -.constraint-help-text { - font-size: 0.75rem; - color: var(--text-secondary); - margin-top: 4px; -} - -/* Responsive for constraints */ -@media (max-width: 768px) { - .constraint-section { - padding: 12px; - } - - .constraint-section h4 { - font-size: 1rem; - } - - .constraint-form-row { - flex-direction: column; - gap: 12px; - } - - .constraint-form-row .form-group { - width: 100%; - } - - .enum-values .badge { - font-size: 0.65rem; - } -} - -/* ==================== Дополнительные стили для аватара и смены пароля ==================== */ - -/* User info with avatar */ -.user-info { - display: flex; - align-items: center; - gap: 12px; - padding: 12px; - background: var(--bg-dark); - border-radius: 8px; - margin-bottom: 12px; - position: relative; -} - -.user-info .user-avatar { - cursor: pointer; - transition: var(--transition); - flex-shrink: 0; -} - -.user-info .user-avatar:hover { - transform: scale(1.05); - opacity: 0.9; -} - -.user-info .user-avatar img { - width: 40px; - height: 40px; - border-radius: 50%; - object-fit: cover; -} - -.user-info .user-details { - flex: 1; - display: flex; - flex-direction: column; - overflow: hidden; -} - -.user-info .user-details #userName { - font-weight: 600; - font-size: 0.9rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.user-info .user-details .user-role { - font-size: 0.7rem; - color: var(--text-secondary); -} - -.user-info .change-password-icon { - background: none; - border: none; - color: var(--text-secondary); - cursor: pointer; - padding: 6px; - border-radius: 4px; - transition: var(--transition); - flex-shrink: 0; -} - -.user-info .change-password-icon:hover { - background: rgba(255, 255, 255, 0.1); - color: var(--primary-color); -} - -.user-info .change-password-icon i { - font-size: 0.9rem; -} - -/* Avatar preview */ -.avatar-preview img { - max-width: 150px; - max-height: 150px; - border-radius: 50%; - object-fit: cover; - border: 2px solid var(--primary-color); -} - -/* Modal styles for avatar upload and change password */ -.modal-content { - max-width: 450px; -} - -/* Responsive adjustments */ -@media (max-width: 768px) { - .user-info { - padding: 8px; - } - - .user-info .user-avatar img { - width: 32px; - height: 32px; - } - - .user-info .user-details #userName { - font-size: 0.8rem; - } - - .user-info .change-password-icon { - padding: 4px; - } -} - -@media (max-width: 480px) { - .user-info { - gap: 8px; - } - - .user-info .user-avatar img { - width: 28px; - height: 28px; - } - - .user-details { - display: none !important; - } -}