Slugy, webp, hromada refaktoringu
This commit is contained in:
@@ -11,14 +11,16 @@ const $router = useRouter();
|
||||
const url = computed(() => $route.query.url);
|
||||
|
||||
onMounted(() => {
|
||||
console.log(useAuthStore().getAccessToken());
|
||||
useAuthStore().refreshAccessToken().then(() => {
|
||||
console.log("refreshnuto", $route.query.url);
|
||||
$router.push($route.query.url)
|
||||
}).catch(e => {
|
||||
$router.push({name: "login"})
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
{{ url }}
|
||||
<q-spinner />
|
||||
</template>
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
<script setup>
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {copyToClipboard, useMeta, useQuasar} from "quasar";
|
||||
import {useMeta, useQuasar} from "quasar";
|
||||
import AircraftDetailSkeleton from "components/aircrafts/skeletons/AircraftDetailSkeleton.vue";
|
||||
import {confirmObject, successObject} from "src/composables/dialog";
|
||||
import {useAppStore} from "stores/App";
|
||||
import FlightsList from "components/flights/FlightsList.vue";
|
||||
import AircraftDetailCard from "components/aircrafts/AircraftInfo.vue";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {useAircraftsStore} from "stores/Aircrafts";
|
||||
import {computed, watch} from "vue";
|
||||
import {watch} from "vue";
|
||||
import {metaData} from "src/composables/meta";
|
||||
import PhotoGallery from "components/photos/PhotoGallery.vue";
|
||||
import TitlePhotoWithGallery from "components/photos/TitlePhotoWithGallery.vue";
|
||||
import ContentCard from "components/ContentCard.vue";
|
||||
import AircraftInfo from "components/aircrafts/AircraftInfo.vue";
|
||||
import {useLoggedUserStore} from "stores/LoggedUser";
|
||||
import {useFlightsStore} from "stores/Flights";
|
||||
import {toggleVisibility} from "src/composables/form/formHandling";
|
||||
import ContentCardEditButton from "components/ContentCardEditButton.vue";
|
||||
|
||||
const $q = useQuasar();
|
||||
const $router = useRouter();
|
||||
import {loadPage, paginationLimit} from "src/composables/pagination";
|
||||
import BasicInfoBanner from "components/banners/BasicInfoBanner.vue";
|
||||
import FlightsListSkeleton from "components/flights/skeletons/FlightsListSkeleton.vue";
|
||||
import CopyLinkButton from "components/inputs/CopyLinkButton.vue";
|
||||
import PublishButton from "components/inputs/PublishButton.vue";
|
||||
|
||||
const aircraftId = parseInt(useRoute().params.id);
|
||||
|
||||
useAircraftsStore().fetchDetail(aircraftId);
|
||||
const loggedUser = storeToRefs(useLoggedUserStore()).user;
|
||||
const {aircraft, isQueryRunning} = storeToRefs(useAircraftsStore());
|
||||
watch(() => aircraft.value, (newVal) => {
|
||||
if (!newVal) return;
|
||||
@@ -37,31 +37,31 @@ watch(() => aircraft.value, (newVal) => {
|
||||
])
|
||||
});
|
||||
|
||||
const $q = useQuasar();
|
||||
const $router = useRouter();
|
||||
const deleteAircraft = (id) => {
|
||||
$q.dialog(confirmObject('Opravdu chceš smazat toto letadlo?'))
|
||||
.onOk(() => {
|
||||
useAircraftsStore().destroy(id).then(() => {
|
||||
$router.push({name: "aircrafts"});
|
||||
$q.notify(successObject("Letadlo úspěšně odstraněno"));
|
||||
});
|
||||
.onOk(() => {
|
||||
useAircraftsStore().destroy(id).then(() => {
|
||||
$router.push({name: "aircrafts"});
|
||||
$q.notify(successObject("Letadlo úspěšně odstraněno"));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const togglePublicVisibility = () => toggleVisibility({
|
||||
$q,
|
||||
store: useAircraftsStore(),
|
||||
object: aircraft.value
|
||||
$q, store: useAircraftsStore(), object: aircraft.value
|
||||
});
|
||||
|
||||
const copyLinkToClipboard = () => {
|
||||
const url = $router.resolve({
|
||||
name: "publicAircraftDetail",
|
||||
params: {id: aircraftId}
|
||||
});
|
||||
copyToClipboard(window.location.origin + url.href).then(() => {
|
||||
$q.notify(successObject("Odkaz zkopírován"))
|
||||
});
|
||||
};
|
||||
const loadNextFlightsPage = (appendItems) => loadPage({
|
||||
fetchFunc: useFlightsStore().fetch,
|
||||
filters: {aircraftId: aircraftId},
|
||||
appendItems
|
||||
});
|
||||
const {isQueryRunning: areFlightsLoading, totalItemsCount, flights} = storeToRefs(useFlightsStore());
|
||||
loadNextFlightsPage(false);
|
||||
|
||||
const loggedUser = storeToRefs(useLoggedUserStore()).user;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -71,18 +71,15 @@ const copyLinkToClipboard = () => {
|
||||
<ContentCard :title-photo="aircraft.titlePhoto" :title="aircraft.callSign">
|
||||
<template #actions v-if="aircraft.createdById === loggedUser?.id">
|
||||
<div class="col-grow">
|
||||
<q-btn
|
||||
@click="togglePublicVisibility"
|
||||
:icon="aircraft.isPublic ? 'visibility_off' : 'visibility'"
|
||||
flat
|
||||
:label="aircraft.isPublic ? 'Skrýt' : 'Zveřejnit'"
|
||||
<PublishButton
|
||||
url-prefix="/letadla"
|
||||
:is-public="aircraft.isPublic"
|
||||
:require-url-slug="false"
|
||||
@change-visibility="togglePublicVisibility"
|
||||
/>
|
||||
<q-btn
|
||||
icon="link"
|
||||
@click="copyLinkToClipboard()"
|
||||
flat
|
||||
v-if="aircraft.isPublic"
|
||||
label="Získat odkaz"
|
||||
<CopyLinkButton
|
||||
v-if="aircraft.isPublic"
|
||||
:route="{name: 'publicAircraftDetail', params: {callsign: aircraft.callSign}}"
|
||||
/>
|
||||
</div>
|
||||
<q-btn @click="deleteAircraft(aircraft.id)" icon="delete" flat text-color="red" label="Smazat"/>
|
||||
@@ -91,21 +88,31 @@ const copyLinkToClipboard = () => {
|
||||
<q-card-section>
|
||||
|
||||
<ContentCardEditButton
|
||||
:to='{name: "aircraftEdit", params: {id: aircraft.id, step: "info"}}'
|
||||
label="Upravit informace"
|
||||
:to='{name: "aircraftEdit", params: {id: aircraft.id, step: "info"}}'
|
||||
label="Upravit informace"
|
||||
/>
|
||||
<AircraftInfo :aircraft="aircraft"/>
|
||||
|
||||
<ContentCardEditButton
|
||||
:to='{name: "aircraftEdit", params: {id: aircraft.id, step: "photo"}}'
|
||||
label="Titulní fotografie"
|
||||
:to='{name: "aircraftEdit", params: {id: aircraft.id, step: "photo"}}'
|
||||
label="Titulní fotografie"
|
||||
/>
|
||||
<PhotoGallery :photos="aircraft.photos"/>
|
||||
|
||||
<h3>Lety</h3>
|
||||
<q-banner v-if="aircraft.flights.length === 0" class="bg-light-blue text-white">
|
||||
<FlightsListSkeleton v-if="areFlightsLoading && flights.length === 0"/>
|
||||
<BasicInfoBanner v-if="flights.length === 0">
|
||||
Zatím žádné lety.
|
||||
</q-banner>
|
||||
<FlightsList :items="aircraft.flights" :public="false" v-else/>
|
||||
</BasicInfoBanner>
|
||||
<FlightsList
|
||||
v-else-if="flights.length > 0"
|
||||
:public="false"
|
||||
:items="flights"
|
||||
:total-items-count="totalItemsCount"
|
||||
:is-query-running="areFlightsLoading"
|
||||
:items-per-page="paginationLimit"
|
||||
@load-more="loadNextFlightsPage(true)"
|
||||
/>
|
||||
</q-card-section>
|
||||
</template>
|
||||
</ContentCard>
|
||||
|
||||
@@ -13,6 +13,7 @@ import {useLoggedUserStore} from "stores/LoggedUser";
|
||||
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 $router = useRouter();
|
||||
const $q = useQuasar();
|
||||
@@ -56,9 +57,10 @@ const formStep = computed(() => useRoute().params.step || "info");
|
||||
<template v-else>
|
||||
<CommonEditSwitcher :route="{name: 'aircraftEdit', params: {id: aircraft?.id}}"/>
|
||||
|
||||
<template v-if="formStep === 'basic'">
|
||||
<template v-if="formStep === 'info'">
|
||||
<AircraftEditSkeleton v-if="isQueryRunning || !aircraft"/>
|
||||
<AircraftForm
|
||||
v-else
|
||||
@save="handleSave"
|
||||
:default-values="aircraft"
|
||||
:organizations="loggedUser.organizations"
|
||||
@@ -68,6 +70,9 @@ const formStep = computed(() => useRoute().params.step || "info");
|
||||
|
||||
<template v-else-if="formStep === 'photo'">
|
||||
<PhotoGallerySkeleton v-if="isQueryRunning || !aircraft"/>
|
||||
<BasicInfoBanner v-else-if="aircraft && aircraft.photos.length === 0">
|
||||
U tohoto letadla nemáš žádnou fotku. Můžeš ji přidat v editaci fotky.
|
||||
</BasicInfoBanner>
|
||||
<PhotosEditorList
|
||||
v-else
|
||||
:photos="aircraft.photos"
|
||||
|
||||
@@ -8,57 +8,96 @@ import {useCopilotsStore} from "stores/Copilots";
|
||||
import {storeToRefs} from "pinia";
|
||||
import PhotoGallery from "components/photos/PhotoGallery.vue";
|
||||
import ContentCard from "components/ContentCard.vue";
|
||||
import {loadPage, paginationLimit} from "src/composables/pagination";
|
||||
import {useFlightsStore} from "stores/Flights";
|
||||
import FlightsListSkeleton from "components/flights/skeletons/FlightsListSkeleton.vue";
|
||||
import {useMeta, useQuasar} from "quasar";
|
||||
import {useLoggedUserStore} from "stores/LoggedUser";
|
||||
import PublishButton from "components/inputs/PublishButton.vue";
|
||||
import CopyLinkButton from "components/inputs/CopyLinkButton.vue";
|
||||
import {toggleVisibility} from "src/composables/form/formHandling";
|
||||
import {metaData} from "src/composables/meta";
|
||||
|
||||
const copilotId = parseInt(useRoute().params.id);
|
||||
onMounted(() => {
|
||||
useCopilotsStore().fetchDetail(copilotId).then(() => {
|
||||
useAppStore().setPageTitle(copilot.value.name);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: "copilots"}, label: "Kopiloti"},
|
||||
{label: copilot.value.name}
|
||||
])
|
||||
});
|
||||
useCopilotsStore().fetchDetail(copilotId).then(() => {
|
||||
useAppStore().setPageTitle(copilot.value.name);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: "copilots"}, label: "Kopiloti"},
|
||||
{label: copilot.value.name}
|
||||
])
|
||||
});
|
||||
|
||||
|
||||
const loadNextFlightsPage = (appendItems) => loadPage({
|
||||
fetchFunc: useFlightsStore().fetch,
|
||||
filters: {copilotId: copilotId},
|
||||
appendItems
|
||||
});
|
||||
loadNextFlightsPage(false);
|
||||
const {isQueryRunning: areFlightsLoading, totalItemsCount, flights} = storeToRefs(useFlightsStore());
|
||||
const {isQueryRunning, copilot} = storeToRefs(useCopilotsStore());
|
||||
const loggedUser = storeToRefs(useLoggedUserStore()).user;
|
||||
|
||||
const $q = useQuasar();
|
||||
const togglePublicVisibility = (data) => toggleVisibility({
|
||||
$q, store: useCopilotsStore(), object: copilot.value, urlSlug: data.urlSlug
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CopilotDetailSkeleton v-if="isQueryRunning || !copilot"/>
|
||||
|
||||
<template v-else>
|
||||
<ContentCard :title-photo="copilot.titlePhoto" :title="copilot.name" v-else>
|
||||
<template #actions>
|
||||
<div class="col-grow">
|
||||
<q-btn
|
||||
flat
|
||||
:to="{name: 'copilotEdit', params: {id: copilotId}}"
|
||||
icon="edit"
|
||||
text-color="primary"
|
||||
label="Upravit"
|
||||
/>
|
||||
|
||||
<ContentCard :title-photo="copilot.titlePhoto" :title="copilot.name">
|
||||
<template #actions>
|
||||
<div class="col-grow">
|
||||
<q-btn
|
||||
flat
|
||||
:to="{name: 'copilotEdit', params: {id: copilotId}}"
|
||||
icon="edit"
|
||||
text-color="primary"
|
||||
label="Upravit"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<q-card-section>
|
||||
<PhotoGallery :photos="copilot.photos" v-if="copilot.photos.length > 0"/>
|
||||
<q-banner v-else class="bg-light-blue text-white">
|
||||
Zatím tu nemáš žádné společné fotky. Po nahrání fotky můžeš označit tuto osobu a takto označené
|
||||
fotografie se zobrazí v galerii.
|
||||
</q-banner>
|
||||
<PublishButton
|
||||
:url-prefix="`/${loggedUser?.publicUsername}/a/`"
|
||||
:is-public="copilot.isPublic"
|
||||
:require-url-slug="copilot.urlSlug === ''"
|
||||
@change-visibility="togglePublicVisibility"
|
||||
/>
|
||||
<CopyLinkButton
|
||||
v-if="copilot.isPublic"
|
||||
:route="{
|
||||
name: 'publicCopilotDetail', params: {
|
||||
username: loggedUser.publicUsername,
|
||||
copilotSlug: copilot.urlSlug
|
||||
}}"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<q-card-section>
|
||||
<PhotoGallery :photos="copilot.photos" v-if="copilot.photos.length > 0"/>
|
||||
<q-banner v-else class="bg-light-blue text-white">
|
||||
Zatím tu nemáš žádné společné fotky. Po nahrání fotky můžeš označit tuto osobu a takto označené
|
||||
fotografie se zobrazí v galerii.
|
||||
</q-banner>
|
||||
|
||||
<h3>Společné lety</h3>
|
||||
<h3>Společné lety</h3>
|
||||
|
||||
<q-banner v-if="copilot.flights.length === 0" class="bg-light-blue text-white">
|
||||
Zatím tu nemáš uložené žádné společné lety.
|
||||
</q-banner>
|
||||
|
||||
<FlightsList :items="copilot.flights" :public="false" v-else/>
|
||||
</q-card-section>
|
||||
</template>
|
||||
|
||||
</ContentCard>
|
||||
|
||||
</template>
|
||||
<FlightsListSkeleton v-if="areFlightsLoading && !flights.length"/>
|
||||
<FlightsList
|
||||
v-else-if="flights.length > 0"
|
||||
:public="false"
|
||||
:items="flights"
|
||||
:total-items-count="totalItemsCount"
|
||||
:is-query-running="areFlightsLoading"
|
||||
:items-per-page="paginationLimit"
|
||||
@load-more="loadNextFlightsPage(true)"
|
||||
/>
|
||||
<q-banner v-if="flights.length === 0" class="bg-light-blue text-white">
|
||||
Zatím tu nemáš uložené žádné společné lety.
|
||||
</q-banner>
|
||||
</q-card-section>
|
||||
</template>
|
||||
</ContentCard>
|
||||
</template>
|
||||
|
||||
@@ -11,6 +11,7 @@ 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();
|
||||
@@ -61,6 +62,9 @@ const setTitlePhoto = (titlePhoto) => {
|
||||
|
||||
<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"
|
||||
|
||||
@@ -8,6 +8,8 @@ import FlightsList from "components/flights/FlightsList.vue";
|
||||
import {FORMAT_DATE, formatDatetime} from "src/composables/datetimeUtils";
|
||||
import {useEventsStore} from "stores/Events";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {loadPage, paginationLimit} from "src/composables/pagination";
|
||||
import {useFlightsStore} from "stores/Flights";
|
||||
|
||||
const eventId = parseInt(useRoute().params.id);
|
||||
onMounted(() => {
|
||||
@@ -18,9 +20,18 @@ onMounted(() => {
|
||||
{label: event.value.name}
|
||||
])
|
||||
});
|
||||
loadNextFlightsPage(false);
|
||||
})
|
||||
|
||||
const {isQueryRunning, event} = storeToRefs(useEventsStore());
|
||||
|
||||
const loadNextFlightsPage = (appendItems) => loadPage({
|
||||
fetchFunc: useFlightsStore().fetch,
|
||||
filters: {eventId: eventId},
|
||||
appendItems
|
||||
});
|
||||
const {isQueryRunning: areFlightsLoading, totalItemsCount, flights} = storeToRefs(useFlightsStore());
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -49,8 +60,15 @@ const {isQueryRunning, event} = storeToRefs(useEventsStore());
|
||||
Zatím tu nemáš uložené žádné lety.
|
||||
</q-banner>
|
||||
|
||||
<FlightsList :items="event.flights" :public="false" v-else/>
|
||||
|
||||
<FlightsList
|
||||
v-else-if="flights.length > 0"
|
||||
:public="false"
|
||||
:items="flights"
|
||||
:total-items-count="totalItemsCount"
|
||||
:is-query-running="areFlightsLoading"
|
||||
:items-per-page="paginationLimit"
|
||||
@load-more="loadNextFlightsPage(true)"
|
||||
/>
|
||||
<FAB mode="edit" :router-link="{name: 'eventEdit', params: {id: eventId}}"/>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -6,10 +6,14 @@ import BasicInfoBanner from "components/banners/BasicInfoBanner.vue";
|
||||
import EventsList from "components/event/EventsList.vue";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {useEventsStore} from "stores/Events";
|
||||
import {onBeforeMount} from "vue";
|
||||
|
||||
useEventsStore().fetch();
|
||||
useAppStore().setPageTitle("Letecké události");
|
||||
|
||||
onBeforeMount(() => {
|
||||
useEventsStore().fetch({});
|
||||
});
|
||||
|
||||
const {isQueryRunning, events} = storeToRefs(useEventsStore());
|
||||
</script>
|
||||
|
||||
@@ -31,6 +35,7 @@ const {isQueryRunning, events} = storeToRefs(useEventsStore());
|
||||
<EventsList
|
||||
v-else
|
||||
:items="events"
|
||||
:route-detail="{name: 'eventDetail', params: {}}"
|
||||
/>
|
||||
|
||||
<FAB :router-link="{name: 'addEvent'}" mode="add"/>
|
||||
|
||||
@@ -208,38 +208,44 @@ const handleBatchPhotoEdit = async (flightId, data) => {
|
||||
<q-tab-panel name="basic">
|
||||
<FlightEditSkeleton :step="formStep" v-if="isQueryRunning || !flight"/>
|
||||
<FlightFormBasic
|
||||
@save="handleFlightEdit"
|
||||
:flight="flight"
|
||||
:locations="pointsOfInterest"
|
||||
:airports="airports"
|
||||
:aircrafts="aircrafts"
|
||||
v-else
|
||||
@save="handleFlightEdit"
|
||||
:flight="flight"
|
||||
:locations="pointsOfInterest"
|
||||
:airports="airports"
|
||||
:aircrafts="aircrafts"
|
||||
/>
|
||||
</q-tab-panel>
|
||||
|
||||
<q-tab-panel name="copilot">
|
||||
<FlightEditCopilotSkeleton :step="formStep" v-if="isQueryRunning || !flight"/>
|
||||
<FlightFormCopilot @save="handleFlightEdit" :flight="flight" :copilots="copilots"/>
|
||||
<FlightEditCopilotSkeleton v-if="isQueryRunning || !flight"/>
|
||||
<FlightFormCopilot
|
||||
v-else
|
||||
@save="handleFlightEdit"
|
||||
:flight="flight"
|
||||
:copilots="copilots"/>
|
||||
</q-tab-panel>
|
||||
|
||||
<q-tab-panel name="track">
|
||||
<FlightEditSkeleton :step="formStep" v-if="isQueryRunning || !flight"/>
|
||||
<FlightFormTrack
|
||||
v-if="pointsOfInterest"
|
||||
:flight="flight"
|
||||
:locations="pointsOfInterest"
|
||||
:airports="airports"
|
||||
@save="handleFlightEdit"
|
||||
v-if="flight && pointsOfInterest"
|
||||
:flight="flight"
|
||||
:locations="pointsOfInterest"
|
||||
:airports="airports"
|
||||
@save="handleFlightEdit"
|
||||
/>
|
||||
</q-tab-panel>
|
||||
|
||||
<q-tab-panel name="photos">
|
||||
<FlightFormPhotos
|
||||
:flight="flight"
|
||||
:is-request-pending="isRequestPending || uploadInProgress"
|
||||
@save="handlePhotosUpload"
|
||||
:flight="flight"
|
||||
:is-request-pending="isRequestPending || uploadInProgress"
|
||||
@save="handlePhotosUpload"
|
||||
/>
|
||||
|
||||
<PhotosEditorList
|
||||
<template v-if="flight">
|
||||
<PhotosEditorList
|
||||
:title-photo="flight.titlePhoto"
|
||||
:photos="flight.photos"
|
||||
:show-actions="true"
|
||||
@@ -248,19 +254,19 @@ const handleBatchPhotoEdit = async (flightId, data) => {
|
||||
@batch-rotate="rotatePhotos"
|
||||
@delete="deletePhoto"
|
||||
@set-title-photo="setTitlePhoto"
|
||||
/>
|
||||
/>
|
||||
|
||||
<!-- Dialogs for photo edit -->
|
||||
<PhotoFormDialog
|
||||
<!-- Dialogs for photo edit -->
|
||||
<PhotoFormDialog
|
||||
v-model="openEdit"
|
||||
:copilots="flight.copilots"
|
||||
:aircrafts="aircrafts"
|
||||
:locations="pointsOfInterest"
|
||||
:photo="editPhoto"
|
||||
@save="handlePhotoUpdate(flightId, $event)"
|
||||
/>
|
||||
/>
|
||||
|
||||
<BatchPhotoFormDialog
|
||||
<BatchPhotoFormDialog
|
||||
v-model="openBatchEdit"
|
||||
:locations="pointsOfInterest"
|
||||
:photos="editBatchPhotos"
|
||||
@@ -268,7 +274,9 @@ const handleBatchPhotoEdit = async (flightId, data) => {
|
||||
:aircrafts="aircrafts"
|
||||
@save="handleBatchPhotoEdit(flightId, $event)"
|
||||
@delete="deletePhoto"
|
||||
/>
|
||||
/>
|
||||
|
||||
</template>
|
||||
</q-tab-panel>
|
||||
|
||||
<q-tab-panel name="notes">
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script setup>
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {computed, onMounted, ref, watch} from "vue";
|
||||
import {watch} from "vue";
|
||||
import FlightDetailSkeleton from "components/flights/skeletons/FlightDetailSkeleton.vue";
|
||||
import {flightName} from "src/composables/flight";
|
||||
import {useAppStore} from "stores/App";
|
||||
import FlightBasicInfo from "components/flights/FlightBasicInfo.vue";
|
||||
import {copyToClipboard, useQuasar} from "quasar";
|
||||
import {useQuasar} from "quasar";
|
||||
import {confirmObject, successObject} from "src/composables/dialog";
|
||||
import {useFlightsStore} from "stores/Flights";
|
||||
import FlightTrackMap from "components/flights/FlightTrackMap.vue";
|
||||
@@ -13,13 +13,12 @@ import {useLoggedUserStore} from "stores/LoggedUser";
|
||||
import {storeToRefs} from "pinia";
|
||||
import BasicInfoBanner from "components/banners/BasicInfoBanner.vue";
|
||||
import PhotoGallery from "components/photos/PhotoGallery.vue";
|
||||
import TitlePhotoWithGallery from "components/photos/TitlePhotoWithGallery.vue";
|
||||
import ContentCard from "components/ContentCard.vue";
|
||||
import ContentCardEditButton from "components/ContentCardEditButton.vue";
|
||||
import {toggleVisibility} from "src/composables/form/formHandling";
|
||||
import PublishButton from "components/inputs/PublishButton.vue";
|
||||
import CopyLinkButton from "components/inputs/CopyLinkButton.vue";
|
||||
|
||||
const $q = useQuasar();
|
||||
const $router = useRouter();
|
||||
const flightId = parseInt(useRoute().params.id);
|
||||
const loggedUser = storeToRefs(useLoggedUserStore()).user;
|
||||
|
||||
@@ -35,76 +34,67 @@ watch(() => flight.value, (f) => {
|
||||
]);
|
||||
});
|
||||
|
||||
const $q = useQuasar();
|
||||
const $router = useRouter();
|
||||
const handleDeleteAndRedirect = () => {
|
||||
$q.dialog(confirmObject("Opravdu chceš smazat tento let?"))
|
||||
.onOk(() => {
|
||||
useFlightsStore().destroy(flightId).then(() => {
|
||||
$router.push({name: "myFlights"});
|
||||
$q.notify(successObject(`Úspěšně smazáno`));
|
||||
});
|
||||
.onOk(() => {
|
||||
useFlightsStore().destroy(flightId).then(() => {
|
||||
$router.push({name: "myFlights"});
|
||||
$q.notify(successObject(`Úspěšně smazáno`));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const togglePublicVisibility = () => toggleVisibility({
|
||||
const togglePublicVisibility = (data) => toggleVisibility({
|
||||
$q,
|
||||
store: useFlightsStore(),
|
||||
object: flight.value
|
||||
object: flight.value,
|
||||
urlSlug: data.isPublic ? data.urlSlug : undefined
|
||||
});
|
||||
|
||||
const copyLinkToClipboard = () => {
|
||||
const loggedUser = useLoggedUserStore().user;
|
||||
const url = $router.resolve({
|
||||
name: "publicFlightDetail",
|
||||
params: {id: flightId, username: loggedUser.publicUsername}
|
||||
});
|
||||
copyToClipboard(window.location.origin + url.href).then(() => {
|
||||
$q.notify(successObject("Odkaz zkopírován"))
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FlightDetailSkeleton v-if="isQueryRunning || !flight"/>
|
||||
|
||||
<ContentCard :title-photo="flight.titlePhoto" :title="flightName(flight)" v-else>
|
||||
|
||||
<template #actions>
|
||||
<div class="col-grow">
|
||||
<q-btn
|
||||
@click="togglePublicVisibility"
|
||||
:icon="flight.isPublic ? 'visibility_off' : 'visibility'"
|
||||
:disable="!loggedUser?.publicUsername"
|
||||
flat
|
||||
:label="flight.isPublic ? 'Skrýt' : 'Zveřejnit'"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
icon="link"
|
||||
@click="copyLinkToClipboard()"
|
||||
flat
|
||||
<template v-if="loggedUser.publicUsername">
|
||||
<div class="col-grow">
|
||||
<PublishButton
|
||||
:url-prefix="`/${loggedUser.publicUsername}/`"
|
||||
:is-public="flight.isPublic"
|
||||
:require-url-slug="!flight.urlSlug"
|
||||
@change-visibility="togglePublicVisibility"
|
||||
/>
|
||||
<CopyLinkButton
|
||||
:route='{
|
||||
name: "publicFlightDetail",
|
||||
params: {flightSlug: flight.urlSlug, username: loggedUser.publicUsername}
|
||||
}'
|
||||
v-if="flight.isPublic"
|
||||
label="Získat odkaz"
|
||||
/>
|
||||
</div>
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<q-btn @click="handleDeleteAndRedirect" icon="delete" flat text-color="red" label="Smazat"/>
|
||||
</template>
|
||||
|
||||
<template #content>
|
||||
<q-card-section>
|
||||
<ContentCardEditButton
|
||||
:to="{name: 'flightEdit', params: {id: flightId, step: 'basic'}}"
|
||||
label="Upravit informace"
|
||||
:to="{name: 'flightEdit', params: {id: flightId, step: 'basic'}}"
|
||||
label="Upravit informace"
|
||||
/>
|
||||
<FlightBasicInfo
|
||||
:flight="flight"
|
||||
:poi-detail-route="{name: 'poiDetail'}"
|
||||
:aircraft-detail-route="{name: 'aircraftDetail'}"
|
||||
:copilot-detail-route="{name: 'copilotDetail'}"
|
||||
:flight="flight"
|
||||
:poi-detail-route="{name: 'poiDetail'}"
|
||||
:aircraft-detail-route="{name: 'aircraftDetail'}"
|
||||
:copilot-detail-route="{name: 'copilotDetail'}"
|
||||
/>
|
||||
|
||||
<ContentCardEditButton
|
||||
:to="{name: 'flightEdit', params: {id: flightId, step: 'notes'}}"
|
||||
label="Upravit text"
|
||||
:to="{name: 'flightEdit', params: {id: flightId, step: 'notes'}}"
|
||||
label="Upravit text"
|
||||
/>
|
||||
<article class="q-my-lg" v-html="flight.description"/>
|
||||
<BasicInfoBanner v-if="flight.description === ''">Popiš, jaký byl let.</BasicInfoBanner>
|
||||
@@ -112,36 +102,36 @@ const copyLinkToClipboard = () => {
|
||||
<q-separator/>
|
||||
|
||||
<ContentCardEditButton
|
||||
:to="{name: 'flightEdit', params: {id: flightId, step: 'photos'}}"
|
||||
label="Upravit fotografie"
|
||||
:to="{name: 'flightEdit', params: {id: flightId, step: 'photos'}}"
|
||||
label="Upravit fotografie"
|
||||
/>
|
||||
<BasicInfoBanner
|
||||
v-if="flight.photos.length === 0"
|
||||
:route-add="{name: 'flightEdit', params: {id: flightId, step: 'photos'}}"
|
||||
v-if="flight.photos.length === 0"
|
||||
:route-add="{name: 'flightEdit', params: {id: flightId, step: 'photos'}}"
|
||||
>
|
||||
U tohoto letu nemáš nahrané žádné fotografie.
|
||||
</BasicInfoBanner>
|
||||
<PhotoGallery
|
||||
v-else
|
||||
:photos="flight.photos"
|
||||
v-else
|
||||
:photos="flight.photos"
|
||||
/>
|
||||
|
||||
<q-separator/>
|
||||
|
||||
<ContentCardEditButton
|
||||
:to="{name: 'flightEdit', params: {id: flightId, step: 'track'}}"
|
||||
label="Upravit trasu"
|
||||
:to="{name: 'flightEdit', params: {id: flightId, step: 'track'}}"
|
||||
label="Upravit trasu"
|
||||
/>
|
||||
<BasicInfoBanner
|
||||
v-if="flight.track.length === 0 && !flight.gpxTrack"
|
||||
:route-add="{name: 'flightEdit', params: {id: flightId, step: 'track'}}"
|
||||
v-if="flight.track.length === 0 && !flight.gpxTrack"
|
||||
:route-add="{name: 'flightEdit', params: {id: flightId, step: 'track'}}"
|
||||
>
|
||||
Nemáš nastavenou žádnou trasu.
|
||||
</BasicInfoBanner>
|
||||
<FlightTrackMap
|
||||
v-else
|
||||
:flight="flight"
|
||||
:photos="flight.photos"
|
||||
v-else
|
||||
:flight="flight"
|
||||
:photos="flight.photos"
|
||||
/>
|
||||
</q-card-section>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import {computed, onMounted, ref} from "vue";
|
||||
import {computed, onMounted} from "vue";
|
||||
import {useAircraftsStore} from "stores/Aircrafts";
|
||||
import {useFlightsStore} from "stores/Flights";
|
||||
import {useRouter} from "vue-router";
|
||||
|
||||
@@ -67,7 +67,11 @@ const {isQueryRunning, organization} = storeToRefs(useOrganizationsStore());
|
||||
|
||||
<BasicListSkeleton :items-count-min="1" :items-count-max="5" v-if="isQueryRunning || !organization"/>
|
||||
<template v-else>
|
||||
<AircraftsList :items="organization.aircrafts" v-if="organization.aircrafts.length > 0"/>
|
||||
<AircraftsList
|
||||
v-if="organization.aircrafts.length > 0"
|
||||
:items="organization.aircrafts"
|
||||
:total-items-count="organization.aircrafts.length"
|
||||
/>
|
||||
<BasicInfoBanner v-else>
|
||||
Žádné letadlo
|
||||
</BasicInfoBanner>
|
||||
|
||||
@@ -15,6 +15,7 @@ import PhotoEditorSkeleton from "components/photos/skeletons/PhotoEditorSkeleton
|
||||
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 poiId = parseInt(useRoute().params.id);
|
||||
|
||||
@@ -69,6 +70,9 @@ const formStep = computed(() => useRoute().params.step || "info");
|
||||
|
||||
<template v-else-if="formStep === 'photo'">
|
||||
<PhotoGallerySkeleton v-if="isQueryRunning || !pointOfInterest"/>
|
||||
<BasicInfoBanner v-else-if="!isQueryRunning && pointOfInterest.photos.length === 0">
|
||||
Toto místo není označené na žádné fotografii.
|
||||
</BasicInfoBanner>
|
||||
<PhotosEditorList
|
||||
v-else
|
||||
:photos="pointOfInterest.photos"
|
||||
|
||||
@@ -16,6 +16,9 @@ import {successObject} from "src/composables/dialog";
|
||||
import ContentCardEditButton from "components/ContentCardEditButton.vue";
|
||||
import {useFlightsStore} from "stores/Flights";
|
||||
import FlightsListSkeleton from "components/flights/skeletons/FlightsListSkeleton.vue";
|
||||
import {loadPage, paginationLimit} from "src/composables/pagination";
|
||||
import PublishButton from "components/inputs/PublishButton.vue";
|
||||
import CopyLinkButton from "components/inputs/CopyLinkButton.vue";
|
||||
|
||||
const loggedUser = storeToRefs(useLoggedUserStore()).user;
|
||||
const poiId = parseInt(useRoute().params.id);
|
||||
@@ -30,23 +33,19 @@ usePointsOfInterestStore().fetchDetail(poiId).then((p) => {
|
||||
])
|
||||
});
|
||||
|
||||
useFlightsStore().fetch({pointOfInterestId: poiId});
|
||||
|
||||
const loadNextFlightsPage = (appendItems) => loadPage({
|
||||
fetchFunc: useFlightsStore().fetch,
|
||||
filters: {pointOfInterestId: poiId},
|
||||
appendItems
|
||||
});
|
||||
loadNextFlightsPage(false);
|
||||
const {isQueryRunning: areFlightsLoading, totalItemsCount, flights} = storeToRefs(useFlightsStore());
|
||||
const {isQueryRunning, pointOfInterest} = storeToRefs(usePointsOfInterestStore());
|
||||
const {isQueryRunning: areFlightsLoading, flights} = storeToRefs(useFlightsStore());
|
||||
|
||||
const $q = useQuasar();
|
||||
const togglePublicVisibility = () => toggleVisibility({
|
||||
$q, store: usePointsOfInterestStore(), object: pointOfInterest.value
|
||||
const togglePublicVisibility = (data) => toggleVisibility({
|
||||
$q, store: usePointsOfInterestStore(), object: pointOfInterest.value, urlSlug: data.urlSlug
|
||||
});
|
||||
|
||||
const $router = useRouter();
|
||||
const copyLinkToClipboard = () => {
|
||||
const url = $router.resolve({name: "publicPOIDetail", params: {id: pointOfInterest.value.id}});
|
||||
copyToClipboard(window.location.origin + url.href).then(() => {
|
||||
$q.notify(successObject("Odkaz zkopírován"))
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -57,18 +56,15 @@ const copyLinkToClipboard = () => {
|
||||
<ContentCard :title-photo="pointOfInterest.titlePhoto" :title="pointOfInterest.name">
|
||||
<template #actions v-if="pointOfInterest.createdById === loggedUser.id">
|
||||
<div class="col-grow">
|
||||
<q-btn
|
||||
@click="togglePublicVisibility"
|
||||
:icon="pointOfInterest.isPublic ? 'visibility_off' : 'visibility'"
|
||||
flat
|
||||
:label="pointOfInterest.isPublic ? 'Skrýt' : 'Zveřejnit'"
|
||||
<PublishButton
|
||||
url-prefix="/mista/"
|
||||
:is-public="pointOfInterest.isPublic"
|
||||
:require-url-slug="pointOfInterest.urlSlug === ''"
|
||||
@change-visibility="togglePublicVisibility"
|
||||
/>
|
||||
<q-btn
|
||||
icon="link"
|
||||
@click="copyLinkToClipboard()"
|
||||
flat
|
||||
v-if="pointOfInterest.isPublic"
|
||||
label="Získat odkaz"
|
||||
<CopyLinkButton
|
||||
v-if="pointOfInterest.isPublic"
|
||||
:route="{name: 'publicPOIDetail', params: {slug: pointOfInterest.urlSlug}}"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -77,28 +73,28 @@ const copyLinkToClipboard = () => {
|
||||
<q-card-section>
|
||||
|
||||
<ContentCardEditButton
|
||||
:to="{name: 'poiEdit', params:{id: pointOfInterest.id, step: 'info'}}"
|
||||
label="Upravit informace"
|
||||
:to="{name: 'poiEdit', params:{id: pointOfInterest.id, step: 'info'}}"
|
||||
label="Upravit informace"
|
||||
/>
|
||||
<article v-html="pointOfInterest.description" class="q-my-lg"/>
|
||||
|
||||
<EmbeddedMap
|
||||
v-if="pointOfInterest.gpsLatitude && pointOfInterest.gpsLongitude"
|
||||
:gps-latitude="pointOfInterest.gpsLatitude"
|
||||
:gps-longitude="pointOfInterest.gpsLongitude"
|
||||
:zoom="13"
|
||||
v-if="pointOfInterest.gpsLatitude && pointOfInterest.gpsLongitude"
|
||||
:gps-latitude="pointOfInterest.gpsLatitude"
|
||||
:gps-longitude="pointOfInterest.gpsLongitude"
|
||||
:zoom="13"
|
||||
/>
|
||||
<BasicInfoBanner v-else>
|
||||
Tento bod nemá nastavenou polohu. Po nastavení polohy tu bude zobrazena mapa.
|
||||
</BasicInfoBanner>
|
||||
|
||||
<ContentCardEditButton
|
||||
:to="{name: 'poiEdit', params:{id: pointOfInterest.id, step: 'photo'}}"
|
||||
label="Úvodní fotografie"
|
||||
:to="{name: 'poiEdit', params:{id: pointOfInterest.id, step: 'photo'}}"
|
||||
label="Úvodní fotografie"
|
||||
/>
|
||||
<PhotoGallery
|
||||
:photos="pointOfInterest.photos"
|
||||
v-if="pointOfInterest.photos.length > 0"
|
||||
:photos="pointOfInterest.photos"
|
||||
v-if="pointOfInterest.photos.length > 0"
|
||||
/>
|
||||
<BasicInfoBanner v-else>
|
||||
Pokud přidáš toto místo k nějaké fotce, zobrazí se tu.
|
||||
@@ -107,11 +103,15 @@ const copyLinkToClipboard = () => {
|
||||
|
||||
<h3>Tvoje lety do místa {{ pointOfInterest.name }}</h3>
|
||||
|
||||
<FlightsListSkeleton v-if="areFlightsLoading && !flights.length" />
|
||||
<FlightsListSkeleton v-if="areFlightsLoading && !flights.length"/>
|
||||
<FlightsList
|
||||
:items="flights"
|
||||
:public="false"
|
||||
v-else-if="flights.length > 0"
|
||||
v-else-if="flights.length > 0"
|
||||
:public="false"
|
||||
:items="flights"
|
||||
:total-items-count="totalItemsCount"
|
||||
:is-query-running="areFlightsLoading"
|
||||
:items-per-page="paginationLimit"
|
||||
@load-more="loadNextFlightsPage(true)"
|
||||
/>
|
||||
<BasicInfoBanner v-else>
|
||||
Na tomto místě jsi zatím nebyl/a.
|
||||
|
||||
@@ -3,7 +3,7 @@ import {useAircraftsStore} from "stores/Aircrafts";
|
||||
|
||||
export default {
|
||||
preFetch({currentRoute}) {
|
||||
return useAircraftsStore().fetchPublicDetail(currentRoute.params.id);
|
||||
return useAircraftsStore().fetchPublicDetail(currentRoute.params.callSign);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -48,6 +48,7 @@ useMeta(() => metaData({
|
||||
}));
|
||||
useAppStore().setBreadcrumbs([
|
||||
{label: "Polétání.cz", to: {name: "homepage"}},
|
||||
{label: "Letadla"},
|
||||
{label: aircraft.value.callSign}
|
||||
]);
|
||||
|
||||
@@ -88,8 +89,8 @@ onMounted(() => {
|
||||
:total-items-count="totalItemsCount"
|
||||
:is-query-running="areFlightsLoading"
|
||||
:items-per-page="paginationLimit"
|
||||
:public="true"
|
||||
@load-more="loadNextFlightsPage(true)"
|
||||
:public="true"
|
||||
/>
|
||||
</q-card-section>
|
||||
</template>
|
||||
|
||||
@@ -3,7 +3,7 @@ import {useCopilotsStore} from "stores/Copilots";
|
||||
|
||||
export default {
|
||||
preFetch({currentRoute}) {
|
||||
return useCopilotsStore().fetchPublicDetail(currentRoute.params.id, currentRoute.params.username);
|
||||
return useCopilotsStore().fetchPublicDetail(currentRoute.params.copilotSlug, currentRoute.params.username);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -3,7 +3,7 @@ import {useEventsStore} from "stores/Events";
|
||||
|
||||
export default {
|
||||
preFetch({currentRoute}) {
|
||||
return useEventsStore().fetchPublicDetail(currentRoute.params.id, currentRoute.params.username);
|
||||
return useEventsStore().fetchPublicDetail(currentRoute.params.eventSlug, currentRoute.params.username);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -3,7 +3,10 @@ import {useFlightsStore} from "stores/Flights";
|
||||
|
||||
export default {
|
||||
preFetch({store, currentRoute}) {
|
||||
return useFlightsStore(store).fetchPublicDetail(currentRoute.params.id, currentRoute.params.username)
|
||||
return useFlightsStore(store).fetchPublicDetail({
|
||||
urlSlug: currentRoute.params.flightSlug,
|
||||
username: currentRoute.params.username
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -3,7 +3,7 @@ import {usePointsOfInterestStore} from "stores/PointsOfInterest";
|
||||
|
||||
export default {
|
||||
preFetch({currentRoute}) {
|
||||
return usePointsOfInterestStore().fetchPublicDetail(currentRoute.params.id);
|
||||
return usePointsOfInterestStore().fetchPublicDetail(currentRoute.params.slug);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -13,7 +13,7 @@ const logUser = () => {
|
||||
useAuthStore().login(formData).then(() => {
|
||||
$router.push({name: "myFlights"});
|
||||
}).catch((err) => {
|
||||
$q.notify(errorObject("Přihlášení se nezdařilo."))
|
||||
$q.notify(errorObject(`Přihlášení se nezdařilo. ${err}`))
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user