Skip to content
Open
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
5 changes: 5 additions & 0 deletions workspaces/lightspeed/.changeset/kind-radios-fold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@red-hat-developer-hub/backstage-plugin-lightspeed': patch
---

Polish MCP settings and chatbot options menu: remove the settings button hover tooltip, relabel it to "Options", show MCP server edit actions on row hover only, display token-required status with a red warning icon, and align the MCP servers table background with the panel in dark mode.
10 changes: 5 additions & 5 deletions workspaces/lightspeed/e2e-tests/pages/LightspeedPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export async function selectDisplayMode(
t: LightspeedMessages,
mode: DisplayMode,
) {
await page.getByRole('button', { name: t['aria.settings.label'] }).click();
await page.getByRole('button', { name: t['aria.options.label'] }).click();
const modeMap: Record<DisplayMode, string> = {
Overlay: t['settings.displayMode.overlay'],
'Dock to window': t['settings.displayMode.docked'],
Expand Down Expand Up @@ -92,15 +92,15 @@ export async function expectChatbotControlsVisible(
await expect(chatHistoryMenuButton).toBeVisible();
}
await expect(
page.getByRole('button', { name: t['aria.settings.label'] }),
page.getByRole('button', { name: t['aria.options.label'] }),
).toBeVisible();
}

export async function verifyDisplayModeMenuOptions(
page: Page,
t: LightspeedMessages,
) {
await page.getByRole('button', { name: t['aria.settings.label'] }).click();
await page.getByRole('button', { name: t['aria.options.label'] }).click();
const settingsMenu = page
.getByRole('menu')
.filter({
Expand Down Expand Up @@ -145,7 +145,7 @@ export async function verifyDisplayModeMenuOptions(
// MCP settings (McpServersSettings — strings from `mcp.settings.*` translations)

export async function openMcpSettingsPanel(page: Page, t: LightspeedMessages) {
await page.getByRole('button', { name: t['aria.settings.label'] }).click();
await page.getByRole('button', { name: t['aria.options.label'] }).click();
await expect(
page.getByRole('menuitem', { name: t['settings.mcp.label'] }),
).toBeVisible();
Expand Down Expand Up @@ -359,7 +359,7 @@ export async function verifyMcpSettingsPanel(
}

await expect(
page.getByRole('button', { name: t['aria.settings.label'] }),
page.getByRole('button', { name: t['aria.options.label'] }),
).toBeVisible();

await closeMcpSettingsPanel(page, t);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class NotebookSurfacePage {
async gotoFullscreenNotebooksTab(): Promise<void> {
await openLightspeed(this.page);
await this.page
.getByRole('button', { name: this.t['aria.settings.label'] })
.getByRole('button', { name: this.t['aria.options.label'] })
.click();
await this.page
.getByRole('menuitem', {
Expand Down
4 changes: 2 additions & 2 deletions workspaces/lightspeed/e2e-tests/utils/chatManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ export const openChatbotSettings = async (
translations: LightspeedMessages,
) => {
await page
.getByRole('button', { name: translations['aria.settings.label'] })
.getByRole('button', { name: translations['aria.options.label'] })
.click();
};

Expand All @@ -247,7 +247,7 @@ export const verifyChatbotSettingsVisible = async (
translations: LightspeedMessages,
) => {
await expect(
page.getByRole('button', { name: translations['aria.settings.label'] }),
page.getByRole('button', { name: translations['aria.options.label'] }),
).toBeVisible();
};

Expand Down
20 changes: 8 additions & 12 deletions workspaces/lightspeed/packages/app-legacy/knip-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@

| Name | Location | Severity |
| :----------- | :---------------- | :------- |
| react-router | package.json:51:6 | error |
| react-router | package.json:55:6 | error |

## Unused devDependencies (4)
## Unused devDependencies (6)

| Name | Location | Severity |
| :-------------------------- | :---------------- | :------- |
| @testing-library/user-event | package.json:60:6 | error |
| @backstage/test-utils | package.json:55:6 | error |
| @testing-library/dom | package.json:57:6 | error |
| cross-env | package.json:62:6 | error |

## Unlisted dependencies (1)

| Name | Location | Severity |
| :--------- | :---------------------------------- | :------- |
| playwright | ../../e2e-tests/utils/testHelper.ts | error |
| @testing-library/user-event | package.json:65:6 | error |
| @backstage/test-utils | package.json:60:6 | error |
| @axe-core/playwright | package.json:59:6 | error |
| @testing-library/dom | package.json:62:6 | error |
| @playwright/test | package.json:61:6 | error |
| cross-env | package.json:67:6 | error |
23 changes: 23 additions & 0 deletions workspaces/lightspeed/packages/app/knip-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Knip report

## Unused dependencies (7)

| Name | Location | Severity |
| :------------------------------ | :---------------- | :------- |
| @backstage/plugin-user-settings | package.json:33:6 | error |
| @backstage/integration-react | package.json:28:6 | error |
| @backstage/plugin-scaffolder | package.json:31:6 | error |
| @backstage/core-compat-api | package.json:23:6 | error |
| @backstage/plugin-catalog | package.json:30:6 | error |
| @backstage/plugin-search | package.json:32:6 | error |
| react-router | package.json:42:6 | error |

## Unused devDependencies (5)

| Name | Location | Severity |
| :----------------------------- | :---------------- | :------- |
| @backstage/frontend-test-utils | package.json:46:6 | error |
| @testing-library/user-event | package.json:51:6 | error |
| @testing-library/dom | package.json:48:6 | error |
| @playwright/test | package.json:47:6 | error |
| cross-env | package.json:53:6 | error |
24 changes: 12 additions & 12 deletions workspaces/lightspeed/packages/backend/knip-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

## Unused dependencies (10)

| Name | Location | Severity |
| :---------------------------------------------------- | :---------------- | :------- |
| @backstage/plugin-auth-backend-module-github-provider | package.json:28:6 | error |
| @backstage/plugin-search-backend-node | package.json:45:6 | error |
| @backstage/plugin-permission-common | package.json:37:6 | error |
| @backstage/plugin-permission-node | package.json:38:6 | error |
| @backstage/plugin-auth-node | package.json:30:6 | error |
| @backstage/config | package.json:25:6 | error |
| better-sqlite3 | package.json:49:6 | error |
| node-gyp | package.json:50:6 | error |
| app | package.json:48:6 | error |
| pg | package.json:51:6 | error |
| Name | Location | Severity |
| :----------------------------------------------------------- | :---------------- | :------- |
| @backstage/plugin-permission-backend-module-allow-all-policy | package.json:37:6 | error |
| @backstage/plugin-search-backend-node | package.json:46:6 | error |
| @backstage/plugin-permission-backend | package.json:36:6 | error |
| @backstage/plugin-permission-common | package.json:38:6 | error |
| @backstage/plugin-permission-node | package.json:39:6 | error |
| @backstage/plugin-auth-node | package.json:31:6 | error |
| @backstage/config | package.json:26:6 | error |
| node-gyp | package.json:51:6 | error |
| app | package.json:49:6 | error |
| pg | package.json:52:6 | error |
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
# Knip report

## Unused dependencies (3)

| Name | Location | Severity |
| :----------------- | :---------------- | :------- |
| llama-stack-client | package.json:60:6 | error |
| @langchain/openai | package.json:52:6 | error |
| @langchain/core | package.json:51:6 | error |
18 changes: 8 additions & 10 deletions workspaces/lightspeed/plugins/lightspeed/knip-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@

| Name | Location | Severity |
| :--------------- | :---------------- | :------- |
| @material-ui/lab | package.json:45:6 | error |
| react-markdown | package.json:52:6 | error |
| @material-ui/lab | package.json:63:6 | error |
| react-markdown | package.json:78:6 | error |

## Unused devDependencies (5)
## Unused devDependencies (3)

| Name | Location | Severity |
| :-------------------------- | :---------------- | :------- |
| @testing-library/user-event | package.json:70:6 | error |
| @backstage/core-app-api | package.json:61:6 | error |
| @emotion/is-prop-valid | package.json:64:6 | error |
| @testing-library/dom | package.json:67:6 | error |
| msw | package.json:71:6 | error |
| Name | Location | Severity |
| :---------------------- | :---------------- | :------- |
| @backstage/core-app-api | package.json:87:6 | error |
| @emotion/is-prop-valid | package.json:90:6 | error |
| msw | package.json:97:6 | error |
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,12 @@ export const LightspeedChatBoxHeader = ({
className={styles.dropdown}
isCompact
toggleProps={{
'aria-label': t('aria.settings.label'),
'aria-label': t('aria.options.label'),
className: styles.optionsToggle,
}}
tooltipProps={{
content: t('tooltip.settings'),
trigger: 'manual',
content: '',
}}
>
<DropdownGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,6 @@ const useStyles = makeStyles(theme => ({
statusOk: {
color: '#147878',
},
statusToken: {
color: '#147878',
},
statusWarn: {
color: '#B1380B',
},
Expand All @@ -173,6 +170,13 @@ const useStyles = makeStyles(theme => ({
},
actionButton: {
color: theme.palette.text.secondary,
opacity: 0,
transition: 'opacity 0.15s ease-in-out',
},
tableRow: {
'&:hover $actionButton, &:focus-within $actionButton': {
opacity: 1,
},
},
modalDescription: {
color: theme.palette.text.secondary,
Expand Down Expand Up @@ -316,6 +320,12 @@ const useStyles = makeStyles(theme => ({
},
table: {
width: '100%',
backgroundColor: 'transparent',
'--pf-v6-c-table--BackgroundColor': 'transparent',
'--pf-v5-c-table--BackgroundColor': 'transparent',
'& table, & thead, & tbody, & tr, & th, & td': {
backgroundColor: 'transparent !important',
},
'& th': {
borderBottom: 0,
fontSize: '0.75rem',
Expand Down Expand Up @@ -904,14 +914,12 @@ export const McpServersSettings = ({
let statusClass = classes.statusWarn;
if (displayStatus === 'ok') {
statusClass = classes.statusOk;
} else if (displayStatus === 'tokenRequired') {
statusClass = classes.statusToken;
} else if (displayStatus === 'disabled') {
statusClass = classes.statusDisabled;
}

return (
<Tr key={server.id}>
<Tr key={server.id} className={classes.tableRow}>
<Td width={10} className={classes.toggleCell}>
{(() => {
const isUnavailable =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
render,
screen,
waitFor,
within,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';

Expand Down Expand Up @@ -237,6 +238,10 @@ describe('LightspeedChat', () => {
} as Partial<ReturnType<typeof useConversations>> as ReturnType<
typeof useConversations
>);
mockUseNotebookSessions.mockReturnValue({
data: [],
refetch: jest.fn(),
});
mockUseLightspeedDrawerContext.mockReturnValue({
isChatbotActive: false,
toggleChatbot: jest.fn(),
Expand Down Expand Up @@ -556,7 +561,7 @@ describe('LightspeedChat', () => {
it('should open settings dropdown when clicking the settings button', async () => {
render(setupLightspeedChat());

const settingsButton = screen.getByLabelText('Chatbot options');
const settingsButton = screen.getByLabelText('Options');
expect(settingsButton).toBeInTheDocument();

await userEvent.click(settingsButton);
Expand All @@ -570,7 +575,7 @@ describe('LightspeedChat', () => {
it('should show all display mode options in the dropdown', async () => {
render(setupLightspeedChat());

const settingsButton = screen.getByLabelText('Chatbot options');
const settingsButton = screen.getByLabelText('Options');
await userEvent.click(settingsButton);

await waitFor(() => {
Expand All @@ -584,7 +589,7 @@ describe('LightspeedChat', () => {
it('should call setDisplayMode with default when clicking Overlay option', async () => {
render(setupLightspeedChat());

const settingsButton = screen.getByLabelText('Chatbot options');
const settingsButton = screen.getByLabelText('Options');
await userEvent.click(settingsButton);

await waitFor(() => {
Expand All @@ -602,7 +607,7 @@ describe('LightspeedChat', () => {
it('should call setDisplayMode with docked when clicking Dock to window option', async () => {
render(setupLightspeedChat());

const settingsButton = screen.getByLabelText('Chatbot options');
const settingsButton = screen.getByLabelText('Options');
await userEvent.click(settingsButton);

await waitFor(() => {
Expand All @@ -620,7 +625,7 @@ describe('LightspeedChat', () => {
it('should call setDisplayMode with embedded when clicking Fullscreen option', async () => {
render(setupLightspeedChat());

const settingsButton = screen.getByLabelText('Chatbot options');
const settingsButton = screen.getByLabelText('Options');
await userEvent.click(settingsButton);

await waitFor(() => {
Expand Down Expand Up @@ -660,7 +665,9 @@ describe('LightspeedChat', () => {
expect(screen.getByText('My Notebooks')).toBeInTheDocument();
});

const settingsButton = screen.getByLabelText('Chatbot options');
const settingsButton = within(
screen.getByRole('region', { name: 'Chatbot' }),
).getByLabelText('Options');
await userEvent.click(settingsButton);

await waitFor(() => {
Expand Down Expand Up @@ -696,7 +703,7 @@ describe('LightspeedChat', () => {
render(setupLightspeedChat());

await waitFor(() => {
expect(screen.getByLabelText('Chatbot options')).toBeInTheDocument();
expect(screen.getByLabelText('Options')).toBeInTheDocument();
});

expect(
Expand Down Expand Up @@ -729,7 +736,7 @@ describe('LightspeedChat', () => {
render(setupLightspeedChat());

await waitFor(() => {
expect(screen.getByLabelText('Chatbot options')).toBeInTheDocument();
expect(screen.getByLabelText('Options')).toBeInTheDocument();
});

expect(
Expand Down Expand Up @@ -761,7 +768,7 @@ describe('LightspeedChat', () => {

render(setupLightspeedChat());

const settingsButton = screen.getByLabelText('Chatbot options');
const settingsButton = screen.getByLabelText('Options');
await userEvent.click(settingsButton);

await waitFor(() => {
Expand Down Expand Up @@ -795,7 +802,7 @@ describe('LightspeedChat', () => {

render(setupLightspeedChat());

const settingsButton = screen.getByLabelText('Chatbot options');
const settingsButton = screen.getByLabelText('Options');
await userEvent.click(settingsButton);

await waitFor(() => {
Expand Down Expand Up @@ -829,7 +836,7 @@ describe('LightspeedChat', () => {

render(setupLightspeedChat());

const settingsButton = screen.getByLabelText('Chatbot options');
const settingsButton = screen.getByLabelText('Options');
await userEvent.click(settingsButton);

await waitFor(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ const lightspeedTranslationDe = createTranslationMessages({
'aria.scroll.up': 'Zurück zum Anfang',
'aria.search.placeholder': 'Suchen',
'aria.searchPreviousConversations': 'Vorherige Unterhaltungen durchsuchen',
'aria.settings.label': 'Chatbot-Optionen',
'attach.menu.description': 'Eine JSON-, YAML- oder TXT-Datei anhängen',
'attach.menu.title': 'Anhängen',
'button.newChat': 'Neuer Chat',
Expand Down Expand Up @@ -347,7 +346,6 @@ const lightspeedTranslationDe = createTranslationMessages({
'tooltip.quickNewChat': 'Neuer Chat',
'tooltip.responseRecorded': 'Antwort aufgezeichnet',
'tooltip.send': 'Senden',
'tooltip.settings': 'Chatbot-Optionen',
'user.guest': 'Gast',
'user.loading': '...',
},
Expand Down
Loading
Loading