Skip to content

Commit 7e6e29c

Browse files
committed
[dashboard] save default image
1 parent d22e969 commit 7e6e29c

File tree

2 files changed

+98
-69
lines changed

2 files changed

+98
-69
lines changed

components/dashboard/src/data/organizations/update-org-settings-mutation.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,19 @@ import { getGitpodService } from "../../service/service";
1010
import { getOrgSettingsQueryKey, OrgSettingsResult } from "./org-settings-query";
1111
import { useCurrentOrg } from "./orgs-query";
1212

13-
type UpdateOrganizationSettingsArgs = Pick<OrganizationSettings, "workspaceSharingDisabled">;
13+
type UpdateOrganizationSettingsArgs = Pick<OrganizationSettings, "workspaceSharingDisabled" | "defaultWorkspaceImage">;
1414

1515
export const useUpdateOrgSettingsMutation = () => {
1616
const queryClient = useQueryClient();
1717
const team = useCurrentOrg().data;
1818
const teamId = team?.id || "";
1919

2020
return useMutation<OrganizationSettings, Error, UpdateOrganizationSettingsArgs>({
21-
mutationFn: async ({ workspaceSharingDisabled }) => {
22-
return await getGitpodService().server.updateOrgSettings(teamId, { workspaceSharingDisabled });
21+
mutationFn: async ({ workspaceSharingDisabled, defaultWorkspaceImage }) => {
22+
return await getGitpodService().server.updateOrgSettings(teamId, {
23+
workspaceSharingDisabled,
24+
defaultWorkspaceImage,
25+
});
2326
},
2427
onSuccess: (newData, _) => {
2528
const queryKey = getOrgSettingsQueryKey(teamId);

components/dashboard/src/teams/TeamSettings.tsx

Lines changed: 92 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import { OrganizationSettings } from "@gitpod/gitpod-protocol";
8-
import React, { useCallback, useState } from "react";
8+
import React, { useCallback, useState, useEffect } from "react";
99
import Alert from "../components/Alert";
1010
import { Button } from "../components/Button";
1111
import { CheckboxInputField } from "../components/forms/CheckboxInputField";
@@ -14,7 +14,7 @@ import { TextInputField } from "../components/forms/TextInputField";
1414
import { Heading2, Subheading } from "../components/typography/headings";
1515
import { useUpdateOrgSettingsMutation } from "../data/organizations/update-org-settings-mutation";
1616
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";
1818
import { useUpdateOrgMutation } from "../data/organizations/update-org-mutation";
1919
import { useOnBlurError } from "../hooks/use-onblur-error";
2020
import { teamsService } from "../service/public-api";
@@ -32,34 +32,6 @@ export default function TeamSettingsPage() {
3232
const [teamName, setTeamName] = useState(org?.name || "");
3333
const [updated, setUpdated] = useState(false);
3434
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-
);
6335

6436
const close = () => setModal(false);
6537

@@ -116,12 +88,6 @@ export default function TeamSettingsPage() {
11688
<span>{updateOrg.error.message || "unknown error"}</span>
11789
</Alert>
11890
)}
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-
)}
12591
{updated && (
12692
<Alert type="message" closable={true} className="mb-2 max-w-xl rounded-md">
12793
Organization name has been updated.
@@ -145,44 +111,16 @@ export default function TeamSettingsPage() {
145111
)}
146112
</form>
147113

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} />
161115

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>
179116
{user?.organizationId !== org?.id && org?.isOwner && (
180117
<>
181118
<Heading2 className="pt-12">Delete Organization</Heading2>
182119
<Subheading className="pb-4 max-w-2xl">
183120
Deleting this organization will also remove all associated data, including projects and
184121
workspaces. Deleted organizations cannot be restored!
185122
</Subheading>
123+
186124
<button className="danger secondary" onClick={() => setModal(true)}>
187125
Delete Organization
188126
</button>
@@ -227,3 +165,91 @@ export default function TeamSettingsPage() {
227165
</>
228166
);
229167
}
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

Comments
 (0)