mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-11 16:05:47 +01:00
♻️ Onboarding page
This commit is contained in:
41
src/components/Onboarding/onboarding-steps.tsx
Normal file
41
src/components/Onboarding/onboarding-steps.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { Stack, Stepper } from '@mantine/core';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { StepUpdatePathMappings } from './step-update-path-mappings';
|
||||
import { StepCreateAccount } from './step-create-account';
|
||||
import { StepOnboardingFinished } from './step-onboarding-finished';
|
||||
import { StepDockerImport } from './step-docker-import';
|
||||
import { StepDocumentation } from './step-documentation';
|
||||
|
||||
export const OnboardingSteps = ({ isUpdate }: { isUpdate: boolean }) => {
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const nextStep = () => setCurrentStep((current) => (current < 4 ? current + 1 : current));
|
||||
const prevStep = () => setCurrentStep((current) => (current > 0 ? current - 1 : current));
|
||||
|
||||
return (
|
||||
<Stack p="lg">
|
||||
<Stepper active={currentStep} onStepClick={setCurrentStep} breakpoint="sm">
|
||||
{isUpdate && (
|
||||
<Stepper.Step
|
||||
label="Update your installation"
|
||||
description="Adjust path mappings and variables"
|
||||
>
|
||||
<StepUpdatePathMappings next={nextStep} />
|
||||
</Stepper.Step>
|
||||
)}
|
||||
<Stepper.Step label="Your account" description="Create an account">
|
||||
<StepCreateAccount next={nextStep} />
|
||||
</Stepper.Step>
|
||||
<Stepper.Step label="Docker import" description="Import applications from Docker">
|
||||
<StepDockerImport next={nextStep} />
|
||||
</Stepper.Step>
|
||||
<Stepper.Step label="Documentation" description="Introduction into Homarr">
|
||||
<StepDocumentation next={nextStep} />
|
||||
</Stepper.Step>
|
||||
<Stepper.Completed>
|
||||
<StepOnboardingFinished />
|
||||
</Stepper.Completed>
|
||||
</Stepper>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
79
src/components/Onboarding/step-create-account.tsx
Normal file
79
src/components/Onboarding/step-create-account.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import { Button, Card, PasswordInput, Stack, TextInput, Title } from '@mantine/core';
|
||||
import { useForm } from '@mantine/form';
|
||||
import { signIn } from 'next-auth/react';
|
||||
import { useState } from 'react';
|
||||
import { z } from 'zod';
|
||||
import { api } from '~/utils/api';
|
||||
import { useI18nZodResolver } from '~/utils/i18n-zod-resolver';
|
||||
import { signUpFormSchema } from '~/validations/user';
|
||||
|
||||
export const StepCreateAccount = ({ next }: { next: () => void }) => {
|
||||
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 (
|
||||
<Card shadow="lg" withBorder>
|
||||
<Title order={2} align="center" mb="md">
|
||||
Create your administrator account
|
||||
</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 disabled={!form.isValid()} mt="sm" fullWidth type="submit" loading={isSigninIn}>
|
||||
Continue
|
||||
</Button>
|
||||
</Stack>
|
||||
</form>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
18
src/components/Onboarding/step-docker-import.tsx
Normal file
18
src/components/Onboarding/step-docker-import.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Button, Card, Stack, Title } from '@mantine/core';
|
||||
import { IconArrowRight } from '@tabler/icons-react';
|
||||
|
||||
export const StepDockerImport = ({ next }: { next: () => void }) => {
|
||||
return (
|
||||
<Card>
|
||||
<Title order={2} align="center" mb="lg">
|
||||
Automatic container import
|
||||
</Title>
|
||||
|
||||
<Stack align="center">
|
||||
<Button onClick={next} rightIcon={<IconArrowRight size="1rem" />}>
|
||||
Next
|
||||
</Button>
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
27
src/components/Onboarding/step-documentation.tsx
Normal file
27
src/components/Onboarding/step-documentation.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Button, Card, Divider, Stack, Text, Title } from '@mantine/core';
|
||||
import { IconArrowRight, IconLink } from '@tabler/icons-react';
|
||||
|
||||
export const StepDocumentation = ({ next }: { next: () => void }) => {
|
||||
return (
|
||||
<Card>
|
||||
<Title order={2} align="center" mb="lg">
|
||||
Documentation
|
||||
</Title>
|
||||
|
||||
<Stack align="center">
|
||||
<Text>We highly encourage you to read the documentation, before you continue.</Text>
|
||||
<Button
|
||||
component="a"
|
||||
href="https://homarr.dev/docs/introduction/after-the-installation"
|
||||
target="_blank"
|
||||
leftIcon={<IconLink size="1rem" />}
|
||||
variant="light"
|
||||
>
|
||||
Open documentation
|
||||
</Button>
|
||||
<Divider w={400} maw="100%" />
|
||||
<Button onClick={next} rightIcon={<IconArrowRight size="1rem" />}>Finish</Button>
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
56
src/components/Onboarding/step-onboarding-finished.tsx
Normal file
56
src/components/Onboarding/step-onboarding-finished.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import { Box, Card, NavLink, Stack, Text, Title, createStyles } from '@mantine/core';
|
||||
import {
|
||||
IconChevronRight,
|
||||
IconDashboard,
|
||||
IconFileText,
|
||||
IconManualGearbox,
|
||||
} from '@tabler/icons-react';
|
||||
import Image from 'next/image';
|
||||
|
||||
export const StepOnboardingFinished = () => {
|
||||
const { classes } = useStyles();
|
||||
return (
|
||||
<Card>
|
||||
<Stack align="center">
|
||||
<Image src="/imgs/logo/logo.svg" alt="" width={50} height={50} />
|
||||
<Title order={2} align="center">
|
||||
Congratulations, you've set Homarr up!
|
||||
</Title>
|
||||
<Text>Awesome! What do you want to do next?</Text>
|
||||
|
||||
<Stack>
|
||||
<NavLink
|
||||
rightSection={<IconChevronRight size="0.8rem" stroke={1.5} />}
|
||||
className={classes.link}
|
||||
icon={<IconDashboard />}
|
||||
label="Go to your board"
|
||||
variant="light"
|
||||
active
|
||||
/>
|
||||
<NavLink
|
||||
rightSection={<IconChevronRight size="0.8rem" stroke={1.5} />}
|
||||
className={classes.link}
|
||||
icon={<IconManualGearbox />}
|
||||
label="Go to the management dashboard"
|
||||
variant="light"
|
||||
active
|
||||
/>
|
||||
<NavLink
|
||||
rightSection={<IconChevronRight size="0.8rem" stroke={1.5} />}
|
||||
className={classes.link}
|
||||
icon={<IconFileText />}
|
||||
label="Check out the documentation"
|
||||
variant="light"
|
||||
active
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
link: {
|
||||
borderRadius: '0.4rem',
|
||||
},
|
||||
}));
|
||||
169
src/components/Onboarding/step-update-path-mappings.tsx
Normal file
169
src/components/Onboarding/step-update-path-mappings.tsx
Normal file
@@ -0,0 +1,169 @@
|
||||
import { Button, Card, Code, Group, List, Tabs, TabsValue, Text } from '@mantine/core';
|
||||
import { Prism } from '@mantine/prism';
|
||||
import { IconArrowRight, IconBrandDebian, IconBrandDocker, IconInfoSquareRounded } from '@tabler/icons-react';
|
||||
import Image from 'next/image';
|
||||
import { useState } from 'react';
|
||||
|
||||
const dockerRunCommand = `docker run \\
|
||||
--name homarr \\
|
||||
--restart unless-stopped \\
|
||||
-p 7575:7575 \\
|
||||
-v your-path/homarr/configs:/app/data/configs \\
|
||||
-v your-path/homarr/data:/app/prisma \\
|
||||
-v your-path/homarr/icons:/app/public/icons \\
|
||||
-d ghcr.io/ajnart/homarr:latest`;
|
||||
|
||||
const dockerComposeCommand = `version: '3'
|
||||
#---------------------------------------------------------------------#
|
||||
# Homarr - A simple, yet powerful dashboard for your server. #
|
||||
#---------------------------------------------------------------------#
|
||||
services:
|
||||
homarr:
|
||||
container_name: homarr
|
||||
image: ghcr.io/ajnart/homarr:latest
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./homarr/configs:/app/data/configs
|
||||
- ./homarr/data:/app/prisma
|
||||
- ./homarr/icons:/app/public/icons
|
||||
ports:
|
||||
- '7575:7575'`;
|
||||
|
||||
const added = { color: 'green', label: '+' };
|
||||
|
||||
export const StepUpdatePathMappings = ({ next }: { next: () => void }) => {
|
||||
const [selectedTab, setSelectedTab] = useState<TabsValue | null>(null);
|
||||
return (
|
||||
<Card shadow="lg" withBorder>
|
||||
<Text color="dimmed">
|
||||
Homarr has updated the location of the saved data. We detected, that your instance might
|
||||
need an update to function as expected. It is recommended, that you take a backup of your
|
||||
.json configuration file on the file system and copy it, in case something goes wrong.
|
||||
</Text>
|
||||
|
||||
<Text weight="bold" mt="xl">
|
||||
What is your installation method?
|
||||
</Text>
|
||||
<Tabs value={selectedTab} onTabChange={(tab) => setSelectedTab(tab)} mt="xs">
|
||||
<Tabs.List>
|
||||
<Tabs.Tab value="standard_docker" icon={<IconBrandDocker size={16} />}>
|
||||
Docker
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab value="docker_compose" icon={<IconBrandDocker size={16} />}>
|
||||
Docker Compose
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab value="standalone" icon={<IconBrandDebian size={16} />}>
|
||||
Standalone Linux / Windows
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
value="unraid"
|
||||
icon={<Image width={16} height={16} src="/imgs/app-icons/unraid-alt.svg" alt="" />}
|
||||
>
|
||||
Unraid
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab value="others" icon={<IconInfoSquareRounded size={16} />}>
|
||||
Others
|
||||
</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
|
||||
<Tabs.Panel value="standard_docker" pt="xs">
|
||||
<List>
|
||||
<List.Item>
|
||||
<Text>
|
||||
<b>Back up your configuration</b>. In case you didn't mount your configuration
|
||||
correctly, you could risk loosing your dashboard. To back up,
|
||||
<b>go on your file system and copy the directory, containing your </b>
|
||||
<Code>default.json</Code> to your local machine.
|
||||
</Text>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Text>
|
||||
Before you continue, check that you still have the command, that you set up Homarr
|
||||
with. Otherwise, your configuration might not be loaded correctly or icons are
|
||||
missing.
|
||||
</Text>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Text>
|
||||
Run <Code>docker rm homarr</Code>, where <Code>homarr</Code> indicates the name of
|
||||
your container
|
||||
</Text>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Text>
|
||||
Run <Code>docker run ...</Code> again, that you used to create the Homarr container.
|
||||
Note, that you need to add a new line:
|
||||
</Text>
|
||||
<Prism highlightLines={{ 6: added }} language="bash" withLineNumbers>
|
||||
{dockerRunCommand}
|
||||
</Prism>
|
||||
</List.Item>
|
||||
<List.Item>Refresh this page and click on "continue"</List.Item>
|
||||
</List>
|
||||
</Tabs.Panel>
|
||||
|
||||
<Tabs.Panel value="docker_compose" pt="xs">
|
||||
<List>
|
||||
<List.Item>
|
||||
<Text>
|
||||
<b>Back up your configuration</b>. In case you didn't mount your configuration
|
||||
correctly, you could risk loosing your dashboard. To back up,
|
||||
<b>go on your file system and copy the directory, containing your </b>
|
||||
<Code>default.json</Code> to your local machine.
|
||||
</Text>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Text>
|
||||
Navigate to the directory, where the <Code>docker-compose.yml</Code> for Homarr is
|
||||
located.
|
||||
</Text>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Text>
|
||||
Run <Code>docker compose down</Code>
|
||||
</Text>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Text>
|
||||
Edit <Code>docker-compose.yml</Code> using text editor. Use Notepad or VSC on GUI
|
||||
based systems. Use <Code>nano</Code> or <Code>vim</Code> on terminal systems.
|
||||
</Text>
|
||||
<Prism highlightLines={{ 12: added }} language="bash" withLineNumbers>
|
||||
{dockerComposeCommand}
|
||||
</Prism>
|
||||
</List.Item>
|
||||
</List>
|
||||
</Tabs.Panel>
|
||||
|
||||
<Tabs.Panel value="standalone" pt="xs">
|
||||
<Text>
|
||||
You're lucky. For installation <b>without Docker</b> on Windows and Linux, there are no
|
||||
additional steps required. However, be advised that your backups should start to include
|
||||
the files located at <Code>/prisma</Code> too, if you run automatic backups.
|
||||
</Text>
|
||||
</Tabs.Panel>
|
||||
|
||||
<Tabs.Panel value="unraid" pt="xs">
|
||||
<List>
|
||||
<List.Item>Click on your Homarr application and click "Edit"</List.Item>
|
||||
<List.Item>Scroll down and click on the link "Add another path, port, variable or device"</List.Item>
|
||||
<List.Item>After the new modal has opened, make sure that "Path" has been selected at the top</List.Item>
|
||||
<List.Item>In the container path, enter <Code>/app/prisma</Code></List.Item>
|
||||
<List.Item>In the host path, enter a new path on your host system. Choose a similar path, but the innermost directory should be different, than your existing mounting points (eg. <Code>/mnt/user/appdata/homarr/data</Code>)</List.Item>
|
||||
</List>
|
||||
</Tabs.Panel>
|
||||
|
||||
<Tabs.Panel value="others" pt="xs">
|
||||
<Text>We are sadly not able to include upgrade guides for all kind of systems. If your system was not listed, you should mount this new mounting point in your container:</Text>
|
||||
<Code>/app/prisma</Code>
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
|
||||
{selectedTab && (
|
||||
<Group align="end" mt="lg">
|
||||
<Button onClick={next} rightIcon={<IconArrowRight />}>Continue</Button>
|
||||
</Group>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user