6 Commits

5 changed files with 93 additions and 6 deletions

View File

@@ -5,6 +5,60 @@ All notable changes to Terra-View will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.7.0] - 2026-03-07
### Added
- **Project Status Management**: Projects can now be placed `on_hold` or `archived`, with automatic cancellation of pending scheduled actions
- **Hard Delete Projects**: Support for permanently deleting projects, in addition to soft-delete with auto-pruning
- **Vibration Location Detail**: New dedicated template for vibration project location detail views
- **Vibration Project Isolation**: Vibration projects no longer show SLM-specific project tabs
- **Manual SD Card Data Upload**: Upload offline NRL data directly from SD card via ZIP or multi-file select
- Accepts `.rnd`/`.rnh` files; parses `.rnh` metadata for session start/stop times, serial number, and store name
- Creates `MonitoringSession` and `DataFile` records automatically; no unit assignment required
- Upload panel on NRL detail Data Files tab with inline feedback and auto-refresh via HTMX
- **Standalone SLM Type**: New SLM device mode that operates without a modem (direct IP connection)
- **NL32 Data Support**: Report generator and web viewer now support NL32 measurement data format
- **Combined Report Wizard**: Multi-session combined Excel report generation tool
- Wizard UI grouped by location with period type badges (day/night)
- Each selected session produces one `.xlsx` in a ZIP archive
- Period type filtering: day sessions keep last calendar date (7AM6:59PM); night sessions span both days (7PM6:59AM)
- **Combined Report Preview**: Interactive spreadsheet-style preview before generating combined reports
- **Chart Preview**: Live chart preview in the report generator matching final report styling
- **SLM Model Schemas**: Per-model configuration schemas for NL32, NL43, NL53 devices
- **Data Collection Mode**: Projects now store a data collection mode field with UI controls and migration
### Changed
- **MonitoringSession rename**: `RecordingSession` renamed to `MonitoringSession` throughout codebase; DB table renamed from `recording_sessions` to `monitoring_sessions`
- Migration: `backend/migrate_rename_recording_to_monitoring_sessions.py`
- **Combined Report Split Logic**: Separate days now generate separate `.xlsx` files; NRLs remain one per sheet
- **Mass Upload Parsing**: Smarter file filtering — no longer imports unneeded Lp files or `.xlsx` files
- **SLM Start Time Grace Period**: 15-minute grace window added so data starting at session start time is included
- **NL32 Date Parsing**: Date now read from `start_time` field instead of file metadata
- **Project Data Labels**: Improved Jinja filters and UI label clarity for project data views
### Fixed
- **Dev/Prod Separation**: Dev server now uses Docker Compose override; production deployment no longer affected by dev config
- **SLM Modal**: Bench/deploy toggle now correctly shown in SLM unit modal
- **Auto-Downloaded Files**: Files downloaded by scheduler now appear in project file listings
- **Duplicate Download**: Removed duplicate file download that occurred following a scheduled stop
- **SLMM Environment Variables**: `TCP_IDLE_TTL` and `TCP_MAX_AGE` now correctly passed to SLMM service via docker-compose
### Technical Details
- `session_label` and `period_type` stored on `monitoring_sessions` table (migration: `migrate_add_session_period_type.py`)
- `device_model` stored on `monitoring_sessions` table (migration: `migrate_add_session_device_model.py`)
- Upload endpoint: `POST /api/projects/{project_id}/nrl/{location_id}/upload-data`
- ZIP filename format: `{session_label}_{project_name}_report.xlsx` (label first)
### Migration Notes
Run the following migration scripts once per database before deploying:
```bash
python backend/migrate_rename_recording_to_monitoring_sessions.py
python backend/migrate_add_session_period_type.py
python backend/migrate_add_session_device_model.py
```
---
## [0.6.1] - 2026-02-16
### Added
@@ -445,6 +499,7 @@ No database migration required for v0.4.0. All new features use existing databas
- Photo management per unit
- Automated status categorization (OK/Pending/Missing)
[0.7.0]: https://github.com/serversdwn/seismo-fleet-manager/compare/v0.6.1...v0.7.0
[0.6.0]: https://github.com/serversdwn/seismo-fleet-manager/compare/v0.5.1...v0.6.0
[0.5.1]: https://github.com/serversdwn/seismo-fleet-manager/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/serversdwn/seismo-fleet-manager/compare/v0.4.4...v0.5.0

View File

