samgis-lisa-on-zero / static /src /components /PagePredictionMap.vue
alessandro trinca tornidor
[feat] refactor UI: navbar, mobile navbar, some links
c75f9b4
raw
history blame
9.2 kB
<template>
<div class="h-auto" id="id-prediction-map-container">
<div class="grid grid-cols-1 2xl:grid-cols-5 lg:gap-1 lg:border-r ml-2 mt-2 md:ml-4 md:mr-4">
<div class="lg:border-r lg:col-span-3">
<div id="id-map-cont" class="">
<p class="hidden lg:block">{{ description }}</p>
<div class="flex w-full md:pt-1 md:pb-1 lg:hidden portrait:xl:hidden">
<span class="flex portrait:hidden bg-slate-200 pl-2 pr-2">SamGIS demo</span>
<ButtonMapSendArrayRequest
id="id-button-submit"
class="h-8 text-sm font-extralight min-w-[180px] max-w-[180px] ml-2 mr-2"
:current-base-map-name="currentBaseMapNameRef"
:map="map"
:prompts-array="promptsArrayRef"
:response-message="responseMessageRef"
:send-m-l-request="sendMLArrayRequest"
:waiting-string="waitingString"
/>
<span class="ml-2 lg:hidden">
<input type="checkbox" id="checkboxMapNavigationLocked" v-model="mapNavigationLocked" />
<span class="ml-2">
<label class="text-red-600" for="checkboxMapNavigationLocked" v-if="mapNavigationLocked">locked map!</label>
<label class="text-blue-600" for="checkboxMapNavigationLocked" v-else>map unlocked</label>
</span>
</span>
</div>
<div id="map" class="map-predictions" />
<ButtonMapSendArrayRequest
class="h-8 min-w-[240px] max-w-[240px] mt-2 mb-2 hidden sd:h-14 lg:block portrait:xl:block"
:current-base-map-name="currentBaseMapNameRef"
id="id-button-submit"
:map="map"
:prompts-array="promptsArrayRef"
:response-message="responseMessageRef"
:send-m-l-request="sendMLArrayRequest"
:waiting-string="waitingString"
/>
<span class="hidden lg:block lg:ml-2">
<input type="checkbox" id="checkboxMapNavigationLocked" v-model="mapNavigationLocked" />
<span class="ml-2">
<label class="text-red-600" for="checkboxMapNavigationLocked" v-if="mapNavigationLocked">locked map navigation!</label>
<label class="text-blue-600" for="checkboxMapNavigationLocked" v-else>map navigation unlocked</label>
</span>
</span>
</div>
</div>
<div class="lg:col-span-2">
<div class="lg:pl-2 lg:pr-2 lg:border-l lg:border-3" id="id-map-info">
<h1>Map Info</h1>
<div class="grid grid-cols-1 md:grid-cols-3">
<StatsGrid :stats-array="[
{statName: 'current Zoom', statValue: currentZoomRef},
{statName: 'current map name/type', statValue: currentBaseMapNameRef},
{statName: 'prompt: points/rectangles number', statValue: promptsArrayRef.length},
]" />
</div>
<div v-if="responseMessageRef === waitingString" />
<h2 v-else-if="responseMessageRef || responseMessageRef == '-'" class="text-lg text-red-600">{{ responseMessageRef }}</h2>
<div v-else>
<div class="grid grid-cols-1 md:grid-cols-3">
<StatsGrid :stats-array="[
{statName: 'request duration', statValue: `${durationRef.toFixed(2)}s`},
{statName: 'polygons number', statValue: numberOfPolygonsRef},
{statName: 'predicted masks number', statValue: numberOfPredictedMasksRef},
]" />
</div>
</div>
</div>
<h1 id="id-ml-request-prompt">ML request prompt</h1>
<p>Exclude points: label 0, include points: label 1.</p>
<div v-if="promptsArrayRef.filter(el => {return el.type === 'point'}).length > 0">
<TableGenericComponent
:header="['id', 'data', 'label']"
:rows="applyFnToObjectWithinArray(promptsArrayRef.filter(el => {return el.type === 'point'}))"
title="Points"
row-key="id"
/>
</div>
<br />
<div v-if="promptsArrayRef.filter(el => {return el.type === 'rectangle'}).length > 0">
<TableGenericComponent
:header="['id', 'data_ne', 'data_sw']"
:rows="applyFnToObjectWithinArray(promptsArrayRef.filter(el => {return el.type === 'rectangle'}))"
title="Rectangles"
row-key="id"
class="2md:min-h-[100px]"
/>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import {
control as LeafletControl,
Evented as LEvented,
type LatLng,
Map as LMap,
map as LeafletMap,
tileLayer,
TileLayer as LTileLayer
} from 'leaflet'
import 'leaflet-providers'
import '@geoman-io/leaflet-geoman-free'
import { onMounted, onUpdated, ref, type Ref } from 'vue'
// workaround because of dist/ content not included in @trincadev/driver.js tag release tarball
import { driver } from "../../node_modules/@trincadev/driver.js/src/driver"
import {
currentBaseMapNameRef,
currentMapBBoxRef,
currentZoomRef,
driverSteps,
durationRef,
layerControlGroupLayersRef,
mapNavigationLocked,
mapOptionsDefaultRef,
maxZoom,
minZoom,
numberOfPolygonsRef,
numberOfPredictedMasksRef,
OpenStreetMap,
prefix,
promptsArrayRef,
responseMessageRef,
Satellite,
waitingString
} from './constants'
import {
applyFnToObjectWithinArray,
getExtentCurrentViewMapBBox,
sendMLArrayRequest,
getQueryParams,
getSelectedPointCoordinate,
setGeomanControls,
updateMapData,
updateZoomBboxMap,
getCurrentBasemap
} from '@/components/helpers'
import type { SourceTileType, ServiceTiles } from '@/components/types';
import StatsGrid from '@/components/StatsGrid.vue';
import TableGenericComponent from '@/components/TableGenericComponent.vue';
import ButtonMapSendArrayRequest from '@/components/buttons/ButtonMapSendArrayRequest.vue';
const driverObj = driver({
showProgress: true,
steps: driverSteps
});
let map: LMap
const props = defineProps<{
mapBounds: Array<LatLng>,
mapName: string,
description: string
}>()
const getPopupContentPoint = (leafletEvent: LEvented, label: number): HTMLDivElement => {
let popupContent: HTMLDivElement = document.createElement('div')
let currentPointLayer: LatLng = getSelectedPointCoordinate(leafletEvent)
popupContent.innerHTML = `<span>lat:${JSON.stringify(currentPointLayer.lat)}<br/>`
popupContent.innerHTML += `lng:${JSON.stringify(currentPointLayer.lng)}<br/>`
popupContent.innerHTML += `label:${label}, id:${leafletEvent.layer._leaflet_id}</span>`
const popupDiv: HTMLDivElement = document.createElement('div')
popupDiv.className = 'leaflet-popup-content-inner'
popupDiv.appendChild(popupContent)
return popupDiv
}
onMounted(async () => {
const osmTile = tileLayer.provider(OpenStreetMap)
const params = getQueryParams()
let localVarSatellite: SourceTileType = params.source ? params.source : Satellite
let localVarSatelliteOptions = params.options ? params.options : {}
const satelliteTile = tileLayer.provider(localVarSatellite, localVarSatelliteOptions)
let localVarTerrain: SourceTileType = "nextzen.terrarium"
const terrainTile = new LTileLayer(
"https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png", {
id: localVarTerrain,
attribution: "<a href='https://nextzen.org'>nextzen</a>," +
"<a href='https://registry.opendata.aws/terrain-tiles/'>Mapzen Terrain Tiles - AWS opendata registry</a>," +
"<a href='https://github.com/tilezen/joerd/blob/master/docs/attribution.md'>Mapzen Source Attributions</a>."
}
)
let baseMaps: ServiceTiles = { OpenStreetMap: osmTile }
baseMaps[localVarSatellite] = satelliteTile
baseMaps[localVarTerrain] = terrainTile
currentBaseMapNameRef.value = OpenStreetMap
map = LeafletMap('map', {
layers: [osmTile],
minZoom: minZoom,
maxZoom: maxZoom
})
map.fitBounds(props.mapBounds)
map.attributionControl.setPrefix(prefix)
LeafletControl.scale({ position: 'bottomleft', imperial: false, metric: true }).addTo(map)
layerControlGroupLayersRef.value = LeafletControl.layers(baseMaps).addTo(map)
setGeomanControls(map)
updateZoomBboxMap(map)
mapOptionsDefaultRef.value = {...map.options}
map.on('zoomend', (e: LEvented) => {
updateZoomBboxMap(map)
})
map.on('mouseup', (e: LEvented) => {
currentMapBBoxRef.value = getExtentCurrentViewMapBBox(map)
})
updateMapData(map, getPopupContentPoint, promptsArrayRef)
map.on('baselayerchange', (e: LEvented) => {
currentBaseMapNameRef.value = getCurrentBasemap(e.layer._url, baseMaps)
})
driverObj.drive();
})
onUpdated(() => {
if (mapNavigationLocked.value) {
map.setMaxZoom(currentZoomRef.value)
map.setMinZoom(currentZoomRef.value)
map.options.maxBoundsViscosity = 1.0
map.setMaxBounds(map.getBounds())
}
if (!mapNavigationLocked.value) {
map.setMaxZoom(maxZoom)
map.setMinZoom(minZoom)
map.options.maxBoundsViscosity = 0.0
map.setMaxBounds([
[90, 180],
[-90, -180]
])
}
})
</script>