@@ -2,16 +2,27 @@ import {
2
2
JupyterFrontEnd ,
3
3
JupyterFrontEndPlugin
4
4
} from "@jupyterlab/application" ;
5
-
6
- import { each } from "@phosphor/algorithm " ;
5
+ import { showErrorMessage } from "@jupyterlab/apputils" ;
6
+ import { ISettingRegistry , URLExt } from "@jupyterlab/coreutils " ;
7
7
import { IFileBrowserFactory } from "@jupyterlab/filebrowser" ;
8
8
import { ServerConnection } from "@jupyterlab/services" ;
9
- import { URLExt , ISettingRegistry } from "@jupyterlab/coreutils " ;
10
- import { showErrorMessage , showDialog , Dialog } from "@jupyterlab/apputils " ;
9
+ import { each } from "@phosphor/algorithm " ;
10
+ import { IDisposable } from "@phosphor/disposable " ;
11
11
import { Menu } from "@phosphor/widgets" ;
12
12
13
13
const DIRECTORIES_URL = "directories" ;
14
14
const EXTRACT_ARCHVE_URL = "extract-archive" ;
15
+ type ArchiveFormat =
16
+ | null
17
+ | "zip"
18
+ | "tgz"
19
+ | "tar.gz"
20
+ | "tbz"
21
+ | "tbz2"
22
+ | "tar.bz"
23
+ | "tar.bz2"
24
+ | "txz"
25
+ | "tar.xz" ;
15
26
16
27
namespace CommandIDs {
17
28
export const downloadArchive = "filebrowser:download-archive" ;
@@ -22,7 +33,7 @@ namespace CommandIDs {
22
33
23
34
function downloadArchiveRequest (
24
35
path : string ,
25
- archiveFormat : string
36
+ archiveFormat : ArchiveFormat
26
37
) : Promise < void > {
27
38
const settings = ServerConnection . makeSettings ( ) ;
28
39
@@ -120,59 +131,97 @@ const extension: JupyterFrontEndPlugin<void> = {
120
131
".txz" ,
121
132
".tar.xz"
122
133
] ;
123
- let archiveFormat : string = "zip" ;
134
+ let archiveFormat : ArchiveFormat ; // Default value read from settings
135
+
136
+ // matches anywhere on filebrowser
137
+ const selectorContent = ".jp-DirListing-content" ;
138
+
139
+ // matches all filebrowser items
140
+ const selectorOnlyDir = '.jp-DirListing-item[data-isdir="true"]' ;
124
141
125
- // Create submenu
126
- const archives = new Menu ( {
142
+ // Create submenus
143
+ const archiveFolder = new Menu ( {
144
+ commands
145
+ } ) ;
146
+ archiveFolder . title . label = "Download As" ;
147
+ archiveFolder . title . iconClass = "jp-MaterialIcon jp-DownloadIcon" ;
148
+ const archiveCurrentFolder = new Menu ( {
127
149
commands
128
150
} ) ;
129
- archives . title . label = "Download As " ;
130
- archives . title . iconClass = "jp-MaterialIcon jp-DownloadIcon" ;
151
+ archiveCurrentFolder . title . label = "Download Current Folder As " ;
152
+ archiveCurrentFolder . title . iconClass = "jp-MaterialIcon jp-DownloadIcon" ;
131
153
132
- [ "zip" , "tar.bz2" , "tar.gz" , "tar.xz" ] . forEach ( format =>
133
- archives . addItem ( {
154
+ [ "zip" , "tar.bz2" , "tar.gz" , "tar.xz" ] . forEach ( format => {
155
+ archiveFolder . addItem ( {
134
156
command : CommandIDs . downloadArchive ,
135
157
args : { format }
136
- } )
137
- ) ;
158
+ } ) ;
159
+ archiveCurrentFolder . addItem ( {
160
+ command : CommandIDs . downloadArchiveCurrentFolder ,
161
+ args : { format }
162
+ } ) ;
163
+ } ) ;
164
+
165
+ // Reference to menu items
166
+ let archiveFolderItem : IDisposable ;
167
+ let archiveCurrentFolderItem : IDisposable ;
168
+
169
+ function updateFormat ( newFormat : ArchiveFormat , oldFormat : ArchiveFormat ) {
170
+ if ( newFormat !== oldFormat ) {
171
+ if (
172
+ newFormat === null ||
173
+ oldFormat === null ||
174
+ oldFormat === undefined
175
+ ) {
176
+ if ( oldFormat !== undefined ) {
177
+ archiveFolderItem . dispose ( ) ;
178
+ archiveCurrentFolderItem . dispose ( ) ;
179
+ }
180
+
181
+ if ( newFormat === null ) {
182
+ archiveFolderItem = app . contextMenu . addItem ( {
183
+ selector : selectorOnlyDir ,
184
+ rank : 10 ,
185
+ type : "submenu" ,
186
+ submenu : archiveFolder
187
+ } ) ;
188
+
189
+ archiveCurrentFolderItem = app . contextMenu . addItem ( {
190
+ selector : selectorContent ,
191
+ rank : 3 ,
192
+ type : "submenu" ,
193
+ submenu : archiveCurrentFolder
194
+ } ) ;
195
+ } else {
196
+ archiveFolderItem = app . contextMenu . addItem ( {
197
+ command : CommandIDs . downloadArchive ,
198
+ selector : selectorOnlyDir ,
199
+ rank : 10
200
+ } ) ;
201
+
202
+ archiveCurrentFolderItem = app . contextMenu . addItem ( {
203
+ command : CommandIDs . downloadArchiveCurrentFolder ,
204
+ selector : selectorContent ,
205
+ rank : 3
206
+ } ) ;
207
+ }
208
+ }
209
+
210
+ archiveFormat = newFormat ;
211
+ }
212
+ }
138
213
139
214
// Load the settings
140
215
settingRegistry
141
216
. load ( "@hadim/jupyter-archive:archive" )
142
217
. then ( settings => {
143
218
settings . changed . connect ( settings => {
144
- const newFormat = settings . get ( "format" ) . composite as string ;
145
- if (
146
- newFormat !== archiveFormat &&
147
- ( newFormat === null || archiveFormat === null )
148
- ) {
149
- showDialog ( {
150
- title : "Information" ,
151
- body :
152
- "You will need to reload the page to apply the new default archive format." ,
153
- buttons : [ Dialog . okButton ( ) ]
154
- } ) ;
155
- } else {
156
- archiveFormat = newFormat ;
157
- }
219
+ const newFormat = settings . get ( "format" ) . composite as ArchiveFormat ;
220
+ updateFormat ( newFormat , archiveFormat ) ;
158
221
} ) ;
159
- archiveFormat = settings . get ( "format" ) . composite as string ;
160
- } )
161
- . then ( ( ) => {
162
- if ( archiveFormat === null ) {
163
- app . contextMenu . addItem ( {
164
- selector : selectorOnlyDir ,
165
- rank : 10 ,
166
- type : "submenu" ,
167
- submenu : archives
168
- } ) ;
169
- } else {
170
- app . contextMenu . addItem ( {
171
- command : CommandIDs . downloadArchive ,
172
- selector : selectorOnlyDir ,
173
- rank : 10
174
- } ) ;
175
- }
222
+
223
+ const newFormat = settings . get ( "format" ) . composite as ArchiveFormat ;
224
+ updateFormat ( newFormat , archiveFormat ) ;
176
225
} )
177
226
. catch ( reason => {
178
227
console . error ( reason ) ;
@@ -182,20 +231,14 @@ const extension: JupyterFrontEndPlugin<void> = {
182
231
) ;
183
232
} ) ;
184
233
185
- // matches anywhere on filebrowser
186
- const selectorContent = ".jp-DirListing-content" ;
187
-
188
- // matches all filebrowser items
189
- const selectorOnlyDir = '.jp-DirListing-item[data-isdir="true"]' ;
190
-
191
234
// Add the 'downloadArchive' command to the file's menu.
192
235
commands . addCommand ( CommandIDs . downloadArchive , {
193
236
execute : args => {
194
237
const widget = tracker . currentWidget ;
195
238
if ( widget ) {
196
239
each ( widget . selectedItems ( ) , item => {
197
240
if ( item . type == "directory" ) {
198
- const format = args [ "format" ] as string ;
241
+ const format = args [ "format" ] as ArchiveFormat ;
199
242
downloadArchiveRequest (
200
243
item . path ,
201
244
allowedArchiveExtensions . indexOf ( "." + format ) >= 0
@@ -209,9 +252,9 @@ const extension: JupyterFrontEndPlugin<void> = {
209
252
iconClass : args =>
210
253
"format" in args ? "" : "jp-MaterialIcon jp-DownloadIcon" ,
211
254
label : args => {
212
- const format = ( args [ "format" ] as string ) || "" ;
213
- const label = format . replace ( "." , " " ) ;
214
- return label ? `${ label } Archive` : "Download as an archive " ;
255
+ const format = ( args [ "format" ] as ArchiveFormat ) || "" ;
256
+ const label = format . replace ( "." , " " ) . toLocaleUpperCase ( ) ;
257
+ return label ? `${ label } Archive` : "Download as an Archive " ;
215
258
}
216
259
} ) ;
217
260
@@ -226,7 +269,7 @@ const extension: JupyterFrontEndPlugin<void> = {
226
269
}
227
270
} ,
228
271
iconClass : "jp-MaterialIcon jp-DownCaretIcon" ,
229
- label : "Extract archive "
272
+ label : "Extract Archive "
230
273
} ) ;
231
274
232
275
// Add a command for each archive extensions
@@ -242,20 +285,27 @@ const extension: JupyterFrontEndPlugin<void> = {
242
285
243
286
// Add the 'downloadArchiveCurrentFolder' command to file browser content.
244
287
commands . addCommand ( CommandIDs . downloadArchiveCurrentFolder , {
245
- execute : ( ) => {
288
+ execute : args => {
246
289
const widget = tracker . currentWidget ;
247
290
if ( widget ) {
248
- downloadArchiveRequest ( widget . model . path , archiveFormat ) ;
291
+ const format = args [ "format" ] as ArchiveFormat ;
292
+ downloadArchiveRequest (
293
+ widget . model . path ,
294
+ allowedArchiveExtensions . indexOf ( "." + format ) >= 0
295
+ ? format
296
+ : archiveFormat
297
+ ) ;
249
298
}
250
299
} ,
251
- iconClass : "jp-MaterialIcon jp-DownloadIcon" ,
252
- label : "Download current folder as an archive"
253
- } ) ;
254
-
255
- app . contextMenu . addItem ( {
256
- command : CommandIDs . downloadArchiveCurrentFolder ,
257
- selector : selectorContent ,
258
- rank : 3
300
+ iconClass : args =>
301
+ "format" in args ? "" : "jp-MaterialIcon jp-DownloadIcon" ,
302
+ label : args => {
303
+ const format = ( args [ "format" ] as ArchiveFormat ) || "" ;
304
+ const label = format . replace ( "." , " " ) . toLocaleUpperCase ( ) ;
305
+ return label
306
+ ? `${ label } Archive`
307
+ : "Download Current Folder as an Archive" ;
308
+ }
259
309
} ) ;
260
310
}
261
311
} ;
0 commit comments