/
h0tnanny
/
IotPlatform
Обзор
Документация
Войти
/
h0tnanny
/
IotPlatform
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
develop
client/src/components/Admin/LogViewer.module.scss
354 строки
7 KB
h0tnanny
Добавление функциональных требований
08 фев 2026, 23:02
08 фев 2026, 23:02
a8a23c5
Код
Авторство
О чём код?
@keyframes slideUp { from { transform: translateY(10px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } .page { animation: slideUp 0.4s ease; } .header { margin-bottom: var(--spacing-xl); h1 { font-size: 2rem; font-weight: 700; margin-bottom: var(--spacing-sm); } } .subtitle { color: var(--color-text-secondary); font-size: 1.1rem; } .backLink { display: inline-flex; align-items: center; gap: var(--spacing-xs); color: var(--color-primary); text-decoration: none; font-size: 0.9rem; margin-bottom: var(--spacing-md); &:hover { text-decoration: underline; } } // ===== Stats ===== .stats { display: flex; gap: var(--spacing-md); margin-bottom: var(--spacing-xl); flex-wrap: wrap; } .statCard { flex: 1; min-width: 120px; background: var(--color-bg-secondary); border: 2px solid var(--border-card, #9ca3af); border-radius: var(--radius-lg); padding: var(--spacing-md) var(--spacing-lg); text-align: center; .statValue { font-size: 1.8rem; font-weight: 700; } .statLabel { font-size: 0.8rem; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.03em; margin-top: var(--spacing-xs); } &.info .statValue { color: #3b82f6; } &.warning .statValue { color: #f59e0b; } &.error .statValue { color: #ef4444; } &.critical .statValue { color: #dc2626; } &.total .statValue { color: var(--color-text); } } // ===== Filters ===== .filters { display: flex; gap: var(--spacing-md); margin-bottom: var(--spacing-lg); flex-wrap: wrap; align-items: flex-end; } .filterField { display: flex; flex-direction: column; gap: var(--spacing-xs); label { font-weight: 500; font-size: 0.8rem; color: var(--color-text-secondary); text-transform: uppercase; } select, input { padding: var(--spacing-sm) var(--spacing-md); background: var(--color-bg); border: 2px solid var(--border-card, #9ca3af); border-radius: var(--radius-md); color: var(--color-text); font-size: 0.9rem; min-width: 140px; &:focus { outline: none; border-color: var(--color-primary); } } } .refreshBtn { display: flex; align-items: center; gap: var(--spacing-xs); padding: var(--spacing-sm) var(--spacing-md); background: var(--color-bg-tertiary); border: 2px solid var(--border-card, #9ca3af); border-radius: var(--radius-md); color: var(--color-text); font-size: 0.9rem; cursor: pointer; transition: all 0.2s ease; &:hover { border-color: var(--color-primary); color: var(--color-primary); } } // ===== Table ===== .tableWrapper { overflow-x: auto; animation: slideUp 0.3s ease; } .logsTable { width: 100%; border-collapse: separate; border-spacing: 0; background: var(--color-bg-secondary); border: 2px solid var(--border-card, #9ca3af); border-radius: var(--radius-lg); overflow: hidden; th, td { padding: var(--spacing-sm) var(--spacing-md); text-align: left; } th { background: var(--color-bg-tertiary); font-size: 0.8rem; font-weight: 600; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.03em; border-bottom: 2px solid var(--border-card, #9ca3af); white-space: nowrap; } td { border-bottom: 1px solid var(--color-border); font-size: 0.9rem; vertical-align: middle; } tbody tr { transition: background 0.15s ease; &:last-child td { border-bottom: none; } &:hover { background: var(--color-bg-tertiary); } } } .timestamp { white-space: nowrap; font-size: 0.8rem; color: var(--color-text-secondary); font-family: monospace; } .levelBadge { display: inline-flex; align-items: center; gap: var(--spacing-xs); padding: 2px var(--spacing-sm); border-radius: var(--radius-sm); font-size: 0.75rem; font-weight: 600; white-space: nowrap; text-transform: uppercase; &.info { background: rgba(59, 130, 246, 0.15); color: #3b82f6; } &.warning { background: rgba(245, 158, 11, 0.15); color: #f59e0b; } &.error { background: rgba(239, 68, 68, 0.15); color: #ef4444; } &.critical { background: rgba(220, 38, 38, 0.2); color: #dc2626; font-weight: 700; } } .categoryBadge { display: inline-flex; padding: 2px var(--spacing-sm); border-radius: var(--radius-sm); font-size: 0.75rem; font-weight: 500; background: var(--color-bg-tertiary); color: var(--color-text-secondary); border: 1px solid var(--color-border); } .message { max-width: 400px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } // ===== Pagination ===== .pagination { display: flex; align-items: center; justify-content: center; gap: var(--spacing-md); margin-top: var(--spacing-lg); } .pageBtn { display: flex; align-items: center; gap: var(--spacing-xs); padding: var(--spacing-sm) var(--spacing-md); background: var(--color-bg-secondary); border: 2px solid var(--border-card, #9ca3af); border-radius: var(--radius-md); color: var(--color-text); font-size: 0.9rem; cursor: pointer; transition: all 0.2s ease; &:hover:not(:disabled) { border-color: var(--color-primary); color: var(--color-primary); } &:disabled { opacity: 0.4; cursor: not-allowed; } } .pageInfo { font-size: 0.9rem; color: var(--color-text-secondary); } // ===== Loading / Empty / Error ===== .loading { display: flex; align-items: center; justify-content: center; min-height: 400px; font-size: 1.2rem; color: var(--color-text-secondary); } .errorMsg { background: rgba(239, 68, 68, 0.1); border: 1px solid rgba(239, 68, 68, 0.3); color: var(--color-danger); border-radius: var(--radius-md); padding: var(--spacing-md) var(--spacing-lg); font-size: 0.95rem; margin-bottom: var(--spacing-lg); display: flex; align-items: center; gap: var(--spacing-sm); } .emptyState { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--spacing-md); text-align: center; padding: var(--spacing-xl) var(--spacing-xl) calc(var(--spacing-xl) * 2); color: var(--color-text-secondary); background: var(--color-bg-secondary); border: 2px dashed var(--border-card, #9ca3af); border-radius: var(--radius-lg); p { font-size: 1.1rem; font-weight: 500; } } @media (max-width: 768px) { .stats { flex-direction: column; } .filters { flex-direction: column; } .filterField { width: 100%; select, input { width: 100%; } } .header h1 { font-size: 1.5rem; } }