Files
speckle-server/packages/frontend-2/components/singleton/FileUploadErrorDialog.vue
T
Kristaps Fabians Geikins 47b9e9c5bc fix(fe2): various performance fixes (#5278)
* fix(fe2): buggy merge policies causing cache read failures

* improved CWV reporting

* improved preview lcp

* more eager load improvements

* more eager load improvements

* SSR friendly relative time

* import fixes
2025-08-21 07:50:57 +03:00

126 lines
3.6 KiB
Vue

<template>
<LayoutDialog v-model:open="open" :title="title" :buttons="buttons">
<p class="text-foreground-2 my-2">
The following file upload{{ failedJobs.length > 1 ? 's' : '' }} failed. You can
retry {{ failedJobs.length > 1 ? 'them' : 'it' }} by re-uploading the file{{
failedJobs.length > 1 ? 's' : ''
}}.
</p>
<LayoutTable
:items="failedJobs"
:columns="[
{ id: 'file', header: 'File', classes: 'col-span-4' },
{ id: 'error', header: 'Error', classes: 'col-span-5' },
{ id: 'date', header: 'Date', classes: 'col-span-2' },
{
id: 'actions',
header: '',
classes: 'col-span-1 flex items-center justify-end'
}
]"
class="text-foreground"
style="max-height: 300px"
>
<template #file="{ item }">
<div
v-tippy="{
content: item.fileName.length > 35 ? item.fileName : undefined,
placement: 'top-start',
delay: 300
}"
class="truncate text-foreground"
>
{{ item.fileName }}
</div>
</template>
<template #error="{ item }">
<span class="text-foreground">{{ getErrorMessage(item) + ' ' }}</span>
<ErrorReference
v-if="shouldShowErrorReference(item)"
class="text-left inline"
size="text-body-xs"
@click="copyErrorReference(item)"
/>
</template>
<template #date="{ item }">
<span v-tippy="formattedFullDate(item.date)" class="text-foreground-2">
{{ formattedRelativeDate(item.date) }}
</span>
</template>
<template #actions="{ item }">
<FormButton
v-tippy="'Go to project'"
:icon-left="ArrowRightIcon"
hide-text
size="sm"
color="outline"
@click="goToProject(item)"
/>
</template>
</LayoutTable>
</LayoutDialog>
</template>
<script setup lang="ts">
import { ArrowRightIcon } from '@heroicons/vue/24/outline'
import type { LayoutDialogButton } from '@speckle/ui-components'
import { omit } from 'lodash-es'
import { useNavigateToProject } from '~/lib/common/helpers/route'
import { useGenerateErrorReference } from '~/lib/core/composables/error'
import {
useGlobalFileImportManager,
type FailedFileImportJob,
FailedFileImportJobError,
useFailedFileImportJobUtils
} from '~/lib/core/composables/fileImport'
const { clearFailedJobs, failedJobs } = useGlobalFileImportManager()
const { getErrorMessage } = useFailedFileImportJobUtils()
const { copyReference } = useGenerateErrorReference()
const navigateToProject = useNavigateToProject()
const { formattedRelativeDate, formattedFullDate } = useDateFormatters()
const open = computed({
get: () => failedJobs.value.length > 0,
set: (value) => {
if (!value) {
clearFailedJobs()
}
}
})
const title = computed(
() => `File upload${failedJobs.value.length > 1 ? 's' : ''} failed`
)
const buttons = computed((): LayoutDialogButton[] => [
{
text: 'Dismiss',
onClick: () => {
open.value = false
}
}
])
const shouldShowErrorReference = (job: FailedFileImportJob) => {
return (
job.error.type === FailedFileImportJobError.UploadFailed ||
job.error.type === FailedFileImportJobError.ImportFailed
)
}
const copyErrorReference = async (job: FailedFileImportJob) => {
await copyReference({ date: job.date, extraPayload: omit(job, ['file']) })
}
const goToProject = async (job: FailedFileImportJob) => {
void navigateToProject({ id: job.projectId })
open.value = false
}
watch(failedJobs, (newJobs) => {
if (newJobs.length > 0) {
open.value = true
}
})
</script>