Compare commits
2 Commits
f66aea5ebf
...
dd7c4bfa43
| Author | SHA1 | Date | |
|---|---|---|---|
| dd7c4bfa43 | |||
| bd78c86122 |
18
frontend/src/components/FormDialogContent.tsx
Normal file
18
frontend/src/components/FormDialogContent.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import DialogContent from '@mui/material/DialogContent'
|
||||
import { DialogContentProps } from '@mui/material/DialogContent'
|
||||
|
||||
export default function FormDialogContent(props: DialogContentProps) {
|
||||
return (
|
||||
<DialogContent
|
||||
{...props}
|
||||
sx={[
|
||||
{
|
||||
display: 'grid',
|
||||
gap: 1.5,
|
||||
pt: '8px !important'
|
||||
},
|
||||
props.sx
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import Alert from '@mui/material/Alert'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -254,7 +255,7 @@ export default function AdminApiKeysPage() {
|
||||
</SectionCard>
|
||||
<Dialog open={Boolean(deleteTarget)} onClose={() => setDeleteTarget(null)} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>Revoke API Key</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
|
||||
Type the API key name to confirm revocation.
|
||||
</Typography>
|
||||
@@ -264,7 +265,7 @@ export default function AdminApiKeysPage() {
|
||||
value={deleteConfirm}
|
||||
onChange={(event) => setDeleteConfirm(event.target.value)}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => { setDeleteTarget(null); setDeleteConfirm('') }}>
|
||||
Cancel
|
||||
@@ -281,7 +282,7 @@ export default function AdminApiKeysPage() {
|
||||
</Dialog>
|
||||
<Dialog open={bulkOpen} onClose={() => setBulkOpen(false)} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>Revoke Selected API Keys</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
|
||||
Type DELETE to revoke {selected.length} selected API key(s).
|
||||
</Typography>
|
||||
@@ -291,7 +292,7 @@ export default function AdminApiKeysPage() {
|
||||
value={bulkConfirm}
|
||||
onChange={(event) => setBulkConfirm(event.target.value)}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => { setBulkOpen(false); setBulkConfirm('') }}>
|
||||
Cancel
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import AddIcon from '@mui/icons-material/Add'
|
||||
import Alert from '@mui/material/Alert'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Autocomplete,
|
||||
Box,
|
||||
@@ -264,7 +265,7 @@ export default function AdminPKIClientProfilesPage() {
|
||||
|
||||
<Dialog open={editOpen} onClose={() => { if (!busy) setEditOpen(false) }} fullWidth maxWidth="md">
|
||||
<DialogTitle>{editID ? 'Edit Client Certificate Profile' : 'New Client Certificate Profile'}</DialogTitle>
|
||||
<DialogContent sx={{ display: 'grid', gap: 1.5, pt: '8px !important' }}>
|
||||
<FormDialogContent>
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
<TextField label="Name" value={name} onChange={(event) => setName(event.target.value)} autoFocus />
|
||||
<TextField select label="Issuer CA" value={caID} onChange={(event) => setCAID(event.target.value)}>
|
||||
@@ -327,7 +328,7 @@ export default function AdminPKIClientProfilesPage() {
|
||||
renderInput={(params) => <TextField {...params} label="Allowed Groups" />}
|
||||
/>
|
||||
<FormControlLabel control={<Checkbox checked={enabled} onChange={(event) => setEnabled(event.target.checked)} />} label="Enabled" />
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setEditOpen(false)} disabled={busy}>Cancel</Button>
|
||||
<Button variant="contained" onClick={save} disabled={busy}>
|
||||
@@ -338,14 +339,14 @@ export default function AdminPKIClientProfilesPage() {
|
||||
|
||||
<Dialog open={Boolean(deleteItem)} onClose={() => { if (!busy) { setDeleteItem(null); setDeleteConfirm('') } }} fullWidth maxWidth="sm">
|
||||
<DialogTitle>Delete Client Certificate Profile</DialogTitle>
|
||||
<DialogContent sx={{ display: 'grid', gap: 1.5, pt: '8px !important' }}>
|
||||
<FormDialogContent>
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Type the profile name to confirm deletion.
|
||||
</Typography>
|
||||
<Typography variant="body2">{deleteItem?.name}</Typography>
|
||||
<TextField label="Confirm Name" value={deleteConfirm} onChange={(event) => setDeleteConfirm(event.target.value)} autoFocus />
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => { setDeleteItem(null); setDeleteConfirm('') }} disabled={busy}>Cancel</Button>
|
||||
<Button
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import DownloadIcon from '@mui/icons-material/Download'
|
||||
import Alert from '@mui/material/Alert'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -821,7 +822,7 @@ export default function AdminPKIPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField label="Name" value={acmeName} onChange={(event) => setACMEName(event.target.value)} />
|
||||
<TextField label="Directory URL" value={acmeDirectoryURL} onChange={(event) => setACMEDirectoryURL(event.target.value)} />
|
||||
@@ -867,7 +868,7 @@ export default function AdminPKIPage() {
|
||||
) : null}
|
||||
<FormControlLabel control={<Checkbox checked={acmeEnabled} onChange={(event) => setACMEEnabled(event.target.checked)} />} label="Enabled" />
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setACMEOpen(false)}>Cancel</Button>
|
||||
<Button
|
||||
@@ -893,9 +894,9 @@ export default function AdminPKIPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Typography variant="body2" color="text.secondary">Delete profile permanently?</Typography>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setACMEDeleteID('')}>Cancel</Button>
|
||||
<Button color="error" variant="contained" onClick={deleteACME} disabled={busy}>{busy ? 'Working...' : 'Delete'}</Button>
|
||||
@@ -943,7 +944,7 @@ export default function AdminPKIPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField
|
||||
select
|
||||
@@ -962,7 +963,7 @@ export default function AdminPKIPage() {
|
||||
onChange={(event) => setACMEOrderSANDNS(event.target.value)}
|
||||
/>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setACMEOrderOpen(false)}>Cancel</Button>
|
||||
<Button variant="contained" onClick={createACMEOrder} disabled={busy || !acmeOrderProfileID || !acmeOrderCommonName.trim()}>
|
||||
@@ -978,9 +979,9 @@ export default function AdminPKIPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Typography variant="body2" color="text.secondary">Delete order permanently?</Typography>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setACMEOrderDeleteID('')}>Cancel</Button>
|
||||
<Button color="error" variant="contained" onClick={deleteACMEOrder} disabled={busy}>{busy ? 'Working...' : 'Delete'}</Button>
|
||||
@@ -994,7 +995,7 @@ export default function AdminPKIPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box sx={{ display: 'grid', gap: 1 }}>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Choose how to store the renewed certificate.
|
||||
@@ -1010,7 +1011,7 @@ export default function AdminPKIPage() {
|
||||
<MenuItem value="new_cert">Create a new cert ID</MenuItem>
|
||||
</TextField>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setACMEFinalizeID('')}>Cancel</Button>
|
||||
<Button
|
||||
@@ -1025,7 +1026,7 @@ export default function AdminPKIPage() {
|
||||
|
||||
<Dialog open={Boolean(acmeOrderView)} onClose={() => setACMEOrderView(null)} maxWidth="md" fullWidth>
|
||||
<DialogTitle>DNS-01 Instructions</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField label="Order ID" value={acmeOrderView?.id || ''} InputProps={{ readOnly: true }} />
|
||||
<TextField label="Status" value={acmeOrderView?.status || ''} InputProps={{ readOnly: true }} />
|
||||
@@ -1044,7 +1045,7 @@ export default function AdminPKIPage() {
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
{acmeOrderView ? (
|
||||
<Button variant="contained" onClick={() => requestFinalizeACMEOrder(acmeOrderView)} disabled={busy || acmeOrderView.status === 'valid'}>
|
||||
@@ -1062,7 +1063,7 @@ export default function AdminPKIPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField label="Name" value={rootName} onChange={(event) => setRootName(event.target.value)} />
|
||||
<TextField label="Common Name" value={rootCN} onChange={(event) => setRootCN(event.target.value)} />
|
||||
@@ -1096,7 +1097,7 @@ export default function AdminPKIPage() {
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setRootOpen(false)}>Cancel</Button>
|
||||
<Button variant="contained" onClick={createRoot} disabled={busy}>{busy ? 'Saving...' : 'Create'}</Button>
|
||||
@@ -1110,7 +1111,7 @@ export default function AdminPKIPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField label="Name" value={interName} onChange={(event) => setInterName(event.target.value)} />
|
||||
<TextField
|
||||
@@ -1154,7 +1155,7 @@ export default function AdminPKIPage() {
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setInterOpen(false)}>Cancel</Button>
|
||||
<Button variant="contained" onClick={createIntermediate} disabled={busy}>{busy ? 'Saving...' : 'Create'}</Button>
|
||||
@@ -1168,7 +1169,7 @@ export default function AdminPKIPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField select label="Issuer CA" value={issueCA} onChange={(event) => setIssueCA(event.target.value)}>
|
||||
{cas.map((ca) => (
|
||||
@@ -1181,7 +1182,7 @@ export default function AdminPKIPage() {
|
||||
<TextField label="Validity Days" value={issueDays} onChange={(event) => setIssueDays(event.target.value)} />
|
||||
<FormControlLabel control={<Checkbox checked={issueIsCA} onChange={(event) => setIssueIsCA(event.target.checked)} />} label="Issue as CA certificate" />
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setIssueOpen(false)}>Cancel</Button>
|
||||
<Button variant="contained" onClick={issueCert} disabled={busy}>{busy ? 'Saving...' : 'Issue'}</Button>
|
||||
@@ -1195,7 +1196,7 @@ export default function AdminPKIPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField select label="Issuer CA (optional)" value={importCA} onChange={(event) => setImportCA(event.target.value)}>
|
||||
<MenuItem value="">(none, standalone)</MenuItem>
|
||||
@@ -1232,7 +1233,7 @@ export default function AdminPKIPage() {
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setImportOpen(false)}>Cancel</Button>
|
||||
<Button variant="contained" onClick={importCert} disabled={busy}>{busy ? 'Saving...' : 'Import'}</Button>
|
||||
@@ -1246,9 +1247,9 @@ export default function AdminPKIPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<TextField fullWidth label="Reason (optional)" value={revokeReason} onChange={(event) => setRevokeReason(event.target.value)} />
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setRevokeID('')}>Cancel</Button>
|
||||
<Button color="warning" variant="contained" onClick={revokeCert} disabled={busy}>{busy ? 'Working...' : 'Revoke'}</Button>
|
||||
@@ -1262,9 +1263,9 @@ export default function AdminPKIPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Typography variant="body2" color="text.secondary">Delete certificate permanently?</Typography>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setDeleteID('')}>Cancel</Button>
|
||||
<Button color="error" variant="contained" onClick={deleteCert} disabled={busy}>{busy ? 'Working...' : 'Delete'}</Button>
|
||||
@@ -1278,7 +1279,7 @@ export default function AdminPKIPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
|
||||
Type the CA name to confirm deletion.
|
||||
</Typography>
|
||||
@@ -1287,7 +1288,7 @@ export default function AdminPKIPage() {
|
||||
control={<Checkbox checked={deleteCAForce} onChange={(event) => setDeleteCAForce(event.target.checked)} />}
|
||||
label="Force delete (includes child CAs and issued certs)"
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setDeleteCAID('')}>Cancel</Button>
|
||||
<Button
|
||||
@@ -1303,7 +1304,7 @@ export default function AdminPKIPage() {
|
||||
|
||||
<Dialog open={Boolean(viewCA)} onClose={() => setViewCA(null)} maxWidth="md" fullWidth>
|
||||
<DialogTitle>CA Details</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField label="ID" value={viewCA?.id || ''} InputProps={{ readOnly: true }} />
|
||||
<TextField label="Name" value={viewCA?.name || ''} InputProps={{ readOnly: true }} />
|
||||
@@ -1326,7 +1327,7 @@ export default function AdminPKIPage() {
|
||||
sx={{ '& .MuiInputBase-input': { fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace' } }}
|
||||
/>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
startIcon={<DownloadIcon />}
|
||||
@@ -1367,7 +1368,7 @@ export default function AdminPKIPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Name"
|
||||
@@ -1375,7 +1376,7 @@ export default function AdminPKIPage() {
|
||||
onChange={(event) => setEditCAName(event.target.value)}
|
||||
sx={{ mt: 1 }}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setEditCAID('')}>Cancel</Button>
|
||||
<Button variant="contained" onClick={saveCAEdit} disabled={busy || !editCAName.trim()}>
|
||||
@@ -1386,7 +1387,7 @@ export default function AdminPKIPage() {
|
||||
|
||||
<Dialog open={Boolean(viewCert)} onClose={() => setViewCert(null)} maxWidth="md" fullWidth>
|
||||
<DialogTitle>Certificate Details</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{dialogError ? <Alert severity="error" sx={{ mb: 1 }}>{dialogError}</Alert> : null}
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField label="ID" value={viewCert?.id || ''} InputProps={{ readOnly: true }} />
|
||||
@@ -1425,7 +1426,7 @@ export default function AdminPKIPage() {
|
||||
/>
|
||||
) : null}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={renewCertWithACME} disabled={busy || !viewCert}>
|
||||
{busy ? 'Working...' : 'Renew via ACME'}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import AddIcon from '@mui/icons-material/Add'
|
||||
import Alert from '@mui/material/Alert'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Autocomplete,
|
||||
Box,
|
||||
@@ -317,7 +318,7 @@ export default function AdminSSHPrincipalGrantsPage() {
|
||||
|
||||
<Dialog open={editOpen} onClose={() => { if (!busy) setEditOpen(false) }} maxWidth="md" fullWidth>
|
||||
<DialogTitle>{editID ? 'Edit Principal Grant' : 'New Principal Grant'}</DialogTitle>
|
||||
<DialogContent sx={{ display: 'grid', gap: 1.25, mt: 1 }}>
|
||||
<FormDialogContent>
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
<TextField label="Principal" value={principal} onChange={(event) => setPrincipal(event.target.value)} />
|
||||
<Autocomplete
|
||||
@@ -365,7 +366,7 @@ export default function AdminSSHPrincipalGrantsPage() {
|
||||
label="Disabled"
|
||||
/>
|
||||
<TextField label="Reason (optional)" value={reason} onChange={(event) => setReason(event.target.value)} />
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setEditOpen(false)} disabled={busy}>Cancel</Button>
|
||||
<Button variant="contained" onClick={save} disabled={busy || !principal.trim() || (targetUserIDs.length + targetGroupIDs.length) === 0}>
|
||||
@@ -376,7 +377,7 @@ export default function AdminSSHPrincipalGrantsPage() {
|
||||
|
||||
<Dialog open={!!deleteItem} onClose={() => { if (!busy) setDeleteItem(null) }} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>Delete Principal Grant</DialogTitle>
|
||||
<DialogContent sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<FormDialogContent>
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
<Typography variant="body2">
|
||||
Type the principal name to confirm deletion.
|
||||
@@ -391,7 +392,7 @@ export default function AdminSSHPrincipalGrantsPage() {
|
||||
value={deleteConfirm}
|
||||
onChange={(event) => setDeleteConfirm(event.target.value)}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setDeleteItem(null)} disabled={busy}>Cancel</Button>
|
||||
<Button
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Alert from '@mui/material/Alert'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -159,7 +160,7 @@ export default function AdminSSHSignHistoryPage() {
|
||||
|
||||
<Dialog open={inspectOpen} onClose={() => setInspectOpen(false)} maxWidth="md" fullWidth>
|
||||
<DialogTitle>Certificate Inspect</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<TextField
|
||||
multiline
|
||||
minRows={12}
|
||||
@@ -168,7 +169,7 @@ export default function AdminSSHSignHistoryPage() {
|
||||
fullWidth
|
||||
sx={{ mt: 1, '& .MuiInputBase-input': { fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace' } }}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setInspectOpen(false)}>Close</Button>
|
||||
</DialogActions>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import AddIcon from '@mui/icons-material/Add'
|
||||
import DownloadIcon from '@mui/icons-material/Download'
|
||||
import Alert from '@mui/material/Alert'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -339,7 +340,7 @@ export default function AdminSSHUserCAPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField label="Name" value={name} onChange={(event) => setName(event.target.value)} />
|
||||
<FormControlLabel control={<Checkbox checked={enabled} onChange={(event) => setEnabled(event.target.checked)} />} label="Enabled" />
|
||||
@@ -394,7 +395,7 @@ export default function AdminSSHUserCAPage() {
|
||||
</Box>
|
||||
) : null}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setEditOpen(false)}>Cancel</Button>
|
||||
<Button
|
||||
@@ -414,12 +415,12 @@ export default function AdminSSHUserCAPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box sx={{ display: 'grid', gap: 1 }}>
|
||||
<Typography variant="body2" color="text.secondary">Type CA name to confirm deletion.</Typography>
|
||||
<TextField size="small" label="Confirm Name" value={deleteConfirm} onChange={(event) => setDeleteConfirm(event.target.value)} />
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setDeleteItem(null)}>Cancel</Button>
|
||||
<Button
|
||||
@@ -435,7 +436,7 @@ export default function AdminSSHUserCAPage() {
|
||||
|
||||
<Dialog open={Boolean(viewItem)} onClose={() => setViewItem(null)} maxWidth="md" fullWidth>
|
||||
<DialogTitle>SSH User CA Details</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField label="Name" value={viewItem?.name || ''} InputProps={{ readOnly: true }} />
|
||||
<TextField label="ID" value={viewItem?.id || ''} InputProps={{ readOnly: true }} />
|
||||
@@ -452,7 +453,7 @@ export default function AdminSSHUserCAPage() {
|
||||
sx={{ '& .MuiInputBase-input': { fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace' } }}
|
||||
/>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
{viewItem ? <Button startIcon={<DownloadIcon />} onClick={() => downloadPublicKey(viewItem)}>Download Public</Button> : null}
|
||||
{viewItem ? <Button startIcon={<DownloadIcon />} color="warning" onClick={() => downloadPrivateKey(viewItem)}>Download Private</Button> : null}
|
||||
@@ -467,7 +468,7 @@ export default function AdminSSHUserCAPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField label="CA" value={signItem ? `${signItem.name} (${signItem.id})` : ''} InputProps={{ readOnly: true }} />
|
||||
<TextField
|
||||
@@ -501,7 +502,7 @@ export default function AdminSSHUserCAPage() {
|
||||
</Box>
|
||||
) : null}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setSignOpen(false)}>Close</Button>
|
||||
{signResult ? <Button onClick={copyResultCert}>Copy Certificate</Button> : null}
|
||||
@@ -518,7 +519,7 @@ export default function AdminSSHUserCAPage() {
|
||||
|
||||
<Dialog open={inspectOpen} onClose={() => setInspectOpen(false)} maxWidth="md" fullWidth>
|
||||
<DialogTitle>Certificate Inspect</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<TextField
|
||||
multiline
|
||||
minRows={12}
|
||||
@@ -527,7 +528,7 @@ export default function AdminSSHUserCAPage() {
|
||||
fullWidth
|
||||
sx={{ mt: 1, '& .MuiInputBase-input': { fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace' } }}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setInspectOpen(false)}>Close</Button>
|
||||
</DialogActions>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Alert from '@mui/material/Alert'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -469,10 +470,10 @@ export default function AdminServicePrincipalsPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent sx={{ display: 'grid', gap: 1, pt: '8px !important' }}>
|
||||
<FormDialogContent>
|
||||
<TextField label="Name" value={name} onChange={(event) => setName(event.target.value)} />
|
||||
<TextField label="Description" value={description} onChange={(event) => setDescription(event.target.value)} />
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setCreateOpen(false)}>Cancel</Button>
|
||||
<Button variant="contained" onClick={createPrincipal} disabled={busy}>{busy ? 'Saving...' : 'Create'}</Button>
|
||||
@@ -486,7 +487,7 @@ export default function AdminServicePrincipalsPage() {
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent sx={{ display: 'grid', gap: 1, pt: '8px !important' }}>
|
||||
<FormDialogContent>
|
||||
<TextField
|
||||
select
|
||||
label="Binding Source"
|
||||
@@ -527,7 +528,7 @@ export default function AdminServicePrincipalsPage() {
|
||||
<MenuItem key={item.id} value={item.id}>{item.name} ({item.id})</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setBindingOpen(false)}>Cancel</Button>
|
||||
<Button variant="contained" onClick={upsertBinding} disabled={busy}>{busy ? 'Saving...' : 'Save'}</Button>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Alert from '@mui/material/Alert'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -537,7 +538,7 @@ export default function AdminTLSSettingsPage() {
|
||||
{listenerError ? <Alert severity="error">{listenerError}</Alert> : null}
|
||||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent sx={{ display: 'grid', gap: 1, pt: '8px !important' }}>
|
||||
<FormDialogContent>
|
||||
{!editingMain ? (
|
||||
<TextField
|
||||
label="Name"
|
||||
@@ -719,7 +720,7 @@ export default function AdminTLSSettingsPage() {
|
||||
<MenuItem value="1.2">1.2</MenuItem>
|
||||
<MenuItem value="1.3">1.3</MenuItem>
|
||||
</TextField>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setDialogOpen(false)}>Cancel</Button>
|
||||
<Button variant="contained" onClick={handleSaveDialog} disabled={listenerSaving}>
|
||||
@@ -730,9 +731,9 @@ export default function AdminTLSSettingsPage() {
|
||||
|
||||
<Dialog open={confirmOpen} onClose={() => setConfirmOpen(false)} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>{confirmTitle}</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Typography variant="body2">{confirmMessage}</Typography>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setConfirmOpen(false)}>Cancel</Button>
|
||||
<Button variant="contained" color={confirmColor} onClick={handleConfirm}>
|
||||
|
||||
@@ -2,6 +2,7 @@ import AddIcon from '@mui/icons-material/Add'
|
||||
import DeleteIcon from '@mui/icons-material/Delete'
|
||||
import EditIcon from '@mui/icons-material/Edit'
|
||||
import Alert from '@mui/material/Alert'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -392,9 +393,9 @@ export default function AdminUserGroupsPage() {
|
||||
sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 1 }}
|
||||
>
|
||||
<Typography variant="body2">{userLabelByID(member.user_id)}</Typography>
|
||||
<IconButton size="small" color="error" onClick={() => removeMember(member.user_id)} disabled={busy}>
|
||||
<DeleteIcon fontSize="small" />
|
||||
</IconButton>
|
||||
<Button size="small" variant="outlined" color="error" onClick={() => removeMember(member.user_id)} disabled={busy}>
|
||||
Delete
|
||||
</Button>
|
||||
</Box>
|
||||
))}
|
||||
{members.length === 0 ? (
|
||||
@@ -434,7 +435,7 @@ export default function AdminUserGroupsPage() {
|
||||
|
||||
<Dialog open={editOpen} onClose={() => setEditOpen(false)} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>{editID ? 'Edit Group' : 'New Group'}</DialogTitle>
|
||||
<DialogContent sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<FormDialogContent>
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
<TextField label="Name" value={name} onChange={(event) => setName(event.target.value)} />
|
||||
<TextField
|
||||
@@ -448,7 +449,7 @@ export default function AdminUserGroupsPage() {
|
||||
control={<Checkbox checked={disabled} onChange={(event) => setDisabled(event.target.checked)} />}
|
||||
label="Disabled"
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setEditOpen(false)}>Cancel</Button>
|
||||
<Button variant="contained" onClick={saveGroup} disabled={busy || !name.trim()}>
|
||||
@@ -459,7 +460,7 @@ export default function AdminUserGroupsPage() {
|
||||
|
||||
<Dialog open={!!deleteItem} onClose={() => setDeleteItem(null)} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>Delete Group</DialogTitle>
|
||||
<DialogContent sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<FormDialogContent>
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
<Typography variant="body2">Type the group name to confirm deletion.</Typography>
|
||||
<TextField
|
||||
@@ -469,7 +470,7 @@ export default function AdminUserGroupsPage() {
|
||||
value={deleteConfirm}
|
||||
onChange={(event) => setDeleteConfirm(event.target.value)}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setDeleteItem(null)}>Cancel</Button>
|
||||
<Button
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import AddIcon from '@mui/icons-material/Add'
|
||||
import Alert from '@mui/material/Alert'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -278,7 +279,7 @@ export default function AdminUsersPage() {
|
||||
</SectionCard>
|
||||
<Dialog open={createOpen} onClose={closeCreateDialog} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>New User</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{createError ? <Alert severity="error" sx={{ mb: 1 }}>{createError}</Alert> : null}
|
||||
<Box component="form" onSubmit={handleCreate} sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField name="username" label="Username" value={username} onChange={(event) => setUsername(event.target.value)} />
|
||||
@@ -320,11 +321,11 @@ export default function AdminUsersPage() {
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
</Dialog>
|
||||
<Dialog open={Boolean(editUser)} onClose={closeEditUser} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Edit User</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{editError ? <Alert severity="error" sx={{ mb: 1 }}>{editError}</Alert> : null}
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField label="Username" value={editUser?.username || ''} disabled />
|
||||
@@ -357,7 +358,7 @@ export default function AdminUsersPage() {
|
||||
label="Allow project creation (direct grant)"
|
||||
/>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={closeEditUser}>Cancel</Button>
|
||||
<Button variant="contained" onClick={handleSaveEdit} disabled={savingEdit}>
|
||||
@@ -367,7 +368,7 @@ export default function AdminUsersPage() {
|
||||
</Dialog>
|
||||
<Dialog open={Boolean(deletingUser)} onClose={() => setDeletingUser(null)} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>Delete User</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
|
||||
Type the username to confirm deletion.
|
||||
</Typography>
|
||||
@@ -377,7 +378,7 @@ export default function AdminUsersPage() {
|
||||
value={deleteConfirm}
|
||||
onChange={(event) => setDeleteConfirm(event.target.value)}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => { setDeletingUser(null); setDeleteConfirm('') }}>Cancel</Button>
|
||||
<Button
|
||||
|
||||
@@ -4,6 +4,7 @@ import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'
|
||||
import ContentCopyIcon from '@mui/icons-material/ContentCopy'
|
||||
import DeleteIcon from '@mui/icons-material/Delete'
|
||||
import Alert from '@mui/material/Alert'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -226,7 +227,7 @@ export default function ApiKeysPage() {
|
||||
|
||||
<Dialog open={createOpen} onClose={closeCreate} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Create API Key</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{createError ? <Alert severity="error" sx={{ mb: 1 }}>{createError}</Alert> : null}
|
||||
<TextField
|
||||
margin="dense"
|
||||
@@ -278,7 +279,7 @@ export default function ApiKeysPage() {
|
||||
Copied.
|
||||
</Typography>
|
||||
) : null}
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={closeCreate}>{newToken ? 'Done' : 'Cancel'}</Button>
|
||||
{!newToken ? (
|
||||
@@ -291,7 +292,7 @@ export default function ApiKeysPage() {
|
||||
|
||||
<Dialog open={Boolean(deleteTarget)} onClose={() => setDeleteTarget(null)} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>Revoke API Key</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
|
||||
Type the API key name to confirm revocation.
|
||||
</Typography>
|
||||
@@ -301,7 +302,7 @@ export default function ApiKeysPage() {
|
||||
value={deleteConfirm}
|
||||
onChange={(event) => setDeleteConfirm(event.target.value)}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => { setDeleteTarget(null); setDeleteConfirm('') }}>Cancel</Button>
|
||||
<Button
|
||||
|
||||
@@ -7,6 +7,7 @@ import RepoSubNav from '../components/RepoSubNav'
|
||||
import EditIcon from '@mui/icons-material/Edit'
|
||||
import DeleteIcon from '@mui/icons-material/Delete'
|
||||
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
|
||||
export default function BranchesPage() {
|
||||
const { projectId, repoId } = useParams()
|
||||
@@ -309,7 +310,7 @@ export default function BranchesPage() {
|
||||
</Paper>
|
||||
<Dialog open={createOpen} onClose={() => setCreateOpen(false)} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Create Branch</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{createError ? (
|
||||
<Typography variant="body2" color="error" sx={{ mb: 1 }}>
|
||||
{createError}
|
||||
@@ -331,7 +332,7 @@ export default function BranchesPage() {
|
||||
margin="dense"
|
||||
placeholder="main"
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setCreateOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleCreate} variant="contained">
|
||||
@@ -341,7 +342,7 @@ export default function BranchesPage() {
|
||||
</Dialog>
|
||||
<Dialog open={renameOpen} onClose={() => setRenameOpen(false)} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Rename Branch</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{renameError ? (
|
||||
<Typography variant="body2" color="error" sx={{ mb: 1 }}>
|
||||
{renameError}
|
||||
@@ -355,7 +356,7 @@ export default function BranchesPage() {
|
||||
fullWidth
|
||||
margin="dense"
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setRenameOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleRename} variant="contained">
|
||||
@@ -365,7 +366,7 @@ export default function BranchesPage() {
|
||||
</Dialog>
|
||||
<Dialog open={deleteOpen} onClose={() => setDeleteOpen(false)} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Delete Branch</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{deleteError ? (
|
||||
<Typography variant="body2" color="error" sx={{ mb: 1 }}>
|
||||
{deleteError}
|
||||
@@ -381,7 +382,7 @@ export default function BranchesPage() {
|
||||
fullWidth
|
||||
margin="dense"
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setDeleteOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleDelete} color="error" variant="contained" disabled={deleteConfirm.trim() !== deleteTarget}>
|
||||
|
||||
@@ -3,6 +3,7 @@ import KeyIcon from '@mui/icons-material/Key'
|
||||
import BlockIcon from '@mui/icons-material/Block'
|
||||
import VisibilityIcon from '@mui/icons-material/Visibility'
|
||||
import Alert from '@mui/material/Alert'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -276,7 +277,7 @@ export default function ClientCertificatesPage() {
|
||||
|
||||
<Dialog open={Boolean(issueProfile)} onClose={() => { if (!busy) setIssueProfile(null) }} fullWidth maxWidth="sm">
|
||||
<DialogTitle>Issue Client Certificate</DialogTitle>
|
||||
<DialogContent sx={{ display: 'grid', gap: 1.5, pt: '8px !important' }}>
|
||||
<FormDialogContent>
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Profile: {issueProfile?.name}
|
||||
@@ -291,7 +292,7 @@ export default function ClientCertificatesPage() {
|
||||
helperText={`Default ${issueProfile?.default_valid_seconds || 0}s, maximum ${issueProfile?.max_valid_seconds || 0}s`}
|
||||
autoFocus
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setIssueProfile(null)} disabled={busy}>Cancel</Button>
|
||||
<Button variant="contained" onClick={submitIssue} disabled={busy}>
|
||||
@@ -302,14 +303,14 @@ export default function ClientCertificatesPage() {
|
||||
|
||||
<Dialog open={Boolean(issueResult)} onClose={() => setIssueResult(null)} fullWidth maxWidth="md">
|
||||
<DialogTitle>Client Certificate Issued</DialogTitle>
|
||||
<DialogContent sx={{ display: 'grid', gap: 1.5, pt: '8px !important' }}>
|
||||
<FormDialogContent>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Profile: {issueResult?.issuance.profile_name} · SAN URI: {issueResult?.issuance.san_uri}
|
||||
</Typography>
|
||||
<TextField label="Certificate" value={issueResult?.certificate || ''} multiline minRows={6} InputProps={{ sx: { fontFamily: 'monospace' } }} />
|
||||
<TextField label="Private Key" value={issueResult?.private_key || ''} multiline minRows={6} InputProps={{ sx: { fontFamily: 'monospace' } }} />
|
||||
<TextField label="CA Certificate" value={issueResult?.ca_certificate || ''} multiline minRows={6} InputProps={{ sx: { fontFamily: 'monospace' } }} />
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setIssueResult(null)}>Close</Button>
|
||||
</DialogActions>
|
||||
@@ -317,7 +318,7 @@ export default function ClientCertificatesPage() {
|
||||
|
||||
<Dialog open={Boolean(viewCert)} onClose={() => setViewCert(null)} fullWidth maxWidth="md">
|
||||
<DialogTitle>Certificate Details</DialogTitle>
|
||||
<DialogContent sx={{ display: 'grid', gap: 1.5, pt: '8px !important' }}>
|
||||
<FormDialogContent>
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
<TextField label="ID" value={viewCert?.id || ''} InputProps={{ readOnly: true }} />
|
||||
<TextField label="Issuer CA ID" value={viewCert?.ca_id || 'standalone'} InputProps={{ readOnly: true }} />
|
||||
@@ -351,7 +352,7 @@ export default function ClientCertificatesPage() {
|
||||
InputProps={{ readOnly: true, sx: { fontFamily: 'monospace' } }}
|
||||
/>
|
||||
) : null}
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={toggleViewDump} disabled={viewCertDumpLoading}>
|
||||
{viewCertDumpLoading ? 'Loading Dump...' : viewCertDumpOpen ? 'Hide X509 Dump' : 'Show X509 Dump'}
|
||||
@@ -362,12 +363,12 @@ export default function ClientCertificatesPage() {
|
||||
|
||||
<Dialog open={Boolean(revokeItem)} onClose={() => { if (!busy) setRevokeItem(null) }} fullWidth maxWidth="sm">
|
||||
<DialogTitle>Revoke Client Certificate</DialogTitle>
|
||||
<DialogContent sx={{ display: 'grid', gap: 1.5, pt: '8px !important' }}>
|
||||
<FormDialogContent>
|
||||
{dialogError ? <Alert severity="error">{dialogError}</Alert> : null}
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Revoke {revokeItem?.common_name} ({revokeItem?.cert_id})?
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setRevokeItem(null)} disabled={busy}>Cancel</Button>
|
||||
<Button variant="contained" color="error" onClick={revoke} disabled={busy}>
|
||||
|
||||
@@ -50,7 +50,7 @@ export default function GlobalReposPage() {
|
||||
return (
|
||||
<Box>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 1 }}>
|
||||
<Typography variant="h6">Repositories</Typography>
|
||||
<Typography variant="h5">Repositories</Typography>
|
||||
</Box>
|
||||
<SectionCard
|
||||
title={
|
||||
|
||||
@@ -12,6 +12,7 @@ import EditIcon from '@mui/icons-material/Edit'
|
||||
import { ListRowActionButton, ListRowActions } from '../components/ListRowActions'
|
||||
import SectionCard from '../components/SectionCard'
|
||||
import DeleteIcon from '@mui/icons-material/Delete'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
|
||||
export default function ProjectHomePage() {
|
||||
const { projectId } = useParams()
|
||||
@@ -572,7 +573,7 @@ export default function ProjectHomePage() {
|
||||
</Box>
|
||||
<Dialog open={editOpen} onClose={() => setEditOpen(false)} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Edit Project</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{editError ? <Alert severity="error">{editError}</Alert> : null}
|
||||
<TextField
|
||||
margin="dense"
|
||||
@@ -638,7 +639,7 @@ export default function ProjectHomePage() {
|
||||
</Paper>
|
||||
)}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setEditOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleEditSave} variant="contained" disabled={savingEdit}>
|
||||
@@ -648,7 +649,7 @@ export default function ProjectHomePage() {
|
||||
</Dialog>
|
||||
<Dialog open={deleteOpen} onClose={closeDelete} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Delete Project</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{deleteError ? <Alert severity="error">{deleteError}</Alert> : null}
|
||||
{deleteLoading ? (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
@@ -679,7 +680,7 @@ export default function ProjectHomePage() {
|
||||
</Box>
|
||||
)
|
||||
) : null}
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={closeDelete}>Cancel</Button>
|
||||
<Button
|
||||
|
||||
@@ -12,6 +12,7 @@ import { ListRowActionButton, ListRowActions } from '../components/ListRowAction
|
||||
import SectionCard from '../components/SectionCard'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
|
||||
export default function ProjectsPage() {
|
||||
const [projects, setProjects] = useState<Project[]>([])
|
||||
@@ -377,7 +378,7 @@ export default function ProjectsPage() {
|
||||
</SectionCard>
|
||||
<Dialog open={Boolean(editProject)} onClose={() => setEditProject(null)} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Edit Project</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{editError ? <Alert severity="error">{editError}</Alert> : null}
|
||||
<TextField
|
||||
margin="dense"
|
||||
@@ -443,7 +444,7 @@ export default function ProjectsPage() {
|
||||
</Paper>
|
||||
)}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setEditProject(null)}>Cancel</Button>
|
||||
<Button onClick={handleEditSave} variant="contained" disabled={savingEdit}>
|
||||
@@ -453,7 +454,7 @@ export default function ProjectsPage() {
|
||||
</Dialog>
|
||||
<Dialog open={createOpen} onClose={closeCreate} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>New Project</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box component="form" onSubmit={handleCreate} sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
{createError ? <Alert severity="error">{createError}</Alert> : null}
|
||||
<TextField
|
||||
@@ -516,11 +517,11 @@ export default function ProjectsPage() {
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
</Dialog>
|
||||
<Dialog open={Boolean(deleteProject)} onClose={closeDelete} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Delete Project</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{deleteError ? <Alert severity="error">{deleteError}</Alert> : null}
|
||||
{deleteLoading ? (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
@@ -551,7 +552,7 @@ export default function ProjectsPage() {
|
||||
</Box>
|
||||
)
|
||||
) : null}
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={closeDelete}>Cancel</Button>
|
||||
<Button
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Alert,
|
||||
Box,
|
||||
@@ -482,7 +483,7 @@ export default function RepoDockerDetailPage(props: RepoDockerDetailPageProps) {
|
||||
</Box>
|
||||
<Dialog open={deleteTagOpen} onClose={() => setDeleteTagOpen(false)} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>Delete tag</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{deleteError ? <Alert severity="error">{deleteError}</Alert> : null}
|
||||
<Typography variant="body2" sx={{ mt: 1 }}>
|
||||
Delete tag "{deleteTagName}"?
|
||||
@@ -494,7 +495,7 @@ export default function RepoDockerDetailPage(props: RepoDockerDetailPageProps) {
|
||||
fullWidth
|
||||
sx={{ mt: 1 }}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setDeleteTagOpen(false)}>Cancel</Button>
|
||||
<Button
|
||||
@@ -509,7 +510,7 @@ export default function RepoDockerDetailPage(props: RepoDockerDetailPageProps) {
|
||||
</Dialog>
|
||||
<Dialog open={deleteImageOpen} onClose={() => setDeleteImageOpen(false)} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>Delete image</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{deleteError ? <Alert severity="error">{deleteError}</Alert> : null}
|
||||
<Typography variant="body2" sx={{ mt: 1 }}>
|
||||
Delete image "{deleteImageLabel || '(root)'}" and all tags?
|
||||
@@ -521,7 +522,7 @@ export default function RepoDockerDetailPage(props: RepoDockerDetailPageProps) {
|
||||
fullWidth
|
||||
sx={{ mt: 1 }}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setDeleteImageOpen(false)}>Cancel</Button>
|
||||
<Button
|
||||
@@ -536,7 +537,7 @@ export default function RepoDockerDetailPage(props: RepoDockerDetailPageProps) {
|
||||
</Dialog>
|
||||
<Dialog open={renameTagOpen} onClose={() => setRenameTagOpen(false)} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>Rename tag</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{renameError ? <Alert severity="error">{renameError}</Alert> : null}
|
||||
<TextField label="From" value={renameTagFrom} fullWidth margin="dense" InputProps={{ readOnly: true }} />
|
||||
<TextField
|
||||
@@ -546,7 +547,7 @@ export default function RepoDockerDetailPage(props: RepoDockerDetailPageProps) {
|
||||
fullWidth
|
||||
margin="dense"
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setRenameTagOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleRenameTag} variant="contained" disabled={renaming}>
|
||||
@@ -556,7 +557,7 @@ export default function RepoDockerDetailPage(props: RepoDockerDetailPageProps) {
|
||||
</Dialog>
|
||||
<Dialog open={renameImageOpen} onClose={() => setRenameImageOpen(false)} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>Rename image</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{renameError ? <Alert severity="error">{renameError}</Alert> : null}
|
||||
<TextField label="From" value={renameImageFromLabel} fullWidth margin="dense" InputProps={{ readOnly: true }} />
|
||||
<TextField
|
||||
@@ -567,7 +568,7 @@ export default function RepoDockerDetailPage(props: RepoDockerDetailPageProps) {
|
||||
margin="dense"
|
||||
helperText="Leave blank to move to root."
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setRenameImageOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleRenameImage} variant="contained" disabled={renaming}>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Alert,
|
||||
Box,
|
||||
@@ -1206,7 +1207,7 @@ export default function RepoRpmDetailPage(props: RepoRpmDetailPageProps) {
|
||||
</Box>
|
||||
<Dialog open={subdirOpen} onClose={() => setSubdirOpen(false)} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>New Subdirectory</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{subdirError ? <Alert severity="error">{subdirError}</Alert> : null}
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField
|
||||
@@ -1298,7 +1299,7 @@ export default function RepoRpmDetailPage(props: RepoRpmDetailPageProps) {
|
||||
</>
|
||||
) : null}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setSubdirOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleCreateSubdir} variant="contained" disabled={subdirSaving}>
|
||||
@@ -1308,7 +1309,7 @@ export default function RepoRpmDetailPage(props: RepoRpmDetailPageProps) {
|
||||
</Dialog>
|
||||
<Dialog open={uploadOpen} onClose={() => setUploadOpen(false)} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Upload RPM</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{uploadError ? <Alert severity="error">{uploadError}</Alert> : null}
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<TextField
|
||||
@@ -1325,7 +1326,7 @@ export default function RepoRpmDetailPage(props: RepoRpmDetailPageProps) {
|
||||
label="Overwrite existing files"
|
||||
/>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setUploadOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleUpload} variant="contained" disabled={uploading}>
|
||||
@@ -1335,7 +1336,7 @@ export default function RepoRpmDetailPage(props: RepoRpmDetailPageProps) {
|
||||
</Dialog>
|
||||
<Dialog open={deleteOpen} onClose={() => setDeleteOpen(false)} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>{deleteIsFile ? 'Delete file' : 'Delete folder'}</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{deleteError ? <Alert severity="error">{deleteError}</Alert> : null}
|
||||
<Typography variant="body2" sx={{ mt: 1 }}>
|
||||
{deleteIsFile
|
||||
@@ -1349,7 +1350,7 @@ export default function RepoRpmDetailPage(props: RepoRpmDetailPageProps) {
|
||||
fullWidth
|
||||
sx={{ mt: 1 }}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setDeleteOpen(false)}>Cancel</Button>
|
||||
<Button
|
||||
@@ -1378,7 +1379,7 @@ export default function RepoRpmDetailPage(props: RepoRpmDetailPageProps) {
|
||||
fullWidth
|
||||
>
|
||||
<DialogTitle>Repo directory status</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{statusError ? <Alert severity="error">{statusError}</Alert> : null}
|
||||
<Box sx={{ display: 'grid', gap: 0.5, mt: 1 }}>
|
||||
<Typography variant="body2">Directory: {statusName}</Typography>
|
||||
@@ -1459,7 +1460,7 @@ export default function RepoRpmDetailPage(props: RepoRpmDetailPageProps) {
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
onClick={() => {
|
||||
@@ -1487,7 +1488,7 @@ export default function RepoRpmDetailPage(props: RepoRpmDetailPageProps) {
|
||||
fullWidth
|
||||
>
|
||||
<DialogTitle>{renameIsRepoDir ? 'Edit repo directory' : 'Rename folder'}</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{renameError ? <Alert severity="error">{renameError}</Alert> : null}
|
||||
<Box sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
<Typography variant="body2">
|
||||
@@ -1559,7 +1560,7 @@ export default function RepoRpmDetailPage(props: RepoRpmDetailPageProps) {
|
||||
</>
|
||||
) : null}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
onClick={() => {
|
||||
@@ -1581,11 +1582,11 @@ export default function RepoRpmDetailPage(props: RepoRpmDetailPageProps) {
|
||||
fullWidth
|
||||
>
|
||||
<DialogTitle>Clear runs</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Typography variant="body2" sx={{ mt: 1 }}>
|
||||
Clear recent mirror runs for "{statusName}"?
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setClearRunsConfirmOpen(false)}>Cancel</Button>
|
||||
<Button
|
||||
|
||||
@@ -5,6 +5,7 @@ import LinkOffIcon from '@mui/icons-material/LinkOff'
|
||||
import LinkIcon from '@mui/icons-material/Link'
|
||||
import Alert from '@mui/material/Alert'
|
||||
import { Autocomplete } from '@mui/material'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -321,6 +322,7 @@ export default function ReposPage() {
|
||||
<Typography variant="h5" sx={{ mb: 1 }}>
|
||||
Repositories
|
||||
</Typography>
|
||||
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 1 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap' }}>
|
||||
<Button component={Link} to="/projects" size="small">
|
||||
@@ -535,7 +537,7 @@ export default function ReposPage() {
|
||||
</SectionCard>
|
||||
<Dialog open={createOpen} onClose={() => setCreateOpen(false)} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>New Repository</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<Box component="form" onSubmit={handleCreate} sx={{ display: 'grid', gap: 1, mt: 1 }}>
|
||||
{createError ? <Alert severity="error">{createError}</Alert> : null}
|
||||
<TextField name="name" label="Name" />
|
||||
@@ -556,11 +558,11 @@ export default function ReposPage() {
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
</Dialog>
|
||||
<Dialog open={Boolean(editRepo)} onClose={() => setEditRepo(null)} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Edit Repository</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{editError ? <Alert severity="error">{editError}</Alert> : null}
|
||||
<TextField
|
||||
autoFocus
|
||||
@@ -570,7 +572,7 @@ export default function ReposPage() {
|
||||
value={editName}
|
||||
onChange={(event) => setEditName(event.target.value)}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setEditRepo(null)}>Cancel</Button>
|
||||
<Button onClick={handleEditSave} variant="contained" disabled={savingEdit}>
|
||||
@@ -580,7 +582,7 @@ export default function ReposPage() {
|
||||
</Dialog>
|
||||
<Dialog open={Boolean(deleteRepo)} onClose={closeDelete} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Delete Repository</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{deleteError ? <Alert severity="error">{deleteError}</Alert> : null}
|
||||
{deleteLoading ? (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
@@ -615,7 +617,7 @@ export default function ReposPage() {
|
||||
Unable to load repository stats.
|
||||
</Typography>
|
||||
)}
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={closeDelete}>Cancel</Button>
|
||||
<Button
|
||||
@@ -630,7 +632,7 @@ export default function ReposPage() {
|
||||
</Dialog>
|
||||
<Dialog open={bulkDeleteOpen} onClose={closeBulkDelete} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Delete Repositories</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{bulkDeleteError ? <Alert severity="error">{bulkDeleteError}</Alert> : null}
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
You are deleting {selectedRepoIds.length} repositories. This action is permanent.
|
||||
@@ -654,7 +656,7 @@ export default function ReposPage() {
|
||||
onChange={(event) => setBulkDeleteConfirm(event.target.value)}
|
||||
fullWidth
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={closeBulkDelete}>Cancel</Button>
|
||||
<Button
|
||||
@@ -669,7 +671,7 @@ export default function ReposPage() {
|
||||
</Dialog>
|
||||
<Dialog open={foreignOpen} onClose={closeForeign} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Add Foreign Repository</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
{foreignError ? <Alert severity="error">{foreignError}</Alert> : null}
|
||||
<TextField
|
||||
margin="dense"
|
||||
@@ -699,7 +701,7 @@ export default function ReposPage() {
|
||||
) : null}
|
||||
</List>
|
||||
)}
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={closeForeign}>Close</Button>
|
||||
</DialogActions>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Alert from '@mui/material/Alert'
|
||||
import ContentCopyIcon from '@mui/icons-material/ContentCopy'
|
||||
import FormDialogContent from '../components/FormDialogContent'
|
||||
import {
|
||||
Autocomplete,
|
||||
Box,
|
||||
@@ -324,7 +325,7 @@ export default function SSHCertificatesPage() {
|
||||
|
||||
<Dialog open={inspectOpen} onClose={() => setInspectOpen(false)} maxWidth="md" fullWidth>
|
||||
<DialogTitle>Certificate Inspect</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormDialogContent>
|
||||
<TextField
|
||||
multiline
|
||||
minRows={12}
|
||||
@@ -333,7 +334,7 @@ export default function SSHCertificatesPage() {
|
||||
fullWidth
|
||||
sx={{ mt: 1, '& .MuiInputBase-input': { fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace' } }}
|
||||
/>
|
||||
</DialogContent>
|
||||
</FormDialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setInspectOpen(false)}>Close</Button>
|
||||
</DialogActions>
|
||||
|
||||
Reference in New Issue
Block a user