fix(ws): Implement dual scrolling for workspace kind wizard (#484)

Signed-off-by: Jenny <32821331+jenny-s51@users.noreply.github.com>

fix(ws): remove extra DrawerPanelBody

remove unused file

Signed-off-by: Jenny <32821331+jenny-s51@users.noreply.github.com>

fix(ws): remove comment and hide drawer on previousStep callback

Signed-off-by: Jenny <32821331+jenny-s51@users.noreply.github.com>

fix(ws): when navigating between wizard steps, show drawer for steps that have drawer content
This commit is contained in:
Jenny 2025-07-21 11:08:58 -04:00 committed by Bhakti Narvekar
parent de0e5c4356
commit 3218768df0
7 changed files with 301 additions and 292 deletions

View File

@ -2,14 +2,21 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { import {
Button, Button,
Content, Content,
Drawer,
DrawerContent,
DrawerContentBody,
DrawerPanelContent,
DrawerHead,
DrawerActions,
DrawerCloseButton,
DrawerPanelBody,
Flex, Flex,
FlexItem, FlexItem,
PageGroup,
PageSection, PageSection,
ProgressStep, ProgressStep,
ProgressStepper, ProgressStepper,
Stack, Stack,
StackItem, Title,
} from '@patternfly/react-core'; } from '@patternfly/react-core';
import useGenericObjectState from '~/app/hooks/useGenericObjectState'; import useGenericObjectState from '~/app/hooks/useGenericObjectState';
import { useNotebookAPI } from '~/app/hooks/useNotebookAPI'; import { useNotebookAPI } from '~/app/hooks/useNotebookAPI';
@ -18,10 +25,18 @@ import { WorkspaceFormKindSelection } from '~/app/pages/Workspaces/Form/kind/Wor
import { WorkspaceFormPodConfigSelection } from '~/app/pages/Workspaces/Form/podConfig/WorkspaceFormPodConfigSelection'; import { WorkspaceFormPodConfigSelection } from '~/app/pages/Workspaces/Form/podConfig/WorkspaceFormPodConfigSelection';
import { WorkspaceFormPropertiesSelection } from '~/app/pages/Workspaces/Form/properties/WorkspaceFormPropertiesSelection'; import { WorkspaceFormPropertiesSelection } from '~/app/pages/Workspaces/Form/properties/WorkspaceFormPropertiesSelection';
import { WorkspaceFormData } from '~/app/types'; import { WorkspaceFormData } from '~/app/types';
import { WorkspaceCreate } from '~/shared/api/backendApiTypes'; import {
WorkspaceCreate,
WorkspaceKind,
WorkspaceImageConfigValue,
WorkspacePodConfigValue,
} from '~/shared/api/backendApiTypes';
import useWorkspaceFormData from '~/app/hooks/useWorkspaceFormData'; import useWorkspaceFormData from '~/app/hooks/useWorkspaceFormData';
import { useTypedNavigate } from '~/app/routerHelper'; import { useTypedNavigate } from '~/app/routerHelper';
import { useWorkspaceFormLocationData } from '~/app/hooks/useWorkspaceFormLocationData'; import { useWorkspaceFormLocationData } from '~/app/hooks/useWorkspaceFormLocationData';
import { WorkspaceFormKindDetails } from '~/app/pages/Workspaces/Form/kind/WorkspaceFormKindDetails';
import { WorkspaceFormImageDetails } from '~/app/pages/Workspaces/Form/image/WorkspaceFormImageDetails';
import { WorkspaceFormPodConfigDetails } from '~/app/pages/Workspaces/Form/podConfig/WorkspaceFormPodConfigDetails';
enum WorkspaceFormSteps { enum WorkspaceFormSteps {
KindSelection, KindSelection,
@ -52,6 +67,7 @@ const WorkspaceForm: React.FC = () => {
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
const [currentStep, setCurrentStep] = useState(WorkspaceFormSteps.KindSelection); const [currentStep, setCurrentStep] = useState(WorkspaceFormSteps.KindSelection);
const [drawerExpanded, setDrawerExpanded] = useState(false);
const [data, setData, resetData, replaceData] = const [data, setData, resetData, replaceData] =
useGenericObjectState<WorkspaceFormData>(initialFormData); useGenericObjectState<WorkspaceFormData>(initialFormData);
@ -76,30 +92,46 @@ const WorkspaceForm: React.FC = () => {
[currentStep], [currentStep],
); );
const isStepValid = useCallback(
(step: WorkspaceFormSteps) => {
switch (step) {
case WorkspaceFormSteps.KindSelection:
return !!data.kind;
case WorkspaceFormSteps.ImageSelection:
return !!data.image;
case WorkspaceFormSteps.PodConfigSelection:
return !!data.podConfig;
case WorkspaceFormSteps.Properties:
return !!data.properties.workspaceName.trim();
default:
return false;
}
},
[data.kind, data.image, data.podConfig, data.properties.workspaceName],
);
const showDrawer = useCallback(
(step: WorkspaceFormSteps) =>
// Only show drawer for steps that have drawer content
step !== WorkspaceFormSteps.Properties && isStepValid(step),
[isStepValid],
);
const previousStep = useCallback(() => { const previousStep = useCallback(() => {
setCurrentStep(currentStep - 1); const newStep = currentStep - 1;
}, [currentStep]); setCurrentStep(newStep);
setDrawerExpanded(showDrawer(newStep));
}, [currentStep, showDrawer]);
const nextStep = useCallback(() => { const nextStep = useCallback(() => {
setCurrentStep(currentStep + 1); const newStep = currentStep + 1;
}, [currentStep]); setCurrentStep(newStep);
setDrawerExpanded(showDrawer(newStep));
}, [currentStep, showDrawer]);
const canGoToPreviousStep = useMemo(() => currentStep > 0, [currentStep]); const canGoToPreviousStep = useMemo(() => currentStep > 0, [currentStep]);
const isCurrentStepValid = useMemo(() => { const isCurrentStepValid = useMemo(() => isStepValid(currentStep), [isStepValid, currentStep]);
switch (currentStep) {
case WorkspaceFormSteps.KindSelection:
return !!data.kind;
case WorkspaceFormSteps.ImageSelection:
return !!data.image;
case WorkspaceFormSteps.PodConfigSelection:
return !!data.podConfig;
case WorkspaceFormSteps.Properties:
return !!data.properties.workspaceName.trim();
default:
return false;
}
}, [currentStep, data]);
const canGoToNextStep = useMemo( const canGoToNextStep = useMemo(
() => currentStep < Object.keys(WorkspaceFormSteps).length / 2 - 1, () => currentStep < Object.keys(WorkspaceFormSteps).length / 2 - 1,
@ -168,6 +200,63 @@ const WorkspaceForm: React.FC = () => {
navigate('workspaces'); navigate('workspaces');
}, [navigate]); }, [navigate]);
const handleKindSelect = useCallback(
(kind: WorkspaceKind | undefined) => {
if (kind) {
resetData();
setData('kind', kind);
setDrawerExpanded(true);
}
},
[resetData, setData],
);
const handleImageSelect = useCallback(
(image: WorkspaceImageConfigValue | undefined) => {
if (image) {
setData('image', image);
setDrawerExpanded(true);
}
},
[setData],
);
const handlePodConfigSelect = useCallback(
(podConfig: WorkspacePodConfigValue | undefined) => {
if (podConfig) {
setData('podConfig', podConfig);
setDrawerExpanded(true);
}
},
[setData],
);
const getDrawerContent = () => {
switch (currentStep) {
case WorkspaceFormSteps.KindSelection:
return <WorkspaceFormKindDetails workspaceKind={data.kind} />;
case WorkspaceFormSteps.ImageSelection:
return <WorkspaceFormImageDetails workspaceImage={data.image} />;
case WorkspaceFormSteps.PodConfigSelection:
return <WorkspaceFormPodConfigDetails workspacePodConfig={data.podConfig} />;
default:
return null;
}
};
const getDrawerTitle = () => {
switch (currentStep) {
case WorkspaceFormSteps.KindSelection:
return 'Workspace Kind';
case WorkspaceFormSteps.ImageSelection:
return 'Image';
case WorkspaceFormSteps.PodConfigSelection:
return 'Pod Config';
default:
return '';
}
};
if (initialFormDataError) { if (initialFormDataError) {
return <p>Error loading workspace data: {initialFormDataError.message}</p>; // TODO: UX for error state return <p>Error loading workspace data: {initialFormDataError.message}</p>; // TODO: UX for error state
} }
@ -176,137 +265,160 @@ const WorkspaceForm: React.FC = () => {
return <p>Loading...</p>; // TODO: UX for loading state return <p>Loading...</p>; // TODO: UX for loading state
} }
const panelContent = (
<DrawerPanelContent>
<DrawerHead>
<Title headingLevel="h1">{getDrawerTitle()}</Title>
<DrawerActions>
<DrawerCloseButton onClick={() => setDrawerExpanded(false)} />
</DrawerActions>
</DrawerHead>
<DrawerPanelBody className="workspace-form__drawer-panel-body">
{getDrawerContent()}
</DrawerPanelBody>
</DrawerPanelContent>
);
return ( return (
<> <Drawer isInline isExpanded={drawerExpanded}>
<PageGroup isFilled={false} stickyOnBreakpoint={{ default: 'top' }}> <DrawerContent panelContent={panelContent}>
<PageSection> <DrawerContentBody>
<Stack hasGutter> <Flex
<Flex direction={{ default: 'column' }} rowGap={{ default: 'rowGapXl' }}> direction={{ default: 'column' }}
<FlexItem> flexWrap={{ default: 'nowrap' }}
<Content> style={{ height: '100%' }}
<h1>{`${mode === 'create' ? 'Create' : 'Edit'} workspace`}</h1> >
</Content> <FlexItem>
</FlexItem> <PageSection>
<FlexItem> <Stack hasGutter>
<ProgressStepper aria-label="Workspace form stepper"> <Flex direction={{ default: 'column' }} rowGap={{ default: 'rowGapXl' }}>
<ProgressStep <FlexItem>
variant={getStepVariant(WorkspaceFormSteps.KindSelection)} <Content>
isCurrent={currentStep === WorkspaceFormSteps.KindSelection} <h1>{`${mode === 'create' ? 'Create' : 'Edit'} workspace`}</h1>
id="kind-selection-step" <p>{stepDescriptions[currentStep]}</p>
titleId="kind-selection-step-title" </Content>
aria-label="Kind selection step" </FlexItem>
> <FlexItem>
Workspace Kind <ProgressStepper aria-label="Workspace form stepper">
</ProgressStep> <ProgressStep
<ProgressStep variant={getStepVariant(WorkspaceFormSteps.KindSelection)}
variant={getStepVariant(WorkspaceFormSteps.ImageSelection)} isCurrent={currentStep === WorkspaceFormSteps.KindSelection}
isCurrent={currentStep === WorkspaceFormSteps.ImageSelection} id="kind-selection-step"
id="image-selection-step" titleId="kind-selection-step-title"
titleId="image-selection-step-title" aria-label="Kind selection step"
aria-label="Image selection step" >
> Workspace Kind
Image </ProgressStep>
</ProgressStep> <ProgressStep
<ProgressStep variant={getStepVariant(WorkspaceFormSteps.ImageSelection)}
variant={getStepVariant(WorkspaceFormSteps.PodConfigSelection)} isCurrent={currentStep === WorkspaceFormSteps.ImageSelection}
isCurrent={currentStep === WorkspaceFormSteps.PodConfigSelection} id="image-selection-step"
id="pod-config-selection-step" titleId="image-selection-step-title"
titleId="pod-config-selection-step-title" aria-label="Image selection step"
aria-label="Pod config selection step" >
> Image
Pod Config </ProgressStep>
</ProgressStep> <ProgressStep
<ProgressStep variant={getStepVariant(WorkspaceFormSteps.PodConfigSelection)}
variant={getStepVariant(WorkspaceFormSteps.Properties)} isCurrent={currentStep === WorkspaceFormSteps.PodConfigSelection}
isCurrent={currentStep === WorkspaceFormSteps.Properties} id="pod-config-selection-step"
id="properties-step" titleId="pod-config-selection-step-title"
titleId="properties-step-title" aria-label="Pod config selection step"
aria-label="Properties step" >
> Pod Config
Properties </ProgressStep>
</ProgressStep> <ProgressStep
</ProgressStepper> variant={getStepVariant(WorkspaceFormSteps.Properties)}
</FlexItem> isCurrent={currentStep === WorkspaceFormSteps.Properties}
</Flex> id="properties-step"
<StackItem> titleId="properties-step-title"
<p>{stepDescriptions[currentStep]}</p> aria-label="Properties step"
</StackItem> >
</Stack> Properties
</PageSection> </ProgressStep>
</PageGroup> </ProgressStepper>
<PageSection isFilled> </FlexItem>
{currentStep === WorkspaceFormSteps.KindSelection && ( </Flex>
<WorkspaceFormKindSelection </Stack>
selectedKind={data.kind} </PageSection>
onSelect={(kind) => { </FlexItem>
resetData(); <FlexItem flex={{ default: 'flex_1' }}>
setData('kind', kind); <PageSection isFilled>
}} {currentStep === WorkspaceFormSteps.KindSelection && (
/> <WorkspaceFormKindSelection
)} selectedKind={data.kind}
{currentStep === WorkspaceFormSteps.ImageSelection && ( onSelect={handleKindSelect}
<WorkspaceFormImageSelection />
selectedImage={data.image} )}
onSelect={(image) => setData('image', image)} {currentStep === WorkspaceFormSteps.ImageSelection && (
images={data.kind?.podTemplate.options.imageConfig.values ?? []} <WorkspaceFormImageSelection
/> selectedImage={data.image}
)} onSelect={handleImageSelect}
{currentStep === WorkspaceFormSteps.PodConfigSelection && ( images={data.kind?.podTemplate.options.imageConfig.values ?? []}
<WorkspaceFormPodConfigSelection />
selectedPodConfig={data.podConfig} )}
onSelect={(podConfig) => setData('podConfig', podConfig)} {currentStep === WorkspaceFormSteps.PodConfigSelection && (
podConfigs={data.kind?.podTemplate.options.podConfig.values ?? []} <WorkspaceFormPodConfigSelection
/> selectedPodConfig={data.podConfig}
)} onSelect={handlePodConfigSelect}
{currentStep === WorkspaceFormSteps.Properties && ( podConfigs={data.kind?.podTemplate.options.podConfig.values ?? []}
<WorkspaceFormPropertiesSelection />
selectedProperties={data.properties} )}
onSelect={(properties) => setData('properties', properties)} {currentStep === WorkspaceFormSteps.Properties && (
selectedImage={data.image} <WorkspaceFormPropertiesSelection
/> selectedProperties={data.properties}
)} onSelect={(properties) => setData('properties', properties)}
</PageSection> selectedImage={data.image}
<PageSection isFilled={false} stickyOnBreakpoint={{ default: 'bottom' }}> />
<Flex> )}
<FlexItem> </PageSection>
<Button </FlexItem>
variant="secondary" <FlexItem>
ouiaId="Secondary" <PageSection>
onClick={previousStep} <Flex>
isDisabled={!canGoToPreviousStep} <FlexItem>
> <Button
Previous variant="secondary"
</Button> ouiaId="Secondary"
</FlexItem> onClick={previousStep}
<FlexItem> isDisabled={!canGoToPreviousStep}
{canGoToNextStep ? ( >
<Button Previous
variant="primary" </Button>
ouiaId="Primary" </FlexItem>
onClick={nextStep} <FlexItem>
isDisabled={!isCurrentStepValid} {canGoToNextStep ? (
> <Button
Next variant="primary"
</Button> ouiaId="Primary"
) : ( onClick={nextStep}
<Button isDisabled={!isCurrentStepValid}
variant="primary" >
ouiaId="Primary" Next
onClick={handleSubmit} </Button>
isDisabled={!canSubmit} ) : (
> <Button
{mode === 'create' ? 'Create' : 'Save'} variant="primary"
</Button> ouiaId="Primary"
)} onClick={handleSubmit}
</FlexItem> isDisabled={!canSubmit}
<FlexItem> >
<Button variant="link" isInline onClick={cancel}> {mode === 'create' ? 'Create' : 'Save'}
Cancel </Button>
</Button> )}
</FlexItem> </FlexItem>
</Flex> <FlexItem>
</PageSection> <Button variant="link" isInline onClick={cancel}>
</> Cancel
</Button>
</FlexItem>
</Flex>
</PageSection>
</FlexItem>
</Flex>
</DrawerContentBody>
</DrawerContent>
</Drawer>
); );
}; };

