@@ -44,7 +44,17 @@ import { PromiseDelegate } from '@lumino/coreutils';
44
44
45
45
import { DisposableDelegate , DisposableSet } from '@lumino/disposable' ;
46
46
47
- import { Widget } from '@lumino/widgets' ;
47
+ import { Menu , Widget } from '@lumino/widgets' ;
48
+
49
+ /**
50
+ * The default notebook factory.
51
+ */
52
+ const NOTEBOOK_FACTORY = 'Notebook' ;
53
+
54
+ /**
55
+ * The editor factory.
56
+ */
57
+ const EDITOR_FACTORY = 'Editor' ;
48
58
49
59
/**
50
60
* A regular expression to match path to notebooks and documents
@@ -65,6 +75,11 @@ namespace CommandIDs {
65
75
*/
66
76
export const toggleTop = 'application:toggle-top' ;
67
77
78
+ /**
79
+ * Toggle sidebar visibility
80
+ */
81
+ export const togglePanel = 'application:toggle-panel' ;
82
+
68
83
/**
69
84
* Toggle the Zen mode
70
85
*/
@@ -91,6 +106,13 @@ namespace CommandIDs {
91
106
export const resolveTree = 'application:resolve-tree' ;
92
107
}
93
108
109
+ /**
110
+ * Are the left and right panels available on the current page?
111
+ */
112
+ const sidePanelsEnabled : ( ) => boolean = ( ) => {
113
+ return PageConfig . getOption ( 'notebookPage' ) === 'notebooks' ;
114
+ } ;
115
+
94
116
/**
95
117
* Check if the application is dirty before closing the browser tab.
96
118
*/
@@ -152,10 +174,12 @@ const opener: JupyterFrontEndPlugin<void> = {
152
174
id : '@jupyter-notebook/application-extension:opener' ,
153
175
autoStart : true ,
154
176
requires : [ IRouter , IDocumentManager ] ,
177
+ optional : [ ISettingRegistry ] ,
155
178
activate : (
156
179
app : JupyterFrontEnd ,
157
180
router : IRouter ,
158
- docManager : IDocumentManager
181
+ docManager : IDocumentManager ,
182
+ settingRegistry : ISettingRegistry | null
159
183
) : void => {
160
184
const { commands } = app ;
161
185
@@ -170,12 +194,21 @@ const opener: JupyterFrontEndPlugin<void> = {
170
194
}
171
195
172
196
const file = decodeURIComponent ( path ) ;
173
- const urlParams = new URLSearchParams ( parsed . search ) ;
174
- const factory = urlParams . get ( 'factory' ) ?? 'default' ;
197
+ const ext = PathExt . extname ( file ) ;
175
198
app . restored . then ( async ( ) => {
176
- docManager . open ( file , factory , undefined , {
177
- ref : '_noref'
178
- } ) ;
199
+ // TODO: get factory from file type instead?
200
+ if ( ext === '.ipynb' ) {
201
+ // TODO: fix upstream?
202
+ await settingRegistry ?. load ( '@jupyterlab/notebook-extension:panel' ) ;
203
+ await Promise . resolve ( ) ;
204
+ docManager . open ( file , NOTEBOOK_FACTORY , undefined , {
205
+ ref : '_noref'
206
+ } ) ;
207
+ } else {
208
+ docManager . open ( file , EDITOR_FACTORY , undefined , {
209
+ ref : '_noref'
210
+ } ) ;
211
+ }
179
212
} ) ;
180
213
}
181
214
} ) ;
@@ -197,7 +230,7 @@ const menus: JupyterFrontEndPlugin<void> = {
197
230
// always disable the Tabs menu
198
231
menu . tabsMenu . dispose ( ) ;
199
232
200
- const page = PageConfig . getOption ( 'notebookPage ' ) ;
233
+ const page = PageConfig . getOption ( 'retroPage ' ) ;
201
234
switch ( page ) {
202
235
case 'consoles' :
203
236
case 'terminals' :
@@ -556,6 +589,135 @@ const topVisibility: JupyterFrontEndPlugin<void> = {
556
589
autoStart : true
557
590
} ;
558
591
592
+ /**
593
+ * Plugin to toggle the left or right sidebar's visibility.
594
+ */
595
+ const sidebarVisibility : JupyterFrontEndPlugin < void > = {
596
+ id : '@jupyter-notebook/application-extension:sidebar' ,
597
+ requires : [ INotebookShell , ITranslator ] ,
598
+ optional : [ IMainMenu , ISettingRegistry ] ,
599
+ activate : (
600
+ app : JupyterFrontEnd < JupyterFrontEnd . IShell > ,
601
+ notebookShell : INotebookShell ,
602
+ translator : ITranslator ,
603
+ menu : IMainMenu | null ,
604
+ settingRegistry : ISettingRegistry | null
605
+ ) => {
606
+ if ( ! sidePanelsEnabled ( ) ) {
607
+ return ;
608
+ }
609
+
610
+ const trans = translator . load ( 'notebook' ) ;
611
+
612
+ /* Arguments for togglePanel command:
613
+ * side, left or right area
614
+ * title, widget title to show in the menu
615
+ * id, widget ID to activate in the sidebar
616
+ */
617
+ app . commands . addCommand ( CommandIDs . togglePanel , {
618
+ label : args => args [ 'title' ] as string ,
619
+ caption : args => {
620
+ // We do not substitute the parameter into the string because the parameter is not
621
+ // localized (e.g., it is always 'left') even though the string is localized.
622
+ if ( args [ 'side' ] === 'left' ) {
623
+ return trans . __ (
624
+ 'Show %1 in the left sidebar' ,
625
+ args [ 'title' ] as string
626
+ ) ;
627
+ } else if ( args [ 'side' ] === 'right' ) {
628
+ return trans . __ (
629
+ 'Show %1 in the right sidebar' ,
630
+ args [ 'title' ] as string
631
+ ) ;
632
+ }
633
+ return trans . __ ( 'Show %1 in the sidebar' , args [ 'title' ] as string ) ;
634
+ } ,
635
+ execute : args => {
636
+ switch ( args [ 'side' ] as string ) {
637
+ case 'left' :
638
+ if ( notebookShell . leftCollapsed ) {
639
+ notebookShell . activateById ( args [ 'id' ] as string ) ;
640
+ notebookShell . expandLeft ( ) ;
641
+ } else {
642
+ notebookShell . collapseLeft ( ) ;
643
+ if ( notebookShell . currentWidget ) {
644
+ notebookShell . activateById ( notebookShell . currentWidget . id ) ;
645
+ }
646
+ }
647
+ break ;
648
+ case 'right' :
649
+ if ( notebookShell . rightCollapsed ) {
650
+ notebookShell . activateById ( args [ 'id' ] as string ) ;
651
+ notebookShell . expandRight ( ) ;
652
+ } else {
653
+ notebookShell . collapseRight ( ) ;
654
+ if ( notebookShell . currentWidget ) {
655
+ notebookShell . activateById ( notebookShell . currentWidget . id ) ;
656
+ }
657
+ }
658
+ break ;
659
+ }
660
+ } ,
661
+ isToggled : args => {
662
+ if ( notebookShell . leftCollapsed ) {
663
+ return false ;
664
+ }
665
+ const currentWidget = notebookShell . leftHandler . current ;
666
+ if ( ! currentWidget ) {
667
+ return false ;
668
+ }
669
+
670
+ return currentWidget . id === ( args [ 'id' ] as string ) ;
671
+ }
672
+ } ) ;
673
+
674
+ const leftSidebarMenu = new Menu ( { commands : app . commands } ) ;
675
+ leftSidebarMenu . title . label = trans . __ ( 'Show Left Sidebar' ) ;
676
+
677
+ const rightSidebarMenu = new Menu ( { commands : app . commands } ) ;
678
+ rightSidebarMenu . title . label = trans . __ ( 'Show Right Sidebar' ) ;
679
+
680
+ app . restored . then ( ( ) => {
681
+ const leftWidgets = notebookShell . widgetsList ( 'left' ) ;
682
+ leftWidgets . forEach ( widget => {
683
+ leftSidebarMenu . addItem ( {
684
+ command : CommandIDs . togglePanel ,
685
+ args : {
686
+ side : 'left' ,
687
+ title : widget . title . caption ,
688
+ id : widget . id
689
+ }
690
+ } ) ;
691
+ } ) ;
692
+
693
+ const rightWidgets = notebookShell . widgetsList ( 'right' ) ;
694
+ rightWidgets . forEach ( widget => {
695
+ rightSidebarMenu . addItem ( {
696
+ command : CommandIDs . togglePanel ,
697
+ args : {
698
+ side : 'right' ,
699
+ title : widget . title . caption ,
700
+ id : widget . id
701
+ }
702
+ } ) ;
703
+ } ) ;
704
+
705
+ const menuItemsToAdd : Menu . IItemOptions [ ] = [ ] ;
706
+ if ( leftWidgets . length > 0 ) {
707
+ menuItemsToAdd . push ( { type : 'submenu' , submenu : leftSidebarMenu } ) ;
708
+ }
709
+ if ( rightWidgets . length > 0 ) {
710
+ menuItemsToAdd . push ( { type : 'submenu' , submenu : rightSidebarMenu } ) ;
711
+ }
712
+
713
+ if ( menu && menuItemsToAdd ) {
714
+ menu . viewMenu . addGroup ( menuItemsToAdd , 2 ) ;
715
+ }
716
+ } ) ;
717
+ } ,
718
+ autoStart : true
719
+ } ;
720
+
559
721
/**
560
722
* The default tree route resolver plugin.
561
723
*/
@@ -710,6 +872,7 @@ const plugins: JupyterFrontEndPlugin<any>[] = [
710
872
router ,
711
873
sessionDialogs ,
712
874
shell ,
875
+ sidebarVisibility ,
713
876
status ,
714
877
tabTitle ,
715
878
title ,
0 commit comments