Route on file browser navigation

Fixes #15
Frédéric Collonval 4 years ago
parent f5507c408d
commit 6f216e9fe3
No known key found for this signature in database
GPG Key ID: B7D0EF991C4BBBD4

@ -10,3 +10,11 @@ test('Tree', async ({ page }) => {
const button = await page.$('text="New Notebook"');
expect(button).toBeDefined();
});
test('should go to subfolder', async ({ page }) => {
await page.goto(`${BASE_URL}retro/tree/binder`);
const breadcrumb = await page.waitForSelector('.jp-FileBrowser-crumbs');
expect(await breadcrumb.textContent()).toEqual('/binder/');
});

@ -50,6 +50,8 @@
"@jupyterlab/mainmenu": "^3.1.8",
"@jupyterlab/settingregistry": "^3.1.8",
"@jupyterlab/translation": "^3.1.8",
"@lumino/coreutils": "^1.8.0",
"@lumino/disposable": "^1.7.0",
"@lumino/widgets": "^1.23.0",
"@retrolab/application": "^0.3.2",
"@retrolab/ui-components": "^0.3.2"

@ -16,7 +16,7 @@ import {
ICommandPalette
} from '@jupyterlab/apputils';
import { PageConfig, PathExt } from '@jupyterlab/coreutils';
import { PageConfig, PathExt, URLExt } from '@jupyterlab/coreutils';
import { IDocumentManager, renameDialog } from '@jupyterlab/docmanager';
@ -30,6 +30,10 @@ import { RetroApp, RetroShell, IRetroShell } from '@retrolab/application';
import { jupyterIcon, retroInlineIcon } from '@retrolab/ui-components';
import { PromiseDelegate } from '@lumino/coreutils';
import { DisposableDelegate, DisposableSet } from '@lumino/disposable';
import { Widget } from '@lumino/widgets';
/**
@ -475,6 +479,68 @@ const translator: JupyterFrontEndPlugin<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('retrolab-router:tree', {
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: 'retrolab-router:tree', 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 };
}
};
/**
* Zen mode plugin
*/
@ -552,6 +618,7 @@ const plugins: JupyterFrontEndPlugin<any>[] = [
title,
topVisibility,
translator,
tree,
zen
];

@ -114,7 +114,12 @@ class RetroTreeHandler(RetroHandler):
if await maybe_future(cm.is_hidden(path)) and not cm.allow_hidden:
self.log.info("Refusing to serve hidden directory, via 404 Error")
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)
elif await maybe_future(cm.file_exists(path)):
# it's not a directory, we have redirecting to do

Loading…
Cancel
Save