359 lines
9.4 KiB
Vue
359 lines
9.4 KiB
Vue
<script setup>
|
|
import axios from 'axios';
|
|
import { ref, computed, watch } from 'vue';
|
|
import { useQuasar } from 'quasar';
|
|
import { useRouter } from 'vue-router';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useSession } from 'composables/useSession';
|
|
import VnConfirm from 'components/ui/VnConfirm.vue';
|
|
import FetchData from 'components/FetchData.vue';
|
|
|
|
const router = useRouter();
|
|
const quasar = useQuasar();
|
|
const { t } = useI18n();
|
|
const { getTokenMultimedia } = useSession();
|
|
const token = getTokenMultimedia();
|
|
|
|
const claimId = computed(() => router.currentRoute.value.params.id);
|
|
|
|
const claimDms = ref([
|
|
{
|
|
dmsFk: claimId,
|
|
},
|
|
]);
|
|
const client = ref({});
|
|
const inputFile = ref();
|
|
const files = ref({});
|
|
const spinnerRef = ref();
|
|
const claimDmsRef = ref();
|
|
const dmsType = ref({});
|
|
const config = ref({});
|
|
const dragFile = ref(false);
|
|
const dragFileTimeout = ref();
|
|
const claimDmsFilter = ref({
|
|
include: [
|
|
{
|
|
relation: 'client',
|
|
scope: {
|
|
fields: ['id', 'name'],
|
|
},
|
|
},
|
|
{
|
|
relation: 'claimDms',
|
|
scope: {
|
|
include: {
|
|
relation: 'dms',
|
|
scope: {
|
|
fields: ['contentType'],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
],
|
|
where: { id: claimId.value },
|
|
});
|
|
|
|
const multimediaDialog = ref();
|
|
const multimediaSlide = ref();
|
|
|
|
watch(
|
|
() => router.currentRoute.value.params.id,
|
|
() => {
|
|
claimDmsFilter.value.where.id = router.currentRoute.value.params.id;
|
|
claimDmsRef.value.fetch();
|
|
}
|
|
);
|
|
|
|
function openDialog(dmsId) {
|
|
multimediaSlide.value = dmsId;
|
|
multimediaDialog.value = true;
|
|
}
|
|
|
|
function viewDeleteDms(index) {
|
|
quasar
|
|
.dialog({
|
|
component: VnConfirm,
|
|
componentProps: {
|
|
title: t('This file will be deleted'),
|
|
icon: 'delete',
|
|
data: { index },
|
|
promise: deleteDms,
|
|
},
|
|
})
|
|
.onOk(() => claimDms.value.splice(index, 1));
|
|
}
|
|
|
|
async function deleteDms({ index }) {
|
|
const dmsId = claimDms.value[index].dmsFk;
|
|
await axios.post(`ClaimDms/${dmsId}/removeFile`);
|
|
quasar.notify({
|
|
message: t('globals.dataDeleted'),
|
|
type: 'positive',
|
|
icon: 'delete',
|
|
});
|
|
}
|
|
|
|
function setClaimDms(data) {
|
|
if (!data) return;
|
|
|
|
claimDms.value = data.claimDms.map((media) => {
|
|
media.isVideo = media.dms.contentType == 'video/mp4';
|
|
media.url = `/api/Claims/${media.dmsFk}/downloadFile?access_token=${token}`;
|
|
return media;
|
|
});
|
|
client.value = data.client;
|
|
}
|
|
|
|
async function create() {
|
|
const formData = new FormData();
|
|
const inputFiles = files.value;
|
|
for (let i = 0; i < inputFiles.length; i++)
|
|
formData.append(inputFiles[i].name, inputFiles[i]);
|
|
|
|
const query = `claims/${claimId.value}/uploadFile`;
|
|
|
|
const dms = {
|
|
hasFile: false,
|
|
hasFileAttached: false,
|
|
reference: claimId.value,
|
|
warehouseId: config.value.warehouseFk,
|
|
companyId: config.value.companyFk,
|
|
dmsTypeId: dmsType.value.id,
|
|
description: t('claim.fileDescription', {
|
|
claimId: claimId.value,
|
|
clientName: client.value.name,
|
|
clientId: client.value.id,
|
|
}).toUpperCase(),
|
|
};
|
|
spinnerRef.value.show();
|
|
await axios.post(query, formData, {
|
|
params: dms,
|
|
});
|
|
spinnerRef.value.hide();
|
|
quasar.notify({
|
|
message: t('globals.dataSaved'),
|
|
type: 'positive',
|
|
icon: 'check',
|
|
});
|
|
|
|
claimDmsRef.value.fetch();
|
|
}
|
|
|
|
function onDrop($data) {
|
|
dragFile.value = false;
|
|
files.value = $data.dataTransfer.files;
|
|
create();
|
|
}
|
|
|
|
function onDrag() {
|
|
clearTimeout(dragFileTimeout.value);
|
|
dragFileTimeout.value = setTimeout(() => (dragFile.value = false), 500);
|
|
dragFile.value = true;
|
|
}
|
|
</script>
|
|
<template>
|
|
<FetchData
|
|
url="Claims"
|
|
:filter="claimDmsFilter"
|
|
@on-fetch="([data]) => setClaimDms(data)"
|
|
limit="20"
|
|
auto-load
|
|
ref="claimDmsRef"
|
|
/>
|
|
<FetchData
|
|
url="DmsTypes/findOne"
|
|
:filter="{ where: { code: 'claim' } }"
|
|
@on-fetch="(data) => (dmsType = data)"
|
|
auto-load
|
|
/>
|
|
<FetchData
|
|
url="UserConfigs/getUserConfig"
|
|
@on-fetch="(data) => (config = data)"
|
|
auto-load
|
|
/>
|
|
<div
|
|
:class="['container', { dragFile }]"
|
|
@drop.prevent="onDrop"
|
|
@dragenter.prevent
|
|
@dragover.prevent="onDrag"
|
|
>
|
|
<div
|
|
class="flex flex-center items-center text-grey q-mt-md column"
|
|
v-if="dragFile"
|
|
>
|
|
<QIcon size="xl" name="file_download" />
|
|
<h5>
|
|
{{ t('claim.dragDrop') }}
|
|
</h5>
|
|
</div>
|
|
<div
|
|
class="text-center text-grey q-mt-md cursor-pointer"
|
|
v-if="!claimDms?.length && !dragFile"
|
|
@click="inputFile.nativeEl.click()"
|
|
>
|
|
<QIcon size="xl" name="image"></QIcon>
|
|
<QIcon size="xl" name="movie"></QIcon>
|
|
<h5>
|
|
{{ t('claim.noData') }}
|
|
</h5>
|
|
</div>
|
|
<div class="multimediaParent bg-transparent" v-if="claimDms?.length && !dragFile">
|
|
<div
|
|
v-for="(media, index) of claimDms"
|
|
:key="index"
|
|
class="relative-position"
|
|
>
|
|
<QBtn
|
|
icon="delete"
|
|
color="primary"
|
|
text-color="white"
|
|
size="md"
|
|
class="all-pointer-events absolute delete-button zindex"
|
|
@click.stop="viewDeleteDms(index)"
|
|
round
|
|
/>
|
|
<QIcon
|
|
name="play_circle"
|
|
color="primary"
|
|
size="xl"
|
|
class="absolute-center zindex"
|
|
v-if="media.isVideo"
|
|
@click.stop="openDialog(media.dmsFk)"
|
|
>
|
|
<QTooltip>Video</QTooltip>
|
|
</QIcon>
|
|
<QCard class="multimedia relative-position">
|
|
<QImg
|
|
:src="media.url"
|
|
class="rounded-borders cursor-pointer fit"
|
|
@click="openDialog(media.dmsFk)"
|
|
v-if="!media.isVideo"
|
|
>
|
|
</QImg>
|
|
<video
|
|
:src="media.url"
|
|
class="rounded-borders cursor-pointer fit"
|
|
muted="muted"
|
|
v-if="media.isVideo"
|
|
@click="openDialog(media.dmsFk)"
|
|
/>
|
|
</QCard>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<QDialog ref="spinnerRef">
|
|
<QSpinner color="primary" size="xl" />
|
|
</QDialog>
|
|
<QPageSticky position="bottom-right" :offset="[25, 25]">
|
|
<label for="fileInput">
|
|
<QBtn
|
|
fab
|
|
@click="inputFile.nativeEl.click()"
|
|
shortcut="+"
|
|
icon="add"
|
|
color="primary"
|
|
>
|
|
<QInput
|
|
ref="inputFile"
|
|
type="file"
|
|
style="display: none"
|
|
multiple
|
|
v-model="files"
|
|
@update:model-value="create()"
|
|
/>
|
|
<QTooltip bottom> {{ t('globals.add') }} </QTooltip>
|
|
</QBtn>
|
|
</label>
|
|
</QPageSticky>
|
|
|
|
<!-- MULTIMEDIA DIALOG START-->
|
|
<QDialog
|
|
v-model="multimediaDialog"
|
|
transition-show="slide-up"
|
|
transition-hide="slide-down"
|
|
>
|
|
<QToolbar class="absolute zindex close-button">
|
|
<QSpace />
|
|
<QBtn icon="close" color="primary" round dense v-close-popup />
|
|
</QToolbar>
|
|
<QCarousel swipeable animated v-model="multimediaSlide" arrows class="fit">
|
|
<QCarouselSlide
|
|
v-for="media of claimDms"
|
|
:key="media.dmsFk"
|
|
:name="media.dmsFk"
|
|
>
|
|
<QImg
|
|
:src="media.url"
|
|
class="fit"
|
|
fit="scale-down"
|
|
v-if="!media.isVideo"
|
|
/>
|
|
<video class="q-ma-none fit" v-if="media.isVideo" controls muted autoplay>
|
|
<source :src="media.url" type="video/mp4" />
|
|
</video>
|
|
</QCarouselSlide>
|
|
</QCarousel>
|
|
</QDialog>
|
|
<!-- MULTIMEDIA DIALOG END-->
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.container {
|
|
min-height: 80vh;
|
|
min-width: 80%;
|
|
}
|
|
.q-dialog__inner--minimized > div {
|
|
max-width: 80%;
|
|
}
|
|
.multimediaParent {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
|
|
|
grid-auto-rows: auto;
|
|
|
|
grid-gap: 1rem;
|
|
}
|
|
|
|
.multimedia {
|
|
transition: all 0.5s;
|
|
opacity: 1;
|
|
height: 250px;
|
|
|
|
.q-img {
|
|
object-fit: cover;
|
|
background-color: black;
|
|
}
|
|
video {
|
|
object-fit: cover;
|
|
background-color: black;
|
|
}
|
|
}
|
|
|
|
.multimedia:hover {
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.delete-button {
|
|
top: 10px;
|
|
left: 10px;
|
|
}
|
|
|
|
.close-button {
|
|
top: 1%;
|
|
right: 10%;
|
|
}
|
|
|
|
.zindex {
|
|
z-index: 1;
|
|
}
|
|
|
|
.dragFile {
|
|
border: 2px dashed $color-spacer;
|
|
}
|
|
</style>
|
|
|
|
<i18n>
|
|
es:
|
|
This file will be deleted: Este archivo va a ser borrado
|
|
</i18n>
|