Procházet zdrojové kódy

Update usages of dialogs

Steven Silvester před 7 roky
rodič
revize
b49714ecbf

+ 2 - 1
packages/application-extension/package.json

@@ -14,7 +14,8 @@
   "dependencies": {
     "@jupyterlab/application": "^0.8.3",
     "@jupyterlab/apputils": "^0.8.2",
-    "@jupyterlab/coreutils": "^0.8.1"
+    "@jupyterlab/coreutils": "^0.8.1",
+    "@phosphor/virtualdom": "^1.1.1"
   },
   "devDependencies": {
     "rimraf": "^2.5.2",

+ 14 - 6
packages/application-extension/src/index.ts

@@ -13,6 +13,9 @@ import {
   IStateDB, PageConfig
 } from '@jupyterlab/coreutils';
 
+import {
+  h
+} from '@phosphor/virtualdom';
 
 /**
  * The command IDs used by the application plugin.
@@ -47,12 +50,17 @@ const mainPlugin: JupyterLabPlugin<void> = {
     // Temporary build message for manual rebuild.
     let buildMessage = PageConfig.getOption('buildRequired');
     if (buildMessage) {
-      let body = document.createElement('div');
-      body.innerHTML = (
-        '<p>JupyterLab build is out of date.<br>' +
-        'Please run <code>jupyter lab build</code> from<br>' +
-        'the command line and relaunch.</p>'
-      );
+      let body = h.div([
+        h.p([
+          'JupyterLab build is out of date',
+          h.br(),
+          'Please run',
+          h.code('jupyter lab build'),
+          'from',
+          h.br(),
+          'the command line and relaunch'
+        ])
+      ]);
       showDialog({
         title: 'Build Recommended',
         body,

+ 43 - 15
packages/apputils/src/clientsession.ts

@@ -25,6 +25,10 @@ import {
   ISignal, Signal
 } from '@phosphor/signaling';
 
+import {
+  h
+} from '@phosphor/virtualdom';
+
 import {
   Widget
 } from '@phosphor/widgets';
@@ -661,11 +665,9 @@ class ClientSession implements IClientSession {
     } catch (err) {
       // no-op
     }
-    let body = document.createElement('pre');
-    body.textContent = response;
     return showDialog({
       title: 'Error Starting Kernel',
-      body: new Widget({ node: body }),
+      body: h.pre(response),
       buttons: [Dialog.okButton()]
     }).then(() => void 0);
   }
@@ -870,6 +872,43 @@ namespace Private {
    */
   export
   function selectKernel(session: ClientSession): Promise<Kernel.IModel> {
+    let select = Dialog.okButton({ label: 'SELECT' });
+    return showDialog({
+      title: 'Select Kernel',
+      body: new KernelSelector(session),
+      buttons: [Dialog.cancelButton(), select]
+    }).then(result => {
+      if (!result.accept) {
+        return void 0;
+      }
+      return result.value;
+    });
+  }
+
+  /**
+   * A widget that provides a kernel selection.
+   */
+  class KernelSelector extends Widget {
+    /**
+     * Create a new kernel selector widget.
+     */
+    constructor(session: ClientSession) {
+      super({ node: createSelectorNode(session) });
+    }
+
+    /**
+     * Get the value of the kernel selector widget.
+     */
+    getValue(): Kernel.IModel {
+      let selector = this.node.querySelector('select') as HTMLSelectElement;
+      return JSON.parse(selector.value) as Kernel.IModel;
+    }
+  }
+
+  /**
+   * Create a node for a kernel selector widget.
+   */
+  function createSelectorNode(session: ClientSession) {
     // Create the dialog body.
     let body = document.createElement('div');
     let text = document.createElement('label');
@@ -880,18 +919,7 @@ namespace Private {
     let selector = document.createElement('select');
     ClientSession.populateKernelSelect(selector, options);
     body.appendChild(selector);
-
-    let select = Dialog.okButton({ label: 'SELECT' });
-    return showDialog({
-      title: 'Select Kernel',
-      body: new Widget({ node: body }),
-      buttons: [Dialog.cancelButton(), select]
-    }).then(result => {
-      if (!result.accept) {
-        return void 0;
-      }
-      return JSON.parse(selector.value) as Kernel.IModel;
-    });
+    return body;
   }
 
   /**

+ 19 - 22
packages/docmanager/src/dialogs.ts

@@ -36,6 +36,7 @@ const FILE_DIALOG_CLASS = 'jp-FileDialog';
  */
 const RENAME_NEWNAME_TITLE_CLASS = 'jp-new-name-title';
 
+
 /**
  * A stripped-down interface for a file container.
  */
@@ -57,7 +58,20 @@ interface IFileContainer extends JSONObject {
  */
 export
 function renameDialog(manager: IDocumentManager, oldPath: string): Promise<Contents.IModel | null> {
-  return (new RenameHandler(manager, oldPath)).showDialog();
+  let body = new RenameHandler(oldPath);
+  return showDialog({
+    title: 'Rename File',
+    body,
+    primaryElement: 'input',
+    buttons: [Dialog.cancelButton(), Dialog.okButton({ label: 'RENAME' })]
+  }).then(result => {
+    if (!result.accept || !result.value) {
+      return null;
+    }
+    let basePath = PathExt.dirname(oldPath);
+    let newPath = PathExt.join(basePath, result.value);
+    return renameFile(manager, oldPath, newPath);
+  });
 }
 
 
@@ -112,11 +126,9 @@ class RenameHandler extends Widget {
   /**
    * Construct a new "rename" dialog.
    */
-  constructor(manager: IDocumentManager, oldPath: string) {
+  constructor(oldPath: string) {
     super({ node: Private.createRenameNode(oldPath) });
     this.addClass(FILE_DIALOG_CLASS);
-    this._manager = manager;
-    this._oldPath = oldPath;
     let ext = PathExt.extname(oldPath);
     let value = this.inputNode.value = PathExt.basename(oldPath);
     this.inputNode.setSelectionRange(0, value.length - ext.length);
@@ -130,26 +142,11 @@ class RenameHandler extends Widget {
   }
 
   /**
-   * Show the rename dialog.
+   * Get the value of the widget.
    */
-  showDialog(): Promise<Contents.IModel | null> {
-    return showDialog({
-      title: 'Rename File',
-      body: this.node,
-      primaryElement: this.inputNode,
-      buttons: [Dialog.cancelButton(), Dialog.okButton({ label: 'RENAME' })]
-    }).then(result => {
-      if (!result.accept || !this.inputNode.value) {
-        return null;
-      }
-      let basePath = PathExt.dirname(this._oldPath);
-      let newPath = PathExt.join(basePath, this.inputNode.value);
-      return renameFile(this._manager, this._oldPath, newPath);
-    });
+  getValue(): string {
+    return this.inputNode.value;
   }
-
-  private _oldPath: string;
-  private _manager: IDocumentManager;
 }
 
 

+ 2 - 2
packages/docmanager/src/savehandler.ts

@@ -171,9 +171,9 @@ class SaveHandler implements IDisposable {
         return;
       }
       this._inDialog = false;
-      if (result.label === 'OVERWRITE') {
+      if (result.button.label === 'OVERWRITE') {
         return this._finishSave();
-      } else if (result.label === 'REVERT') {
+      } else if (result.button.label === 'REVERT') {
         return this._context.revert();
       }
     });

+ 32 - 5
packages/docregistry/src/context.ts

@@ -522,16 +522,14 @@ namespace Private {
    */
   export
   function getSavePath(path: string): Promise<string | undefined> {
-    let input = document.createElement('input');
-    input.value = path;
     let saveBtn = Dialog.okButton({ label: 'SAVE' });
     return showDialog({
       title: 'Save File As..',
-      body: input,
+      body: new SaveWidget(path),
       buttons: [Dialog.cancelButton(), saveBtn]
     }).then(result => {
-      if (result.label === 'SAVE') {
-        return input.value;
+      if (result.button.label === 'SAVE') {
+        return result.value;
       }
       return;
     });
@@ -542,4 +540,33 @@ namespace Private {
    */
   export
   function noOp() { /* no-op */ }
+
+  /*
+   * A widget that gets a file path from a user.
+   */
+  class SaveWidget extends Widget {
+    /**
+     * Construct a new save widget.
+     */
+    constructor(path: string) {
+      super({ node: createSaveNode(path) });
+    }
+
+    /**
+     * Get the value for the widget.
+     */
+    getValue(): string {
+      let input = this.node.querySelector('input') as HTMLInputElement;
+      return input.value;
+    }
+  }
+
+  /**
+   * Create the node for a save widget.
+   */
+  function createSaveNode(path: string): HTMLElement {
+    let input = document.createElement('input');
+    input.value = path;
+    return input;
+  }
 }

+ 5 - 5
packages/help-extension/src/index.ts

@@ -18,7 +18,7 @@ import {
 } from '@phosphor/messaging';
 
 import {
-  h, VirtualDOM
+  h
 } from '@phosphor/virtualdom';
 
 import {
@@ -227,13 +227,13 @@ function activate(app: JupyterLab, mainMenu: IMainMenu, palette: ICommandPalette
         h.span({className: 'jp-About-release'}, release),
         h.span({className: 'jp-About-version'}, versionNumber)
       );
-      let title = VirtualDOM.realize(h.span({className: 'jp-About-header'},
+      let title = h.span({className: 'jp-About-header'},
         headerLogo,
         h.div({className: 'jp-About-header-info'},
           headerWordmark,
           versionInfo
         )
-      ));
+      );
 
       //Create the body of the about dialog
       let jupyterURL = 'https://jupyter.org/about.html';
@@ -243,10 +243,10 @@ function activate(app: JupyterLab, mainMenu: IMainMenu, palette: ICommandPalette
         h.a({href: jupyterURL, target: '_blank', className: 'jp-Button-flat'}, "ABOUT PROJECT JUPYTER")
       );
       let copyright = h.span({className: 'jp-About-copyright'}, "© 2017 Project Jupyter");
-      let body = VirtualDOM.realize(h.div({ className: 'jp-About-body' },
+      let body = h.div({ className: 'jp-About-body' },
         externalLinks,
         copyright
-      ));
+      );
 
       showDialog({
         title,

+ 15 - 4
packages/notebook/src/actions.ts

@@ -26,6 +26,10 @@ import {
   ElementExt
 } from '@phosphor/domutils';
 
+import {
+  h
+} from '@phosphor/virtualdom';
+
 import {
   INotebookModel
 } from './model';
@@ -36,7 +40,16 @@ import {
 
 
 // The message to display to the user when prompting to trust the notebook.
-const TRUST_MESSAGE = '<p>A trusted Jupyter notebook may execute hidden malicious code when you open it.<br>Selecting trust will re-render this notebook in a trusted state.<br>For more information, see the <a href="http://ipython.org/ipython-doc/2/notebook/security.html">Jupyter security documentation</a>.</p>';
+const TRUST_MESSAGE = h.p([
+  'A trusted Jupyter notebook may execute hidden malicious code when you ',
+  'open it.',
+  h.br(),
+  'Selecting trust will re-render this notebook in a trusted state.',
+  h.br(),
+  'For more information, see the',
+  h.a({ href: 'http://ipython.org/ipython-doc/2/notebook/security.html' },
+      'Jupyter security documentation'),
+]);
 
 
 /**
@@ -1016,10 +1029,8 @@ namespace NotebookActions {
         buttons: [Dialog.okButton()]
       }).then(() => void 0);
     }
-    let body = document.createElement('div');
-    body.innerHTML = TRUST_MESSAGE;
     return showDialog({
-      body,
+      body: TRUST_MESSAGE,
       title: 'Trust this notebook?',
       buttons: [Dialog.cancelButton(), Dialog.warnButton()]
     }).then(result => {