Bugfixy
This commit is contained in:
+1
-1
@@ -35,7 +35,7 @@ services:
|
||||
- ./node_modules:/app/node_modules:delegated
|
||||
command: quasar dev
|
||||
environment:
|
||||
VUE_API_URL: "http://localhost:8000"
|
||||
API_URL: "http://localhost:8000"
|
||||
|
||||
# nginx:
|
||||
# image:
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<script setup>
|
||||
import {poi} from "src/composables/objects/poi";
|
||||
|
||||
const props = defineProps({
|
||||
routeBack: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
labelBack: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "Přejít zpět na detail"
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-banner class="bg-red text-white">
|
||||
<template v-slot:avatar>
|
||||
<q-icon name="warning"/>
|
||||
</template>
|
||||
|
||||
Tato data ti nepatří a proto je nemůžeš měnit.
|
||||
|
||||
<template v-slot:action v-if="routeBack">
|
||||
<q-btn flat color="white" :to="routeBack" :label="labelBack"/>
|
||||
</template>
|
||||
</q-banner>
|
||||
</template>
|
||||
@@ -55,7 +55,7 @@ const fullwidthBtn = computed(() => $q.screen.width <= $q.screen.sizes.md);
|
||||
{{ props.saveButton.label }}
|
||||
|
||||
<template v-slot:loading>
|
||||
Loading...
|
||||
<q-spinner />
|
||||
</template>
|
||||
</q-btn>
|
||||
</div>
|
||||
|
||||
@@ -18,6 +18,15 @@ const props = defineProps({
|
||||
|
||||
<template>
|
||||
<q-list bordered separator>
|
||||
<q-item>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="flight"/>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
{{ flight.aircraft.callSign }}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="event"/>
|
||||
|
||||
@@ -50,7 +50,7 @@ const mapPhotos = computed(() => {
|
||||
|
||||
const displayMap = computed(() => {
|
||||
return (
|
||||
!!flight.value.gpsTrackUrl ||
|
||||
!!flight.value.gpxTrackUrl ||
|
||||
mapPhotos.value.length > 0 ||
|
||||
trackWithGPS.value.length > 0 ||
|
||||
flight.value.landingAirport.id !== flight.value.takeoffAirport.id
|
||||
|
||||
@@ -7,6 +7,10 @@ const props = defineProps({
|
||||
flight: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
isRequestPending: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -16,7 +20,7 @@ const formData = reactive({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FormWrapper v-model="formData" :save-button='{
|
||||
<FormWrapper v-model="formData" :is-request-pending="isRequestPending" :save-button='{
|
||||
label: "Nahrát",
|
||||
icon: "upload",
|
||||
align: "left"
|
||||
@@ -31,7 +35,7 @@ const formData = reactive({
|
||||
label="Vybert fotky k nahrání"
|
||||
>
|
||||
<template #prepend>
|
||||
<q-icon name="upload" />
|
||||
<q-icon name="upload"/>
|
||||
</template>
|
||||
</q-file>
|
||||
</FormWrapper>
|
||||
|
||||
@@ -4,14 +4,15 @@ import {commonProps} from "src/composables/inputs";
|
||||
import {reactive, watch} from "vue";
|
||||
import {setDefaultData} from "src/composables/form/formHandling";
|
||||
import AvatarFromPhoto from "components/AvatarFromPhoto.vue";
|
||||
import {user as pilot} from "src/composables/objects/user";
|
||||
import {isRequestPending} from "src/composables/form/props";
|
||||
|
||||
const props = defineProps({
|
||||
user: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
isRequestPending
|
||||
});
|
||||
const formData = reactive({
|
||||
avatarImage: null,
|
||||
@@ -25,7 +26,7 @@ watch(() => props.user, (newVal) => {
|
||||
|
||||
|
||||
<template>
|
||||
<FormWrapper v-model="formData">
|
||||
<FormWrapper v-model="formData" :is-request-pending="props.isRequestPending">
|
||||
|
||||
<div class="text-center">
|
||||
<AvatarFromPhoto :size="200" :src="user.avatarImageUrl" v-if="user.avatarImageUrl" />
|
||||
|
||||
@@ -6,13 +6,16 @@ import {commonProps} from "src/composables/inputs";
|
||||
import RichTextEditor from "components/inputs/RichTextEditor.vue";
|
||||
import FormWrapper from "components/FormWrapper.vue";
|
||||
import {setDefaultData} from "src/composables/form/formHandling";
|
||||
import {isRequestPending} from "src/composables/form/props";
|
||||
|
||||
const props = defineProps({
|
||||
user: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
isRequestPending,
|
||||
|
||||
})
|
||||
|
||||
const formData = reactive({
|
||||
@@ -26,7 +29,7 @@ watch(() => props.user, (newVal) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FormWrapper v-model="formData">
|
||||
<FormWrapper v-model="formData" :is-request-pending="props.isRequestPending">
|
||||
|
||||
<q-list>
|
||||
<q-item v-if="user.publicUsername">
|
||||
|
||||
@@ -4,13 +4,11 @@ import {FRAGMENT_FLIGHT_FULL_INFO} from "src/graphql/fragments/flight";
|
||||
export const CREATE_FLIGHT = gql`
|
||||
mutation createFlight($input: CreateFlightInput!) {
|
||||
createFlight(input: $input) {
|
||||
...flightFullInfo
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
${FRAGMENT_FLIGHT_FULL_INFO}
|
||||
`
|
||||
|
||||
// ^^ nesmim se tu ptat na aircraft, jinak mi to upadne
|
||||
export const EDIT_FLIGHT = gql`
|
||||
mutation editFlight($id: Int!, $input: EditFlightInput!) {
|
||||
editFlight(id: $id, input: $input) {
|
||||
|
||||
@@ -20,13 +20,21 @@
|
||||
<q-icon name="person" v-else/>
|
||||
|
||||
<q-menu auto-close>
|
||||
<q-list>
|
||||
<q-list style="min-width: 200px">
|
||||
<q-item clickable :to="{name: 'profile'}">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="person"/>
|
||||
</q-item-section>
|
||||
<q-item-section>Osobní nastavení</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item clickable @click="logout">
|
||||
<q-item-section>Odhlásit</q-item-section>
|
||||
<q-item clickable @click="logout" class="q-mt-lg">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="logout"/>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
Odhlásit
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
</q-list>
|
||||
|
||||
@@ -13,11 +13,11 @@ useAppStore().setPageTitle("Profil");
|
||||
const loggedUser = storeToRefs(useUserStore()).user;
|
||||
|
||||
const $q = useQuasar();
|
||||
const handleSave = (formData) => {
|
||||
useUserStore().update(loggedUser.id, formData).then((user) => {
|
||||
$q.notify(successObject("Uspesne upraveno"));
|
||||
});
|
||||
const handleSave = async (formData) => {
|
||||
await useUserStore().update(formData);
|
||||
$q.notify(successObject("Úspěšně uloženo"));
|
||||
};
|
||||
const isRequestPending = storeToRefs(useUserStore()).isMutationRunning;
|
||||
const openedTab = ref("profile");
|
||||
</script>
|
||||
|
||||
@@ -30,15 +30,15 @@ const openedTab = ref("profile");
|
||||
|
||||
<q-tab-panels v-model="openedTab">
|
||||
<q-tab-panel name="profile">
|
||||
<ProfileImagesForm :user="loggedUser" @save="handleSave"/>
|
||||
<ProfileImagesForm :user="loggedUser" :isRequestPending="isRequestPending" @save="handleSave"/>
|
||||
</q-tab-panel>
|
||||
|
||||
<q-tab-panel name="changePassword">
|
||||
<ChangePasswordForm @save="handleSave" />
|
||||
<ChangePasswordForm @save="handleSave" :isRequestPending="isRequestPending" />
|
||||
</q-tab-panel>
|
||||
|
||||
<q-tab-panel name="publicProfile">
|
||||
<PublicProfileInfo @save="handleSave" :user="loggedUser" />
|
||||
<PublicProfileInfo @save="handleSave" :isRequestPending="isRequestPending" :user="loggedUser" />
|
||||
</q-tab-panel>
|
||||
|
||||
</q-tab-panels>
|
||||
|
||||
@@ -10,6 +10,7 @@ import FAB from "components/FAB.vue";
|
||||
import {useAppStore} from "stores/App";
|
||||
import FlightsList from "components/flights/FlightsList.vue";
|
||||
import {copilot} from "src/composables/objects/copilot";
|
||||
import {flight} from "src/composables/objects/flight";
|
||||
|
||||
const aircraftId = parseInt(useRoute().params.id);
|
||||
onMounted(() => {
|
||||
@@ -44,6 +45,21 @@ watch(aircraft, (newVal) => {
|
||||
<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">
|
||||
@@ -55,9 +71,10 @@ watch(aircraft, (newVal) => {
|
||||
</q-list>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="right">
|
||||
<q-btn @click="confirmDelete(aircraft.id)" icon="delete" text-color="red" rounded flat/>
|
||||
</q-card-actions>
|
||||
<!-- <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>
|
||||
@@ -68,7 +85,7 @@ watch(aircraft, (newVal) => {
|
||||
<FlightsList :items="aircraft.flights" v-else/>
|
||||
</q-card>
|
||||
|
||||
<FAB :router-link='{name: "aircraftEdit", params: {id: aircraft.id}}' mode="edit"/>
|
||||
<!-- <FAB :router-link='{name: "aircraftEdit", params: {id: aircraft.id}}' mode="edit"/>-->
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
@@ -55,6 +55,8 @@ const handleFlightEdit = (data) => {
|
||||
})
|
||||
}
|
||||
|
||||
const isRequestPending = storeToRefs(useFlightsStore()).isMutationRunning;
|
||||
|
||||
const handlePhotosUpload = (data) => {
|
||||
const promises = [];
|
||||
for (const photo of data.photos) {
|
||||
@@ -134,6 +136,7 @@ const openPhotoEdit = (photo) => {
|
||||
<q-tab-panel name="photos">
|
||||
<FlightFormPhotos
|
||||
:flight="flight"
|
||||
:is-request-pending="isRequestPending"
|
||||
@save="handlePhotosUpload"
|
||||
/>
|
||||
|
||||
@@ -144,6 +147,8 @@ const openPhotoEdit = (photo) => {
|
||||
@save="handlePhotoUpdate"
|
||||
/>
|
||||
|
||||
Tu nejsou videt fotky po nahrani
|
||||
|
||||
<PhotosList
|
||||
:photos="flight.photos"
|
||||
@edit="openPhotoEdit"
|
||||
|
||||
@@ -10,6 +10,8 @@ import {successObject} from "src/composables/dialog";
|
||||
import {usePointsOfInterestTypeStore} from "stores/PointOfInterestType";
|
||||
import {storeToRefs} from "pinia";
|
||||
import POIForm from "components/poi/POIForm.vue";
|
||||
import {useUserStore} from "stores/User";
|
||||
import AccessDeniedBanner from "components/AccessDeniedBanner.vue";
|
||||
|
||||
const poiId = parseInt(useRoute().params.id);
|
||||
|
||||
@@ -27,6 +29,7 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
const poiTypes = storeToRefs(usePointsOfInterestTypeStore()).items;
|
||||
const loggedUser = storeToRefs(useUserStore()).user;
|
||||
|
||||
const $q = useQuasar();
|
||||
const router = useRouter();
|
||||
@@ -40,6 +43,6 @@ const handleSave = (data) => {
|
||||
|
||||
<template>
|
||||
<POIEditSkeleton v-if="loading"/>
|
||||
|
||||
<AccessDeniedBanner v-else-if="poi.createdbyId !== loggedUser.id" :route-back="{name: 'poiDetail', params: {id: poiId}}"/>
|
||||
<POIForm :poi="poi" :types="poiTypes" v-else @save="handleSave"/>
|
||||
</template>
|
||||
|
||||
@@ -29,7 +29,7 @@ onMounted(() => {
|
||||
<POIDetailSkeleton v-if="loading || !poi"/>
|
||||
|
||||
<template v-else>
|
||||
<article v-html="poi.description" />
|
||||
<article v-html="poi.description" class="q-my-lg" />
|
||||
|
||||
<EmbeddedMap
|
||||
v-if="poi.gpsLatitude && poi.gpsLongitude"
|
||||
@@ -51,7 +51,7 @@ onMounted(() => {
|
||||
Pokud přidáš toto místo k nějaké fotce, zobrazí se tu.
|
||||
</BasicInfoBanner>
|
||||
|
||||
<FlightsList :items="poi.flights" />
|
||||
<FlightsList :items="poi.flights" v-if="poi.flights.length > 0 && loggedUser.id === poi.createdById"/>
|
||||
|
||||
<FAB v-if="poi.createdById === loggedUser.id" :router-link="{name: 'poiEdit', params:{id: poi.id}}" mode="edit"/>
|
||||
</template>
|
||||
|
||||
@@ -6,7 +6,8 @@ import {deleteFromItems, updateInItems} from "stores/helpers";
|
||||
|
||||
export const useAircraftsStore = defineStore('Aircrafts', {
|
||||
state: () => ({
|
||||
items: []
|
||||
items: [],
|
||||
isMutationRunning: false
|
||||
}),
|
||||
|
||||
getters: {
|
||||
@@ -15,18 +16,19 @@ export const useAircraftsStore = defineStore('Aircrafts', {
|
||||
|
||||
actions: {
|
||||
fetchDetail(id) {
|
||||
console.log(id);
|
||||
return apolloWrapper
|
||||
.query(AIRCRAFT_DETAIL, {id})
|
||||
.then((result) => result.data.aircraft);
|
||||
},
|
||||
create(formData) {
|
||||
delete formData['id'];
|
||||
|
||||
this.isMutationRunning = true;
|
||||
return apolloWrapper.mutate(CREATE_AIRCRAFT, {input: formData}).then(({data}) => {
|
||||
this.items.push(data.createAircraft);
|
||||
// this.items.push(data.createAircraft);
|
||||
|
||||
return data.createAircraft;
|
||||
})
|
||||
}).finally(() => this.isMutationRunning = false);
|
||||
},
|
||||
delete(id) {
|
||||
return apolloWrapper.mutate(DELETE_AIRCRAFT, {id}).then(({data}) => {
|
||||
@@ -36,11 +38,12 @@ export const useAircraftsStore = defineStore('Aircrafts', {
|
||||
});
|
||||
},
|
||||
update(id, formData) {
|
||||
this.isMutationRunning = true;
|
||||
return apolloWrapper.mutate(EDIT_AIRCRAFT, {id: id, input: formData}).then(({data}) => {
|
||||
const aircraft = data.editAircraft;
|
||||
updateInItems(this.items, 'id', aircraft);
|
||||
return aircraft;
|
||||
});
|
||||
}).finally(() => this.isMutationRunning = false);
|
||||
},
|
||||
fetch() {
|
||||
return apolloWrapper
|
||||
|
||||
+10
-3
@@ -6,7 +6,8 @@ import {updateInItems} from "stores/helpers";
|
||||
|
||||
export const useFlightsStore = defineStore('Flights', {
|
||||
state: () => ({
|
||||
items: []
|
||||
items: [],
|
||||
isMutationRunning: false
|
||||
}),
|
||||
|
||||
getters: {
|
||||
@@ -19,18 +20,24 @@ export const useFlightsStore = defineStore('Flights', {
|
||||
create(formData) {
|
||||
delete formData['id'];
|
||||
return apolloWrapper.mutate(CREATE_FLIGHT, {input: formData}).then(({data}) => {
|
||||
this.items.push(data.createFlight);
|
||||
const flightId = data.createFlight.id;
|
||||
|
||||
// pitomy ohack kvuli tomu, ze se mi nedari dostat z API rovnou informace o nove vytvorenem letadle
|
||||
this.fetchDetail(flightId).then(flight => {
|
||||
this.items.push(flight);
|
||||
})
|
||||
|
||||
return data.createFlight;
|
||||
})
|
||||
},
|
||||
update(id, formData) {
|
||||
this.isMutationRunning = true;
|
||||
return apolloWrapper.mutate(EDIT_FLIGHT, {id: id, input: formData}).then(({data}) => {
|
||||
const flight = data.editFlight;
|
||||
updateInItems(this.items, "id", flight);
|
||||
|
||||
return flight;
|
||||
});
|
||||
}).finally(() => this.isMutationRunning = false);
|
||||
},
|
||||
fetchDetail(id, username = null) {
|
||||
if (typeof id !== "number") {
|
||||
|
||||
+6
-3
@@ -8,15 +8,18 @@ export const useUserStore = defineStore('LoggedUser', {
|
||||
state: () => ({
|
||||
user: {},
|
||||
isRefreshing: false,
|
||||
isMutationRunning: false,
|
||||
}),
|
||||
|
||||
actions: {
|
||||
update(id, formData) {
|
||||
apolloWrapper.mutate(EDIT_USER, {id, input: formData}).then((response) => {
|
||||
update(formData) {
|
||||
this.isMutationRunning = true;
|
||||
|
||||
apolloWrapper.mutate(EDIT_USER, {input: formData}).then((response) => {
|
||||
const user = response.data?.editLoggedUser;
|
||||
this.user = user;
|
||||
return user;
|
||||
});
|
||||
}).finally(() => this.isMutationRunning = false);
|
||||
},
|
||||
|
||||
fetchLoggedUserDetail() {
|
||||
|
||||
Reference in New Issue
Block a user