feat(darkmode): added darkmode with env var setting and live settings on admin page

This commit is contained in:
FrederikBaerentsen
2025-12-15 17:52:05 -05:00
parent 7369d0babf
commit b2e4597ab5
7 changed files with 133 additions and 8 deletions

View File

@@ -445,3 +445,8 @@
# When true, all sections start expanded. When false, all sections start collapsed.
# Default: true
# BK_STATISTICS_DEFAULT_EXPANDED=false
# Optional: Enable dark mode by default
# When true, the application starts in dark mode.
# Default: false
# BK_DARK_MODE=true

View File

@@ -96,4 +96,5 @@ CONFIG: Final[list[dict[str, Any]]] = [
{'n': 'WISHES_DEFAULT_ORDER', 'd': '"bricktracker_wishes"."rowid" DESC'},
{'n': 'STATISTICS_SHOW_CHARTS', 'd': True, 'c': bool},
{'n': 'STATISTICS_DEFAULT_EXPANDED', 'd': True, 'c': bool},
{'n': 'DARK_MODE', 'c': bool},
]

View File

@@ -53,6 +53,7 @@ LIVE_CHANGEABLE_VARS: Final[List[str]] = [
'BK_REBRICKABLE_PAGE_SIZE',
'BK_STATISTICS_SHOW_CHARTS',
'BK_STATISTICS_DEFAULT_EXPANDED',
'BK_DARK_MODE',
# Default ordering and formatting
'BK_INSTRUCTIONS_ALLOWED_EXTENSIONS',
'BK_MINIFIGURES_DEFAULT_ORDER',
@@ -322,6 +323,7 @@ class ConfigManager:
'BK_HIDE_SPARE_PARTS': 'Hide spare parts from parts lists (spare parts must still be in database)',
'BK_USE_REMOTE_IMAGES': 'Use remote images from Rebrickable CDN instead of local',
'BK_STATISTICS_SHOW_CHARTS': 'Show collection growth charts on statistics page',
'BK_STATISTICS_DEFAULT_EXPANDED': 'Expand all statistics sections by default'
'BK_STATISTICS_DEFAULT_EXPANDED': 'Expand all statistics sections by default',
'BK_DARK_MODE': 'Enable dark mode theme'
}
return help_text.get(var_name, 'No help available for this variable')

View File

@@ -11,6 +11,11 @@ document.addEventListener('DOMContentLoaded', function() {
// Debug: Log chart data to console
console.log('Chart Data:', window.chartData);
// Get current theme colors
const isDarkMode = document.documentElement.getAttribute('data-bs-theme') === 'dark';
const textColor = isDarkMode ? '#f8f9fa' : '#212529';
const gridColor = isDarkMode ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)';
// Common chart configuration
const commonConfig = {
type: 'line',
@@ -25,20 +30,30 @@ document.addEventListener('DOMContentLoaded', function() {
x: {
title: {
display: true,
text: 'Release Year'
text: 'Release Year',
color: textColor
},
ticks: {
color: textColor
},
grid: {
display: false
display: false,
color: gridColor
}
},
y: {
beginAtZero: true,
title: {
display: true,
text: 'Count'
text: 'Count',
color: textColor
},
ticks: {
precision: 0
precision: 0,
color: textColor
},
grid: {
color: gridColor
}
}
},
@@ -110,7 +125,8 @@ document.addEventListener('DOMContentLoaded', function() {
...commonConfig.options.scales.y,
title: {
display: true,
text: 'Parts Count'
text: 'Parts Count',
color: textColor
}
}
}
@@ -143,7 +159,8 @@ document.addEventListener('DOMContentLoaded', function() {
...commonConfig.options.scales.y,
title: {
display: true,
text: 'Minifigures Count'
text: 'Minifigures Count',
color: textColor
}
}
}

View File

@@ -87,6 +87,11 @@
border-color: #6c757d;
}
[data-bs-theme="dark"] .table th .dropdown-toggle:hover {
background-color: #2b3035;
border-color: #6c757d;
}
/* Style dropdown items */
.dropdown-menu .dropdown-header {
font-size: 0.75rem;
@@ -106,6 +111,11 @@
color: #212529;
}
[data-bs-theme="dark"] .dropdown-menu .dropdown-item:hover {
background-color: #2b3035;
color: #fff;
}
.dropdown-menu .dropdown-item i {
width: 1.25rem;
text-align: center;
@@ -117,6 +127,11 @@
--th-bg:#fff !important;
}
[data-bs-theme="dark"] .sortable {
--th-color: #fff !important;
--th-bg: #212529 !important;
}
.sortable thead th {
font-weight: bold !important;
}
@@ -180,3 +195,80 @@
pointer-events: none;
}/* Duplicate filter support */
.duplicate-filter-hidden { display: none !important; }
/* Dark mode link and text fixes */
[data-bs-theme="dark"] .text-reset {
color: var(--bs-body-color) !important;
}
[data-bs-theme="dark"] a.text-reset:hover {
color: var(--bs-link-hover-color) !important;
}
[data-bs-theme="dark"] .text-dark {
color: var(--bs-body-color) !important;
}
/* Dark mode border fixes */
[data-bs-theme="dark"] .border-black {
border-color: var(--bs-border-color) !important;
}
/* Dark mode badge fixes */
[data-bs-theme="dark"] .text-bg-light {
background-color: #343a40 !important;
color: #f8f9fa !important;
}
[data-bs-theme="dark"] .bg-white {
background-color: #212529 !important;
}
[data-bs-theme="dark"] .text-black {
color: #f8f9fa !important;
}
/* Dark mode button fixes */
[data-bs-theme="dark"] .btn-outline-dark {
border-color: #f8f9fa;
color: #f8f9fa;
}
[data-bs-theme="dark"] .btn-outline-dark:hover {
background-color: #f8f9fa;
border-color: #f8f9fa;
color: #212529;
}
[data-bs-theme="dark"] .btn-light {
background-color: #343a40;
border-color: #495057;
color: #f8f9fa;
}
[data-bs-theme="dark"] .btn-light:hover {
background-color: #495057;
border-color: #6c757d;
color: #fff;
}
/* Dark mode table fixes */
[data-bs-theme="dark"] .table-light {
--bs-table-bg: #343a40;
--bs-table-color: #f8f9fa;
}
/* Dark mode for card header links */
[data-bs-theme="dark"] .text-decoration-none.text-dark {
color: var(--bs-body-color) !important;
}
/* Dark mode table text fix - ensure all table text is visible */
[data-bs-theme="dark"] .table {
--bs-table-color: var(--bs-body-color);
}
[data-bs-theme="dark"] .table tbody td,
[data-bs-theme="dark"] .table tbody th {
color: var(--bs-body-color);
}

View File

@@ -508,6 +508,14 @@
<div class="text-muted small">Expand all statistics sections by default</div>
</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input config-toggle" type="checkbox" id="BK_DARK_MODE" data-var="BK_DARK_MODE" {{ is_locked('BK_DARK_MODE') }}>
<label class="form-check-label" for="BK_DARK_MODE">
BK_DARK_MODE {{ config_badges('BK_DARK_MODE') }}
<div class="text-muted small">Enable dark mode theme</div>
</label>
</div>
</div>
</div>

View File

@@ -1,5 +1,5 @@
<!doctype html>
<html lang="en">
<html lang="en" data-bs-theme="{{ 'dark' if config.get('DARK_MODE') in [True, 'True', 'true'] else 'light' }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">