Ver Fonte

wip: zen

Frank há 5 meses atrás
pai
commit
c6c153de95

+ 14 - 0
cloud/app/src/routes/workspace/[id].css

@@ -115,11 +115,18 @@
   [data-component="api-keys-section"] {
     [data-slot="create-form"] {
       display: flex;
+      flex-direction: column;
       gap: var(--space-3);
       padding: var(--space-4);
       border: 1px solid var(--color-border);
       border-radius: var(--border-radius-sm);
 
+      [data-slot="input-container"] {
+        display: flex;
+        flex-direction: column;
+        gap: var(--space-1);
+      }
+
       @media (max-width: 30rem) {
         gap: var(--space-2);
       }
@@ -148,6 +155,13 @@
         display: flex;
         gap: var(--space-2);
       }
+
+      [data-slot="form-error"] {
+        color: var(--color-danger);
+        font-size: var(--font-size-sm);
+        margin-top: var(--space-1);
+        line-height: 1.4;
+      }
     }
 
     [data-slot="api-keys-table"] {

+ 27 - 6
cloud/app/src/routes/workspace/[id].tsx

@@ -49,7 +49,13 @@ const createKey = action(async (form: FormData) => {
   const workspaceID = form.get("workspaceID")?.toString()
   if (!workspaceID) return { error: "Workspace ID is required" }
   return json(
-    withActor(() => Key.create({ name }), workspaceID),
+    withActor(
+      () =>
+        Key.create({ name })
+          .then((data) => ({ data }))
+          .catch((e) => ({ error: e.message })),
+      workspaceID,
+    ),
     { revalidate: listKeys.key },
   )
 }, "key.create")
@@ -185,19 +191,27 @@ function KeySection() {
 function KeyCreateForm() {
   const params = useParams()
   const submission = useSubmission(createKey)
-  const [store, setStore] = createStore({
-    show: false,
-  })
+  const [store, setStore] = createStore({ show: false })
 
   let input: HTMLInputElement
 
   createEffect(() => {
-    if (!submission.pending && submission.result) {
+    // @ts-expect-error
+    if (!submission.pending && submission.result?.data) {
       hide()
     }
   })
 
   function show() {
+    // submission.clear() does not clear the result in some cases, ie.
+    //  1. Create key with empty name => error shows
+    //  2. Put in a key name and creates the key => form hides
+    //  3. Click add key button again => form shows with the same error if
+    //     submission.clear() is called only once
+    for (let i = 0; i < 3; i++) {
+      submission.clear()
+      if (!submission.result) break
+    }
     setStore("show", true)
     input.focus()
   }
@@ -216,7 +230,14 @@ function KeyCreateForm() {
       }
     >
       <form action={createKey} method="post" data-slot="create-form">
-        <input ref={(r) => (input = r)} data-component="input" name="name" type="text" placeholder="Enter key name" />
+        <div data-slot="input-container">
+          <input ref={(r) => (input = r)} data-component="input" name="name" type="text" placeholder="Enter key name" />
+          {/* @ts-expect-error */}
+          <Show when={submission.result?.error}>
+            {/* @ts-expect-error */}
+            <div data-slot="form-error">{submission.result.error}</div>
+          </Show>
+        </div>
         <input type="hidden" name="workspaceID" value={params.id} />
         <div data-slot="form-actions">
           <button type="reset" data-color="ghost" onClick={() => hide()}>

+ 5 - 1
cloud/core/src/key.ts

@@ -41,7 +41,11 @@ export namespace Key {
         key: secretKey,
         timeUsed: null,
       }),
-    )
+    ).catch((e: any) => {
+      if (e.message.match(/Duplicate entry '.*' for key 'key.name'/))
+        throw new Error("A key with this name already exists. Please choose a different name.")
+      throw e
+    })
 
     return keyID
   })