Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Frontend driven indexing #52

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@
"@jupyterlab/filebrowser": "^4.2.5",
"@jupyterlab/services": "^7.2.5",
"@jupyterlab/settingregistry": "^4.2.5",
"@jupyterlab/translation": "^4.2.5"
"@jupyterlab/translation": "^4.2.5",
"minimatch": "^10.0.1"
},
"devDependencies": {
"@jupyterlab/builder": "^4.0.0",
Expand Down
133 changes: 11 additions & 122 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,125 +3,13 @@ import {
JupyterFrontEndPlugin
} from '@jupyterlab/application';
import { ICommandPalette, ModalCommandPalette } from '@jupyterlab/apputils';
import { URLExt, PathExt } from '@jupyterlab/coreutils';
import { PathExt } from '@jupyterlab/coreutils';
import { IDocumentManager } from '@jupyterlab/docmanager';
import { ServerConnection } from '@jupyterlab/services';
import { ISettingRegistry } from '@jupyterlab/settingregistry';
import { FileBrowser, IDefaultFileBrowser } from '@jupyterlab/filebrowser';
import { IDefaultFileBrowser } from '@jupyterlab/filebrowser';
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
import { CommandRegistry } from '@lumino/commands';
import { ReadonlyPartialJSONObject } from '@lumino/coreutils';
import { Message } from '@lumino/messaging';
import { ISignal, Signal } from '@lumino/signaling';
import { CommandPalette } from '@lumino/widgets';

/** Structure of the JSON response from the server */
interface IQuickOpenResponse {
readonly contents: { [key: string]: string[] };
readonly scanSeconds: number;
}

/** Makes a HTTP request for the server-side quick open scan */
async function fetchContents(
path: string,
excludes: string[]
): Promise<IQuickOpenResponse> {
const query = excludes
.map(exclude => {
return 'excludes=' + encodeURIComponent(exclude);
})
.join('&');

const settings = ServerConnection.makeSettings();
const fullUrl =
URLExt.join(settings.baseUrl, 'jupyterlab-quickopen', 'api', 'files') +
'?' +
query +
'&path=' +
path;
const response = await ServerConnection.makeRequest(
fullUrl,
{ method: 'GET' },
settings
);
if (response.status !== 200) {
throw new ServerConnection.ResponseError(response);
}
return await response.json();
}

/**
* Shows files nested under directories in the root notebooks directory configured on the server.
*/
class QuickOpenWidget extends CommandPalette {
private _pathSelected = new Signal<this, string>(this);
private _settings: ReadonlyPartialJSONObject;
private _fileBrowser: FileBrowser;

constructor(
defaultBrowser: IDefaultFileBrowser,
settings: ReadonlyPartialJSONObject,
options: CommandPalette.IOptions
) {
super(options);

this.id = 'jupyterlab-quickopen';
this.title.iconClass = 'jp-SideBar-tabIcon jp-SearchIcon';
this.title.caption = 'Quick Open';

this._settings = settings;
this._fileBrowser = defaultBrowser;
}

/** Signal when a selected path is activated. */
get pathSelected(): ISignal<this, string> {
return this._pathSelected;
}

/** Current extension settings */
set settings(settings: ReadonlyPartialJSONObject) {
this._settings = settings;
}

/**
* Refreshes the widget with the paths of files on the server.
*/
protected async onActivateRequest(msg: Message): Promise<void> {
super.onActivateRequest(msg);

// Fetch the current contents from the server
const path = this._settings.relativeSearch
? this._fileBrowser.model.path
: '';
const response = await fetchContents(
path,
this._settings.excludes as string[]
);

// Remove all paths from the view
this.clearItems();

for (const category in response.contents) {
for (const fn of response.contents[category]) {
// Creates commands that are relative file paths on the server
const command = `${category}/${fn}`;
if (!this.commands.hasCommand(command)) {
// Only add the command to the registry if it does not yet exist TODO: Track disposables
// and remove
this.commands.addCommand(command, {
label: fn,
execute: () => {
// Emit a selection signal
this._pathSelected.emit(command);
}
});
}
// Make the file visible under its parent directory heading
this.addItem({ command, category });
}
}
}
}
import { QuickOpenWidget } from './quickopen';

/**
* Initialization data for the jupyterlab-quickopen extension.
Expand All @@ -144,13 +32,14 @@ const extension: JupyterFrontEndPlugin<void> = {
const settings: ISettingRegistry.ISettings = await settingRegistry.load(
extension.id
);
const widget: QuickOpenWidget = new QuickOpenWidget(
defaultFileBrowser,
settings.composite,
{
commands
}
);
const widget: QuickOpenWidget = new QuickOpenWidget({
defaultBrowser: defaultFileBrowser,
settings: settings.composite,
commandPaletteOptions: { commands },
contents: app.serviceManager.contents,
// TODO: remove
useServer: false
});

// Listen for path selection signals and show the selected files in the appropriate
// editor/viewer
Expand Down
Loading
Loading