UNPKG

datajunction-ui

Version:
126 lines (117 loc) 3.68 kB
import DJClientContext from '../../providers/djclient'; import { Light as SyntaxHighlighter } from 'react-syntax-highlighter'; import { useEffect, useRef, useState, useContext } from 'react'; import nightOwl from 'react-syntax-highlighter/dist/esm/styles/hljs/night-owl'; import PythonIcon from '../../icons/PythonIcon'; import LoadingIcon from 'app/icons/LoadingIcon'; export default function ClientCodePopover({ nodeName, buttonStyle }) { const djClient = useContext(DJClientContext).DataJunctionAPI; const [showModal, setShowModal] = useState(false); const modalRef = useRef(null); const [code, setCode] = useState(null); // Drop any cached code when the node changes. useEffect(() => { setCode(null); }, [nodeName]); // The generated client code is only shown inside the modal, and generating it // is expensive (~1s server round trip). Fetch it lazily the first time the // popover is opened rather than on every node-page load. useEffect(() => { if (!showModal || code !== null) return; let cancelled = false; async function fetchCode() { try { const result = await djClient.clientCode(nodeName); if (!cancelled) setCode(result); } catch (err) { console.log(err); } } fetchCode(); return () => { cancelled = true; }; }, [showModal, nodeName, djClient, code]); useEffect(() => { const handleClickOutside = event => { if (modalRef.current && !modalRef.current.contains(event.target)) { setShowModal(false); } }; if (showModal) { document.addEventListener('mousedown', handleClickOutside); } else { document.removeEventListener('mousedown', handleClickOutside); } return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, [showModal]); return ( <> <button onClick={() => setShowModal(true)} style={buttonStyle}> <PythonIcon /> Python </button> {showModal && ( <div className="modal-backdrop fade in" style={{ position: 'fixed', top: 0, left: 0, width: '100vw', height: '100vh', backgroundColor: 'rgba(0, 0, 0, 0.5)', zIndex: 9999, display: 'flex', alignItems: 'center', justifyContent: 'center', }} > <div className="centerPopover" ref={modalRef} style={{ position: 'relative', maxWidth: '80%', width: '600px', maxHeight: '80vh', overflowY: 'auto', padding: '1.5rem', background: '#fff', borderRadius: '10px', boxShadow: '0 3px 10px rgba(0, 0, 0, 0.3)', }} > <button onClick={() => setShowModal(false)} style={{ position: 'absolute', top: '1rem', right: '1rem', background: 'none', border: 'none', fontSize: '1.5rem', cursor: 'pointer', color: '#999', }} aria-label="Close modal" > × </button> <h2>Python Client Code</h2> {code ? ( <SyntaxHighlighter language="python" style={nightOwl}> {code} </SyntaxHighlighter> ) : ( <> <LoadingIcon /> </> )} </div> </div> )} </> ); }