almost functional

This commit is contained in:
Matt Batchelder
2026-02-04 15:26:44 -05:00
parent 2153d3c725
commit f392e5d016
39 changed files with 10115 additions and 602 deletions

View File

@@ -55,8 +55,8 @@ body {
padding: 0;
display: flex;
flex-direction: column;
overflow-y: auto;
z-index: 1000;
overflow: hidden;
z-index: 1200;
}
.ots-main {
@@ -66,6 +66,11 @@ body {
margin-left: 260px;
}
.ots-main,
#page-wrapper {
position: relative;
}
.ots-content {
flex: 1;
padding: 32px;
@@ -106,12 +111,13 @@ body {
============================================================================ */
.sidebar-header {
padding: 20px 16px;
padding: 18px 16px;
border-bottom: 1px solid var(--color-border);
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
flex-shrink: 0;
}
.brand-link {
@@ -139,16 +145,18 @@ body {
flex: 1;
padding: 12px 0;
overflow-y: auto;
min-height: 0;
}
.sidebar-nav {
list-style: none;
margin: 0;
padding: 12px 0 120px;
padding: 12px 0 140px;
}
.sidebar-nav li {
display: block;
margin-top: 6px;
}
/* Compatibility: Xibo sidebar markup uses `sidebar-list`, `sidebar-main`, `sidebar-title`.
@@ -157,10 +165,9 @@ body {
.ots-sidebar li.sidebar-list > a,
.ots-sidebar li.sidebar-main > a,
.ots-sidebar li.sidebar-title > a {
display: grid;
grid-template-columns: 20px 1fr;
display: flex;
align-items: center;
column-gap: 12px;
gap: 12px;
padding: 8px 12px;
color: #c8d5ee;
text-decoration: none;
@@ -171,7 +178,7 @@ body {
border-left: 2px solid transparent;
margin: 3px 10px;
border-radius: 12px;
min-height: 40px;
min-height: 48px;
line-height: 1.25;
}
@@ -192,15 +199,15 @@ body {
}
.ots-sidebar .ots-nav-icon {
width: 24px;
height: 24px;
display: flex;
width: 28px;
height: 28px;
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
font-size: 16px;
color: currentColor;
justify-self: center;
margin-left: 0;
}
.ots-sidebar .ots-nav-text {
@@ -210,6 +217,11 @@ body {
line-height: 1.2;
}
.sidebar-group-toggle .ots-nav-icon,
.ots-sidebar-nav .ots-nav-icon {
justify-self: start;
}
.ots-sidebar li.sidebar-title > a {
display: block;
font-size: 10px;
@@ -223,6 +235,181 @@ body {
line-height: 1;
}
.brand-logo {
width: 32px;
height: 32px;
object-fit: contain;
}
.brand-text {
color: var(--color-text-primary);
font-size: 18px;
font-weight: 600;
letter-spacing: 0.02em;
}
.sidebar-header {
padding: 18px 16px;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
flex-shrink: 0;
height: 72px;
box-sizing: border-box;
position: sticky;
top: 0;
background: #08132a;
z-index: 1210;
}
.sidebar-collapse-btn {
width: 32px;
height: 32px;
border-radius: 8px;
border: 0;
background: rgba(255, 255, 255, 0.08);
color: #d7e2f8;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all var(--transition-fast);
}
.sidebar-collapse-btn:hover {
background: rgba(255, 255, 255, 0.16);
color: #ffffff;
}
.ots-sidebar.collapsed {
width: 88px;
}
.ots-sidebar.collapsed .brand-text,
.ots-sidebar.collapsed .sidebar-group-toggle .ots-nav-text,
.ots-sidebar.collapsed .sidebar-list .ots-nav-text,
.ots-sidebar.collapsed .sidebar-submenu,
.ots-sidebar.collapsed .sidebar-group-caret,
.ots-sidebar.collapsed .user-details {
display: none !important;
}
.ots-sidebar.collapsed .sidebar-group-toggle,
.ots-sidebar.collapsed .sidebar-list > a {
justify-content: center;
padding: 10px;
}
/* Center icons when collapsed */
.ots-sidebar.collapsed .ots-nav-icon {
justify-self: center !important;
margin-left: 0 !important;
}
.ots-sidebar-collapsed #page-wrapper,
.ots-sidebar-collapsed .ots-main {
margin-left: 88px !important;
}
.ots-sidebar-nav {
padding: 12px 0 140px;
padding-top: 8px;
}
.sidebar-group {
margin-top: 6px;
}
.sidebar-group-toggle {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 12px;
margin: 6px 10px;
border-radius: 12px;
color: #d7e2f8;
text-decoration: none;
background: rgba(255, 255, 255, 0.03);
transition: all var(--transition-fast);
}
.sidebar-group-toggle:hover {
background: rgba(255, 255, 255, 0.08);
color: #ffffff;
}
.sidebar-group-caret {
margin-left: auto;
font-size: 12px;
opacity: 0.8;
}
.sidebar-submenu {
list-style: none;
margin: 4px 0 8px;
padding: 0 0 0 12px;
border-left: 1px solid rgba(255, 255, 255, 0.08);
}
.sidebar-group.is-open .sidebar-group-caret {
transform: rotate(180deg);
}
.sidebar-submenu .sidebar-list > a {
margin: 4px 10px 4px 18px;
background: rgba(255, 255, 255, 0.04);
}
.sidebar-submenu .sidebar-list > a:hover {
background: rgba(255, 255, 255, 0.1);
}
.sidebar-submenu .sidebar-list.active > a,
.sidebar-submenu .sidebar-list > a.active {
color: #0b1221;
background-color: #ffffff;
box-shadow: 0 8px 18px rgba(15, 23, 42, 0.25);
}
.sidebar-footer {
border-top: 1px solid rgba(255, 255, 255, 0.08);
padding: 16px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
background-color: rgba(15, 23, 42, 0.6);
}
.sidebar-theme-toggle {
width: 36px;
height: 36px;
border-radius: 10px;
border: 0;
background: rgba(255, 255, 255, 0.08);
color: #ffffff;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all var(--transition-fast);
}
.sidebar-theme-toggle:hover {
background: rgba(255, 255, 255, 0.16);
}
.user-role {
display: inline-flex;
align-items: center;
gap: 8px;
font-size: 12px;
color: var(--color-text-secondary);
margin-bottom: 4px;
}
.nav-section-divider {
padding: 12px 16px 8px;
margin-top: 8px;
@@ -299,6 +486,7 @@ body {
border-top: 1px solid var(--color-border);
padding: 16px;
background-color: rgba(59, 130, 246, 0.05);
flex-shrink: 0;
}
.sidebar-user {
@@ -353,7 +541,6 @@ body {
.ots-topbar {
background-color: var(--color-surface-elevated);
border-bottom: 2px solid var(--color-border);
padding: 10px 32px;
display: flex;
align-items: center;
@@ -395,10 +582,13 @@ body {
white-space: nowrap;
transition: all var(--transition-fast);
position: relative;
border: 0 !important;
background: transparent !important;
box-shadow: none !important;
}
.ots-topbar .nav-link:hover {
background-color: rgba(59, 130, 246, 0.08);
background-color: rgba(59, 130, 246, 0.06);
color: var(--color-primary);
}
@@ -430,8 +620,8 @@ body {
border-radius: 8px;
padding: 6px 0;
margin-top: 4px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
border: 1px solid var(--color-border);
box-shadow: none;
border: 0 !important;
background-color: var(--color-surface);
min-width: 180px;
z-index: 1100;
@@ -688,6 +878,99 @@ body {
overflow: hidden;
}
/* Make DataTables button collections compatible with OTS dropdown styling */
.dt-buttons {
position: relative;
display: inline-block;
}
.dt-button-collection {
position: absolute;
top: 100%;
right: 0;
margin-top: 6px;
display: none;
z-index: 1002;
min-width: 160px;
background-color: var(--color-surface-elevated);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 8px;
box-shadow: 0 20px 45px rgba(0, 0, 0, 0.3);
overflow: hidden;
padding: 6px 0;
}
.dt-buttons.active .dt-button-collection,
.dt-button-collection.active,
.dt-button-collection.show {
display: block;
animation: slideDown 150ms ease-out;
}
/* Ensure collection items are visible and styled */
.dt-button-collection .dt-button,
.dt-button-collection button,
.dt-button-collection a {
display: block;
width: 100%;
padding: 6px 12px;
color: var(--color-text-primary);
background: transparent;
text-decoration: none;
font-size: 13px;
text-align: left;
border: none;
}
.dt-button-collection .dt-button:hover,
.dt-button-collection a:hover,
.dt-button-collection button:hover {
background-color: rgba(59, 130, 246, 0.06);
color: var(--color-primary);
}
.dt-button-collection input[type="checkbox"] {
margin-right: 8px;
vertical-align: middle;
}
.dt-button-collection .dt-button:focus,
.dt-button-collection a:focus,
.dt-button-collection button:focus {
outline: none;
box-shadow: none;
}
/* DataTables sometimes nests a `div.dropdown-menu` inside the collection.
Ensure that inner dropdown-menu is visible when the collection is shown. */
.dt-button-collection .dropdown-menu {
display: block !important;
position: static !important;
background: transparent !important;
border: none !important;
box-shadow: none !important;
padding: 0 !important;
min-width: 160px !important;
}
.dt-button-collection .dropdown-menu .dropdown-item,
.dt-button-collection .dropdown-menu a,
.dt-button-collection .dropdown-menu .dt-button {
display: block !important;
padding: 6px 12px !important;
color: var(--color-text-primary) !important;
text-decoration: none !important;
background: transparent !important;
text-align: left !important;
}
.dt-button-collection .dropdown-menu .dropdown-item:hover,
.dt-button-collection .dropdown-menu a:hover,
.dt-button-collection .dropdown-menu .dt-button:hover {
background-color: rgba(59, 130, 246, 0.06) !important;
color: var(--color-primary) !important;
}
.dropdown.active .dropdown-menu,
.dropdown:focus-within .dropdown-menu {
display: block;
@@ -995,90 +1278,138 @@ body {
background: linear-gradient(180deg, rgba(59, 130, 246, 0.06), rgba(59, 130, 246, 0.02));
border: 1px solid rgba(59, 130, 246, 0.18);
box-shadow: 0 12px 26px rgba(8, 15, 30, 0.35);
display: flex;
flex-direction: column;
min-height: 360px;
align-items: stretch;
display: flex !important;
flex-direction: column !important;
min-height: 380px;
height: 380px;
align-items: stretch !important;
overflow: visible !important;
}
.dashboard-chart-card > * {
width: 100% !important;
float: none !important;
clear: both !important;
}
.dashboard-chart-header {
display: flex;
justify-content: space-between;
align-items: center;
gap: 16px;
width: 100%;
box-sizing: border-box;
float: none;
flex-wrap: wrap;
display: flex !important;
flex-direction: column !important;
gap: 10px !important;
align-items: flex-start !important;
padding: 12px 16px !important;
box-sizing: border-box !important;
width: 100% !important;
background: transparent !important;
border: none !important;
float: none !important;
clear: both !important;
position: static !important;
inset: auto !important;
overflow: visible !important;
height: auto !important;
max-width: none !important;
flex: 0 0 auto !important;
}
.dashboard-chart-card .widget-title,
.dashboard-chart-card .widget-body {
width: 100%;
float: none !important;
clear: both;
display: block !important;
position: static !important;
.panel .dashboard-chart-header {
padding: 12px 20px !important;
}
.dashboard-chart-card .widget-title {
flex: 0 0 auto;
}
.dashboard-chart-card .widget-body {
position: relative !important;
}
.dashboard-chart-title {
display: flex;
align-items: center;
gap: 12px;
.dashboard-chart-info {
display: flex !important;
align-items: center !important;
gap: 10px !important;
flex: 0 0 auto !important;
min-width: 0 !important;
}
.dashboard-chart-icon {
width: 40px;
height: 40px;
border-radius: 12px;
background: rgba(59, 130, 246, 0.18);
color: var(--color-primary-light);
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 18px;
flex-shrink: 0;
width: 32px !important;
height: 32px !important;
border-radius: 10px !important;
background: rgba(59, 130, 246, 0.18) !important;
color: var(--color-primary-light) !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-size: 16px !important;
flex-shrink: 0 !important;
border: none !important;
padding: 0 !important;
margin: 0 !important;
}
.dashboard-chart-meta {
display: flex !important;
flex-direction: column !important;
gap: 2px !important;
flex-shrink: 0 !important;
}
.dashboard-chart-heading {
margin: 0;
font-size: 16px;
font-size: 15px;
font-weight: 700;
line-height: 1.2;
}
.dashboard-chart-subtitle {
margin: 4px 0 0;
font-size: 12px;
margin: 0;
font-size: 11px;
color: var(--color-text-secondary);
line-height: 1.2;
}
.dashboard-chart-link {
.dashboard-chart-actions {
display: flex !important;
align-items: center !important;
gap: 12px !important;
width: 100% !important;
flex-shrink: 0 !important;
padding: 0 !important;
border: none !important;
}
.dashboard-chart-toggle {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 4px;
border-radius: 999px;
background: rgba(15, 23, 42, 0.45);
}
.dashboard-chart-toggle-button {
border: none;
background: transparent;
color: var(--color-text-secondary);
font-size: 12px;
font-weight: 600;
color: var(--color-primary);
text-decoration: none;
padding: 6px 10px;
width: 40px;
height: 34px;
padding: 0;
border-radius: 999px;
border: 1px solid rgba(59, 130, 246, 0.24);
background: rgba(59, 130, 246, 0.12);
transition: all var(--transition-fast);
white-space: nowrap;
cursor: pointer;
transition: all 150ms ease;
display: inline-flex;
align-items: center;
justify-content: center;
}
.dashboard-chart-link:hover {
.dashboard-chart-toggle-button:hover {
color: var(--color-text-primary);
border-color: rgba(59, 130, 246, 0.5);
}
.dashboard-chart-toggle-button.is-active {
background: rgba(59, 130, 246, 0.22);
color: var(--color-text-primary);
}
.dashboard-chart-toggle-button i {
font-size: 16px;
line-height: 1;
display: inline-block;
}
.dashboard-chart-body {
@@ -1097,11 +1428,12 @@ body {
border: 1px solid rgba(255, 255, 255, 0.05);
border-radius: 12px;
padding: 12px;
height: clamp(220px, 32vh, 280px);
height: 200px;
width: 100%;
position: relative;
overflow: hidden;
flex: 1;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);
}
.dashboard-chart-canvas canvas {
@@ -1118,6 +1450,103 @@ body {
min-height: 0 !important;
}
/* Enhanced chart container styling */
.dashboard-chart-card {
transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1) !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
}
.dashboard-chart-card:hover {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25) !important;
transform: translateY(-2px);
}
/* Chart action improvements */
.dashboard-chart-actions {
gap: 16px !important;
}
.dashboard-chart-link {
font-size: 13px;
font-weight: 500;
color: var(--color-primary-light);
text-decoration: none;
white-space: nowrap;
transition: all 150ms ease;
padding: 4px 8px;
border-radius: 6px;
display: inline-block;
}
.dashboard-chart-link:hover {
color: var(--color-primary);
background: rgba(59, 130, 246, 0.1);
}
/* Modern toggle improvements */
.dashboard-chart-toggle {
background: rgba(15, 23, 42, 0.6);
border: 1px solid rgba(59, 130, 246, 0.2);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.dashboard-chart-toggle-button {
transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);
border: 1px solid transparent;
}
.dashboard-chart-toggle-button:hover {
background: rgba(59, 130, 246, 0.12);
border-color: rgba(59, 130, 246, 0.2);
}
.dashboard-chart-toggle-button.is-active {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.3), rgba(59, 130, 246, 0.2));
border-color: rgba(59, 130, 246, 0.3);
box-shadow: 0 0 12px rgba(59, 130, 246, 0.2);
}
.dashboard-chart-toggle-button i {
transition: transform 200ms ease;
}
.dashboard-chart-toggle-button:hover i {
transform: scale(1.15);
}
/* Responsive chart cards */
@media (max-width: 1200px) {
.dashboard-chart-canvas {
height: 180px;
}
}
@media (max-width: 768px) {
.dashboard-chart-card {
max-height: none;
}
.dashboard-chart-header {
flex-direction: row !important;
justify-content: space-between !important;
align-items: center !important;
gap: 12px !important;
}
.dashboard-chart-info {
flex: 1;
min-width: 0;
}
.dashboard-chart-actions {
flex-shrink: 0;
}
.dashboard-chart-canvas {
height: 200px;
}
}
.panel {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
@@ -1329,8 +1758,8 @@ body .panel .panel-heading,
align-items: center;
justify-content: space-between;
padding: 14px 16px;
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
background: rgba(15, 23, 42, 0.3);
border-bottom: none;
background: transparent;
}
.ots-filter-title {
@@ -1362,15 +1791,19 @@ body .panel .panel-heading,
.ots-filter-content {
padding: 16px;
max-height: 600px;
overflow: hidden;
max-height: none;
min-height: auto;
overflow: visible;
transition: max-height 300ms ease-out, padding 300ms ease-out;
display: block;
}
.ots-filter-content.collapsed {
max-height: 0;
min-height: 0;
padding: 0 16px;
overflow: hidden;
display: none;
}
.ots-filter-card .nav-tabs {
@@ -1936,6 +2369,58 @@ body .panel .panel-heading,
color: var(--color-text-primary);
}
/* Minimal Icon-Only Buttons */
.btn-icon {
width: 40px !important;
height: 40px !important;
padding: 0 !important;
border-radius: 8px !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
background-color: var(--color-surface-elevated) !important;
border: 1px solid var(--color-border) !important;
color: var(--color-text-secondary) !important;
font-size: 0 !important;
transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1) !important;
cursor: pointer !important;
position: relative !important;
margin-left: 6px !important;
flex-shrink: 0 !important;
}
.btn-icon:hover {
background-color: rgba(59, 130, 246, 0.12) !important;
border-color: rgba(59, 130, 246, 0.3) !important;
color: var(--color-primary-light) !important;
box-shadow: 0 2px 8px rgba(59, 130, 246, 0.1) !important;
}
.btn-icon:active {
background-color: rgba(59, 130, 246, 0.2) !important;
border-color: rgba(59, 130, 246, 0.4) !important;
transform: scale(0.95);
}
.btn-icon i,
.btn-icon svg {
font-size: 17px !important;
line-height: 1 !important;
display: inline-block !important;
}
.btn-icon.btn-success {
background-color: rgba(34, 197, 94, 0.08) !important;
border-color: rgba(34, 197, 94, 0.2) !important;
color: rgb(34, 197, 94) !important;
}
.btn-icon.btn-success:hover {
background-color: rgba(34, 197, 94, 0.15) !important;
border-color: rgba(34, 197, 94, 0.4) !important;
box-shadow: 0 2px 8px rgba(34, 197, 94, 0.1) !important;
}
/* ============================================================================
UTILITY CLASSES
============================================================================ */
@@ -2083,7 +2568,9 @@ canvas {
#sidebar-wrapper .sidebar-list a,
#sidebar-wrapper .sidebar-main a {
display: block;
display: flex;
align-items: center;
gap: 12px;
margin: 2px 8px;
padding: 10px 12px;
border-radius: 8px;
@@ -2383,17 +2870,34 @@ legend {
/* Dropdowns, modals, and popovers */
.dropdown-menu,
.dropdown-toggle,
.popover,
.modal,
.modal-content,
.modal-header,
.modal-body,
.modal-footer {
.popover {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
.modal,
.modal-body,
.modal-footer {
background-color: transparent !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
.modal-content {
background-color: var(--color-surface) !important;
color: var(--color-text-primary) !important;
border: 1px solid var(--color-border) !important;
}
.modal-backdrop,
.modal-backdrop.show,
.modal-backdrop.in {
background-color: rgba(0, 0, 0, 0.3) !important;
backdrop-filter: blur(4px) !important;
opacity: 1 !important;
}
.modal-header {
background-color: var(--color-surface-elevated) !important;
border-bottom: 1px solid var(--color-border) !important;
@@ -2666,3 +3170,30 @@ a.text-muted:hover {
.invisible {
visibility: hidden !important;
}
/* ============================================================================
FILTER FIELDS PADDING
============================================================================ */
.FilterDiv.card-body {
padding-top: 20px !important;
}
/* ============================================================================
LOGO WITH TEXT STYLING
============================================================================ */
.navbar-brand.xibo-logo-container {
display: flex;
align-items: center;
gap: 12px;
padding: 0;
margin-right: 16px;
}
.xibo-logo-text {
color: var(--color-text-primary);
font-size: 18px;
font-weight: 600;
margin: 0;
white-space: nowrap;
}