From 1c03bb268576809c99186092bdf8cafed67566e4 Mon Sep 17 00:00:00 2001 From: Milan Pavlik Date: Tue, 25 Oct 2022 09:33:20 +0000 Subject: [PATCH] [dashboard Use public-api to CreateTeams --- components/dashboard/BUILD.yaml | 1 + components/dashboard/package.json | 2 + .../src/contexts/FeatureFlagContext.tsx | 11 ++++- .../dashboard/src/projects/NewProject.tsx | 27 ++++++++++++ .../dashboard/src/service/public-api.ts | 43 +++++++++++++++++++ components/dashboard/src/teams/NewTeam.tsx | 20 +++++++++ 6 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 components/dashboard/src/service/public-api.ts diff --git a/components/dashboard/BUILD.yaml b/components/dashboard/BUILD.yaml index 2c3762970d59fb..1b0d88fabc8bf5 100644 --- a/components/dashboard/BUILD.yaml +++ b/components/dashboard/BUILD.yaml @@ -17,6 +17,7 @@ packages: - scripts/run-integration-tests.sh deps: - components/gitpod-protocol:lib + - components/public-api/typescript:lib config: commands: build: ["yarn", "build"] diff --git a/components/dashboard/package.json b/components/dashboard/package.json index cc418bca03ce29..2bf36d0f7cc3f5 100644 --- a/components/dashboard/package.json +++ b/components/dashboard/package.json @@ -4,7 +4,9 @@ "version": "0.0.0", "private": true, "dependencies": { + "@bufbuild/connect-web": "^0.2.1", "@gitpod/gitpod-protocol": "0.1.5", + "@gitpod/public-api": "0.1.5", "@stripe/react-stripe-js": "^1.7.2", "@stripe/stripe-js": "^1.29.0", "configcat-js": "^6.0.0", diff --git a/components/dashboard/src/contexts/FeatureFlagContext.tsx b/components/dashboard/src/contexts/FeatureFlagContext.tsx index f6dc1acd4fade2..234590fe77cfb5 100644 --- a/components/dashboard/src/contexts/FeatureFlagContext.tsx +++ b/components/dashboard/src/contexts/FeatureFlagContext.tsx @@ -19,10 +19,12 @@ const FeatureFlagContext = createContext<{ showPersistentVolumeClaimUI: boolean; showUsageView: boolean; showUseLastSuccessfulPrebuild: boolean; + usePublicApiTeamsService: boolean; }>({ showPersistentVolumeClaimUI: false, showUsageView: false, showUseLastSuccessfulPrebuild: false, + usePublicApiTeamsService: false, }); const FeatureFlagContextProvider: React.FC = ({ children }) => { @@ -34,6 +36,7 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => { const [showPersistentVolumeClaimUI, setShowPersistentVolumeClaimUI] = useState(false); const [showUsageView, setShowUsageView] = useState(false); const [showUseLastSuccessfulPrebuild, setShowUseLastSuccessfulPrebuild] = useState(false); + const [usePublicApiTeamsService, setUsePublicApiTeamsService] = useState(false); useEffect(() => { if (!user) return; @@ -42,6 +45,7 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => { persistent_volume_claim: { defaultValue: true, setter: setShowPersistentVolumeClaimUI }, usage_view: { defaultValue: false, setter: setShowUsageView }, showUseLastSuccessfulPrebuild: { defaultValue: false, setter: setShowUseLastSuccessfulPrebuild }, + usePublicApiTeamsService: { defaultValue: false, setter: setUsePublicApiTeamsService }, }; for (const [flagName, config] of Object.entries(featureFlags)) { if (teams) { @@ -74,7 +78,12 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => { return ( {children} diff --git a/components/dashboard/src/projects/NewProject.tsx b/components/dashboard/src/projects/NewProject.tsx index cbe6fde5793ec1..f217d5ca01be42 100644 --- a/components/dashboard/src/projects/NewProject.tsx +++ b/components/dashboard/src/projects/NewProject.tsx @@ -21,6 +21,8 @@ import { trackEvent } from "../Analytics"; import exclamation from "../images/exclamation.svg"; import ErrorMessage from "../components/ErrorMessage"; import Spinner from "../icons/Spinner.svg"; +import { teamsService } from "../service/public-api"; +import { FeatureFlagContext } from "../contexts/FeatureFlagContext"; export default function NewProject() { const location = useLocation(); @@ -721,6 +723,7 @@ function GitProviders(props: { function NewTeam(props: { onSuccess: (team: Team) => void }) { const { setTeams } = useContext(TeamsContext); + const { usePublicApiTeamsService } = useContext(FeatureFlagContext); const [teamName, setTeamName] = useState(); const [error, setError] = useState(); @@ -729,6 +732,30 @@ function NewTeam(props: { onSuccess: (team: Team) => void }) { if (!teamName) { return; } + + if (usePublicApiTeamsService) { + try { + const response = await teamsService.createTeam({ + name: teamName, + }); + const team = response.team; + setTeams(await getGitpodService().server.getTeams()); + + const mappedTeam: Team = { + id: team?.id || "", + name: team?.name || "", + slug: team?.slug || "", + creationTime: "", + }; + props.onSuccess(mappedTeam); + return; + } catch (error) { + console.error(error); + setError(error?.message || "Failed to create new team!"); + return; + } + } + try { const team = await getGitpodService().server.createTeam(teamName); setTeams(await getGitpodService().server.getTeams()); diff --git a/components/dashboard/src/service/public-api.ts b/components/dashboard/src/service/public-api.ts new file mode 100644 index 00000000000000..4b185f71648b37 --- /dev/null +++ b/components/dashboard/src/service/public-api.ts @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2022 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License-AGPL.txt in the project root for license information. + */ + +import { createConnectTransport, createPromiseClient, Interceptor } from "@bufbuild/connect-web"; + +// Import service definition that you want to connect to. +import { TeamsService } from "@gitpod/public-api/lib/gitpod/experimental/v1/teams_connectweb"; +import { getGitpodService } from "./service"; + +let token: string | undefined; + +const authInterceptor: Interceptor = (next) => async (req) => { + if (!token) { + const newToken = await getGitpodService().server.generateNewGitpodToken({ + type: 1, + scopes: [ + "function:getGitpodTokenScopes", + "function:getWorkspace", + "function:getWorkspaces", + "function:createTeam", + "function:joinTeam", + "function:getTeamMembers", + "function:getGenericInvite", + "function:listenForWorkspaceInstanceUpdates", + "resource:default", + ], + }); + token = newToken; + } + + req.header.set("Authorization", `Bearer ${token}`); + return await next(req); +}; + +const transport = createConnectTransport({ + baseUrl: `${window.location.protocol}//api.${window.location.host}`, + interceptors: [authInterceptor], +}); + +export const teamsService = createPromiseClient(TeamsService, transport); diff --git a/components/dashboard/src/teams/NewTeam.tsx b/components/dashboard/src/teams/NewTeam.tsx index 136c3bc3e093a1..e8c92d7ef2e5c0 100644 --- a/components/dashboard/src/teams/NewTeam.tsx +++ b/components/dashboard/src/teams/NewTeam.tsx @@ -8,15 +8,35 @@ import { FormEvent, useContext, useEffect, useState } from "react"; import { useHistory } from "react-router-dom"; import { getGitpodService } from "../service/service"; import { TeamsContext } from "./teams-context"; +import { teamsService } from "../service/public-api"; +import { FeatureFlagContext } from "../contexts/FeatureFlagContext"; export default function () { const { setTeams } = useContext(TeamsContext); + const { usePublicApiTeamsService } = useContext(FeatureFlagContext); + const history = useHistory(); const [creationError, setCreationError] = useState(); let name = ""; const createTeam = async (event: FormEvent) => { event.preventDefault(); + + if (usePublicApiTeamsService) { + try { + const response = await teamsService.createTeam({ name }); + const team = response.team; + setTeams(await getGitpodService().server.getTeams()); + + history.push(`/t/${team!.slug}`); + return; + } catch (error) { + console.error(error); + setCreationError(error); + return; + } + } + try { const team = await getGitpodService().server.createTeam(name); const teams = await getGitpodService().server.getTeams();