feat(web): Global map showing all assets with geo information (#2355)

* First crude implementation of the global asset map in web

* Use single DOM element for all markers

* Minor layout changes

* Refactor

* Add asset viewer

* Add API endpoint that returns only assets with location information (Thanks @EPP100)

* Remove sidebar icon flip

* Add dark theme support

* Center map to most recent asset

* Allow cluster viewing

* Fix linter errors

* Add newlines

* Fix ts errors

* Fix eslint error

* Run prettier

* Server code style

* Fix openapi mobile code generation issues

* Map markers test

* fix: Support video thumbnails

* Update API

* Review suggestions

* Review suggestions

* Linter error

* Chage mapMarker endpoint to map-marker

* Clean up leaflet imports
This commit is contained in:
Matthias Rupp
2023-05-06 03:33:30 +02:00
committed by GitHub
parent 15a498fd60
commit 65daf342df
28 changed files with 902 additions and 5 deletions

View File

@@ -0,0 +1,23 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals: { api, user } }) => {
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
try {
const { data: mapMarkers } = await api.assetApi.getMapMarkers();
return {
user,
mapMarkers,
meta: {
title: 'Map'
}
};
} catch (e) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
}) satisfies PageServerLoad;

View File

@@ -0,0 +1,80 @@
<script lang="ts">
import type { PageData } from '../map/$types';
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
import Portal from '$lib/components/shared-components/portal/portal.svelte';
import AssetViewer from '$lib/components/asset-viewer/asset-viewer.svelte';
import {
assetInteractionStore,
isViewingAssetStoreState,
viewingAssetStoreState
} from '$lib/stores/asset-interaction.store';
export let data: PageData;
let initialMapCenter: [number, number] = [48, 11];
$: {
if (data.mapMarkers.length) {
let firstMarker = data.mapMarkers[0];
initialMapCenter = [firstMarker.lat, firstMarker.lon];
}
}
let viewingAssets: string[] = [];
let viewingAssetCursor = 0;
function onViewAssets(assets: string[]) {
assetInteractionStore.setViewingAssetId(assets[0]);
viewingAssets = assets;
viewingAssetCursor = 0;
}
function navigateNext() {
if (viewingAssetCursor < viewingAssets.length - 1) {
assetInteractionStore.setViewingAssetId(viewingAssets[++viewingAssetCursor]);
}
}
function navigatePrevious() {
if (viewingAssetCursor > 0) {
assetInteractionStore.setViewingAssetId(viewingAssets[--viewingAssetCursor]);
}
}
</script>
<UserPageLayout user={data.user} title={data.meta.title}>
<div slot="buttons" />
<div class="h-[90%] w-full">
{#await import('$lib/components/shared-components/leaflet') then { Map, TileLayer, AssetMarkerCluster }}
<Map latlng={initialMapCenter} zoom={7}>
<TileLayer
allowDarkMode={true}
urlTemplate={'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'}
options={{
attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}}
/>
<AssetMarkerCluster
markers={data.mapMarkers}
on:view={(event) => onViewAssets(event.detail.assets)}
/>
</Map>
{/await}
</div>
</UserPageLayout>
<Portal target="body">
{#if $isViewingAssetStoreState}
<AssetViewer
asset={$viewingAssetStoreState}
showNavigation={viewingAssets.length > 1}
on:navigate-next={navigateNext}
on:navigate-previous={navigatePrevious}
on:close={() => {
assetInteractionStore.setIsViewingAsset(false);
}}
/>
{/if}
</Portal>