import WithRender from "./click-marker.vue" ; import Vue from "vue" ; import { Component , Watch } from "vue-property-decorator" ; import { InjectClient , Client , InjectMapComponents , InjectMapContext , InjectContext } from "../../utils/decorators" ; import { MapComponents , MapContext } from "../leaflet-map/leaflet-map" ; import { LineCreate , MarkerCreate , Point , SearchResult , Type } from "facilmap-types" ; import { round } from "facilmap-utils" ; import { lineStringToTrackPoints , mapSearchResultToType } from "../search-results/utils" ; import { showErrorToast } from "../../utils/toasts" ; import { SearchResultsLayer } from "facilmap-leaflet" ; import SearchResultInfo from "../search-result-info/search-result-info" ; import Icon from "../ui/icon/icon" ; import { Util } from "leaflet" ; import StringMap from "../../utils/string-map" ; import { Portal } from "portal-vue" ; import { Context } from "../facilmap/facilmap" ; @ WithRender @ Component ( { components : { Icon , Portal , SearchResultInfo } } ) export default class ClickMarker extends Vue { @ InjectContext ( ) context ! : Context ; @ InjectMapContext ( ) mapContext ! : MapContext ; @ InjectMapComponents ( ) mapComponents ! : MapComponents ; @ InjectClient ( ) client ! : Client ; lastClick = 0 ; results : SearchResult [ ] = [ ] ; layers ! : SearchResultsLayer [ ] ; isAdding = false ; mounted ( ) { this . layers = [ ] ; this . mapContext . $on ( "fm-map-long-click" , this . handleMapLongClick ) ; this . mapContext . $on ( "fm-open-selection" , this . handleOpenSelection ) ; } beforeDestroy ( ) { this . mapContext . $off ( "fm-map-long-click" , this . handleMapLongClick ) ; this . mapContext . $off ( "fm-open-selection" , this . handleOpenSelection ) ; } get layerIds ( ) : number [ ] { return this . results . map ( ( result , i ) => { return Util . stamp ( this . layers [ i ] ) ; } ) ; } @ Watch ( "mapContext.selection" ) handleSelectionChange ( ) { for ( let i = this . results . length - 1 ; i >= 0 ; i -- ) { if ( ! this . mapContext . selection . some ( ( item ) => item . type == "searchResult" && item . layerId == this . layerIds [ i ] ) ) this . close ( this . results [ i ] ) ; } } handleOpenSelection ( ) { for ( let i = 0 ; i < this . layerIds . length ; i ++ ) { if ( this . mapContext . selection . some ( ( item ) => item . type == "searchResult" && item . layerId == this . layerIds [ i ] ) ) { this . mapContext . $emit ( "fm-search-box-show-tab" , `fm${ this . context . id }-click-marker-tab-${ i }` ) ; break ; } } } async handleMapLongClick ( pos ) { const now = Date . now ( ) ; this . lastClick = now ; const results = await this . client . find ( { query : `geo:${ round ( pos . lat , 5 ) },${ round ( pos . lon , 5 ) }?z=${ this . mapContext . zoom }` , loadUrls : false , elevation : true } ) ; if ( now !== this . lastClick ) { return ; } if ( results . length > 0 ) { const layer = new SearchResultsLayer ( [ results [ 0 ] ] ) . addTo ( this . mapComponents . map ) ; this . mapComponents . selectionHandler . addSearchResultLayer ( layer ) ; this . results . push ( results [ 0 ] ) ; this . layers . push ( layer ) ; this . mapComponents . selectionHandler . setSelectedItems ( [ { type : "searchResult" , result : results [ 0 ] , layerId : Util . stamp ( layer ) } ] ) ; setTimeout ( ( ) => { this . mapContext . $emit ( "fm-search-box-show-tab" , `fm${ this . context . id }-click-marker-tab-${ this . results . length - 1 }` ) ; } , 0 ) ; } } close ( result ) { const idx = this . results . indexOf ( result ) ; if ( idx == - 1 ) return ; this . mapComponents . selectionHandler . removeSearchResultLayer ( this . layers [ idx ] ) ; this . layers [ idx ] . remove ( ) ; this . results . splice ( idx , 1 ) ; this . layers . splice ( idx , 1 ) ; } clear ( ) { for ( let i = this . results . length - 1 ; i >= 0 ; i -- ) this . close ( this . results [ i ] ) ; } async addToMap ( result , type ) { this . $bvToast . hide ( `fm${ this . context . id }-click-marker-add-error` ) ; this . isAdding = true ; try { const obj = { name : result . short_name , data : mapSearchResultToType ( result , type ) } ; if ( type . type == "marker" ) { const marker = await this . client . addMarker ( { ... obj , lat : result . lat ! , lon : result . lon ! , typeId : type . id } ) ; this . mapComponents . selectionHandler . setSelectedItems ( [ { type : "marker" , id : marker . id } ] , true ) ; } else if ( type . type == "line" ) { const trackPoints = lineStringToTrackPoints ( result . geojson as any ) ; const line = await this . client . addLine ( { ... obj , typeId : type . id , routePoints : [ trackPoints [ 0 ] , trackPoints [ trackPoints . length - 1 ] ] , trackPoints : trackPoints , mode : "track" } ) ; this . mapComponents . selectionHandler . setSelectedItems ( [ { type : "line" , id : line . id } ] , true ) ; } this . close ( result ) ; } catch ( err ) { showErrorToast ( this , `fm${ this . context . id }-click-marker-add-error` , "Error adding to map" , err ) ; } finally { this . isAdding = false ; } } useAs ( result , event ) { this . mapContext . $emit ( event , result . short_name , [ result ] , [ ] , result ) ; this . mapContext . $emit ( "fm-search-box-show-tab" , `fm${ this . context . id }-route-form-tab` ) ; } useAsFrom ( result ) { this . useAs ( result , "fm-route-set-from" ) ; } useAsVia ( result ) { this . useAs ( result , "fm-route-add-via" ) ; } useAsTo ( result ) { this . useAs ( result , "fm-route-set-to" ) ; } }