Refactor TemplateEditor and TemplatePreview components for improved performance and error handling
Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
- Updated TemplateEditor to use useCallback for handlePreviewMessage, optimizing performance. - Enhanced TemplatePreview by adding default no-op functions for onTestObjectOpen and onPreviewMessage props. - Improved error handling in fetchTemplatePDF and fetchTemplatePreview methods to ensure callbacks are only invoked if they are functions. - Refactored preview loading logic to prevent unnecessary calls when template ID is not available.
This commit is contained in:
parent
59d16f80aa
commit
f743f9b892
@ -1,4 +1,4 @@
|
||||
import { useState } from 'react'
|
||||
import { useState, useCallback } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {
|
||||
Flex,
|
||||
@ -31,10 +31,10 @@ const TemplateEditor = ({
|
||||
const [previewError, setPreviewError] = useState(false)
|
||||
//const isMobile = useMediaQuery({ maxWidth: 768 })
|
||||
|
||||
const handlePreviewMessage = (message, isError) => {
|
||||
const handlePreviewMessage = useCallback((message, isError) => {
|
||||
setPreviewMessage(message)
|
||||
setPreviewError(isError)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@ -7,17 +7,20 @@ import InfoCircleIcon from '../../Icons/InfoCircleIcon.jsx'
|
||||
import ObjectProperty from '../common/ObjectProperty.jsx'
|
||||
import { ApiServerContext } from '../context/ApiServerContext.jsx'
|
||||
|
||||
const noop = () => {}
|
||||
|
||||
const TemplatePreview = ({
|
||||
objectData,
|
||||
documentTemplate,
|
||||
loading,
|
||||
isEditing,
|
||||
onTestObjectOpen,
|
||||
onPreviewMessage,
|
||||
onTestObjectOpen = noop,
|
||||
onPreviewMessage = noop,
|
||||
showTestObject = false,
|
||||
showPreviewSwitch = true
|
||||
}) => {
|
||||
const iframeRef = useRef(null)
|
||||
const previewRequestIdRef = useRef(0)
|
||||
const { fetchTemplatePreview, fetchTemplatePDF } =
|
||||
useContext(ApiServerContext)
|
||||
const [previewContentHTML, setPreviewContentHTML] = useState('')
|
||||
@ -46,11 +49,19 @@ const TemplatePreview = ({
|
||||
|
||||
const reloadPreviewPDF = useCallback(
|
||||
(content, testObject = {}) => {
|
||||
const templateId = documentTemplate?._id
|
||||
if (!templateId) {
|
||||
return
|
||||
}
|
||||
|
||||
const requestId = ++previewRequestIdRef.current
|
||||
setReloadLoading(true)
|
||||
fetchTemplatePDF(documentTemplate._id, content, testObject, (result) => {
|
||||
fetchTemplatePDF(templateId, content, testObject, (result) => {
|
||||
if (requestId !== previewRequestIdRef.current) {
|
||||
return
|
||||
}
|
||||
setReloadLoading(false)
|
||||
if (result?.error) {
|
||||
// Handle error through parent component
|
||||
onPreviewMessage(result.error, true)
|
||||
} else {
|
||||
const pdfBlob = new Blob([result.pdf], { type: 'application/pdf' })
|
||||
@ -66,16 +77,24 @@ const TemplatePreview = ({
|
||||
|
||||
const reloadPreview = useCallback(
|
||||
(content, testObject = {}, scale = 1) => {
|
||||
const templateId = documentTemplate?._id
|
||||
if (!templateId) {
|
||||
return
|
||||
}
|
||||
|
||||
const requestId = ++previewRequestIdRef.current
|
||||
setReloadLoading(true)
|
||||
fetchTemplatePreview(
|
||||
documentTemplate._id,
|
||||
templateId,
|
||||
content,
|
||||
testObject,
|
||||
scale,
|
||||
(result) => {
|
||||
if (requestId !== previewRequestIdRef.current) {
|
||||
return
|
||||
}
|
||||
setReloadLoading(false)
|
||||
if (result?.error) {
|
||||
// Handle error through parent component
|
||||
onPreviewMessage(result.error, true)
|
||||
} else {
|
||||
updatePreviewContentHTML(result.html)
|
||||
@ -87,18 +106,30 @@ const TemplatePreview = ({
|
||||
[fetchTemplatePreview, onPreviewMessage, documentTemplate?._id]
|
||||
)
|
||||
|
||||
const templateContent = documentTemplate?.content
|
||||
const templateId = documentTemplate?._id
|
||||
|
||||
// Move useEffect to component level and use state to track objectData changes
|
||||
useEffect(() => {
|
||||
if (documentTemplate?.content) {
|
||||
if (previewType == 'HTML') {
|
||||
reloadPreview(documentTemplate.content, objectData, previewScale)
|
||||
} else {
|
||||
reloadPreviewPDF(documentTemplate.content, objectData)
|
||||
if (!templateId || !templateContent) {
|
||||
return
|
||||
}
|
||||
|
||||
const timeoutId = window.setTimeout(() => {
|
||||
if (previewType == 'HTML') {
|
||||
reloadPreview(templateContent, objectData, previewScale)
|
||||
} else {
|
||||
reloadPreviewPDF(templateContent, objectData)
|
||||
}
|
||||
}, 300)
|
||||
|
||||
return () => {
|
||||
window.clearTimeout(timeoutId)
|
||||
}
|
||||
}, [
|
||||
objectData,
|
||||
documentTemplate,
|
||||
templateContent,
|
||||
templateId,
|
||||
previewScale,
|
||||
previewType,
|
||||
reloadPreview,
|
||||
@ -197,8 +228,8 @@ TemplatePreview.propTypes = {
|
||||
isEditing: PropTypes.bool,
|
||||
style: PropTypes.object,
|
||||
showTestObject: PropTypes.bool,
|
||||
onTestObjectOpen: PropTypes.func.isRequired,
|
||||
onPreviewMessage: PropTypes.func.isRequired,
|
||||
onTestObjectOpen: PropTypes.func,
|
||||
onPreviewMessage: PropTypes.func,
|
||||
showPreviewSwitch: PropTypes.bool
|
||||
}
|
||||
|
||||
|
||||
@ -1691,6 +1691,9 @@ const ApiServerProvider = ({ children }) => {
|
||||
callback
|
||||
)
|
||||
}
|
||||
if (typeof callback === 'function') {
|
||||
callback({ error: 'Api Server disconnected' })
|
||||
}
|
||||
}
|
||||
|
||||
const fetchTemplatePDF = async (id, content, testObject, callback) => {
|
||||
@ -1706,6 +1709,9 @@ const ApiServerProvider = ({ children }) => {
|
||||
callback
|
||||
)
|
||||
}
|
||||
if (typeof callback === 'function') {
|
||||
callback({ error: 'Api Server disconnected' })
|
||||
}
|
||||
}
|
||||
|
||||
const downloadTemplatePDF = async (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user