feat(ws): Notebooks 2.0 // Frontend // Workspaces table // Workspace redirect status column #147 (#191)
Signed-off-by: Asaad Balum <asaad.balum@gmail.com>
This commit is contained in:
parent
6d04cffd61
commit
f22890d307
|
@ -19,3 +19,34 @@ export function buildKindLogoDictionary(workspaceKinds: WorkspaceKind[] | []): K
|
|||
}
|
||||
return kindLogoDict;
|
||||
}
|
||||
|
||||
type WorkspaceRedirectStatus = Record<
|
||||
string,
|
||||
{ to: string; message: string; level: string } | null
|
||||
>;
|
||||
|
||||
/**
|
||||
* Builds a dictionary of workspace kinds to redirect statuses.
|
||||
* @param {WorkspaceKind[]} workspaceKinds - The list of workspace kinds.
|
||||
* @returns {WorkspaceRedirectStatus} A dictionary with kind names as keys and redirect status objects as values.
|
||||
*/
|
||||
export function buildWorkspaceRedirectStatus(
|
||||
workspaceKinds: WorkspaceKind[] | [],
|
||||
): WorkspaceRedirectStatus {
|
||||
const workspaceRedirectStatus: WorkspaceRedirectStatus = {};
|
||||
for (const workspaceKind of workspaceKinds) {
|
||||
// Loop through the `values` array inside `imageConfig`
|
||||
const redirect = workspaceKind.podTemplate.options.imageConfig.values.find(
|
||||
(value) => value.redirect,
|
||||
)?.redirect;
|
||||
// If redirect exists, extract the necessary properties
|
||||
workspaceRedirectStatus[workspaceKind.name] = redirect
|
||||
? {
|
||||
to: redirect.to,
|
||||
message: redirect.message.text,
|
||||
level: redirect.message.level,
|
||||
}
|
||||
: null;
|
||||
}
|
||||
return workspaceRedirectStatus;
|
||||
}
|
||||
|
|
|
@ -25,13 +25,22 @@ import {
|
|||
ActionsColumn,
|
||||
IActions,
|
||||
} from '@patternfly/react-table';
|
||||
import {
|
||||
InfoCircleIcon,
|
||||
ExclamationTriangleIcon,
|
||||
TimesCircleIcon,
|
||||
QuestionCircleIcon,
|
||||
CodeIcon,
|
||||
} from '@patternfly/react-icons';
|
||||
import { useState } from 'react';
|
||||
import { CodeIcon } from '@patternfly/react-icons';
|
||||
import { Workspace, WorkspacesColumnNames, WorkspaceState } from '~/shared/types';
|
||||
import { WorkspaceDetails } from '~/app/pages/Workspaces/Details/WorkspaceDetails';
|
||||
import { ExpandedWorkspaceRow } from '~/app/pages/Workspaces/ExpandedWorkspaceRow';
|
||||
import DeleteModal from '~/shared/components/DeleteModal';
|
||||
import { buildKindLogoDictionary } from '~/app/actions/WorkspaceKindsActions';
|
||||
import {
|
||||
buildKindLogoDictionary,
|
||||
buildWorkspaceRedirectStatus,
|
||||
} from '~/app/actions/WorkspaceKindsActions';
|
||||
import useWorkspaceKinds from '~/app/hooks/useWorkspaceKinds';
|
||||
import { WorkspaceConnectAction } from '~/app/pages/Workspaces/WorkspaceConnectAction';
|
||||
import { WorkspaceStartActionModal } from '~/app/pages/Workspaces/workspaceActions/WorkspaceStartActionModal';
|
||||
|
@ -107,6 +116,10 @@ export const Workspaces: React.FunctionComponent = () => {
|
|||
state: WorkspaceState.Paused,
|
||||
stateMessage: 'It is paused.',
|
||||
},
|
||||
redirectStatus: {
|
||||
level: 'Info',
|
||||
text: 'This is informational', // Tooltip text
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'My Other Jupyter Notebook',
|
||||
|
@ -162,6 +175,10 @@ export const Workspaces: React.FunctionComponent = () => {
|
|||
state: WorkspaceState.Running,
|
||||
stateMessage: 'It is running.',
|
||||
},
|
||||
redirectStatus: {
|
||||
level: 'Danger',
|
||||
text: 'This is dangerous',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -169,8 +186,15 @@ export const Workspaces: React.FunctionComponent = () => {
|
|||
let kindLogoDict: Record<string, string> = {};
|
||||
kindLogoDict = buildKindLogoDictionary(workspaceKinds);
|
||||
|
||||
let workspaceRedirectStatus: Record<
|
||||
string,
|
||||
{ to: string; message: string; level: string } | null
|
||||
> = {}; // Initialize the redirect status dictionary
|
||||
workspaceRedirectStatus = buildWorkspaceRedirectStatus(workspaceKinds); // Populate the dictionary
|
||||
|
||||
// Table columns
|
||||
const columnNames: WorkspacesColumnNames = {
|
||||
redirectStatus: 'Redirect Status',
|
||||
name: 'Name',
|
||||
kind: 'Kind',
|
||||
image: 'Image',
|
||||
|
@ -266,18 +290,20 @@ export const Workspaces: React.FunctionComponent = () => {
|
|||
const [activeSortDirection, setActiveSortDirection] = React.useState<'asc' | 'desc' | null>(null);
|
||||
|
||||
const getSortableRowValues = (workspace: Workspace): (string | number)[] => {
|
||||
const { name, kind, image, podConfig, state, homeVol, cpu, ram, lastActivity } = {
|
||||
name: workspace.name,
|
||||
kind: workspace.kind,
|
||||
image: workspace.options.imageConfig,
|
||||
podConfig: workspace.options.podConfig,
|
||||
state: WorkspaceState[workspace.status.state],
|
||||
homeVol: workspace.podTemplate.volumes.home,
|
||||
cpu: workspace.cpu,
|
||||
ram: workspace.ram,
|
||||
lastActivity: workspace.status.activity.lastActivity,
|
||||
};
|
||||
return [name, kind, image, podConfig, state, homeVol, cpu, ram, lastActivity];
|
||||
const { redirectStatus, name, kind, image, podConfig, state, homeVol, cpu, ram, lastActivity } =
|
||||
{
|
||||
redirectStatus: '',
|
||||
name: workspace.name,
|
||||
kind: workspace.kind,
|
||||
image: workspace.options.imageConfig,
|
||||
podConfig: workspace.options.podConfig,
|
||||
state: WorkspaceState[workspace.status.state],
|
||||
homeVol: workspace.podTemplate.volumes.home,
|
||||
cpu: workspace.cpu,
|
||||
ram: workspace.ram,
|
||||
lastActivity: workspace.status.activity.lastActivity,
|
||||
};
|
||||
return [redirectStatus, name, kind, image, podConfig, state, homeVol, cpu, ram, lastActivity];
|
||||
};
|
||||
|
||||
let sortedWorkspaces = workspaces;
|
||||
|
@ -436,6 +462,43 @@ export const Workspaces: React.FunctionComponent = () => {
|
|||
| 'yellow'
|
||||
)[] = ['green', 'orange', 'yellow', 'blue', 'red', 'purple'];
|
||||
|
||||
// Redirect Status Icons
|
||||
|
||||
const getRedirectStatusIcon = (level: string | undefined, message: string) => {
|
||||
switch (level) {
|
||||
case 'Info':
|
||||
return (
|
||||
<Tooltip content={message}>
|
||||
<InfoCircleIcon color="blue" aria-hidden="true" />
|
||||
</Tooltip>
|
||||
);
|
||||
case 'Warning':
|
||||
return (
|
||||
<Tooltip content={message}>
|
||||
<ExclamationTriangleIcon color="orange" aria-hidden="true" />
|
||||
</Tooltip>
|
||||
);
|
||||
case 'Danger':
|
||||
return (
|
||||
<Tooltip content={message}>
|
||||
<TimesCircleIcon color="red" aria-hidden="true" />
|
||||
</Tooltip>
|
||||
);
|
||||
case undefined:
|
||||
return (
|
||||
<Tooltip content={message}>
|
||||
<QuestionCircleIcon color="gray" aria-hidden="true" />
|
||||
</Tooltip>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<Tooltip content={`Invalid level: ${level}`}>
|
||||
<QuestionCircleIcon color="gray" aria-hidden="true" />
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Pagination
|
||||
|
||||
const [page, setPage] = React.useState(1);
|
||||
|
@ -494,7 +557,10 @@ export const Workspaces: React.FunctionComponent = () => {
|
|||
<Tr>
|
||||
<Th />
|
||||
{Object.values(columnNames).map((columnName, index) => (
|
||||
<Th key={`${columnName}-col-name`} sort={getSortParams(index)}>
|
||||
<Th
|
||||
key={`${columnName}-col-name`}
|
||||
sort={columnName !== 'Redirect Status' ? getSortParams(index) : undefined}
|
||||
>
|
||||
{columnName}
|
||||
</Th>
|
||||
))}
|
||||
|
@ -517,6 +583,15 @@ export const Workspaces: React.FunctionComponent = () => {
|
|||
setWorkspaceExpanded(workspace, !isWorkspaceExpanded(workspace)),
|
||||
}}
|
||||
/>
|
||||
<Td dataLabel={columnNames.redirectStatus}>
|
||||
{workspaceRedirectStatus[workspace.kind]
|
||||
? getRedirectStatusIcon(
|
||||
workspaceRedirectStatus[workspace.kind]?.level,
|
||||
workspaceRedirectStatus[workspace.kind]?.message ||
|
||||
'No API response available',
|
||||
)
|
||||
: getRedirectStatusIcon(undefined, 'No API response available')}
|
||||
</Td>
|
||||
<Td dataLabel={columnNames.name}>{workspace.name}</Td>
|
||||
<Td dataLabel={columnNames.kind}>
|
||||
{kindLogoDict[workspace.kind] ? (
|
||||
|
|
|
@ -38,7 +38,7 @@ export interface WorkspaceKind {
|
|||
pythonVersion: string;
|
||||
};
|
||||
hidden: true;
|
||||
redirect: {
|
||||
redirect?: {
|
||||
to: string;
|
||||
message: {
|
||||
text: string;
|
||||
|
@ -126,6 +126,10 @@ export interface Workspace {
|
|||
podConfig: string;
|
||||
};
|
||||
status: WorkspaceStatus;
|
||||
redirectStatus: {
|
||||
level: 'Info' | 'Warning' | 'Danger';
|
||||
text: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type WorkspacesColumnNames = {
|
||||
|
@ -138,4 +142,5 @@ export type WorkspacesColumnNames = {
|
|||
cpu: string;
|
||||
ram: string;
|
||||
lastActivity: string;
|
||||
redirectStatus: string;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue