1
- import React , { useCallback , useMemo , useState } from 'react' ;
1
+ import React , { useCallback , useEffect , useMemo , useState } from 'react' ;
2
2
import {
3
3
Button ,
4
4
Content ,
5
5
ContentVariants ,
6
+ EmptyState ,
7
+ EmptyStateBody ,
6
8
Flex ,
7
9
FlexItem ,
8
10
PageGroup ,
@@ -11,25 +13,42 @@ import {
11
13
StackItem ,
12
14
} from '@patternfly/react-core' ;
13
15
import { t_global_spacer_sm as SmallPadding } from '@patternfly/react-tokens' ;
16
+ import { ExclamationCircleIcon } from '@patternfly/react-icons' ;
14
17
import { 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' ;
16
21
import { useCurrentRouteKey } from '~/app/hooks/useCurrentRouteKey' ;
17
22
import useGenericObjectState from '~/app/hooks/useGenericObjectState' ;
18
23
import { useNotebookAPI } from '~/app/hooks/useNotebookAPI' ;
19
24
import { WorkspaceKindFormData } from '~/app/types' ;
20
25
import { ErrorEnvelopeException } from '~/shared/api/apiUtils' ;
21
- import { ValidationError } from '~/shared/api/backendApiTypes' ;
22
26
import { WorkspaceKindFileUpload } from './fileUpload/WorkspaceKindFileUpload' ;
23
27
import { WorkspaceKindFormProperties } from './properties/WorkspaceKindFormProperties' ;
24
28
import { WorkspaceKindFormImage } from './image/WorkspaceKindFormImage' ;
25
29
import { WorkspaceKindFormPodConfig } from './podConfig/WorkspaceKindFormPodConfig' ;
30
+ import { WorkspaceKindFormPodTemplate } from './podTemplate/WorkspaceKindFormPodTemplate' ;
31
+ import { EMPTY_WORKSPACE_KIND_FORM_DATA } from './helpers' ;
26
32
27
33
export enum WorkspaceKindFormView {
28
34
Form ,
29
35
FileUpload ,
30
36
}
31
37
32
38
export 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
+ } ;
33
52
34
53
export const WorkspaceKindForm : React . FC = ( ) => {
35
54
const navigate = useTypedNavigate ( ) ;
@@ -38,28 +57,23 @@ export const WorkspaceKindForm: React.FC = () => {
38
57
const [ yamlValue , setYamlValue ] = useState ( '' ) ;
39
58
const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
40
59
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
+ ) ;
43
70
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 ] ) ;
63
77
64
78
const handleSubmit = useCallback ( async ( ) => {
65
79
setIsSubmitting ( true ) ;
@@ -71,14 +85,20 @@ export const WorkspaceKindForm: React.FC = () => {
71
85
console . info ( 'New workspace kind created:' , JSON . stringify ( newWorkspaceKind ) ) ;
72
86
navigate ( 'workspaceKinds' ) ;
73
87
}
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');
74
92
} catch ( err ) {
75
93
if ( err instanceof ErrorEnvelopeException ) {
76
94
const validationErrors = err . envelope . error ?. cause ?. validation_errors ;
77
95
if ( validationErrors && validationErrors . length > 0 ) {
78
- setSpecErrors ( validationErrors ) ;
96
+ setSpecErrors ( ( prev ) => [ ... prev , ... validationErrors ] ) ;
79
97
setValidated ( 'error' ) ;
80
98
return ;
81
99
}
100
+ setSpecErrors ( ( prev ) => [ ...prev , err ] ) ;
101
+ setValidated ( 'error' ) ;
82
102
}
83
103
// TODO: alert user about error
84
104
console . error ( `Error ${ mode === 'edit' ? 'editing' : 'creating' } workspace kind: ${ err } ` ) ;
@@ -88,14 +108,26 @@ export const WorkspaceKindForm: React.FC = () => {
88
108
} , [ navigate , mode , api , yamlValue ] ) ;
89
109
90
110
const canSubmit = useMemo (
91
- ( ) => ! isSubmitting && yamlValue . length > 0 && validated === 'success' ,
92
- [ yamlValue , isSubmitting , validated ] ,
111
+ ( ) => ! isSubmitting && validated === 'success' ,
112
+ [ isSubmitting , validated ] ,
93
113
) ;
94
114
95
115
const cancel = useCallback ( ( ) => {
96
116
navigate ( 'workspaceKinds' ) ;
97
117
} , [ navigate ] ) ;
98
118
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
+ }
99
131
return (
100
132
< >
101
133
< PageGroup isFilled = { false } stickyOnBreakpoint = { { default : 'top' } } >
@@ -159,6 +191,12 @@ export const WorkspaceKindForm: React.FC = () => {
159
191
setData ( 'podConfig' , podConfig ) ;
160
192
} }
161
193
/>
194
+ < WorkspaceKindFormPodTemplate
195
+ podTemplate = { data . podTemplate }
196
+ updatePodTemplate = { ( podTemplate ) => {
197
+ setData ( 'podTemplate' , podTemplate ) ;
198
+ } }
199
+ />
162
200
</ >
163
201
) }
164
202
</ PageSection >
@@ -169,9 +207,10 @@ export const WorkspaceKindForm: React.FC = () => {
169
207
variant = "primary"
170
208
ouiaId = "Primary"
171
209
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' }
173
212
>
174
- { mode === 'create' ? 'Create' : 'Edit ' }
213
+ { mode === 'create' ? 'Create' : 'Save ' }
175
214
</ Button >
176
215
</ FlexItem >
177
216
< FlexItem >
0 commit comments