facilmap/frontend/src/lib/components/search-result-info.vue

111 wiersze
3.9 KiB
Vue
Czysty Zwykły widok Historia

2023-09-12 09:15:28 +00:00
<script setup lang="ts">
import WithRender from "./search-result-info.vue";
import Vue from "vue";
import { Component, Prop } from "vue-property-decorator";
import { renderOsmTag } from "facilmap-utils";
import { SearchResult, Type } from "facilmap-types";
import Icon from "../ui/icon/icon";
import { Client, InjectClient, InjectContext, InjectMapComponents, InjectMapContext } from "../../utils/decorators";
import "./search-result-info.scss";
import { FileResult } from "../../utils/files";
import { MapComponents, MapContext } from "../leaflet-map/leaflet-map";
import { isLineResult, isMarkerResult } from "../../utils/search";
import { flyTo, getZoomDestinationForSearchResult } from "../../utils/zoom";
import { Context } from "../facilmap/facilmap";
import Coordinates from "../ui/coordinates/coordinates";
@WithRender
@Component({
components: { Coordinates, Icon }
})
export default class SearchResultInfo extends Vue {
2023-10-23 21:05:19 +00:00
const context = injectContextRequired();
const client = injectClientRequired();
const mapComponents = injectMapComponentsRequired();
const mapContext = injectMapContextRequired();
2023-09-12 09:15:28 +00:00
@Prop({ type: Object, required: true }) result!: SearchResult | FileResult;
@Prop({ type: Boolean, default: false }) showBackButton!: boolean;
@Prop({ type: Boolean, default: false }) isAdding!: boolean;
renderOsmTag = renderOsmTag;
get isMarker(): boolean {
return isMarkerResult(this.result);
}
get isLine(): boolean {
return isLineResult(this.result);
}
get types(): Type[] {
// Result can be both marker and line
return Object.values(this.client.types).filter((type) => (this.isMarker && type.type == "marker") || (this.isLine && type.type == "line"));
}
zoomToResult(): void {
const dest = getZoomDestinationForSearchResult(this.result);
if (dest)
flyTo(this.mapComponents.map, dest);
}
}
</script>
<template>
<div class="fm-search-result-info" v-if="result">
<h2>
<a v-if="showBackButton" href="javascript:" @click="$emit('back')"><Icon icon="arrow-left"></Icon></a>
{{result.short_name}}
</h2>
<dl class="fm-search-box-collapse-point">
<dt v-if="result.type">Type</dt>
<dd v-if="result.type">{{result.type}}</dd>
<dt v-if="result.address">Address</dt>
<dd v-if="result.address">{{result.address}}</dd>
<dt v-if="result.type != 'coordinates' && result.lat != null && result.lon != null">Coordinates</dt>
<dd v-if="result.type != 'coordinates' && result.lat != null && result.lon != null"><Coordinates :point="result"></Coordinates></dd>
<dt v-if="result.elevation != null">Elevation</dt>
<dd v-if="result.elevation != null">{{result.elevation}} m</dd>
<template v-for="(value, key) in result.extratags">
<dt>{{key}}</dt>
<dd v-html="renderOsmTag(key, value)"></dd>
</template>
2023-09-12 09:15:28 +00:00
</dl>
<b-button-toolbar>
<b-button v-b-tooltip.hover="'Zoom to search result'" @click="zoomToResult()" size="sm"><Icon icon="zoom-in" alt="Zoom to search result"></Icon></b-button>
<b-dropdown v-if="!client.readonly && types.length > 0" :disabled="isAdding" size="sm">
<template #button-content>
2023-10-06 23:13:51 +00:00
<div v-if="isAdding" class="spinner-border spinner-border-sm"></div>
2023-09-12 09:15:28 +00:00
Add to map
</template>
<b-dropdown-item v-for="type in types" href="javascript:" @click="$emit('add-to-map', type)">{{type.name}}</b-dropdown-item>
</b-dropdown>
<b-dropdown v-if="isMarker && context.search" text="Use as" size="sm">
<b-dropdown-item href="javascript:" @click="$emit('use-as-from')">Route start</b-dropdown-item>
<b-dropdown-item href="javascript:" @click="$emit('use-as-via')">Route via</b-dropdown-item>
<b-dropdown-item href="javascript:" @click="$emit('use-as-to')">Route destination</b-dropdown-item>
</b-dropdown>
</b-button-toolbar>
</div>
</template>
<style lang="scss">
.fm-search-result-info {
display: flex;
flex-direction: column;
min-height: 0;
.fm-search-box-collapse-point {
min-height: 1.5em;
}
}
</style>