quality / commitlint (push) Skipped
quality / changes (push) Successful in 9s
quality / docker-check (push) Skipped
quality / openapi (push) Successful in 39s
quality / web (push) Successful in 1m29s
quality / go (push) Successful in 1m3s
quality / bird2 (push) Successful in 15s
CD / quality (push) Successful in 3m43s
CD / publish (push) Failing after 8m29s
Единый kitDataGridTableLayout и ResourcePage/FrameDataGrid на всех списках. Календарь задач переведён на EventCalendar, lookup — на cascader, у операций появился вид доски. Удалены settings-7 и самописные DataGridSection/toolbar. Co-authored-by: Cursor <[email protected]>
95 lines
2.7 KiB
TypeScript
95 lines
2.7 KiB
TypeScript
import { useState } from 'react'
|
|
import { Plus, RefreshCw } from 'lucide-react'
|
|
|
|
import { Button } from '@evobgp/ui/components/button'
|
|
import { AccessApiKeysGrid } from '@/components/access/access-api-keys-grid'
|
|
import { ApiKeyCreateDialog } from '@/components/access/api-key-create-dialog'
|
|
import { ApiKeyTokenDialog } from '@/components/access/api-key-token-dialog'
|
|
import { QueryState } from '@/components/query-state'
|
|
import { TableSkeleton } from '@/components/skeletons'
|
|
import { useRevokeApiKeyMutation, useRotateApiKeyMutation } from '@/queries/api-keys'
|
|
import type { ApiKey, ApiKeyCreated } from '@/types/api'
|
|
|
|
interface AccessApiKeysCardProps {
|
|
items: ApiKey[]
|
|
isLoading: boolean
|
|
isError: boolean
|
|
error: unknown
|
|
onRetry: () => void
|
|
}
|
|
|
|
export function AccessApiKeysCard({
|
|
items,
|
|
isLoading,
|
|
isError,
|
|
error,
|
|
onRetry,
|
|
}: AccessApiKeysCardProps) {
|
|
const [createOpen, setCreateOpen] = useState(false)
|
|
const [tokenDialogOpen, setTokenDialogOpen] = useState(false)
|
|
const [revealedToken, setRevealedToken] = useState('')
|
|
|
|
const revoke = useRevokeApiKeyMutation()
|
|
const rotate = useRotateApiKeyMutation()
|
|
|
|
function showToken(created: ApiKeyCreated) {
|
|
setRevealedToken(created.token)
|
|
setTokenDialogOpen(true)
|
|
}
|
|
|
|
function handleRotated(id: string) {
|
|
rotate.mutate(id, {
|
|
onSuccess: (created) => showToken(created),
|
|
})
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<QueryState
|
|
data={items}
|
|
isLoading={isLoading}
|
|
isError={isError}
|
|
error={error}
|
|
empty={false}
|
|
skeleton={<TableSkeleton rows={4} cols={6} />}
|
|
onRetry={onRetry}
|
|
>
|
|
{(data) => (
|
|
<AccessApiKeysGrid
|
|
items={data}
|
|
isLoading={isLoading}
|
|
onRotate={handleRotated}
|
|
onRevoke={(id) => revoke.mutate(id)}
|
|
rotatePending={rotate.isPending}
|
|
revokePending={revoke.isPending}
|
|
actions={
|
|
<>
|
|
<Button size="sm" variant="outline" type="button" onClick={onRetry} disabled={isLoading}>
|
|
<RefreshCw className={isLoading ? 'animate-spin' : ''} />
|
|
Обновить
|
|
</Button>
|
|
<Button size="sm" type="button" onClick={() => setCreateOpen(true)}>
|
|
<Plus />
|
|
Создать
|
|
</Button>
|
|
</>
|
|
}
|
|
/>
|
|
)}
|
|
</QueryState>
|
|
|
|
<ApiKeyCreateDialog
|
|
open={createOpen}
|
|
onOpenChange={setCreateOpen}
|
|
onCreated={showToken}
|
|
/>
|
|
|
|
<ApiKeyTokenDialog
|
|
open={tokenDialogOpen}
|
|
token={revealedToken}
|
|
onOpenChange={setTokenDialogOpen}
|
|
/>
|
|
</>
|
|
)
|
|
}
|