Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Omnibus #577

Merged
merged 2 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 30 additions & 15 deletions htdocs/json/vtec_events.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
"""Listing of VTEC events for a WFO and year"""
import datetime
import json
from io import BytesIO, StringIO

import pandas as pd
from pyiem.util import get_dbconnc, html_escape, utc
from pyiem.webutil import iemapp
from pymemcache.client import Client

ISO9660 = "%Y-%m-%dT%H:%M:%SZ"
EXL = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"


def run(wfo, year, phenomena, significance, combo):
def get_res(wfo, year, phenomena, significance, combo):
"""Generate a report of VTEC ETNs used for a WFO and year

Args:
Expand Down Expand Up @@ -95,7 +97,7 @@ def run(wfo, year, phenomena, significance, combo):
)
)
pgconn.close()
return json.dumps(res)
return res


@iemapp()
Expand All @@ -119,21 +121,34 @@ def application(environ, start_response):
cb = environ.get("callback")
combo = int(environ.get("combo", 0))

mckey = (
f"/json/vtec_events/{wfo}/{year}/{phenomena}/{significance}/{combo}"
)
mc = Client("iem-memcached:11211")
res = mc.get(mckey)
if not res:
res = run(wfo, year, phenomena, significance, combo)
mc.set(mckey, res, 60)
else:
res = res.decode("utf-8")
mc.close()
fmt = environ.get("fmt", "json")
res = get_res(wfo, year, phenomena, significance, combo)

if fmt == "xlsx":
fn = f"vtec_{wfo}_{year}_{phenomena}_{significance}.xlsx"
headers = [
("Content-type", EXL),
("Content-disposition", f"attachment; Filename={fn}"),
]
start_response("200 OK", headers)
bio = BytesIO()
pd.DataFrame(res["events"]).to_excel(bio, index=False)
return [bio.getvalue()]
if fmt == "csv":
fn = f"vtec_{wfo}_{year}_{phenomena}_{significance}.csv"
headers = [
("Content-type", "application/octet-stream"),
("Content-disposition", f"attachment; Filename={fn}"),
]
start_response("200 OK", headers)
bio = StringIO()
pd.DataFrame(res["events"]).to_csv(bio, index=False)
return [bio.getvalue().encode("utf-8")]

res = json.dumps(res)
if cb is not None:
res = f"{html_escape(cb)}({res})"

headers = [("Content-type", "application/json")]
start_response("200 OK", headers)
return [res.encode("utf-8")]
return [res.encode("ascii")]
45 changes: 28 additions & 17 deletions htdocs/json/vtec_events_bystate.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
"""Listing of VTEC events for state and year"""
import json
from io import BytesIO, StringIO

import pandas as pd
from pyiem.util import get_dbconnc, html_escape
from pyiem.webutil import iemapp
from pymemcache.client import Client

ISO9660 = "%Y-%m-%dT%H:%M:%SZ"
EXL = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"


def run(state, year, phenomena, significance):
def get_res(state, year, phenomena, significance):
"""Generate a report of VTEC ETNs used for a WFO and year

Args:
Expand Down Expand Up @@ -82,7 +84,7 @@ def run(state, year, phenomena, significance):
)
)
pgconn.close()
return json.dumps(res)
return res


@iemapp()
Expand All @@ -93,22 +95,31 @@ def application(environ, start_response):
phenomena = environ.get("phenomena", "__")[:2]
significance = environ.get("significance", "_")[:1]
cb = environ.get("callback")
fmt = environ.get("fmt", "json")
res = get_res(state, year, phenomena, significance)

mckey = "/json/vtec_events_bystate/%s/%s/%s/%s" % (
state,
year,
phenomena,
significance,
)
mc = Client("iem-memcached:11211")
res = mc.get(mckey)
if not res:
res = run(state, year, phenomena, significance)
mc.set(mckey, res, 60)
else:
res = res.decode("utf-8")
mc.close()
if fmt == "xlsx":
fn = f"vtec_{state}_{year}_{phenomena}_{significance}.xlsx"
headers = [
("Content-type", EXL),
("Content-disposition", f"attachment; Filename={fn}"),
]
start_response("200 OK", headers)
bio = BytesIO()
pd.DataFrame(res["events"]).to_excel(bio, index=False)
return [bio.getvalue()]
if fmt == "csv":
fn = f"vtec_{state}_{year}_{phenomena}_{significance}.csv"
headers = [
("Content-type", "application/octet-stream"),
("Content-disposition", f"attachment; Filename={fn}"),
]
start_response("200 OK", headers)
bio = StringIO()
pd.DataFrame(res["events"]).to_csv(bio, index=False)
return [bio.getvalue().encode("utf-8")]

