- Fix UTC display bug: upload_nrl_data now wraps RNH datetimes with
local_to_utc() before storing, matching patch_session behavior.
Period type and label are derived from local time before conversion.
- Add period_start_hour / period_end_hour to MonitoringSession model
(nullable integers 0–23). Migration: migrate_add_session_period_hours.py
- Update patch_session to accept and store period_start_hour / period_end_hour.
Response now includes both fields.
- Update get_project_sessions to compute "Effective: M/D H:MM AM → M/D H:MM AM"
string from period hours and pass it to session_list.html.
- Rework period edit UI in session_list.html: clicking the period badge now
opens an inline editor with period type selector + start/end hour inputs.
Selecting a period type pre-fills default hours (Day: 7–19, Night: 19–7).
- Wire period hours into _build_location_data_from_sessions: uses
period_start/end_hour when set, falls back to hardcoded defaults.
- RND viewer: inject SESSION_PERIOD_START/END_HOUR from template context.
renderTable() dims rows outside the period window (opacity-40) with a
tooltip; shows "(N in period window)" in the row count.
- New session detail page at /api/projects/{id}/sessions/{id}/detail:
shows breadcrumb, files list with View/Download/Report actions,
editable session info form (label, period type, hours, times).
- Add local_datetime_input Jinja filter for datetime-local input values.
- Monthly calendar view: new get_sessions_calendar endpoint returns
sessions_calendar.html partial; added below sessions list in detail.html.
Color-coded per NRL with legend, HTMX prev/next navigation, session dots
link to detail page.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
91 lines
2.7 KiB
Python
91 lines
2.7 KiB
Python
"""
|
|
Shared Jinja2 templates configuration.
|
|
|
|
All routers should import `templates` from this module to get consistent
|
|
filter and global function registration.
|
|
"""
|
|
|
|
import json as _json
|
|
from fastapi.templating import Jinja2Templates
|
|
|
|
# Import timezone utilities
|
|
from backend.utils.timezone import (
|
|
format_local_datetime, format_local_time,
|
|
get_user_timezone, get_timezone_abbreviation
|
|
)
|
|
|
|
|
|
def jinja_local_datetime(dt, fmt="%Y-%m-%d %H:%M"):
|
|
"""Jinja filter to convert UTC datetime to local timezone."""
|
|
return format_local_datetime(dt, fmt)
|
|
|
|
|
|
def jinja_local_time(dt):
|
|
"""Jinja filter to format time in local timezone."""
|
|
return format_local_time(dt)
|
|
|
|
|
|
def jinja_timezone_abbr():
|
|
"""Jinja global to get current timezone abbreviation."""
|
|
return get_timezone_abbreviation()
|
|
|
|
|
|
# Create templates instance
|
|
templates = Jinja2Templates(directory="templates")
|
|
|
|
def jinja_local_date(dt, fmt="%m-%d-%y"):
|
|
"""Jinja filter: format a UTC datetime as a local date string (e.g. 02-19-26)."""
|
|
return format_local_datetime(dt, fmt)
|
|
|
|
|
|
def jinja_fromjson(s):
|
|
"""Jinja filter: parse a JSON string into a dict (returns {} on failure)."""
|
|
if not s:
|
|
return {}
|
|
try:
|
|
return _json.loads(s)
|
|
except Exception:
|
|
return {}
|
|
|
|
|
|
def jinja_same_date(dt1, dt2) -> bool:
|
|
"""Jinja global: True if two datetimes fall on the same local date."""
|
|
if not dt1 or not dt2:
|
|
return False
|
|
try:
|
|
d1 = format_local_datetime(dt1, "%Y-%m-%d")
|
|
d2 = format_local_datetime(dt2, "%Y-%m-%d")
|
|
return d1 == d2
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def jinja_log_tail_display(s):
|
|
"""Jinja filter: decode a JSON-encoded log tail array into a plain-text string."""
|
|
if not s:
|
|
return ""
|
|
try:
|
|
lines = _json.loads(s)
|
|
if isinstance(lines, list):
|
|
return "\n".join(str(l) for l in lines)
|
|
return str(s)
|
|
except Exception:
|
|
return str(s)
|
|
|
|
|
|
def jinja_local_datetime_input(dt):
|
|
"""Jinja filter: format UTC datetime as local YYYY-MM-DDTHH:MM for <input type='datetime-local'>."""
|
|
return format_local_datetime(dt, "%Y-%m-%dT%H:%M")
|
|
|
|
|
|
# Register Jinja filters and globals
|
|
templates.env.filters["local_datetime"] = jinja_local_datetime
|
|
templates.env.filters["local_time"] = jinja_local_time
|
|
templates.env.filters["local_date"] = jinja_local_date
|
|
templates.env.filters["local_datetime_input"] = jinja_local_datetime_input
|
|
templates.env.filters["fromjson"] = jinja_fromjson
|
|
templates.env.globals["timezone_abbr"] = jinja_timezone_abbr
|
|
templates.env.globals["get_user_timezone"] = get_user_timezone
|
|
templates.env.globals["same_date"] = jinja_same_date
|
|
templates.env.filters["log_tail_display"] = jinja_log_tail_display
|