Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: CrisisCleanup/crisiscleanup-4-web
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 84dd9eff540e3693bc8910efc068767ce42b662b
Choose a base ref
..
head repository: CrisisCleanup/crisiscleanup-4-web
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3096b359509a1ada9713153ccf5eeaa340ec46ca
Choose a head ref
Showing with 125 additions and 22 deletions.
  1. +4 −4 pnpm-lock.yaml
  2. +78 −0 src/components/downloads/DownloadWorksiteCsv.vue
  3. +21 −13 src/pages/Downloads.vue
  4. +9 −5 src/pages/Work.vue
  5. +13 −0 src/utils/downloads.ts
8 changes: 4 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

78 changes: 78 additions & 0 deletions src/components/downloads/DownloadWorksiteCsv.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<script setup lang="ts">
import axios from 'axios';
import { forceFileDownloadFromURl } from '@/utils/downloads';
import Spinner from '@/components/Spinner.vue';
const props = defineProps<{
downloadId: string;
wait?: number;
}>();
const { t } = useI18n();
// Reactive variables for UI feedback
const waitingForFile = ref(true);
const errorMessage = ref<string | null>(null);
const message = ref<string | null>(null);
// Function to download the file
const downloadFile = async (fileId: string) => {
try {
const url = `/files/${fileId}`;
const { data } = await axios.get(url);
const csvUrl = data.csv_url;
forceFileDownloadFromURl(csvUrl, data.filename_original);
waitingForFile.value = false;
message.value = t('~~ Download complete!');
} catch (error) {
console.error('Error downloading file:', error);
errorMessage.value = 'Failed to download the file.';
waitingForFile.value = false;
}
};
onMounted(() => {
const maxAttempts = props.wait || 20; // 20 seconds by default
let attempts = 0;
const interval = setInterval(async () => {
attempts += 1;
try {
const { data } = await axios.get(`/user_downloads/${props.downloadId}`);
if (data.file) {
clearInterval(interval);
await downloadFile(data.file);
} else if (attempts >= maxAttempts) {
clearInterval(interval);
message.value = t('info.processing_download_d');
waitingForFile.value = false;
}
} catch (error) {
console.error('Error checking file status:', error);
clearInterval(interval);
errorMessage.value = 'An error occurred while checking the file status.';
waitingForFile.value = false;
}
}, 1000);
});
</script>

<template>
<div>
<div v-if="waitingForFile">
<p>{{ $t('~~Waiting for the file to be ready for download...') }}</p>
<spinner />
</div>
<div v-else-if="message">
<p v-html="message"></p>
</div>
<div v-else-if="errorMessage">
<p>{{ errorMessage }}</p>
</div>
<!-- Optionally, you can add more UI elements here -->
</div>
</template>

<style scoped>
/* Add your styles here */
</style>
34 changes: 21 additions & 13 deletions src/pages/Downloads.vue
Original file line number Diff line number Diff line change
@@ -12,17 +12,14 @@
>
<template #file="{ item }">
<div v-if="item.file">
<base-link
:href="item.file.csv_url"
:data-testid="`testDownloads${item.file}Div`"
text-variant="bodysm"
class="px-2"
:download="item.file.filename_original"
>{{ item.file.filename_original }}</base-link
<base-button
:action="() => downloadFile(item.file)"
variant="solid"
class="ml-3"
size="small"
>
</div>
<div v-else>
{{ item.status }}
{{ $t('actions.download') }}
</base-button>
</div>
</template>
</AjaxTable>
@@ -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,
};
},
});
14 changes: 9 additions & 5 deletions src/pages/Work.vue
Original file line number Diff line number Diff line change
@@ -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({
13 changes: 13 additions & 0 deletions src/utils/downloads.ts
Original file line number Diff line number Diff line change
@@ -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);
}