@tscircuit/fake-snippets 0.0.26 → 0.0.28
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/bun-tests/fake-snippets-api/routes/package_files/create.test.ts +5 -6
- package/bun-tests/fake-snippets-api/routes/packages/list-1.test.ts +3 -0
- package/bun-tests/fake-snippets-api/routes/packages/list-2.test.ts +2 -0
- package/bun-tests/fake-snippets-api/routes/snippets/list_newest.test.ts +5 -3
- package/bun-tests/fake-snippets-api/routes/snippets/list_trending.test.ts +8 -5
- package/bun-tests/fake-snippets-api/routes/snippets/update.test.ts +1 -1
- package/bun.lock +110 -5
- package/dist/bundle.js +62 -11
- package/dist/index.d.ts +5 -0
- package/dist/index.js +4 -2
- package/fake-snippets-api/lib/db/autoload-snippets.json +4 -0
- package/fake-snippets-api/lib/db/db-client.ts +2 -1
- package/fake-snippets-api/lib/db/schema.ts +1 -0
- package/fake-snippets-api/lib/public-mapping/public-map-package.ts +1 -0
- package/fake-snippets-api/routes/api/package_files/list.ts +6 -3
- package/fake-snippets-api/routes/api/package_releases/get.ts +67 -1
- package/fake-snippets-api/routes/api/packages/create.ts +2 -1
- package/fake-snippets-api/routes/api/snippets/create.ts +1 -0
- package/package.json +2 -1
- package/public/placeholder-logo.png +0 -0
- package/public/placeholder-logo.svg +1 -0
- package/public/placeholder-user.jpg +0 -0
- package/public/placeholder.jpg +0 -0
- package/public/placeholder.svg +1 -0
- package/src/App.tsx +6 -0
- package/src/components/ViewPackagePage/components/ShikiCodeViewer.tsx +50 -0
- package/src/components/ViewPackagePage/components/file-explorer.tsx +118 -0
- package/src/components/ViewPackagePage/components/important-files-view.tsx +231 -0
- package/src/components/ViewPackagePage/components/main-content-header.tsx +172 -0
- package/src/components/ViewPackagePage/components/main-content-view-selector.tsx +106 -0
- package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +130 -0
- package/src/components/ViewPackagePage/components/package-header.tsx +107 -0
- package/src/components/ViewPackagePage/components/preview-image-squares.tsx +63 -0
- package/src/components/ViewPackagePage/components/readme-view.tsx +58 -0
- package/src/components/ViewPackagePage/components/repo-header-button.tsx +36 -0
- package/src/components/ViewPackagePage/components/repo-header.tsx +4 -0
- package/src/components/ViewPackagePage/components/repo-page-content.tsx +213 -0
- package/src/components/ViewPackagePage/components/repo-tab-header.tsx +12 -0
- package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +103 -0
- package/src/components/ViewPackagePage/components/sidebar-contributors-section.tsx +31 -0
- package/src/components/ViewPackagePage/components/sidebar-packages-section.tsx +16 -0
- package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +44 -0
- package/src/components/ViewPackagePage/components/sidebar.tsx +40 -0
- package/src/components/ViewPackagePage/components/tab-views/3d-view.tsx +9 -0
- package/src/components/ViewPackagePage/components/tab-views/bom-view.tsx +9 -0
- package/src/components/ViewPackagePage/components/tab-views/files-view.tsx +166 -0
- package/src/components/ViewPackagePage/components/tab-views/pcb-view.tsx +9 -0
- package/src/components/ViewPackagePage/components/tab-views/schematic-view.tsx +9 -0
- package/src/components/ViewPackagePage/components/theme-toggle.tsx +42 -0
- package/src/components/ViewPackagePage/hooks/use-mobile.tsx +19 -0
- package/src/components/ViewPackagePage/hooks/use-toast.ts +191 -0
- package/src/components/ViewPackagePage/simulate-page.tsx +120 -0
- package/src/components/ViewPackagePage/utils/is-package-file-important.ts +21 -0
- package/src/hooks/use-package-files.ts +29 -0
- package/src/hooks/use-package-release.ts +22 -0
- package/src/index.css +15 -0
- package/src/pages/beta.tsx +282 -99
- package/src/pages/view-package.tsx +38 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const importanceMap = {
|
|
2
|
+
"readme.md": 200,
|
|
3
|
+
license: 100,
|
|
4
|
+
"license.md": 100,
|
|
5
|
+
"index.ts": 90,
|
|
6
|
+
"index.tsx": 90,
|
|
7
|
+
"circuit.tsx": 90,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const scorePackageFileImportance = (filePath: string) => {
|
|
11
|
+
for (const [key, value] of Object.entries(importanceMap)) {
|
|
12
|
+
if (filePath.endsWith(key)) {
|
|
13
|
+
return value
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return 0
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const isPackageFileImportant = (filePath: string) => {
|
|
20
|
+
return scorePackageFileImportance(filePath) > 0
|
|
21
|
+
}
|
|
@@ -82,3 +82,32 @@ export const usePackageFileByRelease = (
|
|
|
82
82
|
: null,
|
|
83
83
|
)
|
|
84
84
|
}
|
|
85
|
+
|
|
86
|
+
// Hook to list all files for a package release
|
|
87
|
+
export const usePackageFiles = (packageReleaseId?: string | null) => {
|
|
88
|
+
const axios = useAxios()
|
|
89
|
+
|
|
90
|
+
return useQuery<PackageFile[], Error & { status: number }>(
|
|
91
|
+
["packageFiles", packageReleaseId],
|
|
92
|
+
async () => {
|
|
93
|
+
if (!packageReleaseId) return []
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
const { data } = await axios.post("/package_files/list", {
|
|
97
|
+
package_release_id: packageReleaseId,
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
if (!data.package_files) {
|
|
101
|
+
return []
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return data.package_files
|
|
105
|
+
} catch (error) {
|
|
106
|
+
throw error
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
enabled: Boolean(packageReleaseId),
|
|
111
|
+
},
|
|
112
|
+
)
|
|
113
|
+
}
|
|
@@ -9,6 +9,14 @@ type PackageReleaseQuery =
|
|
|
9
9
|
| {
|
|
10
10
|
package_name_with_version: string
|
|
11
11
|
}
|
|
12
|
+
| {
|
|
13
|
+
package_name: string
|
|
14
|
+
is_latest: boolean
|
|
15
|
+
}
|
|
16
|
+
| {
|
|
17
|
+
package_id: string
|
|
18
|
+
is_latest: boolean
|
|
19
|
+
}
|
|
12
20
|
|
|
13
21
|
export const usePackageRelease = (query: PackageReleaseQuery | null) => {
|
|
14
22
|
const axios = useAxios()
|
|
@@ -49,3 +57,17 @@ export const usePackageReleaseByNameAndVersion = (
|
|
|
49
57
|
: null,
|
|
50
58
|
)
|
|
51
59
|
}
|
|
60
|
+
|
|
61
|
+
export const useLatestPackageRelease = (
|
|
62
|
+
packageId?: string | null,
|
|
63
|
+
packageName?: string | null,
|
|
64
|
+
) => {
|
|
65
|
+
// Prioritize packageName if both are provided
|
|
66
|
+
const query = packageName
|
|
67
|
+
? { package_name: packageName, is_latest: true }
|
|
68
|
+
: packageId
|
|
69
|
+
? { package_id: packageId, is_latest: true }
|
|
70
|
+
: null
|
|
71
|
+
|
|
72
|
+
return usePackageRelease(query)
|
|
73
|
+
}
|
package/src/index.css
CHANGED
|
@@ -19,3 +19,18 @@
|
|
|
19
19
|
.animate-fadeIn {
|
|
20
20
|
animation: fadeIn 0.3s ease-in-out;
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
.shiki code {
|
|
24
|
+
counter-reset: step;
|
|
25
|
+
counter-increment: step 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.shiki code .line::before {
|
|
29
|
+
content: counter(step);
|
|
30
|
+
counter-increment: step;
|
|
31
|
+
width: 1rem;
|
|
32
|
+
margin-right: 1.5rem;
|
|
33
|
+
display: inline-block;
|
|
34
|
+
text-align: right;
|
|
35
|
+
color: rgba(115, 138, 148, 0.4);
|
|
36
|
+
}
|
package/src/pages/beta.tsx
CHANGED
|
@@ -3,16 +3,81 @@ import { useCreatePackageMutation } from "@/hooks/use-create-package-mutation"
|
|
|
3
3
|
import { useCreatePackageReleaseMutation } from "@/hooks/use-create-package-release-mutation"
|
|
4
4
|
import { useForkPackageMutation } from "@/hooks/use-fork-package-mutation"
|
|
5
5
|
import { usePackageById } from "@/hooks/use-package-by-package-id"
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { usePackageByName } from "@/hooks/use-package-by-package-name"
|
|
7
|
+
import { usePackageFile, usePackageFiles } from "@/hooks/use-package-files"
|
|
8
|
+
import {
|
|
9
|
+
useLatestPackageRelease,
|
|
10
|
+
usePackageRelease,
|
|
11
|
+
usePackageReleaseByNameAndVersion,
|
|
12
|
+
} from "@/hooks/use-package-release"
|
|
13
|
+
import { useEffect, useState } from "react"
|
|
14
|
+
import { useLocation } from "wouter"
|
|
9
15
|
|
|
10
16
|
export const BetaPage = () => {
|
|
17
|
+
// Get the current path and extract author/packageName
|
|
18
|
+
const [location] = useLocation()
|
|
19
|
+
const pathParts = location.split("/")
|
|
20
|
+
const author = pathParts[2]
|
|
21
|
+
const urlPackageName = pathParts[3]
|
|
22
|
+
const packageNameWithVersion =
|
|
23
|
+
author && urlPackageName ? `${author}/${urlPackageName}` : null
|
|
24
|
+
|
|
25
|
+
// States for package creation flow
|
|
11
26
|
const [createdPackageId, setCreatedPackageId] = useState<string | null>(null)
|
|
12
27
|
const [createdReleaseId, setCreatedReleaseId] = useState<string | null>(null)
|
|
13
28
|
const [createdFileId, setCreatedFileId] = useState<string | null>(null)
|
|
14
29
|
const [forkedPackageId, setForkedPackageId] = useState<string | null>(null)
|
|
15
30
|
const [packageName, setPackageName] = useState("")
|
|
31
|
+
const [selectedFileId, setSelectedFileId] = useState<string | null>(null)
|
|
32
|
+
const [isLoading, setIsLoading] = useState(!!packageNameWithVersion)
|
|
33
|
+
|
|
34
|
+
// Load existing package if URL params are provided
|
|
35
|
+
const { data: existingPackage, isSuccess: packageLoaded } = usePackageByName(
|
|
36
|
+
packageNameWithVersion,
|
|
37
|
+
)
|
|
38
|
+
// Use the new hook instead of usePackageReleaseByNameAndVersion
|
|
39
|
+
const { data: existingRelease, isSuccess: releaseLoaded } =
|
|
40
|
+
useLatestPackageRelease(existingPackage?.package_id)
|
|
41
|
+
|
|
42
|
+
// Log for debugging
|
|
43
|
+
console.log("Location path:", location)
|
|
44
|
+
console.log("Author:", author, "Package:", urlPackageName)
|
|
45
|
+
console.log("Package name with version:", packageNameWithVersion)
|
|
46
|
+
console.log("Existing package:", existingPackage)
|
|
47
|
+
console.log("Existing release:", existingRelease)
|
|
48
|
+
|
|
49
|
+
// Set IDs from existing package when they're loaded
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (existingPackage) {
|
|
52
|
+
console.log("Setting package ID:", existingPackage.package_id)
|
|
53
|
+
setCreatedPackageId(existingPackage.package_id)
|
|
54
|
+
setPackageName(existingPackage.name)
|
|
55
|
+
}
|
|
56
|
+
}, [existingPackage])
|
|
57
|
+
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (existingRelease) {
|
|
60
|
+
console.log("Setting release ID:", existingRelease.package_release_id)
|
|
61
|
+
setCreatedReleaseId(existingRelease.package_release_id)
|
|
62
|
+
|
|
63
|
+
// Force refetch package files by setting a dummy state to trigger useEffect
|
|
64
|
+
setTimeout(() => {
|
|
65
|
+
console.log("Triggering files refetch...")
|
|
66
|
+
setIsLoading(false)
|
|
67
|
+
}, 500)
|
|
68
|
+
}
|
|
69
|
+
}, [existingRelease])
|
|
70
|
+
|
|
71
|
+
// Update loading state
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
if (packageNameWithVersion) {
|
|
74
|
+
if (packageLoaded && releaseLoaded) {
|
|
75
|
+
setIsLoading(false)
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
setIsLoading(false)
|
|
79
|
+
}
|
|
80
|
+
}, [packageNameWithVersion, packageLoaded, releaseLoaded])
|
|
16
81
|
|
|
17
82
|
// Demo data
|
|
18
83
|
const demoData = {
|
|
@@ -58,122 +123,240 @@ export const BetaPage = () => {
|
|
|
58
123
|
onSuccess: (forkedPackage) => setForkedPackageId(forkedPackage.package_id),
|
|
59
124
|
})
|
|
60
125
|
|
|
126
|
+
// Package data
|
|
61
127
|
const { data: packageData } = usePackageById(createdPackageId)
|
|
62
|
-
|
|
63
|
-
|
|
128
|
+
|
|
129
|
+
// Package release data
|
|
130
|
+
const { data: releaseData } = useLatestPackageRelease(createdPackageId, null)
|
|
131
|
+
|
|
132
|
+
// All package files for the release
|
|
133
|
+
const { data: packageFiles, isLoading: filesLoading } =
|
|
134
|
+
usePackageFiles(createdReleaseId)
|
|
135
|
+
|
|
136
|
+
// Log the files data for debugging
|
|
137
|
+
console.log(
|
|
138
|
+
"Package files:",
|
|
139
|
+
packageFiles,
|
|
140
|
+
"createdReleaseId:",
|
|
141
|
+
createdReleaseId,
|
|
64
142
|
)
|
|
65
|
-
|
|
66
|
-
|
|
143
|
+
|
|
144
|
+
// Individual file data when selected
|
|
145
|
+
const { data: selectedFileData } = usePackageFile(
|
|
146
|
+
selectedFileId ? { package_file_id: selectedFileId } : null,
|
|
67
147
|
)
|
|
148
|
+
|
|
68
149
|
const { data: forkedPackageData } = usePackageById(forkedPackageId)
|
|
69
150
|
|
|
151
|
+
if (isLoading) {
|
|
152
|
+
return (
|
|
153
|
+
<div className="p-4">
|
|
154
|
+
<h2 className="text-lg font-semibold mb-4">Loading package data...</h2>
|
|
155
|
+
</div>
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
|
|
70
159
|
return (
|
|
71
160
|
<div className="p-4">
|
|
72
|
-
<h1 className="text-xl font-bold mb-4">
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
161
|
+
<h1 className="text-xl font-bold mb-4">
|
|
162
|
+
{packageNameWithVersion
|
|
163
|
+
? `Package: ${packageNameWithVersion}`
|
|
164
|
+
: "Package Management Demo"}
|
|
165
|
+
</h1>
|
|
166
|
+
{!packageNameWithVersion && (
|
|
167
|
+
<div className="mb-4">
|
|
168
|
+
<div className="flex items-center gap-2">
|
|
169
|
+
<input
|
|
170
|
+
type="text"
|
|
171
|
+
value={packageName}
|
|
172
|
+
onChange={(e) => setPackageName(e.target.value)}
|
|
173
|
+
placeholder="test-package"
|
|
174
|
+
className="flex-1 px-3 py-2 border rounded text-sm"
|
|
175
|
+
disabled={Boolean(createdPackageId)}
|
|
176
|
+
/>
|
|
177
|
+
</div>
|
|
83
178
|
</div>
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
179
|
+
)}
|
|
180
|
+
|
|
181
|
+
{/* Package creation UI only shown when not viewing an existing package */}
|
|
182
|
+
{!packageNameWithVersion && (
|
|
183
|
+
<div className="grid grid-cols-4 gap-4 mb-4">
|
|
184
|
+
{/* Package Creation */}
|
|
185
|
+
<div className="bg-white p-4 rounded-lg shadow">
|
|
186
|
+
<div className="flex items-center justify-between mb-2">
|
|
187
|
+
<h2 className="font-semibold">1. Create Package</h2>
|
|
188
|
+
<button
|
|
189
|
+
onClick={() => createPackage(demoData.package)}
|
|
190
|
+
disabled={
|
|
191
|
+
isCreatingPackage || Boolean(createdPackageId) || !packageName
|
|
192
|
+
}
|
|
193
|
+
className="bg-blue-500 text-white px-3 py-1 text-sm rounded hover:bg-blue-600 disabled:bg-blue-300"
|
|
194
|
+
>
|
|
195
|
+
{createdPackageId ? "✓" : "Create"}
|
|
196
|
+
</button>
|
|
197
|
+
</div>
|
|
198
|
+
{packageData && (
|
|
199
|
+
<pre className="text-xs bg-gray-50 p-2 rounded overflow-auto max-h-32">
|
|
200
|
+
{JSON.stringify(packageData, null, 2)}
|
|
201
|
+
</pre>
|
|
202
|
+
)}
|
|
203
|
+
</div>
|
|
204
|
+
|
|
205
|
+
{/* Release Creation */}
|
|
206
|
+
<div className="bg-white p-4 rounded-lg shadow">
|
|
207
|
+
<div className="flex items-center justify-between mb-2">
|
|
208
|
+
<h2 className="font-semibold">2. Create Release</h2>
|
|
209
|
+
<button
|
|
210
|
+
onClick={() =>
|
|
211
|
+
createdPackageId &&
|
|
212
|
+
createRelease({
|
|
213
|
+
package_id: createdPackageId,
|
|
214
|
+
...demoData.release,
|
|
215
|
+
})
|
|
216
|
+
}
|
|
217
|
+
disabled={!createdPackageId || Boolean(createdReleaseId)}
|
|
218
|
+
className="bg-blue-500 text-white px-3 py-1 text-sm rounded hover:bg-blue-600 disabled:bg-blue-300"
|
|
219
|
+
>
|
|
220
|
+
{createdReleaseId ? "✓" : "Create"}
|
|
221
|
+
</button>
|
|
222
|
+
</div>
|
|
223
|
+
{releaseData && (
|
|
224
|
+
<pre className="text-xs bg-gray-50 p-2 rounded overflow-auto max-h-32">
|
|
225
|
+
{JSON.stringify(releaseData, null, 2)}
|
|
226
|
+
</pre>
|
|
227
|
+
)}
|
|
228
|
+
</div>
|
|
229
|
+
|
|
230
|
+
{/* File Creation */}
|
|
231
|
+
<div className="bg-white p-4 rounded-lg shadow">
|
|
232
|
+
<div className="flex items-center justify-between mb-2">
|
|
233
|
+
<h2 className="font-semibold">3. Create Files</h2>
|
|
234
|
+
<button
|
|
235
|
+
onClick={() =>
|
|
236
|
+
createdReleaseId &&
|
|
237
|
+
Promise.all(
|
|
238
|
+
demoData.files.map((file) =>
|
|
239
|
+
createFile({
|
|
240
|
+
package_release_id: createdReleaseId,
|
|
241
|
+
...file,
|
|
242
|
+
}),
|
|
243
|
+
),
|
|
244
|
+
)
|
|
245
|
+
}
|
|
246
|
+
disabled={!createdReleaseId || Boolean(createdFileId)}
|
|
247
|
+
className="bg-blue-500 text-white px-3 py-1 text-sm rounded hover:bg-blue-600 disabled:bg-blue-300"
|
|
248
|
+
>
|
|
249
|
+
{createdFileId ? "✓" : "Create"}
|
|
250
|
+
</button>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
|
|
254
|
+
{/* Fork Package */}
|
|
255
|
+
<div className="bg-white p-4 rounded-lg shadow">
|
|
256
|
+
<div className="flex items-center justify-between mb-2">
|
|
257
|
+
<h2 className="font-semibold">4. Fork Package</h2>
|
|
258
|
+
<button
|
|
259
|
+
onClick={() =>
|
|
260
|
+
createdPackageId && forkPackage(createdPackageId)
|
|
261
|
+
}
|
|
262
|
+
disabled={!createdPackageId || isForking}
|
|
263
|
+
className="bg-green-500 text-white px-3 py-1 text-sm rounded hover:bg-green-600 disabled:bg-green-300"
|
|
264
|
+
>
|
|
265
|
+
{forkedPackageId ? "✓" : "Fork"}
|
|
266
|
+
</button>
|
|
267
|
+
</div>
|
|
268
|
+
{forkedPackageData && (
|
|
269
|
+
<pre className="text-xs bg-gray-50 p-2 rounded overflow-auto max-h-32">
|
|
270
|
+
{JSON.stringify(forkedPackageData, null, 2)}
|
|
271
|
+
</pre>
|
|
272
|
+
)}
|
|
99
273
|
</div>
|
|
100
|
-
{packageData && (
|
|
101
|
-
<pre className="text-xs bg-gray-50 p-2 rounded overflow-auto max-h-40">
|
|
102
|
-
{JSON.stringify(packageData, null, 2)}
|
|
103
|
-
</pre>
|
|
104
|
-
)}
|
|
105
274
|
</div>
|
|
275
|
+
)}
|
|
106
276
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
className="
|
|
121
|
-
>
|
|
122
|
-
|
|
123
|
-
|
|
277
|
+
{/* Package info section shown when viewing an existing package */}
|
|
278
|
+
{packageNameWithVersion && packageData && (
|
|
279
|
+
<div className="bg-white p-4 rounded-lg shadow mb-4">
|
|
280
|
+
<h2 className="font-semibold mb-3">Package Information</h2>
|
|
281
|
+
<div className="grid grid-cols-2 gap-4">
|
|
282
|
+
<div>
|
|
283
|
+
<div className="text-sm font-medium mb-1">ID:</div>
|
|
284
|
+
<div className="text-sm text-gray-700">
|
|
285
|
+
{packageData.package_id}
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
288
|
+
<div>
|
|
289
|
+
<div className="text-sm font-medium mb-1">Name:</div>
|
|
290
|
+
<div className="text-sm text-gray-700">{packageData.name}</div>
|
|
291
|
+
</div>
|
|
292
|
+
<div>
|
|
293
|
+
<div className="text-sm font-medium mb-1">Description:</div>
|
|
294
|
+
<div className="text-sm text-gray-700">
|
|
295
|
+
{packageData.description || "No description"}
|
|
296
|
+
</div>
|
|
297
|
+
</div>
|
|
298
|
+
<div>
|
|
299
|
+
<div className="text-sm font-medium mb-1">Visibility:</div>
|
|
300
|
+
<div className="text-sm text-gray-700">
|
|
301
|
+
{packageData.is_private ? "Private" : "Public"}
|
|
302
|
+
</div>
|
|
303
|
+
</div>
|
|
124
304
|
</div>
|
|
125
|
-
{releaseData && (
|
|
126
|
-
<pre className="text-xs bg-gray-50 p-2 rounded overflow-auto max-h-40">
|
|
127
|
-
{JSON.stringify(releaseData, null, 2)}
|
|
128
|
-
</pre>
|
|
129
|
-
)}
|
|
130
305
|
</div>
|
|
306
|
+
)}
|
|
131
307
|
|
|
132
|
-
|
|
308
|
+
{/* Second row: package data exploration */}
|
|
309
|
+
<div className="grid grid-cols-2 gap-6">
|
|
310
|
+
{/* Package Files List */}
|
|
133
311
|
<div className="bg-white p-4 rounded-lg shadow">
|
|
134
|
-
<
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
onClick={() =>
|
|
138
|
-
createdReleaseId &&
|
|
139
|
-
Promise.all(
|
|
140
|
-
demoData.files.map((file) =>
|
|
141
|
-
createFile({
|
|
142
|
-
package_release_id: createdReleaseId,
|
|
143
|
-
...file,
|
|
144
|
-
}),
|
|
145
|
-
),
|
|
146
|
-
)
|
|
147
|
-
}
|
|
148
|
-
disabled={!createdReleaseId || Boolean(createdFileId)}
|
|
149
|
-
className="bg-blue-500 text-white px-3 py-1 text-sm rounded hover:bg-blue-600 disabled:bg-blue-300"
|
|
150
|
-
>
|
|
151
|
-
{createdFileId ? "✓" : "Create"}
|
|
152
|
-
</button>
|
|
312
|
+
<h2 className="font-semibold mb-3">Package Files</h2>
|
|
313
|
+
<div className="text-xs text-gray-600 mb-2">
|
|
314
|
+
Release ID: {createdReleaseId || "None"}
|
|
153
315
|
</div>
|
|
154
|
-
{
|
|
155
|
-
<
|
|
156
|
-
|
|
157
|
-
|
|
316
|
+
{filesLoading ? (
|
|
317
|
+
<div className="text-sm text-gray-500">Loading files...</div>
|
|
318
|
+
) : packageFiles && packageFiles.length > 0 ? (
|
|
319
|
+
<div className="divide-y">
|
|
320
|
+
{packageFiles.map((file) => (
|
|
321
|
+
<button
|
|
322
|
+
key={file.package_file_id}
|
|
323
|
+
onClick={() => setSelectedFileId(file.package_file_id)}
|
|
324
|
+
className={`text-left w-full py-2 px-1 text-sm hover:bg-gray-50 ${
|
|
325
|
+
selectedFileId === file.package_file_id ? "bg-blue-50" : ""
|
|
326
|
+
}`}
|
|
327
|
+
>
|
|
328
|
+
{file.file_path}
|
|
329
|
+
</button>
|
|
330
|
+
))}
|
|
331
|
+
</div>
|
|
332
|
+
) : (
|
|
333
|
+
<div className="text-sm text-gray-500">
|
|
334
|
+
{createdReleaseId
|
|
335
|
+
? "No files found. Files array length: " +
|
|
336
|
+
(packageFiles ? packageFiles.length : "undefined")
|
|
337
|
+
: "Create a release and files first"}
|
|
338
|
+
</div>
|
|
158
339
|
)}
|
|
159
340
|
</div>
|
|
160
341
|
|
|
161
|
-
{/*
|
|
342
|
+
{/* Selected File Content */}
|
|
162
343
|
<div className="bg-white p-4 rounded-lg shadow">
|
|
163
|
-
<
|
|
164
|
-
|
|
165
|
-
<
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
<
|
|
175
|
-
{
|
|
176
|
-
|
|
344
|
+
<h2 className="font-semibold mb-3">File Content</h2>
|
|
345
|
+
{selectedFileData ? (
|
|
346
|
+
<div>
|
|
347
|
+
<div className="text-xs text-gray-500 mb-2">
|
|
348
|
+
{selectedFileData.file_path}
|
|
349
|
+
</div>
|
|
350
|
+
<pre className="text-xs bg-gray-50 p-3 rounded overflow-auto border max-h-80">
|
|
351
|
+
{selectedFileData.content_text}
|
|
352
|
+
</pre>
|
|
353
|
+
</div>
|
|
354
|
+
) : (
|
|
355
|
+
<div className="text-sm text-gray-500">
|
|
356
|
+
{packageFiles && packageFiles.length > 0
|
|
357
|
+
? "Select a file to view its content"
|
|
358
|
+
: "Create files first"}
|
|
359
|
+
</div>
|
|
177
360
|
)}
|
|
178
361
|
</div>
|
|
179
362
|
</div>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import RepoPageContent from "@/components/ViewPackagePage/components/repo-page-content"
|
|
2
|
+
import SimulatePage from "@/components/ViewPackagePage/simulate-page"
|
|
3
|
+
import { usePackageByName } from "@/hooks/use-package-by-package-name"
|
|
4
|
+
import { usePackageFiles } from "@/hooks/use-package-files"
|
|
5
|
+
import { usePackageRelease } from "@/hooks/use-package-release"
|
|
6
|
+
import { useLocation } from "wouter"
|
|
7
|
+
|
|
8
|
+
export const ViewPackagePage = () => {
|
|
9
|
+
// Get the current path and extract author/packageName
|
|
10
|
+
const [location] = useLocation()
|
|
11
|
+
const pathParts = location.split("/")
|
|
12
|
+
const author = pathParts[2]
|
|
13
|
+
const urlPackageName = pathParts[3]
|
|
14
|
+
const fullPackageName = `${author}/${urlPackageName}`
|
|
15
|
+
|
|
16
|
+
const { data: packageInfo } = usePackageByName(fullPackageName)
|
|
17
|
+
|
|
18
|
+
const { data: packageRelease } = usePackageRelease({
|
|
19
|
+
is_latest: true,
|
|
20
|
+
package_name: fullPackageName,
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const { data: packageFiles } = usePackageFiles(
|
|
24
|
+
packageRelease?.package_release_id,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<RepoPageContent
|
|
29
|
+
packageFiles={packageFiles as any}
|
|
30
|
+
packageInfo={packageInfo as any}
|
|
31
|
+
importantFilePaths={["README.md", "LICENSE", "package.json"]}
|
|
32
|
+
onFileClicked={() => {}}
|
|
33
|
+
onDirectoryClicked={() => {}}
|
|
34
|
+
onExportClicked={() => {}}
|
|
35
|
+
onEditClicked={() => {}}
|
|
36
|
+
/>
|
|
37
|
+
)
|
|
38
|
+
}
|