Skip to content

Commit

Permalink
refactor: Change install page to client component, remove url state
Browse files Browse the repository at this point in the history
  • Loading branch information
aXenDeveloper committed Jun 17, 2024
1 parent 62043e2 commit f5ecd98
Show file tree
Hide file tree
Showing 24 changed files with 159 additions and 285 deletions.
19 changes: 1 addition & 18 deletions backend/src/plugins/core/admin/install/layout/layout.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import {
} from "./dto/layout.obj";

import { core_users } from "@/plugins/core/admin/database/schema/users";
import { core_sessions } from "@/plugins/core/admin/database/schema/sessions";
import { core_admin_sessions } from "@/plugins/core/admin/database/schema/admins";
import { core_languages } from "@/plugins/core/admin/database/schema/languages";
import { DatabaseService } from "@/database/database.service";

Expand All @@ -22,22 +20,7 @@ export class LayoutAdminInstallService {
.select({ count: count() })
.from(core_users);
if (users[0].count > 0) {
const [sessionCount, sessionCountAdmin] = [
await this.databaseService.db
.select({ count: count() })
.from(core_sessions),
await this.databaseService.db
.select({ count: count() })
.from(core_admin_sessions)
];

if (sessionCount[0].count > 0 || sessionCountAdmin[0].count > 0) {
throw new AccessDeniedError();
}

return {
status: LayoutAdminInstallEnum.FINISH
};
throw new AccessDeniedError();
}

const languages = await this.databaseService.db
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

48 changes: 0 additions & 48 deletions frontend/app/[locale]/(admin)/admin/(configs)/install/layout.tsx

This file was deleted.

This file was deleted.

41 changes: 38 additions & 3 deletions frontend/app/[locale]/(admin)/admin/(configs)/install/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,40 @@
import { InstallConfigsView } from "@/plugins/admin/configs/views/install/steps/install-configs-view";
import { redirect } from "@vitnode/frontend/navigation";

export default function Page() {
return <InstallConfigsView />;
import { ErrorType, fetcher } from "@/graphql/fetcher";
import {
Admin__Install__Layout,
Admin__Install__LayoutQuery,
Admin__Install__LayoutQueryVariables
} from "@/graphql/hooks";
import { LayoutInstallConfigsView } from "@/plugins/admin/configs/views/install/layout-install-configs-view";
import { InternalErrorView } from "@/plugins/admin/global/internal-error/internal-error-view";

const getData = async () => {
const { data } = await fetcher<
Admin__Install__LayoutQuery,
Admin__Install__LayoutQueryVariables
>({
query: Admin__Install__Layout,
cache: "force-cache"
});

return data;
};

export default async function Page() {
try {
const data = await getData();

return (
<LayoutInstallConfigsView data={data.admin__install__layout.status} />
);
} catch (error) {
const code = error as ErrorType;

if (code.extensions?.code === "ACCESS_DENIED") {
redirect("/admin");
}

return <InternalErrorView />;
}
}
1 change: 1 addition & 0 deletions frontend/components/steps/steps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Link } from "@vitnode/frontend/navigation";
import { cn } from "@vitnode/frontend/helpers";

export interface ItemStepProps {
component: React.ReactNode;
id: string;
title: string;
checked?: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useTranslations } from "next-intl";
import { Home, KeyRound } from "lucide-react";
import { Link } from "@vitnode/frontend/navigation";

Expand All @@ -13,28 +12,28 @@ import {
import { buttonVariants } from "@/components/ui/button";

export const FinishInstallConfigsView = () => {
const t = useTranslations("admin.configs.install.finish");

return (
<Card className="text-center">
<CardHeader>
<CardTitle>{t("title", { name: "VitNode" })}</CardTitle>
<CardDescription>{t("desc")}</CardDescription>
<CardTitle>Welcome to VitNode!</CardTitle>
<CardDescription>Your website is ready.</CardDescription>
</CardHeader>
<CardContent>
<p>{t("text")}</p>
<p>
The installation process is complete. You can now use your website.
</p>
</CardContent>
<CardFooter className="flex items-center justify-center gap-4">
<Link href="/" className={buttonVariants()}>
<Home /> {t("buttons.home_page")}
<Home /> Home Page
</Link>
<Link
href="/admin"
className={buttonVariants({
variant: "secondary"
variant: "ghost"
})}
>
<KeyRound /> {t("buttons.admin_control_panel")}
<KeyRound /> Admin Control Panel
</Link>
</CardFooter>
</Card>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as React from "react";

interface Args {
currentStep: number;
setCurrentStep: React.Dispatch<React.SetStateAction<number>>;
}

export const InstallVitNodeContext = React.createContext<Args>({
currentStep: 0,
setCurrentStep: () => {}
});

export const useInstallVitnode = () => React.useContext(InstallVitNodeContext);
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"use client";

import * as React from "react";
import { useTranslations } from "next-intl";
import { useSelectedLayoutSegment } from "next/navigation";

import { Steps, ItemStepProps } from "@/components/steps/steps";
import {
Expand All @@ -11,64 +9,84 @@ import {
CardHeader,
CardTitle
} from "@/components/ui/card";
import { InstallConfigsView } from "./steps/install-configs-view";
import { InstallVitNodeContext } from "./hooks/use-install-vitnode";
import { LicenseInstallConfigsView } from "./steps/license/license-install-configs-view";
import { DatabaseInstallConfigsView } from "./steps/database/database-install-configs-view";
import { AccountInstallConfigsView } from "./steps/account/account-install-configs-view";
import { LayoutAdminInstallEnum } from "@/graphql/hooks";
import { FinishInstallConfigsView } from "./finish/finish-install-config-view";

interface Props {
children: React.ReactNode;
data: LayoutAdminInstallEnum;
}

export const LayoutInstallConfigsView = ({ children }: Props) => {
const t = useTranslations("admin.configs.install");
const segment = useSelectedLayoutSegment();

const stepsNumber: Record<string, number> = {
license: 2,
database: 3,
account: 4
};

const activeStep = segment ? stepsNumber[segment] : 1;
export const LayoutInstallConfigsView = ({ data }: Props) => {
const [currentStep, setCurrentStep] = React.useState(0);

const items: ItemStepProps[] = [
{
id: "welcome",
title: t("steps.welcome.title"),
description: t("steps.welcome.desc"),
checked: activeStep >= 2
title: "Welcome",
description: "Before you begin...",
checked: currentStep >= 1,
component: <InstallConfigsView />
},
{
id: "license",
title: t("steps.license.title"),
description: t("steps.license.desc"),
checked: activeStep >= 3
title: "License",
description: "Read carefully",
checked: currentStep >= 2,
component: <LicenseInstallConfigsView />
},
{
id: "database",
title: t("steps.database.title"),
description: t("steps.database.desc"),
checked: activeStep >= 4
title: "Database",
description: "Create schema and first records",
checked: currentStep >= 3,
component: <DatabaseInstallConfigsView />
},
{
id: "account",
title: t("steps.account.title"),
description: t("steps.account.desc"),
checked: activeStep >= 5
title: "Admin Account",
description: "Create admin account",
checked: currentStep >= 4,
component: <AccountInstallConfigsView />
}
];

React.useEffect(() => {
if (currentStep < 2) {
return;
}

if (data === LayoutAdminInstallEnum.account && currentStep < 3) {
setCurrentStep(3);
}
}, [data, currentStep]);

if (currentStep === items.length) {
return <FinishInstallConfigsView />;
}

return (
<Card className="hidden sm:flex">
<Steps className="max-w-64 p-5 pr-0" items={items} />

<div className="grow">
<CardHeader>
<CardDescription>{t("title", { name: "VitNode" })}</CardDescription>
<CardTitle>
{/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
{/* @ts-expect-error */}
{t(`steps.${items.at(activeStep - 1)?.id}.title`)}
</CardTitle>
<CardDescription>Install VitNode</CardDescription>
<CardTitle>{items.at(currentStep)?.title}</CardTitle>
</CardHeader>
{children}

<InstallVitNodeContext.Provider
value={{
currentStep,
setCurrentStep
}}
>
{items.at(currentStep)?.component}
</InstallVitNodeContext.Provider>
</div>
</Card>
);
Expand Down

This file was deleted.

Loading

0 comments on commit f5ecd98

Please sign in to comment.