Skip to content

feat(ws): Introduce drawer to workspace creation wizard #310

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

Open
wants to merge 2 commits into
base: notebooks-v2
Choose a base branch
from
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { Ref } from 'react';
import {
Drawer,
DrawerPanelContent,
DrawerContent,
DrawerContentBody,
DrawerHead,
DrawerActions,
DrawerCloseButton,
Title,
} from '@patternfly/react-core';

interface WorkspaceCreationDrawerProps {
children: React.ReactNode;
title: string;
info: React.ReactNode;
isExpanded: boolean;
drawerRef?: Ref<HTMLSpanElement>;
onCloseClick: () => void;
onExpand: () => void;
}

export const WorkspaceCreationDrawer: React.FC<WorkspaceCreationDrawerProps> = ({
children,
isExpanded,
drawerRef,
title,
info,
onCloseClick,
onExpand,
}) => {
const panelContent = (
<DrawerPanelContent>
<DrawerHead>
<span role="button" tabIndex={isExpanded ? 0 : -1} ref={drawerRef as Ref<HTMLSpanElement>}>
<Title headingLevel="h6">{title}</Title>
</span>
<DrawerActions>
<DrawerCloseButton onClick={onCloseClick} />
</DrawerActions>
</DrawerHead>
{info}
</DrawerPanelContent>
);

return (
<>
<Drawer isExpanded={isExpanded} isInline onExpand={onExpand}>
<DrawerContent panelContent={panelContent}>
<DrawerContentBody>{children}</DrawerContentBody>
</DrawerContent>
</Drawer>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@ type WorkspaceCreationImageDetailsProps = {
export const WorkspaceCreationImageDetails: React.FunctionComponent<
WorkspaceCreationImageDetailsProps
> = ({ workspaceImage }) => (
<>
{!workspaceImage && <p>Select an image to view its details here.</p>}

<div style={{ marginLeft: 'var(--pf-t--global--spacer--md)' }}>
{workspaceImage && (
<>
<Title headingLevel="h6">Image</Title>
<Title headingLevel="h3">{workspaceImage.displayName}</Title>
<br />
<List isPlain>
Expand All @@ -26,5 +23,5 @@ export const WorkspaceCreationImageDetails: React.FunctionComponent<
</List>
</>
)}
</>
</div>
);
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as React from 'react';
import React, { useMemo, useState } from 'react';
import { Content, Divider, Split, SplitItem } from '@patternfly/react-core';
import { useMemo, useState } from 'react';
import { WorkspaceImage } from '~/shared/types';
import { WorkspaceCreationImageDetails } from '~/app/pages/Workspaces/Creation/image/WorkspaceCreationImageDetails';
import { WorkspaceCreationImageList } from '~/app/pages/Workspaces/Creation/image/WorkspaceCreationImageList';
import { FilterByLabels } from '~/app/pages/Workspaces/Creation/labelFilter/FilterByLabels';
import { WorkspaceCreationDrawer } from '~/app/pages/Workspaces/Creation/WorkspaceCreationDrawer';

interface WorkspaceCreationImageSelectionProps {
images: WorkspaceImage[];
Expand All @@ -16,6 +16,23 @@ const WorkspaceCreationImageSelection: React.FunctionComponent<
WorkspaceCreationImageSelectionProps
> = ({ images, selectedImage, onSelect }) => {
const [selectedLabels, setSelectedLabels] = useState<Map<string, Set<string>>>(new Map());
const [isExpanded, setIsExpanded] = useState(false);
const drawerRef = React.useRef<HTMLSpanElement>(undefined);

const onExpand = () => {
if (drawerRef.current) {
drawerRef.current.focus();
}
};

const onClick = (image?: WorkspaceImage) => {
setIsExpanded(true);
onSelect(image);
};

const onCloseClick = () => {
setIsExpanded(false);
};

const imageFilterContent = useMemo(
() => (
Expand All @@ -40,14 +57,21 @@ const WorkspaceCreationImageSelection: React.FunctionComponent<
<Split hasGutter>
<SplitItem style={{ minWidth: '200px' }}>{imageFilterContent}</SplitItem>
<SplitItem isFilled>
<WorkspaceCreationImageList
images={images}
selectedLabels={selectedLabels}
selectedImage={selectedImage}
onSelect={onSelect}
/>
<WorkspaceCreationDrawer
title="Image"
info={imageDetailsContent}
isExpanded={isExpanded}
onCloseClick={onCloseClick}
onExpand={onExpand}
>
<WorkspaceCreationImageList
images={images}
selectedLabels={selectedLabels}
selectedImage={selectedImage}
onSelect={onClick}
/>
</WorkspaceCreationDrawer>
</SplitItem>
<SplitItem style={{ minWidth: '200px' }}>{imageDetailsContent}</SplitItem>
</Split>
</Content>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,12 @@ type WorkspaceCreationKindDetailsProps = {
export const WorkspaceCreationKindDetails: React.FunctionComponent<
WorkspaceCreationKindDetailsProps
> = ({ workspaceKind }) => (
<>
{!workspaceKind && <p>Select a workspace kind to view its details here.</p>}

<div style={{ marginLeft: 'var(--pf-t--global--spacer--md)' }}>
{workspaceKind && (
<>
<Title headingLevel="h6">Workspace kind</Title>
<Title headingLevel="h3">{workspaceKind.name}</Title>
<p>{workspaceKind.description}</p>
</>
)}
</>
</div>
);
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as React from 'react';
import { Content, Divider, Split, SplitItem } from '@patternfly/react-core';
import { useMemo } from 'react';
import React, { useState, useRef, useMemo } from 'react';
import { Content, Divider } from '@patternfly/react-core';
import { WorkspaceKind } from '~/shared/types';
import { WorkspaceCreationKindDetails } from '~/app/pages/Workspaces/Creation/kind/WorkspaceCreationKindDetails';
import { WorkspaceCreationKindList } from '~/app/pages/Workspaces/Creation/kind/WorkspaceCreationKindList';
import { WorkspaceCreationDrawer } from '~/app/pages/Workspaces/Creation/WorkspaceCreationDrawer';

interface WorkspaceCreationKindSelectionProps {
selectedKind: WorkspaceKind | undefined;
Expand All @@ -13,6 +13,24 @@ interface WorkspaceCreationKindSelectionProps {
const WorkspaceCreationKindSelection: React.FunctionComponent<
WorkspaceCreationKindSelectionProps
> = ({ selectedKind, onSelect }) => {
const [isExpanded, setIsExpanded] = useState(false);
const drawerRef = useRef<HTMLSpanElement>(undefined);

const onExpand = () => {
if (drawerRef.current) {
drawerRef.current.focus();
}
};

const onClick = (kind?: WorkspaceKind) => {
setIsExpanded(true);
return onSelect(kind);
};

const onCloseClick = () => {
setIsExpanded(false);
};

/* Replace mocks below for BFF call */
const mockedWorkspaceKind: WorkspaceKind = useMemo(
() => ({
Expand Down Expand Up @@ -41,7 +59,7 @@ const WorkspaceCreationKindSelection: React.FunctionComponent<
{
id: 'jupyterlab_scipy_180',
displayName: 'jupyter-scipy:v1.8.0',
labels: { pythonVersion: '3.11', jupyterlabVersion: '1.8.0' },
labels: { 'Python Version': '3.11', 'JupyterLab Version': '1.8.0' },
hidden: true,
redirect: {
to: 'jupyterlab_scipy_190',
Expand All @@ -54,7 +72,7 @@ const WorkspaceCreationKindSelection: React.FunctionComponent<
{
id: 'jupyterlab_scipy_190',
displayName: 'jupyter-scipy:v1.9.0',
labels: { pythonVersion: '3.12', jupyterlabVersion: '1.9.0' },
labels: { 'Python Version': '3.12', 'JupyterLab Version': '1.9.0' },
hidden: true,
redirect: {
to: 'jupyterlab_scipy_200',
Expand All @@ -67,7 +85,7 @@ const WorkspaceCreationKindSelection: React.FunctionComponent<
{
id: 'jupyterlab_scipy_200',
displayName: 'jupyter-scipy:v2.0.0',
labels: { pythonVersion: '3.12', jupyterlabVersion: '2.0.0' },
labels: { 'Python Version': '3.12', 'JupyterLab Version': '2.0.0' },
hidden: true,
redirect: {
to: 'jupyterlab_scipy_210',
Expand All @@ -80,7 +98,7 @@ const WorkspaceCreationKindSelection: React.FunctionComponent<
{
id: 'jupyterlab_scipy_210',
displayName: 'jupyter-scipy:v2.1.0',
labels: { pythonVersion: '3.13', jupyterlabVersion: '2.1.0' },
labels: { 'Python Version': '3.13', 'JupyterLab Version': '2.1.0' },
hidden: true,
redirect: {
to: 'jupyterlab_scipy_220',
Expand Down Expand Up @@ -152,16 +170,19 @@ const WorkspaceCreationKindSelection: React.FunctionComponent<
<Content style={{ height: '100%' }}>
<p>Select a workspace kind to use for the workspace.</p>
<Divider />
<Split hasGutter>
<SplitItem isFilled>
<WorkspaceCreationKindList
allWorkspaceKinds={allWorkspaceKinds}
selectedKind={selectedKind}
onSelect={onSelect}
/>
</SplitItem>
<SplitItem style={{ minWidth: '200px' }}>{kindDetailsContent}</SplitItem>
</Split>
<WorkspaceCreationDrawer
title="Workspace kind"
info={kindDetailsContent}
isExpanded={isExpanded}
onCloseClick={onCloseClick}
onExpand={onExpand}
>
<WorkspaceCreationKindList
allWorkspaceKinds={allWorkspaceKinds}
selectedKind={selectedKind}
onSelect={onClick}
/>
</WorkspaceCreationDrawer>
</Content>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { List, ListItem, Title } from '@patternfly/react-core';
import { List, ListItem } from '@patternfly/react-core';
import { WorkspacePodConfig } from '~/shared/types';

type WorkspaceCreationPodConfigDetailsProps = {
Expand All @@ -10,12 +10,8 @@ export const WorkspaceCreationPodConfigDetails: React.FunctionComponent<
WorkspaceCreationPodConfigDetailsProps
> = ({ workspacePodConfig }) => (
<>
{!workspacePodConfig && <p>Select a pod config to view its details here.</p>}

{workspacePodConfig && (
<>
<Title headingLevel="h6">Pod config</Title>
<Title headingLevel="h3">{workspacePodConfig.displayName}</Title>
<div style={{ marginLeft: 'var(--pf-t--global--spacer--md)' }}>
<p>{workspacePodConfig.description}</p>
<List isPlain>
{Object.keys(workspacePodConfig.labels).map((labelKey) => (
Expand All @@ -24,7 +20,7 @@ export const WorkspaceCreationPodConfigDetails: React.FunctionComponent<
</ListItem>
))}
</List>
</>
</div>
)}
</>
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { WorkspacePodConfig } from '~/shared/types';
import { WorkspaceCreationPodConfigDetails } from '~/app/pages/Workspaces/Creation/podConfig/WorkspaceCreationPodConfigDetails';
import { WorkspaceCreationPodConfigList } from '~/app/pages/Workspaces/Creation/podConfig/WorkspaceCreationPodConfigList';
import { FilterByLabels } from '~/app/pages/Workspaces/Creation/labelFilter/FilterByLabels';
import { WorkspaceCreationDrawer } from '~/app/pages/Workspaces/Creation/WorkspaceCreationDrawer';

interface WorkspaceCreationPodConfigSelectionProps {
podConfigs: WorkspacePodConfig[];
Expand All @@ -16,6 +17,23 @@ const WorkspaceCreationPodConfigSelection: React.FunctionComponent<
WorkspaceCreationPodConfigSelectionProps
> = ({ podConfigs, selectedPodConfig, onSelect }) => {
const [selectedLabels, setSelectedLabels] = useState<Map<string, Set<string>>>(new Map());
const [isExpanded, setIsExpanded] = useState(false);
const drawerRef = React.useRef<HTMLSpanElement>(undefined);

const onExpand = () => {
if (drawerRef.current) {
drawerRef.current.focus();
}
};

const onClick = (podConfig?: WorkspacePodConfig) => {
setIsExpanded(true);
onSelect(podConfig);
};

const onCloseClick = () => {
setIsExpanded(false);
};
Comment on lines +23 to +36
Copy link
Member

Choose a reason for hiding this comment

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

Can we memoize these @thaorell ?


const podConfigFilterContent = useMemo(
() => (
Expand All @@ -40,14 +58,21 @@ const WorkspaceCreationPodConfigSelection: React.FunctionComponent<
<Split hasGutter>
<SplitItem style={{ minWidth: '200px' }}>{podConfigFilterContent}</SplitItem>
<SplitItem isFilled>
<WorkspaceCreationPodConfigList
podConfigs={podConfigs}
selectedLabels={selectedLabels}
selectedPodConfig={selectedPodConfig}
onSelect={onSelect}
/>
<WorkspaceCreationDrawer
title="Pod config"
info={podConfigDetailsContent}
isExpanded={isExpanded}
onCloseClick={onCloseClick}
onExpand={onExpand}
>
<WorkspaceCreationPodConfigList
podConfigs={podConfigs}
selectedLabels={selectedLabels}
selectedPodConfig={selectedPodConfig}
onSelect={onClick}
/>
</WorkspaceCreationDrawer>
</SplitItem>
<SplitItem style={{ minWidth: '200px' }}>{podConfigDetailsContent}</SplitItem>
</Split>
</Content>
);
Expand Down