@tscircuit/fake-snippets 0.0.109 → 0.0.111
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/.github/workflows/bun-formatcheck.yml +2 -2
- package/.github/workflows/bun-pver-release.yml +3 -3
- package/.github/workflows/bun-test.yml +1 -1
- package/.github/workflows/bun-typecheck.yml +2 -2
- package/.github/workflows/update-snapshots.yml +1 -1
- package/README.md +4 -0
- package/api/generated-index.js +37 -3
- package/biome.json +2 -1
- package/bun-tests/fake-snippets-api/fixtures/get-test-server.ts +32 -3
- package/bun-tests/fake-snippets-api/fixtures/preload.ts +18 -0
- package/bun-tests/fake-snippets-api/routes/orgs/add_member.test.ts +26 -0
- package/bun-tests/fake-snippets-api/routes/orgs/create.test.ts +37 -0
- package/bun-tests/fake-snippets-api/routes/orgs/get.test.ts +52 -0
- package/bun-tests/fake-snippets-api/routes/orgs/list.test.ts +17 -0
- package/bun-tests/fake-snippets-api/routes/orgs/list_members.test.ts +23 -0
- package/bun-tests/fake-snippets-api/routes/orgs/remove_member.test.ts +81 -0
- package/bun-tests/fake-snippets-api/routes/orgs/update.test.ts +151 -0
- package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +1 -1
- package/bun-tests/fake-snippets-api/routes/package_files/create.test.ts +15 -13
- package/bun-tests/fake-snippets-api/routes/package_files/create_or_update.test.ts +26 -24
- package/bun-tests/fake-snippets-api/routes/package_files/delete.test.ts +9 -9
- package/bun-tests/fake-snippets-api/routes/package_files/download.test.ts +4 -4
- package/bun-tests/fake-snippets-api/routes/package_files/get.test.ts +38 -28
- package/bun-tests/fake-snippets-api/routes/package_files/list.test.ts +23 -15
- package/bun-tests/fake-snippets-api/routes/package_releases/create.test.ts +33 -0
- package/bun-tests/fake-snippets-api/routes/package_releases/get.test.ts +4 -4
- package/bun-tests/fake-snippets-api/routes/package_releases/get_image_generation_fields.test.ts +38 -0
- package/bun-tests/fake-snippets-api/routes/packages/create.test.ts +19 -0
- package/bun-tests/fake-snippets-api/routes/packages/fork.test.ts +3 -4
- package/bun-tests/fake-snippets-api/routes/packages/get.test.ts +30 -0
- package/bun-tests/fake-snippets-api/routes/packages/images.test.ts +4 -2
- package/bun-tests/fake-snippets-api/routes/packages/list-1.test.ts +34 -0
- package/bun.lock +361 -453
- package/bunfig.toml +2 -1
- package/dist/bundle.js +1313 -639
- package/dist/index.d.ts +313 -6
- package/dist/index.js +328 -24
- package/dist/schema.d.ts +290 -1
- package/dist/schema.js +54 -1
- package/fake-snippets-api/lib/db/autoload-dev-packages.ts +31 -20
- package/fake-snippets-api/lib/db/db-client.ts +219 -4
- package/fake-snippets-api/lib/db/schema.ts +63 -1
- package/fake-snippets-api/lib/db/seed.ts +100 -0
- package/fake-snippets-api/lib/middleware/with-session-auth.ts +60 -8
- package/fake-snippets-api/lib/package_file/get-package-file-id-from-file-descriptor.ts +2 -2
- package/fake-snippets-api/lib/public-mapping/public-map-org.ts +33 -0
- package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +10 -0
- package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +17 -0
- package/fake-snippets-api/routes/api/orgs/add_member.ts +52 -0
- package/fake-snippets-api/routes/api/orgs/create.ts +48 -0
- package/fake-snippets-api/routes/api/orgs/get.ts +39 -0
- package/fake-snippets-api/routes/api/orgs/list.ts +31 -0
- package/fake-snippets-api/routes/api/orgs/list_members.ts +60 -0
- package/fake-snippets-api/routes/api/orgs/remove_member.ts +46 -0
- package/fake-snippets-api/routes/api/orgs/update.ts +118 -0
- package/fake-snippets-api/routes/api/package_files/get.ts +3 -6
- package/fake-snippets-api/routes/api/package_files/list.ts +7 -4
- package/fake-snippets-api/routes/api/packages/create.ts +57 -10
- package/fake-snippets-api/routes/api/packages/get.ts +23 -0
- package/fake-snippets-api/routes/api/packages/images/[owner_github_username]/[unscoped_name]/[view_format].ts +13 -11
- package/fake-snippets-api/routes/api/packages/list.ts +29 -2
- package/fake-snippets-api/routes/api/packages/update_ai_description.ts +37 -0
- package/package.json +25 -19
- package/renovate.json +1 -1
- package/scripts/generate-sitemap.ts +1 -1
- package/src/App.tsx +27 -8
- package/src/ContextProviders.tsx +25 -2
- package/src/components/CircuitJsonImportDialog.tsx +1 -1
- package/src/components/CmdKMenu.tsx +281 -247
- package/src/components/DownloadButtonAndMenu.tsx +17 -5
- package/src/components/FileSidebar.tsx +11 -17
- package/src/components/Footer.tsx +8 -9
- package/src/components/Header.tsx +19 -32
- package/src/components/Header2.tsx +16 -32
- package/src/components/HeaderDropdown.tsx +13 -8
- package/src/components/HeaderLogin.tsx +43 -15
- package/src/components/NotFound.tsx +5 -5
- package/src/components/PackageBreadcrumb.tsx +6 -12
- package/src/components/PackageSearchResults.tsx +1 -1
- package/src/components/PrefetchPageLink.tsx +7 -1
- package/src/components/ProfileRouter.tsx +32 -0
- package/src/components/SearchComponent.tsx +12 -8
- package/src/components/SentryNotFoundReporter.tsx +44 -0
- package/src/components/UserCard.tsx +80 -0
- package/src/components/ViewPackagePage/components/build-status.tsx +1 -1
- package/src/components/ViewPackagePage/components/important-files-view.tsx +105 -34
- package/src/components/ViewPackagePage/components/main-content-header.tsx +10 -6
- package/src/components/ViewPackagePage/components/main-content-view-selector.tsx +1 -1
- package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +54 -19
- package/src/components/ViewPackagePage/components/package-header.tsx +25 -33
- package/src/components/ViewPackagePage/components/preview-image-squares.tsx +11 -18
- package/src/components/ViewPackagePage/components/repo-page-content.tsx +12 -5
- package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +16 -10
- package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +11 -11
- package/src/components/ViewPackagePage/components/tab-views/pcb-view.tsx +1 -2
- package/src/components/ViewPackagePage/components/tab-views/schematic-view.tsx +2 -1
- package/src/components/dialogs/GitHubRepositorySelector.tsx +56 -49
- package/src/components/dialogs/edit-package-details-dialog.tsx +5 -6
- package/src/components/dialogs/import-component-dialog.tsx +16 -9
- package/src/components/dialogs/import-package-dialog.tsx +3 -2
- package/src/components/dialogs/new-package-save-prompt-dialog.tsx +190 -0
- package/src/components/organization/OrganizationCard.tsx +206 -0
- package/src/components/organization/OrganizationCardSkeleton.tsx +55 -0
- package/src/components/organization/OrganizationHeader.tsx +154 -0
- package/src/components/organization/OrganizationMembers.tsx +146 -0
- package/src/components/package-port/CodeAndPreview.tsx +15 -12
- package/src/components/package-port/CodeEditor.tsx +4 -30
- package/src/components/package-port/CodeEditorHeader.tsx +123 -61
- package/src/components/package-port/EditorNav.tsx +32 -49
- package/src/components/preview/ConnectedPackagesList.tsx +8 -8
- package/src/components/preview/ConnectedRepoOverview.tsx +102 -2
- package/src/components/preview/PackageReleasesDashboard.tsx +23 -11
- package/src/components/ui/tree-view.tsx +6 -3
- package/src/hooks/use-add-org-member-mutation.ts +51 -0
- package/src/hooks/use-create-org-mutation.ts +38 -0
- package/src/hooks/use-create-package-mutation.ts +3 -0
- package/src/hooks/use-current-package-release.ts +4 -3
- package/src/hooks/use-download-zip.ts +2 -2
- package/src/hooks/use-global-store.ts +6 -4
- package/src/hooks/use-hydration.ts +30 -0
- package/src/hooks/use-jlcpcb-component-import.tsx +164 -0
- package/src/hooks/use-list-org-members.ts +27 -0
- package/src/hooks/use-list-user-orgs.ts +25 -0
- package/src/hooks/use-org-by-github-handle.ts +26 -0
- package/src/hooks/use-org.ts +24 -0
- package/src/hooks/use-organization.ts +42 -0
- package/src/hooks/use-package-as-snippet.ts +4 -2
- package/src/hooks/use-package-builds.ts +6 -2
- package/src/hooks/use-package-files.ts +5 -3
- package/src/hooks/use-package-release-by-id-or-version.ts +29 -20
- package/src/hooks/use-package-release-images.ts +105 -0
- package/src/hooks/use-package-release.ts +2 -2
- package/src/hooks/use-package-stars.ts +80 -4
- package/src/hooks/use-preview-images.ts +6 -3
- package/src/hooks/use-remove-org-member-mutation.ts +32 -0
- package/src/hooks/use-update-ai-description-mutation.ts +42 -0
- package/src/hooks/use-update-org-mutation.ts +41 -0
- package/src/hooks/use-warn-user-on-page-change.ts +71 -4
- package/src/hooks/useFileManagement.ts +51 -22
- package/src/hooks/useOptimizedPackageFilesLoader.ts +11 -24
- package/src/hooks/usePackageFilesLoader.ts +2 -2
- package/src/hooks/useUpdatePackageFilesMutation.ts +13 -1
- package/src/lib/download-fns/download-gltf-from-circuit-json.ts +1 -1
- package/src/lib/download-fns/download-kicad-files.ts +22 -11
- package/src/lib/download-fns/download-step.ts +12 -0
- package/src/lib/normalize-svg-for-tile.ts +50 -0
- package/src/lib/posthog.ts +11 -9
- package/src/lib/react-query-api-failure-tracking.ts +148 -0
- package/src/lib/sentry.ts +14 -0
- package/src/lib/templates/blank-circuit-board-template.ts +0 -4
- package/src/lib/ts-lib-cache.ts +122 -7
- package/src/lib/utils/checkIfManualEditsImported.ts +4 -4
- package/src/lib/utils/findTargetFile.ts +45 -10
- package/src/lib/utils/isComponentExported.ts +2 -1
- package/src/main.tsx +2 -1
- package/src/pages/create-organization.tsx +169 -0
- package/src/pages/dashboard.tsx +38 -6
- package/src/pages/datasheet.tsx +1 -1
- package/src/pages/datasheets.tsx +3 -3
- package/src/pages/editor.tsx +4 -6
- package/src/pages/landing.tsx +6 -6
- package/src/pages/latest.tsx +3 -0
- package/src/pages/organization-profile.tsx +199 -0
- package/src/pages/organization-settings.tsx +569 -0
- package/src/pages/package-editor.tsx +21 -21
- package/src/pages/preview-release.tsx +75 -145
- package/src/pages/quickstart.tsx +159 -123
- package/src/pages/release-detail.tsx +119 -31
- package/src/pages/search.tsx +197 -57
- package/src/pages/settings-redirect.tsx +44 -0
- package/src/pages/trending.tsx +29 -20
- package/src/pages/user-profile.tsx +58 -7
- package/src/pages/user-settings.tsx +161 -0
- package/src/pages/view-package.tsx +30 -16
- package/vite.config.ts +9 -0
- package/fake-snippets-api/routes/api/autocomplete/create_autocomplete.ts +0 -133
- package/src/components/JLCPCBImportDialog.tsx +0 -280
- package/src/components/PackageBuildsPage/LogContent.tsx +0 -72
- package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +0 -113
- package/src/components/PackageBuildsPage/build-preview-content.tsx +0 -56
- package/src/components/PackageBuildsPage/collapsible-section.tsx +0 -63
- package/src/components/PackageBuildsPage/package-build-details-panel.tsx +0 -166
- package/src/components/PackageBuildsPage/package-build-header.tsx +0 -79
- package/src/components/PageSearchComponent.tsx +0 -148
- package/src/pages/package-builds.tsx +0 -33
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Button } from "@/components/ui/button"
|
|
2
|
-
import { GitFork, Star } from "lucide-react"
|
|
2
|
+
import { GitFork, Loader2, Star } from "lucide-react"
|
|
3
3
|
import {
|
|
4
4
|
DropdownMenu,
|
|
5
5
|
DropdownMenuContent,
|
|
@@ -42,7 +42,6 @@ import { useViewTsFilesDialog } from "@/components/dialogs/view-ts-files-dialog"
|
|
|
42
42
|
import { DownloadButtonAndMenu } from "@/components/DownloadButtonAndMenu"
|
|
43
43
|
import { TypeBadge } from "@/components/TypeBadge"
|
|
44
44
|
import { useForkPackageMutation } from "@/hooks/useForkPackageMutation"
|
|
45
|
-
import tscircuitCorePkg from "@tscircuit/core/package.json"
|
|
46
45
|
import { useRenamePackageDialog } from "../dialogs/rename-package-dialog"
|
|
47
46
|
import { useUpdatePackageDescriptionDialog } from "../dialogs/update-package-description-dialog"
|
|
48
47
|
import { useCreateReleaseDialog } from "@/hooks/use-create-release-dialog"
|
|
@@ -295,52 +294,37 @@ export default function EditorNav({
|
|
|
295
294
|
Not logged in, can't save
|
|
296
295
|
</div>
|
|
297
296
|
)}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
297
|
+
{(canSavePackage || (isLoggedIn && pkg)) && (
|
|
298
|
+
<Button
|
|
299
|
+
variant="outline"
|
|
300
|
+
size="sm"
|
|
301
|
+
className={"ml-1 h-6 px-2 text-xs save-button"}
|
|
302
|
+
disabled={
|
|
303
|
+
canSavePackage && pkg ? !hasUnsavedChanges : !isLoggedIn
|
|
304
|
+
}
|
|
305
|
+
onClick={canSavePackage ? onSave : () => forkSnippet()}
|
|
306
|
+
>
|
|
307
|
+
{canSavePackage ? (
|
|
308
|
+
<>
|
|
309
|
+
<Save className="mr-1 h-3 w-3" />
|
|
310
|
+
Save
|
|
311
|
+
</>
|
|
312
|
+
) : (
|
|
313
|
+
<>
|
|
314
|
+
<GitFork className="mr-1 h-3 w-3" />
|
|
315
|
+
Fork
|
|
316
|
+
</>
|
|
317
|
+
)}
|
|
318
|
+
</Button>
|
|
319
|
+
)}
|
|
317
320
|
{isSaving && (
|
|
318
|
-
<div className="animate-fadeIn bg-blue-100 text-blue-800 text-xs font-medium px-2.5 py-0.5 rounded flex items-center">
|
|
319
|
-
<
|
|
320
|
-
className="animate-spin h-3 w-3 mr-2 text-blue-600"
|
|
321
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
322
|
-
fill="none"
|
|
323
|
-
viewBox="0 0 24 24"
|
|
324
|
-
>
|
|
325
|
-
<circle
|
|
326
|
-
className="opacity-25"
|
|
327
|
-
cx="12"
|
|
328
|
-
cy="12"
|
|
329
|
-
r="10"
|
|
330
|
-
stroke="currentColor"
|
|
331
|
-
strokeWidth="4"
|
|
332
|
-
></circle>
|
|
333
|
-
<path
|
|
334
|
-
className="opacity-75"
|
|
335
|
-
fill="currentColor"
|
|
336
|
-
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
337
|
-
></path>
|
|
338
|
-
</svg>
|
|
321
|
+
<div className="animate-fadeIn bg-blue-100 select-none text-blue-800 text-xs font-medium px-2.5 py-0.5 rounded flex items-center">
|
|
322
|
+
<Loader2 className="animate-spin h-3 w-3 mr-2 text-blue-600" />
|
|
339
323
|
Saving...
|
|
340
324
|
</div>
|
|
341
325
|
)}
|
|
342
326
|
{hasUnsavedChanges && !isSaving && isLoggedIn && (
|
|
343
|
-
<div className="animate-fadeIn bg-yellow-100 text-yellow-800 text-xs font-medium px-2.5 py-0.5 rounded">
|
|
327
|
+
<div className="animate-fadeIn bg-yellow-100 select-none text-yellow-800 text-xs font-medium px-2.5 py-0.5 rounded">
|
|
344
328
|
{pkg ? "unsaved changes" : "unsaved"}
|
|
345
329
|
</div>
|
|
346
330
|
)}
|
|
@@ -359,7 +343,6 @@ export default function EditorNav({
|
|
|
359
343
|
</div>
|
|
360
344
|
<div className="flex items-center justify-end -space-x-1">
|
|
361
345
|
<div className="flex mx-2 items-center space-x-1">
|
|
362
|
-
{pkg && <TypeBadge type={`${packageType ?? pkg.snippet_type}`} />}
|
|
363
346
|
{/* <Button
|
|
364
347
|
variant="ghost"
|
|
365
348
|
size="sm"
|
|
@@ -481,9 +464,6 @@ export default function EditorNav({
|
|
|
481
464
|
</DropdownMenuItem>
|
|
482
465
|
</>
|
|
483
466
|
)}
|
|
484
|
-
<DropdownMenuItem className="text-xs text-gray-500" disabled>
|
|
485
|
-
@tscircuit/core@{tscircuitCorePkg.version}
|
|
486
|
-
</DropdownMenuItem>
|
|
487
467
|
</DropdownMenuContent>
|
|
488
468
|
</DropdownMenu>
|
|
489
469
|
|
|
@@ -505,7 +485,7 @@ export default function EditorNav({
|
|
|
505
485
|
)}
|
|
506
486
|
</Button>
|
|
507
487
|
</div>
|
|
508
|
-
<div className="flex items-center
|
|
488
|
+
<div className="flex items-center">
|
|
509
489
|
<DropdownMenu>
|
|
510
490
|
<DropdownMenuTrigger asChild>
|
|
511
491
|
<div className="md:hidden rounded-full p-1 hover:bg-gray-100 cursor-pointer">
|
|
@@ -514,7 +494,7 @@ export default function EditorNav({
|
|
|
514
494
|
</Button>
|
|
515
495
|
</div>
|
|
516
496
|
</DropdownMenuTrigger>
|
|
517
|
-
<DropdownMenuContent>
|
|
497
|
+
<DropdownMenuContent className="z-[101]">
|
|
518
498
|
{hasUnsavedChanges && onDiscard && (
|
|
519
499
|
<DropdownMenuItem
|
|
520
500
|
className="text-xs text-red-600"
|
|
@@ -601,6 +581,9 @@ export default function EditorNav({
|
|
|
601
581
|
<RenameDialog
|
|
602
582
|
packageId={pkg?.package_id ?? ""}
|
|
603
583
|
currentName={pkg?.unscoped_name ?? ""}
|
|
584
|
+
onRename={() => {
|
|
585
|
+
qc.invalidateQueries({ queryKey: ["package", pkg?.package_id] })
|
|
586
|
+
}}
|
|
604
587
|
/>
|
|
605
588
|
<DeleteDialog
|
|
606
589
|
packageId={pkg?.package_id ?? ""}
|
|
@@ -3,7 +3,7 @@ import { Badge } from "@/components/ui/badge"
|
|
|
3
3
|
import { Button } from "@/components/ui/button"
|
|
4
4
|
import { GitBranch, Rocket, Github } from "lucide-react"
|
|
5
5
|
import { cn } from "@/lib/utils"
|
|
6
|
-
import {
|
|
6
|
+
import { Link } from "wouter"
|
|
7
7
|
import { formatTimeAgo } from "@/lib/utils/formatTimeAgo"
|
|
8
8
|
import { getBuildStatus, StatusIcon } from "."
|
|
9
9
|
import { Package } from "fake-snippets-api/lib/db/schema"
|
|
@@ -116,12 +116,12 @@ export const ConnectedPackageCard = ({
|
|
|
116
116
|
>
|
|
117
117
|
<div className="flex items-start justify-between mb-4">
|
|
118
118
|
<div className="flex items-center gap-3">
|
|
119
|
-
<
|
|
120
|
-
href=
|
|
119
|
+
<Link
|
|
120
|
+
href={`/${pkg.owner_github_username}/${pkg.unscoped_name}`}
|
|
121
121
|
className="text-lg font-semibold text-gray-900 hover:text-blue-600 transition-colors"
|
|
122
122
|
>
|
|
123
123
|
{pkg.unscoped_name}
|
|
124
|
-
</
|
|
124
|
+
</Link>
|
|
125
125
|
</div>
|
|
126
126
|
|
|
127
127
|
<div className="flex items-center justify-center gap-2">
|
|
@@ -174,25 +174,25 @@ export const ConnectedPackageCard = ({
|
|
|
174
174
|
</div>
|
|
175
175
|
|
|
176
176
|
<div className="flex gap-2 w-full mt-auto">
|
|
177
|
-
<
|
|
177
|
+
<Link className="w-full" href={`/${pkg.name}/releases`}>
|
|
178
178
|
<Button
|
|
179
179
|
size="sm"
|
|
180
180
|
className="bg-blue-600 w-full hover:bg-blue-700 text-white px-4 py-2"
|
|
181
181
|
>
|
|
182
182
|
View
|
|
183
183
|
</Button>
|
|
184
|
-
</
|
|
184
|
+
</Link>
|
|
185
185
|
{latestBuildInfo?.preview_url &&
|
|
186
186
|
latestBuildInfo?.package_build_id &&
|
|
187
187
|
status === "success" && (
|
|
188
|
-
<
|
|
188
|
+
<Link
|
|
189
189
|
className="w-full"
|
|
190
190
|
href={`/${pkg.name}/releases/${latestBuildInfo.package_release_id}/preview`}
|
|
191
191
|
>
|
|
192
192
|
<Button size="sm" variant="outline" className="px-4 py-2 w-full">
|
|
193
193
|
Preview
|
|
194
194
|
</Button>
|
|
195
|
-
</
|
|
195
|
+
</Link>
|
|
196
196
|
)}
|
|
197
197
|
</div>
|
|
198
198
|
</Card>
|
|
@@ -41,6 +41,7 @@ export const ConnectedRepoOverview = ({
|
|
|
41
41
|
const [openSections, setOpenSections] = useState({
|
|
42
42
|
transpilation: false,
|
|
43
43
|
circuitJson: false,
|
|
44
|
+
imageGeneration: false,
|
|
44
45
|
})
|
|
45
46
|
|
|
46
47
|
// Gracefully handle when there is no build yet
|
|
@@ -120,15 +121,25 @@ export const ConnectedRepoOverview = ({
|
|
|
120
121
|
1000,
|
|
121
122
|
)
|
|
122
123
|
: 0
|
|
124
|
+
const imageGenerationDuration = packageBuild?.image_generation_started_at
|
|
125
|
+
? Math.floor(
|
|
126
|
+
(new Date(
|
|
127
|
+
packageBuild.image_generation_completed_at || new Date(),
|
|
128
|
+
).getTime() -
|
|
129
|
+
new Date(packageBuild.image_generation_started_at).getTime()) /
|
|
130
|
+
1000,
|
|
131
|
+
)
|
|
132
|
+
: 0
|
|
123
133
|
|
|
124
134
|
if (
|
|
125
135
|
!packageBuild?.transpilation_started_at &&
|
|
126
|
-
!packageBuild?.circuit_json_build_started_at
|
|
136
|
+
!packageBuild?.circuit_json_build_started_at &&
|
|
137
|
+
!packageBuild?.image_generation_started_at
|
|
127
138
|
) {
|
|
128
139
|
return null
|
|
129
140
|
}
|
|
130
141
|
|
|
131
|
-
return transpilationDuration + circuitJsonDuration
|
|
142
|
+
return transpilationDuration + circuitJsonDuration + imageGenerationDuration
|
|
132
143
|
})()
|
|
133
144
|
const toggleSection = (section: keyof typeof openSections) => {
|
|
134
145
|
setOpenSections((prev) => ({ ...prev, [section]: !prev[section] }))
|
|
@@ -482,6 +493,95 @@ export const ConnectedRepoOverview = ({
|
|
|
482
493
|
</div>
|
|
483
494
|
</CollapsibleContent>
|
|
484
495
|
</Collapsible>
|
|
496
|
+
|
|
497
|
+
<Collapsible
|
|
498
|
+
open={openSections.imageGeneration}
|
|
499
|
+
onOpenChange={() => toggleSection("imageGeneration")}
|
|
500
|
+
>
|
|
501
|
+
<CollapsibleTrigger asChild>
|
|
502
|
+
<div className="flex items-center justify-between p-4 bg-white border border-gray-200 rounded-lg cursor-pointer hover:bg-gray-50">
|
|
503
|
+
<div className="flex items-center gap-3">
|
|
504
|
+
<ChevronRight
|
|
505
|
+
className={`w-4 h-4 transition-transform ${openSections.imageGeneration ? "rotate-90" : ""}`}
|
|
506
|
+
/>
|
|
507
|
+
{packageBuild.image_generation_error ? (
|
|
508
|
+
<AlertCircle className="w-5 h-5 text-red-500" />
|
|
509
|
+
) : packageBuild.image_generation_completed_at ? (
|
|
510
|
+
<CheckCircle className="w-5 h-5 text-green-500" />
|
|
511
|
+
) : packageBuild.image_generation_in_progress ? (
|
|
512
|
+
<Loader2 className="w-5 h-5 text-blue-500 animate-spin" />
|
|
513
|
+
) : (
|
|
514
|
+
<Clock className="w-5 h-5 text-gray-400" />
|
|
515
|
+
)}
|
|
516
|
+
<span className="font-medium">Image Generation</span>
|
|
517
|
+
</div>
|
|
518
|
+
<div className="flex items-center gap-2">
|
|
519
|
+
{getStepDuration(
|
|
520
|
+
packageBuild.image_generation_started_at,
|
|
521
|
+
packageBuild.image_generation_completed_at,
|
|
522
|
+
) && (
|
|
523
|
+
<span className="text-sm text-gray-600">
|
|
524
|
+
{getStepDuration(
|
|
525
|
+
packageBuild.image_generation_started_at,
|
|
526
|
+
packageBuild.image_generation_completed_at,
|
|
527
|
+
)}
|
|
528
|
+
</span>
|
|
529
|
+
)}
|
|
530
|
+
<Badge
|
|
531
|
+
variant={
|
|
532
|
+
getStepStatus(
|
|
533
|
+
packageBuild.image_generation_error,
|
|
534
|
+
packageBuild.image_generation_completed_at,
|
|
535
|
+
packageBuild.image_generation_in_progress,
|
|
536
|
+
) === "success"
|
|
537
|
+
? "default"
|
|
538
|
+
: getStepStatus(
|
|
539
|
+
packageBuild.image_generation_error,
|
|
540
|
+
packageBuild.image_generation_completed_at,
|
|
541
|
+
packageBuild.image_generation_in_progress,
|
|
542
|
+
) === "error"
|
|
543
|
+
? "destructive"
|
|
544
|
+
: "secondary"
|
|
545
|
+
}
|
|
546
|
+
className="text-xs"
|
|
547
|
+
>
|
|
548
|
+
{packageBuild.image_generation_error
|
|
549
|
+
? "Failed"
|
|
550
|
+
: packageBuild.image_generation_completed_at
|
|
551
|
+
? "Completed"
|
|
552
|
+
: packageBuild.image_generation_in_progress
|
|
553
|
+
? "Running"
|
|
554
|
+
: "Queued"}
|
|
555
|
+
</Badge>
|
|
556
|
+
</div>
|
|
557
|
+
</div>
|
|
558
|
+
</CollapsibleTrigger>
|
|
559
|
+
<CollapsibleContent>
|
|
560
|
+
<div className="bg-white border-x border-b border-gray-200 rounded-b-lg p-4">
|
|
561
|
+
<div className="font-mono text-xs space-y-1">
|
|
562
|
+
{packageBuild.image_generation_error ? (
|
|
563
|
+
<div className="text-red-600 whitespace-pre-wrap">
|
|
564
|
+
{packageBuild.image_generation_error}
|
|
565
|
+
</div>
|
|
566
|
+
) : packageBuild.image_generation_logs &&
|
|
567
|
+
packageBuild.image_generation_logs.length > 0 ? (
|
|
568
|
+
packageBuild.image_generation_logs.map(
|
|
569
|
+
(log: any, i: number) => (
|
|
570
|
+
<div
|
|
571
|
+
key={i}
|
|
572
|
+
className="text-gray-600 whitespace-pre-wrap"
|
|
573
|
+
>
|
|
574
|
+
{log.msg || log.message || JSON.stringify(log)}
|
|
575
|
+
</div>
|
|
576
|
+
),
|
|
577
|
+
)
|
|
578
|
+
) : (
|
|
579
|
+
<div className="text-gray-500">No logs available</div>
|
|
580
|
+
)}
|
|
581
|
+
</div>
|
|
582
|
+
</div>
|
|
583
|
+
</CollapsibleContent>
|
|
584
|
+
</Collapsible>
|
|
485
585
|
</div>
|
|
486
586
|
</div>
|
|
487
587
|
)
|
|
@@ -8,18 +8,20 @@ import {
|
|
|
8
8
|
} from "@/components/ui/dropdown-menu"
|
|
9
9
|
import { MoreHorizontal, Clock, GitBranch, Eye } from "lucide-react"
|
|
10
10
|
import { GitHubLogoIcon } from "@radix-ui/react-icons"
|
|
11
|
-
import { useLocation } from "wouter"
|
|
12
11
|
import { BuildsList } from "./BuildsList"
|
|
13
12
|
import Header from "../Header"
|
|
14
13
|
import { formatTimeAgo } from "@/lib/utils/formatTimeAgo"
|
|
15
14
|
import { getBuildStatus } from "."
|
|
16
|
-
import {
|
|
15
|
+
import { Link } from "wouter"
|
|
17
16
|
import { PackageBreadcrumb } from "../PackageBreadcrumb"
|
|
18
17
|
import {
|
|
19
18
|
Package,
|
|
20
19
|
PackageBuild,
|
|
21
20
|
PackageRelease,
|
|
22
21
|
} from "fake-snippets-api/lib/db/schema"
|
|
22
|
+
import { useDownloadZip } from "@/hooks/use-download-zip"
|
|
23
|
+
import { useToast } from "@/hooks/use-toast"
|
|
24
|
+
import { usePackageFiles } from "@/hooks/use-package-files"
|
|
23
25
|
|
|
24
26
|
export const PackageReleasesDashboard = ({
|
|
25
27
|
latestRelease,
|
|
@@ -30,9 +32,21 @@ export const PackageReleasesDashboard = ({
|
|
|
30
32
|
latestBuild: PackageBuild | null
|
|
31
33
|
pkg: Package
|
|
32
34
|
}) => {
|
|
33
|
-
const [, setLocation] = useLocation()
|
|
34
35
|
const { status, label } = getBuildStatus(latestBuild)
|
|
35
|
-
|
|
36
|
+
const { toastLibrary } = useToast()
|
|
37
|
+
const { downloadZip } = useDownloadZip()
|
|
38
|
+
const { data: packageFiles } = usePackageFiles(
|
|
39
|
+
latestRelease.package_release_id,
|
|
40
|
+
)
|
|
41
|
+
const handleDownloadZip = () => {
|
|
42
|
+
if (pkg && packageFiles) {
|
|
43
|
+
toastLibrary.promise(downloadZip(pkg, packageFiles ?? []), {
|
|
44
|
+
loading: "Downloading ZIP...",
|
|
45
|
+
success: "ZIP downloaded successfully!",
|
|
46
|
+
error: "Failed to download ZIP",
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
}
|
|
36
50
|
return (
|
|
37
51
|
<>
|
|
38
52
|
<Header />
|
|
@@ -59,12 +73,12 @@ export const PackageReleasesDashboard = ({
|
|
|
59
73
|
</div>
|
|
60
74
|
<div className="min-w-0 flex-1">
|
|
61
75
|
<div className="flex flex-col sm:flex-row sm:items-center gap-3">
|
|
62
|
-
<
|
|
76
|
+
<Link
|
|
63
77
|
href={"/" + pkg.name}
|
|
64
78
|
className="text-2xl font-bold text-gray-900 truncate"
|
|
65
79
|
>
|
|
66
80
|
{pkg.name}
|
|
67
|
-
</
|
|
81
|
+
</Link>
|
|
68
82
|
<Badge
|
|
69
83
|
variant={
|
|
70
84
|
status === "success"
|
|
@@ -139,7 +153,7 @@ export const PackageReleasesDashboard = ({
|
|
|
139
153
|
<span className="sm:hidden">Repository</span>
|
|
140
154
|
</Button>
|
|
141
155
|
)}
|
|
142
|
-
{latestBuild && (
|
|
156
|
+
{latestBuild && status !== "error" && (
|
|
143
157
|
<Button
|
|
144
158
|
variant="outline"
|
|
145
159
|
size="sm"
|
|
@@ -178,10 +192,8 @@ export const PackageReleasesDashboard = ({
|
|
|
178
192
|
</a>
|
|
179
193
|
</DropdownMenuItem>
|
|
180
194
|
)}
|
|
181
|
-
<DropdownMenuItem asChild>
|
|
182
|
-
<
|
|
183
|
-
Download Build
|
|
184
|
-
</a>
|
|
195
|
+
<DropdownMenuItem asChild onClick={handleDownloadZip}>
|
|
196
|
+
<span>Download Zip</span>
|
|
185
197
|
</DropdownMenuItem>
|
|
186
198
|
<DropdownMenuItem
|
|
187
199
|
onClick={() => {
|
|
@@ -317,9 +317,12 @@ const TreeNode = ({
|
|
|
317
317
|
default={defaultNodeIcon}
|
|
318
318
|
/>
|
|
319
319
|
<span className="text-sm truncate">{item.name}</span>
|
|
320
|
-
<
|
|
321
|
-
|
|
322
|
-
|
|
320
|
+
<div
|
|
321
|
+
className="flex items-center"
|
|
322
|
+
onClick={(e) => e.stopPropagation()}
|
|
323
|
+
>
|
|
324
|
+
<TreeActions isSelected={true}>{item.actions}</TreeActions>
|
|
325
|
+
</div>
|
|
323
326
|
</AccordionTrigger>
|
|
324
327
|
<AccordionContent className="ml-4 pl-1 border-l">
|
|
325
328
|
<TreeItem
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { useMutation, useQueryClient } from "react-query"
|
|
2
|
+
import { useAxios } from "@/hooks/use-axios"
|
|
3
|
+
import { useGlobalStore } from "@/hooks/use-global-store"
|
|
4
|
+
|
|
5
|
+
export const useAddOrgMemberMutation = ({
|
|
6
|
+
onSuccess,
|
|
7
|
+
onError,
|
|
8
|
+
}: { onSuccess?: () => void; onError?: (error: any) => void } = {}) => {
|
|
9
|
+
const axios = useAxios()
|
|
10
|
+
const session = useGlobalStore((s) => s.session)
|
|
11
|
+
const queryClient = useQueryClient()
|
|
12
|
+
|
|
13
|
+
return useMutation(
|
|
14
|
+
["addOrgMember"],
|
|
15
|
+
async ({
|
|
16
|
+
orgId,
|
|
17
|
+
accountId,
|
|
18
|
+
githubUsername,
|
|
19
|
+
}: {
|
|
20
|
+
orgId: string
|
|
21
|
+
accountId?: string
|
|
22
|
+
githubUsername?: string
|
|
23
|
+
}) => {
|
|
24
|
+
if (!session) throw new Error("No session")
|
|
25
|
+
|
|
26
|
+
const payload: any = {
|
|
27
|
+
org_id: orgId,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (accountId) {
|
|
31
|
+
payload.account_id = accountId
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (githubUsername) {
|
|
35
|
+
payload.github_username = githubUsername
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
await axios.post("/orgs/add_member", payload)
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
onSuccess: () => {
|
|
42
|
+
queryClient.invalidateQueries(["orgs", "members"])
|
|
43
|
+
onSuccess?.()
|
|
44
|
+
},
|
|
45
|
+
onError: (error: any) => {
|
|
46
|
+
console.error("Error adding organization member:", error)
|
|
47
|
+
onError?.(error)
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
)
|
|
51
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useMutation } from "react-query"
|
|
2
|
+
import { useAxios } from "./use-axios"
|
|
3
|
+
import { useGlobalStore } from "./use-global-store"
|
|
4
|
+
import type { PublicOrgSchema } from "fake-snippets-api/lib/db/schema"
|
|
5
|
+
|
|
6
|
+
export const useCreateOrgMutation = ({
|
|
7
|
+
onSuccess,
|
|
8
|
+
}: { onSuccess?: (org: PublicOrgSchema) => void } = {}) => {
|
|
9
|
+
const axios = useAxios()
|
|
10
|
+
const session = useGlobalStore((s) => s.session)
|
|
11
|
+
|
|
12
|
+
return useMutation(
|
|
13
|
+
["createOrg"],
|
|
14
|
+
async ({ name }: { name: string }) => {
|
|
15
|
+
if (!session) throw new Error("No session")
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
data: { org: newOrg },
|
|
19
|
+
} = await axios.post("/orgs/create", {
|
|
20
|
+
name,
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
if (!newOrg) {
|
|
24
|
+
throw new Error("Failed to create organization")
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return newOrg
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
onSuccess: (org: PublicOrgSchema) => {
|
|
31
|
+
onSuccess?.(org)
|
|
32
|
+
},
|
|
33
|
+
onError: (error: any) => {
|
|
34
|
+
console.error("Error creating organization:", error)
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
)
|
|
38
|
+
}
|
|
@@ -16,11 +16,13 @@ export const useCreatePackageMutation = ({
|
|
|
16
16
|
description,
|
|
17
17
|
is_private,
|
|
18
18
|
is_unlisted,
|
|
19
|
+
org_id,
|
|
19
20
|
}: {
|
|
20
21
|
name?: string
|
|
21
22
|
description?: string
|
|
22
23
|
is_private?: boolean
|
|
23
24
|
is_unlisted?: boolean
|
|
25
|
+
org_id?: string
|
|
24
26
|
}) => {
|
|
25
27
|
if (!session) throw new Error("No session")
|
|
26
28
|
|
|
@@ -31,6 +33,7 @@ export const useCreatePackageMutation = ({
|
|
|
31
33
|
description,
|
|
32
34
|
is_private,
|
|
33
35
|
is_unlisted,
|
|
36
|
+
org_id,
|
|
34
37
|
})
|
|
35
38
|
|
|
36
39
|
if (!newPackage) {
|
|
@@ -21,12 +21,13 @@ export const useCurrentPackageRelease = (options?: {
|
|
|
21
21
|
|
|
22
22
|
let query: Parameters<typeof usePackageRelease>[0] | null = null
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
// Prioritize package_name + is_latest for better caching consistency
|
|
25
|
+
if (author && packageName && !version && !releaseId) {
|
|
26
|
+
query = { package_name: `${author}/${packageName}`, is_latest: true }
|
|
27
|
+
} else if (releaseId) {
|
|
25
28
|
query = { package_release_id: releaseId }
|
|
26
29
|
} else if (version && author && packageName) {
|
|
27
30
|
query = { package_name_with_version: `${author}/${packageName}@${version}` }
|
|
28
|
-
} else if (author && packageName) {
|
|
29
|
-
query = { package_name: `${author}/${packageName}`, is_latest: true }
|
|
30
31
|
} else if (packageId) {
|
|
31
32
|
query = { package_id: packageId, is_latest: true }
|
|
32
33
|
}
|
|
@@ -20,8 +20,8 @@ export const useDownloadZip = () => {
|
|
|
20
20
|
|
|
21
21
|
for (const file of visibleFiles) {
|
|
22
22
|
try {
|
|
23
|
-
const response = await axios.
|
|
24
|
-
package_file_id: file.package_file_id,
|
|
23
|
+
const response = await axios.get("/package_files/get", {
|
|
24
|
+
params: { package_file_id: file.package_file_id },
|
|
25
25
|
})
|
|
26
26
|
|
|
27
27
|
const content = response.data.package_file?.content_text || ""
|
|
@@ -28,7 +28,9 @@ export const useGlobalStore = create<Store>()(
|
|
|
28
28
|
),
|
|
29
29
|
)
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
if (typeof window !== "undefined") {
|
|
32
|
+
useGlobalStore.subscribe((state) => {
|
|
33
|
+
;(window as any).globalStore = state
|
|
34
|
+
window.TSCIRCUIT_REGISTRY_TOKEN = state.session?.token ?? null
|
|
35
|
+
})
|
|
36
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useEffect, useState } from "react"
|
|
2
|
+
import { useGlobalStore } from "@/hooks/use-global-store"
|
|
3
|
+
|
|
4
|
+
export const useHydration = () => {
|
|
5
|
+
const [hasHydrated, setHasHydrated] = useState(() => {
|
|
6
|
+
if (typeof window === "undefined") return false
|
|
7
|
+
return useGlobalStore.persist?.hasHydrated?.() ?? false
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (typeof window === "undefined") return
|
|
12
|
+
|
|
13
|
+
if (useGlobalStore.persist?.hasHydrated?.()) {
|
|
14
|
+
setHasHydrated(true)
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const unsubFinishHydration = useGlobalStore.persist?.onFinishHydration?.(
|
|
19
|
+
() => {
|
|
20
|
+
setHasHydrated(true)
|
|
21
|
+
},
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
return () => {
|
|
25
|
+
unsubFinishHydration?.()
|
|
26
|
+
}
|
|
27
|
+
}, [])
|
|
28
|
+
|
|
29
|
+
return hasHydrated
|
|
30
|
+
}
|