@tscircuit/fake-snippets 0.0.106 → 0.0.108
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +92 -0
- package/api/generated-index.js +84 -25
- package/biome.json +7 -1
- package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +0 -15
- package/bun-tests/fake-snippets-api/routes/package_builds/list.test.ts +0 -12
- package/dist/bundle.js +360 -434
- package/dist/index.d.ts +26 -15
- package/dist/index.js +40 -21
- package/dist/schema.d.ts +32 -24
- package/dist/schema.js +7 -5
- package/fake-snippets-api/lib/db/db-client.ts +19 -1
- package/fake-snippets-api/lib/db/schema.ts +6 -3
- package/fake-snippets-api/lib/db/seed.ts +23 -12
- package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +0 -3
- package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +3 -0
- package/fake-snippets-api/routes/api/package_builds/list.ts +0 -1
- package/package.json +3 -2
- package/src/App.tsx +27 -9
- package/src/components/FileSidebar.tsx +14 -159
- package/src/components/PackageBreadcrumb.tsx +111 -0
- package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +1 -1
- package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +18 -2
- package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +18 -8
- package/src/components/preview/BuildsList.tsx +84 -167
- package/src/components/preview/ConnectedPackagesList.tsx +92 -62
- package/src/components/preview/ConnectedRepoOverview.tsx +171 -155
- package/src/components/preview/{ConnectedRepoDashboard.tsx → PackageReleasesDashboard.tsx} +31 -69
- package/src/components/preview/index.tsx +20 -154
- package/src/hooks/use-package-builds.ts +0 -48
- package/src/hooks/use-package-release-by-id-or-version.ts +36 -0
- package/src/hooks/use-package-release.ts +32 -0
- package/src/index.css +24 -0
- package/src/lib/utils/isUuid.ts +5 -0
- package/src/lib/utils/transformFilesToTreeData.tsx +195 -0
- package/src/pages/404.tsx +3 -5
- package/src/pages/preview-release.tsx +269 -0
- package/src/pages/release-builds.tsx +99 -0
- package/src/pages/release-detail.tsx +120 -0
- package/src/pages/releases.tsx +55 -0
- package/fake-snippets-api/routes/api/package_builds/latest.ts +0 -109
- package/src/hooks/use-snippets-base-api-url.ts +0 -3
- package/src/pages/preview-build.tsx +0 -380
- package/src/pages/view-connected-repo.tsx +0 -49
|
@@ -2,15 +2,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
|
|
2
2
|
import { Badge } from "@/components/ui/badge"
|
|
3
3
|
import { Button } from "@/components/ui/button"
|
|
4
4
|
import { Skeleton } from "@/components/ui/skeleton"
|
|
5
|
-
import {
|
|
6
|
-
Clock,
|
|
7
|
-
GitBranch,
|
|
8
|
-
AlertCircle,
|
|
9
|
-
CheckCircle,
|
|
10
|
-
Loader2,
|
|
11
|
-
MoreHorizontal,
|
|
12
|
-
GitCommit,
|
|
13
|
-
} from "lucide-react"
|
|
5
|
+
import { GitBranch, MoreHorizontal, GitCommit } from "lucide-react"
|
|
14
6
|
import {
|
|
15
7
|
DropdownMenu,
|
|
16
8
|
DropdownMenuContent,
|
|
@@ -28,63 +20,52 @@ import {
|
|
|
28
20
|
import { getBuildStatus, StatusIcon } from "."
|
|
29
21
|
import { formatTimeAgo } from "@/lib/utils/formatTimeAgo"
|
|
30
22
|
import { Package, PackageBuild } from "fake-snippets-api/lib/db/schema"
|
|
31
|
-
import {
|
|
32
|
-
import { usePackageReleaseById } from "@/hooks/use-package-release"
|
|
23
|
+
import { usePackageReleasesByPackageId } from "@/hooks/use-package-release"
|
|
33
24
|
import { useQueries } from "react-query"
|
|
34
25
|
import { useAxios } from "@/hooks/use-axios"
|
|
26
|
+
import { useLocation } from "wouter"
|
|
35
27
|
|
|
36
|
-
export const BuildsList = ({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}: {
|
|
40
|
-
pkg: Package
|
|
41
|
-
onSelectBuild?: (build: PackageBuild) => void
|
|
42
|
-
}) => {
|
|
43
|
-
const { data: builds, isLoading } = usePackageBuilds({
|
|
44
|
-
package_id: pkg.package_id,
|
|
45
|
-
})
|
|
28
|
+
export const BuildsList = ({ pkg }: { pkg: Package }) => {
|
|
29
|
+
const { data: releases, isLoading: isLoadingReleases } =
|
|
30
|
+
usePackageReleasesByPackageId(pkg.package_id)
|
|
46
31
|
const axios = useAxios()
|
|
32
|
+
const [, setLocation] = useLocation()
|
|
33
|
+
// Get the latest build for each release to show status
|
|
34
|
+
const latestBuildQueries = useQueries(
|
|
35
|
+
(releases || [])
|
|
36
|
+
.filter((release) => release.latest_package_build_id)
|
|
37
|
+
.map((release) => ({
|
|
38
|
+
queryKey: ["packageBuild", release.latest_package_build_id],
|
|
39
|
+
queryFn: async () => {
|
|
40
|
+
if (!release.latest_package_build_id) return null
|
|
41
|
+
const { data } = await axios.get("/package_builds/get", {
|
|
42
|
+
params: { package_build_id: release.latest_package_build_id },
|
|
43
|
+
})
|
|
44
|
+
return data.package_build
|
|
45
|
+
},
|
|
46
|
+
enabled: Boolean(release.latest_package_build_id),
|
|
47
|
+
retry: false,
|
|
48
|
+
refetchOnWindowFocus: false,
|
|
49
|
+
})),
|
|
50
|
+
)
|
|
47
51
|
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
builds?.map((build) => build.package_release_id).filter(Boolean) || [],
|
|
51
|
-
),
|
|
52
|
-
]
|
|
52
|
+
const isLoading =
|
|
53
|
+
isLoadingReleases || latestBuildQueries.some((q) => q.isLoading)
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
queryKey: ["packageRelease", { package_release_id: releaseId }],
|
|
57
|
-
queryFn: async () => {
|
|
58
|
-
const { data } = await axios.post("/package_releases/get", {
|
|
59
|
-
package_release_id: releaseId,
|
|
60
|
-
})
|
|
61
|
-
return data.package_release
|
|
62
|
-
},
|
|
63
|
-
enabled: Boolean(releaseId),
|
|
64
|
-
retry: false,
|
|
65
|
-
refetchOnWindowFocus: false,
|
|
66
|
-
})),
|
|
67
|
-
)
|
|
55
|
+
// Create a map of release ID to latest build for easy access
|
|
56
|
+
const latestBuildsMap = new Map<string, PackageBuild>()
|
|
68
57
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
packageReleasesMap.set(uniqueReleaseIds[index], query.data)
|
|
58
|
+
latestBuildQueries.forEach((query, index) => {
|
|
59
|
+
if (query.data && releases?.[index]) {
|
|
60
|
+
latestBuildsMap.set(releases[index].package_release_id, query.data)
|
|
73
61
|
}
|
|
74
62
|
})
|
|
75
63
|
return (
|
|
76
64
|
<>
|
|
77
65
|
<div className="space-y-6">
|
|
78
|
-
<div className="flex items-center justify-between">
|
|
79
|
-
<div>
|
|
80
|
-
<h2 className="text-2xl font-bold text-gray-900">Builds</h2>
|
|
81
|
-
<p className="text-gray-600">Manage and monitor your builds</p>
|
|
82
|
-
</div>
|
|
83
|
-
</div>
|
|
84
|
-
|
|
85
66
|
<Card>
|
|
86
67
|
<CardHeader>
|
|
87
|
-
<CardTitle>Recent
|
|
68
|
+
<CardTitle>Recent Releases</CardTitle>
|
|
88
69
|
</CardHeader>
|
|
89
70
|
<CardContent>
|
|
90
71
|
<div className="overflow-x-auto [&>div]:no-scrollbar">
|
|
@@ -92,10 +73,10 @@ export const BuildsList = ({
|
|
|
92
73
|
<TableHeader>
|
|
93
74
|
<TableRow>
|
|
94
75
|
<TableHead>Status</TableHead>
|
|
95
|
-
<TableHead>
|
|
76
|
+
<TableHead>Release ID</TableHead>
|
|
77
|
+
<TableHead>Version</TableHead>
|
|
96
78
|
<TableHead>Branch/PR</TableHead>
|
|
97
|
-
<TableHead>
|
|
98
|
-
<TableHead>Author</TableHead>
|
|
79
|
+
<TableHead>Latest Build</TableHead>
|
|
99
80
|
<TableHead>Created</TableHead>
|
|
100
81
|
<TableHead>Actions</TableHead>
|
|
101
82
|
</TableRow>
|
|
@@ -127,16 +108,20 @@ export const BuildsList = ({
|
|
|
127
108
|
</TableCell>
|
|
128
109
|
</TableRow>
|
|
129
110
|
))
|
|
130
|
-
:
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
build.package_release_id,
|
|
111
|
+
: releases?.map((release) => {
|
|
112
|
+
const latestBuild = latestBuildsMap.get(
|
|
113
|
+
release.package_release_id,
|
|
134
114
|
)
|
|
115
|
+
const { status, label } = getBuildStatus(latestBuild)
|
|
135
116
|
return (
|
|
136
117
|
<TableRow
|
|
137
|
-
key={
|
|
118
|
+
key={release.package_release_id}
|
|
138
119
|
className="cursor-pointer hover:bg-gray-50 no-scrollbar"
|
|
139
|
-
onClick={() =>
|
|
120
|
+
onClick={() => {
|
|
121
|
+
setLocation(
|
|
122
|
+
`/${pkg.name}/releases/${release.package_release_id}`,
|
|
123
|
+
)
|
|
124
|
+
}}
|
|
140
125
|
>
|
|
141
126
|
<TableCell>
|
|
142
127
|
<div className="flex items-center gap-2">
|
|
@@ -157,38 +142,45 @@ export const BuildsList = ({
|
|
|
157
142
|
</TableCell>
|
|
158
143
|
<TableCell>
|
|
159
144
|
<code className="text-sm bg-gray-100 px-2 py-1 rounded">
|
|
160
|
-
{
|
|
145
|
+
{release.package_release_id.slice(-8)}
|
|
161
146
|
</code>
|
|
162
147
|
</TableCell>
|
|
148
|
+
<TableCell>
|
|
149
|
+
<span className="text-sm font-medium">
|
|
150
|
+
{release.version ||
|
|
151
|
+
"v" + release.package_release_id.slice(-6)}
|
|
152
|
+
</span>
|
|
153
|
+
</TableCell>
|
|
163
154
|
<TableCell>
|
|
164
155
|
<div className="flex items-center gap-2">
|
|
165
|
-
{
|
|
156
|
+
{release.is_pr_preview ? (
|
|
166
157
|
<GitBranch className="w-3 h-3 text-gray-500" />
|
|
167
158
|
) : (
|
|
168
159
|
<GitCommit className="w-3 h-3 text-gray-500" />
|
|
169
160
|
)}
|
|
170
161
|
<Badge variant="outline" className="text-xs">
|
|
171
|
-
{
|
|
172
|
-
? `#${
|
|
173
|
-
:
|
|
162
|
+
{release.is_pr_preview
|
|
163
|
+
? `#${release.github_pr_number}`
|
|
164
|
+
: "main"}
|
|
174
165
|
</Badge>
|
|
175
166
|
</div>
|
|
176
167
|
</TableCell>
|
|
177
168
|
<TableCell>
|
|
178
169
|
<div className="max-w-xs">
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
170
|
+
{latestBuild ? (
|
|
171
|
+
<p className="text-sm text-gray-600">
|
|
172
|
+
{formatTimeAgo(latestBuild.created_at)}
|
|
173
|
+
</p>
|
|
174
|
+
) : (
|
|
175
|
+
<p className="text-sm text-gray-400">
|
|
176
|
+
No builds
|
|
177
|
+
</p>
|
|
178
|
+
)}
|
|
182
179
|
</div>
|
|
183
180
|
</TableCell>
|
|
184
181
|
<TableCell>
|
|
185
182
|
<span className="text-sm text-gray-600">
|
|
186
|
-
{
|
|
187
|
-
</span>
|
|
188
|
-
</TableCell>
|
|
189
|
-
<TableCell>
|
|
190
|
-
<span className="text-sm text-gray-600">
|
|
191
|
-
{formatTimeAgo(build.created_at)}
|
|
183
|
+
{formatTimeAgo(release.created_at)}
|
|
192
184
|
</span>
|
|
193
185
|
</TableCell>
|
|
194
186
|
<TableCell>
|
|
@@ -205,14 +197,27 @@ export const BuildsList = ({
|
|
|
205
197
|
</DropdownMenuTrigger>
|
|
206
198
|
<DropdownMenuContent align="end">
|
|
207
199
|
<DropdownMenuItem
|
|
208
|
-
onClick={() =>
|
|
200
|
+
onClick={() => {
|
|
201
|
+
window.location.href = `/${pkg.name}/releases/${release.package_release_id}`
|
|
202
|
+
}}
|
|
209
203
|
>
|
|
210
|
-
View
|
|
204
|
+
View Release
|
|
211
205
|
</DropdownMenuItem>
|
|
206
|
+
{status !== "error" && (
|
|
207
|
+
<DropdownMenuItem>
|
|
208
|
+
<a
|
|
209
|
+
href={`/${pkg.name}/releases/${latestBuild?.package_release_id}/preview`}
|
|
210
|
+
>
|
|
211
|
+
Preview Release
|
|
212
|
+
</a>
|
|
213
|
+
</DropdownMenuItem>
|
|
214
|
+
)}
|
|
212
215
|
<DropdownMenuItem
|
|
213
|
-
onClick={() =>
|
|
216
|
+
onClick={() => {
|
|
217
|
+
window.location.href = `/${pkg.name}/releases/${release.package_release_id}/builds`
|
|
218
|
+
}}
|
|
214
219
|
>
|
|
215
|
-
View
|
|
220
|
+
View All Builds
|
|
216
221
|
</DropdownMenuItem>
|
|
217
222
|
</DropdownMenuContent>
|
|
218
223
|
</DropdownMenu>
|
|
@@ -226,94 +231,6 @@ export const BuildsList = ({
|
|
|
226
231
|
</div>
|
|
227
232
|
</CardContent>
|
|
228
233
|
</Card>
|
|
229
|
-
|
|
230
|
-
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
231
|
-
<Card>
|
|
232
|
-
<CardContent className="p-6">
|
|
233
|
-
<div className="flex items-center gap-3">
|
|
234
|
-
<div className="p-2 bg-green-100 rounded-lg">
|
|
235
|
-
<CheckCircle className="w-5 h-5 text-green-600" />
|
|
236
|
-
</div>
|
|
237
|
-
<div>
|
|
238
|
-
<p className="text-sm text-gray-600">Successful</p>
|
|
239
|
-
{isLoading ? (
|
|
240
|
-
<Skeleton className="h-8 w-8" />
|
|
241
|
-
) : (
|
|
242
|
-
<p className="text-2xl font-bold text-gray-900">
|
|
243
|
-
{builds?.filter(
|
|
244
|
-
(d) => getBuildStatus(d).status === "success",
|
|
245
|
-
).length || 0}
|
|
246
|
-
</p>
|
|
247
|
-
)}
|
|
248
|
-
</div>
|
|
249
|
-
</div>
|
|
250
|
-
</CardContent>
|
|
251
|
-
</Card>
|
|
252
|
-
|
|
253
|
-
<Card>
|
|
254
|
-
<CardContent className="p-6">
|
|
255
|
-
<div className="flex items-center gap-3">
|
|
256
|
-
<div className="p-2 bg-red-100 rounded-lg">
|
|
257
|
-
<AlertCircle className="w-5 h-5 text-red-600" />
|
|
258
|
-
</div>
|
|
259
|
-
<div>
|
|
260
|
-
<p className="text-sm text-gray-600">Failed</p>
|
|
261
|
-
{isLoading ? (
|
|
262
|
-
<Skeleton className="h-8 w-8" />
|
|
263
|
-
) : (
|
|
264
|
-
<p className="text-2xl font-bold text-gray-900">
|
|
265
|
-
{builds?.filter(
|
|
266
|
-
(d) => getBuildStatus(d).status === "error",
|
|
267
|
-
).length || 0}
|
|
268
|
-
</p>
|
|
269
|
-
)}
|
|
270
|
-
</div>
|
|
271
|
-
</div>
|
|
272
|
-
</CardContent>
|
|
273
|
-
</Card>
|
|
274
|
-
|
|
275
|
-
<Card>
|
|
276
|
-
<CardContent className="p-6">
|
|
277
|
-
<div className="flex items-center gap-3">
|
|
278
|
-
<div className="p-2 bg-blue-100 rounded-lg">
|
|
279
|
-
<Loader2 className="w-5 h-5 text-blue-600 animate-spin" />
|
|
280
|
-
</div>
|
|
281
|
-
<div>
|
|
282
|
-
<p className="text-sm text-gray-600">Building</p>
|
|
283
|
-
{isLoading ? (
|
|
284
|
-
<Skeleton className="h-8 w-8" />
|
|
285
|
-
) : (
|
|
286
|
-
<p className="text-2xl font-bold text-gray-900">
|
|
287
|
-
{builds?.filter(
|
|
288
|
-
(d) => getBuildStatus(d).status === "building",
|
|
289
|
-
).length || 0}
|
|
290
|
-
</p>
|
|
291
|
-
)}
|
|
292
|
-
</div>
|
|
293
|
-
</div>
|
|
294
|
-
</CardContent>
|
|
295
|
-
</Card>
|
|
296
|
-
|
|
297
|
-
<Card>
|
|
298
|
-
<CardContent className="p-6">
|
|
299
|
-
<div className="flex items-center gap-3">
|
|
300
|
-
<div className="p-2 bg-gray-100 rounded-lg">
|
|
301
|
-
<Clock className="w-5 h-5 text-gray-600" />
|
|
302
|
-
</div>
|
|
303
|
-
<div>
|
|
304
|
-
<p className="text-sm text-gray-600">Total</p>
|
|
305
|
-
{isLoading ? (
|
|
306
|
-
<Skeleton className="h-8 w-8" />
|
|
307
|
-
) : (
|
|
308
|
-
<p className="text-2xl font-bold text-gray-900">
|
|
309
|
-
{builds?.length || 0}
|
|
310
|
-
</p>
|
|
311
|
-
)}
|
|
312
|
-
</div>
|
|
313
|
-
</div>
|
|
314
|
-
</CardContent>
|
|
315
|
-
</Card>
|
|
316
|
-
</div>
|
|
317
234
|
</div>
|
|
318
235
|
</>
|
|
319
236
|
)
|
|
@@ -1,52 +1,83 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Card, CardContent, CardHeader } from "@/components/ui/card"
|
|
1
|
+
import { Card } from "@/components/ui/card"
|
|
3
2
|
import { Badge } from "@/components/ui/badge"
|
|
4
3
|
import { Button } from "@/components/ui/button"
|
|
5
4
|
import { GitBranch, Rocket, Github } from "lucide-react"
|
|
6
5
|
import { cn } from "@/lib/utils"
|
|
7
6
|
import { PrefetchPageLink } from "../PrefetchPageLink"
|
|
8
7
|
import { formatTimeAgo } from "@/lib/utils/formatTimeAgo"
|
|
8
|
+
import { getBuildStatus, StatusIcon } from "."
|
|
9
|
+
import { Package } from "fake-snippets-api/lib/db/schema"
|
|
10
|
+
import { usePackageBuild } from "@/hooks/use-package-builds"
|
|
9
11
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
StatusIcon,
|
|
14
|
-
} from "."
|
|
15
|
-
import { Package, PackageBuild } from "fake-snippets-api/lib/db/schema"
|
|
16
|
-
import { useLatestPackageBuild } from "@/hooks/use-package-builds"
|
|
12
|
+
useLatestPackageRelease,
|
|
13
|
+
usePackageReleaseById,
|
|
14
|
+
} from "@/hooks/use-package-release"
|
|
17
15
|
|
|
18
16
|
export const ConnectedPackageCardSkeleton = () => {
|
|
19
17
|
return (
|
|
20
|
-
<Card
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
18
|
+
<Card
|
|
19
|
+
className={cn(
|
|
20
|
+
"group relative overflow-hidden",
|
|
21
|
+
"border border-gray-200",
|
|
22
|
+
"hover:border-gray-300",
|
|
23
|
+
"bg-white shadow-none",
|
|
24
|
+
"p-6",
|
|
25
|
+
"flex flex-col",
|
|
26
|
+
"min-h-[200px]",
|
|
27
|
+
"animate-pulse",
|
|
28
|
+
)}
|
|
29
|
+
>
|
|
30
|
+
<div className="flex items-start justify-between mb-4">
|
|
31
|
+
<div className="flex items-center gap-3">
|
|
32
|
+
<div className="h-6 w-32 bg-gray-200 rounded" />
|
|
33
33
|
</div>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<div className="w-16 h-3 bg-gray-200 rounded" />
|
|
39
|
-
<div className="w-20 h-3 bg-gray-200 rounded" />
|
|
34
|
+
|
|
35
|
+
<div className="flex items-center justify-center gap-2">
|
|
36
|
+
<div className="w-16 h-5 bg-gray-200 rounded-full" />
|
|
37
|
+
<div className="w-4 h-4 bg-gray-200 rounded-full" />
|
|
40
38
|
</div>
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div className="flex items-center gap-2 mb-4">
|
|
42
|
+
<div className="w-4 h-4 bg-gray-200 rounded" />
|
|
43
|
+
<div className="w-48 h-5 bg-gray-200 rounded" />
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div className="mb-6 flex-1">
|
|
47
|
+
<div className="h-5 w-3/4 bg-gray-200 rounded mb-2" />
|
|
48
|
+
<div className="flex items-center gap-2">
|
|
49
|
+
<div className="w-32 h-4 bg-gray-200 rounded" />
|
|
50
|
+
<div className="flex items-center gap-1">
|
|
51
|
+
<div className="w-3 h-3 bg-gray-200 rounded" />
|
|
52
|
+
<div className="w-16 h-4 bg-gray-200 rounded-full" />
|
|
53
|
+
</div>
|
|
44
54
|
</div>
|
|
45
|
-
</
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<div className="flex gap-2 w-full mt-auto">
|
|
58
|
+
<div className="w-full h-9 bg-gray-200 rounded" />
|
|
59
|
+
<div className="w-full h-9 bg-gray-200 rounded" />
|
|
60
|
+
</div>
|
|
46
61
|
</Card>
|
|
47
62
|
)
|
|
48
63
|
}
|
|
49
64
|
|
|
65
|
+
// Custom hook to get latest package build info
|
|
66
|
+
const useLatestPackageBuildInfo = (packageId: string) => {
|
|
67
|
+
const { data: latestRelease, isLoading: releaseLoading } =
|
|
68
|
+
useLatestPackageRelease(packageId)
|
|
69
|
+
const { data: latestBuild, isLoading: buildLoading } = usePackageBuild(
|
|
70
|
+
latestRelease?.latest_package_build_id || null,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
data: latestBuild,
|
|
75
|
+
isLoading:
|
|
76
|
+
releaseLoading ||
|
|
77
|
+
(latestRelease?.latest_package_build_id && buildLoading),
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
50
81
|
export const ConnectedPackageCard = ({
|
|
51
82
|
pkg,
|
|
52
83
|
className,
|
|
@@ -54,9 +85,13 @@ export const ConnectedPackageCard = ({
|
|
|
54
85
|
pkg: Package
|
|
55
86
|
className?: string
|
|
56
87
|
}) => {
|
|
57
|
-
const { data: latestBuildInfo, isLoading } =
|
|
58
|
-
|
|
59
|
-
|
|
88
|
+
const { data: latestBuildInfo, isLoading } = useLatestPackageBuildInfo(
|
|
89
|
+
pkg.package_id,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
const { data: packageRelease } = usePackageReleaseById(
|
|
93
|
+
latestBuildInfo?.package_release_id,
|
|
94
|
+
)
|
|
60
95
|
|
|
61
96
|
if (isLoading && !latestBuildInfo) {
|
|
62
97
|
return <ConnectedPackageCardSkeleton />
|
|
@@ -72,7 +107,7 @@ export const ConnectedPackageCard = ({
|
|
|
72
107
|
"group relative overflow-hidden",
|
|
73
108
|
"border border-gray-200",
|
|
74
109
|
"hover:border-gray-300",
|
|
75
|
-
"bg-white",
|
|
110
|
+
"bg-white shadow-none",
|
|
76
111
|
"p-6",
|
|
77
112
|
"flex flex-col",
|
|
78
113
|
"min-h-[200px]",
|
|
@@ -118,46 +153,41 @@ export const ConnectedPackageCard = ({
|
|
|
118
153
|
</a>
|
|
119
154
|
</div>
|
|
120
155
|
|
|
121
|
-
|
|
122
|
-
|
|
156
|
+
<div className="mb-6 flex-1">
|
|
157
|
+
{packageRelease?.commit_message && (
|
|
123
158
|
<h4
|
|
124
|
-
title={
|
|
159
|
+
title={packageRelease.commit_message}
|
|
125
160
|
className="text-sm font-medium truncate text-gray-900 mb-2"
|
|
126
161
|
>
|
|
127
|
-
{
|
|
162
|
+
{packageRelease.commit_message}
|
|
128
163
|
</h4>
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
</
|
|
164
|
+
)}
|
|
165
|
+
<div className="flex items-center gap-2 text-xs text-gray-500">
|
|
166
|
+
<span>{formatTimeAgo(String(latestBuildInfo?.created_at))} on</span>
|
|
167
|
+
<div className="flex items-center gap-1">
|
|
168
|
+
<GitBranch className="w-3 h-3" />
|
|
169
|
+
<span className="bg-blue-100 text-blue-800 px-2 py-0.5 rounded-full font-medium">
|
|
170
|
+
{packageRelease?.branch_name || "main"}
|
|
171
|
+
</span>
|
|
137
172
|
</div>
|
|
138
173
|
</div>
|
|
139
|
-
|
|
174
|
+
</div>
|
|
140
175
|
|
|
141
176
|
<div className="flex gap-2 w-full mt-auto">
|
|
142
|
-
|
|
143
|
-
<
|
|
144
|
-
|
|
145
|
-
|
|
177
|
+
<PrefetchPageLink className="w-full" href={`/${pkg.name}/releases`}>
|
|
178
|
+
<Button
|
|
179
|
+
size="sm"
|
|
180
|
+
className="bg-blue-600 w-full hover:bg-blue-700 text-white px-4 py-2"
|
|
146
181
|
>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
>
|
|
151
|
-
View
|
|
152
|
-
</Button>
|
|
153
|
-
</PrefetchPageLink>
|
|
154
|
-
)}
|
|
182
|
+
View
|
|
183
|
+
</Button>
|
|
184
|
+
</PrefetchPageLink>
|
|
155
185
|
{latestBuildInfo?.preview_url &&
|
|
156
186
|
latestBuildInfo?.package_build_id &&
|
|
157
187
|
status === "success" && (
|
|
158
188
|
<PrefetchPageLink
|
|
159
189
|
className="w-full"
|
|
160
|
-
href={
|
|
190
|
+
href={`/${pkg.name}/releases/${latestBuildInfo.package_release_id}/preview`}
|
|
161
191
|
>
|
|
162
192
|
<Button size="sm" variant="outline" className="px-4 py-2 w-full">
|
|
163
193
|
Preview
|