feat: add not found pages for boards (#1671)
This commit is contained in:
5
apps/nextjs/src/app/[locale]/(home)/(board)/layout.tsx
Normal file
5
apps/nextjs/src/app/[locale]/(home)/(board)/layout.tsx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import definition from "../../boards/(content)/(home)/_definition";
|
||||||
|
|
||||||
|
const { layout } = definition;
|
||||||
|
|
||||||
|
export default layout;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import definition from "../boards/(content)/(home)/_definition";
|
import definition from "../../boards/(content)/(home)/_definition";
|
||||||
|
|
||||||
const { generateMetadataAsync: generateMetadata, page } = definition;
|
const { generateMetadataAsync: generateMetadata, page } = definition;
|
||||||
|
|
||||||
3
apps/nextjs/src/app/[locale]/(home)/not-found.tsx
Normal file
3
apps/nextjs/src/app/[locale]/(home)/not-found.tsx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import HomeBoardNotFoundPage from "../boards/(content)/not-found";
|
||||||
|
|
||||||
|
export default HomeBoardNotFoundPage;
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import definition from "../boards/(content)/(home)/_definition";
|
|
||||||
|
|
||||||
const { layout } = definition;
|
|
||||||
|
|
||||||
export default layout;
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { api } from "@homarr/api/server";
|
import { api } from "@homarr/api/server";
|
||||||
|
|
||||||
import { createBoardContentPage } from "../_creator";
|
import { createBoardContentPage } from "../../_creator";
|
||||||
|
|
||||||
export default createBoardContentPage<{ locale: string; name: string }>({
|
export default createBoardContentPage<{ locale: string; name: string }>({
|
||||||
async getInitialBoardAsync({ name }) {
|
async getInitialBoardAsync({ name }) {
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { IconLayoutOff } from "@tabler/icons-react";
|
||||||
|
|
||||||
|
import { getScopedI18n } from "@homarr/translation/server";
|
||||||
|
|
||||||
|
import { BoardNotFound } from "~/components/board/not-found";
|
||||||
|
|
||||||
|
export default async function BoardNotFoundPage() {
|
||||||
|
const tNotFound = await getScopedI18n("board.error.notFound");
|
||||||
|
return (
|
||||||
|
<BoardNotFound
|
||||||
|
icon={IconLayoutOff}
|
||||||
|
title={tNotFound("title")}
|
||||||
|
description={tNotFound("description")}
|
||||||
|
link={{ label: tNotFound("link"), href: "/manage/boards" }}
|
||||||
|
notice={tNotFound("notice")}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
47
apps/nextjs/src/app/[locale]/boards/(content)/not-found.tsx
Normal file
47
apps/nextjs/src/app/[locale]/boards/(content)/not-found.tsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { IconHomeOff } from "@tabler/icons-react";
|
||||||
|
|
||||||
|
import { auth } from "@homarr/auth/next";
|
||||||
|
import { db } from "@homarr/db";
|
||||||
|
import { boards } from "@homarr/db/schema/sqlite";
|
||||||
|
import { getI18n } from "@homarr/translation/server";
|
||||||
|
|
||||||
|
import type { BoardNotFoundProps } from "~/components/board/not-found";
|
||||||
|
import { BoardNotFound } from "~/components/board/not-found";
|
||||||
|
|
||||||
|
export default async function NotFoundBoardHomePage() {
|
||||||
|
const boardNotFoundProps = await getPropsAsync();
|
||||||
|
|
||||||
|
return <BoardNotFound {...boardNotFoundProps} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPropsAsync = async (): Promise<BoardNotFoundProps> => {
|
||||||
|
const boardCount = await db.$count(boards);
|
||||||
|
const t = await getI18n();
|
||||||
|
|
||||||
|
if (boardCount === 0) {
|
||||||
|
return {
|
||||||
|
icon: { src: "/favicon.ico", alt: "Homarr logo" },
|
||||||
|
title: t("board.error.noBoard.title"),
|
||||||
|
description: t("board.error.noBoard.description"),
|
||||||
|
link: { label: t("board.error.noBoard.link"), href: "/manage/boards" },
|
||||||
|
notice: t("board.error.noBoard.notice"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const session = await auth();
|
||||||
|
const isAdmin = session?.user.permissions.includes("admin");
|
||||||
|
const type = isAdmin ? "admin" : session !== null ? "user" : "anonymous";
|
||||||
|
const href = {
|
||||||
|
admin: "/manage/settings",
|
||||||
|
user: `/manage/users/${session?.user.id}/general`,
|
||||||
|
anonymous: "/manage/boards",
|
||||||
|
}[type];
|
||||||
|
|
||||||
|
return {
|
||||||
|
icon: IconHomeOff,
|
||||||
|
title: t(`board.error.homeBoard.title`),
|
||||||
|
description: t(`board.error.homeBoard.${type}.description`),
|
||||||
|
link: { label: t(`board.error.homeBoard.${type}.link`), href },
|
||||||
|
notice: t(`board.error.homeBoard.${type}.notice`),
|
||||||
|
};
|
||||||
|
};
|
||||||
41
apps/nextjs/src/components/board/not-found.tsx
Normal file
41
apps/nextjs/src/components/board/not-found.tsx
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { Anchor, AppShellMain, Center, Flex, Group, Image, Text, Title } from "@mantine/core";
|
||||||
|
|
||||||
|
import type { TablerIcon } from "@homarr/ui";
|
||||||
|
|
||||||
|
import { fullHeightWithoutHeaderAndFooter } from "~/constants";
|
||||||
|
import { MainHeader } from "../layout/header";
|
||||||
|
import { HomarrLogoWithTitle } from "../layout/logo/homarr-logo";
|
||||||
|
import { ClientShell } from "../layout/shell";
|
||||||
|
|
||||||
|
export interface BoardNotFoundProps {
|
||||||
|
icon: TablerIcon | { src: string; alt: string };
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
link: {
|
||||||
|
label: string;
|
||||||
|
href: string;
|
||||||
|
};
|
||||||
|
notice: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BoardNotFound = ({ icon: Icon, title, description, link, notice }: BoardNotFoundProps) => {
|
||||||
|
return (
|
||||||
|
<ClientShell hasNavigation={false}>
|
||||||
|
<MainHeader logo={<HomarrLogoWithTitle size="md" />} hasNavigation={false} />
|
||||||
|
<AppShellMain>
|
||||||
|
<Center h={fullHeightWithoutHeaderAndFooter}>
|
||||||
|
<Flex direction="column" align="center" ta="center">
|
||||||
|
<Group gap="sm" justify="center">
|
||||||
|
{"src" in Icon ? <Image fit="fill" h={48} w={48} src={Icon.src} alt={Icon.alt} /> : <Icon size={32} />}
|
||||||
|
|
||||||
|
<Title>{title}</Title>
|
||||||
|
</Group>
|
||||||
|
<Text>{description}</Text>
|
||||||
|
<Anchor href={link.href}>{link.label}</Anchor>
|
||||||
|
<Text c="dimmed">{notice}</Text>
|
||||||
|
</Flex>
|
||||||
|
</Center>
|
||||||
|
</AppShellMain>
|
||||||
|
</ClientShell>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1978,6 +1978,38 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"noBoard": {
|
||||||
|
"title": "Welcome to Homarr",
|
||||||
|
"description": "A sleek, modern dashboard that puts all of your apps and services at your fingertips.",
|
||||||
|
"link": "Create your first board",
|
||||||
|
"notice": "To make this page disappear, create a board and set it as the home board"
|
||||||
|
},
|
||||||
|
"notFound": {
|
||||||
|
"title": "Board not found",
|
||||||
|
"description": "The board specified was either not found or you don't have access to it.",
|
||||||
|
"link": "View all boards",
|
||||||
|
"notice": "Check the link or contact an administrator if you think it should be accessible"
|
||||||
|
},
|
||||||
|
"homeBoard": {
|
||||||
|
"title": "No home board",
|
||||||
|
"admin": {
|
||||||
|
"description": "You haven't set a home board for the server yet.",
|
||||||
|
"link": "Configure server-wide home board",
|
||||||
|
"notice": "To make this page disappear for all users, set a home board for the server"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"description": "You haven't set a home board yet.",
|
||||||
|
"link": "Configure your home board",
|
||||||
|
"notice": "To make this page disappear, specify the home board in your preferences"
|
||||||
|
},
|
||||||
|
"anonymous": {
|
||||||
|
"description": "The server administrator hasn't set a home board yet.",
|
||||||
|
"link": "View public boards",
|
||||||
|
"notice": "To make this page disappear, ask the server administrator to set a home board for the server"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"management": {
|
"management": {
|
||||||
|
|||||||
Reference in New Issue
Block a user