|
@@ -8,6 +8,8 @@ import {
|
|
|
JupyterLabPlugin
|
|
|
} from '@jupyterlab/application';
|
|
|
|
|
|
+import { Dialog, showDialog } from '@jupyterlab/apputils';
|
|
|
+
|
|
|
import { ISettingRegistry } from '@jupyterlab/coreutils';
|
|
|
|
|
|
import { ExtensionView } from '@jupyterlab/extensionmanager';
|
|
@@ -39,18 +41,7 @@ const plugin: JupyterLabPlugin<void> = {
|
|
|
router: IRouter
|
|
|
) => {
|
|
|
const settings = await registry.load(plugin.id);
|
|
|
- const enabled = settings.composite['enabled'] === true;
|
|
|
-
|
|
|
- // If the extension is enabled or disabled, refresh the page.
|
|
|
- app.restored.then(() => {
|
|
|
- settings.changed.connect(() => {
|
|
|
- router.reload();
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- if (!enabled) {
|
|
|
- return;
|
|
|
- }
|
|
|
+ let enabled = settings.composite['enabled'] === true;
|
|
|
|
|
|
const { shell, serviceManager } = app;
|
|
|
const view = new ExtensionView(serviceManager);
|
|
@@ -58,7 +49,29 @@ const plugin: JupyterLabPlugin<void> = {
|
|
|
view.id = 'extensionmanager.main-view';
|
|
|
view.title.label = 'Extensions';
|
|
|
restorer.add(view, view.id);
|
|
|
- shell.addToLeftArea(view);
|
|
|
+
|
|
|
+ if (enabled) {
|
|
|
+ shell.addToLeftArea(view);
|
|
|
+ }
|
|
|
+
|
|
|
+ // If the extension is enabled or disabled,
|
|
|
+ // add or remove it from the left area.
|
|
|
+ app.restored.then(() => {
|
|
|
+ settings.changed.connect(async () => {
|
|
|
+ enabled = settings.composite['enabled'] === true;
|
|
|
+ if (enabled && !view.isAttached) {
|
|
|
+ const accepted = await Private.showWarning();
|
|
|
+ if (!accepted) {
|
|
|
+ settings.set('enabled', false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ shell.addToLeftArea(view);
|
|
|
+ } else if (!enabled && view.isAttached) {
|
|
|
+ view.close();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
addCommands(app, view);
|
|
|
}
|
|
|
};
|
|
@@ -101,3 +114,36 @@ function addCommands(app: JupyterLab, view: ExtensionView): void {
|
|
|
* Export the plugin as the default.
|
|
|
*/
|
|
|
export default plugin;
|
|
|
+
|
|
|
+/**
|
|
|
+ * A namespace for module-private functions.
|
|
|
+ */
|
|
|
+namespace Private {
|
|
|
+ /**
|
|
|
+ * Show a warning dialog about extension security.
|
|
|
+ *
|
|
|
+ * @returns whether the user accepted the dialog.
|
|
|
+ */
|
|
|
+ export async function showWarning(): Promise<boolean> {
|
|
|
+ return showDialog({
|
|
|
+ title: 'Enable Extension Manager?',
|
|
|
+ body:
|
|
|
+ "Thanks for trying out JupyterLab's extension manager. " +
|
|
|
+ 'The JupyterLab development team is excited to have a robust ' +
|
|
|
+ 'third-party extension community. ' +
|
|
|
+ 'However, we cannot vouch for every extension, ' +
|
|
|
+ 'and some may introduce security risks. ' +
|
|
|
+ 'Do you want to continue?',
|
|
|
+ buttons: [
|
|
|
+ Dialog.cancelButton({ label: 'DISABLE' }),
|
|
|
+ Dialog.warnButton({ label: 'ENABLE' })
|
|
|
+ ]
|
|
|
+ }).then(result => {
|
|
|
+ if (result.button.accept) {
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|