diff --git a/components/AddContributorsHeader/add-contributors-header.tsx b/components/AddContributorsHeader/add-contributors-header.tsx
deleted file mode 100644
index 14e07f35e..000000000
--- a/components/AddContributorsHeader/add-contributors-header.tsx
+++ /dev/null
@@ -1,101 +0,0 @@
-import { FaPlus } from "react-icons/fa";
-
-import clsx from "clsx";
-
-import { useEffect, useState } from "react";
-
-import Link from "next/link";
-import { MdOutlineArrowBackIos } from "react-icons/md";
-import Button from "components/shared/Button/button";
-import Search from "components/atoms/Search/search";
-import useDebounceTerm from "lib/hooks/useDebounceTerm";
-
-interface AddContributorsHeaderProps {
- selectedContributorsIds: number[];
- list: DbUserList;
- workspaceId?: string;
- onAddToList?: () => void;
- loading?: boolean;
- onSearch: (searchTerm: string | undefined) => void;
- searchSuggestions?: string[];
- onSearchSelect?: (username: string) => void;
-}
-
-const AddContributorsHeader = ({
- selectedContributorsIds,
- list,
- workspaceId,
- onAddToList,
- loading,
- onSearch,
- searchSuggestions,
- onSearchSelect,
-}: AddContributorsHeaderProps): JSX.Element => {
- const [contributorSearch, setContributorSearch] = useState("");
- const debouncedSearchTerm = useDebounceTerm(contributorSearch, 300);
-
- useEffect(() => {
- onSearch(debouncedSearchTerm);
- }, [debouncedSearchTerm]);
-
- return (
-
-
-
-
-
-
- {list.name}
-
-
-
-
0 ? "bg-sauced-orange text-white" : "bg-light-slate-5 text-slate-400"
- )}
- >
- {selectedContributorsIds.length}
-
-
- Contributors Selected
-
-
-
- Add to List
-
-
-
-
-
- Search for contributors to add to your list
- setContributorSearch(value)}
- suggestions={searchSuggestions}
- onSearch={onSearch}
- onSelect={onSearchSelect}
- />
-
-
-
- );
-};
-
-export default AddContributorsHeader;
diff --git a/components/Contributors/AddToContributorInsightDrawer.tsx b/components/Contributors/AddToContributorInsightDrawer.tsx
index 1acb2ccf9..b10b76cc9 100644
--- a/components/Contributors/AddToContributorInsightDrawer.tsx
+++ b/components/Contributors/AddToContributorInsightDrawer.tsx
@@ -135,6 +135,7 @@ export default function AddToContributorInsightDrawer({
})),
]}
value={selectedInsight ?? "new"}
+ labelText="Select a workspace"
placeholder="Select a workspace"
onValueChange={(value) => {
setSelectedInsight(value);
@@ -154,6 +155,7 @@ export default function AddToContributorInsightDrawer({
})),
]}
value={workspaceId}
+ labelText="Select a workspace"
placeholder="Select a workspace"
onValueChange={(value) => {
setWorkspaceId(value);
diff --git a/components/Contributors/AddToContributorInsightModal.tsx b/components/Contributors/AddToContributorInsightModal.tsx
index a5dc7d82e..7848cfe6a 100644
--- a/components/Contributors/AddToContributorInsightModal.tsx
+++ b/components/Contributors/AddToContributorInsightModal.tsx
@@ -136,6 +136,7 @@ export default function AddToContributorInsightModal({
})),
]}
value={selectedInsight ?? "new"}
+ labelText="Select a workspace"
placeholder="Select a workspace"
onValueChange={(value) => {
setSelectedInsight(value);
@@ -155,6 +156,7 @@ export default function AddToContributorInsightModal({
})),
]}
value={workspaceId}
+ labelText="Select a workspace"
placeholder="Select a workspace"
onValueChange={(value) => {
setWorkspaceId(value);
diff --git a/components/Repositories/AddToWorkspaceDrawer.tsx b/components/Repositories/AddToWorkspaceDrawer.tsx
index 0f212d6fd..930d6eb49 100644
--- a/components/Repositories/AddToWorkspaceDrawer.tsx
+++ b/components/Repositories/AddToWorkspaceDrawer.tsx
@@ -137,6 +137,7 @@ export default function AddToWorkspaceDrawer({ repository, type = "repo" }: AddT
]}
position="popper"
value={workspaceId ?? "new"}
+ labelText="Select a workspace"
placeholder="Select a workspace"
onValueChange={(value) => {
setWorkspaceId(value);
diff --git a/components/Repositories/AddToWorkspaceModal.tsx b/components/Repositories/AddToWorkspaceModal.tsx
index 7c7c2fe79..b880e4f9e 100644
--- a/components/Repositories/AddToWorkspaceModal.tsx
+++ b/components/Repositories/AddToWorkspaceModal.tsx
@@ -131,6 +131,7 @@ export default function AddToWorkspaceModal({ repository, isOpen, onCloseModal,
})),
]}
value={workspaceId ?? "new"}
+ labelText="Select a workspace"
placeholder="Select a workspace"
onValueChange={(value) => {
setWorkspaceId(value);
diff --git a/components/Workspaces/SearchReposTable.tsx b/components/Workspaces/SearchReposTable.tsx
index 340359745..6615e51b5 100644
--- a/components/Workspaces/SearchReposTable.tsx
+++ b/components/Workspaces/SearchReposTable.tsx
@@ -62,7 +62,13 @@ export const SearchedReposTable = ({
event.preventDefault;
}}
>
-
+
diff --git a/components/Workspaces/SearchedContributorsTable.tsx b/components/Workspaces/SearchedContributorsTable.tsx
index 7c4383a9e..ff66e78ad 100644
--- a/components/Workspaces/SearchedContributorsTable.tsx
+++ b/components/Workspaces/SearchedContributorsTable.tsx
@@ -43,7 +43,13 @@ export const SearchedContributorsTable = ({
event.preventDefault;
}}
>
-
+
diff --git a/components/Workspaces/TrackedContributorsWizard/SearchByContributorsStep.tsx b/components/Workspaces/TrackedContributorsWizard/SearchByContributorsStep.tsx
index c0cc614b4..193624ef0 100644
--- a/components/Workspaces/TrackedContributorsWizard/SearchByContributorsStep.tsx
+++ b/components/Workspaces/TrackedContributorsWizard/SearchByContributorsStep.tsx
@@ -81,6 +81,7 @@ export const SearchByContributorsStep = ({
>
{
diff --git a/components/Workspaces/WorkspaceMembersConfig/workspace-members-config.tsx b/components/Workspaces/WorkspaceMembersConfig/workspace-members-config.tsx
index 207a6ef86..65f2c9286 100644
--- a/components/Workspaces/WorkspaceMembersConfig/workspace-members-config.tsx
+++ b/components/Workspaces/WorkspaceMembersConfig/workspace-members-config.tsx
@@ -62,6 +62,7 @@ const WorkspaceMembersConfig = ({
value={username}
onChange={(value) => handleChange(value)}
placeholder="Enter username"
+ labelText="Enter full username"
name="search"
className="flex-1 text-base"
/>
diff --git a/components/atoms/Search/search.tsx b/components/atoms/Search/search.tsx
index b9d4fe922..8444ab62a 100644
--- a/components/atoms/Search/search.tsx
+++ b/components/atoms/Search/search.tsx
@@ -24,6 +24,7 @@ interface SearchProps {
onSelect?: (value: string) => void;
isLoading?: boolean;
isDisabled?: boolean;
+ labelText: string;
}
const suggestionsStyle = {
@@ -45,6 +46,7 @@ const Search = ({
isLoading,
onSelect,
isDisabled,
+ labelText,
}: SearchProps): JSX.Element => {
const [cursor, setCursor] = useState(-1);
const [search, setSearch] = useState(value);
@@ -111,11 +113,12 @@ const Search = ({
// using min-w-[15rem] to take into account the width of the X icon when it gets rendered
// to avoid the search input from expanding when someone starts typing.
return (
-
+ {labelText}
{
if (e.code === "Enter") {
@@ -176,7 +178,7 @@ const Search = ({
)}
>
)}
-
+
);
};
export default Search;
diff --git a/components/atoms/Select/single-select.tsx b/components/atoms/Select/single-select.tsx
index 1672ccdfe..f78c473c8 100644
--- a/components/atoms/Select/single-select.tsx
+++ b/components/atoms/Select/single-select.tsx
@@ -15,6 +15,7 @@ interface SingleSelectProps {
position?: "popper" | "item-aligned";
isSearchable?: boolean;
insetLabel?: string;
+ labelText: string;
}
const SingleSelect = ({
@@ -26,6 +27,7 @@ const SingleSelect = ({
inputPlaceholder,
isSearchable = false,
insetLabel,
+ labelText,
}: SingleSelectProps) => {
const inputRef = useRef(null);
const [inputValue, setInputValue] = useState("");
@@ -64,8 +66,9 @@ const SingleSelect = ({
insetLabel && `before:content-[attr(data-inset-label)] before:mr-1 before:font-normal before:text-slate-500`
)}
>
-
-
+
{labelText}
+
+
{current?.label ?? placeholder}
diff --git a/components/atoms/Select/single.select.stories.tsx b/components/atoms/Select/single.select.stories.tsx
index e6a207286..c32ef320d 100644
--- a/components/atoms/Select/single.select.stories.tsx
+++ b/components/atoms/Select/single.select.stories.tsx
@@ -38,6 +38,7 @@ const baseProps: ComponentProps
= {
// eslint-disable-next-line no-console
console.log(value);
},
+ labelText: "Accessible label",
};
export const Default: Story = {
diff --git a/components/molecules/ContributorHighlight/contributor-highlight-card.tsx b/components/molecules/ContributorHighlight/contributor-highlight-card.tsx
index bc62c3797..a1aa47fa6 100644
--- a/components/molecules/ContributorHighlight/contributor-highlight-card.tsx
+++ b/components/molecules/ContributorHighlight/contributor-highlight-card.tsx
@@ -794,6 +794,7 @@ const ContributorHighlightCard = ({
setContributorSearch(value)}
diff --git a/components/molecules/TableHeader/table-header.tsx b/components/molecules/TableHeader/table-header.tsx
index f440cd7b2..e0b59a92b 100644
--- a/components/molecules/TableHeader/table-header.tsx
+++ b/components/molecules/TableHeader/table-header.tsx
@@ -88,6 +88,7 @@ const TableHeader = ({ title, metaInfo, entity, onSearch, layout, onLayoutToggle
{onSearch ? (
handleChange(value)}
placeholder="Enter email address"
+ labelText="Enter email address"
name="search"
className="flex-1 text-base"
/>
diff --git a/components/organisms/InsightPage/InsightPage.tsx b/components/organisms/InsightPage/InsightPage.tsx
deleted file mode 100644
index 5d9ab874d..000000000
--- a/components/organisms/InsightPage/InsightPage.tsx
+++ /dev/null
@@ -1,723 +0,0 @@
-import { useEffect, useState } from "react";
-import { useRouter } from "next/router";
-import dynamic from "next/dynamic";
-
-import { useDebounce } from "rooks";
-import Button from "components/shared/Button/button";
-import TextInput from "components/atoms/TextInput/text-input";
-import Text from "components/atoms/Typography/text";
-import Title from "components/atoms/Typography/title";
-import RepositoriesCart from "components/organisms/RepositoriesCart/repositories-cart";
-import RepositoryCartItem from "components/molecules/ReposoitoryCartItem/repository-cart-item";
-import RepoNotIndexed from "components/organisms/Repositories/repository-not-indexed";
-import useRepositories from "lib/hooks/api/useRepositories";
-
-import useSupabaseAuth from "lib/hooks/useSupabaseAuth";
-import { generateRepoParts, getAvatarByUsername } from "lib/utils/github";
-import Error from "components/atoms/Error/Error";
-import Search from "components/atoms/Search/search";
-import { useToast } from "lib/hooks/useToast";
-import { useFetchInsightRecommendedRepositories } from "lib/hooks/useFetchOrgRecommendations";
-import { RepoCardProfileProps } from "components/molecules/RepoCardProfile/repo-card-profile";
-import SingleSelect from "components/atoms/Select/single-select";
-import { fetchApiData } from "helpers/fetchApiData";
-import { useGetUserWorkspaces } from "lib/hooks/api/useGetUserWorkspaces";
-import SuggestedRepositoriesList from "../SuggestedRepoList/suggested-repo-list";
-
-// lazy import DeleteInsightPageModal and TeamMembersConfig component to optimize bundle size they don't load on initial render
-const DeleteInsightPageModal = dynamic(() => import("./DeleteInsightPageModal"));
-const TransferInsightModal = dynamic(() => import("components/Workspaces/TransferInsightModal"));
-
-const enum RepoLookupError {
- Initial = 0,
- NotIndexed = 1,
- Invalid = 3,
- Error = 4,
-}
-
-const enum OrgLookupError {
- Initial = 0,
- Invalid = 1,
- Error = 2,
-}
-
-interface InsightPageProps {
- edit?: boolean;
- insight?: DbUserInsight;
- pageRepos?: DbRepo[];
- workspaceId?: string;
-}
-const staticSuggestedRepos: RepoCardProfileProps[] = [
- {
- avatar: "https://avatars.githubusercontent.com/u/57568598?s=200&v=4",
- prCount: 8,
- repoName: "app",
- issueCount: 87,
- orgName: "open-sauced",
- },
- {
- avatar: "https://avatars.githubusercontent.com/u/59704711?s=200&v=4",
- prCount: 26,
- repoName: "cli",
- issueCount: 398,
- orgName: "cli",
- },
- {
- avatar: "https://avatars.githubusercontent.com/u/42048915?s=200&v=4",
- prCount: 100,
- repoName: "deno",
- issueCount: 1200,
- orgName: "denoland",
- },
-];
-
-const InsightPage = ({ edit, insight, pageRepos, workspaceId }: InsightPageProps) => {
- const { sessionToken, providerToken, user } = useSupabaseAuth();
-
- const { toast } = useToast();
- const router = useRouter();
- const pageHref = router.asPath;
- const [reposIds, setReposIds] = useState([]);
- const { data: repoListData } = useRepositories(reposIds);
-
- useEffect(() => {
- const searchParams = new URLSearchParams(pageHref.substring(pageHref.indexOf("?")));
- if (router.query.selectedRepos) {
- setRepos(JSON.parse(router.query.selectedRepos as string) || []);
- } else if (searchParams.has("selectedReposIDs")) {
- setReposIds(JSON.parse(searchParams.get("selectedReposIDs") as string) || []);
- setRepos(repoListData);
- }
- }, [repoListData, router.query.selectedRepos, pageHref]);
-
- const { data: recommendedRepos, isLoading } = useFetchInsightRecommendedRepositories();
-
- // Loading States
- const [deleteLoading, setDeleteLoading] = useState(false);
- const [createLoading, setCreateLoading] = useState(false);
- const [addRepoLoading, setAddRepoLoading] = useState({ repoName: "", isAddedFromCart: false, isLoading: false });
-
- const [name, setName] = useState(insight?.name || "");
- const [organization, setOrganization] = useState("");
- const [isNameValid, setIsNameValid] = useState(false);
- const [submitted, setSubmitted] = useState(false);
- const [repos, setRepos] = useState([]);
- const [repoHistory, setRepoHistory] = useState([]);
- const [addRepoError, setAddRepoError] = useState(RepoLookupError.Initial);
- const [syncOrganizationError, setSyncOrganizationError] = useState(OrgLookupError.Initial);
- const [isModalOpen, setIsModalOpen] = useState(false);
- const [repoSearchTerm, setRepoSearchTerm] = useState("");
- const [suggestions, setSuggestions] = useState([]);
-
- const { data: workspacesData, isLoading: workspacesLoading } = useGetUserWorkspaces();
- const [options, setOptions] = useState<{ label: string; value: string }[]>([]);
- const [selectedWorkspace, setSelectedWorkspace] = useState(workspaceId!);
- const [isTransferModalOpen, setIsTransferModalOpen] = useState(false);
-
- useEffect(() => {
- if (workspaceId && !workspacesLoading) {
- const filteredWorkspaces = workspacesData?.data?.filter((workspace) =>
- workspace.members.find(
- (member) => member.user_id === Number(user?.user_metadata.sub) && ["owner", "editor"].includes(member.role)
- )
- );
-
- setOptions(
- Array.from(filteredWorkspaces!, (workspace) => {
- return { label: workspace.name, value: workspace.id };
- })
- );
- }
- }, [workspacesData]);
-
- const recommendedReposWithoutSelected =
- recommendedRepos && recommendedRepos.length > 0
- ? recommendedRepos
- .filter((repo) => !repos.find((selectedRepo) => selectedRepo.id === repo.id))
- .map((repo) => {
- const [orgName, repoName] = repo.full_name.split("/");
- const totalPrs = (repo.open_prs_count || 0) + (repo.closed_prs_count || 0) + (repo.merged_prs_count || 0);
- const avatar = getAvatarByUsername(orgName, 60);
- const totalIssues = repo.issues || 0;
-
- return {
- orgName,
- repoName,
- totalPrs,
- avatar,
- totalIssues,
- };
- })
- .slice(0, 3)
- : staticSuggestedRepos;
-
- useEffect(() => {
- if (pageRepos) {
- setRepos(pageRepos);
- }
- }, [pageRepos, insight?.is_public]);
-
- const reposRemoved = repoHistory.map((repo) => {
- const [repoOwner, repoName] = repo.full_name.split("/");
- const totalPrs =
- (repo.open_prs_count || 0) +
- (repo.closed_prs_count || 0) +
- (repo.merged_prs_count || 0) +
- (repo.draft_prs_count || 0);
-
- return {
- orgName: repoOwner,
- repoName: repoName,
- totalPrs,
- avatar: getAvatarByUsername(repoOwner, 60),
- handleRemoveItem: () => {},
- };
- });
-
- const validateName = (name: string) => {
- if (!name || name.trim().length <= 3) return false;
-
- return true;
- };
-
- const handleOnNameChange = (value: string) => {
- setName(value);
- setIsNameValid(validateName(value));
- };
-
- const handleOnOrganizationChange = (value: string) => {
- setOrganization(value);
- };
-
- const disableCreateButton = () => {
- if ((insight?.name && validateName(name)) || (repos.length && validateName(name))) return false;
- if (submitted) return true;
- if (!isNameValid) return true;
-
- return false;
- };
-
- const handleCreateInsightPage = async () => {
- setSubmitted(true);
- setCreateLoading(true);
-
- if (!sessionToken || !user) {
- toast({ description: "You must be logged in to create a page", variant: "danger" });
- return;
- }
- const response = await fetch(
- `${process.env.NEXT_PUBLIC_API_URL}/${workspaceId ? `workspaces/${workspaceId}` : user}/insights`,
- {
- method: "POST",
- headers: {
- "Content-type": "application/json",
- Authorization: `Bearer ${sessionToken}`,
- },
- body: JSON.stringify({
- name,
- repos: repos.map((repo) => ({ id: repo.id, fullName: repo.full_name })),
- is_public: true,
- }),
- }
- );
- setCreateLoading(false);
- if (response.ok) {
- const { insight_id } = await response.json();
- toast({ description: "Page created successfully", variant: "success" });
- router.push(`/workspaces/${workspaceId}/repository-insights/${insight_id}/dashboard`);
- }
-
- setSubmitted(false);
- };
-
- const handleUpdateInsightPage = async () => {
- setSubmitted(true);
- setCreateLoading(true);
- const response = await fetch(
- `${process.env.NEXT_PUBLIC_API_URL}/workspaces/${workspaceId}/insights/${insight?.id}`,
- {
- method: "PATCH",
- headers: {
- "Content-type": "application/json",
- Authorization: `Bearer ${sessionToken}`,
- },
- body: JSON.stringify({
- name,
- repos: repos.map((repo) => ({ id: repo.id, fullName: repo.full_name })),
- // eslint-disable-next-line
- is_public: true,
- }),
- }
- );
- setCreateLoading(false);
- if (response && response.ok) {
- toast({ description: "Page updated successfully", variant: "success" });
- router.push(`/workspaces/${workspaceId}/repository-insights/${insight?.id}/dashboard`);
- } else {
- toast({ description: "An error occurred!", variant: "danger" });
- }
-
- setSubmitted(false);
- };
-
- const addSuggestedRepo = (repoToAdd: string) => {
- const hasRepo = repos.find((repo) => `${repo.full_name}` === repoToAdd);
-
- if (hasRepo) {
- return;
- }
-
- const actualRepo = recommendedRepos?.find((repo) => repo.full_name === repoToAdd);
-
- if (!actualRepo) {
- loadAndAddRepo(repoToAdd);
- return;
- }
-
- setRepos((repos) => {
- return [...repos, actualRepo as unknown as DbRepo];
- });
- };
-
- const loadAndAddRepo = async (repoToAdd: string, isAddedFromCart = false) => {
- setAddRepoError(RepoLookupError.Initial);
-
- const hasRepo = repos.find((repo) => `${repo.full_name}` === repoToAdd);
-
- if (hasRepo) {
- return;
- }
-
- const { apiPaths, isValidUrl } = generateRepoParts(repoToAdd);
-
- if (!isValidUrl) {
- setAddRepoError(RepoLookupError.Invalid);
- return;
- }
-
- const { repoFullName } = apiPaths;
-
- setAddRepoLoading({ repoName: repoToAdd, isAddedFromCart, isLoading: true });
- try {
- const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/repos/${repoFullName}`);
- setAddRepoLoading({ repoName: repoToAdd, isAddedFromCart, isLoading: false });
-
- if (response.ok) {
- const addedRepo = (await response.json()) as DbRepo;
-
- setRepos((repos) => {
- return [...repos, addedRepo];
- });
- setAddRepoError(RepoLookupError.Initial);
- setRepoSearchTerm("");
- } else {
- const publicRepoResponse = await fetch(`https://api.github.com/repos/${repoFullName}`);
-
- if (publicRepoResponse.ok) {
- const publicRepo = await publicRepoResponse.json();
-
- // create a stub repo to send to API
- const addedRepo = {
- id: publicRepo.id,
- full_name: publicRepo.full_name,
- } as DbRepo;
-
- setRepos((repos) => {
- return [...repos, addedRepo];
- });
- setAddRepoError(RepoLookupError.Initial);
- setRepoSearchTerm("");
- } else {
- setAddRepoError(RepoLookupError.Invalid);
- }
- }
- } catch {
- setAddRepoLoading({ repoName: repoToAdd, isAddedFromCart, isLoading: false });
- setAddRepoError(RepoLookupError.Error);
- }
- };
-
- const handleAddRepository = async () => {
- await loadAndAddRepo(repoSearchTerm);
- };
-
- const handleReAddRepository = async (repoAdded: string) => {
- const existInSuggestions = recommendedRepos.find((repo) => `${repo.full_name}` === repoAdded);
-
- if (existInSuggestions) {
- setRepoHistory((historyRepos) => {
- return historyRepos.filter((repo) => `${repo.full_name}` !== repoAdded);
- });
-
- addSuggestedRepo(repoAdded);
- return;
- }
-
- try {
- await loadAndAddRepo(repoAdded, true);
-
- setRepoHistory((historyRepos) => {
- return historyRepos.filter((repo) => `${repo.full_name}` !== repoAdded);
- });
- } catch (e) {}
- };
-
- const handleRemoveRepository = (id: string) => {
- setRepos((addedRepos) => {
- return addedRepos.filter((repo) => repo.id !== id);
- });
-
- const repoRemoved = repos.find((repo) => repo.id === id);
-
- const repoAlreadyInHistory = repoHistory.find((repo) => repo.id === id);
- if (repoAlreadyInHistory) {
- return;
- }
-
- setRepoHistory((historyRepos) => {
- return [...historyRepos, repoRemoved as DbRepo];
- });
- };
-
- const getRepoLookupError = (code: RepoLookupError) => {
- if (code === RepoLookupError.Error) {
- return ;
- }
-
- if (code === RepoLookupError.Invalid) {
- return ;
- }
-
- if (code === RepoLookupError.NotIndexed) {
- return ;
- }
-
- return null;
- };
-
- const getOrganizationLookupError = (code: OrgLookupError) => {
- if (code === OrgLookupError.Error) {
- return ;
- }
-
- if (code === OrgLookupError.Invalid) {
- return ;
- }
-
- return <>>;
- };
-
- const handleDeleteInsightPage = async () => {
- setSubmitted(true);
- setDeleteLoading(true);
- const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/insights/${insight?.id}`, {
- method: "DELETE",
- headers: {
- "Content-type": "application/json",
- Authorization: `Bearer ${sessionToken}`,
- },
- });
-
- setDeleteLoading(false);
- if (response.ok) {
- toast({ description: "Page deleted successfully!", variant: "success" });
- setIsModalOpen(false);
- router.push(`/workspaces/${workspaceId}/repository-insights`);
- }
-
- setSubmitted(false);
- };
-
- const handleOnModalClose = () => {
- setIsModalOpen(false);
- };
-
- const updateSuggestionsDebounced = useDebounce(async () => {
- setCreateLoading(true);
-
- const req = await fetch(
- `https://api.github.com/search/repositories?q=${encodeURIComponent(
- `${repoSearchTerm} in:name in:repo:owner/name sort:updated`
- )}`,
- {
- ...(providerToken
- ? {
- headers: {
- Authorization: `Bearer ${providerToken}`,
- },
- }
- : {}),
- }
- );
-
- setCreateLoading(false);
- if (req.ok) {
- const res = await req.json();
- const suggestions = res.items.map((item: any) => item.full_name);
- setSuggestions(suggestions);
- }
- }, 250);
-
- const handleAddOrganizationRepositories = async () => {
- setSyncOrganizationError(OrgLookupError.Initial);
-
- const orgReposResponse = await fetch(
- `https://api.github.com/orgs/${organization}/repos?type=public&sort=pushed&direction=desc`,
- {
- headers: providerToken
- ? {
- Authorization: `Bearer ${providerToken}`,
- }
- : {},
- }
- );
-
- if (orgReposResponse.ok) {
- const orgReposData = await orgReposResponse.json();
-
- // create a stub repo to send to API
- const orgRepos = orgReposData
- .filter(
- (orgRepo: { id: number; full_name: string }) => !repos.find((repo) => orgRepo.full_name === repo.full_name)
- )
- .slice(0, 10)
- .map((orgRepo: { id: number; full_name: string }) => ({
- id: orgRepo.id,
- full_name: orgRepo.full_name,
- })) as DbRepo[];
-
- setRepos((repos) => {
- return [...repos, ...orgRepos];
- });
-
- setSyncOrganizationError(OrgLookupError.Initial);
- setOrganization("");
- } else {
- if (orgReposResponse.status === 404) {
- setSyncOrganizationError(OrgLookupError.Invalid);
- } else {
- setSyncOrganizationError(OrgLookupError.Error);
- }
- }
- };
-
- const transferWorkspace = async () => {
- const selectedOption = options.find((opt) => opt.value === selectedWorkspace);
- const response = await fetchApiData({
- method: "POST",
- path: `workspaces/${workspaceId!}/insights/${selectedWorkspace}`,
- body: {
- id: insight?.id,
- },
- bearerToken: sessionToken!,
- pathValidator: () => true,
- });
- if (response.error) {
- toast({ description: "An error has occurred. Try again.", variant: "success" });
- return;
- }
-
- toast({ description: `Moved insight to ${selectedOption?.label}`, variant: "success" });
- router.push(`/workspaces/${selectedWorkspace}/repository-insights/${insight?.id}/dashboard`);
- };
-
- useEffect(() => {
- setSuggestions([]);
- if (!repoSearchTerm) return;
- updateSuggestionsDebounced();
- }, [repoSearchTerm]);
-
- return (
-
-
-
-
- {edit ? "Update" : "Create New"} {workspaceId ? "Repository Insight" : "Insight Page"}
-
-
- An insight page is a dashboard containing selected repositories that you and your team can get insights
- from.
-
-
-
-
-
- Page Name
-
-
-
-
-
-
-
- Sync GitHub Organization
-
-
-
-
-
-
-
- Sync Organization
-
-
-
-
{getOrganizationLookupError(syncOrganizationError)}
-
-
-
-
- Add Repository
-
-
setRepoSearchTerm(value)}
- onSearch={(search) => setRepoSearchTerm(search as string)}
- />
-
-
-
- Add Repository
-
-
-
-
- {
- addSuggestedRepo(repo);
- }}
- />
-
-
-
-
{getRepoLookupError(addRepoError)}
-
- {edit && (
-
-
- Danger Zone
-
-
-
- {workspaceId && (
-
-
-
Transfer to other Workspace
- Move this insight to another workspace where you are an owner or editor.
-
- opt.value === workspaceId)?.label}
- options={options}
- onValueChange={(value: string) => {
- setSelectedWorkspace(value);
- }}
- />
- setIsTransferModalOpen(true)}
- disabled={selectedWorkspace === workspaceId}
- variant="primary"
- className="w-fit"
- >
- Transfer
-
-
- )}
-
- Delete Page
-
-
Once you delete a page, you're past the point of no return.
-
-
- setIsModalOpen(true)} variant="destructive">
- Delete page
-
-
-
-
- )}
-
-
-
- 0}
- handleCreatePage={handleCreateInsightPage}
- handleUpdatePage={handleUpdateInsightPage}
- handleAddToCart={handleReAddRepository}
- history={reposRemoved.filter(
- (repo) => !repos.find((r) => r.full_name === `${repo.orgName}/${repo.repoName}`)
- )}
- createPageButtonDisabled={disableCreateButton()}
- >
- {repos.map((repo) => {
- const [repoOwner, repoName] = repo.full_name.split("/");
- const totalPrs =
- (repo.open_prs_count || 0) +
- (repo.closed_prs_count || 0) +
- (repo.merged_prs_count || 0) +
- (repo.draft_prs_count || 0);
-
- return (
- handleRemoveRepository(repo.id)}
- orgName={repoOwner}
- repoName={repoName}
- totalPrs={totalPrs}
- />
- );
- })}
-
-
-
- {workspaceId && (
- setIsTransferModalOpen(false)}
- handleTransfer={transferWorkspace}
- insightName={insight?.name || ""}
- currentWorkspaceName={options.find((opt) => opt.value === workspaceId)?.label || ""}
- destinationWorkspaceName={options.find((opt) => opt.value === selectedWorkspace)?.label || ""}
- />
- )}
-
-
-
- );
-};
-
-export default InsightPage;
diff --git a/components/organisms/UserSettingsPage/user-settings-page.tsx b/components/organisms/UserSettingsPage/user-settings-page.tsx
index b348c99bb..b7e211aef 100644
--- a/components/organisms/UserSettingsPage/user-settings-page.tsx
+++ b/components/organisms/UserSettingsPage/user-settings-page.tsx
@@ -336,11 +336,12 @@ const UserSettingsPage = ({ user }: UserSettingsPageProps) => {
-
-
+
+
Time zone
setTimezone(value)} value={timezone}>
@@ -397,9 +398,9 @@ const UserSettingsPage = ({ user }: UserSettingsPageProps) => {
Update Interests
-
+
- Email Preferences
+ Email Preferences
setEmailPreference((prev) => ({ ...prev, display_email: !prev.display_email }))}
checked={emailPreference.display_email}
@@ -432,7 +433,7 @@ const UserSettingsPage = ({ user }: UserSettingsPageProps) => {
>
Update Preferences
-
+
{userInfo && (