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'
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
const NewDocumentJob = ({ onOk, defaultValues = {} }) => {
|
const NewDocumentJob = ({ onOk, defaultValues = {} }) => {
|
||||||
const { sendObjectAction, downloadTemplatePDF, formatFileName } =
|
const { sendObjectAction, downloadTemplate, formatFileName } =
|
||||||
useContext(ApiServerContext)
|
useContext(ApiServerContext)
|
||||||
const [downloading, setDownloading] = useState(false)
|
const [downloading, setDownloading] = useState(false)
|
||||||
|
|
||||||
@ -92,11 +92,12 @@ const NewDocumentJob = ({ onOk, defaultValues = {} }) => {
|
|||||||
key: 'pdf',
|
key: 'pdf',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
setDownloading(true)
|
setDownloading(true)
|
||||||
downloadTemplatePDF(
|
downloadTemplate(
|
||||||
objectData.documentTemplate._id,
|
objectData.documentTemplate._id,
|
||||||
objectData.documentTemplate.content,
|
objectData.documentTemplate.content,
|
||||||
objectData.object,
|
objectData.object,
|
||||||
fileName,
|
fileName,
|
||||||
|
'pdf',
|
||||||
() => {
|
() => {
|
||||||
setDownloading(false)
|
setDownloading(false)
|
||||||
}
|
}
|
||||||
@ -105,11 +106,54 @@ const NewDocumentJob = ({ onOk, defaultValues = {} }) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'PNG',
|
label: 'PNG',
|
||||||
key: 'png'
|
key: 'png',
|
||||||
|
onClick: () => {
|
||||||
|
setDownloading(true)
|
||||||
|
downloadTemplate(
|
||||||
|
objectData.documentTemplate._id,
|
||||||
|
objectData.documentTemplate.content,
|
||||||
|
objectData.object,
|
||||||
|
fileName,
|
||||||
|
'png',
|
||||||
|
() => {
|
||||||
|
setDownloading(false)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'JPEG',
|
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
|
if (!objectData?.name) return null
|
||||||
|
|
||||||
const textElement = (
|
const textElement = (
|
||||||
<ElipsisText style={{ lineHeight: '1', paddingBottom: '2px' }}>
|
<ElipsisText style={{ lineHeight: '1' }}>{objectData.name}</ElipsisText>
|
||||||
{objectData.name}
|
|
||||||
</ElipsisText>
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// If hyperlink is enabled
|
// 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 (
|
const fetchTemplatePreview = async (
|
||||||
id,
|
id,
|
||||||
content,
|
content,
|
||||||
@ -1758,38 +1782,138 @@ const ApiServerProvider = ({ children }) => {
|
|||||||
callback
|
callback
|
||||||
) => {
|
) => {
|
||||||
logger.debug('Fetching preview...')
|
logger.debug('Fetching preview...')
|
||||||
if (socketRef.current && socketRef.current.connected) {
|
try {
|
||||||
return socketRef.current.emit(
|
const response = await axios.post(
|
||||||
'previewTemplate',
|
`${config.backendUrl}/documenttemplates/${id}/preview`,
|
||||||
{
|
{
|
||||||
_id: id,
|
content,
|
||||||
content: content,
|
testObject,
|
||||||
testObject: testObject,
|
scale
|
||||||
scale: 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) => {
|
const fetchTemplatePDF = async (id, content, testObject, callback) => {
|
||||||
logger.debug('Fetching pdf template...')
|
logger.debug('Fetching pdf template...')
|
||||||
if (socketRef.current && socketRef.current.connected) {
|
try {
|
||||||
return socketRef.current.emit(
|
const result = await fetchTemplateDownload(
|
||||||
'renderTemplatePDF',
|
id,
|
||||||
{
|
content,
|
||||||
_id: id,
|
testObject,
|
||||||
content: content,
|
'pdf'
|
||||||
object: testObject
|
|
||||||
},
|
|
||||||
callback
|
|
||||||
)
|
)
|
||||||
|
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,
|
filename,
|
||||||
callback
|
callback
|
||||||
) => {
|
) => {
|
||||||
logger.debug('Downloading template PDF...')
|
return downloadTemplate(id, content, object, filename, 'pdf', callback)
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchHostOTP = async (id, callback) => {
|
const fetchHostOTP = async (id, callback) => {
|
||||||
@ -2253,6 +2355,7 @@ const ApiServerProvider = ({ children }) => {
|
|||||||
fetchTemplatePreview,
|
fetchTemplatePreview,
|
||||||
fetchTemplatePDF,
|
fetchTemplatePDF,
|
||||||
fetchNotes,
|
fetchNotes,
|
||||||
|
downloadTemplate,
|
||||||
downloadTemplatePDF,
|
downloadTemplatePDF,
|
||||||
fetchHostOTP,
|
fetchHostOTP,
|
||||||
sendObjectAction,
|
sendObjectAction,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user