@autobe/ui 0.19.1 → 0.21.0

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.
Files changed (177) hide show
  1. package/lib/AutoBeChatMain.d.ts +16 -0
  2. package/lib/AutoBeChatMain.js +51 -0
  3. package/lib/AutoBeChatMain.js.map +1 -0
  4. package/lib/banner/AutoBeAgentInformation.d.ts +15 -0
  5. package/lib/banner/AutoBeAgentInformation.js +41 -0
  6. package/lib/banner/AutoBeAgentInformation.js.map +1 -0
  7. package/lib/banner/AutoBeChatBanner.d.ts +15 -0
  8. package/lib/banner/AutoBeChatBanner.js +29 -0
  9. package/lib/banner/AutoBeChatBanner.js.map +1 -0
  10. package/lib/banner/AutoBeChatState.d.ts +6 -0
  11. package/lib/banner/AutoBeChatState.js +80 -0
  12. package/lib/banner/AutoBeChatState.js.map +1 -0
  13. package/lib/banner/AutoBeTokenUsage.d.ts +14 -0
  14. package/lib/banner/AutoBeTokenUsage.js +60 -0
  15. package/lib/banner/AutoBeTokenUsage.js.map +1 -0
  16. package/lib/banner/index.d.ts +4 -0
  17. package/lib/banner/index.js +21 -0
  18. package/lib/banner/index.js.map +1 -0
  19. package/lib/common/Collapsible.d.ts +15 -0
  20. package/lib/common/Collapsible.js +45 -0
  21. package/lib/common/Collapsible.js.map +1 -0
  22. package/lib/common/index.d.ts +2 -0
  23. package/lib/common/index.js +19 -0
  24. package/lib/common/index.js.map +1 -0
  25. package/lib/constant/color.d.ts +18 -0
  26. package/lib/constant/color.js +25 -0
  27. package/lib/constant/color.js.map +1 -0
  28. package/lib/events/AutoBeCompleteEventMovie.d.ts +7 -0
  29. package/lib/events/AutoBeCompleteEventMovie.js +210 -0
  30. package/lib/events/AutoBeCompleteEventMovie.js.map +1 -0
  31. package/lib/events/AutoBeEventMovie.d.ts +8 -0
  32. package/lib/events/AutoBeEventMovie.js +84 -0
  33. package/lib/events/AutoBeEventMovie.js.map +1 -0
  34. package/lib/events/AutoBeProgressEventMovie.js +2 -61
  35. package/lib/events/AutoBeProgressEventMovie.js.map +1 -1
  36. package/lib/events/AutoBeScenarioEventMovie.js +2 -44
  37. package/lib/events/AutoBeScenarioEventMovie.js.map +1 -1
  38. package/lib/events/AutoBeValidateEventMovie.d.ts +6 -0
  39. package/lib/events/AutoBeValidateEventMovie.js +115 -0
  40. package/lib/events/AutoBeValidateEventMovie.js.map +1 -0
  41. package/lib/events/common/CollapsibleEventGroup.d.ts +28 -0
  42. package/lib/events/common/CollapsibleEventGroup.js +89 -0
  43. package/lib/events/common/CollapsibleEventGroup.js.map +1 -0
  44. package/lib/events/common/EventCard.d.ts +13 -0
  45. package/lib/events/common/EventCard.js +43 -0
  46. package/lib/events/common/EventCard.js.map +1 -0
  47. package/lib/events/common/EventContent.d.ts +11 -0
  48. package/lib/events/common/EventContent.js +14 -0
  49. package/lib/events/common/EventContent.js.map +1 -0
  50. package/lib/events/common/EventHeader.d.ts +15 -0
  51. package/lib/events/common/EventHeader.js +41 -0
  52. package/lib/events/common/EventHeader.js.map +1 -0
  53. package/lib/events/common/EventIcon.d.ts +11 -0
  54. package/lib/events/common/EventIcon.js +50 -0
  55. package/lib/events/common/EventIcon.js.map +1 -0
  56. package/lib/events/common/ProgressBar.d.ts +14 -0
  57. package/lib/events/common/ProgressBar.js +33 -0
  58. package/lib/events/common/ProgressBar.js.map +1 -0
  59. package/lib/events/common/index.d.ts +6 -0
  60. package/lib/events/common/index.js +16 -0
  61. package/lib/events/common/index.js.map +1 -0
  62. package/lib/events/groups/ValidateEventGroup.d.ts +12 -0
  63. package/lib/events/groups/ValidateEventGroup.js +78 -0
  64. package/lib/events/groups/ValidateEventGroup.js.map +1 -0
  65. package/lib/events/groups/index.d.ts +1 -0
  66. package/lib/events/groups/index.js +6 -0
  67. package/lib/events/groups/index.js.map +1 -0
  68. package/lib/events/index.d.ts +6 -0
  69. package/lib/events/index.js +27 -1
  70. package/lib/events/index.js.map +1 -1
  71. package/lib/events/utils/eventGrouper.d.ts +20 -0
  72. package/lib/events/utils/eventGrouper.js +74 -0
  73. package/lib/events/utils/eventGrouper.js.map +1 -0
  74. package/lib/events/utils/index.d.ts +1 -0
  75. package/lib/events/utils/index.js +6 -0
  76. package/lib/events/utils/index.js.map +1 -0
  77. package/lib/hooks/index.d.ts +2 -0
  78. package/lib/hooks/index.js +19 -0
  79. package/lib/hooks/index.js.map +1 -0
  80. package/lib/hooks/useIsomorphicLayoutEffect.d.ts +6 -0
  81. package/lib/hooks/useIsomorphicLayoutEffect.js +10 -0
  82. package/lib/hooks/useIsomorphicLayoutEffect.js.map +1 -0
  83. package/lib/hooks/useMediaQuery.d.ts +11 -0
  84. package/lib/hooks/useMediaQuery.js +52 -0
  85. package/lib/hooks/useMediaQuery.js.map +1 -0
  86. package/lib/index.d.ts +5 -0
  87. package/lib/index.js +8 -1
  88. package/lib/index.js.map +1 -1
  89. package/lib/structure/AutoBeListener.d.ts +17 -0
  90. package/lib/structure/AutoBeListener.js +250 -0
  91. package/lib/structure/AutoBeListener.js.map +1 -0
  92. package/lib/structure/AutoBeListenerState.d.ts +14 -0
  93. package/lib/structure/AutoBeListenerState.js +39 -0
  94. package/lib/structure/AutoBeListenerState.js.map +1 -0
  95. package/lib/structure/IAutoBeEventGroup.d.ts +5 -0
  96. package/lib/structure/IAutoBeEventGroup.js +3 -0
  97. package/lib/structure/IAutoBeEventGroup.js.map +1 -0
  98. package/lib/structure/index.d.ts +3 -0
  99. package/lib/structure/index.js +20 -0
  100. package/lib/structure/index.js.map +1 -0
  101. package/lib/upload/AutoBeChatUploadBox.d.ts +31 -0
  102. package/lib/upload/AutoBeChatUploadBox.js +221 -0
  103. package/lib/upload/AutoBeChatUploadBox.js.map +1 -0
  104. package/lib/upload/AutoBeChatUploadSendButton.d.ts +15 -0
  105. package/lib/upload/AutoBeChatUploadSendButton.js +38 -0
  106. package/lib/upload/AutoBeChatUploadSendButton.js.map +1 -0
  107. package/lib/upload/AutoBeFileUploadBox.d.ts +8 -0
  108. package/lib/upload/AutoBeFileUploadBox.js +68 -0
  109. package/lib/upload/AutoBeFileUploadBox.js.map +1 -0
  110. package/lib/upload/AutoBeUploadConfig.d.ts +9 -0
  111. package/lib/upload/AutoBeUploadConfig.js +3 -0
  112. package/lib/upload/AutoBeUploadConfig.js.map +1 -0
  113. package/lib/upload/AutoBeVoiceRecoderButton.d.ts +11 -0
  114. package/lib/upload/AutoBeVoiceRecoderButton.js +58 -0
  115. package/lib/upload/AutoBeVoiceRecoderButton.js.map +1 -0
  116. package/lib/upload/index.d.ts +5 -0
  117. package/lib/upload/index.js +22 -0
  118. package/lib/upload/index.js.map +1 -0
  119. package/lib/utils/AutoBeFileUploader.d.ts +28 -0
  120. package/lib/utils/AutoBeFileUploader.js +237 -0
  121. package/lib/utils/AutoBeFileUploader.js.map +1 -0
  122. package/lib/utils/AutoBeVoiceRecorder.d.ts +7 -0
  123. package/lib/utils/AutoBeVoiceRecorder.js +94 -0
  124. package/lib/utils/AutoBeVoiceRecorder.js.map +1 -0
  125. package/lib/utils/index.d.ts +4 -0
  126. package/lib/utils/index.js +21 -0
  127. package/lib/utils/index.js.map +1 -0
  128. package/lib/utils/number.d.ts +1 -0
  129. package/lib/utils/number.js +20 -0
  130. package/lib/utils/number.js.map +1 -0
  131. package/package.json +13 -2
  132. package/src/AutoBeChatMain.tsx +123 -0
  133. package/src/banner/AutoBeAgentInformation.tsx +102 -0
  134. package/src/banner/AutoBeChatBanner.tsx +72 -0
  135. package/src/banner/AutoBeChatState.tsx +152 -0
  136. package/src/banner/AutoBeTokenUsage.tsx +152 -0
  137. package/src/banner/index.ts +4 -0
  138. package/src/common/Collapsible.tsx +95 -0
  139. package/src/common/index.ts +2 -0
  140. package/src/constant/color.ts +24 -0
  141. package/src/events/AutoBeCompleteEventMovie.tsx +402 -0
  142. package/src/events/AutoBeEventMovie.tsx +114 -0
  143. package/src/events/AutoBeProgressEventMovie.tsx +12 -125
  144. package/src/events/AutoBeScenarioEventMovie.tsx +5 -93
  145. package/src/events/AutoBeValidateEventMovie.tsx +326 -0
  146. package/src/events/README.md +300 -0
  147. package/src/events/common/CollapsibleEventGroup.tsx +220 -0
  148. package/src/events/common/EventCard.tsx +61 -0
  149. package/src/events/common/EventContent.tsx +31 -0
  150. package/src/events/common/EventHeader.tsx +85 -0
  151. package/src/events/common/EventIcon.tsx +82 -0
  152. package/src/events/common/ProgressBar.tsx +63 -0
  153. package/src/events/common/index.ts +13 -0
  154. package/src/events/groups/ValidateEventGroup.tsx +150 -0
  155. package/src/events/groups/index.ts +4 -0
  156. package/src/events/index.ts +12 -0
  157. package/src/events/utils/eventGrouper.tsx +118 -0
  158. package/src/events/utils/index.ts +1 -0
  159. package/src/hooks/index.ts +2 -0
  160. package/src/hooks/useIsomorphicLayoutEffect.ts +8 -0
  161. package/src/hooks/useMediaQuery.ts +68 -0
  162. package/src/index.ts +5 -0
  163. package/src/structure/AutoBeListener.ts +263 -0
  164. package/src/structure/AutoBeListenerState.ts +53 -0
  165. package/src/structure/IAutoBeEventGroup.ts +6 -0
  166. package/src/structure/index.ts +3 -0
  167. package/src/upload/AutoBeChatUploadBox.tsx +372 -0
  168. package/src/upload/AutoBeChatUploadSendButton.tsx +66 -0
  169. package/src/upload/AutoBeFileUploadBox.tsx +123 -0
  170. package/src/upload/AutoBeUploadConfig.ts +5 -0
  171. package/src/upload/AutoBeVoiceRecoderButton.tsx +100 -0
  172. package/src/upload/index.ts +5 -0
  173. package/src/utils/AutoBeFileUploader.ts +279 -0
  174. package/src/utils/AutoBeVoiceRecorder.ts +95 -0
  175. package/src/utils/index.ts +4 -0
  176. package/src/utils/number.ts +17 -0
  177. package/tsconfig.json +2 -1