res = json.dumps(res)
if cb is not None:
res = f"{html_escape(cb)}({res})"

Expand Down
116 changes: 114 additions & 2 deletions htdocs/vtec/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ let mapwidget1 = null;
let mapwidget2 = null;
let table1 = null;
let table2 = null;
let table3 = null;
let table2IsByPoint = true;
let hashlinkUGC = null;
let edate = null;
Expand All @@ -13,6 +14,8 @@ let sdate1 = null;
const BACKEND_EVENTS_BYPOINT = '/json/vtec_events_bypoint.py';
const BACKEND_EVENTS_BYUGC = '/json/vtec_events_byugc.py';
const BACKEND_SBW_BYPOINT = '/json/sbw_by_point.py';
const BACKEND_EVENTS = "/json/vtec_events.py";
const BACKEND_EVENTS_BYSTATE = "/json/vtec_events_bystate.py";

const states = [["AL", "Alabama"], ["AK", "Alaska"], ["AZ", "Arizona"],
["AR", "Arkansas"], ["CA", "California"], ["CO", "Colorado"],
Expand Down Expand Up @@ -156,12 +159,46 @@ function updateTable2ByPoint(){
});
}

function updateTable3(){
// get currently selected by3 radio button
const by = text($("input[name='by3']:checked").val());
const datum = (by == "state") ? text(stateSelect.val()) : text($("#wfo3").val());
const year = text($("#year3").val());
const ph = text($("#ph3").val());
const sig = text($("#sig3").val());
window.location.href = `#list/${by}/${datum}/${year}/${ph}/${sig}`;
Fixed Show fixed Hide fixed
$("#table3title").text(`Events for ${by} ${datum} in ${year}`);
// Do what we need to for table 3
$.ajax({
data: {
wfo: $("#wfo3").val(),
state: stateSelect.val(),
year: year,
phenomena: ph,
significance: sig
},
url: (by == "wfo") ? BACKEND_EVENTS: BACKEND_EVENTS_BYSTATE,
dataType: "json",
method: "GET",
success: (data) => {
table3.clear();
$.map(data.events, (row) => {
const uri = `<a href="${row.uri}" target="_blank">${row.phenomena}.${row.significance}.${row.eventid}</a>`;
table3.row.add(
[uri, row.wfo, row.locations, row.issue, row.expire]);
});
table3.draw();
}
});
}


function buildUI(){
// Export Buttons
$(".iemtool").click(function(){ // this
const btn = $(this);
let url = BACKEND_SBW_BYPOINT;
const params = {
var params = {
fmt: (btn.data("opt") == "csv") ? "csv" : "xlsx",
lat: $("#lat").val(),
lon: $("#lon").val(),
Expand All @@ -179,6 +216,18 @@ function buildUI(){
params.lat = $("#lat2").val();
}
}
if (btn.data("table") == "3"){
const by = $("input[name='by3']:checked").val();
url = (by == "state") ? BACKEND_EVENTS_BYSTATE: BACKEND_EVENTS;
params = {
fmt: (btn.data("opt") == "csv") ? "csv" : "xlsx",
wfo: $("#wfo3").val(),
state: stateSelect.val(),
year: $("#year3").val(),
phenomena: $("#ph3").val(),
significance: $("#sig3").val()
};
}
window.location = `${url}?${$.param(params)}`;
});
// Tables
Expand All @@ -192,6 +241,11 @@ function buildUI(){
"emptyTable": "Drag marker on map or select UGC to auto-populate this table"
}
});
table3 = $("#table3").DataTable({
"language": {
"emptyTable": "Select options to auto-populate this table"
}
});
// Date pickers
sdate = $("input[name='sdate']").datepicker({
dateFormat:"mm/dd/yy",
Expand Down Expand Up @@ -300,7 +354,46 @@ function buildUI(){
mapwidget2.marker.setPosition(latlng);
updateMarkerPosition2(lo, la);
});

$("#button3").click(() => {
updateTable3();
});
// Populate wfos select with iemdata.wfos data
const wfos = $.map(iemdata.wfos, (obj) => {
const ee = {};
ee.id = obj[0];
ee.text = `[${obj[0]}] ${obj[1]}`;
return ee;
});
$("select[name='wfo']").select2({
placeholder: "Select a WFO",
data: wfos
});
const ph = $.map(iemdata.vtec_phenomena, (obj) => {
const ee = {};
ee.id = obj[0];
ee.text = obj[1];
return ee;
});
$("select[name='ph']").select2({
placeholder: "Select a Phenomena",
data: ph
});
const sig = $.map(iemdata.vtec_significance, (obj) => {
const ee = {};
ee.id = obj[0];
ee.text = obj[1];
return ee;
});
$("select[name='sig']").select2({
placeholder: "Select a Phenomena",
data: sig
});
// populate year3 select with values from 1986 to current year
const year3 = $("select[name='year']");
const currentYear = new Date().getFullYear();
for (let i = 1986; i <= currentYear; i++){
year3.append(new Option(i, i, false, false));
}
};

function _load() {
Expand Down Expand Up @@ -340,6 +433,25 @@ function _load() {
updateMarkerPosition2(default_lon, default_lat);
}
}
if (tokens2.length == 6){
const aTag = $("a[name='list']");
$('html,body').animate({scrollTop: aTag.offset().top},'slow');
const by = text(tokens2[1]);
const datum = text(tokens2[2]);
const year = text(tokens2[3]);
const ph = text(tokens2[4]);
const sig = text(tokens2[5]);
$("input[name='by3'][value='"+by+"']").prop("checked", true);
$("#year3").val(year);
$("#ph3").val(ph);
$("#sig3").val(sig);
if (by == "state"){
stateSelect.val(datum).trigger("change");
} else {
$("#wfo3").val(datum);
}
updateTable3();
}
}

mapwidget1 = new MapMarkerWidget("map", default_lon, default_lat);
Expand Down
50 changes: 47 additions & 3 deletions htdocs/vtec/search.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
<script src="/vendor/jquery-datatables/1.10.20/datatables.min.js"></script>
<script src="/vendor/jquery-ui/1.11.4/jquery-ui.js"></script>
<script src="/vendor/select2/4.1.0rc0/select2.min.js"></script>
<script type="text/javascript" src="search.js?v=5"></script>
<script type="text/javascript" src="wfos.js"></script>
<script type="text/javascript" src="search.js?v=6"></script>
<script src="https://maps.googleapis.com/maps/api/js?key={$gmapskey}&callback=_load" type="text/javascript"></script>
EOF;
$t->headextra = <<<EOF
Expand All @@ -36,8 +37,9 @@
<ul>
<li><a href="#bypoint">1. Search for Storm Based Warnings by Point</a></li>
<li><a href="#byugc">2. Search of Watch/Warning/Advisories by County/Zone or by Point</a></li>
<li><a href="#list">3. List Watch/Warning/Advisories by State/WFO by Year</a></li>
</ul>

<h3><a name="bypoint">1.</a> Search for Storm Based Warnings by Point</h3>

<br />The official warned area for some products the NWS issues is a polygon.
Expand Down Expand Up @@ -138,6 +140,48 @@
</div>
</div><!-- ./row -->
</form><!-- ./form2 -->


<br clear="all" />
<h3><a name="list">3.</a> List NWS Watch/Warning/Advisories by State/WFO by Year</h3>
<br />
<p>This section generates a simple list of NWS Watch, Warning, and Advisories
by state and year.</p>
<br />

<form id="form3">
<div class="row">
<div class="col-md-4">
<input type="radio" name="by3" value="state" checked="checked" id="bystate"/>
<label for="bystate">Select By State</label>
<br /><select name="state" style="width: 100%" id="state3"></select></p>

<p><input type="radio" name="by3" value="wfo" id="bywfo"/>
<label for="bywfo">Select By WFO</label>
<br /><select name="wfo" style="width: 100%" id="wfo3"></select></p>

<p><label for="ph3">Select VTEC Phenomena:</label>
<select name="ph" style="width: 100%" id="ph3"></select></p>

<p><label for="sig3">Select VTEC Significance:</label>
<select name="sig" style="width: 100%" id="sig3"></select></p>

<p><label for="year3">Select Year:</label>
<select name="year" style="width: 100%" id="year3"></select></p>

<br /><button type="button" class="btn btn-default" id="button3">Update Table</button>
</div>
<div class="col-md-8">
<h4 id="table3title"></h4>
<button type="button" data-table="3" data-opt="excel" class="btn btn-default iemtool"><i class="fa fa-download"></i> Export to Excel...</button>
<button type="button" data-table="3" data-opt="csv" class="btn btn-default iemtool"><i class="fa fa-download"></i> Export to CSV...</button>

<table id="table3" data-order='[[ 3, "desc" ]]'>
<thead>
<tr><th>Event</th><th>WFO</th><th>Locations</th><th>Issued</th>
<th>Expired</th></tr></thead>
</table>
</div>
</div><!-- ./row -->
</form><!-- ./form3 -->
EOF;
$t->render('full.phtml');
Loading