mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-15 20:25:23 +02:00
feat(ui): implement bulk delete dialog for services in project dashboard
This commit is contained in:
@@ -290,6 +290,8 @@ const Project = (
|
||||
const [openCombobox, setOpenCombobox] = useState(false);
|
||||
const [selectedServices, setSelectedServices] = useState<string[]>([]);
|
||||
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
||||
const [isBulkDeleteDialogOpen, setIsBulkDeleteDialogOpen] = useState(false);
|
||||
const [deleteVolumes, setDeleteVolumes] = useState(false);
|
||||
|
||||
const handleSelectAll = () => {
|
||||
if (selectedServices.length === filteredServices.length) {
|
||||
@@ -532,7 +534,7 @@ const Project = (
|
||||
setIsBulkActionLoading(false);
|
||||
};
|
||||
|
||||
const handleBulkDelete = async () => {
|
||||
const handleBulkDelete = async (deleteVolumes = false) => {
|
||||
let success = 0;
|
||||
setIsBulkActionLoading(true);
|
||||
for (const serviceId of selectedServices) {
|
||||
@@ -549,7 +551,7 @@ const Project = (
|
||||
case "compose":
|
||||
await composeActions.delete.mutateAsync({
|
||||
composeId: serviceId,
|
||||
deleteVolumes: false,
|
||||
deleteVolumes,
|
||||
});
|
||||
break;
|
||||
case "postgres":
|
||||
@@ -879,7 +881,7 @@ const Project = (
|
||||
disabled={
|
||||
selectedServicesWithRunningStatus.length > 0
|
||||
}
|
||||
onClick={handleBulkDelete}
|
||||
onClick={() => setIsBulkDeleteDialogOpen(true)}
|
||||
>
|
||||
<Button
|
||||
variant="ghost"
|
||||
@@ -975,6 +977,113 @@ const Project = (
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{/* Bulk Delete Dialog */}
|
||||
<Dialog
|
||||
open={isBulkDeleteDialogOpen}
|
||||
onOpenChange={setIsBulkDeleteDialogOpen}
|
||||
>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Delete Services</DialogTitle>
|
||||
<DialogDescription>
|
||||
Are you sure you want to delete{" "}
|
||||
{selectedServices.length} service
|
||||
{selectedServices.length !== 1 ? "s" : ""}?
|
||||
This action cannot be undone.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-4">
|
||||
{/* Show services to be deleted */}
|
||||
<div className="max-h-40 overflow-y-auto space-y-2">
|
||||
{selectedServices.map((serviceId) => {
|
||||
const service = filteredServices.find(
|
||||
(s) => s.id === serviceId,
|
||||
);
|
||||
return service ? (
|
||||
<div
|
||||
key={serviceId}
|
||||
className="flex items-center space-x-2 text-sm"
|
||||
>
|
||||
<span className="px-2 py-1 text-xs bg-secondary rounded">
|
||||
{service.type}
|
||||
</span>
|
||||
<span>{service.name}</span>
|
||||
</div>
|
||||
) : null;
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Volume deletion option for compose services */}
|
||||
{(() => {
|
||||
const servicesWithVolumeSupport =
|
||||
selectedServices.filter((serviceId) => {
|
||||
const service = filteredServices.find(
|
||||
(s) => s.id === serviceId,
|
||||
);
|
||||
// Currently only compose services support volume deletion
|
||||
return service?.type === "compose";
|
||||
});
|
||||
|
||||
if (servicesWithVolumeSupport.length === 0)
|
||||
return null;
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="deleteVolumes"
|
||||
checked={deleteVolumes}
|
||||
onCheckedChange={(checked) =>
|
||||
setDeleteVolumes(checked === true)
|
||||
}
|
||||
/>
|
||||
<label
|
||||
htmlFor="deleteVolumes"
|
||||
className="text-sm font-medium"
|
||||
>
|
||||
Delete volumes associated with
|
||||
services
|
||||
</label>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Volume deletion is available for:{" "}
|
||||
{servicesWithVolumeSupport.length}{" "}
|
||||
compose service
|
||||
{servicesWithVolumeSupport.length !== 1
|
||||
? "s"
|
||||
: ""}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
setIsBulkDeleteDialogOpen(false);
|
||||
setDeleteVolumes(false); // Reset checkbox
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="destructive"
|
||||
onClick={() => {
|
||||
handleBulkDelete(deleteVolumes);
|
||||
setIsBulkDeleteDialogOpen(false);
|
||||
setDeleteVolumes(false); // Reset checkbox
|
||||
}}
|
||||
disabled={isBulkActionLoading}
|
||||
>
|
||||
Delete Services
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user