From 0fcce28d1691e08279cb7905b8a3a874d5a08fbf Mon Sep 17 00:00:00 2001 From: Jeremy Tuloup Date: Tue, 8 Dec 2020 22:05:28 +0100 Subject: [PATCH 1/3] Add a running page --- builder/index.js | 5 ++ builder/package.json | 2 + builder/style.css | 2 + jupyterlab_classic/app.py | 15 ++++++ jupyterlab_classic/templates/running.html | 36 +++++++++++++++ packages/running-extension/package.json | 53 ++++++++++++++++++++++ packages/running-extension/src/index.ts | 36 +++++++++++++++ packages/running-extension/style/base.css | 3 ++ packages/running-extension/style/index.css | 3 ++ packages/running-extension/tsconfig.json | 8 ++++ yarn.lock | 29 ++++++++++++ 11 files changed, 192 insertions(+) create mode 100644 jupyterlab_classic/templates/running.html create mode 100644 packages/running-extension/package.json create mode 100644 packages/running-extension/src/index.ts create mode 100644 packages/running-extension/style/base.css create mode 100644 packages/running-extension/style/index.css create mode 100644 packages/running-extension/tsconfig.json diff --git a/builder/index.js b/builder/index.js index 81e274d90..4615c2206 100644 --- a/builder/index.js +++ b/builder/index.js @@ -114,6 +114,11 @@ async function main() { ].includes(id) ) ]); + } else if (page === 'running') { + mods = mods.concat([ + require('@jupyterlab-classic/running-extension'), + require('@jupyterlab/running-extension') + ]); } else if (page === 'notebooks') { mods = mods.concat([ require('@jupyterlab/completer-extension').default.filter(({ id }) => diff --git a/builder/package.json b/builder/package.json index f9a5c0ce5..2447ad297 100644 --- a/builder/package.json +++ b/builder/package.json @@ -15,6 +15,7 @@ "@jupyterlab-classic/docmanager-extension": "^0.1.0", "@jupyterlab-classic/filebrowser-extension": "^0.1.0", "@jupyterlab-classic/notebook-extension": "^0.1.0", + "@jupyterlab-classic/running-extension": "^0.1.0", "@jupyterlab-classic/ui-components": "^0.1.0", "@jupyterlab/apputils-extension": "^3.0.0-rc.12", "@jupyterlab/codemirror-extension": "^3.0.0-rc.12", @@ -24,6 +25,7 @@ "@jupyterlab/mathjax2-extension": "^3.0.0-rc.12", "@jupyterlab/notebook-extension": "^3.0.0-rc.12", "@jupyterlab/rendermime-extension": "^3.0.0-rc.12", + "@jupyterlab/running-extension": "^3.0.0-rc.12", "@jupyterlab/shortcuts-extension": "^3.0.0-rc.12", "@jupyterlab/tooltip-extension": "^3.0.0-rc.12", "@jupyterlab/theme-light-extension": "^3.0.0-rc.12", diff --git a/builder/style.css b/builder/style.css index 7a8664963..5b4cd751e 100644 --- a/builder/style.css +++ b/builder/style.css @@ -1,11 +1,13 @@ @import url('~@jupyterlab-classic/application-extension/style/index.css'); @import url('~@jupyterlab-classic/filebrowser-extension/style/index.css'); @import url('~@jupyterlab-classic/notebook-extension/style/index.css'); +@import url('~@jupyterlab-classic/running-extension/style/index.css'); @import url('~@jupyterlab-classic/ui-components/style/index.css'); /* TODO: check is the the extension package can be used directly */ @import url('~@jupyterlab/completer/style/index.css'); @import url('~@jupyterlab/tooltip/style/index.css'); +@import url('~@jupyterlab/running/style/index.css'); @import url('~@jupyterlab/codemirror-extension/style/index.css'); @import url('~@jupyterlab/docmanager-extension/style/index.css'); diff --git a/jupyterlab_classic/app.py b/jupyterlab_classic/app.py index da4d5c7f3..8aa089933 100644 --- a/jupyterlab_classic/app.py +++ b/jupyterlab_classic/app.py @@ -87,6 +87,20 @@ class ClassicTreeHandler(ClassicPageConfigMixin, ExtensionHandlerJinjaMixin, Ext ) +class ClassicRunningHandler(ClassicPageConfigMixin, ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler): + @web.authenticated + def get(self, path=None): + page_config = self.get_page_config() + return self.write( + self.render_template( + "running.html", + base_url=self.base_url, + token=self.settings["token"], + page_config=page_config, + ) + ) + + class ClassicNotebookHandler(ClassicPageConfigMixin, ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler): @web.authenticated def get(self, path=None): @@ -117,6 +131,7 @@ class ClassicApp(NBClassicConfigShimMixin, LabServerApp): def initialize_handlers(self): super().initialize_handlers() self.handlers.append(("/classic/tree(.*)", ClassicTreeHandler)) + self.handlers.append(("/classic/running", ClassicRunningHandler)) self.handlers.append(("/classic/notebooks(.*)", ClassicNotebookHandler)) def initialize_templates(self): diff --git a/jupyterlab_classic/templates/running.html b/jupyterlab_classic/templates/running.html new file mode 100644 index 000000000..126474aa4 --- /dev/null +++ b/jupyterlab_classic/templates/running.html @@ -0,0 +1,36 @@ + + + + + + {{page_config['appName'] | e}} - Running Sessions + + + + {# Copy so we do not modify the page_config with updates. #} + {% set page_config_full = page_config.copy() %} + + {# Set a dummy variable - we just want the side effect of the update. #} + {% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %} + + {# Sentinel value to say that we are on the tree page #} + {% set _ = page_config_full.update(classicPage='running') %} + + + + + + + + diff --git a/packages/running-extension/package.json b/packages/running-extension/package.json new file mode 100644 index 000000000..af0cf2e3f --- /dev/null +++ b/packages/running-extension/package.json @@ -0,0 +1,53 @@ +{ + "name": "@jupyterlab-classic/running-extension", + "version": "0.1.0", + "description": "JupyterLab Classic - Running Extension", + "homepage": "https://github.com/jtpio/jupyterlab-classic", + "bugs": { + "url": "https://github.com/jtpio/jupyterlab-classic/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/jtpio/jupyterlab-classic.git" + }, + "license": "BSD-3-Clause", + "author": "Project Jupyter", + "sideEffects": [ + "style/**/*.css" + ], + "main": "lib/index.js", + "types": "lib/index.d.ts", + "style": "style/index.css", + "directories": { + "lib": "lib/" + }, + "files": [ + "lib/*.d.ts", + "lib/*.js.map", + "lib/*.js", + "schema/*.json", + "style/**/*.css" + ], + "scripts": { + "build": "tsc -b", + "clean": "rimraf lib && rimraf tsconfig.tsbuildinfo", + "docs": "typedoc src", + "prepublishOnly": "npm run build", + "watch": "tsc -b --watch" + }, + "dependencies": { + "@jupyterlab/application": "^3.0.0-rc.12", + "@jupyterlab/running": "^3.0.0-rc.12", + "@jupyterlab/translation": "^3.0.0-rc.12" + }, + "devDependencies": { + "rimraf": "~3.0.0", + "typescript": "~4.0.2" + }, + "publishConfig": { + "access": "public" + }, + "jupyterlab": { + "extension": true + } +} diff --git a/packages/running-extension/src/index.ts b/packages/running-extension/src/index.ts new file mode 100644 index 000000000..ebdc76b66 --- /dev/null +++ b/packages/running-extension/src/index.ts @@ -0,0 +1,36 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. + +import { + JupyterFrontEnd, + JupyterFrontEndPlugin +} from '@jupyterlab/application'; + +import { IRunningSessionManagers, RunningSessions } from '@jupyterlab/running'; + +import { ITranslator } from '@jupyterlab/translation'; + +/** + * The default running sessions extension. + */ +const plugin: JupyterFrontEndPlugin = { + id: '@jupyterlab-classic/running-extension:plugin', + requires: [IRunningSessionManagers], + autoStart: true, + activate: ( + app: JupyterFrontEnd, + manager: IRunningSessionManagers, + translator: ITranslator + ): void => { + const running = new RunningSessions(manager, translator); + running.id = 'jp-running-sessions'; + + // re-add the widget to the main area + app.shell.add(running, 'main'); + } +}; + +/** + * Export the plugin as default. + */ +export default plugin; diff --git a/packages/running-extension/style/base.css b/packages/running-extension/style/base.css new file mode 100644 index 000000000..efb564000 --- /dev/null +++ b/packages/running-extension/style/base.css @@ -0,0 +1,3 @@ +.jp-RunningSessions { + height: 100%; +} diff --git a/packages/running-extension/style/index.css b/packages/running-extension/style/index.css new file mode 100644 index 000000000..0dfc4ba6c --- /dev/null +++ b/packages/running-extension/style/index.css @@ -0,0 +1,3 @@ +@import url('~@jupyterlab/running/style/index.css'); + +@import url('./base.css'); diff --git a/packages/running-extension/tsconfig.json b/packages/running-extension/tsconfig.json new file mode 100644 index 000000000..399b75b7a --- /dev/null +++ b/packages/running-extension/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfigbase", + "compilerOptions": { + "outDir": "lib", + "rootDir": "src" + }, + "include": ["src/**/*"] +} diff --git a/yarn.lock b/yarn.lock index 162a64f03..976e09306 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2148,6 +2148,35 @@ lodash.escape "^4.0.1" marked "^1.1.1" +"@jupyterlab/running-extension@^3.0.0-rc.12": + version "3.0.0-rc.13" + resolved "https://registry.yarnpkg.com/@jupyterlab/running-extension/-/running-extension-3.0.0-rc.13.tgz#dab8b62512e0ef7318393c5683d0104cb84c7183" + integrity sha512-vdAY+wsvSwZoXfnO/U7Md+bnBH7RSbbUxXjwuGEJ4ht1eaOOEFs9llIx9CuJeN/FQkfZufpH/MV5JM5FqHtKMw== + dependencies: + "@jupyterlab/application" "^3.0.0-rc.13" + "@jupyterlab/coreutils" "^5.0.0-rc.13" + "@jupyterlab/docregistry" "^3.0.0-rc.13" + "@jupyterlab/running" "^3.0.0-rc.13" + "@jupyterlab/services" "^6.0.0-rc.13" + "@jupyterlab/translation" "^3.0.0-rc.13" + "@jupyterlab/ui-components" "^3.0.0-rc.13" + "@lumino/algorithm" "^1.3.3" + "@lumino/signaling" "^1.4.3" + "@lumino/widgets" "^1.16.1" + +"@jupyterlab/running@^3.0.0-rc.12", "@jupyterlab/running@^3.0.0-rc.13": + version "3.0.0-rc.13" + resolved "https://registry.yarnpkg.com/@jupyterlab/running/-/running-3.0.0-rc.13.tgz#df0d732d23d6c0c56a1512bfb0a988b05a8af4df" + integrity sha512-852VZ6+H3xSl6DtPBe5VE1NhVprY6xgL9a5EAxeqrTljeC2IbBgt9FjBjYDfBcBkj9kdupuyU8biHbFJKNlSiw== + dependencies: + "@jupyterlab/apputils" "^3.0.0-rc.13" + "@jupyterlab/translation" "^3.0.0-rc.13" + "@jupyterlab/ui-components" "^3.0.0-rc.13" + "@lumino/coreutils" "^1.5.3" + "@lumino/disposable" "^1.4.3" + "@lumino/signaling" "^1.4.3" + react "^17.0.1" + "@jupyterlab/services@^6.0.0-rc.12": version "6.0.0-rc.12" resolved "https://registry.yarnpkg.com/@jupyterlab/services/-/services-6.0.0-rc.12.tgz#f0b1415ee3f203d74ac791193b87d5b126fc8ea2" From d1e051077770434c355ab3318106b926996b2256 Mon Sep 17 00:00:00 2001 From: Jeremy Tuloup Date: Tue, 8 Dec 2020 22:24:08 +0100 Subject: [PATCH 2/3] Add commands to open tree and running --- packages/application-extension/src/index.ts | 77 +++++++++++++++++---- 1 file changed, 65 insertions(+), 12 deletions(-) diff --git a/packages/application-extension/src/index.ts b/packages/application-extension/src/index.ts index e9330693b..4c8b3006c 100644 --- a/packages/application-extension/src/index.ts +++ b/packages/application-extension/src/index.ts @@ -44,19 +44,17 @@ namespace CommandIDs { * Toggle the Zen mode */ export const toggleZen = 'application:toggle-zen'; -} -/** - * A plugin to dispose the Tabs menu - */ -const noTabsMenu: JupyterFrontEndPlugin = { - id: '@jupyterlab-classic/application-extension:no-tabs-menu', - requires: [IMainMenu], - autoStart: true, - activate: (app: JupyterFrontEnd, menu: IMainMenu) => { - menu.tabsMenu.dispose(); - } -}; + /** + * Open the tree page. + */ + export const openTree = 'application:open-tree'; + + /** + * Open the runnning page. + */ + export const openRunning = 'application:open-running'; +} /** * The logo plugin. @@ -83,6 +81,60 @@ const logo: JupyterFrontEndPlugin = { } }; +/** + * A plugin to dispose the Tabs menu + */ +const noTabsMenu: JupyterFrontEndPlugin = { + id: '@jupyterlab-classic/application-extension:no-tabs-menu', + requires: [IMainMenu], + autoStart: true, + activate: (app: JupyterFrontEnd, menu: IMainMenu) => { + menu.tabsMenu.dispose(); + } +}; + +/** + * Add commands to open the tree and running pages. + */ +const pages: JupyterFrontEndPlugin = { + id: '@jupyterlab-classic/application-extension:pages', + autoStart: true, + optional: [ICommandPalette, IMainMenu], + activate: ( + app: JupyterFrontEnd, + palette: ICommandPalette, + menu: IMainMenu + ): void => { + const baseUrl = PageConfig.getBaseUrl(); + + app.commands.addCommand(CommandIDs.openTree, { + label: 'Open the File Browser', + execute: (args: any) => { + window.open(`${baseUrl}classic/tree`); + } + }); + + app.commands.addCommand(CommandIDs.openRunning, { + label: 'Open the Running Sessions', + execute: (args: any) => { + window.open(`${baseUrl}classic/running`); + } + }); + + if (palette) { + palette.addItem({ command: CommandIDs.openTree, category: 'View' }); + palette.addItem({ command: CommandIDs.openRunning, category: 'View' }); + } + + if (menu) { + menu.viewMenu.addGroup( + [{ command: CommandIDs.openTree }, { command: CommandIDs.openRunning }], + 0 + ); + } + } +}; + /** * The default paths for a JupyterLab Classic app. */ @@ -275,6 +327,7 @@ const zen: JupyterFrontEndPlugin = { const plugins: JupyterFrontEndPlugin[] = [ logo, noTabsMenu, + pages, paths, router, sessionDialogs, From c4cc1613d1f859b39fc99296156ebc10b1bc2486 Mon Sep 17 00:00:00 2001 From: Jeremy Tuloup Date: Tue, 8 Dec 2020 22:36:08 +0100 Subject: [PATCH 3/3] Add a command to open JupyterLab --- packages/application-extension/src/index.ts | 33 ++++++++++++++++----- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/packages/application-extension/src/index.ts b/packages/application-extension/src/index.ts index 4c8b3006c..df95f4e9a 100644 --- a/packages/application-extension/src/index.ts +++ b/packages/application-extension/src/index.ts @@ -45,6 +45,11 @@ namespace CommandIDs { */ export const toggleZen = 'application:toggle-zen'; + /** + * Open JupyterLab + */ + export const openLab = 'application:open-lab'; + /** * Open the tree page. */ @@ -107,28 +112,42 @@ const pages: JupyterFrontEndPlugin = { ): void => { const baseUrl = PageConfig.getBaseUrl(); + app.commands.addCommand(CommandIDs.openLab, { + label: 'Open JupyterLab', + execute: () => { + window.open(`${baseUrl}lab`); + } + }); + app.commands.addCommand(CommandIDs.openTree, { label: 'Open the File Browser', - execute: (args: any) => { + execute: () => { window.open(`${baseUrl}classic/tree`); } }); app.commands.addCommand(CommandIDs.openRunning, { label: 'Open the Running Sessions', - execute: (args: any) => { + execute: () => { window.open(`${baseUrl}classic/running`); } }); if (palette) { - palette.addItem({ command: CommandIDs.openTree, category: 'View' }); - palette.addItem({ command: CommandIDs.openRunning, category: 'View' }); + [CommandIDs.openLab, CommandIDs.openRunning, CommandIDs.openTree].forEach( + command => { + palette.addItem({ command, category: 'View' }); + } + ); } if (menu) { menu.viewMenu.addGroup( - [{ command: CommandIDs.openTree }, { command: CommandIDs.openRunning }], + [ + { command: CommandIDs.openLab }, + { command: CommandIDs.openTree }, + { command: CommandIDs.openRunning } + ], 0 ); } @@ -235,7 +254,7 @@ const topVisibility: JupyterFrontEndPlugin = { app.commands.addCommand(CommandIDs.toggleTop, { label: 'Show Header', - execute: (args: any) => { + execute: () => { top.setHidden(top.isVisible); }, isToggled: () => top.isVisible @@ -294,7 +313,7 @@ const zen: JupyterFrontEndPlugin = { let zenModeEnabled = false; commands.addCommand(CommandIDs.toggleZen, { label: 'Toggle Zen Mode', - execute: (args: any) => { + execute: () => { if (!zenModeEnabled) { elem.requestFullscreen(); toggleOn();