From f89547ddffc6178e88a564f655eebb10cb7518c3 Mon Sep 17 00:00:00 2001 From: Dima Grossman Date: Thu, 1 Aug 2024 14:34:03 +0300 Subject: [PATCH] fix(web): fix container logs (#6221) --- .../pages/auth/onboarding/PlaygroundPage.tsx | 40 +++++++++++++++++-- .../auth/onboarding/PlaygroundTourGuide.tsx | 17 ++++++-- .../PlaygroundWorkflowComponent.tsx | 2 +- .../step-editor/editor/useContainer.tsx | 30 +++++++++----- apps/web/src/studio/hooks/useBridgeAPI.ts | 4 +- 5 files changed, 73 insertions(+), 20 deletions(-) diff --git a/apps/web/src/pages/auth/onboarding/PlaygroundPage.tsx b/apps/web/src/pages/auth/onboarding/PlaygroundPage.tsx index 4afb7202c76..e2b6c156873 100644 --- a/apps/web/src/pages/auth/onboarding/PlaygroundPage.tsx +++ b/apps/web/src/pages/auth/onboarding/PlaygroundPage.tsx @@ -36,14 +36,14 @@ export function PlaygroundPage() { payload: {}, }); const [clickedStepId, setClickedStepId] = useState(''); - const { testUser, bridgeURL } = useStudioState(); + const { testUser, bridgeURL, setBridgeURL } = useStudioState(); - const { data: discover } = useDiscover(); + const { data: discover, refetch } = useDiscover(); const workflow = discover?.workflows?.[0]; const steps = workflow?.steps; - const { initializeWebContainer, isBridgeAppLoading } = useContainer(); + const { initializeWebContainer, isBridgeAppLoading, containerBridgeUrl } = useContainer(); const { toggleColorScheme, colorScheme } = useThemeChange(); const segment = useSegment(); @@ -77,9 +77,43 @@ export function PlaygroundPage() { useEffectOnce(() => { segment.track('Visit Playground page - [Playground]'); + if (containerBridgeUrl) { + setBridgeURL(containerBridgeUrl); + setTimeout(() => { + refetch(); + }, 500); + } + initializeWebContainer(); }, true); + useEffect(() => { + if (containerBridgeUrl) { + setBridgeURL(containerBridgeUrl); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + refetch(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [bridgeURL]); + + useEffect(() => { + window.addEventListener('webcontainer:serverReady', () => { + if (bridgeURL !== containerBridgeUrl && containerBridgeUrl) { + setBridgeURL(containerBridgeUrl); + } + + refetch(); + }); + + return () => { + window.removeEventListener('webcontainer:serverReady', () => {}); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + useEffect(() => { if (colorScheme === 'light') { toggleColorScheme(); diff --git a/apps/web/src/pages/auth/onboarding/PlaygroundTourGuide.tsx b/apps/web/src/pages/auth/onboarding/PlaygroundTourGuide.tsx index 630356f3e10..dd40b79b460 100644 --- a/apps/web/src/pages/auth/onboarding/PlaygroundTourGuide.tsx +++ b/apps/web/src/pages/auth/onboarding/PlaygroundTourGuide.tsx @@ -1,7 +1,7 @@ import { Code } from '@mantine/core'; import { css } from '@novu/novui/css'; import { useState, useEffect } from 'react'; -import Joyride, { CallBackProps, STATUS, Step, TooltipRenderProps } from 'react-joyride'; +import Joyride, { ACTIONS, CallBackProps, LIFECYCLE, STATUS, Step, TooltipRenderProps } from 'react-joyride'; import { Button } from '@novu/novui'; import { Accordion } from '@mantine/core'; @@ -135,9 +135,18 @@ export function TourGuideComponent({ ]; const handleJoyrideCallback = (data: CallBackProps) => { - const { status, lifecycle, action } = data; + const { status, lifecycle, action, index } = data; - if (action === 'next' && data.step.target === '.workflow-flow' && steps?.length && lifecycle === 'complete') { + if (action === ACTIONS.NEXT && lifecycle === LIFECYCLE.COMPLETE) { + setJoyStepIndex(index + 1); + } + + if ( + action === ACTIONS.NEXT && + data.step.target === '.workflow-flow' && + steps?.length && + lifecycle === LIFECYCLE.COMPLETE + ) { setRunJoyride(false); setJoyStepIndex(3); setClickedStepId(steps[0].stepId); @@ -153,7 +162,7 @@ export function TourGuideComponent({ }; useEffect(() => { - if (joyStepIndex !== undefined) { + if (joyStepIndex !== undefined && joyStepIndex !== null) { setRunJoyride(true); } }, [joyStepIndex, setRunJoyride]); diff --git a/apps/web/src/pages/auth/onboarding/PlaygroundWorkflowComponent.tsx b/apps/web/src/pages/auth/onboarding/PlaygroundWorkflowComponent.tsx index 0328e45ecd1..2979c622c01 100644 --- a/apps/web/src/pages/auth/onboarding/PlaygroundWorkflowComponent.tsx +++ b/apps/web/src/pages/auth/onboarding/PlaygroundWorkflowComponent.tsx @@ -9,7 +9,7 @@ import { WorkflowNodes } from '../../../studio/components/workflows/node-view/Wo import { When } from '../../../components/utils/When'; import { HStack, VStack } from '@novu/novui/jsx'; import { StepNode } from '../../../studio/components/workflows/node-view/StepNode'; -import { useBridgeAPI } from '../../../studio/hooks/useBridgeAPI'; +import { useBridgeAPI, useDiscover } from '../../../studio/hooks/useBridgeAPI'; import { useControlsHandler } from '../../../hooks/workflow/useControlsHandler'; import { WorkflowsStepEditor } from '../../../components/workflow_v2/StepEditorComponent'; import { BackButton } from '../../../components/layout/components/LocalStudioHeader/BackButton'; diff --git a/apps/web/src/studio/components/workflows/step-editor/editor/useContainer.tsx b/apps/web/src/studio/components/workflows/step-editor/editor/useContainer.tsx index fe81dc500f4..25ab7d3a9ce 100644 --- a/apps/web/src/studio/components/workflows/step-editor/editor/useContainer.tsx +++ b/apps/web/src/studio/components/workflows/step-editor/editor/useContainer.tsx @@ -18,6 +18,7 @@ type ContainerState = { setCode: (code: Record) => void; isBridgeAppLoading: boolean; initializeWebContainer: () => Promise; + containerBridgeUrl: string | null; }; const ContainerContext = React.createContext(undefined); @@ -36,13 +37,14 @@ export const ContainerProvider: FCWithChildren = ({ children }) => { 'react-email.tsx': REACT_EMAIL_CODE, }); const [isBridgeAppLoading, setIsBridgeAppLoading] = useState(true); + const [containerBridgeUrl, setContainerBridgeUrl] = useState(null); const [webContainer, setWebContainer] = useState(null); const [sandboxBridgeAddress, setSandboxBridgeAddress] = useState(null); const [initStarted, setInitStarted] = useState(false); const terminalRef = useRef(null); const studioState = useStudioState() || {}; - const { setBridgeURL } = studioState; - const { refetch } = useDiscover(); + const { setBridgeURL, bridgeURL } = studioState; + const segment = useSegment(); const writeOutput = (data: string) => { @@ -57,11 +59,18 @@ export const ContainerProvider: FCWithChildren = ({ children }) => { segment.track('Starting Playground - [Playground]'); setInitStarted(true); - setWebContainer( - await WebContainer.boot({ - coep: 'credentialless', - }) - ); + const webContainerInstance = await WebContainer.boot({ + coep: 'credentialless', + }); + + setWebContainer(webContainerInstance); + + webContainerInstance.on('server-ready', (port, url) => { + segment.track('Sandbox bridge app is ready - [Playground]'); + setSandboxBridgeAddress(url + ':' + port); + + window.dispatchEvent(new CustomEvent('webcontainer:serverReady')); + }); } } catch (error: any) { segment.track('Error booting web container - [Playground]', { @@ -85,8 +94,6 @@ export const ContainerProvider: FCWithChildren = ({ children }) => { setSandboxBridgeAddress(url + ':' + port); window.dispatchEvent(new CustomEvent('webcontainer:serverReady')); - - refetch(); }); async function installDependencies() { @@ -163,6 +170,7 @@ export const ContainerProvider: FCWithChildren = ({ children }) => { write(data) { if (data.includes('novu.sh')) { setBridgeURL(data.trim()); + setContainerBridgeUrl(data.trim()); setIsBridgeAppLoading(false); } writeOutput(data); @@ -189,9 +197,9 @@ export const ContainerProvider: FCWithChildren = ({ children }) => { return () => clearTimeout(debounceTimeout); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [code, refetch]); + }, [code]); - const value = { terminalRef, code, setCode, isBridgeAppLoading, initializeWebContainer }; + const value = { terminalRef, code, setCode, isBridgeAppLoading, initializeWebContainer, containerBridgeUrl }; return {children}; }; diff --git a/apps/web/src/studio/hooks/useBridgeAPI.ts b/apps/web/src/studio/hooks/useBridgeAPI.ts index efe8c4b47a0..bb0337d9cf9 100644 --- a/apps/web/src/studio/hooks/useBridgeAPI.ts +++ b/apps/web/src/studio/hooks/useBridgeAPI.ts @@ -34,7 +34,9 @@ export const useDiscover = (options?: any) => { const { refetch } = discoverQuery; useEffect(() => { - refetch(); + if (!bridgeURL) { + refetch(); + } }, [bridgeURL, setBridgeURL, refetch]); return discoverQuery;