@@ -0,0 +1,402 @@
1
+ import {
2
+ AutoBeAnalyzeCompleteEvent,
3
+ AutoBeInterfaceCompleteEvent,
4
+ AutoBePrismaCompleteEvent,
5
+ AutoBeRealizeCompleteEvent,
6
+ AutoBeTestCompleteEvent,
7
+ IAutoBeGetFilesOptions,
8
+ } from "@autobe/interface";
9
+ import StackBlitzSDK from "@stackblitz/sdk";
10
+ import JsZip from "jszip";
11
+ import { useState } from "react";
12
+ import { VariadicSingleton } from "tstl";
13
+
14
+ import { EventCard, EventContent, EventHeader } from "./common";
15
+
16
+ export interface IAutoBeCompleteEventMovieProps {
17
+ getFiles: (
18
+ options?: Partial<IAutoBeGetFilesOptions>,
19
+ ) => Promise<Record<string, string>>;
20
+ event:
21
+ | AutoBeAnalyzeCompleteEvent
22
+ | AutoBePrismaCompleteEvent
23
+ | AutoBeInterfaceCompleteEvent
24
+ | AutoBeTestCompleteEvent
25
+ | AutoBeRealizeCompleteEvent;
26
+ }
27
+
28
+ export const AutoBeCompleteEventMovie = (
29
+ props: IAutoBeCompleteEventMovieProps,
30
+ ) => {
31
+ const stage = getStage(props.event);
32
+ const [size, setSize] = useState<number | null>(null);
33
+ const [downloading, setDownloading] = useState(false);
34
+
35
+ const getFiles = async (dbms: "postgres" | "sqlite") => {
36
+ setDownloading(true);
37
+ try {
38
+ const result = await props.getFiles({
39
+ dbms,
40
+ stage,
41
+ });
42
+ return result;
43
+ } catch (error) {
44
+ throw error;
45
+ } finally {
46
+ setDownloading(false);
47
+ }
48
+ };
49
+
50
+ const openStackBlitz = async () => {
51
+ const files: Record<string, string> = Object.fromEntries(
52
+ Object.entries(await getFiles("sqlite")).filter(
53
+ ([key, value]) =>
54
+ key.startsWith("autobe/") === false &&
55
+ new TextEncoder().encode(value).length < 512 * 1024, // 512 KB
56
+ ),
57
+ );
58
+ const size: number = Object.values(files)
59
+ .map((str) => new TextEncoder().encode(str).length)
60
+ .reduce((a, b) => a + b, 0);
61
+ setSize(size);
62
+ StackBlitzSDK.openProject(
63
+ {
64
+ title: `AutoBE Generated Backend Server (${props.event.type})`,
65
+ template: "node",
66
+ files,
67
+ },
68
+ {
69
+ newWindow: true,
70
+ },
71
+ );
72
+ };
73
+
74
+ const download = async (dbms: "postgres" | "sqlite") => {
75
+ const zip: JsZip = new JsZip();
76
+ const directory = new VariadicSingleton((location: string): JsZip => {
77
+ const separated: string[] = location.split("/");
78
+ if (separated.length === 1) return zip.folder(separated[0])!;
79
+ const parent: JsZip = directory.get(separated.slice(0, -1).join("/"));
80
+ return parent.folder(separated.at(-1)!)!;
81
+ });
82
+ for (const [file, content] of Object.entries(await getFiles(dbms))) {
83
+ const separated: string[] = file.split("/");
84
+ if (separated.length === 1) zip.file(file, content);
85
+ else {
86
+ const folder: JsZip = directory.get(separated.slice(0, -1).join("/"));
87
+ folder.file(separated.at(-1)!, content);
88
+ }
89
+ }
90
+ const data: Blob = await zip.generateAsync({ type: "blob" });
91
+
92
+ const url: string = URL.createObjectURL(data);
93
+ const a: HTMLAnchorElement = document.createElement("a");
94
+ a.href = url;
95
+ a.download = `AutoBE.${props.event.type}.zip`;
96
+ document.body.appendChild(a);
97
+ a.click();
98
+ document.body.removeChild(a);
99
+ URL.revokeObjectURL(url);
100
+ };
101
+
102
+ const title: string | null = getTitle(props.event);
103
+ if (title === null) return null;
104
+
105
+ return (
106
+ <EventCard variant="success">
107
+ <EventHeader
108
+ title={`${title} Completed`}
109
+ timestamp={props.event.created_at}
110
+ iconType="success"
111
+ />
112
+ <EventContent>
113
+ <div style={{ marginBottom: "1rem" }}>
114
+ <div
115
+ style={{
116
+ display: "inline-flex",
117
+ alignItems: "center",
118
+ padding: "6px 12px",
119
+ border: "1px solid #4caf50",
120
+ borderRadius: "16px",
121
+ backgroundColor: "transparent",
122
+ color: "#4caf50",
123
+ fontSize: "14px",
124
+ fontWeight: 500,
125
+ gap: "6px",
126
+ marginBottom: "1rem",
127
+ }}
128
+ >
129
+ ✅ {title} Completed
130
+ </div>
131
+ <br />
132
+ <br />
133
+ {title} has been completed.
134
+ {getMessage(openStackBlitz, props.event)}
135
+ <br />
136
+ <br />
137
+ Please check the result in the file explorer.
138
+ {size !== null && size >= LIMIT && (
139
+ <div
140
+ style={{
141
+ backgroundColor: "#fffbeb",
142
+ border: "1px solid #fed7aa",
143
+ borderRadius: "0.5rem",
144
+ padding: "1rem",
145
+ marginTop: "1rem",
146
+ color: "#92400e",
147
+ }}
148
+ >
149
+ <strong>⚠️ Warning:</strong> This project is too large (
150
+ {(size / 1024 / 1024).toFixed(1)} MB) for StackBlitz.
151
+ <br />
152
+ <br />
153
+ Try downloading it directly instead!
154
+ </div>
155
+ )}
156
+ </div>
157
+
158
+ {/* Action Buttons */}
159
+ <div
160
+ style={{
161
+ display: "flex",
162
+ gap: "0.75rem",
163
+ justifyContent: "flex-end",
164
+ flexWrap: "wrap",
165
+ }}
166
+ >
167
+ {downloading ? (
168
+ <button
169
+ disabled
170
+ style={{
171
+ display: "flex",
172
+ alignItems: "center",
173
+ gap: "0.5rem",
174
+ padding: "0.75rem 1rem",
175
+ backgroundColor: "#f3f4f6",
176
+ border: "1px solid #d1d5db",
177
+ borderRadius: "0.5rem",
178
+ cursor: "not-allowed",
179
+ fontSize: "0.875rem",
180
+ color: "#6b7280",
181
+ }}
182
+ >
183
+ ⏳ Downloading Source Codes...
184
+ </button>
185
+ ) : props.event.type === "analyzeComplete" ? (
186
+ <>
187
+ <ActionButton
188
+ icon="📥"
189
+ text="Zip (SQLite)"
190
+ onClick={() => download("sqlite")}
191
+ title={
192
+ stage !== "analyze"
193
+ ? "Download SQLite-based backend application (ideal for local development and testing)"
194
+ : "Download requirement analysis report"
195
+ }
196
+ />
197
+ <ActionButton
198
+ icon="🚀"
199
+ text="StackBlitz"
200
+ onClick={() => openStackBlitz()}
201
+ variant={size !== null && size >= LIMIT ? "warning" : "primary"}
202
+ title="Open project in StackBlitz for instant online development and testing"
203
+ />
204
+ </>
205
+ ) : (
206
+ <>
207
+ <ActionButton
208
+ icon="☁️"
209
+ text="Zip (Postgres)"
210
+ onClick={() => download("postgres")}
211
+ title="Download PostgreSQL-based backend application (optimized for production deployment)"
212
+ />
213
+ <ActionButton
214
+ icon="📥"
215
+ text="Zip (SQLite)"
216
+ onClick={() => download("sqlite")}
217
+ title="Download SQLite-based backend application (ideal for local development and testing)"
218
+ />
219
+ <ActionButton
220
+ icon="🚀"
221
+ text="StackBlitz"
222
+ onClick={() => openStackBlitz()}
223
+ variant={size !== null && size >= LIMIT ? "warning" : "primary"}
224
+ title="Open project in StackBlitz for instant online development and testing"
225
+ />
226
+ </>
227
+ )}
228
+ </div>
229
+ </EventContent>
230
+ </EventCard>
231
+ );
232
+ };
233
+
234
+ interface IActionButtonProps {
235
+ icon: string;
236
+ text: string;
237
+ onClick: () => void;
238
+ title?: string;
239
+ variant?: "primary" | "warning";
240
+ }
241
+
242
+ const ActionButton = (props: IActionButtonProps) => {
243
+ const { icon, text, onClick, title, variant = "primary" } = props;
244
+
245
+ const getButtonStyles = () => {
246
+ const baseStyles = {
247
+ display: "flex",
248
+ alignItems: "center",
249
+ gap: "0.5rem",
250
+ padding: "0.75rem 1rem",
251
+ borderRadius: "0.5rem",
252
+ cursor: "pointer",
253
+ fontSize: "0.875rem",
254
+ fontWeight: 500,
255
+ border: "1px solid",
256
+ transition: "all 0.2s ease",
257
+ };
258
+
259
+ if (variant === "warning") {
260
+ return {
261
+ ...baseStyles,
262
+ backgroundColor: "#fffbeb",
263
+ borderColor: "#f59e0b",
264
+ color: "#92400e",
265
+ };
266
+ }
267
+
268
+ return {
269
+ ...baseStyles,
270
+ backgroundColor: "#3b82f6",
271
+ borderColor: "#3b82f6",
272
+ color: "#ffffff",
273
+ };
274
+ };
275
+
276
+ return (
277
+ <button
278
+ onClick={onClick}
279
+ title={title}
280
+ style={getButtonStyles()}
281
+ onMouseEnter={(e) => {
282
+ if (variant === "warning") {
283
+ e.currentTarget.style.backgroundColor = "#fef3c7";
284
+ } else {
285
+ e.currentTarget.style.backgroundColor = "#2563eb";
286
+ }
287
+ }}
288
+ onMouseLeave={(e) => {
289
+ if (variant === "warning") {
290
+ e.currentTarget.style.backgroundColor = "#fffbeb";
291
+ } else {
292
+ e.currentTarget.style.backgroundColor = "#3b82f6";
293
+ }
294
+ }}
295
+ >
296
+ <span>{icon}</span>
297
+ <span>{text}</span>
298
+ </button>
299
+ );
300
+ };
301
+
302
+ // Helper functions
303
+
304
+ function getTitle(
305
+ event: IAutoBeCompleteEventMovieProps["event"],
306
+ ): string | null {
307
+ switch (event.type) {
308
+ case "analyzeComplete":
309
+ return "Analyze";
310
+ case "prismaComplete":
311
+ if (event.compiled.type !== "success") return "Prisma (Error)";
312
+ return "Prisma";
313
+ case "interfaceComplete":
314
+ return "Interface";
315
+ case "testComplete":
316
+ return "Test";
317
+ case "realizeComplete":
318
+ return "Realize";
319
+ default:
320
+ event satisfies never;
321
+ throw new Error("Unknown event type");
322
+ }
323
+ }
324
+
325
+ const getMessage = (
326
+ openStackBlitz: () => void,
327
+ event: IAutoBeCompleteEventMovieProps["event"],
328
+ ) => {
329
+ if (event.type === "prismaComplete" && event.compiled.type === "failure")
330
+ return (
331
+ <>
332
+ <br />
333
+ <br />
334
+ Succeeded to compose <code>AutoBePrisma.IApplication</code> typed AST
335
+ (Abstract Syntax Tree) data, but failed to generate Prisma schema files
336
+ from it. This is a bug of <code>@autobe</code>. Please{" "}
337
+ <a
338
+ href="https://github.com/wrtnlabs/autobe/issues"
339
+ target="_blank"
340
+ style={{ color: "#3b82f6", textDecoration: "underline" }}
341
+ >
342
+ write a bug report to our repository
343
+ </a>{" "}
344
+ with the{" "}
345
+ <a
346
+ href="#"
347
+ onClick={() => openStackBlitz()}
348
+ style={{ color: "#3b82f6", textDecoration: "underline" }}
349
+ >
350
+ <code>autobe/histories.json</code>
351
+ </a>{" "}
352
+ file.
353
+ </>
354
+ );
355
+ else if (
356
+ (event.type === "testComplete" || event.type === "realizeComplete") &&
357
+ event.compiled.type !== "success"
358
+ )
359
+ return (
360
+ <>
361
+ <br />
362
+ <br />
363
+ Succeeded to compose{" "}
364
+ {event.type === "testComplete" ? "test functions" : "realize functions"}
365
+ , but failed to pass the TypeScript compilation. This is a bug of{" "}
366
+ <code>@autobe</code>. Please{" "}
367
+ <a
368
+ href="https://github.com/wrtnlabs/autobe/issues"
369
+ target="_blank"
370
+ style={{ color: "#3b82f6", textDecoration: "underline" }}
371
+ >
372
+ write a bug report to our repository
373
+ </a>{" "}
374
+ with the{" "}
375
+ <a
376
+ href="#"
377
+ onClick={() => openStackBlitz()}
378
+ style={{ color: "#3b82f6", textDecoration: "underline" }}
379
+ >
380
+ <code>autobe/histories.json</code>
381
+ </a>{" "}
382
+ file.
383
+ </>
384
+ );
385
+ return null;
386
+ };
387
+
388
+ const getStage = (event: IAutoBeCompleteEventMovieProps["event"]) => {
389
+ if (event.type === "analyzeComplete") return "analyze";
390
+ else if (event.type === "prismaComplete") return "prisma";
391
+ else if (event.type === "interfaceComplete") return "interface";
392
+ else if (event.type === "testComplete") return "test";
393
+ else if (event.type === "realizeComplete") return "realize";
394
+ else {
395
+ event satisfies never;
396
+ return undefined;
397
+ }
398
+ };
399
+
400
+ const LIMIT = 3 * 1024 * 1024;
401
+
402
+ export default AutoBeCompleteEventMovie;
@@ -0,0 +1,114 @@
1
+ import { AutoBeEvent, IAutoBeGetFilesOptions } from "@autobe/interface";
2
+
3
+ import {
4
+ AutoBeCompleteEventMovie,
5
+ AutoBeProgressEventMovie,
6
+ AutoBeScenarioEventMovie,
7
+ AutoBeStartEventMovie,
8
+ AutoBeValidateEventMovie,
9
+ IValidateEventGroupProps,
10
+ ValidateEventGroup,
11
+ } from ".";
12
+ import { AutoBeAssistantMessageMovie, AutoBeUserMessageMovie } from "..";
13
+
14
+ export interface IAutoBeEventMovieProps<Event extends AutoBeEvent> {
15
+ getFiles: (
16
+ options?: Partial<IAutoBeGetFilesOptions>,
17
+ ) => Promise<Record<string, string>>;
18
+ events: Event[];
19
+ last: boolean;
20
+ }
21
+
22
+ export function AutoBeEventMovie<Event extends AutoBeEvent>(
23
+ props: IAutoBeEventMovieProps<Event>,
24
+ ) {
25
+ const back: Event = props.events[props.events.length - 1]!;
26
+ switch (back.type) {
27
+ case "userMessage":
28
+ return <AutoBeUserMessageMovie message={back.contents} />;
29
+ case "assistantMessage":
30
+ return (
31
+ <AutoBeAssistantMessageMovie
32
+ text={back.text}
33
+ isoTimestamp={back.created_at}
34
+ />
35
+ );
36
+ // START EVENTS
37
+ case "analyzeStart":
38
+ case "prismaStart":
39
+ case "interfaceStart":
40
+ case "testStart":
41
+ case "realizeStart":
42
+ case "realizeTestStart":
43
+ case "realizeAuthorizationStart":
44
+ return <AutoBeStartEventMovie event={back} />;
45
+ // SCENARIO EVENTS
46
+ case "analyzeScenario":
47
+ case "prismaComponents":
48
+ case "interfaceGroups":
49
+ case "realizeTestReset":
50
+ return <AutoBeScenarioEventMovie event={back} />;
51
+ // PROGRESS EVENTS
52
+ case "analyzeWrite":
53
+ case "analyzeReview":
54
+ case "interfaceEndpoints":
55
+ case "prismaSchemas":
56
+ case "prismaReview":
57
+ case "interfaceOperations":
58
+ case "interfaceOperationsReview":
59
+ case "interfaceAuthorization":
60
+ case "interfaceSchemas":
61
+ case "interfaceSchemasReview":
62
+ case "testWrite":
63
+ case "testScenarios":
64
+ case "realizeWrite":
65
+ case "realizeAuthorizationWrite":
66
+ case "realizeTestOperation":
67
+ return <AutoBeProgressEventMovie event={back} />;
68
+ // VALIDATE EVENTS
69
+ case "prismaInsufficient":
70
+ case "prismaValidate":
71
+ case "interfaceComplement":
72
+ case "testValidate":
73
+ case "realizeValidate":
74
+ case "realizeAuthorizationValidate":
75
+ if (props.events.length === 1) {
76
+ return <AutoBeValidateEventMovie event={back} />;
77
+ }
78
+
79
+ return (
80
+ <ValidateEventGroup
81
+ events={props.events as IValidateEventGroupProps["events"]}
82
+ defaultCollapsed={true}
83
+ />
84
+ );
85
+ // COMPLETE EVENTS
86
+ case "analyzeComplete":
87
+ case "prismaComplete":
88
+ case "interfaceComplete":
89
+ case "testComplete":
90
+ case "realizeComplete":
91
+ return (
92
+ <AutoBeCompleteEventMovie getFiles={props.getFiles} event={back} />
93
+ );
94
+ // DISCARD
95
+ case "prismaCorrect":
96
+ case "interfaceEndpointsReview":
97
+ case "testCorrect":
98
+ case "realizeAuthorizationCorrect":
99
+ case "realizeCorrect":
100
+ case "realizeTestComplete":
101
+ case "realizeAuthorizationComplete":
102
+ case "vendorRequest":
103
+ case "vendorResponse":
104
+ case "jsonParseError":
105
+ case "jsonValidateError":
106
+ case "consentFunctionCall":
107
+ return null;
108
+ default:
109
+ back satisfies never;
110
+ return null;
111
+ }
112
+ }
113
+
114
+ export default AutoBeEventMovie;
@@ -1,6 +1,6 @@
1
1
  import { AutoBeEvent, AutoBeProgressEventBase } from "@autobe/interface";
