mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
fix: project details table refresh
This commit is contained in:
@@ -33,7 +33,7 @@ export function DatabaseActionsCell({backup, activeMember, isAlreadyRestore}: Da
|
||||
<div className={cn("flex items-center space-x-2")}>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon">
|
||||
<Button variant="ghost" size="icon" type="button" onClick={(e) => e.stopPropagation()}>
|
||||
<span className="sr-only">Open menu</span>
|
||||
<MoreHorizontal className="w-4 h-4"/>
|
||||
</Button>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client"
|
||||
import {Backup, BackupWith, Restoration} from "@/db/schema/07_database";
|
||||
import React from "react";
|
||||
import {Swiper, SwiperSlide} from "swiper/react";
|
||||
//@ts-ignore
|
||||
import "swiper/css";
|
||||
import "swiper/css/pagination";
|
||||
import {Pagination, Mousewheel} from "swiper/modules";
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
BackupActionsType
|
||||
} from "@/components/wrappers/dashboard/database/backup/actions/backup-actions.schema";
|
||||
import {ButtonWithLoading} from "@/components/wrappers/common/button/button-with-loading";
|
||||
import {useMutation} from "@tanstack/react-query";
|
||||
import {useMutation, useQueryClient} from "@tanstack/react-query";
|
||||
import {BackupStorageWith} from "@/db/schema/14_storage-backup";
|
||||
import {TooltipProvider} from "@/components/ui/tooltip";
|
||||
import {getChannelIcon} from "@/components/wrappers/dashboard/admin/channels/helpers/common";
|
||||
@@ -29,8 +29,7 @@ import {SafeActionResult} from "next-safe-action";
|
||||
import {ServerActionResult} from "@/types/action-type";
|
||||
import {ZodString} from "zod";
|
||||
import {Alert, AlertDescription, AlertTitle} from "@/components/ui/alert";
|
||||
import {AlertCircleIcon, Trash2} from "lucide-react";
|
||||
import {ButtonWithConfirm} from "@/components/wrappers/common/button/button-with-confirm";
|
||||
import {AlertCircleIcon} from "lucide-react";
|
||||
|
||||
type BackupActionsFormProps = {
|
||||
backup: BackupWith;
|
||||
@@ -42,6 +41,7 @@ export const BackupActionsForm = ({backup, action}: BackupActionsFormProps) => {
|
||||
const filteredBackupStorages = backup.storages?.filter((storage) => storage.deletedAt === null) ?? []
|
||||
const isMobile = useIsMobile();
|
||||
const {closeModal} = useBackupModal();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const form = useZodForm({
|
||||
schema: BackupActionsSchema,
|
||||
@@ -74,8 +74,8 @@ export const BackupActionsForm = ({backup, action}: BackupActionsFormProps) => {
|
||||
|
||||
if (inner?.success) {
|
||||
toast.success(inner.actionSuccess?.message);
|
||||
queryClient.invalidateQueries({queryKey: ["database-data", backup.databaseId]});
|
||||
if (action === "download") {
|
||||
console.log(inner.value)
|
||||
const url = inner.value
|
||||
if (typeof url === "string") {
|
||||
window.open(url, "_self");
|
||||
@@ -91,6 +91,7 @@ export const BackupActionsForm = ({backup, action}: BackupActionsFormProps) => {
|
||||
} else {
|
||||
if (action === "delete") {
|
||||
toast.success("Backup deleted successfully.")
|
||||
queryClient.invalidateQueries({queryKey: ["database-data", backup.databaseId]});
|
||||
closeModal()
|
||||
} else {
|
||||
toast.error(inner?.actionError?.message ?? "An error occurred.");
|
||||
@@ -111,6 +112,7 @@ export const BackupActionsForm = ({backup, action}: BackupActionsFormProps) => {
|
||||
|
||||
if (inner?.success) {
|
||||
toast.success(inner.actionSuccess?.message);
|
||||
queryClient.invalidateQueries({queryKey: ["database-data", backup.databaseId]});
|
||||
closeModal()
|
||||
} else {
|
||||
toast.error(inner?.actionError?.message);
|
||||
@@ -130,10 +132,7 @@ export const BackupActionsForm = ({backup, action}: BackupActionsFormProps) => {
|
||||
}}
|
||||
>
|
||||
|
||||
|
||||
{filteredBackupStorages.length > 0 ?
|
||||
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="backupStorageId"
|
||||
@@ -230,35 +229,45 @@ export const BackupActionsForm = ({backup, action}: BackupActionsFormProps) => {
|
||||
// >
|
||||
// Delete entire backup
|
||||
// </ButtonWithLoading>
|
||||
|
||||
|
||||
|
||||
<ButtonWithConfirm
|
||||
title={"Delete entire backup"}
|
||||
description={"Are you sure you want to delete this entire backup?"}
|
||||
button={{
|
||||
main: {
|
||||
type: "button",
|
||||
variant: "destructive",
|
||||
text: "Delete entire backup",
|
||||
},
|
||||
confirm: {
|
||||
className: "w-full",
|
||||
text: "Delete",
|
||||
icon: <Trash2/>,
|
||||
variant: "destructive",
|
||||
onClick: async () => {
|
||||
mutationDeleteEntireBackup.mutateAsync()
|
||||
},
|
||||
},
|
||||
cancel: {
|
||||
className: "w-full",
|
||||
text: "Cancel",
|
||||
icon: <Trash2/>,
|
||||
variant: "outline",
|
||||
},
|
||||
}}
|
||||
<ButtonWithLoading
|
||||
type="button"
|
||||
variant="destructive"
|
||||
onClick={() => mutationDeleteEntireBackup.mutateAsync()}
|
||||
isPending={mutationDeleteEntireBackup.isPending}
|
||||
/>
|
||||
disabled={mutationDeleteEntireBackup.isPending}
|
||||
>
|
||||
Delete entire backup
|
||||
</ButtonWithLoading>
|
||||
|
||||
// <ButtonWithConfirm
|
||||
// title={"Delete entire backup"}
|
||||
// description={"Are you sure you want to delete this entire backup?"}
|
||||
// button={{
|
||||
// main: {
|
||||
// type: "button",
|
||||
// variant: "destructive",
|
||||
// text: "Delete entire backup",
|
||||
// },
|
||||
// confirm: {
|
||||
// className: "w-full",
|
||||
// text: "Delete",
|
||||
// icon: <Trash2/>,
|
||||
// variant: "destructive",
|
||||
// onClick: async () => {
|
||||
// mutationDeleteEntireBackup.mutateAsync()
|
||||
// },
|
||||
// },
|
||||
// cancel: {
|
||||
// className: "w-full",
|
||||
// text: "Cancel",
|
||||
// icon: <Trash2/>,
|
||||
// variant: "outline",
|
||||
// },
|
||||
// }}
|
||||
// isPending={mutationDeleteEntireBackup.isPending}
|
||||
// />
|
||||
|
||||
)}
|
||||
|
||||
|
||||
@@ -57,10 +57,8 @@ export const downloadBackupAction = userAction.schema(
|
||||
}
|
||||
};
|
||||
|
||||
console.log(input)
|
||||
|
||||
const result = await dispatchStorage(input, undefined, backupStorage.storageChannelId);
|
||||
console.log(result);
|
||||
return {
|
||||
success: result.success,
|
||||
value: result.url,
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
"use server"
|
||||
import {userAction} from "@/lib/safe-actions/actions";
|
||||
import {z} from "zod";
|
||||
import {db} from "@/db";
|
||||
import {eq} from "drizzle-orm";
|
||||
import * as drizzleDb from "@/db";
|
||||
import {BackupWith, Restoration} from "@/db/schema/07_database";
|
||||
|
||||
export const getDatabaseDataAction = userAction
|
||||
.schema(
|
||||
z.object({
|
||||
databaseId: z.string(),
|
||||
})
|
||||
)
|
||||
.action(async ({parsedInput}) => {
|
||||
const {databaseId} = parsedInput;
|
||||
|
||||
const database = await db.query.database.findFirst({
|
||||
where: eq(drizzleDb.schemas.database.id, databaseId),
|
||||
with: {
|
||||
project: true,
|
||||
}
|
||||
});
|
||||
|
||||
const backups = await db.query.backup.findMany({
|
||||
where: eq(drizzleDb.schemas.backup.databaseId, databaseId),
|
||||
with: {
|
||||
restorations: true,
|
||||
storages: {
|
||||
with: {
|
||||
storageChannel: true
|
||||
}
|
||||
}
|
||||
},
|
||||
orderBy: (b, {desc}) => [desc(b.createdAt)],
|
||||
}) as BackupWith[];
|
||||
|
||||
const restorations = await db.query.restoration.findMany({
|
||||
where: eq(drizzleDb.schemas.restoration.databaseId, databaseId),
|
||||
orderBy: (r, {desc}) => [desc(r.createdAt)],
|
||||
}) as Restoration[];
|
||||
|
||||
const totalBackups = backups.length;
|
||||
const availableBackups = backups.filter(b => !b.deletedAt).length;
|
||||
const successfulBackups = backups.filter(b => b.status === "success").length;
|
||||
const successRate = totalBackups > 0 ? (successfulBackups / totalBackups) * 100 : null;
|
||||
|
||||
return {
|
||||
database,
|
||||
backups,
|
||||
restorations,
|
||||
stats: {
|
||||
totalBackups,
|
||||
availableBackups,
|
||||
successRate
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import {createContext, useContext, useState, ReactNode} from "react";
|
||||
import {BackupWith} from "@/db/schema/07_database";
|
||||
import {useRouter} from "next/navigation";
|
||||
|
||||
export type DatabaseActionKind = "restore" | "download" | "delete";
|
||||
|
||||
@@ -32,7 +31,6 @@ const BackupModalContext = createContext<BackupModalContextType | undefined>(und
|
||||
|
||||
export const BackupModalProvider = ({children}: { children: ReactNode }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const router = useRouter();
|
||||
const [action, setAction] = useState<DatabaseActionKind | null>(null);
|
||||
const [backup, setBackup] = useState<BackupWith | null>(null);
|
||||
|
||||
@@ -46,7 +44,6 @@ export const BackupModalProvider = ({children}: { children: ReactNode }) => {
|
||||
setOpen(false);
|
||||
setAction(null);
|
||||
setBackup(null);
|
||||
router.refresh()
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user