Browse Source

Merge pull request #47 from blink1073/update-handlers

Update handlers
Jason Grout 9 years ago
parent
commit
7bb21bea6c
7 changed files with 153 additions and 47 deletions
  1. 2 0
      README.md
  2. 2 2
      package.json
  3. 106 11
      src/filebrowser/plugin.css
  4. 8 4
      src/fileopener/index.ts
  5. 17 12
      src/fileopener/plugin.ts
  6. 5 5
      src/imagehandler/plugin.ts
  7. 13 13
      src/notebook/plugin.ts

+ 2 - 0
README.md

@@ -96,6 +96,8 @@ Follow the package install instructions first.
 Any bundler that understands how to `require()` files with `.js` and `.css`
 extensions can be used with this package.
 
+The following alias is required: `requirejs: 'requirejs/require'`.
+
 
 Usage Examples
 --------------

+ 2 - 2
package.json

@@ -1,6 +1,6 @@
 {
   "name": "jupyter-js-plugins",
-  "version": "0.2.3",
+  "version": "0.3.1",
   "description": "Plugins for JupyterLab",
   "main": "lib/index.js",
   "typings": "lib/index.d.ts",
@@ -9,7 +9,7 @@
     "jquery": "^2.2.0",
     "jquery-ui": "^1.10.5",
     "jupyter-js-cells": "^0.2.5",
-    "jupyter-js-filebrowser": "^0.4.9",
+    "jupyter-js-filebrowser": "^0.6.1",
     "jupyter-js-notebook": "^0.3.7",
     "jupyter-js-services": "^0.4.2",
     "jupyter-js-terminal": "^0.1.12",

+ 106 - 11
src/filebrowser/plugin.css

@@ -5,15 +5,18 @@
 .jp-FileBrowser {
   background-color: #F5F5F5;
   color: #757575;
-  font-family: "Helvetica Neue", Helvetica;
-  min-width: 300px;
+  font: 13px Helvetica, Arial, sans-serif;
+  height: 500px;
 }
 
 
 .jp-BreadCrumbs-item {
-  margin-right: 5px;
-  padding-bottom: 8px;
+  margin-left: 4px;
+  margin-right: 4px;
+  padding-top: 4px;
+  padding-bottom: 4px;
   border: 1px solid transparent;
+  cursor: pointer;
 }
 
 
@@ -33,7 +36,7 @@
 .jp-FileButtons-item {
   background-color: #FAFAFA;
   font-size: 16px;
-  border: 1px solid rgb(212,212,212);
+  border: 1px solid #757575;
   height: 30px;
   border-radius: 3px;
   margin-right: 3px;
@@ -41,22 +44,95 @@
 }
 
 
+.jp-FileButtons-item:focus {
+  outline: 0;
+}
+
+
+.jp-FileButtons-item:hover {
+  background-color: #EEEEEE;
+}
+
+
+.jp-FileButtons-drop {
+  margin-left: -0.5em;
+  color: #757575;
+}
+
+
+.jp-DirListing:focus {
+  outline: 0;
+}
+
+
 .jp-DirListing-header {
-  min-width: 300px;
+  background-color: #FAFAFA;
+  border-top: 1px solid #757575;
   border-bottom: 1px solid #757575;
 }
 
 
-.jp-DirListing-headerFile {
-  flex-basis: 200px;
+.jp-DirListing-headerText {
+  padding-left: 4px;
+  padding-right: 4px;
+  padding-top: 4px;
+  padding-bottom: 4px;
+}
+
+
+.jp-DirListing-headerText {
+  margin-right: auto;
+}
+
+
+.jp-DirListing-headerIcon {
+  margin-left: -0.5em;
+}
+
+
+
+.jp-DirListing-headerIcon {
   padding-top: 4px;
   padding-bottom: 4px;
 }
 
 
-.jp-DirListing-headerModified {
-  flex-basis: 95px;
+.jp-DirListing-headerItem:hover {
+  cursor: pointer;
+}
+
+
+.jp-DirListing-headerItem.jp-mod-selected {
+  font-weight: bold;
+}
+
+
+.jp-DirListing-headerFile {
+  flex-basis: 200px;
   padding-right: 5px;
+  border-right: 1px solid #757575;
+}
+
+
+.jp-DirListing-headerItem:focus {
+  outline: 0;
+}
+
+
+.jp-DirListing-headerTime {
+  flex-basis: 120px;
+  padding-right: 5px;
+  padding-left: 5px;
+}
+
+
+.jp-DirListing-headerItem.jp-mod-selected > .jp-DirListing-headerIcon:before {
+  content: "\f0d8";
+}
+
+
+.jp-DirListing-headerItem.jp-mod-selected.jp-mod-descending > .jp-DirListing-headerIcon:before {
+  content: "\f0d7";
 }
 
 
@@ -66,6 +142,17 @@
 }
 
 
+.jp-DirListing-item:hover {
+  background-color: #EEEEEE;
+  cursor: pointer;
+}
+
+
+.jp-DirListing-item.jp-mod-selected:hover {
+  background-color: #2196F3;
+}
+
+
 .jp-DirListing-itemFile {
   min-width: 200px;
 }
@@ -87,13 +174,21 @@
 
 
 .jp-DirListing-itemModified {
+  width: 120px;
+  min-width: 120px;
   padding-right: 5px;
-  width: 95px;
+  padding-left: 5px;
   padding-top: 4px;
   padding-bottom: 4px;
 }
 
 
+.jp-FileButtons-item {
+  color: #757575;
+  cursor: pointer;
+}
+
+
 .jp-FileButtons-item.jp-mod-selected {
   background-color: #2196F3;
   color: #F5F5F5;

+ 8 - 4
src/fileopener/index.ts

@@ -2,6 +2,10 @@
 // Distributed under the terms of the Modified BSD License.
 'use strict';
 
+import {
+  IContentsModel
+} from 'jupyter-js-services';
+
 import {
   Token
 } from 'phosphor-di';
@@ -23,7 +27,7 @@ interface IFileHandler {
   /**
    * A signal emitted when the widget is finished populating.
    */
-  finished: ISignal<IFileHandler, string>;
+  finished: ISignal<IFileHandler, IContentsModel>;
 
   /**
    * he list of file extensions supported by the handler.
@@ -33,7 +37,7 @@ interface IFileHandler {
   /**
    * Open the file and return a populated widget.
    */
-  open(path: string): Widget;
+  open(model: IContentsModel): Widget;
 
   /**
    * Close the file widget.
@@ -50,11 +54,11 @@ interface IFileOpener {
   /**
    * Open the file and add the widget to the application shell.
    */
-  open(path: string): Widget;
+  open(model: IContentsModel): Widget;
 
   /**
    * Register a file opener.
-   * 
+   *
    * @param handler - The file handler to register.
    */
   register(handler: IFileHandler): void;

+ 17 - 12
src/fileopener/plugin.ts

@@ -6,6 +6,10 @@ import {
   FileBrowserWidget, FileHandler
 } from 'jupyter-js-filebrowser';
 
+import {
+  IContentsModel
+} from 'jupyter-js-services';
+
 import {
   IAppShell, ICommandPalette, ICommandRegistry, IShortcutManager
 } from 'phosphide';
@@ -57,7 +61,7 @@ function resolve(container: Container): Promise<void> {
         caption: 'Create a new text file',
         handler: () => {
           browser.newUntitled('file', '.txt').then(
-            contents => opener.open(contents.path)
+            contents => opener.open(contents)
           );
         }
       });
@@ -92,7 +96,7 @@ function resolve(container: Container): Promise<void> {
         caption: 'Create a new Jupyter Notebook',
         handler: () => {
           browser.newUntitled('notebook').then(
-            contents => opener.open(contents.path)
+            contents => opener.open(contents)
           );
         }
       });
@@ -117,8 +121,8 @@ function resolve(container: Container): Promise<void> {
         }
       ]);
 
