mirror of
https://github.com/GlueOps/autoglue.git
synced 2026-02-13 04:40:05 +01:00
chore: updates in UI due to migration to OAS3.1
Signed-off-by: allanice001 <allanice001@gmail.com>
This commit is contained in:
79
internal/web/dist/assets/index-52pog1DZ.js
vendored
79
internal/web/dist/assets/index-52pog1DZ.js
vendored
File diff suppressed because one or more lines are too long
BIN
internal/web/dist/assets/index-52pog1DZ.js.br
vendored
BIN
internal/web/dist/assets/index-52pog1DZ.js.br
vendored
Binary file not shown.
BIN
internal/web/dist/assets/index-52pog1DZ.js.gz
vendored
BIN
internal/web/dist/assets/index-52pog1DZ.js.gz
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
2
internal/web/dist/assets/index-tX4seA_J.css
vendored
2
internal/web/dist/assets/index-tX4seA_J.css
vendored
File diff suppressed because one or more lines are too long
BIN
internal/web/dist/assets/index-tX4seA_J.css.br
vendored
BIN
internal/web/dist/assets/index-tX4seA_J.css.br
vendored
Binary file not shown.
BIN
internal/web/dist/assets/index-tX4seA_J.css.gz
vendored
BIN
internal/web/dist/assets/index-tX4seA_J.css.gz
vendored
Binary file not shown.
4
internal/web/dist/assets/react-B75e6Si-.js
vendored
4
internal/web/dist/assets/react-B75e6Si-.js
vendored
File diff suppressed because one or more lines are too long
BIN
internal/web/dist/assets/react-B75e6Si-.js.br
vendored
BIN
internal/web/dist/assets/react-B75e6Si-.js.br
vendored
Binary file not shown.
BIN
internal/web/dist/assets/react-B75e6Si-.js.gz
vendored
BIN
internal/web/dist/assets/react-B75e6Si-.js.gz
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -12,7 +12,7 @@ export async function logoutEverywhere(): Promise<void> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const body: DtoLogoutRequest = { refresh_token: tokens.refresh_token } as DtoLogoutRequest
|
const body: DtoLogoutRequest = { refresh_token: tokens.refresh_token } as DtoLogoutRequest
|
||||||
await makeAuthApi().logout({ body })
|
await makeAuthApi().logout({ dtoLogoutRequest: body })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn("Logout API failed; clearing local state anyway", err)
|
console.warn("Logout API failed; clearing local state anyway", err)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
;
|
;
|
||||||
|
|
||||||
// src/pages/ClustersPage.tsx
|
// src/pages/ClustersPage.tsx
|
||||||
|
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
@@ -27,6 +28,36 @@ import { Label } from "@/components/ui/label.tsx";
|
|||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select.tsx";
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select.tsx";
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table.tsx";
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table.tsx";
|
||||||
import { Textarea } from "@/components/ui/textarea.tsx";
|
import { Textarea } from "@/components/ui/textarea.tsx";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1268,6 +1299,8 @@ export const ClustersPage = () => {
|
|||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
|
<pre>{JSON.stringify(clustersQ.data, null, 2)}</pre>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
import { useEffect, useState, type FC } from "react"
|
import { type FC, useEffect, useState } from "react"
|
||||||
import { archerAdminApi } from "@/api/archer_admin"
|
import { archerAdminApi } from "@/api/archer_admin"
|
||||||
import type { AdminListArcherJobsRequest } from "@/sdk"
|
|
||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
||||||
import { Loader2, Plus, RefreshCw, Search, X } from "lucide-react"
|
import { Loader2, Plus, RefreshCw, Search, X } from "lucide-react"
|
||||||
|
import {
|
||||||
|
type AdminListArcherJobsRequest,
|
||||||
|
AdminListArcherJobsStatusEnum,
|
||||||
|
type DtoJob,
|
||||||
|
type DtoPageJob,
|
||||||
|
type DtoQueueInfo,
|
||||||
|
} from "@/sdk"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { Badge } from "@/components/ui/badge"
|
import { Badge } from "@/components/ui/badge"
|
||||||
@@ -19,67 +25,20 @@ import {
|
|||||||
} from "@/components/ui/dialog"
|
} from "@/components/ui/dialog"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/ui/input"
|
||||||
import { Label } from "@/components/ui/label"
|
import { Label } from "@/components/ui/label"
|
||||||
import {
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"
|
||||||
Select,
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue,
|
|
||||||
} from "@/components/ui/select"
|
|
||||||
import {
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableHead,
|
|
||||||
TableHeader,
|
|
||||||
TableRow,
|
|
||||||
} from "@/components/ui/table"
|
|
||||||
import { Textarea } from "@/components/ui/textarea"
|
import { Textarea } from "@/components/ui/textarea"
|
||||||
|
|
||||||
// Types (align with generated client camelCase)
|
type JobStatus = AdminListArcherJobsStatusEnum
|
||||||
type JobStatus =
|
|
||||||
| "queued"
|
|
||||||
| "running"
|
|
||||||
| "succeeded"
|
|
||||||
| "failed"
|
|
||||||
| "canceled"
|
|
||||||
| "retrying"
|
|
||||||
| "scheduled"
|
|
||||||
type DtoJob = {
|
|
||||||
id: string
|
|
||||||
type: string
|
|
||||||
queue: string
|
|
||||||
status: JobStatus
|
|
||||||
attempts: number
|
|
||||||
maxAttempts?: number
|
|
||||||
createdAt: string
|
|
||||||
updatedAt?: string
|
|
||||||
lastError?: string | null
|
|
||||||
runAt?: string | null
|
|
||||||
payload?: unknown
|
|
||||||
}
|
|
||||||
type DtoPageJob = {
|
|
||||||
items: DtoJob[]
|
|
||||||
total: number
|
|
||||||
page: number
|
|
||||||
pageSize: number
|
|
||||||
}
|
|
||||||
type QueueInfo = {
|
|
||||||
name: string
|
|
||||||
pending: number
|
|
||||||
running: number
|
|
||||||
failed: number
|
|
||||||
scheduled: number
|
|
||||||
}
|
|
||||||
|
|
||||||
const STATUS: JobStatus[] = [
|
const STATUS: JobStatus[] = [
|
||||||
"queued",
|
AdminListArcherJobsStatusEnum.queued,
|
||||||
"running",
|
AdminListArcherJobsStatusEnum.running,
|
||||||
"succeeded",
|
AdminListArcherJobsStatusEnum.succeeded,
|
||||||
"failed",
|
AdminListArcherJobsStatusEnum.failed,
|
||||||
"canceled",
|
AdminListArcherJobsStatusEnum.canceled,
|
||||||
"retrying",
|
AdminListArcherJobsStatusEnum.retrying,
|
||||||
"scheduled",
|
AdminListArcherJobsStatusEnum.scheduled,
|
||||||
]
|
]
|
||||||
|
|
||||||
const statusClass: Record<JobStatus, string> = {
|
const statusClass: Record<JobStatus, string> = {
|
||||||
@@ -95,7 +54,10 @@ const statusClass: Record<JobStatus, string> = {
|
|||||||
function fmt(dt?: string | null) {
|
function fmt(dt?: string | null) {
|
||||||
if (!dt) return "—"
|
if (!dt) return "—"
|
||||||
const d = new Date(dt)
|
const d = new Date(dt)
|
||||||
return new Intl.DateTimeFormat(undefined, { dateStyle: "medium", timeStyle: "short" }).format(d)
|
return new Intl.DateTimeFormat(undefined, {
|
||||||
|
dateStyle: "medium",
|
||||||
|
timeStyle: "short",
|
||||||
|
}).format(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Small debounce hook for search input
|
// Small debounce hook for search input
|
||||||
@@ -126,12 +88,12 @@ export const JobsPage: FC = () => {
|
|||||||
queryKey: key,
|
queryKey: key,
|
||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
archerAdminApi.listJobs({
|
archerAdminApi.listJobs({
|
||||||
status: status,
|
status: status ? (status as JobStatus) : undefined,
|
||||||
queue: queue || undefined,
|
queue: queue || undefined,
|
||||||
q: debouncedQ || undefined,
|
q: debouncedQ || undefined,
|
||||||
page,
|
page,
|
||||||
pageSize,
|
pageSize,
|
||||||
} as AdminListArcherJobsRequest) as Promise<DtoPageJob>,
|
} as AdminListArcherJobsRequest),
|
||||||
placeholderData: (prev) => prev,
|
placeholderData: (prev) => prev,
|
||||||
staleTime: 10_000,
|
staleTime: 10_000,
|
||||||
})
|
})
|
||||||
@@ -139,7 +101,7 @@ export const JobsPage: FC = () => {
|
|||||||
// Queues summary (optional header)
|
// Queues summary (optional header)
|
||||||
const queuesQ = useQuery({
|
const queuesQ = useQuery({
|
||||||
queryKey: ["archer", "queues"],
|
queryKey: ["archer", "queues"],
|
||||||
queryFn: () => archerAdminApi.listQueues() as Promise<QueueInfo[]>,
|
queryFn: () => archerAdminApi.listQueues() as Promise<DtoQueueInfo[]>,
|
||||||
staleTime: 30_000,
|
staleTime: 30_000,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -153,10 +115,12 @@ export const JobsPage: FC = () => {
|
|||||||
}) => archerAdminApi.enqueue(body),
|
}) => archerAdminApi.enqueue(body),
|
||||||
onSuccess: () => qc.invalidateQueries({ queryKey: ["archer", "jobs"] }),
|
onSuccess: () => qc.invalidateQueries({ queryKey: ["archer", "jobs"] }),
|
||||||
})
|
})
|
||||||
|
|
||||||
const retryM = useMutation({
|
const retryM = useMutation({
|
||||||
mutationFn: (id: string) => archerAdminApi.retryJob(id),
|
mutationFn: (id: string) => archerAdminApi.retryJob(id),
|
||||||
onSuccess: () => qc.invalidateQueries({ queryKey: ["archer", "jobs"] }),
|
onSuccess: () => qc.invalidateQueries({ queryKey: ["archer", "jobs"] }),
|
||||||
})
|
})
|
||||||
|
|
||||||
const cancelM = useMutation({
|
const cancelM = useMutation({
|
||||||
mutationFn: (id: string) => archerAdminApi.cancelJob(id),
|
mutationFn: (id: string) => archerAdminApi.cancelJob(id),
|
||||||
onSuccess: () => qc.invalidateQueries({ queryKey: ["archer", "jobs"] }),
|
onSuccess: () => qc.invalidateQueries({ queryKey: ["archer", "jobs"] }),
|
||||||
@@ -164,8 +128,10 @@ export const JobsPage: FC = () => {
|
|||||||
|
|
||||||
const busy = jobsQ.isFetching
|
const busy = jobsQ.isFetching
|
||||||
|
|
||||||
const data = jobsQ.data as DtoPageJob
|
const data = jobsQ.data as DtoPageJob | undefined
|
||||||
const totalPages = data ? Math.max(1, Math.ceil(data.total / data.pageSize)) : 1
|
const items: DtoJob[] = data?.items ?? []
|
||||||
|
const total = data?.total ?? 0
|
||||||
|
const totalPages = Math.max(1, Math.ceil(total / pageSize))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto space-y-6 p-6">
|
<div className="container mx-auto space-y-6 p-6">
|
||||||
@@ -204,10 +170,10 @@ export const JobsPage: FC = () => {
|
|||||||
<CardTitle className="text-base">{q.name}</CardTitle>
|
<CardTitle className="text-base">{q.name}</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="grid grid-cols-2 gap-2 text-sm">
|
<CardContent className="grid grid-cols-2 gap-2 text-sm">
|
||||||
<Metric label="Pending" value={q.pending} />
|
<Metric label="Pending" value={q.pending ?? 0} />
|
||||||
<Metric label="Running" value={q.running} />
|
<Metric label="Running" value={q.running ?? 0} />
|
||||||
<Metric label="Failed" value={q.failed} />
|
<Metric label="Failed" value={q.failed ?? 0} />
|
||||||
<Metric label="Scheduled" value={q.scheduled} />
|
<Metric label="Scheduled" value={q.scheduled ?? 0} />
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
@@ -321,67 +287,85 @@ export const JobsPage: FC = () => {
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
)}
|
)}
|
||||||
{!jobsQ.isLoading && data && data.items.length === 0 && (
|
{!jobsQ.isLoading && items.length === 0 && (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={7} className="text-muted-foreground py-8 text-center">
|
<TableCell colSpan={7} className="text-muted-foreground py-8 text-center">
|
||||||
No jobs match your filters.
|
No jobs match your filters.
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
)}
|
)}
|
||||||
{data?.items.map((j) => (
|
{items.map((j) => {
|
||||||
<TableRow key={j.id}>
|
const jobStatus: JobStatus =
|
||||||
<TableCell>
|
(j.status as JobStatus | undefined) ??
|
||||||
<code className="text-xs">{j.id}</code>
|
AdminListArcherJobsStatusEnum.queued
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
return (
|
||||||
<Badge variant="secondary">{j.queue}</Badge>
|
<TableRow key={j.id}>
|
||||||
</TableCell>
|
<TableCell>
|
||||||
<TableCell>
|
<code className="text-xs">{j.id}</code>
|
||||||
<span className={cn("rounded-md px-2 py-0.5 text-xs", statusClass[j.status])}>
|
</TableCell>
|
||||||
{j.status}
|
<TableCell>
|
||||||
</span>
|
<Badge variant="secondary">{j.queue}</Badge>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
{j.maxAttempts ? `${j.attempts}/${j.maxAttempts}` : j.attempts}
|
<span
|
||||||
</TableCell>
|
className={cn(
|
||||||
<TableCell>{fmt(j.runAt)}</TableCell>
|
"rounded-md px-2 py-0.5 text-xs",
|
||||||
<TableCell>{fmt(j.updatedAt ?? j.createdAt)}</TableCell>
|
statusClass[jobStatus],
|
||||||
<TableCell className="text-right">
|
)}
|
||||||
<div className="flex justify-end gap-2">
|
>
|
||||||
{(j.status === "failed" || j.status === "canceled") && (
|
{jobStatus}
|
||||||
<Button
|
</span>
|
||||||
size="sm"
|
</TableCell>
|
||||||
variant="outline"
|
<TableCell>
|
||||||
disabled={retryM.isPending}
|
{j.max_attempts ? `${j.attempts}/${j.max_attempts}` : j.attempts}
|
||||||
onClick={() => retryM.mutate(j.id)}
|
</TableCell>
|
||||||
>
|
<TableCell>{fmt(j.run_at)}</TableCell>
|
||||||
Retry
|
<TableCell>{fmt(j.updated_at ?? j.created_at)}</TableCell>
|
||||||
</Button>
|
<TableCell className="text-right">
|
||||||
)}
|
<div className="flex justify-end gap-2">
|
||||||
{(j.status === "queued" ||
|
{(jobStatus === AdminListArcherJobsStatusEnum.failed ||
|
||||||
j.status === "running" ||
|
jobStatus === AdminListArcherJobsStatusEnum.canceled) && (
|
||||||
j.status === "scheduled") && (
|
<Button
|
||||||
<Button
|
size="sm"
|
||||||
size="sm"
|
variant="outline"
|
||||||
variant="outline"
|
disabled={retryM.isPending || !j.id}
|
||||||
disabled={cancelM.isPending}
|
onClick={() => {
|
||||||
onClick={() => cancelM.mutate(j.id)}
|
if (!j.id) return
|
||||||
>
|
retryM.mutate(j.id)
|
||||||
Cancel
|
}}
|
||||||
</Button>
|
>
|
||||||
)}
|
Retry
|
||||||
<DetailsButton job={j} />
|
</Button>
|
||||||
</div>
|
)}
|
||||||
</TableCell>
|
{(jobStatus === AdminListArcherJobsStatusEnum.queued ||
|
||||||
</TableRow>
|
jobStatus === AdminListArcherJobsStatusEnum.running ||
|
||||||
))}
|
jobStatus === AdminListArcherJobsStatusEnum.scheduled) && (
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
disabled={cancelM.isPending || !j.id}
|
||||||
|
onClick={() => {
|
||||||
|
if (!j.id) return
|
||||||
|
cancelM.mutate(j.id)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<DetailsButton job={j} />
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
})}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
{/* Pagination */}
|
{/* Pagination */}
|
||||||
<div className="flex items-center justify-between border-t p-3 text-sm">
|
<div className="flex items-center justify-between border-t p-3 text-sm">
|
||||||
<div>
|
<div>
|
||||||
Page {page} of {totalPages} • {data?.total ?? 0} total
|
Page {page} of {totalPages} • {total} total
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Button
|
<Button
|
||||||
@@ -428,13 +412,15 @@ function DetailsButton({ job }: { job: DtoJob }) {
|
|||||||
<DialogTitle>Job {job.id}</DialogTitle>
|
<DialogTitle>Job {job.id}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="grid gap-3">
|
<div className="grid gap-3">
|
||||||
{job.lastError && (
|
{job.last_error && (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-sm">Last error</CardTitle>
|
<CardTitle className="text-sm">Last error</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<pre className="overflow-auto text-xs whitespace-pre-wrap">{job.lastError}</pre>
|
<pre className="overflow-auto text-xs whitespace-pre-wrap">
|
||||||
|
{job.last_error}
|
||||||
|
</pre>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
@@ -460,9 +446,9 @@ function DetailsButton({ job }: { job: DtoJob }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function EnqueueDialog({
|
function EnqueueDialog({
|
||||||
onSubmit,
|
onSubmit,
|
||||||
submitting,
|
submitting,
|
||||||
}: {
|
}: {
|
||||||
onSubmit: (body: {
|
onSubmit: (body: {
|
||||||
queue: string
|
queue: string
|
||||||
type: string
|
type: string
|
||||||
@@ -527,7 +513,11 @@ function EnqueueDialog({
|
|||||||
</div>
|
</div>
|
||||||
<div className="grid gap-2">
|
<div className="grid gap-2">
|
||||||
<Label>Run at (optional)</Label>
|
<Label>Run at (optional)</Label>
|
||||||
<Input type="datetime-local" value={runAt} onChange={(e) => setRunAt(e.target.value)} />
|
<Input
|
||||||
|
type="datetime-local"
|
||||||
|
value={runAt}
|
||||||
|
onChange={(e) => setRunAt(e.target.value)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
|
|||||||
@@ -31,32 +31,17 @@ import {
|
|||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
} from "@/components/ui/dialog.tsx"
|
} from "@/components/ui/dialog.tsx"
|
||||||
import {
|
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form.tsx"
|
||||||
Form,
|
|
||||||
FormControl,
|
|
||||||
FormField,
|
|
||||||
FormItem,
|
|
||||||
FormLabel,
|
|
||||||
FormMessage,
|
|
||||||
} from "@/components/ui/form.tsx"
|
|
||||||
import { Input } from "@/components/ui/input.tsx"
|
import { Input } from "@/components/ui/input.tsx"
|
||||||
import { Label } from "@/components/ui/label.tsx"
|
import { Label } from "@/components/ui/label.tsx"
|
||||||
import { Separator } from "@/components/ui/separator.tsx"
|
import { Separator } from "@/components/ui/separator.tsx"
|
||||||
import {
|
import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table.tsx"
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCaption,
|
|
||||||
TableCell,
|
|
||||||
TableHead,
|
|
||||||
TableHeader,
|
|
||||||
TableRow,
|
|
||||||
} from "@/components/ui/table.tsx"
|
|
||||||
|
|
||||||
const orgsApi = makeOrgsApi()
|
const orgsApi = makeOrgsApi()
|
||||||
|
|
||||||
const orgApi = {
|
const orgApi = {
|
||||||
create: (body: { name: string; domain?: string }) =>
|
create: (body: { name: string; domain?: string }) =>
|
||||||
withRefresh(async () => orgsApi.createOrg({ body })), // POST /orgs
|
withRefresh(async () => orgsApi.createOrg({ handlersOrgCreateReq: body })), // POST /orgs
|
||||||
}
|
}
|
||||||
|
|
||||||
const profileSchema = z.object({
|
const profileSchema = z.object({
|
||||||
|
|||||||
@@ -10,30 +10,10 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { Button } from "@/components/ui/button.tsx"
|
import { Button } from "@/components/ui/button.tsx"
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"
|
||||||
import {
|
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog.tsx"
|
||||||
Dialog,
|
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form.tsx"
|
||||||
DialogContent,
|
|
||||||
DialogFooter,
|
|
||||||
DialogHeader,
|
|
||||||
DialogTitle,
|
|
||||||
} from "@/components/ui/dialog.tsx"
|
|
||||||
import {
|
|
||||||
Form,
|
|
||||||
FormControl,
|
|
||||||
FormField,
|
|
||||||
FormItem,
|
|
||||||
FormLabel,
|
|
||||||
FormMessage,
|
|
||||||
} from "@/components/ui/form.tsx"
|
|
||||||
import { Input } from "@/components/ui/input.tsx"
|
import { Input } from "@/components/ui/input.tsx"
|
||||||
import {
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table.tsx"
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableHead,
|
|
||||||
TableHeader,
|
|
||||||
TableRow,
|
|
||||||
} from "@/components/ui/table.tsx"
|
|
||||||
|
|
||||||
const createSchema = z.object({
|
const createSchema = z.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
@@ -66,7 +46,7 @@ export const OrgApiKeys = () => {
|
|||||||
} | null>(null)
|
} | null>(null)
|
||||||
|
|
||||||
const createMut = useMutation({
|
const createMut = useMutation({
|
||||||
mutationFn: (v: CreateValues) => api.createOrgKey({ id: orgId!, body: v }),
|
mutationFn: (v: CreateValues) => api.createOrgKey({ id: orgId!, handlersOrgKeyCreateReq: v }),
|
||||||
onSuccess: (resp) => {
|
onSuccess: (resp) => {
|
||||||
void qc.invalidateQueries({ queryKey: ["org:keys", orgId] })
|
void qc.invalidateQueries({ queryKey: ["org:keys", orgId] })
|
||||||
setShowSecret({ key: resp.org_key, secret: resp.org_secret })
|
setShowSecret({ key: resp.org_key, secret: resp.org_secret })
|
||||||
|
|||||||
@@ -11,30 +11,10 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { Button } from "@/components/ui/button.tsx"
|
import { Button } from "@/components/ui/button.tsx"
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"
|
||||||
import {
|
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form.tsx"
|
||||||
Form,
|
|
||||||
FormControl,
|
|
||||||
FormField,
|
|
||||||
FormItem,
|
|
||||||
FormLabel,
|
|
||||||
FormMessage,
|
|
||||||
} from "@/components/ui/form.tsx"
|
|
||||||
import { Input } from "@/components/ui/input.tsx"
|
import { Input } from "@/components/ui/input.tsx"
|
||||||
import {
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select.tsx"
|
||||||
Select,
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table.tsx"
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue,
|
|
||||||
} from "@/components/ui/select.tsx"
|
|
||||||
import {
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableHead,
|
|
||||||
TableHeader,
|
|
||||||
TableRow,
|
|
||||||
} from "@/components/ui/table.tsx"
|
|
||||||
|
|
||||||
const addSchema = z.object({
|
const addSchema = z.object({
|
||||||
user_id: z.uuid("Invalid UUID"),
|
user_id: z.uuid("Invalid UUID"),
|
||||||
@@ -68,7 +48,7 @@ export const OrgMembers = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const addMut = useMutation({
|
const addMut = useMutation({
|
||||||
mutationFn: (v: AddValues) => api.addOrUpdateMember({ id: orgId!, body: v }),
|
mutationFn: (v: AddValues) => api.addOrUpdateMember({ id: orgId!, handlersMemberUpsertReq: v }),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
toast.success("Member added/updated")
|
toast.success("Member added/updated")
|
||||||
void qc.invalidateQueries({ queryKey: ["org:members", orgId] })
|
void qc.invalidateQueries({ queryKey: ["org:members", orgId] })
|
||||||
@@ -88,7 +68,7 @@ export const OrgMembers = () => {
|
|||||||
|
|
||||||
const roleMut = useMutation({
|
const roleMut = useMutation({
|
||||||
mutationFn: ({ userId, role }: { userId: string; role: "owner" | "admin" | "member" }) =>
|
mutationFn: ({ userId, role }: { userId: string; role: "owner" | "admin" | "member" }) =>
|
||||||
api.addOrUpdateMember({ id: orgId!, body: { user_id: userId, role } }),
|
api.addOrUpdateMember({ id: orgId!, handlersMemberUpsertReq: { user_id: userId, role } }),
|
||||||
onMutate: async ({ userId, role }) => {
|
onMutate: async ({ userId, role }) => {
|
||||||
setUpdatingId(userId)
|
setUpdatingId(userId)
|
||||||
// cancel queries and snapshot previous
|
// cancel queries and snapshot previous
|
||||||
|
|||||||
@@ -10,14 +10,7 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { Button } from "@/components/ui/button.tsx"
|
import { Button } from "@/components/ui/button.tsx"
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"
|
||||||
import {
|
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form.tsx"
|
||||||
Form,
|
|
||||||
FormControl,
|
|
||||||
FormField,
|
|
||||||
FormItem,
|
|
||||||
FormLabel,
|
|
||||||
FormMessage,
|
|
||||||
} from "@/components/ui/form.tsx"
|
|
||||||
import { Input } from "@/components/ui/input.tsx"
|
import { Input } from "@/components/ui/input.tsx"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -80,7 +73,7 @@ export const OrgSettings = () => {
|
|||||||
}, [q.data, form])
|
}, [q.data, form])
|
||||||
|
|
||||||
const updateMut = useMutation({
|
const updateMut = useMutation({
|
||||||
mutationFn: (v: Partial<Values>) => api.updateOrg({ id: orgId!, body: v }),
|
mutationFn: (v: Partial<Values>) => api.updateOrg({ id: orgId!, handlersOrgUpdateReq: v }),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
void qc.invalidateQueries({ queryKey: ["org", orgId] })
|
void qc.invalidateQueries({ queryKey: ["org", orgId] })
|
||||||
toast.success("Organization updated")
|
toast.success("Organization updated")
|
||||||
|
|||||||
@@ -28,5 +28,5 @@
|
|||||||
"@/*": ["./src/*"]
|
"@/*": ["./src/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["src", "src/types"]
|
"include": ["src"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,5 +11,4 @@
|
|||||||
},
|
},
|
||||||
"jsx": "react-jsx"
|
"jsx": "react-jsx"
|
||||||
},
|
},
|
||||||
"include": ["src", "src/types"]
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user