Skip to content

Commit 9fcb9a2

Browse files
committed
feat(ws): Introduce drawer to workspace creation wizard
Signed-off-by: Charles Thao <[email protected]>
1 parent 6123650 commit 9fcb9a2

7 files changed

+161
-46
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React, { Ref } from 'react';
2+
import {
3+
Drawer,
4+
DrawerPanelContent,
5+
DrawerContent,
6+
DrawerContentBody,
7+
DrawerHead,
8+
DrawerActions,
9+
DrawerCloseButton,
10+
Title,
11+
} from '@patternfly/react-core';
12+
13+
interface WorkspaceCreationDrawerProps {
14+
children: React.ReactNode;
15+
title: string;
16+
info: React.ReactNode;
17+
isExpanded: boolean;
18+
drawerRef?: Ref<HTMLSpanElement>;
19+
onCloseClick: () => void;
20+
onExpand: () => void;
21+
}
22+
23+
export const WorkspaceCreationDrawer: React.FC<WorkspaceCreationDrawerProps> = ({
24+
children,
25+
isExpanded,
26+
drawerRef,
27+
title,
28+
info,
29+
onCloseClick,
30+
onExpand,
31+
}) => {
32+
const panelContent = (
33+
<DrawerPanelContent>
34+
<DrawerHead>
35+
<span role="button" tabIndex={isExpanded ? 0 : -1} ref={drawerRef as Ref<HTMLSpanElement>}>
36+
<Title headingLevel="h6">{title}</Title>
37+
</span>
38+
<DrawerActions>
39+
<DrawerCloseButton onClick={onCloseClick} />
40+
</DrawerActions>
41+
</DrawerHead>
42+
{info}
43+
</DrawerPanelContent>
44+
);
45+
46+
return (
47+
<>
48+
<Drawer isExpanded={isExpanded} isInline onExpand={onExpand}>
49+
<DrawerContent panelContent={panelContent}>
50+
<DrawerContentBody>{children}</DrawerContentBody>
51+
</DrawerContent>
52+
</Drawer>
53+
</>
54+
);
55+
};

workspaces/frontend/src/app/pages/Workspaces/Creation/image/WorkspaceCreationImageDetails.tsx

