2026-03-02 11:21:20 +01:00
|
|
|
"use client";
|
2026-06-27 17:08:38 +02:00
|
|
|
import {DatabaseBackupActionsModal} from "@/features/database/components/backup-actions-modal";
|
|
|
|
|
import {DatabaseTabs} from "@/features/database/components/database-tabs";
|
2026-04-24 21:42:20 +02:00
|
|
|
import {Setting} from "@/db/schema/01_setting";
|
2026-06-07 11:15:21 +02:00
|
|
|
import {BackupWith, DatabaseWith, RestorationWith} from "@/db/schema/07_database";
|
2026-04-24 21:42:20 +02:00
|
|
|
import {MemberWithUser} from "@/db/schema/03_organization";
|
2026-06-27 17:08:38 +02:00
|
|
|
import {useBackupModal} from "@/features/database/components/backup-modal-context";
|
|
|
|
|
import {DatabaseKpi} from "@/features/database/components/database-kpi";
|
2026-04-24 21:42:20 +02:00
|
|
|
import {useQuery} from "@tanstack/react-query";
|
2026-06-27 17:08:38 +02:00
|
|
|
import {getDatabaseDataAction} from "@/features/database/actions/backup-get-data.action";
|
2026-03-02 11:21:20 +01:00
|
|
|
import {
|
2026-04-24 21:42:20 +02:00
|
|
|
PageContent,
|
|
|
|
|
PageDescription,
|
|
|
|
|
PageTitle,
|
2026-06-27 17:08:38 +02:00
|
|
|
} from "@/features/layout/components/page";
|
2026-04-24 21:42:20 +02:00
|
|
|
import {capitalizeFirstLetter} from "@/utils/text";
|
2026-06-27 17:08:38 +02:00
|
|
|
import {RetentionPolicySheet} from "@/features/database/components/retention-policy-sheet";
|
|
|
|
|
import {CronButton} from "@/features/database/components/cron-button";
|
|
|
|
|
import {ChannelPoliciesModal} from "@/features/database/components/channels-policy-modal";
|
2026-04-24 21:42:20 +02:00
|
|
|
import {HardDrive, Megaphone} from "lucide-react";
|
2026-06-27 17:08:38 +02:00
|
|
|
import {ImportModal} from "@/features/database/components/import-modal";
|
|
|
|
|
import {BackupButton} from "@/features/database/components/backup-button";
|
|
|
|
|
import {HealthModal} from "@/features/database/components/health-modal";
|
2026-03-28 16:35:02 +01:00
|
|
|
import {HealthcheckLog} from "@/db/schema/15_healthcheck-log";
|
2026-04-29 22:39:37 +02:00
|
|
|
import {Badge} from "@/components/ui/badge";
|
2026-06-27 17:08:38 +02:00
|
|
|
import {LogsModal} from "@/features/logs/components/logs-modal";
|
2026-01-17 15:57:37 +01:00
|
|
|
|
|
|
|
|
export type DatabaseContentProps = {
|
2026-04-24 21:42:20 +02:00
|
|
|
settings: Setting;
|
|
|
|
|
backups: BackupWith[];
|
2026-06-07 11:15:21 +02:00
|
|
|
restorations: RestorationWith[];
|
2026-04-24 21:42:20 +02:00
|
|
|
isAlreadyRestore: boolean;
|
|
|
|
|
database: DatabaseWith;
|
|
|
|
|
activeMember: MemberWithUser;
|
|
|
|
|
totalBackups: number;
|
|
|
|
|
availableBackups: number;
|
|
|
|
|
successRate: number | null;
|
|
|
|
|
organizationId: string;
|
|
|
|
|
activeOrganizationChannels: any[];
|
|
|
|
|
activeOrganizationStorageChannels: any[];
|
|
|
|
|
databaseHealthLogs: HealthcheckLog[]
|
2026-03-02 11:21:20 +01:00
|
|
|
};
|
2026-01-17 15:57:37 +01:00
|
|
|
|
2026-02-10 11:44:45 +01:00
|
|
|
export const DatabaseContent = (props: DatabaseContentProps) => {
|
2026-04-24 21:42:20 +02:00
|
|
|
const {} = useBackupModal();
|
2026-01-17 15:57:37 +01:00
|
|
|
|
2026-04-24 21:42:20 +02:00
|
|
|
const {data} = useQuery({
|
|
|
|
|
queryKey: ["database-data", props.database.id],
|
|
|
|
|
queryFn: async () => {
|
|
|
|
|
const result = await getDatabaseDataAction({
|
|
|
|
|
databaseId: props.database.id,
|
|
|
|
|
});
|
|
|
|
|
return result?.data;
|
|
|
|
|
},
|
|
|
|
|
initialData: {
|
|
|
|
|
// TODO : to be patched
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
database: {
|
|
|
|
|
...props.database,
|
|
|
|
|
project: props.database.project ?? null,
|
|
|
|
|
},
|
|
|
|
|
backups: props.backups,
|
|
|
|
|
restorations: props.restorations,
|
|
|
|
|
activeOrganizationChannels: props.activeOrganizationChannels,
|
|
|
|
|
activeOrganizationStorageChannels:
|
|
|
|
|
props.activeOrganizationStorageChannels,
|
|
|
|
|
stats: {
|
|
|
|
|
totalBackups: props.totalBackups,
|
|
|
|
|
availableBackups: props.availableBackups,
|
|
|
|
|
successRate: props.successRate,
|
|
|
|
|
},
|
|
|
|
|
health: props.databaseHealthLogs
|
|
|
|
|
},
|
|
|
|
|
staleTime: 0,
|
|
|
|
|
gcTime: 0,
|
|
|
|
|
refetchInterval: 1000,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const database = data?.database ?? props.database;
|
|
|
|
|
const backups = data?.backups ?? props.backups;
|
|
|
|
|
const restorations = data?.restorations ?? props.restorations;
|
|
|
|
|
const activeOrganizationChannels =
|
|
|
|
|
data?.activeOrganizationChannels ?? props.activeOrganizationChannels;
|
|
|
|
|
const activeOrganizationStorageChannels =
|
|
|
|
|
data?.activeOrganizationStorageChannels ??
|
|
|
|
|
props.activeOrganizationStorageChannels;
|
|
|
|
|
const stats = data?.stats ?? {
|
2026-02-10 11:44:45 +01:00
|
|
|
totalBackups: props.totalBackups,
|
|
|
|
|
availableBackups: props.availableBackups,
|
2026-03-02 11:21:20 +01:00
|
|
|
successRate: props.successRate,
|
2026-04-24 21:42:20 +02:00
|
|
|
};
|
2026-02-10 11:44:45 +01:00
|
|
|
|
2026-04-24 21:42:20 +02:00
|
|
|
const isAlreadyRestore = restorations.some((r) => r.status === "waiting");
|
|
|
|
|
const isAlreadyBackup = backups.some(
|
|
|
|
|
(b) => b.status === "waiting" || b.status === "ongoing",
|
|
|
|
|
);
|
2026-02-10 11:44:45 +01:00
|
|
|
|
2026-04-24 21:42:20 +02:00
|
|
|
const isMember = props.activeMember.role === "member";
|
2026-02-10 11:44:45 +01:00
|
|
|
|
2026-04-24 21:42:20 +02:00
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<div className="justify-between gap-2 sm:flex">
|
|
|
|
|
<PageTitle className="flex flex-col md:flex-row items-center justify-between w-full ">
|
2026-04-29 22:39:37 +02:00
|
|
|
<div className="flex min-w-full md:min-w-fit justify-between gap-2 items-center ">
|
2026-04-24 21:42:20 +02:00
|
|
|
{capitalizeFirstLetter(database.name)}
|
2026-04-29 22:39:37 +02:00
|
|
|
<div className=" flex items-center justify-center">
|
|
|
|
|
<Badge variant="outline" className="bg-orange-400/10 border-orange-600/50 text-orange-600">
|
|
|
|
|
{database.dbms}
|
|
|
|
|
</Badge>
|
|
|
|
|
</div>
|
2026-04-24 21:42:20 +02:00
|
|
|
</div>
|
|
|
|
|
{!isMember && (
|
|
|
|
|
<div className="flex items-center gap-2 md:justify-between w-full ">
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<RetentionPolicySheet database={database}/>
|
|
|
|
|
<CronButton database={database}/>
|
|
|
|
|
<ChannelPoliciesModal
|
|
|
|
|
database={database}
|
|
|
|
|
kind={"notification"}
|
|
|
|
|
icon={<Megaphone/>}
|
|
|
|
|
channels={activeOrganizationChannels}
|
|
|
|
|
organizationId={props.organizationId}
|
|
|
|
|
/>
|
|
|
|
|
<ChannelPoliciesModal
|
|
|
|
|
database={database}
|
|
|
|
|
icon={<HardDrive/>}
|
|
|
|
|
kind={"storage"}
|
|
|
|
|
channels={activeOrganizationStorageChannels}
|
|
|
|
|
organizationId={props.organizationId}
|
|
|
|
|
/>
|
2026-07-05 16:33:28 +02:00
|
|
|
{database.dbms != "docker-volume" && (
|
|
|
|
|
<ImportModal database={database}/>
|
|
|
|
|
)}
|
2026-04-24 21:42:20 +02:00
|
|
|
<HealthModal database={database} healthLogs={data?.health ?? []}/>
|
|
|
|
|
</div>
|
2026-03-28 16:35:02 +01:00
|
|
|
|
|
|
|
|
|
2026-04-24 21:42:20 +02:00
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<BackupButton
|
|
|
|
|
disable={isAlreadyBackup || !database.lastContact}
|
|
|
|
|
databaseId={database.id}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</PageTitle>
|
2026-02-10 11:44:45 +01:00
|
|
|
</div>
|
|
|
|
|
|
2026-04-24 21:42:20 +02:00
|
|
|
{database.description && (
|
|
|
|
|
<PageDescription className="mt-5 sm:mt-0">
|
|
|
|
|
{database.description}
|
|
|
|
|
</PageDescription>
|
|
|
|
|
)}
|
2026-02-10 11:44:45 +01:00
|
|
|
|
2026-04-24 21:42:20 +02:00
|
|
|
<PageContent className="flex flex-col w-full h-full">
|
|
|
|
|
<DatabaseKpi
|
|
|
|
|
successRate={stats.successRate}
|
|
|
|
|
database={database}
|
|
|
|
|
availableBackups={stats.availableBackups}
|
|
|
|
|
totalBackups={stats.totalBackups}
|
|
|
|
|
/>
|
2026-06-06 22:46:36 +02:00
|
|
|
<LogsModal/>
|
2026-04-24 21:42:20 +02:00
|
|
|
<DatabaseBackupActionsModal/>
|
|
|
|
|
<DatabaseTabs
|
|
|
|
|
activeMember={props.activeMember}
|
|
|
|
|
settings={props.settings}
|
|
|
|
|
database={database}
|
|
|
|
|
isAlreadyRestore={isAlreadyRestore}
|
|
|
|
|
backups={backups}
|
|
|
|
|
restorations={restorations}
|
|
|
|
|
/>
|
|
|
|
|
</PageContent>
|
|
|
|
|
</>
|
|
|
|
|
);
|
2026-03-02 11:21:20 +01:00
|
|
|
};
|