kopia lustrzana https://github.com/FacilMap/facilmap
pull/256/head
rodzic
e12dd1920e
commit
bc2c14dd25
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { CRU, Line, Marker, Point, SearchResult, Type } from "facilmap-types";
|
||||
import type { CRU, Line, Marker, Point, SearchResult, Type } from "facilmap-types";
|
||||
import { round } from "facilmap-utils";
|
||||
import { lineStringToTrackPoints, mapSearchResultToType } from "./search-results/utils";
|
||||
import { useToasts } from "./ui/toasts/toasts.vue";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent, InjectionKey, inject, onBeforeUnmount, provide, reactive, ref, toRaw, watch } from "vue";
|
||||
import { defineComponent, InjectionKey, inject, onBeforeUnmount, provide, reactive, ref, toRaw, watch, readonly } from "vue";
|
||||
import FmClient from "facilmap-client";
|
||||
import { PadData, PadId } from "facilmap-types";
|
||||
import type { PadData, PadId } from "facilmap-types";
|
||||
import PadSettingsDialog from "./pad-settings-dialog/pad-settings-dialog.vue";
|
||||
import storage from "../utils/storage";
|
||||
import { useToasts } from "./ui/toasts/toasts.vue";
|
||||
|
@ -64,6 +64,7 @@
|
|||
emit("update:padId", padId);
|
||||
}
|
||||
});
|
||||
provide(clientContextInject, readonly(clientContext));
|
||||
|
||||
const createId = ref<string>();
|
||||
const counter = ref(1);
|
||||
|
@ -181,7 +182,8 @@
|
|||
const ClientProvider = defineComponent({
|
||||
setup(props, { slots }) {
|
||||
provide(clientInject, client.value!);
|
||||
return slots.default;
|
||||
provide("test", "testValue");
|
||||
return () => slots.default?.();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { ID } from "facilmap-types";
|
||||
import type { ID } from "facilmap-types";
|
||||
import { canControl, getUniqueId, mergeObject, validateRequired } from "../utils/utils";
|
||||
import { clone } from "facilmap-utils";
|
||||
import { isEqual, omit } from "lodash-es";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { ID } from "facilmap-types";
|
||||
import type { ID } from "facilmap-types";
|
||||
import { canControl, getUniqueId, mergeObject, validateRequired } from "../utils/utils";
|
||||
import { clone } from "facilmap-utils";
|
||||
import { isEqual } from "lodash-es";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { Field, ID, Type } from "facilmap-types";
|
||||
import type { Field, ID, Type } from "facilmap-types";
|
||||
import { clone } from "facilmap-utils";
|
||||
import { canControl, getUniqueId, validateRequired, validations } from "../../utils/utils";
|
||||
import { mergeTypeObject } from "./edit-type-utils";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { Field, FieldOption, FieldOptionUpdate, FieldUpdate, Type } from "facilmap-types";
|
||||
import type { Field, FieldOption, FieldOptionUpdate, FieldUpdate, Type } from "facilmap-types";
|
||||
import { clone } from "facilmap-utils";
|
||||
import { canControl, getUniqueId, mergeObject, validateRequired } from "../../utils/utils";
|
||||
import { isEqual } from "lodash-es";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { CRU, FieldUpdate, Type } from "facilmap-types";
|
||||
import type { CRU, FieldUpdate, Type } from "facilmap-types";
|
||||
import { clone } from "facilmap-utils";
|
||||
import { mergeObject } from "../../utils/utils";
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { FileResultObject } from "../utils/files";
|
||||
import type { FileResultObject } from "../utils/files";
|
||||
import Icon from "./ui/icon.vue";
|
||||
import SearchResults from "./search-results/search-results.vue";
|
||||
import { displayView } from "facilmap-leaflet";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { getLabelsForHistoryEntry, HistoryEntryLabels } from "./history-utils";
|
||||
import { HistoryEntry, ID } from "facilmap-types";
|
||||
import type { HistoryEntry, ID } from "facilmap-types";
|
||||
import { orderBy } from "lodash-es";
|
||||
import Icon from "../ui/icon.vue";
|
||||
import { computed, onScopeDispose, reactive, ref } from "vue";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { HistoryEntry } from "facilmap-types";
|
||||
import type { HistoryEntry } from "facilmap-types";
|
||||
import { getObjectDiff, ObjectDiffItem } from "facilmap-utils";
|
||||
import { Client } from "../client-context.vue";
|
||||
import type { Client } from "../client-context.vue";
|
||||
|
||||
function existsNow(client: Client, entry: HistoryEntry) {
|
||||
// Look through the history of this particular object and see if the last entry indicates that the object exists now
|
||||
|
|
|
@ -9,12 +9,12 @@ import "leaflet-graphicscale/src/Leaflet.GraphicScale.scss";
|
|||
import "leaflet-mouse-position";
|
||||
import "leaflet-mouse-position/src/L.Control.MousePosition.css";
|
||||
import SelectionHandler from "../../utils/selection";
|
||||
import { Client } from "../client-context.vue";
|
||||
import { MapComponents, MapContextData, MapContextEvents, WritableMapContext } from "./leaflet-map.vue";
|
||||
import type { Client } from "../client-context.vue";
|
||||
import type { MapComponents, MapContextData, MapContextEvents, WritableMapContext } from "./leaflet-map.vue";
|
||||
import { getHashQuery, openSpecialQuery } from "../../utils/zoom";
|
||||
import { Context } from "../../utils/context";
|
||||
import type { Context } from "../../utils/context";
|
||||
import mitt from "mitt";
|
||||
import { Optional } from "../../utils/utils";
|
||||
import type { Optional } from "../../utils/utils";
|
||||
|
||||
type MapContextWithoutComponents = Optional<WritableMapContext, 'components'>;
|
||||
|
||||
|
|
|
@ -1,21 +1,24 @@
|
|||
<script lang="ts">
|
||||
import { DeepReadonly, inject, InjectionKey, Ref, computed, onMounted, ref, defineComponent, provide } from "vue";
|
||||
import L, { LatLng, LatLngBounds, Map } from "leaflet";
|
||||
import type L from "leaflet";
|
||||
import type { LatLng, LatLngBounds, Map } from "leaflet";
|
||||
import "leaflet/dist/leaflet.css";
|
||||
import { BboxHandler, HashHandler, LinesLayer, MarkersLayer, SearchResultsLayer, OverpassLayer, VisibleLayers, HashQuery, OverpassPreset } from "facilmap-leaflet";
|
||||
import type { BboxHandler, HashHandler, LinesLayer, MarkersLayer, SearchResultsLayer, OverpassLayer, VisibleLayers, HashQuery, OverpassPreset } from "facilmap-leaflet";
|
||||
import "leaflet.locatecontrol";
|
||||
import "leaflet.locatecontrol/dist/L.Control.Locate.css";
|
||||
import "leaflet-graphicscale";
|
||||
import "leaflet-graphicscale/src/Leaflet.GraphicScale.scss";
|
||||
import "leaflet-mouse-position";
|
||||
import "leaflet-mouse-position/src/L.Control.MousePosition.css";
|
||||
import SelectionHandler, { SelectedItem } from "../../utils/selection";
|
||||
import type SelectionHandler from "../../utils/selection";
|
||||
import type { SelectedItem } from "../../utils/selection";
|
||||
import { injectClientRequired } from "../client-context.vue";
|
||||
import { injectContextRequired } from "../../utils/context";
|
||||
import { FindOnMapResult, Point, SearchResult } from "facilmap-types";
|
||||
import { FilterFunc } from "facilmap-utils";
|
||||
import { Emitter } from "mitt";
|
||||
import type { FindOnMapResult, Point, SearchResult } from "facilmap-types";
|
||||
import type { FilterFunc } from "facilmap-utils";
|
||||
import type { Emitter } from "mitt";
|
||||
import { createMapContext } from "./components";
|
||||
import vTooltip from "../../utils/tooltip";
|
||||
|
||||
export type MapContextEvents = {
|
||||
"import-file": void;
|
||||
|
@ -95,6 +98,7 @@
|
|||
const mapRef = ref<HTMLElement>();
|
||||
|
||||
const loaded = ref(false);
|
||||
const fatalError = ref<string>();
|
||||
|
||||
const selfUrl = computed(() => {
|
||||
return `${location.origin}${location.pathname}${mapContext.value?.hash ? `#${mapContext.value.hash}` : ''}`;
|
||||
|
@ -103,7 +107,13 @@
|
|||
const mapContext = ref<MapContext>();
|
||||
|
||||
onMounted(async () => {
|
||||
mapContext.value = await createMapContext(client, context, mapRef as Ref<HTMLElement>, innerContainerRef as Ref<HTMLElement>);
|
||||
try {
|
||||
mapContext.value = await createMapContext(client, context, mapRef as Ref<HTMLElement>, innerContainerRef as Ref<HTMLElement>);
|
||||
loaded.value = true;
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
fatalError.value = err.message;
|
||||
}
|
||||
});
|
||||
|
||||
const MapContextProvider = defineComponent({
|
||||
|
@ -128,7 +138,13 @@
|
|||
{{mapContext.overpassMessage}}
|
||||
</div>
|
||||
|
||||
<a v-if="context.linkLogo" :href="selfUrl" target="_blank" class="fm-open-external" uib-tooltip="Open FacilMap in full size" tooltip-placement="right"></a>
|
||||
<a
|
||||
v-if="context.linkLogo"
|
||||
:href="selfUrl"
|
||||
target="_blank"
|
||||
class="fm-open-external"
|
||||
v-tooltip.right="'Open FacilMap in full size'"
|
||||
></a>
|
||||
<div class="fm-logo">
|
||||
<img src="./logo.png"/>
|
||||
</div>
|
||||
|
@ -146,8 +162,8 @@
|
|||
</div>
|
||||
|
||||
<div class="fm-leaflet-map-disabled-cover" v-show="client.padId && (client.disconnected || client.serverError || client.deleted)"></div>
|
||||
<div class="fm-leaflet-map-loading" v-show="!loaded && !client.serverError">
|
||||
Loading...
|
||||
<div class="fm-leaflet-map-loading" v-show="!loaded && !client.serverError" :class="{ 'fatal-error': !!fatalError }">
|
||||
{{fatalError || 'Loading...'}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -254,6 +270,10 @@
|
|||
z-index:100000;
|
||||
font-size:1.5em;
|
||||
font-weight:bold;
|
||||
|
||||
&.fatal-error {
|
||||
color: #d00;
|
||||
}
|
||||
}
|
||||
|
||||
.fm-overpass-message {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { getMarkerHtml, getSymbolHtml } from "facilmap-leaflet";
|
||||
import { makeTypeFilter, markdownBlock } from "facilmap-utils";
|
||||
import { LegendItem, LegendType } from "./legend-utils";
|
||||
import type { LegendItem, LegendType } from "./legend-utils";
|
||||
import { createLinePlaceholderHtml } from "../../utils/ui";
|
||||
import Popover from "../ui/popover.vue";
|
||||
import { injectMapContextRequired } from "../leaflet-map/leaflet-map.vue";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { ID, Shape, Symbol, Type } from "facilmap-types";
|
||||
import type { ID, Shape, Symbol, Type } from "facilmap-types";
|
||||
import { symbolList } from "facilmap-leaflet";
|
||||
import { getBrightness } from "facilmap-utils";
|
||||
import { Client } from "../client-context.vue";
|
||||
import { MapContext } from "../leaflet-map/leaflet-map.vue";
|
||||
import type { Client } from "../client-context.vue";
|
||||
import type { MapContext } from "../leaflet-map/leaflet-map.vue";
|
||||
|
||||
export interface LegendType {
|
||||
key: string;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { ExportFormat, ID } from "facilmap-types";
|
||||
import type { ExportFormat, ID } from "facilmap-types";
|
||||
import EditLineDialog from "../edit-line-dialog.vue";
|
||||
import ElevationStats from "../ui/elevation-stats.vue";
|
||||
import ElevationPlot from "../ui/elevation-plot.vue";
|
||||
|
@ -8,7 +8,7 @@
|
|||
import RouteForm from "../route-form/route-form.vue";
|
||||
import { saveAs } from "file-saver";
|
||||
import vTooltip from "../../utils/tooltip";
|
||||
import { formatField, formatRouteMode, formatTime, round } from "facilmap-utils";
|
||||
import { formatField, formatRouteMode, formatTime, normalizeLineName, round } from "facilmap-utils";
|
||||
import { injectContextRequired } from "../../utils/context";
|
||||
import { injectClientRequired } from "../client-context.vue";
|
||||
import { injectMapContextRequired } from "../leaflet-map/leaflet-map.vue";
|
||||
|
@ -31,6 +31,7 @@
|
|||
|
||||
const routeForm = ref<InstanceType<typeof RouteForm>>();
|
||||
|
||||
const showEditDialog = ref(false);
|
||||
const isDeleting = ref(false);
|
||||
const isExporting = ref(false);
|
||||
const showElevationPlot = ref(false);
|
||||
|
@ -147,7 +148,7 @@
|
|||
<div class="d-flex align-items-center">
|
||||
<h2 class="flex-grow-1">
|
||||
<a v-if="showBackButton" href="javascript:" @click="$emit('back')"><Icon icon="arrow-left"></Icon></a>
|
||||
{{line.name || "Untitled line"}}
|
||||
{{normalizeLineName(line.name)}}
|
||||
</h2>
|
||||
<div v-if="!isMoving" class="btn-group">
|
||||
<button
|
||||
|
@ -225,7 +226,7 @@
|
|||
type="button"
|
||||
class="btn btn-light btn-sm"
|
||||
size="sm"
|
||||
v-b-modal="`fm${context.id}-line-info-edit`"
|
||||
@click="showEditDialog = true"
|
||||
:disabled="isDeleting || mapContext.interaction"
|
||||
>Edit data</button>
|
||||
|
||||
|
@ -251,7 +252,11 @@
|
|||
|
||||
<RouteForm v-if="isMoving" active ref="routeForm" :route-id="`l${line.id}`" :show-toolbar="false"></RouteForm>
|
||||
|
||||
<EditLineDialog :id="`fm${context.id}-line-info-edit`" :line-id="lineId"></EditLineDialog>
|
||||
<EditLineDialog
|
||||
v-if="showEditDialog"
|
||||
:lineId="lineId"
|
||||
@hidden="showEditDialog = false"
|
||||
></EditLineDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { ID, Type } from "facilmap-types";
|
||||
import type { ID, Type } from "facilmap-types";
|
||||
import EditTypeDialog from "./edit-type-dialog/edit-type-dialog.vue";
|
||||
import { injectContextRequired } from "../utils/context";
|
||||
import { injectClientRequired } from "./client-context.vue";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { ID, View } from "facilmap-types";
|
||||
import type { ID, View } from "facilmap-types";
|
||||
import { displayView } from "facilmap-leaflet";
|
||||
import { injectContextRequired } from "../utils/context";
|
||||
import { injectClientRequired } from "./client-context.vue";
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { FindOnMapResult, ID } from "facilmap-types";
|
||||
import type { FindOnMapResult, ID } from "facilmap-types";
|
||||
import { moveMarker } from "../../utils/draw";
|
||||
import EditMarkerDialog from "../edit-marker-dialog.vue";
|
||||
import { flyTo, getZoomDestinationForMarker } from "../../utils/zoom";
|
||||
import Icon from "../ui/icon.vue";
|
||||
import Coordinates from "../ui/coordinates.vue";
|
||||
import vTooltip from "../../utils/tooltip";
|
||||
import { formatField } from "facilmap-utils";
|
||||
import { formatField, normalizeMarkerName } from "facilmap-utils";
|
||||
import { computed, ref } from "vue";
|
||||
import { injectMapContextRequired } from "../leaflet-map/leaflet-map.vue";
|
||||
import { injectClientRequired } from "../client-context.vue";
|
||||
|
@ -27,6 +27,7 @@
|
|||
});
|
||||
|
||||
const isDeleting = ref(false);
|
||||
const showEditDialog = ref(false);
|
||||
|
||||
const marker = computed(() => client.markers[props.markerId]);
|
||||
|
||||
|
@ -62,7 +63,7 @@
|
|||
|
||||
const markerSuggestion: FindOnMapResult = { ...marker.value, kind: "marker", similarity: 1 };
|
||||
mapContext.emit(event, {
|
||||
query: marker.value.name,
|
||||
query: normalizeMarkerName(marker.value.name),
|
||||
mapSuggestions: [markerSuggestion],
|
||||
selectedSuggestion: markerSuggestion
|
||||
});
|
||||
|
@ -86,7 +87,7 @@
|
|||
<div class="fm-marker-info" v-if="marker">
|
||||
<h2>
|
||||
<a v-if="showBackButton" href="javascript:" @click="$emit('back')"><Icon icon="arrow-left"></Icon></a>
|
||||
{{marker.name || "Untitled marker"}}
|
||||
{{normalizeMarkerName(marker.name)}}
|
||||
</h2>
|
||||
<dl class="fm-search-box-collapse-point">
|
||||
<dt class="pos">Coordinates</dt>
|
||||
|
@ -146,7 +147,7 @@
|
|||
v-if="!client.readonly"
|
||||
type="button"
|
||||
class="btn btn-light btn-sm"
|
||||
v-b-modal="`fm${context.id}-marker-info-edit`"
|
||||
@click="showEditDialog = true"
|
||||
:disabled="isDeleting || mapContext.interaction"
|
||||
>Edit data</button>
|
||||
<button
|
||||
|
@ -168,7 +169,11 @@
|
|||
</button>
|
||||
</div>
|
||||
|
||||
<EditMarkerDialog :id="`fm${context.id}-marker-info-edit`" :markerId="markerId"></EditMarkerDialog>
|
||||
<EditMarkerDialog
|
||||
v-if="showEditDialog"
|
||||
:markerId="markerId"
|
||||
@hidden="showEditDialog = false"
|
||||
></EditMarkerDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import MultipleInfo from "./multiple-info.vue";
|
||||
import { Line, Marker } from "facilmap-types";
|
||||
import type { Line, Marker } from "facilmap-types";
|
||||
import { isLine, isMarker, useEventListener } from "../../utils/utils";
|
||||
import SearchBoxTab from "../search-box/search-box-tab.vue";
|
||||
import { injectContextRequired } from "../../utils/context";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { ID, Line, Marker } from "facilmap-types";
|
||||
import type { ID, Line, Marker } from "facilmap-types";
|
||||
import { combineZoomDestinations, flyTo, getZoomDestinationForLine, getZoomDestinationForMarker } from "../../utils/zoom";
|
||||
import Icon from "../ui/icon.vue";
|
||||
import { isLine, isMarker } from "../../utils/utils";
|
||||
|
@ -11,6 +11,7 @@
|
|||
import { injectClientRequired } from "../client-context.vue";
|
||||
import { injectContextRequired } from "../../utils/context";
|
||||
import { showConfirm } from "../ui/alert.vue";
|
||||
import { useCarousel } from "../../utils/carousel";
|
||||
|
||||
const context = injectContextRequired();
|
||||
const client = injectClientRequired();
|
||||
|
@ -24,7 +25,9 @@
|
|||
const isDeleting = ref(false);
|
||||
const openedObjectId = ref<ID>();
|
||||
const openedObjectType = ref<"marker" | "line">();
|
||||
const activeTab = ref(0);
|
||||
|
||||
const carouselRef = ref<HTMLElement>();
|
||||
const carousel = useCarousel(carouselRef);
|
||||
|
||||
function zoomToObject(object: Marker | Line): void {
|
||||
const zoomDestination = isMarker(object) ? getZoomDestinationForMarker(object) : isLine(object) ? getZoomDestinationForLine(object) : undefined;
|
||||
|
@ -35,7 +38,7 @@
|
|||
function openObject(object: Marker | Line): void {
|
||||
openedObjectId.value = object.id;
|
||||
openedObjectType.value = isMarker(object) ? "marker" : isLine(object) ? "line" : undefined;
|
||||
activeTab.value = 1;
|
||||
carousel.setTab(1);
|
||||
}
|
||||
|
||||
const openedObject = computed(() => {
|
||||
|
@ -52,7 +55,7 @@
|
|||
|
||||
watch(openedObject, () => {
|
||||
if (!openedObject.value)
|
||||
activeTab.value = 0;
|
||||
carousel.setTab(0);
|
||||
});
|
||||
|
||||
async function deleteObjects(): Promise<void> {
|
||||
|
@ -93,8 +96,8 @@
|
|||
|
||||
<template>
|
||||
<div class="fm-multiple-info">
|
||||
<b-carousel :interval="0" v-model="activeTab">
|
||||
<b-carousel-slide>
|
||||
<div class="carousel slide" ref="carouselRef">
|
||||
<div class="carousel-item" :class="{ active: carousel.tab === 0 }">
|
||||
<div class="fm-search-box-collapse-point">
|
||||
<ul class="list-group">
|
||||
<li v-for="object in props.objects" :key="`${isMarker(object) ? 'm' : 'l'}-${object.id}`" class="list-group-item active">
|
||||
|
@ -130,23 +133,23 @@
|
|||
Remove
|
||||
</button>
|
||||
</div>
|
||||
</b-carousel-slide>
|
||||
</div>
|
||||
|
||||
<b-carousel-slide>
|
||||
<div class="carousel-item" :class="{ active: carousel.tab === 1 }">
|
||||
<MarkerInfo
|
||||
v-if="openedObject && isMarker(openedObject)"
|
||||
:markerId="openedObject.id"
|
||||
show-back-button
|
||||
@back="activeTab = 0"
|
||||
@back="carousel.setTab(0)"
|
||||
></MarkerInfo>
|
||||
<LineInfo
|
||||
v-else-if="openedObject && isLine(openedObject)"
|
||||
:lineId="openedObject.id"
|
||||
show-back-button
|
||||
@back="activeTab = 0"
|
||||
@back="carousel.setTab(0)"
|
||||
></LineInfo>
|
||||
</b-carousel-slide>
|
||||
</b-carousel>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import Icon from "./ui/icon.vue";
|
||||
import { FindPadsResult } from "facilmap-types";
|
||||
import type { FindPadsResult } from "facilmap-types";
|
||||
import decodeURIComponent from "decode-uri-component";
|
||||
import { Context, injectContextRequired } from "../utils/context";
|
||||
import { injectClientContextRequired, injectClientRequired } from "./client-context.vue";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import OverpassForm from "./overpass-form.vue";
|
||||
import SearchBoxTab from "../search-box/search-box-tab.vue";
|
||||
import { injectContextRequired } from "../../utils/context";
|
||||
import { injectContextRequired } from "../../utils/context";
|
||||
|
||||
const context = injectContextRequired();
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { OverpassElement } from "facilmap-leaflet";
|
||||
import type { OverpassElement } from "facilmap-leaflet";
|
||||
import OverpassMultipleInfo from "./overpass-multiple-info.vue";
|
||||
import SearchBoxTab from "../search-box/search-box-tab.vue";
|
||||
import { useEventListener } from "../../utils/utils";
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { renderOsmTag } from "facilmap-utils";
|
||||
import Icon from "../ui/icon.vue";
|
||||
import { flyTo, getZoomDestinationForMarker } from "../../utils/zoom";
|
||||
import { OverpassElement } from "facilmap-leaflet";
|
||||
import type { OverpassElement } from "facilmap-leaflet";
|
||||
import Coordinates from "../ui/coordinates.vue";
|
||||
import vTooltip from "../../utils/tooltip";
|
||||
import { computed } from "vue";
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
import { combineZoomDestinations, flyTo, getZoomDestinationForMarker } from "../../utils/zoom";
|
||||
import Icon from "../ui/icon.vue";
|
||||
import OverpassInfo from "./overpass-info.vue";
|
||||
import { OverpassElement } from "facilmap-leaflet";
|
||||
import { CRU, Marker, Type } from "facilmap-types";
|
||||
import { SelectedItem } from "../../utils/selection";
|
||||
import type { OverpassElement } from "facilmap-leaflet";
|
||||
import type { CRU, Marker, Type } from "facilmap-types";
|
||||
import type { SelectedItem } from "../../utils/selection";
|
||||
import { mapTagsToType } from "../search-results/utils";
|
||||
import vTooltip from "../../utils/tooltip";
|
||||
import { injectContextRequired } from "../../utils/context";
|
||||
|
@ -12,6 +12,7 @@
|
|||
import { injectMapContextRequired } from "../leaflet-map/leaflet-map.vue";
|
||||
import { computed, ref } from "vue";
|
||||
import { useToasts } from "../ui/toasts/toasts.vue";
|
||||
import { useCarousel } from "../../utils/carousel";
|
||||
|
||||
const context = injectContextRequired();
|
||||
const client = injectClientRequired();
|
||||
|
@ -23,9 +24,11 @@
|
|||
}>();
|
||||
|
||||
const openedElement = ref<OverpassElement>();
|
||||
const activeTab = ref(0);
|
||||
const isAdding = ref(false);
|
||||
|
||||
const carouselRef = ref<HTMLElement>();
|
||||
const carousel = useCarousel(carouselRef);
|
||||
|
||||
const types = computed(() => {
|
||||
return Object.values(client.types).filter((type) => type.type == "marker");
|
||||
});
|
||||
|
@ -38,7 +41,7 @@
|
|||
|
||||
function openElement(element: OverpassElement): void {
|
||||
openedElement.value = element;
|
||||
activeTab.value = 1;
|
||||
carousel.setTab(1);
|
||||
}
|
||||
|
||||
function zoom(): void {
|
||||
|
@ -81,67 +84,70 @@
|
|||
|
||||
<template>
|
||||
<div class="fm-overpass-multiple-info">
|
||||
<OverpassInfo
|
||||
v-if="elements.length == 1"
|
||||
:element="elements[0]"
|
||||
:is-adding="isAdding"
|
||||
@add-to-map="addToMap(elements, $event)"
|
||||
></OverpassInfo>
|
||||
<b-carousel v-else :interval="0" v-model="activeTab">
|
||||
<b-carousel-slide>
|
||||
<div class="fm-search-box-collapse-point">
|
||||
<ul class="list-group">
|
||||
<li v-for="element in elements" :key="element.id" class="list-group-item active">
|
||||
<span>
|
||||
<a href="javascript:" @click="$emit('click-element', element, $event)">{{element.tags.name || 'Unnamed POI'}}</a>
|
||||
</span>
|
||||
<a href="javascript:" @click="zoomToElement(element)" v-tooltip.left="'Zoom to object'"><Icon icon="zoom-in" alt="Zoom"></Icon></a>
|
||||
<a href="javascript:" @click="openElement(element)" v-tooltip.right="'Show details'"><Icon icon="arrow-right" alt="Details"></Icon></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div v-if="client.padData && !client.readonly" class="btn-group">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-light btn-sm"
|
||||
v-tooltip="'Zoom to selection'"
|
||||
@click="zoom()"
|
||||
>
|
||||
<Icon icon="zoom-in" alt="Zoom to selection"></Icon>
|
||||
</button>
|
||||
|
||||
<div v-if="client.padData && !client.readonly && types.length > 0" class="dropdown">
|
||||
<button type="button" class="btn btn-light dropdown-toggle" :disabled="isAdding">
|
||||
<div v-if="isAdding" class="spinner-border spinner-border-sm"></div>
|
||||
Add to map
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<template v-for="type in types" :key="type.id">
|
||||
<li>
|
||||
<a
|
||||
href="javascript:"
|
||||
class="dropdown-item"
|
||||
@click="addToMap(elements, type)"
|
||||
>{{type.name}}</a>
|
||||
</li>
|
||||
</template>
|
||||
<template v-if="elements.length == 1">
|
||||
<OverpassInfo
|
||||
:element="elements[0]"
|
||||
:is-adding="isAdding"
|
||||
@add-to-map="addToMap(elements, $event)"
|
||||
></OverpassInfo>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="carousel slide" ref="carouselRef">
|
||||
<div class="carousel-item" :class="{ active: carousel.tab === 0 }">
|
||||
<div class="fm-search-box-collapse-point">
|
||||
<ul class="list-group">
|
||||
<li v-for="element in elements" :key="element.id" class="list-group-item active">
|
||||
<span>
|
||||
<a href="javascript:" @click="$emit('click-element', element, $event)">{{element.tags.name || 'Unnamed POI'}}</a>
|
||||
</span>
|
||||
<a href="javascript:" @click="zoomToElement(element)" v-tooltip.left="'Zoom to object'"><Icon icon="zoom-in" alt="Zoom"></Icon></a>
|
||||
<a href="javascript:" @click="openElement(element)" v-tooltip.right="'Show details'"><Icon icon="arrow-right" alt="Details"></Icon></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</b-carousel-slide>
|
||||
|
||||
<b-carousel-slide>
|
||||
<OverpassInfo
|
||||
v-if="openedElement"
|
||||
:element="openedElement"
|
||||
show-back-button
|
||||
:is-adding="isAdding"
|
||||
@back="activeTab = 0"
|
||||
@add-to-map="addToMap([openedElement], $event)"
|
||||
></OverpassInfo>
|
||||
</b-carousel-slide>
|
||||
</b-carousel>
|
||||
<div v-if="client.padData && !client.readonly" class="btn-group">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-light btn-sm"
|
||||
v-tooltip="'Zoom to selection'"
|
||||
@click="zoom()"
|
||||
>
|
||||
<Icon icon="zoom-in" alt="Zoom to selection"></Icon>
|
||||
</button>
|
||||
|
||||
<div v-if="client.padData && !client.readonly && types.length > 0" class="dropdown">
|
||||
<button type="button" class="btn btn-light dropdown-toggle" :disabled="isAdding">
|
||||
<div v-if="isAdding" class="spinner-border spinner-border-sm"></div>
|
||||
Add to map
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<template v-for="type in types" :key="type.id">
|
||||
<li>
|
||||
<a
|
||||
href="javascript:"
|
||||
class="dropdown-item"
|
||||
@click="addToMap(elements, type)"
|
||||
>{{type.name}}</a>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="carousel-item" :class="{ active: carousel.tab === 1 }">
|
||||
<OverpassInfo
|
||||
v-if="openedElement"
|
||||
:element="openedElement"
|
||||
show-back-button
|
||||
:is-adding="isAdding"
|
||||
@back="carousel.setTab(0)"
|
||||
@add-to-map="addToMap([openedElement], $event)"
|
||||
></OverpassInfo>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { CRU, PadData } from 'facilmap-types';
|
||||
import type { CRU, PadData } from 'facilmap-types';
|
||||
import { computed, ref } from 'vue';
|
||||
import { getUniqueId } from '../../utils/utils';
|
||||
import copyToClipboard from 'copy-to-clipboard';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from "vue";
|
||||
import { CRU, PadData } from "facilmap-types";
|
||||
import type { CRU, PadData } from "facilmap-types";
|
||||
import { clone, generateRandomPadId } from "facilmap-utils";
|
||||
import { getUniqueId, mergeObject } from "../../utils/utils";
|
||||
import { isEqual } from "lodash-es";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import RouteForm from "./route-form.vue";
|
||||
import { HashQuery } from "facilmap-leaflet";
|
||||
import type { HashQuery } from "facilmap-leaflet";
|
||||
import SearchBoxTab from "../search-box/search-box-tab.vue";
|
||||
import { ref } from "vue";
|
||||
import { injectMapContextRequired } from "../leaflet-map/leaflet-map.vue";
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import Icon from "../ui/icon.vue";
|
||||
import { formatRouteMode, formatTime, isSearchId, round, splitRouteQuery } from "facilmap-utils";
|
||||
import { useToasts } from "../ui/toasts/toasts.vue";
|
||||
import { ExportFormat, FindOnMapResult, SearchResult, Type } from "facilmap-types";
|
||||
import type { ExportFormat, FindOnMapResult, SearchResult, Type } from "facilmap-types";
|
||||
import { getMarkerIcon, HashQuery, MarkerLayer, RouteLayer } from "facilmap-leaflet";
|
||||
import { getZoomDestinationForRoute, flyTo, normalizeZoomDestination } from "../../utils/zoom";
|
||||
import { latLng, LatLng } from "leaflet";
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { HashQuery } from "facilmap-leaflet";
|
||||
import type { HashQuery } from "facilmap-leaflet";
|
||||
import mitt, { Emitter } from "mitt";
|
||||
import { InjectionKey, inject, provide, Ref, Slot, reactive, ref, readonly, DeepReadonly, watch, nextTick } from "vue";
|
||||
import { InjectionKey, inject, provide, Ref, reactive, ref, readonly, DeepReadonly, watch, nextTick } from "vue";
|
||||
import type { Slot } from "vue";
|
||||
|
||||
export type SearchBoxEventMap = {
|
||||
"resizestart": void;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, onBeforeUnmount, onMounted } from 'vue';
|
||||
import { SearchBoxTab, injectSearchBoxContextRequired } from './search-box-context.vue';
|
||||
import { HashQuery } from 'facilmap-leaflet';
|
||||
import { injectSearchBoxContextRequired } from './search-box-context.vue';
|
||||
import type { SearchBoxTab } from './search-box-context.vue';
|
||||
import type { HashQuery } from 'facilmap-leaflet';
|
||||
|
||||
const props = defineProps<{
|
||||
id: string;
|
||||
|
@ -38,4 +39,8 @@
|
|||
onBeforeUnmount(() => {
|
||||
searchBoxContext.removeTab(props.id);
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<!-- eslint-disable-next-line vue/valid-template-root -->
|
||||
<template>
|
||||
</template>
|
|
@ -110,7 +110,10 @@
|
|||
mapContext.components.map.invalidateSize({ pan: false });
|
||||
}
|
||||
|
||||
const TabContent = defineComponent<{ isActive: boolean }>({
|
||||
const TabContent = defineComponent({
|
||||
props: {
|
||||
isActive: Boolean
|
||||
},
|
||||
setup(props) {
|
||||
return () => searchBoxContext.activeTab?.content?.(props);
|
||||
}
|
||||
|
@ -221,16 +224,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.tabs, .tab-content, .vue-portal-target {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.card-body {
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.tabs, .tab-content, .tab-pane {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import SearchForm from "./search-form.vue";
|
||||
import { Util } from "leaflet";
|
||||
import { HashQuery } from "facilmap-leaflet";
|
||||
import type { HashQuery } from "facilmap-leaflet";
|
||||
import { injectContextRequired } from "../../utils/context";
|
||||
import { injectMapContextRequired } from "../leaflet-map/leaflet-map.vue";
|
||||
import { ref } from "vue";
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
import Icon from "../ui/icon.vue";
|
||||
import { isSearchId } from "facilmap-utils";
|
||||
import { useToasts } from "../ui/toasts/toasts.vue";
|
||||
import { FindOnMapResult, SearchResult } from "facilmap-types";
|
||||
import type { FindOnMapResult, SearchResult } from "facilmap-types";
|
||||
import SearchResults from "../search-results/search-results.vue";
|
||||
import { flyTo, getZoomDestinationForMapResult, getZoomDestinationForResults, getZoomDestinationForSearchResult, normalizeZoomDestination, openSpecialQuery } from "../../utils/zoom";
|
||||
import { Util } from "leaflet";
|
||||
import { isMapResult } from "../../utils/search";
|
||||
import storage from "../../utils/storage";
|
||||
import { HashQuery } from "facilmap-leaflet";
|
||||
import type { HashQuery } from "facilmap-leaflet";
|
||||
import { FileResultObject, parseFiles } from "../../utils/files";
|
||||
import FileResults from "../file-results.vue";
|
||||
import { injectContextRequired } from "../../utils/context";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import { renderOsmTag } from "facilmap-utils";
|
||||
import { Point, SearchResult } from "facilmap-types";
|
||||
import type { Point, SearchResult } from "facilmap-types";
|
||||
import Icon from "./ui/icon.vue";
|
||||
import { FileResult } from "../utils/files";
|
||||
import type { FileResult } from "../utils/files";
|
||||
import { isLineResult, isMarkerResult } from "../utils/search";
|
||||
import { flyTo, getZoomDestinationForSearchResult } from "../utils/zoom";
|
||||
import Coordinates from "./ui/coordinates.vue";
|
||||
|
@ -74,61 +74,63 @@
|
|||
</template>
|
||||
</dl>
|
||||
|
||||
<div class="btn-group" role="group">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-light btn-sm"
|
||||
v-tooltip="'Zoom to search result'"
|
||||
@click="zoomToResult()"
|
||||
>
|
||||
<Icon icon="zoom-in" alt="Zoom to search result"></Icon>
|
||||
</button>
|
||||
|
||||
<div v-if="!client.readonly && types.length > 0" class="dropdown">
|
||||
<button type="button" class="btn btn-light btn-sm dropdown-toggle" :disabled="isAdding">
|
||||
<div v-if="isAdding" class="spinner-border spinner-border-sm"></div>
|
||||
Add to map
|
||||
<div>
|
||||
<div class="btn-group" role="group">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-light btn-sm"
|
||||
v-tooltip="'Zoom to search result'"
|
||||
@click="zoomToResult()"
|
||||
>
|
||||
<Icon icon="zoom-in" alt="Zoom to search result"></Icon>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<template v-for="type in types" :key="type.id">
|
||||
|
||||
<div v-if="!client.readonly && types.length > 0" class="dropdown">
|
||||
<button type="button" class="btn btn-light btn-sm dropdown-toggle" :disabled="isAdding">
|
||||
<div v-if="isAdding" class="spinner-border spinner-border-sm"></div>
|
||||
Add to map
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<template v-for="type in types" :key="type.id">
|
||||
<li>
|
||||
<a
|
||||
href="javascript:"
|
||||
class="dropdown-item"
|
||||
@click="$emit('add-to-map', type)"
|
||||
>{{type.name}}</a>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div v-if="isMarker && context.search" class="dropdown">
|
||||
<button type="button" class="btn btn-light btn-sm dropdown-toggle">Use as</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a
|
||||
href="javascript:"
|
||||
class="dropdown-item"
|
||||
@click="$emit('add-to-map', type)"
|
||||
>{{type.name}}</a>
|
||||
@click="$emit('use-as-from')"
|
||||
>Route start</a>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div v-if="isMarker && context.search" class="dropdown">
|
||||
<button type="button" class="btn btn-light btn-sm dropdown-toggle">Use as</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a
|
||||
href="javascript:"
|
||||
class="dropdown-item"
|
||||
@click="$emit('use-as-from')"
|
||||
>Route start</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="javascript:"
|
||||
class="dropdown-item"
|
||||
@click="$emit('use-as-via')"
|
||||
>Route via</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a
|
||||
href="javascript:"
|
||||
class="dropdown-item"
|
||||
@click="$emit('use-as-via')"
|
||||
>Route via</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a
|
||||
href="javascript:"
|
||||
class="dropdown-item"
|
||||
@click="$emit('use-as-to')"
|
||||
>Route destination</a>
|
||||
</li>
|
||||
</ul>
|
||||
<li>
|
||||
<a
|
||||
href="javascript:"
|
||||
class="dropdown-item"
|
||||
@click="$emit('use-as-to')"
|
||||
>Route destination</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { ID, Type } from "facilmap-types";
|
||||
import { FileResult, FileResultObject } from "../../utils/files";
|
||||
import type { ID, Type } from "facilmap-types";
|
||||
import type { FileResult, FileResultObject } from "../../utils/files";
|
||||
import { addSearchResultsToMap } from "./utils";
|
||||
import { isLineResult, isMarkerResult, typeExists } from "../../utils/search";
|
||||
import { mapValues, pickBy, uniq } from "lodash-es";
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import { FindOnMapResult, SearchResult, Type } from "facilmap-types";
|
||||
import type { FindOnMapResult, SearchResult, Type } from "facilmap-types";
|
||||
import Icon from "../ui/icon.vue";
|
||||
import SearchResultInfo from "../search-result-info.vue";
|
||||
import { SelectedItem } from "../../utils/selection";
|
||||
import { FileResult, FileResultObject } from "../../utils/files";
|
||||
import type { SelectedItem } from "../../utils/selection";
|
||||
import type { FileResult, FileResultObject } from "../../utils/files";
|
||||
import { addSearchResultsToMap } from "./utils";
|
||||
import { isFileResult, isLineResult, isMapResult, isMarkerResult } from "../../utils/search";
|
||||
import { combineZoomDestinations, flyTo, getZoomDestinationForMapResult, getZoomDestinationForResults, getZoomDestinationForSearchResult } from "../../utils/zoom";
|
||||
|
@ -15,6 +15,7 @@
|
|||
import { computed, ref, watch } from "vue";
|
||||
import { useToasts } from "../ui/toasts/toasts.vue";
|
||||
import CustomImportDialog from "./custom-import-dialog.vue";
|
||||
import { useCarousel } from "../../utils/carousel";
|
||||
|
||||
const context = injectContextRequired();
|
||||
const client = injectClientRequired();
|
||||
|
@ -36,7 +37,8 @@
|
|||
customTypes: () => ({})
|
||||
});
|
||||
|
||||
const activeTab = ref(0);
|
||||
const carouselRef = ref<HTMLElement>();
|
||||
const carousel = useCarousel(carouselRef);
|
||||
const isAdding = ref(false);
|
||||
const customImport = ref(false);
|
||||
|
||||
|
@ -96,12 +98,12 @@
|
|||
});
|
||||
|
||||
function closeResult(): void {
|
||||
activeTab.value = 0;
|
||||
carousel.setTab(0);
|
||||
}
|
||||
|
||||
watch(openResult, () => {
|
||||
if (!openResult.value && activeTab.value != 0)
|
||||
activeTab.value = 0;
|
||||
if (!openResult.value && carousel.tab != 0)
|
||||
carousel.setTab(0);
|
||||
});
|
||||
|
||||
function handleClick(result: SearchResult | FileResult | FindOnMapResult, event: MouseEvent): void {
|
||||
|
@ -135,7 +137,7 @@
|
|||
await client.getMarker({ id: result.id });
|
||||
mapContext.emit("search-box-show-tab", { id: `fm${context.id}-${result.kind}-info-tab`, expand: false });
|
||||
} else
|
||||
activeTab.value = 1;
|
||||
carousel.setTab(1);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
|
@ -203,8 +205,8 @@
|
|||
|
||||
<template>
|
||||
<div class="fm-search-results" :class="{ isNarrow: context.isNarrow }">
|
||||
<b-carousel :interval="0" v-model="activeTab">
|
||||
<b-carousel-slide>
|
||||
<div class="carousel slide" ref="carouselRef">
|
||||
<div class="carousel-item" :class="{ active: carousel.tab === 0 }">
|
||||
<div v-if="(!searchResults || searchResults.length == 0) && (!mapResults || mapResults.length == 0)" class="alert alert-danger">No results have been found.</div>
|
||||
|
||||
<div class="fm-search-box-collapse-point">
|
||||
|
@ -300,9 +302,9 @@
|
|||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</b-carousel-slide>
|
||||
</div>
|
||||
|
||||
<b-carousel-slide>
|
||||
<div class="carousel-item" :class="{ active: carousel.tab === 1 }">
|
||||
<SearchResultInfo
|
||||
v-if="openResult"
|
||||
:result="openResult"
|
||||
|
@ -314,8 +316,8 @@
|
|||
@use-as-via="useAsVia(openResult)"
|
||||
@use-as-to="useAsTo(openResult)"
|
||||
></SearchResultInfo>
|
||||
</b-carousel-slide>
|
||||
</b-carousel>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<CustomImportDialog
|
||||
v-if="customImport"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { CRU, Line, Marker, Point, SearchResult, Type } from "facilmap-types";
|
||||
import { LineString, MultiLineString, MultiPolygon, Polygon, Position } from "geojson";
|
||||
import { FileResult } from "../../utils/files";
|
||||
import { SelectedItem } from "../../utils/selection";
|
||||
import { Client } from "../client-context.vue";
|
||||
import type { CRU, Line, Marker, Point, SearchResult, Type } from "facilmap-types";
|
||||
import type { LineString, MultiLineString, MultiPolygon, Polygon, Position } from "geojson";
|
||||
import type { FileResult } from "../../utils/files";
|
||||
import type { SelectedItem } from "../../utils/selection";
|
||||
import type { Client } from "../client-context.vue";
|
||||
|
||||
/**
|
||||
* Prefills the fields of a type with information from a search result. The "address" and "extratags" from
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { getLayers } from "facilmap-leaflet";
|
||||
import copyToClipboard from "copy-to-clipboard";
|
||||
import { getLegendItems } from "./legend/legend-utils";
|
||||
import { Writable } from "facilmap-types";
|
||||
import type { Writable } from "facilmap-types";
|
||||
import { quoteHtml, round } from "facilmap-utils";
|
||||
import { injectMapContextRequired } from "./leaflet-map/leaflet-map.vue";
|
||||
import { injectClientRequired } from "./client-context.vue";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { Type } from "facilmap-types";
|
||||
import type { Type } from "facilmap-types";
|
||||
import { drawLine, drawMarker } from "../../utils/draw";
|
||||
import { injectClientRequired } from "../client-context.vue";
|
||||
import { ref } from "vue";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { displayView } from "facilmap-leaflet";
|
||||
import { View } from "facilmap-types";
|
||||
import type { View } from "facilmap-types";
|
||||
import SaveViewDialog from "../save-view-dialog.vue";
|
||||
import ManageViewsDialog from "../manage-views-dialog.vue";
|
||||
import { injectClientRequired } from "../client-context.vue";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { Point } from "facilmap-types";
|
||||
import type { Point } from "facilmap-types";
|
||||
import copyToClipboard from "copy-to-clipboard";
|
||||
import { round } from "facilmap-utils";
|
||||
import Icon from "./icon.vue";
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import FmHeightgraph from "../../utils/heightgraph";
|
||||
import { LineWithTrackPoints, RouteWithTrackPoints } from "facilmap-client";
|
||||
import $ from "jquery";
|
||||
import type { LineWithTrackPoints, RouteWithTrackPoints } from "facilmap-client";
|
||||
import { injectMapContextRequired } from "../leaflet-map/leaflet-map.vue";
|
||||
import { injectSearchBoxContextOptional, injectSearchBoxContextRequired } from "../search-box/search-box-context.vue";
|
||||
import { injectSearchBoxContextOptional } from "../search-box/search-box-context.vue";
|
||||
import { onBeforeUnmount, onMounted, ref, watch } from "vue";
|
||||
import { useDomEventListener, useEventListener } from "../../utils/utils";
|
||||
import { useDomEventListener, useEventListener } from "../../utils/utils";
|
||||
|
||||
const props = defineProps<{
|
||||
route: RouteWithTrackPoints | LineWithTrackPoints;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { sortBy } from "lodash-es";
|
||||
import { LineWithTrackPoints, RouteWithTrackPoints } from "facilmap-client";
|
||||
import type { LineWithTrackPoints, RouteWithTrackPoints } from "facilmap-client";
|
||||
import { createElevationStats } from "../../utils/heightgraph";
|
||||
import Icon from "./icon.vue";
|
||||
import { numberKeys, round } from "facilmap-utils";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { Field } from "facilmap-types";
|
||||
import { computed } from "vue";
|
||||
import type { Field } from "facilmap-types";
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
field: Field;
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
showPopover.value = false;
|
||||
} else if (!showModal.value && !showPopover.value) {
|
||||
if (shouldUseModal.value) {
|
||||
showModal.value = true;
|
||||
modal.hide();
|
||||
} else {
|
||||
showPopover.value = true;
|
||||
}
|
||||
|
@ -47,7 +47,8 @@
|
|||
|
||||
const trigger = ref<HTMLElement>();
|
||||
|
||||
const modal = useModal({
|
||||
const modalRef = ref<HTMLElement>();
|
||||
const modal = useModal(modalRef, {
|
||||
onHidden: () => {
|
||||
showModal.value = false;
|
||||
show.value = false;
|
||||
|
@ -89,7 +90,7 @@
|
|||
</Popover>
|
||||
|
||||
<Teleport to="body">
|
||||
<div v-if="showModal" class="modal fade" :class="props.customClass" tabindex="-1" aria-hidden="true" :ref="modal.ref">
|
||||
<div v-if="showModal" class="modal fade" :class="props.customClass" tabindex="-1" aria-hidden="true" ref="modalRef">
|
||||
<div class="modal-dialog modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div v-if="props.title" class="modal-header">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { RouteMode as RouteModeType } from "facilmap-types";
|
||||
import type { RouteMode as RouteModeType } from "facilmap-types";
|
||||
import { DecodedRouteMode, decodeRouteMode, encodeRouteMode } from "facilmap-utils";
|
||||
import Icon from "./icon.vue";
|
||||
import { computed, ref, watch } from "vue";
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { getMarkerUrl, shapeList } from "facilmap-leaflet";
|
||||
import { quoteHtml } from "facilmap-utils";
|
||||
import Picker from "./picker.vue";
|
||||
import { Shape } from "facilmap-types";
|
||||
import type { Shape } from "facilmap-types";
|
||||
import { arrowNavigation } from "../../utils/ui";
|
||||
import { keyBy, mapValues } from "lodash-es";
|
||||
import PrerenderedList from "./prerendered-list.vue";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Directive } from "vue";
|
||||
import type { Directive } from "vue";
|
||||
import { isPromise } from "../../../utils/utils";
|
||||
import { getValidatedForm } from "./validated-form.vue";
|
||||
import { ToastContext, useToasts } from "../toasts/toasts.vue";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: number | undefined;
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import { Carousel } from "bootstrap";
|
||||
import { Ref, reactive, readonly, watch } from "vue";
|
||||
|
||||
export interface CarouselContext {
|
||||
tab: number;
|
||||
setTab(tab: number): void;
|
||||
}
|
||||
|
||||
export function useCarousel(element: Ref<HTMLElement | undefined>): Readonly<CarouselContext> {
|
||||
const context = reactive<CarouselContext>({
|
||||
tab: 0,
|
||||
setTab: (tab) => {
|
||||
const carousel = element.value && Carousel.getInstance(element.value);
|
||||
if (carousel) {
|
||||
carousel.to(tab);
|
||||
} else {
|
||||
context.tab = tab;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
watch(element, (newRef, oldRef, onCleanup) => {
|
||||
if (newRef) {
|
||||
const carousel = new Carousel(newRef, {
|
||||
interval: 0,
|
||||
wrap: false
|
||||
});
|
||||
|
||||
if (context.tab !== 0) {
|
||||
carousel.to(context.tab);
|
||||
}
|
||||
|
||||
newRef.addEventListener("slide.bs.carousel", handleSlide);
|
||||
|
||||
onCleanup(() => {
|
||||
carousel.dispose();
|
||||
newRef.removeEventListener("slide.bs.carousel", handleSlide);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function handleSlide(e: Event) {
|
||||
const event = e as Event & Carousel.Event;
|
||||
context.tab = event.to;
|
||||
}
|
||||
|
||||
return readonly(context);
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
import { addClickListener } from "facilmap-leaflet";
|
||||
import { ID, Type } from "facilmap-types";
|
||||
import type { ID, Type } from "facilmap-types";
|
||||
import { getUniqueId } from "./utils";
|
||||
import { ToastContext } from "../components/ui/toasts/toasts.vue";
|
||||
import { Client } from "../components/client-context.vue";
|
||||
import { MapContext } from "../components/leaflet-map/leaflet-map.vue";
|
||||
import type { ToastContext } from "../components/ui/toasts/toasts.vue";
|
||||
import type { Client } from "../components/client-context.vue";
|
||||
import type { MapContext } from "../components/leaflet-map/leaflet-map.vue";
|
||||
|
||||
export function drawMarker(type: Type, client: Client, mapContext: MapContext, toasts: ToastContext): void {
|
||||
const clickListener = addClickListener(mapContext.components.map, async (point) => {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { gpx, kml, tcx } from "@tmcw/togeojson";
|
||||
import osmtogeojson from "osmtogeojson";
|
||||
import $ from "jquery";
|
||||
import { Feature, Geometry } from "geojson";
|
||||
import { GeoJsonExport, LineFeature, MarkerFeature, SearchResult } from "facilmap-types";
|
||||
import type { Feature, Geometry } from "geojson";
|
||||
import type { GeoJsonExport, LineFeature, MarkerFeature, SearchResult } from "facilmap-types";
|
||||
import { flattenObject } from "facilmap-utils";
|
||||
|
||||
type FmFeatureProperties = Partial<MarkerFeature["properties"]> | Partial<LineFeature["properties"]>;
|
||||
|
|
|
@ -2,9 +2,9 @@ import 'leaflet.heightgraph';
|
|||
import { Control, Map, Polyline } from 'leaflet';
|
||||
import "leaflet.heightgraph/src/L.Control.Heightgraph.css";
|
||||
import "./heightgraph.scss";
|
||||
import { TrackPoints } from 'facilmap-client';
|
||||
import { ExtraInfo, TrackPoint } from 'facilmap-types';
|
||||
import { FeatureCollection } from "geojson";
|
||||
import type { TrackPoints } from 'facilmap-client';
|
||||
import type { ExtraInfo, TrackPoint } from 'facilmap-types';
|
||||
import type { FeatureCollection } from "geojson";
|
||||
import { calculateDistance, round } from 'facilmap-utils';
|
||||
|
||||
function trackSegment(trackPoints: TrackPoints, fromIdx: number, toIdx: number): TrackPoint[] {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Directive } from "vue";
|
||||
import type { Directive } from "vue";
|
||||
|
||||
const vLinkDisabled: Directive<HTMLAnchorElement, boolean> = (el, binding) => {
|
||||
if (binding.value) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { FindOnMapResult, SearchResult } from "facilmap-types";
|
||||
import type { FindOnMapResult, SearchResult } from "facilmap-types";
|
||||
import { numberKeys } from "facilmap-utils";
|
||||
import { isEqual } from "lodash-es";
|
||||
import { Client } from "./decorators";
|
||||
import { FileResult, FileResultObject } from "./files";
|
||||
import type { FileResult, FileResultObject } from "./files";
|
||||
import type { Client } from "../components/client-context.vue";
|
||||
|
||||
const VIEW_KEYS: Array<keyof FileResultObject["views"][0]> = ["name", "baseLayer", "layers", "top", "bottom", "left", "right", "filter"];
|
||||
const TYPE_KEYS: Array<keyof FileResultObject["types"][0]> = ["name", "type", "defaultColour", "colourFixed", "defaultSize", "sizeFixed", "defaultSymbol", "symbolFixed", "defaultShape", "shapeFixed", "defaultWidth", "widthFixed", "defaultMode", "modeFixed", "fields"];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ID, SearchResult } from "facilmap-types";
|
||||
import type { ID, SearchResult } from "facilmap-types";
|
||||
import { DomEvent, Evented, Handler, LatLngBounds, LeafletEvent, Map, Point, Polyline, Util } from "leaflet";
|
||||
import { LinesLayer, MarkerLayer, MarkersLayer, OverpassElement, OverpassLayer, SearchResultsLayer } from "facilmap-leaflet";
|
||||
import BoxSelection from "./box-selection";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { PadId } from "facilmap-types";
|
||||
import type { PadId } from "facilmap-types";
|
||||
import { isEqual } from "lodash-es";
|
||||
import { reactive, watch } from "vue";
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Tooltip } from "bootstrap";
|
||||
import { Directive } from "vue";
|
||||
import type { Directive } from "vue";
|
||||
|
||||
declare global {
|
||||
interface Element {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { isEqual } from "lodash-es";
|
||||
import { clone } from "facilmap-utils";
|
||||
import { Field, Line, Marker, Type } from "facilmap-types";
|
||||
import { Emitter } from "mitt";
|
||||
import type { Field, Line, Marker, Type } from "facilmap-types";
|
||||
import type { Emitter } from "mitt";
|
||||
import { DeepReadonly, onBeforeUnmount, onMounted } from "vue";
|
||||
|
||||
export type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import { LatLng, latLng, LatLngBounds, latLngBounds, Map } from "leaflet";
|
||||
import { fmToLeafletBbox, HashQuery, OverpassElement } from "facilmap-leaflet";
|
||||
import { RouteWithTrackPoints } from "facilmap-client";
|
||||
import { SelectedItem } from "./selection";
|
||||
import { FindOnMapLine, FindOnMapMarker, FindOnMapResult, Line, Marker, SearchResult } from "facilmap-types";
|
||||
import { Geometry } from "geojson";
|
||||
import type { RouteWithTrackPoints } from "facilmap-client";
|
||||
import type { SelectedItem } from "./selection";
|
||||
import type { FindOnMapLine, FindOnMapMarker, FindOnMapResult, Line, Marker, SearchResult } from "facilmap-types";
|
||||
import type { Geometry } from "geojson";
|
||||
import { isMapResult } from "./search";
|
||||
import { decodeLonLatUrl } from "facilmap-utils";
|
||||
import { Client } from "./client";
|
||||
import { Context } from "./context";
|
||||
import { MapContext } from "../components/leaflet-map/leaflet-map.vue";
|
||||
import { decodeLonLatUrl, normalizeLineName, normalizeMarkerName } from "facilmap-utils";
|
||||
import type { Client } from "./client";
|
||||
import type { Context } from "./context";
|
||||
import type { MapContext } from "../components/leaflet-map/leaflet-map.vue";
|
||||
|
||||
export type ZoomDestination = {
|
||||
center?: LatLng;
|
||||
|
@ -119,13 +119,13 @@ export function getHashQuery(map: Map, client: Client, items: SelectedItem[]): H
|
|||
const marker = client.markers[items[0].id];
|
||||
return {
|
||||
query: `m${items[0].id}`,
|
||||
...(marker ? { ...normalizeZoomDestination(map, getZoomDestinationForMarker(marker)), description: marker.name || "Untitled marker" } : {})
|
||||
...(marker ? { ...normalizeZoomDestination(map, getZoomDestinationForMarker(marker)), description: normalizeMarkerName(marker.name) } : {})
|
||||
};
|
||||
} else if (items[0].type == "line") {
|
||||
const line = client.lines[items[0].id];
|
||||
return {
|
||||
query: `l${items[0].id}`,
|
||||
...(line ? { ...normalizeZoomDestination(map, getZoomDestinationForLine(line)), description: line.name || "Untitled line" } : {})
|
||||
...(line ? { ...normalizeZoomDestination(map, getZoomDestinationForLine(line)), description: normalizeLineName(line.name) } : {})
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
"skipLibCheck": true,
|
||||
"experimentalDecorators": true,
|
||||
"resolveJsonModule": true,
|
||||
"module": "esnext"
|
||||
"module": "esnext",
|
||||
"importsNotUsedAsValues": "error"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
|
@ -23,5 +23,9 @@
|
|||
"eslint-plugin-vue": "^9.18.1"
|
||||
},
|
||||
"version": "0.0.0",
|
||||
"packageManager": "yarn@3.6.3"
|
||||
"packageManager": "yarn@3.6.3",
|
||||
"resolutions": {
|
||||
"vite": "4.5.0",
|
||||
"rollup": "3.29.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { jsonStream, asyncIteratorToArray } from "../utils/streams.js";
|
||||
import { compileExpression } from "facilmap-utils";
|
||||
import { compileExpression, normalizeLineName, normalizeMarkerName } from "facilmap-utils";
|
||||
import { Marker, MarkerFeature, LineFeature, PadId } from "facilmap-types";
|
||||
import Database from "../database/database.js";
|
||||
import { clone, keyBy, mapValues, omit } from "lodash-es";
|
||||
|
@ -67,7 +67,7 @@ function markerToGeoJson(marker: Marker): MarkerFeature {
|
|||
coordinates: [marker.lon, marker.lat]
|
||||
},
|
||||
properties: {
|
||||
name: marker.name || "Untitled marker",
|
||||
name: normalizeMarkerName(marker.name),
|
||||
colour: marker.colour,
|
||||
size: marker.size,
|
||||
symbol: marker.symbol,
|
||||
|
@ -86,7 +86,7 @@ function lineToGeoJson(line: LineWithTrackPoints): LineFeature {
|
|||
coordinates: line.trackPoints.map((trackPoint) => [trackPoint.lon, trackPoint.lat])
|
||||
},
|
||||
properties: {
|
||||
name: line.name || "Untitled line",
|
||||
name: normalizeLineName(line.name),
|
||||
mode: line.mode,
|
||||
colour: line.colour,
|
||||
width: line.width,
|
||||
|
|
|
@ -2,7 +2,7 @@ import { asyncIteratorToArray, asyncIteratorToStream } from "../utils/streams.js
|
|||
import { compile } from "ejs";
|
||||
import Database from "../database/database.js";
|
||||
import { Field, PadId, Type } from "facilmap-types";
|
||||
import { compileExpression, quoteHtml } from "facilmap-utils";
|
||||
import { compileExpression, normalizeLineName, normalizeMarkerName, quoteHtml } from "facilmap-utils";
|
||||
import { LineWithTrackPoints } from "../database/line.js";
|
||||
import { keyBy } from "lodash-es";
|
||||
import gpxLineEjs from "./gpx-line.ejs?raw";
|
||||
|
@ -45,7 +45,7 @@ export function exportGpx(database: Database, padId: PadId, useTracks: boolean,
|
|||
if (filterFunc(marker, types[marker.typeId])) {
|
||||
yield (
|
||||
`\t<wpt lat="${quoteHtml(marker.lat)}" lon="${quoteHtml(marker.lon)}"${marker.ele != null ? ` ele="${quoteHtml(marker.ele)}"` : ""}>\n` +
|
||||
`\t\t<name>${quoteHtml(marker.name || "Untitled marker")}</name>\n` +
|
||||
`\t\t<name>${quoteHtml(normalizeMarkerName(marker.name))}</name>\n` +
|
||||
`\t\t<desc>${quoteHtml(dataToText(types[marker.typeId].fields, marker.data))}</desc>\n` +
|
||||
`\t</wpt>\n`
|
||||
);
|
||||
|
@ -57,7 +57,7 @@ export function exportGpx(database: Database, padId: PadId, useTracks: boolean,
|
|||
if (useTracks || line.mode == "track") {
|
||||
yield (
|
||||
`\t<trk>\n` +
|
||||
`\t\t<name>${quoteHtml(line.name || "Untitled line")}</name>\n` +
|
||||
`\t\t<name>${quoteHtml(normalizeLineName(line.name))}</name>\n` +
|
||||
`\t\t<desc>${dataToText(types[line.typeId].fields, line.data)}</desc>\n` +
|
||||
`\t\t<trkseg>\n` +
|
||||
line.trackPoints.map((trackPoint) => (
|
||||
|
@ -69,7 +69,7 @@ export function exportGpx(database: Database, padId: PadId, useTracks: boolean,
|
|||
} else {
|
||||
yield (
|
||||
`\t<rte>\n` +
|
||||
`\t\t<name>${quoteHtml(line.name || "Untitled line")}</name>\n` +
|
||||
`\t\t<name>${quoteHtml(normalizeLineName(line.name))}</name>\n` +
|
||||
`\t\t<desc>${quoteHtml(dataToText(types[line.typeId].fields, line.data))}</desc>\n` +
|
||||
line.routePoints.map((routePoint) => (
|
||||
`\t\t<rtept lat="${quoteHtml(routePoint.lat)}" lon="${quoteHtml(routePoint.lon)}" />\n`
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
"scripts": {
|
||||
"build": "vite build",
|
||||
"watch": "vite build --watch",
|
||||
"clean": "rimraf dist"
|
||||
"clean": "rimraf dist",
|
||||
"check-types": "tsc --noEmit"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
|
|
|
@ -28,6 +28,9 @@ export type Width = z.infer<typeof widthValidator>;
|
|||
export const idValidator = z.number();
|
||||
export type ID = z.infer<typeof idValidator>;
|
||||
|
||||
export const padIdValidator = z.string();
|
||||
export type PadId = z.infer<typeof padIdValidator>;
|
||||
|
||||
export const routeModeValidator = z.string();
|
||||
export type RouteMode = z.infer<typeof routeModeValidator>;
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { ID } from "./base.js";
|
||||
import { ID, PadId } from "./base.js";
|
||||
import { Marker } from "./marker.js";
|
||||
import { Line } from "./line.js";
|
||||
import { View } from "./view.js";
|
||||
import { PadData, PadId } from "./padData.js";
|
||||
import { PadData } from "./padData.js";
|
||||
import { Type } from "./type.js";
|
||||
|
||||
export type HistoryEntryType = "Marker" | "Line" | "View" | "Type" | "Pad";
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { bboxValidator, colourValidator, idValidator, pointValidator, routeModeValidator, zoomLevelValidator } from "./base.js";
|
||||
import { bboxValidator, colourValidator, idValidator, padIdValidator, pointValidator, routeModeValidator, zoomLevelValidator } from "./base.js";
|
||||
import { CRU, CRUType, cruValidator } from "./cru";
|
||||
import { padIdValidator } from "./padData.js";
|
||||
import * as z from "zod";
|
||||
|
||||
export const extraInfoValidator = z.record(z.array(z.tuple([z.number(), z.number(), z.number()])));
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { colourValidator, idValidator, pointValidator, shapeValidator, sizeValidator, symbolValidator } from "./base.js";
|
||||
import { colourValidator, idValidator, padIdValidator, pointValidator, shapeValidator, sizeValidator, symbolValidator } from "./base.js";
|
||||
import { CRU, CRUType, cruValidator } from "./cru";
|
||||
import { padIdValidator } from "./padData.js";
|
||||
import * as z from "zod";
|
||||
|
||||
export const markerValidator = cruValidator({
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
import { viewValidator } from "./view.js";
|
||||
import { idValidator } from "./base.js";
|
||||
import { idValidator, padIdValidator } from "./base.js";
|
||||
import * as z from "zod";
|
||||
import { CRU, CRUType, cruValidator } from "./cru";
|
||||
|
||||
export const padIdValidator = z.string();
|
||||
export type PadId = z.infer<typeof padIdValidator>;
|
||||
|
||||
export enum Writable {
|
||||
READ = 0,
|
||||
WRITE = 1,
|
||||
|
|
|
@ -61,15 +61,17 @@ export type FindOnMapMarker = Pick<Marker, "id" | "name" | "typeId" | "lat" | "l
|
|||
export type FindOnMapLine = Pick<Line, "id" | "name" | "typeId" | "left" | "top" | "right" | "bottom"> & { kind: "line"; similarity: number };
|
||||
export type FindOnMapResult = FindOnMapMarker | FindOnMapLine;
|
||||
|
||||
const voidValidator = z.null().or(z.undefined()) as any as z.ZodVoid;
|
||||
|
||||
export const requestDataValidators = {
|
||||
updateBbox: bboxWithZoomValidator,
|
||||
getPad: getPadQueryValidator,
|
||||
findPads: findPadsQueryValidator,
|
||||
createPad: padDataValidator.create,
|
||||
editPad: padDataValidator.update,
|
||||
deletePad: z.void(),
|
||||
listenToHistory: z.void(),
|
||||
stopListeningToHistory: z.void(),
|
||||
deletePad: voidValidator,
|
||||
listenToHistory: voidValidator,
|
||||
stopListeningToHistory: voidValidator,
|
||||
revertHistoryEntry: objectWithIdValidator,
|
||||
getMarker: objectWithIdValidator,
|
||||
addMarker: markerValidator.create,
|
||||
|
@ -93,7 +95,7 @@ export const requestDataValidators = {
|
|||
addView: viewValidator.create,
|
||||
editView: viewValidator.update,
|
||||
deleteView: objectWithIdValidator,
|
||||
geoip: z.void(),
|
||||
geoip: voidValidator,
|
||||
setPadId: z.string()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { colourValidator, idValidator, routeModeValidator, shapeValidator, sizeValidator, symbolValidator, widthValidator } from "./base.js";
|
||||
import { colourValidator, idValidator, padIdValidator, routeModeValidator, shapeValidator, sizeValidator, symbolValidator, widthValidator } from "./base.js";
|
||||
import { CRU, CRUType, cruValidator } from "./cru";
|
||||
import { padIdValidator } from "./padData.js";
|
||||
import * as z from "zod";
|
||||
|
||||
export const objectTypeValidator = z.enum(["marker", "line"]);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { bboxValidator, idValidator, layerValidator } from "./base.js";
|
||||
import { padIdValidator } from "./padData.js";
|
||||
import { bboxValidator, idValidator, layerValidator, padIdValidator } from "./base.js";
|
||||
import { CRU, CRUType, cruValidator } from "./cru.js";
|
||||
import * as z from "zod";
|
||||
|
||||
|
|
|
@ -146,3 +146,11 @@ export async function sleep(ms: number): Promise<void> {
|
|||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
||||
export function normalizeMarkerName(name: string | undefined): string {
|
||||
return name || "Untitled marker";
|
||||
}
|
||||
|
||||
export function normalizeLineName(name: string | undefined): string {
|
||||
return name || "Untitled line";
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue