Skip to content

Commit 9ed6ea6

Browse files
SaxonFjoshenlim
andauthored
Project list updates (supabase#38021)
* update project list page layout * prettier * size actions * Clean up * Smol fix * Fix TS * Refactor to improve readability, remove duplicated code, make org page consistent * use TimestampInfo * Last bit * Fix * niiiiiiit --------- Co-authored-by: Joshen Lim <[email protected]>
1 parent a1f2e50 commit 9ed6ea6

File tree

13 files changed

+563
-286
lines changed

13 files changed

+563
-286
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import { Plus } from 'lucide-react'
2+
import Link from 'next/link'
3+
4+
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
5+
import {
6+
Button,
7+
Card,
8+
cn,
9+
Skeleton,
10+
Table,
11+
TableBody,
12+
TableCell,
13+
TableHead,
14+
TableHeader,
15+
TableRow,
16+
} from 'ui'
17+
import { ShimmeringCard } from './ShimmeringCard'
18+
19+
export const NoFilterResults = ({
20+
filterStatus,
21+
resetFilterStatus,
22+
className,
23+
}: {
24+
filterStatus: string[]
25+
resetFilterStatus?: () => void
26+
className?: string
27+
}) => {
28+
return (
29+
<div
30+
className={cn(
31+
'bg-surface-100 px-4 md:px-6 py-4 rounded flex items-center justify-between border border-default',
32+
className
33+
)}
34+
>
35+
<div className="space-y-1">
36+
{/* [Joshen] Just keeping it simple for now unless we decide to extend this to other statuses */}
37+
<p className="text-sm text-foreground">
38+
{filterStatus.length === 0
39+
? `No projects found`
40+
: `No ${filterStatus[0] === 'INACTIVE' ? 'paused' : 'active'} projects found`}
41+
</p>
42+
<p className="text-sm text-foreground-light">
43+
Your search for projects with the specified status did not return any results
44+
</p>
45+
</div>
46+
{resetFilterStatus !== undefined && (
47+
<Button type="default" onClick={() => resetFilterStatus()}>
48+
Reset filter
49+
</Button>
50+
)}
51+
</div>
52+
)
53+
}
54+
55+
export const LoadingTableView = () => {
56+
return (
57+
<Card>
58+
<Table>
59+
<TableHeader>
60+
<TableRow>
61+
<TableHead>Project</TableHead>
62+
<TableHead>Status</TableHead>
63+
<TableHead>Compute</TableHead>
64+
<TableHead>Region</TableHead>
65+
<TableHead>Created</TableHead>
66+
</TableRow>
67+
</TableHeader>
68+
<TableBody>
69+
{[...Array(3)].map((_, i) => (
70+
<TableRow key={i}>
71+
<TableCell>
72+
<Skeleton className="bg-surface-400 h-4 w-32"></Skeleton>
73+
</TableCell>
74+
<TableCell>
75+
<Skeleton className="bg-surface-400 h-4 w-16"></Skeleton>
76+
</TableCell>
77+
<TableCell>
78+
<Skeleton className="bg-surface-400 h-4 w-20"></Skeleton>
79+
</TableCell>
80+
<TableCell>
81+
<Skeleton className="bg-surface-400 h-4 w-20"></Skeleton>
82+
</TableCell>
83+
<TableCell>
84+
<Skeleton className="bg-surface-400 h-4 w-24"></Skeleton>
85+
</TableCell>
86+
</TableRow>
87+
))}
88+
</TableBody>
89+
</Table>
90+
</Card>
91+
)
92+
}
93+
94+
export const LoadingCardView = () => {
95+
return (
96+
<ul className="w-full mx-auto grid grid-cols-1 gap-4 sm:grid-cols-1 md:grid-cols-1 lg:grid-cols-2 xl:grid-cols-3">
97+
<ShimmeringCard />
98+
<ShimmeringCard />
99+
</ul>
100+
)
101+
}
102+
103+
export const NoProjectsState = ({ slug }: { slug: string }) => {
104+
const projectCreationEnabled = useIsFeatureEnabled('projects:create')
105+
106+
return (
107+
<div className="col-span-4 space-y-4 rounded-lg border border-dashed p-6 text-center">
108+
<div className="space-y-1">
109+
<p>No projects</p>
110+
<p className="text-sm text-foreground-light">Get started by creating a new project.</p>
111+
</div>
112+
113+
{projectCreationEnabled && (
114+
<Button asChild icon={<Plus />}>
115+
<Link href={`/new/${slug}`}>New Project</Link>
116+
</Button>
117+
)}
118+
</div>
119+
)
120+
}

apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export interface ProjectCardProps {
2020
resourceWarnings?: ResourceWarning
2121
}
2222

23-
const ProjectCard = ({
23+
export const ProjectCard = ({
2424
project,
2525
rewriteHref,
2626
githubIntegration,
@@ -86,5 +86,3 @@ const ProjectCard = ({
8686
</li>
8787
)
8888
}
89-
90-
export default ProjectCard

apps/studio/components/interfaces/Home/ProjectList/ProjectCardStatus.tsx

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,27 @@ import { AlertTriangle, Info, PauseCircle, RefreshCcw } from 'lucide-react'
33
import { RESOURCE_WARNING_MESSAGES } from 'components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner.constants'
44
import { getWarningContent } from 'components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner.utils'
55
import type { ResourceWarning } from 'data/usage/resource-warnings-query'
6-
import { Alert_Shadcn_, AlertTitle_Shadcn_, cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
6+
import {
7+
Alert_Shadcn_,
8+
AlertTitle_Shadcn_,
9+
Badge,
10+
cn,
11+
Tooltip,
12+
TooltipContent,
13+
TooltipTrigger,
14+
} from 'ui'
715
import { InferredProjectStatus } from './ProjectCard.utils'
816

917
export interface ProjectCardWarningsProps {
1018
resourceWarnings?: ResourceWarning
1119
projectStatus: InferredProjectStatus
20+
renderMode?: 'alert' | 'badge' // New prop to control rendering mode
1221
}
1322

1423
export const ProjectCardStatus = ({
1524
resourceWarnings: allResourceWarnings,
1625
projectStatus,
26+
renderMode = 'alert',
1727
}: ProjectCardWarningsProps) => {
1828
const showResourceExhaustionWarnings = false
1929

@@ -47,17 +57,30 @@ export const ProjectCardStatus = ({
4757
: undefined
4858

4959
const getTitle = () => {
50-
if (projectStatus === 'isPaused') return 'Project is paused'
51-
if (projectStatus === 'isPausing') return 'Project is pausing'
52-
if (projectStatus === 'isRestarting') return 'Project is restarting'
53-
if (projectStatus === 'isResizing') return 'Project is resizing'
54-
if (projectStatus === 'isComingUp') return 'Project is coming up'
55-
if (projectStatus === 'isRestoring') return 'Project is restoring'
56-
if (projectStatus === 'isUpgrading') return 'Project is upgrading'
57-
if (projectStatus === 'isRestoreFailed') return 'Project restore failed'
58-
if (projectStatus === 'isPauseFailed') return 'Project pause failed'
60+
switch (projectStatus) {
61+
case 'isPaused':
62+
return renderMode === 'badge' ? 'Paused' : 'Project is paused'
63+
case 'isPausing':
64+
return renderMode === 'badge' ? 'Pausing' : 'Project is pausing'
65+
case 'isRestarting':
66+
return renderMode === 'badge' ? 'Restarting' : 'Project is restarting'
67+
case 'isResizing':
68+
return renderMode === 'badge' ? 'Resizing' : 'Project is resizing'
69+
case 'isComingUp':
70+
return renderMode === 'badge' ? 'Starting' : 'Project is coming up'
71+
case 'isRestoring':
72+
return renderMode === 'badge' ? 'Restoring' : 'Project is restoring'
73+
case 'isUpgrading':
74+
return renderMode === 'badge' ? 'Upgrading' : 'Project is upgrading'
75+
case 'isRestoreFailed':
76+
return renderMode === 'badge' ? 'Restore Failed' : 'Project restore failed'
77+
case 'isPauseFailed':
78+
return renderMode === 'badge' ? 'Pause Failed' : 'Project pause failed'
79+
}
5980

60-
if (!resourceWarnings) return undefined
81+
if (!resourceWarnings) {
82+
return renderMode === 'badge' && projectStatus === 'isHealthy' ? 'Active' : undefined
83+
}
6184

6285
// If none of the paused/restoring states match, proceed with the default logic
6386
return activeWarnings.length > 1
@@ -106,9 +129,41 @@ export const ProjectCardStatus = ({
106129
(activeWarnings.length === 0 || warningContent === undefined) &&
107130
projectStatus === 'isHealthy'
108131
) {
132+
if (renderMode === 'badge') {
133+
return (
134+
<Badge variant="success" className="rounded-md">
135+
Active
136+
</Badge>
137+
)
138+
}
109139
return null
110140
}
111141

142+
if (renderMode === 'badge') {
143+
const badgeVariant = isCritical
144+
? 'destructive'
145+
: projectStatus !== 'isHealthy'
146+
? 'warning'
147+
: activeWarnings.length > 0
148+
? 'warning'
149+
: 'success'
150+
151+
return alertDescription ? (
152+
<Tooltip>
153+
<TooltipTrigger asChild>
154+
<Badge className="rounded-md" variant={badgeVariant}>
155+
{alertTitle}
156+
</Badge>
157+
</TooltipTrigger>
158+
<TooltipContent side="bottom">{alertDescription}</TooltipContent>
159+
</Tooltip>
160+
) : (
161+
<Badge className="rounded-md" variant={badgeVariant}>
162+
{alertTitle}
163+
</Badge>
164+
)
165+
}
166+
112167
return (
113168
<Alert_Shadcn_
114169
variant={alertType}

0 commit comments

Comments
 (0)