Upravy UI, refaktoring, davkove upravy a mazani fotek
This commit is contained in:
@@ -7,11 +7,6 @@ const props = defineProps({
|
|||||||
modelValue: {
|
modelValue: {
|
||||||
type: Object,
|
type: Object,
|
||||||
},
|
},
|
||||||
resetAfterSubmit: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
isRequestPending,
|
isRequestPending,
|
||||||
saveButton: {
|
saveButton: {
|
||||||
type: [Object, Boolean],
|
type: [Object, Boolean],
|
||||||
@@ -27,10 +22,6 @@ const props = defineProps({
|
|||||||
const emits = defineEmits(["save"]);
|
const emits = defineEmits(["save"]);
|
||||||
const saveForm = () => {
|
const saveForm = () => {
|
||||||
emits("save", props.modelValue);
|
emits("save", props.modelValue);
|
||||||
|
|
||||||
if (props.resetAfterSubmit) {
|
|
||||||
console.error("Not implemented")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
@@ -47,7 +38,7 @@ const fullwidthBtn = computed(() => $q.screen.width <= $q.screen.sizes.md);
|
|||||||
color="primary"
|
color="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
size="lg"
|
size="lg"
|
||||||
:class="{'q-my-lg': true, 'q-mx-lg': !fullwidthBtn, 'btn--fullwidth': fullwidthBtn}"
|
:class="{'q-my-lg': true, 'btn--fullwidth': fullwidthBtn}"
|
||||||
v-if="saveButton"
|
v-if="saveButton"
|
||||||
:icon="props.saveButton.icon"
|
:icon="props.saveButton.icon"
|
||||||
:loading="props.isRequestPending"
|
:loading="props.isRequestPending"
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<script setup>
|
||||||
|
import {aircraft} from "src/composables/objects/aircraft";
|
||||||
|
import {confirmObject} from "src/composables/dialog";
|
||||||
|
import {useQuasar} from "quasar";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
aircraft: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits(["delete"]);
|
||||||
|
|
||||||
|
const $q = useQuasar();
|
||||||
|
|
||||||
|
const confirmDelete = (aircraftId) => {
|
||||||
|
$q.dialog(confirmObject('Opravdu chceš smazat toto letadlo?'))
|
||||||
|
.onOk(() => {
|
||||||
|
emits("delete", aircraftId);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-card class="q-mx-md q-my-md flight-detail-card">
|
||||||
|
<q-img :src="aircraft.photoUrl" v-if="aircraft.photoUrl"/>
|
||||||
|
|
||||||
|
<q-card-actions class="q-my-md">
|
||||||
|
<div class="col-grow">
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
:to='{name: "aircraftEdit", params: {id: aircraft.id}}'
|
||||||
|
icon="edit"
|
||||||
|
text-color="primary"
|
||||||
|
label="Upravit"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<q-btn @click="confirmDelete(aircraft.id)" icon="delete" flat text-color="red" label="Smazat"/>
|
||||||
|
</q-card-actions>
|
||||||
|
|
||||||
|
<q-card-section>
|
||||||
|
<q-list>
|
||||||
|
<q-item v-if="aircraft.manufacturer">
|
||||||
|
Výrobce: {{ aircraft.manufacturer }}
|
||||||
|
</q-item>
|
||||||
|
<q-item v-if="aircraft.model">
|
||||||
|
Model: {{ aircraft.model }}
|
||||||
|
</q-item>
|
||||||
|
<q-item v-if="aircraft.seats">
|
||||||
|
Počet míst: {{ aircraft.seats }}
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section>
|
||||||
|
<article v-html="aircraft.description" class="q-my-md"/>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</template>
|
||||||
@@ -1,5 +1,23 @@
|
|||||||
<script setup></script>
|
<script setup>
|
||||||
|
import BasicListSkeleton from "components/basicSkeletons/BasicListSkeleton.vue";
|
||||||
|
import {randomInt} from "src/composables/random";
|
||||||
|
import BasicTextSkeleton from "components/basicSkeletons/BasicTextSkeleton.vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-skeleton></q-skeleton>
|
<q-card class="flight-detail-card">
|
||||||
|
<q-skeleton type="rect" height="400px"/>
|
||||||
|
|
||||||
|
<q-card-section>
|
||||||
|
<q-skeleton type="text" v-for="i in 3" :key="i" :width="randomInt(30, 50)+'%'"/>
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
<q-card-section class="q-my-md">
|
||||||
|
<BasicTextSkeleton :paragraphs="1" :lines="randomInt(1, 3)"/>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
|
||||||
|
<q-card class="flight-detail-card" flat>
|
||||||
|
<BasicListSkeleton :items-count-min="1" :items-count-max="4"/>
|
||||||
|
</q-card>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,5 +1,22 @@
|
|||||||
<script setup></script>
|
<script setup>
|
||||||
|
|
||||||
|
import {randomInt} from "src/composables/random";
|
||||||
|
import BasicTextSkeleton from "components/basicSkeletons/BasicTextSkeleton.vue";
|
||||||
|
import BasicListSkeleton from "components/basicSkeletons/BasicListSkeleton.vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<em>Aircraft edit skeleton</em>
|
<q-card class="flight-detail-card">
|
||||||
|
<q-skeleton type="rect" height="400px"/>
|
||||||
|
|
||||||
|
<q-card-section>
|
||||||
|
<q-skeleton type="QInput" v-for="i in 3" :key="i" class="q-my-lg" />
|
||||||
|
<q-skeleton type="QInput" height="200px" class="q-my-lg" />
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-actions>
|
||||||
|
<!-- TODO: posunout vpravo, zvetsit a na mobilu udelat fullwidth-->
|
||||||
|
<q-skeleton type="QBtn" />
|
||||||
|
</q-card-actions>
|
||||||
|
|
||||||
|
</q-card>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<script setup></script>
|
<script setup>
|
||||||
|
import BasicListSkeleton from "components/basicSkeletons/BasicListSkeleton.vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<em>Copilot skeleton</em>
|
<q-card class="flight-detail-card">
|
||||||
|
<BasicListSkeleton :items-count-min="1" :items-count-max="5"/>
|
||||||
|
</q-card>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -4,17 +4,24 @@ import {onMounted, reactive} from "vue";
|
|||||||
import {setDefaultData} from "src/composables/form/formHandling";
|
import {setDefaultData} from "src/composables/form/formHandling";
|
||||||
import FormWrapper from "components/FormWrapper.vue";
|
import FormWrapper from "components/FormWrapper.vue";
|
||||||
import {commonProps} from "src/composables/inputs";
|
import {commonProps} from "src/composables/inputs";
|
||||||
|
import {isRequestPending} from "src/composables/form/props";
|
||||||
|
import {isRequired} from "src/composables/form/rules";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
copilot: {
|
copilot: {
|
||||||
type: Object
|
type: Object
|
||||||
}
|
},
|
||||||
|
isRequestPending
|
||||||
})
|
})
|
||||||
|
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
name: null,
|
name: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
name: [isRequired]
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.copilot) {
|
if (props.copilot) {
|
||||||
setDefaultData(formData, props.copilot);
|
setDefaultData(formData, props.copilot);
|
||||||
@@ -24,7 +31,12 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FormWrapper v-model="formData">
|
<FormWrapper v-model="formData" :is-request-pending="props.isRequestPending">
|
||||||
<q-input v-bind="commonProps" label="Jméno" v-model="formData.name" />
|
<q-input
|
||||||
|
v-bind="commonProps"
|
||||||
|
label="Jméno"
|
||||||
|
:rules="rules.name"
|
||||||
|
v-model="formData.name"
|
||||||
|
/>
|
||||||
</FormWrapper>
|
</FormWrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import BasicTextSkeleton from "components/basicSkeletons/BasicTextSkeleton.vue";
|
|||||||
|
|
||||||
<q-item>
|
<q-item>
|
||||||
<q-list>
|
<q-list>
|
||||||
<ListItemSkeleton v-for="i in randomInt(2, 5)" :key="i"/>
|
<ListItemSkeleton v-for="i in randomInt(1, 3)" :key="i"/>
|
||||||
</q-list>
|
</q-list>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ import BasicTextSkeleton from "components/basicSkeletons/BasicTextSkeleton.vue";
|
|||||||
</q-list>
|
</q-list>
|
||||||
|
|
||||||
<article class="q-my-lg">
|
<article class="q-my-lg">
|
||||||
<BasicTextSkeleton :lines="randomInt(5, 10)" :paragraphs="randomInt(1, 3)" />
|
<BasicTextSkeleton :lines="randomInt(2, 5)" :paragraphs="randomInt(1, 2)" />
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<q-skeleton height="400px" square class="q-mt-lg"/>
|
<q-skeleton height="400px" square class="q-mt-lg"/>
|
||||||
|
|||||||
@@ -1,7 +1,20 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
|
||||||
|
import {randomInt} from "src/composables/random";
|
||||||
|
import BasicTextSkeleton from "components/basicSkeletons/BasicTextSkeleton.vue";
|
||||||
|
import BasicListSkeleton from "components/basicSkeletons/BasicListSkeleton.vue";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<em>Flight edit skeleton</em>
|
<q-card class="flight-detail-card">
|
||||||
</template>
|
<q-skeleton type="rect" height="400px"/>
|
||||||
|
|
||||||
|
<q-card-section>
|
||||||
|
<q-skeleton type="QInput" v-for="i in 3" :key="i" />
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
</q-card>
|
||||||
|
|
||||||
|
<q-card class="flight-detail-card" flat>
|
||||||
|
<BasicListSkeleton :items-count-min="1" :items-count-max="4"/>
|
||||||
|
</q-card></template>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const pointsOfInterests = computed(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
path.push({
|
path.push({
|
||||||
label: flight.value.takeoffAirport.name,
|
label: flight.value.landingAirport.name,
|
||||||
position: {
|
position: {
|
||||||
lat: flight.value.landingAirport.gpsLatitude,
|
lat: flight.value.landingAirport.gpsLatitude,
|
||||||
lng: flight.value.landingAirport.gpsLongitude
|
lng: flight.value.landingAirport.gpsLongitude
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import DatetimePicker from "components/inputs/DatetimePicker.vue";
|
|||||||
import ComboboxInput from "components/inputs/ComboboxInput.vue";
|
import ComboboxInput from "components/inputs/ComboboxInput.vue";
|
||||||
import {commonProps} from "src/composables/inputs";
|
import {commonProps} from "src/composables/inputs";
|
||||||
import {isRequired} from "src/composables/form/rules";
|
import {isRequired} from "src/composables/form/rules";
|
||||||
|
import {isRequestPending} from "src/composables/form/props";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
aircrafts: {
|
aircrafts: {
|
||||||
@@ -19,9 +20,9 @@ const props = defineProps({
|
|||||||
flight: {
|
flight: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: false
|
required: false
|
||||||
}
|
},
|
||||||
}
|
isRequestPending,
|
||||||
)
|
});
|
||||||
|
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
aircraft: null,
|
aircraft: null,
|
||||||
@@ -69,7 +70,7 @@ watch(() => formData.takeoffAirport, () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FormWrapper v-model="formData">
|
<FormWrapper v-model="formData" :is-request-pending="props.isRequestPending">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<q-card class="q-mx-md q-my-md">
|
<q-card class="q-mx-md q-my-md">
|
||||||
@@ -140,8 +141,6 @@ watch(() => formData.takeoffAirport, () => {
|
|||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</FormWrapper>
|
</FormWrapper>
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const formData = reactive({
|
|||||||
icon: "upload",
|
icon: "upload",
|
||||||
align: "left"
|
align: "left"
|
||||||
}'>
|
}'>
|
||||||
|
|
||||||
<q-file
|
<q-file
|
||||||
class="q-my-lg"
|
class="q-my-lg"
|
||||||
outlined
|
outlined
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<script setup>
|
||||||
|
import {computed, ref} from "vue";
|
||||||
|
import {setDefaultData} from "src/composables/form/formHandling";
|
||||||
|
import DialogWrapper from "components/DialogWrapper.vue";
|
||||||
|
import FormWrapper from "components/FormWrapper.vue";
|
||||||
|
import {commonProps} from "src/composables/inputs";
|
||||||
|
import ComboboxInput from "components/inputs/ComboboxInput.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
photos: {
|
||||||
|
type: Array
|
||||||
|
},
|
||||||
|
locations: {
|
||||||
|
type: Array
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const formData = ref({
|
||||||
|
name: "",
|
||||||
|
description: "",
|
||||||
|
pointOfInterest: null,
|
||||||
|
photoIds: []
|
||||||
|
});
|
||||||
|
|
||||||
|
const setup = () => {
|
||||||
|
formData.value.photoIds = props.photos.map(p => p.id);
|
||||||
|
formData.value.name = "";
|
||||||
|
formData.value.description = "";
|
||||||
|
formData.value.pointOfInterest = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DialogWrapper :formData="formData" @show="setup()">
|
||||||
|
<q-card-section class="text-center">
|
||||||
|
<!-- <q-scroll-area style="min-height: 80px; max-height: 150px">-->
|
||||||
|
<q-img :src="photo.thumbnailUrl" width="80px" class="q-ma-sm" v-for="photo in photos" :key="photo.thumbnailUrl"/>
|
||||||
|
<!-- {{ photos }}-->
|
||||||
|
<!-- </q-scroll-area>-->
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section>
|
||||||
|
<FormWrapper :save-button="false">
|
||||||
|
<q-input v-model="formData.name" label="Název" v-bind="commonProps"/>
|
||||||
|
<q-input type="textarea" v-model="formData.description" label="Popis" v-bind="commonProps"/>
|
||||||
|
|
||||||
|
<ComboboxInput
|
||||||
|
:options="locations"
|
||||||
|
v-bind="commonProps"
|
||||||
|
v-model="formData.pointOfInterest"
|
||||||
|
:enable-new-values="false"
|
||||||
|
label="POI"
|
||||||
|
/>
|
||||||
|
</FormWrapper>
|
||||||
|
</q-card-section>
|
||||||
|
</DialogWrapper>
|
||||||
|
</template>
|
||||||
@@ -3,6 +3,7 @@ import EmbeddedMap from "components/map/EmbeddedMap.vue";
|
|||||||
import {computed, onMounted, ref} from "vue";
|
import {computed, onMounted, ref} from "vue";
|
||||||
import {formatDatetime} from "src/composables/datetimeUtils";
|
import {formatDatetime} from "src/composables/datetimeUtils";
|
||||||
import 'vue-inner-image-zoom/lib/vue-inner-image-zoom.css'
|
import 'vue-inner-image-zoom/lib/vue-inner-image-zoom.css'
|
||||||
|
import {useQuasar} from "quasar";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
photos: {
|
photos: {
|
||||||
@@ -50,12 +51,17 @@ const prevPhoto = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const showExtra = ref(false);
|
const showExtra = ref(false);
|
||||||
|
|
||||||
|
const $q = useQuasar();
|
||||||
|
const isMaximized = computed(() => $q.screen.width <= $q.screen.sizes.md);
|
||||||
|
const imageFullscreen = ref(false);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-dialog
|
<q-dialog
|
||||||
v-model="open"
|
v-model="open"
|
||||||
full-width
|
full-width
|
||||||
|
:maximized="isMaximized"
|
||||||
>
|
>
|
||||||
<q-card
|
<q-card
|
||||||
v-touch-swipe.mouse.left="prevPhoto"
|
v-touch-swipe.mouse.left="prevPhoto"
|
||||||
@@ -63,10 +69,29 @@ const showExtra = ref(false);
|
|||||||
@keyup.left="prevPhoto"
|
@keyup.left="prevPhoto"
|
||||||
@keyup.right="nextPhoto"
|
@keyup.right="nextPhoto"
|
||||||
>
|
>
|
||||||
<q-card-section>
|
<q-card-section class="bg-black text-white" v-if="isMaximized">
|
||||||
<div class="relative-position">
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<strong v-if="photo.name !== ''">{{ photo.name }}</strong>
|
||||||
|
</div>
|
||||||
|
<div class="col text-right">
|
||||||
|
<q-btn round text-color="white" size="sm" icon="close" @click="open = false"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
<q-card-section :class="{'q-pa-none': isMaximized}">
|
||||||
|
<div :class="{'relative-position': true, 'image-full-height': imageFullscreen}">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<inner-image-zoom move-type="pan" :zoomScale="0.75" :hide-hint="true" :src="photo.url"/>
|
<inner-image-zoom
|
||||||
|
move-type="pan"
|
||||||
|
:zoomScale="0.75"
|
||||||
|
:hide-hint="true"
|
||||||
|
:after-zoom-in="() => imageFullscreen = true"
|
||||||
|
:after-zoom-out="() => imageFullscreen = false"
|
||||||
|
:src="photo.url"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<q-btn
|
<q-btn
|
||||||
@@ -75,14 +100,14 @@ const showExtra = ref(false);
|
|||||||
flat
|
flat
|
||||||
icon="info"
|
icon="info"
|
||||||
:text-color="showExtra ? 'primary' : 'white'"
|
:text-color="showExtra ? 'primary' : 'white'"
|
||||||
style="background: rgba(0, 0, 0, 0.25); top: 8px; right: 8px"
|
style="background: rgba(0, 0, 0, 0.25); bottom: 16px; left: 8px"
|
||||||
@click="showExtra = !showExtra"
|
@click="showExtra = !showExtra"
|
||||||
/>
|
/>
|
||||||
<q-btn
|
<q-btn
|
||||||
class="absolute all-pointer-events"
|
class="absolute all-pointer-events"
|
||||||
style="background: rgba(0, 0, 0, 0.25); top: 50%; left: 8px;"
|
style="background: rgba(0, 0, 0, 0.25); top: 50%; left: 8px;"
|
||||||
@click="prevPhoto"
|
@click="prevPhoto"
|
||||||
v-if="photoIndex > 0"
|
v-if="photoIndex > 0 && !isMaximized"
|
||||||
icon="chevron_left"
|
icon="chevron_left"
|
||||||
text-color="white"
|
text-color="white"
|
||||||
flat
|
flat
|
||||||
@@ -93,19 +118,18 @@ const showExtra = ref(false);
|
|||||||
class="absolute all-pointer-events"
|
class="absolute all-pointer-events"
|
||||||
style="background: rgba(0, 0, 0, 0.25); top: 50%; right: 8px;"
|
style="background: rgba(0, 0, 0, 0.25); top: 50%; right: 8px;"
|
||||||
@click="nextPhoto"
|
@click="nextPhoto"
|
||||||
v-if="photoIndex < photos.length - 1"
|
v-if="photoIndex < photos.length - 1 && !isMaximized"
|
||||||
icon-right="chevron_right"
|
icon-right="chevron_right"
|
||||||
text-color="white"
|
text-color="white"
|
||||||
flat
|
flat
|
||||||
rounded
|
rounded
|
||||||
>
|
>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<strong v-if="photo.name !== ''">{{ photo.name }}</strong>
|
<strong v-if="photo.name !== '' && !isMaximized">{{ photo.name }}</strong>
|
||||||
<p v-if="photo.description !== ''">{{ photo.description }}</p>
|
<p v-if="photo.description !== ''">{{ photo.description }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
<div class="col-12 q-my-md" v-if="showExtra">
|
<div class="col-12 q-my-md" v-if="showExtra">
|
||||||
<EmbeddedMap
|
<EmbeddedMap
|
||||||
v-if="photo.gpsLatitude && photo.gpsLongitude"
|
v-if="photo.gpsLatitude && photo.gpsLongitude"
|
||||||
@@ -153,8 +177,20 @@ const showExtra = ref(false);
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image-full-height .iiz {
|
||||||
|
height: calc(95vh - 65px) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.iiz__img {
|
.iiz__img {
|
||||||
max-height: 90vh !important;
|
max-height: 90vh !important;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.iiz__img--hidden {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iiz__zoom-img--visible {
|
||||||
|
//height: 125vh !important
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {setDefaultData} from "src/composables/form/formHandling";
|
|||||||
import DialogWrapper from "components/DialogWrapper.vue";
|
import DialogWrapper from "components/DialogWrapper.vue";
|
||||||
import FormWrapper from "components/FormWrapper.vue";
|
import FormWrapper from "components/FormWrapper.vue";
|
||||||
import {commonProps} from "src/composables/inputs";
|
import {commonProps} from "src/composables/inputs";
|
||||||
|
import ComboboxInput from "components/inputs/ComboboxInput.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
photo: {
|
photo: {
|
||||||
@@ -18,7 +19,7 @@ const photoId = computed(() => props.photo?.id || null);
|
|||||||
const formData = ref({
|
const formData = ref({
|
||||||
name: "",
|
name: "",
|
||||||
description: "",
|
description: "",
|
||||||
pointOfInterestId: null,
|
pointOfInterest: null,
|
||||||
isFlightCover: false
|
isFlightCover: false
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ const setup = (() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DialogWrapper :formData="formData" :object-id="photoId" @show="setup">
|
<DialogWrapper :formData="formData" :object-id="photoId" @show="setup">
|
||||||
|
{{ formData }}
|
||||||
<q-img :src="photo.thumbnailUrl"/>
|
<q-img :src="photo.thumbnailUrl"/>
|
||||||
|
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
@@ -36,16 +38,10 @@ const setup = (() => {
|
|||||||
<q-input v-model="formData.name" label="Název" v-bind="commonProps"/>
|
<q-input v-model="formData.name" label="Název" v-bind="commonProps"/>
|
||||||
<q-input type="textarea" v-model="formData.description" label="Popis" v-bind="commonProps"/>
|
<q-input type="textarea" v-model="formData.description" label="Popis" v-bind="commonProps"/>
|
||||||
|
|
||||||
{{ locations }}
|
<ComboboxInput
|
||||||
|
|
||||||
<q-select
|
|
||||||
:options="locations"
|
:options="locations"
|
||||||
option-label="name"
|
|
||||||
option-value="id"
|
|
||||||
emit-value
|
|
||||||
map-options
|
|
||||||
v-bind="commonProps"
|
v-bind="commonProps"
|
||||||
v-model="formData.pointOfInterestId"
|
v-model="formData.pointOfInterest"
|
||||||
label="POI"
|
label="POI"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import {computed, onMounted, ref} from "vue";
|
||||||
|
import {useQuasar} from "quasar";
|
||||||
|
import {confirmObject} from "src/composables/dialog";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
photos: {
|
photos: {
|
||||||
type: Array
|
type: Array
|
||||||
@@ -10,26 +14,73 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const emits = defineEmits(["edit", "delete", "openDetail"])
|
const batchEdit = ref({});
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
for (const photo of props.photos) {
|
||||||
|
batchEdit.value[photo.id] = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits(["edit", "delete", "batch-edit"])
|
||||||
|
|
||||||
const openEdit = (photo) => {
|
const openEdit = (photo) => {
|
||||||
emits("edit", photo);
|
emits("edit", photo);
|
||||||
};
|
};
|
||||||
|
|
||||||
const deletePhoto = (id) => {
|
const $q = useQuasar();
|
||||||
emits("delete", id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const openDetail = (photo, idx) => {
|
const confirmPhotoDelete = (id) => {
|
||||||
emits("openDetail", {photo, idx, allPhotos: props.photos});
|
$q.dialog(confirmObject("Opravdu chces smazat tuto fotku?"))
|
||||||
|
.onOk(() => {
|
||||||
|
emits("delete", id);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const confirmBatchPhotoDelete = () => {
|
||||||
|
$q.dialog(confirmObject("Opravdu chces smazat vybrané fotky?" + JSON.stringify(batchEdit.value)))
|
||||||
|
.onOk(() => {
|
||||||
|
for (const id in batchEdit.value) {
|
||||||
|
if (!batchEdit.value[id]) continue;
|
||||||
|
emits("delete", parseInt(id));
|
||||||
|
batchEdit.value[id] = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleImageClick = (photo, idx) => {
|
||||||
|
if (props.showActions) {
|
||||||
|
batchEdit.value[photo.id] = !batchEdit.value[photo.id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const openBatchEdit = () => {
|
||||||
|
const photos = [];
|
||||||
|
for (const i in batchEdit.value) {
|
||||||
|
const photo = props.photos.find(p => p.id === parseInt(i));
|
||||||
|
if (photo && batchEdit.value[i]) photos.push(photo);
|
||||||
|
batchEdit.value[i] = false;
|
||||||
|
}
|
||||||
|
emits('batch-edit', photos);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isBatchEditAllowed = computed(() => Object.values(batchEdit.value).filter(v => v).length > 0);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<div class="row q-my-md">
|
||||||
|
<div class="col text-right">
|
||||||
|
<q-btn round flat icon="edit" :color="isBatchEditAllowed ? 'primary' : 'grey'" :disable="!isBatchEditAllowed" @click="openBatchEdit" v-if="showActions"/>
|
||||||
|
<q-btn round flat icon="delete" :color="isBatchEditAllowed ? 'red' : 'grey'" :disable="!isBatchEditAllowed" @click="confirmBatchPhotoDelete" v-if="showActions"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-sm-4 col-md-4 col-lg-3" v-for="(photo, idx) in photos" :key="photo.id">
|
<div class="col-12 col-sm-4 col-md-4 col-lg-3" v-for="(photo, idx) in photos" :key="photo.id">
|
||||||
<q-card class="q-my-sm q-mx-sm">
|
<q-card :class='{"q-ma-sm": true, "shadow-1": !batchEdit[photo.id], "shadow-10": batchEdit[photo.id]}'>
|
||||||
<q-img :src="photo.thumbnailUrl" @click="openDetail(photo, idx)">
|
<q-img :src="photo.thumbnailUrl" @click="handleImageClick(photo, idx)">
|
||||||
<div class="absolute-bottom" v-if="photo.name !== '' || photo.description !== ''">
|
<div class="absolute-bottom" v-if="photo.name !== '' || photo.description !== ''">
|
||||||
<div class="text-h6" v-if="photo.name !== ''">
|
<div class="text-h6" v-if="photo.name !== ''">
|
||||||
{{ photo.name }}
|
{{ photo.name }}
|
||||||
@@ -40,16 +91,17 @@ const openDetail = (photo, idx) => {
|
|||||||
</div>
|
</div>
|
||||||
</q-img>
|
</q-img>
|
||||||
|
|
||||||
<q-card-actions v-if="showActions" align="right">
|
<q-card-actions v-if="showActions" align="right" :class="{'bg-primary': batchEdit[photo.id], 'text-white': batchEdit[photo.id]}">
|
||||||
<div class="col-grow">
|
<div class="col-grow">
|
||||||
|
<q-checkbox v-model="batchEdit[photo.id]"/>
|
||||||
<q-icon name="star" v-if="photo.isFlightCover" color="red"/>
|
<q-icon name="star" v-if="photo.isFlightCover" color="red"/>
|
||||||
<q-icon name="place" v-if="photo.pointOfInterestId" />
|
<q-icon name="place" v-if="photo.pointOfInterestId"/>
|
||||||
<q-icon name="gps_fixed" v-if="photo.gpsLatitude && photo.gpsLongitude" />
|
<q-icon name="gps_fixed" v-if="photo.gpsLatitude && photo.gpsLongitude"/>
|
||||||
<q-icon name="gps_off" v-else />
|
<q-icon name="gps_off" v-else/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<q-btn flat icon="edit" color="blue" @click="openEdit(photo)"></q-btn>
|
<q-btn flat icon="edit" color="blue" @click="openEdit(photo)"></q-btn>
|
||||||
<q-btn flat icon="delete" color="red" @click="deletePhoto(photo.id)"></q-btn>
|
<q-btn flat icon="delete" color="red" @click="confirmPhotoDelete(photo.id)"></q-btn>
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,11 +8,21 @@ export const confirmObject = (message, title) => ({
|
|||||||
export const successObject = (message) => ({
|
export const successObject = (message) => ({
|
||||||
message,
|
message,
|
||||||
position: "top",
|
position: "top",
|
||||||
color: "positive"
|
color: "positive",
|
||||||
|
progress: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const warningObject = (message) => ({
|
||||||
|
message,
|
||||||
|
position: "top",
|
||||||
|
color: "warning",
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
export const errorObject = (message) => ({
|
export const errorObject = (message) => ({
|
||||||
message,
|
message,
|
||||||
position: "top",
|
position: "top",
|
||||||
color: "negative"
|
color: "negative",
|
||||||
|
timeout: 5 * 60 * 1000,
|
||||||
|
actions: [{ icon: 'close', color: 'white', round: true, handler: () => { }}]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -21,3 +21,5 @@ export const fetchAircrafts = () => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
useAircraftsStore().fetch().finally(() => loading.value = false);
|
useAircraftsStore().fetch().finally(() => loading.value = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const isRequestPending = storeToRefs(useAircraftsStore).isMutationRunning;
|
||||||
|
|||||||
@@ -19,3 +19,5 @@ export const fetchCopilots = () => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
return useCopilotsStore().fetch().finally(() => loading.value = false);
|
return useCopilotsStore().fetch().finally(() => loading.value = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const isRequestPending = storeToRefs(useCopilotsStore()).isMutationRunning;
|
||||||
|
|||||||
@@ -43,3 +43,5 @@ export const handleDeleteFlight = ($q, flightId, onOkCallback = () => {
|
|||||||
useFlightsStore().delete(flightId).then(onOkCallback);
|
useFlightsStore().delete(flightId).then(onOkCallback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const isRequestPending = storeToRefs(useFlightsStore()).isRequestPending;
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import {ref} from "vue";
|
||||||
|
import {usePhotosStore} from "stores/Photo";
|
||||||
|
import {fetchFlight} from "src/composables/objects/flight";
|
||||||
|
|
||||||
|
export const openBatchEdit = ref(false);
|
||||||
|
export const editBatchPhotos = ref([]);
|
||||||
|
export const openBatchPhotoForm = (photos) => {
|
||||||
|
openBatchEdit.value = true;
|
||||||
|
editBatchPhotos.value = photos;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const handleBatchPhotoEdit = (flightId, data) => {
|
||||||
|
const photoIds = data.photoIds;
|
||||||
|
delete data.photoIds;
|
||||||
|
delete data.id;
|
||||||
|
|
||||||
|
const promises = [];
|
||||||
|
for (const id of photoIds) {
|
||||||
|
const updateData = {};
|
||||||
|
if (data.name !== '') updateData.name = data.name;
|
||||||
|
if (data.description !== '') updateData.description = data.description;
|
||||||
|
if (data.pointOfInterest) updateData.pointOfInterest = data.pointOfInterest;
|
||||||
|
|
||||||
|
if (Object.keys(updateData).length === 0) continue;
|
||||||
|
|
||||||
|
promises.push(usePhotosStore().update(id, updateData));
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.all(promises).finally(() => fetchFlight(flightId))
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import {usePhotosStore} from "stores/Photo";
|
||||||
|
import {fetchFlight} from "src/composables/objects/flight";
|
||||||
|
import {usePointsOfInterestStore} from "stores/PointsOfInterest";
|
||||||
|
import {ref} from "vue";
|
||||||
|
|
||||||
|
export const handlePhotoUpdate = (flightId, formData) => {
|
||||||
|
const photoId = formData.id;
|
||||||
|
delete formData.id;
|
||||||
|
|
||||||
|
usePhotosStore().update(photoId, formData).then((data) => {
|
||||||
|
fetchFlight(flightId); // nenacita se mi nove vytvoreny POI z comboboxu
|
||||||
|
usePointsOfInterestStore().fetch();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const openEdit = ref(false);
|
||||||
|
export const editPhoto = ref(null);
|
||||||
|
|
||||||
|
export const openPhotoEdit = (photo) => {
|
||||||
|
openEdit.value = true;
|
||||||
|
editPhoto.value = photo;
|
||||||
|
};
|
||||||
@@ -4,18 +4,20 @@ import {createUploadLink} from 'apollo-upload-client';
|
|||||||
import {onError} from "@apollo/client/link/error";
|
import {onError} from "@apollo/client/link/error";
|
||||||
import {useUserStore} from "stores/User";
|
import {useUserStore} from "stores/User";
|
||||||
import {useAppStore} from "stores/App";
|
import {useAppStore} from "stores/App";
|
||||||
|
import {Notify} from "quasar";
|
||||||
|
import {errorObject, warningObject} from "src/composables/dialog";
|
||||||
|
|
||||||
|
|
||||||
const uploadLink = createUploadLink({
|
const uploadLink = createUploadLink({
|
||||||
uri: process.env.API_URL+'/graphql',
|
uri: process.env.API_URL + '/graphql',
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleRefreshToken = (forward, operation) => {
|
const handleRefreshToken = (forward, operation) => {
|
||||||
return fromPromise(
|
return fromPromise(
|
||||||
useUserStore().refreshAccessToken()
|
useUserStore().refreshAccessToken()
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log("neumim refresh");
|
Notify.create(warningObject("Tvoje přihlášení vypřešlo. Přihlaš se prosím znovu."));
|
||||||
// window.location = "/login";
|
window.location = "/login";
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.filter((value) => Boolean(value))
|
.filter((value) => Boolean(value))
|
||||||
@@ -40,17 +42,14 @@ const errorLink = onError(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (graphQLErrors) {
|
if (graphQLErrors) {
|
||||||
const messages = [];
|
|
||||||
for (const error of graphQLErrors) {
|
for (const error of graphQLErrors) {
|
||||||
if (error.message === "Not found") {
|
if (error.message === "Not found") {
|
||||||
useAppStore().appStatus = 404;
|
useAppStore().appStatus = 404;
|
||||||
} else if (error.message.includes("401") || error.message.includes("Not authorized")) {
|
} else if (error.message.includes("401") || error.message.includes("Not authorized")) {
|
||||||
return handleRefreshToken(forward, operation);
|
return handleRefreshToken(forward, operation);
|
||||||
} else {
|
} else {
|
||||||
messages.push(error.message);
|
Notify.create(errorObject("API error: " + error.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: zaridit zobrazeni erroru z messages
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -81,8 +80,7 @@ export const apolloWrapper = {
|
|||||||
})
|
})
|
||||||
.then((response) => response)
|
.then((response) => response)
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.log(err.message);
|
console.error("Error during query: ", err)
|
||||||
// console.error("Error during query: ", err)
|
|
||||||
return err;
|
return err;
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ fragment flightFullInfo on Flight {
|
|||||||
...weatherFullInfo
|
...weatherFullInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
aircraft {
|
aircraft {
|
||||||
...aircraftFullInfo
|
...aircraftFullInfo
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ export const FRAGMENT_PHOTO_FULL_INFO = gql`
|
|||||||
name
|
name
|
||||||
description
|
description
|
||||||
flightId
|
flightId
|
||||||
pointOfInterestId
|
pointOfInterest {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
isFlightCover
|
isFlightCover
|
||||||
gpsLatitude
|
gpsLatitude
|
||||||
gpsLongitude
|
gpsLongitude
|
||||||
|
|||||||
@@ -75,11 +75,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {onMounted, ref, watch} from 'vue'
|
import {onMounted, ref} from 'vue'
|
||||||
import NavigationButton from "components/navigation/NavigationButton.vue";
|
import NavigationButton from "components/navigation/NavigationButton.vue";
|
||||||
import {useUserStore} from "stores/User";
|
import {useUserStore} from "stores/User";
|
||||||
import {storeToRefs} from "pinia";
|
import {storeToRefs} from "pinia";
|
||||||
import BreadcrumbsNavigation from "components/BreadcrumbsNavigation.vue";
|
import BreadcrumbsNavigation from "components/navigation/BreadcrumbsNavigation.vue";
|
||||||
import {useAppStore} from "stores/App";
|
import {useAppStore} from "stores/App";
|
||||||
import {useMeta, useQuasar} from "quasar";
|
import {useMeta, useQuasar} from "quasar";
|
||||||
import AvatarFromPhoto from "components/AvatarFromPhoto.vue";
|
import AvatarFromPhoto from "components/AvatarFromPhoto.vue";
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import {useUserStore} from "stores/User";
|
|||||||
import {onMounted} from "vue";
|
import {onMounted} from "vue";
|
||||||
import {useAppStore} from "stores/App";
|
import {useAppStore} from "stores/App";
|
||||||
import {useMeta} from "quasar";
|
import {useMeta} from "quasar";
|
||||||
import BreadcrumbsNavigation from "components/BreadcrumbsNavigation.vue";
|
import BreadcrumbsNavigation from "components/navigation/BreadcrumbsNavigation.vue";
|
||||||
import AvatarFromPhoto from "components/AvatarFromPhoto.vue";
|
import AvatarFromPhoto from "components/AvatarFromPhoto.vue";
|
||||||
|
|
||||||
const {pageTitle, breadcrumbs} = storeToRefs(useAppStore());
|
const {pageTitle, breadcrumbs} = storeToRefs(useAppStore());
|
||||||
|
|||||||
@@ -4,29 +4,26 @@ import {useAircraftsStore} from "stores/Aircrafts";
|
|||||||
import {useRoute, useRouter} from "vue-router";
|
import {useRoute, useRouter} from "vue-router";
|
||||||
import {useQuasar} from "quasar";
|
import {useQuasar} from "quasar";
|
||||||
import AircraftDetailSkeleton from "components/aircrafts/AircraftDetailSkeleton.vue";
|
import AircraftDetailSkeleton from "components/aircrafts/AircraftDetailSkeleton.vue";
|
||||||
import {confirmObject, successObject} from "src/composables/dialog";
|
import {successObject} from "src/composables/dialog";
|
||||||
import {loading, aircraft, fetchAircraft} from "src/composables/objects/aircraft";
|
import {loading, aircraft, fetchAircraft} from "src/composables/objects/aircraft";
|
||||||
import FAB from "components/FAB.vue";
|
|
||||||
import {useAppStore} from "stores/App";
|
import {useAppStore} from "stores/App";
|
||||||
import FlightsList from "components/flights/FlightsList.vue";
|
import FlightsList from "components/flights/FlightsList.vue";
|
||||||
import {copilot} from "src/composables/objects/copilot";
|
import AircraftDetailCard from "components/aircrafts/AircraftDetailCard.vue";
|
||||||
import {flight} from "src/composables/objects/flight";
|
|
||||||
|
const $q = useQuasar();
|
||||||
|
const $router = useRouter();
|
||||||
|
|
||||||
const aircraftId = parseInt(useRoute().params.id);
|
const aircraftId = parseInt(useRoute().params.id);
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchAircraft(aircraftId);
|
fetchAircraft(aircraftId);
|
||||||
})
|
})
|
||||||
|
|
||||||
const $q = useQuasar();
|
const deleteAircraft = (id) => {
|
||||||
const confirmDelete = (id) => {
|
|
||||||
$q.dialog(confirmObject('Opravdu chceš smazat toto letadlo?'))
|
|
||||||
.onOk(() => {
|
|
||||||
useAircraftsStore().delete(id).then(() => {
|
useAircraftsStore().delete(id).then(() => {
|
||||||
useRouter().push({name: "aircrafts"});
|
$router.push({name: "aircrafts"});
|
||||||
$q.notify(successObject("Letadlo uspesne odstraneno"));
|
$q.notify(successObject("Letadlo úspěšně odstraněno"));
|
||||||
});
|
});
|
||||||
})
|
}
|
||||||
};
|
|
||||||
|
|
||||||
watch(aircraft, (newVal) => {
|
watch(aircraft, (newVal) => {
|
||||||
useAppStore().setPageTitle(newVal.callSign);
|
useAppStore().setPageTitle(newVal.callSign);
|
||||||
@@ -35,47 +32,12 @@ watch(aircraft, (newVal) => {
|
|||||||
{label: newVal.callSign}
|
{label: newVal.callSign}
|
||||||
])
|
])
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<AircraftDetailSkeleton v-if="loading || !aircraft"/>
|
<AircraftDetailSkeleton v-if="loading || !aircraft"/>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
<AircraftDetailCard :aircraft="aircraft" @delete="deleteAircraft" />
|
||||||
<q-card class="q-mx-md q-my-md flight-detail-card">
|
|
||||||
<q-img :src="aircraft.photoUrl" v-if="aircraft.photoUrl" />
|
|
||||||
|
|
||||||
<q-card-actions class="q-my-md">
|
|
||||||
<div class="col-grow">
|
|
||||||
<q-btn
|
|
||||||
flat
|
|
||||||
:to='{name: "aircraftEdit", params: {id: aircraft.id}}'
|
|
||||||
icon="edit"
|
|
||||||
text-color="primary"
|
|
||||||
label="Upravit"
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<q-btn @click="confirmDelete(aircraft.id)" icon="delete" flat text-color="red" label="Smazat"/>
|
|
||||||
</q-card-actions>
|
|
||||||
|
|
||||||
<q-card-section>
|
|
||||||
<q-list>
|
|
||||||
<q-item v-if="aircraft.manufacturer">
|
|
||||||
Výrobce: {{ aircraft.manufacturer }}
|
|
||||||
</q-item>
|
|
||||||
<q-item v-if="aircraft.model">
|
|
||||||
Model: {{ aircraft.model }}
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</q-card-section>
|
|
||||||
|
|
||||||
<!-- <q-card-actions align="right">-->
|
|
||||||
<!-- <q-btn :to='{name: "aircraftEdit", params: {id: aircraft.id}}' icon="edit" text-color="primary" rounded flat/>-->
|
|
||||||
<!-- <q-btn @click="confirmDelete(aircraft.id)" icon="delete" text-color="red" rounded flat/>-->
|
|
||||||
<!-- </q-card-actions>-->
|
|
||||||
</q-card>
|
|
||||||
|
|
||||||
<q-card class="flight-detail-card" flat>
|
<q-card class="flight-detail-card" flat>
|
||||||
<h3>Lety</h3>
|
<h3>Lety</h3>
|
||||||
@@ -84,8 +46,6 @@ watch(aircraft, (newVal) => {
|
|||||||
</q-banner>
|
</q-banner>
|
||||||
<FlightsList :items="aircraft.flights" v-else/>
|
<FlightsList :items="aircraft.flights" v-else/>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
|
||||||
<!-- <FAB :router-link='{name: "aircraftEdit", params: {id: aircraft.id}}' mode="edit"/>-->
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import AircraftsList from "components/aircrafts/AircraftsList.vue";
|
|||||||
import {aircrafts, fetchAircrafts, loading} from "src/composables/objects/aircraft";
|
import {aircrafts, fetchAircrafts, loading} from "src/composables/objects/aircraft";
|
||||||
import FAB from "components/FAB.vue";
|
import FAB from "components/FAB.vue";
|
||||||
import BasicListSkeleton from "components/basicSkeletons/BasicListSkeleton.vue";
|
import BasicListSkeleton from "components/basicSkeletons/BasicListSkeleton.vue";
|
||||||
|
import BasicInfoBanner from "components/banners/BasicInfoBanner.vue";
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchAircrafts();
|
fetchAircrafts();
|
||||||
@@ -13,17 +14,13 @@ onMounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<BasicListSkeleton v-if="loading"/>
|
<BasicListSkeleton v-if="loading"/>
|
||||||
|
|
||||||
<div class="q-pa-md q-gutter-sm" v-else-if="!loading && aircrafts.length === 0">
|
<BasicInfoBanner
|
||||||
<q-banner class="bg-light-blue text-white">
|
v-if="!loading && aircrafts.length === 0"
|
||||||
<template v-slot:avatar>
|
:route-add="{name: 'addAircraft'}"
|
||||||
<q-icon name="info"/>
|
label-add="Vytvořit letadlo"
|
||||||
</template>
|
>
|
||||||
Aktuálně nemáš přidané žádné letadlo.
|
Aktuálně nemáš přidané žádné letadlo.
|
||||||
<template v-slot:action>
|
</BasicInfoBanner>
|
||||||
<q-btn flat color="white" :to="{name: 'addAircraft'}" label="Vytvořit letadlo"/>
|
|
||||||
</template>
|
|
||||||
</q-banner>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<AircraftsList
|
<AircraftsList
|
||||||
v-else
|
v-else
|
||||||
|
|||||||
@@ -3,26 +3,21 @@ import AircraftForm from "components/aircrafts/AircraftForm.vue";
|
|||||||
import {useAircraftsStore} from "stores/Aircrafts";
|
import {useAircraftsStore} from "stores/Aircrafts";
|
||||||
import {useRoute, useRouter} from "vue-router";
|
import {useRoute, useRouter} from "vue-router";
|
||||||
import {useQuasar} from "quasar";
|
import {useQuasar} from "quasar";
|
||||||
import {onMounted, ref} from "vue";
|
import {onMounted} from "vue";
|
||||||
import AircraftEditSkeleton from "components/aircrafts/AircraftEditSkeleton.vue";
|
import AircraftEditSkeleton from "components/aircrafts/AircraftEditSkeleton.vue";
|
||||||
import {successObject} from "src/composables/dialog";
|
import {successObject} from "src/composables/dialog";
|
||||||
import {aircraft, fetchAircraft, loading} from "src/composables/objects/aircraft";
|
import {aircraft, fetchAircraft, loading, isRequestPending} from "src/composables/objects/aircraft";
|
||||||
import {useAppStore} from "stores/App";
|
import {useAppStore} from "stores/App";
|
||||||
import {copilot} from "src/composables/objects/copilot";
|
|
||||||
|
|
||||||
|
|
||||||
const isRequestPending = ref(false);
|
|
||||||
const $router = useRouter();
|
const $router = useRouter();
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const aircraftId = parseInt(useRoute().params.id);
|
const aircraftId = parseInt(useRoute().params.id);
|
||||||
|
|
||||||
const handleSave = (formData) => {
|
const handleSave = (formData) => {
|
||||||
isRequestPending.value = true;
|
|
||||||
useAircraftsStore().update(aircraftId, formData).then(() => {
|
useAircraftsStore().update(aircraftId, formData).then(() => {
|
||||||
$q.notify(successObject("Letadlo úspěšně upraveno"));
|
$q.notify(successObject("Letadlo úspěšně upraveno"));
|
||||||
$router.push({name: "aircrafts"});
|
$router.push({name: "aircraftDetail", params: {id: aircraftId}});
|
||||||
}).finally(() => {
|
|
||||||
isRequestPending.value = false;
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,21 +6,17 @@ import {useQuasar} from "quasar";
|
|||||||
import {ref} from "vue";
|
import {ref} from "vue";
|
||||||
import {useAppStore} from "stores/App";
|
import {useAppStore} from "stores/App";
|
||||||
import {successObject} from "src/composables/dialog";
|
import {successObject} from "src/composables/dialog";
|
||||||
|
import {isRequestPending} from "src/composables/objects/aircraft";
|
||||||
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
let isRequestPending = ref(false);
|
|
||||||
const handleSave = (formData) => {
|
const handleSave = (formData) => {
|
||||||
isRequestPending.value = true;
|
|
||||||
useAircraftsStore().create(formData).then(() => {
|
useAircraftsStore().create(formData).then(() => {
|
||||||
$q.notify(successObject("Letadlo úspěšně vytvořeno"));
|
$q.notify(successObject("Letadlo úspěšně vytvořeno"));
|
||||||
router.push({name: "aircrafts"});
|
router.push({name: "aircrafts"});
|
||||||
}).finally(() => {
|
});
|
||||||
isRequestPending.value = false;
|
};
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
useAppStore().setPageTitle("Nové letadlo");
|
useAppStore().setPageTitle("Nové letadlo");
|
||||||
useAppStore().setBreadcrumbs([
|
useAppStore().setBreadcrumbs([
|
||||||
|
|||||||
@@ -24,9 +24,11 @@ onMounted(() => {
|
|||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<h3>Společné lety</h3>
|
<h3>Společné lety</h3>
|
||||||
|
|
||||||
<q-banner v-if="copilot.flights.length === 0" class="bg-light-blue text-white">
|
<q-banner v-if="copilot.flights.length === 0" class="bg-light-blue text-white">
|
||||||
Zatím žádné společné lety
|
Zatím tu nemáš uložené žádné společné lety.
|
||||||
</q-banner>
|
</q-banner>
|
||||||
|
|
||||||
<FlightsList :items="copilot.flights" v-else/>
|
<FlightsList :items="copilot.flights" v-else/>
|
||||||
|
|
||||||
<FAB mode="edit" :router-link="{name: 'copilotEdit', params: {id: copilotId}}"/>
|
<FAB mode="edit" :router-link="{name: 'copilotEdit', params: {id: copilotId}}"/>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import CopilotsList from "components/copilots/CopilotsList.vue";
|
|||||||
import FAB from "components/FAB.vue";
|
import FAB from "components/FAB.vue";
|
||||||
import {useAppStore} from "stores/App";
|
import {useAppStore} from "stores/App";
|
||||||
import BasicListSkeleton from "components/basicSkeletons/BasicListSkeleton.vue";
|
import BasicListSkeleton from "components/basicSkeletons/BasicListSkeleton.vue";
|
||||||
import BasicInfoBanner from "components/BasicInfoBanner.vue";
|
import BasicInfoBanner from "components/banners/BasicInfoBanner.vue";
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchCopilots();
|
fetchCopilots();
|
||||||
@@ -16,7 +16,10 @@ onMounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<BasicListSkeleton :items-count-min="5" :items-count-max="10" v-if="loading"/>
|
<BasicListSkeleton :items-count-min="5" :items-count-max="10" v-if="loading"/>
|
||||||
|
|
||||||
<BasicInfoBanner v-else-if="!loading && copilots.length === 0" :router-add="{name: 'addCopilot'}">
|
<BasicInfoBanner
|
||||||
|
v-else-if="!loading && copilots.length === 0"
|
||||||
|
:router-add="{name: 'addCopilot'}"
|
||||||
|
>
|
||||||
Zatím tu není nikdo. Přidej si let s někým nebo kopilota vytvoř ručně tu.
|
Zatím tu není nikdo. Přidej si let s někým nebo kopilota vytvoř ručně tu.
|
||||||
</BasicInfoBanner>
|
</BasicInfoBanner>
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {onMounted} from "vue";
|
import {onMounted} from "vue";
|
||||||
import {loading, copilot, fetchCopilot} from "src/composables/objects/copilot";
|
import {loading, copilot, fetchCopilot, isRequestPending} from "src/composables/objects/copilot";
|
||||||
import {useAppStore} from "stores/App";
|
import {useAppStore} from "stores/App";
|
||||||
import CopilotEditSkeleton from "components/copilots/CopilotEditSkeleton.vue";
|
import CopilotEditSkeleton from "components/copilots/CopilotEditSkeleton.vue";
|
||||||
import CopilotEditForm from "components/copilots/CopilotForm.vue";
|
import CopilotEditForm from "components/copilots/CopilotForm.vue";
|
||||||
import {useRoute} from "vue-router";
|
import {useRoute, useRouter} from "vue-router";
|
||||||
import {useCopilotsStore} from "stores/Copilots";
|
import {useCopilotsStore} from "stores/Copilots";
|
||||||
import {successObject} from "src/composables/dialog";
|
import {successObject} from "src/composables/dialog";
|
||||||
import {useQuasar} from "quasar";
|
import {useQuasar} from "quasar";
|
||||||
@@ -23,19 +23,23 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
|
const $router = useRouter();
|
||||||
|
|
||||||
const handleSave = (formData) => {
|
const handleSave = (formData) => {
|
||||||
useCopilotsStore().update(copilotId, formData).then(() => {
|
useCopilotsStore().update(copilotId, formData).then(() => {
|
||||||
$q.notify(successObject("Kopilot úspěšně upraven"));
|
$q.notify(successObject("Kopilot úspěšně upraven"));
|
||||||
|
$router.push({name: "copilotDetail", params: {id: copilotId}});
|
||||||
// useRouter().push({name: "copilots"});
|
});
|
||||||
// TODO: ^^ hazi error
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CopilotEditSkeleton v-if="loading"/>
|
<CopilotEditSkeleton v-if="loading"/>
|
||||||
|
|
||||||
<CopilotEditForm v-else :copilot="copilot" @save="handleSave"/>
|
<CopilotEditForm
|
||||||
|
v-else
|
||||||
|
:copilot="copilot"
|
||||||
|
:is-request-pending="isRequestPending"
|
||||||
|
@save="handleSave"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,24 +1,20 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {useRouter} from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
import {useQuasar} from "quasar";
|
import {useQuasar} from "quasar";
|
||||||
import {ref} from "vue";
|
|
||||||
import {successObject} from "src/composables/dialog";
|
import {successObject} from "src/composables/dialog";
|
||||||
import {useCopilotsStore} from "stores/Copilots";
|
import {useCopilotsStore} from "stores/Copilots";
|
||||||
import CopilotForm from "components/copilots/CopilotForm.vue";
|
import CopilotForm from "components/copilots/CopilotForm.vue";
|
||||||
import {useAppStore} from "stores/App";
|
import {useAppStore} from "stores/App";
|
||||||
|
import {isRequestPending} from "src/composables/objects/copilot";
|
||||||
|
|
||||||
let isRequestPending = ref(false);
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const handleSave = (formData) => {
|
const handleSave = (formData) => {
|
||||||
isRequestPending.value = true;
|
|
||||||
useCopilotsStore().create(formData).then(() => {
|
useCopilotsStore().create(formData).then(() => {
|
||||||
$q.notify(successObject("Kopilot úspěšně vytvořen"));
|
$q.notify(successObject("Kopilot úspěšně vytvořen"));
|
||||||
router.push({name: "copilots"});
|
router.push({name: "copilots"});
|
||||||
}).finally(() => {
|
});
|
||||||
isRequestPending.value = false;
|
};
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
useAppStore().setPageTitle("Nový spolucestující");
|
useAppStore().setPageTitle("Nový spolucestující");
|
||||||
useAppStore().setBreadcrumbs([
|
useAppStore().setBreadcrumbs([
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import FlightFormSteps from "components/flights/form/FlightFormSteps.vue";
|
import FlightFormSteps from "components/flights/form/FlightFormSteps.vue";
|
||||||
import {computed, onMounted, reactive, ref, watch} from "vue";
|
import {onMounted, ref, watch} from "vue";
|
||||||
import {useRoute} from "vue-router";
|
import {useRoute} from "vue-router";
|
||||||
import {useFlightsStore} from "stores/Flights";
|
import {useFlightsStore} from "stores/Flights";
|
||||||
import FlightFormBasic from "components/flights/form/FlightFormBasic.vue";
|
import FlightFormBasic from "components/flights/form/FlightFormBasic.vue";
|
||||||
import {useAircraftsStore} from "stores/Aircrafts";
|
import {useAircraftsStore} from "stores/Aircrafts";
|
||||||
import {usePointsOfInterestStore} from "stores/PointsOfInterest";
|
import {usePointsOfInterestStore} from "stores/PointsOfInterest";
|
||||||
import {useAirportsStore} from "stores/Airports";
|
import {useAirportsStore} from "stores/Airports";
|
||||||
import {useMeta, useQuasar} from "quasar";
|
import {useQuasar} from "quasar";
|
||||||
import {storeToRefs} from "pinia";
|
import {storeToRefs} from "pinia";
|
||||||
import {flightName} from "src/composables/objects/flight";
|
import {flightName} from "src/composables/objects/flight";
|
||||||
import FlightFormCopilot from "components/flights/form/FlightFormCopilot.vue";
|
import FlightFormCopilot from "components/flights/form/FlightFormCopilot.vue";
|
||||||
@@ -16,17 +16,19 @@ import FlightFormNotes from "components/flights/form/FlightFormNotes.vue";
|
|||||||
import FlightFormPhotos from "components/flights/form/FlightFormPhotos.vue";
|
import FlightFormPhotos from "components/flights/form/FlightFormPhotos.vue";
|
||||||
import {usePhotosStore} from "stores/Photo";
|
import {usePhotosStore} from "stores/Photo";
|
||||||
import PhotosList from "components/photos/PhotosList.vue";
|
import PhotosList from "components/photos/PhotosList.vue";
|
||||||
import {confirmObject, successObject} from "src/composables/dialog";
|
import {successObject} from "src/composables/dialog";
|
||||||
import PhotoForm from "components/photos/PhotoForm.vue";
|
import PhotoFormDialog from "components/photos/PhotoFormDialog.vue";
|
||||||
import FlightFormTrack from "components/flights/form/FlightFormTrack.vue";
|
import FlightFormTrack from "components/flights/form/FlightFormTrack.vue";
|
||||||
import {fetchFlight, flight, loading} from "src/composables/objects/flight";
|
import {fetchFlight, flight, loading} from "src/composables/objects/flight";
|
||||||
import FlightEditSkeleton from "components/flights/FlightEditSkeleton.vue";
|
import FlightEditSkeleton from "components/flights/FlightEditSkeleton.vue";
|
||||||
|
import BatchPhotoFormDialog from "components/photos/BatchPhotoFormDialog.vue";
|
||||||
useMeta({title: "Editace letu"});
|
import {useAppStore} from "stores/App";
|
||||||
|
import {editBatchPhotos, handleBatchPhotoEdit, openBatchEdit, openBatchPhotoForm} from "src/composables/photos/batchEdit";
|
||||||
|
import {editPhoto, handlePhotoUpdate, openEdit, openPhotoEdit} from "src/composables/photos/simpleEdit";
|
||||||
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const route = useRoute();
|
const $route = useRoute();
|
||||||
const flightId = parseInt(route.params.id);
|
const flightId = parseInt($route.params.id);
|
||||||
|
|
||||||
const aircrafts = storeToRefs(useAircraftsStore()).items;
|
const aircrafts = storeToRefs(useAircraftsStore()).items;
|
||||||
const locations = storeToRefs(usePointsOfInterestStore()).items;
|
const locations = storeToRefs(usePointsOfInterestStore()).items;
|
||||||
@@ -34,17 +36,26 @@ const airports = storeToRefs(useAirportsStore()).items;
|
|||||||
const copilots = storeToRefs(useCopilotsStore()).items;
|
const copilots = storeToRefs(useCopilotsStore()).items;
|
||||||
|
|
||||||
const formStep = ref("");
|
const formStep = ref("");
|
||||||
watch(() => route.params.step, (val) => formStep.value = val);
|
watch(() => $route.params.step, (val) => formStep.value = val);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
formStep.value = route.params.step || "basic";
|
formStep.value = $route.params.step || "basic";
|
||||||
|
|
||||||
useAircraftsStore().fetch();
|
useAircraftsStore().fetch();
|
||||||
usePointsOfInterestStore().fetch();
|
usePointsOfInterestStore().fetch();
|
||||||
useAirportsStore().fetch();
|
useAirportsStore().fetch();
|
||||||
useCopilotsStore().fetch();
|
useCopilotsStore().fetch();
|
||||||
|
|
||||||
fetchFlight(flightId);
|
fetchFlight(flightId).then(() => {
|
||||||
|
const flightNameFormatted = flightName(flight.value);
|
||||||
|
|
||||||
|
useAppStore().setPageTitle(`Editace - ${flightNameFormatted}`);
|
||||||
|
useAppStore().setBreadcrumbs([
|
||||||
|
{to: {name: "myFlights"}, label: "Moje lety"},
|
||||||
|
{to: {name: "flightDetail", params: {id: flightId}}, label: flightNameFormatted},
|
||||||
|
{label: "Editace"}
|
||||||
|
]);
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleFlightEdit = (data) => {
|
const handleFlightEdit = (data) => {
|
||||||
@@ -56,9 +67,11 @@ const handleFlightEdit = (data) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isRequestPending = storeToRefs(useFlightsStore()).isMutationRunning;
|
const isRequestPending = storeToRefs(useFlightsStore()).isMutationRunning;
|
||||||
|
const uploadInProgress = ref(false);
|
||||||
|
|
||||||
const handlePhotosUpload = (data) => {
|
const handlePhotosUpload = (data) => {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
uploadInProgress.value = true;
|
||||||
for (const photo of data.photos) {
|
for (const photo of data.photos) {
|
||||||
promises.push(usePhotosStore().upload(flightId, {photo}));
|
promises.push(usePhotosStore().upload(flightId, {photo}));
|
||||||
}
|
}
|
||||||
@@ -66,48 +79,24 @@ const handlePhotosUpload = (data) => {
|
|||||||
Promise.all(promises).then(() => {
|
Promise.all(promises).then(() => {
|
||||||
$q.notify(successObject("Úspěšně nahráno"));
|
$q.notify(successObject("Úspěšně nahráno"));
|
||||||
fetchFlight(flightId);
|
fetchFlight(flightId);
|
||||||
});
|
}).finally(() => uploadInProgress.value = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const _findPhotoIndex = (photoId) => flight.value.photos.findIndex((object) => object.id === photoId);
|
const _findPhotoIndex = (photoId) => flight.value.photos.findIndex((object) => object.id === photoId);
|
||||||
const confirmPhotoDelete = (id) => {
|
const deletePhoto = (id) => {
|
||||||
$q.dialog(confirmObject("Opravdu chces smazat tuto fotku?"))
|
|
||||||
.onOk(() => {
|
|
||||||
usePhotosStore().delete(id).then((data) => {
|
usePhotosStore().delete(id).then((data) => {
|
||||||
flight.value.photos.splice(_findPhotoIndex(data.id), 1);
|
flight.value.photos.splice(_findPhotoIndex(data.id), 1);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlePhotoUpdate = (formData) => {
|
|
||||||
const photoId = formData.id;
|
|
||||||
delete formData.id;
|
|
||||||
|
|
||||||
usePhotosStore().update(photoId, formData).then((data) => {
|
|
||||||
const idx = _findPhotoIndex(data.id);
|
|
||||||
flight.value.photos[idx] = data;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const openEdit = ref(false);
|
|
||||||
const editPhoto = ref(null);
|
|
||||||
const openPhotoEdit = (photo) => {
|
|
||||||
openEdit.value = true;
|
|
||||||
editPhoto.value = photo;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FlightEditSkeleton v-if="loading"/>
|
<FlightEditSkeleton v-if="loading"/>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<q-breadcrumbs :key="loading">
|
<FlightFormSteps :router-edit-mode="true" :flightId="flightId"/>
|
||||||
<q-breadcrumbs-el :to="{name: 'myFlights'}">Moje lety</q-breadcrumbs-el>
|
|
||||||
<q-breadcrumbs-el :to="{name: 'flightDetail', params: {id: flightId}}">{{ flightName(flight) }}</q-breadcrumbs-el>
|
|
||||||
<q-breadcrumbs-el>Editace</q-breadcrumbs-el>
|
|
||||||
</q-breadcrumbs>
|
|
||||||
|
|
||||||
<FlightFormSteps :router-edit-mode="true" :flightId="flightId" />
|
|
||||||
|
|
||||||
<q-tab-panels v-model="formStep">
|
<q-tab-panels v-model="formStep">
|
||||||
<q-tab-panel name="basic">
|
<q-tab-panel name="basic">
|
||||||
@@ -136,23 +125,31 @@ const openPhotoEdit = (photo) => {
|
|||||||
<q-tab-panel name="photos">
|
<q-tab-panel name="photos">
|
||||||
<FlightFormPhotos
|
<FlightFormPhotos
|
||||||
:flight="flight"
|
:flight="flight"
|
||||||
:is-request-pending="isRequestPending"
|
:is-request-pending="isRequestPending || uploadInProgress"
|
||||||
@save="handlePhotosUpload"
|
@save="handlePhotosUpload"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<PhotoForm
|
|
||||||
v-model="openEdit"
|
|
||||||
:locations="locations"
|
|
||||||
:photo="editPhoto"
|
|
||||||
@save="handlePhotoUpdate"
|
|
||||||
/>
|
|
||||||
|
|
||||||
Tu nejsou videt fotky po nahrani
|
|
||||||
|
|
||||||
<PhotosList
|
<PhotosList
|
||||||
:photos="flight.photos"
|
:photos="flight.photos"
|
||||||
@edit="openPhotoEdit"
|
@edit="openPhotoEdit"
|
||||||
@delete="confirmPhotoDelete"
|
@batch-edit="openBatchPhotoForm"
|
||||||
|
@delete="deletePhoto"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Dialogs for photo edit -->
|
||||||
|
<PhotoFormDialog
|
||||||
|
v-model="openEdit"
|
||||||
|
:locations="locations"
|
||||||
|
:photo="editPhoto"
|
||||||
|
@save="handlePhotoUpdate(flightId, $event)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<BatchPhotoFormDialog
|
||||||
|
v-model="openBatchEdit"
|
||||||
|
:locations="locations"
|
||||||
|
:photos="editBatchPhotos"
|
||||||
|
@save="handleBatchPhotoEdit(flightId, $event)"
|
||||||
|
@delete="deletePhoto"
|
||||||
/>
|
/>
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,14 @@ import {useFlightsStore} from "stores/Flights";
|
|||||||
import PhotoCarousel from "components/flights/PhotoCarousel.vue";
|
import PhotoCarousel from "components/flights/PhotoCarousel.vue";
|
||||||
import FlightTrackMap from "components/flights/FlightTrackMap.vue";
|
import FlightTrackMap from "components/flights/FlightTrackMap.vue";
|
||||||
import {useUserStore} from "stores/User";
|
import {useUserStore} from "stores/User";
|
||||||
|
import {storeToRefs} from "pinia";
|
||||||
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const $router = useRouter();
|
const $router = useRouter();
|
||||||
const flightId = parseInt(useRoute().params.id);
|
const flightId = parseInt(useRoute().params.id);
|
||||||
|
|
||||||
|
const loggedUser = storeToRefs(useUserStore()).user;
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchFlight(flightId);
|
fetchFlight(flightId);
|
||||||
})
|
})
|
||||||
@@ -59,7 +62,6 @@ const copyLinkToClipboard = () => {
|
|||||||
$q.notify(successObject("Odkaz zkopírován"))
|
$q.notify(successObject("Odkaz zkopírován"))
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
@@ -82,6 +84,7 @@ const copyLinkToClipboard = () => {
|
|||||||
<q-btn
|
<q-btn
|
||||||
@click="togglePublicVisibility"
|
@click="togglePublicVisibility"
|
||||||
:icon="flight.isPublic ? 'visibility_off' : 'visibility'"
|
:icon="flight.isPublic ? 'visibility_off' : 'visibility'"
|
||||||
|
:disable="!loggedUser.publicUsername"
|
||||||
flat
|
flat
|
||||||
:label="flight.isPublic ? 'Skrýt' : 'Zveřejnit'"
|
:label="flight.isPublic ? 'Skrýt' : 'Zveřejnit'"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import FlightsListSkeleton from "components/flights/FlightsListSkeleton.vue";
|
|||||||
import FAB from "components/FAB.vue";
|
import FAB from "components/FAB.vue";
|
||||||
import {fetchFlights, flights, handleDeleteFlight, loading} from "src/composables/objects/flight";
|
import {fetchFlights, flights, handleDeleteFlight, loading} from "src/composables/objects/flight";
|
||||||
import {useAppStore} from "stores/App";
|
import {useAppStore} from "stores/App";
|
||||||
|
import BasicInfoBanner from "components/banners/BasicInfoBanner.vue";
|
||||||
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
|
|
||||||
@@ -18,19 +19,15 @@ onMounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<FlightsListSkeleton v-if="loading"/>
|
<FlightsListSkeleton v-if="loading"/>
|
||||||
|
|
||||||
<div class="q-pa-md q-gutter-sm" v-else-if="!loading && flights.length === 0">
|
<BasicInfoBanner
|
||||||
<q-banner class="bg-light-blue text-white">
|
v-else-if="!loading && flights.length === 0"
|
||||||
<template v-slot:avatar>
|
:route-add="{name: 'addFlight'}"
|
||||||
<q-icon name="info"/>
|
label-add="Přidat let"
|
||||||
</template>
|
>
|
||||||
Nemáš zaznamenaný žádný let.
|
Nemáš zaznamenaný žádný let.
|
||||||
<template v-slot:action>
|
</BasicInfoBanner>
|
||||||
<q-btn flat color="white" :to="{name: 'addFlight'}" label="Přidat let"/>
|
|
||||||
</template>
|
|
||||||
</q-banner>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<FlightsList v-else :items="flights" @delete="handleDeleteFlight($q, $event)" />
|
<FlightsList v-else :items="flights" @delete="handleDeleteFlight($q, $event)"/>
|
||||||
|
|
||||||
<FAB mode="add" :router-link="{name: 'addFlight'}"/>
|
<FAB mode="add" :router-link="{name: 'addFlight'}"/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {onMounted} from "vue";
|
import {onMounted, ref} from "vue";
|
||||||
import {useAircraftsStore} from "stores/Aircrafts";
|
import {useAircraftsStore} from "stores/Aircrafts";
|
||||||
import {useFlightsStore} from "stores/Flights";
|
import {useFlightsStore} from "stores/Flights";
|
||||||
import {useRouter} from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
@@ -9,13 +9,20 @@ import {useAirportsStore} from "stores/Airports";
|
|||||||
import FlightFormSteps from "components/flights/form/FlightFormSteps.vue";
|
import FlightFormSteps from "components/flights/form/FlightFormSteps.vue";
|
||||||
import FlightFormBasic from "components/flights/form/FlightFormBasic.vue";
|
import FlightFormBasic from "components/flights/form/FlightFormBasic.vue";
|
||||||
import {useAppStore} from "stores/App";
|
import {useAppStore} from "stores/App";
|
||||||
|
import {isRequestPending} from "src/composables/objects/flight";
|
||||||
|
import FlightEditSkeleton from "components/flights/FlightEditSkeleton.vue";
|
||||||
|
|
||||||
|
const loading = ref(true);
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
useAircraftsStore().fetch();
|
const promises = [
|
||||||
usePointsOfInterestStore().fetch();
|
useAircraftsStore().fetch(),
|
||||||
useFlightsStore().fetch();
|
usePointsOfInterestStore().fetch(),
|
||||||
useAirportsStore().fetch();
|
useFlightsStore().fetch(),
|
||||||
|
useAirportsStore().fetch(),
|
||||||
|
];
|
||||||
|
|
||||||
|
loading.value = true;
|
||||||
|
Promise.all(promises).finally(() => loading.value = false);
|
||||||
|
|
||||||
useAppStore().setPageTitle("Nový let");
|
useAppStore().setPageTitle("Nový let");
|
||||||
useAppStore().setBreadcrumbs([
|
useAppStore().setBreadcrumbs([
|
||||||
@@ -38,10 +45,15 @@ const handleSave = (formData) => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FlightFormSteps :disabled="['copilot', 'track', 'photos', 'notes']"/>
|
<FlightFormSteps :disabled="['copilot', 'track', 'photos', 'notes']"/>
|
||||||
|
|
||||||
|
<FlightEditSkeleton v-if="loading"/>
|
||||||
|
<template v-else>
|
||||||
<FlightFormBasic
|
<FlightFormBasic
|
||||||
@save="handleSave"
|
@save="handleSave"
|
||||||
|
:is-request-pending="isRequestPending"
|
||||||
:aircrafts="aircrafts"
|
:aircrafts="aircrafts"
|
||||||
:airports="airports"
|
:airports="airports"
|
||||||
:locations="locations"
|
:locations="locations"
|
||||||
/>
|
/>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {usePointsOfInterestTypeStore} from "stores/PointOfInterestType";
|
|||||||
import {storeToRefs} from "pinia";
|
import {storeToRefs} from "pinia";
|
||||||
import POIForm from "components/poi/POIForm.vue";
|
import POIForm from "components/poi/POIForm.vue";
|
||||||
import {useUserStore} from "stores/User";
|
import {useUserStore} from "stores/User";
|
||||||
import AccessDeniedBanner from "components/AccessDeniedBanner.vue";
|
import AccessDeniedBanner from "components/banners/AccessDeniedBanner.vue";
|
||||||
|
|
||||||
const poiId = parseInt(useRoute().params.id);
|
const poiId = parseInt(useRoute().params.id);
|
||||||
|
|
||||||
@@ -43,6 +43,9 @@ const handleSave = (data) => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<POIEditSkeleton v-if="loading"/>
|
<POIEditSkeleton v-if="loading"/>
|
||||||
<AccessDeniedBanner v-else-if="poi.createdbyId !== loggedUser.id" :route-back="{name: 'poiDetail', params: {id: poiId}}"/>
|
<AccessDeniedBanner
|
||||||
|
v-else-if="poi.createdById !== loggedUser.id"
|
||||||
|
:route-back="{name: 'poiDetail', params: {id: poiId}}"
|
||||||
|
/>
|
||||||
<POIForm :poi="poi" :types="poiTypes" v-else @save="handleSave"/>
|
<POIForm :poi="poi" :types="poiTypes" v-else @save="handleSave"/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {useRouter} from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
import {useQuasar} from "quasar";
|
import {useQuasar} from "quasar";
|
||||||
import {ref} from "vue";
|
|
||||||
import POIForm from "components/poi/POIForm.vue";
|
import POIForm from "components/poi/POIForm.vue";
|
||||||
import {usePointsOfInterestStore} from "stores/PointsOfInterest";
|
import {usePointsOfInterestStore} from "stores/PointsOfInterest";
|
||||||
import {successObject} from "src/composables/dialog";
|
import {successObject} from "src/composables/dialog";
|
||||||
@@ -17,7 +16,6 @@ const handleSave = (formData) => {
|
|||||||
router.push({name: "poi"});
|
router.push({name: "poi"});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const isRequestPending = storeToRefs(usePointsOfInterestStore()).isMutationRunning;
|
const isRequestPending = storeToRefs(usePointsOfInterestStore()).isMutationRunning;
|
||||||
|
|
||||||
useAppStore().setPageTitle("Nové zajímavé místo");
|
useAppStore().setPageTitle("Nové zajímavé místo");
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {useAppStore} from "stores/App";
|
|||||||
import EmbeddedMap from "components/map/EmbeddedMap.vue";
|
import EmbeddedMap from "components/map/EmbeddedMap.vue";
|
||||||
import {useUserStore} from "stores/User";
|
import {useUserStore} from "stores/User";
|
||||||
import {storeToRefs} from "pinia";
|
import {storeToRefs} from "pinia";
|
||||||
import BasicInfoBanner from "components/BasicInfoBanner.vue";
|
import BasicInfoBanner from "components/banners/BasicInfoBanner.vue";
|
||||||
import FlightsList from "components/flights/FlightsList.vue";
|
import FlightsList from "components/flights/FlightsList.vue";
|
||||||
|
|
||||||
const loggedUser = storeToRefs(useUserStore()).user;
|
const loggedUser = storeToRefs(useUserStore()).user;
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import {useAppStore} from "stores/App";
|
|||||||
import POIList from "components/poi/POIList.vue";
|
import POIList from "components/poi/POIList.vue";
|
||||||
import FAB from "components/FAB.vue";
|
import FAB from "components/FAB.vue";
|
||||||
import BasicListSkeleton from "components/basicSkeletons/BasicListSkeleton.vue";
|
import BasicListSkeleton from "components/basicSkeletons/BasicListSkeleton.vue";
|
||||||
|
import {flights} from "src/composables/objects/flight";
|
||||||
|
import BasicInfoBanner from "components/banners/BasicInfoBanner.vue";
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchPOIList();
|
fetchPOIList();
|
||||||
@@ -15,19 +17,14 @@ useAppStore().setPageTitle("Zajímavá místa")
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<BasicListSkeleton :items-count-min="5" :items-count-max="10" v-if="loading"/>
|
<BasicListSkeleton :items-count-min="5" :items-count-max="10" v-if="loading"/>
|
||||||
|
<BasicInfoBanner
|
||||||
<div class="q-pa-md q-gutter-sm" v-else-if="!loading && pointsOfInterest.length === 0">
|
v-else-if="!loading && pointsOfInterest.length === 0"
|
||||||
<q-banner class="bg-light-blue text-white">
|
:route-add="{name: 'addPoi'}"
|
||||||
<template v-slot:avatar>
|
label-add="Přidat"
|
||||||
<q-icon name="info"/>
|
>
|
||||||
</template>
|
|
||||||
Nemáš tu uložené žádné zajímavé místo. Přidej si let, nastav si tam ručně trasu a jednotlivé body se zobrazí
|
Nemáš tu uložené žádné zajímavé místo. Přidej si let, nastav si tam ručně trasu a jednotlivé body se zobrazí
|
||||||
i v tomto seznamu.
|
i v tomto seznamu.
|
||||||
<template v-slot:action>
|
</BasicInfoBanner>
|
||||||
<q-btn flat color="white" :to="{name: 'addPoi'}" label="Přidat"/>
|
|
||||||
</template>
|
|
||||||
</q-banner>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<POIList
|
<POIList
|
||||||
v-else
|
v-else
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import {ref} from "vue";
|
import {ref} from "vue";
|
||||||
import {useUserStore} from "stores/User";
|
import {useUserStore} from "stores/User";
|
||||||
import {useRouter} from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
|
import {isRequired, isValidEmail, minLength} from "src/composables/form/rules";
|
||||||
|
|
||||||
const email = ref("");
|
const email = ref("");
|
||||||
const password = ref("");
|
const password = ref("");
|
||||||
@@ -12,6 +13,11 @@ const logUser = () => {
|
|||||||
router.push({name: "myFlights"});
|
router.push({name: "myFlights"});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
email: [isRequired, isValidEmail],
|
||||||
|
password: [isRequired, minLength(4)]
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -25,12 +31,12 @@ const logUser = () => {
|
|||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-form class="q-px-sm q-pt-xl" @submit.prevent="logUser()">
|
<q-form class="q-px-sm q-pt-xl" @submit.prevent="logUser()">
|
||||||
<q-input square clearable v-model="email" type="email" label="Email">
|
<q-input square clearable v-model="email" :rules="rules.email" type="email" label="E-mail">
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
<q-icon name="email"/>
|
<q-icon name="email"/>
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
<q-input square clearable v-model="password" type="password" label="Password">
|
<q-input square clearable v-model="password" :rules="rules.password" type="password" label="Password">
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
<q-icon name="lock"/>
|
<q-icon name="lock"/>
|
||||||
</template>
|
</template>
|
||||||
@@ -41,9 +47,9 @@ const logUser = () => {
|
|||||||
<q-card-actions class="q-px-lg">
|
<q-card-actions class="q-px-lg">
|
||||||
<q-btn unelevated size="lg" class="full-width" label="Přihlásit se" @click.prevent="logUser()"/>
|
<q-btn unelevated size="lg" class="full-width" label="Přihlásit se" @click.prevent="logUser()"/>
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
<q-card-section class="text-center q-pa-sm">
|
<!-- <q-card-section class="text-center q-pa-sm">-->
|
||||||
<router-link :to="{name: 'forgottenPassword'}" class="text-grey-6">Zapomenuté heslo</router-link>
|
<!-- <router-link :to="{name: 'forgottenPassword'}" class="text-grey-6">Zapomenuté heslo</router-link>-->
|
||||||
</q-card-section>
|
<!-- </q-card-section>-->
|
||||||
</q-card>
|
</q-card>
|
||||||
|
|
||||||
</q-page>
|
</q-page>
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ onMounted(() => {
|
|||||||
:items="flights"
|
:items="flights"
|
||||||
:displayVisibilityInfo="loggedUser.id === pilot.id"
|
:displayVisibilityInfo="loggedUser.id === pilot.id"
|
||||||
:route-detail="{name: 'publicFlightDetail', params: {username: username}}"
|
:route-detail="{name: 'publicFlightDetail', params: {username: username}}"
|
||||||
|
class="q-mb-md"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ const registerUser = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
}).catch(({response}) => {
|
}).catch(({response}) => {
|
||||||
console.log(response.detail);
|
|
||||||
if (response.detail === 'User already exists') {
|
if (response.detail === 'User already exists') {
|
||||||
$q.notify(errorObject("Uživatel s tímto e-mailem je již registrovaný. Zkus se přihlásit."));
|
$q.notify(errorObject("Uživatel s tímto e-mailem je již registrovaný. Zkus se přihlásit."));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import {updateInItems} from "stores/helpers";
|
|||||||
|
|
||||||
export const useCopilotsStore = defineStore('SecondPilots', {
|
export const useCopilotsStore = defineStore('SecondPilots', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
items: []
|
items: [],
|
||||||
|
isMutationRunning: false,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
@@ -21,19 +22,20 @@ export const useCopilotsStore = defineStore('SecondPilots', {
|
|||||||
},
|
},
|
||||||
create(formData) {
|
create(formData) {
|
||||||
delete formData['id'];
|
delete formData['id'];
|
||||||
return apolloWrapper.mutate(CREATE_COPILOT, {input: formData}).then(({data}) => {
|
|
||||||
this.items.push(data.createCopilot);
|
|
||||||
|
|
||||||
return data.createCopilot;
|
this.isMutationRunning = true;
|
||||||
})
|
return apolloWrapper.mutate(CREATE_COPILOT, {input: formData}).then(({data}) => {
|
||||||
|
const copilot = data.createCopilot;
|
||||||
|
this.items.push(copilot);
|
||||||
|
return copilot;
|
||||||
|
}).finally(() => this.isMutationRunning = false);
|
||||||
},
|
},
|
||||||
update(id, formData) {
|
update(id, formData) {
|
||||||
return apolloWrapper.mutate(EDIT_COPILOT, {id: id, input: formData}).then(({data}) => {
|
return apolloWrapper.mutate(EDIT_COPILOT, {id: id, input: formData}).then(({data}) => {
|
||||||
const copilot = data.editCopilot;
|
const copilot = data.editCopilot;
|
||||||
|
|
||||||
updateInItems(this.items, "id", copilot);
|
updateInItems(this.items, "id", copilot);
|
||||||
return copilot;
|
return copilot;
|
||||||
});
|
}).finally(() => this.isMutationRunning = false);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
import {defineStore} from 'pinia'
|
|
||||||
|
|
||||||
export const useFlashMessagesStore = defineStore('FlashMessages', {
|
|
||||||
state: () => ({
|
|
||||||
items: []
|
|
||||||
}),
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
add(title, content, type) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@@ -49,11 +49,8 @@ export const useFlightsStore = defineStore('Flights', {
|
|||||||
return apolloWrapper
|
return apolloWrapper
|
||||||
.query(FLIGHTS_LIST, {username})
|
.query(FLIGHTS_LIST, {username})
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
console.log(resp);
|
|
||||||
const data = resp.data;
|
const data = resp.data;
|
||||||
|
|
||||||
this.items = data.flights;
|
this.items = data.flights;
|
||||||
|
|
||||||
return data.flights;
|
return data.flights;
|
||||||
}).catch(err => console.log(err));
|
}).catch(err => console.log(err));
|
||||||
},
|
},
|
||||||
|
|||||||
+8
-3
@@ -3,6 +3,9 @@ import {apolloWrapper} from "src/graphql/apollo";
|
|||||||
import {DELETE_PHOTO, EDIT_PHOTO, UPLOAD_PHOTO} from "src/graphql/mutations/photo";
|
import {DELETE_PHOTO, EDIT_PHOTO, UPLOAD_PHOTO} from "src/graphql/mutations/photo";
|
||||||
|
|
||||||
export const usePhotosStore = defineStore('photos', {
|
export const usePhotosStore = defineStore('photos', {
|
||||||
|
state: () => ({
|
||||||
|
isMutationRunning: false,
|
||||||
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
upload(flightId, formData) {
|
upload(flightId, formData) {
|
||||||
@@ -20,15 +23,17 @@ export const usePhotosStore = defineStore('photos', {
|
|||||||
if (!formData.description) {
|
if (!formData.description) {
|
||||||
formData.description = "";
|
formData.description = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.isMutationRunning = true;
|
||||||
return apolloWrapper.mutate(UPLOAD_PHOTO, {input: formData}).then(({data}) => {
|
return apolloWrapper.mutate(UPLOAD_PHOTO, {input: formData}).then(({data}) => {
|
||||||
return data.uploadPhoto;
|
return data.uploadPhoto;
|
||||||
})
|
}).finally(() => this.isMutationRunning = false);
|
||||||
},
|
},
|
||||||
update(id, formData) {
|
update(id, formData) {
|
||||||
|
this.isMutationRunning = true;
|
||||||
return apolloWrapper.mutate(EDIT_PHOTO, {id, input: formData}).then(({data}) => {
|
return apolloWrapper.mutate(EDIT_PHOTO, {id, input: formData}).then(({data}) => {
|
||||||
return data.editPhoto;
|
return data.editPhoto;
|
||||||
})
|
}).finally(() => this.isMutationRunning = false);
|
||||||
},
|
},
|
||||||
delete(photoId) {
|
delete(photoId) {
|
||||||
return apolloWrapper.mutate(DELETE_PHOTO, {id: photoId}).then(({data}) => {
|
return apolloWrapper.mutate(DELETE_PHOTO, {id: photoId}).then(({data}) => {
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import { createPinia } from 'pinia'
|
|||||||
export default store((/* { ssrContext } */) => {
|
export default store((/* { ssrContext } */) => {
|
||||||
const pinia = createPinia()
|
const pinia = createPinia()
|
||||||
|
|
||||||
console.log("Pinia index");
|
|
||||||
// You can add Pinia plugins here
|
// You can add Pinia plugins here
|
||||||
// pinia.use(SomePiniaPlugin)
|
// pinia.use(SomePiniaPlugin)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user