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

Adds quick settings button to the new launcher #52

Merged
merged 19 commits into from
Jun 14, 2024
Merged
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
34 changes: 34 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,38 @@ export function addCommands(
await settings.set('columnOrder', order);
}
});
app.commands.addCommand(CommandIDs.showStarred, {
isToggleable: true,
isToggled: () => {
return settings.composite
.starredSection as ISettingsLayout['starredSection'];
},
label: trans.__('Show Starred Section'),
execute: async () => {
const starredSection = settings.composite
.starredSection as ISettingsLayout['starredSection'];
await settings.set('starredSection', !starredSection);
}
});
app.commands.addCommand(CommandIDs.searchAllSections, {
isToggleable: true,
isToggled: () => {
return settings.composite
.searchAllSections as ISettingsLayout['searchAllSections'];
},
label: trans.__('Search in All Sections'),
execute: async () => {
const searchAllSections = settings.composite
.searchAllSections as ISettingsLayout['searchAllSections'];
await settings.set('searchAllSections', !searchAllSections);
}
});
app.commands.addCommand(CommandIDs.openSettings, {
label: trans.__('Open Settings Editor'),
execute: () => {
app.commands.execute('settingeditor:open', {
query: 'New Launcher'
});
}
});
}
48 changes: 48 additions & 0 deletions src/components/quick-settings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { TranslationBundle } from '@jupyterlab/translation';
import type { CommandRegistry } from '@lumino/commands';
import { MenuSvg, settingsIcon } from '@jupyterlab/ui-components';
import * as React from 'react';

import { CommandIDs } from '../types';

export function QuickSettings(props: {
trans: TranslationBundle;
commands: CommandRegistry;
}): React.ReactElement {
const { commands } = props;

const menu = new MenuSvg({ commands: commands });
menu.addItem({ command: CommandIDs.showStarred });
menu.addItem({ command: CommandIDs.searchAllSections });
menu.addItem({ command: CommandIDs.openSettings });

const iconRef = React.useRef<HTMLDivElement>(null);

const onClickHandler = (event: React.MouseEvent) => {
const current = iconRef.current;
let x, y;
if (current) {
const position = current.getBoundingClientRect();
x = position.left;
y = position.bottom;
} else {
x = event.clientX;
y = event.clientY;
}
menu.open(x, y);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the menu is positioned within the browser window:

image

I wonder if it would be nicer if it was positioned relative to the launcher body or the button. You can pass a third argument to menu.open() with Menu.IOpenOptions object. Once jupyterlab/lumino#700 is released we will be able to pass a custom host but for now we could only try using forceX to improve the positioning.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It currently should be positioned to the button. It's just shifting the menu so it fits in the window. This is what it looks like when the panel isn't directly next the edge of the window:

image

If I use forceX the part of the menu isn't viewable which I think may be worse:

image

I wonder if there is a way to align it so the top-right corner of the menu aligns with the bottom right corner of the button. In my opinion that would look the cleanest.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

align it so the top-right corner of the menu aligns with the bottom right corner of the button. In my opinion that would look the cleanest.

💯 agree. There is no way as of today. Can you open a feature request on lumino, and another issue here to track it as a follow-up enhancement?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. I opened Lumino#709 for this

};

return (
<div
className="jp-Launcher-TypeCard jp-LauncherCard jp-Launcher-QuickSettings"
ref={iconRef}
onClick={event => {
onClickHandler(event);
}}
>
<div className="jp-LauncherCard-icon">
<settingsIcon.react />
</div>
</div>
);
}
6 changes: 5 additions & 1 deletion src/launcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
notebookIcon,
consoleIcon
} from '@jupyterlab/ui-components';

import * as React from 'react';
import {
IItem,
Expand All @@ -23,6 +24,7 @@ import { Item } from './item';
import { KernelTable } from './components/table';
import { CollapsibleSection } from './components/section';
import { TypeCard } from './components/card';
import { QuickSettings } from './components/quick-settings';

function LauncherBody(props: {
trans: TranslationBundle;
Expand All @@ -36,7 +38,8 @@ function LauncherBody(props: {
favouritesChanged: ISignal<IFavoritesDatabase, void>;
lastUsedChanged: ISignal<ILastUsedDatabase, void>;
}): React.ReactElement {
const { trans, cwd, typeItems, otherItems, favouritesChanged } = props;
const { trans, cwd, typeItems, commands, otherItems, favouritesChanged } =
props;
const [query, updateQuery] = React.useState<string>('');
const [, forceUpdate] = React.useReducer(x => x + 1, 0);
const [showStarred, updateShowStarred] = React.useState<
Expand Down Expand Up @@ -116,6 +119,7 @@ function LauncherBody(props: {
{otherItems.map(item => (
<TypeCard item={item} trans={trans} />
))}
<QuickSettings commands={commands} trans={trans} />
</div>
</div>
{searchAll ? (
Expand Down
3 changes: 3 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export namespace CommandIDs {
export const create = 'launcher:create';
export const moveColumn = 'new-launcher:table-move-column';
export const toggleColumn = 'new-launcher:table-toggle-column';
export const showStarred = 'new-launcher:show-starred';
export const searchAllSections = 'new-launcher:search-all-sections';
export const openSettings = 'new-launcher:open-settings';
}

export interface ISettingsLayout {
Expand Down
23 changes: 23 additions & 0 deletions ui-tests/tests/jupyterlab_new_launcher.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect, test, galata } from '@jupyterlab/galata';
import { Page } from '@playwright/test';

const SETTINGS_ID = 'jupyterlab-new-launcher:plugin';

Expand Down Expand Up @@ -80,3 +81,25 @@ test.describe('Filter individual', () => {
);
});
});

test.describe('Quick Settings', () => {
test('open quick settings menu', async ({ page }) => {
const launcher = page.locator('.jp-LauncherBody');
await page.locator('.jp-Launcher-QuickSettings').click();
expect(await launcher.screenshot()).toMatchSnapshot(
'launcher_open_quicksettings.png'
);
});

test('show starred from quick settings', async ({ page }) => {
const launcher = page.locator('.jp-LauncherBody');
await page.locator('.jp-Launcher-QuickSettings').click();
await page
.locator('.lm-Menu-itemLabel:text("Show Starred Section")')
.click();
const starredSection = page.locator(
'.jp-CollapsibleSection-Title:has-text("starred")'
);
await expect(starredSection).toBeVisible();
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading