Refactor document job download functionality and enhance error handling
- Updated the download functionality in NewDocumentJob to use a unified downloadTemplate method, supporting multiple file formats (PDF, PNG, JPEG, SVG). - Improved error handling in ApiServerContext by adding getTemplateErrorFromResponse and triggerFileDownload functions for better response management. - Refactored fetchTemplatePDF to utilize fetchTemplateDownload for streamlined code and improved maintainability. - Cleaned up ObjectDisplay component by removing unnecessary line breaks for better readability.
This commit is contained in:
parent
b121179322
commit
3b69be7584
@ -8,7 +8,7 @@ import { useContext, useRef, useState } from 'react'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const NewDocumentJob = ({ onOk, defaultValues = {} }) => {
|
||||
const { sendObjectAction, downloadTemplatePDF, formatFileName } =
|
||||
const { sendObjectAction, downloadTemplate, formatFileName } =
|
||||
useContext(ApiServerContext)
|
||||
const [downloading, setDownloading] = useState(false)
|
||||
|
||||
@ -92,11 +92,12 @@ const NewDocumentJob = ({ onOk, defaultValues = {} }) => {
|
||||
key: 'pdf',
|
||||
onClick: () => {
|
||||
setDownloading(true)
|
||||
downloadTemplatePDF(
|
||||
downloadTemplate(
|
||||
objectData.documentTemplate._id,
|
||||
objectData.documentTemplate.content,
|
||||
objectData.object,
|
||||
fileName,
|
||||
'pdf',
|
||||
() => {
|
||||
setDownloading(false)
|
||||
}
|
||||
@ -105,11 +106,54 @@ const NewDocumentJob = ({ onOk, defaultValues = {} }) => {
|
||||
},
|
||||
{
|
||||
label: 'PNG',
|
||||
key: 'png'
|
||||
key: 'png',
|
||||
onClick: () => {
|
||||
setDownloading(true)
|
||||
downloadTemplate(
|
||||
objectData.documentTemplate._id,
|
||||
objectData.documentTemplate.content,
|
||||
objectData.object,
|
||||
fileName,
|
||||
'png',
|
||||
() => {
|
||||
setDownloading(false)
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'JPEG',
|
||||
key: 'jpeg'
|
||||
key: 'jpeg',
|
||||
onClick: () => {
|
||||
setDownloading(true)
|
||||
downloadTemplate(
|
||||
objectData.documentTemplate._id,
|
||||
objectData.documentTemplate.content,
|
||||
objectData.object,
|
||||
fileName,
|
||||
'jpeg',
|
||||
() => {
|
||||
setDownloading(false)
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'SVG',
|
||||
key: 'svg',
|
||||
onClick: () => {
|
||||
setDownloading(true)
|
||||
downloadTemplate(
|
||||
objectData.documentTemplate._id,
|
||||
objectData.documentTemplate.content,
|
||||
objectData.object,
|
||||
fileName,
|
||||
'svg',
|
||||
() => {
|
||||
setDownloading(false)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -192,9 +192,7 @@ const ObjectDisplay = ({
|
||||
if (!objectData?.name) return null
|
||||
|
||||
const textElement = (
|
||||
<ElipsisText style={{ lineHeight: '1', paddingBottom: '2px' }}>
|
||||
{objectData.name}
|
||||
</ElipsisText>
|
||||
<ElipsisText style={{ lineHeight: '1' }}>{objectData.name}</ElipsisText>
|
||||
)
|
||||
|
||||
// If hyperlink is enabled
|
||||
|
||||
@ -1750,6 +1750,30 @@ const ApiServerProvider = ({ children }) => {
|
||||
}
|
||||
}
|
||||
|
||||
const getTemplateErrorFromResponse = (err) => {
|
||||
const data = err?.response?.data
|
||||
if (data instanceof ArrayBuffer) {
|
||||
try {
|
||||
const parsed = JSON.parse(new TextDecoder().decode(data))
|
||||
return parsed?.error || err.message
|
||||
} catch {
|
||||
return err.message
|
||||
}
|
||||
}
|
||||
return data?.error || err.message
|
||||
}
|
||||
|
||||
const triggerFileDownload = (blob, filename) => {
|
||||
const fileUrl = URL.createObjectURL(blob)
|
||||
const fileLink = document.createElement('a')
|
||||
fileLink.href = fileUrl
|
||||
fileLink.setAttribute('download', filename)
|
||||
document.body.appendChild(fileLink)
|
||||
fileLink.click()
|
||||
fileLink.parentNode.removeChild(fileLink)
|
||||
URL.revokeObjectURL(fileUrl)
|
||||
}
|
||||
|
||||
const fetchTemplatePreview = async (
|
||||
id,
|
||||
content,
|
||||
@ -1758,38 +1782,138 @@ const ApiServerProvider = ({ children }) => {
|
||||
callback
|
||||
) => {
|
||||
logger.debug('Fetching preview...')
|
||||
if (socketRef.current && socketRef.current.connected) {
|
||||
return socketRef.current.emit(
|
||||
'previewTemplate',
|
||||
try {
|
||||
const response = await axios.post(
|
||||
`${config.backendUrl}/documenttemplates/${id}/preview`,
|
||||
{
|
||||
_id: id,
|
||||
content: content,
|
||||
testObject: testObject,
|
||||
scale: scale
|
||||
content,
|
||||
testObject,
|
||||
scale
|
||||
},
|
||||
callback
|
||||
{
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
if (typeof callback === 'function') {
|
||||
callback(response.data)
|
||||
}
|
||||
return response.data
|
||||
} catch (err) {
|
||||
const error = getTemplateErrorFromResponse(err)
|
||||
logger.error('Error fetching template preview:', error)
|
||||
if (typeof callback === 'function') {
|
||||
callback({ error })
|
||||
}
|
||||
return { error }
|
||||
}
|
||||
if (typeof callback === 'function') {
|
||||
callback({ error: 'Api Server disconnected' })
|
||||
}
|
||||
|
||||
const fetchTemplateDownload = async (id, content, object, type = 'pdf') => {
|
||||
logger.debug(`Fetching template download as ${type}...`)
|
||||
const response = await axios.post(
|
||||
`${config.backendUrl}/documenttemplates/${id}/download`,
|
||||
{
|
||||
content,
|
||||
object
|
||||
},
|
||||
{
|
||||
params: { type },
|
||||
responseType: 'arraybuffer',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
)
|
||||
const contentType = response.headers['content-type'] || ''
|
||||
if (contentType.includes('application/json')) {
|
||||
return JSON.parse(new TextDecoder().decode(response.data))
|
||||
}
|
||||
return {
|
||||
type,
|
||||
mime: contentType,
|
||||
buffer: response.data
|
||||
}
|
||||
}
|
||||
|
||||
const fetchTemplatePDF = async (id, content, testObject, callback) => {
|
||||
logger.debug('Fetching pdf template...')
|
||||
if (socketRef.current && socketRef.current.connected) {
|
||||
return socketRef.current.emit(
|
||||
'renderTemplatePDF',
|
||||
{
|
||||
_id: id,
|
||||
content: content,
|
||||
object: testObject
|
||||
},
|
||||
callback
|
||||
try {
|
||||
const result = await fetchTemplateDownload(
|
||||
id,
|
||||
content,
|
||||
testObject,
|
||||
'pdf'
|
||||
)
|
||||
const payload = result.error
|
||||
? result
|
||||
: { pdf: result.buffer || result }
|
||||
if (typeof callback === 'function') {
|
||||
callback(payload)
|
||||
}
|
||||
return payload
|
||||
} catch (err) {
|
||||
const error = getTemplateErrorFromResponse(err)
|
||||
logger.error('Error fetching template PDF:', error)
|
||||
if (typeof callback === 'function') {
|
||||
callback({ error })
|
||||
}
|
||||
return { error }
|
||||
}
|
||||
if (typeof callback === 'function') {
|
||||
callback({ error: 'Api Server disconnected' })
|
||||
}
|
||||
|
||||
const downloadTemplate = async (
|
||||
id,
|
||||
content,
|
||||
object,
|
||||
filename,
|
||||
type = 'pdf',
|
||||
callback
|
||||
) => {
|
||||
logger.debug(`Downloading template as ${type}...`)
|
||||
try {
|
||||
const result = await fetchTemplateDownload(id, content, object, type)
|
||||
if (result?.error) {
|
||||
if (callback) {
|
||||
callback(result.error)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
if (Array.isArray(result.images)) {
|
||||
result.images.forEach((image, index) => {
|
||||
const binary = atob(image)
|
||||
const bytes = new Uint8Array(binary.length)
|
||||
for (let i = 0; i < binary.length; i += 1) {
|
||||
bytes[i] = binary.charCodeAt(i)
|
||||
}
|
||||
const blob = new Blob([bytes], { type: result.mime })
|
||||
const suffix = result.images.length > 1 ? `-${index + 1}` : ''
|
||||
triggerFileDownload(
|
||||
blob,
|
||||
`${filename}${suffix}.${result.extension || type}`
|
||||
)
|
||||
})
|
||||
} else {
|
||||
const blob = new Blob([result.buffer], {
|
||||
type: result.mime || 'application/octet-stream'
|
||||
})
|
||||
const extension = type === 'jpeg' ? 'jpeg' : type
|
||||
triggerFileDownload(blob, `${filename}.${extension}`)
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback()
|
||||
}
|
||||
} catch (err) {
|
||||
const error = getTemplateErrorFromResponse(err)
|
||||
logger.error('Error downloading template:', error)
|
||||
if (callback) {
|
||||
callback(error)
|
||||
}
|
||||
return { error }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1800,29 +1924,7 @@ const ApiServerProvider = ({ children }) => {
|
||||
filename,
|
||||
callback
|
||||
) => {
|
||||
logger.debug('Downloading template PDF...')
|
||||
|
||||
fetchTemplatePDF(id, content, object, (result) => {
|
||||
logger.debug('Downloading template PDF result:', result)
|
||||
if (result?.error) {
|
||||
console.error(result.error)
|
||||
if (callback) {
|
||||
callback(result.error)
|
||||
}
|
||||
} else {
|
||||
const pdfBlob = new Blob([result.pdf], { type: 'application/pdf' })
|
||||
const pdfUrl = URL.createObjectURL(pdfBlob)
|
||||
const fileLink = document.createElement('a')
|
||||
fileLink.href = pdfUrl
|
||||
fileLink.setAttribute('download', `${filename}.pdf`)
|
||||
document.body.appendChild(fileLink)
|
||||
fileLink.click()
|
||||
fileLink.parentNode.removeChild(fileLink)
|
||||
if (callback) {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
})
|
||||
return downloadTemplate(id, content, object, filename, 'pdf', callback)
|
||||
}
|
||||
|
||||
const fetchHostOTP = async (id, callback) => {
|
||||
@ -2253,6 +2355,7 @@ const ApiServerProvider = ({ children }) => {
|
||||
fetchTemplatePreview,
|
||||
fetchTemplatePDF,
|
||||
fetchNotes,
|
||||
downloadTemplate,
|
||||
downloadTemplatePDF,
|
||||
fetchHostOTP,
|
||||
sendObjectAction,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user