View File

@ -16,7 +16,7 @@ type WorkspaceFormImageDetailsProps = {
export const WorkspaceFormImageDetails: React.FunctionComponent<WorkspaceFormImageDetailsProps> = ({ export const WorkspaceFormImageDetails: React.FunctionComponent<WorkspaceFormImageDetailsProps> = ({
workspaceImage, workspaceImage,
}) => ( }) => (
<div style={{ marginLeft: 'var(--pf-t--global--spacer--md)' }}> <>
{workspaceImage && ( {workspaceImage && (
<> <>
<Title headingLevel="h3">{workspaceImage.displayName}</Title> <Title headingLevel="h3">{workspaceImage.displayName}</Title>
@ -38,5 +38,5 @@ export const WorkspaceFormImageDetails: React.FunctionComponent<WorkspaceFormIma
))} ))}
</> </>
)} )}
</div> </>
); );

View File

@ -1,10 +1,8 @@
import React, { useCallback, useMemo, useRef, useState } from 'react'; import React, { useMemo, useState } from 'react';
import { Content, Split, SplitItem } from '@patternfly/react-core'; import { Content, Split, SplitItem } from '@patternfly/react-core';
import { WorkspaceFormImageDetails } from '~/app/pages/Workspaces/Form/image/WorkspaceFormImageDetails';
import { WorkspaceFormImageList } from '~/app/pages/Workspaces/Form/image/WorkspaceFormImageList'; import { WorkspaceFormImageList } from '~/app/pages/Workspaces/Form/image/WorkspaceFormImageList';
import { FilterByLabels } from '~/app/pages/Workspaces/Form/labelFilter/FilterByLabels'; import { FilterByLabels } from '~/app/pages/Workspaces/Form/labelFilter/FilterByLabels';
import { WorkspaceImageConfigValue } from '~/shared/api/backendApiTypes'; import { WorkspaceImageConfigValue } from '~/shared/api/backendApiTypes';
import { WorkspaceFormDrawer } from '~/app/pages/Workspaces/Form/WorkspaceFormDrawer';
interface WorkspaceFormImageSelectionProps { interface WorkspaceFormImageSelectionProps {
images: WorkspaceImageConfigValue[]; images: WorkspaceImageConfigValue[];
@ -18,26 +16,6 @@ const WorkspaceFormImageSelection: React.FunctionComponent<WorkspaceFormImageSel
onSelect, onSelect,
}) => { }) => {
const [selectedLabels, setSelectedLabels] = useState<Map<string, Set<string>>>(new Map()); const [selectedLabels, setSelectedLabels] = useState<Map<string, Set<string>>>(new Map());
const [isExpanded, setIsExpanded] = useState(false);
const drawerRef = useRef<HTMLSpanElement>(undefined);
const onExpand = useCallback(() => {
if (drawerRef.current) {
drawerRef.current.focus();
}
}, []);
const onClick = useCallback(
(image?: WorkspaceImageConfigValue) => {
setIsExpanded(true);
onSelect(image);
},
[onSelect],
);
const onCloseClick = useCallback(() => {
setIsExpanded(false);
}, []);
const imageFilterContent = useMemo( const imageFilterContent = useMemo(
() => ( () => (
@ -50,32 +28,19 @@ const WorkspaceFormImageSelection: React.FunctionComponent<WorkspaceFormImageSel
[images, selectedLabels, setSelectedLabels], [images, selectedLabels, setSelectedLabels],
); );
const imageDetailsContent = useMemo(
() => <WorkspaceFormImageDetails workspaceImage={selectedImage} />,
[selectedImage],
);
return ( return (
<Content style={{ height: '100%' }}> <Content style={{ height: '100%' }}>
<WorkspaceFormDrawer <Split hasGutter>
title="Image" <SplitItem style={{ minWidth: '200px' }}>{imageFilterContent}</SplitItem>
info={imageDetailsContent} <SplitItem isFilled>
isExpanded={isExpanded} <WorkspaceFormImageList
onCloseClick={onCloseClick} images={images}
onExpand={onExpand} selectedLabels={selectedLabels}
> selectedImage={selectedImage}
<Split hasGutter> onSelect={onSelect}
<SplitItem style={{ minWidth: '200px' }}>{imageFilterContent}</SplitItem> />
<SplitItem isFilled> </SplitItem>
<WorkspaceFormImageList </Split>
images={images}
selectedLabels={selectedLabels}
selectedImage={selectedImage}
onSelect={onClick}
/>
</SplitItem>
</Split>
</WorkspaceFormDrawer>
</Content> </Content>
); );
}; };

View File

@ -9,12 +9,12 @@ type WorkspaceFormKindDetailsProps = {
export const WorkspaceFormKindDetails: React.FunctionComponent<WorkspaceFormKindDetailsProps> = ({ export const WorkspaceFormKindDetails: React.FunctionComponent<WorkspaceFormKindDetailsProps> = ({
workspaceKind, workspaceKind,
}) => ( }) => (
<div style={{ marginLeft: 'var(--pf-t--global--spacer--md)' }}> <>
{workspaceKind && ( {workspaceKind && (
<> <>
<Title headingLevel="h3">{workspaceKind.displayName}</Title> <Title headingLevel="h3">{workspaceKind.displayName}</Title>
<p>{workspaceKind.description}</p> <p>{workspaceKind.description}</p>
</> </>
)} )}
</div> </>
); );

View File

@ -1,10 +1,8 @@
import React, { useCallback, useMemo, useRef, useState } from 'react'; import React from 'react';
import { Content } from '@patternfly/react-core'; import { Content } from '@patternfly/react-core';
import { WorkspaceKind } from '~/shared/api/backendApiTypes'; import { WorkspaceKind } from '~/shared/api/backendApiTypes';
import useWorkspaceKinds from '~/app/hooks/useWorkspaceKinds'; import useWorkspaceKinds from '~/app/hooks/useWorkspaceKinds';
import { WorkspaceFormKindDetails } from '~/app/pages/Workspaces/Form/kind/WorkspaceFormKindDetails';
import { WorkspaceFormKindList } from '~/app/pages/Workspaces/Form/kind/WorkspaceFormKindList'; import { WorkspaceFormKindList } from '~/app/pages/Workspaces/Form/kind/WorkspaceFormKindList';
import { WorkspaceFormDrawer } from '~/app/pages/Workspaces/Form/WorkspaceFormDrawer';
interface WorkspaceFormKindSelectionProps { interface WorkspaceFormKindSelectionProps {
selectedKind: WorkspaceKind | undefined; selectedKind: WorkspaceKind | undefined;
@ -16,31 +14,6 @@ const WorkspaceFormKindSelection: React.FunctionComponent<WorkspaceFormKindSelec
onSelect, onSelect,
}) => { }) => {
const [workspaceKinds, loaded, error] = useWorkspaceKinds(); const [workspaceKinds, loaded, error] = useWorkspaceKinds();
const [isExpanded, setIsExpanded] = useState(false);
const drawerRef = useRef<HTMLSpanElement>(undefined);
const onExpand = useCallback(() => {
if (drawerRef.current) {
drawerRef.current.focus();
}
}, []);
const onClick = useCallback(
(kind?: WorkspaceKind) => {
setIsExpanded(true);
onSelect(kind);
},
[onSelect],
);
const onCloseClick = useCallback(() => {
setIsExpanded(false);
}, []);
const kindDetailsContent = useMemo(
() => <WorkspaceFormKindDetails workspaceKind={selectedKind} />,
[selectedKind],
);
if (error) { if (error) {
return <p>Error loading workspace kinds: {error.message}</p>; // TODO: UX for error state return <p>Error loading workspace kinds: {error.message}</p>; // TODO: UX for error state
@ -52,19 +25,11 @@ const WorkspaceFormKindSelection: React.FunctionComponent<WorkspaceFormKindSelec
return ( return (
<Content style={{ height: '100%' }}> <Content style={{ height: '100%' }}>
<WorkspaceFormDrawer <WorkspaceFormKindList
title="Workspace kind" allWorkspaceKinds={workspaceKinds}
info={kindDetailsContent} selectedKind={selectedKind}
isExpanded={isExpanded} onSelect={onSelect}
onCloseClick={onCloseClick} />
onExpand={onExpand}
>
<WorkspaceFormKindList
allWorkspaceKinds={workspaceKinds}
selectedKind={selectedKind}
onSelect={onClick}
/>
</WorkspaceFormDrawer>
</Content> </Content>
); );
}; };

View File

@ -19,10 +19,12 @@ export const WorkspaceFormPodConfigDetails: React.FunctionComponent<
> = ({ workspacePodConfig }) => ( > = ({ workspacePodConfig }) => (
<> <>
{workspacePodConfig && ( {workspacePodConfig && (
<div style={{ marginLeft: 'var(--pf-t--global--spacer--md)' }}> <>
<Title headingLevel="h3">{workspacePodConfig.displayName}</Title>{' '} <Title headingLevel="h3">{workspacePodConfig.displayName}</Title>{' '}
<p>{workspacePodConfig.description}</p> <p>{workspacePodConfig.description}</p>
<br />
<Divider /> <Divider />
<br />
{workspacePodConfig.labels.map((label) => ( {workspacePodConfig.labels.map((label) => (
<DescriptionList <DescriptionList
key={label.key} key={label.key}
@ -37,7 +39,7 @@ export const WorkspaceFormPodConfigDetails: React.FunctionComponent<
</DescriptionListGroup> </DescriptionListGroup>
</DescriptionList> </DescriptionList>
))} ))}
</div> </>
)} )}
</> </>
); );

View File

@ -1,9 +1,7 @@
import React, { useCallback, useMemo, useRef, useState } from 'react'; import React, { useMemo, useState } from 'react';
import { Content, Split, SplitItem } from '@patternfly/react-core'; import { Content, Split, SplitItem } from '@patternfly/react-core';
import { WorkspaceFormPodConfigDetails } from '~/app/pages/Workspaces/Form/podConfig/WorkspaceFormPodConfigDetails';
import { WorkspaceFormPodConfigList } from '~/app/pages/Workspaces/Form/podConfig/WorkspaceFormPodConfigList'; import { WorkspaceFormPodConfigList } from '~/app/pages/Workspaces/Form/podConfig/WorkspaceFormPodConfigList';
import { FilterByLabels } from '~/app/pages/Workspaces/Form/labelFilter/FilterByLabels'; import { FilterByLabels } from '~/app/pages/Workspaces/Form/labelFilter/FilterByLabels';
import { WorkspaceFormDrawer } from '~/app/pages/Workspaces/Form/WorkspaceFormDrawer';
import { WorkspacePodConfigValue } from '~/shared/api/backendApiTypes'; import { WorkspacePodConfigValue } from '~/shared/api/backendApiTypes';
interface WorkspaceFormPodConfigSelectionProps { interface WorkspaceFormPodConfigSelectionProps {
@ -16,26 +14,6 @@ const WorkspaceFormPodConfigSelection: React.FunctionComponent<
WorkspaceFormPodConfigSelectionProps WorkspaceFormPodConfigSelectionProps
> = ({ podConfigs, selectedPodConfig, onSelect }) => { > = ({ podConfigs, selectedPodConfig, onSelect }) => {
const [selectedLabels, setSelectedLabels] = useState<Map<string, Set<string>>>(new Map()); const [selectedLabels, setSelectedLabels] = useState<Map<string, Set<string>>>(new Map());
const [isExpanded, setIsExpanded] = useState(false);
const drawerRef = useRef<HTMLSpanElement>(undefined);
const onExpand = useCallback(() => {
if (drawerRef.current) {
drawerRef.current.focus();
}
}, []);
const onClick = useCallback(
(podConfig?: WorkspacePodConfigValue) => {
setIsExpanded(true);
onSelect(podConfig);
},
[onSelect],
);
const onCloseClick = useCallback(() => {
setIsExpanded(false);
}, []);
const podConfigFilterContent = useMemo( const podConfigFilterContent = useMemo(
() => ( () => (
@ -48,32 +26,19 @@ const WorkspaceFormPodConfigSelection: React.FunctionComponent<
[podConfigs, selectedLabels, setSelectedLabels], [podConfigs, selectedLabels, setSelectedLabels],
); );
const podConfigDetailsContent = useMemo(
() => <WorkspaceFormPodConfigDetails workspacePodConfig={selectedPodConfig} />,
[selectedPodConfig],
);
return ( return (
<Content style={{ height: '100%' }}> <Content style={{ height: '100%' }}>
<WorkspaceFormDrawer <Split hasGutter>
title="Pod config" <SplitItem style={{ minWidth: '200px' }}>{podConfigFilterContent}</SplitItem>
info={podConfigDetailsContent} <SplitItem isFilled>
isExpanded={isExpanded} <WorkspaceFormPodConfigList
onCloseClick={onCloseClick} podConfigs={podConfigs}
onExpand={onExpand} selectedLabels={selectedLabels}
> selectedPodConfig={selectedPodConfig}
<Split hasGutter> onSelect={onSelect}
<SplitItem style={{ minWidth: '200px' }}>{podConfigFilterContent}</SplitItem> />
<SplitItem isFilled> </SplitItem>
<WorkspaceFormPodConfigList </Split>
podConfigs={podConfigs}
selectedLabels={selectedLabels}
selectedPodConfig={selectedPodConfig}
onSelect={onClick}
/>
</SplitItem>
</Split>
</WorkspaceFormDrawer>
</Content> </Content>
); );
}; };