mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
Working on bugs, add delete restore. Review the auth style. working on the RBAC.
This commit is contained in:
@@ -1,15 +1,33 @@
|
||||
"use client";
|
||||
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { MoreHorizontal } from "lucide-react";
|
||||
import {MoreHorizontal, Trash2} from "lucide-react";
|
||||
import { ReloadIcon } from "@radix-ui/react-icons";
|
||||
import { StatusBadge } from "@/components/wrappers/common/status-badge";
|
||||
import {Restoration} from "@/db/schema/06_database";
|
||||
import {Backup, Restoration} from "@/db/schema/06_database";
|
||||
import {formatFrenchDate} from "@/utils/date-formatting";
|
||||
import {useMutation} from "@tanstack/react-query";
|
||||
import {
|
||||
deleteBackupAction,
|
||||
deleteRestoreAction,
|
||||
rerunRestorationAction
|
||||
} from "@/features/dashboard/restore/restore.action";
|
||||
import {toast} from "sonner";
|
||||
import {useRouter} from "next/navigation";
|
||||
import {TooltipCustom} from "@/components/wrappers/common/tooltipCustom/TooltipCustom";
|
||||
|
||||
export const restoreColumns: ColumnDef<Restoration>[] = [
|
||||
|
||||
export function restoreColumns(isAlreadyRestore: boolean): ColumnDef<Restoration>[] {
|
||||
return[
|
||||
{
|
||||
accessorKey: "id",
|
||||
header: "Reference",
|
||||
@@ -31,6 +49,58 @@ export const restoreColumns: ColumnDef<Restoration>[] = [
|
||||
{
|
||||
id: "actions",
|
||||
cell: ({ row }) => {
|
||||
const status = row.getValue("status");
|
||||
|
||||
const router = useRouter();
|
||||
const rowData: Restoration = row.original;
|
||||
|
||||
|
||||
const mutationDeleteRestore = useMutation({
|
||||
mutationFn: async () => {
|
||||
const restoration = await deleteRestoreAction({
|
||||
restorationId: rowData.id,
|
||||
});
|
||||
// @ts-ignore
|
||||
if (restoration.data.success) {
|
||||
// @ts-ignore
|
||||
toast.success(restoration.data.actionSuccess.message);
|
||||
router.refresh();
|
||||
} else {
|
||||
// @ts-ignore
|
||||
toast.error(restoration.data.actionError.message);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const mutationRerunRestore = useMutation({
|
||||
mutationFn: async () => {
|
||||
const restoration = await rerunRestorationAction({
|
||||
restorationId: rowData.id,
|
||||
});
|
||||
// @ts-ignore
|
||||
if (restoration.data.success) {
|
||||
// @ts-ignore
|
||||
toast.success(restoration.data.actionSuccess.message);
|
||||
router.refresh();
|
||||
} else {
|
||||
// @ts-ignore
|
||||
toast.error(restoration.data.actionError.message);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
|
||||
const handleDelete = async () => {
|
||||
await mutationDeleteRestore.mutateAsync();
|
||||
};
|
||||
|
||||
const handleRerunRestore = async () => {
|
||||
await mutationRerunRestore.mutateAsync();
|
||||
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@@ -42,8 +112,26 @@ export const restoreColumns: ColumnDef<Restoration>[] = [
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||
|
||||
<DropdownMenuItem onClick={() => {}}>
|
||||
<ReloadIcon /> Rerun
|
||||
<TooltipCustom disabled={isAlreadyRestore} text="Already a restoration waiting">
|
||||
<DropdownMenuItem
|
||||
disabled={mutationRerunRestore.isPending || isAlreadyRestore}
|
||||
onClick={async () => {
|
||||
await handleRerunRestore();
|
||||
}}
|
||||
>
|
||||
<ReloadIcon/> Rerun
|
||||
</DropdownMenuItem>
|
||||
</TooltipCustom>
|
||||
<DropdownMenuSeparator/>
|
||||
|
||||
<DropdownMenuItem
|
||||
disabled={status == "waiting"}
|
||||
className="text-red-600"
|
||||
onClick={async () => {
|
||||
await handleDelete();
|
||||
}}
|
||||
>
|
||||
<Trash2/> Delete
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
@@ -51,3 +139,5 @@ export const restoreColumns: ColumnDef<Restoration>[] = [
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,43 @@ import { db } from "@/db";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import {Backup, Restoration} from "@/db/schema/06_database";
|
||||
|
||||
export const deleteRestoreAction = userAction
|
||||
.schema(
|
||||
z.object({
|
||||
restorationId: z.string(),
|
||||
})
|
||||
)
|
||||
.action(async ({ parsedInput }): Promise<ServerActionResult<Backup>> => {
|
||||
try {
|
||||
await db
|
||||
.delete(drizzleDb.schemas.restoration)
|
||||
.where(and(eq(drizzleDb.schemas.restoration.id, parsedInput.restorationId)))
|
||||
.execute();
|
||||
|
||||
|
||||
return {
|
||||
success: true,
|
||||
actionSuccess: {
|
||||
message: "Restoration deleted successfully.",
|
||||
},
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
actionError: {
|
||||
message: "Failed to delete restoration.",
|
||||
status: 500,
|
||||
cause: error instanceof Error ? error.message : "Unknown error",
|
||||
messageParams: { message: "Error deleting the restoration" },
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
export const deleteBackupAction = userAction
|
||||
.schema(
|
||||
z.object({
|
||||
@@ -60,6 +97,58 @@ export const deleteBackupAction = userAction
|
||||
});
|
||||
|
||||
|
||||
|
||||
export const rerunRestorationAction = userAction
|
||||
.schema(
|
||||
z.object({
|
||||
restorationId: z.string(),
|
||||
})
|
||||
)
|
||||
.action(async ({ parsedInput }): Promise<ServerActionResult<Restoration>> => {
|
||||
try {
|
||||
const updateResult = await db
|
||||
.update(drizzleDb.schemas.restoration)
|
||||
.set({ status: "waiting" })
|
||||
.where(eq(drizzleDb.schemas.restoration.id, parsedInput.restorationId))
|
||||
.returning()
|
||||
.execute();
|
||||
|
||||
const updatedRestoration = updateResult[0];
|
||||
|
||||
if (!updatedRestoration) {
|
||||
return {
|
||||
success: false,
|
||||
actionError: {
|
||||
message: "Restoration not found.",
|
||||
status: 404,
|
||||
cause: "No restoration with the given ID exists.",
|
||||
messageParams: { message: "Restoration not found" },
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
value: updatedRestoration,
|
||||
actionSuccess: {
|
||||
message: "Restoration has been requeued.",
|
||||
messageParams: { restorationId: updatedRestoration.id },
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
actionError: {
|
||||
message: "Failed to rerun restoration.",
|
||||
status: 500,
|
||||
cause: error instanceof Error ? error.message : "Unknown error",
|
||||
messageParams: { message: "Error updating the restoration" },
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Create Restoration Action (Drizzle version)
|
||||
export const createRestorationAction = userAction
|
||||
.schema(
|
||||
|
||||
Reference in New Issue
Block a user