@jupyterlab/filebrowser 4.0.0-alpha.2 → 4.0.0-alpha.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser.d.ts +15 -18
- package/lib/browser.js +50 -64
- package/lib/browser.js.map +1 -1
- package/lib/crumbs.d.ts +1 -0
- package/lib/crumbs.js +41 -10
- package/lib/crumbs.js.map +1 -1
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -1
- package/lib/index.js.map +1 -1
- package/lib/listing.d.ts +54 -12
- package/lib/listing.js +296 -56
- package/lib/listing.js.map +1 -1
- package/lib/model.d.ts +19 -9
- package/lib/model.js +32 -11
- package/lib/model.js.map +1 -1
- package/lib/opendialog.d.ts +2 -1
- package/lib/opendialog.js +42 -10
- package/lib/opendialog.js.map +1 -1
- package/lib/tokens.d.ts +16 -8
- package/lib/tokens.js +9 -2
- package/lib/tokens.js.map +1 -1
- package/lib/upload.d.ts +4 -0
- package/lib/upload.js +1 -0
- package/lib/upload.js.map +1 -1
- package/lib/uploadstatus.js +4 -4
- package/lib/uploadstatus.js.map +1 -1
- package/package.json +27 -28
- package/src/browser.ts +444 -0
- package/src/crumbs.ts +441 -0
- package/src/index.ts +15 -0
- package/src/listing.ts +2609 -0
- package/src/model.ts +832 -0
- package/src/opendialog.ts +257 -0
- package/src/tokens.ts +122 -0
- package/src/upload.ts +119 -0
- package/src/uploadstatus.tsx +259 -0
- package/style/base.css +83 -62
- package/lib/search.d.ts +0 -15
- package/lib/search.js +0 -92
- package/lib/search.js.map +0 -1
package/src/browser.ts
ADDED
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
|
|
4
|
+
import { showErrorMessage } from '@jupyterlab/apputils';
|
|
5
|
+
import { IDocumentManager } from '@jupyterlab/docmanager';
|
|
6
|
+
import { Contents, ServerConnection } from '@jupyterlab/services';
|
|
7
|
+
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
8
|
+
import { SidePanel } from '@jupyterlab/ui-components';
|
|
9
|
+
import { Panel } from '@lumino/widgets';
|
|
10
|
+
import { BreadCrumbs } from './crumbs';
|
|
11
|
+
import { DirListing } from './listing';
|
|
12
|
+
import { FilterFileBrowserModel } from './model';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The class name added to file browsers.
|
|
16
|
+
*/
|
|
17
|
+
const FILE_BROWSER_CLASS = 'jp-FileBrowser';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The class name added to file browser panel (gather filter, breadcrumbs and listing).
|
|
21
|
+
*/
|
|
22
|
+
const FILE_BROWSER_PANEL_CLASS = 'jp-FileBrowser-Panel';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The class name added to the filebrowser crumbs node.
|
|
26
|
+
*/
|
|
27
|
+
const CRUMBS_CLASS = 'jp-FileBrowser-crumbs';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The class name added to the filebrowser toolbar node.
|
|
31
|
+
*/
|
|
32
|
+
const TOOLBAR_CLASS = 'jp-FileBrowser-toolbar';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The class name added to the filebrowser listing node.
|
|
36
|
+
*/
|
|
37
|
+
const LISTING_CLASS = 'jp-FileBrowser-listing';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A widget which hosts a file browser.
|
|
41
|
+
*
|
|
42
|
+
* The widget uses the Jupyter Contents API to retrieve contents,
|
|
43
|
+
* and presents itself as a flat list of files and directories with
|
|
44
|
+
* breadcrumbs.
|
|
45
|
+
*/
|
|
46
|
+
export class FileBrowser extends SidePanel {
|
|
47
|
+
/**
|
|
48
|
+
* Construct a new file browser.
|
|
49
|
+
*
|
|
50
|
+
* @param options - The file browser options.
|
|
51
|
+
*/
|
|
52
|
+
constructor(options: FileBrowser.IOptions) {
|
|
53
|
+
super({ content: new Panel(), translator: options.translator });
|
|
54
|
+
this.addClass(FILE_BROWSER_CLASS);
|
|
55
|
+
this.toolbar.addClass(TOOLBAR_CLASS);
|
|
56
|
+
this.id = options.id;
|
|
57
|
+
const translator = (this.translator = options.translator ?? nullTranslator);
|
|
58
|
+
|
|
59
|
+
const model = (this.model = options.model);
|
|
60
|
+
const renderer = options.renderer;
|
|
61
|
+
|
|
62
|
+
model.connectionFailure.connect(this._onConnectionFailure, this);
|
|
63
|
+
this._manager = model.manager;
|
|
64
|
+
|
|
65
|
+
// a11y
|
|
66
|
+
this.toolbar.node.setAttribute('role', 'navigation');
|
|
67
|
+
this.toolbar.node.setAttribute(
|
|
68
|
+
'aria-label',
|
|
69
|
+
this._trans.__('file browser')
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
this._directoryPending = false;
|
|
73
|
+
|
|
74
|
+
// File browser widgets container
|
|
75
|
+
this.mainPanel = new Panel();
|
|
76
|
+
this.mainPanel.addClass(FILE_BROWSER_PANEL_CLASS);
|
|
77
|
+
this.mainPanel.title.label = this._trans.__('File Browser');
|
|
78
|
+
|
|
79
|
+
this.crumbs = new BreadCrumbs({ model, translator });
|
|
80
|
+
this.crumbs.addClass(CRUMBS_CLASS);
|
|
81
|
+
|
|
82
|
+
this.listing = this.createDirListing({
|
|
83
|
+
model,
|
|
84
|
+
renderer,
|
|
85
|
+
translator
|
|
86
|
+
});
|
|
87
|
+
this.listing.addClass(LISTING_CLASS);
|
|
88
|
+
|
|
89
|
+
this.mainPanel.addWidget(this.crumbs);
|
|
90
|
+
this.mainPanel.addWidget(this.listing);
|
|
91
|
+
|
|
92
|
+
this.addWidget(this.mainPanel);
|
|
93
|
+
|
|
94
|
+
if (options.restore !== false) {
|
|
95
|
+
void model.restore(this.id);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* The model used by the file browser.
|
|
101
|
+
*/
|
|
102
|
+
readonly model: FilterFileBrowserModel;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Whether to show active file in file browser
|
|
106
|
+
*/
|
|
107
|
+
get navigateToCurrentDirectory(): boolean {
|
|
108
|
+
return this._navigateToCurrentDirectory;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
set navigateToCurrentDirectory(value: boolean) {
|
|
112
|
+
this._navigateToCurrentDirectory = value;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Whether to show the last modified column
|
|
117
|
+
*/
|
|
118
|
+
get showLastModifiedColumn(): boolean {
|
|
119
|
+
return this._showLastModifiedColumn;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
set showLastModifiedColumn(value: boolean) {
|
|
123
|
+
if (this.listing.setColumnVisibility) {
|
|
124
|
+
this.listing.setColumnVisibility('last_modified', value);
|
|
125
|
+
this._showLastModifiedColumn = value;
|
|
126
|
+
} else {
|
|
127
|
+
console.warn('Listing does not support toggling column visibility');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Whether to show the file size column
|
|
133
|
+
*/
|
|
134
|
+
get showFileSizeColumn(): boolean {
|
|
135
|
+
return this._showFileSizeColumn;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
set showFileSizeColumn(value: boolean) {
|
|
139
|
+
if (this.listing.setColumnVisibility) {
|
|
140
|
+
this.listing.setColumnVisibility('file_size', value);
|
|
141
|
+
this._showFileSizeColumn = value;
|
|
142
|
+
} else {
|
|
143
|
+
console.warn('Listing does not support toggling column visibility');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Whether to show hidden files
|
|
149
|
+
*/
|
|
150
|
+
get showHiddenFiles(): boolean {
|
|
151
|
+
return this._showHiddenFiles;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
set showHiddenFiles(value: boolean) {
|
|
155
|
+
this.model.showHiddenFiles(value);
|
|
156
|
+
this._showHiddenFiles = value;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Whether to show checkboxes next to files and folders
|
|
161
|
+
*/
|
|
162
|
+
get showFileCheckboxes(): boolean {
|
|
163
|
+
return this._showFileCheckboxes;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
set showFileCheckboxes(value: boolean) {
|
|
167
|
+
if (this.listing.setColumnVisibility) {
|
|
168
|
+
this.listing.setColumnVisibility('is_selected', value);
|
|
169
|
+
this._showFileCheckboxes = value;
|
|
170
|
+
} else {
|
|
171
|
+
console.warn('Listing does not support toggling column visibility');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Create an iterator over the listing's selected items.
|
|
177
|
+
*
|
|
178
|
+
* @returns A new iterator over the listing's selected items.
|
|
179
|
+
*/
|
|
180
|
+
selectedItems(): IterableIterator<Contents.IModel> {
|
|
181
|
+
return this.listing.selectedItems();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Select an item by name.
|
|
186
|
+
*
|
|
187
|
+
* @param name - The name of the item to select.
|
|
188
|
+
*/
|
|
189
|
+
async selectItemByName(name: string): Promise<void> {
|
|
190
|
+
await this.listing.selectItemByName(name);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
clearSelectedItems(): void {
|
|
194
|
+
this.listing.clearSelectedItems();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Rename the first currently selected item.
|
|
199
|
+
*
|
|
200
|
+
* @returns A promise that resolves with the new name of the item.
|
|
201
|
+
*/
|
|
202
|
+
rename(): Promise<string> {
|
|
203
|
+
return this.listing.rename();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Cut the selected items.
|
|
208
|
+
*/
|
|
209
|
+
cut(): void {
|
|
210
|
+
this.listing.cut();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Copy the selected items.
|
|
215
|
+
*/
|
|
216
|
+
copy(): void {
|
|
217
|
+
this.listing.copy();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Paste the items from the clipboard.
|
|
222
|
+
*
|
|
223
|
+
* @returns A promise that resolves when the operation is complete.
|
|
224
|
+
*/
|
|
225
|
+
paste(): Promise<void> {
|
|
226
|
+
return this.listing.paste();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Create a new directory
|
|
231
|
+
*/
|
|
232
|
+
createNewDirectory(): void {
|
|
233
|
+
if (this._directoryPending === true) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
this._directoryPending = true;
|
|
237
|
+
// TODO: We should provide a hook into when the
|
|
238
|
+
// directory is done being created. This probably
|
|
239
|
+
// means storing a pendingDirectory promise and
|
|
240
|
+
// returning that if there is already a directory
|
|
241
|
+
// request.
|
|
242
|
+
void this._manager
|
|
243
|
+
.newUntitled({
|
|
244
|
+
path: this.model.path,
|
|
245
|
+
type: 'directory'
|
|
246
|
+
})
|
|
247
|
+
.then(async model => {
|
|
248
|
+
await this.listing.selectItemByName(model.name);
|
|
249
|
+
await this.rename();
|
|
250
|
+
this._directoryPending = false;
|
|
251
|
+
})
|
|
252
|
+
.catch(err => {
|
|
253
|
+
void showErrorMessage(this._trans.__('Error'), err);
|
|
254
|
+
this._directoryPending = false;
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Create a new file
|
|
260
|
+
*/
|
|
261
|
+
createNewFile(options: FileBrowser.IFileOptions): void {
|
|
262
|
+
if (this._filePending === true) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
this._filePending = true;
|
|
266
|
+
// TODO: We should provide a hook into when the
|
|
267
|
+
// file is done being created. This probably
|
|
268
|
+
// means storing a pendingFile promise and
|
|
269
|
+
// returning that if there is already a file
|
|
270
|
+
// request.
|
|
271
|
+
void this._manager
|
|
272
|
+
.newUntitled({
|
|
273
|
+
path: this.model.path,
|
|
274
|
+
type: 'file',
|
|
275
|
+
ext: options.ext
|
|
276
|
+
})
|
|
277
|
+
.then(async model => {
|
|
278
|
+
await this.listing.selectItemByName(model.name);
|
|
279
|
+
await this.rename();
|
|
280
|
+
this._filePending = false;
|
|
281
|
+
})
|
|
282
|
+
.catch(err => {
|
|
283
|
+
void showErrorMessage(this._trans.__('Error'), err);
|
|
284
|
+
this._filePending = false;
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Delete the currently selected item(s).
|
|
290
|
+
*
|
|
291
|
+
* @returns A promise that resolves when the operation is complete.
|
|
292
|
+
*/
|
|
293
|
+
delete(): Promise<void> {
|
|
294
|
+
return this.listing.delete();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Duplicate the currently selected item(s).
|
|
299
|
+
*
|
|
300
|
+
* @returns A promise that resolves when the operation is complete.
|
|
301
|
+
*/
|
|
302
|
+
duplicate(): Promise<void> {
|
|
303
|
+
return this.listing.duplicate();
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Download the currently selected item(s).
|
|
308
|
+
*/
|
|
309
|
+
download(): Promise<void> {
|
|
310
|
+
return this.listing.download();
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Shut down kernels on the applicable currently selected items.
|
|
315
|
+
*
|
|
316
|
+
* @returns A promise that resolves when the operation is complete.
|
|
317
|
+
*/
|
|
318
|
+
shutdownKernels(): Promise<void> {
|
|
319
|
+
return this.listing.shutdownKernels();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Select next item.
|
|
324
|
+
*/
|
|
325
|
+
selectNext(): void {
|
|
326
|
+
this.listing.selectNext();
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Select previous item.
|
|
331
|
+
*/
|
|
332
|
+
selectPrevious(): void {
|
|
333
|
+
this.listing.selectPrevious();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Find a model given a click.
|
|
338
|
+
*
|
|
339
|
+
* @param event - The mouse event.
|
|
340
|
+
*
|
|
341
|
+
* @returns The model for the selected file.
|
|
342
|
+
*/
|
|
343
|
+
modelForClick(event: MouseEvent): Contents.IModel | undefined {
|
|
344
|
+
return this.listing.modelForClick(event);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Create the underlying DirListing instance.
|
|
349
|
+
*
|
|
350
|
+
* @param options - The DirListing constructor options.
|
|
351
|
+
*
|
|
352
|
+
* @returns The created DirListing instance.
|
|
353
|
+
*/
|
|
354
|
+
protected createDirListing(options: DirListing.IOptions): DirListing {
|
|
355
|
+
return new DirListing(options);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
protected translator: ITranslator;
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Handle a connection lost signal from the model.
|
|
362
|
+
*/
|
|
363
|
+
private _onConnectionFailure(
|
|
364
|
+
sender: FilterFileBrowserModel,
|
|
365
|
+
args: Error
|
|
366
|
+
): void {
|
|
367
|
+
if (
|
|
368
|
+
args instanceof ServerConnection.ResponseError &&
|
|
369
|
+
args.response.status === 404
|
|
370
|
+
) {
|
|
371
|
+
const title = this._trans.__('Directory not found');
|
|
372
|
+
args.message = this._trans.__(
|
|
373
|
+
'Directory not found: "%1"',
|
|
374
|
+
this.model.path
|
|
375
|
+
);
|
|
376
|
+
void showErrorMessage(title, args);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
protected listing: DirListing;
|
|
381
|
+
protected crumbs: BreadCrumbs;
|
|
382
|
+
protected mainPanel: Panel;
|
|
383
|
+
|
|
384
|
+
private _manager: IDocumentManager;
|
|
385
|
+
private _directoryPending: boolean;
|
|
386
|
+
private _filePending: boolean;
|
|
387
|
+
private _navigateToCurrentDirectory: boolean;
|
|
388
|
+
private _showLastModifiedColumn: boolean = true;
|
|
389
|
+
private _showFileSizeColumn: boolean = false;
|
|
390
|
+
private _showHiddenFiles: boolean = false;
|
|
391
|
+
private _showFileCheckboxes: boolean = false;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* The namespace for the `FileBrowser` class statics.
|
|
396
|
+
*/
|
|
397
|
+
export namespace FileBrowser {
|
|
398
|
+
/**
|
|
399
|
+
* An options object for initializing a file browser widget.
|
|
400
|
+
*/
|
|
401
|
+
export interface IOptions {
|
|
402
|
+
/**
|
|
403
|
+
* The widget/DOM id of the file browser.
|
|
404
|
+
*/
|
|
405
|
+
id: string;
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* A file browser model instance.
|
|
409
|
+
*/
|
|
410
|
+
model: FilterFileBrowserModel;
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* An optional renderer for the directory listing area.
|
|
414
|
+
*
|
|
415
|
+
* The default is a shared instance of `DirListing.Renderer`.
|
|
416
|
+
*/
|
|
417
|
+
renderer?: DirListing.IRenderer;
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Whether a file browser automatically restores state when instantiated.
|
|
421
|
+
* The default is `true`.
|
|
422
|
+
*
|
|
423
|
+
* #### Notes
|
|
424
|
+
* The file browser model will need to be restored manually for the file
|
|
425
|
+
* browser to be able to save its state.
|
|
426
|
+
*/
|
|
427
|
+
restore?: boolean;
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* The application language translator.
|
|
431
|
+
*/
|
|
432
|
+
translator?: ITranslator;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* An options object for creating a file.
|
|
437
|
+
*/
|
|
438
|
+
export interface IFileOptions {
|
|
439
|
+
/**
|
|
440
|
+
* The file extension.
|
|
441
|
+
*/
|
|
442
|
+
ext: string;
|
|
443
|
+
}
|
|
444
|
+
}
|