| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- import { Copy, Github, MoreVertical, Settings } from 'lucide-react'
- import { useRouter } from 'next/router'
- import InlineSVG from 'react-inlinesvg'
- import { toast } from 'sonner'
- import {
- Button,
- copyToClipboard,
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger,
- } from 'ui'
- import { inferProjectStatus } from './ProjectCard.utils'
- import { ProjectCardStatus } from './ProjectCardStatus'
- import CardButton from '@/components/ui/CardButton'
- import { ComputeBadgeWrapper } from '@/components/ui/ComputeBadgeWrapper'
- import PartnerIcon from '@/components/ui/PartnerIcon'
- import type { IntegrationProjectConnection } from '@/data/integrations/integrations.types'
- import { getManagedByFromOrganizationPartner } from '@/data/organizations/managed-by-utils'
- import { ProjectIndexPageLink } from '@/data/prefetchers/project.$ref'
- import { getComputeSize, OrgProject } from '@/data/projects/org-projects-infinite-query'
- import type { ResourceWarning } from '@/data/usage/resource-warnings-query'
- import { useCustomContent } from '@/hooks/custom-content/useCustomContent'
- import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
- import { BASE_PATH } from '@/lib/constants'
- import type { Organization } from '@/types'
- export interface ProjectCardProps {
- slug?: string
- project: OrgProject
- organization?: Organization
- rewriteHref?: string
- githubIntegration?: IntegrationProjectConnection
- vercelIntegration?: IntegrationProjectConnection
- resourceWarnings?: ResourceWarning
- }
- export const ProjectCard = ({
- slug,
- project,
- rewriteHref,
- githubIntegration,
- vercelIntegration,
- resourceWarnings,
- }: ProjectCardProps) => {
- const router = useRouter()
- const { name, ref: projectRef } = project
- const { infraAwsNimbusLabel } = useCustomContent(['infra:aws_nimbus_label'])
- const providerLabel =
- project.cloud_provider === 'AWS_NIMBUS' ? infraAwsNimbusLabel : project.cloud_provider
- const desc = `${providerLabel} | ${project.region}`
- const { projectHomepageShowInstanceSize } = useIsFeatureEnabled([
- 'project_homepage:show_instance_size',
- ])
- const isGithubIntegrated = githubIntegration !== undefined
- const isVercelIntegrated = vercelIntegration !== undefined
- const githubRepository = githubIntegration?.metadata.name ?? undefined
- const projectManagedBy = getManagedByFromOrganizationPartner(
- undefined,
- project.integration_source
- )
- const projectStatus = inferProjectStatus(project.status)
- return (
- <>
- <li className="list-none h-min">
- <CardButton
- linkHref={rewriteHref ? rewriteHref : `/project/${projectRef}`}
- className="h-44 px-0! group pt-5 pb-0 overflow-hidden relative"
- hideChevron
- title={
- <div className="w-full flex flex-col gap-y-4 justify-between px-5">
- <div className="flex flex-col gap-y-0.5 relative">
- <div className="flex items-center justify-between">
- <h5 className="text-sm shrink truncate pr-5">{name}</h5>
- <div onClick={(e) => e.preventDefault()}>
- <DropdownMenu>
- <DropdownMenuTrigger asChild>
- <Button
- type="text"
- icon={<MoreVertical size={14} />}
- className="w-6 h-6 px-0"
- onClick={(e) => {
- e.stopPropagation()
- e.preventDefault()
- }}
- onPointerDown={(e) => e.stopPropagation()}
- />
- </DropdownMenuTrigger>
- <DropdownMenuContent align="end" className="w-48">
- <DropdownMenuItem
- className="gap-x-2"
- onClick={(e) => {
- e.stopPropagation()
- copyToClipboard(projectRef)
- toast.success('Copied project ID to clipboard')
- }}
- >
- <Copy size={14} />
- <span>Copy project ID</span>
- </DropdownMenuItem>
- <DropdownMenuItem
- className="gap-x-2"
- onClick={(e) => {
- e.stopPropagation()
- router.push(`/project/${projectRef}/settings/general`)
- }}
- >
- <Settings size={14} />
- <span>Settings</span>
- </DropdownMenuItem>
- </DropdownMenuContent>
- </DropdownMenu>
- </div>
- </div>
- <p className="text-sm text-foreground-lighter">{desc}</p>
- </div>
- <div className="flex items-center gap-x-1.5 relative overflow-hidden">
- {project.status !== 'INACTIVE' && projectHomepageShowInstanceSize && (
- <ComputeBadgeWrapper
- slug={slug}
- projectRef={project.ref}
- cloudProvider={project.cloud_provider}
- computeSize={getComputeSize(project)}
- resourceWarnings={resourceWarnings}
- badgeClassName="text-[10px] leading-none tracking-[0.07em]"
- />
- )}
- {isVercelIntegrated && (
- <div className="bg-surface-100 w-5 h-5 p-1 border border-strong rounded-md flex items-center justify-center text-black dark:text-white">
- <InlineSVG
- src={`${BASE_PATH}/img/icons/vercel-icon.svg`}
- title="Vercel Icon"
- className="w-3"
- />
- </div>
- )}
- <PartnerIcon organization={{ managed_by: projectManagedBy }} />
- {isGithubIntegrated && (
- <div className="bg-surface-100 flex items-center gap-x-0.5 h-5 pr-1 border border-strong rounded-md min-w-0">
- <div className="w-5 h-5 p-1 flex items-center justify-center shrink-0">
- <Github size={12} strokeWidth={1.5} />
- </div>
- <p className="text-xs text-foreground-light truncate">{githubRepository}</p>
- </div>
- )}
- </div>
- </div>
- }
- footer={
- <ProjectCardStatus projectStatus={projectStatus} resourceWarnings={resourceWarnings} />
- }
- containerElement={<ProjectIndexPageLink projectRef={projectRef} />}
- />
- </li>
- </>
- )
- }
|