Merge pull request #6 from BaaRai/fix/credentials-ui-regression

Fix credentials UI regression from #4
This commit is contained in:
BaaRai
2026-10-09 14:46:17 +02:00
committed by GitHub
2 changed files with 56 additions and 56 deletions
@@ -434,15 +434,15 @@ function TaskDetailInner() {
<TabsContent value="findings" className="mt-0">
<FindingsTab taskId={id} />
</TabsContent>
<TabsContent value="credentials" className="mt-0">
<CredentialsTab taskId={task.id} />
</TabsContent>
<TabsContent value="retests" className="mt-0">
<RetestsTab key={id} taskId={id} />
</TabsContent>
<TabsContent value="assets" className="mt-0">
<AssetsTab taskId={id} />
</TabsContent>
<TabsContent value="credentials" className="mt-0">
<CredentialsTab taskId={id} />
</TabsContent>
<TabsContent value="coverage" className="mt-0">
<CoverageGraphTab taskId={id} coverageEnabled={task?.coverage_enabled !== false} />
</TabsContent>
+53 -53
View File
@@ -3335,6 +3335,59 @@ function CreateTaskSheet({
/>
<FieldDescription>Failover follows the list order; the first entry is the current config, and the next one is used only when the quota is clearly insufficient.</FieldDescription>
</Field>
<Field>
<FieldLabel htmlFor="task-credentials">Test accounts (optional)</FieldLabel>
<div className="grid gap-2">
{credentials.map((c, i) => (
<div key={i} className="grid gap-2 sm:grid-cols-[1fr_1fr_1fr_auto]">
<Input
placeholder="domain (e.g. target.example.com)"
value={c.domain}
onChange={(e) => setCredentials((prev) => prev.map((x, j) => (j === i ? { ...x, domain: e.target.value } : x)))}
/>
<Input
placeholder="username"
value={c.username}
onChange={(e) => setCredentials((prev) => prev.map((x, j) => (j === i ? { ...x, username: e.target.value } : x)))}
/>
<Input
placeholder="password (empty = agent generates)"
value={c.password}
onChange={(e) => setCredentials((prev) => prev.map((x, j) => (j === i ? { ...x, password: e.target.value } : x)))}
/>
<Button
type="button"
variant="ghost"
size="icon"
aria-label="Remove account"
onClick={() => setCredentials((prev) => prev.filter((_, j) => j !== i))}
>
<TrashIcon />
</Button>
<Input
className="sm:col-span-4"
placeholder="note (optional, e.g. program alias account)"
value={c.note ?? ""}
onChange={(e) => setCredentials((prev) => prev.map((x, j) => (j === i ? { ...x, note: e.target.value } : x)))}
/>
</div>
))}
<Button
type="button"
size="sm"
variant="outline"
className="w-fit"
onClick={() => setCredentials((prev) => [...prev, { domain: "", username: "", password: "", note: "" }])}
>
<PlusIcon className="size-4" /> Add account
</Button>
</div>
<FieldDescription>
Test accounts reused by the agent for authenticated testing. Leave the password empty to have the agent register that
account itself and record the password it chose. Use dedicated test accounts only — anything declared here is sent to
the configured LLM provider during the task.
</FieldDescription>
</Field>
{/* Advanced parameters are collapsed by default: timeout/heartbeat/first intent; they take space only when expanded, keeping the common path clean. */}
<Collapsible>
@@ -3408,59 +3461,6 @@ function CreateTaskSheet({
</div>
</div>
<div className="grid gap-2">
<div className="flex items-center justify-between">
<label className="text-sm font-medium">Test accounts (optional)</label>
<Button
type="button"
variant="outline"
size="sm"
onClick={() => setCredentials((prev) => [...prev, { domain: "", username: "", password: "", note: "" }])}
>
<PlusIcon /> Add account
</Button>
</div>
<p className="text-muted-foreground text-xs">
Test accounts reused by the agent for authenticated testing. Leave the password empty to have the agent register that
account itself and record the password it chose. Use dedicated test accounts only — anything declared here is sent to
the configured LLM provider during the task.
</p>
{credentials.map((c, i) => (
<div key={i} className="grid gap-2 sm:grid-cols-[1fr_1fr_1fr_auto]">
<Input
placeholder="domain (e.g. target.example.com)"
value={c.domain}
onChange={(e) => setCredentials((prev) => prev.map((x, j) => (j === i ? { ...x, domain: e.target.value } : x)))}
/>
<Input
placeholder="username"
value={c.username}
onChange={(e) => setCredentials((prev) => prev.map((x, j) => (j === i ? { ...x, username: e.target.value } : x)))}
/>
<Input
placeholder="password (empty = agent generates)"
value={c.password}
onChange={(e) => setCredentials((prev) => prev.map((x, j) => (j === i ? { ...x, password: e.target.value } : x)))}
/>
<Button
type="button"
variant="ghost"
size="icon"
aria-label="Remove account"
onClick={() => setCredentials((prev) => prev.filter((_, j) => j !== i))}
>
<TrashIcon />
</Button>
<Input
className="sm:col-span-4"
placeholder="note (optional, e.g. program alias account)"
value={c.note ?? ""}
onChange={(e) => setCredentials((prev) => prev.map((x, j) => (j === i ? { ...x, note: e.target.value } : x)))}
/>
</div>
))}
</div>
<SheetFooter className="flex-row justify-end gap-2 border-t p-4">
<SheetClose asChild>
<Button variant="outline">Cancel</Button>