Skip to content

Commit 2fd6864

Browse files
committed
[dashboard] List projects using Public API
1 parent 88cb2b1 commit 2fd6864

File tree

7 files changed

+146
-22
lines changed

7 files changed

+146
-22
lines changed

components/dashboard/src/Menu.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import FeedbackFormModal from "./feedback-form/FeedbackModal";
2727
import { inResource, isGitpodIo } from "./utils";
2828
import { BillingMode } from "@gitpod/gitpod-protocol/lib/billing-mode";
2929
import { FeatureFlagContext } from "./contexts/FeatureFlagContext";
30+
import { listAllProjects } from "./service/public-api";
3031

3132
interface Entry {
3233
title: string;
@@ -37,6 +38,7 @@ interface Entry {
3738
export default function Menu() {
3839
const { user } = useContext(UserContext);
3940
const { showUsageView } = useContext(FeatureFlagContext);
41+
const { usePublicApiProjectsService } = useContext(FeatureFlagContext);
4042
const { teams } = useContext(TeamsContext);
4143
const location = useLocation();
4244
const team = getCurrentTeam(location, teams);
@@ -143,9 +145,16 @@ export default function Menu() {
143145
return;
144146
}
145147
(async () => {
146-
const projects = !!team
147-
? await getGitpodService().server.getTeamProjects(team.id)
148-
: await getGitpodService().server.getUserProjects();
148+
let projects: Project[];
149+
if (!!team) {
150+
projects = usePublicApiProjectsService
151+
? await listAllProjects({ teamId: team.id })
152+
: await getGitpodService().server.getTeamProjects(team.id);
153+
} else {
154+
projects = usePublicApiProjectsService
155+
? await listAllProjects({ userId: user?.id })
156+
: await getGitpodService().server.getUserProjects();
157+
}
149158

150159
// Find project matching with slug, otherwise with name
151160
const project =

components/dashboard/src/projects/Events.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@ import Spinner from "../icons/Spinner.svg";
1717
import NoAccess from "../icons/NoAccess.svg";
1818
import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
1919
import { openAuthorizeWindow } from "../provider-utils";
20+
import { UserContext } from "../user-context";
21+
import { FeatureFlagContext } from "../contexts/FeatureFlagContext";
22+
import { listAllProjects } from "../service/public-api";
2023

2124
export default function () {
2225
const location = useLocation();
2326

2427
const { teams } = useContext(TeamsContext);
28+
const { user } = useContext(UserContext);
29+
const { usePublicApiProjectsService } = useContext(FeatureFlagContext);
2530
const team = getCurrentTeam(location, teams);
2631

2732
const match = useRouteMatch<{ team: string; resource: string }>("/(t/)?:team/:resource");
@@ -61,9 +66,16 @@ export default function () {
6166
if (!teams || !projectSlug) {
6267
return;
6368
}
64-
const projects = !!team
65-
? await getGitpodService().server.getTeamProjects(team.id)
66-
: await getGitpodService().server.getUserProjects();
69+
let projects: Project[];
70+
if (!!team) {
71+
projects = usePublicApiProjectsService
72+
? await listAllProjects({ teamId: team.id })
73+
: await getGitpodService().server.getTeamProjects(team.id);
74+
} else {
75+
projects = usePublicApiProjectsService
76+
? await listAllProjects({ userId: user?.id })
77+
: await getGitpodService().server.getUserProjects();
78+
}
6779

6880
// Find project matching with slug, otherwise with name
6981
const project = projectSlug && projects.find((p) => (p.slug ? p.slug === projectSlug : p.name === projectSlug));

components/dashboard/src/projects/Prebuild.tsx

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

77
import dayjs from "dayjs";
8-
import { PrebuildWithStatus } from "@gitpod/gitpod-protocol";
8+
import { PrebuildWithStatus, Project } from "@gitpod/gitpod-protocol";
99
import { useContext, useEffect, useState } from "react";
1010
import { useHistory, useLocation, useRouteMatch } from "react-router";
1111
import Header from "../components/Header";
@@ -14,12 +14,17 @@ import Spinner from "../icons/Spinner.svg";
1414
import { getGitpodService, gitpodHostUrl } from "../service/service";
1515
import { TeamsContext, getCurrentTeam } from "../teams/teams-context";
1616
import { shortCommitMessage } from "./render-utils";
17+
import { listAllProjects } from "../service/public-api";
18+
import { UserContext } from "../user-context";
19+
import { FeatureFlagContext } from "../contexts/FeatureFlagContext";
1720

1821
export default function () {
1922
const history = useHistory();
2023
const location = useLocation();
2124

2225
const { teams } = useContext(TeamsContext);
26+
const { user } = useContext(UserContext);
27+
const { usePublicApiProjectsService } = useContext(FeatureFlagContext);
2328
const team = getCurrentTeam(location, teams);
2429

2530
const match = useRouteMatch<{ team: string; project: string; prebuildId: string }>(
@@ -37,9 +42,16 @@ export default function () {
3742
return;
3843
}
3944
(async () => {
40-
const projects = !!team
41-
? await getGitpodService().server.getTeamProjects(team.id)
42-
: await getGitpodService().server.getUserProjects();
45+
let projects: Project[];
46+
if (!!team) {
47+
projects = usePublicApiProjectsService
48+
? await listAllProjects({ teamId: team.id })
49+
: await getGitpodService().server.getTeamProjects(team.id);
50+
} else {
51+
projects = usePublicApiProjectsService
52+
? await listAllProjects({ userId: user?.id })
53+
: await getGitpodService().server.getUserProjects();
54+
}
4355

4456
const project =
4557
projectSlug && projects.find((p) => (!!p.slug ? p.slug === projectSlug : p.name === projectSlug));

components/dashboard/src/projects/Prebuilds.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,16 @@ import { TeamsContext, getCurrentTeam } from "../teams/teams-context";
2222
import { shortCommitMessage } from "./render-utils";
2323
import { Link } from "react-router-dom";
2424
import { Disposable } from "vscode-jsonrpc";
25+
import { UserContext } from "../user-context";
26+
import { FeatureFlagContext } from "../contexts/FeatureFlagContext";
27+
import { listAllProjects } from "../service/public-api";
2528

2629
export default function (props: { project?: Project; isAdminDashboard?: boolean }) {
2730
const location = useLocation();
2831

2932
const { teams } = useContext(TeamsContext);
33+
const { user } = useContext(UserContext);
34+
const { usePublicApiProjectsService } = useContext(FeatureFlagContext);
3035
const team = getCurrentTeam(location, teams);
3136

3237
const match = useRouteMatch<{ team: string; resource: string }>("/(t/)?:team/:resource");
@@ -84,10 +89,16 @@ export default function (props: { project?: Project; isAdminDashboard?: boolean
8489
return;
8590
}
8691
(async () => {
87-
const projects = !!team
88-
? await getGitpodService().server.getTeamProjects(team.id)
89-
: await getGitpodService().server.getUserProjects();
90-
92+
let projects: Project[];
93+
if (!!team) {
94+
projects = usePublicApiProjectsService
95+
? await listAllProjects({ teamId: team.id })
96+
: await getGitpodService().server.getTeamProjects(team.id);
97+
} else {
98+
projects = usePublicApiProjectsService
99+
? await listAllProjects({ userId: user?.id })
100+
: await getGitpodService().server.getUserProjects();
101+
}
91102
const newProject =
92103
projectSlug && projects.find((p) => (p.slug ? p.slug === projectSlug : p.name === projectSlug));
93104

components/dashboard/src/projects/Project.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,17 @@ import NoAccess from "../icons/NoAccess.svg";
1919
import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
2020
import { openAuthorizeWindow } from "../provider-utils";
2121
import Alert from "../components/Alert";
22+
import { FeatureFlagContext } from "../contexts/FeatureFlagContext";
23+
import { listAllProjects } from "../service/public-api";
24+
import { UserContext } from "../user-context";
2225

2326
export default function () {
2427
const location = useLocation();
2528
const history = useHistory();
2629

2730
const { teams } = useContext(TeamsContext);
31+
const { user } = useContext(UserContext);
32+
const { usePublicApiProjectsService } = useContext(FeatureFlagContext);
2833
const team = getCurrentTeam(location, teams);
2934

3035
const match = useRouteMatch<{ team: string; resource: string }>("/(t/)?:team/:resource");
@@ -69,10 +74,16 @@ export default function () {
6974
if (!teams || !projectSlug) {
7075
return;
7176
}
72-
const projects = !!team
73-
? await getGitpodService().server.getTeamProjects(team.id)
74-
: await getGitpodService().server.getUserProjects();
75-
77+
let projects: Project[];
78+
if (!!team) {
79+
projects = usePublicApiProjectsService
80+
? await listAllProjects({ teamId: team.id })
81+
: await getGitpodService().server.getTeamProjects(team.id);
82+
} else {
83+
projects = usePublicApiProjectsService
84+
? await listAllProjects({ userId: user?.id })
85+
: await getGitpodService().server.getUserProjects();
86+
}
7687
// Find project matching with slug, otherwise with name
7788
const project = projectSlug && projects.find((p) => (p.slug ? p.slug === projectSlug : p.name === projectSlug));
7889

components/dashboard/src/projects/Projects.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,17 @@ import ContextMenu from "../components/ContextMenu";
2020
import ConfirmationModal from "../components/ConfirmationModal";
2121
import { prebuildStatusIcon } from "./Prebuilds";
2222
import Alert from "../components/Alert";
23+
import { FeatureFlagContext } from "../contexts/FeatureFlagContext";
24+
import { listAllProjects } from "../service/public-api";
25+
import { UserContext } from "../user-context";
2326

2427
export default function () {
2528
const location = useLocation();
2629
const history = useHistory();
2730

2831
const { teams } = useContext(TeamsContext);
32+
const { user } = useContext(UserContext);
33+
const { usePublicApiProjectsService } = useContext(FeatureFlagContext);
2934
const team = getCurrentTeam(location, teams);
3035
const [projects, setProjects] = useState<Project[]>([]);
3136
const [lastPrebuilds, setLastPrebuilds] = useState<Map<string, PrebuildWithStatus>>(new Map());
@@ -42,9 +47,17 @@ export default function () {
4247
if (!teams) {
4348
return;
4449
}
45-
const infos = !!team
46-
? await getGitpodService().server.getTeamProjects(team.id)
47-
: await getGitpodService().server.getUserProjects();
50+
51+
let infos: Project[];
52+
if (!!team) {
53+
infos = usePublicApiProjectsService
54+
? await listAllProjects({ teamId: team.id })
55+
: await getGitpodService().server.getTeamProjects(team.id);
56+
} else {
57+
infos = usePublicApiProjectsService
58+
? await listAllProjects({ userId: user?.id })
59+
: await getGitpodService().server.getUserProjects();
60+
}
4861
setProjects(infos);
4962

5063
const map = new Map();

components/dashboard/src/service/public-api.ts

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
*/
66

77
import { createConnectTransport, createPromiseClient } from "@bufbuild/connect-web";
8-
import { Team as ProtocolTeam } from "@gitpod/gitpod-protocol/lib/teams-projects-protocol";
8+
import { Project as ProtocolProject, Team as ProtocolTeam } from "@gitpod/gitpod-protocol/lib/teams-projects-protocol";
99
import { TeamsService } from "@gitpod/public-api/lib/gitpod/experimental/v1/teams_connectweb";
1010
import { TokensService } from "@gitpod/public-api/lib/gitpod/experimental/v1/tokens_connectweb";
11+
import { ProjectsService } from "@gitpod/public-api/lib/gitpod/experimental/v1/projects_connectweb";
1112
import { Team } from "@gitpod/public-api/lib/gitpod/experimental/v1/teams_pb";
1213
import { TeamMemberInfo, TeamMemberRole } from "@gitpod/gitpod-protocol";
1314
import { TeamMember, TeamRole } from "@gitpod/public-api/lib/gitpod/experimental/v1/teams_pb";
15+
import { Project } from "@gitpod/public-api/lib/gitpod/experimental/v1/projects_pb";
1416

1517
const transport = createConnectTransport({
1618
baseUrl: `${window.location.protocol}//api.${window.location.host}`,
@@ -19,6 +21,7 @@ const transport = createConnectTransport({
1921

2022
export const teamsService = createPromiseClient(TeamsService, transport);
2123
export const personalAccessTokensService = createPromiseClient(TokensService, transport);
24+
export const projectsService = createPromiseClient(ProjectsService, transport);
2225

2326
export function publicApiTeamToProtocol(team: Team): ProtocolTeam {
2427
return {
@@ -58,3 +61,56 @@ export function publicApiTeamRoleToProtocol(role: TeamRole): TeamMemberRole {
5861
return "member";
5962
}
6063
}
64+
65+
export async function listAllProjects(opts: { userId?: string; teamId?: string }): Promise<ProtocolProject[]> {
66+
let pagination = {
67+
page: 1,
68+
pageSize: 100,
69+
};
70+
71+
const response = await projectsService.listProjects({
72+
teamId: opts.teamId,
73+
userId: opts.userId,
74+
pagination,
75+
});
76+
const results = response.projects;
77+
78+
while (results.length < response.totalResults) {
79+
pagination = {
80+
pageSize: 100,
81+
page: 1 + pagination.page,
82+
};
83+
const response = await projectsService.listProjects({
84+
teamId: opts.teamId,
85+
userId: opts.userId,
86+
pagination,
87+
});
88+
results.push(...response.projects);
89+
}
90+
91+
return results.map(projectToProtocol);
92+
}
93+
94+
export function projectToProtocol(project: Project): ProtocolProject {
95+
return {
96+
id: project.id,
97+
name: project.name,
98+
cloneUrl: project.cloneUrl,
99+
creationTime: project.creationTime?.toDate().toISOString() || "",
100+
slug: project.slug,
101+
teamId: project.teamId,
102+
userId: project.userId,
103+
appInstallationId: "undefined",
104+
settings: {
105+
allowUsingPreviousPrebuilds: project.settings?.prebuild?.usePreviousPrebuilds,
106+
keepOutdatedPrebuildsRunning: project.settings?.prebuild?.keepOutdatedPrebuildsRunning,
107+
prebuildEveryNthCommit: project.settings?.prebuild?.prebuildEveryNth,
108+
useIncrementalPrebuilds: project.settings?.prebuild?.enableIncrementalPrebuilds,
109+
usePersistentVolumeClaim: project.settings?.workspace?.enablePersistentVolumeClaim,
110+
workspaceClasses: {
111+
prebuild: project.settings?.workspace?.workspaceClass?.prebuild || "",
112+
regular: project.settings?.workspace?.workspaceClass?.regular || "",
113+
},
114+
},
115+
};
116+
}

0 commit comments

Comments
 (0)