draft planovace

This commit is contained in:
Michal Kváček
2024-03-25 21:59:55 +01:00
parent 02b839674e
commit 9af80cda06
12 changed files with 262 additions and 57 deletions
@@ -0,0 +1,27 @@
<script setup>
const props = defineProps({
items: {
type: Array,
required: true
}
})
</script>
<template>
<q-list bordered separator>
<q-item
clickable
:to="{name: 'flightPlan', params: {id: flightPlan.id }}"
v-ripple
v-for="flightPlan of items" :key="flightPlan">
<q-item-section avatar>
<q-avatar icon="person" color="primary" text-color="white"/>
</q-item-section>
<q-item-section>
{{ flightPlan.name }}
</q-item-section>
</q-item>
</q-list>
</template>
+1 -2
View File
@@ -1,7 +1,6 @@
<script setup>
import {Marker} from "vue3-google-map";
import {defineEmits, onMounted, ref} from "vue";
import axios from "axios";
import {onMounted} from "vue";
import MapWrapper from "components/map/MapWrapper.vue";
import {useGeocode} from "src/composables/geocoding";
-1
View File
@@ -1,5 +1,4 @@
<script setup>
import FlightsListSkeleton from "components/flights/skeletons/FlightsListSkeleton.vue";
import LoadMoreList from "components/LoadMoreList.vue";
import BasicListSkeleton from "components/basicSkeletons/BasicListSkeleton.vue";
+21
View File
@@ -0,0 +1,21 @@
import gql from "graphql-tag";
export const FRAGMENT_FLIGHT_PLAN_FULL_INFO = gql`
fragment flightPlanFullInfo on FlightPlan {
id
name
markers {
name
position
type
gpsLatitude
gpsLongitude
}
}`;
export const FRAGMENT_FLIGHT_PLAN_LIST_INFO = gql`
fragment flightPlanListInfo on FlightPlanListInfo {
id
name
}
`;
+28
View File
@@ -0,0 +1,28 @@
import gql from "graphql-tag";
import {FRAGMENT_FLIGHT_PLAN_FULL_INFO} from "src/graphql/fragments/flightPlan";
export const CREATE_FLIGHT_PLAN = gql`
mutation createFlight_Plan($input: CreateFlightPlanInput!) {
createFlightPlan(input: $input) {
...flightPlanFullInfo
}
}
${FRAGMENT_FLIGHT_PLAN_FULL_INFO}
`;
export const EDIT_FLIGHT_PLAN = gql`
mutation editFlightPlan($id: Int!, $input: EditFlightPlanInput!) {
editFlight_Plan(id: $id, input: $input) {
...flight_planFullInfo
}
}
${FRAGMENT_FLIGHT_PLAN_FULL_INFO}
`;
export const DELETE_FLIGHT_PLAN = gql`
mutation deleteFlightPlan($id: Int!) {
deleteFlightPlan(id: $id) {
id
}
}
`;
+12
View File
@@ -0,0 +1,12 @@
import gql from "graphql-tag";
import {FRAGMENT_FLIGHT_PLAN_LIST_INFO} from "src/graphql/fragments/flightPlan";
export const FLIGHT_PLANS_LIST = gql`
query flightPlansList {
flightPlans {
...flightPlanListInfo
}
}
${FRAGMENT_FLIGHT_PLAN_LIST_INFO}
`;
+11 -11
View File
@@ -11,16 +11,16 @@ import FlightFormSteps from "components/flights/form/FlightFormSteps.vue";
import FlightFormBasic from "components/flights/form/FlightFormBasic.vue";
import FlightEditSkeleton from "components/flights/skeletons/FlightEditSkeleton.vue";
useAppStore().setPageTitle("Nový let");
useAppStore().setBreadcrumbs([
{to: {name: "myFlights"}, label: "Moje lety"},
{label: "Nový"}
]);
onMounted(() => {
useAircraftsStore().fetch({})
usePointsOfInterestStore().fetch({})
useAirportsStore().fetch()
useAppStore().setPageTitle("Nový let");
useAppStore().setBreadcrumbs([
{to: {name: "myFlights"}, label: "Moje lety"},
{label: "Nový"}
]);
});
const {isMutationRunning} = storeToRefs(useFlightsStore());
@@ -46,11 +46,11 @@ const handleSave = (formData) => {
<FlightEditSkeleton step="basic" v-if="loading"/>
<template v-else>
<FlightFormBasic
@save="handleSave"
:is-request-pending="isMutationRunning"
:aircrafts="aircrafts"
:airports="airports"
:locations="pointsOfInterest"
@save="handleSave"
:is-request-pending="isMutationRunning"
:aircrafts="aircrafts"
:airports="airports"
:locations="pointsOfInterest"
/>
</template>
</template>
@@ -0,0 +1,76 @@
<script setup>
import {computed, onMounted} from "vue";
import {useAppStore} from "stores/App";
import CopilotEditSkeleton from "components/copilots/skeletons/CopilotEditSkeleton.vue";
import CopilotEditForm from "components/copilots/CopilotForm.vue";
import {useRoute, useRouter} from "vue-router";
import {useCopilotsStore} from "stores/Copilots";
import {successObject} from "src/composables/dialog";
import {useQuasar} from "quasar";
import {storeToRefs} from "pinia";
import PhotosEditorList from "components/photos/PhotosEditorList.vue";
import CommonEditSwitcher from "components/navigation/CommonEditSwitcher.vue";
import PhotoGallerySkeleton from "components/photos/skeletons/PhotoGallerySkeleton.vue";
import BasicInfoBanner from "components/banners/BasicInfoBanner.vue";
const $q = useQuasar();
const $router = useRouter();
const $route = useRoute();
const copilotId = parseInt($route.params.id);
onMounted(() => {
useCopilotsStore().fetchDetail(copilotId).then(() => {
useAppStore().setPageTitle(`${copilot.value.name} - editace`);
useAppStore().setBreadcrumbs([
{to: {name: "copilots"}, label: "Kopiloti"},
{to: {name: "copilotDetail", params: {id: copilotId}}, label: copilot.value.name},
{label: "Editace"}
])
});
});
const handleSave = (formData) => {
useCopilotsStore().update(copilotId, formData).then(() => {
$q.notify(successObject("Kopilot úspěšně upraven"));
$router.push({name: "copilotDetail", params: {id: copilotId}});
});
}
const {isQueryRunning, isMutationRunning, copilot} = storeToRefs(useCopilotsStore());
const formStep = computed(() => useRoute().params.step || "info");
const setTitlePhoto = (titlePhoto) => {
useCopilotsStore().update(copilotId, {titlePhotoId: titlePhoto.id}).then(() => {
$q.notify(successObject("Úvodní fotka nastavena"));
})
}
</script>
<template>
<CommonEditSwitcher :route="{name: 'copilotEdit', params: {id: copilot.id}}"/>
<template v-if="formStep === 'info'">
<CopilotEditSkeleton v-if="isQueryRunning || !copilot"/>
<CopilotEditForm
v-else
:copilot="copilot"
:is-request-pending="isMutationRunning"
@save="handleSave"
/>
</template>
<template v-else-if="formStep === 'photo'">
<PhotoGallerySkeleton v-if="isQueryRunning || !copilot" />
<BasicInfoBanner v-else-if="!isQueryRunning && copilot.photos.length === 0">
U tohoto kopilota nemáš označenou žádnou fotku. Bez toho není možné zvolit úvodní fotografii.
</BasicInfoBanner>
<PhotosEditorList
v-else
:photos="copilot.photos"
:title-photo="copilot.titlePhoto"
:show-actions="false"
@set-title-photo="setTitlePhoto"
/>
</template>
</template>
@@ -0,0 +1,38 @@
<script setup>
import {useFlightPlansStore} from "stores/FlightPlans";
import {storeToRefs} from "pinia";
import {onMounted} from "vue";
import {useAppStore} from "stores/App";
import BasicListSkeleton from "components/basicSkeletons/BasicListSkeleton.vue";
import BasicInfoBanner from "components/banners/BasicInfoBanner.vue";
import FAB from "components/FAB.vue";
import FlightPlansList from "components/flightPlans/FlightPlansList.vue";
useAppStore().setPageTitle("Nový plán");
useAppStore().setBreadcrumbs([
{to: {name: "myFlights"}, label: "Moje lety"},
{to: {name: "flightPlans"}, label: "Plány"},
{label: "Nový"}
]);
onMounted(() => {
useFlightPlansStore().fetch();
});
const {flightPlans, isQueryRunning} = storeToRefs(useFlightPlansStore());
</script>
<template>
<BasicListSkeleton v-if="isQueryRunning || !flightPlans"/>
<BasicInfoBanner
v-else-if="!isQueryRunning && flightPlans.length === 0"
:route-add='{name: "addOrganization"}'
>
Aktuálně nemáš žádné naplánované lety.
</BasicInfoBanner>
<FlightPlansList :items="flightPlans" v-else/>
<FAB :router-link="{name: 'newFlightPlan'}" mode="add"/>
</template>
@@ -10,6 +10,7 @@ import MapWrapper from "components/map/MapWrapper.vue";
import {useGeocode} from "src/composables/geocoding";
import {errorObject} from "src/composables/dialog";
import {useAirportsStore} from "stores/Airports";
import {useFlightPlansStore} from "stores/FlightPlans";
const place = ref("");
@@ -29,20 +30,24 @@ onMounted(() => {
const markers = ref([]);
watch(() => markers.value, (newVal) => {
});
}, {deep: true});
const addPoint = async (point) => {
markers.value.push({
label: point.name,
type: point.type,
position: {
lat: point.gpsLatitude,
lng: point.gpsLongitude
}
})
if (!point) return;
markers.value.push(point);
// {
// label: point.name,
// type: point.type,
//
// position: {
// lat: point.gpsLatitude,
// lng: point.gpsLongitude
// }
// })
}
const track = computed(() => {
return markers.value.map(m => m.position);
return markers.value.map(m => ({lat: m.gpsLatitude, lng: m.gpsLongitude}));
})
const removeMarker = (idx) => {
@@ -58,19 +63,11 @@ 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
})),
...pointsOfInterest.value.map(poi => ({...poi, type: "poi"})),
...airports.value.map(airport => ({
...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}));
});
@@ -103,6 +100,20 @@ watch(() => place.value, (newVal) => {
addPoint(newVal);
place.value = null;
});
const saveMarkers = () => {
useFlightPlansStore().create({
name: "",
isPublic: false,
markers: markers.value.map(m => ({
name: m.name,
type: m.type,
gpsLatitude: m.gpsLatitude,
gpsLongitude: m.gpsLongitude,
}))
});
}
</script>
<template>
@@ -110,7 +121,7 @@ watch(() => place.value, (newVal) => {
<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"/>
<Marker :options="{label: marker.name, position: {lat: marker.gpsLatitude, lng: marker.gpsLongitude}}"/>
</template>
<Polyline :options="{path: track, geodesic: true, strokeColor: '#ff0000', strokeOpacity: 0.5, strokeWeight: 5}"/>
</MapWrapper>
@@ -143,7 +154,6 @@ watch(() => place.value, (newVal) => {
</q-item>
</template>
</q-list>
</div>
</div>
@@ -168,6 +178,9 @@ watch(() => place.value, (newVal) => {
<!-- </template>-->
</q-select>
<q-btn @click="saveMarkers" color="primary">Save</q-btn>
<!-- <q-input type="text" v-bind="commonProps" v-model="place" label="Misto"/>-->
<q-list bordered v-if="false">
+4 -1
View File
@@ -47,7 +47,10 @@ const routes = [
{path: 'lety/novy', name: "addFlight", component: () => import('pages/profile/flight/NewFlightPage.vue')},
{path: 'lety/:id', name: "flightDetail", component: () => import('pages/profile/flight/FlightDetailPage.vue')},
{path: 'lety/:id/edit/:step?', name: "flightEdit", component: () => import('pages/profile/flight/EditFlightPage.vue')},
{path: 'planovani', name: "flightPlanner", component: () => import('pages/profile/flight/PlannerPage.vue')},
{path: 'plany', name: "flightPlans", component: () => import('pages/profile/flightPlanner/FlightPlansPage.vue')},
{path: 'plany/novy', name: "newFlightPlan", component: () => import('pages/profile/flightPlanner/NewFlightPlanPage.vue')},
{path: 'plany/:id', name: "flightPlan", component: () => import('pages/profile/flightPlanner/FlightPlanEditPage.vue')},
{path: 'poi', name: "poi", component: () => import('pages/profile/poi/PointsOfInterestPage.vue')},
{path: 'poi/novy', name: "addPOI", component: () => import('pages/profile/poi/NewPointOfInterestPage.vue')},
+9 -20
View File
@@ -1,5 +1,5 @@
import {defineStore} from 'pinia'
import {FLIGHT_PLAN_DETAIL, FLIGHT_PLAN_PUBLIC_DETAIL, FLIGHT_PLAN_LIST} from "src/graphql/queries/flightPlans";
import {FLIGHT_PLANS_LIST} from "src/graphql/queries/flightPlan";
import {CREATE_FLIGHT_PLAN, EDIT_FLIGHT_PLAN} from "src/graphql/mutations/flightPlan";
import {mutate, query, updateInItems} from "stores/helpers";
import {ref} from "vue";
@@ -10,24 +10,13 @@ export const useFlightPlansStore = defineStore('FlightPlans', () => {
const isMutationRunning = ref(false);
const isQueryRunning = ref(false);
const fetchDetail = (id) => {
return query({
isQueryRunning,
query: FLIGHT_PLAN_DETAIL,
variables: {id},
}).then(item => flightPlan.value = item);
};
const fetchPublicDetail = ({urlSlug, username, uploadToken, uploadFlightSlug}) => {
return query({
isQueryRunning,
query: FLIGHT_PLAN_PUBLIC_DETAIL,
variables: {urlSlug, pilotUsername: username, uploadToken, uploadFlightSlug},
}).then(item => {
flightPlan.value = item;
return item;
});
};
// const fetchDetail = (id) => {
// return query({
// isQueryRunning,
// query: FLIGHT_PLAN_DETAIL,
// variables: {id},
// }).then(item => flightPlan.value = item);
// };
const fetch = () => {
return query({
@@ -61,6 +50,6 @@ export const useFlightPlansStore = defineStore('FlightPlans', () => {
return {
flightPlan, flightPlans, isMutationRunning, isQueryRunning,
fetch, fetchDetail, create, update, fetchPublicDetail
fetch, create, update
}
})