feat: add report_date to monitoring sessions and update related functionality
fix: chart properly renders centered
This commit is contained in:
@@ -77,6 +77,12 @@
|
||||
<dd class="font-medium text-indigo-600 dark:text-indigo-400 text-right text-xs" id="info-effective"></dd>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="flex justify-between">
|
||||
<dt class="text-gray-500 dark:text-gray-400">Report Date</dt>
|
||||
<dd class="font-medium text-gray-900 dark:text-white" id="info-report-date">
|
||||
{{ report_date or '— (auto)' }}
|
||||
</dd>
|
||||
</div>
|
||||
{% if session.started_at %}
|
||||
<div class="flex justify-between">
|
||||
<dt class="text-gray-500 dark:text-gray-400">Started</dt>
|
||||
@@ -118,66 +124,107 @@
|
||||
|
||||
<!-- Edit Card -->
|
||||
<div class="bg-white dark:bg-slate-800 rounded-xl border border-gray-200 dark:border-gray-700 p-5">
|
||||
<h2 class="text-sm font-semibold text-gray-700 dark:text-gray-300 uppercase tracking-wide mb-3">Edit Session</h2>
|
||||
<form id="edit-form" class="space-y-3" onsubmit="saveSession(event)">
|
||||
<div>
|
||||
<h2 class="text-sm font-semibold text-gray-700 dark:text-gray-300 uppercase tracking-wide mb-4">Edit Session</h2>
|
||||
<form id="edit-form" onsubmit="saveSession(event)">
|
||||
|
||||
<!-- Label -->
|
||||
<div class="mb-4">
|
||||
<label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">Label</label>
|
||||
<input type="text" id="edit-label" name="session_label"
|
||||
value="{{ session.session_label or '' }}"
|
||||
placeholder="e.g. NRL-1 — Mon 3/24 — Night"
|
||||
class="w-full text-sm bg-gray-50 dark:bg-slate-700 border border-gray-200 dark:border-gray-600 rounded-lg px-3 py-2 text-gray-900 dark:text-white focus:outline-none focus:border-seismo-orange">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">Period Type</label>
|
||||
<select id="edit-period-type" name="period_type"
|
||||
class="w-full text-sm bg-gray-50 dark:bg-slate-700 border border-gray-200 dark:border-gray-600 rounded-lg px-3 py-2 text-gray-900 dark:text-white focus:outline-none focus:border-seismo-orange">
|
||||
<option value="">— Not Set —</option>
|
||||
<option value="weekday_day" {% if session.period_type == 'weekday_day' %}selected{% endif %}>Weekday Day</option>
|
||||
<option value="weekday_night" {% if session.period_type == 'weekday_night' %}selected{% endif %}>Weekday Night</option>
|
||||
<option value="weekend_day" {% if session.period_type == 'weekend_day' %}selected{% endif %}>Weekend Day</option>
|
||||
<option value="weekend_night" {% if session.period_type == 'weekend_night' %}selected{% endif %}>Weekend Night</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">Start Hour (0–23)</label>
|
||||
<input type="number" min="0" max="23" id="edit-start-hour" name="period_start_hour"
|
||||
value="{{ session.period_start_hour if session.period_start_hour is not none else '' }}"
|
||||
placeholder="e.g. 19"
|
||||
class="w-full text-sm bg-gray-50 dark:bg-slate-700 border border-gray-200 dark:border-gray-600 rounded-lg px-3 py-2 text-gray-900 dark:text-white focus:outline-none focus:border-seismo-orange">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">End Hour (0–23)</label>
|
||||
<input type="number" min="0" max="23" id="edit-end-hour" name="period_end_hour"
|
||||
value="{{ session.period_end_hour if session.period_end_hour is not none else '' }}"
|
||||
placeholder="e.g. 7"
|
||||
class="w-full text-sm bg-gray-50 dark:bg-slate-700 border border-gray-200 dark:border-gray-600 rounded-lg px-3 py-2 text-gray-900 dark:text-white focus:outline-none focus:border-seismo-orange">
|
||||
|
||||
<!-- Section: Required Recording Window -->
|
||||
<div class="mb-4 p-3 bg-indigo-50 dark:bg-indigo-900/20 rounded-lg border border-indigo-100 dark:border-indigo-800">
|
||||
<p class="text-xs font-semibold text-indigo-700 dark:text-indigo-300 mb-0.5">Required Recording Window</p>
|
||||
<p class="text-xs text-indigo-500 dark:text-indigo-400 mb-3">The hours that count for reports. Only data within this window is included.</p>
|
||||
|
||||
<div class="space-y-2">
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">Period Type</label>
|
||||
<select id="edit-period-type" name="period_type"
|
||||
onchange="fillPeriodDefaults()"
|
||||
class="w-full text-sm bg-white dark:bg-slate-700 border border-gray-200 dark:border-gray-600 rounded-lg px-3 py-2 text-gray-900 dark:text-white focus:outline-none focus:border-seismo-orange">
|
||||
<option value="">— Not Set —</option>
|
||||
<option value="weekday_day" {% if session.period_type == 'weekday_day' %}selected{% endif %}>Weekday Day</option>
|
||||
<option value="weekday_night" {% if session.period_type == 'weekday_night' %}selected{% endif %}>Weekday Night</option>
|
||||
<option value="weekend_day" {% if session.period_type == 'weekend_day' %}selected{% endif %}>Weekend Day</option>
|
||||
<option value="weekend_night" {% if session.period_type == 'weekend_night' %}selected{% endif %}>Weekend Night</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">From (hour)</label>
|
||||
<div class="relative">
|
||||
<input type="number" min="0" max="23" id="edit-start-hour" name="period_start_hour"
|
||||
value="{{ session.period_start_hour if session.period_start_hour is not none else '' }}"
|
||||
placeholder="e.g. 19"
|
||||
oninput="updateWindowPreview()"
|
||||
class="w-full text-sm bg-white dark:bg-slate-700 border border-gray-200 dark:border-gray-600 rounded-lg px-3 py-2 text-gray-900 dark:text-white focus:outline-none focus:border-seismo-orange">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">To (hour)</label>
|
||||
<input type="number" min="0" max="23" id="edit-end-hour" name="period_end_hour"
|
||||
value="{{ session.period_end_hour if session.period_end_hour is not none else '' }}"
|
||||
placeholder="e.g. 7"
|
||||
oninput="updateWindowPreview()"
|
||||
class="w-full text-sm bg-white dark:bg-slate-700 border border-gray-200 dark:border-gray-600 rounded-lg px-3 py-2 text-gray-900 dark:text-white focus:outline-none focus:border-seismo-orange">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Live preview -->
|
||||
<div id="window-preview" class="text-xs font-medium text-indigo-600 dark:text-indigo-300 min-h-[1rem]">
|
||||
{% if session.period_start_hour is not none and session.period_end_hour is not none %}
|
||||
{% set sh = session.period_start_hour %}
|
||||
{% set eh = session.period_end_hour %}
|
||||
Window: {{ (sh % 12) or 12 }}:00 {{ 'AM' if sh < 12 else 'PM' }} → {{ (eh % 12) or 12 }}:00 {{ 'AM' if eh < 12 else 'PM' }}{% if eh <= sh %} (crosses midnight){% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="mt-2">
|
||||
<label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">
|
||||
Target Date <span class="text-gray-400">(optional — day sessions only)</span>
|
||||
</label>
|
||||
<input type="date" id="edit-report-date" name="report_date"
|
||||
value="{{ report_date or '' }}"
|
||||
class="w-full text-sm bg-white dark:bg-slate-700 border border-gray-200 dark:border-gray-600 rounded-lg px-3 py-2 text-gray-900 dark:text-white focus:outline-none focus:border-seismo-orange">
|
||||
<p class="text-xs text-gray-400 dark:text-gray-500 mt-1">Leave blank to auto-select the last day with data in the window.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">Start Time (local)</label>
|
||||
<input type="datetime-local" id="edit-started-at" name="started_at"
|
||||
value="{{ session.started_at|local_datetime_input if session.started_at else '' }}"
|
||||
class="w-full text-sm bg-gray-50 dark:bg-slate-700 border border-gray-200 dark:border-gray-600 rounded-lg px-3 py-2 text-gray-900 dark:text-white focus:outline-none focus:border-seismo-orange">
|
||||
|
||||
<!-- Section: Device On/Off Times -->
|
||||
<div class="mb-4 p-3 bg-gray-50 dark:bg-slate-700/40 rounded-lg border border-gray-200 dark:border-gray-600">
|
||||
<p class="text-xs font-semibold text-gray-600 dark:text-gray-400 mb-0.5">Device On/Off Times</p>
|
||||
<p class="text-xs text-gray-400 dark:text-gray-500 mb-3">When the meter was actually running. Usually set automatically from the data file.</p>
|
||||
|
||||
<div class="space-y-2">
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">Powered on</label>
|
||||
<input type="datetime-local" id="edit-started-at" name="started_at"
|
||||
value="{{ session.started_at|local_datetime_input if session.started_at else '' }}"
|
||||
class="w-full text-sm bg-white dark:bg-slate-700 border border-gray-200 dark:border-gray-600 rounded-lg px-3 py-2 text-gray-900 dark:text-white focus:outline-none focus:border-seismo-orange">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">Powered off</label>
|
||||
<input type="datetime-local" id="edit-stopped-at" name="stopped_at"
|
||||
value="{{ session.stopped_at|local_datetime_input if session.stopped_at else '' }}"
|
||||
class="w-full text-sm bg-white dark:bg-slate-700 border border-gray-200 dark:border-gray-600 rounded-lg px-3 py-2 text-gray-900 dark:text-white focus:outline-none focus:border-seismo-orange">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">End Time (local)</label>
|
||||
<input type="datetime-local" id="edit-stopped-at" name="stopped_at"
|
||||
value="{{ session.stopped_at|local_datetime_input if session.stopped_at else '' }}"
|
||||
class="w-full text-sm bg-gray-50 dark:bg-slate-700 border border-gray-200 dark:border-gray-600 rounded-lg px-3 py-2 text-gray-900 dark:text-white focus:outline-none focus:border-seismo-orange">
|
||||
</div>
|
||||
<div class="flex gap-2 pt-1">
|
||||
|
||||
<div class="flex gap-2">
|
||||
<button type="submit"
|
||||
class="flex-1 text-sm py-2 bg-seismo-orange text-white rounded-lg hover:bg-orange-600 transition-colors font-medium">
|
||||
Save Changes
|
||||
</button>
|
||||
<button type="button" onclick="fillPeriodDefaults()"
|
||||
class="text-sm py-2 px-3 border border-gray-200 dark:border-gray-600 rounded-lg text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-slate-700 transition-colors"
|
||||
title="Fill default hours for selected period type">
|
||||
Defaults
|
||||
</button>
|
||||
</div>
|
||||
<div id="save-status" class="hidden text-xs text-center pt-1"></div>
|
||||
<div id="save-status" class="hidden text-xs text-center pt-2"></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -307,8 +354,23 @@ function fillPeriodDefaults() {
|
||||
document.getElementById('edit-start-hour').value = defaults.start;
|
||||
document.getElementById('edit-end-hour').value = defaults.end;
|
||||
}
|
||||
updateWindowPreview();
|
||||
}
|
||||
|
||||
function updateWindowPreview() {
|
||||
const sh = parseInt(document.getElementById('edit-start-hour').value, 10);
|
||||
const eh = parseInt(document.getElementById('edit-end-hour').value, 10);
|
||||
const el = document.getElementById('window-preview');
|
||||
if (!el) return;
|
||||
if (isNaN(sh) || isNaN(eh)) { el.textContent = ''; return; }
|
||||
function fmt(h) { return `${h % 12 || 12}:00 ${h < 12 ? 'AM' : 'PM'}`; }
|
||||
const crosses = eh <= sh;
|
||||
el.textContent = `Window: ${fmt(sh)} → ${fmt(eh)}${crosses ? ' (crosses midnight)' : ''}`;
|
||||
}
|
||||
|
||||
// Run once on load to populate preview if values already set
|
||||
document.addEventListener('DOMContentLoaded', updateWindowPreview);
|
||||
|
||||
async function saveSession(e) {
|
||||
e.preventDefault();
|
||||
const status = document.getElementById('save-status');
|
||||
@@ -330,6 +392,9 @@ async function saveSession(e) {
|
||||
payload.period_start_hour = sh !== '' ? parseInt(sh, 10) : null;
|
||||
payload.period_end_hour = eh !== '' ? parseInt(eh, 10) : null;
|
||||
|
||||
const rd = form.report_date.value;
|
||||
payload.report_date = rd || null;
|
||||
|
||||
const sa = form.started_at.value;
|
||||
if (sa) payload.started_at = sa;
|
||||
|
||||
@@ -354,6 +419,7 @@ async function saveSession(e) {
|
||||
weekday_day: 'Weekday Day', weekday_night: 'Weekday Night',
|
||||
weekend_day: 'Weekend Day', weekend_night: 'Weekend Night'
|
||||
}[result.period_type] || '—';
|
||||
document.getElementById('info-report-date').textContent = result.report_date || '— (auto)';
|
||||
|
||||
status.className = 'text-xs text-center pt-1 text-green-600 dark:text-green-400';
|
||||
status.textContent = 'Saved!';
|
||||
|
||||
Reference in New Issue
Block a user