@@ -5,6 +5,8 @@ import { EverywhereIcons } from '../icons';
55import { ToolbarButton , IToolbarWidgetRegistry } from '@jupyterlab/apputils' ;
66import { DownloadDropdownButton } from '../ui-components/DownloadDropdownButton' ;
77import { Commands } from '../commands' ;
8+ import { SharingService } from '../sharing-service' ;
9+ import { INotebookContent } from '@jupyterlab/nbformat' ;
810
911export const notebookPlugin : JupyterFrontEndPlugin < void > = {
1012 id : 'jupytereverywhere:notebook' ,
@@ -19,57 +21,104 @@ export const notebookPlugin: JupyterFrontEndPlugin<void> = {
1921 const contents = app . serviceManager . contents ;
2022
2123 const params = new URLSearchParams ( window . location . search ) ;
22- const notebookId = params . get ( 'notebook' ) ;
24+ let notebookId = params . get ( 'notebook' ) ;
2325
24- if ( notebookId ) {
25- // TODO replace with API call (and iteration over cells to set `editable: false`)
26- const content = {
27- cells : [
28- {
29- cell_type : 'code' ,
30- execution_count : null ,
31- id : '55eb9a2d-401d-4abd-b0eb-373ded5b408d' ,
32- metadata : {
33- // This makes cell non-editable
26+ if ( notebookId ?. endsWith ( '.ipynb' ) ) {
27+ notebookId = notebookId . slice ( 0 , - 6 ) ;
28+ }
29+
30+ /**
31+ * Load a shared notebook from the CKHub API
32+ */
33+ const loadSharedNotebook = async ( id : string ) : Promise < void > => {
34+ try {
35+ console . log ( `Loading shared notebook with ID: ${ id } ` ) ;
36+
37+ const apiUrl = 'http://localhost:8080/api/v1' ;
38+ const sharingService = new SharingService ( apiUrl ) ;
39+
40+ console . log ( `API URL: ${ apiUrl } ` ) ;
41+ console . log ( 'Retrieving notebook from API...' ) ;
42+
43+ const notebookResponse = await sharingService . retrieve ( id ) ;
44+ console . log ( 'API Response received:' , notebookResponse ) ; // debug
45+
46+ const content : INotebookContent = notebookResponse . content ;
47+
48+ // We make all cells read-only by setting editable: false
49+ // by iterating over each cell in the notebook content.
50+ if ( content . cells ) {
51+ content . cells . forEach ( cell => {
52+ cell . metadata = {
53+ ...cell . metadata ,
3454 editable : false
35- } ,
36- outputs : [ ] ,
37- source : [ `# This is notebook '${ notebookId } '` ]
38- }
39- ] ,
40- metadata : {
41- kernelspec : {
42- display_name : 'Python 3 (ipykernel)' ,
43- language : 'python' ,
44- name : 'python3'
45- } ,
46- language_info : {
47- codemirror_mode : {
48- name : 'ipython' ,
49- version : 3
50- } ,
51- file_extension : '.py' ,
52- mimetype : 'text/x-python' ,
53- name : 'python' ,
54- nbconvert_exporter : 'python' ,
55- pygments_lexer : 'ipython3'
56- }
57- } ,
58- nbformat : 4 ,
59- nbformat_minor : 5
60- } ;
61- contents
62- . save ( 'Untitled.ipynb' , {
55+ } ;
56+ } ) ;
57+ }
58+
59+ content . metadata = {
60+ ...content . metadata ,
61+ isSharedNotebook : true ,
62+ sharedId : notebookResponse . id ,
63+ readableId : notebookResponse . readable_id ,
64+ domainId : notebookResponse . domain_id
65+ } ;
66+
67+ // Generate a meaningful filename for the shared notebook
68+ const filename = `Shared_${ notebookResponse . readable_id || notebookResponse . id } .ipynb` ;
69+
70+ await contents . save ( filename , {
6371 content,
6472 format : 'json' ,
6573 type : 'notebook' ,
6674 writable : false
67- } )
68- . then ( ( ) => commands . execute ( 'docmanager:open' , { path : 'Untitled.ipynb' } ) ) ;
75+ } ) ;
76+
77+ await commands . execute ( 'docmanager:open' , {
78+ path : filename ,
79+ factory : 'Notebook'
80+ } ) ;
81+
82+ console . log ( `Successfully loaded shared notebook: ${ filename } ` ) ;
83+ } catch ( error ) {
84+ console . error ( 'Failed to load shared notebook:' , error ) ;
85+
86+ const errorMessage = error instanceof Error ? error . message : 'Unknown error' ;
87+ const errorStack = error instanceof Error ? error . stack : undefined ;
88+
89+ console . error ( 'Error details:' , {
90+ message : errorMessage ,
91+ stack : errorStack ,
92+ notebookId : id ,
93+ errorType : typeof error ,
94+ errorConstructor : error ?. constructor ?. name
95+ } ) ;
96+
97+ alert ( `Failed to load shared notebook "${ id } ": ${ errorMessage } ` ) ;
98+ await createNewNotebook ( ) ;
99+ }
100+ } ;
101+
102+ /**
103+ * Create a new blank notebook
104+ */
105+ const createNewNotebook = async ( ) : Promise < void > => {
106+ try {
107+ const result = await commands . execute ( 'docmanager:new-untitled' , { type : 'notebook' } ) ;
108+ if ( result ) {
109+ await commands . execute ( 'docmanager:open' , { path : 'Untitled.ipynb' } ) ;
110+ }
111+ } catch ( error ) {
112+ console . error ( 'Failed to create new notebook:' , error ) ;
113+ }
114+ } ;
115+
116+ // If a notebook ID is provided in the URL, load it; otherwise,
117+ // create a new notebook
118+ if ( notebookId ) {
119+ void loadSharedNotebook ( notebookId ) ;
69120 } else {
70- commands . execute ( 'docmanager:new-untitled' , { type : 'notebook' } ) . then ( ( ) => {
71- commands . execute ( 'docmanager:open' , { path : 'Untitled.ipynb' } ) ;
72- } ) ;
121+ void createNewNotebook ( ) ;
73122 }
74123
75124 const sidebarItem = new SidebarIcon ( {
0 commit comments