Compare commits
6 Commits
86010de60c
...
v0.7.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 1dd396acd8 | |||
| e89a04f58c | |||
| e4ef065db8 | |||
| b15d434fce | |||
| 7b4e12c127 | |||
| 742a98a8ed |
55
CHANGELOG.md
55
CHANGELOG.md
@@ -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/),
|
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).
|
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 (7AM–6:59PM); night sessions span both days (7PM–6: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
|
## [0.6.1] - 2026-02-16
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
@@ -445,6 +499,7 @@ No database migration required for v0.4.0. All new features use existing databas
|
|||||||
- Photo management per unit
|
- Photo management per unit
|
||||||
- Automated status categorization (OK/Pending/Missing)
|
- 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.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.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
|
[0.5.0]: https://github.com/serversdwn/seismo-fleet-manager/compare/v0.4.4...v0.5.0
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -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.
|
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
|
## Features
|
||||||
@@ -496,6 +496,16 @@ docker compose down -v
|
|||||||
|
|
||||||
## Release Highlights
|
## 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
|
### v0.6.1 — 2026-02-16
|
||||||
- **One-Off Recording Schedules**: Schedule single recordings with specific start/end datetimes
|
- **One-Off Recording Schedules**: Schedule single recordings with specific start/end datetimes
|
||||||
- **Bidirectional Pairing Sync**: Device-modem pairing now updates both sides automatically
|
- **Bidirectional Pairing Sync**: Device-modem pairing now updates both sides automatically
|
||||||
@@ -584,11 +594,13 @@ MIT
|
|||||||
|
|
||||||
## Version
|
## 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.0 — Calendar & reservation mode, device pairing interface, calibration UX overhaul, modem dashboard enhancements (2026-02-06)
|
Previous: 0.6.1 — One-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)
|
0.4.4 — Recurring schedules, alerting UI, report templates + RND viewer, and SLM workflow polish (2026-01-23)
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Base.metadata.create_all(bind=engine)
|
|||||||
ENVIRONMENT = os.getenv("ENVIRONMENT", "production")
|
ENVIRONMENT = os.getenv("ENVIRONMENT", "production")
|
||||||
|
|
||||||
# Initialize FastAPI app
|
# Initialize FastAPI app
|
||||||
VERSION = "0.6.1"
|
VERSION = "0.7.0"
|
||||||
if ENVIRONMENT == "development":
|
if ENVIRONMENT == "development":
|
||||||
_build = os.getenv("BUILD_NUMBER", "0")
|
_build = os.getenv("BUILD_NUMBER", "0")
|
||||||
if _build and _build != "0":
|
if _build and _build != "0":
|
||||||
|
|||||||
@@ -2038,6 +2038,7 @@ async def generate_excel_report(
|
|||||||
import openpyxl
|
import openpyxl
|
||||||
from openpyxl.chart import LineChart, Reference
|
from openpyxl.chart import LineChart, Reference
|
||||||
from openpyxl.chart.label import DataLabelList
|
from openpyxl.chart.label import DataLabelList
|
||||||
|
from openpyxl.chart.shapes import GraphicalProperties
|
||||||
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
|
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
|
||||||
from openpyxl.utils import get_column_letter
|
from openpyxl.utils import get_column_letter
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -2340,6 +2341,10 @@ async def generate_excel_report(
|
|||||||
chart.series[2].graphicalProperties.line.solidFill = "0070C0"
|
chart.series[2].graphicalProperties.line.solidFill = "0070C0"
|
||||||
chart.series[2].graphicalProperties.line.width = 19050
|
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")
|
ws.add_chart(chart, "H4")
|
||||||
|
|
||||||
# --- Stats table: note at I28-I29, headers at I31, data rows 32-34 ---
|
# --- Stats table: note at I28-I29, headers at I31, data rows 32-34 ---
|
||||||
@@ -2679,6 +2684,7 @@ async def generate_report_from_preview(
|
|||||||
try:
|
try:
|
||||||
import openpyxl
|
import openpyxl
|
||||||
from openpyxl.chart import LineChart, Reference
|
from openpyxl.chart import LineChart, Reference
|
||||||
|
from openpyxl.chart.shapes import GraphicalProperties
|
||||||
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
|
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
|
||||||
from openpyxl.utils import get_column_letter
|
from openpyxl.utils import get_column_letter
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -2821,6 +2827,10 @@ async def generate_report_from_preview(
|
|||||||
chart.series[1].graphicalProperties.line.width = 19050
|
chart.series[1].graphicalProperties.line.width = 19050
|
||||||
chart.series[2].graphicalProperties.line.solidFill = "0070C0"
|
chart.series[2].graphicalProperties.line.solidFill = "0070C0"
|
||||||
chart.series[2].graphicalProperties.line.width = 19050
|
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")
|
ws.add_chart(chart, "H4")
|
||||||
|
|
||||||
# --- Stats block starting at I28 ---
|
# --- Stats block starting at I28 ---
|
||||||
@@ -2957,6 +2967,7 @@ async def generate_combined_excel_report(
|
|||||||
try:
|
try:
|
||||||
import openpyxl
|
import openpyxl
|
||||||
from openpyxl.chart import LineChart, Reference
|
from openpyxl.chart import LineChart, Reference
|
||||||
|
from openpyxl.chart.shapes import GraphicalProperties
|
||||||
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
|
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
|
||||||
from openpyxl.utils import get_column_letter
|
from openpyxl.utils import get_column_letter
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -3163,6 +3174,10 @@ async def generate_combined_excel_report(
|
|||||||
chart.series[2].graphicalProperties.line.solidFill = "0070C0"
|
chart.series[2].graphicalProperties.line.solidFill = "0070C0"
|
||||||
chart.series[2].graphicalProperties.line.width = 19050
|
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")
|
ws.add_chart(chart, "H4")
|
||||||
|
|
||||||
# Stats table: note at I28-I29, headers at I31, data rows 32-34, border row 35
|
# 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:
|
try:
|
||||||
import openpyxl
|
import openpyxl
|
||||||
from openpyxl.chart import LineChart, Reference
|
from openpyxl.chart import LineChart, Reference
|
||||||
|
from openpyxl.chart.shapes import GraphicalProperties
|
||||||
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
|
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
|
||||||
from openpyxl.utils import get_column_letter
|
from openpyxl.utils import get_column_letter
|
||||||
from openpyxl.worksheet.properties import PageSetupProperties
|
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.solidFill = "0070C0"
|
||||||
chart.series[2].graphicalProperties.line.width = 19050
|
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")
|
ws.add_chart(chart, "H4")
|
||||||
|
|
||||||
hdr_fill_tbl = PatternFill(start_color="F2F2F2", end_color="F2F2F2", fill_type="solid")
|
hdr_fill_tbl = PatternFill(start_color="F2F2F2", end_color="F2F2F2", fill_type="solid")
|
||||||
|
|||||||
@@ -75,7 +75,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Sessions Card -->
|
<!-- 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">
|
<div class="flex items-center justify-between mb-1">
|
||||||
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">Monitoring Sessions</h2>
|
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">Monitoring Sessions</h2>
|
||||||
<div class="flex gap-3 text-sm">
|
<div class="flex gap-3 text-sm">
|
||||||
|
|||||||
Reference in New Issue
Block a user