@tscircuit/fake-snippets 0.0.80 → 0.0.82
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_releases/create.test.ts +6 -0
- package/bun-tests/fake-snippets-api/routes/package_releases/update.test.ts +3 -0
- package/bun.lock +24 -18
- package/dist/bundle.js +25 -9
- package/dist/index.d.ts +10 -0
- package/dist/index.js +4 -1
- package/dist/schema.d.ts +16 -0
- package/dist/schema.js +4 -1
- package/fake-snippets-api/lib/db/schema.ts +4 -0
- package/fake-snippets-api/routes/api/package_releases/update.ts +14 -1
- package/fake-snippets-api/routes/api/packages/generate_from_jlcpcb.ts +3 -3
- package/package.json +5 -5
- package/src/components/JLCPCBImportDialog.tsx +164 -62
- package/src/components/PackageBuildsPage/LogContent.tsx +12 -5
- package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +8 -7
- package/src/components/PackageBuildsPage/build-preview-content.tsx +1 -1
- package/src/components/PackageBuildsPage/collapsible-section.tsx +14 -46
- package/src/components/PackageBuildsPage/package-build-details-panel.tsx +28 -10
- package/src/components/PackageBuildsPage/package-build-header.tsx +14 -2
- package/src/components/ViewPackagePage/components/build-status.tsx +24 -85
- package/src/components/ViewPackagePage/components/important-files-view.tsx +65 -2
- package/src/components/ViewPackagePage/components/repo-page-content.tsx +13 -0
- package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +28 -5
- package/src/components/package-port/CodeAndPreview.tsx +7 -1
- package/src/components/package-port/CodeEditor.tsx +9 -1
- package/src/hooks/use-current-package-release.ts +4 -2
- package/src/hooks/use-now.ts +12 -0
- package/src/hooks/use-package-release.ts +3 -2
- package/src/hooks/use-rebuild-package-release-mutation.ts +41 -0
- package/src/hooks/use-request-ai-review-mutation.ts +45 -0
- package/src/hooks/useFileManagement.ts +1 -2
- package/src/lib/codemirror/basic-setup.ts +17 -1
- package/src/pages/dashboard.tsx +3 -1
- package/src/pages/editor.tsx +5 -1
- package/src/pages/user-profile.tsx +9 -2
- package/src/pages/view-package.tsx +1 -0
- package/.github/workflows/formatbot.yml +0 -63
package/dist/index.d.ts
CHANGED
|
@@ -435,6 +435,8 @@ declare const packageReleaseSchema: z.ZodObject<{
|
|
|
435
435
|
circuit_json_build_completed_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
436
436
|
circuit_json_build_logs: z.ZodDefault<z.ZodArray<z.ZodAny, "many">>;
|
|
437
437
|
circuit_json_build_is_stale: z.ZodDefault<z.ZodBoolean>;
|
|
438
|
+
ai_review_text: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
439
|
+
ai_review_requested: z.ZodDefault<z.ZodBoolean>;
|
|
438
440
|
}, "strip", z.ZodTypeAny, {
|
|
439
441
|
package_release_id: string;
|
|
440
442
|
created_at: string;
|
|
@@ -452,6 +454,8 @@ declare const packageReleaseSchema: z.ZodObject<{
|
|
|
452
454
|
circuit_json_build_in_progress: boolean;
|
|
453
455
|
circuit_json_build_logs: any[];
|
|
454
456
|
circuit_json_build_is_stale: boolean;
|
|
457
|
+
ai_review_text: string | null;
|
|
458
|
+
ai_review_requested: boolean;
|
|
455
459
|
commit_sha?: string | null | undefined;
|
|
456
460
|
license?: string | null | undefined;
|
|
457
461
|
circuit_json_build_error?: string | null | undefined;
|
|
@@ -491,6 +495,8 @@ declare const packageReleaseSchema: z.ZodObject<{
|
|
|
491
495
|
circuit_json_build_completed_at?: string | null | undefined;
|
|
492
496
|
circuit_json_build_logs?: any[] | undefined;
|
|
493
497
|
circuit_json_build_is_stale?: boolean | undefined;
|
|
498
|
+
ai_review_text?: string | null | undefined;
|
|
499
|
+
ai_review_requested?: boolean | undefined;
|
|
494
500
|
}>;
|
|
495
501
|
type PackageRelease = z.infer<typeof packageReleaseSchema>;
|
|
496
502
|
declare const packageFileSchema: z.ZodObject<{
|
|
@@ -760,6 +766,8 @@ declare const createDatabase: ({ seed }?: {
|
|
|
760
766
|
circuit_json_build_in_progress: boolean;
|
|
761
767
|
circuit_json_build_logs: any[];
|
|
762
768
|
circuit_json_build_is_stale: boolean;
|
|
769
|
+
ai_review_text: string | null;
|
|
770
|
+
ai_review_requested: boolean;
|
|
763
771
|
commit_sha?: string | null | undefined;
|
|
764
772
|
license?: string | null | undefined;
|
|
765
773
|
circuit_json_build_error?: string | null | undefined;
|
|
@@ -1070,6 +1078,8 @@ declare const createDatabase: ({ seed }?: {
|
|
|
1070
1078
|
circuit_json_build_in_progress: boolean;
|
|
1071
1079
|
circuit_json_build_logs: any[];
|
|
1072
1080
|
circuit_json_build_is_stale: boolean;
|
|
1081
|
+
ai_review_text: string | null;
|
|
1082
|
+
ai_review_requested: boolean;
|
|
1073
1083
|
commit_sha?: string | null | undefined;
|
|
1074
1084
|
license?: string | null | undefined;
|
|
1075
1085
|
circuit_json_build_error?: string | null | undefined;
|
package/dist/index.js
CHANGED
|
@@ -165,7 +165,10 @@ var packageReleaseSchema = z.object({
|
|
|
165
165
|
circuit_json_build_started_at: z.string().datetime().nullable().optional(),
|
|
166
166
|
circuit_json_build_completed_at: z.string().datetime().nullable().optional(),
|
|
167
167
|
circuit_json_build_logs: z.array(z.any()).default([]),
|
|
168
|
-
circuit_json_build_is_stale: z.boolean().default(false)
|
|
168
|
+
circuit_json_build_is_stale: z.boolean().default(false),
|
|
169
|
+
// AI Review
|
|
170
|
+
ai_review_text: z.string().nullable().default(null),
|
|
171
|
+
ai_review_requested: z.boolean().default(false)
|
|
169
172
|
});
|
|
170
173
|
var packageFileSchema = z.object({
|
|
171
174
|
package_file_id: z.string(),
|
package/dist/schema.d.ts
CHANGED
|
@@ -560,6 +560,8 @@ declare const packageReleaseSchema: z.ZodObject<{
|
|
|
560
560
|
circuit_json_build_completed_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
561
561
|
circuit_json_build_logs: z.ZodDefault<z.ZodArray<z.ZodAny, "many">>;
|
|
562
562
|
circuit_json_build_is_stale: z.ZodDefault<z.ZodBoolean>;
|
|
563
|
+
ai_review_text: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
564
|
+
ai_review_requested: z.ZodDefault<z.ZodBoolean>;
|
|
563
565
|
}, "strip", z.ZodTypeAny, {
|
|
564
566
|
package_release_id: string;
|
|
565
567
|
created_at: string;
|
|
@@ -577,6 +579,8 @@ declare const packageReleaseSchema: z.ZodObject<{
|
|
|
577
579
|
circuit_json_build_in_progress: boolean;
|
|
578
580
|
circuit_json_build_logs: any[];
|
|
579
581
|
circuit_json_build_is_stale: boolean;
|
|
582
|
+
ai_review_text: string | null;
|
|
583
|
+
ai_review_requested: boolean;
|
|
580
584
|
commit_sha?: string | null | undefined;
|
|
581
585
|
license?: string | null | undefined;
|
|
582
586
|
circuit_json_build_error?: string | null | undefined;
|
|
@@ -616,6 +620,8 @@ declare const packageReleaseSchema: z.ZodObject<{
|
|
|
616
620
|
circuit_json_build_completed_at?: string | null | undefined;
|
|
617
621
|
circuit_json_build_logs?: any[] | undefined;
|
|
618
622
|
circuit_json_build_is_stale?: boolean | undefined;
|
|
623
|
+
ai_review_text?: string | null | undefined;
|
|
624
|
+
ai_review_requested?: boolean | undefined;
|
|
619
625
|
}>;
|
|
620
626
|
type PackageRelease = z.infer<typeof packageReleaseSchema>;
|
|
621
627
|
declare const packageFileSchema: z.ZodObject<{
|
|
@@ -939,6 +945,8 @@ declare const databaseSchema: z.ZodObject<{
|
|
|
939
945
|
circuit_json_build_completed_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
940
946
|
circuit_json_build_logs: z.ZodDefault<z.ZodArray<z.ZodAny, "many">>;
|
|
941
947
|
circuit_json_build_is_stale: z.ZodDefault<z.ZodBoolean>;
|
|
948
|
+
ai_review_text: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
949
|
+
ai_review_requested: z.ZodDefault<z.ZodBoolean>;
|
|
942
950
|
}, "strip", z.ZodTypeAny, {
|
|
943
951
|
package_release_id: string;
|
|
944
952
|
created_at: string;
|
|
@@ -956,6 +964,8 @@ declare const databaseSchema: z.ZodObject<{
|
|
|
956
964
|
circuit_json_build_in_progress: boolean;
|
|
957
965
|
circuit_json_build_logs: any[];
|
|
958
966
|
circuit_json_build_is_stale: boolean;
|
|
967
|
+
ai_review_text: string | null;
|
|
968
|
+
ai_review_requested: boolean;
|
|
959
969
|
commit_sha?: string | null | undefined;
|
|
960
970
|
license?: string | null | undefined;
|
|
961
971
|
circuit_json_build_error?: string | null | undefined;
|
|
@@ -995,6 +1005,8 @@ declare const databaseSchema: z.ZodObject<{
|
|
|
995
1005
|
circuit_json_build_completed_at?: string | null | undefined;
|
|
996
1006
|
circuit_json_build_logs?: any[] | undefined;
|
|
997
1007
|
circuit_json_build_is_stale?: boolean | undefined;
|
|
1008
|
+
ai_review_text?: string | null | undefined;
|
|
1009
|
+
ai_review_requested?: boolean | undefined;
|
|
998
1010
|
}>, "many">>;
|
|
999
1011
|
packageFiles: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1000
1012
|
package_file_id: z.ZodString;
|
|
@@ -1602,6 +1614,8 @@ declare const databaseSchema: z.ZodObject<{
|
|
|
1602
1614
|
circuit_json_build_in_progress: boolean;
|
|
1603
1615
|
circuit_json_build_logs: any[];
|
|
1604
1616
|
circuit_json_build_is_stale: boolean;
|
|
1617
|
+
ai_review_text: string | null;
|
|
1618
|
+
ai_review_requested: boolean;
|
|
1605
1619
|
commit_sha?: string | null | undefined;
|
|
1606
1620
|
license?: string | null | undefined;
|
|
1607
1621
|
circuit_json_build_error?: string | null | undefined;
|
|
@@ -1845,6 +1859,8 @@ declare const databaseSchema: z.ZodObject<{
|
|
|
1845
1859
|
circuit_json_build_completed_at?: string | null | undefined;
|
|
1846
1860
|
circuit_json_build_logs?: any[] | undefined;
|
|
1847
1861
|
circuit_json_build_is_stale?: boolean | undefined;
|
|
1862
|
+
ai_review_text?: string | null | undefined;
|
|
1863
|
+
ai_review_requested?: boolean | undefined;
|
|
1848
1864
|
}[] | undefined;
|
|
1849
1865
|
packageFiles?: {
|
|
1850
1866
|
package_release_id: string;
|
package/dist/schema.js
CHANGED
|
@@ -160,7 +160,10 @@ var packageReleaseSchema = z.object({
|
|
|
160
160
|
circuit_json_build_started_at: z.string().datetime().nullable().optional(),
|
|
161
161
|
circuit_json_build_completed_at: z.string().datetime().nullable().optional(),
|
|
162
162
|
circuit_json_build_logs: z.array(z.any()).default([]),
|
|
163
|
-
circuit_json_build_is_stale: z.boolean().default(false)
|
|
163
|
+
circuit_json_build_is_stale: z.boolean().default(false),
|
|
164
|
+
// AI Review
|
|
165
|
+
ai_review_text: z.string().nullable().default(null),
|
|
166
|
+
ai_review_requested: z.boolean().default(false)
|
|
164
167
|
});
|
|
165
168
|
var packageFileSchema = z.object({
|
|
166
169
|
package_file_id: z.string(),
|
|
@@ -201,6 +201,10 @@ export const packageReleaseSchema = z.object({
|
|
|
201
201
|
circuit_json_build_completed_at: z.string().datetime().nullable().optional(),
|
|
202
202
|
circuit_json_build_logs: z.array(z.any()).default([]),
|
|
203
203
|
circuit_json_build_is_stale: z.boolean().default(false),
|
|
204
|
+
|
|
205
|
+
// AI Review
|
|
206
|
+
ai_review_text: z.string().nullable().default(null),
|
|
207
|
+
ai_review_requested: z.boolean().default(false),
|
|
204
208
|
})
|
|
205
209
|
export type PackageRelease = z.infer<typeof packageReleaseSchema>
|
|
206
210
|
|
|
@@ -12,6 +12,7 @@ export default withRouteSpec({
|
|
|
12
12
|
license: z.string().optional(),
|
|
13
13
|
fs_sha: z.string().optional(),
|
|
14
14
|
ready_to_build: z.boolean().optional(),
|
|
15
|
+
ai_review_requested: z.boolean().optional(),
|
|
15
16
|
}),
|
|
16
17
|
jsonResponse: z.object({
|
|
17
18
|
ok: z.boolean(),
|
|
@@ -25,6 +26,7 @@ export default withRouteSpec({
|
|
|
25
26
|
license,
|
|
26
27
|
fs_sha,
|
|
27
28
|
ready_to_build,
|
|
29
|
+
ai_review_requested,
|
|
28
30
|
} = req.jsonBody
|
|
29
31
|
let releaseId = package_release_id
|
|
30
32
|
|
|
@@ -49,7 +51,14 @@ export default withRouteSpec({
|
|
|
49
51
|
})
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
const delta = {
|
|
54
|
+
const delta = {
|
|
55
|
+
is_locked,
|
|
56
|
+
is_latest,
|
|
57
|
+
license,
|
|
58
|
+
fs_sha,
|
|
59
|
+
ready_to_build,
|
|
60
|
+
ai_review_requested,
|
|
61
|
+
}
|
|
53
62
|
if (
|
|
54
63
|
Object.keys(delta).filter(
|
|
55
64
|
(k) => delta[k as keyof typeof delta] !== undefined,
|
|
@@ -79,6 +88,10 @@ export default withRouteSpec({
|
|
|
79
88
|
...(license !== undefined && { license }),
|
|
80
89
|
...(fs_sha !== undefined && { fs_sha }),
|
|
81
90
|
...(ready_to_build !== undefined && { ready_to_build }),
|
|
91
|
+
...(ai_review_requested !== undefined && { ai_review_requested }),
|
|
92
|
+
...(ai_review_requested === true && {
|
|
93
|
+
ai_review_text: "Placeholder AI Review Text",
|
|
94
|
+
}),
|
|
82
95
|
}
|
|
83
96
|
|
|
84
97
|
// Handle is_latest updates atomically
|
|
@@ -46,9 +46,9 @@ export default withRouteSpec({
|
|
|
46
46
|
const existingPackage = ctx.db.packages.find((p) => p.name === packageName)
|
|
47
47
|
|
|
48
48
|
if (existingPackage) {
|
|
49
|
-
return ctx.
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
return ctx.error(409, {
|
|
50
|
+
error_code: "package_already_exists",
|
|
51
|
+
message: componentName,
|
|
52
52
|
})
|
|
53
53
|
}
|
|
54
54
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/fake-snippets",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.82",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"@radix-ui/react-toggle": "^1.1.0",
|
|
71
71
|
"@radix-ui/react-toggle-group": "^1.1.0",
|
|
72
72
|
"@radix-ui/react-tooltip": "^1.1.2",
|
|
73
|
-
"@tscircuit/footprinter": "^0.0.
|
|
73
|
+
"@tscircuit/footprinter": "^0.0.176",
|
|
74
74
|
"@tscircuit/layout": "^0.0.29",
|
|
75
75
|
"@tscircuit/math-utils": "^0.0.10",
|
|
76
76
|
"@tscircuit/mm": "^0.0.8",
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
"recharts": "^2.12.7",
|
|
127
127
|
"remark-gfm": "^4.0.1",
|
|
128
128
|
"rollup-plugin-visualizer": "^5.12.0",
|
|
129
|
-
"schematic-symbols": "^0.0.
|
|
129
|
+
"schematic-symbols": "^0.0.155",
|
|
130
130
|
"sitemap": "^8.0.0",
|
|
131
131
|
"sonner": "^1.5.0",
|
|
132
132
|
"states-us": "^1.1.1",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"@tailwindcss/typography": "^0.5.16",
|
|
147
147
|
"@tscircuit/core": "^0.0.433",
|
|
148
148
|
"@tscircuit/prompt-benchmarks": "^0.0.28",
|
|
149
|
-
"@tscircuit/runframe": "^0.0.
|
|
149
|
+
"@tscircuit/runframe": "^0.0.562",
|
|
150
150
|
"@types/babel__standalone": "^7.1.7",
|
|
151
151
|
"@types/bun": "^1.1.10",
|
|
152
152
|
"@types/country-list": "^2.1.4",
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
"@typescript/vfs": "^1.6.0",
|
|
161
161
|
"@vitejs/plugin-react": "^4.3.1",
|
|
162
162
|
"autoprefixer": "^10.4.20",
|
|
163
|
-
"circuit-to-svg": "^0.0.
|
|
163
|
+
"circuit-to-svg": "^0.0.152",
|
|
164
164
|
"get-port": "^7.1.0",
|
|
165
165
|
"globals": "^15.9.0",
|
|
166
166
|
"he": "^1.2.0",
|
|
@@ -20,43 +20,102 @@ interface JLCPCBImportDialogProps {
|
|
|
20
20
|
onOpenChange: (open: boolean) => void
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
interface ImportState {
|
|
24
|
+
isLoading: boolean
|
|
25
|
+
error: string | null
|
|
26
|
+
existingComponent: {
|
|
27
|
+
partNumber: string
|
|
28
|
+
username: string
|
|
29
|
+
} | null
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface JLCPCBResponse {
|
|
33
|
+
ok: boolean
|
|
34
|
+
package: {
|
|
35
|
+
package_id: string
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface APIError {
|
|
40
|
+
status: number
|
|
41
|
+
data?: {
|
|
42
|
+
message?: string
|
|
43
|
+
existing_part_number?: string
|
|
44
|
+
part_number?: string
|
|
45
|
+
error?: {
|
|
46
|
+
message?: string
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const extractErrorMessage = (error: APIError): string => {
|
|
52
|
+
return (
|
|
53
|
+
error?.data?.message ||
|
|
54
|
+
error?.data?.error?.message ||
|
|
55
|
+
"An unexpected error occurred"
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const extractExistingPartNumber = (
|
|
60
|
+
error: APIError,
|
|
61
|
+
fallback: string,
|
|
62
|
+
): string => {
|
|
63
|
+
return error?.data?.message || error?.data?.error?.message || fallback
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const useJLCPCBImport = () => {
|
|
67
|
+
const [state, setState] = useState<ImportState>({
|
|
68
|
+
isLoading: false,
|
|
69
|
+
error: null,
|
|
70
|
+
existingComponent: null,
|
|
71
|
+
})
|
|
72
|
+
|
|
32
73
|
const axios = useAxios()
|
|
33
74
|
const { toast } = useToast()
|
|
34
75
|
const [, navigate] = useLocation()
|
|
35
|
-
const isLoggedIn = useGlobalStore((s) => Boolean(s.session))
|
|
36
76
|
const session = useGlobalStore((s) => s.session)
|
|
37
77
|
|
|
38
|
-
const
|
|
39
|
-
|
|
78
|
+
const resetState = () => {
|
|
79
|
+
setState({
|
|
80
|
+
isLoading: false,
|
|
81
|
+
error: null,
|
|
82
|
+
existingComponent: null,
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const importComponent = async (partNumber: string) => {
|
|
87
|
+
if (!partNumber.startsWith("C") || partNumber.length < 2) {
|
|
40
88
|
toast({
|
|
41
89
|
title: "Invalid Part Number",
|
|
42
|
-
description:
|
|
90
|
+
description:
|
|
91
|
+
"JLCPCB part numbers should start with 'C' and be at least 2 characters long.",
|
|
43
92
|
variant: "destructive",
|
|
44
93
|
})
|
|
45
|
-
return
|
|
94
|
+
return { success: false }
|
|
46
95
|
}
|
|
47
96
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
97
|
+
setState((prev) => ({
|
|
98
|
+
...prev,
|
|
99
|
+
isLoading: true,
|
|
100
|
+
error: null,
|
|
101
|
+
existingComponent: null,
|
|
102
|
+
}))
|
|
51
103
|
|
|
52
104
|
try {
|
|
53
|
-
const response = await axios.post(
|
|
54
|
-
|
|
55
|
-
|
|
105
|
+
const response = await axios.post<JLCPCBResponse>(
|
|
106
|
+
"/packages/generate_from_jlcpcb",
|
|
107
|
+
{
|
|
108
|
+
jlcpcb_part_number: partNumber,
|
|
109
|
+
},
|
|
110
|
+
)
|
|
111
|
+
|
|
56
112
|
if (!response.data.ok) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
113
|
+
setState((prev) => ({
|
|
114
|
+
...prev,
|
|
115
|
+
isLoading: false,
|
|
116
|
+
error: "Failed to generate package from JLCPCB part",
|
|
117
|
+
}))
|
|
118
|
+
return { success: false }
|
|
60
119
|
}
|
|
61
120
|
|
|
62
121
|
const { package: generatedPackage } = response.data
|
|
@@ -66,27 +125,84 @@ export function JLCPCBImportDialog({
|
|
|
66
125
|
description: "JLCPCB component has been imported successfully.",
|
|
67
126
|
})
|
|
68
127
|
|
|
69
|
-
onOpenChange(false)
|
|
70
128
|
navigate(`/editor?package_id=${generatedPackage.package_id}`)
|
|
129
|
+
return { success: true }
|
|
71
130
|
} catch (error: any) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
131
|
+
const apiError = error as APIError
|
|
132
|
+
|
|
133
|
+
if (apiError.status === 404) {
|
|
134
|
+
setState((prev) => ({
|
|
135
|
+
...prev,
|
|
136
|
+
isLoading: false,
|
|
137
|
+
error: `Component with JLCPCB part number ${partNumber} not found`,
|
|
138
|
+
}))
|
|
139
|
+
} else if (apiError.status === 409) {
|
|
140
|
+
const existingPartNumber = extractExistingPartNumber(
|
|
141
|
+
apiError,
|
|
142
|
+
partNumber,
|
|
143
|
+
)
|
|
144
|
+
setState((prev) => ({
|
|
145
|
+
...prev,
|
|
146
|
+
isLoading: false,
|
|
147
|
+
existingComponent: {
|
|
148
|
+
partNumber: existingPartNumber,
|
|
149
|
+
username: session?.github_username || "",
|
|
150
|
+
},
|
|
151
|
+
}))
|
|
76
152
|
} else {
|
|
77
|
-
|
|
153
|
+
const errorMessage = extractErrorMessage(apiError)
|
|
154
|
+
setState((prev) => ({ ...prev, isLoading: false, error: errorMessage }))
|
|
155
|
+
|
|
78
156
|
toast({
|
|
79
157
|
title: "Import Failed",
|
|
80
|
-
description:
|
|
81
|
-
"Failed to import the JLCPCB component. Please try again.",
|
|
158
|
+
description: errorMessage,
|
|
82
159
|
variant: "destructive",
|
|
83
160
|
})
|
|
84
161
|
}
|
|
85
|
-
|
|
86
|
-
|
|
162
|
+
|
|
163
|
+
return { success: false }
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
...state,
|
|
169
|
+
importComponent,
|
|
170
|
+
resetState,
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function JLCPCBImportDialog({
|
|
175
|
+
open,
|
|
176
|
+
onOpenChange,
|
|
177
|
+
}: JLCPCBImportDialogProps) {
|
|
178
|
+
const [partNumber, setPartNumber] = useState("")
|
|
179
|
+
const isLoggedIn = useGlobalStore((s) => Boolean(s.session))
|
|
180
|
+
|
|
181
|
+
const { isLoading, error, existingComponent, importComponent, resetState } =
|
|
182
|
+
useJLCPCBImport()
|
|
183
|
+
|
|
184
|
+
const handleImport = async () => {
|
|
185
|
+
const result = await importComponent(partNumber)
|
|
186
|
+
if (result.success) {
|
|
187
|
+
onOpenChange(false)
|
|
87
188
|
}
|
|
88
189
|
}
|
|
89
190
|
|
|
191
|
+
const handleInputChange = (value: string) => {
|
|
192
|
+
setPartNumber(value)
|
|
193
|
+
resetState()
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const createGitHubIssue = () => {
|
|
197
|
+
const issueTitle = `[${partNumber}] Failed to import from JLCPCB`
|
|
198
|
+
const issueBody = `I tried to import the part number ${partNumber} from JLCPCB, but it failed. Here's the error I got:\n\`\`\`\n${error}\n\`\`\`\n\nCould be an issue in \`fetchEasyEDAComponent\` or \`convertRawEasyEdaToTs\``
|
|
199
|
+
const issueLabels = "snippets,good first issue"
|
|
200
|
+
const url = `https://github.com/tscircuit/easyeda-converter/issues/new?title=${encodeURIComponent(
|
|
201
|
+
issueTitle,
|
|
202
|
+
)}&body=${encodeURIComponent(issueBody)}&labels=${encodeURIComponent(issueLabels)}`
|
|
203
|
+
window.open(url, "_blank")
|
|
204
|
+
}
|
|
205
|
+
|
|
90
206
|
return (
|
|
91
207
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
92
208
|
<DialogContent>
|
|
@@ -96,6 +212,7 @@ export function JLCPCBImportDialog({
|
|
|
96
212
|
Enter the JLCPCB part number to import the component.
|
|
97
213
|
</DialogDescription>
|
|
98
214
|
</DialogHeader>
|
|
215
|
+
|
|
99
216
|
<div className="py-4 text-center">
|
|
100
217
|
<a
|
|
101
218
|
href="https://yaqwsx.github.io/jlcparts/#/"
|
|
@@ -105,16 +222,13 @@ export function JLCPCBImportDialog({
|
|
|
105
222
|
>
|
|
106
223
|
JLCPCB Part Search
|
|
107
224
|
</a>
|
|
225
|
+
|
|
108
226
|
<Input
|
|
109
227
|
className="mt-3"
|
|
110
228
|
placeholder="Enter JLCPCB part number (e.g., C46749)"
|
|
111
229
|
value={partNumber}
|
|
112
230
|
disabled={isLoading}
|
|
113
|
-
onChange={(e) =>
|
|
114
|
-
setPartNumber(e.target.value)
|
|
115
|
-
setError(null)
|
|
116
|
-
setHasBeenImportedToAccountAlready(false)
|
|
117
|
-
}}
|
|
231
|
+
onChange={(e) => handleInputChange(e.target.value)}
|
|
118
232
|
onKeyDown={(e) => {
|
|
119
233
|
if (
|
|
120
234
|
e.key === "Enter" &&
|
|
@@ -126,43 +240,31 @@ export function JLCPCBImportDialog({
|
|
|
126
240
|
}
|
|
127
241
|
}}
|
|
128
242
|
/>
|
|
129
|
-
{error && !hasBeenImportedToAccountAlready && (
|
|
130
|
-
<p className="bg-red-100 p-2 mt-2 pre-wrap">{error}</p>
|
|
131
|
-
)}
|
|
132
243
|
|
|
133
|
-
{error && !
|
|
134
|
-
|
|
135
|
-
<
|
|
136
|
-
|
|
137
|
-
onClick={
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
issueTitle,
|
|
143
|
-
)}&body=${encodeURIComponent(
|
|
144
|
-
issueBody,
|
|
145
|
-
)}&labels=${encodeURIComponent(issueLabels)}`
|
|
146
|
-
window.open(url, "_blank")
|
|
147
|
-
}}
|
|
148
|
-
>
|
|
149
|
-
File Issue on GitHub (prefilled)
|
|
150
|
-
</Button>
|
|
151
|
-
</div>
|
|
244
|
+
{error && !existingComponent && (
|
|
245
|
+
<>
|
|
246
|
+
<p className="bg-red-100 p-2 mt-2 pre-wrap">{error}</p>
|
|
247
|
+
<div className="flex justify-end mt-2">
|
|
248
|
+
<Button variant="default" onClick={createGitHubIssue}>
|
|
249
|
+
File Issue on GitHub (prefilled)
|
|
250
|
+
</Button>
|
|
251
|
+
</div>
|
|
252
|
+
</>
|
|
152
253
|
)}
|
|
153
254
|
|
|
154
|
-
{
|
|
255
|
+
{existingComponent && (
|
|
155
256
|
<p className="p-2 mt-2 pre-wrap text-md text-green-600">
|
|
156
257
|
This part number has already been imported to your profile.{" "}
|
|
157
258
|
<PrefetchPageLink
|
|
158
259
|
className="text-blue-500 hover:underline"
|
|
159
|
-
href={`/${
|
|
260
|
+
href={`/${existingComponent.username}/${existingComponent.partNumber}`}
|
|
160
261
|
>
|
|
161
262
|
View it here
|
|
162
263
|
</PrefetchPageLink>
|
|
163
264
|
</p>
|
|
164
265
|
)}
|
|
165
266
|
</div>
|
|
267
|
+
|
|
166
268
|
<DialogFooter>
|
|
167
269
|
<Button onClick={handleImport} disabled={isLoading || !isLoggedIn}>
|
|
168
270
|
{!isLoggedIn
|
|
@@ -23,26 +23,33 @@ export const LogContent = ({
|
|
|
23
23
|
error?: ErrorObject | string | null
|
|
24
24
|
}) => {
|
|
25
25
|
return (
|
|
26
|
-
<div className="
|
|
26
|
+
<div className="font-mono text-xs space-y-1 min-w-0">
|
|
27
27
|
{logs.map(
|
|
28
28
|
(log, i) =>
|
|
29
29
|
log.timestamp &&
|
|
30
30
|
log.message && (
|
|
31
31
|
<div
|
|
32
32
|
key={i}
|
|
33
|
-
className={
|
|
33
|
+
className={`break-words whitespace-pre-wrap ${
|
|
34
34
|
log.type === "error"
|
|
35
35
|
? "text-red-600"
|
|
36
36
|
: log.type === "success"
|
|
37
37
|
? "text-green-600"
|
|
38
38
|
: "text-gray-600"
|
|
39
|
-
}
|
|
39
|
+
}`}
|
|
40
40
|
>
|
|
41
|
-
|
|
41
|
+
<span className="text-gray-500 whitespace-nowrap">
|
|
42
|
+
{new Date(log.timestamp).toLocaleTimeString()}
|
|
43
|
+
</span>{" "}
|
|
44
|
+
<span className="break-all">{log.message}</span>
|
|
42
45
|
</div>
|
|
43
46
|
),
|
|
44
47
|
)}
|
|
45
|
-
{error &&
|
|
48
|
+
{error && (
|
|
49
|
+
<div className="text-red-600 break-words whitespace-pre-wrap">
|
|
50
|
+
{getErrorText(error)}
|
|
51
|
+
</div>
|
|
52
|
+
)}
|
|
46
53
|
</div>
|
|
47
54
|
)
|
|
48
55
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
+
import { useCurrentPackageRelease } from "@/hooks/use-current-package-release"
|
|
4
|
+
import { PackageRelease } from "fake-snippets-api/lib/db/schema"
|
|
3
5
|
import { useState } from "react"
|
|
6
|
+
import { LogContent } from "./LogContent"
|
|
4
7
|
import { BuildPreviewContent } from "./build-preview-content"
|
|
8
|
+
import { CollapsibleSection } from "./collapsible-section"
|
|
5
9
|
import { PackageBuildDetailsPanel } from "./package-build-details-panel"
|
|
6
10
|
import { PackageBuildHeader } from "./package-build-header"
|
|
7
|
-
import { CollapsibleSection } from "./collapsible-section"
|
|
8
|
-
import { useCurrentPackageRelease } from "@/hooks/use-current-package-release"
|
|
9
|
-
import { LogContent } from "./LogContent"
|
|
10
|
-
import { PackageRelease } from "fake-snippets-api/lib/db/schema"
|
|
11
11
|
|
|
12
12
|
function computeDuration(
|
|
13
13
|
startedAt: string | null | undefined,
|
|
@@ -18,7 +18,10 @@ function computeDuration(
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export const PackageBuildDetailsPage = () => {
|
|
21
|
-
const { packageRelease } = useCurrentPackageRelease({
|
|
21
|
+
const { packageRelease } = useCurrentPackageRelease({
|
|
22
|
+
include_logs: true,
|
|
23
|
+
refetchInterval: 2000,
|
|
24
|
+
})
|
|
22
25
|
const [openSections, setOpenSections] = useState<Record<string, boolean>>({})
|
|
23
26
|
|
|
24
27
|
const {
|
|
@@ -73,7 +76,6 @@ export const PackageBuildDetailsPage = () => {
|
|
|
73
76
|
transpilation_completed_at,
|
|
74
77
|
)}
|
|
75
78
|
displayStatus={transpilation_display_status}
|
|
76
|
-
error={transpilation_error}
|
|
77
79
|
isOpen={openSections.summary}
|
|
78
80
|
onToggle={() => toggleSection("summary")}
|
|
79
81
|
>
|
|
@@ -94,7 +96,6 @@ export const PackageBuildDetailsPage = () => {
|
|
|
94
96
|
circuit_json_build_completed_at,
|
|
95
97
|
)}
|
|
96
98
|
displayStatus={circuit_json_build_display_status}
|
|
97
|
-
error={circuit_json_build_error}
|
|
98
99
|
isOpen={openSections.logs}
|
|
99
100
|
onToggle={() => toggleSection("logs")}
|
|
100
101
|
>
|
|
@@ -2,7 +2,7 @@ import { useCurrentPackageInfo } from "@/hooks/use-current-package-info"
|
|
|
2
2
|
import { useCurrentPackageRelease } from "@/hooks/use-current-package-release"
|
|
3
3
|
|
|
4
4
|
export function BuildPreviewContent() {
|
|
5
|
-
const { packageRelease } = useCurrentPackageRelease()
|
|
5
|
+
const { packageRelease } = useCurrentPackageRelease({ refetchInterval: 2000 })
|
|
6
6
|
const { packageInfo } = useCurrentPackageInfo()
|
|
7
7
|
|
|
8
8
|
if (!packageRelease) {
|