1af5a94f57
UI for the pending-deployment workflow (commits 2 + 3 from the plan,
landed together since commit 1 already shipped the full backend).
New surfaces
- /deploy — mobile-first 3-step wizard. Pick unit → take photo (uses
<input capture="environment"> so it opens the phone camera) → add
optional note + submit. EXIF GPS auto-extracted on the server.
Success page shows the captured coords + links to either "Deploy
another" or "View pending hopper." Whole flow is meant to take
under 90 seconds on site.
- /tools/pending-deployments — the hopper. Filter pills: Awaiting /
Assigned / Cancelled. Each card shows photo thumbnail, unit serial
link, captured-at timestamp, coordinates, operator note, and
status-appropriate actions.
- Classify modal on the hopper: two modes — "Assign to existing
location" (project + location pickers, scoped to vibration_monitoring)
or "Create new location" (with new-or-existing project, plus a
"use captured coords" checkbox that writes the pending row's coords
onto the new location). Calls /pending/{id}/promote on submit.
- Cancel button uses prompt() for the optional reason → POSTs to
/pending/{id}/cancel.
Backend additions
- GET /api/deployments/seismograph-picker — JSON list of non-retired
seismograph units for the /deploy unit picker. Annotates each unit
with has_pending so the picker can flag units that already have a
pending capture waiting.
Discovery
- New "Field Deploy" + "Pending Deployments" cards on /tools.
- Dashboard banner: auto-shows when there are awaiting captures,
polled every 30s. Hides when count drops to 0. Click → /tools/
pending-deployments.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
166 lines
10 KiB
HTML
166 lines
10 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Tools - Seismo Fleet Manager{% endblock %}
|
|
|
|
{% block content %}
|
|
<!-- Header -->
|
|
<div class="mb-8">
|
|
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">Tools</h1>
|
|
<p class="text-gray-600 dark:text-gray-400 mt-1">
|
|
Active operator workflows. Pair devices, clean up duplicates, generate reports.
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Card grid -->
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
|
|
<!-- Field Deploy (mobile-first) -->
|
|
<a href="/deploy"
|
|
class="block bg-white dark:bg-slate-800 rounded-xl shadow-lg p-5 hover:shadow-xl transition-shadow border border-transparent hover:border-seismo-orange">
|
|
<div class="flex items-start gap-3">
|
|
<div class="w-10 h-10 rounded-lg bg-orange-100 dark:bg-orange-900/30 text-seismo-orange flex items-center justify-center shrink-0">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"/>
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1 min-w-0">
|
|
<h3 class="font-semibold text-gray-900 dark:text-white">Field Deploy</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">
|
|
On site? Pick a unit, snap an install photo, leave. GPS is auto-captured. Classify the project/location later from a desk.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- Pending Deployments (the hopper) -->
|
|
<a href="/tools/pending-deployments"
|
|
class="block bg-white dark:bg-slate-800 rounded-xl shadow-lg p-5 hover:shadow-xl transition-shadow border border-transparent hover:border-seismo-orange">
|
|
<div class="flex items-start gap-3">
|
|
<div class="w-10 h-10 rounded-lg bg-amber-100 dark:bg-amber-900/30 text-amber-600 dark:text-amber-400 flex items-center justify-center shrink-0">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1 min-w-0">
|
|
<h3 class="font-semibold text-gray-900 dark:text-white">Pending Deployments</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">
|
|
Field captures waiting to be classified into a project + location.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- Pair Devices -->
|
|
<a href="/pair-devices"
|
|
class="block bg-white dark:bg-slate-800 rounded-xl shadow-lg p-5 hover:shadow-xl transition-shadow border border-transparent hover:border-seismo-orange">
|
|
<div class="flex items-start gap-3">
|
|
<div class="w-10 h-10 rounded-lg bg-orange-100 dark:bg-orange-900/30 text-seismo-orange flex items-center justify-center shrink-0">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/>
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1 min-w-0">
|
|
<h3 class="font-semibold text-gray-900 dark:text-white">Pair Devices</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">
|
|
Bidirectionally link seismographs ↔ modems (or SLMs ↔ modems) so they ship out together as a deployed pair.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- Project Tidy -->
|
|
<a href="/settings/developer/project-tidy"
|
|
class="block bg-white dark:bg-slate-800 rounded-xl shadow-lg p-5 hover:shadow-xl transition-shadow border border-transparent hover:border-seismo-orange">
|
|
<div class="flex items-start gap-3">
|
|
<div class="w-10 h-10 rounded-lg bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 flex items-center justify-center shrink-0">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14-4H5m14 8H5m14 4H5"/>
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1 min-w-0">
|
|
<h3 class="font-semibold text-gray-900 dark:text-white">Project Tidy</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">
|
|
Find duplicate-looking projects via fuzzy name match (typos, abbreviations) and bulk-merge them. Useful after a metadata backfill run.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- Metadata Backfill -->
|
|
<a href="/settings/developer/metadata-backfill"
|
|
class="block bg-white dark:bg-slate-800 rounded-xl shadow-lg p-5 hover:shadow-xl transition-shadow border border-transparent hover:border-seismo-orange">
|
|
<div class="flex items-start gap-3">
|
|
<div class="w-10 h-10 rounded-lg bg-purple-100 dark:bg-purple-900/30 text-purple-600 dark:text-purple-400 flex items-center justify-center shrink-0">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"/>
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1 min-w-0">
|
|
<h3 class="font-semibold text-gray-900 dark:text-white">Backfill from event metadata</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">
|
|
Auto-create projects, locations, and unit assignments from the operator-typed metadata baked into SFM events. Skip the manual entry.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- Deployment History -->
|
|
<a href="/tools/deployment-history"
|
|
class="block bg-white dark:bg-slate-800 rounded-xl shadow-lg p-5 hover:shadow-xl transition-shadow border border-transparent hover:border-seismo-orange">
|
|
<div class="flex items-start gap-3">
|
|
<div class="w-10 h-10 rounded-lg bg-indigo-100 dark:bg-indigo-900/30 text-indigo-600 dark:text-indigo-400 flex items-center justify-center shrink-0">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1 min-w-0">
|
|
<h3 class="font-semibold text-gray-900 dark:text-white">Deployment History</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">
|
|
12-month calendar of every unit assignment across every project. Visual bars per project per day; click a day for the full active-deployments list.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- Reports (per-project) -->
|
|
<a href="/projects"
|
|
class="block bg-white dark:bg-slate-800 rounded-xl shadow-lg p-5 hover:shadow-xl transition-shadow border border-transparent hover:border-seismo-orange">
|
|
<div class="flex items-start gap-3">
|
|
<div class="w-10 h-10 rounded-lg bg-emerald-100 dark:bg-emerald-900/30 text-emerald-600 dark:text-emerald-400 flex items-center justify-center shrink-0">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1 min-w-0">
|
|
<h3 class="font-semibold text-gray-900 dark:text-white">Reports</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">
|
|
Excel report generation lives on each project's detail page. Open a project and use <em>Generate Combined Report</em> (for multi-location sound studies) or single-location export.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- Swap Detection (Phase 5c — coming soon) -->
|
|
<div class="bg-gray-50 dark:bg-slate-800/50 rounded-xl shadow p-5 border border-dashed border-gray-300 dark:border-gray-700 cursor-not-allowed">
|
|
<div class="flex items-start gap-3">
|
|
<div class="w-10 h-10 rounded-lg bg-gray-200 dark:bg-gray-700 text-gray-400 flex items-center justify-center shrink-0">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4"/>
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1 min-w-0">
|
|
<div class="flex items-center gap-2 mb-1">
|
|
<h3 class="font-semibold text-gray-500 dark:text-gray-400">Swap Detection</h3>
|
|
<span class="px-1.5 py-0.5 rounded text-xs bg-gray-200 dark:bg-gray-700 text-gray-500 dark:text-gray-400">soon</span>
|
|
</div>
|
|
<p class="text-sm text-gray-500 dark:text-gray-500">
|
|
Daily background job that auto-detects unit swaps in the field (BE12345 → BE67890 at the same project + location) from operator-typed metadata. Coming in Phase 5c.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
{% endblock %}
|