diff --git a/packages/react/public/index-local.html b/packages/react/public/index-local.html index fb50c0ba..d4d1cce2 100755 --- a/packages/react/public/index-local.html +++ b/packages/react/public/index-local.html @@ -13,10 +13,10 @@ { "jupyterServerUrl": "http://localhost:8686/api/jupyter-server", "jupyterServerToken": "60c1661cc408f978c309d04157af55c9588ff9557c9380e4fb50785750703da6", - "runUrl": "https://oss.datalayer.run", + "runUrl": "https://prod1.datalayer.run", "token": "", "cpuEnvironment": "python-cpu-env", - "gpuEnvironment": "pytorch-cuda-env", + "gpuEnvironment": "pytorch-gpu-env", "credits": 1 } diff --git a/packages/react/public/index.html b/packages/react/public/index.html index 9c330249..5aa5a6ac 100755 --- a/packages/react/public/index.html +++ b/packages/react/public/index.html @@ -11,12 +11,12 @@ Jupyter React Example diff --git a/packages/react/src/components/notebook/Notebook.tsx b/packages/react/src/components/notebook/Notebook.tsx index e28a62ca..9251cb8d 100644 --- a/packages/react/src/components/notebook/Notebook.tsx +++ b/packages/react/src/components/notebook/Notebook.tsx @@ -16,10 +16,10 @@ import { IRenderMime } from '@jupyterlab/rendermime-interfaces'; import { INotebookContent } from '@jupyterlab/nbformat'; import { ServiceManager, Kernel as JupyterKernel } from '@jupyterlab/services'; import { WebsocketProvider as YWebsocketProvider } from 'y-websocket'; -import { useJupyter, Lite, Kernel, requestDocSession, COLLABORATION_ROOM_URL_PATH } from './../../jupyter'; +import { useJupyter, Lite, Kernel, requestDocSession, ICollaborative, COLLABORATION_ROOM_URL_PATH } from './../../jupyter'; import { asObservable, Lumino } from '../lumino'; import { newUuid } from '../../utils'; -import { OnSessionConnection, KernelTransfer } from '../../state'; +import { OnSessionConnection, KernelTransfer, jupyterReactStore } from '../../state'; import { CellMetadataEditor } from './cell/metadata'; import { ICellSidebarProps } from './cell/sidebar'; import { INotebookToolbarProps } from './toolbar/NotebookToolbar'; @@ -52,7 +52,7 @@ export type INotebookProps = { Toolbar?: (props: INotebookToolbarProps) => JSX.Element; cellMetadataPanel: boolean; cellSidebarMargin: number; - collaborative?: boolean; + collaborative?: ICollaborative; extensions: DatalayerNotebookExtension[] height?: string; id: string; @@ -118,7 +118,7 @@ export const Notebook = (props: INotebookProps) => { const notebookStore = useNotebookStore(); const portals = notebookStore.selectNotebookPortals(id); // Bootstrap the Notebook Adapter. - const bootstrapAdapter = async (collaborative: boolean, serviceManager?: ServiceManager.IManager, kernel?: Kernel) => { + const bootstrapAdapter = async (collaborative: ICollaborative, serviceManager?: ServiceManager.IManager, kernel?: Kernel) => { const adapter = new NotebookAdapter({ ...props, id, @@ -136,28 +136,48 @@ export const Notebook = (props: INotebookProps) => { extension.createNew(adapter.notebookPanel!, adapter.context!); setExtensionComponents(extensionComponents.concat(extension.component ?? <>)); }); - if (collaborative) { - // Setup Collaboration. + // Setup Collaboration. + if (collaborative == 'jupyter') { const ydoc = (adapter.notebookPanel?.model?.sharedModel as any).ydoc; + const token = jupyterReactStore.getState().jupyterConfig?.jupyterServerToken; const session = await requestDocSession("json", "notebook", path!); - const yWebsocketProvider = new YWebsocketProvider( - URLExt.join(serviceManager?.serverSettings.wsUrl!, COLLABORATION_ROOM_URL_PATH), - `${session.format}:${session.type}:${session.fileId}`, - ydoc, + const roomURL = URLExt.join(serviceManager?.serverSettings.wsUrl!, COLLABORATION_ROOM_URL_PATH); + const roomName = `${session.format}:${session.type}:${session.fileId}`; + const yWebsocketProvider = new YWebsocketProvider(roomURL, roomName, ydoc, { disableBc: true, - params: { sessionId: session.sessionId }, - // awareness: this._awareness + params: { + sessionId: session.sessionId, + token: token!, + }, +// awareness: this._awareness } ); console.log('Collaboration is setup with websocket provider.', yWebsocketProvider); - // Update the notebook state with the adapter. - notebookStore.update({ id, state: { adapter } }); - // Update the notebook state further to events. - adapter.notebookPanel?.model?.contentChanged.connect((notebookModel, _) => { - notebookStore.changeModel({ id, notebookModel }); - }); } + else if (collaborative == 'datalayer') { + const ydoc = (adapter.notebookPanel?.model?.sharedModel as any).ydoc; + const token = jupyterReactStore.getState().datalayerConfig?.token; + const runURL = jupyterReactStore.getState().datalayerConfig?.runUrl; + const roomName = id; + const roomURL = URLExt.join(runURL!.replace('http', 'ws'), `/api/spacer/v1/rooms`); + const yWebsocketProvider = new YWebsocketProvider(roomURL, roomName, ydoc, + { + disableBc: true, + params: { + token: token!, + } +// awareness: this._awareness + } + ); + console.log('Collaboration is setup with websocket provider.', yWebsocketProvider); + } + // Update the notebook state with the adapter. + notebookStore.update({ id, state: { adapter } }); + // Update the notebook state further to events. + adapter.notebookPanel?.model?.contentChanged.connect((notebookModel, _) => { + notebookStore.changeModel({ id, notebookModel }); + }); /* adapter.notebookPanel?.model?.sharedModel.changed.connect((_, notebookChange) => { notebookStore.changeNotebook({ id, notebookChange }); @@ -206,7 +226,7 @@ export const Notebook = (props: INotebookProps) => { }); } // - const createAdapter = (collaborative: boolean, serviceManager?: ServiceManager.IManager, kernel?: Kernel) => { + const createAdapter = (collaborative: ICollaborative, serviceManager?: ServiceManager.IManager, kernel?: Kernel) => { if (!kernel) { bootstrapAdapter(collaborative, serviceManager, kernel); } else { @@ -227,10 +247,10 @@ export const Notebook = (props: INotebookProps) => { // Mutation Effects. useEffect(() => { if (serviceManager && serverless) { - createAdapter(collaborative ?? false, serviceManager, kernel); + createAdapter(collaborative, serviceManager, kernel); } else if (serviceManager && kernel) { - createAdapter(collaborative ?? false, serviceManager, kernel); + createAdapter(collaborative, serviceManager, kernel); } }, [collaborative, serviceManager, kernel]); useEffect(() => { @@ -256,13 +276,13 @@ export const Notebook = (props: INotebookProps) => { useEffect(() => { if (adapter && path && adapter.path !== path) { disposeAdapter(); - createAdapter(collaborative ?? false, serviceManager); + createAdapter(collaborative, serviceManager); } }, [path]); useEffect(() => { if (adapter && url && adapter.url !== url) { disposeAdapter(); - createAdapter(collaborative ?? false, serviceManager); + createAdapter(collaborative, serviceManager); } }, [collaborative, url]); // Dispose Effects. @@ -360,7 +380,7 @@ export const Notebook = (props: INotebookProps) => { Notebook.defaultProps = { cellMetadataPanel: false, cellSidebarMargin: 120, - collaborative: false, + collaborative: undefined, extensions: [], height: '100vh', kernelClients: [], diff --git a/packages/react/src/components/notebook/NotebookState.ts b/packages/react/src/components/notebook/NotebookState.ts index 2bec123c..028b6e12 100644 --- a/packages/react/src/components/notebook/NotebookState.ts +++ b/packages/react/src/components/notebook/NotebookState.ts @@ -231,11 +231,11 @@ export const notebookStore = createStore((set, get) => ({ set((state: NotebookState) => ({ notebooks })); } }, - addPortals: (portalsId: ReactPortalsMutation) => { + addPortals: (portalsMutation: ReactPortalsMutation) => { const notebooks = get().notebooks; - const notebook = notebooks.get(portalsId.id); + const notebook = notebooks.get(portalsMutation.id); if (notebook) { - notebook.portals = notebook.portals.concat(portalsId.portals); + notebook.portals = notebook.portals.concat(portalsMutation.portals); set((state: NotebookState) => ({ notebooks })); } }, @@ -248,19 +248,19 @@ export const notebookStore = createStore((set, get) => ({ } set((state: NotebookState) => ({ notebooks })); }, - setPortals: (portalsId: ReactPortalsMutation) => { + setPortals: (portalsMutation: ReactPortalsMutation) => { const notebooks = get().notebooks; - const notebook = notebooks.get(portalsId.id); + const notebook = notebooks.get(portalsMutation.id); if (notebook) { - notebook.portals = portalsId.portals; + notebook.portals = portalsMutation.portals; set((state: NotebookState) => ({ notebooks })); } }, - setPortalDisplay: (portalDisplayId: PortalDisplayMutation) => { + setPortalDisplay: (portalDisplayMutation: PortalDisplayMutation) => { const notebooks = get().notebooks; - const notebook = notebooks.get(portalDisplayId.id); + const notebook = notebooks.get(portalDisplayMutation.id); if (notebook) { - notebook.portalDisplay = portalDisplayId.portalDisplay; + notebook.portalDisplay = portalDisplayMutation.portalDisplay; set((state: NotebookState) => ({ notebooks })); } }, diff --git a/packages/react/src/examples/NotebookCollaborative.tsx b/packages/react/src/examples/NotebookCollaborative.tsx index d66dc538..6433e712 100644 --- a/packages/react/src/examples/NotebookCollaborative.tsx +++ b/packages/react/src/examples/NotebookCollaborative.tsx @@ -14,7 +14,7 @@ const NotebookCollaborative = () => { return (