diff --git a/src/lib/components/RegistryActivitiesMap.svelte b/src/lib/components/RegistryActivitiesMap.svelte index a8bd15a..b4daadd 100644 --- a/src/lib/components/RegistryActivitiesMap.svelte +++ b/src/lib/components/RegistryActivitiesMap.svelte @@ -30,6 +30,19 @@ let map = $state(null); /** Each drawn outline by activity id, so the page can zoom to one. Not reactive. */ const outlinesById = new Map(); + /** Every drawn outline, for zooming back out to them all. Not reactive. */ + let allOutlines: import('leaflet').FeatureGroup | null = null; + + /** Frames every drawn area again, as the map first opened. */ + export function showAll() { + map?.closePopup(); + frameAll(); + } + + function frameAll() { + const bounds = allOutlines?.getBounds(); + if (map && bounds?.isValid()) map.fitBounds(bounds, { padding: [32, 32], maxZoom: 14 }); + } /** Zooms to one activity's area and opens its popup. Returns false if it has none drawn. */ export function focusActivity(activityId: string): boolean { @@ -109,8 +122,8 @@ }; m.on('zoomend', syncDots); - const bounds = outlines.getBounds(); - if (bounds.isValid()) m.fitBounds(bounds, { padding: [32, 32], maxZoom: 14 }); + allOutlines = outlines; + frameAll(); syncDots(); return () => { @@ -118,6 +131,7 @@ outlines.remove(); dots.remove(); outlinesById.clear(); + allOutlines = null; }; }); diff --git a/src/routes/registry/activities/+page.svelte b/src/routes/registry/activities/+page.svelte index 3dcb4ab..c3ff518 100644 --- a/src/routes/registry/activities/+page.svelte +++ b/src/routes/registry/activities/+page.svelte @@ -4,6 +4,7 @@ import Pill from '$lib/components/Pill.svelte'; import ObpErrorDisplay from '$lib/components/ObpErrorDisplay.svelte'; import ToggleGroup from '$lib/components/ToggleGroup.svelte'; + import Button from '$lib/components/Button.svelte'; import RegistryActivitiesMap from '$lib/components/RegistryActivitiesMap.svelte'; import { goto } from '$app/navigation'; import { page } from '$app/state'; @@ -15,7 +16,7 @@ registryOperatorHref, type RegistryActivity } from '$lib/registry/activities'; - import { Search, List, Map as MapIcon, Layers } from '@lucide/svelte'; + import { Search, List, Map as MapIcon, Layers, Maximize } from '@lucide/svelte'; import { findAreaOverlaps } from '$lib/registry/areaOverlaps'; let { data }: { data: PageData } = $props(); @@ -91,6 +92,10 @@ function focusOnMap(activityId: string) { if (activitiesMap?.focusActivity(activityId)) focusedId = activityId; } + function showAllOnMap() { + activitiesMap?.showAll(); + focusedId = null; + } const filtersApplied = $derived( search.trim() !== '' || creditType !== 'all' || country !== 'all' || status !== 'all' @@ -237,13 +242,18 @@
Verified Unverified + {#if mapped.length > 0} + + {/if}
{#if overlappingCount > 0}

{/if} {#if mapped.length > 0} @@ -406,8 +416,13 @@ .ogcr-legend { display: flex; flex-wrap: wrap; + align-items: center; gap: var(--space-xs); } + /* Sits at the right, above the map it acts on. */ + .ogcr-legend :global(.ogcr-legend__action) { + margin-left: auto; + } /* Small and capped at a few lines, so the map stays the main thing on the page. */ .ogcr-map-list {