import React, { useEffect, useLayoutEffect, useRef, useState, useMemo } from 'react'; import { JSONTree } from 'react-json-tree'; import { Tab, ListGroup, Row, Col } from 'react-bootstrap'; import { getTheme, tabs } from '../constants'; import ArrowDownTriangle from '@/_ui/Icon/solidIcons/ArrowDownTriangle'; import { useEventListener } from '@/_hooks/use-event-listener'; import { reservedKeywordReplacer } from '@/_lib/reserved-keyword-replacer'; import useStore from '@/AppBuilder/_stores/store'; import { generateCypressDataCy } from '@/modules/common/helpers/cypressHelpers'; const Preview = ({ darkMode, calculatePreviewHeight }) => { const [key, setKey] = useState('raw'); const [isJson, setIsJson] = useState(false); const [isDragging, setDragging] = useState(false); const [isTopOfPreviewPanel, setIsTopOfPreviewPanel] = useState(false); const storedHeight = useStore((state) => state.queryPanel.previewPanelHeight); // initialize height with stored height if present in state const heightSetOnce = useRef(!!storedHeight); const previewPanelExpanded = useStore((state) => state.queryPanel.previewPanelExpanded); const setPreviewPanelExpanded = useStore((state) => state.queryPanel.setPreviewPanelExpanded); const [height, setHeight] = useState(storedHeight); const [theme, setTheme] = useState(() => getTheme(darkMode)); const queryPreviewData = useStore((state) => state.queryPanel.queryPreviewData); const previewLoading = useStore((state) => state.queryPanel.previewLoading); const previewPanelRef = useRef(); const queryPanelHeight = useStore((state) => state.queryPanel.queryPanelHeight); useEffect(() => { calculatePreviewHeight(height, previewPanelExpanded); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { setTheme(() => getTheme(darkMode)); }, [darkMode]); useLayoutEffect(() => { if (queryPreviewData || previewLoading) { previewPanelRef.current.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest', }); } }, [queryPreviewData, previewLoading]); useEffect(() => { if (queryPreviewData !== null && typeof queryPreviewData === 'object') { setKey('json'); } else { setKey('raw'); } setIsJson(queryPreviewData !== null && typeof queryPreviewData === 'object'); }, [queryPreviewData]); const renderRawData = () => { if (!queryPreviewData) { return queryPreviewData === null ? '' : `${queryPreviewData}`; } else { return isJson ? JSON.stringify(queryPreviewData, reservedKeywordReplacer).toString() : queryPreviewData.toString(); } }; useEffect(() => { // query panel collapse scenario if (queryPanelHeight === 95 || queryPanelHeight === 0) { return; } if (queryPanelHeight - 85 < 40) { setHeight(40); return; } if (queryPanelHeight - 85 < height) { setHeight((queryPanelHeight - 85) * 0.7); } else if (!heightSetOnce.current) { setHeight((queryPanelHeight - 85) * 0.7); heightSetOnce.current = true; } }, [queryPanelHeight]); const onMouseMove = (e) => { if (previewPanelRef.current) { const componentTop = Math.round(previewPanelRef.current.getBoundingClientRect().top); const clientY = e.clientY; if ((clientY >= componentTop - 12) & (clientY <= componentTop + 1)) { setIsTopOfPreviewPanel(true); } else if (isTopOfPreviewPanel) { setIsTopOfPreviewPanel(false); } if (isDragging) { const parentHeight = queryPanelHeight; const shift = componentTop - clientY; const currentHeight = previewPanelRef.current.offsetHeight; const newHeight = currentHeight + shift; if (newHeight < 50) { setPreviewPanelExpanded(false); setHeight((queryPanelHeight - 85) * 0.7); return; } if (newHeight > parentHeight - 95) { return; } setHeight(newHeight); } } }; const onMouseUp = () => { setDragging(false); calculatePreviewHeight(height, previewPanelExpanded); }; const onMouseDown = () => { isTopOfPreviewPanel && setDragging(true); }; useEventListener('mousemove', onMouseMove); useEventListener('mouseup', onMouseUp); const queryPreviewDataWithCircularDependenciesRemoved = useMemo(() => { const stringifiedValue = JSON.stringify(queryPreviewData, reservedKeywordReplacer); return stringifiedValue ? JSON.parse(stringifiedValue) : undefined; }, [queryPreviewData]); return (
{ setPreviewPanelExpanded(!previewPanelExpanded); calculatePreviewHeight(height, !previewPanelExpanded); }} className="left" data-cy="preview-toggle-button" > Preview
{previewPanelExpanded && (
setKey(k)} defaultActiveKey="raw"> {tabs.map((tab) => ( {tab} ))}
)}
setKey(k)} defaultActiveKey="raw">
{previewLoading && (
)}
{renderRawData()}
); }; export default Preview;