mirror of
https://github.com/andwati/dokploy.git
synced 2026-11-08 04:55:17 +00:00
feat: add dashboard home page with overview and recent deployments
Adds a new /dashboard/home landing with welcome header, KPI cards (deploys/24h, build, CPU, memory) and a recent deployments list. Home is now the post-login landing and the destination for permission fallback redirects across the app. Projects remains accessible from the sidebar.
This commit is contained in:
@@ -0,0 +1,223 @@
|
|||||||
|
import { formatDistanceToNow } from "date-fns";
|
||||||
|
import { Plus, Rocket } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { api } from "@/utils/api";
|
||||||
|
|
||||||
|
type DeploymentStatus = "idle" | "running" | "done" | "error";
|
||||||
|
|
||||||
|
const statusDotClass: Record<string, string> = {
|
||||||
|
done: "bg-muted-foreground/60",
|
||||||
|
running: "bg-amber-500",
|
||||||
|
error: "bg-red-500",
|
||||||
|
idle: "bg-muted-foreground/30",
|
||||||
|
};
|
||||||
|
|
||||||
|
function getServiceInfo(d: any) {
|
||||||
|
const app = d.application;
|
||||||
|
const comp = d.compose;
|
||||||
|
if (app?.environment?.project && app.environment) {
|
||||||
|
return {
|
||||||
|
name: app.name as string,
|
||||||
|
environment: app.environment.name as string,
|
||||||
|
projectName: app.environment.project.name as string,
|
||||||
|
href: `/dashboard/project/${app.environment.project.projectId}/environment/${app.environment.environmentId}/services/application/${app.applicationId}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (comp?.environment?.project && comp.environment) {
|
||||||
|
return {
|
||||||
|
name: comp.name as string,
|
||||||
|
environment: comp.environment.name as string,
|
||||||
|
projectName: comp.environment.project.name as string,
|
||||||
|
href: `/dashboard/project/${comp.environment.project.projectId}/environment/${comp.environment.environmentId}/services/compose/${comp.composeId}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function StatCard({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
delta,
|
||||||
|
}: {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
delta?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="rounded-xl border bg-background p-5 min-h-[120px] flex flex-col justify-between">
|
||||||
|
<span className="text-xs uppercase tracking-wider text-muted-foreground">
|
||||||
|
{label}
|
||||||
|
</span>
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<span className="text-3xl font-semibold tracking-tight">{value}</span>
|
||||||
|
{delta && (
|
||||||
|
<span className="text-xs text-muted-foreground">
|
||||||
|
{delta}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ShowHome = () => {
|
||||||
|
const { data: auth } = api.user.get.useQuery();
|
||||||
|
const { data: projects } = api.project.all.useQuery();
|
||||||
|
const { data: servers } = api.server.all.useQuery();
|
||||||
|
const { data: permissions } = api.user.getPermissions.useQuery();
|
||||||
|
const canReadDeployments = !!permissions?.deployment.read;
|
||||||
|
const { data: deployments } = api.deployment.allCentralized.useQuery(
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
enabled: canReadDeployments,
|
||||||
|
refetchInterval: 10000,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const firstName = auth?.user?.firstName?.trim();
|
||||||
|
|
||||||
|
const { totals, serverCount } = useMemo(() => {
|
||||||
|
let applications = 0;
|
||||||
|
let compose = 0;
|
||||||
|
let databases = 0;
|
||||||
|
const dbKeys = [
|
||||||
|
"postgres",
|
||||||
|
"mysql",
|
||||||
|
"mariadb",
|
||||||
|
"mongo",
|
||||||
|
"redis",
|
||||||
|
"libsql",
|
||||||
|
] as const;
|
||||||
|
for (const p of projects ?? []) {
|
||||||
|
for (const env of p.environments ?? []) {
|
||||||
|
applications += env.applications?.length ?? 0;
|
||||||
|
compose += env.compose?.length ?? 0;
|
||||||
|
for (const key of dbKeys) {
|
||||||
|
databases += (env as any)[key]?.length ?? 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
totals: {
|
||||||
|
projects: projects?.length ?? 0,
|
||||||
|
applications,
|
||||||
|
compose,
|
||||||
|
databases,
|
||||||
|
services: applications + compose + databases,
|
||||||
|
},
|
||||||
|
serverCount: servers?.length ?? 0,
|
||||||
|
};
|
||||||
|
}, [projects, servers]);
|
||||||
|
|
||||||
|
const recentDeployments = useMemo(() => {
|
||||||
|
if (!deployments) return [];
|
||||||
|
return [...deployments]
|
||||||
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
|
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
|
||||||
|
)
|
||||||
|
.slice(0, 10);
|
||||||
|
}, [deployments]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-full flex flex-col gap-6">
|
||||||
|
<div className="flex flex-col gap-6 sm:flex-row sm:items-end sm:justify-between">
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<h1 className="text-3xl font-semibold tracking-tight">
|
||||||
|
{firstName ? `Welcome back, ${firstName}` : "Welcome back"}
|
||||||
|
</h1>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
{totals.services} services across {serverCount}{" "}
|
||||||
|
{serverCount === 1 ? "server" : "servers"} · {totals.projects}{" "}
|
||||||
|
{totals.projects === 1 ? "project" : "projects"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Button asChild className="w-fit">
|
||||||
|
<Link href="/dashboard/projects">
|
||||||
|
<Plus className="size-4" />
|
||||||
|
New project
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||||
|
<StatCard
|
||||||
|
label="Deploys / 24h"
|
||||||
|
value={String(recentDeployments.length)}
|
||||||
|
delta="placeholder"
|
||||||
|
/>
|
||||||
|
<StatCard label="Avg build" value="—" delta="placeholder" />
|
||||||
|
<StatCard label="CPU" value="—" delta="placeholder" />
|
||||||
|
<StatCard label="Memory" value="—" delta="placeholder" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="rounded-xl border bg-background">
|
||||||
|
<div className="flex items-center justify-between px-5 py-4 border-b">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Rocket className="size-4 text-muted-foreground" />
|
||||||
|
<h2 className="text-sm font-semibold">Recent deployments</h2>
|
||||||
|
</div>
|
||||||
|
{canReadDeployments && (
|
||||||
|
<Link
|
||||||
|
href="/dashboard/deployments"
|
||||||
|
className="text-xs text-muted-foreground hover:text-foreground transition-colors"
|
||||||
|
>
|
||||||
|
view all →
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{!canReadDeployments ? (
|
||||||
|
<div className="p-10 text-center text-sm text-muted-foreground">
|
||||||
|
You do not have permission to view deployments.
|
||||||
|
</div>
|
||||||
|
) : recentDeployments.length === 0 ? (
|
||||||
|
<div className="p-10 text-center text-sm text-muted-foreground">
|
||||||
|
No deployments yet.
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<ul className="divide-y">
|
||||||
|
{recentDeployments.map((d) => {
|
||||||
|
const info = getServiceInfo(d);
|
||||||
|
if (!info) return null;
|
||||||
|
const status = (d.status ?? "idle") as DeploymentStatus;
|
||||||
|
return (
|
||||||
|
<li key={d.deploymentId}>
|
||||||
|
<Link
|
||||||
|
href={info.href}
|
||||||
|
className="flex items-center gap-4 px-5 py-4 hover:bg-muted/40 transition-colors"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={`size-2 rounded-full shrink-0 ${statusDotClass[status] ?? statusDotClass.idle}`}
|
||||||
|
aria-hidden
|
||||||
|
/>
|
||||||
|
<div className="flex flex-col min-w-0 flex-1">
|
||||||
|
<span className="text-sm truncate">
|
||||||
|
{info.name}
|
||||||
|
</span>
|
||||||
|
<span className="text-xs text-muted-foreground truncate">
|
||||||
|
{info.projectName} · {info.environment}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span className="text-xs text-muted-foreground w-20 text-right hidden sm:inline">
|
||||||
|
{status}
|
||||||
|
</span>
|
||||||
|
<span className="text-xs text-muted-foreground w-24 text-right hidden md:inline">
|
||||||
|
{formatDistanceToNow(new Date(d.createdAt), {
|
||||||
|
addSuffix: true,
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
<span className="text-xs text-muted-foreground hover:text-foreground transition-colors">
|
||||||
|
logs →
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -167,7 +167,7 @@ export const SearchCommand = () => {
|
|||||||
<CommandGroup heading={"Application"} hidden={true}>
|
<CommandGroup heading={"Application"} hidden={true}>
|
||||||
<CommandItem
|
<CommandItem
|
||||||
onSelect={() => {
|
onSelect={() => {
|
||||||
router.push("/dashboard/projects");
|
router.push("/dashboard/home");
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
+1
-1
@@ -425,7 +425,7 @@ export const WelcomeSubscription = () => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (stepper.isLast) {
|
if (stepper.isLast) {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
push("/dashboard/projects");
|
push("/dashboard/home");
|
||||||
} else {
|
} else {
|
||||||
stepper.next();
|
stepper.next();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
Forward,
|
Forward,
|
||||||
GalleryVerticalEnd,
|
GalleryVerticalEnd,
|
||||||
GitBranch,
|
GitBranch,
|
||||||
|
House,
|
||||||
Key,
|
Key,
|
||||||
KeyRound,
|
KeyRound,
|
||||||
Loader2,
|
Loader2,
|
||||||
@@ -148,6 +149,12 @@ type Menu = {
|
|||||||
// The `isEnabled` function is called to determine if the item should be displayed
|
// The `isEnabled` function is called to determine if the item should be displayed
|
||||||
const MENU: Menu = {
|
const MENU: Menu = {
|
||||||
home: [
|
home: [
|
||||||
|
{
|
||||||
|
isSingle: true,
|
||||||
|
title: "Home",
|
||||||
|
url: "/dashboard/home",
|
||||||
|
icon: House,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
isSingle: true,
|
isSingle: true,
|
||||||
title: "Projects",
|
title: "Projects",
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export const UserNav = () => {
|
|||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
router.push("/dashboard/projects");
|
router.push("/dashboard/home");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Projects
|
Projects
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export function SignInWithSSO({ children }: SignInWithSSOProps) {
|
|||||||
try {
|
try {
|
||||||
const { data, error } = await authClient.signIn.sso({
|
const { data, error } = await authClient.signIn.sso({
|
||||||
email: values.email,
|
email: values.email,
|
||||||
callbackURL: "/dashboard/projects",
|
callbackURL: "/dashboard/home",
|
||||||
});
|
});
|
||||||
if (error) {
|
if (error) {
|
||||||
toast.error(error.message ?? "Failed to sign in with SSO");
|
toast.error(error.message ?? "Failed to sign in with SSO");
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export default function Custom404({ statusCode, error }: Props) {
|
|||||||
|
|
||||||
<div className="mt-5 flex flex-col justify-center items-center gap-2 sm:flex-row sm:gap-3">
|
<div className="mt-5 flex flex-col justify-center items-center gap-2 sm:flex-row sm:gap-3">
|
||||||
<Link
|
<Link
|
||||||
href="/dashboard/projects"
|
href="/dashboard/home"
|
||||||
className={buttonVariants({
|
className={buttonVariants({
|
||||||
variant: "secondary",
|
variant: "secondary",
|
||||||
className: "flex flex-row gap-2",
|
className: "flex flex-row gap-2",
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ export async function getServerSideProps(ctx: GetServerSidePropsContext) {
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { validateRequest } from "@dokploy/server/lib/auth";
|
||||||
|
import { createServerSideHelpers } from "@trpc/react-query/server";
|
||||||
|
import type { GetServerSidePropsContext } from "next";
|
||||||
|
import type { ReactElement } from "react";
|
||||||
|
import superjson from "superjson";
|
||||||
|
import { ShowHome } from "@/components/dashboard/home/show-home";
|
||||||
|
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||||
|
import { appRouter } from "@/server/api/root";
|
||||||
|
|
||||||
|
const Home = () => {
|
||||||
|
return <ShowHome />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Home;
|
||||||
|
|
||||||
|
Home.getLayout = (page: ReactElement) => {
|
||||||
|
return <DashboardLayout>{page}</DashboardLayout>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getServerSideProps(ctx: GetServerSidePropsContext) {
|
||||||
|
const { req, res } = ctx;
|
||||||
|
const { user, session } = await validateRequest(req);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return {
|
||||||
|
redirect: {
|
||||||
|
permanent: true,
|
||||||
|
destination: "/",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const helpers = createServerSideHelpers({
|
||||||
|
router: appRouter,
|
||||||
|
ctx: {
|
||||||
|
req: req as any,
|
||||||
|
res: res as any,
|
||||||
|
db: null as any,
|
||||||
|
session: session as any,
|
||||||
|
user: user as any,
|
||||||
|
},
|
||||||
|
transformer: superjson,
|
||||||
|
});
|
||||||
|
|
||||||
|
await helpers.settings.isCloud.prefetch();
|
||||||
|
await helpers.user.get.prefetch();
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
trpcState: helpers.dehydrate(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -96,7 +96,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -122,7 +122,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import { AddTemplate } from "@/components/dashboard/project/add-template";
|
|||||||
import { AdvancedEnvironmentSelector } from "@/components/dashboard/project/advanced-environment-selector";
|
import { AdvancedEnvironmentSelector } from "@/components/dashboard/project/advanced-environment-selector";
|
||||||
import { DuplicateProject } from "@/components/dashboard/project/duplicate-project";
|
import { DuplicateProject } from "@/components/dashboard/project/duplicate-project";
|
||||||
import { EnvironmentVariables } from "@/components/dashboard/project/environment-variables";
|
import { EnvironmentVariables } from "@/components/dashboard/project/environment-variables";
|
||||||
import { ProjectEnvironment } from "@/components/dashboard/projects/project-environment";
|
import { ProjectEnvironment } from "@/components/dashboard/home/project-environment";
|
||||||
import {
|
import {
|
||||||
LibsqlIcon,
|
LibsqlIcon,
|
||||||
MariadbIcon,
|
MariadbIcon,
|
||||||
@@ -1856,7 +1856,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -490,7 +490,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -492,7 +492,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -343,7 +343,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -372,7 +372,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -376,7 +376,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -353,7 +353,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -360,7 +360,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -363,7 +363,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: false,
|
permanent: false,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export async function getServerSideProps(
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ export default function Home({ IS_CLOUD }: Props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toast.success("Logged in successfully");
|
toast.success("Logged in successfully");
|
||||||
router.push("/dashboard/projects");
|
router.push("/dashboard/home");
|
||||||
} catch {
|
} catch {
|
||||||
toast.error("An error occurred while logging in");
|
toast.error("An error occurred while logging in");
|
||||||
} finally {
|
} finally {
|
||||||
@@ -133,7 +133,7 @@ export default function Home({ IS_CLOUD }: Props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toast.success("Logged in successfully");
|
toast.success("Logged in successfully");
|
||||||
router.push("/dashboard/projects");
|
router.push("/dashboard/home");
|
||||||
} catch {
|
} catch {
|
||||||
toast.error("An error occurred while verifying 2FA code");
|
toast.error("An error occurred while verifying 2FA code");
|
||||||
} finally {
|
} finally {
|
||||||
@@ -163,7 +163,7 @@ export default function Home({ IS_CLOUD }: Props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toast.success("Logged in successfully");
|
toast.success("Logged in successfully");
|
||||||
router.push("/dashboard/projects");
|
router.push("/dashboard/home");
|
||||||
} catch {
|
} catch {
|
||||||
toast.error("An error occurred while verifying backup code");
|
toast.error("An error occurred while verifying backup code");
|
||||||
} finally {
|
} finally {
|
||||||
@@ -408,7 +408,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -437,7 +437,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ const Invitation = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
toast.success("Account created successfully");
|
toast.success("Account created successfully");
|
||||||
router.push("/dashboard/projects");
|
router.push("/dashboard/home");
|
||||||
} catch {
|
} catch {
|
||||||
toast.error("An error occurred while creating your account");
|
toast.error("An error occurred while creating your account");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
|||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
destination: "/dashboard/projects",
|
destination: "/dashboard/home",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user