Skip to content

Commit

Permalink
Add a setting to show full path in breadcrumbs (jupyterlab#14866)
Browse files Browse the repository at this point in the history
* BROKEN first pass at overriding ellipses logic

* cleaning up click handler for full path

* cleaning up comments and const vars

* fixing destination typo

* adding setting for toggling full path

* fixing config name

* adding full path to settings schema

* moving and adding comments on new set/get method for full path

* Add a unit test for new crumbs option

---------

Co-authored-by: Stephanie Stattel <stephaniestattel@Stephanies-MacBook-Air.local>
Co-authored-by: krassowski <5832902+krassowski@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 3, 2023
1 parent 453adc4 commit c106f0a
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 16 deletions.
6 changes: 6 additions & 0 deletions packages/filebrowser-extension/schema/browser.json
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,12 @@
"description": "Whether to show checkboxes next to files and folders",
"default": false
},
"showFullPath": {
"type": "boolean",
"title": "Show full path in browser bread crumbs",
"description": "Whether to show full path in browser bread crumbs",
"default": false
},
"sortNotebooksFirst": {
"type": "boolean",
"title": "When sorting by name, group notebooks before other files",
Expand Down
21 changes: 20 additions & 1 deletion packages/filebrowser-extension/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ namespace CommandIDs {

export const toggleLastModified = 'filebrowser:toggle-last-modified';

export const toggleShowFullPath = 'filebrowser:toggle-show-full-path';

export const toggleFileSize = 'filebrowser:toggle-file-size';

export const toggleSortNotebooksFirst =
Expand Down Expand Up @@ -222,7 +224,8 @@ const browser: JupyterFrontEndPlugin<void> = {
showFileSizeColumn: false,
showHiddenFiles: false,
showFileCheckboxes: false,
sortNotebooksFirst: false
sortNotebooksFirst: false,
showFullPath: false
};
const fileBrowserModelConfig = {
filterDirectories: true
Expand Down Expand Up @@ -1260,6 +1263,22 @@ function addCommands(
}
});

commands.addCommand(CommandIDs.toggleShowFullPath, {
label: trans.__('Show Full Path'),
isToggled: () => browser.showFullPath,
execute: () => {
const value = !browser.showFullPath;
const key = 'showFullPath';
if (settingRegistry) {
return settingRegistry
.set(FILE_BROWSER_PLUGIN_ID, key, value)
.catch((reason: Error) => {
console.error(`Failed to set ${key} setting`);
});
}
}
});

commands.addCommand(CommandIDs.toggleSortNotebooksFirst, {
label: trans.__('Sort Notebooks Above Files'),
isToggled: () => browser.sortNotebooksFirst,
Expand Down
11 changes: 11 additions & 0 deletions packages/filebrowser/src/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,17 @@ export class FileBrowser extends SidePanel {
}
}

/**
* Whether to show the full path in the breadcrumbs
*/
get showFullPath(): boolean {
return this.crumbs.fullPath;
}

set showFullPath(value: boolean) {
this.crumbs.fullPath = value;
}

/**
* Whether to show the file size column
*/
Expand Down
72 changes: 57 additions & 15 deletions packages/filebrowser/src/crumbs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export class BreadCrumbs extends Widget {
this.translator = options.translator || nullTranslator;
this._trans = this.translator.load('jupyterlab');
this._model = options.model;
this._fullPath = options.fullPath || false;
this.addClass(BREADCRUMB_CLASS);
this._crumbs = Private.createCrumbs();
this._crumbSeps = Private.createCrumbSeparators();
Expand Down Expand Up @@ -114,6 +115,17 @@ export class BreadCrumbs extends Widget {
}
}

/**
* Whether to show the full path in the breadcrumbs
*/
get fullPath(): boolean {
return this._fullPath;
}

set fullPath(value: boolean) {
this._fullPath = value;
}

/**
* A message handler invoked on an `'after-attach'` message.
*/
Expand Down Expand Up @@ -152,7 +164,8 @@ export class BreadCrumbs extends Widget {
this._crumbs,
this._crumbSeps,
localPath,
this._hasPreferred
this._hasPreferred,
this._fullPath
);
}

Expand Down Expand Up @@ -184,12 +197,20 @@ export class BreadCrumbs extends Widget {
node.classList.contains(BREADCRUMB_ITEM_CLASS) ||
node.classList.contains(BREADCRUMB_ROOT_CLASS)
) {
const index = ArrayExt.findFirstIndex(
let index = ArrayExt.findFirstIndex(
this._crumbs,
value => value === node
);
let destination = BREAD_CRUMB_PATHS[index];
if (
this._fullPath &&
index < 0 &&
!node.classList.contains(BREADCRUMB_ROOT_CLASS)
) {
destination = node.title;
}
this._model
.cd(BREAD_CRUMB_PATHS[index])
.cd(destination)
.catch(error =>
showErrorMessage(this._trans.__('Open Error'), error)
);
Expand Down Expand Up @@ -309,6 +330,7 @@ export class BreadCrumbs extends Widget {
private _hasPreferred: boolean;
private _crumbs: ReadonlyArray<HTMLElement>;
private _crumbSeps: ReadonlyArray<HTMLElement>;
private _fullPath: boolean;
}

/**
Expand All @@ -328,6 +350,11 @@ export namespace BreadCrumbs {
* The application language translator.
*/
translator?: ITranslator;

/**
* Show the full file browser path in breadcrumbs
*/
fullPath?: boolean;
}
}

Expand All @@ -353,7 +380,8 @@ namespace Private {
breadcrumbs: ReadonlyArray<HTMLElement>,
separators: ReadonlyArray<HTMLElement>,
path: string,
hasPreferred: boolean
hasPreferred: boolean,
fullPath: boolean
): void {
const node = breadcrumbs[0].parentNode as HTMLElement;

Expand All @@ -371,25 +399,39 @@ namespace Private {
}

const parts = path.split('/');
if (parts.length > 2) {
if (!fullPath && parts.length > 2) {
node.appendChild(breadcrumbs[Crumb.Ellipsis]);
const grandParent = parts.slice(0, parts.length - 2).join('/');
breadcrumbs[Crumb.Ellipsis].title = grandParent;
node.appendChild(separators[1]);
}

if (path) {
if (parts.length >= 2) {
breadcrumbs[Crumb.Parent].textContent = parts[parts.length - 2];
node.appendChild(breadcrumbs[Crumb.Parent]);
const parent = parts.slice(0, parts.length - 1).join('/');
breadcrumbs[Crumb.Parent].title = parent;
node.appendChild(separators[2]);
if (!fullPath) {
if (parts.length >= 2) {
breadcrumbs[Crumb.Parent].textContent = parts[parts.length - 2];
node.appendChild(breadcrumbs[Crumb.Parent]);
const parent = parts.slice(0, parts.length - 1).join('/');
breadcrumbs[Crumb.Parent].title = parent;
node.appendChild(separators[2]);
}
breadcrumbs[Crumb.Current].textContent = parts[parts.length - 1];
node.appendChild(breadcrumbs[Crumb.Current]);
breadcrumbs[Crumb.Current].title = path;
node.appendChild(separators[3]);
} else {
for (let i = 0; i < parts.length; i++) {
const elem = document.createElement('span');
elem.className = BREADCRUMB_ITEM_CLASS;
elem.textContent = parts[i];
const elemPath = `/${parts.slice(0, i + 1).join('/')}`;
elem.title = elemPath;
node.appendChild(elem);
const separator = document.createElement('span');
separator.textContent = '/';
node.appendChild(separator);
}
}
breadcrumbs[Crumb.Current].textContent = parts[parts.length - 1];
node.appendChild(breadcrumbs[Crumb.Current]);
breadcrumbs[Crumb.Current].title = path;
node.appendChild(separators[3]);
}
}

Expand Down
16 changes: 16 additions & 0 deletions packages/filebrowser/test/crumbs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,22 @@ describe('filebrowser/model', () => {
});
});

describe('#fullPath', () => {
it('should show/hide full path', async () => {
Widget.attach(crumbs, document.body);
MessageLoop.sendMessage(crumbs, Widget.Msg.UpdateRequest);
expect(crumbs.node.textContent).toMatch(
/\/\/Untitled Folder.*?\/Untitled Folder.*?\//
);
crumbs.fullPath = true;
MessageLoop.sendMessage(crumbs, Widget.Msg.UpdateRequest);
await framePromise();
expect(crumbs.node.textContent).toMatch(
/\/Untitled Folder.*?\/Untitled Folder.*?\/Untitled Folder.*?\//
);
});
});

describe('#onUpdateRequest()', () => {
it('should be called when the model updates', async () => {
const model = new FileBrowserModel({ manager });
Expand Down

0 comments on commit c106f0a

Please sign in to comment.