Skip to content

Commit 767a844

Browse files
committed
improved UI
Signed-off-by: Yi Cai <yicai@redhat.com>
1 parent 550ec7b commit 767a844

2 files changed

Lines changed: 261 additions & 58 deletions

File tree

workspaces/lightspeed/plugins/lightspeed/src/components/McpServersSettings.tsx

Lines changed: 81 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { useMemo, useState } from 'react';
1919
import { makeStyles } from '@material-ui/core';
2020
import ModeEditOutlineOutlinedIcon from '@mui/icons-material/ModeEditOutlineOutlined';
2121
import Typography from '@mui/material/Typography';
22-
import { Button, Switch, Title } from '@patternfly/react-core';
22+
import { Button, Switch, Title, Tooltip } from '@patternfly/react-core';
2323
import {
2424
CheckCircleIcon,
2525
ExclamationCircleIcon,
@@ -31,14 +31,15 @@ import {
3131
} from '@patternfly/react-icons';
3232
import { Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table';
3333

34-
type ServerStatus = 'tokenRequired' | 'disabled' | 'ok' | 'failed';
34+
type ServerStatus = 'tokenRequired' | 'disabled' | 'ok' | 'failed' | 'unknown';
3535

3636
type McpServer = {
3737
id: string;
3838
name: string;
3939
enabled: boolean;
4040
status: ServerStatus;
4141
detail: string;
42+
errorMessage?: string;
4243
};
4344

4445
type McpServersSettingsProps = {
@@ -80,7 +81,7 @@ const useStyles = makeStyles(theme => ({
8081
paddingLeft: 0,
8182
paddingTop: 0,
8283
paddingBottom: 0,
83-
marginLeft: 0,
84+
marginLeft: '-0.85rem',
8485
fontWeight: 600,
8586
fontSize: '0.75rem',
8687
lineHeight: '1.25rem',
@@ -164,7 +165,7 @@ const INITIAL_SERVERS: McpServer[] = [
164165
{
165166
id: 'github',
166167
name: 'Github',
167-
enabled: false,
168+
enabled: true,
168169
status: 'tokenRequired',
169170
detail: 'Token required',
170171
},
@@ -185,9 +186,11 @@ const INITIAL_SERVERS: McpServer[] = [
185186
{
186187
id: 'kubernetes',
187188
name: 'Kubernetes',
188-
enabled: false,
189+
enabled: true,
189190
status: 'failed',
190-
detail: '5 tools',
191+
detail: '4 tools',
192+
errorMessage:
193+
'Token authentication failed, click edit to configure it again',
191194
},
192195
{
193196
id: 'developerhub',
@@ -213,7 +216,7 @@ const INITIAL_SERVERS: McpServer[] = [
213216
{
214217
id: 'figma',
215218
name: 'Figma',
216-
enabled: false,
219+
enabled: true,
217220
status: 'failed',
218221
detail: 'Failed',
219222
},
@@ -227,6 +230,24 @@ const getStatusIcon = (status: ServerStatus, className: string) => {
227230
return <CheckCircleIcon className={className} />;
228231
};
229232

233+
const getDisplayStatus = (server: McpServer): ServerStatus => {
234+
if (!server.enabled) return 'disabled';
235+
if (server.status === 'tokenRequired') return 'tokenRequired';
236+
if (server.status === 'failed') return 'failed';
237+
if (server.status === 'ok') return 'ok';
238+
return 'unknown';
239+
};
240+
241+
const getDisplayDetail = (
242+
server: McpServer,
243+
displayStatus: ServerStatus,
244+
): string => {
245+
if (displayStatus === 'disabled') return 'Disabled';
246+
if (displayStatus === 'tokenRequired') return 'Token required';
247+
if (displayStatus === 'failed') return server.detail || 'Failed';
248+
return server.detail;
249+
};
250+
230251
export const McpServersSettings = ({
231252
onClose,
232253
backgroundColor,
@@ -295,32 +316,50 @@ export const McpServersSettings = ({
295316
</Thead>
296317
<Tbody>
297318
{sortedServers.map(server => {
319+
const displayStatus = getDisplayStatus(server);
320+
const displayDetail = getDisplayDetail(server, displayStatus);
298321
let statusClass = classes.statusWarn;
299-
if (server.status === 'ok') {
322+
if (displayStatus === 'ok') {
300323
statusClass = classes.statusOk;
301-
} else if (server.status === 'tokenRequired') {
324+
} else if (displayStatus === 'tokenRequired') {
302325
statusClass = classes.statusToken;
303-
} else if (server.status === 'disabled') {
326+
} else if (displayStatus === 'disabled') {
304327
statusClass = classes.statusDisabled;
305328
}
306329

307330
return (
308331
<Tr key={server.id}>
309332
<Td width={10} className={classes.toggleCell}>
310-
<Switch
311-
id={`mcp-switch-${server.id}`}
312-
aria-label={`Toggle ${server.name}`}
313-
isChecked={server.enabled}
314-
onChange={(_event, checked) =>
315-
setServers(prev =>
316-
prev.map(item =>
317-
item.id === server.id
318-
? { ...item, enabled: checked }
319-
: item,
320-
),
321-
)
322-
}
323-
/>
333+
{(() => {
334+
const isUnavailable =
335+
server.status === 'failed' ||
336+
server.status === 'tokenRequired';
337+
const isChecked = isUnavailable ? false : server.enabled;
338+
339+
return (
340+
<Switch
341+
id={`mcp-switch-${server.id}`}
342+
aria-label={`Toggle ${server.name}`}
343+
isChecked={isChecked}
344+
isDisabled={isUnavailable}
345+
onChange={(_event, checked) =>
346+
setServers(prev =>
347+
prev.map(item =>
348+
item.id === server.id
349+
? {
350+
...item,
351+
enabled: checked,
352+
...(checked && item.status === 'disabled'
353+
? { status: 'ok', detail: '5 tools' }
354+
: {}),
355+
}
356+
: item,
357+
),
358+
)
359+
}
360+
/>
361+
);
362+
})()}
324363
</Td>
325364
<Td
326365
width={35}
@@ -332,13 +371,24 @@ export const McpServersSettings = ({
332371
</Td>
333372
<Td width={40} className={classes.statusColumnCell}>
334373
<div className={classes.statusCell}>
335-
{getStatusIcon(server.status, statusClass)}
336-
<Typography
337-
component="span"
338-
className={classes.statusValue}
339-
>
340-
{server.detail}
341-
</Typography>
374+
{getStatusIcon(displayStatus, statusClass)}
375+
{displayStatus === 'failed' && server.errorMessage ? (
376+
<Tooltip content={server.errorMessage}>
377+
<Typography
378+
component="span"
379+
className={classes.statusValue}
380+
>
381+
{displayDetail}
382+
</Typography>
383+
</Tooltip>
384+
) : (
385+
<Typography
386+
component="span"
387+
className={classes.statusValue}
388+
>
389+
{displayDetail}
390+
</Typography>
391+
)}
342392
</div>
343393
</Td>
344394
<Td width={15} isActionCell style={{ textAlign: 'right' }}>

0 commit comments

Comments
 (0)