mirror of
https://github.com/jupyter/notebook.git
synced 2025-01-18 11:55:46 +08:00
Merge pull request #202 from fcollonval/fix/Route-on-file-browser-navigation
Route on file browser navigation
This commit is contained in:
commit
ac9bac4f3c
@ -10,3 +10,21 @@ test('Tree', async ({ page }) => {
|
|||||||
const button = await page.$('text="New Notebook"');
|
const button = await page.$('text="New Notebook"');
|
||||||
expect(button).toBeDefined();
|
expect(button).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should go to subfolder', async ({ page }) => {
|
||||||
|
await page.goto(`${BASE_URL}retro/tree/binder`);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await page.waitForSelector('.jp-FileBrowser-crumbs >> text=/binder/')
|
||||||
|
).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should update url when navigating in filebrowser', async ({ page }) => {
|
||||||
|
await page.goto(`${BASE_URL}retro/tree`);
|
||||||
|
|
||||||
|
await page.dblclick('.jp-FileBrowser-listing >> text=binder');
|
||||||
|
|
||||||
|
await page.waitForSelector('.jp-FileBrowser-crumbs >> text=/binder/');
|
||||||
|
|
||||||
|
expect(page.url()).toEqual(`${BASE_URL}retro/tree/binder`);
|
||||||
|
});
|
||||||
|
@ -50,6 +50,8 @@
|
|||||||
"@jupyterlab/mainmenu": "^3.1.8",
|
"@jupyterlab/mainmenu": "^3.1.8",
|
||||||
"@jupyterlab/settingregistry": "^3.1.8",
|
"@jupyterlab/settingregistry": "^3.1.8",
|
||||||
"@jupyterlab/translation": "^3.1.8",
|
"@jupyterlab/translation": "^3.1.8",
|
||||||
|
"@lumino/coreutils": "^1.8.0",
|
||||||
|
"@lumino/disposable": "^1.7.0",
|
||||||
"@lumino/widgets": "^1.23.0",
|
"@lumino/widgets": "^1.23.0",
|
||||||
"@retrolab/application": "^0.3.2",
|
"@retrolab/application": "^0.3.2",
|
||||||
"@retrolab/ui-components": "^0.3.2"
|
"@retrolab/ui-components": "^0.3.2"
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
import {
|
import {
|
||||||
ILabStatus,
|
ILabStatus,
|
||||||
IRouter,
|
IRouter,
|
||||||
|
ITreePathUpdater,
|
||||||
JupyterFrontEnd,
|
JupyterFrontEnd,
|
||||||
JupyterFrontEndPlugin,
|
JupyterFrontEndPlugin,
|
||||||
Router
|
Router
|
||||||
@ -16,7 +17,7 @@ import {
|
|||||||
ICommandPalette
|
ICommandPalette
|
||||||
} from '@jupyterlab/apputils';
|
} from '@jupyterlab/apputils';
|
||||||
|
|
||||||
import { PageConfig, PathExt } from '@jupyterlab/coreutils';
|
import { PageConfig, PathExt, URLExt } from '@jupyterlab/coreutils';
|
||||||
|
|
||||||
import { IDocumentManager, renameDialog } from '@jupyterlab/docmanager';
|
import { IDocumentManager, renameDialog } from '@jupyterlab/docmanager';
|
||||||
|
|
||||||
@ -30,6 +31,10 @@ import { RetroApp, RetroShell, IRetroShell } from '@retrolab/application';
|
|||||||
|
|
||||||
import { jupyterIcon, retroInlineIcon } from '@retrolab/ui-components';
|
import { jupyterIcon, retroInlineIcon } from '@retrolab/ui-components';
|
||||||
|
|
||||||
|
import { PromiseDelegate } from '@lumino/coreutils';
|
||||||
|
|
||||||
|
import { DisposableDelegate, DisposableSet } from '@lumino/disposable';
|
||||||
|
|
||||||
import { Widget } from '@lumino/widgets';
|
import { Widget } from '@lumino/widgets';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,6 +75,11 @@ namespace CommandIDs {
|
|||||||
* Open the tree page.
|
* Open the tree page.
|
||||||
*/
|
*/
|
||||||
export const openTree = 'application:open-tree';
|
export const openTree = 'application:open-tree';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve tree path
|
||||||
|
*/
|
||||||
|
export const resolveTree = 'application:resolve-tree';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -475,6 +485,91 @@ const translator: JupyterFrontEndPlugin<ITranslator> = {
|
|||||||
provides: ITranslator
|
provides: ITranslator
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default tree route resolver plugin.
|
||||||
|
*/
|
||||||
|
const tree: JupyterFrontEndPlugin<JupyterFrontEnd.ITreeResolver> = {
|
||||||
|
id: '@retrolab/application-extension:tree-resolver',
|
||||||
|
autoStart: true,
|
||||||
|
requires: [IRouter],
|
||||||
|
provides: JupyterFrontEnd.ITreeResolver,
|
||||||
|
activate: (
|
||||||
|
app: JupyterFrontEnd,
|
||||||
|
router: IRouter
|
||||||
|
): JupyterFrontEnd.ITreeResolver => {
|
||||||
|
const { commands } = app;
|
||||||
|
const set = new DisposableSet();
|
||||||
|
const delegate = new PromiseDelegate<JupyterFrontEnd.ITreeResolver.Paths>();
|
||||||
|
|
||||||
|
const treePattern = new RegExp('/retro(/tree/.*)?');
|
||||||
|
|
||||||
|
set.add(
|
||||||
|
commands.addCommand(CommandIDs.resolveTree, {
|
||||||
|
execute: (async (args: IRouter.ILocation) => {
|
||||||
|
if (set.isDisposed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = URLExt.queryStringToObject(args.search ?? '');
|
||||||
|
const browser = query['file-browser-path'] || '';
|
||||||
|
|
||||||
|
// Remove the file browser path from the query string.
|
||||||
|
delete query['file-browser-path'];
|
||||||
|
|
||||||
|
// Clean up artifacts immediately upon routing.
|
||||||
|
set.dispose();
|
||||||
|
|
||||||
|
delegate.resolve({ browser, file: PageConfig.getOption('treePath') });
|
||||||
|
}) as (args: any) => Promise<void>
|
||||||
|
})
|
||||||
|
);
|
||||||
|
set.add(
|
||||||
|
router.register({ command: CommandIDs.resolveTree, pattern: treePattern })
|
||||||
|
);
|
||||||
|
|
||||||
|
// If a route is handled by the router without the tree command being
|
||||||
|
// invoked, resolve to `null` and clean up artifacts.
|
||||||
|
const listener = () => {
|
||||||
|
if (set.isDisposed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set.dispose();
|
||||||
|
delegate.resolve(null);
|
||||||
|
};
|
||||||
|
router.routed.connect(listener);
|
||||||
|
set.add(
|
||||||
|
new DisposableDelegate(() => {
|
||||||
|
router.routed.disconnect(listener);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return { paths: delegate.promise };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const treePathUpdater: JupyterFrontEndPlugin<ITreePathUpdater> = {
|
||||||
|
id: '@retrolab/application-extension:tree-updater',
|
||||||
|
requires: [IRouter],
|
||||||
|
provides: ITreePathUpdater,
|
||||||
|
activate: (app: JupyterFrontEnd, router: IRouter) => {
|
||||||
|
function updateTreePath(treePath: string) {
|
||||||
|
if (treePath !== PageConfig.getOption('treePath')) {
|
||||||
|
const path = URLExt.join(
|
||||||
|
PageConfig.getOption('baseUrl') || '/',
|
||||||
|
'retro',
|
||||||
|
'tree',
|
||||||
|
URLExt.encodeParts(treePath)
|
||||||
|
);
|
||||||
|
router.navigate(path, { skipRouting: true });
|
||||||
|
// Persist the new tree path to PageConfig as it is used elsewhere at runtime.
|
||||||
|
PageConfig.setOption('treePath', treePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return updateTreePath;
|
||||||
|
},
|
||||||
|
autoStart: true
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zen mode plugin
|
* Zen mode plugin
|
||||||
*/
|
*/
|
||||||
@ -552,6 +647,8 @@ const plugins: JupyterFrontEndPlugin<any>[] = [
|
|||||||
title,
|
title,
|
||||||
topVisibility,
|
topVisibility,
|
||||||
translator,
|
translator,
|
||||||
|
tree,
|
||||||
|
treePathUpdater,
|
||||||
zen
|
zen
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -115,7 +115,12 @@ class RetroTreeHandler(RetroHandler):
|
|||||||
if await maybe_future(cm.is_hidden(path)) and not cm.allow_hidden:
|
if await maybe_future(cm.is_hidden(path)) and not cm.allow_hidden:
|
||||||
self.log.info("Refusing to serve hidden directory, via 404 Error")
|
self.log.info("Refusing to serve hidden directory, via 404 Error")
|
||||||
raise web.HTTPError(404)
|
raise web.HTTPError(404)
|
||||||
tpl = self.render_template("tree.html", page_config=self.get_page_config())
|
|
||||||
|
# Set treePath for routing to the directory
|
||||||
|
page_config = self.get_page_config()
|
||||||
|
page_config['treePath'] = path
|
||||||
|
|
||||||
|
tpl = self.render_template("tree.html", page_config=page_config)
|
||||||
return self.write(tpl)
|
return self.write(tpl)
|
||||||
elif await maybe_future(cm.file_exists(path)):
|
elif await maybe_future(cm.file_exists(path)):
|
||||||
# it's not a directory, we have redirecting to do
|
# it's not a directory, we have redirecting to do
|
||||||
|
Loading…
Reference in New Issue
Block a user