2
2
 
3
- import { formatTime } from "../utils/time";
3
+ import { EventCard, EventContent, EventHeader, ProgressBar } from "./common";
4
4
 
5
5
  export function AutoBeProgressEventMovie(
6
6
  props: AutoBeProgressEventMovie.IProps,
@@ -8,130 +8,17 @@ export function AutoBeProgressEventMovie(
8
8
  const state: IState = getState(props.event);
9
9
 
10
10
  return (
11
- <div
12
- style={{
13
- backgroundColor: "#f8fafc",
14
- border: "1px solid #e2e8f0",
15
- borderRadius: "0.75rem",
16
- padding: "1.5rem",
17
- marginBottom: "1rem",
18
- boxShadow: "0 1px 3px 0 rgb(0 0 0 / 0.1)",
19
- }}
20
- >
21
- {/* Header */}
22
- <div
23
- style={{
24
- display: "flex",
25
- alignItems: "center",
26
- justifyContent: "space-between",
27
- marginBottom: "1rem",
28
- }}
29
- >
30
- <div
31
- style={{
32
- display: "flex",
33
- alignItems: "center",
34
- gap: "0.75rem",
35
- }}
36
- >
37
- {/* Status Icon */}
38
- <div
39
- style={{
40
- width: "2rem",
41
- height: "2rem",
42
- backgroundColor: "#4caf50",
43
- borderRadius: "50%",
44
- display: "flex",
45
- alignItems: "center",
46
- justifyContent: "center",
47
- }}
48
- >
49
- <svg
50
- width="16"
51
- height="16"
52
- viewBox="0 0 24 24"
53
- fill="currentColor"
54
- style={{ color: "#ffffff" }}
55
- >
56
- <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
57
- </svg>
58
- </div>
59
-
60
- {/* Title */}
61
- <div>
62
- <h3
63
- style={{
64
- fontSize: "1.125rem",
65
- fontWeight: "600",
66
- color: "#1e293b",
67
- margin: 0,
68
- marginBottom: "0.25rem",
69
- }}
70
- >
71
- {state.title}
72
- </h3>
73
- </div>
74
- </div>
75
-
76
- {/* Timestamp */}
77
- <div
78
- style={{
79
- fontSize: "0.75rem",
80
- color: "#64748b",
81
- textAlign: "right",
82
- }}
83
- >
84
- {formatTime(props.event.created_at)}
85
- </div>
86
- </div>
87
-
88
- {/* Content */}
89
- <div
90
- style={{
91
- fontSize: "0.875rem",
92
- lineHeight: "1.5",
93
- color: "#475569",
94
- backgroundColor: "#ffffff",
95
- padding: "1rem",
96
- borderRadius: "0.5rem",
97
- border: "1px solid #e2e8f0",
98
- }}
99
- >
100
- <div style={{ marginBottom: "1rem" }}>{state.description}</div>
101
-
102
- {/* Progress Bar */}
103
- <div
104
- style={{
105
- width: "100%",
106
- height: "10px",
107
- backgroundColor: "#e2e8f0",
108
- borderRadius: "10px",
109
- overflow: "hidden",
110
- marginBottom: "0.5rem",
111
- }}
112
- >
113
- <div
114
- style={{
115
- width: `${Math.round((state.completed / state.total) * 100)}%`,
116
- height: "100%",
117
- backgroundColor: "#4caf50",
118
- borderRadius: "10px",
119
- transition: "width 0.3s ease",
120
- }}
121
- />
122
- </div>
123
-
124
- <div
125
- style={{
126
- fontSize: "0.75rem",
127
- color: "#64748b",
128
- textAlign: "center",
129
- }}
130
- >
131
- {state.completed} / {state.total} completed
132
- </div>
133
- </div>
134
- </div>
11
+ <EventCard>
12
+ <EventHeader
13
+ title={state.title}
14
+ timestamp={props.event.created_at}
15
+ iconType="progress"
16
+ />
17
+ <EventContent>
18
+ <div style={{ marginBottom: 0 }}>{state.description}</div>
19
+ <ProgressBar current={state.completed} total={state.total} />
20
+ </EventContent>
21
+ </EventCard>
135
22
  );
136
23
  }
137
24
  type ExtractType<T, U> = T extends U ? T : never;