Skip to content

Commit 3feccf7

Browse files
jenny-s51Bhakti Narvekar
authored andcommitted
fix(ws): Improve workspace form drawer details and wizard flow (kubeflow#467)
Signed-off-by: Jenny <[email protected]> move formatLabel to separate util add title, divider, and fix wizard buttons to align with PF design guidelines Signed-off-by: Jenny <[email protected]> prevent wizard button from active state when no selection Signed-off-by: Jenny <[email protected]> rebase Signed-off-by: Jenny <[email protected]> handle standard infra resource types
1 parent 3fed049 commit 3feccf7

File tree

7 files changed

+106
-42
lines changed

7 files changed

+106
-42
lines changed

workspaces/frontend/src/app/pages/Workspaces/Form/WorkspaceForm.tsx

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,29 @@ const WorkspaceForm: React.FC = () => {
8686

8787
const canGoToPreviousStep = useMemo(() => currentStep > 0, [currentStep]);
8888

89+
const isCurrentStepValid = useMemo(() => {
90+
switch (currentStep) {
91+
case WorkspaceFormSteps.KindSelection:
92+
return !!data.kind;
93+
case WorkspaceFormSteps.ImageSelection:
94+
return !!data.image;
95+
case WorkspaceFormSteps.PodConfigSelection:
96+
return !!data.podConfig;
97+
case WorkspaceFormSteps.Properties:
98+
return !!data.properties.workspaceName.trim();
99+
default:
100+
return false;
101+
}
102+
}, [currentStep, data]);
103+
89104
const canGoToNextStep = useMemo(
90105
() => currentStep < Object.keys(WorkspaceFormSteps).length / 2 - 1,
91106
[currentStep],
92107
);
93108

94109
const canSubmit = useMemo(
95-
() => !isSubmitting && !canGoToNextStep,
96-
[canGoToNextStep, isSubmitting],
110+
() => !isSubmitting && !canGoToNextStep && isCurrentStepValid,
111+
[canGoToNextStep, isSubmitting, isCurrentStepValid],
97112
);
98113

99114
const handleSubmit = useCallback(async () => {
@@ -255,33 +270,34 @@ const WorkspaceForm: React.FC = () => {
255270
<Flex>
256271
<FlexItem>
257272
<Button
258-
variant="primary"
259-
ouiaId="Primary"
273+
variant="secondary"
274+
ouiaId="Secondary"
260275
onClick={previousStep}
261276
isDisabled={!canGoToPreviousStep}
262277
>
263278
Previous
264279
</Button>
265280
</FlexItem>
266281
<FlexItem>
267-
<Button
268-
variant="primary"
269-
ouiaId="Primary"
270-
onClick={nextStep}
271-
isDisabled={!canGoToNextStep}
272-
>
273-
Next
274-
</Button>
275-
</FlexItem>
276-
<FlexItem>
277-
<Button
278-
variant="primary"
279-
ouiaId="Primary"
280-
onClick={handleSubmit}
281-
isDisabled={!canSubmit}
282-
>
283-
{mode === 'create' ? 'Create' : 'Save'}
284-
</Button>
282+
{canGoToNextStep ? (
283+
<Button
284+
variant="primary"
285+
ouiaId="Primary"
286+
onClick={nextStep}
287+
isDisabled={!isCurrentStepValid}
288+
>
289+
Next
290+
</Button>
291+
) : (
292+
<Button
293+
variant="primary"
294+
ouiaId="Primary"
295+
onClick={handleSubmit}
296+
isDisabled={!canSubmit}
297+
>
298+
{mode === 'create' ? 'Create' : 'Save'}
299+
</Button>
300+
)}
285301
</FlexItem>
286302
<FlexItem>
287303
<Button variant="link" isInline onClick={cancel}>

workspaces/frontend/src/app/pages/Workspaces/Form/image/WorkspaceFormImageDetails.tsx

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import React from 'react';
2-
import { List, ListItem, Title } from '@patternfly/react-core';
2+
import {
3+
DescriptionList,
4+
DescriptionListTerm,
5+
DescriptionListGroup,
6+
DescriptionListDescription,
7+
Title,
8+
} from '@patternfly/react-core';
39
import { WorkspacePodConfigValue } from '~/shared/api/backendApiTypes';
10+
import { formatLabelKey } from '~/shared/utilities/WorkspaceUtils';
411

512
type WorkspaceFormImageDetailsProps = {
613
workspaceImage?: WorkspacePodConfigValue;
@@ -14,13 +21,21 @@ export const WorkspaceFormImageDetails: React.FunctionComponent<WorkspaceFormIma
1421
<>
1522
<Title headingLevel="h3">{workspaceImage.displayName}</Title>
1623
<br />
17-
<List isPlain>
18-
{workspaceImage.labels.map((label) => (
19-
<ListItem key={label.key}>
20-
{label.key}={label.value}
21-
</ListItem>
22-
))}
23-
</List>
24+
{workspaceImage.labels.map((label) => (
25+
<DescriptionList
26+
key={label.key}
27+
isHorizontal
28+
isCompact
29+
horizontalTermWidthModifier={{
30+
default: '17ch',
31+
}}
32+
>
33+
<DescriptionListGroup>
34+
<DescriptionListTerm>{formatLabelKey(label.key)}</DescriptionListTerm>
35+
<DescriptionListDescription>{label.value}</DescriptionListDescription>
36+
</DescriptionListGroup>
37+
</DescriptionList>
38+
))}
2439
</>
2540
)}
2641
</div>

workspaces/frontend/src/app/pages/Workspaces/Form/kind/WorkspaceFormKindDetails.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export const WorkspaceFormKindDetails: React.FunctionComponent<WorkspaceFormKind
1212
<div style={{ marginLeft: 'var(--pf-t--global--spacer--md)' }}>
1313
{workspaceKind && (
1414
<>
15-
<Title headingLevel="h3">{workspaceKind.name}</Title>
15+
<Title headingLevel="h3">{workspaceKind.displayName}</Title>
1616
<p>{workspaceKind.description}</p>
1717
</>
1818
)}

workspaces/frontend/src/app/pages/Workspaces/Form/labelFilter/FilterByLabels.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
} from '@patternfly/react-catalog-view-extension';
77
import '@patternfly/react-catalog-view-extension/dist/css/react-catalog-view-extension.css';
88
import { WorkspaceOptionLabel } from '~/shared/api/backendApiTypes';
9+
import { formatLabelKey } from '~/shared/utilities/WorkspaceUtils';
910

1011
type FilterByLabelsProps = {
1112
labelledObjects: WorkspaceOptionLabel[];
@@ -60,7 +61,7 @@ export const FilterByLabels: React.FunctionComponent<FilterByLabelsProps> = ({
6061
return (
6162
<FilterSidePanel id="filter-panel">
6263
{[...filterMap.keys()].map((label) => (
63-
<FilterSidePanelCategory key={label} title={label}>
64+
<FilterSidePanelCategory key={label} title={formatLabelKey(label)}>
6465
{Array.from(filterMap.get(label)?.values() ?? []).map((labelValue) => (
6566
<FilterSidePanelCategoryItem
6667
key={`${label}|||${labelValue}`}

workspaces/frontend/src/app/pages/Workspaces/Form/podConfig/WorkspaceFormPodConfigDetails.tsx

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
import React from 'react';
2-
import { List, ListItem } from '@patternfly/react-core';
2+
import {
3+
DescriptionList,
4+
DescriptionListTerm,
5+
DescriptionListGroup,
6+
DescriptionListDescription,
7+
Title,
8+
Divider,
9+
} from '@patternfly/react-core';
310
import { WorkspacePodConfigValue } from '~/shared/api/backendApiTypes';
11+
import { formatLabelKey } from '~/shared/utilities/WorkspaceUtils';
412

513
type WorkspaceFormPodConfigDetailsProps = {
614
workspacePodConfig?: WorkspacePodConfigValue;
@@ -12,14 +20,23 @@ export const WorkspaceFormPodConfigDetails: React.FunctionComponent<
1220
<>
1321
{workspacePodConfig && (
1422
<div style={{ marginLeft: 'var(--pf-t--global--spacer--md)' }}>
23+
<Title headingLevel="h3">{workspacePodConfig.displayName}</Title>{' '}
1524
<p>{workspacePodConfig.description}</p>
16-
<List isPlain>
17-
{workspacePodConfig.labels.map((label) => (
18-
<ListItem key={label.key}>
19-
{label.key}={label.value}
20-
</ListItem>
21-
))}
22-
</List>
25+
<Divider />
26+
{workspacePodConfig.labels.map((label) => (
27+
<DescriptionList
28+
key={label.key}
29+
isHorizontal
30+
horizontalTermWidthModifier={{
31+
default: '12ch',
32+
}}
33+
>
34+
<DescriptionListGroup>
35+
<DescriptionListTerm>{formatLabelKey(label.key)}</DescriptionListTerm>
36+
<DescriptionListDescription>{label.value}</DescriptionListDescription>
37+
</DescriptionListGroup>
38+
</DescriptionList>
39+
))}
2340
</div>
2441
)}
2542
</>

workspaces/frontend/src/shared/style/MUI-theme.scss

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,18 @@
177177
}
178178

179179
.mui-theme .pf-v6-c-card {
180-
--pf-v6-c-card--BorderWidth: 0px;
180+
--pf-v6-c-card--BorderWidth: 1px;
181181
--pf-v6-c-card--BorderRadius: var(--mui-shape-borderRadius);
182-
box-shadow: var(--mui-shadows-1);
182+
--pf-v6-c-card--BorderColor: var(--mui-palette-divider);
183+
}
184+
185+
.pf-v6-c-card__selectable-actions :is(.pf-v6-c-check__label, .pf-v6-c-radio__label, .pf-v6-c-card__clickable-action):hover {
186+
--pf-v6-c-card--BorderColor: var(--mui-palette-grey-300);
183187
}
184188

185189
.mui-theme .pf-v6-c-card:hover {
186190
--pf-v6-c-card--BackgroundColor: var(--mui-palette-grey-100);
191+
--pf-v6-c-card--BorderColor: var(--mui-palette-grey-200);
187192
}
188193

189194
.mui-theme .pf-v6-c-card.pf-m-selected {
@@ -865,6 +870,11 @@
865870

866871
}
867872

873+
// Fix hover state margin issue by removing problematic padding
874+
.mui-theme .pf-v6-c-menu__list {
875+
--pf-v6-c-content--list--PaddingInlineStart: 0;
876+
}
877+
868878
.mui-theme .pf-v6-c-expandable-section .pf-v6-c-expandable-section__content {
869879
margin-block-end: var(--mui-spacing-16px);
870880
}

workspaces/frontend/src/shared/utilities/WorkspaceUtils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ export const formatLabelKey = (key: string): string => {
111111
return baseName.charAt(0).toUpperCase() + baseName.slice(1);
112112
}
113113

114+
// Handle standard infrastructure resource types
115+
if (key === 'cpu' || key === 'gpu') {
116+
return key.toLocaleUpperCase();
117+
}
118+
114119
// Otherwise just capitalize the first letter
115120
return key.charAt(0).toUpperCase() + key.slice(1);
116121
};

0 commit comments

Comments
 (0)