Files
giglez/templates/index.html
T
Trilltechnician d84aded40b feat: Implement heatmap visualization for device density
- Add Leaflet.heat plugin (leaflet-heat.js)
- Create renderHeatmap() function with confidence-based intensity
- Toggle between markers and heatmap view
- Support frequency filtering in heatmap mode
- Custom gradient: blue -> cyan -> lime -> yellow -> red
- Configurable radius (25px), blur (15px), and maxZoom (17)
- Console logging for debugging heatmap rendering
- Intensity based on device match confidence (0.5 default)
2026-01-14 11:04:54 -08:00

297 lines
13 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GigLez - IoT RF Device Mapping Platform</title>
<!-- Leaflet CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.Default.css" />
<!-- Custom CSS -->
<link rel="stylesheet" href="/static/css/main.css">
</head>
<body>
<!-- Header -->
<header>
<div class="container">
<div class="logo">
<h1>🛰️ GigLez</h1>
<p>IoT RF Device Mapping Platform</p>
</div>
<nav>
<a href="#map" class="nav-link active">Map</a>
<a href="#upload" class="nav-link">Upload</a>
<a href="#search" class="nav-link">Search</a>
<a href="#stats" class="nav-link">Statistics</a>
<a href="/docs" class="nav-link" target="_blank">API Docs</a>
</nav>
</div>
</header>
<!-- Main Content -->
<main>
<!-- Map View -->
<section id="map-section" class="section active">
<div class="map-controls">
<div class="control-group">
<label>
<input type="checkbox" id="cluster-toggle" checked>
Cluster Markers
</label>
<label>
<input type="checkbox" id="heatmap-toggle">
Heatmap View
</label>
</div>
<div class="control-group">
<label>Filter by Frequency:</label>
<select id="frequency-filter">
<option value="">All Frequencies</option>
<option value="315">315 MHz</option>
<option value="433">433 MHz</option>
<option value="868">868 MHz</option>
<option value="915">915 MHz</option>
</select>
</div>
<div class="stats-summary">
<span>Total Captures: <strong id="total-captures">0</strong></span>
<span>Unique Devices: <strong id="unique-devices">0</strong></span>
</div>
</div>
<div id="map"></div>
</section>
<!-- Upload View -->
<section id="upload-section" class="section">
<div class="container">
<h2>Upload RF Captures</h2>
<p class="subtitle">Upload .sub files with GPS coordinates from your wardriving session</p>
<!-- Upload Form -->
<div class="upload-container">
<!-- Drop Zone -->
<div id="drop-zone" class="drop-zone">
<div class="drop-zone-content">
<svg class="upload-icon" width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="17 8 12 3 7 8"></polyline>
<line x1="12" y1="3" x2="12" y2="15"></line>
</svg>
<h3>Drop .sub files here</h3>
<p>or click to browse</p>
<button type="button" class="btn btn-primary" onclick="document.getElementById('file-input').click()">
Select Files
</button>
<input type="file" id="file-input" multiple accept=".sub" style="display: none;">
</div>
</div>
<!-- GPS Manifest Form -->
<div class="manifest-form">
<h3>GPS Coordinates</h3>
<p>Provide GPS data for your captures</p>
<div class="form-group">
<label>Session UUID (optional)</label>
<input type="text" id="session-uuid" placeholder="Auto-generated if not provided">
</div>
<div class="form-group">
<label>Default GPS Coordinates</label>
<div class="gps-inputs">
<input type="number" id="default-lat" placeholder="Latitude" step="0.000001" min="-90" max="90">
<input type="number" id="default-lon" placeholder="Longitude" step="0.000001" min="-180" max="180">
</div>
<small>Applied to all files. Individual coordinates can be set below.</small>
</div>
<div class="form-group">
<label>GPS Accuracy (meters)</label>
<input type="number" id="default-accuracy" placeholder="5.0" step="0.1" min="0" value="5.0">
</div>
<div class="form-group">
<label>Altitude (meters)</label>
<input type="number" id="default-altitude" placeholder="Optional" step="0.1">
</div>
<button type="button" class="btn btn-secondary" onclick="useCurrentLocation()">
Use Current Location
</button>
</div>
<!-- File List -->
<div id="file-list" class="file-list" style="display: none;">
<h3>Files to Upload</h3>
<div id="files-container"></div>
<div class="upload-actions">
<button type="button" class="btn btn-primary btn-large" onclick="uploadFiles()">
Upload All Files
</button>
<button type="button" class="btn btn-secondary" onclick="clearFiles()">
Clear All
</button>
</div>
</div>
<!-- Upload Progress -->
<div id="upload-progress" class="upload-progress" style="display: none;">
<h3>Uploading...</h3>
<div class="progress-bar">
<div class="progress-fill" id="progress-fill"></div>
</div>
<p id="progress-text">Preparing upload...</p>
</div>
<!-- Upload Results -->
<div id="upload-results" class="upload-results" style="display: none;">
<h3>Upload Complete</h3>
<div id="results-container"></div>
<button type="button" class="btn btn-primary" onclick="resetUpload()">
Upload More Files
</button>
</div>
</div>
</div>
</section>
<!-- Search View -->
<section id="search-section" class="section">
<div class="container">
<h2>Search Captures</h2>
<div class="search-form">
<div class="form-group">
<label>Search Query</label>
<input type="text" id="search-query" placeholder="Device name, protocol, or frequency">
</div>
<div class="form-row">
<div class="form-group">
<label>Frequency (MHz)</label>
<select id="search-frequency">
<option value="">All</option>
<option value="315">315</option>
<option value="433">433</option>
<option value="868">868</option>
<option value="915">915</option>
</select>
</div>
<div class="form-group">
<label>Protocol</label>
<select id="search-protocol">
<option value="">All</option>
<option value="RAW">RAW</option>
<option value="Princeton">Princeton</option>
<option value="KeeLoq">KeeLoq</option>
<option value="MegaCode">MegaCode</option>
</select>
</div>
<div class="form-group">
<label>Date Range</label>
<input type="date" id="search-date-start">
<input type="date" id="search-date-end">
</div>
</div>
<div class="form-group">
<label>Geographic Search</label>
<div class="gps-inputs">
<input type="number" id="search-lat" placeholder="Latitude" step="0.000001">
<input type="number" id="search-lon" placeholder="Longitude" step="0.000001">
<input type="number" id="search-radius" placeholder="Radius (km)" step="0.1" min="0.1">
</div>
</div>
<button type="button" class="btn btn-primary" onclick="searchCaptures()">
Search
</button>
</div>
<div id="search-results" class="search-results" style="display: none;">
<h3>Search Results</h3>
<div id="results-list"></div>
</div>
</div>
</section>
<!-- Statistics View -->
<section id="stats-section" class="section">
<div class="container">
<h2>Platform Statistics</h2>
<div class="stats-grid">
<div class="stat-card">
<h3>Total Captures</h3>
<p class="stat-value" id="stat-captures">-</p>
</div>
<div class="stat-card">
<h3>Unique Devices</h3>
<p class="stat-value" id="stat-devices">-</p>
</div>
<div class="stat-card">
<h3>Coverage Area</h3>
<p class="stat-value" id="stat-coverage">-</p>
</div>
<div class="stat-card">
<h3>Contributors</h3>
<p class="stat-value" id="stat-contributors">-</p>
</div>
</div>
<div class="chart-container">
<h3>Frequency Distribution</h3>
<canvas id="frequency-chart"></canvas>
</div>
<div class="chart-container">
<h3>Captures Over Time</h3>
<canvas id="timeline-chart"></canvas>
</div>
</div>
</section>
</main>
<!-- Capture Detail Modal -->
<div id="detail-modal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h2>Capture Details</h2>
<button id="modal-close-btn" class="modal-close">&times;</button>
</div>
<div class="modal-body" id="modal-body-content">
<!-- Content loaded dynamically -->
</div>
</div>
</div>
<!-- Footer -->
<footer>
<div class="container">
<p>&copy; 2026 GigLez - IoT RF Device Mapping Platform</p>
<p>Wigle for Sub-GHz Signals</p>
</div>
</footer>
<!-- Leaflet JS -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.markercluster@1.5.3/dist/leaflet.markercluster.js"></script>
<script src="https://unpkg.com/leaflet.heat@0.2.0/dist/leaflet-heat.js"></script>
<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
<!-- Custom JS -->
<script src="/static/js/detail-modal.js"></script>
<script src="/static/js/map.js"></script>
<script src="/static/js/upload.js"></script>
<script src="/static/js/search.js"></script>
<script src="/static/js/stats.js"></script>
<script src="/static/js/main.js"></script>
</body>
</html>