From 333a557717e6cc21f429a72af8309a5a63c1a77b Mon Sep 17 00:00:00 2001 From: Lucas Massemin Date: Fri, 15 Nov 2024 14:14:12 +0100 Subject: [PATCH] Can inspect code for visualizations. Layout shift needs fix. (#8648) * Can inspect code for visualizations. Layout shift needs fix. * ui improvements --------- Co-authored-by: Lucas Co-authored-by: Thomas Draier --- .../actions/VisualizationActionIframe.tsx | 53 +++++++++++++++++-- types/src/front/assistant/visualization.ts | 25 ++++++++- viz/app/components/VisualizationWrapper.tsx | 23 ++++++-- 3 files changed, 93 insertions(+), 8 deletions(-) diff --git a/front/components/assistant/conversation/actions/VisualizationActionIframe.tsx b/front/components/assistant/conversation/actions/VisualizationActionIframe.tsx index 4b1a07e295f6..ef2f090d4ceb 100644 --- a/front/components/assistant/conversation/actions/VisualizationActionIframe.tsx +++ b/front/components/assistant/conversation/actions/VisualizationActionIframe.tsx @@ -1,6 +1,12 @@ -import { Button, Spinner } from "@dust-tt/sparkle"; -import { MarkdownContentContext } from "@dust-tt/sparkle"; -import { Markdown } from "@dust-tt/sparkle"; +import { + Button, + CodeBlock, + Markdown, + MarkdownContentContext, + Modal, + Page, + Spinner, +} from "@dust-tt/sparkle"; import type { CommandResultMap, LightWorkspaceType, @@ -58,12 +64,14 @@ function useVisualizationDataHandler({ visualization, setContentHeight, setErrorMessage, + setCodeDrawerOpened, vizIframeRef, workspaceId, }: { visualization: Visualization; setContentHeight: (v: SetStateAction) => void; setErrorMessage: (v: SetStateAction) => void; + setCodeDrawerOpened: (v: SetStateAction) => void; vizIframeRef: React.MutableRefObject; workspaceId: string; }) { @@ -147,6 +155,10 @@ function useVisualizationDataHandler({ downloadFileFromBlob(data.params.blob, data.params.filename); break; + case "displayCode": + setCodeDrawerOpened(true); + break; + default: assertNever(data); } @@ -160,11 +172,36 @@ function useVisualizationDataHandler({ getFileBlob, setContentHeight, setErrorMessage, + setCodeDrawerOpened, visualization.identifier, vizIframeRef, ]); } +export function CodeDrawer({ + isOpened, + onClose, + code, +}: { + isOpened: boolean; + onClose: () => void; + code: string; +}) { + return ( + + + {code} + + + ); +} + export function VisualizationActionIframe({ owner, visualization, @@ -179,7 +216,7 @@ export function VisualizationActionIframe({ const [contentHeight, setContentHeight] = useState(0); const [errorMessage, setErrorMessage] = useState(null); const [retryClicked, setRetryClicked] = useState(false); - + const [isCodeDrawerOpen, setCodeDrawerOpened] = useState(false); const vizIframeRef = useRef(null); const isErrored = !!errorMessage || retryClicked; @@ -189,6 +226,7 @@ export function VisualizationActionIframe({ workspaceId: owner.sId, setContentHeight, setErrorMessage, + setCodeDrawerOpened, vizIframeRef, }); @@ -226,6 +264,13 @@ export function VisualizationActionIframe({ )} + {code && ( + setCodeDrawerOpened(false)} + code={code} + /> + )}
; + + return ( + v.command === "displayCode" && + typeof v.identifier === "string" && + typeof v.messageUniqueId === "string" + ); +} + export function isVisualizationRPCRequest( value: unknown ): value is VisualizationRPCRequest { @@ -182,6 +204,7 @@ export function isVisualizationRPCRequest( isGetFileRequest(value) || isDownloadFileRequest(value) || isSetContentHeightRequest(value) || - isSetErrorMessageRequest(value) + isSetErrorMessageRequest(value) || + isDisplayCodeRequest(value) ); } diff --git a/viz/app/components/VisualizationWrapper.tsx b/viz/app/components/VisualizationWrapper.tsx index 57f6d5a04412..145d447c842f 100644 --- a/viz/app/components/VisualizationWrapper.tsx +++ b/viz/app/components/VisualizationWrapper.tsx @@ -14,7 +14,7 @@ import { importCode, Runner } from "react-runner"; import * as rechartsAll from "recharts"; import { useResizeDetector } from "react-resize-detector"; import { ErrorBoundary } from "@viz/app/components/ErrorBoundary"; -import { Download } from "lucide-react"; +import { Download, SquareTerminal } from "lucide-react"; import { toBlob } from "html-to-image"; export function useVisualizationAPI( @@ -83,12 +83,20 @@ export function useVisualizationAPI( [sendCrossDocumentMessage] ); + const displayCode = useCallback( + async () => { + await sendCrossDocumentMessage("displayCode", null); + }, + [sendCrossDocumentMessage] + ); + return { error, fetchCode, fetchFile, sendHeightToParent, downloadFile, + displayCode, }; } @@ -182,7 +190,7 @@ export function VisualizationWrapper({ const [errored, setErrorMessage] = useState(null); - const { fetchCode, fetchFile, error, sendHeightToParent, downloadFile } = api; + const { fetchCode, fetchFile, error, sendHeightToParent, downloadFile, displayCode } = api; const memoizedDownloadFile = useDownloadFileCallback(downloadFile); @@ -249,6 +257,10 @@ export function VisualizationWrapper({ } }, [ref, downloadFile]); + const handleDisplayCode = useCallback(async () => { + await displayCode(); + }, [displayCode]); + useEffect(() => { if (error) { setErrorMessage(error); @@ -266,12 +278,17 @@ export function VisualizationWrapper({ return (
+
+ +