UNPKG

jupyterlab-emrys

Version:

A computational environment for Jupyter. Powered by Emrys

370 lines (369 loc) 13.6 kB
// Copyright (c) Jupyter Development Team. // Distributed under the terms of the Modified BSD License. "use strict"; var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var phosphor_menus_1 = require('phosphor-menus'); var phosphor_widget_1 = require('phosphor-widget'); var dialog_1 = require('../dialog'); var utils = require('./utils'); /** * The class name added to a file buttons widget. */ var FILE_BUTTONS_CLASS = 'jp-FileButtons'; /** * The class name added to a button node. */ var BUTTON_CLASS = 'jp-FileButtons-button'; /** * The class name added to a button content node. */ var CONTENT_CLASS = 'jp-FileButtons-buttonContent'; /** * The class name added to a button icon node. */ var ICON_CLASS = 'jp-FileButtons-buttonIcon'; /** * The class name added to the create button. */ var CREATE_CLASS = 'jp-id-create'; /** * The class name added to the upload button. */ var UPLOAD_CLASS = 'jp-id-upload'; /** * The class name added to the refresh button. */ var REFRESH_CLASS = 'jp-id-refresh'; /** * The class name added to an active create button. */ var ACTIVE_CLASS = 'jp-mod-active'; /** * The class name added to a dropdown icon. */ var DROPDOWN_CLASS = 'jp-FileButtons-dropdownIcon'; /** * A widget which hosts the file browser buttons. */ var FileButtons = (function (_super) { __extends(FileButtons, _super); /** * Construct a new file browser buttons widget. * * @param model - The file browser view model. */ function FileButtons(options) { var _this = this; _super.call(this); /** * The 'mousedown' handler for the create button. */ this._onCreateButtonPressed = function (event) { // Do nothing if nothing if it's not a left press. if (event.button !== 0) { return; } // Do nothing if the create button is already active. var button = _this._buttons.create; if (button.classList.contains(ACTIVE_CLASS)) { return; } // Create a new dropdown menu and snap the button geometry. var dropdown = Private.createDropdownMenu(_this); var rect = button.getBoundingClientRect(); // Mark the button as active. button.classList.add(ACTIVE_CLASS); // Setup the `closed` signal handler. The menu is disposed on an // animation frame to allow a mouse press event which closed the // menu to run its course. This keeps the button from re-opening. dropdown.closed.connect(function () { requestAnimationFrame(function () { dropdown.dispose(); }); }); // Setup the `disposed` signal handler. This restores the button // to the non-active state and allows a new menu to be opened. dropdown.disposed.connect(function () { button.classList.remove(ACTIVE_CLASS); }); // Popup the menu aligned with the bottom of the create button. dropdown.popup(rect.left, rect.bottom, false, false); }; /** * The 'click' handler for the upload button. */ this._onUploadButtonClicked = function (event) { if (event.button !== 0) { return; } _this._input.click(); }; /** * The 'click' handler for the refresh button. */ this._onRefreshButtonClicked = function (event) { if (event.button !== 0) { return; } _this._model.refresh().catch(function (error) { utils.showErrorMessage(_this, 'Server Connection Error', error); }); }; /** * The 'change' handler for the input field. */ this._onInputChanged = function () { var files = Array.prototype.slice.call(_this._input.files); Private.uploadFiles(_this, files); }; this._buttons = Private.createButtons(); this._input = Private.createUploadInput(); this._manager = null; this._opener = null; this.addClass(FILE_BUTTONS_CLASS); this._model = options.model; this._buttons.create.onmousedown = this._onCreateButtonPressed; this._buttons.upload.onclick = this._onUploadButtonClicked; this._buttons.refresh.onclick = this._onRefreshButtonClicked; this._input.onchange = this._onInputChanged; var node = this.node; node.appendChild(this._buttons.create); node.appendChild(this._buttons.upload); node.appendChild(this._buttons.refresh); this._manager = options.manager; this._opener = options.opener; } /** * Dispose of the resources held by the widget. */ FileButtons.prototype.dispose = function () { this._model = null; this._buttons = null; this._input = null; this._manager = null; this._opener = null; _super.prototype.dispose.call(this); }; Object.defineProperty(FileButtons.prototype, "model", { /** * Get the model used by the widget. * * #### Notes * This is a read-only property. */ get: function () { return this._model; }, enumerable: true, configurable: true }); Object.defineProperty(FileButtons.prototype, "manager", { /** * Get the document manager used by the widget. */ get: function () { return this._manager; }, enumerable: true, configurable: true }); /** * Open a file by path. */ FileButtons.prototype.open = function (path, widgetName, kernel) { var _this = this; if (widgetName === void 0) { widgetName = 'default'; } var widget = this._manager.open(path, widgetName, kernel); var opener = this._opener; opener.open(widget); var context = this._manager.contextForWidget(widget); context.populated.connect(function () { return _this.model.refresh(); }); context.kernelChanged.connect(function () { return _this.model.refresh(); }); }; /** * Create a new file by path. */ FileButtons.prototype.createNew = function (path, widgetName, kernel) { var _this = this; if (widgetName === void 0) { widgetName = 'default'; } var widget = this._manager.createNew(path, widgetName, kernel); var opener = this._opener; opener.open(widget); var context = this._manager.contextForWidget(widget); context.populated.connect(function () { return _this.model.refresh(); }); context.kernelChanged.connect(function () { return _this.model.refresh(); }); }; return FileButtons; }(phosphor_widget_1.Widget)); exports.FileButtons = FileButtons; /** * The namespace for the `FileButtons` private data. */ var Private; (function (Private) { /** * Create the button group for a file buttons widget. */ function createButtons() { var create = document.createElement('button'); var upload = document.createElement('button'); var refresh = document.createElement('button'); var createContent = document.createElement('span'); var uploadContent = document.createElement('span'); var refreshContent = document.createElement('span'); var createIcon = document.createElement('span'); var uploadIcon = document.createElement('span'); var refreshIcon = document.createElement('span'); var dropdownIcon = document.createElement('span'); create.type = 'button'; upload.type = 'button'; refresh.type = 'button'; create.title = 'Create New...'; upload.title = 'Upload File(s)'; refresh.title = 'Refresh File List'; create.className = BUTTON_CLASS + " " + CREATE_CLASS; upload.className = BUTTON_CLASS + " " + UPLOAD_CLASS; refresh.className = BUTTON_CLASS + " " + REFRESH_CLASS; createContent.className = CONTENT_CLASS; uploadContent.className = CONTENT_CLASS; refreshContent.className = CONTENT_CLASS; // TODO make these icons configurable. createIcon.className = ICON_CLASS + ' fa fa-plus'; uploadIcon.className = ICON_CLASS + ' fa fa-upload'; refreshIcon.className = ICON_CLASS + ' fa fa-refresh'; dropdownIcon.className = DROPDOWN_CLASS + ' fa fa-caret-down'; createContent.appendChild(createIcon); createContent.appendChild(dropdownIcon); uploadContent.appendChild(uploadIcon); refreshContent.appendChild(refreshIcon); create.appendChild(createContent); upload.appendChild(uploadContent); refresh.appendChild(refreshContent); return { create: create, upload: upload, refresh: refresh }; } Private.createButtons = createButtons; /** * Create the upload input node for a file buttons widget. */ function createUploadInput() { var input = document.createElement('input'); input.type = 'file'; input.multiple = true; return input; } Private.createUploadInput = createUploadInput; /** * Create a new source file. */ function createNewFile(widget) { widget.model.newUntitled({ type: 'file' }).then(function (contents) { return widget.open(contents.path); }).catch(function (error) { utils.showErrorMessage(widget, 'New File Error', error); }); } Private.createNewFile = createNewFile; /** * Create a new folder. */ function createNewFolder(widget) { widget.model.newUntitled({ type: 'directory' }).then(function (contents) { widget.model.refresh(); }).catch(function (error) { utils.showErrorMessage(widget, 'New Folder Error', error); }); } Private.createNewFolder = createNewFolder; /** * Create a new item using a file creator. */ function createNewItem(widget, fileType, widgetName, kernelName) { var kernel; if (kernelName) { kernel = { name: kernelName }; } widget.model.newUntitled({ type: fileType.fileType, ext: fileType.extension }) .then(function (contents) { widget.createNew(contents.path, widgetName, kernel); }); } /** * Create a new dropdown menu for the create new button. */ function createDropdownMenu(widget) { var items = [ new phosphor_menus_1.MenuItem({ text: 'Text File', handler: function () { createNewFile(widget); } }), new phosphor_menus_1.MenuItem({ text: 'Folder', handler: function () { createNewFolder(widget); } }) ]; var registry = widget.manager.registry; var creators = registry.listCreators(); if (creators) { items.push(new phosphor_menus_1.MenuItem({ type: phosphor_menus_1.MenuItem.Separator })); } var _loop_1 = function(creator) { var fileType = registry.getFileType(creator.fileType); var item = new phosphor_menus_1.MenuItem({ text: creator.name, handler: function () { var widgetName = creator.widgetName || 'default'; var kernelName = creator.kernelName; createNewItem(widget, fileType, widgetName, kernelName); } }); items.push(item); }; for (var _i = 0, creators_1 = creators; _i < creators_1.length; _i++) { var creator = creators_1[_i]; _loop_1(creator); } return new phosphor_menus_1.Menu(items); } Private.createDropdownMenu = createDropdownMenu; /** * Upload an array of files to the server. */ function uploadFiles(widget, files) { var pending = files.map(function (file) { return uploadFile(widget, file); }); Promise.all(pending).then(function () { widget.model.refresh(); }).catch(function (error) { utils.showErrorMessage(widget, 'Upload Error', error); }); } Private.uploadFiles = uploadFiles; /** * Upload a file to the server. */ function uploadFile(widget, file) { return widget.model.upload(file).catch(function (error) { var exists = error.message.indexOf('already exists') !== -1; if (exists) { return uploadFileOverride(widget, file); } throw error; }); } /** * Upload a file to the server checking for override. */ function uploadFileOverride(widget, file) { var options = { title: 'Overwrite File?', body: "\"" + file.name + "\" already exists, overwrite?" }; return dialog_1.showDialog(options).then(function (button) { if (button.text !== 'Ok') { return; } return widget.model.upload(file, true); }); } })(Private || (Private = {}));