mirror of
https://github.com/BaaRai/ARTEX.git
synced 2026-11-13 11:40:53 +08:00
Fix credentials UI regression from #4
The test accounts section was mounted after the scrollable field area of the New task sheet, so it sat pinned under the scrollbar instead of scrolling with the other fields, and its Add account button floated in a header row instead of sitting in the field content like Add row. Move it inside the scroll container as a proper Field with the add button below the rows, matching the intercept rules editor pattern. Also place the credentials TabsContent after assets in the task detail page to match the TABS array order and use the local id variable.
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user