Moznost nahravat fotky copilotem
This commit is contained in:
@@ -1,29 +1,39 @@
|
||||
<script>
|
||||
import {useFlightsStore} from "stores/Flights";
|
||||
|
||||
export default {
|
||||
preFetch({currentRoute}) {
|
||||
const flightId = currentRoute.params.id
|
||||
return useFlightsStore().fetchDetail(flightId);
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import FlightFormSteps from "components/flights/form/FlightFormSteps.vue";
|
||||
import {computed, onMounted, ref, watch} from "vue";
|
||||
import {onMounted, ref, toRefs, watch} from "vue";
|
||||
import {useRoute} from "vue-router";
|
||||
import {useFlightsStore} from "stores/Flights";
|
||||
import FlightFormBasic from "components/flights/form/FlightFormBasic.vue";
|
||||
import {useAircraftsStore} from "stores/Aircrafts";
|
||||
import {usePointsOfInterestStore} from "stores/PointsOfInterest";
|
||||
import {useAirportsStore} from "stores/Airports";
|
||||
import {useQuasar} from "quasar";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {flightName} from "src/composables/flight";
|
||||
import FlightFormCopilot from "components/flights/form/FlightFormCopilot.vue";
|
||||
import {useCopilotsStore} from "stores/Copilots";
|
||||
import FlightFormNotes from "components/flights/form/FlightFormNotes.vue";
|
||||
import FlightFormPhotos from "components/flights/form/FlightFormPhotos.vue";
|
||||
import {usePhotosStore} from "stores/Photos";
|
||||
import PhotosEditorList from "components/photos/PhotosEditorList.vue";
|
||||
import {errorObject, successObject, warningObject} from "src/composables/dialog";
|
||||
import PhotoFormDialog from "components/photos/PhotoFormDialog.vue";
|
||||
import FlightFormTrack from "components/flights/form/FlightFormTrack.vue";
|
||||
import FlightEditSkeleton from "components/flights/skeletons/FlightEditSkeleton.vue";
|
||||
import BatchPhotoFormDialog from "components/photos/BatchPhotoFormDialog.vue";
|
||||
import {useAppStore} from "stores/App";
|
||||
import {useEventsStore} from "stores/Events";
|
||||
import FlightEditCopilotSkeleton from "components/flights/skeletons/FlightEditCopilotSkeleton.vue";
|
||||
import {useBasicPhotoOperations} from "src/composables/photos/basicOperations";
|
||||
import {usePhotosStore} from "stores/Photos";
|
||||
|
||||
const $q = useQuasar();
|
||||
const $route = useRoute();
|
||||
@@ -34,29 +44,33 @@ const {pointsOfInterest} = storeToRefs(usePointsOfInterestStore());
|
||||
const {airports} = storeToRefs(useAirportsStore());
|
||||
const {copilots} = storeToRefs(useCopilotsStore());
|
||||
const {events} = storeToRefs(useEventsStore());
|
||||
const {flight, isQueryRunning, isMutationRunning} = storeToRefs(useFlightsStore());
|
||||
const {photos} = storeToRefs(usePhotosStore());
|
||||
const {flight, isQueryRunning, isRequestPending: isMutationRunning} = storeToRefs(useFlightsStore());
|
||||
|
||||
const formStep = ref("basic");
|
||||
watch(() => $route.params.step, (val) => formStep.value = val);
|
||||
|
||||
onMounted(() => {
|
||||
formStep.value = $route.params.step || "basic";
|
||||
import {flightName} from "src/composables/flight";
|
||||
import {useAppStore} from "stores/App";
|
||||
|
||||
const flightNameFormatted = flightName(flight.value);
|
||||
useAppStore().setPageTitle(`Editace - ${flightNameFormatted}`);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: "myFlights"}, label: "Moje lety"},
|
||||
{to: {name: "flightDetail", params: {id: flight.id}}, label: flightNameFormatted},
|
||||
{label: "Editace"}
|
||||
]);
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
photos.value = flight.value.photos;
|
||||
|
||||
formStep.value = $route.params.step || "basic";
|
||||
useAircraftsStore().fetch({});
|
||||
usePointsOfInterestStore().fetch({});
|
||||
useAirportsStore().fetch();
|
||||
useCopilotsStore().fetch();
|
||||
useEventsStore().fetch({});
|
||||
|
||||
useFlightsStore().fetchDetail(flightId).then((f) => {
|
||||
const flightNameFormatted = flightName(f);
|
||||
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) => {
|
||||
@@ -64,40 +78,9 @@ const handleFlightEdit = (data) => {
|
||||
$q.notify(successObject("Úspěšně upraveno"));
|
||||
})
|
||||
}
|
||||
|
||||
const isRequestPending = storeToRefs(useFlightsStore()).isMutationRunning;
|
||||
const uploadInProgress = ref(false);
|
||||
|
||||
const handlePhotosUpload = (data) => {
|
||||
const promises = [];
|
||||
uploadInProgress.value = true;
|
||||
for (const photo of data.photos) {
|
||||
promises.push(usePhotosStore().upload(flightId, {photo}).then((data) => {
|
||||
flight.value.photos.push(data);
|
||||
photo._uploaded = true;
|
||||
}));
|
||||
}
|
||||
|
||||
Promise.allSettled(promises).then((values) => {
|
||||
const success = values.filter(v => v.status === 'fulfilled');
|
||||
const failed = values.filter(v => v.status === 'rejected'); // TODO: nebo vse - success?
|
||||
|
||||
if (success.length > 0)
|
||||
$q.notify(successObject(`Úspěšně nahráno ${success.length} fotek`));
|
||||
|
||||
if (failed.length > 0)
|
||||
$q.notify(warningObject(`Nepovedlo se nahrát ${failed.length} fotek. Zde jsou důvody: ${failed.map(f => f.reason)}`));
|
||||
|
||||
data.photos = [];
|
||||
}).finally(() => uploadInProgress.value = false);
|
||||
}
|
||||
|
||||
const _findPhotoIndex = (photoId) => flight.value.photos.findIndex((object) => object.id === photoId);
|
||||
const deletePhoto = (id) => {
|
||||
usePhotosStore().destroy(id).then((data) => {
|
||||
flight.value.photos.splice(_findPhotoIndex(data.id), 1);
|
||||
});
|
||||
}
|
||||
const {
|
||||
uploadInProgress, handlePhotosUpload, batchRotatePhotos, deletePhoto, updateSinglePhoto
|
||||
} = useBasicPhotoOperations({});
|
||||
|
||||
const setTitlePhoto = (photo) => {
|
||||
useFlightsStore().update(flight.value.id, {titlePhotoId: photo.id}).then(f => {
|
||||
@@ -105,38 +88,6 @@ const setTitlePhoto = (photo) => {
|
||||
});
|
||||
}
|
||||
|
||||
const rotatePhotos = ({photos, direction}) => {
|
||||
const promises = [];
|
||||
for (const photo of photos) {
|
||||
promises.push(usePhotosStore().changeOrientation(photo.id, direction).then(data => {
|
||||
const idx = _findPhotoIndex(data.id);
|
||||
data.thumbnailUrl += "?t=" + (new Date()).getTime();
|
||||
flight.value.photos[idx] = data;
|
||||
}));
|
||||
}
|
||||
|
||||
let success = 0;
|
||||
Promise.allSettled(promises).then(result => {
|
||||
for (const item of result) {
|
||||
if (item.status === 'fulfilled') success++;
|
||||
}
|
||||
const error = result.length - success;
|
||||
|
||||
if (success > 0) $q.notify(successObject("Otočeno " + success + " fotografií"));
|
||||
if (error > 0) $q.notify(errorObject(`Nepovedlo se otočit ${error} fotografi`))
|
||||
});
|
||||
}
|
||||
|
||||
const updateSinglePhoto = (id, formData) => {
|
||||
formData.copilots = formData.copilots.map(c => ({id: c.id, name: c.name}));
|
||||
|
||||
return usePhotosStore().update(id, formData).then((data) => {
|
||||
const idx = _findPhotoIndex(data.id);
|
||||
flight.value.photos[idx] = data;
|
||||
usePointsOfInterestStore().fetch({});
|
||||
});
|
||||
}
|
||||
|
||||
const handlePhotoUpdate = (flightId, formData) => {
|
||||
const photoId = formData.id;
|
||||
delete formData.id;
|
||||
@@ -240,18 +191,18 @@ const handleBatchPhotoEdit = async (flightId, data) => {
|
||||
<q-tab-panel name="photos">
|
||||
<FlightFormPhotos
|
||||
:flight="flight"
|
||||
:is-request-pending="isRequestPending || uploadInProgress"
|
||||
:is-request-pending="uploadInProgress"
|
||||
@save="handlePhotosUpload"
|
||||
/>
|
||||
|
||||
<template v-if="flight">
|
||||
<PhotosEditorList
|
||||
:title-photo="flight.titlePhoto"
|
||||
:photos="flight.photos"
|
||||
:photos="photos"
|
||||
:show-actions="true"
|
||||
@edit="openPhotoEdit"
|
||||
@batch-edit="openBatchPhotoForm"
|
||||
@batch-rotate="rotatePhotos"
|
||||
@batch-rotate="batchRotatePhotos"
|
||||
@delete="deletePhoto"
|
||||
@set-title-photo="setTitlePhoto"
|
||||
/>
|
||||
|
||||
@@ -97,6 +97,7 @@ const togglePublicVisibility = (variables) => toggleVisibility({
|
||||
:event-detail-route="flight.event ? {name: 'eventDetail', params: {id: flight.event.id}} : null"
|
||||
:aircraft-detail-route="{name: 'aircraftDetail'}"
|
||||
:copilot-detail-route="{name: 'copilotDetail'}"
|
||||
:logged-user="loggedUser"
|
||||
/>
|
||||
|
||||
<ContentCardEditButton
|
||||
|
||||
Reference in New Issue
Block a user