fix(ui): import agent button
This commit is contained in:
parent
c440f98381
commit
184d86c58a
|
|
@ -9,9 +9,25 @@ import { useAuth } from "@/auth/clerk";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { AgentsTable } from "@/components/agents/AgentsTable";
|
import { AgentsTable } from "@/components/agents/AgentsTable";
|
||||||
|
import { GatewayAgentImportDialog } from "@/components/gateways/GatewayAgentImportDialog";
|
||||||
import { DashboardPageLayout } from "@/components/templates/DashboardPageLayout";
|
import { DashboardPageLayout } from "@/components/templates/DashboardPageLayout";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { ConfirmActionDialog } from "@/components/ui/confirm-action-dialog";
|
import { ConfirmActionDialog } from "@/components/ui/confirm-action-dialog";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
|
||||||
import { ApiError } from "@/api/mutator";
|
import { ApiError } from "@/api/mutator";
|
||||||
import {
|
import {
|
||||||
|
|
@ -25,7 +41,12 @@ import {
|
||||||
getListBoardsApiV1BoardsGetQueryKey,
|
getListBoardsApiV1BoardsGetQueryKey,
|
||||||
useListBoardsApiV1BoardsGet,
|
useListBoardsApiV1BoardsGet,
|
||||||
} from "@/api/generated/boards/boards";
|
} from "@/api/generated/boards/boards";
|
||||||
import { type AgentRead } from "@/api/generated/model";
|
import {
|
||||||
|
type listGatewaysApiV1GatewaysGetResponse,
|
||||||
|
getListGatewaysApiV1GatewaysGetQueryKey,
|
||||||
|
useListGatewaysApiV1GatewaysGet,
|
||||||
|
} from "@/api/generated/gateways/gateways";
|
||||||
|
import { type AgentRead, type GatewayRead } from "@/api/generated/model";
|
||||||
import { createOptimisticListDeleteMutation } from "@/lib/list-delete";
|
import { createOptimisticListDeleteMutation } from "@/lib/list-delete";
|
||||||
import { useOrganizationMembership } from "@/lib/use-organization-membership";
|
import { useOrganizationMembership } from "@/lib/use-organization-membership";
|
||||||
import { useUrlSorting } from "@/lib/use-url-sorting";
|
import { useUrlSorting } from "@/lib/use-url-sorting";
|
||||||
|
|
@ -52,9 +73,13 @@ export default function AgentsPage() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const [deleteTarget, setDeleteTarget] = useState<AgentRead | null>(null);
|
const [deleteTarget, setDeleteTarget] = useState<AgentRead | null>(null);
|
||||||
|
const [importGatewayPickerOpen, setImportGatewayPickerOpen] = useState(false);
|
||||||
|
const [selectedGatewayId, setSelectedGatewayId] = useState<string>("");
|
||||||
|
const [importTarget, setImportTarget] = useState<GatewayRead | null>(null);
|
||||||
|
|
||||||
const boardsKey = getListBoardsApiV1BoardsGetQueryKey();
|
const boardsKey = getListBoardsApiV1BoardsGetQueryKey();
|
||||||
const agentsKey = getListAgentsApiV1AgentsGetQueryKey();
|
const agentsKey = getListAgentsApiV1AgentsGetQueryKey();
|
||||||
|
const gatewaysKey = getListGatewaysApiV1GatewaysGetQueryKey();
|
||||||
|
|
||||||
const boardsQuery = useListBoardsApiV1BoardsGet<
|
const boardsQuery = useListBoardsApiV1BoardsGet<
|
||||||
listBoardsApiV1BoardsGetResponse,
|
listBoardsApiV1BoardsGetResponse,
|
||||||
|
|
@ -77,6 +102,16 @@ export default function AgentsPage() {
|
||||||
refetchOnMount: "always",
|
refetchOnMount: "always",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const gatewaysQuery = useListGatewaysApiV1GatewaysGet<
|
||||||
|
listGatewaysApiV1GatewaysGetResponse,
|
||||||
|
ApiError
|
||||||
|
>(undefined, {
|
||||||
|
query: {
|
||||||
|
enabled: Boolean(isSignedIn && isAdmin),
|
||||||
|
refetchInterval: 30_000,
|
||||||
|
refetchOnMount: "always",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const boards = useMemo(
|
const boards = useMemo(
|
||||||
() =>
|
() =>
|
||||||
|
|
@ -92,6 +127,13 @@ export default function AgentsPage() {
|
||||||
: [],
|
: [],
|
||||||
[agentsQuery.data],
|
[agentsQuery.data],
|
||||||
);
|
);
|
||||||
|
const gateways = useMemo(
|
||||||
|
() =>
|
||||||
|
gatewaysQuery.data?.status === 200
|
||||||
|
? (gatewaysQuery.data.data.items ?? [])
|
||||||
|
: [],
|
||||||
|
[gatewaysQuery.data],
|
||||||
|
);
|
||||||
|
|
||||||
const deleteMutation = useDeleteAgentApiV1AgentsAgentIdDelete<
|
const deleteMutation = useDeleteAgentApiV1AgentsAgentIdDelete<
|
||||||
ApiError,
|
ApiError,
|
||||||
|
|
@ -121,6 +163,26 @@ export default function AgentsPage() {
|
||||||
deleteMutation.mutate({ agentId: deleteTarget.id });
|
deleteMutation.mutate({ agentId: deleteTarget.id });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleImportAgentsClick = () => {
|
||||||
|
if (gateways.length === 1) {
|
||||||
|
setImportTarget(gateways[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setImportGatewayPickerOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOpenImportForSelectedGateway = () => {
|
||||||
|
const gateway = gateways.find((item) => item.id === selectedGatewayId);
|
||||||
|
if (!gateway) return;
|
||||||
|
setImportGatewayPickerOpen(false);
|
||||||
|
setImportTarget(gateway);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleImported = async () => {
|
||||||
|
await queryClient.invalidateQueries({ queryKey: agentsKey });
|
||||||
|
await queryClient.invalidateQueries({ queryKey: gatewaysKey });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DashboardPageLayout
|
<DashboardPageLayout
|
||||||
|
|
@ -133,9 +195,18 @@ export default function AgentsPage() {
|
||||||
description={`${agents.length} agent${agents.length === 1 ? "" : "s"} total.`}
|
description={`${agents.length} agent${agents.length === 1 ? "" : "s"} total.`}
|
||||||
headerActions={
|
headerActions={
|
||||||
agents.length > 0 ? (
|
agents.length > 0 ? (
|
||||||
<Button onClick={() => router.push("/agents/new")}>
|
<div className="flex items-center gap-2">
|
||||||
New agent
|
<Button
|
||||||
</Button>
|
variant="outline"
|
||||||
|
onClick={handleImportAgentsClick}
|
||||||
|
disabled={gateways.length === 0}
|
||||||
|
>
|
||||||
|
Import agents
|
||||||
|
</Button>
|
||||||
|
<Button onClick={() => router.push("/agents/new")}>
|
||||||
|
New agent
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
isAdmin={isAdmin}
|
isAdmin={isAdmin}
|
||||||
|
|
@ -187,6 +258,65 @@ export default function AgentsPage() {
|
||||||
onConfirm={handleDelete}
|
onConfirm={handleDelete}
|
||||||
isConfirming={deleteMutation.isPending}
|
isConfirming={deleteMutation.isPending}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Dialog
|
||||||
|
open={importGatewayPickerOpen}
|
||||||
|
onOpenChange={(open) => {
|
||||||
|
setImportGatewayPickerOpen(open);
|
||||||
|
if (!open) {
|
||||||
|
setSelectedGatewayId("");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Import Agents</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Select a gateway to open the agent import screen.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<p className="text-sm font-medium text-foreground">Gateway</p>
|
||||||
|
<Select value={selectedGatewayId} onValueChange={setSelectedGatewayId}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select a gateway" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{gateways.map((gateway) => (
|
||||||
|
<SelectItem key={gateway.id} value={gateway.id}>
|
||||||
|
{gateway.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => setImportGatewayPickerOpen(false)}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={handleOpenImportForSelectedGateway}
|
||||||
|
disabled={!selectedGatewayId}
|
||||||
|
>
|
||||||
|
Continue
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
<GatewayAgentImportDialog
|
||||||
|
open={Boolean(importTarget)}
|
||||||
|
onOpenChange={(open) => {
|
||||||
|
if (!open) {
|
||||||
|
setImportTarget(null);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
gateway={importTarget}
|
||||||
|
onImported={handleImported}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue