Compare commits

...

7 Commits

Author SHA1 Message Date
Matt Walsh
407da90f8a 6.2.5 2025-10-21 04:15:53 +00:00
Matt Walsh
3a0e6aa345 Merge branch 'geolookup-latlongquery' 2025-10-21 04:15:38 +00:00
Matt Walsh
650dda7b61 allow for latLon only in query string #154 2025-10-21 04:12:21 +00:00
Matt Walsh
8f1e8ffb74 Merge branch 'rmitchellscott-static-redirect-index' 2025-10-21 03:26:25 +00:00
Mitchell Scott
93af84cbd8 fix: geolookup if only latLonQuery is provided 2025-10-20 13:37:18 -06:00
Mitchell Scott
117f66e9d0 fix(static builds): duplicate query params 2025-10-20 13:28:45 -06:00
Mitchell Scott
bca9376edc fix: nginx query parameter redirect works like node.js 2025-10-20 11:42:42 -06:00
5 changed files with 82 additions and 9 deletions

View File

@@ -10,8 +10,10 @@ server {
add_header X-Weatherstar true always; add_header X-Weatherstar true always;
include /etc/nginx/includes/wsqs_redirect.conf;
location / { location / {
index redirect.html index.html index.htm; index index.html index.htm;
try_files $uri $uri/ =404; try_files $uri $uri/ =404;
} }

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "ws4kp", "name": "ws4kp",
"version": "6.2.4", "version": "6.2.5",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ws4kp", "name": "ws4kp",
"version": "6.2.4", "version": "6.2.5",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"dotenv": "^17.0.1", "dotenv": "^17.0.1",

View File

@@ -1,6 +1,6 @@
{ {
"name": "ws4kp", "name": "ws4kp",
"version": "6.2.4", "version": "6.2.5",
"description": "Welcome to the WeatherStar 4000+ project page!", "description": "Welcome to the WeatherStar 4000+ project page!",
"main": "index.mjs", "main": "index.mjs",
"type": "module", "type": "module",

View File

@@ -106,17 +106,34 @@ const init = async () => {
// attempt to parse the url parameters // attempt to parse the url parameters
const parsedParameters = parseQueryString(); const parsedParameters = parseQueryString();
const loadFromParsed = parsedParameters.latLonQuery && parsedParameters.latLon; const loadFromParsed = !!parsedParameters.latLon;
// Auto load the parsed parameters and fall back to the previous query // Auto load the parsed parameters and fall back to the previous query
const query = parsedParameters.latLonQuery ?? localStorage.getItem('latLonQuery'); const query = parsedParameters.latLonQuery ?? localStorage.getItem('latLonQuery');
const latLon = parsedParameters.latLon ?? localStorage.getItem('latLon'); const latLon = parsedParameters.latLon ?? localStorage.getItem('latLon');
const fromGPS = localStorage.getItem('latLonFromGPS') && !loadFromParsed; const fromGPS = localStorage.getItem('latLonFromGPS') && !loadFromParsed;
if (query && latLon && !fromGPS) { if (parsedParameters.latLonQuery && !parsedParameters.latLon) {
const txtAddress = document.querySelector(TXT_ADDRESS_SELECTOR); const txtAddress = document.querySelector(TXT_ADDRESS_SELECTOR);
txtAddress.value = query; txtAddress.value = parsedParameters.latLonQuery;
loadData(JSON.parse(latLon)); const geometry = await geocodeLatLonQuery(parsedParameters.latLonQuery);
if (geometry) {
doRedirectToGeometry(geometry);
}
} else if (latLon && !fromGPS) {
// update in-page search box if using cached data, or parsed parameter
if ((query && !loadFromParsed) || (parsedParameters.latLonQuery && loadFromParsed)) {
const txtAddress = document.querySelector(TXT_ADDRESS_SELECTOR);
txtAddress.value = query;
}
// use lat-long lookup if that's all that was provided in the query string
if (loadFromParsed && parsedParameters.latLon && !parsedParameters.latLonQuery) {
const { lat, lon } = JSON.parse(latLon);
getForecastFromLatLon(lat, lon, true);
} else {
// otherwise use pre-stored data
loadData(JSON.parse(latLon));
}
} }
if (fromGPS) { if (fromGPS) {
btnGetGpsClick(); btnGetGpsClick();
@@ -162,6 +179,26 @@ const init = async () => {
document.querySelector('#container').addEventListener('swiped-right', () => swipeCallBack('right')); document.querySelector('#container').addEventListener('swiped-right', () => swipeCallBack('right'));
}; };
const geocodeLatLonQuery = async (query) => {
try {
const data = await json('https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find', {
data: {
text: query,
f: 'json',
},
});
const loc = data.locations?.[0];
if (loc) {
return loc.feature.geometry;
}
return null;
} catch (error) {
console.error('Geocoding failed:', error);
return null;
}
};
const autocompleteOnSelect = async (suggestion) => { const autocompleteOnSelect = async (suggestion) => {
// Note: it's fine that this uses json instead of safeJson since it's infrequent and user-initiated // Note: it's fine that this uses json instead of safeJson since it's infrequent and user-initiated
const data = await json('https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find', { const data = await json('https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find', {

View File

@@ -12,6 +12,9 @@ url_encode() {
# build query string from WSQS_ env vars # build query string from WSQS_ env vars
while IFS='=' read -r key val; do while IFS='=' read -r key val; do
# Skip empty lines
[ -z "$key" ] && continue
# Remove WSQS_ prefix and convert underscores to hyphens # Remove WSQS_ prefix and convert underscores to hyphens
key="${key#WSQS_}" key="${key#WSQS_}"
key="${key//_/-}" key="${key//_/-}"
@@ -23,11 +26,16 @@ while IFS='=' read -r key val; do
QS="${key}=${encoded_val}" QS="${key}=${encoded_val}"
fi fi
done << EOF done << EOF
$(env | grep '^WSQS_') $(env | grep '^WSQS_' || true)
EOF EOF
mkdir -p /etc/nginx/includes
if [ -n "$QS" ]; then if [ -n "$QS" ]; then
# Escape the query string for use in JavaScript (escape backslashes and single quotes)
QS_ESCAPED=$(printf '%s' "$QS" | sed "s/\\\\/\\\\\\\\/g; s/'/\\\'/g")
# Generate redirect.html with JavaScript logic
cat > "$ROOT/redirect.html" <<EOF cat > "$ROOT/redirect.html" <<EOF
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
@@ -35,10 +43,36 @@ if [ -n "$QS" ]; then
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>Redirecting</title> <title>Redirecting</title>
<meta http-equiv="refresh" content="0;url=/index.html?$QS" /> <meta http-equiv="refresh" content="0;url=/index.html?$QS" />
<script>
(function() {
var wsqsParams = '$QS_ESCAPED';
var currentParams = window.location.search.substring(1);
var targetParams = currentParams || wsqsParams;
window.location.replace('/index.html?' + targetParams);
})();
</script>
</head> </head>
<body></body> <body></body>
</html> </html>
EOF EOF
# Generate nginx config for conditional redirects
cat > /etc/nginx/includes/wsqs_redirect.conf <<'EOF'
location = / {
if ($args = '') {
rewrite ^ /redirect.html last;
}
rewrite ^/$ /index.html?$args? redirect;
}
location = /index.html {
if ($args = '') {
rewrite ^ /redirect.html last;
}
}
EOF
else
touch /etc/nginx/includes/wsqs_redirect.conf
fi fi
exec nginx -g 'daemon off;' exec nginx -g 'daemon off;'