From feb981c8e64c0c4c79bc6521118c82cdf676e2b4 Mon Sep 17 00:00:00 2001 From: Tobi Abiodun Date: Wed, 8 Jan 2025 16:13:42 -0500 Subject: [PATCH] feat: enhance file download functionality and refactor UI (#1319) - Add `forceFileDownloadFromURl` utility function for better file download handling. - Replace `base-link` with `base-button` in `Downloads.vue` for initiating file downloads. - Introduce `DownloadWorksiteCsv` component to manage async file downloads with a modal UI. - Update `Work.vue` to integrate `DownloadWorksiteCsv` for processing and downloading CSV files dynamically. - Refactor and improve user feedback during file download processes. --- .../downloads/DownloadWorksiteCsv.vue | 78 +++++++++++++++++++ src/pages/Downloads.vue | 34 ++++---- src/pages/Work.vue | 14 ++-- src/utils/downloads.ts | 13 ++++ 4 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 src/components/downloads/DownloadWorksiteCsv.vue diff --git a/src/components/downloads/DownloadWorksiteCsv.vue b/src/components/downloads/DownloadWorksiteCsv.vue new file mode 100644 index 000000000..7ced06ca6 --- /dev/null +++ b/src/components/downloads/DownloadWorksiteCsv.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/src/pages/Downloads.vue b/src/pages/Downloads.vue index 53c87d4e3..71b7999c6 100644 --- a/src/pages/Downloads.vue +++ b/src/pages/Downloads.vue @@ -12,17 +12,14 @@ > @@ -34,28 +31,39 @@ import moment from 'moment/moment'; import { makeTableColumns } from '@/utils/table'; import AjaxTable from '@/components/AjaxTable.vue'; import BaseText from '@/components/BaseText.vue'; +import BaseButton from '@/components/BaseButton.vue'; +import axios from 'axios'; +import { forceFileDownloadFromURl } from '@/utils/downloads'; export default defineComponent({ name: 'Downloads', - components: { BaseText, AjaxTable }, + components: { BaseButton, BaseText, AjaxTable }, setup() { const tableUrl = `${import.meta.env.VITE_APP_API_BASE_URL}/user_downloads`; const columns = makeTableColumns([ ['created_at', '1fr', 'Created At'], - ['file', '1fr', 'Status'], + ['status', '1fr', 'Status'], + ['file', '1fr', ''], ]); for (const column of columns) { // overwrite default column title from `Name` to `Organization` if (column.key === 'created_at') { column.transformer = (field) => { - return moment(field).format('ddd MMMM Do YYYY'); + return moment(field).format('ddd MMMM Do YYYY h:mm:ss a'); }; } } + const downloadFile = async (file: any) => { + const { data } = await axios.get(`/files/${file}`); + const url = data.csv_url; + return forceFileDownloadFromURl(url, data.filename_original); + }; + return { tableUrl, columns, + downloadFile, }; }, }); diff --git a/src/pages/Work.vue b/src/pages/Work.vue index 993225d43..7229405b3 100644 --- a/src/pages/Work.vue +++ b/src/pages/Work.vue @@ -1037,9 +1037,9 @@ import BaseButton from '@/components/BaseButton.vue'; import AjaxTable from '@/components/AjaxTable.vue'; import { momentFromNow } from '@/filters'; import User from '@/models/User'; -import { string } from 'zod'; import _ from 'lodash'; import Spinner from '@/components/Spinner.vue'; +import DownloadWorksiteCsv from '@/components/downloads/DownloadWorksiteCsv.vue'; export default defineComponent({ name: 'Work', @@ -1892,14 +1892,18 @@ export default defineComponent({ }/worksites_download/download_csv`, { params, - headers: { Accept: 'text/csv' }, - responseType: 'blob', }, ); if (response.status === 202) { - await confirm({ + await component({ title: t('info.processing_download'), - content: t('info.processing_download_d'), + component: DownloadWorksiteCsv, + classes: 'w-full overflow-auto p-3', + modalClasses: 'bg-white max-w-4xl shadow', + props: { + downloadId: response.data.download_id, + wait: Number(20), + }, }); } else if (response.status === 400) { const result = await confirm({ diff --git a/src/utils/downloads.ts b/src/utils/downloads.ts index 0d51442c7..4be1dbd98 100644 --- a/src/utils/downloads.ts +++ b/src/utils/downloads.ts @@ -72,3 +72,16 @@ export function downloadCSVFile(csvContent: string, fileName: string) { link.click(); link.remove(); } + +export function forceFileDownloadFromURl(url: string, fileName = 'unknown') { + const link = document.createElement('a'); + link.href = url; + const name = fileName ?? 'unknown'; + link.setAttribute('download', name); + document.body.append(link); + link.href = url; + // link.target = '_blank'; + link.click(); + link.remove(); + window.URL.revokeObjectURL(url); +}