5
5
*/
6
6
7
7
import { OrganizationSettings } from "@gitpod/gitpod-protocol" ;
8
- import React , { useCallback , useState } from "react" ;
8
+ import React , { useCallback , useState , useEffect } from "react" ;
9
9
import Alert from "../components/Alert" ;
10
10
import { Button } from "../components/Button" ;
11
11
import { CheckboxInputField } from "../components/forms/CheckboxInputField" ;
@@ -14,7 +14,7 @@ import { TextInputField } from "../components/forms/TextInputField";
14
14
import { Heading2 , Subheading } from "../components/typography/headings" ;
15
15
import { useUpdateOrgSettingsMutation } from "../data/organizations/update-org-settings-mutation" ;
16
16
import { useOrgSettingsQuery } from "../data/organizations/org-settings-query" ;
17
- import { useCurrentOrg , useOrganizationsInvalidator } from "../data/organizations/orgs-query" ;
17
+ import { OrganizationInfo , useCurrentOrg , useOrganizationsInvalidator } from "../data/organizations/orgs-query" ;
18
18
import { useUpdateOrgMutation } from "../data/organizations/update-org-mutation" ;
19
19
import { useOnBlurError } from "../hooks/use-onblur-error" ;
20
20
import { teamsService } from "../service/public-api" ;
@@ -32,34 +32,6 @@ export default function TeamSettingsPage() {
32
32
const [ teamName , setTeamName ] = useState ( org ?. name || "" ) ;
33
33
const [ updated , setUpdated ] = useState ( false ) ;
34
34
const updateOrg = useUpdateOrgMutation ( ) ;
35
- const { data : settings , isLoading } = useOrgSettingsQuery ( ) ;
36
- const updateTeamSettings = useUpdateOrgSettingsMutation ( ) ;
37
- const [ defaultWorkspaceImage , setDefaultWorkspaceImage ] = useState ( settings ?. defaultWorkspaceImage ?? "" ) ;
38
- const { toast } = useToast ( ) ;
39
-
40
- const handleUpdateTeamSettings = useCallback (
41
- async ( newSettings : Partial < OrganizationSettings > ) => {
42
- if ( ! org ?. id ) {
43
- throw new Error ( "no organization selected" ) ;
44
- }
45
- if ( ! org . isOwner ) {
46
- throw new Error ( "no organization settings change permission" ) ;
47
- }
48
- try {
49
- await updateTeamSettings . mutateAsync ( {
50
- ...settings ,
51
- ...newSettings ,
52
- } ) ;
53
- if ( newSettings . defaultWorkspaceImage ) {
54
- toast ( "Default workspace image has been updated." ) ;
55
- }
56
- } catch ( error ) {
57
- console . error ( error ) ;
58
- toast ( error . message || "Oh no, there was a problem with our service." ) ;
59
- }
60
- } ,
61
- [ updateTeamSettings , org ?. id , org ?. isOwner , settings , toast ] ,
62
- ) ;
63
35
64
36
const close = ( ) => setModal ( false ) ;
65
37
@@ -116,12 +88,6 @@ export default function TeamSettingsPage() {
116
88
< span > { updateOrg . error . message || "unknown error" } </ span >
117
89
</ Alert >
118
90
) }
119
- { updateTeamSettings . isError && (
120
- < Alert type = "error" closable = { true } className = "mb-2 max-w-xl rounded-md" >
121
- < span > Failed to update organization settings: </ span >
122
- < span > { updateTeamSettings . error . message || "unknown error" } </ span >
123
- </ Alert >
124
- ) }
125
91
{ updated && (
126
92
< Alert type = "message" closable = { true } className = "mb-2 max-w-xl rounded-md" >
127
93
Organization name has been updated.
@@ -145,44 +111,16 @@ export default function TeamSettingsPage() {
145
111
) }
146
112
</ form >
147
113
148
- < form onSubmit = { ( ) => handleUpdateTeamSettings ( { defaultWorkspaceImage } ) } >
149
- < Heading2 className = "pt-12" > Collaboration & Sharing </ Heading2 >
150
- < Subheading className = "max-w-2xl" >
151
- Choose which workspace images you want to use for your workspaces.
152
- </ Subheading >
153
-
154
- < CheckboxInputField
155
- label = "Workspace Sharing"
156
- hint = "Allow workspaces created within an Organization to share the workspace with any authenticated user."
157
- checked = { ! settings ?. workspaceSharingDisabled }
158
- onChange = { ( checked ) => handleUpdateTeamSettings ( { workspaceSharingDisabled : ! checked } ) }
159
- disabled = { isLoading || ! org ?. isOwner }
160
- />
114
+ < OrgSettingsForm org = { org } />
161
115
162
- < Heading2 className = "pt-12" > Workspace Settings</ Heading2 >
163
- < TextInputField
164
- label = "Default Image"
165
- // TODO: ECR is dedicated only now
166
- // TODO: Provide document links
167
- hint = "Use any workspace image from Gitpod, or any image from your private ECR registry, e.g. <xyz>.amazonaws.com/<your-image-name:tag>. "
168
- value = { defaultWorkspaceImage }
169
- onChange = { setDefaultWorkspaceImage }
170
- disabled = { isLoading || ! org ?. isOwner }
171
- />
172
-
173
- { org ?. isOwner && (
174
- < Button htmlType = "submit" size = "block" className = "mt-4" disabled = { ! org . isOwner } >
175
- Save
176
- </ Button >
177
- ) }
178
- </ form >
179
116
{ user ?. organizationId !== org ?. id && org ?. isOwner && (
180
117
< >
181
118
< Heading2 className = "pt-12" > Delete Organization</ Heading2 >
182
119
< Subheading className = "pb-4 max-w-2xl" >
183
120
Deleting this organization will also remove all associated data, including projects and
184
121
workspaces. Deleted organizations cannot be restored!
185
122
</ Subheading >
123
+
186
124
< button className = "danger secondary" onClick = { ( ) => setModal ( true ) } >
187
125
Delete Organization
188
126
</ button >
@@ -227,3 +165,91 @@ export default function TeamSettingsPage() {
227
165
</ >
228
166
) ;
229
167
}
168
+
169
+ function OrgSettingsForm ( props : { org ?: OrganizationInfo } ) {
170
+ const { org } = props ;
171
+ const { data : settings , isLoading } = useOrgSettingsQuery ( ) ;
172
+ const updateTeamSettings = useUpdateOrgSettingsMutation ( ) ;
173
+ const [ defaultWorkspaceImage , setDefaultWorkspaceImage ] = useState ( settings ?. defaultWorkspaceImage ?? "" ) ;
174
+ const { toast } = useToast ( ) ;
175
+
176
+ useEffect ( ( ) => {
177
+ if ( ! settings ) {
178
+ return ;
179
+ }
180
+ setDefaultWorkspaceImage ( settings . defaultWorkspaceImage ?? "" ) ;
181
+ } , [ settings ] ) ;
182
+
183
+ const handleUpdateTeamSettings = useCallback (
184
+ async ( newSettings : Partial < OrganizationSettings > ) => {
185
+ if ( ! org ?. id ) {
186
+ throw new Error ( "no organization selected" ) ;
187
+ }
188
+ if ( ! org . isOwner ) {
189
+ throw new Error ( "no organization settings change permission" ) ;
190
+ }
191
+ try {
192
+ await updateTeamSettings . mutateAsync ( {
193
+ ...settings ,
194
+ ...newSettings ,
195
+ } ) ;
196
+ if ( newSettings . defaultWorkspaceImage ) {
197
+ toast ( "Default workspace image has been updated." ) ;
198
+ }
199
+ } catch ( error ) {
200
+ console . error ( error ) ;
201
+ toast (
202
+ error . message
203
+ ? "Failed to update organization settings: " + error . message
204
+ : "Oh no, there was a problem with our service." ,
205
+ ) ;
206
+ }
207
+ } ,
208
+ [ updateTeamSettings , org ?. id , org ?. isOwner , settings , toast ] ,
209
+ ) ;
210
+
211
+ return (
212
+ < form
213
+ onSubmit = { ( e ) => {
214
+ e . preventDefault ( ) ;
215
+ handleUpdateTeamSettings ( { defaultWorkspaceImage } ) ;
216
+ } }
217
+ >
218
+ < Heading2 className = "pt-12" > Collaboration & Sharing </ Heading2 >
219
+ < Subheading className = "max-w-2xl" >
220
+ Choose which workspace images you want to use for your workspaces.
221
+ </ Subheading >
222
+
223
+ { updateTeamSettings . isError && (
224
+ < Alert type = "error" closable = { true } className = "mb-2 max-w-xl rounded-md" >
225
+ < span > Failed to update organization settings: </ span >
226
+ < span > { updateTeamSettings . error . message || "unknown error" } </ span >
227
+ </ Alert >
228
+ ) }
229
+
230
+ < CheckboxInputField
231
+ label = "Workspace Sharing"
232
+ hint = "Allow workspaces created within an Organization to share the workspace with any authenticated user."
233
+ checked = { ! settings ?. workspaceSharingDisabled }
234
+ onChange = { ( checked ) => handleUpdateTeamSettings ( { workspaceSharingDisabled : ! checked } ) }
235
+ disabled = { isLoading || ! org ?. isOwner }
236
+ />
237
+
238
+ < Heading2 className = "pt-12" > Workspace Settings</ Heading2 >
239
+ < TextInputField
240
+ label = "Default Image"
241
+ // TODO: Provide document links
242
+ hint = "Use any official Gitpod Docker image, or a URL to an image."
243
+ value = { defaultWorkspaceImage }
244
+ onChange = { setDefaultWorkspaceImage }
245
+ disabled = { isLoading || ! org ?. isOwner }
246
+ />
247
+
248
+ { org ?. isOwner && (
249
+ < Button htmlType = "submit" className = "mt-4" disabled = { ! org . isOwner } >
250
+ Save
251
+ </ Button >
252
+ ) }
253
+ </ form >
254
+ ) ;
255
+ }
0 commit comments