UNPKG

10.9 kBJavaScriptView Raw
1// Copyright (c) Jupyter Development Team.
2// Distributed under the terms of the Modified BSD License.
3import { showErrorMessage } from '@jupyterlab/apputils';
4import { PathExt } from '@jupyterlab/coreutils';
5import { ServerConnection } from '@jupyterlab/services';
6import { nullTranslator } from '@jupyterlab/translation';
7import { SidePanel } from '@jupyterlab/ui-components';
8import { Panel } from '@lumino/widgets';
9import { BreadCrumbs } from './crumbs';
10import { DirListing } from './listing';
11/**
12 * The class name added to file browsers.
13 */
14const FILE_BROWSER_CLASS = 'jp-FileBrowser';
15/**
16 * The class name added to file browser panel (gather filter, breadcrumbs and listing).
17 */
18const FILE_BROWSER_PANEL_CLASS = 'jp-FileBrowser-Panel';
19/**
20 * The class name added to the filebrowser crumbs node.
21 */
22const CRUMBS_CLASS = 'jp-FileBrowser-crumbs';
23/**
24 * The class name added to the filebrowser toolbar node.
25 */
26const TOOLBAR_CLASS = 'jp-FileBrowser-toolbar';
27/**
28 * The class name added to the filebrowser listing node.
29 */
30const LISTING_CLASS = 'jp-FileBrowser-listing';
31/**
32 * A widget which hosts a file browser.
33 *
34 * The widget uses the Jupyter Contents API to retrieve contents,
35 * and presents itself as a flat list of files and directories with
36 * breadcrumbs.
37 */
38export class FileBrowser extends SidePanel {
39 /**
40 * Construct a new file browser.
41 *
42 * @param options - The file browser options.
43 */
44 constructor(options) {
45 var _a;
46 super({ content: new Panel(), translator: options.translator });
47 this._directoryPending = null;
48 this._filePending = null;
49 this._showLastModifiedColumn = true;
50 this._showFileSizeColumn = false;
51 this._showHiddenFiles = false;
52 this._showFileCheckboxes = false;
53 this._sortNotebooksFirst = false;
54 this.addClass(FILE_BROWSER_CLASS);
55 this.toolbar.addClass(TOOLBAR_CLASS);
56 this.id = options.id;
57 const translator = (this.translator = (_a = options.translator) !== null && _a !== void 0 ? _a : nullTranslator);
58 const model = (this.model = options.model);
59 const renderer = options.renderer;
60 model.connectionFailure.connect(this._onConnectionFailure, this);
61 this._manager = model.manager;
62 this.toolbar.node.setAttribute('aria-label', this._trans.__('file browser'));
63 // File browser widgets container
64 this.mainPanel = new Panel();
65 this.mainPanel.addClass(FILE_BROWSER_PANEL_CLASS);
66 this.mainPanel.title.label = this._trans.__('File Browser');
67 this.crumbs = new BreadCrumbs({ model, translator });
68 this.crumbs.addClass(CRUMBS_CLASS);
69 this.listing = this.createDirListing({
70 model,
71 renderer,
72 translator
73 });
74 this.listing.addClass(LISTING_CLASS);
75 this.mainPanel.addWidget(this.crumbs);
76 this.mainPanel.addWidget(this.listing);
77 this.addWidget(this.mainPanel);
78 if (options.restore !== false) {
79 void model.restore(this.id);
80 }
81 }
82 /**
83 * Whether to show active file in file browser
84 */
85 get navigateToCurrentDirectory() {
86 return this._navigateToCurrentDirectory;
87 }
88 set navigateToCurrentDirectory(value) {
89 this._navigateToCurrentDirectory = value;
90 }
91 /**
92 * Whether to show the last modified column
93 */
94 get showLastModifiedColumn() {
95 return this._showLastModifiedColumn;
96 }
97 set showLastModifiedColumn(value) {
98 if (this.listing.setColumnVisibility) {
99 this.listing.setColumnVisibility('last_modified', value);
100 this._showLastModifiedColumn = value;
101 }
102 else {
103 console.warn('Listing does not support toggling column visibility');
104 }
105 }
106 /**
107 * Whether to show the full path in the breadcrumbs
108 */
109 get showFullPath() {
110 return this.crumbs.fullPath;
111 }
112 set showFullPath(value) {
113 this.crumbs.fullPath = value;
114 }
115 /**
116 * Whether to show the file size column
117 */
118 get showFileSizeColumn() {
119 return this._showFileSizeColumn;
120 }
121 set showFileSizeColumn(value) {
122 if (this.listing.setColumnVisibility) {
123 this.listing.setColumnVisibility('file_size', value);
124 this._showFileSizeColumn = value;
125 }
126 else {
127 console.warn('Listing does not support toggling column visibility');
128 }
129 }
130 /**
131 * Whether to show hidden files
132 */
133 get showHiddenFiles() {
134 return this._showHiddenFiles;
135 }
136 set showHiddenFiles(value) {
137 this.model.showHiddenFiles(value);
138 this._showHiddenFiles = value;
139 }
140 /**
141 * Whether to show checkboxes next to files and folders
142 */
143 get showFileCheckboxes() {
144 return this._showFileCheckboxes;
145 }
146 set showFileCheckboxes(value) {
147 if (this.listing.setColumnVisibility) {
148 this.listing.setColumnVisibility('is_selected', value);
149 this._showFileCheckboxes = value;
150 }
151 else {
152 console.warn('Listing does not support toggling column visibility');
153 }
154 }
155 /**
156 * Whether to sort notebooks above other files
157 */
158 get sortNotebooksFirst() {
159 return this._sortNotebooksFirst;
160 }
161 set sortNotebooksFirst(value) {
162 if (this.listing.setNotebooksFirstSorting) {
163 this.listing.setNotebooksFirstSorting(value);
164 this._sortNotebooksFirst = value;
165 }
166 else {
167 console.warn('Listing does not support sorting notebooks first');
168 }
169 }
170 /**
171 * Create an iterator over the listing's selected items.
172 *
173 * @returns A new iterator over the listing's selected items.
174 */
175 selectedItems() {
176 return this.listing.selectedItems();
177 }
178 /**
179 * Select an item by name.
180 *
181 * @param name - The name of the item to select.
182 */
183 async selectItemByName(name) {
184 await this.listing.selectItemByName(name);
185 }
186 clearSelectedItems() {
187 this.listing.clearSelectedItems();
188 }
189 /**
190 * Rename the first currently selected item.
191 *
192 * @returns A promise that resolves with the new name of the item.
193 */
194 rename() {
195 return this.listing.rename();
196 }
197 /**
198 * Cut the selected items.
199 */
200 cut() {
201 this.listing.cut();
202 }
203 /**
204 * Copy the selected items.
205 */
206 copy() {
207 this.listing.copy();
208 }
209 /**
210 * Paste the items from the clipboard.
211 *
212 * @returns A promise that resolves when the operation is complete.
213 */
214 paste() {
215 return this.listing.paste();
216 }
217 async _createNew(options) {
218 // normalize the path if the file is created from a custom drive
219 if (options.path) {
220 const localPath = this._manager.services.contents.localPath(options.path);
221 options.path = this._toDrivePath(this.model.driveName, localPath);
222 }
223 try {
224 const model = await this._manager.newUntitled(options);
225 await this.listing.selectItemByName(model.name, true);
226 await this.rename();
227 return model;
228 }
229 catch (err) {
230 void showErrorMessage(this._trans.__('Error'), err);
231 throw err;
232 }
233 }
234 /**
235 * Create a new directory
236 */
237 async createNewDirectory() {
238 if (this._directoryPending) {
239 return this._directoryPending;
240 }
241 this._directoryPending = this._createNew({
242 path: this.model.path,
243 type: 'directory'
244 });
245 try {
246 return await this._directoryPending;
247 }
248 finally {
249 this._directoryPending = null;
250 }
251 }
252 /**
253 * Create a new file
254 */
255 async createNewFile(options) {
256 if (this._filePending) {
257 return this._filePending;
258 }
259 this._filePending = this._createNew({
260 path: this.model.path,
261 type: 'file',
262 ext: options.ext
263 });
264 try {
265 return await this._filePending;
266 }
267 finally {
268 this._filePending = null;
269 }
270 }
271 /**
272 * Delete the currently selected item(s).
273 *
274 * @returns A promise that resolves when the operation is complete.
275 */
276 delete() {
277 return this.listing.delete();
278 }
279 /**
280 * Duplicate the currently selected item(s).
281 *
282 * @returns A promise that resolves when the operation is complete.
283 */
284 duplicate() {
285 return this.listing.duplicate();
286 }
287 /**
288 * Download the currently selected item(s).
289 */
290 download() {
291 return this.listing.download();
292 }
293 /**
294 * cd ..
295 *
296 * Go up one level in the directory tree.
297 */
298 async goUp() {
299 return this.listing.goUp();
300 }
301 /**
302 * Shut down kernels on the applicable currently selected items.
303 *
304 * @returns A promise that resolves when the operation is complete.
305 */
306 shutdownKernels() {
307 return this.listing.shutdownKernels();
308 }
309 /**
310 * Select next item.
311 */
312 selectNext() {
313 this.listing.selectNext();
314 }
315 /**
316 * Select previous item.
317 */
318 selectPrevious() {
319 this.listing.selectPrevious();
320 }
321 /**
322 * Find a model given a click.
323 *
324 * @param event - The mouse event.
325 *
326 * @returns The model for the selected file.
327 */
328 modelForClick(event) {
329 return this.listing.modelForClick(event);
330 }
331 /**
332 * Create the underlying DirListing instance.
333 *
334 * @param options - The DirListing constructor options.
335 *
336 * @returns The created DirListing instance.
337 */
338 createDirListing(options) {
339 return new DirListing(options);
340 }
341 /**
342 * Handle a connection lost signal from the model.
343 */
344 _onConnectionFailure(sender, args) {
345 if (args instanceof ServerConnection.ResponseError &&
346 args.response.status === 404) {
347 const title = this._trans.__('Directory not found');
348 args.message = this._trans.__('Directory not found: "%1"', this.model.path);
349 void showErrorMessage(title, args);
350 }
351 }
352 /**
353 * Given a drive name and a local path, return the full
354 * drive path which includes the drive name and the local path.
355 *
356 * @param driveName: the name of the drive
357 * @param localPath: the local path on the drive.
358 *
359 * @returns the full drive path
360 */
361 _toDrivePath(driveName, localPath) {
362 if (driveName === '') {
363 return localPath;
364 }
365 else {
366 return `${driveName}:${PathExt.removeSlash(localPath)}`;
367 }
368 }
369}
370//# sourceMappingURL=browser.js.map
\No newline at end of file