alessandro trinca tornidor
[feat] update the onbard user tour with driver.js
0e6892b
raw
history blame
No virus
10.6 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="">
<details id="detail-prompt-examples-array" :open="detailIsOpenRef">
<summary><i>Expand this detail element for some prompt examples</i></summary>
<div class="grid grid-cols-1 md:grid-cols-3" id="prompt-examples-array">
<div class="text-xs font-extralight flex bg-green-200">
<textarea
id="prompt-text-placeholder"
v-model="promptTextPlaceholderRef"
class="p-2 border-2 border-indigo-500/100 w-full"
/>
</div>
<StringArray
:string-array="promptTextArray"
:string-prefix="promptTextPlaceholderRef"
@set-prompt="(stringPrompt: string) => promptTextRef = stringPrompt"
/>
</div>
</details>
<div class="flex">
<textarea
id="prompt-text-llm-ref"
v-model="promptTextRef"
:placeholder=promptTextPlaceholderRef
rows="2"
class="w-full md:pt-1 md:pb-1 flex border-2 mt-2 mb-2 mr-2 border-indigo-500/100"
></textarea>
<div class="w-full md:pt-1 md:pb-1 flex">
<ButtonMapSendStringRequest
id="id-button-submit"
class="h-8 mt-2 text-sm font-extralight min-w-[180px] max-w-[180px]"
:current-base-map-name="currentBaseMapNameRef"
:map="map"
:promptText="promptTextRef"
:response-message="responseMessageRef"
:send-m-l-request="sendMLStringRequest"
:waiting-string="waitingString"
/>
</div>
</div>
<div id="map" class="map-predictions"/>
</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}
]"/>
</div>
<h2 id="lisa-response-text">LISA response: <span class="text-lg text-blue-600">{{ responseMessageLisaRef }}</span></h2>
<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>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import {
control as LeafletControl,
Evented as LEvented,
geoJSON as LeafletGeoJSON,
type LatLng,
Map as LMap,
map as LeafletMap,
tileLayer,
TileLayer as LTileLayer
} from 'leaflet'
import 'leaflet-providers'
import {onMounted, ref, type Ref} from 'vue'
import {driver} from "../../node_modules/driver.js/src/driver"
import {
durationRef,
numberOfPolygonsRef,
numberOfPredictedMasksRef,
OpenStreetMap,
prefix,
promptPlaceHolder,
promptTextArray,
responseMessageRef,
responseMessageLisaRef,
Satellite,
waitingString
} from './constants'
import {
getExtentCurrentViewMapBBox,
getGeoJSONRequest,
getQueryParams,
getSelectedPointCoordinate,
updateMapData
} from '@/components/helpers'
import type {IBodyLatLngWithStringPoints, SourceTileType} from '@/components/types';
import StatsGrid from '@/components/StatsGrid.vue';
import StringArray from '@/components/StringArray.vue';
import ButtonMapSendStringRequest from '@/components/buttons/ButtonMapSendStringRequest.vue';
const lisaDriverObj = driver({
showProgress: true,
steps: [
{
element: 'id-prediction-map-container', popover: {
title: 'SamGIS with LISA',
description: 'A quick tour about functionalities of SamGIS with LISA',
onNextClick: () => {
detailIsOpenRef.value = true
lisaDriverObj.moveNext();
}
}
},
{
element: '#map',
popover: {
title: 'Geographic map',
description: 'Choose here the map area where you can execute your machine learning prompt'
}
},
{
element: "#prompt-examples-array",
popover: {title: 'Some prompt examples', description: 'A selection of prompt examples'}
},
{
element: "#prompt-text-placeholder", popover: {
title: 'Default prompt prefix',
description: 'A good LLM prompt prefix tailored for photogrammetry, remote sensing and geomorphology (editable)'
}
},
{
element: "#prompt-text-llm-ref", popover: {
title: 'Prompt text',
description: 'Editable text area for the LLM text prompt (you can precompile it clicking on the examples)'
}
},
{
element: "#id-button-submit",
popover: {title: 'LLM submit button', description: 'submit button for the LISA request'}
},
{
element: '.leaflet-control-layers-toggle',
popover: {title: 'Map provider selector', description: 'select a different map provider'}
},
{
element: '#lisa-response-text',
popover: {title: 'LISA response text', description: 'Output area with the LISA response text'}
},
{
element: '#id-map-info', popover: {
title: 'map info',
description: 'Section about various map info',
onNextClick: () => {
detailIsOpenRef.value = false
lisaDriverObj.moveNext();
}
}
},
{
element: "#detail-prompt-examples-array", popover: {
title: 'Detail: Array of Prompt Examples',
description: 'Click here to expand the array of prompt examples (closed by default)'
}
},
]
});
const currentBaseMapNameRef = ref("")
const currentMapBBoxRef = ref()
const currentZoomRef = ref()
const promptTextRef: Ref<string> = ref("")
const promptTextPlaceholderRef: Ref<string> = ref(promptPlaceHolder)
const detailIsOpenRef: Ref<boolean> = ref(false)
let map: LMap
type ServiceTiles = {
[key: SourceTileType]: LTileLayer;
};
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
}
const sendMLStringRequest = async (leafletMap: LMap, promptRequest: string, sourceType: SourceTileType = OpenStreetMap) => {
const bodyRequest: IBodyLatLngWithStringPoints = {
bbox: getExtentCurrentViewMapBBox(leafletMap),
string_prompt: promptRequest,
zoom: leafletMap.getZoom(),
source_type: sourceType
}
try {
const geojsonOutputOnMounted = await getGeoJSONRequest(bodyRequest, '/infer_lisa')
const featureNew = LeafletGeoJSON(geojsonOutputOnMounted)
leafletMap.addLayer(featureNew)
} catch (errGeojsonOutputOnMounted) {
console.error('sendMLRequest:: sourceType: ', sourceType)
console.error('sendMLRequest:: promptRequest: ', promptRequest.length, '::', promptRequest)
console.error('sendMLRequest:: bodyRequest => ', bodyRequest, "#")
console.error("errGeojsonOutputOnMounted => ", errGeojsonOutputOnMounted)
}
}
const updateZoomBboxMap = (localMap: LMap) => {
currentZoomRef.value = localMap.getZoom()
currentMapBBoxRef.value = getExtentCurrentViewMapBBox(localMap)
}
const getCurrentBasemap = (url: string, providersArray: ServiceTiles) => {
for (const [key, value] of Object.entries(providersArray)) {
if (value._url == url) {
return key
}
}
}
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]
})
map.fitBounds(props.mapBounds)
map.attributionControl.setPrefix(prefix)
LeafletControl.scale({position: 'bottomleft', imperial: false, metric: true}).addTo(map)
LeafletControl.layers(baseMaps).addTo(map)
updateZoomBboxMap(map)
map.on('zoomend', (e: LEvented) => {
updateZoomBboxMap(map)
})
map.on('mouseup', (e: LEvented) => {
currentMapBBoxRef.value = getExtentCurrentViewMapBBox(map)
})
updateMapData(map, getPopupContentPoint, promptTextRef)
map.on('baselayerchange', (e: LEvented) => {
currentBaseMapNameRef.value = getCurrentBasemap(e.layer._url, baseMaps)
})
lisaDriverObj.drive();
})
</script>