Client - a user can request and download data export archive

This commit is contained in:
Sam
2023-03-01 21:16:25 +01:00
parent 073c677b92
commit 67d7fc13b5
16 changed files with 207 additions and 7 deletions

View File

@ -62,13 +62,39 @@
<button class="danger" @click.prevent="updateDisplayModal(true)">
{{ $t('buttons.DELETE_MY_ACCOUNT') }}
</button>
<button class="confirm" v-if="canRequestExport()" @click.prevent="requestExport">
{{ $t('buttons.REQUEST_DATA_EXPORT') }}
</button>
</div>
</form>
<div class="data-export">
<span class="info-box">
<i class="fa fa-info-circle" aria-hidden="true" />
{{ $t('user.EXPORT_REQUEST.ONLY_ONE_EXPORT_PER_DAY') }}
</span>
<div v-if="exportRequest" class="data-export-archive">
{{$t('user.EXPORT_REQUEST.DATA_EXPORT')}}
({{ exportRequestDate }}):
<span
v-if="exportRequest.status=== 'successful'"
class="archive-link"
@click.prevent="downloadArchive(exportRequest.file_name)"
>
<i class="fa fa-download" aria-hidden="true" />
{{ $t("user.EXPORT_REQUEST.DOWNLOAD_ARCHIVE") }}
({{ getReadableFileSize(exportRequest.file_size) }})
</span>
<span v-else>
{{ $t(`user.EXPORT_REQUEST.STATUS.${exportRequest.status}`)}}
</span>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { isBefore, subDays } from 'date-fns'
import {
ComputedRef,
Ref,
@ -81,14 +107,17 @@
onUnmounted,
} from 'vue'
import authApi from "@/api/authApi";
import PasswordInput from '@/components/Common/PasswordInput.vue'
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
import { TAppConfig } from '@/types/application'
import { IUserProfile, IUserAccountPayload } from '@/types/user'
import {IAuthUserProfile, IUserAccountPayload, IExportRequest} from '@/types/user'
import { useStore } from '@/use/useStore'
import { formatDate } from '@/utils/dates'
import { getReadableFileSize } from '@/utils/files'
interface Props {
user: IUserProfile
user: IAuthUserProfile
}
const props = defineProps<Props>()
const { user } = toRefs(props)
@ -114,9 +143,16 @@
)
const formErrors = ref(false)
const displayModal: Ref<boolean> = ref(false)
const exportRequest: ComputedRef<IExportRequest | null> = computed(
() => store.getters[AUTH_USER_STORE.GETTERS.EXPORT_REQUEST]
)
const exportRequestDate: ComputedRef<string | null> = computed(
() => getExportRequestDate()
)
onMounted(() => {
if (props.user) {
store.dispatch(AUTH_USER_STORE.ACTIONS.GET_REQUEST_DATA_EXPORT)
updateUserForm(props.user)
}
})
@ -124,7 +160,7 @@
function invalidateForm() {
formErrors.value = true
}
function updateUserForm(user: IUserProfile) {
function updateUserForm(user: IAuthUserProfile) {
userForm.email = user.email
}
function updatePassword(password: string) {
@ -133,6 +169,21 @@
function updateNewPassword(new_password: string) {
userForm.new_password = new_password
}
function getExportRequestDate() {
return exportRequest.value ? formatDate(
exportRequest.value.created_at,
user.value.timezone,
user.value.date_format,
true,
null, true
) : null
}
function canRequestExport() {
return exportRequestDate.value
? isBefore(new Date(exportRequestDate.value), subDays(new Date(), 1))
: true
}
function updateProfile() {
const payload: IUserAccountPayload = {
email: userForm.email,
@ -150,6 +201,25 @@
function deleteAccount(username: string) {
store.dispatch(AUTH_USER_STORE.ACTIONS.DELETE_ACCOUNT, { username })
}
function requestExport() {
store.dispatch(AUTH_USER_STORE.ACTIONS.REQUEST_DATA_EXPORT)
}
async function downloadArchive(filename: string) {
await authApi
.get(`/auth/profile/export/${filename}`, {
responseType: 'blob',
})
.then((response) => {
const archiveFileUrl = window.URL.createObjectURL(
new Blob([response.data], { type: 'application/zip' })
)
const archive_link = document.createElement('a')
archive_link.href = archiveFileUrl
archive_link.setAttribute('download', filename)
document.body.appendChild(archive_link)
archive_link.click()
})
}
onUnmounted(() => {
store.commit(AUTH_USER_STORE.MUTATIONS.UPDATE_IS_SUCCESS, false)
@ -203,4 +273,17 @@
flex-direction: column;
}
}
.data-export {
padding: $default-padding 0;
.data-export-archive {
padding-top: $default-padding*2;
font-size: .9em;
.archive-link {
color: var(--app-a-color);
cursor: pointer;
}
}
}
</style>