+2-5
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,9 @@ type WorkspaceCreationImageDetailsProps = {
99
export const WorkspaceCreationImageDetails: React.FunctionComponent<
1010
WorkspaceCreationImageDetailsProps
1111
> = ({ workspaceImage }) => (
12-
<>
13-
{!workspaceImage && <p>Select an image to view its details here.</p>}
14-
12+
<div style={{ marginLeft: 'var(--pf-t--global--spacer--md)' }}>
1513
{workspaceImage && (
1614
<>
17-
<Title headingLevel="h6">Image</Title>
1815
<Title headingLevel="h3">{workspaceImage.displayName}</Title>
1916
<br />
2017
<List isPlain>
@@ -26,5 +23,5 @@ export const WorkspaceCreationImageDetails: React.FunctionComponent<
2623
</List>
2724
</>
2825
)}
29-
</>
26+
</div>
3027
);

workspaces/frontend/src/app/pages/Workspaces/Creation/image/WorkspaceCreationImageSelection.tsx

+33-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import * as React from 'react';
1+
import React, { useMemo, useState } from 'react';
22
import { Content, Divider, Split, SplitItem } from '@patternfly/react-core';
3-
import { useMemo, useState } from 'react';
43
import { WorkspaceImage } from '~/shared/types';
54
import { WorkspaceCreationImageDetails } from '~/app/pages/Workspaces/Creation/image/WorkspaceCreationImageDetails';
65
import { WorkspaceCreationImageList } from '~/app/pages/Workspaces/Creation/image/WorkspaceCreationImageList';
76
import { FilterByLabels } from '~/app/pages/Workspaces/Creation/labelFilter/FilterByLabels';
7+
import { WorkspaceCreationDrawer } from '~/app/pages/Workspaces/Creation/WorkspaceCreationDrawer';
88

99
interface WorkspaceCreationImageSelectionProps {
1010
images: WorkspaceImage[];
@@ -16,6 +16,23 @@ const WorkspaceCreationImageSelection: React.FunctionComponent<
1616
WorkspaceCreationImageSelectionProps
1717
> = ({ images, selectedImage, onSelect }) => {
1818
const [selectedLabels, setSelectedLabels] = useState<Map<string, Set<string>>>(new Map());
19+
const [isExpanded, setIsExpanded] = useState(false);
20+
const drawerRef = React.useRef<HTMLSpanElement>(undefined);
21+
22+
const onExpand = () => {
23+
if (drawerRef.current) {
24+
drawerRef.current.focus();
25+
}
26+
};
27+
28+
const onClick = (image?: WorkspaceImage) => {
29+
setIsExpanded(true);
30+
onSelect(image);
31+
};
32+
33+
const onCloseClick = () => {
34+
setIsExpanded(false);
35+
};
1936

2037
const imageFilterContent = useMemo(
2138
() => (
@@ -40,14 +57,21 @@ const WorkspaceCreationImageSelection: React.FunctionComponent<
4057
<Split hasGutter>
4158
<SplitItem style={{ minWidth: '200px' }}>{imageFilterContent}</SplitItem>
4259
<SplitItem isFilled>
43-
<WorkspaceCreationImageList
44-
images={images}
45-
selectedLabels={selectedLabels}
46-
selectedImage={selectedImage}
47-
onSelect={onSelect}
48-
/>
60+
<WorkspaceCreationDrawer
61+
title="Image"
62+
info={imageDetailsContent}
63+
isExpanded={isExpanded}
64+
onCloseClick={onCloseClick}
65+
onExpand={onExpand}
66+
>
67+
<WorkspaceCreationImageList
68+
images={images}
69+
selectedLabels={selectedLabels}
70+
selectedImage={selectedImage}
71+
onSelect={onClick}
72+
/>
73+
</WorkspaceCreationDrawer>
4974
</SplitItem>
50-
<SplitItem style={{ minWidth: '200px' }}>{imageDetailsContent}</SplitItem>
5175
</Split>
5276
</Content>
5377
);

workspaces/frontend/src/app/pages/Workspaces/Creation/kind/WorkspaceCreationKindDetails.tsx

+2-5
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,12 @@ type WorkspaceCreationKindDetailsProps = {
99
export const WorkspaceCreationKindDetails: React.FunctionComponent<
1010
WorkspaceCreationKindDetailsProps
1111
> = ({ workspaceKind }) => (
12-
<>
13-
{!workspaceKind && <p>Select a workspace kind to view its details here.</p>}
14-
12+
<div style={{ marginLeft: 'var(--pf-t--global--spacer--md)' }}>
1513
{workspaceKind && (
1614
<>
17-
<Title headingLevel="h6">Workspace kind</Title>
1815
<Title headingLevel="h3">{workspaceKind.name}</Title>
1916
<p>{workspaceKind.description}</p>
2017
</>
2118
)}
22-
</>
19+
</div>
2320
);

workspaces/frontend/src/app/pages/Workspaces/Creation/kind/WorkspaceCreationKindSelection.tsx

+34-13
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import * as React from 'react';
2-
import { Content, Divider, Split, SplitItem } from '@patternfly/react-core';
3-
import { useMemo } from 'react';
1+
import React, { useState, useRef, useMemo } from 'react';
2+
import { Content, Divider } from '@patternfly/react-core';
43
import { WorkspaceKind } from '~/shared/types';
54
import { WorkspaceCreationKindDetails } from '~/app/pages/Workspaces/Creation/kind/WorkspaceCreationKindDetails';
65
import { WorkspaceCreationKindList } from '~/app/pages/Workspaces/Creation/kind/WorkspaceCreationKindList';
6+
import { WorkspaceCreationDrawer } from '~/app/pages/Workspaces/Creation/WorkspaceCreationDrawer';
77

88
interface WorkspaceCreationKindSelectionProps {
99
selectedKind: WorkspaceKind | undefined;
@@ -13,6 +13,24 @@ interface WorkspaceCreationKindSelectionProps {
1313
const WorkspaceCreationKindSelection: React.FunctionComponent<
1414
WorkspaceCreationKindSelectionProps
1515
> = ({ selectedKind, onSelect }) => {
16+
const [isExpanded, setIsExpanded] = useState(false);
17+
const drawerRef = useRef<HTMLSpanElement>(undefined);
18+
19+
const onExpand = () => {
20+
if (drawerRef.current) {
21+
drawerRef.current.focus();
22+
}
23+
};
24+
25+
const onClick = (kind?: WorkspaceKind) => {
26+
setIsExpanded(true);
27+
return onSelect(kind);
28+
};
29+
30+
const onCloseClick = () => {
31+
setIsExpanded(false);
32+
};
33+
1634
/* Replace mocks below for BFF call */
1735
const mockedWorkspaceKind: WorkspaceKind = useMemo(
1836
() => ({
@@ -152,16 +170,19 @@ const WorkspaceCreationKindSelection: React.FunctionComponent<
152170
<Content style={{ height: '100%' }}>
153171
<p>Select a workspace kind to use for the workspace.</p>
154172
<Divider />
155-
<Split hasGutter>
156-
<SplitItem isFilled>
157-
<WorkspaceCreationKindList
158-
allWorkspaceKinds={allWorkspaceKinds}
159-
selectedKind={selectedKind}
160-
onSelect={onSelect}
161-
/>
162-
</SplitItem>
163-
<SplitItem style={{ minWidth: '200px' }}>{kindDetailsContent}</SplitItem>
164-
</Split>
173+
<WorkspaceCreationDrawer
174+
title="Workspace kind"
175+
info={kindDetailsContent}
176+
isExpanded={isExpanded}
177+
onCloseClick={onCloseClick}
178+
onExpand={onExpand}
179+
>
180+
<WorkspaceCreationKindList
181+
allWorkspaceKinds={allWorkspaceKinds}
182+
selectedKind={selectedKind}
183+
onSelect={onClick}
184+
/>
185+
</WorkspaceCreationDrawer>
165186
</Content>
166187
);
167188
};
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { List, ListItem, Title } from '@patternfly/react-core';
2+
import { List, ListItem } from '@patternfly/react-core';
33
import { WorkspacePodConfig } from '~/shared/types';
44

55
type WorkspaceCreationPodConfigDetailsProps = {
@@ -10,12 +10,8 @@ export const WorkspaceCreationPodConfigDetails: React.FunctionComponent<
1010
WorkspaceCreationPodConfigDetailsProps
1111
> = ({ workspacePodConfig }) => (
1212
<>
13-
{!workspacePodConfig && <p>Select a pod config to view its details here.</p>}
14-
1513
{workspacePodConfig && (
16-
<>
17-
<Title headingLevel="h6">Pod config</Title>
18-
<Title headingLevel="h3">{workspacePodConfig.displayName}</Title>
14+
<div style={{ marginLeft: 'var(--pf-t--global--spacer--md)' }}>
1915
<p>{workspacePodConfig.description}</p>
2016
<List isPlain>
2117
{Object.keys(workspacePodConfig.labels).map((labelKey) => (
@@ -24,7 +20,7 @@ export const WorkspaceCreationPodConfigDetails: React.FunctionComponent<
2420
</ListItem>
2521
))}
2622
</List>
27-
</>
23+
</div>
2824
)}
2925
</>
3026
);

workspaces/frontend/src/app/pages/Workspaces/Creation/podConfig/WorkspaceCreationPodConfigSelection.tsx

+32-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { WorkspacePodConfig } from '~/shared/types';
55
import { WorkspaceCreationPodConfigDetails } from '~/app/pages/Workspaces/Creation/podConfig/WorkspaceCreationPodConfigDetails';
66
import { WorkspaceCreationPodConfigList } from '~/app/pages/Workspaces/Creation/podConfig/WorkspaceCreationPodConfigList';
77
import { FilterByLabels } from '~/app/pages/Workspaces/Creation/labelFilter/FilterByLabels';
8+
import { WorkspaceCreationDrawer } from '~/app/pages/Workspaces/Creation/WorkspaceCreationDrawer';
89

910
interface WorkspaceCreationPodConfigSelectionProps {
1011
podConfigs: WorkspacePodConfig[];
@@ -16,6 +17,23 @@ const WorkspaceCreationPodConfigSelection: React.FunctionComponent<
1617
WorkspaceCreationPodConfigSelectionProps
1718
> = ({ podConfigs, selectedPodConfig, onSelect }) => {
1819
const [selectedLabels, setSelectedLabels] = useState<Map<string, Set<string>>>(new Map());
20+
const [isExpanded, setIsExpanded] = useState(false);
21+
const drawerRef = React.useRef<HTMLSpanElement>(undefined);
22+
23+
const onExpand = () => {
24+
if (drawerRef.current) {
25+
drawerRef.current.focus();
26+
}
27+
};
28+
29+
const onClick = (podConfig?: WorkspacePodConfig) => {
30+
setIsExpanded(true);
31+
onSelect(podConfig);
32+
};
33+
34+
const onCloseClick = () => {
35+
setIsExpanded(false);
36+
};
1937

2038
const podConfigFilterContent = useMemo(
2139
() => (
@@ -40,14 +58,21 @@ const WorkspaceCreationPodConfigSelection: React.FunctionComponent<
4058
<Split hasGutter>
4159
<SplitItem style={{ minWidth: '200px' }}>{podConfigFilterContent}</SplitItem>
4260
<SplitItem isFilled>
43-
<WorkspaceCreationPodConfigList
44-
podConfigs={podConfigs}
45-
selectedLabels={selectedLabels}
46-
selectedPodConfig={selectedPodConfig}
47-
onSelect={onSelect}
48-
/>
61+
<WorkspaceCreationDrawer
62+
title="Pod config"
63+
info={podConfigDetailsContent}
64+
isExpanded={isExpanded}
65+
onCloseClick={onCloseClick}
66+
onExpand={onExpand}
67+
>
68+
<WorkspaceCreationPodConfigList
69+
podConfigs={podConfigs}
70+
selectedLabels={selectedLabels}
71+
selectedPodConfig={selectedPodConfig}
72+
onSelect={onClick}
73+
/>
74+
</WorkspaceCreationDrawer>
4975
</SplitItem>
50-
<SplitItem style={{ minWidth: '200px' }}>{podConfigDetailsContent}</SplitItem>
5176
</Split>
5277
</Content>
5378
);

0 commit comments

Comments
 (0)