diff --git a/packages/embed-widget/src/App.tsx b/packages/embed-widget/src/App.tsx index 817289b5cc..75f3c2b83a 100644 --- a/packages/embed-widget/src/App.tsx +++ b/packages/embed-widget/src/App.tsx @@ -63,12 +63,17 @@ const LAYOUT_SETTINGS = { function App(): JSX.Element { const [error, setError] = useState(); const [definition, setDefinition] = useState(); + const [sharedReady, setSharedReady] = useState(false); const searchParams = useMemo( () => new URLSearchParams(window.location.search), [] ); // Get the widget name from the query param `name`. const name = searchParams.get('name'); + // Get the type of shared object from the query param, + // which is necessary if the widget is shared. + const type = searchParams.get('type'); + const isShared = searchParams.get('isShared'); const api = useApi(); const connection = useConnection(); const client = useClient(); @@ -115,13 +120,28 @@ function App(): JSX.Element { ) ); - log.debug(`Loading widget definition for ${name}...`); + if (isShared === 'true') { + log.debug(`Checking if shared parameters are valid...`); - const newDefinition = await fetchVariableDefinition(connection, name); + if (type == null) { + throw new Error('Missing URL parameter "type"'); + } - setDefinition(newDefinition); + setSharedReady(true); - log.debug(`Widget definition successfully loaded for ${name}`); + log.debug(`Shared parameters are valid`); + } else { + log.debug(`Loading widget definition for ${name}...`); + + const newDefinition = await fetchVariableDefinition( + connection, + name + ); + + setDefinition(newDefinition); + + log.debug(`Widget definition successfully loaded for ${name}`); + } } catch (e: unknown) { log.error(`Unable to load widget definition for ${name}`, e); setError(`${e}`); @@ -129,20 +149,57 @@ function App(): JSX.Element { } initApp(); }, - [api, client, connection, dispatch, name, serverConfig, user] + [ + api, + client, + connection, + dispatch, + name, + serverConfig, + user, + isShared, + type, + ] ); - const isLoaded = definition != null && error == null; - const isLoading = definition == null && error == null; + const isLoaded = + (definition != null || sharedReady != false) && error == null; + const isLoading = definition == null && sharedReady == false && error == null; + + type ConnectionWithGetSharedObject = dh.IdeConnection & { + getSharedObject(name: string, type: string): Promise; + }; + + function isConnectionWithGetSharedObject( + connection: dh.IdeConnection + ): connection is ConnectionWithGetSharedObject { + return ( + 'getSharedObject' in connection && + typeof connection.getSharedObject === 'function' + ); + } const fetch = useMemo(() => { - if (definition == null) { + if (definition == null && !sharedReady) { return async () => { throw new Error('Definition is null'); }; } - return () => connection.getObject(definition); - }, [connection, definition]); + return () => { + if (name != null && type != null) { + if (isConnectionWithGetSharedObject(connection)) { + return connection.getSharedObject(name, type); + } + throw new Error( + 'Connection does not have getSharedObject method. Cannot fetch shared object.' + ); + } + if (definition != null) { + return connection.getObject(definition); + } + throw new Error('Definition is null or shared parameters are not set'); + }; + }, [connection, definition, sharedReady, name, type]); const [goldenLayout, setGoldenLayout] = useState(null); const [dashboardId, setDashboardId] = useState('default-embed-widget'); // Can't be DEFAULT_DASHBOARD_ID because its dashboard layout is not stored in dashboardData @@ -175,16 +232,40 @@ function App(): JSX.Element { const [hasEmittedWidget, setHasEmittedWidget] = useState(false); const handleDashboardInitialized = useCallback(() => { - if (goldenLayout == null || definition == null || hasEmittedWidget) { + if ( + goldenLayout == null || + (definition == null && sharedReady == null) || + hasEmittedWidget + ) { return; } - setHasEmittedWidget(true); + + let widget = null; + if (sharedReady != null) { + widget = { + type, + name, + } as dh.ide.VariableDescriptor; + } else if (definition != null) { + widget = getVariableDescriptor(definition); + } else { + return; + } + emitPanelOpen(goldenLayout.eventHub, { fetch, - widget: getVariableDescriptor(definition), + widget, }); - }, [goldenLayout, definition, fetch, hasEmittedWidget]); + }, [ + goldenLayout, + definition, + fetch, + hasEmittedWidget, + name, + type, + sharedReady, + ]); const allDashboardData = useSelector(getAllDashboardsData);