@@ -15,18 +15,19 @@ import {
1515 JupyterCadModel
1616} from '@jupytercad/schema' ;
1717
18+ import { showErrorMessage } from '@jupyterlab/apputils' ;
1819import {
1920 JupyterFrontEnd ,
2021 JupyterFrontEndPlugin
2122} from '@jupyterlab/application' ;
2223import { Contents } from '@jupyterlab/services' ;
2324import { MessageLoop } from '@lumino/messaging' ;
2425import { Panel , Widget } from '@lumino/widgets' ;
25- import * as Y from 'yjs' ;
2626import {
2727 IJupyterYWidget ,
2828 IJupyterYWidgetManager ,
29- JupyterYModel
29+ JupyterYModel ,
30+ JupyterYDoc
3031} from 'yjs-widgets' ;
3132import { Toolbar } from '@jupyterlab/ui-components' ;
3233import { ConsolePanel } from '@jupyterlab/console' ;
@@ -94,10 +95,6 @@ export class YJupyterCADLuminoWidget extends Panel {
9495 private _buildWidget = ( options : IOptions ) => {
9596 const { commands, workerRegistry, model, externalCommands, tracker } =
9697 options ;
97- // Ensure the model filePath is relevant with the shared model path.
98- if ( model . sharedModel . getState ( 'path' ) ) {
99- model . filePath = model . sharedModel . getState ( 'path' ) as string ;
100- }
10198 const content = new JupyterCadPanel ( {
10299 model : model ,
103100 workerRegistry : workerRegistry as IJCadWorkerRegistry
@@ -153,17 +150,57 @@ export const notebookRenderePlugin: JupyterFrontEndPlugin<void> = {
153150 console . error ( 'Missing IJupyterYWidgetManager token!' ) ;
154151 return ;
155152 }
156- if ( ! drive ) {
157- console . error ( 'Missing ICollaborativeDrive token!' ) ;
158- return ;
159- }
153+
160154 class YJupyterCADModelFactory extends YJupyterCADModel {
161- ydocFactory ( commMetadata : ICommMetadata ) : Y . Doc {
155+ protected async initialize ( commMetadata : {
156+ [ key : string ] : any ;
157+ } ) : Promise < void > {
162158 const { path, format, contentType } = commMetadata ;
163159 const fileFormat = format as Contents . FileFormat ;
164160
161+ if ( ! drive ) {
162+ showErrorMessage (
163+ 'Error using the JupyterCAD Python API' ,
164+ 'You cannot use the JupyterCAD Python API without a collaborative drive. You need to install a package providing collaboration features (e.g. jupyter-collaboration).'
165+ ) ;
166+ throw new Error (
167+ 'Failed to create the YDoc without a collaborative drive'
168+ ) ;
169+ }
170+
171+ // The path of the project is relative to the path of the notebook
172+ let currentWidgetPath = '' ;
173+ const currentWidget = app . shell . currentWidget ;
174+ if (
175+ currentWidget instanceof NotebookPanel ||
176+ currentWidget instanceof ConsolePanel
177+ ) {
178+ currentWidgetPath = currentWidget . sessionContext . path ;
179+ }
180+
181+ let localPath = '' ;
182+ if ( path ) {
183+ localPath = PathExt . join ( PathExt . dirname ( currentWidgetPath ) , path ) ;
184+
185+ // If the file does not exist yet, create it
186+ try {
187+ await app . serviceManager . contents . get ( localPath ) ;
188+ } catch ( e ) {
189+ await app . serviceManager . contents . save ( localPath , {
190+ content : btoa ( '{}' ) ,
191+ format : 'base64'
192+ } ) ;
193+ }
194+ } else {
195+ // If the user did not provide a path, do not create
196+ localPath = PathExt . join (
197+ PathExt . dirname ( currentWidgetPath ) ,
198+ 'unsaved_project'
199+ ) ;
200+ }
201+
165202 const sharedModel = drive ! . sharedModelFactory . createNew ( {
166- path,
203+ path : localPath ,
167204 format : fileFormat ,
168205 contentType,
169206 collaborative : true
@@ -174,28 +211,10 @@ export const notebookRenderePlugin: JupyterFrontEndPlugin<void> = {
174211 } ) ;
175212
176213 this . jupyterCADModel . contentsManager = app . serviceManager . contents ;
214+ this . jupyterCADModel . filePath = localPath ;
177215
178- if ( ! sharedModel ) {
179- // The path of the project is set to the path of the notebook, to be able to
180- // add local geoJSON/shape file in a "file-less" project.
181- let currentWidgetPath : string | undefined = undefined ;
182- const currentWidget = app . shell . currentWidget ;
183- if (
184- currentWidget instanceof NotebookPanel ||
185- currentWidget instanceof ConsolePanel
186- ) {
187- currentWidgetPath = currentWidget . sessionContext . path ;
188- }
189-
190- if ( currentWidgetPath ) {
191- this . jupyterCADModel . filePath = PathExt . join (
192- PathExt . dirname ( currentWidgetPath ) ,
193- 'unsaved_project'
194- ) ;
195- }
196- }
197-
198- return this . jupyterCADModel . sharedModel . ydoc ;
216+ this . ydoc = this . jupyterCADModel . sharedModel . ydoc ;
217+ this . sharedModel = new JupyterYDoc ( commMetadata , this . ydoc ) ;
199218 }
200219 }
201220
0 commit comments