Skip to content

Commit c33b555

Browse files
committed
[public-api] align with API guidelines
1 parent 2e3429a commit c33b555

31 files changed

+894
-653
lines changed

components/dashboard/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"version": "0.0.0",
55
"private": true,
66
"dependencies": {
7+
"@bufbuild/protobuf": "^1.3.3",
78
"@connectrpc/connect": "1.1.2",
89
"@connectrpc/connect-web": "1.1.2",
910
"@gitpod/gitpod-protocol": "0.1.5",

components/dashboard/src/components/PrebuildLogs.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ export default function PrebuildLogs(props: PrebuildLogsProps) {
6767
// Try get hold of a recent WorkspaceInfo
6868
try {
6969
const request = new GetWorkspaceRequest();
70-
request.id = props.workspaceId;
70+
request.workspaceId = props.workspaceId;
7171
const response = await workspaceClient.getWorkspace(request);
7272
setWorkspace({
73-
instanceId: response.item?.status?.instanceId,
74-
phase: response.item?.status?.phase?.name,
73+
instanceId: response.workspace?.status?.instanceId,
74+
phase: response.workspace?.status?.phase?.name,
7575
});
7676
} catch (err) {
7777
console.error(err);

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
* See License.AGPL.txt in the project root for license information.
55
*/
66

7-
import { Organization } from "@gitpod/gitpod-protocol";
87
import { useMutation } from "@tanstack/react-query";
9-
import { getGitpodService } from "../../service/service";
108
import { useCurrentOrg, useOrganizationsInvalidator } from "./orgs-query";
9+
import { organizationClient } from "../../service/public-api";
10+
import { Organization } from "@gitpod/public-api/lib/gitpod/v1/organization_pb";
1111

1212
type UpdateOrgArgs = Pick<Organization, "name">;
1313

@@ -21,7 +21,8 @@ export const useUpdateOrgMutation = () => {
2121
throw new Error("No current organization selected");
2222
}
2323

24-
return await getGitpodService().server.updateTeam(org.id, { name });
24+
const response = await organizationClient.updateOrganization({ name });
25+
return response.organization!;
2526
},
2627
onSuccess(updatedOrg) {
2728
// TODO: Update query cache with new org prior to invalidation so it's reflected immediately

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

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import { useMutation } from "@tanstack/react-query";
88
import { useOrgSettingsQueryInvalidator } from "./org-settings-query";
99
import { useCurrentOrg } from "./orgs-query";
1010
import { organizationClient } from "../../service/public-api";
11-
import { OrganizationSettings } from "@gitpod/public-api/lib/gitpod/v1/organization_pb";
11+
import {
12+
OrganizationSettings,
13+
UpdateOrganizationSettingsRequest,
14+
} from "@gitpod/public-api/lib/gitpod/v1/organization_pb";
15+
import { FieldMask } from "@bufbuild/protobuf";
1216

1317
type UpdateOrganizationSettingsArgs = Partial<
1418
Pick<OrganizationSettings, "workspaceSharingDisabled" | "defaultWorkspaceImage">
@@ -17,17 +21,23 @@ type UpdateOrganizationSettingsArgs = Partial<
1721
export const useUpdateOrgSettingsMutation = () => {
1822
const org = useCurrentOrg().data;
1923
const invalidator = useOrgSettingsQueryInvalidator();
20-
const teamId = org?.id || "";
24+
const organizationId = org?.id || "";
2125

2226
return useMutation<OrganizationSettings, Error, UpdateOrganizationSettingsArgs>({
2327
mutationFn: async ({ workspaceSharingDisabled, defaultWorkspaceImage }) => {
24-
const settings = await organizationClient.updateOrganizationSettings({
25-
organizationId: teamId,
26-
settings: {
27-
workspaceSharingDisabled: workspaceSharingDisabled || false,
28-
defaultWorkspaceImage,
29-
},
28+
const request = new UpdateOrganizationSettingsRequest({
29+
organizationId,
30+
workspaceSharingDisabled,
3031
});
32+
defaultWorkspaceImage = defaultWorkspaceImage?.trim();
33+
if (defaultWorkspaceImage) {
34+
request.defaultWorkspaceImage = defaultWorkspaceImage;
35+
} else if (defaultWorkspaceImage === "") {
36+
request.resetMask = new FieldMask({
37+
paths: ["defaultWorkspaceImage"],
38+
});
39+
}
40+
const settings = await organizationClient.updateOrganizationSettings(request);
3141
return settings.settings || new OrganizationSettings();
3242
},
3343
onSuccess: invalidator,

components/dashboard/src/data/setup.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import * as ConfigurationClasses from "@gitpod/public-api/lib/gitpod/v1/configur
2525
// This is used to version the cache
2626
// If data we cache changes in a non-backwards compatible way, increment this version
2727
// That will bust any previous cache versions a client may have stored
28-
const CACHE_VERSION = "2";
28+
const CACHE_VERSION = "3";
2929

3030
export function noPersistence(queryKey: QueryKey): QueryKey {
3131
return [...queryKey, "no-persistence"];

components/dashboard/src/service/json-rpc-organization-client.ts

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
} from "@gitpod/public-api/lib/gitpod/v1/organization_pb";
3838
import { getGitpodService } from "./service";
3939
import { converter } from "./public-api";
40+
import { OrganizationSettings } from "@gitpod/gitpod-protocol";
4041

4142
export class JsonRpcOrganizationClient implements PromiseClient<typeof OrganizationService> {
4243
async createOrganization(
@@ -71,7 +72,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
7172
options?: CallOptions | undefined,
7273
): Promise<UpdateOrganizationResponse> {
7374
if (!request.organizationId) {
74-
throw new ConnectError("id is required", Code.InvalidArgument);
75+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
7576
}
7677
if (!request.name) {
7778
throw new ConnectError("name is required", Code.InvalidArgument);
@@ -97,7 +98,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
9798
options?: CallOptions | undefined,
9899
): Promise<DeleteOrganizationResponse> {
99100
if (!request.organizationId) {
100-
throw new ConnectError("id is required", Code.InvalidArgument);
101+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
101102
}
102103
await getGitpodService().server.deleteTeam(request.organizationId);
103104
return new DeleteOrganizationResponse();
@@ -108,7 +109,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
108109
options?: CallOptions | undefined,
109110
): Promise<GetOrganizationInvitationResponse> {
110111
if (!request.organizationId) {
111-
throw new ConnectError("id is required", Code.InvalidArgument);
112+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
112113
}
113114
const result = await getGitpodService().server.getGenericInvite(request.organizationId);
114115
return new GetOrganizationInvitationResponse({
@@ -134,7 +135,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
134135
options?: CallOptions | undefined,
135136
): Promise<ResetOrganizationInvitationResponse> {
136137
if (!request.organizationId) {
137-
throw new ConnectError("id is required", Code.InvalidArgument);
138+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
138139
}
139140
const newInvite = await getGitpodService().server.resetGenericInvite(request.organizationId);
140141
return new ResetOrganizationInvitationResponse({
@@ -147,7 +148,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
147148
options?: CallOptions | undefined,
148149
): Promise<ListOrganizationMembersResponse> {
149150
if (!request.organizationId) {
150-
throw new ConnectError("id is required", Code.InvalidArgument);
151+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
151152
}
152153
const result = await getGitpodService().server.getTeamMembers(request.organizationId);
153154
return new ListOrganizationMembersResponse({
@@ -160,7 +161,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
160161
options?: CallOptions | undefined,
161162
): Promise<UpdateOrganizationMemberResponse> {
162163
if (!request.organizationId) {
163-
throw new ConnectError("id is required", Code.InvalidArgument);
164+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
164165
}
165166
if (!request.userId) {
166167
throw new ConnectError("userId is required", Code.InvalidArgument);
@@ -181,7 +182,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
181182
options?: CallOptions | undefined,
182183
): Promise<DeleteOrganizationMemberResponse> {
183184
if (!request.organizationId) {
184-
throw new ConnectError("id is required", Code.InvalidArgument);
185+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
185186
}
186187
if (!request.userId) {
187188
throw new ConnectError("userId is required", Code.InvalidArgument);
@@ -195,7 +196,7 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
195196
options?: CallOptions | undefined,
196197
): Promise<GetOrganizationSettingsResponse> {
197198
if (!request.organizationId) {
198-
throw new ConnectError("id is required", Code.InvalidArgument);
199+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
199200
}
200201
const result = await getGitpodService().server.getOrgSettings(request.organizationId);
201202
return new GetOrganizationSettingsResponse({
@@ -208,12 +209,18 @@ export class JsonRpcOrganizationClient implements PromiseClient<typeof Organizat
208209
options?: CallOptions | undefined,
209210
): Promise<UpdateOrganizationSettingsResponse> {
210211
if (!request.organizationId) {
211-
throw new ConnectError("id is required", Code.InvalidArgument);
212-
}
213-
await getGitpodService().server.updateOrgSettings(request.organizationId, {
214-
workspaceSharingDisabled: request.settings?.workspaceSharingDisabled,
215-
defaultWorkspaceImage: request.settings?.defaultWorkspaceImage,
216-
});
212+
throw new ConnectError("organizationId is required", Code.InvalidArgument);
213+
}
214+
const update: Partial<OrganizationSettings> = {
215+
workspaceSharingDisabled: request?.workspaceSharingDisabled,
216+
};
217+
const resetDefaultWorkspaceImage = request.resetMask?.paths?.includes("defaultWorkspaceImage");
218+
if (resetDefaultWorkspaceImage) {
219+
update.defaultWorkspaceImage = null;
220+
} else if (typeof request?.defaultWorkspaceImage === "string") {
221+
update.defaultWorkspaceImage = request.defaultWorkspaceImage;
222+
}
223+
await getGitpodService().server.updateOrgSettings(request.organizationId, update);
217224
return new UpdateOrganizationSettingsResponse();
218225
}
219226
}

components/dashboard/src/service/json-rpc-workspace-client.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ import { WorkspaceInstance } from "@gitpod/gitpod-protocol";
2020

2121
export class JsonRpcWorkspaceClient implements PromiseClient<typeof WorkspaceService> {
2222
async getWorkspace(request: PartialMessage<GetWorkspaceRequest>): Promise<GetWorkspaceResponse> {
23-
if (!request.id) {
24-
throw new ConnectError("id is required", Code.InvalidArgument);
23+
if (!request.workspaceId) {
24+
throw new ConnectError("workspaceId is required", Code.InvalidArgument);
2525
}
26-
const info = await getGitpodService().server.getWorkspace(request.id);
26+
const info = await getGitpodService().server.getWorkspace(request.workspaceId);
2727
const workspace = converter.toWorkspace(info);
2828
const result = new GetWorkspaceResponse();
29-
result.item = workspace;
29+
result.workspace = workspace;
3030
return result;
3131
}
3232

@@ -38,11 +38,11 @@ export class JsonRpcWorkspaceClient implements PromiseClient<typeof WorkspaceSer
3838
throw new ConnectError("signal is required", Code.InvalidArgument);
3939
}
4040
if (request.workspaceId) {
41-
const resp = await this.getWorkspace({ id: request.workspaceId });
42-
if (resp.item?.status) {
41+
const resp = await this.getWorkspace({ workspaceId: request.workspaceId });
42+
if (resp.workspace?.status) {
4343
const response = new WatchWorkspaceStatusResponse();
44-
response.workspaceId = resp.item.id;
45-
response.status = resp.item.status;
44+
response.workspaceId = resp.workspace.id;
45+
response.status = resp.workspace.status;
4646
yield response;
4747
}
4848
}

components/dashboard/src/start/StartWorkspace.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,14 @@ export default class StartWorkspace extends React.Component<StartWorkspaceProps,
272272
const { workspaceId } = this.props;
273273
try {
274274
const request = new GetWorkspaceRequest();
275-
request.id = workspaceId;
275+
request.workspaceId = workspaceId;
276276
const response = await workspaceClient.getWorkspace(request);
277-
if (response.item?.status?.instanceId) {
277+
if (response.workspace?.status?.instanceId) {
278278
this.setState((s) => ({
279-
workspace: response.item,
280-
startedInstanceId: s.startedInstanceId || response.item?.status?.instanceId, // note: here's a potential mismatch between startedInstanceId and instance.id. TODO(gpl) How to handle this?
279+
workspace: response.workspace,
280+
startedInstanceId: s.startedInstanceId || response.workspace?.status?.instanceId, // note: here's a potential mismatch between startedInstanceId and instance.id. TODO(gpl) How to handle this?
281281
}));
282-
this.onWorkspaceUpdate(response.item);
282+
this.onWorkspaceUpdate(response.workspace);
283283
}
284284
} catch (error) {
285285
console.error(error);

components/dashboard/src/teams/TeamSettings.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { organizationClient } from "../service/public-api";
2727
import { gitpodHostUrl } from "../service/service";
2828
import { useCurrentUser } from "../user-context";
2929
import { OrgSettingsPage } from "./OrgSettingsPage";
30+
import { ErrorCode } from "@gitpod/gitpod-protocol/lib/messaging/error";
3031

3132
export default function TeamSettingsPage() {
3233
const user = useCurrentUser();
@@ -204,7 +205,6 @@ function OrgSettingsForm(props: { org?: Organization; isOwner: boolean }) {
204205
<form
205206
onSubmit={(e) => {
206207
e.preventDefault();
207-
// handleUpdateTeamSettings({ defaultWorkspaceImage });
208208
}}
209209
>
210210
{props.org && (
@@ -282,7 +282,7 @@ function WorkspaceImageButton(props: {
282282
};
283283
}
284284

285-
const image = props.settings?.defaultWorkspaceImage ?? props.defaultWorkspaceImage ?? "";
285+
const image = props.settings?.defaultWorkspaceImage || props.defaultWorkspaceImage || "";
286286

287287
const descList = useMemo(() => {
288288
const arr: ReactNode[] = [<span>Default image</span>];
@@ -348,7 +348,7 @@ interface OrgDefaultWorkspaceImageModalProps {
348348

349349
function OrgDefaultWorkspaceImageModal(props: OrgDefaultWorkspaceImageModalProps) {
350350
const [errorMsg, setErrorMsg] = useState("");
351-
const [defaultWorkspaceImage, setDefaultWorkspaceImage] = useState(props.settings?.defaultWorkspaceImage ?? "");
351+
const [defaultWorkspaceImage, setDefaultWorkspaceImage] = useState(props.settings?.defaultWorkspaceImage || "");
352352
const updateTeamSettings = useUpdateOrgSettingsMutation();
353353

354354
const handleUpdateTeamSettings = useCallback(
@@ -360,7 +360,9 @@ function OrgDefaultWorkspaceImageModal(props: OrgDefaultWorkspaceImageModalProps
360360
});
361361
props.onClose();
362362
} catch (error) {
363-
console.error(error);
363+
if (!ErrorCode.isUserError(error["code"])) {
364+
console.error(error);
365+
}
364366
setErrorMsg(error.message);
365367
}
366368
},

components/gitpod-db/src/team-db.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export interface TeamDB extends TransactionalDB<TeamDB> {
4040
deleteTeam(teamId: string): Promise<void>;
4141

4242
findOrgSettings(teamId: string): Promise<OrganizationSettings | undefined>;
43-
setOrgSettings(teamId: string, settings: Partial<OrganizationSettings>): Promise<void>;
43+
setOrgSettings(teamId: string, settings: Partial<OrganizationSettings>): Promise<OrganizationSettings>;
4444

4545
hasActiveSSO(organizationId: string): Promise<boolean>;
4646
}

components/gitpod-db/src/typeorm/team-db-impl.ts

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -366,28 +366,19 @@ export class TeamDBImpl extends TransactionalDBImpl<TeamDB> implements TeamDB {
366366
});
367367
}
368368

369-
public async setOrgSettings(orgId: string, settings: Partial<OrganizationSettings>): Promise<void> {
369+
public async setOrgSettings(orgId: string, settings: Partial<OrganizationSettings>): Promise<OrganizationSettings> {
370370
const repo = await this.getOrgSettingsRepo();
371371
const team = await repo.findOne({ where: { orgId, deleted: false } });
372-
const update: Partial<OrganizationSettings> = {
373-
defaultWorkspaceImage: settings.defaultWorkspaceImage,
374-
workspaceSharingDisabled: settings.workspaceSharingDisabled,
375-
};
376-
// Set to null if defaultWorkspaceImage is empty string, so that it can fallback to default image
377-
if (update.defaultWorkspaceImage?.trim() === "") {
378-
update.defaultWorkspaceImage = null;
379-
}
380372
if (!team) {
381-
await repo.insert({
382-
...update,
373+
return await repo.save({
374+
...settings,
383375
orgId,
384376
});
385-
} else {
386-
await repo.save({
387-
...team,
388-
...update,
389-
});
390377
}
378+
return await repo.save({
379+
...team,
380+
...settings,
381+
});
391382
}
392383

393384
public async hasActiveSSO(organizationId: string): Promise<boolean> {

0 commit comments

Comments
 (0)