feature: the package installs the Router Manager, which is no longer a package of its own.
Release / release (push) Failing after 4s

This commit is contained in:
slawek committed 2026-11-14 12:52:44 +01:00
1 parent 6d90441bee
commit 8efe21bfa6
129 files changed
+17381 -104

No files matched your search

+54
View File
@@ -0,0 +1,54 @@
import { Alert, Button, Dialog, DialogActions, DialogContent, DialogTitle, Stack } from '@mui/material'
import { useState, type FormEvent } from 'react'
import PersonFields from './PersonFields.tsx'
import type { Person, User } from './api.ts'
import { personComplete, personProblems, trimmed } from './person.ts'
/**
* A dialog that edits the first name, last name and e-mail address of a VPN user, or the optional e-mail address of a
* Manager-only account, where an empty one removes it; onSave sends them.
*/
export default function PersonDialog(props: { user: User; onSave: (person: Partial<Person>) => Promise<void>; onCancel: () => void }) {
const [person, setPerson] = useState<Person>({
first_name: props.user.first_name ?? '',
last_name: props.user.last_name ?? '',
email: props.user.email ?? '',
})
const [saving, setSaving] = useState(false)
const [error, setError] = useState<string | null>(null)
const managerOnly = props.user.manager_only
const blocked = managerOnly ? personProblems(person).email !== '' : !personComplete(person)
async function submit(event: FormEvent) {
event.preventDefault()
if (blocked) {
return
}
setSaving(true)
setError(null)
try {
await props.onSave(managerOnly ? { email: person.email.trim() } : trimmed(person))
} catch (caught) {
setError((caught as Error).message)
setSaving(false)
}
}
return (
<Dialog open onClose={(_event, reason) => reason !== 'backdropClick' && props.onCancel()} maxWidth="xs" fullWidth slotProps={{ paper: { component: 'form', onSubmit: submit } }}>
<DialogTitle>Details of {props.user.name}</DialogTitle>
<DialogContent>
<Stack sx={{ gap: 2, pt: 1 }}>
{error && <Alert severity="error" sx={{ whiteSpace: 'pre-line' }}>{error}</Alert>}
<PersonFields person={person} onChange={setPerson} autoFocus emailOnly={managerOnly} />
</Stack>
</DialogContent>
<DialogActions>
<Button onClick={props.onCancel}>Cancel</Button>
<Button type="submit" variant="contained" disabled={saving || blocked}>
Save
</Button>
</DialogActions>
</Dialog>
)
}