feat: add multi-select functionality across various pages

- Implemented checkbox selection for multiple items in DeploymentRulesPage, DomainsPage, EnvironmentsPage, ServicesPage, TargetsPage, TemplateCategoriesPage, and TemplatesPage.
- Added delete functionality for selected items with confirmation prompts.
- Updated state management to handle selected IDs for batch operations.
- Enhanced UI with a toolbar for actions related to selected items.
- Adjusted API calls to accommodate changes in data structure, including deployment requests and job details.
This commit is contained in:
Torsten Brendgen
2026-07-09 23:49:10 +02:00
parent 3083e81452
commit 1894f740b0
13 changed files with 911 additions and 118 deletions

View File

@@ -1,6 +1,7 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
Button,
Checkbox,
Combobox,
Dialog,
DialogActions,
@@ -59,6 +60,7 @@ export function DomainsPage() {
const [netBIOS, setNetBIOS] = useState("");
const [linkDomainId, setLinkDomainId] = useState("");
const [environmentId, setEnvironmentId] = useState("");
const [selectedIds, setSelectedIds] = useState<string[]>([]);
const { data, error, isLoading } = useQuery({
queryKey: ["domains"],
queryFn: ({ signal }) => portalApi.getDomains(signal),
@@ -120,6 +122,15 @@ export function DomainsPage() {
await queryClient.invalidateQueries({ queryKey: ["domains"] });
},
});
const deleteSelectedDomains = useMutation({
mutationFn: async (ids: string[]) => {
await Promise.all(ids.map((id) => portalApi.deleteDomain(id)));
},
onSuccess: async () => {
setSelectedIds([]);
await queryClient.invalidateQueries({ queryKey: ["domains"] });
},
});
const linkDomainToEnvironment = useMutation({
mutationFn: ({ domainId, environmentId: targetEnvironmentId }: { domainId: string; environmentId: string }) =>
portalApi.linkDomainToEnvironment(domainId, targetEnvironmentId),
@@ -145,6 +156,10 @@ export function DomainsPage() {
const formError = addDomain.error?.message ?? updateDomain.error?.message;
const isSaving = addDomain.isPending || updateDomain.isPending;
const allSelected = Boolean(data?.length) && data!.every((domain) => selectedIds.includes(domain.id));
const toggleSelected = (id: string, checked: boolean) => {
setSelectedIds((current) => (checked ? [...new Set([...current, id])] : current.filter((entry) => entry !== id)));
};
return (
<>
@@ -156,6 +171,18 @@ export function DomainsPage() {
<Button appearance="secondary" icon={<LinkMultiple24Regular />} onClick={openLinkDialog}>
Link to Environment
</Button>
<Button
appearance="secondary"
disabled={selectedIds.length === 0 || deleteSelectedDomains.isPending}
icon={<DeleteRegular />}
onClick={() => {
if (window.confirm(`${selectedIds.length} Domains wirklich loeschen?`)) {
deleteSelectedDomains.mutate(selectedIds);
}
}}
>
Auswahl loeschen
</Button>
</div>
<Dialog open={dialogMode !== null} onOpenChange={(_, data) => !data.open && closeDialog()}>
@@ -251,11 +278,20 @@ export function DomainsPage() {
</DialogSurface>
</Dialog>
<DataState isLoading={isLoading || environmentsLoading} error={error ?? environmentsError ?? deleteDomain.error ?? linkDomainToEnvironment.error} />
<DataState
isLoading={isLoading || environmentsLoading}
error={error ?? environmentsError ?? deleteDomain.error ?? deleteSelectedDomains.error ?? linkDomainToEnvironment.error}
/>
{data && (
<Table aria-label="Domains">
<TableHeader>
<TableRow>
<TableHeaderCell>
<Checkbox
checked={allSelected}
onChange={(_, checkboxData) => setSelectedIds(checkboxData.checked ? data.map((domain) => domain.id) : [])}
/>
</TableHeaderCell>
<TableHeaderCell>Name</TableHeaderCell>
<TableHeaderCell>FQDN</TableHeaderCell>
<TableHeaderCell>NetBIOS</TableHeaderCell>
@@ -266,6 +302,12 @@ export function DomainsPage() {
<TableBody>
{data.map((domain) => (
<TableRow key={domain.id}>
<TableCell>
<Checkbox
checked={selectedIds.includes(domain.id)}
onChange={(_, checkboxData) => toggleSelected(domain.id, Boolean(checkboxData.checked))}
/>
</TableCell>
<TableCell>{domain.name}</TableCell>
<TableCell>{domain.fqdn}</TableCell>
<TableCell>{domain.netBIOS}</TableCell>