Add print badges, pagination, route splitting, JWT auth fixes, and list page alignment

- Fix equipment badge barcode not rendering (loading race condition)
- Fix printer QR code not rendering on initial load (same race condition)
- Add model image to equipment badge via imageurl from Model table
- Fix white-on-white machine number text on badge, tighten barcode spacing
- Add PaginationBar component used across all list pages
- Split monolithic router into per-plugin route modules
- Fix 25 GET API endpoints returning 401 (jwt_required -> optional=True)
- Align list page columns across Equipment, PCs, and Network pages
- Add print views: EquipmentBadge, PrinterQRSingle, PrinterQRBatch, USBLabelBatch
- Add PC Relationships report, migration docs, and CLAUDE.md project guide
- Various plugin model, API, and frontend refinements

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-02-04 07:32:44 -05:00
parent c4bfdc2db2
commit 9efdb5f52d
89 changed files with 3951 additions and 1138 deletions

View File

@@ -33,6 +33,17 @@
--sidebar-bg: #00003d;
--sidebar-text: #ffffff;
--sidebar-width: 250px;
/* Hover variants */
--secondary-dark: #82503f;
--success-dark: #019e4c;
--info-dark: #039ce0;
--warning-dark: #e67c02;
--danger-dark: #e62c51;
/* Additional semantic colors */
--purple: #9c27b0;
--bg-popover: #111111;
}
/* Dark Mode - via data-theme attribute or system preference fallback */
@@ -146,7 +157,7 @@ h1, h2, h3, h4, h5, h6 {
font-size: 14px;
font-weight: 400;
text-transform: uppercase;
color: #ffffff;
color: var(--sidebar-text);
margin: 0.5rem 0 0 0;
letter-spacing: 1px;
}
@@ -189,6 +200,7 @@ h1, h2, h3, h4, h5, h6 {
.sidebar-nav a {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.7rem 1.25rem;
color: rgba(255,255,255,0.85);
text-decoration: none;
@@ -196,6 +208,11 @@ h1, h2, h3, h4, h5, h6 {
font-size: 14px;
}
.sidebar-nav a svg {
margin-right: 0.5rem;
flex-shrink: 0;
}
.sidebar-nav a:hover,
.sidebar-nav a.active {
background: rgba(255,255,255,0.1);
@@ -431,8 +448,8 @@ tr:hover {
}
.btn-secondary:hover {
background: #82503f;
border-color: #82503f;
background: var(--secondary-dark);
border-color: var(--secondary-dark);
color: white;
}
@@ -443,8 +460,8 @@ tr:hover {
}
.btn-success:hover {
background: #019e4c;
border-color: #019e4c;
background: var(--success-dark);
border-color: var(--success-dark);
}
.btn-info {
@@ -454,8 +471,8 @@ tr:hover {
}
.btn-info:hover {
background: #039ce0;
border-color: #039ce0;
background: var(--info-dark);
border-color: var(--info-dark);
}
.btn-warning {
@@ -465,8 +482,8 @@ tr:hover {
}
.btn-warning:hover {
background: #e67c02;
border-color: #e67c02;
background: var(--warning-dark);
border-color: var(--warning-dark);
}
.btn-danger {
@@ -476,8 +493,8 @@ tr:hover {
}
.btn-danger:hover {
background: #e62c51;
border-color: #e62c51;
background: var(--danger-dark);
border-color: var(--danger-dark);
}
.btn-link {
@@ -614,7 +631,7 @@ input[type="radio"] {
}
select.form-control option {
background: #1a1a2e;
background: var(--text);
}
}
@@ -690,7 +707,7 @@ input[type="radio"] {
.error-message {
background: rgba(245, 54, 92, 0.2);
color: #f5365c;
color: var(--danger);
padding: 0.75rem 1rem;
border-radius: 0.25rem;
margin-bottom: 1rem;
@@ -789,11 +806,35 @@ input[type="radio"] {
}
/* Pagination */
.pagination-bar {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 1rem;
padding-top: 0.75rem;
border-top: 1px solid var(--border);
}
.pagination-info {
display: flex;
align-items: center;
}
.perpage-select {
padding: 0.375rem 0.5rem;
border: 1px solid var(--border);
border-radius: 0.25rem;
background: var(--bg-card);
color: var(--text);
font-size: 13px;
cursor: pointer;
}
.pagination {
display: flex;
justify-content: center;
gap: 0.25rem;
margin-top: 1rem;
margin-top: 0;
}
.pagination button {
@@ -806,8 +847,14 @@ input[type="radio"] {
color: var(--text);
}
.pagination button:hover {
background: rgba(255, 255, 255, 0.1);
.pagination button:hover:not(:disabled):not(.ellipsis) {
background: var(--bg);
border-color: var(--primary);
}
.pagination button:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.pagination button.active {
@@ -816,6 +863,12 @@ input[type="radio"] {
border-color: var(--primary);
}
.pagination button.ellipsis {
border: none;
cursor: default;
padding: 0.5rem 0.25rem;
}
/* Loading */
.loading {
text-align: center;
@@ -1260,7 +1313,7 @@ td.actions {
}
.badge-printer {
background: #9c27b0;
background: var(--purple);
color: white;
}
@@ -1354,7 +1407,7 @@ td.actions {
}
.fc .fc-popover {
background: #111111;
background: var(--bg-popover);
border: 1px solid var(--border);
border-radius: 0.25rem;
box-shadow: 0 16px 38px -12px rgba(0,0,0,.56), 0 4px 25px 0 rgba(0,0,0,.12), 0 8px 10px -5px rgba(0,0,0,.2);
@@ -1413,18 +1466,18 @@ td.actions {
LEAFLET DARK THEME OVERRIDES
============================================ */
.leaflet-container {
background: #111111;
background: var(--bg-popover);
}
.leaflet-popup-content-wrapper {
background: #111111;
background: var(--bg-popover);
color: var(--text);
border-radius: 0.25rem;
box-shadow: 0 16px 38px -12px rgba(0,0,0,.56), 0 4px 25px 0 rgba(0,0,0,.12), 0 8px 10px -5px rgba(0,0,0,.2);
}
.leaflet-popup-tip {
background: #111111;
background: var(--bg-popover);
}
.leaflet-popup-content {