Selaa lähdekoodia

fix(tui): render skill load errors inline (#33298)

Aiden Cline 1 kuukausi sitten
vanhempi
sitoutus
9dadc2455f
1 muutettua tiedostoa jossa 40 lisäystä ja 6 poistoa
  1. 40 6
      packages/tui/src/component/dialog-skill.tsx

+ 40 - 6
packages/tui/src/component/dialog-skill.tsx

@@ -1,7 +1,10 @@
+import { TextAttributes } from "@opentui/core"
 import { DialogSelect, type DialogSelectOption } from "../ui/dialog-select"
-import { createResource, createMemo } from "solid-js"
+import { createResource, createMemo, createSignal } from "solid-js"
 import { useDialog } from "../ui/dialog"
 import { useSDK } from "../context/sdk"
+import { useTheme } from "../context/theme"
+import { errorMessage } from "../util/error"
 
 export type DialogSkillProps = {
   onSelect: (skill: string) => void
@@ -10,14 +13,27 @@ export type DialogSkillProps = {
 export function DialogSkill(props: DialogSkillProps) {
   const dialog = useDialog()
   const sdk = useSDK()
+  const { theme } = useTheme()
   dialog.setSize("large")
 
-  const [skills] = createResource(async () => {
-    const result = await sdk.client.app.skills()
-    return result.data ?? []
-  })
+  const [loadError, setLoadError] = createSignal<unknown>()
+
+  const [skills] = createResource(() =>
+    sdk.client.app
+      .skills({}, { throwOnError: true })
+      .then((result) => result.data ?? [])
+      // Catch so the rejected resource never reaches the memo below: reading
+      // skills() in an errored state re-throws and tears down the dialog.
+      .catch((error) => {
+        setLoadError(error)
+        return undefined
+      }),
+  )
+
+  const showError = createMemo(() => Boolean(loadError()))
 
   const options = createMemo<DialogSelectOption<string>[]>(() => {
+    if (showError()) return []
     const list = skills() ?? []
     const maxWidth = Math.max(0, ...list.map((s) => s.name.length))
     return list.map((skill) => ({
@@ -32,5 +48,23 @@ export function DialogSkill(props: DialogSkillProps) {
     }))
   })
 
-  return <DialogSelect title="Skills" placeholder="Search skills..." options={options()} />
+  return (
+    <DialogSelect
+      title="Skills"
+      placeholder="Search skills..."
+      options={options()}
+      renderFilter={!showError()}
+      locked={showError()}
+      emptyView={
+        showError() ? (
+          <box paddingLeft={4} paddingRight={4}>
+            <text fg={theme.error} attributes={TextAttributes.BOLD}>
+              Could not load skills
+            </text>
+            <text fg={theme.textMuted}>{errorMessage(loadError())}</text>
+          </box>
+        ) : undefined
+      }
+    />
+  )
 }