@@ -27,7 +27,35 @@ function isIDEAlias(ide: string | undefined): ide is IDEAlias {
27
27
}
28
28
type IDEKind = IDEAlias | 'image' ;
29
29
30
- export class IDESettings extends React . Component < IDESettingsProps > {
30
+ export interface IDESettingsState {
31
+ value ?: IDEKind
32
+ image ?: string
33
+ }
34
+
35
+ export class IDESettings extends React . Component < IDESettingsProps , IDESettingsState > {
36
+
37
+ constructor ( props : IDESettingsProps ) {
38
+ super ( props ) ;
39
+ this . state = this . updateStateFromProps ( { } )
40
+ }
41
+
42
+ componentDidUpdate ( prevProps : IDESettingsProps ) : void {
43
+ if ( this . props . user === prevProps . user ) {
44
+ return ;
45
+ }
46
+ this . setState ( state => this . updateStateFromProps ( state ) ) ;
47
+ }
48
+
49
+ private updateStateFromProps ( current : IDESettingsState ) : IDESettingsState {
50
+ const defaultIde = this . props . user . additionalData ?. ideSettings ?. defaultIde ;
51
+ if ( isIDEAlias ( defaultIde ) ) {
52
+ return { ...current , value : defaultIde } ;
53
+ }
54
+ if ( defaultIde === undefined ) {
55
+ return { ...current , value : 'theia' } ;
56
+ }
57
+ return { ...current , value : 'image' , image : defaultIde } ;
58
+ }
31
59
32
60
render ( ) {
33
61
return < React . Fragment >
@@ -38,50 +66,53 @@ export class IDESettings extends React.Component<IDESettingsProps> {
38
66
}
39
67
40
68
private renderRadio ( label : string , value : IDEKind ) {
41
- const checked = value === this . value ;
42
- return < Grid item xs = { 12 } >
43
- < FormControlLabel control = { < Radio color = "default" /> } label = { label } value = { value } checked = { checked } onChange = { this . updateDefaultIde } />
44
- { value === 'image' && < Input value = { this . image } onChange = { this . updateDefaultIde } /> }
45
- </ Grid > ;
69
+ const checked = value === this . state . value ;
70
+ return < Grid container >
71
+ < Grid item xs = { 1 } >
72
+ < FormControlLabel control = { < Radio color = "default" /> } label = { label } value = { value } checked = { checked } onChange = { this . updateState } />
73
+ </ Grid >
74
+ < Grid item xs = { 11 } >
75
+ { value === 'image' && this . renderImage ( ) }
76
+ </ Grid >
77
+ </ Grid >
46
78
}
47
79
48
- private get value ( ) : IDEKind {
49
- const defaultIde = this . props . user . additionalData ?. ideSettings ?. defaultIde ;
50
- if ( isIDEAlias ( defaultIde ) ) {
51
- return defaultIde ;
52
- }
53
- if ( defaultIde ) {
54
- return 'image' ;
55
- }
56
- return 'theia' ;
57
- }
58
-
59
- private get image ( ) : string | undefined {
60
- const defaultIde = this . props . user . additionalData ?. ideSettings ?. defaultIde ;
61
- if ( isIDEAlias ( defaultIde ) ) {
62
- return undefined ;
63
- }
64
- return defaultIde ;
80
+ private renderImage ( ) {
81
+ return < Input
82
+ value = { this . state . image }
83
+ onChange = { this . updateState }
84
+ placeholder = "Type a reference to docker image, e.g. index.docker.io/gitpod-io/theia-ide:latest"
85
+ error = { this . state . value === 'image' && ( this . state . image === undefined || this . state . image . trim ( ) === "" ) }
86
+ fullWidth = { true }
87
+ /> ;
65
88
}
66
89
67
- private updateDefaultIde = ( event : React . ChangeEvent < HTMLInputElement > ) => {
68
- let value = this . value ;
69
- let image = this . image ;
90
+ private updateState = ( event : React . ChangeEvent < HTMLInputElement > ) => {
91
+ const state : IDESettingsState = { }
70
92
if ( event . target . type === 'radio' ) {
71
- value = event . target . value as IDEKind ;
93
+ state . value = event . target . value as IDEKind ;
72
94
} else {
73
- image = event . target . value ;
95
+ state . image = event . target . value ;
74
96
}
97
+ this . setState ( state , ( ) => this . fireStateChange ( ) ) ;
98
+ }
99
+
100
+ private fireStateChange ( ) : void {
101
+ const { value, image } = this . state ;
75
102
76
103
const additionalData = ( this . props . user . additionalData || { } ) ;
77
104
const settings = additionalData . ideSettings || { } ;
78
105
if ( value === 'theia' ) {
79
106
delete settings . defaultIde ;
80
107
} else if ( value === 'image' ) {
81
- settings . defaultIde = image ;
108
+ settings . defaultIde = image || '' ;
82
109
} else {
83
110
settings . defaultIde = value ;
84
111
}
112
+ if ( settings . defaultIde ?. trim ( ) === "" ) {
113
+ // invalid
114
+ return ;
115
+ }
85
116
additionalData . ideSettings = settings ;
86
117
this . props . onChange ( { additionalData } ) ;
87
118
}
0 commit comments