Otaceni fotek
This commit is contained in:
@@ -28,7 +28,7 @@ const props = defineProps({
|
|||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>
|
<q-item-label>
|
||||||
{{ organization.name }}
|
{{ organization.name }}
|
||||||
<q-icon name="star" color="gold" v-if="myOrganizationsIds.includes(organization.id)"/>
|
<q-icon name="star" color="red" v-if="myOrganizationsIds.includes(organization.id)"/>
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {computed, onMounted, ref, watch} from "vue";
|
import {computed, onMounted, reactive, ref, watch} from "vue";
|
||||||
import {useQuasar} from "quasar";
|
import {useQuasar} from "quasar";
|
||||||
import {confirmObject} from "src/composables/dialog";
|
import {confirmObject} from "src/composables/dialog";
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const emits = defineEmits(["edit", "delete", "batch-edit"])
|
const emits = defineEmits(["edit", "delete", "batch-edit", "batch-rotate"])
|
||||||
|
|
||||||
const openEdit = (photo) => {
|
const openEdit = (photo) => {
|
||||||
emits("edit", photo);
|
emits("edit", photo);
|
||||||
@@ -55,17 +55,29 @@ const handleImageClick = (photo, idx) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const selectedPhotos = computed(() => {
|
||||||
const openBatchEdit = () => {
|
|
||||||
const photos = [];
|
const photos = [];
|
||||||
for (const i in batchEdit.value) {
|
for (const i in batchEdit.value) {
|
||||||
const photo = props.photos.find(p => p.id === parseInt(i));
|
const photo = props.photos.find(p => p.id === parseInt(i));
|
||||||
if (photo && batchEdit.value[i]) photos.push(photo);
|
if (photo && batchEdit.value[i]) photos.push(photo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return photos;
|
||||||
|
});
|
||||||
|
|
||||||
|
const openBatchEdit = () => {
|
||||||
|
const photos = selectedPhotos.value;
|
||||||
|
for (const i in batchEdit.value) {
|
||||||
batchEdit.value[i] = false;
|
batchEdit.value[i] = false;
|
||||||
}
|
}
|
||||||
emits('batch-edit', photos);
|
emits('batch-edit', photos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const batchRotate = (angle) => {
|
||||||
|
const photos = selectedPhotos.value;
|
||||||
|
emits("batch-rotate", {photos, angle});
|
||||||
|
}
|
||||||
|
|
||||||
const isBatchEditAllowed = computed(() => Object.values(batchEdit.value).filter(v => v).length > 0);
|
const isBatchEditAllowed = computed(() => Object.values(batchEdit.value).filter(v => v).length > 0);
|
||||||
|
|
||||||
const checkAll = ref(false);
|
const checkAll = ref(false);
|
||||||
@@ -96,6 +108,12 @@ watch(() => batchEdit.value, () => {
|
|||||||
}
|
}
|
||||||
}, {deep: true});
|
}, {deep: true});
|
||||||
|
|
||||||
|
const batchOptionsProps = computed(() => ({
|
||||||
|
round: true,
|
||||||
|
flat: true,
|
||||||
|
class: "q-ml-lg",
|
||||||
|
disable: !isBatchEditAllowed.value
|
||||||
|
}));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -133,8 +151,10 @@ watch(() => batchEdit.value, () => {
|
|||||||
<q-card>
|
<q-card>
|
||||||
<q-card-actions>
|
<q-card-actions>
|
||||||
<q-checkbox v-model="checkAll" label="Vybrat vše"/>
|
<q-checkbox v-model="checkAll" label="Vybrat vše"/>
|
||||||
<q-btn round class="q-ml-lg" flat icon="edit" :color="isBatchEditAllowed ? 'primary' : 'grey'" :disable="!isBatchEditAllowed" @click="openBatchEdit" v-if="showActions"/>
|
<q-btn v-bind="batchOptionsProps" icon="edit" :color="isBatchEditAllowed ? 'primary' : 'grey'" @click="openBatchEdit"/>
|
||||||
<q-btn round flat icon="delete" :color="isBatchEditAllowed ? 'red' : 'grey'" :disable="!isBatchEditAllowed" @click="confirmBatchPhotoDelete" v-if="showActions"/>
|
<q-btn v-bind="batchOptionsProps" icon="rotate_left" :color="isBatchEditAllowed ? 'secondary' : 'grey'" @click="batchRotate(90)"/>
|
||||||
|
<q-btn v-bind="batchOptionsProps" icon="rotate_right" :color="isBatchEditAllowed ? 'secondary' : 'grey'" @click="batchRotate(-90)"/>
|
||||||
|
<q-btn v-bind="batchOptionsProps" icon="delete" :color="isBatchEditAllowed ? 'red' : 'grey'" @click="confirmBatchPhotoDelete"/>
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-page-sticky>
|
</q-page-sticky>
|
||||||
|
|||||||
@@ -21,6 +21,17 @@ mutation editPhoto($id: Int!, $input: EditPhotoInput!) {
|
|||||||
${FRAGMENT_PHOTO_FULL_INFO}
|
${FRAGMENT_PHOTO_FULL_INFO}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const ROTATE_PHOTO = gql`
|
||||||
|
mutation rotatePhoto($id: Int!, $angle: Int!) {
|
||||||
|
rotatePhoto(id: $id, angle: $angle) {
|
||||||
|
...photoFullInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
${FRAGMENT_PHOTO_FULL_INFO}
|
||||||
|
`;
|
||||||
|
|
||||||
|
|
||||||
export const DELETE_PHOTO = gql`
|
export const DELETE_PHOTO = gql`
|
||||||
mutation deletePhoto($id: Int!) {
|
mutation deletePhoto($id: Int!) {
|
||||||
deletePhoto(id: $id) {
|
deletePhoto(id: $id) {
|
||||||
|
|||||||
@@ -100,6 +100,28 @@ const deletePhoto = (id) => {
|
|||||||
flight.value.photos.splice(_findPhotoIndex(data.id), 1);
|
flight.value.photos.splice(_findPhotoIndex(data.id), 1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rotatePhotos = ({photos, angle}) => {
|
||||||
|
const promises = [];
|
||||||
|
for (const photo of photos) {
|
||||||
|
promises.push(usePhotosStore().rotate(photo.id, angle));
|
||||||
|
}
|
||||||
|
|
||||||
|
let success = 0;
|
||||||
|
Promise.allSettled(promises).then(result => {
|
||||||
|
for (const updatedPhoto of result) {
|
||||||
|
const {status, value} = updatedPhoto;
|
||||||
|
if (status === 'fulfilled') success++;
|
||||||
|
|
||||||
|
const idx =_findPhotoIndex(value.id);
|
||||||
|
value.thumbnailUrl += "?t=" + (new Date()).getTime();
|
||||||
|
flight.value.photos[idx] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success > 0)
|
||||||
|
$q.notify(successObject("Otočeno " + success + " fotek"));
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -143,6 +165,7 @@ const deletePhoto = (id) => {
|
|||||||
:photos="flight.photos"
|
:photos="flight.photos"
|
||||||
@edit="openPhotoEdit"
|
@edit="openPhotoEdit"
|
||||||
@batch-edit="openBatchPhotoForm"
|
@batch-edit="openBatchPhotoForm"
|
||||||
|
@batch-rotate="rotatePhotos"
|
||||||
@delete="deletePhoto"
|
@delete="deletePhoto"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -31,14 +31,25 @@ onMounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<h3>Členové</h3>
|
<h3>Členové</h3>
|
||||||
|
|
||||||
<BasicListSkeleton :items-count-min="1" :items-count-max="5" v-if="loading || !organization"/>
|
|
||||||
|
|
||||||
|
<div class="q-my-md">
|
||||||
|
<q-btn color="positive" @click="addToOrganization(organizationId)" v-if="!myOrganizationIds.includes(organizationId)">
|
||||||
|
<q-icon name="add"/>
|
||||||
|
Přidat se
|
||||||
|
</q-btn>
|
||||||
|
<q-btn color="warning" @click="removeFromOrganization(organizationId)" v-else>
|
||||||
|
<q-icon name="remove"/>
|
||||||
|
Opustit organizaci
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<BasicListSkeleton :items-count-min="1" :items-count-max="5" v-if="loading || !organization"/>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<q-list bordered separator v-if="organization.users.length > 0">
|
<q-list bordered separator v-if="organization.users.length > 0">
|
||||||
<q-item v-for="user in organization.users" :key="user">
|
<q-item v-for="user in organization.users" :key="user">
|
||||||
<q-item-section avatar>
|
<q-item-section avatar>
|
||||||
<AvatarFromPhoto :src="user.avatarImageUrl" v-if="user.avatarImageUrl" size="50"/>
|
<AvatarFromPhoto :src="user.avatarImageUrl" v-if="user.avatarImageUrl" size="50"/>
|
||||||
<q-avatar icon="person" v-else class="bg-primary text-white" />
|
<q-avatar icon="person" v-else class="bg-primary text-white"/>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
{{ user.name || user.email }}
|
{{ user.name || user.email }}
|
||||||
@@ -49,19 +60,12 @@ onMounted(() => {
|
|||||||
<BasicInfoBanner v-else>
|
<BasicInfoBanner v-else>
|
||||||
Zatím nikdo...
|
Zatím nikdo...
|
||||||
</BasicInfoBanner>
|
</BasicInfoBanner>
|
||||||
|
</template>
|
||||||
|
|
||||||
<q-btn color="positive" @click="addToOrganization(organizationId)" v-if="!myOrganizationIds.includes(organizationId)">
|
<h3>Letadla</h3>
|
||||||
<q-icon name="add"/>
|
|
||||||
Přidat se
|
|
||||||
</q-btn>
|
|
||||||
<q-btn color="warning" size="lg" @click="removeFromOrganization(organizationId)" v-else>
|
|
||||||
<q-icon name="remove"/>
|
|
||||||
Opustit organizaci
|
|
||||||
</q-btn>
|
|
||||||
|
|
||||||
<h3>Letadla</h3>
|
<BasicListSkeleton :items-count-min="1" :items-count-max="5" v-if="loading || !organization"/>
|
||||||
|
<template v-else>
|
||||||
<BasicListSkeleton :items-count-min="1" :items-count-max="5" v-if="loading"/>
|
|
||||||
<AircraftsList :items="organization.aircrafts" v-if="organization.aircrafts.length > 0"/>
|
<AircraftsList :items="organization.aircrafts" v-if="organization.aircrafts.length > 0"/>
|
||||||
<BasicInfoBanner v-else>
|
<BasicInfoBanner v-else>
|
||||||
Žádné letadlo
|
Žádné letadlo
|
||||||
|
|||||||
+7
-1
@@ -1,6 +1,6 @@
|
|||||||
import {defineStore} from "pinia";
|
import {defineStore} from "pinia";
|
||||||
import {apolloWrapper} from "src/graphql/apollo";
|
import {apolloWrapper} from "src/graphql/apollo";
|
||||||
import {DELETE_PHOTO, EDIT_PHOTO, UPLOAD_PHOTO} from "src/graphql/mutations/photo";
|
import {DELETE_PHOTO, EDIT_PHOTO, ROTATE_PHOTO, UPLOAD_PHOTO} from "src/graphql/mutations/photo";
|
||||||
|
|
||||||
export const usePhotosStore = defineStore('Photos', {
|
export const usePhotosStore = defineStore('Photos', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
@@ -35,6 +35,12 @@ export const usePhotosStore = defineStore('Photos', {
|
|||||||
return data.editPhoto;
|
return data.editPhoto;
|
||||||
}).finally(() => this.isMutationRunning = false);
|
}).finally(() => this.isMutationRunning = false);
|
||||||
},
|
},
|
||||||
|
rotate(id, angle) {
|
||||||
|
this.isMutationRunning = true;
|
||||||
|
return apolloWrapper.mutate(ROTATE_PHOTO, {id, angle}).then(({data}) => {
|
||||||
|
return data.rotatePhoto;
|
||||||
|
}).finally(() => this.isMutationRunning = false);
|
||||||
|
},
|
||||||
delete(photoId) {
|
delete(photoId) {
|
||||||
return apolloWrapper.mutate(DELETE_PHOTO, {id: photoId}).then(({data}) => {
|
return apolloWrapper.mutate(DELETE_PHOTO, {id: photoId}).then(({data}) => {
|
||||||
return data.deletePhoto;
|
return data.deletePhoto;
|
||||||
|
|||||||
Reference in New Issue
Block a user