retro css
This commit is contained in:
+6
-2
@@ -168,8 +168,12 @@ def create_app():
|
||||
if type_:
|
||||
query = query.filter(SensorReadout.type == type_)
|
||||
rows = query.order_by(SensorReadout.timestamp).all()
|
||||
# Zakresy today i 24h: wszystkie pomiary jako punkty, bez uśredniania.
|
||||
if range_ in ("today", "24h"):
|
||||
# Zakresy today i 24h domyślnie zwracają wszystkie pomiary bez
|
||||
# uśredniania; checkbox "hourly average" wymusza średnie godzinowe.
|
||||
averaged = range_ not in ("today", "24h") or request.args.get(
|
||||
"avg", "0"
|
||||
).lower() in ("1", "true", "yes")
|
||||
if not averaged:
|
||||
return jsonify(
|
||||
[
|
||||
{
|
||||
|
||||
@@ -63,6 +63,27 @@ h1 {
|
||||
|
||||
h2 { color: var(--mc-bright); letter-spacing: 2px; }
|
||||
|
||||
/* Yggdrasil logo — pixel art, so keep it crisp when scaled down.
|
||||
* On the home page it spans the full width of the blue band. */
|
||||
.logo {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin: 1rem auto;
|
||||
image-rendering: pixelated;
|
||||
border: 3px double var(--mc-bright);
|
||||
box-shadow: 8px 8px 0 rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
/* Small logo pinned to the right side of the black navbar. */
|
||||
nav { display: flex; align-items: center; }
|
||||
.nav-logo {
|
||||
height: 68px;
|
||||
width: auto;
|
||||
margin-left: auto;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
@keyframes mcblink { 50% { opacity: 0; } }
|
||||
|
||||
/* --- Menu bar (navigation) --- */
|
||||
@@ -166,6 +187,12 @@ button:disabled { opacity: 0.5; cursor: default; }
|
||||
|
||||
#refresh-button { margin-top: 0.6rem; }
|
||||
|
||||
/* Sensors page: the "hourly average" checkbox must stay a small inline
|
||||
* box next to its text — the global `input { width: 100% }` would
|
||||
* otherwise stretch it full-width and break the row layout. */
|
||||
#avg-label { display: flex; align-items: center; gap: 0.5em; margin-top: 0.6rem; }
|
||||
#avg-label input { width: auto; margin: 0; }
|
||||
|
||||
.error {
|
||||
background: var(--mc-red);
|
||||
color: var(--mc-bright);
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
@@ -13,6 +13,7 @@
|
||||
<a href="{{ url_for('home') }}">Home</a>
|
||||
<a href="{{ url_for('sensors_page') }}">Sensors</a>
|
||||
<a href="{{ url_for('logout') }}">Log out</a>
|
||||
<img class="nav-logo" src="{{ url_for('static', filename='yggdrasil-logo.png') }}" alt="Yggdrasil logo">
|
||||
</nav>
|
||||
<h1>Sensor Readouts — API Documentation</h1>
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<a href="{{ url_for('sensors_page') }}">Sensors</a>
|
||||
<a href="{{ url_for('api_docs') }}">API</a>
|
||||
<a href="{{ url_for('logout') }}">Log out</a>
|
||||
<img class="nav-logo" src="{{ url_for('static', filename='yggdrasil-logo.png') }}" alt="Yggdrasil logo">
|
||||
</nav>
|
||||
<h1>Yggdrasil</h1>
|
||||
<div class="panel">
|
||||
@@ -26,6 +27,7 @@
|
||||
</ul>
|
||||
<p class="hint">Tip: press <b>1</b>, <b>2</b> or <b>0</b> to navigate.</p>
|
||||
</div>
|
||||
<img class="logo" src="{{ url_for('static', filename='yggdrasil-logo.png') }}" alt="Yggdrasil logo">
|
||||
<footer class="statusbar">
|
||||
<span>{{ user.username }}@yggdrasil:~$</span>
|
||||
</footer>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<a href="{{ url_for('home') }}">Home</a>
|
||||
<a href="{{ url_for('api_docs') }}">API</a>
|
||||
<a href="{{ url_for('logout') }}">Log out</a>
|
||||
<img class="nav-logo" src="{{ url_for('static', filename='yggdrasil-logo.png') }}" alt="Yggdrasil logo">
|
||||
</nav>
|
||||
<h1>Sensor Readouts</h1>
|
||||
|
||||
@@ -40,6 +41,9 @@
|
||||
<option value="month">Month</option>
|
||||
<option value="all" selected>All</option>
|
||||
</select>
|
||||
<label id="avg-label" class="hidden">
|
||||
<input type="checkbox" id="avg-checkbox"> hourly average
|
||||
</label>
|
||||
<button id="refresh-button" type="button">[ Refresh ]</button>
|
||||
</div>
|
||||
|
||||
@@ -77,6 +81,8 @@
|
||||
const readoutsSection = document.getElementById('readouts-section');
|
||||
const readoutsBody = document.getElementById('readouts-body');
|
||||
const chartInfo = document.getElementById('chart-info');
|
||||
const avgCheckbox = document.getElementById('avg-checkbox');
|
||||
const avgLabel = document.getElementById('avg-label');
|
||||
let chart = null;
|
||||
|
||||
// Strefa czasowa przeglądarki — backend liczy "today" od północy
|
||||
@@ -97,20 +103,35 @@
|
||||
return d.toLocaleString('pl-PL', { timeZone: userTz });
|
||||
}
|
||||
|
||||
function formatChartLabel(iso) {
|
||||
function formatChartLabel(iso, timeOnly) {
|
||||
const d = new Date(iso + 'Z');
|
||||
return d.toLocaleString('pl-PL', { timeZone: userTz, hour: '2-digit', minute: '2-digit', day: '2-digit', month: '2-digit', year: 'numeric' });
|
||||
if (timeOnly) {
|
||||
return d.toLocaleString('pl-PL', { timeZone: userTz, hour: '2-digit', minute: '2-digit' });
|
||||
}
|
||||
return d.toLocaleString('pl-PL', { timeZone: userTz, day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' });
|
||||
}
|
||||
|
||||
function chartInfoText(range) {
|
||||
function chartInfoText(range, averaged) {
|
||||
if (!averaged) {
|
||||
if (range === 'today') return `Raw measurements since local midnight (${userTz}) — no averaging.`;
|
||||
if (range === '24h') return 'Raw measurements from the last 24 hours — no averaging.';
|
||||
const period = range === 'week' ? 'the last 7 days'
|
||||
return 'Raw measurements from the last 24 hours — no averaging.';
|
||||
}
|
||||
const period = range === 'today' ? 'today (since local midnight)'
|
||||
: range === '24h' ? 'the last 24 hours'
|
||||
: range === 'week' ? 'the last 7 days'
|
||||
: range === 'month' ? 'the last 30 days'
|
||||
: 'all stored data';
|
||||
return `Hourly averages over ${period} — each point is the mean of all measurements in that local hour (${userTz}).`;
|
||||
}
|
||||
|
||||
function isRawRange(range) {
|
||||
return range === 'today' || range === '24h';
|
||||
}
|
||||
|
||||
function updateAvgVisibility() {
|
||||
avgLabel.classList.toggle('hidden', !isRawRange(rangeSelect.value));
|
||||
}
|
||||
|
||||
// Ciśnienie jest składowane w bazie w paskalach (tak wysyła firmware),
|
||||
// a wyświetlane w hektopaskalach z jednym miejscem po przecinku.
|
||||
function displayValue(type, value) {
|
||||
@@ -176,14 +197,16 @@
|
||||
|
||||
try {
|
||||
// fetch hourly data for chart
|
||||
const hourly = await fetchJSON(`/api/sensors/${sensorId}/readouts/hourly?type=${encodeURIComponent(type)}&range=${encodeURIComponent(range)}&tz=${encodeURIComponent(userTz)}`);
|
||||
const averaged = !isRawRange(range) || avgCheckbox.checked;
|
||||
const hourly = await fetchJSON(`/api/sensors/${sensorId}/readouts/hourly?type=${encodeURIComponent(type)}&range=${encodeURIComponent(range)}&tz=${encodeURIComponent(userTz)}&avg=${averaged ? '1' : '0'}`);
|
||||
if (!hourly.length) throw new Error('no data for this range');
|
||||
|
||||
const labels = hourly.map(r => formatChartLabel(r.timestamp));
|
||||
// Surowe punkty today/24h (~1/min) — mniejsze markery,
|
||||
// żeby wykres był czytelny. W obrębie doby na osi X
|
||||
// wystarczy sama godzina (też po uśrednieniu).
|
||||
const dense = !averaged;
|
||||
const labels = hourly.map(r => formatChartLabel(r.timestamp, isRawRange(range)));
|
||||
const values = hourly.map(r => displayValue(type, r.value));
|
||||
// Przy zakresach today/24h punktów jest dużo (~1/min),
|
||||
// więc mniejsze markery żeby wykres był czytelny.
|
||||
const dense = range === 'today' || range === '24h';
|
||||
|
||||
if (chart) chart.destroy();
|
||||
const ctx = document.getElementById('chart').getContext('2d');
|
||||
@@ -216,7 +239,7 @@
|
||||
// The chart was created while the container was hidden,
|
||||
// so force a re-measure now that it is visible.
|
||||
chart.resize();
|
||||
chartInfo.textContent = '> ' + chartInfoText(range);
|
||||
chartInfo.textContent = '> ' + chartInfoText(range, averaged);
|
||||
} catch (err) {
|
||||
chartError.textContent = '! Chart error: ' + err.message;
|
||||
chartError.classList.remove('hidden');
|
||||
@@ -265,8 +288,14 @@
|
||||
}
|
||||
});
|
||||
|
||||
rangeSelect.addEventListener('change', loadChart);
|
||||
rangeSelect.addEventListener('change', () => {
|
||||
updateAvgVisibility();
|
||||
loadChart();
|
||||
});
|
||||
|
||||
avgCheckbox.addEventListener('change', loadChart);
|
||||
|
||||
updateAvgVisibility();
|
||||
loadSensors();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user