-      browser.widgetFactory = path => {
-        return opener.open(path);
+      browser.widgetFactory = model => {
+        return opener.open(model);
       }
     }
   });
@@ -171,10 +175,11 @@ class FileOpener implements IFileOpener {
   /**
    * Open a file and add it to the application shell.
    */
-  open(path: string): Widget {
+  open(model: IContentsModel): Widget {
     if (this._handlers.length === 0) {
       return;
     }
+    let path = model.path;
     let ext = '.' + path.split('.').pop();
     let handlers: IFileHandler[] = [];
     // Look for matching file extensions.
@@ -184,12 +189,12 @@ class FileOpener implements IFileOpener {
 
     // If there was only one match, use it.
     if (handlers.length === 1) {
-      return this._open(handlers[0], path);
+      return this._open(handlers[0], model);
 
     // If there were no matches, use default handler.
     } else if (handlers.length === 0) {
       if (this._defaultHandler !== null) {
-        return this._open(this._defaultHandler, path);
+        return this._open(this._defaultHandler, model);
       } else {
         throw new Error(`Could not open file '${path}'`);
       }
@@ -197,22 +202,22 @@ class FileOpener implements IFileOpener {
     // There are more than one possible handlers.
     } else {
       // TODO: Ask the user to choose one.
-      return this._open(handlers[0], path);
+      return this._open(handlers[0], model);
     }
   }
 
   /**
    * Handle an `openRequested` signal by invoking the appropriate handler.
    */
-  private _openRequested(browser: FileBrowserWidget, path: string): void {
-    this.open(path);
+  private _openRequested(browser: FileBrowserWidget, model: IContentsModel): void {
+    this.open(model);
   }
 
   /**
    * Open a file and add it to the application shell and give it focus.
    */
-  private _open(handler: IFileHandler, path: string): Widget {
-    let widget = handler.open(path);
+  private _open(handler: IFileHandler, model: IContentsModel): Widget {
+    let widget = handler.open(model);
     if (!widget.isAttached) {
       this._appShell.addToMainArea(widget);
     }

+ 5 - 5
src/imagehandler/plugin.ts

@@ -57,21 +57,21 @@ class ImageHandler extends AbstractFileHandler {
   /**
    * Get file contents given a path.
    */
-  protected getContents(path: string): Promise<IContentsModel> {
-    return this.manager.get(path, { type: 'file' });
+  protected getContents(model: IContentsModel): Promise<IContentsModel> {
+    return this.manager.get(model.path, { type: 'file' });
   }
 
   /**
    * Create the widget from an `IContentsModel`.
    */
-  protected createWidget(path: string): Widget {
-    let ext = path.split('.').pop();
+  protected createWidget(model: IContentsModel): Widget {
+    let ext = model.path.split('.').pop();
     var widget = new Widget();
     let image = document.createElement('img');
     widget.node.appendChild(image);
     widget.node.style.overflowX = 'auto';
     widget.node.style.overflowY = 'auto';
-    widget.title.text = path.split('/').pop();
+    widget.title.text = model.name;
     return widget;
   }
 

+ 13 - 13
src/notebook/plugin.ts

@@ -132,16 +132,16 @@ class NotebookFileHandler extends AbstractFileHandler {
   }
 
   /**
-   * Get file contents given a path.
+   * Get file contents given a contents model.
    */
-  protected getContents(path: string): Promise<IContentsModel> {
-    return this.manager.get(path, { type: 'notebook' });
+  protected getContents(model: IContentsModel): Promise<IContentsModel> {
+    return this.manager.get(model.path, { type: 'notebook' });
   }
 
   /**
    * Create the widget from an `IContentsModel`.
    */
-  protected createWidget(path: string): Widget {
+  protected createWidget(contents: IContentsModel): Widget {
     let model = new NotebookModel();
     let panel = new Panel();
 
@@ -150,11 +150,11 @@ class NotebookFileHandler extends AbstractFileHandler {
     b.appendChild(document.createTextNode('Execute Current Cell'))
     button.node.appendChild(b);
 
-    
+
     let widgetarea = new Widget();
-    let manager = new WidgetManager(widgetarea.node);    
-    
-    this.session.startNew({notebookPath: path}).then(s => {
+    let manager = new WidgetManager(widgetarea.node);
+
+    this.session.startNew({notebookPath: contents.path}).then(s => {
       b.addEventListener('click', ev=> {
         executeSelectedCell(model, s);
       })
@@ -165,9 +165,9 @@ class NotebookFileHandler extends AbstractFileHandler {
         }
         let comm = kernel.connectToComm('jupyter.widget', content.comm_id);
         console.log('comm message', msg);
-        
+
         let modelPromise = manager.handle_comm_open(comm, msg);
-        
+
 
         comm.onMsg = (msg) => {
           manager.handle_comm_open(comm, msg)
@@ -180,14 +180,14 @@ class NotebookFileHandler extends AbstractFileHandler {
       })
     })
 
-    
-    
+
+
 
     panel.addChild(button);
     panel.addChild(widgetarea)
     panel.addChild(new NotebookWidget(model));
 
-    panel.title.text = path.split('/').pop();
+    panel.title.text = contents.name;
     panel.addClass('jp-NotebookContainer')
     return panel;
   }