@@ -1,4 +1,4 @@
# Terra-View v0.6.1
# Terra-View v0.7.0
Backend API and HTMX-powered web interface for managing a mixed fleet of seismographs and field modems. Track deployments, monitor health in real time, merge roster intent with incoming telemetry, and control your fleet through a unified database and dashboard.
## Features
@@ -496,6 +496,16 @@ docker compose down -v
## Release Highlights
### v0.7.0 — 2026-03-07
- **Project Status Management**: On-hold and archived project states with automatic cancellation of pending actions
- **Manual SD Card Upload**: Upload offline NRL/SLM data directly from SD card (ZIP or multi-file); auto-creates monitoring sessions from `.rnh` metadata
- **Combined Report Wizard**: Multi-session Excel report generation with location grouping, period type filtering, and ZIP download
- **NL32 Support**: Report generator and web viewer now handle NL32 measurement data
- **Chart Preview**: Live chart preview in the report generator matching final output styling
- **Standalone SLM Mode**: SLMs can now be configured without a paired modem (direct IP)
- **Vibration Project Isolation**: Vibration project views no longer show SLM-specific tabs
- **MonitoringSession Rename**: `RecordingSession` renamed to `MonitoringSession` throughout; run migration before deploying
### v0.6.1 — 2026-02-16
- **One-Off Recording Schedules**: Schedule single recordings with specific start/end datetimes
- **Bidirectional Pairing Sync**: Device-modem pairing now updates both sides automatically
@@ -584,11 +594,13 @@ MIT
## Version
**Current: 0.6.1**One-off recording schedules, bidirectional pairing sync, scheduler timezone fix (2026-02-16)
**Current: 0.7.0**Project status management, manual SD card upload, combined report wizard, NL32 support, MonitoringSession rename (2026-03-07)
Previous: 0.6.0Calendar & reservation mode, device pairing interface, calibration UX overhaul, modem dashboard enhancements (2026-02-06)
Previous: 0.6.1One-off recording schedules, bidirectional pairing sync, scheduler timezone fix (2026-02-16)
Previous: 0.5.1 — Dashboard schedule view with today's actions panel, new Terra-View branding and logo rework (2026-01-27)
0.6.0 — Calendar & reservation mode, device pairing interface, calibration UX overhaul, modem dashboard enhancements (2026-02-06)
0.5.1 — Dashboard schedule view with today's actions panel, new Terra-View branding and logo rework (2026-01-27)
0.4.4 — Recurring schedules, alerting UI, report templates + RND viewer, and SLM workflow polish (2026-01-23)

View File

@@ -30,7 +30,7 @@ Base.metadata.create_all(bind=engine)
ENVIRONMENT = os.getenv("ENVIRONMENT", "production")
# Initialize FastAPI app
VERSION = "0.6.1"
VERSION = "0.7.0"
if ENVIRONMENT == "development":
_build = os.getenv("BUILD_NUMBER", "0")
if _build and _build != "0":

View File

@@ -2038,6 +2038,7 @@ async def generate_excel_report(
import openpyxl
from openpyxl.chart import LineChart, Reference
from openpyxl.chart.label import DataLabelList
from openpyxl.chart.shapes import GraphicalProperties
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
from openpyxl.utils import get_column_letter
except ImportError:
@@ -2340,6 +2341,10 @@ async def generate_excel_report(
chart.series[2].graphicalProperties.line.solidFill = "0070C0"
chart.series[2].graphicalProperties.line.width = 19050
_plot_border = GraphicalProperties()
_plot_border.ln.solidFill = "000000"
_plot_border.ln.w = 12700
chart.plot_area.spPr = _plot_border
ws.add_chart(chart, "H4")
# --- Stats table: note at I28-I29, headers at I31, data rows 32-34 ---
@@ -2679,6 +2684,7 @@ async def generate_report_from_preview(
try:
import openpyxl
from openpyxl.chart import LineChart, Reference
from openpyxl.chart.shapes import GraphicalProperties
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
from openpyxl.utils import get_column_letter
except ImportError:
@@ -2821,6 +2827,10 @@ async def generate_report_from_preview(
chart.series[1].graphicalProperties.line.width = 19050
chart.series[2].graphicalProperties.line.solidFill = "0070C0"
chart.series[2].graphicalProperties.line.width = 19050
_plot_border = GraphicalProperties()
_plot_border.ln.solidFill = "000000"
_plot_border.ln.w = 12700
chart.plot_area.spPr = _plot_border
ws.add_chart(chart, "H4")
# --- Stats block starting at I28 ---
@@ -2957,6 +2967,7 @@ async def generate_combined_excel_report(
try:
import openpyxl
from openpyxl.chart import LineChart, Reference
from openpyxl.chart.shapes import GraphicalProperties
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
from openpyxl.utils import get_column_letter
except ImportError:
@@ -3163,6 +3174,10 @@ async def generate_combined_excel_report(
chart.series[2].graphicalProperties.line.solidFill = "0070C0"
chart.series[2].graphicalProperties.line.width = 19050
_plot_border = GraphicalProperties()
_plot_border.ln.solidFill = "000000"
_plot_border.ln.w = 12700
chart.plot_area.spPr = _plot_border
ws.add_chart(chart, "H4")
# Stats table: note at I28-I29, headers at I31, data rows 32-34, border row 35
@@ -3569,6 +3584,7 @@ async def generate_combined_from_preview(
try:
import openpyxl
from openpyxl.chart import LineChart, Reference
from openpyxl.chart.shapes import GraphicalProperties
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
from openpyxl.utils import get_column_letter
from openpyxl.worksheet.properties import PageSetupProperties
@@ -3736,6 +3752,10 @@ async def generate_combined_from_preview(
chart.series[2].graphicalProperties.line.solidFill = "0070C0"
chart.series[2].graphicalProperties.line.width = 19050
_plot_border = GraphicalProperties()
_plot_border.ln.solidFill = "000000"
_plot_border.ln.w = 12700
chart.plot_area.spPr = _plot_border
ws.add_chart(chart, "H4")
hdr_fill_tbl = PatternFill(start_color="F2F2F2", end_color="F2F2F2", fill_type="solid")

View File

@@ -75,7 +75,7 @@
</div>
<!-- Sessions Card -->
<div class="bg-white dark:bg-slate-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-6">
<div class="bg-white dark:bg-slate-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-6 overflow-hidden">
<div class="flex items-center justify-between mb-1">
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">Monitoring Sessions</h2>
<div class="flex gap-3 text-sm">