chore: Adds loader for attachment download buttons (#10748)
This commit is contained in:
@@ -18,6 +18,7 @@ const attachment = computed(() => {
|
|||||||
|
|
||||||
const hasError = ref(false);
|
const hasError = ref(false);
|
||||||
const showGallery = ref(false);
|
const showGallery = ref(false);
|
||||||
|
const isDownloading = ref(false);
|
||||||
|
|
||||||
const handleError = () => {
|
const handleError = () => {
|
||||||
hasError.value = true;
|
hasError.value = true;
|
||||||
@@ -26,7 +27,14 @@ const handleError = () => {
|
|||||||
|
|
||||||
const downloadAttachment = async () => {
|
const downloadAttachment = async () => {
|
||||||
const { fileType, dataUrl, extension } = attachment.value;
|
const { fileType, dataUrl, extension } = attachment.value;
|
||||||
downloadFile({ url: dataUrl, type: fileType, extension });
|
try {
|
||||||
|
isDownloading.value = true;
|
||||||
|
await downloadFile({ url: dataUrl, type: fileType, extension });
|
||||||
|
} catch (error) {
|
||||||
|
// error
|
||||||
|
} finally {
|
||||||
|
isDownloading.value = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -60,7 +68,9 @@ const downloadAttachment = async () => {
|
|||||||
slate
|
slate
|
||||||
icon="i-lucide-download"
|
icon="i-lucide-download"
|
||||||
class="opacity-60"
|
class="opacity-60"
|
||||||
@click="downloadAttachment"
|
:is-loading="isDownloading"
|
||||||
|
:disabled="isDownloading"
|
||||||
|
@click.stop="downloadAttachment"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
|
|||||||
import { messageTimestamp } from 'shared/helpers/timeHelper';
|
import { messageTimestamp } from 'shared/helpers/timeHelper';
|
||||||
import { downloadFile } from '@chatwoot/utils';
|
import { downloadFile } from '@chatwoot/utils';
|
||||||
|
|
||||||
|
import NextButton from 'dashboard/components-next/button/Button.vue';
|
||||||
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
|
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -33,6 +34,7 @@ const ALLOWED_FILE_TYPES = {
|
|||||||
const MAX_ZOOM_LEVEL = 2;
|
const MAX_ZOOM_LEVEL = 2;
|
||||||
const MIN_ZOOM_LEVEL = 1;
|
const MIN_ZOOM_LEVEL = 1;
|
||||||
|
|
||||||
|
const isDownloading = ref(false);
|
||||||
const zoomScale = ref(1);
|
const zoomScale = ref(1);
|
||||||
const activeAttachment = ref({});
|
const activeAttachment = ref({});
|
||||||
const activeFileType = ref('');
|
const activeFileType = ref('');
|
||||||
@@ -117,12 +119,20 @@ const onClickChangeAttachment = (attachment, index) => {
|
|||||||
zoomScale.value = 1;
|
zoomScale.value = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClickDownload = () => {
|
const onClickDownload = async () => {
|
||||||
const { file_type: type, data_url: url, extension } = activeAttachment.value;
|
const { file_type: type, data_url: url, extension } = activeAttachment.value;
|
||||||
if (!Object.values(ALLOWED_FILE_TYPES).includes(type)) {
|
if (!Object.values(ALLOWED_FILE_TYPES).includes(type)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
downloadFile({ url, type, extension });
|
|
||||||
|
try {
|
||||||
|
isDownloading.value = true;
|
||||||
|
await downloadFile({ url, type, extension });
|
||||||
|
} catch (error) {
|
||||||
|
// error
|
||||||
|
} finally {
|
||||||
|
isDownloading.value = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRotate = type => {
|
const onRotate = type => {
|
||||||
@@ -162,6 +172,12 @@ const onZoom = scale => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onClickZoomImage = () => {
|
const onClickZoomImage = () => {
|
||||||
|
// If already at max zoom, clicking should zoom out to minimum
|
||||||
|
if (zoomScale.value >= MAX_ZOOM_LEVEL) {
|
||||||
|
zoomScale.value = MIN_ZOOM_LEVEL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Otherwise zoom in
|
||||||
onZoom(0.1);
|
onZoom(0.1);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -211,7 +227,6 @@ onMounted(() => {
|
|||||||
:on-close="onClose"
|
:on-close="onClose"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-on-clickaway="onClose"
|
|
||||||
class="bg-white dark:bg-slate-900 flex flex-col h-[inherit] w-[inherit] overflow-hidden"
|
class="bg-white dark:bg-slate-900 flex flex-col h-[inherit] w-[inherit] overflow-hidden"
|
||||||
@click="onClose"
|
@click="onClose"
|
||||||
>
|
>
|
||||||
@@ -256,63 +271,54 @@ onMounted(() => {
|
|||||||
<div
|
<div
|
||||||
class="items-center flex gap-2 justify-end min-w-[8rem] sm:min-w-[15rem]"
|
class="items-center flex gap-2 justify-end min-w-[8rem] sm:min-w-[15rem]"
|
||||||
>
|
>
|
||||||
<woot-button
|
<NextButton
|
||||||
v-if="isImage"
|
v-if="isImage"
|
||||||
size="large"
|
icon="i-lucide-zoom-in"
|
||||||
color-scheme="secondary"
|
slate
|
||||||
variant="clear"
|
ghost
|
||||||
icon="zoom-in"
|
|
||||||
@click="onZoom(0.1)"
|
@click="onZoom(0.1)"
|
||||||
/>
|
/>
|
||||||
<woot-button
|
<NextButton
|
||||||
v-if="isImage"
|
v-if="isImage"
|
||||||
size="large"
|
icon="i-lucide-zoom-out"
|
||||||
color-scheme="secondary"
|
slate
|
||||||
variant="clear"
|
ghost
|
||||||
icon="zoom-out"
|
|
||||||
@click="onZoom(-0.1)"
|
@click="onZoom(-0.1)"
|
||||||
/>
|
/>
|
||||||
<woot-button
|
<NextButton
|
||||||
v-if="isImage"
|
v-if="isImage"
|
||||||
size="large"
|
icon="i-lucide-rotate-ccw"
|
||||||
color-scheme="secondary"
|
slate
|
||||||
variant="clear"
|
ghost
|
||||||
icon="arrow-rotate-counter-clockwise"
|
|
||||||
@click="onRotate('counter-clockwise')"
|
@click="onRotate('counter-clockwise')"
|
||||||
/>
|
/>
|
||||||
<woot-button
|
<NextButton
|
||||||
v-if="isImage"
|
v-if="isImage"
|
||||||
size="large"
|
icon="i-lucide-rotate-cw"
|
||||||
color-scheme="secondary"
|
slate
|
||||||
variant="clear"
|
ghost
|
||||||
icon="arrow-rotate-clockwise"
|
|
||||||
@click="onRotate('clockwise')"
|
@click="onRotate('clockwise')"
|
||||||
/>
|
/>
|
||||||
<woot-button
|
<NextButton
|
||||||
size="large"
|
icon="i-lucide-download"
|
||||||
color-scheme="secondary"
|
slate
|
||||||
variant="clear"
|
ghost
|
||||||
icon="arrow-download"
|
:is-loading="isDownloading"
|
||||||
|
:disabled="isDownloading"
|
||||||
@click="onClickDownload"
|
@click="onClickDownload"
|
||||||
/>
|
/>
|
||||||
<woot-button
|
<NextButton icon="i-lucide-x" slate ghost @click="onClose" />
|
||||||
size="large"
|
|
||||||
color-scheme="secondary"
|
|
||||||
variant="clear"
|
|
||||||
icon="dismiss"
|
|
||||||
@click="onClose"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-center w-full h-full">
|
<div class="flex items-center justify-center w-full h-full">
|
||||||
<div class="flex justify-center min-w-[6.25rem] w-[6.25rem]">
|
<div class="flex justify-center min-w-[6.25rem] w-[6.25rem]">
|
||||||
<woot-button
|
<NextButton
|
||||||
v-if="hasMoreThanOneAttachment"
|
v-if="hasMoreThanOneAttachment"
|
||||||
class="z-10"
|
icon="i-lucide-chevron-left"
|
||||||
size="large"
|
class="z-10 disabled:pointer-events-auto"
|
||||||
variant="smooth"
|
blue
|
||||||
color-scheme="primary"
|
faded
|
||||||
icon="chevron-left"
|
lg
|
||||||
:disabled="activeImageIndex === 0"
|
:disabled="activeImageIndex === 0"
|
||||||
@click.stop="
|
@click.stop="
|
||||||
onClickChangeAttachment(
|
onClickChangeAttachment(
|
||||||
@@ -354,14 +360,14 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-center min-w-[6.25rem] w-[6.25rem]">
|
<div class="flex justify-center min-w-[6.25rem] w-[6.25rem]">
|
||||||
<woot-button
|
<NextButton
|
||||||
v-if="hasMoreThanOneAttachment"
|
v-if="hasMoreThanOneAttachment"
|
||||||
class="z-10"
|
icon="i-lucide-chevron-right"
|
||||||
size="large"
|
class="z-10 disabled:pointer-events-auto"
|
||||||
variant="smooth"
|
blue
|
||||||
color-scheme="primary"
|
faded
|
||||||
|
lg
|
||||||
:disabled="activeImageIndex === allAttachments.length - 1"
|
:disabled="activeImageIndex === allAttachments.length - 1"
|
||||||
icon="chevron-right"
|
|
||||||
@click.stop="
|
@click.stop="
|
||||||
onClickChangeAttachment(
|
onClickChangeAttachment(
|
||||||
allAttachments[activeImageIndex + 1],
|
allAttachments[activeImageIndex + 1],
|
||||||
|
|||||||
Reference in New Issue
Block a user