mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-14 17:26:26 +01:00
🐛 Header scaling
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
import { Stack, Stepper } from '@mantine/core';
|
import { Stack, Stepper } from '@mantine/core';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
import { StepUpdatePathMappings } from './step-update-path-mappings';
|
|
||||||
import { StepCreateAccount } from './step-create-account';
|
import { StepCreateAccount } from './step-create-account';
|
||||||
import { StepOnboardingFinished } from './step-onboarding-finished';
|
|
||||||
import { StepDockerImport } from './step-docker-import';
|
import { StepDockerImport } from './step-docker-import';
|
||||||
import { StepDocumentation } from './step-documentation';
|
import { StepDocumentation } from './step-documentation';
|
||||||
|
import { StepOnboardingFinished } from './step-onboarding-finished';
|
||||||
|
import { StepUpdatePathMappings } from './step-update-path-mappings';
|
||||||
|
|
||||||
export const OnboardingSteps = ({ isUpdate }: { isUpdate: boolean }) => {
|
export const OnboardingSteps = ({ isUpdate }: { isUpdate: boolean }) => {
|
||||||
const [currentStep, setCurrentStep] = useState(0);
|
const [currentStep, setCurrentStep] = useState(0);
|
||||||
@@ -14,7 +14,12 @@ export const OnboardingSteps = ({ isUpdate }: { isUpdate: boolean }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack p="lg">
|
<Stack p="lg">
|
||||||
<Stepper active={currentStep} onStepClick={setCurrentStep} breakpoint="sm">
|
<Stepper
|
||||||
|
allowNextStepsSelect={false}
|
||||||
|
active={currentStep}
|
||||||
|
onStepClick={setCurrentStep}
|
||||||
|
breakpoint="sm"
|
||||||
|
>
|
||||||
{isUpdate && (
|
{isUpdate && (
|
||||||
<Stepper.Step
|
<Stepper.Step
|
||||||
label="Update your installation"
|
label="Update your installation"
|
||||||
|
|||||||
@@ -140,6 +140,8 @@ export const StepUpdatePathMappings = ({ next }: { next: () => void }) => {
|
|||||||
{dockerComposeCommand}
|
{dockerComposeCommand}
|
||||||
</Prism>
|
</Prism>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
|
<List.Item>Run <Code>docker compose up</Code>.</List.Item>
|
||||||
|
<List.Item>Refresh this page and click on "continue"</List.Item>
|
||||||
</List>
|
</List>
|
||||||
</Tabs.Panel>
|
</Tabs.Panel>
|
||||||
|
|
||||||
@@ -168,6 +170,8 @@ export const StepUpdatePathMappings = ({ next }: { next: () => void }) => {
|
|||||||
innermost directory should be different, than your existing mounting points (eg.{' '}
|
innermost directory should be different, than your existing mounting points (eg.{' '}
|
||||||
<Code>/mnt/user/appdata/homarr/data</Code>)
|
<Code>/mnt/user/appdata/homarr/data</Code>)
|
||||||
</List.Item>
|
</List.Item>
|
||||||
|
<List.Item>Click "Apply" and wait for the container to be restarted.</List.Item>
|
||||||
|
<List.Item>Refresh this page and click on "continue"</List.Item>
|
||||||
</List>
|
</List>
|
||||||
</Tabs.Panel>
|
</Tabs.Panel>
|
||||||
|
|
||||||
|
|||||||
@@ -1,41 +1,13 @@
|
|||||||
import {
|
import { Box, Button, Center, Image, Stack, Text, Title, useMantineTheme } from '@mantine/core';
|
||||||
Box,
|
import { useDisclosure } from '@mantine/hooks';
|
||||||
Button,
|
import { IconArrowRight } from '@tabler/icons-react';
|
||||||
Card,
|
|
||||||
Center,
|
|
||||||
Divider,
|
|
||||||
Flex,
|
|
||||||
Grid,
|
|
||||||
Group,
|
|
||||||
Image,
|
|
||||||
PasswordInput,
|
|
||||||
Stack,
|
|
||||||
Stepper,
|
|
||||||
Text,
|
|
||||||
TextInput,
|
|
||||||
Title,
|
|
||||||
UnstyledButton,
|
|
||||||
createStyles,
|
|
||||||
useMantineTheme,
|
|
||||||
} from '@mantine/core';
|
|
||||||
import { useForm } from '@mantine/form';
|
|
||||||
import { useDisclosure, useMediaQuery } from '@mantine/hooks';
|
|
||||||
import { IconLayoutDashboard, IconUserCog } from '@tabler/icons-react';
|
|
||||||
import { IconArrowRight, IconBook2, IconUserPlus } from '@tabler/icons-react';
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { GetServerSideProps, GetServerSidePropsResult, InferGetServerSidePropsType } from 'next';
|
import { GetServerSideProps, InferGetServerSidePropsType } from 'next';
|
||||||
import { signIn } from 'next-auth/react';
|
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import Link from 'next/link';
|
|
||||||
import { ReactNode, useMemo, useState } from 'react';
|
|
||||||
import { z } from 'zod';
|
|
||||||
import { OnboardingSteps } from '~/components/Onboarding/onboarding-steps';
|
import { OnboardingSteps } from '~/components/Onboarding/onboarding-steps';
|
||||||
import { prisma } from '~/server/db';
|
import { prisma } from '~/server/db';
|
||||||
import { getConfig } from '~/tools/config/getConfig';
|
import { getConfig } from '~/tools/config/getConfig';
|
||||||
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
|
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
|
||||||
import { api } from '~/utils/api';
|
|
||||||
import { useI18nZodResolver } from '~/utils/i18n-zod-resolver';
|
|
||||||
import { signUpFormSchema } from '~/validations/user';
|
|
||||||
|
|
||||||
export default function OnboardPage({
|
export default function OnboardPage({
|
||||||
configSchemaVersions,
|
configSchemaVersions,
|
||||||
@@ -54,7 +26,11 @@ export default function OnboardPage({
|
|||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<Stack h="100dvh" bg={background} spacing={0}>
|
<Stack h="100dvh" bg={background} spacing={0}>
|
||||||
<Center bg={fn.linearGradient(145, colors.red[7], colors.red[5])} h={175}>
|
<Center
|
||||||
|
bg={fn.linearGradient(145, colors.red[7], colors.red[5])}
|
||||||
|
mih={150}
|
||||||
|
h={150}
|
||||||
|
>
|
||||||
<Center bg={background} w={100} h={100} style={{ borderRadius: 64 }}>
|
<Center bg={background} w={100} h={100} style={{ borderRadius: 64 }}>
|
||||||
<Image width={70} src="/imgs/logo/logo-color.svg" alt="Homarr Logo" />
|
<Image width={70} src="/imgs/logo/logo-color.svg" alt="Homarr Logo" />
|
||||||
</Center>
|
</Center>
|
||||||
@@ -89,154 +65,6 @@ export default function OnboardPage({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
type StepContentComponent = (props: { isMobile: boolean; next: () => void }) => ReactNode;
|
|
||||||
|
|
||||||
const FirstStepContent: StepContentComponent = ({ isMobile, next }) => {
|
|
||||||
return (
|
|
||||||
<Stepper.Step label="First step" description="Create an account">
|
|
||||||
<Stack spacing={4} align="center">
|
|
||||||
<Title order={isMobile ? 3 : 1}>Hi there!</Title>
|
|
||||||
<Title order={isMobile ? 3 : 1}>Welcome to Homarr! 👋</Title>
|
|
||||||
</Stack>
|
|
||||||
<Text color="dimmed" size="lg" align="center">
|
|
||||||
Before you can use Homarr, you need to configure a few things.
|
|
||||||
</Text>
|
|
||||||
<Button onClick={next} size="lg" mt="sm" w={400} maw="90%">
|
|
||||||
Start configuration
|
|
||||||
</Button>
|
|
||||||
</Stepper.Step>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const SecondStepContent: StepContentComponent = ({ isMobile, next }) => {
|
|
||||||
const [isSigninIn, setIsSigninIn] = useState(false);
|
|
||||||
const { mutateAsync } = api.user.createOwnerAccount.useMutation();
|
|
||||||
const { i18nZodResolver } = useI18nZodResolver();
|
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof signUpFormSchema>>({
|
|
||||||
validate: i18nZodResolver(signUpFormSchema),
|
|
||||||
validateInputOnBlur: true,
|
|
||||||
});
|
|
||||||
const handleSubmit = (values: z.infer<typeof signUpFormSchema>) => {
|
|
||||||
setIsSigninIn(true);
|
|
||||||
void mutateAsync(values, {
|
|
||||||
onSuccess: () => {
|
|
||||||
signIn('credentials', {
|
|
||||||
redirect: false,
|
|
||||||
name: values.username,
|
|
||||||
password: values.password,
|
|
||||||
callbackUrl: '/',
|
|
||||||
}).then((response) => {
|
|
||||||
if (!response?.ok) {
|
|
||||||
setIsSigninIn(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Stepper.Step label="Second step" description="Create an account">
|
|
||||||
<Title order={isMobile ? 3 : 1}>Configure your credentials</Title>
|
|
||||||
<form
|
|
||||||
style={{ width: '100%', display: 'flex', justifyContent: 'center' }}
|
|
||||||
onSubmit={form.onSubmit(handleSubmit)}
|
|
||||||
>
|
|
||||||
<Stack w={400} maw="90%" spacing="sm" align="center">
|
|
||||||
<TextInput
|
|
||||||
size="md"
|
|
||||||
w="100%"
|
|
||||||
label="Username"
|
|
||||||
withAsterisk
|
|
||||||
{...form.getInputProps('username')}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<PasswordInput
|
|
||||||
size="md"
|
|
||||||
w="100%"
|
|
||||||
label="Password"
|
|
||||||
withAsterisk
|
|
||||||
{...form.getInputProps('password')}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<PasswordInput
|
|
||||||
size="md"
|
|
||||||
w="100%"
|
|
||||||
label="Confirm password"
|
|
||||||
withAsterisk
|
|
||||||
{...form.getInputProps('passwordConfirmation')}
|
|
||||||
/>
|
|
||||||
<Button mt="sm" fullWidth type="submit" loading={isSigninIn}>
|
|
||||||
Continue
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
</form>
|
|
||||||
</Stepper.Step>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const firstActions = [
|
|
||||||
{
|
|
||||||
icon: IconBook2,
|
|
||||||
label: 'Read the documentation',
|
|
||||||
href: 'https://homarr.dev/docs/introduction/after-the-installation',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: IconUserPlus,
|
|
||||||
label: 'Invite an user',
|
|
||||||
href: '/manage/users/invites',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: IconLayoutDashboard,
|
|
||||||
label: 'Setup your board',
|
|
||||||
href: '/board',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: IconUserCog,
|
|
||||||
label: 'Configure your profile',
|
|
||||||
href: '/user/preferences',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const ThirdStepContent: StepContentComponent = ({ isMobile, next }) => {
|
|
||||||
const { breakpoints } = useMantineTheme();
|
|
||||||
const { classes } = useStyles();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Stepper.Step label="Third step" description="Create an account">
|
|
||||||
<Title order={isMobile ? 3 : 1}>Get started! 🚀</Title>
|
|
||||||
<Grid w="100%" maw={breakpoints.sm} mt="xl">
|
|
||||||
{firstActions.map((action) => (
|
|
||||||
<Grid.Col key={action.label} sm={6}>
|
|
||||||
<UnstyledButton component={Link} href={action.href} w="100%">
|
|
||||||
<Card withBorder className={classes.button}>
|
|
||||||
<Group position="apart">
|
|
||||||
<Group>
|
|
||||||
<action.icon size={isMobile ? 16 : 20} stroke={1.5} />
|
|
||||||
<Title order={isMobile ? 6 : 5}>{action.label}</Title>
|
|
||||||
</Group>
|
|
||||||
|
|
||||||
<IconArrowRight size={isMobile ? 16 : 20} stroke={1.5} />
|
|
||||||
</Group>
|
|
||||||
</Card>
|
|
||||||
</UnstyledButton>
|
|
||||||
</Grid.Col>
|
|
||||||
))}
|
|
||||||
</Grid>
|
|
||||||
</Stepper.Step>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const useStyles = createStyles((theme) => ({
|
|
||||||
button: {
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[1],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
||||||
const userCount = await prisma.user.count();
|
const userCount = await prisma.user.count();
|
||||||
if (userCount >= 1) {
|
if (userCount >= 1) {
|
||||||
|
|||||||
Reference in New Issue
Block a user