feat(post-form): reverse-geocode City/Country + drop hero-image field
Get Location now reverse-geocodes the captured coordinates into City + Country via BigDataCloud's free client endpoint, filling only blank fields (never clobbering a manual entry) and appending the resolved place to the location status. Best-effort — a failure leaves the coordinates intact. Removes the redundant hero_image field: journal entries render their hero from the first uploaded photo (entry-journal uses entry.media.images|first), so an explicit hero filename served no purpose. Stories still use hero_image but are not posted through this form. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -129,15 +129,11 @@ form:
|
|||||||
'car': '🚗 Car'
|
'car': '🚗 Car'
|
||||||
'plane': '✈️ Plane'
|
'plane': '✈️ Plane'
|
||||||
|
|
||||||
# Advanced fields — collapsed behind "More options" (see U5)
|
# Advanced fields — collapsed behind "More options" (see U5).
|
||||||
-
|
# No hero_image field: journal entries render their hero from the first
|
||||||
name: hero_image
|
# uploaded photo (entry-journal.html.twig uses entry.media.images|first),
|
||||||
label: Hero Image Filename
|
# so an explicit hero filename was redundant. Stories still use hero_image
|
||||||
type: text
|
# but they aren't posted through this form.
|
||||||
classes: advanced-field
|
|
||||||
placeholder: 'photo.jpg'
|
|
||||||
help: 'Filename of the hero/header image. Leave blank to use the first uploaded photo.'
|
|
||||||
|
|
||||||
-
|
-
|
||||||
name: force_connect
|
name: force_connect
|
||||||
label: Force connector line
|
label: Force connector line
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -290,8 +290,8 @@ function field(name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ── "More options" disclosure (U5, KTD5) ─────────────────────
|
/* ── "More options" disclosure (U5, KTD5) ─────────────────────
|
||||||
* The blueprint renders the advanced trio (hero_image/force_connect/featured)
|
* The blueprint renders the advanced fields (force_connect/featured) flat;
|
||||||
* flat; here we relocate their .form-field wrappers into a native <details> so
|
* here we relocate their .form-field wrappers into a native <details> so
|
||||||
* they collapse by default with full keyboard/AT support. Auto-opens if any
|
* they collapse by default with full keyboard/AT support. Auto-opens if any
|
||||||
* advanced field already carries a value (edit / draft restore).
|
* advanced field already carries a value (edit / draft restore).
|
||||||
*/
|
*/
|
||||||
@@ -370,6 +370,33 @@ function initGeo() {
|
|||||||
}
|
}
|
||||||
syncWeatherEnabled();
|
syncWeatherEnabled();
|
||||||
|
|
||||||
|
// Reverse-geocode the captured coordinates into City + Country via
|
||||||
|
// BigDataCloud's free client endpoint (no API key, CORS-enabled). Only
|
||||||
|
// fills fields the traveller left blank — never clobbers a manual entry —
|
||||||
|
// and appends the resolved place to the location status. Best-effort: a
|
||||||
|
// failure leaves the coordinates (and the manual city/country fields) intact.
|
||||||
|
function reverseGeocode(lat, lng) {
|
||||||
|
var cityEl = field('location_city');
|
||||||
|
var countryEl = field('location_country');
|
||||||
|
// Nothing to fill if the traveller already typed both.
|
||||||
|
if ((!cityEl || cityEl.value.trim()) && (!countryEl || countryEl.value.trim())) return;
|
||||||
|
|
||||||
|
var url = 'https://api.bigdatacloud.net/data/reverse-geocode-client?latitude=' +
|
||||||
|
encodeURIComponent(lat) + '&longitude=' + encodeURIComponent(lng) + '&localityLanguage=en';
|
||||||
|
fetch(url).then(function (r) { return r.json(); }).then(function (data) {
|
||||||
|
// BigDataCloud's `city` is often empty in rural areas; `locality`
|
||||||
|
// is the more reliably-populated place name, so fall back to it.
|
||||||
|
var city = (data.city || data.locality || '').trim();
|
||||||
|
var country = (data.countryName || '').trim();
|
||||||
|
if (cityEl && !cityEl.value.trim() && city) cityEl.value = city;
|
||||||
|
if (countryEl && !countryEl.value.trim() && country) countryEl.value = country;
|
||||||
|
var place = [city, country].filter(Boolean).join(', ');
|
||||||
|
if (place) {
|
||||||
|
setStatus(locStatus, '✓ Location captured · ' + place, 'ok');
|
||||||
|
}
|
||||||
|
}).catch(function () { /* keep the coordinates-only status */ });
|
||||||
|
}
|
||||||
|
|
||||||
if (locBtn) {
|
if (locBtn) {
|
||||||
locBtn.addEventListener('click', function () {
|
locBtn.addEventListener('click', function () {
|
||||||
if (!navigator.geolocation) {
|
if (!navigator.geolocation) {
|
||||||
@@ -390,6 +417,7 @@ function initGeo() {
|
|||||||
locBtn.disabled = false;
|
locBtn.disabled = false;
|
||||||
setStatus(locStatus, '✓ Location captured · ' + lat + ', ' + lng, 'ok');
|
setStatus(locStatus, '✓ Location captured · ' + lat + ', ' + lng, 'ok');
|
||||||
syncWeatherEnabled();
|
syncWeatherEnabled();
|
||||||
|
reverseGeocode(lat, lng); // fill City/Country in the background
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
locBtn.classList.remove('is-loading');
|
locBtn.classList.remove('is-loading');
|
||||||
locBtn.disabled = false;
|
locBtn.disabled = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user