204 lines
10 KiB
HTML
204 lines
10 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>NWS VTEC Browser</title>
|
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
|
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
|
|
<link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/smoothness/jquery-ui.css">
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.8.0/dist/leaflet.css" integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9+580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ==" crossorigin="" />
|
|
<script src="https://unpkg.com/leaflet@1.8.0/dist/leaflet.js" integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ==" crossorigin=""></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@^2.0.0/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@6.5.0/turf.min.js"></script>
|
|
<!-- CSS -->
|
|
<style type="text/css">
|
|
body, html {
|
|
height: 100%; width: 100%; margin: 0; padding: 0; font-family: sans-serif;
|
|
}
|
|
#container {
|
|
display: flex; height: 100%; width: 100%;
|
|
}
|
|
#map-container {
|
|
flex-grow: 1; height: 100%; display: flex; flex-direction: column;
|
|
}
|
|
#mapid {
|
|
flex-grow: 1; width: 100%; z-index: 1;
|
|
}
|
|
#summary-container {
|
|
height: 60%; /* Adjust map/summary ratio (higher % = smaller map) */
|
|
overflow-y: auto; padding: 15px; background: #f9f9f9;
|
|
border-top: 1px solid #ddd; line-height: 1.4; box-sizing: border-box;
|
|
}
|
|
#summary-container img {
|
|
max-width: calc(100% - 450px); height: auto; border: 1px solid #ccc; margin-top: 10px;
|
|
margin-bottom: 10px; display: block;
|
|
}
|
|
#summary-container h2 {
|
|
margin-top: 0; margin-bottom: 10px; padding-bottom: 5px; border-bottom: 2px solid #ccc;
|
|
}
|
|
#summary-container h3 {
|
|
margin-top: 18px; margin-bottom: 8px; padding-bottom: 3px; border-bottom: 1px solid #eee;
|
|
}
|
|
#summary-container h4 { margin-top: 10px; margin-bottom: 5px; }
|
|
#summary-container p { margin-top: 0.5em; margin-bottom: 0.5em; }
|
|
#summary-container ul { margin-top: 0.5em; padding-left: 25px; }
|
|
#summary-container li { margin-bottom: 0.4em; }
|
|
#summary-container .gauge-summary { margin-bottom: 20px; border-top: 1px solid #eee; padding-top: 10px; }
|
|
#summary-container .event-summary-item { border-left-width: 5px; border-left-style: solid; padding-left: 10px; margin-bottom: 15px; }
|
|
#copySummaryBtn {
|
|
float: right; margin-bottom: 10px; padding: 5px 10px; cursor: pointer; border: 1px solid #ccc;
|
|
background-color: #f0f0f0; border-radius: 3px; font-size: 0.9em;
|
|
}
|
|
#copySummaryBtn:hover { background-color: #e0e0e0; }
|
|
#controls {
|
|
width: 400px; /* Set the desired width */
|
|
flex-shrink: 0; /* Prevent the item from shrinking */
|
|
padding: 10px;
|
|
background: #f0f0f0;
|
|
overflow-y: auto;
|
|
border-right: 1px solid #ccc;
|
|
z-index: 1000;
|
|
display: flex;
|
|
flex-direction: column;
|
|
box-sizing: border-box;
|
|
}
|
|
#controls label, #controls select, #controls input[type=number], #controls input[type=text], #controls input[type=button] {
|
|
display: block;
|
|
margin-bottom: 8px;
|
|
width: 100%; /* Make controls fill width */
|
|
box-sizing: border-box;
|
|
}
|
|
#controls select[multiple] {
|
|
height: 250px;
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
}
|
|
/* Leaflet Layer Styling */
|
|
.my-label { /* County Labels */
|
|
font-size: 8px; font-weight: bold; color: #333; background-color: rgba(255, 255, 255, 0.7);
|
|
border: 0px; border-radius: 3px; padding: 1px 3px; white-space: nowrap; pointer-events: none;
|
|
}
|
|
.leaflet-tooltip { /* Optional overrides for base tooltip */ }
|
|
.lsr-label-tooltip {
|
|
font-size: 9px !important; font-weight: bold !important; color: black !important; white-space: nowrap;
|
|
background: transparent !important; border: none !important; box-shadow: none !important;
|
|
padding: 0 !important; margin: 0 !important; display: inline-block; text-align: center;
|
|
vertical-align: middle; pointer-events: none;
|
|
}
|
|
/* Hide the template canvas */
|
|
#hydrograph-canvas-template { display: none; }
|
|
#summary-container ul.analysis-list {
|
|
margin-top: 0; /* Remove extra space above list */
|
|
padding-left: 25px; /* Keep indentation */
|
|
list-style-type: disc; /* Or desired bullet style */
|
|
}
|
|
/* Style for the per-zone verification list */
|
|
#summary-container .zone-verification-list {
|
|
margin-top: 0; /* Remove extra space above list */
|
|
padding-left: 25px; /* Keep indentation */
|
|
list-style-type: disc; /* Or desired bullet style */
|
|
font-size: 0.9em; /* Match other sub-details */
|
|
}
|
|
#summary-container .zone-verification-list li {
|
|
margin-bottom: 0.2em; /* Smaller spacing between zones */
|
|
}
|
|
/* Style for export buttons */
|
|
#export-controls {
|
|
margin-top: 15px;
|
|
border-top: 1px solid #ccc;
|
|
padding-top: 10px;
|
|
}
|
|
#export-controls h3 {
|
|
margin-bottom: 5px;
|
|
}
|
|
#export-controls input[type=button] {
|
|
background-color: #e7e7e7;
|
|
border: 1px solid #ccc;
|
|
padding: 6px 12px;
|
|
cursor: pointer;
|
|
margin-top: 5px; /* Space between buttons */
|
|
}
|
|
#export-controls input[type=button]:hover {
|
|
background-color: #d7d7d7;
|
|
}
|
|
#export-controls input[type=button]:disabled {
|
|
background-color: #f5f5f5;
|
|
color: #aaa;
|
|
cursor: not-allowed;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="container">
|
|
<div id="controls">
|
|
<h3>Select Products</h3>
|
|
<label for="yeartowork">Choose a year:</label>
|
|
<select name="yeartowork" id="yeartowork" onchange="getwwas()">
|
|
<option value="2025">2025</option>
|
|
<option value="2024">2024</option>
|
|
<option value="2023">2023</option>
|
|
<option value="2022">2022</option>
|
|
</select>
|
|
<!-- Event selector added by JS -->
|
|
<label for="eventFilterInput" style="margin-top: 15px;">Filter Events:</label>
|
|
<input type="text" id="eventFilterInput" placeholder="Type to filter list..." />
|
|
<h3>Options</h3>
|
|
<label for="lsrbuffer">Time Buffer for Reports (hrs):</label>
|
|
<input id="lsrbuffer" name="lsrbuffer" type="number" value="1">
|
|
<label for="powerthresh">Power Outage Threshold for Reporting:</label>
|
|
<input id="powerthresh" name="powerthresh" type="number" value="50">
|
|
<input id="generateSummaryBtn" type="button" value="Generate Summary" onclick="generateSummaryForSelectedEvents();" style="margin-top: 15px; font-weight: bold; background-color: #add8e6;" />
|
|
<!-- Export Controls Section -->
|
|
<div id="export-controls">
|
|
<h3>Export Options</h3>
|
|
<input type="button" id="exportLsrCsvBtn" value="Export All Reports (CSV)" onclick="generateLsrCsv();" disabled>
|
|
<input type="button" id="exportKmlBtn" value="Export Products/Reports (KML)" onclick="generateKml();" disabled>
|
|
Note: Reports not from LSRs (power outage, DOT, 911, etc) will be filtered if an LSR has already been issued within 1 mile of them.
|
|
</div>
|
|
</div>
|
|
<div id="map-container">
|
|
<div id="mapid"></div>
|
|
<div id="summary-container">
|
|
<!-- Copy button will be added here by JS in buildHtmlSummary -->
|
|
<p>Select one or more warnings and click "Generate Summary".</p>
|
|
<!-- Summary content will be generated here -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
let mymap;
|
|
let geoJSONwwas; // Layer for selected warning polygons
|
|
let geoJSONcounties; // Layer for county/zone outlines & zone lookup
|
|
let markersLayer; // Layer for LSR markers (Filtered by selected product polygons)
|
|
let gaugeMarkersLayer; // Layer for NWS Gauge markers
|
|
let currentSelectedEvents = []; // Raw event objects selected by the user
|
|
let currentSelectedEventDetails = []; // Detailed info { event, data, fullDetails } for selected events
|
|
let unfilteredLSRs = { type: "FeatureCollection", features: [] }; // Stores ALL LSRs fetched for the time range + buffer
|
|
let hydrographCharts = {}; // Keep track of Chart.js instances if needed (though now generating images directly)
|
|
let prePlotLayer; // Layer for pre-plotting selected warnings
|
|
let eventGeometryCache = {}; // Simple cache for event geometry { 'phen|sig|etn|year': geoJsonData }
|
|
</script>
|
|
<!-- Core helper functions (constants, lookups, LSR verification helpers, contrast colors, status calculations) -->
|
|
<script src="stormdata/core_helpers.js"></script>
|
|
<!-- Utility functions (date formatting, formatting helpers, utility functions) -->
|
|
<script src="stormdata/utility_functions.js"></script>
|
|
<!-- Data fetching functions (fetching from APIs, data retrieval helpers) -->
|
|
<script src="stormdata/data_fetching.js"></script>
|
|
<!-- Parsing functions (NWS product parsing, time string parsing, text parsing) -->
|
|
<script src="stormdata/parsing_functions.js"></script>
|
|
<!-- Analysis functions (hydrograph analysis, LSR processing, data analysis) -->
|
|
<script src="stormdata/analysis_functions.js"></script>
|
|
<!-- Hydro functions (gauge handling, hydrograph generation, water data functions) -->
|
|
<script src="stormdata/hydro_functions.js"></script>
|
|
<!-- Map functions (map setup, styling, Leaflet helpers, marker creation) -->
|
|
<script src="stormdata/map_functions.js"></script>
|
|
<!-- Event handling functions (VTEC event handling, selection, summary generation triggers) -->
|
|
<script src="stormdata/event_handling_functions.js"></script>
|
|
<!-- UI/Summary functions (HTML generation, summary building, export functions) -->
|
|
<script src="stormdata/ui_summary_functions.js"></script>
|
|
<canvas id="hydrograph-canvas-template" width="800" height="450" style="display: none;"></canvas>
|
|
</body>
|
|
</html>
|