{"id":"6aa13eaba7b06e82ff1a5585","title":"2026 09 09 Issue 99","path":"how-to/committee/release-notes/2026-09-09-issue-99","contentMarkdown":"# 09-Sep-2026 — OS Maps routes page - search-first landing, real map thumbnails, mobile-responsive card [#99](https://github.com/nbarrett/ngx-ramblers/issues/99)\n\n## [build 885](https://github.com/nbarrett/ngx-ramblers/actions/runs/34342625474) — [commit 66a062c](https://github.com/nbarrett/ngx-ramblers/commit/66a062c5ef07ed6b5e4e6d2a34969d8efaaf60c3)\n\n_____\n\n### **maps**: OS Maps routes page ([#99](https://github.com/nbarrett/ngx-ramblers/issues/99))\n\n## The problem\n\nThe routes page loaded and displayed every saved route at once (630+ on a\nbusy account) in a plain table - overwhelming, slow to scan, and none of it\nworked on a phone.\n\n## Search-first landing, capped results\n\nNothing is shown until you type a search or choose a filter; the landing\nstate explains how many routes there are and prompts you to search. Results\nare capped to the first 50 matches, with a note showing the total and asking\nyou to narrow the search when there are more. Sorting moved to a Sort by\ncontrol with a direction toggle.\n\n## Real map thumbnails\n\nFor routes that have already been converted, the real GPX geometry is\nalready held in S3, so each card fetches it (reusing GpxParserService,\nRouteFollowPayloadService.gpxDownloadUrl and MapTilesService's base layer -\nthe same machinery the app's full map views already use) and draws an actual\nsmall Leaflet map: real OpenStreetMap tiles, the route line in its saved\ncolour, fitted to the route's bounds. A checkmark badge on the thumbnail\ncorner shows imported status, matching OS Maps' own visual language, instead\nof a separate text field. Not-yet-imported routes, which have no geometry\nanywhere in our system, keep an icon placeholder.\n\nGetting the map's lifecycle right took a few passes: Angular's structural\n@if was recreating the map's container on every data change, and the leaflet\ndirective gave no way to guard against Leaflet's \"container is being reused\"\nerror when @for reused a DOM node across component instances faster than the\nold map's teardown ran. Fixed by taking direct control of L.map() construction\nin ngAfterViewInit, with an explicit clear of any stale internal marker\nbefore creating a new map.\n\n## Card layout matching OS Maps' own design\n\nDistance, date, a source badge and an imported-status line were crammed into\none free-flowing row, so a longer title or date pushed everything after it\nsideways - a jagged, misaligned look row to row. Rebuilt to match OS Maps'\nown card design instead: one short metadata line (distance + a compact date,\nnot the full weekday form), source as an icon-only tooltip rather than a text\nbadge, imported status moved to the thumbnail badge. The title (for\nalready-imported routes) and the thumbnail now open this app's own edit page\ndirectly, since \"Open in OS Maps\" already covers the external link and\nhaving both was redundant; the separate edit icon button is gone.\n\nAlso added the real OS Maps logo (already used elsewhere in the app for\nattribution) to the \"Open in OS Maps\" link, in place of a generic icon.\n\n## Mobile\n\n- The thumbnail stretches to fill the card's actual height rather than\nsitting at a fixed size while wrapped titles make mobile cards much\ntaller - capped at 140px so a very tall card doesn't stretch it into a\nsliver.\n- Back to walks admin / Convert selected to GPX / Load routes from OS Maps\ngo full width and stack on narrow screens; Last loaded and the refresh\nbutton stay grouped as one unit.\n- Search / Show / Sort by each take the full row width on narrow screens.\n- Tightened row gaps that were adding more vertical space than the shorter,\nsingle-line content needed.\n\n## Diagnostics\n\nAdded a one-off debug log of the real OS Maps routes/search response shape\n(route names redacted) - the fields we map today (id, title, date, distance)\nare a small slice of what that response might carry, and this lets a future\npass build a real preview for not-yet-imported routes against the actual\npayload instead of a guess.","contentHtml":"<h1>09-Sep-2026 — OS Maps routes page - search-first landing, real map thumbnails, mobile-responsive card <a href=\"https://github.com/nbarrett/ngx-ramblers/issues/99\">#99</a></h1>\n<h2><a href=\"https://github.com/nbarrett/ngx-ramblers/actions/runs/34342625474\">build 885</a> — <a href=\"https://github.com/nbarrett/ngx-ramblers/commit/66a062c5ef07ed6b5e4e6d2a34969d8efaaf60c3\">commit 66a062c</a></h2>\n<hr>\n<h3><strong>maps</strong>: OS Maps routes page (<a href=\"https://github.com/nbarrett/ngx-ramblers/issues/99\">#99</a>)</h3>\n<h2>The problem</h2>\n<p>The routes page loaded and displayed every saved route at once (630+ on a\nbusy account) in a plain table - overwhelming, slow to scan, and none of it\nworked on a phone.</p>\n<h2>Search-first landing, capped results</h2>\n<p>Nothing is shown until you type a search or choose a filter; the landing\nstate explains how many routes there are and prompts you to search. Results\nare capped to the first 50 matches, with a note showing the total and asking\nyou to narrow the search when there are more. Sorting moved to a Sort by\ncontrol with a direction toggle.</p>\n<h2>Real map thumbnails</h2>\n<p>For routes that have already been converted, the real GPX geometry is\nalready held in S3, so each card fetches it (reusing GpxParserService,\nRouteFollowPayloadService.gpxDownloadUrl and MapTilesService&#39;s base layer -\nthe same machinery the app&#39;s full map views already use) and draws an actual\nsmall Leaflet map: real OpenStreetMap tiles, the route line in its saved\ncolour, fitted to the route&#39;s bounds. A checkmark badge on the thumbnail\ncorner shows imported status, matching OS Maps&#39; own visual language, instead\nof a separate text field. Not-yet-imported routes, which have no geometry\nanywhere in our system, keep an icon placeholder.</p>\n<p>Getting the map&#39;s lifecycle right took a few passes: Angular&#39;s structural\n@if was recreating the map&#39;s container on every data change, and the leaflet\ndirective gave no way to guard against Leaflet&#39;s &quot;container is being reused&quot;\nerror when @for reused a DOM node across component instances faster than the\nold map&#39;s teardown ran. Fixed by taking direct control of L.map() construction\nin ngAfterViewInit, with an explicit clear of any stale internal marker\nbefore creating a new map.</p>\n<h2>Card layout matching OS Maps&#39; own design</h2>\n<p>Distance, date, a source badge and an imported-status line were crammed into\none free-flowing row, so a longer title or date pushed everything after it\nsideways - a jagged, misaligned look row to row. Rebuilt to match OS Maps&#39;\nown card design instead: one short metadata line (distance + a compact date,\nnot the full weekday form), source as an icon-only tooltip rather than a text\nbadge, imported status moved to the thumbnail badge. The title (for\nalready-imported routes) and the thumbnail now open this app&#39;s own edit page\ndirectly, since &quot;Open in OS Maps&quot; already covers the external link and\nhaving both was redundant; the separate edit icon button is gone.</p>\n<p>Also added the real OS Maps logo (already used elsewhere in the app for\nattribution) to the &quot;Open in OS Maps&quot; link, in place of a generic icon.</p>\n<h2>Mobile</h2>\n<ul>\n<li>The thumbnail stretches to fill the card&#39;s actual height rather than\nsitting at a fixed size while wrapped titles make mobile cards much\ntaller - capped at 140px so a very tall card doesn&#39;t stretch it into a\nsliver.</li>\n<li>Back to walks admin / Convert selected to GPX / Load routes from OS Maps\ngo full width and stack on narrow screens; Last loaded and the refresh\nbutton stay grouped as one unit.</li>\n<li>Search / Show / Sort by each take the full row width on narrow screens.</li>\n<li>Tightened row gaps that were adding more vertical space than the shorter,\nsingle-line content needed.</li>\n</ul>\n<h2>Diagnostics</h2>\n<p>Added a one-off debug log of the real OS Maps routes/search response shape\n(route names redacted) - the fields we map today (id, title, date, distance)\nare a small slice of what that response might carry, and this lets a future\npass build a real preview for not-yet-imported routes against the actual\npayload instead of a guess.</p>\n"}