feat: show download token with copy and regenerate on Config Detail
This commit is contained in:
@@ -10,8 +10,16 @@ import Tabs from '@mui/material/Tabs'
|
|||||||
import Tab from '@mui/material/Tab'
|
import Tab from '@mui/material/Tab'
|
||||||
import Typography from '@mui/material/Typography'
|
import Typography from '@mui/material/Typography'
|
||||||
import Breadcrumbs from '@mui/material/Breadcrumbs'
|
import Breadcrumbs from '@mui/material/Breadcrumbs'
|
||||||
|
import IconButton from '@mui/material/IconButton'
|
||||||
|
import InputAdornment from '@mui/material/InputAdornment'
|
||||||
|
import OutlinedInput from '@mui/material/OutlinedInput'
|
||||||
|
import FormControl from '@mui/material/FormControl'
|
||||||
|
import InputLabel from '@mui/material/InputLabel'
|
||||||
|
import Tooltip from '@mui/material/Tooltip'
|
||||||
import AddIcon from '@mui/icons-material/Add'
|
import AddIcon from '@mui/icons-material/Add'
|
||||||
import BuildIcon from '@mui/icons-material/Build'
|
import BuildIcon from '@mui/icons-material/Build'
|
||||||
|
import ContentCopyIcon from '@mui/icons-material/ContentCopy'
|
||||||
|
import RefreshIcon from '@mui/icons-material/Refresh'
|
||||||
import { zonesApi, interfacesApi, policiesApi, rulesApi, snatApi, hostsApi, paramsApi, configsApi } from '../api'
|
import { zonesApi, interfacesApi, policiesApi, rulesApi, snatApi, hostsApi, paramsApi, configsApi } from '../api'
|
||||||
|
|
||||||
// ---- Types ----
|
// ---- Types ----
|
||||||
@@ -41,9 +49,13 @@ export default function ConfigDetail() {
|
|||||||
const [formOpen, setFormOpen] = useState(false)
|
const [formOpen, setFormOpen] = useState(false)
|
||||||
const [editing, setEditing] = useState<AnyEntity | null>(null)
|
const [editing, setEditing] = useState<AnyEntity | null>(null)
|
||||||
const [generateOpen, setGenerateOpen] = useState(false)
|
const [generateOpen, setGenerateOpen] = useState(false)
|
||||||
|
const [downloadToken, setDownloadToken] = useState('')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
configsApi.get(configId).then((r) => setConfigName(r.data.name))
|
configsApi.get(configId).then((r) => {
|
||||||
|
setConfigName(r.data.name)
|
||||||
|
setDownloadToken(r.data.download_token)
|
||||||
|
})
|
||||||
zonesApi.list(configId).then((r) => setZones(r.data))
|
zonesApi.list(configId).then((r) => setZones(r.data))
|
||||||
interfacesApi.list(configId).then((r) => setInterfaces(r.data))
|
interfacesApi.list(configId).then((r) => setInterfaces(r.data))
|
||||||
policiesApi.list(configId).then((r) => setPolicies(r.data))
|
policiesApi.list(configId).then((r) => setPolicies(r.data))
|
||||||
@@ -269,6 +281,12 @@ export default function ConfigDetail() {
|
|||||||
current.setRows(res.data as any)
|
current.setRows(res.data as any)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleRegenerate = async () => {
|
||||||
|
if (!confirm('Regenerate the download token? The old token will stop working.')) return
|
||||||
|
const res = await configsApi.regenerateToken(configId)
|
||||||
|
setDownloadToken(res.data.download_token)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout title={configName || 'Config Detail'}>
|
<Layout title={configName || 'Config Detail'}>
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
|
||||||
@@ -283,6 +301,32 @@ export default function ConfigDetail() {
|
|||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 2 }}>
|
||||||
|
<FormControl size="small" sx={{ flex: 1 }}>
|
||||||
|
<InputLabel>Download Token</InputLabel>
|
||||||
|
<OutlinedInput
|
||||||
|
label="Download Token"
|
||||||
|
value={downloadToken}
|
||||||
|
readOnly
|
||||||
|
endAdornment={
|
||||||
|
<InputAdornment position="end">
|
||||||
|
<Tooltip title="Copy token">
|
||||||
|
<IconButton onClick={() => navigator.clipboard.writeText(downloadToken)} edge="end">
|
||||||
|
<ContentCopyIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</InputAdornment>
|
||||||
|
}
|
||||||
|
inputProps={{ style: { fontFamily: 'monospace', fontSize: 12 } }}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<Tooltip title="Regenerate token">
|
||||||
|
<IconButton onClick={handleRegenerate} color="warning">
|
||||||
|
<RefreshIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<Box sx={{ bgcolor: 'white', borderRadius: 2, border: '1px solid #e2e8f0', overflow: 'hidden' }}>
|
<Box sx={{ bgcolor: 'white', borderRadius: 2, border: '1px solid #e2e8f0', overflow: 'hidden' }}>
|
||||||
<Tabs value={tab} onChange={(_, v) => setTab(v)} sx={{ borderBottom: 1, borderColor: 'divider', px: 2 }}>
|
<Tabs value={tab} onChange={(_, v) => setTab(v)} sx={{ borderBottom: 1, borderColor: 'divider', px: 2 }}>
|
||||||
{tabConfig.map((tc) => <Tab key={tc.label} label={tc.label} />)}
|
{tabConfig.map((tc) => <Tab key={tc.label} label={tc.label} />)}
|
||||||
|
|||||||
Reference in New Issue
Block a user