feat: add about page (#388)
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
.root {
|
||||
border-radius: var(--mantine-radius-sm);
|
||||
background-color: light-dark(
|
||||
var(--mantine-color-gray-0),
|
||||
var(--mantine-color-dark-6)
|
||||
);
|
||||
}
|
||||
|
||||
.item {
|
||||
background-color: light-dark(
|
||||
var(--mantine-color-gray-0),
|
||||
var(--mantine-color-dark-6)
|
||||
);
|
||||
border: 1px solid transparent;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
transition: transform 150ms ease;
|
||||
|
||||
&[data-active] {
|
||||
transform: scale(1.015);
|
||||
z-index: 1;
|
||||
background-color: var(--mantine-color-body);
|
||||
border-color: light-dark(
|
||||
var(--mantine-color-gray-2),
|
||||
var(--mantine-color-dark-4)
|
||||
);
|
||||
box-shadow: var(--mantine-shadow-md);
|
||||
border-radius: var(--mantine-radius-md);
|
||||
}
|
||||
}
|
||||
|
||||
.chevron {
|
||||
&[data-rotate] {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
93
apps/nextjs/src/app/[locale]/manage/about/page.tsx
Normal file
93
apps/nextjs/src/app/[locale]/manage/about/page.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
import Image from "next/image";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionControl,
|
||||
AccordionItem,
|
||||
AccordionPanel,
|
||||
Center,
|
||||
Group,
|
||||
List,
|
||||
ListItem,
|
||||
Stack,
|
||||
Text,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import { IconLanguage, IconLibrary, IconUsers } from "@tabler/icons-react";
|
||||
|
||||
import { getScopedI18n } from "@homarr/translation/server";
|
||||
|
||||
import { getPackageAttributes } from "~/versions/package-reader";
|
||||
import logo from "../../../../../public/logo/logo.png";
|
||||
import classes from "./accordion.module.css";
|
||||
|
||||
export async function generateMetadata() {
|
||||
const t = await getScopedI18n("management");
|
||||
const metaTitle = `${t("metaTitle")} • Homarr`;
|
||||
|
||||
return {
|
||||
title: metaTitle,
|
||||
};
|
||||
}
|
||||
|
||||
export default async function AboutPage() {
|
||||
const t = await getScopedI18n("management.page.about");
|
||||
const attributes = getPackageAttributes();
|
||||
return (
|
||||
<div>
|
||||
<Center w="100%">
|
||||
<Group py="lg">
|
||||
<Image src={logo} width={100} height={100} alt="" />
|
||||
<Stack gap={0}>
|
||||
<Title order={1} tt="uppercase">
|
||||
Homarr
|
||||
</Title>
|
||||
<Title order={2}>
|
||||
{t("version", { version: attributes.version })}
|
||||
</Title>
|
||||
</Stack>
|
||||
</Group>
|
||||
</Center>
|
||||
<Text mb="xl">{t("text")}</Text>
|
||||
|
||||
<Accordion classNames={classes}>
|
||||
<AccordionItem value="contributors">
|
||||
<AccordionControl icon={<IconUsers size="1rem" />}>
|
||||
{t("accordion.contributors.title")}
|
||||
</AccordionControl>
|
||||
<AccordionPanel></AccordionPanel>
|
||||
</AccordionItem>
|
||||
<AccordionItem value="translators">
|
||||
<AccordionControl icon={<IconLanguage size="1rem" />}>
|
||||
{t("accordion.translators.title")}
|
||||
</AccordionControl>
|
||||
<AccordionPanel></AccordionPanel>
|
||||
</AccordionItem>
|
||||
<AccordionItem value="libraries">
|
||||
<AccordionControl icon={<IconLibrary size="1rem" />}>
|
||||
<Stack gap={0}>
|
||||
<Text>{t("accordion.libraries.title")}</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
{t("accordion.libraries.subtitle", {
|
||||
count: Object.keys(attributes.dependencies).length,
|
||||
})}
|
||||
</Text>
|
||||
</Stack>
|
||||
</AccordionControl>
|
||||
<AccordionPanel>
|
||||
<List>
|
||||
{Object.entries(attributes.dependencies).map(([key, value]) => (
|
||||
<ListItem key={key}>
|
||||
{value.includes("workspace:") ? (
|
||||
<Text>{key}</Text>
|
||||
) : (
|
||||
<a href={`https://www.npmjs.com/package/${key}`}>{key}</a>
|
||||
)}
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
4
apps/nextjs/src/react-app-env.d.ts
vendored
Normal file
4
apps/nextjs/src/react-app-env.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
declare module "*.png";
|
||||
declare module "*.svg";
|
||||
declare module "*.jpeg";
|
||||
declare module "*.jpg";
|
||||
13
apps/nextjs/src/versions/package-reader.ts
Normal file
13
apps/nextjs/src/versions/package-reader.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import packageJson from "~/../package.json";
|
||||
|
||||
const getPackageVersion = () => packageJson.version;
|
||||
const getDependencies = (): PackageJsonDependencies => packageJson.dependencies;
|
||||
|
||||
export const getPackageAttributes = () => {
|
||||
return {
|
||||
version: getPackageVersion(),
|
||||
dependencies: getDependencies(),
|
||||
};
|
||||
};
|
||||
|
||||
type PackageJsonDependencies = { [key in string]: string };
|
||||
@@ -948,6 +948,22 @@ export default {
|
||||
},
|
||||
},
|
||||
},
|
||||
about: {
|
||||
version: "Version {version}",
|
||||
text: "Homarr is a community driven open source project that is being maintained by volunteers. Thanks to these people, Homarr has been a growing project since 2021. Our team is working completely remote from many different countries on Homarr in their leisure time for no compensation.",
|
||||
accordion: {
|
||||
contributors: {
|
||||
title: "Contributors",
|
||||
},
|
||||
translators: {
|
||||
title: "Translators",
|
||||
},
|
||||
libraries: {
|
||||
title: "Libraries",
|
||||
subtitle: "{count} used",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
Reference in New Issue
Block a user