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:
parent
de0e5c4356
commit
3218768df0
|
|
@ -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,18 +92,9 @@ const WorkspaceForm: React.FC = () => {
|
||||||
[currentStep],
|
[currentStep],
|
||||||
);
|
);
|
||||||
|
|
||||||
const previousStep = useCallback(() => {
|
const isStepValid = useCallback(
|
||||||
setCurrentStep(currentStep - 1);
|
(step: WorkspaceFormSteps) => {
|
||||||
}, [currentStep]);
|
switch (step) {
|
||||||
|
|
||||||
const nextStep = useCallback(() => {
|
|
||||||
setCurrentStep(currentStep + 1);
|
|
||||||
}, [currentStep]);
|
|
||||||
|
|
||||||
const canGoToPreviousStep = useMemo(() => currentStep > 0, [currentStep]);
|
|
||||||
|
|
||||||
const isCurrentStepValid = useMemo(() => {
|
|
||||||
switch (currentStep) {
|
|
||||||
case WorkspaceFormSteps.KindSelection:
|
case WorkspaceFormSteps.KindSelection:
|
||||||
return !!data.kind;
|
return !!data.kind;
|
||||||
case WorkspaceFormSteps.ImageSelection:
|
case WorkspaceFormSteps.ImageSelection:
|
||||||
|
|
@ -99,7 +106,32 @@ const WorkspaceForm: React.FC = () => {
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}, [currentStep, data]);
|
},
|
||||||
|
[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 newStep = currentStep - 1;
|
||||||
|
setCurrentStep(newStep);
|
||||||
|
setDrawerExpanded(showDrawer(newStep));
|
||||||
|
}, [currentStep, showDrawer]);
|
||||||
|
|
||||||
|
const nextStep = useCallback(() => {
|
||||||
|
const newStep = currentStep + 1;
|
||||||
|
setCurrentStep(newStep);
|
||||||
|
setDrawerExpanded(showDrawer(newStep));
|
||||||
|
}, [currentStep, showDrawer]);
|
||||||
|
|
||||||
|
const canGoToPreviousStep = useMemo(() => currentStep > 0, [currentStep]);
|
||||||
|
|
||||||
|
const isCurrentStepValid = useMemo(() => isStepValid(currentStep), [isStepValid, currentStep]);
|
||||||
|
|
||||||
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,15 +265,37 @@ 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}>
|
||||||
|
<DrawerContentBody>
|
||||||
|
<Flex
|
||||||
|
direction={{ default: 'column' }}
|
||||||
|
flexWrap={{ default: 'nowrap' }}
|
||||||
|
style={{ height: '100%' }}
|
||||||
|
>
|
||||||
|
<FlexItem>
|
||||||
<PageSection>
|
<PageSection>
|
||||||
<Stack hasGutter>
|
<Stack hasGutter>
|
||||||
<Flex direction={{ default: 'column' }} rowGap={{ default: 'rowGapXl' }}>
|
<Flex direction={{ default: 'column' }} rowGap={{ default: 'rowGapXl' }}>
|
||||||
<FlexItem>
|
<FlexItem>
|
||||||
<Content>
|
<Content>
|
||||||
<h1>{`${mode === 'create' ? 'Create' : 'Edit'} workspace`}</h1>
|
<h1>{`${mode === 'create' ? 'Create' : 'Edit'} workspace`}</h1>
|
||||||
|
<p>{stepDescriptions[currentStep]}</p>
|
||||||
</Content>
|
</Content>
|
||||||
</FlexItem>
|
</FlexItem>
|
||||||
<FlexItem>
|
<FlexItem>
|
||||||
|
|
@ -228,33 +339,28 @@ const WorkspaceForm: React.FC = () => {
|
||||||
</ProgressStepper>
|
</ProgressStepper>
|
||||||
</FlexItem>
|
</FlexItem>
|
||||||
</Flex>
|
</Flex>
|
||||||
<StackItem>
|
|
||||||
<p>{stepDescriptions[currentStep]}</p>
|
|
||||||
</StackItem>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</PageSection>
|
</PageSection>
|
||||||
</PageGroup>
|
</FlexItem>
|
||||||
|
<FlexItem flex={{ default: 'flex_1' }}>
|
||||||
<PageSection isFilled>
|
<PageSection isFilled>
|
||||||
{currentStep === WorkspaceFormSteps.KindSelection && (
|
{currentStep === WorkspaceFormSteps.KindSelection && (
|
||||||
<WorkspaceFormKindSelection
|
<WorkspaceFormKindSelection
|
||||||
selectedKind={data.kind}
|
selectedKind={data.kind}
|
||||||
onSelect={(kind) => {
|
onSelect={handleKindSelect}
|
||||||
resetData();
|
|
||||||
setData('kind', kind);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{currentStep === WorkspaceFormSteps.ImageSelection && (
|
{currentStep === WorkspaceFormSteps.ImageSelection && (
|
||||||
<WorkspaceFormImageSelection
|
<WorkspaceFormImageSelection
|
||||||
selectedImage={data.image}
|
selectedImage={data.image}
|
||||||
onSelect={(image) => setData('image', image)}
|
onSelect={handleImageSelect}
|
||||||
images={data.kind?.podTemplate.options.imageConfig.values ?? []}
|
images={data.kind?.podTemplate.options.imageConfig.values ?? []}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{currentStep === WorkspaceFormSteps.PodConfigSelection && (
|
{currentStep === WorkspaceFormSteps.PodConfigSelection && (
|
||||||
<WorkspaceFormPodConfigSelection
|
<WorkspaceFormPodConfigSelection
|
||||||
selectedPodConfig={data.podConfig}
|
selectedPodConfig={data.podConfig}
|
||||||
onSelect={(podConfig) => setData('podConfig', podConfig)}
|
onSelect={handlePodConfigSelect}
|
||||||
podConfigs={data.kind?.podTemplate.options.podConfig.values ?? []}
|
podConfigs={data.kind?.podTemplate.options.podConfig.values ?? []}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
@ -266,7 +372,9 @@ const WorkspaceForm: React.FC = () => {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</PageSection>
|
</PageSection>
|
||||||
<PageSection isFilled={false} stickyOnBreakpoint={{ default: 'bottom' }}>
|
</FlexItem>
|
||||||
|
<FlexItem>
|
||||||
|
<PageSection>
|
||||||
<Flex>
|
<Flex>
|
||||||
<FlexItem>
|
<FlexItem>
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -306,7 +414,11 @@ const WorkspaceForm: React.FC = () => {
|
||||||
</FlexItem>
|
</FlexItem>
|
||||||
</Flex>
|
</Flex>
|
||||||
</PageSection>
|
</PageSection>
|
||||||
</>
|
</FlexItem>
|
||||||
|
</Flex>
|
||||||
|
</DrawerContentBody>
|
||||||
|
</DrawerContent>
|
||||||
|
</Drawer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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,20 +28,8 @@ 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
|
|
||||||
title="Image"
|
|
||||||
info={imageDetailsContent}
|
|
||||||
isExpanded={isExpanded}
|
|
||||||
onCloseClick={onCloseClick}
|
|
||||||
onExpand={onExpand}
|
|
||||||
>
|
|
||||||
<Split hasGutter>
|
<Split hasGutter>
|
||||||
<SplitItem style={{ minWidth: '200px' }}>{imageFilterContent}</SplitItem>
|
<SplitItem style={{ minWidth: '200px' }}>{imageFilterContent}</SplitItem>
|
||||||
<SplitItem isFilled>
|
<SplitItem isFilled>
|
||||||
|
|
@ -71,11 +37,10 @@ const WorkspaceFormImageSelection: React.FunctionComponent<WorkspaceFormImageSel
|
||||||
images={images}
|
images={images}
|
||||||
selectedLabels={selectedLabels}
|
selectedLabels={selectedLabels}
|
||||||
selectedImage={selectedImage}
|
selectedImage={selectedImage}
|
||||||
onSelect={onClick}
|
onSelect={onSelect}
|
||||||
/>
|
/>
|
||||||
</SplitItem>
|
</SplitItem>
|
||||||
</Split>
|
</Split>
|
||||||
</WorkspaceFormDrawer>
|
|
||||||
</Content>
|
</Content>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
title="Workspace kind"
|
|
||||||
info={kindDetailsContent}
|
|
||||||
isExpanded={isExpanded}
|
|
||||||
onCloseClick={onCloseClick}
|
|
||||||
onExpand={onExpand}
|
|
||||||
>
|
|
||||||
<WorkspaceFormKindList
|
<WorkspaceFormKindList
|
||||||
allWorkspaceKinds={workspaceKinds}
|
allWorkspaceKinds={workspaceKinds}
|
||||||
selectedKind={selectedKind}
|
selectedKind={selectedKind}
|
||||||
onSelect={onClick}
|
onSelect={onSelect}
|
||||||
/>
|
/>
|
||||||
</WorkspaceFormDrawer>
|
|
||||||
</Content>
|
</Content>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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,20 +26,8 @@ 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
|
|
||||||
title="Pod config"
|
|
||||||
info={podConfigDetailsContent}
|
|
||||||
isExpanded={isExpanded}
|
|
||||||
onCloseClick={onCloseClick}
|
|
||||||
onExpand={onExpand}
|
|
||||||
>
|
|
||||||
<Split hasGutter>
|
<Split hasGutter>
|
||||||
<SplitItem style={{ minWidth: '200px' }}>{podConfigFilterContent}</SplitItem>
|
<SplitItem style={{ minWidth: '200px' }}>{podConfigFilterContent}</SplitItem>
|
||||||
<SplitItem isFilled>
|
<SplitItem isFilled>
|
||||||
|
|
@ -69,11 +35,10 @@ const WorkspaceFormPodConfigSelection: React.FunctionComponent<
|
||||||
podConfigs={podConfigs}
|
podConfigs={podConfigs}
|
||||||
selectedLabels={selectedLabels}
|
selectedLabels={selectedLabels}
|
||||||
selectedPodConfig={selectedPodConfig}
|
selectedPodConfig={selectedPodConfig}
|
||||||
onSelect={onClick}
|
onSelect={onSelect}
|
||||||
/>
|
/>
|
||||||
</SplitItem>
|
</SplitItem>
|
||||||
</Split>
|
</Split>
|
||||||
</WorkspaceFormDrawer>
|
|
||||||
</Content>
|
</Content>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue