Slugy, webp, hromada refaktoringu

This commit is contained in:
Michal Kváček
2024-01-13 23:29:51 +01:00
parent e7cde2f425
commit 5a5c7cb645
57 changed files with 755 additions and 399 deletions
+4 -2
View File
@@ -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"
+79 -40
View File
@@ -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"
+20 -2
View File
@@ -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 -1
View File
@@ -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"/>
+30 -22
View File
@@ -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">
+51 -61
View File
@@ -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 -1
View File
@@ -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>
+1 -1
View File
@@ -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}`))
})
};