1- import React , { useCallback , useMemo , useState } from 'react' ;
1+ import React , { useCallback , useEffect , useMemo , useState } from 'react' ;
22import {
33 Button ,
44 Content ,
55 ContentVariants ,
6+ EmptyState ,
7+ EmptyStateBody ,
68 Flex ,
79 FlexItem ,
810 PageGroup ,
@@ -11,25 +13,42 @@ import {
1113 StackItem ,
1214} from '@patternfly/react-core' ;
1315import { t_global_spacer_sm as SmallPadding } from '@patternfly/react-tokens' ;
16+ import { ExclamationCircleIcon } from '@patternfly/react-icons' ;
1417import { ValidationErrorAlert } from '~/app/components/ValidationErrorAlert' ;
15- import { useTypedNavigate } from '~/app/routerHelper' ;
18+ import useWorkspaceKindByName from '~/app/hooks/useWorkspaceKindByName' ;
19+ import { WorkspaceKind , ValidationError } from '~/shared/api/backendApiTypes' ;
20+ import { useTypedNavigate , useTypedParams } from '~/app/routerHelper' ;
1621import { useCurrentRouteKey } from '~/app/hooks/useCurrentRouteKey' ;
1722import useGenericObjectState from '~/app/hooks/useGenericObjectState' ;
1823import { useNotebookAPI } from '~/app/hooks/useNotebookAPI' ;
1924import { WorkspaceKindFormData } from '~/app/types' ;
2025import { ErrorEnvelopeException } from '~/shared/api/apiUtils' ;
21- import { ValidationError } from '~/shared/api/backendApiTypes' ;
2226import { WorkspaceKindFileUpload } from './fileUpload/WorkspaceKindFileUpload' ;
2327import { WorkspaceKindFormProperties } from './properties/WorkspaceKindFormProperties' ;
2428import { WorkspaceKindFormImage } from './image/WorkspaceKindFormImage' ;
2529import { WorkspaceKindFormPodConfig } from './podConfig/WorkspaceKindFormPodConfig' ;
30+ import { WorkspaceKindFormPodTemplate } from './podTemplate/WorkspaceKindFormPodTemplate' ;
31+ import { EMPTY_WORKSPACE_KIND_FORM_DATA } from './helpers' ;
2632
2733export enum WorkspaceKindFormView {
2834 Form ,
2935 FileUpload ,
3036}
3137
3238export type ValidationStatus = 'success' | 'error' | 'default' ;
39+ export type FormMode = 'edit' | 'create' ;
40+
41+ const convertToFormData = ( initialData : WorkspaceKind ) : WorkspaceKindFormData => {
42+ const { podTemplate, ...properties } = initialData ;
43+ const { options, ...spec } = podTemplate ;
44+ const { podConfig, imageConfig } = options ;
45+ return {
46+ properties,
47+ podConfig,
48+ imageConfig,
49+ podTemplate : spec ,
50+ } ;
51+ } ;
3352
3453export const WorkspaceKindForm : React . FC = ( ) => {
3554 const navigate = useTypedNavigate ( ) ;
@@ -38,28 +57,23 @@ export const WorkspaceKindForm: React.FC = () => {
3857 const [ yamlValue , setYamlValue ] = useState ( '' ) ;
3958 const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
4059 const [ validated , setValidated ] = useState < ValidationStatus > ( 'default' ) ;
41- const mode = useCurrentRouteKey ( ) === 'workspaceKindCreate' ? 'create' : 'edit' ;
42- const [ specErrors , setSpecErrors ] = useState < ValidationError [ ] > ( [ ] ) ;
60+ const mode : FormMode = useCurrentRouteKey ( ) === 'workspaceKindCreate' ? 'create' : 'edit' ;
61+ const [ specErrors , setSpecErrors ] = useState < ( ValidationError | ErrorEnvelopeException ) [ ] > ( [ ] ) ;
62+
63+ const { kind } = useTypedParams < 'workspaceKindEdit' > ( ) ;
64+ const [ initialFormData , initialFormDataLoaded , initialFormDataError ] =
65+ useWorkspaceKindByName ( kind ) ;
66+
67+ const [ data , setData , resetData , replaceData ] = useGenericObjectState < WorkspaceKindFormData > (
68+ initialFormData ? convertToFormData ( initialFormData ) : EMPTY_WORKSPACE_KIND_FORM_DATA ,
69+ ) ;
4370
44- const [ data , setData , resetData ] = useGenericObjectState < WorkspaceKindFormData > ( {
45- properties : {
46- displayName : '' ,
47- description : '' ,
48- deprecated : false ,
49- deprecationMessage : '' ,
50- hidden : false ,
51- icon : { url : '' } ,
52- logo : { url : '' } ,
53- } ,
54- imageConfig : {
55- default : '' ,
56- values : [ ] ,
57- } ,
58- podConfig : {
59- default : '' ,
60- values : [ ] ,
61- } ,
62- } ) ;
71+ useEffect ( ( ) => {
72+ if ( ! initialFormDataLoaded || initialFormData === null || mode === 'create' ) {
73+ return ;
74+ }
75+ replaceData ( convertToFormData ( initialFormData ) ) ;
76+ } , [ initialFormData , initialFormDataLoaded , mode , replaceData ] ) ;
6377
6478 const handleSubmit = useCallback ( async ( ) => {
6579 setIsSubmitting ( true ) ;
@@ -71,14 +85,20 @@ export const WorkspaceKindForm: React.FC = () => {
7185 console . info ( 'New workspace kind created:' , JSON . stringify ( newWorkspaceKind ) ) ;
7286 navigate ( 'workspaceKinds' ) ;
7387 }
88+ // TODO: Finish when WSKind API is finalized
89+ // const updatedWorkspace = await api.updateWorkspaceKind({}, kind, { data: {} });
90+ // console.info('Workspace Kind updated:', JSON.stringify(updatedWorkspace));
91+ // navigate('workspaceKinds');
7492 } catch ( err ) {
7593 if ( err instanceof ErrorEnvelopeException ) {
7694 const validationErrors = err . envelope . error ?. cause ?. validation_errors ;
7795 if ( validationErrors && validationErrors . length > 0 ) {
78- setSpecErrors ( validationErrors ) ;
96+ setSpecErrors ( ( prev ) => [ ... prev , ... validationErrors ] ) ;
7997 setValidated ( 'error' ) ;
8098 return ;
8199 }
100+ setSpecErrors ( ( prev ) => [ ...prev , err ] ) ;
101+ setValidated ( 'error' ) ;
82102 }
83103 // TODO: alert user about error
84104 console . error ( `Error ${ mode === 'edit' ? 'editing' : 'creating' } workspace kind: ${ err } ` ) ;
@@ -88,14 +108,26 @@ export const WorkspaceKindForm: React.FC = () => {
88108 } , [ navigate , mode , api , yamlValue ] ) ;
89109
90110 const canSubmit = useMemo (
91- ( ) => ! isSubmitting && yamlValue . length > 0 && validated === 'success' ,
92- [ yamlValue , isSubmitting , validated ] ,
111+ ( ) => ! isSubmitting && validated === 'success' ,
112+ [ isSubmitting , validated ] ,
93113 ) ;
94114
95115 const cancel = useCallback ( ( ) => {
96116 navigate ( 'workspaceKinds' ) ;
97117 } , [ navigate ] ) ;
98118
119+ if ( mode === 'edit' && initialFormDataError ) {
120+ return (
121+ < EmptyState
122+ titleText = "Error loading Workspace Kind data"
123+ headingLevel = "h4"
124+ icon = { ExclamationCircleIcon }
125+ status = "danger"
126+ >
127+ < EmptyStateBody > { initialFormDataError . message } </ EmptyStateBody >
128+ </ EmptyState >
129+ ) ;
130+ }
99131 return (
100132 < >
101133 < PageGroup isFilled = { false } stickyOnBreakpoint = { { default : 'top' } } >
@@ -159,6 +191,12 @@ export const WorkspaceKindForm: React.FC = () => {
159191 setData ( 'podConfig' , podConfig ) ;
160192 } }
161193 />
194+ < WorkspaceKindFormPodTemplate
195+ podTemplate = { data . podTemplate }
196+ updatePodTemplate = { ( podTemplate ) => {
197+ setData ( 'podTemplate' , podTemplate ) ;
198+ } }
199+ />
162200 </ >
163201 ) }
164202 </ PageSection >
@@ -169,9 +207,10 @@ export const WorkspaceKindForm: React.FC = () => {
169207 variant = "primary"
170208 ouiaId = "Primary"
171209 onClick = { handleSubmit }
172- isDisabled = { ! canSubmit }
210+ // TODO: button is always disabled on edit mode. Need to modify when WorkspaceKind edit is finalized
211+ isDisabled = { ! canSubmit || mode === 'edit' }
173212 >
174- { mode === 'create' ? 'Create' : 'Edit ' }
213+ { mode === 'create' ? 'Create' : 'Save ' }
175214 </ Button >
176215 </ FlexItem >
177216 < FlexItem >
0 commit comments