Feature 11: Settings home and Admin AI assistant #86

Merged
approver_agent merged 9 commits from feature/b28d9979-0f7a-4e81-bdff-2f16f3db2053-settings-admin-ai into dev 2026-10-06 12:45:06 -04:00
3 changed files with 37 additions and 3 deletions
Showing only changes of commit 42d58aad94 - Show all commits
+3 -2
View File
@@ -305,8 +305,9 @@
resize: none;
}
/* A form locked while its save is pending, so no edit is made that the
saved settings would then replace. It lays out as if it were not there. */
/* A form locked while its save or prompt reset is pending, so no edit is
made that the response would then replace. It lays out as if it were not
there. */
.lock {
display: contents;
}
+33
View File
@@ -431,6 +431,39 @@ describe('AISettingsPage', () => {
await waitFor(() => expect(unload()).toBe(false))
})
it('locks the form while a prompt reset is pending, even with the sheet closed', async () => {
let answer: (response: Response) => void = () => {}
stubAPI({
'POST /api/v1/settings/ai/reset-prompt': () => new Promise<Response>((resolve) => (answer = resolve)),
})
await renderPage()
const unload = () => {
const event = new Event('beforeunload', { cancelable: true })
act(() => void window.dispatchEvent(event))
return event.defaultPrevented
}
fireEvent.change(slider(), { target: { value: '0.2' } })
fireEvent.click(screen.getByRole('button', { name: 'Reset' }))
const confirm = screen.getByRole('dialog', { name: 'Reset the system prompt?' })
fireEvent.click(within(confirm).getByRole('button', { name: 'Reset prompt' }))
expect(await within(confirm).findByRole('button', { name: 'Resetting…' })).toBeDisabled()
fireEvent.click(within(confirm).getByRole('button', { name: 'Cancel' }))
await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument())
for (const field of [provider(), model(), slider(), prompt()]) expect(field).toBeDisabled()
expect(screen.getByRole('button', { name: 'Reset' })).toBeDisabled()
expect(save()).toBeDisabled()
expect(unload()).toBe(true)
answer(jsonResponse(200, { ...AI_SETTINGS, system_prompt: DEFAULT_PROMPT }))
await waitFor(() => expect(prompt()).toBeEnabled())
expect(prompt()).toHaveValue(DEFAULT_PROMPT)
expect(slider()).toHaveValue('0.2')
expect(unload()).toBe(true)
fireEvent.change(prompt(), { target: { value: 'After the reset.' } })
expect(prompt()).toHaveValue('After the reset.')
})
it('keeps 44 px tap targets', async () => {
stubAPI()
await renderPage()
+1 -1
View File
@@ -201,7 +201,7 @@ function AISettingsForm({ saved, onDirtyChange }: AISettingsFormProps) {
}
return (
<fieldset className={styles.lock} disabled={save.isPending}>
<fieldset className={styles.lock} disabled={save.isPending || resetPrompt.isPending}>
<div className={styles.columns}>
<Select
label="Provider"