From c3d1b4f3eb226f475a4bdaebfd156e85b0672c51 Mon Sep 17 00:00:00 2001 From: Nabarun Gogoi Date: Mon, 19 Feb 2024 16:55:07 +0530 Subject: [PATCH] Use branches from GitHub API in edit domain dialog (#74) * Use branches from GitHub API * Disable git branch input if repo not found * Disable git branch if branches is empty * Use async select for accounts dropdown * Log actual HTTP error in console --------- Co-authored-by: neeraj --- .../projects/create/RepositoryList.tsx | 8 ++--- .../projects/project/settings/DomainCard.tsx | 7 ++-- .../project/settings/EditDomainDialog.tsx | 15 ++++---- .../frontend/src/context/OctokitContext.tsx | 4 +-- .../pages/org-slug/projects/create/index.tsx | 2 +- .../pages/org-slug/projects/id/Overview.tsx | 4 --- .../org-slug/projects/id/settings/Domains.tsx | 34 +++++++++++++++++-- packages/frontend/src/types.ts | 9 ----- 8 files changed, 50 insertions(+), 33 deletions(-) diff --git a/packages/frontend/src/components/projects/create/RepositoryList.tsx b/packages/frontend/src/components/projects/create/RepositoryList.tsx index ad69e776..d0f360bb 100644 --- a/packages/frontend/src/components/projects/create/RepositoryList.tsx +++ b/packages/frontend/src/components/projects/create/RepositoryList.tsx @@ -3,11 +3,12 @@ import { Octokit } from 'octokit'; import assert from 'assert'; import { useDebounce } from 'usehooks-ts'; -import { Button, Typography, Option, Select } from '@material-tailwind/react'; +import { Button, Typography, Option } from '@material-tailwind/react'; import SearchBar from '../../SearchBar'; import ProjectRepoCard from './ProjectRepoCard'; import { GitOrgDetails, GitRepositoryDetails } from '../../../types'; +import AsyncSelect from '../../shared/AsyncSelect'; const DEFAULT_SEARCHED_REPO = ''; const REPOS_PER_PAGE = 5; @@ -109,8 +110,7 @@ const RepositoryList = ({ octokit }: RepositoryListProps) => {
- {/* TODO: Fix selection of Git user at start */} - +
Promise; } @@ -44,7 +43,7 @@ const DOMAIN_RECORD = { const DomainCard = ({ domains, domain, - repo, + branches, project, onUpdate, }: DomainCardProps) => { @@ -188,7 +187,7 @@ const DomainCard = ({ domains={domains} open={editDialogOpen} domain={domain} - repo={repo} + branches={branches} onUpdate={onUpdate} /> diff --git a/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx b/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx index 78e4aceb..b9d2866c 100644 --- a/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx +++ b/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx @@ -15,7 +15,6 @@ import { Option, } from '@material-tailwind/react'; -import { RepositoryDetails } from '../../../../types'; import { useGQLClient } from '../../../../context/GQLClientContext'; const DEFAULT_REDIRECT_OPTIONS = ['none']; @@ -25,7 +24,7 @@ interface EditDomainDialogProp { open: boolean; handleOpen: () => void; domain: Domain; - repo: RepositoryDetails; + branches: string[]; onUpdate: () => Promise; } @@ -40,7 +39,7 @@ const EditDomainDialog = ({ open, handleOpen, domain, - repo, + branches, onUpdate, }: EditDomainDialogProp) => { const client = useGQLClient(); @@ -120,7 +119,7 @@ const EditDomainDialog = ({ branch: domain.branch, redirectedTo: getRedirectUrl(domain), }); - }, [domain, repo]); + }, [domain]); return ( @@ -166,9 +165,13 @@ const EditDomainDialog = ({ repo.branch.includes(value), + validate: (value) => + Boolean(branches.length) ? branches.includes(value) : true, })} - disabled={watch('redirectedTo') !== DEFAULT_REDIRECT_OPTIONS[0]} + disabled={ + !Boolean(branches.length) || + watch('redirectedTo') !== DEFAULT_REDIRECT_OPTIONS[0] + } /> {!isValid && ( diff --git a/packages/frontend/src/context/OctokitContext.tsx b/packages/frontend/src/context/OctokitContext.tsx index 0eed37ce..21ffe246 100644 --- a/packages/frontend/src/context/OctokitContext.tsx +++ b/packages/frontend/src/context/OctokitContext.tsx @@ -14,13 +14,13 @@ import { useGQLClient } from './GQLClientContext'; const UNAUTHORIZED_ERROR_CODE = 401; interface ContextValue { - octokit: Octokit | null; + octokit: Octokit; isAuth: boolean; updateAuth: () => void; } const OctokitContext = createContext({ - octokit: null, + octokit: new Octokit(), isAuth: false, updateAuth: () => {}, }); diff --git a/packages/frontend/src/pages/org-slug/projects/create/index.tsx b/packages/frontend/src/pages/org-slug/projects/create/index.tsx index 8658d18c..a48f4dd4 100644 --- a/packages/frontend/src/pages/org-slug/projects/create/index.tsx +++ b/packages/frontend/src/pages/org-slug/projects/create/index.tsx @@ -24,7 +24,7 @@ const NewProject = () => { })}
Import a repository
- + ) : ( diff --git a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx index c5db5c34..a5f1ad73 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx @@ -24,10 +24,6 @@ const OverviewTabPanel = () => { const { project } = useOutletContext(); useEffect(() => { - if (!octokit) { - return; - } - // TODO: Save repo commits in DB and avoid using GitHub API in frontend // TODO: Figure out fetching latest commits for all branches const fetchRepoActivity = async () => { diff --git a/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx b/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx index f912e8fa..24457b1a 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx @@ -1,4 +1,5 @@ -import React, { useEffect, useState } from 'react'; +import { RequestError } from 'octokit'; +import React, { useCallback, useEffect, useState } from 'react'; import { Link, useOutletContext } from 'react-router-dom'; import { Domain } from 'gql-client'; @@ -6,14 +7,41 @@ import { Button, Typography } from '@material-tailwind/react'; import DomainCard from '../../../../../components/projects/project/settings/DomainCard'; import { useGQLClient } from '../../../../../context/GQLClientContext'; -import repositories from '../../../../../assets/repositories.json'; import { OutletContextType } from '../../../../../types'; +import { useOctokit } from '../../../../../context/OctokitContext'; const Domains = () => { const client = useGQLClient(); + const { octokit } = useOctokit(); const { project } = useOutletContext(); const [domains, setDomains] = useState([]); + const [branches, setBranches] = useState([]); + + const fetchBranches = useCallback(async () => { + const [owner, repo] = project.repository.split('/'); + + try { + const result = await octokit.rest.repos.listBranches({ + owner, + repo, + }); + + const branches = result.data.map((repo) => repo.name); + + setBranches(branches); + } catch (err) { + if (!(err instanceof RequestError && err.status === 404)) { + throw err; + } + + console.error(err); + } + }, []); + + useEffect(() => { + fetchBranches(); + }, []); const fetchDomains = async () => { if (project === undefined) { @@ -46,7 +74,7 @@ const Domains = () => { domain={domain} key={domain.id} // TODO: Use github API for getting linked repository - repo={repositories[0]!} + branches={branches} project={project} onUpdate={fetchDomains} /> diff --git a/packages/frontend/src/types.ts b/packages/frontend/src/types.ts index 1ece61d3..2ca22da6 100644 --- a/packages/frontend/src/types.ts +++ b/packages/frontend/src/types.ts @@ -6,15 +6,6 @@ export interface GitOrgDetails { avatar_url: string; } -// TODO: Use GitRepositoryDetails -export interface RepositoryDetails { - title: string; - updatedAt: string; - user: string; - private: boolean; - branch: string[]; -} - export interface GitRepositoryDetails { id: number; name: string;