feat(ws): Add "Connect" column to workspace table and display popup with workspace endpoints. (#161)
* feat(ws): Add Connect column to workspace table and popup with workspace endpoints Signed-off-by: Yael <fishel.yael@gmail.com> * feat(ws): Split the Connect button, such that clicking it opens the default (main) endpoint Signed-off-by: Yael <fishel.yael@gmail.com> --------- Signed-off-by: Yael <fishel.yael@gmail.com>
This commit is contained in:
parent
055150bb2e
commit
16f97f86d9
|
|
@ -0,0 +1,78 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
Dropdown,
|
||||||
|
DropdownItem,
|
||||||
|
DropdownList,
|
||||||
|
MenuToggle,
|
||||||
|
MenuToggleElement,
|
||||||
|
MenuToggleAction,
|
||||||
|
} from '@patternfly/react-core';
|
||||||
|
import { Workspace, WorkspaceState } from '~/shared/types';
|
||||||
|
|
||||||
|
type WorkspaceConnectActionProps = {
|
||||||
|
workspace: Workspace;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WorkspaceConnectAction: React.FunctionComponent<WorkspaceConnectActionProps> = ({
|
||||||
|
workspace,
|
||||||
|
}) => {
|
||||||
|
const [open, setIsOpen] = React.useState(false);
|
||||||
|
|
||||||
|
const onToggleClick = () => {
|
||||||
|
setIsOpen(!open);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSelect = (
|
||||||
|
_event: React.MouseEvent<Element, MouseEvent> | undefined,
|
||||||
|
value: string | number | undefined,
|
||||||
|
) => {
|
||||||
|
setIsOpen(false);
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
openEndpoint(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onClickConnect = () => {
|
||||||
|
openEndpoint(workspace.podTemplate.endpoints[0].port);
|
||||||
|
};
|
||||||
|
|
||||||
|
const openEndpoint = (port: string) => {
|
||||||
|
window.open(`workspace/${workspace.namespace}/${workspace.name}/${port}`, '_blank');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dropdown
|
||||||
|
isOpen={open}
|
||||||
|
onSelect={onSelect}
|
||||||
|
onOpenChange={(isOpen: boolean) => setIsOpen(isOpen)}
|
||||||
|
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
|
||||||
|
<MenuToggle
|
||||||
|
ref={toggleRef}
|
||||||
|
onClick={onToggleClick}
|
||||||
|
isExpanded={open}
|
||||||
|
isFullWidth
|
||||||
|
isDisabled={workspace.status.state !== WorkspaceState.Running}
|
||||||
|
splitButtonItems={[
|
||||||
|
<MenuToggleAction
|
||||||
|
id="connect-endpoint-button"
|
||||||
|
key="connect-endpoint-button"
|
||||||
|
onClick={onClickConnect}
|
||||||
|
>
|
||||||
|
Connect
|
||||||
|
</MenuToggleAction>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
ouiaId="BasicDropdown"
|
||||||
|
shouldFocusToggleOnSelect
|
||||||
|
>
|
||||||
|
<DropdownList>
|
||||||
|
{workspace.podTemplate.endpoints.map((endpoint) => (
|
||||||
|
<DropdownItem value={endpoint.port} key={`${workspace.name}-${endpoint.port}`}>
|
||||||
|
{endpoint.displayName}
|
||||||
|
</DropdownItem>
|
||||||
|
))}
|
||||||
|
</DropdownList>
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -33,6 +33,7 @@ import { ExpandedWorkspaceRow } from '~/app/pages/Workspaces/ExpandedWorkspaceRo
|
||||||
import DeleteModal from '~/shared/components/DeleteModal';
|
import DeleteModal from '~/shared/components/DeleteModal';
|
||||||
import { buildKindLogoDictionary } from '~/app/actions/WorkspaceKindsActions';
|
import { buildKindLogoDictionary } from '~/app/actions/WorkspaceKindsActions';
|
||||||
import useWorkspaceKinds from '~/app/hooks/useWorkspaceKinds';
|
import useWorkspaceKinds from '~/app/hooks/useWorkspaceKinds';
|
||||||
|
import { WorkspaceConnectAction } from '~/app/pages/Workspaces/WorkspaceConnectAction';
|
||||||
import Filter, { FilteredColumn } from 'shared/components/Filter';
|
import Filter, { FilteredColumn } from 'shared/components/Filter';
|
||||||
import { formatRam } from 'shared/utilities/WorkspaceResources';
|
import { formatRam } from 'shared/utilities/WorkspaceResources';
|
||||||
|
|
||||||
|
|
@ -67,6 +68,12 @@ export const Workspaces: React.FunctionComponent = () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
endpoints: [
|
||||||
|
{
|
||||||
|
displayName: 'JupyterLab',
|
||||||
|
port: '7777',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
imageConfig: 'jupyterlab_scipy_180',
|
imageConfig: 'jupyterlab_scipy_180',
|
||||||
|
|
@ -112,6 +119,16 @@ export const Workspaces: React.FunctionComponent = () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
endpoints: [
|
||||||
|
{
|
||||||
|
displayName: 'JupyterLab',
|
||||||
|
port: '8888',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Spark Master',
|
||||||
|
port: '9999',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
imageConfig: 'jupyterlab_scipy_180',
|
imageConfig: 'jupyterlab_scipy_180',
|
||||||
|
|
@ -461,6 +478,9 @@ export const Workspaces: React.FunctionComponent = () => {
|
||||||
1 hour ago
|
1 hour ago
|
||||||
</Timestamp>
|
</Timestamp>
|
||||||
</Td>
|
</Td>
|
||||||
|
<Td>
|
||||||
|
<WorkspaceConnectAction workspace={workspace} />
|
||||||
|
</Td>
|
||||||
<Td isActionCell data-testid="action-column">
|
<Td isActionCell data-testid="action-column">
|
||||||
<ActionsColumn
|
<ActionsColumn
|
||||||
items={defaultActions(workspace).map((action) => ({
|
items={defaultActions(workspace).map((action) => ({
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,10 @@ export interface Workspace {
|
||||||
readOnly: boolean;
|
readOnly: boolean;
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
|
endpoints: {
|
||||||
|
displayName: string;
|
||||||
|
port: string;
|
||||||
|
}[];
|
||||||
};
|
};
|
||||||
options: {
|
options: {
|
||||||
imageConfig: string;
|
imageConfig: string;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue