mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
migration
This commit is contained in:
@@ -1,42 +1,29 @@
|
||||
import {PageParams} from "@/types/next";
|
||||
|
||||
import {Page, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
|
||||
import {requiredCurrentUser} from "@/auth/current-user";
|
||||
import {prisma} from "@/prisma";
|
||||
import {AdminTabs} from "@/components/wrappers/dashboard/admin/admin-tabs";
|
||||
import { PageParams } from "@/types/next";
|
||||
|
||||
import { Page, PageContent, PageHeader, PageTitle } from "@/features/layout/page";
|
||||
import { AdminTabs } from "@/components/wrappers/dashboard/admin/admin-tabs";
|
||||
import { currentUser } from "@/lib/auth/current-user";
|
||||
import { db } from "@/db";
|
||||
|
||||
export default async function RoutePage(props: PageParams<{}>) {
|
||||
const user = await currentUser()!;
|
||||
|
||||
const users = await db.query.user.findMany({
|
||||
where: (fields, { isNull, not }) => not(isNull(fields.deletedAt)),
|
||||
});
|
||||
|
||||
const user = await requiredCurrentUser()
|
||||
|
||||
const users = await prisma.user.findMany({
|
||||
where: {
|
||||
// id: {
|
||||
// not: user.id
|
||||
// },
|
||||
deleted: {not: true},
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
const settings = await prisma.settings.findUnique({
|
||||
where: {
|
||||
name: "system"
|
||||
}
|
||||
})
|
||||
const settings = await db.query.setting.findFirst({
|
||||
where: (fields, { eq }) => eq(fields.name, "system"),
|
||||
});
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<PageHeader>
|
||||
<PageTitle>
|
||||
Administration Panel
|
||||
</PageTitle>
|
||||
<PageTitle>Administration Panel</PageTitle>
|
||||
</PageHeader>
|
||||
<PageContent className="mt-10">
|
||||
<AdminTabs settings={settings} currentUser={user} users={users}/>
|
||||
<AdminTabs settings={settings!} currentUser={user} users={users} />
|
||||
</PageContent>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import {PageParams} from "@/types/next";
|
||||
import {Page, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
|
||||
import {AgentForm} from "@/components/wrappers/dashboard/agent/AgentForm/AgentForm";
|
||||
import {prisma} from "@/prisma";
|
||||
import {notFound} from "next/navigation";
|
||||
import { PageParams } from "@/types/next";
|
||||
import { Page, PageContent, PageHeader, PageTitle } from "@/features/layout/page";
|
||||
import { AgentForm } from "@/components/wrappers/dashboard/agent/AgentForm/AgentForm";
|
||||
import { notFound } from "next/navigation";
|
||||
import { db } from "@/db";
|
||||
|
||||
export default async function RoutePage(
|
||||
props: PageParams<{
|
||||
agentId: string;
|
||||
}>
|
||||
) {
|
||||
const { agentId } = await props.params;
|
||||
|
||||
export default async function RoutePage(props: PageParams<{
|
||||
agentId: string;
|
||||
}>) {
|
||||
|
||||
const {agentId} = await props.params
|
||||
const agent = await prisma.agent.findUnique({
|
||||
where: {
|
||||
id: agentId,
|
||||
}
|
||||
const agent = await db.query.agent.findFirst({
|
||||
where: (fields, { eq }) => eq(fields.id, agentId),
|
||||
});
|
||||
|
||||
if (!agent) {
|
||||
@@ -23,13 +22,11 @@ export default async function RoutePage(props: PageParams<{
|
||||
return (
|
||||
<Page>
|
||||
<PageHeader>
|
||||
<PageTitle>
|
||||
Edit {agent.name}
|
||||
</PageTitle>
|
||||
<PageTitle>Edit {agent.name}</PageTitle>
|
||||
</PageHeader>
|
||||
<PageContent>
|
||||
<AgentForm defaultValues={agent} agentId={agent.id}/>
|
||||
<AgentForm defaultValues={agent} agentId={agent.id} />
|
||||
</PageContent>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,28 +1,16 @@
|
||||
import {PageParams} from "@/types/next";
|
||||
import {Page, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
|
||||
import {AgentForm} from "@/components/wrappers/dashboard/agent/AgentForm/AgentForm";
|
||||
import {currentUser} from "@/auth/current-user";
|
||||
import {notFound} from "next/navigation";
|
||||
|
||||
import { PageParams } from "@/types/next";
|
||||
import { Page, PageContent, PageHeader, PageTitle } from "@/features/layout/page";
|
||||
import { AgentForm } from "@/components/wrappers/dashboard/agent/AgentForm/AgentForm";
|
||||
|
||||
export default async function RoutePage(props: PageParams<{}>) {
|
||||
|
||||
const user = await currentUser();
|
||||
|
||||
if(user.role != "admin"){
|
||||
notFound()
|
||||
}
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<PageHeader>
|
||||
<PageTitle>
|
||||
Create new agent
|
||||
</PageTitle>
|
||||
<PageTitle>Create new agent</PageTitle>
|
||||
</PageHeader>
|
||||
<PageContent>
|
||||
<AgentForm/>
|
||||
<AgentForm />
|
||||
</PageContent>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,29 +1,24 @@
|
||||
import {PageParams} from "@/types/next";
|
||||
import {AgentCard} from "@/components/wrappers/dashboard/agent/AgentCard/AgentCard";
|
||||
import {CardsWithPagination} from "@/components/wrappers/common/cards-with-pagination";
|
||||
import {Button} from "@/components/ui/button";
|
||||
import Link from 'next/link'
|
||||
import {Page, PageActions, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
|
||||
import {prisma} from "@/prisma";
|
||||
import {notFound} from "next/navigation";
|
||||
import { PageParams } from "@/types/next";
|
||||
import { AgentCard } from "@/components/wrappers/dashboard/agent/AgentCard/AgentCard";
|
||||
import { CardsWithPagination } from "@/components/wrappers/common/cards-with-pagination";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import Link from "next/link";
|
||||
import { Page, PageActions, PageContent, PageHeader, PageTitle } from "@/features/layout/page";
|
||||
import { notFound } from "next/navigation";
|
||||
import { db } from "@/db";
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
|
||||
export default async function RoutePage(props: PageParams<{}>) {
|
||||
const agents = await db.query.agent.findMany();
|
||||
|
||||
const agents = await prisma.agent.findMany()
|
||||
|
||||
if(!agents){
|
||||
notFound()
|
||||
if (!agents) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<PageHeader>
|
||||
<PageTitle>
|
||||
Agents
|
||||
</PageTitle>
|
||||
<PageTitle>Agents</PageTitle>
|
||||
{agents.length > 0 && (
|
||||
<PageActions>
|
||||
<Link href={"/dashboard/agents/new"}>
|
||||
@@ -33,21 +28,17 @@ export default async function RoutePage(props: PageParams<{}>) {
|
||||
)}
|
||||
</PageHeader>
|
||||
<PageContent className="mt-10">
|
||||
{agents.length > 0 ?
|
||||
<CardsWithPagination
|
||||
data={agents}
|
||||
cardItem={AgentCard}
|
||||
cardsPerPage={4}
|
||||
numberOfColumns={1}
|
||||
/>
|
||||
:
|
||||
{agents.length > 0 ? (
|
||||
<CardsWithPagination data={agents} cardItem={AgentCard} cardsPerPage={4} numberOfColumns={1} />
|
||||
) : (
|
||||
<Link
|
||||
href={"/dashboard/agents/new"}
|
||||
className=" flex item-center justify-center border-2 border-dashed transition-colors border-primary p-8 lg:p-12 w-full rounded-md">
|
||||
className=" flex item-center justify-center border-2 border-dashed transition-colors border-primary p-8 lg:p-12 w-full rounded-md"
|
||||
>
|
||||
Create new Agent
|
||||
</Link>
|
||||
}
|
||||
)}
|
||||
</PageContent>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
import React from "react";
|
||||
import {currentUser, requiredCurrentUser} from "@/auth/current-user";
|
||||
import {notFound} from "next/navigation";
|
||||
import { notFound } from "next/navigation";
|
||||
import { currentUser } from "@/lib/auth/current-user";
|
||||
|
||||
export default async function Layout({children}: { children: React.ReactNode }) {
|
||||
export default async function Layout({ children }: { children: React.ReactNode }) {
|
||||
const user = await currentUser();
|
||||
|
||||
const user = await requiredCurrentUser()
|
||||
|
||||
if(user.role != "admin"){
|
||||
notFound()
|
||||
if (user!.role !== "superadmin" && user!.role !== "admin") {
|
||||
notFound();
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
@@ -1,55 +1,41 @@
|
||||
import {PageParams} from "@/types/next";
|
||||
import {Page, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
|
||||
import {requiredCurrentUser} from "@/auth/current-user";
|
||||
import {prisma} from "@/prisma";
|
||||
import {notFound} from "next/navigation";
|
||||
import {RestoreForm} from "@/components/wrappers/dashboard/database/RestoreForm";
|
||||
import { PageParams } from "@/types/next";
|
||||
import { Page, PageContent, PageHeader, PageTitle } from "@/features/layout/page";
|
||||
import { notFound } from "next/navigation";
|
||||
import { RestoreForm } from "@/components/wrappers/dashboard/database/RestoreForm";
|
||||
import { currentUser } from "@/lib/auth/current-user";
|
||||
|
||||
import { db } from "@/db";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { database, backup } from "@/db/schema";
|
||||
|
||||
export default async function RoutePage(props: PageParams<{
|
||||
databaseId: string;
|
||||
}>) {
|
||||
export default async function RoutePage(
|
||||
props: PageParams<{
|
||||
databaseId: string;
|
||||
}>
|
||||
) {
|
||||
const { databaseId } = await props.params;
|
||||
|
||||
const {databaseId} = await props.params
|
||||
const user = await currentUser();
|
||||
if (!user) notFound();
|
||||
|
||||
const [dbToRestore] = await db.select().from(database).where(eq(database.id, databaseId));
|
||||
|
||||
const user = await requiredCurrentUser()
|
||||
|
||||
const database = await prisma.database.findUnique({
|
||||
where: {
|
||||
id: databaseId,
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const databases = await prisma.database.findMany({
|
||||
where: {
|
||||
dbms: database.dbms,
|
||||
}
|
||||
})
|
||||
|
||||
const backups = await prisma.backup.findMany({
|
||||
where: {
|
||||
status: "success",
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (!database) {
|
||||
if (!dbToRestore) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const dbsOfSameType = await db.select().from(database).where(eq(database.dbms!, dbToRestore.dbms!));
|
||||
|
||||
const successfulBackups = await db.select().from(backup).where(eq(backup.status, "success"));
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<PageHeader>
|
||||
<PageTitle>
|
||||
Restore {database.name}
|
||||
</PageTitle>
|
||||
<PageTitle>Restore {dbToRestore.name}</PageTitle>
|
||||
</PageHeader>
|
||||
<PageContent>
|
||||
<RestoreForm databaseToRestore={database} databases={databases} backups={backups}/>
|
||||
<RestoreForm databaseToRestore={dbToRestore} databases={dbsOfSameType} backups={successfulBackups} />
|
||||
</PageContent>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
import {PageParams} from "@/types/next";
|
||||
import {redirect} from "next/navigation";
|
||||
"use client";
|
||||
import { authClient } from "@/lib/auth/auth-client";
|
||||
import { PageParams } from "@/types/next";
|
||||
|
||||
export default async function RoutePage(props: PageParams<{}>) {
|
||||
export default function RoutePage(props: PageParams<{}>) {
|
||||
const { data: activeOrganization } = authClient.useActiveOrganization();
|
||||
|
||||
|
||||
// return (
|
||||
// <div className="flex flex-1 flex-col gap-4 p-4">
|
||||
// <div className="grid auto-rows-min gap-4 md:grid-cols-3">
|
||||
// <div className="aspect-video rounded-xl bg-muted/50"/>
|
||||
// <div className="aspect-video rounded-xl bg-muted/50"/>
|
||||
// <div className="aspect-video rounded-xl bg-muted/50"/>
|
||||
// </div>
|
||||
// <div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min"/>
|
||||
// </div>
|
||||
// )
|
||||
}
|
||||
return (
|
||||
<div className="flex flex-1 flex-col gap-4 p-4">
|
||||
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
|
||||
<div className="aspect-video rounded-xl bg-muted/50" />
|
||||
<div className="aspect-video rounded-xl bg-muted/50" />
|
||||
<div className="aspect-video rounded-xl bg-muted/50" />
|
||||
</div>
|
||||
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min" />
|
||||
{JSON.stringify(activeOrganization)}
|
||||
{activeOrganization?.name}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+19
-24
@@ -1,39 +1,34 @@
|
||||
import {PageParams} from "@/types/next";
|
||||
import {Page, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
|
||||
import {requiredCurrentUser} from "@/auth/current-user";
|
||||
import {prisma} from "@/prisma";
|
||||
import {notFound} from "next/navigation";
|
||||
import {DatabaseForm} from "@/components/wrappers/dashboard/database/DatabaseForm/DatabaseForm";
|
||||
import { PageParams } from "@/types/next";
|
||||
import { Page, PageContent, PageHeader, PageTitle } from "@/features/layout/page";
|
||||
import { notFound } from "next/navigation";
|
||||
import { DatabaseForm } from "@/components/wrappers/dashboard/database/DatabaseForm/DatabaseForm";
|
||||
|
||||
import { db } from "@/db";
|
||||
import { database } from "@/db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
export default async function RoutePage(props: PageParams<{
|
||||
databaseId: string;
|
||||
}>) {
|
||||
export default async function RoutePage(props: PageParams<{ databaseId: string }>) {
|
||||
const { databaseId } = await props.params;
|
||||
|
||||
const {databaseId} = await props.params
|
||||
|
||||
const user = await requiredCurrentUser()
|
||||
const database = await prisma.database.findUnique({
|
||||
where: {
|
||||
id: databaseId,
|
||||
}
|
||||
const dbItem = await db.query.database.findFirst({
|
||||
where: eq(database.id, databaseId),
|
||||
});
|
||||
|
||||
if (!database) {
|
||||
if (!dbItem) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<PageHeader>
|
||||
<PageTitle>
|
||||
Edit {database.name}
|
||||
</PageTitle>
|
||||
<PageTitle>Edit {dbItem.name}</PageTitle>
|
||||
</PageHeader>
|
||||
<PageContent>
|
||||
<DatabaseForm databaseId={databaseId} defaultValues={database}/>
|
||||
<DatabaseForm
|
||||
databaseId={databaseId}
|
||||
defaultValues={{ ...dbItem, dbms: dbItem.dbms ?? "inactive", description: dbItem.description ?? undefined }}
|
||||
/>
|
||||
</PageContent>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
+54
-70
@@ -1,91 +1,75 @@
|
||||
import {PageParams} from "@/types/next";
|
||||
import {prisma} from "@/prisma";
|
||||
import {notFound} from "next/navigation";
|
||||
import {Page, PageActions, PageContent, PageDescription, PageTitle} from "@/features/layout/page";
|
||||
import {BackupButton} from "@/components/wrappers/dashboard/backup/backup-button/backup-button";
|
||||
import {DatabaseTabs} from "@/components/wrappers/dashboard/projects/Database/DatabaseTabs";
|
||||
import {DatabaseKpi} from "@/components/wrappers/dashboard/projects/Database/DatabaseKpi";
|
||||
import {EditButton} from "@/components/wrappers/dashboard/database/EditButton/EditButton";
|
||||
import {CronButton} from "@/components/wrappers/dashboard/database/CronButton/CronButton";
|
||||
import { PageParams } from "@/types/next";
|
||||
import { notFound } from "next/navigation";
|
||||
import { Page, PageActions, PageContent, PageDescription, PageTitle } from "@/features/layout/page";
|
||||
import { BackupButton } from "@/components/wrappers/dashboard/backup/backup-button/backup-button";
|
||||
import { DatabaseTabs } from "@/components/wrappers/dashboard/projects/Database/DatabaseTabs";
|
||||
import { DatabaseKpi } from "@/components/wrappers/dashboard/projects/Database/DatabaseKpi";
|
||||
import { EditButton } from "@/components/wrappers/dashboard/database/EditButton/EditButton";
|
||||
import { CronButton } from "@/components/wrappers/dashboard/database/CronButton/CronButton";
|
||||
|
||||
import { db } from "@/db";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import { backup as drizzleBackup, database as drizzleDatabase, restoration as drizzleRestoration } from "@/db/schema";
|
||||
|
||||
export default async function RoutePage(props: PageParams<{ databaseId: string }>) {
|
||||
const { databaseId } = await props.params;
|
||||
|
||||
const {databaseId} = await props.params
|
||||
const database = await prisma.database.findUnique({
|
||||
where: {
|
||||
id: databaseId,
|
||||
},
|
||||
})
|
||||
if (!database) {
|
||||
notFound()
|
||||
const dbItem = await db.query.database.findFirst({
|
||||
where: eq(drizzleDatabase.id, databaseId),
|
||||
});
|
||||
|
||||
if (!dbItem) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
|
||||
const backups = await prisma.backup.findMany({
|
||||
where: {
|
||||
databaseId: database.id
|
||||
},
|
||||
include:{
|
||||
restorations: {}
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "desc"
|
||||
}
|
||||
})
|
||||
|
||||
const restorations = await prisma.restoration.findMany({
|
||||
where: {
|
||||
databaseId: databaseId,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "desc"
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const isAlreadyBackup = !!backups.find(backup => backup.status === "waiting");
|
||||
const isAlreadyRestore = !!restorations.find(restoration => restoration.status === "waiting");
|
||||
|
||||
const totalBackups = await prisma.backup.count({
|
||||
where: {
|
||||
databaseId: databaseId,
|
||||
const backups = await db.query.backup.findMany({
|
||||
where: eq(drizzleBackup.databaseId, dbItem.id),
|
||||
with: {
|
||||
restorations: true,
|
||||
},
|
||||
orderBy: (b, { desc }) => [desc(b.createdAt)],
|
||||
});
|
||||
const successfulBackups = await prisma.backup.count({
|
||||
where: {
|
||||
databaseId: databaseId,
|
||||
status: 'success',
|
||||
},
|
||||
|
||||
const restorations = await db.query.restoration.findMany({
|
||||
where: eq(drizzleRestoration.databaseId, dbItem.id),
|
||||
orderBy: (r, { desc }) => [desc(r.createdAt)],
|
||||
});
|
||||
const successRate = totalBackups > 0 ? (successfulBackups / totalBackups) * 100 : null
|
||||
|
||||
const isAlreadyBackup = backups.some((b) => b.status === "waiting");
|
||||
const isAlreadyRestore = restorations.some((r) => r.status === "waiting");
|
||||
|
||||
const [totalBackups, successfulBackups] = await Promise.all([
|
||||
db
|
||||
.select({ count: drizzleBackup.id })
|
||||
.from(drizzleBackup)
|
||||
.where(eq(drizzleBackup.databaseId, dbItem.id))
|
||||
.then((rows) => rows.length),
|
||||
db
|
||||
.select({ count: drizzleBackup.id })
|
||||
.from(drizzleBackup)
|
||||
.where(and(eq(drizzleBackup.databaseId, dbItem.id), eq(drizzleBackup.status, "success")))
|
||||
.then((rows) => rows.length),
|
||||
]);
|
||||
|
||||
const successRate = totalBackups > 0 ? (successfulBackups / totalBackups) * 100 : null;
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<div className="justify-between gap-2 sm:flex">
|
||||
<PageTitle className="flex items-center">
|
||||
{database.name}
|
||||
<EditButton/>
|
||||
<CronButton database={database}/>
|
||||
{dbItem.name}
|
||||
<EditButton />
|
||||
<CronButton database={dbItem} />
|
||||
</PageTitle>
|
||||
<PageActions className="justify-between">
|
||||
<BackupButton disable={isAlreadyBackup} databaseId={databaseId}/>
|
||||
<BackupButton disable={isAlreadyBackup} databaseId={databaseId} />
|
||||
</PageActions>
|
||||
</div>
|
||||
<PageDescription className="mt-5 sm:mt-0">{database.description}</PageDescription>
|
||||
<PageDescription className="mt-5 sm:mt-0">{dbItem.description}</PageDescription>
|
||||
<PageContent className="flex flex-col w-full h-full">
|
||||
<DatabaseKpi
|
||||
successRate={successRate}
|
||||
database={database}
|
||||
totalBackups={totalBackups}
|
||||
/>
|
||||
<DatabaseTabs
|
||||
database={database}
|
||||
isAlreadyRestore={isAlreadyRestore}
|
||||
backups={backups}
|
||||
restorations={restorations}
|
||||
/>
|
||||
<DatabaseKpi successRate={successRate} database={dbItem} totalBackups={totalBackups} />
|
||||
<DatabaseTabs database={dbItem} isAlreadyRestore={isAlreadyRestore} backups={backups} restorations={restorations} />
|
||||
</PageContent>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,61 +1,61 @@
|
||||
import {notFound} from "next/navigation";
|
||||
import { notFound } from "next/navigation";
|
||||
import { PageParams } from "@/types/next";
|
||||
import { Page, PageContent, PageHeader, PageTitle } from "@/features/layout/page";
|
||||
import { ProjectForm } from "@/components/wrappers/dashboard/projects/ProjectsForm/ProjectForm";
|
||||
|
||||
import {PageParams} from "@/types/next";
|
||||
import {Page, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
|
||||
import {prisma} from "@/prisma";
|
||||
import {ProjectForm} from "@/components/wrappers/dashboard/projects/ProjectsForm/ProjectForm";
|
||||
import { db } from "@/db";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { project as drizzleProject, organization as drizzleOrganization, DatabaseWith } from "@/db/schema";
|
||||
|
||||
export default async function RoutePage(props: PageParams<{ projectId: string }>) {
|
||||
const { projectId } = await props.params;
|
||||
|
||||
export default async function RoutePage(props: PageParams<{
|
||||
projectId: string;
|
||||
}>) {
|
||||
|
||||
const {projectId} = await props.params
|
||||
|
||||
const project = await prisma.project.findUnique({
|
||||
where: {
|
||||
id: projectId,
|
||||
const proj = await db.query.project.findFirst({
|
||||
where: eq(drizzleProject.id, projectId),
|
||||
with: {
|
||||
databases: true,
|
||||
},
|
||||
include: {
|
||||
databases: {}
|
||||
}
|
||||
});
|
||||
|
||||
if (!project) {
|
||||
if (!proj) {
|
||||
notFound();
|
||||
}
|
||||
const organization = await prisma.organization.findFirst({
|
||||
where: {
|
||||
slug: 'default',
|
||||
}
|
||||
})
|
||||
const availableDatabases = await prisma.database.findMany({
|
||||
where: {
|
||||
OR: [
|
||||
{projectId: null},
|
||||
{projectId: project.id},
|
||||
],
|
||||
},
|
||||
include: {
|
||||
agent: {}
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
})
|
||||
|
||||
//
|
||||
const org = await db.query.organization.findFirst({
|
||||
where: eq(drizzleOrganization.slug, "default"),
|
||||
});
|
||||
|
||||
if (!org) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const availableDatabases = (
|
||||
await db.query.database.findMany({
|
||||
where: (db, { or, eq, isNull }) => or(isNull(db.projectId), eq(db.projectId, proj.id)),
|
||||
with: {
|
||||
agent: true,
|
||||
project: true,
|
||||
backups: true,
|
||||
restorations: true,
|
||||
},
|
||||
orderBy: (db, { desc }) => [desc(db.createdAt)],
|
||||
})
|
||||
).filter((db): db is DatabaseWith => db.project !== null);
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<PageHeader>
|
||||
<PageTitle>
|
||||
Edit {project.name}
|
||||
</PageTitle>
|
||||
<PageTitle>Edit {proj.name}</PageTitle>
|
||||
</PageHeader>
|
||||
<PageContent>
|
||||
<ProjectForm organization={organization} databases={availableDatabases} defaultValues={project}
|
||||
projectId={project.id}/>
|
||||
<ProjectForm
|
||||
organization={org}
|
||||
databases={availableDatabases}
|
||||
defaultValues={{ name: proj.name, slug: proj.slug, databases: proj.databases.map((db) => db.id) }}
|
||||
projectId={proj.id}
|
||||
/>
|
||||
</PageContent>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,77 +1,70 @@
|
||||
import {PageParams} from "@/types/next";
|
||||
import {Page, PageActions, PageContent, PageDescription, PageTitle} from "@/features/layout/page";
|
||||
import {buttonVariants} from "@/components/ui/button";
|
||||
import {prisma} from "@/prisma";
|
||||
import {GearIcon} from "@radix-ui/react-icons";
|
||||
import { PageParams } from "@/types/next";
|
||||
import { Page, PageActions, PageContent, PageDescription, PageTitle } from "@/features/layout/page";
|
||||
import { buttonVariants } from "@/components/ui/button";
|
||||
import { GearIcon } from "@radix-ui/react-icons";
|
||||
import Link from "next/link";
|
||||
import {ButtonDeleteProject} from "@/components/wrappers/dashboard/projects/ButtonDeleteProject/ButtonDeleteProject";
|
||||
import {CardsWithPagination} from "@/components/wrappers/common/cards-with-pagination";
|
||||
import {ProjectDatabaseCard} from "@/components/wrappers/dashboard/projects/ProjectCard/ProjectDatabaseCard";
|
||||
import {notFound} from "next/navigation";
|
||||
import {getCurrentOrganizationSlug} from "@/features/dashboard/organization-cookie";
|
||||
import { ButtonDeleteProject } from "@/components/wrappers/dashboard/projects/ButtonDeleteProject/ButtonDeleteProject";
|
||||
import { CardsWithPagination } from "@/components/wrappers/common/cards-with-pagination";
|
||||
import { ProjectDatabaseCard } from "@/components/wrappers/dashboard/projects/ProjectCard/ProjectDatabaseCard";
|
||||
import { notFound } from "next/navigation";
|
||||
import { getCurrentOrganizationSlug } from "@/features/dashboard/organization-cookie";
|
||||
|
||||
import { db } from "@/db";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { organization as drizzleOrganization } from "@/db/schema";
|
||||
|
||||
export default async function RoutePage(props: PageParams<{ slug:string, projectId: string }>) {
|
||||
export default async function RoutePage(props: PageParams<{ slug: string; projectId: string }>) {
|
||||
const { slug: organizationSlug, projectId } = await props.params;
|
||||
|
||||
const {slug: organizationSlug, projectId} = await props.params
|
||||
const currentOrganizationSlug = await getCurrentOrganizationSlug();
|
||||
|
||||
|
||||
const currentOrganizationSlug = await getCurrentOrganizationSlug()
|
||||
|
||||
if(currentOrganizationSlug != organizationSlug) {
|
||||
notFound()
|
||||
if (currentOrganizationSlug !== organizationSlug) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const org = await db.query.organization.findFirst({
|
||||
where: eq(drizzleOrganization.slug, currentOrganizationSlug),
|
||||
});
|
||||
|
||||
if (!org) notFound();
|
||||
|
||||
const project = await prisma.project.findUnique({
|
||||
where: {
|
||||
id: projectId,
|
||||
isArchived: {not: true}
|
||||
const proj = await db.query.project.findFirst({
|
||||
where: (proj, { and, eq, not }) => and(eq(proj.id, projectId), eq(proj.organizationId, org.id), not(eq(proj.isArchived, true))),
|
||||
with: {
|
||||
databases: true,
|
||||
},
|
||||
include:{
|
||||
databases: {}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
if(!project){
|
||||
notFound()
|
||||
}
|
||||
if (!proj) notFound();
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<div className="justify-between gap-2 sm:flex">
|
||||
<PageTitle className="flex items-center">
|
||||
{project.name}
|
||||
<Link className={buttonVariants({variant: "outline"})}
|
||||
href={`/dashboard/${currentOrganizationSlug}/projects/${project.id}/edit`}>
|
||||
<GearIcon className="w-7 h-7"/>
|
||||
{proj.name}
|
||||
<Link className={buttonVariants({ variant: "outline" })} href={`/dashboard/${currentOrganizationSlug}/projects/${proj.id}/edit`}>
|
||||
<GearIcon className="w-7 h-7" />
|
||||
</Link>
|
||||
</PageTitle>
|
||||
<PageActions className="justify-between">
|
||||
<ButtonDeleteProject
|
||||
projectId={projectId}
|
||||
text={"Delete Project"}
|
||||
/>
|
||||
<ButtonDeleteProject projectId={projectId} text={"Delete Project"} />
|
||||
</PageActions>
|
||||
</div>
|
||||
<PageDescription>
|
||||
The list of associated databases
|
||||
</PageDescription>
|
||||
|
||||
<PageDescription>The list of associated databases</PageDescription>
|
||||
|
||||
<PageContent className="flex flex-col w-full h-full">
|
||||
{project.databases.length > 0 ?
|
||||
{proj.databases.length > 0 ? (
|
||||
<CardsWithPagination
|
||||
data={project.databases}
|
||||
data={proj.databases}
|
||||
organizationSlug={organizationSlug}
|
||||
cardItem={ProjectDatabaseCard}
|
||||
cardsPerPage={4}
|
||||
numberOfColumns={1}
|
||||
extendedProps={project}
|
||||
extendedProps={proj}
|
||||
/>
|
||||
:
|
||||
null
|
||||
}
|
||||
) : null}
|
||||
</PageContent>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
import {PageParams} from "@/types/next";
|
||||
import {Page, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
|
||||
import {prisma} from "@/prisma";
|
||||
import {ProjectForm} from "@/components/wrappers/dashboard/projects/ProjectsForm/ProjectForm";
|
||||
import {notFound} from "next/navigation";
|
||||
import {getCurrentOrganizationSlug} from "@/features/dashboard/organization-cookie";
|
||||
import { PageParams } from "@/types/next";
|
||||
import { Page, PageContent, PageHeader, PageTitle } from "@/features/layout/page";
|
||||
import { ProjectForm } from "@/components/wrappers/dashboard/projects/ProjectsForm/ProjectForm";
|
||||
import { notFound } from "next/navigation";
|
||||
import { getCurrentOrganizationSlug } from "@/features/dashboard/organization-cookie";
|
||||
|
||||
import { db } from "@/db";
|
||||
import { DatabaseWith, organization as drizzleOrganization } from "@/db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
export default async function RoutePage(props: PageParams<{slug: string}>) {
|
||||
const {slug: organizationSlug} = await props.params
|
||||
export default async function RoutePage(props: PageParams<{ slug: string }>) {
|
||||
const { slug: organizationSlug } = await props.params;
|
||||
|
||||
const currentOrganizationSlug = await getCurrentOrganizationSlug()
|
||||
if(currentOrganizationSlug != organizationSlug) {
|
||||
notFound()
|
||||
const currentOrganizationSlug = await getCurrentOrganizationSlug();
|
||||
if (currentOrganizationSlug !== organizationSlug) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const availableDatabases = (
|
||||
await db.query.database.findMany({
|
||||
where: (db, { isNull }) => isNull(db.projectId),
|
||||
with: {
|
||||
agent: true,
|
||||
project: true,
|
||||
backups: true,
|
||||
restorations: true,
|
||||
},
|
||||
orderBy: (db, { desc }) => [desc(db.createdAt)],
|
||||
})
|
||||
).filter((db) => db.project !== null) as DatabaseWith[];
|
||||
|
||||
const availableDatabases = await prisma.database.findMany({
|
||||
where: {
|
||||
projectId: null
|
||||
},
|
||||
include: {
|
||||
agent: {}
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
})
|
||||
const org = await db.query.organization.findFirst({
|
||||
where: eq(drizzleOrganization.slug, currentOrganizationSlug),
|
||||
});
|
||||
|
||||
const organization = await prisma.organization.findFirst({
|
||||
where: {
|
||||
slug: currentOrganizationSlug,
|
||||
}
|
||||
})
|
||||
if (!org) notFound();
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<PageHeader>
|
||||
<PageTitle>
|
||||
Create new project
|
||||
</PageTitle>
|
||||
<PageTitle>Create new project</PageTitle>
|
||||
</PageHeader>
|
||||
<PageContent>
|
||||
<ProjectForm databases={availableDatabases} organization={organization}/>
|
||||
<ProjectForm databases={availableDatabases} organization={org} />
|
||||
</PageContent>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,43 +1,34 @@
|
||||
import Link from 'next/link'
|
||||
import Link from "next/link";
|
||||
|
||||
import {PageParams} from "@/types/next";
|
||||
import {prisma} from "@/prisma";
|
||||
import {CardsWithPagination} from "@/components/wrappers/common/cards-with-pagination";
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {Page, PageActions, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
|
||||
import {ProjectCard} from "@/components/wrappers/dashboard/projects/ProjectCard/ProjectCard";
|
||||
import {getCurrentOrganizationSlug} from "@/features/dashboard/organization-cookie";
|
||||
import {notFound} from "next/navigation";
|
||||
import { PageParams } from "@/types/next";
|
||||
import { CardsWithPagination } from "@/components/wrappers/common/cards-with-pagination";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Page, PageActions, PageContent, PageHeader, PageTitle } from "@/features/layout/page";
|
||||
import { ProjectCard } from "@/components/wrappers/dashboard/projects/ProjectCard/ProjectCard";
|
||||
import { db } from "@/db";
|
||||
import { notFound } from "next/navigation";
|
||||
import { getOrganization } from "@/lib/auth/auth";
|
||||
|
||||
export default async function RoutePage(props: PageParams<{ slug: string }>) {
|
||||
const { slug: organizationSlug } = await props.params;
|
||||
|
||||
export default async function RoutePage(props: PageParams<{slug: string}>) {
|
||||
const {slug: organizationSlug} = await props.params
|
||||
const organization = await getOrganization(organizationSlug);
|
||||
|
||||
if (!organization || organization?.slug !== organizationSlug) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const projects = await prisma.project.findMany({
|
||||
where: {
|
||||
isArchived: {not: true},
|
||||
|
||||
organization: {
|
||||
slug: organizationSlug,
|
||||
// users: {
|
||||
// some: {
|
||||
// userId: user.id
|
||||
// },
|
||||
// },
|
||||
}
|
||||
const projects = await db.query.project.findMany({
|
||||
where: (project, { eq, and, not }) => and(eq(project.organizationId, organization.id), not(eq(project.isArchived, true))),
|
||||
with: {
|
||||
databases: true,
|
||||
},
|
||||
include: {
|
||||
databases: {}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<PageHeader>
|
||||
<PageTitle>
|
||||
Projects
|
||||
</PageTitle>
|
||||
<PageTitle>Projects</PageTitle>
|
||||
{projects.length > 0 && (
|
||||
<PageActions>
|
||||
<Link href={`/dashboard/${organizationSlug}/projects/new`}>
|
||||
@@ -45,28 +36,20 @@ export default async function RoutePage(props: PageParams<{slug: string}>) {
|
||||
</Link>
|
||||
</PageActions>
|
||||
)}
|
||||
|
||||
</PageHeader>
|
||||
|
||||
<PageContent className="mt-10">
|
||||
|
||||
{projects.length > 0 ?
|
||||
<CardsWithPagination
|
||||
organizationSlug={organizationSlug}
|
||||
data={projects}
|
||||
cardItem={ProjectCard}
|
||||
cardsPerPage={4}
|
||||
numberOfColumns={1}
|
||||
/>
|
||||
:
|
||||
{projects.length > 0 ? (
|
||||
<CardsWithPagination organizationSlug={organizationSlug} data={projects} cardItem={ProjectCard} cardsPerPage={4} numberOfColumns={1} />
|
||||
) : (
|
||||
<Link
|
||||
href={`/dashboard/${organizationSlug}/projects/new`}
|
||||
className=" flex item-center justify-center border-2 border-dashed transition-colors border-primary p-8 lg:p-12 w-full rounded-md">
|
||||
className=" flex item-center justify-center border-2 border-dashed transition-colors border-primary p-8 lg:p-12 w-full rounded-md"
|
||||
>
|
||||
Create new Project
|
||||
</Link>
|
||||
|
||||
}
|
||||
)}
|
||||
</PageContent>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,48 +1,57 @@
|
||||
import {PageParams} from "@/types/next";
|
||||
import {Page, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
|
||||
import {prisma} from "@/prisma";
|
||||
import {Card, CardContent, CardHeader, CardTitle} from "@/components/ui/card";
|
||||
import {EvolutionLineChart} from "@/components/wrappers/dashboard/statistics/charts/evolution-line-chart";
|
||||
import {PercentageLineChart} from "@/components/wrappers/dashboard/statistics/charts/percentage-line-chart";
|
||||
import { PageParams } from "@/types/next";
|
||||
import { Page, PageContent, PageHeader, PageTitle } from "@/features/layout/page";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { EvolutionLineChart } from "@/components/wrappers/dashboard/statistics/charts/evolution-line-chart";
|
||||
import { PercentageLineChart } from "@/components/wrappers/dashboard/statistics/charts/percentage-line-chart";
|
||||
import { getCurrentOrganizationSlug } from "@/features/dashboard/organization-cookie";
|
||||
import { notFound } from "next/navigation";
|
||||
import { db } from "@/db";
|
||||
import { asc, count, eq, inArray } from "drizzle-orm";
|
||||
import { organization as drizzleOrganization, project as drizzleProject, backup as drizzleBackup } from "@/db/schema";
|
||||
|
||||
export default async function RoutePage(props: PageParams<{}>) {
|
||||
export default async function RoutePage(props: PageParams<{ slug: string }>) {
|
||||
const { slug: organizationSlug } = await props.params;
|
||||
|
||||
const projectsCount = await prisma.project.count({
|
||||
where: {
|
||||
organization: {
|
||||
slug: "default"
|
||||
}
|
||||
},
|
||||
const currentOrganizationSlug = await getCurrentOrganizationSlug();
|
||||
if (currentOrganizationSlug !== organizationSlug) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const org = await db.query.organization.findFirst({
|
||||
where: eq(drizzleOrganization.slug, currentOrganizationSlug),
|
||||
});
|
||||
|
||||
const backupsEvolution = await prisma.backup.findMany({
|
||||
select: {
|
||||
if (!org) notFound();
|
||||
|
||||
const projects = await db.query.project.findMany({
|
||||
where: eq(drizzleProject.organizationId, org.id),
|
||||
});
|
||||
|
||||
const projectsCount = projects.length;
|
||||
|
||||
const backupsEvolution = await db.query.backup.findMany({
|
||||
columns: {
|
||||
id: true,
|
||||
createdAt: true,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "asc",
|
||||
},
|
||||
});
|
||||
|
||||
const backupsRate = await prisma.backup.groupBy({
|
||||
by: ['createdAt', 'status'],
|
||||
where: {
|
||||
status: {
|
||||
in: ['success', 'failed'],
|
||||
},
|
||||
},
|
||||
_count: {
|
||||
id: true,
|
||||
},
|
||||
orderBy: [asc(drizzleBackup.id)],
|
||||
});
|
||||
|
||||
const backupsRate = await db
|
||||
.select({
|
||||
createdAt: drizzleBackup.createdAt,
|
||||
status: drizzleBackup.status,
|
||||
_count: count(),
|
||||
})
|
||||
.from(drizzleBackup)
|
||||
.where(inArray(drizzleBackup.status, ["success", "failed"]))
|
||||
.groupBy(drizzleBackup.createdAt, drizzleBackup.status)
|
||||
.orderBy(drizzleBackup.createdAt);
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<PageHeader>
|
||||
<PageTitle>
|
||||
Statistics
|
||||
</PageTitle>
|
||||
<PageTitle>Statistics</PageTitle>
|
||||
</PageHeader>
|
||||
<PageContent className="flex flex-col gap-y-4">
|
||||
<div className="flex flex-col md:flex-row gap-4">
|
||||
@@ -50,23 +59,19 @@ export default async function RoutePage(props: PageParams<{}>) {
|
||||
<CardHeader>
|
||||
<CardTitle>Projects</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{projectsCount}
|
||||
</CardContent>
|
||||
<CardContent>{projectsCount}</CardContent>
|
||||
</Card>
|
||||
<Card className="w-full">
|
||||
<CardHeader>
|
||||
<CardTitle>KPI 2</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
</CardContent>
|
||||
<CardContent></CardContent>
|
||||
</Card>
|
||||
<Card className="w-full">
|
||||
<CardHeader>
|
||||
<CardTitle>KPI 3</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
</CardContent>
|
||||
<CardContent></CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
<div className="flex flex-col md:flex-row gap-4">
|
||||
@@ -75,7 +80,7 @@ export default async function RoutePage(props: PageParams<{}>) {
|
||||
<CardTitle>Evolution of the number of backups</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<EvolutionLineChart data={backupsEvolution}/>
|
||||
<EvolutionLineChart data={backupsEvolution} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="w-full">
|
||||
@@ -83,11 +88,11 @@ export default async function RoutePage(props: PageParams<{}>) {
|
||||
<CardTitle>Success rate of backups</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<PercentageLineChart data={backupsRate}/>
|
||||
<PercentageLineChart data={backupsRate} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</PageContent>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,37 +1,31 @@
|
||||
import React from "react";
|
||||
import {redirect} from "next/navigation";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
import {SidebarInset, SidebarProvider} from "@/components/ui/sidebar"
|
||||
import {AppSidebar} from "@/components/wrappers/dashboard/sideBar/app-sidebar";
|
||||
import {currentUser, requiredCurrentUser} from "@/auth/current-user";
|
||||
import {Header} from "@/features/layout/Header";
|
||||
import {prisma} from "@/prisma";
|
||||
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
|
||||
import { AppSidebar } from "@/components/wrappers/dashboard/sideBar/app-sidebar";
|
||||
import { Header } from "@/features/layout/Header";
|
||||
import { currentUser } from "@/lib/auth/current-user";
|
||||
|
||||
export default async function Layout({ children }: { children: React.ReactNode }) {
|
||||
const user = await currentUser();
|
||||
|
||||
export default async function Layout({children}: { children: React.ReactNode }) {
|
||||
|
||||
const user = await requiredCurrentUser()
|
||||
|
||||
if (!user) redirect('/login')
|
||||
if (!user) redirect("/login");
|
||||
|
||||
return (
|
||||
// <HydrationZustand>
|
||||
// <GlobalStoreProvider>
|
||||
<>
|
||||
|
||||
<SidebarProvider>
|
||||
<div className="flex flex-col lg:flex-row w-full">
|
||||
<AppSidebar/>
|
||||
<AppSidebar />
|
||||
<SidebarInset>
|
||||
<Header/>
|
||||
<main className="h-full">
|
||||
{children}
|
||||
</main>
|
||||
<Header />
|
||||
<main className="h-full">{children}</main>
|
||||
</SidebarInset>
|
||||
</div>
|
||||
</SidebarProvider>
|
||||
</>
|
||||
// </GlobalStoreProvider>
|
||||
// </HydrationZustand>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {LoadingSpinner} from "@/components/wrappers/common/loading/LoadingSpinner";
|
||||
import { LoadingSpinner } from "@/components/wrappers/common/loading/LoadingSpinner";
|
||||
|
||||
export default function Loading() {
|
||||
return (
|
||||
<div className="w-full h-full flex flex-col items-center justify-center">
|
||||
<LoadingSpinner size={50} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,44 +1,62 @@
|
||||
import {PageParams} from "@/types/next";
|
||||
import {Page, PageActions, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
|
||||
import {notFound} from "next/navigation";
|
||||
import {requiredCurrentUser} from "@/auth/current-user";
|
||||
import {UserForm} from "@/components/wrappers/dashboard/profile/UserForm/UserForm";
|
||||
import {prisma} from "@/prisma";
|
||||
import {Badge} from "@/components/ui/badge";
|
||||
import {ButtonDeleteAccount} from "@/components/wrappers/dashboard/profile/ButtonDeleteAccount/ButtonDeleteAccount";
|
||||
import {AvatarWithUpload} from "@/components/wrappers/dashboard/profile/Avatar/AvatarWithUpload";
|
||||
import { PageParams } from "@/types/next";
|
||||
import { Page, PageActions, PageContent, PageHeader, PageTitle } from "@/features/layout/page";
|
||||
import { notFound } from "next/navigation";
|
||||
import { UserForm } from "@/components/wrappers/dashboard/profile/UserForm/UserForm";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { ButtonDeleteAccount } from "@/components/wrappers/dashboard/profile/ButtonDeleteAccount/ButtonDeleteAccount";
|
||||
import { AvatarWithUpload } from "@/components/wrappers/dashboard/profile/Avatar/AvatarWithUpload";
|
||||
import { currentUser } from "@/lib/auth/current-user";
|
||||
//import { getAccounts, getSessions } from "@/lib/auth/auth";
|
||||
|
||||
export default async function RoutePage(props: PageParams<{}>) {
|
||||
const user = await currentUser();
|
||||
|
||||
const user = await requiredCurrentUser()
|
||||
if (!user) {
|
||||
notFound()
|
||||
return notFound();
|
||||
}
|
||||
const userInfo = await prisma.user.findUnique({
|
||||
where: {
|
||||
email: user.email
|
||||
}
|
||||
})
|
||||
|
||||
if (user.role !== "user" && user.role !== "admin" && user.role !== "superadmin") {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
// const sessions = await getSessions();
|
||||
// const accounts = await getAccounts();
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<div className="justify-between gap-2 sm:flex">
|
||||
<PageTitle className="flex items-center">
|
||||
<AvatarWithUpload user={userInfo}/>
|
||||
{user.name}
|
||||
<Badge className="ml-3 hidden lg:block">{userInfo.authMethod}</Badge>
|
||||
<Badge className="ml-3 hidden lg:block">{userInfo.role}</Badge>
|
||||
</PageTitle>
|
||||
<PageActions className="mt-2 hidden sm:block">
|
||||
<ButtonDeleteAccount text="Delete my account"/>
|
||||
</PageActions>
|
||||
</div>
|
||||
<div className="justify-between gap-2 sm:flex">
|
||||
<PageTitle className="flex items-center">
|
||||
<AvatarWithUpload
|
||||
user={{
|
||||
...user,
|
||||
image: user.image ?? null,
|
||||
role: user.role ?? null,
|
||||
banned: user.banned ?? null,
|
||||
banReason: user.banReason ?? null,
|
||||
banExpires: user.banExpires ?? null,
|
||||
deletedAt: user.deletedAt ? new Date(user.deletedAt) : null,
|
||||
}}
|
||||
/>
|
||||
{user.name}
|
||||
<Badge className="ml-3 hidden lg:block">{user.role}</Badge>
|
||||
</PageTitle>
|
||||
<PageActions className="mt-2 hidden sm:block">
|
||||
<ButtonDeleteAccount text="Delete my account" />
|
||||
</PageActions>
|
||||
</div>
|
||||
<PageContent>
|
||||
<UserForm userId={userInfo.id} defaultValues={userInfo}/>
|
||||
<UserForm
|
||||
userId={user.id}
|
||||
defaultValues={{
|
||||
name: user.name,
|
||||
email: user.email,
|
||||
role: user.role ?? undefined,
|
||||
}}
|
||||
/>
|
||||
<div className="mt-4 sm:hidden">
|
||||
<ButtonDeleteAccount text="Delete my account" />
|
||||
</div>
|
||||
|
||||
</PageContent>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user