Skip to content

Commit b185dfc

Browse files
committed
templating html
1 parent bfd7478 commit b185dfc

File tree

3 files changed

+274
-174
lines changed

3 files changed

+274
-174
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Common functionality for all PiTrac pages
2+
3+
// Theme management
4+
function setTheme(theme) {
5+
if (theme === 'system') {
6+
localStorage.removeItem('theme');
7+
applySystemTheme();
8+
} else {
9+
localStorage.setItem('theme', theme);
10+
document.documentElement.setAttribute('data-theme', theme);
11+
}
12+
updateThemeButtons();
13+
}
14+
15+
function applySystemTheme() {
16+
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
17+
document.documentElement.setAttribute('data-theme', systemTheme);
18+
}
19+
20+
function updateThemeButtons() {
21+
const currentTheme = localStorage.getItem('theme') || 'system';
22+
document.querySelectorAll('.theme-btn').forEach(btn => {
23+
btn.classList.toggle('active', btn.dataset.theme === currentTheme);
24+
});
25+
}
26+
27+
// Initialize theme on page load
28+
document.addEventListener('DOMContentLoaded', () => {
29+
const savedTheme = localStorage.getItem('theme');
30+
if (savedTheme) {
31+
document.documentElement.setAttribute('data-theme', savedTheme);
32+
} else {
33+
applySystemTheme();
34+
}
35+
updateThemeButtons();
36+
37+
// Initialize dropdown menu
38+
initDropdown();
39+
});
40+
41+
// Listen for system theme changes
42+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
43+
if (!localStorage.getItem('theme')) {
44+
applySystemTheme();
45+
}
46+
});
47+
48+
// Dropdown menu functionality
49+
function initDropdown() {
50+
const dropdownToggle = document.querySelector('.dropdown-toggle');
51+
const dropdownMenu = document.querySelector('.dropdown-menu');
52+
53+
if (dropdownToggle && dropdownMenu) {
54+
dropdownToggle.addEventListener('click', (e) => {
55+
e.stopPropagation();
56+
dropdownMenu.classList.toggle('show');
57+
});
58+
59+
// Close dropdown when clicking outside
60+
document.addEventListener('click', () => {
61+
dropdownMenu.classList.remove('show');
62+
});
63+
64+
// Prevent dropdown from closing when clicking inside
65+
dropdownMenu.addEventListener('click', (e) => {
66+
e.stopPropagation();
67+
});
68+
}
69+
}
70+
71+
// Modal functionality
72+
function closeModal() {
73+
const modal = document.getElementById('testModal');
74+
if (modal) {
75+
modal.style.display = 'none';
76+
}
77+
}
78+
79+
// Close modal when clicking outside
80+
window.onclick = function(event) {
81+
const modal = document.getElementById('testModal');
82+
if (modal && event.target === modal) {
83+
modal.style.display = 'none';
84+
}
85+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>{% block title %}PiTrac{% endblock %}</title>
7+
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
8+
<link rel="stylesheet" href="/static/dashboard.css">
9+
{% block extra_css %}{% endblock %}
10+
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
11+
<meta http-equiv="Pragma" content="no-cache">
12+
<meta http-equiv="Expires" content="0">
13+
</head>
14+
<body>
15+
<div class="container">
16+
<!-- Shared Navigation Header -->
17+
<div class="header">
18+
<div class="header-content">
19+
<a href="/" style="display: flex; align-items: center; gap: 0.75rem; text-decoration: none; color: inherit;">
20+
<img src="/static/logos/PiTrac.svg" alt="PiTrac Logo" class="header-logo">
21+
<h1>{% block page_title %}PiTrac{% endblock %}</h1>
22+
</a>
23+
</div>
24+
<div class="header-right">
25+
<div class="dropdown">
26+
<button class="dropdown-toggle" aria-label="Menu">
27+
<svg fill="currentColor" viewBox="0 0 20 20" width="24" height="24">
28+
<path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z"/>
29+
</svg>
30+
</button>
31+
<div class="dropdown-menu">
32+
<a href="/" class="dropdown-item">
33+
<svg fill="currentColor" viewBox="0 0 20 20" width="20" height="20">
34+
<path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"/>
35+
</svg>
36+
Dashboard
37+
</a>
38+
<a href="/config" class="dropdown-item">
39+
<svg fill="currentColor" viewBox="0 0 20 20" width="20" height="20">
40+
<path fill-rule="evenodd" d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z" clip-rule="evenodd"/>
41+
</svg>
42+
Configuration
43+
</a>
44+
<a href="/calibration" class="dropdown-item">
45+
<svg fill="currentColor" viewBox="0 0 20 20" width="20" height="20">
46+
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z"/>
47+
</svg>
48+
Calibration
49+
</a>
50+
<a href="/testing" class="dropdown-item">
51+
<svg fill="currentColor" viewBox="0 0 20 20" width="20" height="20">
52+
<path fill-rule="evenodd" d="M6 2a2 2 0 00-2 2v12a2 2 0 002 2h8a2 2 0 002-2V7.414A2 2 0 0015.414 6L12 2.586A2 2 0 0010.586 2H6zm5 6a1 1 0 10-2 0v2H7a1 1 0 100 2h2v2a1 1 0 102 0v-2h2a1 1 0 100-2h-2V8z" clip-rule="evenodd"/>
53+
</svg>
54+
Testing Tools
55+
</a>
56+
<a href="/logs" class="dropdown-item">
57+
<svg fill="currentColor" viewBox="0 0 20 20" width="20" height="20">
58+
<path fill-rule="evenodd" d="M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z" clip-rule="evenodd"/>
59+
</svg>
60+
Logs
61+
</a>
62+
<div class="dropdown-divider"></div>
63+
<div class="theme-selector">
64+
<span class="dropdown-label">Theme</span>
65+
<div class="theme-options">
66+
<button class="theme-btn" data-theme="light" title="Light mode" onclick="setTheme('light')">
67+
<svg fill="currentColor" viewBox="0 0 20 20">
68+
<path fill-rule="evenodd" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" clip-rule="evenodd"/>
69+
</svg>
70+
</button>
71+
<button class="theme-btn" data-theme="dark" title="Dark mode" onclick="setTheme('dark')">
72+
<svg fill="currentColor" viewBox="0 0 20 20">
73+
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"/>
74+
</svg>
75+
</button>
76+
<button class="theme-btn" data-theme="system" title="System theme" onclick="setTheme('system')">
77+
<svg fill="currentColor" viewBox="0 0 20 20">
78+
<path fill-rule="evenodd" d="M3 5a2 2 0 012-2h10a2 2 0 012 2v8a2 2 0 01-2 2h-2.22l.123.489.804.804A1 1 0 0113 18H7a1 1 0 01-.707-1.707l.804-.804L7.22 15H5a2 2 0 01-2-2V5zm5.771 7H5V5h10v7H8.771z" clip-rule="evenodd"/>
79+
</svg>
80+
</button>
81+
</div>
82+
</div>
83+
</div>
84+
</div>
85+
</div>
86+
</div>
87+
88+
<!-- Main Content Area -->
89+
{% block content %}{% endblock %}
90+
</div>
91+
92+
<!-- Common Scripts -->
93+
<script src="/static/js/common.js"></script>
94+
{% block extra_scripts %}{% endblock %}
95+
</body>
96+
</html>

0 commit comments

Comments
 (0)