From 99eb514306e38239cbc2b222cdd3b647bc332b78 Mon Sep 17 00:00:00 2001 From: Wahyu Kurniawan Date: Wed, 28 Feb 2024 21:16:26 +0700 Subject: [PATCH 1/8] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20restructur?= =?UTF-8?q?ed=20and=20restryling=20repository=20list=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{ => RepositoryList}/RepositoryList.tsx | 92 +++++++++++-------- .../projects/create/RepositoryList/index.ts | 1 + .../pages/org-slug/projects/create/index.tsx | 8 +- 3 files changed, 61 insertions(+), 40 deletions(-) rename packages/frontend/src/components/projects/create/{ => RepositoryList}/RepositoryList.tsx (59%) create mode 100644 packages/frontend/src/components/projects/create/RepositoryList/index.ts diff --git a/packages/frontend/src/components/projects/create/RepositoryList.tsx b/packages/frontend/src/components/projects/create/RepositoryList/RepositoryList.tsx similarity index 59% rename from packages/frontend/src/components/projects/create/RepositoryList.tsx rename to packages/frontend/src/components/projects/create/RepositoryList/RepositoryList.tsx index f09e61d6..171082ed 100644 --- a/packages/frontend/src/components/projects/create/RepositoryList.tsx +++ b/packages/frontend/src/components/projects/create/RepositoryList/RepositoryList.tsx @@ -3,13 +3,17 @@ import { Octokit } from 'octokit'; import assert from 'assert'; import { useDebounce } from 'usehooks-ts'; -import { Button, Typography, Option } from '@material-tailwind/react'; +import { Button, Typography } from '@material-tailwind/react'; -import SearchBar from '../../SearchBar'; -import ProjectRepoCard from './ProjectRepoCard'; -import { GitOrgDetails, GitRepositoryDetails } from '../../../types'; -import AsyncSelect from '../../shared/AsyncSelect'; -import { GithubIcon } from 'components/shared/CustomIcon'; +import { ProjectRepoCard } from 'components/projects/create/ProjectRepoCard'; +import { GitOrgDetails, GitRepositoryDetails } from 'types'; +import { + ChevronGrabberHorizontal, + GithubIcon, + SearchIcon, +} from 'components/shared/CustomIcon'; +import { Select, SelectOption } from 'components/shared/Select'; +import { Input } from 'components/shared/Input'; const DEFAULT_SEARCHED_REPO = ''; const REPOS_PER_PAGE = 5; @@ -18,9 +22,9 @@ interface RepositoryListProps { octokit: Octokit; } -const RepositoryList = ({ octokit }: RepositoryListProps) => { +export const RepositoryList = ({ octokit }: RepositoryListProps) => { const [searchedRepo, setSearchedRepo] = useState(DEFAULT_SEARCHED_REPO); - const [selectedAccount, setSelectedAccount] = useState(''); + const [selectedAccount, setSelectedAccount] = useState(); const [orgs, setOrgs] = useState([]); // TODO: Add new type for Git user when required const [gitUser, setGitUser] = useState(); @@ -35,7 +39,7 @@ const RepositoryList = ({ octokit }: RepositoryListProps) => { const orgs = await octokit.rest.orgs.listForAuthenticatedUser(); setOrgs(orgs.data); setGitUser(user.data); - setSelectedAccount(user.data.login); + setSelectedAccount({ label: user.data.login, value: user.data.login }); }; fetchUserAndOrgs(); @@ -54,7 +58,7 @@ const RepositoryList = ({ octokit }: RepositoryListProps) => { let query = `${debouncedSearchedRepo} in:name fork:true`; // Check if selected account is an organization - if (selectedAccount === gitUser.login) { + if (selectedAccount.value === gitUser.login) { query = query + ` user:${selectedAccount}`; } else { query = query + ` org:${selectedAccount}`; @@ -69,7 +73,7 @@ const RepositoryList = ({ octokit }: RepositoryListProps) => { return; } - if (selectedAccount === gitUser.login) { + if (selectedAccount.value === gitUser.login) { const result = await octokit.rest.repos.listForAuthenticatedUser({ per_page: REPOS_PER_PAGE, affiliation: 'owner', @@ -78,7 +82,9 @@ const RepositoryList = ({ octokit }: RepositoryListProps) => { return; } - const selectedOrg = orgs.find((org) => org.login === selectedAccount); + const selectedOrg = orgs.find( + (org) => org.login === selectedAccount.value, + ); assert(selectedOrg, 'Selected org not found in list'); const result = await octokit.rest.repos.listForOrg({ @@ -96,7 +102,7 @@ const RepositoryList = ({ octokit }: RepositoryListProps) => { const handleResetFilters = useCallback(() => { assert(gitUser, 'Git user is not available'); setSearchedRepo(DEFAULT_SEARCHED_REPO); - setSelectedAccount(gitUser.login); + setSelectedAccount({ label: gitUser.login, value: gitUser.login }); }, [gitUser]); const accounts = useMemo(() => { @@ -107,35 +113,51 @@ const RepositoryList = ({ octokit }: RepositoryListProps) => { return [gitUser, ...orgs]; }, [octokit, orgs, gitUser]); + const options = useMemo(() => { + return accounts.map((account) => ({ + label: account.login, + value: account.login, + leftIcon: , + })); + }, [accounts]); + return ( -
-
-
- + {/* Dropdown and search */} +
+
+ setSearchedRepo(event.target.value)} placeholder="Search for repository" + leftIcon={} + onChange={(e) => setSearchedRepo(e.target.value)} />
+ + {/* Repository list */} {Boolean(repositoryDetails.length) ? ( - repositoryDetails.map((repo, key) => { - return ; - }) +
+ {repositoryDetails.map((repo, index) => ( + <> + + {/* Horizontal line */} + {index !== repositoryDetails.length - 1 && ( +
+ )} + + ))} +
) : (
@@ -151,8 +173,6 @@ const RepositoryList = ({ octokit }: RepositoryListProps) => {
)} -
+ ); }; - -export default RepositoryList; diff --git a/packages/frontend/src/components/projects/create/RepositoryList/index.ts b/packages/frontend/src/components/projects/create/RepositoryList/index.ts new file mode 100644 index 00000000..dc3bc8c5 --- /dev/null +++ b/packages/frontend/src/components/projects/create/RepositoryList/index.ts @@ -0,0 +1 @@ +export * from './RepositoryList'; 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 1c86ee3b..49eeed96 100644 --- a/packages/frontend/src/pages/org-slug/projects/create/index.tsx +++ b/packages/frontend/src/pages/org-slug/projects/create/index.tsx @@ -1,7 +1,7 @@ import React from 'react'; import templates from 'assets/templates'; -import RepositoryList from 'components/projects/create/RepositoryList'; +import { RepositoryList } from 'components/projects/create/RepositoryList'; import ConnectAccount from 'components/projects/create/ConnectAccount'; import { useOctokit } from 'context/OctokitContext'; import { Heading } from 'components/shared/Heading'; @@ -13,8 +13,8 @@ const NewProject = () => { return isAuth ? ( <>
- - Start with template + + Start with a template
{templates.map((template) => { @@ -28,7 +28,7 @@ const NewProject = () => { })}
- + Import a repository From eda2cc76edad4b94d83f26c0e38fe1dbc73cba57 Mon Sep 17 00:00:00 2001 From: Wahyu Kurniawan Date: Wed, 28 Feb 2024 21:16:59 +0700 Subject: [PATCH 2/8] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20restructur?= =?UTF-8?q?ed=20and=20restyling=20project=20repo=20card=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../projects/create/ProjectRepoCard.tsx | 81 ---------------- .../ProjectRepoCard/ProjectRepoCard.tsx | 94 +++++++++++++++++++ .../projects/create/ProjectRepoCard/index.ts | 1 + 3 files changed, 95 insertions(+), 81 deletions(-) delete mode 100644 packages/frontend/src/components/projects/create/ProjectRepoCard.tsx create mode 100644 packages/frontend/src/components/projects/create/ProjectRepoCard/ProjectRepoCard.tsx create mode 100644 packages/frontend/src/components/projects/create/ProjectRepoCard/index.ts diff --git a/packages/frontend/src/components/projects/create/ProjectRepoCard.tsx b/packages/frontend/src/components/projects/create/ProjectRepoCard.tsx deleted file mode 100644 index fbcf50b4..00000000 --- a/packages/frontend/src/components/projects/create/ProjectRepoCard.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import React, { useCallback } from 'react'; -import toast from 'react-hot-toast'; -import { useNavigate, useParams } from 'react-router-dom'; - -import { Chip, IconButton, Spinner } from '@material-tailwind/react'; - -import { relativeTimeISO } from '../../../utils/time'; -import { GitRepositoryDetails } from '../../../types'; -import { useGQLClient } from '../../../context/GQLClientContext'; -import { GithubIcon, LockIcon } from 'components/shared/CustomIcon'; - -interface ProjectRepoCardProps { - repository: GitRepositoryDetails; -} - -const ProjectRepoCard: React.FC = ({ repository }) => { - const client = useGQLClient(); - const navigate = useNavigate(); - const [isLoading, setIsLoading] = React.useState(false); - - const { orgSlug } = useParams(); - - const createProject = useCallback(async () => { - if (!repository) { - return; - } - - setIsLoading(true); - const { addProject } = await client.addProject(orgSlug!, { - name: `${repository.owner!.login}-${repository.name}`, - prodBranch: repository.default_branch!, - repository: repository.full_name, - // TODO: Compute template from repo - template: 'webapp', - }); - - if (Boolean(addProject)) { - setIsLoading(false); - navigate(`import?projectId=${addProject.id}`); - } else { - setIsLoading(false); - toast.error('Failed to create project'); - } - }, [client, repository]); - - return ( -
-
- -
-
-
- {repository.full_name} - {repository.visibility === 'private' && ( - } - /> - )} -
-

{repository.updated_at && relativeTimeISO(repository.updated_at)}

-
- {isLoading ? ( - - ) : ( -
- - {'>'} - -
- )} -
- ); -}; - -export default ProjectRepoCard; diff --git a/packages/frontend/src/components/projects/create/ProjectRepoCard/ProjectRepoCard.tsx b/packages/frontend/src/components/projects/create/ProjectRepoCard/ProjectRepoCard.tsx new file mode 100644 index 00000000..6c8363ef --- /dev/null +++ b/packages/frontend/src/components/projects/create/ProjectRepoCard/ProjectRepoCard.tsx @@ -0,0 +1,94 @@ +import React, { useCallback } from 'react'; +import toast from 'react-hot-toast'; +import { useNavigate, useParams } from 'react-router-dom'; + +import { Spinner } from '@material-tailwind/react'; + +import { relativeTimeISO } from 'utils/time'; +import { GitRepositoryDetails } from 'types'; +import { useGQLClient } from 'context/GQLClientContext'; +import { + ArrowRightCircleIcon, + GithubIcon, + LockIcon, +} from 'components/shared/CustomIcon'; +import { Button } from 'components/shared/Button'; + +interface ProjectRepoCardProps { + repository: GitRepositoryDetails; +} + +export const ProjectRepoCard: React.FC = ({ + repository, +}) => { + const client = useGQLClient(); + const navigate = useNavigate(); + const [isLoading, setIsLoading] = React.useState(false); + + const { orgSlug } = useParams(); + + const createProject = useCallback(async () => { + if (!repository) { + return; + } + + setIsLoading(true); + const { addProject } = await client.addProject(orgSlug!, { + name: `${repository.owner!.login}-${repository.name}`, + prodBranch: repository.default_branch!, + repository: repository.full_name, + // TODO: Compute template from repo + template: 'webapp', + }); + + if (Boolean(addProject)) { + setIsLoading(false); + navigate(`import?projectId=${addProject.id}`); + } else { + setIsLoading(false); + toast.error('Failed to create project'); + } + }, [client, repository]); + + return ( +
+ {/* Icon container */} +
+ +
+ {/* Content */} +
+
+

+ {repository.full_name} +

+

+ {repository.updated_at && relativeTimeISO(repository.updated_at)} +

+
+ {repository.visibility === 'private' && ( +
+ + Private +
+ )} +
+ {/* Right action */} + {isLoading ? ( + + ) : ( + + )} +
+ ); +}; diff --git a/packages/frontend/src/components/projects/create/ProjectRepoCard/index.ts b/packages/frontend/src/components/projects/create/ProjectRepoCard/index.ts new file mode 100644 index 00000000..78472497 --- /dev/null +++ b/packages/frontend/src/components/projects/create/ProjectRepoCard/index.ts @@ -0,0 +1 @@ +export * from './ProjectRepoCard'; From 769593913e22b2ea6ac71d50a67f6f6bdf6ef60f Mon Sep 17 00:00:00 2001 From: Wahyu Kurniawan Date: Wed, 28 Feb 2024 21:17:30 +0700 Subject: [PATCH 3/8] =?UTF-8?q?=F0=9F=90=9B=20fix:=20button=20inside=20but?= =?UTF-8?q?ton=20console=20browser=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../projects/create/TemplateCard/TemplateCard.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/components/projects/create/TemplateCard/TemplateCard.tsx b/packages/frontend/src/components/projects/create/TemplateCard/TemplateCard.tsx index b7c549fd..b26ff856 100644 --- a/packages/frontend/src/components/projects/create/TemplateCard/TemplateCard.tsx +++ b/packages/frontend/src/components/projects/create/TemplateCard/TemplateCard.tsx @@ -49,9 +49,9 @@ export const TemplateCard = ({ template, isGitAuth }: TemplateCardProps) => { }, [isGitAuth, navigate, template, toast]); return ( - )} - +
); }; From eb4ccfbc9cb4a7cef1c5522b28d3e8ba1ac834e7 Mon Sep 17 00:00:00 2001 From: Wahyu Kurniawan Date: Wed, 28 Feb 2024 21:17:59 +0700 Subject: [PATCH 4/8] =?UTF-8?q?=F0=9F=8E=A8=20style:=20make=20the=20input?= =?UTF-8?q?=20width=20full?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/components/shared/Input/Input.theme.ts | 4 +++- packages/frontend/src/components/shared/Input/Input.tsx | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/components/shared/Input/Input.theme.ts b/packages/frontend/src/components/shared/Input/Input.theme.ts index b1ecb705..0144d578 100644 --- a/packages/frontend/src/components/shared/Input/Input.theme.ts +++ b/packages/frontend/src/components/shared/Input/Input.theme.ts @@ -8,6 +8,8 @@ export const inputTheme = tv( 'items-center', 'rounded-lg', 'relative', + 'gap-2', + 'w-full', 'placeholder:text-elements-disabled', 'disabled:cursor-not-allowed', 'disabled:bg-controls-disabled', @@ -27,7 +29,7 @@ export const inputTheme = tv( 'disabled:shadow-none', 'disabled:border-none', ], - icon: ['text-elements-mid-em'], + icon: ['text-elements-low-em'], iconContainer: [ 'absolute', 'inset-y-0', diff --git a/packages/frontend/src/components/shared/Input/Input.tsx b/packages/frontend/src/components/shared/Input/Input.tsx index fb3fd7d6..dd88bd80 100644 --- a/packages/frontend/src/components/shared/Input/Input.tsx +++ b/packages/frontend/src/components/shared/Input/Input.tsx @@ -87,12 +87,12 @@ export const Input = ({ ); return ( -
+
{renderLabels}
{leftIcon && renderLeftIcon} Date: Wed, 28 Feb 2024 21:18:29 +0700 Subject: [PATCH 5/8] =?UTF-8?q?=F0=9F=90=9B=20fix:=20controlled=20and=20un?= =?UTF-8?q?controller=20console=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/shared/Select/Select.theme.ts | 4 +-- .../src/components/shared/Select/Select.tsx | 34 +++++-------------- 2 files changed, 11 insertions(+), 27 deletions(-) diff --git a/packages/frontend/src/components/shared/Select/Select.theme.ts b/packages/frontend/src/components/shared/Select/Select.theme.ts index 43d4b0f4..fed6531e 100644 --- a/packages/frontend/src/components/shared/Select/Select.theme.ts +++ b/packages/frontend/src/components/shared/Select/Select.theme.ts @@ -85,7 +85,7 @@ export const selectTheme = tv({ size: { md: { container: ['min-h-11'], - inputWrapper: ['min-h-11', 'text-sm', 'pl-4', 'pr-4', 'py-1'], + inputWrapper: ['min-h-11', 'text-sm', 'pl-4', 'pr-4'], icon: ['h-[18px]', 'w-[18px]'], helperText: 'text-sm', helperIcon: ['h-5', 'w-5'], @@ -93,7 +93,7 @@ export const selectTheme = tv({ }, sm: { container: ['min-h-8'], - inputWrapper: ['min-h-8', 'text-xs', 'pl-3', 'pr-3', 'py-0.5'], + inputWrapper: ['min-h-8', 'text-xs', 'pl-3', 'pr-3'], icon: ['h-4', 'w-4'], helperText: 'text-xs', helperIcon: ['h-4', 'w-4'], diff --git a/packages/frontend/src/components/shared/Select/Select.tsx b/packages/frontend/src/components/shared/Select/Select.tsx index 963cc0bb..8c7e9149 100644 --- a/packages/frontend/src/components/shared/Select/Select.tsx +++ b/packages/frontend/src/components/shared/Select/Select.tsx @@ -3,7 +3,6 @@ import React, { useState, ComponentPropsWithoutRef, useMemo, - useCallback, MouseEvent, useRef, useEffect, @@ -135,7 +134,9 @@ export const Select = ({ const theme = selectTheme({ size, error, variant, orientation }); const [inputValue, setInputValue] = useState(''); - const [selectedItem, setSelectedItem] = useState(null); + const [selectedItem, setSelectedItem] = useState( + (value as SelectOption) || null, + ); const [dropdownOpen, setDropdownOpen] = useState(false); const [dropdownPosition, setDropdownPosition] = useState<'top' | 'bottom'>( 'bottom', @@ -166,22 +167,6 @@ export const Select = ({ } }, [dropdownOpen]); // Re-calculate whenever the dropdown is opened - useEffect(() => { - // If multiple selection is enabled, ensure the internal state is an array - if (multiple) { - if (Array.isArray(value)) { - // Directly use the provided array - setSelectedItems(value); - } else { - // Reset or set to empty array if the value is not an array - setSelectedItems([]); - } - } else { - // For single selection, directly set the selected item - setSelectedItem(value as SelectOption); - } - }, [value, multiple]); - const handleSelectedItemChange = (selectedItem: SelectOption | null) => { setSelectedItem(selectedItem); setInputValue(selectedItem ? selectedItem.label : ''); @@ -194,9 +179,10 @@ export const Select = ({ addSelectedItem, removeSelectedItem, selectedItems, - setSelectedItems, + // setSelectedItems, reset, } = useMultipleSelection({ + selectedItems: multiple ? (value as SelectOption[]) : [], onSelectedItemsChange: multiple ? undefined : ({ selectedItems }) => { @@ -234,6 +220,7 @@ export const Select = ({ openMenu, } = useCombobox({ items: filteredItems, + selectedItem: multiple ? null : (value as SelectOption) || null, // @ts-expect-error – there are two params but we don't need the second one isItemDisabled: (item) => item.disabled, onInputValueChange: ({ inputValue = '' }) => setInputValue(inputValue), @@ -265,16 +252,12 @@ export const Select = ({ setInputValue(''); } }, - selectedItem: multiple ? null : selectedItem, // TODO: Make the input value empty when the dropdown is open, has a value, it is not multiple, and searchable itemToString: (item) => (item && !multiple ? item.label : ''), }); - const isSelected = useCallback( - (item: SelectOption) => - multiple ? selectedItems.includes(item) : selectedItem === item, - [selectedItems, selectedItem, multiple], - ); + const isSelected = (item: SelectOption) => + multiple ? selectedItems.includes(item) : selectedItem === item; const handleClear = (e: MouseEvent) => { e.stopPropagation(); @@ -336,6 +319,7 @@ export const Select = ({ const isMultipleHasValue = multiple && selectedItems.length > 0; const isMultipleHasValueButNotSearchable = multiple && !searchable && selectedItems.length > 0; + const displayPlaceholder = useMemo(() => { if (hideValues && isMultipleHasValue) { return `${selectedItems.length} selected`; From 075cec58e5d039ef4c3dd5c7feb6349df43dd715 Mon Sep 17 00:00:00 2001 From: Wahyu Kurniawan Date: Wed, 28 Feb 2024 21:27:04 +0700 Subject: [PATCH 6/8] =?UTF-8?q?=F0=9F=8E=A8=20style:=20add=20github=20icon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../projects/create/RepositoryList/RepositoryList.tsx | 1 + packages/frontend/src/components/shared/Select/Select.tsx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/frontend/src/components/projects/create/RepositoryList/RepositoryList.tsx b/packages/frontend/src/components/projects/create/RepositoryList/RepositoryList.tsx index 171082ed..14af57e6 100644 --- a/packages/frontend/src/components/projects/create/RepositoryList/RepositoryList.tsx +++ b/packages/frontend/src/components/projects/create/RepositoryList/RepositoryList.tsx @@ -130,6 +130,7 @@ export const RepositoryList = ({ octokit }: RepositoryListProps) => { options={options} placeholder="Select a repository" value={selectedAccount} + leftIcon={selectedAccount ? : undefined} rightIcon={} onChange={(value) => setSelectedAccount(value as SelectOption)} /> diff --git a/packages/frontend/src/components/shared/Select/Select.tsx b/packages/frontend/src/components/shared/Select/Select.tsx index 8c7e9149..0e82edcc 100644 --- a/packages/frontend/src/components/shared/Select/Select.tsx +++ b/packages/frontend/src/components/shared/Select/Select.tsx @@ -375,6 +375,8 @@ export const Select = ({ 'w-6': isMultipleHasValueButNotSearchable && !hideValues, // Add margin to the X icon 'ml-6': isMultipleHasValueButNotSearchable && clearable, + // Add padding if there's a left icon + 'pl-7': leftIcon, }, )} /> From f08081932c9b298a96fff00057b27fba4539e2bd Mon Sep 17 00:00:00 2001 From: Wahyu Kurniawan Date: Thu, 29 Feb 2024 09:21:28 +0700 Subject: [PATCH 7/8] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20use=20cust?= =?UTF-8?q?om=20toast=20component=20and=20handle=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectRepoCard/ProjectRepoCard.tsx | 60 ++++++++++++------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/packages/frontend/src/components/projects/create/ProjectRepoCard/ProjectRepoCard.tsx b/packages/frontend/src/components/projects/create/ProjectRepoCard/ProjectRepoCard.tsx index 6c8363ef..b06fc233 100644 --- a/packages/frontend/src/components/projects/create/ProjectRepoCard/ProjectRepoCard.tsx +++ b/packages/frontend/src/components/projects/create/ProjectRepoCard/ProjectRepoCard.tsx @@ -1,5 +1,4 @@ -import React, { useCallback } from 'react'; -import toast from 'react-hot-toast'; +import React, { useCallback, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { Spinner } from '@material-tailwind/react'; @@ -13,6 +12,7 @@ import { LockIcon, } from 'components/shared/CustomIcon'; import { Button } from 'components/shared/Button'; +import { useToast } from 'components/shared/Toast'; interface ProjectRepoCardProps { repository: GitRepositoryDetails; @@ -23,32 +23,52 @@ export const ProjectRepoCard: React.FC = ({ }) => { const client = useGQLClient(); const navigate = useNavigate(); - const [isLoading, setIsLoading] = React.useState(false); + const [isLoading, setIsLoading] = useState(false); const { orgSlug } = useParams(); + const { toast, dismiss } = useToast(); const createProject = useCallback(async () => { - if (!repository) { - return; + if (!repository || !orgSlug) { + return toast({ + id: 'missing-repository-or-org-slug', + title: 'Repository or organization slug is missing', + variant: 'error', + onDismiss: dismiss, + }); } - setIsLoading(true); - const { addProject } = await client.addProject(orgSlug!, { - name: `${repository.owner!.login}-${repository.name}`, - prodBranch: repository.default_branch!, - repository: repository.full_name, - // TODO: Compute template from repo - template: 'webapp', - }); - - if (Boolean(addProject)) { + try { + setIsLoading(true); + const { addProject } = await client.addProject(orgSlug, { + name: `${repository.owner?.login}-${repository.name}`, + prodBranch: repository.default_branch as string, + repository: repository.full_name, + // TODO: Compute template from repo + template: 'webapp', + }); + if (addProject) { + navigate(`import?projectId=${addProject.id}`); + } else { + toast({ + id: 'failed-to-create-project', + title: 'Failed to create project', + variant: 'error', + onDismiss: dismiss, + }); + } + } catch (error) { + console.error(error); + toast({ + id: 'failed-to-create-project', + title: 'Failed to create project', + variant: 'error', + onDismiss: dismiss, + }); + } finally { setIsLoading(false); - navigate(`import?projectId=${addProject.id}`); - } else { - setIsLoading(false); - toast.error('Failed to create project'); } - }, [client, repository]); + }, [client, repository, orgSlug, setIsLoading, navigate, toast]); return (
Date: Thu, 29 Feb 2024 09:21:49 +0700 Subject: [PATCH 8/8] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20remove=20u?= =?UTF-8?q?nused=20comment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/components/shared/Select/Select.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/frontend/src/components/shared/Select/Select.tsx b/packages/frontend/src/components/shared/Select/Select.tsx index 0e82edcc..fa22428c 100644 --- a/packages/frontend/src/components/shared/Select/Select.tsx +++ b/packages/frontend/src/components/shared/Select/Select.tsx @@ -179,7 +179,6 @@ export const Select = ({ addSelectedItem, removeSelectedItem, selectedItems, - // setSelectedItems, reset, } = useMultipleSelection({ selectedItems: multiple ? (value as SelectOption[]) : [],