import { useState } from "react"; import { useForm } from "react-hook-form"; import { faArrowDownAZ, faBorderAll, faCheck, faCheckCircle, faFolderOpen, faList, faMagnifyingGlass, faPlus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useNavigate } from "@tanstack/react-router"; import { twMerge } from "tailwind-merge"; import { createNotification } from "@app/components/notifications"; import { OrgPermissionCan } from "@app/components/permissions"; import { Badge, Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger, FormControl, IconButton, Input, Lottie, Modal, ModalContent, Pagination, Skeleton, Tooltip } from "@app/components/v2"; import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context"; import { OrgPermissionAdminConsoleAction } from "@app/context/OrgPermissionContext/types"; import { getProjectHomePage, getProjectLottieIcon, getProjectTitle } from "@app/helpers/project"; import { getUserTablePreference, PreferenceKey, setUserTablePreference } from "@app/helpers/userTablePreferences"; import { useDebounce, usePagination, usePopUp, useResetPageHelper } from "@app/hooks"; import { useOrgAdminAccessProject, useRequestProjectAccess, useSearchProjects } from "@app/hooks/api"; import { ProjectType, Workspace, WorkspaceEnv } from "@app/hooks/api/workspace/types"; import { ProjectListToggle, ProjectListView } from "@app/pages/organization/ProjectsPage/components/ProjectListToggle"; type Props = { onAddNewProject: () => void; onUpgradePlan: () => void; isAddingProjectsAllowed: boolean; projectListView: ProjectListView; onProjectListViewChange: (value: ProjectListView) => void; }; type RequestAccessModalProps = { projectId: string; onPopUpToggle: () => void; }; const RequestAccessModal = ({ projectId, onPopUpToggle }: RequestAccessModalProps) => { const form = useForm<{ note: string }>(); const requestProjectAccess = useRequestProjectAccess(); const onFormSubmit = ({ note }: { note: string }) => { if (requestProjectAccess.isPending) return; requestProjectAccess.mutate( { comment: note, projectId }, { onSuccess: () => { createNotification({ type: "success", title: "Project Access Request Sent", text: "Project admins will receive an email of your request" }); onPopUpToggle(); } } ); }; return (
); }; export const AllProjectView = ({ onAddNewProject, onUpgradePlan, isAddingProjectsAllowed, projectListView, onProjectListViewChange }: Props) => { const navigate = useNavigate(); const [searchFilter, setSearchFilter] = useState(""); const [debouncedSearch] = useDebounce(searchFilter); const [projectTypeFilter, setProjectTypeFilter] = useState(); const { setPage, perPage, setPerPage, page, offset, limit, toggleOrderDirection, orderDirection } = usePagination("name", { initPerPage: getUserTablePreference("allProjectsTable", PreferenceKey.PerPage, 50) }); const orgAdminAccessProject = useOrgAdminAccessProject(); const handlePerPageChange = (newPerPage: number) => { setPerPage(newPerPage); setUserTablePreference("allProjectsTable", PreferenceKey.PerPage, newPerPage); }; const { popUp, handlePopUpToggle, handlePopUpOpen } = usePopUp([ "requestAccessConfirmation" ] as const); const { data: searchedProjects, isPending: isProjectLoading } = useSearchProjects({ limit, offset, name: debouncedSearch || undefined, orderDirection, type: projectTypeFilter }); const handleAccessProject = async ( type: ProjectType, projectId: string, environments: WorkspaceEnv[] ) => { try { await orgAdminAccessProject.mutateAsync({ projectId }); await navigate({ to: getProjectHomePage(type, environments), params: { projectId } }); } catch { createNotification({ text: "Failed to access project", type: "error" }); } }; useResetPageHelper({ setPage, offset, totalCount: searchedProjects?.totalCount || 0 }); const requestedWorkspaceDetails = (popUp.requestAccessConfirmation.data || {}) as Workspace; const handleToggleFilterByProjectType = (el: ProjectType) => setProjectTypeFilter((state) => (state === el ? undefined : el)); return (
setSearchFilter(e.target.value)} leftIcon={} />
Filter By Project Type {Object.values(ProjectType).map((el) => ( { e.preventDefault(); handleToggleFilterByProjectType(el); }} icon={projectTypeFilter === el && } iconPos="right" >
{getProjectTitle(el)}
))}
{(isAllowed) => ( )}
{isProjectLoading && Array.apply(0, Array(3)).map((_x, i) => (
))} {!isProjectLoading && searchedProjects?.projects?.map((workspace) => (
{ if (evt.key === "Enter" && workspace.isMember) { navigate({ to: getProjectHomePage(workspace.type, workspace.environments), params: { projectId: workspace.id } }); } }} onClick={() => { if (workspace.isMember) { navigate({ to: getProjectHomePage(workspace.type, workspace.environments), params: { projectId: workspace.id } }); } }} key={workspace.id} className={twMerge( "group flex min-w-72 items-center justify-center border-l border-r border-t border-mineshaft-600 bg-mineshaft-800 px-6 py-3 first:rounded-t-md", workspace.isMember ? "cursor-pointer hover:bg-mineshaft-700" : "cursor-default" )} >

{workspace.name}

{getProjectTitle(workspace.type)}{" "} {workspace.description ? `- ${workspace.description}` : ""}

{workspace.isMember ? ( Joined ) : ( {(isAllowed) => isAllowed ? ( ) : ( ) } )}
))}
{!isProjectLoading && Boolean(searchedProjects?.totalCount) && ( )} {!isProjectLoading && !searchedProjects?.totalCount && (
No Projects Found
)} handlePopUpToggle("requestAccessConfirmation", isOpen)} > handlePopUpToggle("requestAccessConfirmation")} projectId={requestedWorkspaceDetails?.id} />
); };