import React, { useEffect, useState } from 'react'; import { computeCoercion, getCurrentNodeType, hasDeepChildren, resolveReferences } from './utils'; import CodeHinter from '.'; import { copyToClipboard } from '@/_helpers/appUtils'; import { Alert } from '@/_ui/Alert/Alert'; import _, { isEmpty } from 'lodash'; import { handleCircularStructureToJSON, hasCircularDependency } from '@/_helpers/utils'; import OverlayTrigger from 'react-bootstrap/OverlayTrigger'; import Popover from 'react-bootstrap/Popover'; import Card from 'react-bootstrap/Card'; // eslint-disable-next-line import/no-unresolved import { JsonViewer } from '@textea/json-viewer'; export const PreviewBox = ({ currentValue, validationSchema, setErrorStateActive, setErrorMessage, customVariables, isWorkspaceVariable, }) => { const [resolvedValue, setResolvedValue] = useState(''); const [error, setError] = useState(null); const [coersionData, setCoersionData] = useState(null); const getPreviewContent = (content, type) => { if (content === undefined || content === null) return currentValue; try { switch (type) { case 'Object': case 'Array': return JSON.stringify(content); case 'Boolean': return content.toString(); default: return content; } } catch (e) { return undefined; } }; let previewType = getCurrentNodeType(resolvedValue); let previewContent = resolvedValue; if (hasCircularDependency(resolvedValue)) { previewContent = JSON.stringify(resolvedValue, handleCircularStructureToJSON()); previewType = typeof previewContent; } const ifCoersionErrorHasCircularDependency = (value) => { if (hasCircularDependency(value)) { return JSON.stringify(value, handleCircularStructureToJSON()); } return value; }; const content = getPreviewContent(previewContent, previewType); useEffect(() => { if (error) { setErrorStateActive(true); setErrorMessage(error.message); } else { setErrorStateActive(false); setErrorMessage(null); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [error]); useEffect(() => { const [valid, _error, newValue, resolvedValue] = resolveReferences(currentValue, validationSchema, customVariables); if (isWorkspaceVariable || !validationSchema || isEmpty(validationSchema)) { return setResolvedValue(newValue); } if (valid) { const [coercionPreview, typeAfterCoercion, typeBeforeCoercion] = computeCoercion(resolvedValue, newValue); setResolvedValue(resolvedValue); setCoersionData({ coercionPreview, typeAfterCoercion, typeBeforeCoercion, }); setError(null); } else if (!valid && !newValue && !resolvedValue) { const err = !error ? `Invalid value for ${validationSchema?.schema?.type}` : `${_error}`; setError({ message: err, value: resolvedValue, type: 'Invalid' }); } else { const jsErrorType = _error?.includes('ReferenceError') ? 'ReferenceError' : _error?.includes('TypeError') ? 'TypeError' : _error?.includes('SyntaxError') ? 'SyntaxError' : 'Invalid'; const errValue = ifCoersionErrorHasCircularDependency(resolvedValue); setError({ message: _error, value: jsErrorType === 'Invalid' ? JSON.stringify(errValue) : resolvedValue, type: jsErrorType, }); setCoersionData(null); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [currentValue]); return ( <> copyToClipboard(error ? error?.value : content)} icon={'copy'} tip={'Copy to clipboard'} /> ); }; const RenderResolvedValue = ({ error, previewType, resolvedValue, coersionData, withValidation, isWorkspaceVariable, }) => { const computeCoersionPreview = (resolvedValue, coersionData) => { if (coersionData?.typeBeforeCoercion === coersionData?.typeAfterCoercion) return resolvedValue; if (coersionData?.typeBeforeCoercion === 'array') { return '[...]' + coersionData?.coercionPreview; } if (coersionData?.typeBeforeCoercion === 'object') { return '{...}' + coersionData?.coercionPreview; } return resolvedValue + coersionData?.coercionPreview; }; const previewValueType = isWorkspaceVariable ? previewType : withValidation || (coersionData && coersionData?.typeBeforeCoercion) ? `${coersionData?.typeBeforeCoercion} ${ coersionData?.coercionPreview ? ` → ${coersionData?.typeAfterCoercion}` : '' }` : previewType; const previewContent = !withValidation ? resolvedValue : computeCoersionPreview(resolvedValue, coersionData); const cls = error ? 'codehinter-error-banner' : 'codehinter-success-banner'; return (
{error ? error.type : previewValueType}
); }; const PreviewContainer = ({ children, isFocused, enablePreview, setCursorInsidePreview, isPortalOpen, ...restProps }) => { const { validationSchema, isWorkspaceVariable, errorStateActive, previewPlacement } = restProps; const [errorMessage, setErrorMessage] = useState(''); const typeofError = getCurrentNodeType(errorMessage); const errorMsg = typeofError === 'Array' ? errorMessage[0] : errorMessage; const darkMode = localStorage.getItem('darkMode') === 'true'; const popover = ( setCursorInsidePreview(true)} onMouseLeave={() => setCursorInsidePreview(false)} >
{errorStateActive && (
{errorMsg !== 'null' ? errorMsg : 'Invalid'}
)} {!isEmpty(validationSchema) && ( <>
Expected
{validationSchema?.schema?.type}
)}
{!isEmpty(validationSchema) && (
Current
)}
{isWorkspaceVariable && }
); return ( {children} ); }; const PreviewCodeBlock = ({ code, isExpectValue = false }) => { let preview = code && code.trim ? code?.trim() : `${code}`; const shouldTrim = preview.length > 35; let showJSONTree = false; if (isExpectValue && shouldTrim) { preview = preview.substring(0, 35) + '...' + preview.substring(preview.length - 2, preview.length); } let prettyPrintedJson = preview; try { prettyPrintedJson = JSON.parse(preview); const typeOfValue = typeof prettyPrintedJson; if (typeOfValue === 'object' || typeOfValue === 'array') { showJSONTree = true; } else { prettyPrintedJson = preview; showJSONTree = false; } } catch (e) { prettyPrintedJson = preview; showJSONTree = false; } if (showJSONTree) { const darkMode = localStorage.getItem('darkMode') === 'true'; const hasDeepChild = hasDeepChildren(prettyPrintedJson); return (
); } return (
        {prettyPrintedJson?.startsWith('{{') && prettyPrintedJson?.endsWith('{{')
          ? prettyPrintedJson?.replace(/{{/g, '').replace(/}}/g, '')
          : prettyPrintedJson}
      
); }; PreviewBox.RenderResolvedValue = RenderResolvedValue; PreviewBox.Container = PreviewContainer; PreviewBox.CodeBlock = PreviewCodeBlock;