feat(plugin-import-export): show delayed toast when export download takes time (#13126)
### What? Added a delayed toast message to indicate when an export is being processed, and disabled the download button unless the export form has been modified. ### Why? Previously, there was no feedback during longer export operations, which could confuse users if the request took time to complete. Also, the download button was always enabled, even when the form had not been modified — which could lead to unnecessary exports. ### How? - Introduced a 200ms delay before showing a "Your export is being processed..." toast - Automatically dismisses the toast once the download completes or fails - Hooked into `useFormModified` to: - Track whether the export form has been changed - Disable the download button when the form is unmodified - Reset the modified state after triggering a download
This commit is contained in:
@@ -1,6 +1,15 @@
|
||||
'use client'
|
||||
|
||||
import { Button, SaveButton, Translation, useConfig, useForm, useTranslation } from '@payloadcms/ui'
|
||||
import {
|
||||
Button,
|
||||
SaveButton,
|
||||
toast,
|
||||
Translation,
|
||||
useConfig,
|
||||
useForm,
|
||||
useFormModified,
|
||||
useTranslation,
|
||||
} from '@payloadcms/ui'
|
||||
import React from 'react'
|
||||
|
||||
import type {
|
||||
@@ -17,13 +26,24 @@ export const ExportSaveButton: React.FC = () => {
|
||||
},
|
||||
} = useConfig()
|
||||
|
||||
const { getData } = useForm()
|
||||
const { getData, setModified } = useForm()
|
||||
const modified = useFormModified()
|
||||
|
||||
const label = t('general:save')
|
||||
|
||||
const handleDownload = async () => {
|
||||
let timeoutID: null | ReturnType<typeof setTimeout> = null
|
||||
let toastID: null | number | string = null
|
||||
|
||||
try {
|
||||
setModified(false) // Reset modified state
|
||||
const data = getData()
|
||||
|
||||
// Set a timeout to show toast if the request takes longer than 200ms
|
||||
timeoutID = setTimeout(() => {
|
||||
toastID = toast.success('Your export is being processed...')
|
||||
}, 200)
|
||||
|
||||
const response = await fetch(`${serverURL}${api}/exports/download`, {
|
||||
body: JSON.stringify({
|
||||
data,
|
||||
@@ -35,6 +55,16 @@ export const ExportSaveButton: React.FC = () => {
|
||||
method: 'POST',
|
||||
})
|
||||
|
||||
// Clear the timeout if fetch completes quickly
|
||||
if (timeoutID) {
|
||||
clearTimeout(timeoutID)
|
||||
}
|
||||
|
||||
// Dismiss the toast if it was shown
|
||||
if (toastID) {
|
||||
toast.dismiss(toastID)
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to download file')
|
||||
}
|
||||
@@ -63,13 +93,14 @@ export const ExportSaveButton: React.FC = () => {
|
||||
URL.revokeObjectURL(url)
|
||||
} catch (error) {
|
||||
console.error('Error downloading file:', error)
|
||||
toast.error('Error downloading file')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<SaveButton label={label}></SaveButton>
|
||||
<Button onClick={handleDownload} size="medium" type="button">
|
||||
<Button disabled={!modified} onClick={handleDownload} size="medium" type="button">
|
||||
<Translation i18nKey="upload:download" t={t} />
|
||||
</Button>
|
||||
</React.Fragment>
|
||||
|
||||
Reference in New Issue
Block a user