Planovac, zobrazeni vzdusnych prostoru
This commit is contained in:
@@ -3,14 +3,14 @@ import {useFlightsStore} from "stores/Flights";
|
||||
|
||||
export default {
|
||||
preFetch({currentRoute}) {
|
||||
useFlightsStore().fetchDetail(currentRoute.params.id);
|
||||
return useFlightsStore().fetchDetail(currentRoute.params.id);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {watch} from "vue";
|
||||
import {onMounted, watch} from "vue";
|
||||
import FlightDetailSkeleton from "components/flights/skeletons/FlightDetailSkeleton.vue";
|
||||
import {flightName} from "src/composables/flight";
|
||||
import {useAppStore} from "stores/App";
|
||||
@@ -28,20 +28,18 @@ import {toggleVisibility} from "src/composables/form/formHandling";
|
||||
import PublishButton from "components/inputs/PublishButton.vue";
|
||||
import CopyLinkButton from "components/inputs/CopyLinkButton.vue";
|
||||
import {TOGGLE_FLIGHT_PUBLISH} from "src/graphql/mutations/flight";
|
||||
import {useAirspacesStore} from "stores/Airspaces";
|
||||
|
||||
const flightId = parseInt(useRoute().params.id);
|
||||
const loggedUser = storeToRefs(useLoggedUserStore()).user;
|
||||
|
||||
const {isQueryRunning, flight} = storeToRefs(useFlightsStore());
|
||||
watch(() => flight.value, (f) => {
|
||||
if (!f) return;
|
||||
const flightNameFormatted = flightName(f);
|
||||
useAppStore().setPageTitle(flightNameFormatted);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: "myFlights"}, label: "Moje lety"},
|
||||
{label: flightNameFormatted}
|
||||
]);
|
||||
});
|
||||
const flightNameFormatted = flightName(flight.value);
|
||||
useAppStore().setPageTitle(flightNameFormatted);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: "myFlights"}, label: "Moje lety"},
|
||||
{label: flightNameFormatted}
|
||||
]);
|
||||
|
||||
const $q = useQuasar();
|
||||
const $router = useRouter();
|
||||
@@ -53,7 +51,12 @@ const handleDeleteAndRedirect = () => {
|
||||
$q.notify(successObject(`Úspěšně smazáno`));
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const {airspaces: airspacesData} = storeToRefs(useAirspacesStore());
|
||||
onMounted(() => {
|
||||
useAirspacesStore().fetch();
|
||||
});
|
||||
|
||||
const togglePublicVisibility = (variables) => toggleVisibility({
|
||||
$q, store: useFlightsStore(), object: flight.value, mutation: TOGGLE_FLIGHT_PUBLISH, variables
|
||||
@@ -144,6 +147,7 @@ const togglePublicVisibility = (variables) => toggleVisibility({
|
||||
|
||||
<q-no-ssr v-else>
|
||||
<FlightTrackMap
|
||||
:airspaces-data="airspacesData"
|
||||
:flight="flight"
|
||||
:photos="flight.photos"
|
||||
/>
|
||||
|
||||
@@ -1,34 +1,189 @@
|
||||
<script setup>
|
||||
import MapWithMarkers from "components/map/MapWithMarkers.vue";
|
||||
import {onMounted, ref, watch} from "vue";
|
||||
import {computed, defineEmits, onMounted, ref, watch} from "vue";
|
||||
import {usePointsOfInterestStore} from "stores/PointsOfInterest";
|
||||
import ComboboxInput from "components/inputs/ComboboxInput.vue";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {debounce} from "quasar";
|
||||
import {useQuasar} from "quasar";
|
||||
import {commonProps} from "src/composables/inputs";
|
||||
import {Marker, Polyline} from "vue3-google-map";
|
||||
import {useAirspacesStore} from "stores/Airspaces";
|
||||
import MapWrapper from "components/map/MapWrapper.vue";
|
||||
import {useGeocode} from "src/composables/geocoding";
|
||||
import {errorObject} from "src/composables/dialog";
|
||||
import {useAirportsStore} from "stores/Airports";
|
||||
|
||||
const markers = ref([]);
|
||||
|
||||
const place = ref("");
|
||||
|
||||
const {pointsOfInterest} = storeToRefs(usePointsOfInterestStore());
|
||||
// onMounted(() => {
|
||||
// usePointsOfInterestStore().fetch({});
|
||||
// })
|
||||
const {airspaces: airspacesData, areAirspacesLoading: isQueryRunning} = storeToRefs(useAirspacesStore())
|
||||
|
||||
watch(() => place.value, (newVal) => {
|
||||
usePointsOfInterestStore().fetch({search: newVal});
|
||||
const $q = useQuasar();
|
||||
|
||||
onMounted(() => {
|
||||
useAirspacesStore().fetch();
|
||||
|
||||
usePointsOfInterestStore().fetch({limit: 10000});
|
||||
useAirportsStore().fetch()
|
||||
});
|
||||
|
||||
const markers = ref([]);
|
||||
watch(() => markers.value, (newVal) => {
|
||||
|
||||
});
|
||||
|
||||
const addPoint = async (point) => {
|
||||
markers.value.push({
|
||||
label: point.name,
|
||||
type: point.type,
|
||||
position: {
|
||||
lat: point.gpsLatitude,
|
||||
lng: point.gpsLongitude
|
||||
}
|
||||
})
|
||||
}
|
||||
const track = computed(() => {
|
||||
return markers.value.map(m => m.position);
|
||||
})
|
||||
|
||||
const searchPosition = () => {
|
||||
|
||||
const removeMarker = (idx) => {
|
||||
markers.value.splice(idx, 1);
|
||||
}
|
||||
|
||||
const emits = defineEmits(["update:gpsLatitude", "update:gpsLongitude", "notFound"]);
|
||||
const {center, zoom, searchGeocode} = useGeocode(emits);
|
||||
zoom.value = 8;
|
||||
|
||||
const {airports} = storeToRefs(useAirportsStore());
|
||||
|
||||
const placesOptions = ref(null);
|
||||
const allPlacesOptions = computed(() => {
|
||||
return [
|
||||
...pointsOfInterest.value.map(poi => ({
|
||||
name: poi.name,
|
||||
type: "poi",
|
||||
id: poi.id,
|
||||
gpsLatitude: poi.gpsLatitude,
|
||||
gpsLongitude: poi.gpsLongitude
|
||||
})),
|
||||
...airports.value.map(airport => ({
|
||||
name: `${airport.icaoCode} - ${airport.name}`,
|
||||
type: "airport",
|
||||
id: airport.id,
|
||||
gpsLatitude: airport.gpsLatitude,
|
||||
gpsLongitude: airport.gpsLongitude
|
||||
}))
|
||||
].map(i => ({...i, disabled: !i.gpsLatitude || !i.gpsLongitude}));
|
||||
});
|
||||
|
||||
const placesFilter = (val, update, abort) => {
|
||||
update(() => {
|
||||
console.log(val);
|
||||
|
||||
if (val && val !== '') {
|
||||
placesOptions.value = allPlacesOptions.value.filter(p => p.name.includes(val));
|
||||
console.log(placesOptions.value);
|
||||
if (placesOptions.value.length === 0) {
|
||||
searchGeocode(val).then(results => {
|
||||
placesOptions.value = results.map(result => ({
|
||||
name: result.formatted_address,
|
||||
type: "geocode",
|
||||
id: null,
|
||||
gpsLatitude: result.geometry.location.lat,
|
||||
gpsLongitude: result.geometry.location.lng,
|
||||
}))
|
||||
});
|
||||
}
|
||||
} else {
|
||||
placesOptions.value = [];
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
watch(() => place.value, (newVal) => {
|
||||
addPoint(newVal);
|
||||
place.value = null;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="row">
|
||||
<div class="col" style="min-width: 1px">
|
||||
<MapWrapper style="width: 100%; height: 500px" :center="center" :zoom="zoom" :airspaces-data="airspacesData">
|
||||
<template v-for="marker in markers" :key="marker">
|
||||
<Marker :options="marker"/>
|
||||
</template>
|
||||
<Polyline :options="{path: track, geodesic: true, strokeColor: '#ff0000', strokeOpacity: 0.5, strokeWeight: 5}"/>
|
||||
</MapWrapper>
|
||||
</div>
|
||||
<div class="col-12 col-md-5 col-lg-3" v-if="markers.length">
|
||||
<q-list bordered class="q-ml-md-md">
|
||||
<template v-for="(marker, i) in markers" :key="marker">
|
||||
<q-item>
|
||||
<q-item-section>
|
||||
<q-item-label>
|
||||
{{ i + 1 }}. {{ marker.label }}
|
||||
</q-item-label>
|
||||
<q-item-section caption>
|
||||
{{ marker.type }}
|
||||
</q-item-section>
|
||||
<q-item-label caption>
|
||||
<q-btn icon="add" color="green" flat dense round></q-btn>
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
|
||||
<ComboboxInput :options="pointsOfInterest" v-bind="commonProps" :v-model="place" label="Misto" />
|
||||
<q-btn @click="searchPosition">Najit</q-btn>
|
||||
<q-item-section middle side>
|
||||
<div class="text-grey-8 q-gutter-xs">
|
||||
<!-- <q-btn class="gt-xs" size="12px" flat dense round icon="delete" />-->
|
||||
<!-- <q-btn class="gt-xs" size="12px" flat dense round icon="done" />-->
|
||||
<!-- <q-btn size="12px" flat dense round icon="more_vert" />-->
|
||||
|
||||
<MapWithMarkers :markers="markers" />
|
||||
<q-btn color="red" flat round dense icon="delete" @click="removeMarker(i)"/>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-list>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<q-select
|
||||
v-model="place"
|
||||
label="Místo"
|
||||
use-input
|
||||
input-debounce="100"
|
||||
map-options
|
||||
emit-value
|
||||
option-label="name"
|
||||
option-disable="disabled"
|
||||
:options="placesOptions"
|
||||
@filter="placesFilter"
|
||||
>
|
||||
<!-- <template #option="{opt}">-->
|
||||
<!-- <q-item>-->
|
||||
<!-- <q-item-section>-->
|
||||
<!-- Option! {{ opt }}-->
|
||||
<!-- </q-item-section>-->
|
||||
<!-- </q-item>-->
|
||||
<!-- </template>-->
|
||||
</q-select>
|
||||
|
||||
<!-- <q-input type="text" v-bind="commonProps" v-model="place" label="Misto"/>-->
|
||||
|
||||
<q-list bordered v-if="false">
|
||||
<q-item v-for="poi in pointsOfInterest" :key="poi">
|
||||
<q-item-section>{{ poi.name }}</q-item-section>
|
||||
<q-item-section v-if="poi.gpsLatitude">
|
||||
<q-btn @click="addPoint(poi)">Přidat do trasy</q-btn>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item v-if="pointsOfInterest.length === 0 && place !== ''">
|
||||
<q-btn @click="addPoint(null, place)">Najít {{ place }} na mapě</q-btn>
|
||||
</q-item>
|
||||
</q-list>
|
||||
|
||||
<!-- <q-btn @click="searchPosition">Najit</q-btn>-->
|
||||
|
||||
<!-- <MapWithMarkers :markers="markers" />-->
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user