All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
- Introduced new EmailAccounts and EmailMessages components for managing email accounts and messages. - Implemented ObjectTable for displaying data with filtering and sorting capabilities. - Integrated InfoActionButtons for enhanced user interactions across various management functionalities. - Refactored existing components to replace DocumentPrintButton with InfoActionButtons for consistency in action handling. - Added EmailAccountInfo component for detailed view and management of individual email accounts.
776 lines
22 KiB
JavaScript
776 lines
22 KiB
JavaScript
import {
|
|
useState,
|
|
useContext,
|
|
useEffect,
|
|
useLayoutEffect,
|
|
useRef,
|
|
useCallback
|
|
} from 'react'
|
|
import PropTypes from 'prop-types'
|
|
import { Flex, Button, Input, InputNumber, Select, Card, Popover } from 'antd'
|
|
import PlusIcon from '../../Icons/PlusIcon.jsx'
|
|
import MinusIcon from '../../Icons/MinusIcon.jsx'
|
|
import InfoCircleIcon from '../../Icons/InfoCircleIcon.jsx'
|
|
import PanIcon from '../../Icons/PanIcon.jsx'
|
|
import PanFilledIcon from '../../Icons/PanFilledIcon.jsx'
|
|
import ObjectProperty from '../common/ObjectProperty.jsx'
|
|
import PDFViewer from './PDFViewer.jsx'
|
|
import ScrollBox from './ScrollBox.jsx'
|
|
import { ApiServerContext } from '../context/ApiServerContext.jsx'
|
|
import ProgressDisplay from './ProgressDisplay.jsx'
|
|
import { CaretDownFilled } from '@ant-design/icons'
|
|
const noop = () => {}
|
|
|
|
const TemplatePreview = ({
|
|
objectData,
|
|
documentTemplate,
|
|
content = null,
|
|
template,
|
|
templateType = 'documentTemplate',
|
|
capabilities = {},
|
|
loading,
|
|
isEditing,
|
|
onTestObjectOpen = noop,
|
|
onPreviewMessage = noop,
|
|
showTestObject = false,
|
|
showPreviewSwitch = true
|
|
}) => {
|
|
const currentTemplate = template || documentTemplate
|
|
const htmlOnly = capabilities.htmlOnly === true
|
|
const showWidthControl = capabilities.widthControl === true
|
|
const defaultPreviewWidth = capabilities.defaultWidth || 600
|
|
const iframeRef = useRef(null)
|
|
const scrollElementRef = useRef(null)
|
|
const savedScrollRef = useRef({ top: 0, left: 0 })
|
|
const iframeSizeObserverRef = useRef(null)
|
|
const previewRequestIdRef = useRef(0)
|
|
const renderUnsubscribeRef = useRef(null)
|
|
const {
|
|
fetchTemplatePreview,
|
|
fetchTemplateDownload,
|
|
subscribeToObjectEvent
|
|
} = useContext(ApiServerContext)
|
|
const [previewContentHTML, setPreviewContentHTML] = useState('')
|
|
const [pdfBlob, setPDFBlob] = useState(null)
|
|
const [reloadLoading, setReloadLoading] = useState(false)
|
|
const [downloadProgress, setDownloadProgress] = useState(null)
|
|
const [previewScale, setPreviewScale] = useState(1)
|
|
const [previewType, setPreviewType] = useState('HTML')
|
|
const [previewWidth, setPreviewWidth] = useState(defaultPreviewWidth)
|
|
const [panMode, setPanMode] = useState(false)
|
|
const [isPanning, setIsPanning] = useState(false)
|
|
const panStartRef = useRef({ x: 0, y: 0, scrollLeft: 0, scrollTop: 0 })
|
|
const [iframeSize, setIframeSize] = useState({
|
|
width: '100%',
|
|
height: 'auto'
|
|
})
|
|
|
|
const toolbarRef = useRef(null)
|
|
const [usePopoverSettings, setUsePopoverSettings] = useState(false)
|
|
|
|
useLayoutEffect(() => {
|
|
const toolbar = toolbarRef.current
|
|
if (!toolbar) return undefined
|
|
|
|
const updateLayout = () => {
|
|
const { width, height } = toolbar.getBoundingClientRect()
|
|
console.log('Preview card size', { width, height })
|
|
setUsePopoverSettings(width < 620)
|
|
}
|
|
|
|
updateLayout()
|
|
|
|
const observer = new ResizeObserver(updateLayout)
|
|
observer.observe(toolbar)
|
|
|
|
return () => observer.disconnect()
|
|
}, [])
|
|
|
|
const applyIframeContentSize = useCallback(() => {
|
|
const iframe = iframeRef.current
|
|
const doc = iframe?.contentDocument
|
|
if (!iframe || !doc?.documentElement) {
|
|
return
|
|
}
|
|
|
|
const wrappers = doc.querySelectorAll('.previewWrapper')
|
|
wrappers.forEach((wrapper) => {
|
|
const page = wrapper.querySelector('.previewDocument')
|
|
if (!page) {
|
|
return
|
|
}
|
|
const pageVisual = page.getBoundingClientRect()
|
|
if (pageVisual.width <= 0 && pageVisual.height <= 0) {
|
|
return
|
|
}
|
|
wrapper.style.width = `${pageVisual.width}px`
|
|
wrapper.style.height = `${pageVisual.height}px`
|
|
})
|
|
|
|
const documentEl =
|
|
doc.querySelector('.previewPages') ||
|
|
doc.querySelector('.previewDocument') ||
|
|
doc.querySelector('.previewWrapper') ||
|
|
doc.body
|
|
const container = doc.querySelector('.previewContainer')
|
|
const visual = documentEl.getBoundingClientRect()
|
|
if (visual.width <= 0 && visual.height <= 0) {
|
|
return
|
|
}
|
|
|
|
let padX = 0
|
|
let padY = 0
|
|
if (container) {
|
|
const containerStyle = doc.defaultView.getComputedStyle(container)
|
|
padX =
|
|
parseFloat(containerStyle.paddingLeft) +
|
|
parseFloat(containerStyle.paddingRight)
|
|
padY =
|
|
parseFloat(containerStyle.paddingTop) +
|
|
parseFloat(containerStyle.paddingBottom)
|
|
}
|
|
|
|
const contentWidth = showWidthControl
|
|
? previewWidth
|
|
: Math.ceil(visual.width + padX)
|
|
const contentHeight = Math.ceil(
|
|
Math.max(visual.height + padY, doc.documentElement.scrollHeight)
|
|
)
|
|
|
|
if (!doc.head?.querySelector('style[data-preview-outer-scroll]')) {
|
|
const styleEl = doc.createElement('style')
|
|
styleEl.setAttribute('data-preview-outer-scroll', 'true')
|
|
styleEl.textContent =
|
|
'html, body { overflow: hidden !important; height: auto !important; }'
|
|
doc.head?.appendChild(styleEl)
|
|
}
|
|
|
|
setIframeSize((prev) => {
|
|
const width = `${contentWidth}px`
|
|
const height = `${contentHeight}px`
|
|
if (prev.width === width && prev.height === height) {
|
|
return prev
|
|
}
|
|
return { width, height }
|
|
})
|
|
}, [previewWidth, showWidthControl])
|
|
|
|
const restoreScrollPosition = useCallback(() => {
|
|
const scrollEl = scrollElementRef.current
|
|
if (!scrollEl) {
|
|
return
|
|
}
|
|
scrollEl.scrollTo(savedScrollRef.current.left, savedScrollRef.current.top)
|
|
}, [])
|
|
|
|
const handleIframeLoad = useCallback(() => {
|
|
iframeSizeObserverRef.current?.disconnect()
|
|
iframeSizeObserverRef.current = null
|
|
|
|
if (previewType != 'HTML') {
|
|
return
|
|
}
|
|
|
|
applyIframeContentSize()
|
|
|
|
const doc = iframeRef.current?.contentDocument
|
|
const observed =
|
|
doc?.querySelector('.previewPages') ||
|
|
doc?.querySelector('.previewContainer') ||
|
|
doc?.querySelector('.previewDocument') ||
|
|
doc?.body
|
|
if (observed && typeof ResizeObserver === 'function') {
|
|
const observer = new ResizeObserver(() => {
|
|
applyIframeContentSize()
|
|
})
|
|
observer.observe(observed)
|
|
iframeSizeObserverRef.current = observer
|
|
}
|
|
}, [applyIframeContentSize, previewType])
|
|
|
|
useLayoutEffect(() => {
|
|
restoreScrollPosition()
|
|
}, [iframeSize, restoreScrollPosition])
|
|
|
|
const updatePreviewContentHTML = (html) => {
|
|
const scrollEl = scrollElementRef.current
|
|
if (scrollEl) {
|
|
savedScrollRef.current = {
|
|
top: scrollEl.scrollTop,
|
|
left: scrollEl.scrollLeft
|
|
}
|
|
}
|
|
setPreviewContentHTML(html)
|
|
}
|
|
|
|
const clearIframeContents = useCallback(() => {
|
|
iframeSizeObserverRef.current?.disconnect()
|
|
iframeSizeObserverRef.current = null
|
|
|
|
const iframe = iframeRef.current
|
|
if (iframe) {
|
|
iframe.srcdoc = ''
|
|
}
|
|
|
|
setPreviewContentHTML('')
|
|
setIframeSize({
|
|
width: showWidthControl ? `${previewWidth}px` : '100%',
|
|
height: 'auto'
|
|
})
|
|
}, [previewWidth, showWidthControl])
|
|
|
|
const stopRenderProgressListener = useCallback(() => {
|
|
if (typeof renderUnsubscribeRef.current === 'function') {
|
|
renderUnsubscribeRef.current()
|
|
}
|
|
renderUnsubscribeRef.current = null
|
|
}, [])
|
|
|
|
const applyPdfResult = useCallback(
|
|
(result, requestId) => {
|
|
if (requestId !== previewRequestIdRef.current) {
|
|
return
|
|
}
|
|
setReloadLoading(false)
|
|
setDownloadProgress(null)
|
|
stopRenderProgressListener()
|
|
if (result?.error) {
|
|
onPreviewMessage(result.error, true)
|
|
return
|
|
}
|
|
setPDFBlob(
|
|
new Blob([result.buffer || result.pdf], {
|
|
type: result.mime || 'application/pdf'
|
|
})
|
|
)
|
|
onPreviewMessage('No issues found.', false)
|
|
},
|
|
[onPreviewMessage, stopRenderProgressListener]
|
|
)
|
|
|
|
const reloadPreviewPDF = useCallback(
|
|
(content, testObject = {}) => {
|
|
const templateId = currentTemplate?._id
|
|
if (!templateId) {
|
|
return
|
|
}
|
|
|
|
const requestId = ++previewRequestIdRef.current
|
|
stopRenderProgressListener()
|
|
setPDFBlob(null)
|
|
setReloadLoading(true)
|
|
setDownloadProgress({ progress: 0, message: 'Starting render...' })
|
|
|
|
const startDownload = async () => {
|
|
try {
|
|
const startResult = await fetchTemplateDownload(
|
|
templateId,
|
|
content,
|
|
testObject,
|
|
'pdf',
|
|
{ async: true }
|
|
)
|
|
if (requestId !== previewRequestIdRef.current) {
|
|
return
|
|
}
|
|
if (startResult?.error || !startResult?.renderRequestId) {
|
|
applyPdfResult(startResult, requestId)
|
|
return
|
|
}
|
|
|
|
const renderRequestId = startResult.renderRequestId
|
|
const eventType = `render:${renderRequestId}`
|
|
let fetched = false
|
|
|
|
const fetchRenderedFile = async () => {
|
|
if (fetched) {
|
|
return true
|
|
}
|
|
try {
|
|
const result = await fetchTemplateDownload(
|
|
templateId,
|
|
content,
|
|
testObject,
|
|
'pdf',
|
|
{ renderRequestId }
|
|
)
|
|
fetched = true
|
|
applyPdfResult(result, requestId)
|
|
return true
|
|
} catch (err) {
|
|
if (err?.response?.status === 404) {
|
|
return false
|
|
}
|
|
applyPdfResult(
|
|
{
|
|
error: err?.message || 'Failed to download rendered template.'
|
|
},
|
|
requestId
|
|
)
|
|
return true
|
|
}
|
|
}
|
|
|
|
const unsubscribe = subscribeToObjectEvent(
|
|
renderRequestId,
|
|
'render',
|
|
eventType,
|
|
(event) => {
|
|
if (requestId !== previewRequestIdRef.current) {
|
|
return
|
|
}
|
|
setDownloadProgress({
|
|
progress: Number(event?.progress) || 0,
|
|
message: event?.message || ''
|
|
})
|
|
if (event?.error) {
|
|
applyPdfResult({ error: event.error }, requestId)
|
|
return
|
|
}
|
|
if (Number(event?.progress) >= 1) {
|
|
fetchRenderedFile()
|
|
}
|
|
}
|
|
)
|
|
|
|
const pollId = window.setInterval(async () => {
|
|
if (requestId !== previewRequestIdRef.current) {
|
|
window.clearInterval(pollId)
|
|
return
|
|
}
|
|
const didFetch = await fetchRenderedFile()
|
|
if (didFetch) {
|
|
window.clearInterval(pollId)
|
|
}
|
|
}, 1000)
|
|
|
|
renderUnsubscribeRef.current = () => {
|
|
window.clearInterval(pollId)
|
|
if (typeof unsubscribe === 'function') {
|
|
unsubscribe()
|
|
}
|
|
}
|
|
} catch (err) {
|
|
applyPdfResult(
|
|
{ error: err?.message || 'Failed to start template download.' },
|
|
requestId
|
|
)
|
|
}
|
|
}
|
|
|
|
startDownload()
|
|
},
|
|
[
|
|
applyPdfResult,
|
|
currentTemplate?._id,
|
|
fetchTemplateDownload,
|
|
stopRenderProgressListener,
|
|
subscribeToObjectEvent
|
|
]
|
|
)
|
|
|
|
const reloadPreview = useCallback(
|
|
(content, testObject = {}, scale = 1) => {
|
|
const templateId = currentTemplate?._id
|
|
if (!templateId) {
|
|
return
|
|
}
|
|
|
|
const requestId = ++previewRequestIdRef.current
|
|
setReloadLoading(true)
|
|
fetchTemplatePreview(
|
|
templateId,
|
|
content,
|
|
testObject,
|
|
scale,
|
|
(result) => {
|
|
if (requestId !== previewRequestIdRef.current) {
|
|
return
|
|
}
|
|
setReloadLoading(false)
|
|
if (result?.error) {
|
|
onPreviewMessage(result.error, true)
|
|
} else {
|
|
updatePreviewContentHTML(result.html)
|
|
onPreviewMessage('No issues found.', false)
|
|
}
|
|
},
|
|
templateType,
|
|
showWidthControl ? { width: previewWidth } : {}
|
|
)
|
|
},
|
|
[
|
|
currentTemplate?._id,
|
|
fetchTemplatePreview,
|
|
onPreviewMessage,
|
|
previewWidth,
|
|
showWidthControl,
|
|
templateType
|
|
]
|
|
)
|
|
|
|
const templateContent = currentTemplate?.content
|
|
const templateId = currentTemplate?._id
|
|
|
|
useEffect(() => {
|
|
if (content != null) {
|
|
updatePreviewContentHTML(content)
|
|
return
|
|
}
|
|
|
|
if (!templateId || !templateContent || previewType != 'HTML') {
|
|
return
|
|
}
|
|
|
|
const timeoutId = window.setTimeout(() => {
|
|
if (content == null) {
|
|
reloadPreview(templateContent, objectData, previewScale)
|
|
}
|
|
}, 300)
|
|
|
|
return () => {
|
|
window.clearTimeout(timeoutId)
|
|
}
|
|
}, [
|
|
objectData,
|
|
templateContent,
|
|
templateId,
|
|
previewScale,
|
|
previewWidth,
|
|
previewType,
|
|
reloadPreview,
|
|
content
|
|
])
|
|
|
|
useEffect(() => {
|
|
if (!templateId || !templateContent || previewType != 'PDF') {
|
|
return
|
|
}
|
|
|
|
setPDFBlob(null)
|
|
|
|
const timeoutId = window.setTimeout(() => {
|
|
reloadPreviewPDF(templateContent, objectData)
|
|
}, 300)
|
|
|
|
return () => {
|
|
window.clearTimeout(timeoutId)
|
|
}
|
|
}, [objectData, templateContent, templateId, previewType, reloadPreviewPDF])
|
|
|
|
useEffect(() => {
|
|
return () => {
|
|
iframeSizeObserverRef.current?.disconnect()
|
|
stopRenderProgressListener()
|
|
}
|
|
}, [stopRenderProgressListener])
|
|
|
|
useEffect(() => {
|
|
if (!panMode) {
|
|
setIsPanning(false)
|
|
}
|
|
}, [panMode])
|
|
|
|
useEffect(() => {
|
|
const scrollEl = scrollElementRef.current
|
|
if (!panMode || !scrollEl || previewType != 'HTML') {
|
|
return
|
|
}
|
|
|
|
const handlePointerDown = (event) => {
|
|
if (event.pointerType === 'mouse' && event.button !== 0) {
|
|
return
|
|
}
|
|
event.preventDefault()
|
|
panStartRef.current = {
|
|
x: event.clientX,
|
|
y: event.clientY,
|
|
scrollLeft: scrollEl.scrollLeft,
|
|
scrollTop: scrollEl.scrollTop
|
|
}
|
|
setIsPanning(true)
|
|
}
|
|
|
|
scrollEl.addEventListener('pointerdown', handlePointerDown)
|
|
return () => {
|
|
scrollEl.removeEventListener('pointerdown', handlePointerDown)
|
|
}
|
|
}, [panMode, previewType])
|
|
|
|
useEffect(() => {
|
|
if (!isPanning) {
|
|
return
|
|
}
|
|
|
|
const previousCursor = document.body.style.cursor
|
|
const previousUserSelect = document.body.style.userSelect
|
|
document.body.style.cursor = 'grabbing'
|
|
document.body.style.userSelect = 'none'
|
|
|
|
const handlePointerMove = (event) => {
|
|
const scrollEl = scrollElementRef.current
|
|
if (!scrollEl) {
|
|
return
|
|
}
|
|
const { x, y, scrollLeft, scrollTop } = panStartRef.current
|
|
scrollEl.scrollLeft = scrollLeft - (event.clientX - x)
|
|
scrollEl.scrollTop = scrollTop - (event.clientY - y)
|
|
}
|
|
|
|
const handlePointerUp = () => {
|
|
setIsPanning(false)
|
|
}
|
|
|
|
window.addEventListener('pointermove', handlePointerMove)
|
|
window.addEventListener('pointerup', handlePointerUp)
|
|
window.addEventListener('pointercancel', handlePointerUp)
|
|
return () => {
|
|
document.body.style.cursor = previousCursor
|
|
document.body.style.userSelect = previousUserSelect
|
|
window.removeEventListener('pointermove', handlePointerMove)
|
|
window.removeEventListener('pointerup', handlePointerUp)
|
|
window.removeEventListener('pointercancel', handlePointerUp)
|
|
}
|
|
}, [isPanning])
|
|
|
|
const showProgressOverlay = previewType != 'HTML' && downloadProgress != null
|
|
|
|
const toolbarContent = (
|
|
<>
|
|
<Button
|
|
icon={
|
|
panMode ? (
|
|
<PanFilledIcon style={{ color: 'var(--color-primary)' }} />
|
|
) : (
|
|
<PanIcon />
|
|
)
|
|
}
|
|
disabled={loading || reloadLoading}
|
|
onClick={() => {
|
|
setPanMode((prev) => !prev)
|
|
}}
|
|
/>
|
|
<Button
|
|
icon={<PlusIcon />}
|
|
onClick={() => {
|
|
setPreviewScale((prev) => prev + 0.05)
|
|
}}
|
|
disabled={loading || reloadLoading}
|
|
/>
|
|
<Button
|
|
readOnly={true}
|
|
style={{ width: '65px' }}
|
|
disabled={loading || reloadLoading}
|
|
onClick={() => {
|
|
setPreviewScale(1)
|
|
}}
|
|
>
|
|
{previewScale.toFixed(2)}x
|
|
</Button>
|
|
<Button
|
|
icon={<MinusIcon />}
|
|
onClick={() => {
|
|
setPreviewScale((prev) => Math.max(0.1, prev - 0.05))
|
|
}}
|
|
disabled={loading || reloadLoading}
|
|
/>
|
|
{showWidthControl ? (
|
|
<InputNumber
|
|
min={240}
|
|
max={1600}
|
|
step={10}
|
|
addonAfter='px'
|
|
value={previewWidth}
|
|
disabled={loading || reloadLoading}
|
|
onChange={(value) => setPreviewWidth(value || defaultPreviewWidth)}
|
|
style={{ width: 130 }}
|
|
aria-label='Email preview width'
|
|
/>
|
|
) : null}
|
|
{showPreviewSwitch == true && !htmlOnly ? (
|
|
<Select
|
|
options={[
|
|
{ value: 'HTML', label: 'HTML' },
|
|
{ value: 'PDF', label: 'PDF' }
|
|
]}
|
|
style
|
|
loading={(loading || reloadLoading) && !usePopoverSettings}
|
|
disabled={loading || reloadLoading}
|
|
value={previewType}
|
|
onChange={(value) => {
|
|
if (value == 'PDF') {
|
|
clearIframeContents()
|
|
setPDFBlob(null)
|
|
}
|
|
setPreviewType(value)
|
|
}}
|
|
/>
|
|
) : null}
|
|
</>
|
|
)
|
|
|
|
return (
|
|
<Flex vertical gap={'middle'} style={{ height: '100%' }}>
|
|
<Flex gap={'small'} ref={toolbarRef}>
|
|
{showTestObject == true ? (
|
|
<>
|
|
{currentTemplate?.objectType ? (
|
|
<ObjectProperty
|
|
objectType={currentTemplate?.objectType}
|
|
name={'testObject'}
|
|
isEditing={true}
|
|
objectData={currentTemplate}
|
|
disabled={!isEditing || currentTemplate?.global}
|
|
type={'object'}
|
|
style={{ minWidth: 0 }}
|
|
/>
|
|
) : (
|
|
<div style={{ flexGrow: 1 }}>
|
|
<Input disabled={true} />
|
|
</div>
|
|
)}
|
|
<Button
|
|
icon={<InfoCircleIcon />}
|
|
disabled={currentTemplate?.global}
|
|
onClick={() => {
|
|
onTestObjectOpen()
|
|
}}
|
|
/>
|
|
</>
|
|
) : null}
|
|
{!usePopoverSettings ? (
|
|
toolbarContent
|
|
) : (
|
|
<Popover
|
|
content={<Flex gap={'small'}>{toolbarContent}</Flex>}
|
|
trigger={['hover', 'click']}
|
|
placement='bottomRight'
|
|
arrow={false}
|
|
>
|
|
<Button
|
|
icon={<CaretDownFilled />}
|
|
loading={loading || reloadLoading}
|
|
/>
|
|
</Popover>
|
|
)}
|
|
</Flex>
|
|
|
|
<div
|
|
style={{
|
|
flex: '1 1 auto',
|
|
minHeight: 0,
|
|
border: '1px solid #85858541',
|
|
position: 'relative'
|
|
}}
|
|
>
|
|
<div
|
|
className={`previewProgressOverlay ${showProgressOverlay ? 'visible' : 'hidden'}`}
|
|
>
|
|
{showProgressOverlay ? (
|
|
<Flex
|
|
style={{ width: '100%', height: '100%' }}
|
|
align='center'
|
|
justify='center'
|
|
>
|
|
<Card
|
|
style={{
|
|
maxWidth: 360,
|
|
minWidth: 100,
|
|
width: '100%',
|
|
margin: 24
|
|
}}
|
|
styles={{ body: { padding: 18 } }}
|
|
>
|
|
<ProgressDisplay
|
|
percent={Math.round(
|
|
(Number(downloadProgress.progress) || 0) * 100
|
|
)}
|
|
status='active'
|
|
>
|
|
{downloadProgress.message || 'Rendering...'}
|
|
</ProgressDisplay>
|
|
</Card>
|
|
</Flex>
|
|
) : null}
|
|
</div>
|
|
|
|
{previewType == 'HTML' ? (
|
|
<ScrollBox
|
|
scrollableNodeProps={{ ref: scrollElementRef }}
|
|
style={{
|
|
cursor: panMode ? (isPanning ? 'grabbing' : 'grab') : undefined,
|
|
touchAction: panMode ? 'none' : undefined
|
|
}}
|
|
>
|
|
<Flex
|
|
justify='center'
|
|
align='center'
|
|
style={{
|
|
minWidth: '100%',
|
|
width: iframeSize.width,
|
|
height: iframeSize.height
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
width: iframeSize.width,
|
|
height: iframeSize.height,
|
|
cursor: panMode
|
|
? isPanning
|
|
? 'grabbing'
|
|
: 'grab'
|
|
: undefined
|
|
}}
|
|
>
|
|
<iframe
|
|
ref={iframeRef}
|
|
srcDoc={previewContentHTML}
|
|
onLoad={handleIframeLoad}
|
|
scrolling='no'
|
|
frameBorder='0'
|
|
style={{
|
|
width: '100%',
|
|
height: iframeSize.height === 'auto' ? 150 : '100%',
|
|
display: 'block',
|
|
border: 0,
|
|
overflow: 'hidden',
|
|
pointerEvents: panMode ? 'none' : undefined
|
|
}}
|
|
/>
|
|
</div>
|
|
</Flex>
|
|
</ScrollBox>
|
|
) : (
|
|
<PDFViewer
|
|
file={pdfBlob}
|
|
scale={previewScale}
|
|
panMode={panMode}
|
|
loading={false}
|
|
onLoadError={() => {
|
|
onPreviewMessage('Failed to render PDF preview.', true)
|
|
}}
|
|
/>
|
|
)}
|
|
</div>
|
|
</Flex>
|
|
)
|
|
}
|
|
|
|
TemplatePreview.propTypes = {
|
|
loading: PropTypes.bool,
|
|
objectData: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
|
|
documentTemplate: PropTypes.object,
|
|
template: PropTypes.object,
|
|
templateType: PropTypes.string,
|
|
capabilities: PropTypes.object,
|
|
isEditing: PropTypes.bool,
|
|
style: PropTypes.object,
|
|
showTestObject: PropTypes.bool,
|
|
onTestObjectOpen: PropTypes.func,
|
|
onPreviewMessage: PropTypes.func,
|
|
showPreviewSwitch: PropTypes.bool,
|
|
content: PropTypes.string
|
|
}
|
|
|
|
export default TemplatePreview
|