{"id":"696adb8f41cdd986d503929d","title":"2026 01 17","path":"how-to/committee/release-notes/2026-01-17","contentMarkdown":"# 17-Jan-2026 — Added reverse geocoding for walks missing locations [ref: #104](https://github.com/nbarrett/ngx-ramblers/issues/104)\n\n## [build 423](https://github.com/nbarrett/ngx-ramblers/actions/runs/21085180136) — [commit 5a382cc](https://github.com/nbarrett/ngx-ramblers/commit/5a382ccd3542ff449a8deb0a3bc1785a49a8c70d)\n\n_____\n\n### Migrations performed\n- Add migration to populate missing locations from lat/lng coordinates\n- Uses postcodes.io reverse geocoding API\n- Also populates grid references, locations, and incorrect end times if missing/invalid\nPurpose: clarify what a Ramblers operator will see/address now that we tightened the “No location details” experience, OS Map styling, and location extraction.\n\n\n### No Location Details filter\n- The advanced search now has a “No location details” checkbox. This checks for  either a `start location` (walks) or  `location` (group events) fields for missing latitude/longitude/postcode/grid references. \n- “No location details”  means that the system cannot render a map for the event,  or showing a pin for this event on a map view. When the checkbox is checked, the filter only matches walks truly lacking coordinates or postcodes.\n- The backend now inspects `postcode` + `lat/lng` and even `grid references(6/8/10)`, so the search criteria that you set in the UI have the same expectations that the renderer (map view) has. Keep in mind the filter still behaves as before on\nthe UI\nside: checking “No location details” hides walks that do not have a postcode or coordinates to show on the map.\n\n\n### Walks admin UX and data safety\n- Walk edit history view was expanded for clearer event context (table layout and field display) so operators can diagnose location or migration changes without digging into raw JSON.\n- WalksAndEventsService now consistently reads/deletes from the local store to avoid cross-population confusion for group walks vs socials.\n- edit-group-event-images now guards against missing fields to avoid failures during edit flows.\n\n\n### Minor extras\n- The location extraction tests now cover “Meet at…” phrasing (e.g., “Meet at Hitchin station”), and the extractor trims parentheses so the start location is stored cleanly.\n- All shared helpers such as entries now live in functions/object-utils.ts, meaning components like AGM stats rely on the same helper and the functions folder is consolidated.\n- You’ll still see the usual build/test warnings about deprecated Sass imports and CommonJS dependencies—they existed before this change and haven’t changed in behavior.\n\n\n### Walk navigation improvements\n- Walk views now shows a “view” button on all walks for members with walk admin privileges. This provides a navigation to a read-only view of all the fields that NGX-Ramblers users see when they use the full \"local\" data population workflow. Of particular interest to this release is that the event history view (`walks/view/<slug>?tab=history`). Data migrations now write events to history to show fields changed. This provides more insight in cases where a migration doesn't have the expected outcome e.g. geocoding failures are recorded here.\n- Walk edit action row now groups copy-link / JSON utilities; input enablement respects view mode and walk write access.\n\n\n### Walk event history improvements\n- Walk edit history rebuilt as an accordion with show/hide per entry.\n- Added field-level change tables with from/to values and targeted change filtering for location/fix events.\n- Added “revert to this version” for local walks with local walk population.\n\n\n### Refactor / code quality improvements\n##### Location extraction is now consistent and DRY\n- The data pipeline now uses the standardized GeocodeMatchType (kebab-case values only) everywhere, including the extracted-location type used in forms/transformations. That removes mismatched string literals and ensures the extractor and UI both understand whether a match\noriginated from a postcode, grid reference, or place name.\n- The “ExtractedLocationType” union now explicitly restricts location fields to GeocodeMatchType.POSTCODE, .GRID_REFERENCE, or .PLACE_NAME. When you paste content into the page-transformation engine or walk editor, the system now enforces that rule, so you won’t accidentally\nstore\nunsupported match types.\n##### OS Map style selection is centralized\n- Instead of hardcoded strings floating around, there is now a single OSMapStyle record with helper flags (is27700, is3857) and a lookup by key. Every map control/service (walk-edit map, walk list map, dynamic-content map, admin map controls, migration editors, etc.) now\nconsults\nthat record.\n- If you switch to a “27700” basemap or the “outdoor” variant, the map controls, export links, and map overlays now all agree because they rely on the same constants and boolean helpers (OSMapStyle.is27700, OSMapStyle.is3857).\n##### Mailchimp batch-subscribe compatibility cleaned up\n- We now mirror the Mailchimp SDK’s Status type exactly (const object plus union type) so the backend can call lists.batchListMembers without type errors and still know which statuses/segments you’re targeting.\n##### Admin/Migration UX polish\n- Migration UI log timestamps now use DateUtils for consistent time values, and the migration history view is presented in a cleaner, more readable table.\n- Migration runner now records startedAt alongside appliedAt so operators can see duration context for each migration attempt.\n- Migrated enums/string unions (map providers, backup/session/status/payloads, markdown list types, route profiles, input sizes, Agm stats/tabs, sorting, migration/page-transformation modes, location/session statuses, etc.) into model files so the frontend and server share the same\ntypes; enums now always use kebab-case values and are used everywhere (e.g., projects/ngx-ramblers/src/app/models/.ts, server/lib/mongo/models/.ts, admin pages, services, migration tools).\n- Replaced the standalone entries helper with a consolidated implementation in projects/ngx-ramblers/src/app/functions/object-utils.ts (also updated to use keys from es-toolkit/compat), then cleaned imports such as agm-stats to reference the new helper.\n- Updated Mailchimp type definitions to export const objects + union types so the backend code now accepts the same shape as the official SDK without introducing new string literals (projects/ngx-ramblers/src/app/models/mailchimp.model.ts, server/lib/mailchimp/lists/lists-batch-\nsubscribe.ts).\n- Maintained DRY through shared model files for backup/session configs and ensured server imports only rely on frontend model definitions (no direct server/lib/... imports from the client).","contentHtml":"<h1>17-Jan-2026 — Added reverse geocoding for walks missing locations <a href=\"https://github.com/nbarrett/ngx-ramblers/issues/104\">ref: #104</a></h1>\n<h2><a href=\"https://github.com/nbarrett/ngx-ramblers/actions/runs/21085180136\">build 423</a> — <a href=\"https://github.com/nbarrett/ngx-ramblers/commit/5a382ccd3542ff449a8deb0a3bc1785a49a8c70d\">commit 5a382cc</a></h2>\n<hr>\n<h3>Migrations performed</h3>\n<ul>\n<li>Add migration to populate missing locations from lat/lng coordinates</li>\n<li>Uses postcodes.io reverse geocoding API</li>\n<li>Also populates grid references, locations, and incorrect end times if missing/invalid\nPurpose: clarify what a Ramblers operator will see/address now that we tightened the “No location details” experience, OS Map styling, and location extraction.</li>\n</ul>\n<h3>No Location Details filter</h3>\n<ul>\n<li>The advanced search now has a “No location details” checkbox. This checks for  either a <code>start location</code> (walks) or  <code>location</code> (group events) fields for missing latitude/longitude/postcode/grid references. </li>\n<li>“No location details”  means that the system cannot render a map for the event,  or showing a pin for this event on a map view. When the checkbox is checked, the filter only matches walks truly lacking coordinates or postcodes.</li>\n<li>The backend now inspects <code>postcode</code> + <code>lat/lng</code> and even <code>grid references(6/8/10)</code>, so the search criteria that you set in the UI have the same expectations that the renderer (map view) has. Keep in mind the filter still behaves as before on\nthe UI\nside: checking “No location details” hides walks that do not have a postcode or coordinates to show on the map.</li>\n</ul>\n<h3>Walks admin UX and data safety</h3>\n<ul>\n<li>Walk edit history view was expanded for clearer event context (table layout and field display) so operators can diagnose location or migration changes without digging into raw JSON.</li>\n<li>WalksAndEventsService now consistently reads/deletes from the local store to avoid cross-population confusion for group walks vs socials.</li>\n<li>edit-group-event-images now guards against missing fields to avoid failures during edit flows.</li>\n</ul>\n<h3>Minor extras</h3>\n<ul>\n<li>The location extraction tests now cover “Meet at…” phrasing (e.g., “Meet at Hitchin station”), and the extractor trims parentheses so the start location is stored cleanly.</li>\n<li>All shared helpers such as entries now live in functions/object-utils.ts, meaning components like AGM stats rely on the same helper and the functions folder is consolidated.</li>\n<li>You’ll still see the usual build/test warnings about deprecated Sass imports and CommonJS dependencies—they existed before this change and haven’t changed in behavior.</li>\n</ul>\n<h3>Walk navigation improvements</h3>\n<ul>\n<li>Walk views now shows a “view” button on all walks for members with walk admin privileges. This provides a navigation to a read-only view of all the fields that NGX-Ramblers users see when they use the full &quot;local&quot; data population workflow. Of particular interest to this release is that the event history view (<code>walks/view/&lt;slug&gt;?tab=history</code>). Data migrations now write events to history to show fields changed. This provides more insight in cases where a migration doesn&#39;t have the expected outcome e.g. geocoding failures are recorded here.</li>\n<li>Walk edit action row now groups copy-link / JSON utilities; input enablement respects view mode and walk write access.</li>\n</ul>\n<h3>Walk event history improvements</h3>\n<ul>\n<li>Walk edit history rebuilt as an accordion with show/hide per entry.</li>\n<li>Added field-level change tables with from/to values and targeted change filtering for location/fix events.</li>\n<li>Added “revert to this version” for local walks with local walk population.</li>\n</ul>\n<h3>Refactor / code quality improvements</h3>\n<h5>Location extraction is now consistent and DRY</h5>\n<ul>\n<li>The data pipeline now uses the standardized GeocodeMatchType (kebab-case values only) everywhere, including the extracted-location type used in forms/transformations. That removes mismatched string literals and ensures the extractor and UI both understand whether a match\noriginated from a postcode, grid reference, or place name.</li>\n<li>The “ExtractedLocationType” union now explicitly restricts location fields to GeocodeMatchType.POSTCODE, .GRID_REFERENCE, or .PLACE_NAME. When you paste content into the page-transformation engine or walk editor, the system now enforces that rule, so you won’t accidentally\nstore\nunsupported match types.</li>\n</ul>\n<h5>OS Map style selection is centralized</h5>\n<ul>\n<li>Instead of hardcoded strings floating around, there is now a single OSMapStyle record with helper flags (is27700, is3857) and a lookup by key. Every map control/service (walk-edit map, walk list map, dynamic-content map, admin map controls, migration editors, etc.) now\nconsults\nthat record.</li>\n<li>If you switch to a “27700” basemap or the “outdoor” variant, the map controls, export links, and map overlays now all agree because they rely on the same constants and boolean helpers (OSMapStyle.is27700, OSMapStyle.is3857).</li>\n</ul>\n<h5>Mailchimp batch-subscribe compatibility cleaned up</h5>\n<ul>\n<li>We now mirror the Mailchimp SDK’s Status type exactly (const object plus union type) so the backend can call lists.batchListMembers without type errors and still know which statuses/segments you’re targeting.</li>\n</ul>\n<h5>Admin/Migration UX polish</h5>\n<ul>\n<li>Migration UI log timestamps now use DateUtils for consistent time values, and the migration history view is presented in a cleaner, more readable table.</li>\n<li>Migration runner now records startedAt alongside appliedAt so operators can see duration context for each migration attempt.</li>\n<li>Migrated enums/string unions (map providers, backup/session/status/payloads, markdown list types, route profiles, input sizes, Agm stats/tabs, sorting, migration/page-transformation modes, location/session statuses, etc.) into model files so the frontend and server share the same\ntypes; enums now always use kebab-case values and are used everywhere (e.g., projects/ngx-ramblers/src/app/models/.ts, server/lib/mongo/models/.ts, admin pages, services, migration tools).</li>\n<li>Replaced the standalone entries helper with a consolidated implementation in projects/ngx-ramblers/src/app/functions/object-utils.ts (also updated to use keys from es-toolkit/compat), then cleaned imports such as agm-stats to reference the new helper.</li>\n<li>Updated Mailchimp type definitions to export const objects + union types so the backend code now accepts the same shape as the official SDK without introducing new string literals (projects/ngx-ramblers/src/app/models/mailchimp.model.ts, server/lib/mailchimp/lists/lists-batch-\nsubscribe.ts).</li>\n<li>Maintained DRY through shared model files for backup/session configs and ensured server imports only rely on frontend model definitions (no direct server/lib/... imports from the client).</li>\n</ul>\n"}