From 74de89285986283ef65a7af19eddd76ffdc141c6 Mon Sep 17 00:00:00 2001 From: Manuel Date: Sat, 19 Aug 2023 12:16:00 +0200 Subject: [PATCH 1/7] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Onboarding=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 2 +- .gitignore | 3 +- package.json | 1 + public/imgs/app-icons/truenas.svg | 1 + public/imgs/app-icons/unraid-alt.svg | 1 + .../Onboarding/onboarding-steps.tsx | 41 +++++ .../Onboarding/step-create-account.tsx | 79 ++++++++ .../Onboarding/step-docker-import.tsx | 18 ++ .../Onboarding/step-documentation.tsx | 27 +++ .../Onboarding/step-onboarding-finished.tsx | 56 ++++++ .../Onboarding/step-update-path-mappings.tsx | 169 ++++++++++++++++++ src/pages/onboard.tsx | 103 ++++++----- yarn.lock | 25 +++ 13 files changed, 475 insertions(+), 51 deletions(-) create mode 100644 public/imgs/app-icons/truenas.svg create mode 100644 public/imgs/app-icons/unraid-alt.svg create mode 100644 src/components/Onboarding/onboarding-steps.tsx create mode 100644 src/components/Onboarding/step-create-account.tsx create mode 100644 src/components/Onboarding/step-docker-import.tsx create mode 100644 src/components/Onboarding/step-documentation.tsx create mode 100644 src/components/Onboarding/step-onboarding-finished.tsx create mode 100644 src/components/Onboarding/step-update-path-mappings.tsx diff --git a/.env.example b/.env.example index 37c6640d7..444562c2d 100644 --- a/.env.example +++ b/.env.example @@ -11,7 +11,7 @@ # Prisma # https://www.prisma.io/docs/reference/database-reference/connection-urls#env -DATABASE_URL="file:./db.sqlite" +DATABASE_URL="file:../database/db.sqlite" # Next Auth # You can generate a new secret on the command line with: diff --git a/.gitignore b/.gitignore index 4f96eb93c..9472a3696 100644 --- a/.gitignore +++ b/.gitignore @@ -58,4 +58,5 @@ public/locales/* !public/locales/en #database -prisma/db.sqlite \ No newline at end of file +prisma/db.sqlite +database/*.sqlite \ No newline at end of file diff --git a/package.json b/package.json index 4db04bb10..089a5013b 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "@mantine/modals": "^6.0.0", "@mantine/next": "^6.0.0", "@mantine/notifications": "^6.0.0", + "@mantine/prism": "^6.0.19", "@mantine/tiptap": "^6.0.17", "@next-auth/prisma-adapter": "^1.0.5", "@nivo/core": "^0.83.0", diff --git a/public/imgs/app-icons/truenas.svg b/public/imgs/app-icons/truenas.svg new file mode 100644 index 000000000..c3d96ff70 --- /dev/null +++ b/public/imgs/app-icons/truenas.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/imgs/app-icons/unraid-alt.svg b/public/imgs/app-icons/unraid-alt.svg new file mode 100644 index 000000000..7d695dadc --- /dev/null +++ b/public/imgs/app-icons/unraid-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/Onboarding/onboarding-steps.tsx b/src/components/Onboarding/onboarding-steps.tsx new file mode 100644 index 000000000..5b476c934 --- /dev/null +++ b/src/components/Onboarding/onboarding-steps.tsx @@ -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 ( + + + {isUpdate && ( + + + + )} + + + + + + + + + + + + + + + ); +}; diff --git a/src/components/Onboarding/step-create-account.tsx b/src/components/Onboarding/step-create-account.tsx new file mode 100644 index 000000000..245be24f8 --- /dev/null +++ b/src/components/Onboarding/step-create-account.tsx @@ -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>({ + validate: i18nZodResolver(signUpFormSchema), + validateInputOnBlur: true, + }); + const handleSubmit = (values: z.infer) => { + 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 ( + + + Create your administrator account + +
+ + + + + + + + +
+
+ ); +}; diff --git a/src/components/Onboarding/step-docker-import.tsx b/src/components/Onboarding/step-docker-import.tsx new file mode 100644 index 000000000..b2edd3e29 --- /dev/null +++ b/src/components/Onboarding/step-docker-import.tsx @@ -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 ( + + + Automatic container import + + + + + + + ); +}; diff --git a/src/components/Onboarding/step-documentation.tsx b/src/components/Onboarding/step-documentation.tsx new file mode 100644 index 000000000..1b5117a23 --- /dev/null +++ b/src/components/Onboarding/step-documentation.tsx @@ -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 ( + + + Documentation + + + + We highly encourage you to read the documentation, before you continue. + + + + + + ); +}; diff --git a/src/components/Onboarding/step-onboarding-finished.tsx b/src/components/Onboarding/step-onboarding-finished.tsx new file mode 100644 index 000000000..0d74317e3 --- /dev/null +++ b/src/components/Onboarding/step-onboarding-finished.tsx @@ -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 ( + + + + + Congratulations, you've set Homarr up! + + Awesome! What do you want to do next? + + + } + className={classes.link} + icon={} + label="Go to your board" + variant="light" + active + /> + } + className={classes.link} + icon={} + label="Go to the management dashboard" + variant="light" + active + /> + } + className={classes.link} + icon={} + label="Check out the documentation" + variant="light" + active + /> + + + + ); +}; + +const useStyles = createStyles((theme) => ({ + link: { + borderRadius: '0.4rem', + }, +})); diff --git a/src/components/Onboarding/step-update-path-mappings.tsx b/src/components/Onboarding/step-update-path-mappings.tsx new file mode 100644 index 000000000..7a1ef2173 --- /dev/null +++ b/src/components/Onboarding/step-update-path-mappings.tsx @@ -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(null); + return ( + + + 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. + + + + What is your installation method? + + setSelectedTab(tab)} mt="xs"> + + }> + Docker + + }> + Docker Compose + + }> + Standalone Linux / Windows + + } + > + Unraid + + }> + Others + + + + + + + + Back up your configuration. In case you didn't mount your configuration + correctly, you could risk loosing your dashboard. To back up, + go on your file system and copy the directory, containing your + default.json to your local machine. + + + + + 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. + + + + + Run docker rm homarr, where homarr indicates the name of + your container + + + + + Run docker run ... again, that you used to create the Homarr container. + Note, that you need to add a new line: + + + {dockerRunCommand} + + + Refresh this page and click on "continue" + + + + + + + + Back up your configuration. In case you didn't mount your configuration + correctly, you could risk loosing your dashboard. To back up, + go on your file system and copy the directory, containing your + default.json to your local machine. + + + + + Navigate to the directory, where the docker-compose.yml for Homarr is + located. + + + + + Run docker compose down + + + + + Edit docker-compose.yml using text editor. Use Notepad or VSC on GUI + based systems. Use nano or vim on terminal systems. + + + {dockerComposeCommand} + + + + + + + + You're lucky. For installation without Docker on Windows and Linux, there are no + additional steps required. However, be advised that your backups should start to include + the files located at /prisma too, if you run automatic backups. + + + + + + Click on your Homarr application and click "Edit" + Scroll down and click on the link "Add another path, port, variable or device" + After the new modal has opened, make sure that "Path" has been selected at the top + In the container path, enter /app/prisma + 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. /mnt/user/appdata/homarr/data) + + + + + 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: + /app/prisma + + + + {selectedTab && ( + + + + )} + + ); +}; diff --git a/src/pages/onboard.tsx b/src/pages/onboard.tsx index aa776bc2e..13effaced 100644 --- a/src/pages/onboard.tsx +++ b/src/pages/onboard.tsx @@ -3,12 +3,14 @@ import { Button, Card, Center, + Divider, Flex, Grid, Group, Image, PasswordInput, Stack, + Stepper, Text, TextInput, Title, @@ -17,32 +19,34 @@ import { useMantineTheme, } from '@mantine/core'; import { useForm } from '@mantine/form'; -import { useMediaQuery } from '@mantine/hooks'; +import { useDisclosure, useMediaQuery } from '@mantine/hooks'; import { IconLayoutDashboard, IconUserCog } from '@tabler/icons-react'; import { IconArrowRight, IconBook2, IconUserPlus } from '@tabler/icons-react'; -import { GetServerSideProps } from 'next'; +import fs from 'fs'; +import { GetServerSideProps, GetServerSidePropsResult, InferGetServerSidePropsType } from 'next'; import { signIn } from 'next-auth/react'; 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 { prisma } from '~/server/db'; +import { getConfig } from '~/tools/config/getConfig'; import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations'; import { api } from '~/utils/api'; import { useI18nZodResolver } from '~/utils/i18n-zod-resolver'; import { signUpFormSchema } from '~/validations/user'; -const getStepContents = () => [FirstStepContent, SecondStepContent, ThirdStepContent] as const; - -export default function OnboardPage() { - const { fn, colors, breakpoints, colorScheme } = useMantineTheme(); - const [currentStep, setStep] = useState(0); - const next = () => setStep((prev) => prev + 1); - const isSmallerThanMd = useMediaQuery(`(max-width: ${breakpoints.sm})`); - const stepContents = useMemo(() => getStepContents(), []); - const CurrentStepComponent = useMemo(() => stepContents[currentStep], [currentStep]); +export default function OnboardPage({ + configSchemaVersions, +}: InferGetServerSidePropsType) { + const { fn, colors, colorScheme } = useMantineTheme(); const background = colorScheme === 'dark' ? 'dark.6' : 'gray.1'; + const [onboardingSteps, { open: showOnboardingSteps }] = useDisclosure(false); + + const isUpgradeFromSchemaOne = configSchemaVersions.includes(1); + return ( <> @@ -50,50 +54,46 @@ export default function OnboardPage() { -
-
- Homarr Logo +
+
+ Homarr Logo
- - - {stepContents.map((_, index) => ( - - ))} - - - + + {onboardingSteps ? ( + + ) : ( +
+ + + Welcome to Homarr! + + + Your favorite dashboard has received a big upgrade. +
+ We'll help you update within the next few steps +
+ + +
+
+ )} ); } -type StepProps = { - isCurrent: boolean; - isMobile: boolean; - isDark: boolean; -}; -const Step = ({ isCurrent, isMobile, isDark }: StepProps) => { - return ( - - ); -}; - type StepContentComponent = (props: { isMobile: boolean; next: () => void }) => ReactNode; const FirstStepContent: StepContentComponent = ({ isMobile, next }) => { return ( - <> + Hi there! Welcome to Homarr! 👋 @@ -104,7 +104,7 @@ const FirstStepContent: StepContentComponent = ({ isMobile, next }) => { - + ); }; @@ -138,7 +138,7 @@ const SecondStepContent: StepContentComponent = ({ isMobile, next }) => { }; return ( - <> + Configure your credentials
{
- +
); }; @@ -205,7 +205,7 @@ const ThirdStepContent: StepContentComponent = ({ isMobile, next }) => { const { classes } = useStyles(); return ( - <> + Get started! 🚀 {firstActions.map((action) => ( @@ -225,7 +225,7 @@ const ThirdStepContent: StepContentComponent = ({ isMobile, next }) => { ))} - + ); }; @@ -245,11 +245,16 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => { }; } + const files = fs.readdirSync('./data/configs').filter((file) => file.endsWith('.json')); + const configs = files.map((file) => getConfig(file)); + const configSchemaVersions = configs.map((config) => config.schemaVersion); + const translations = await getServerSideTranslations([], ctx.locale, ctx.req, ctx.res); return { props: { ...translations, + configSchemaVersions: configSchemaVersions, }, }; }; diff --git a/yarn.lock b/yarn.lock index 7e6e74b8d..d1baa73ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1086,6 +1086,21 @@ __metadata: languageName: node linkType: hard +"@mantine/prism@npm:^6.0.19": + version: 6.0.19 + resolution: "@mantine/prism@npm:6.0.19" + dependencies: + "@mantine/utils": 6.0.19 + prism-react-renderer: ^1.2.1 + peerDependencies: + "@mantine/core": 6.0.19 + "@mantine/hooks": 6.0.19 + react: ">=16.8.0" + react-dom: ">=16.8.0" + checksum: ae806b6341a0a34831ffd04cd5254e0d37ae3946cb3a0d3fd774b2a86feca09815616a580a581af3338cd7f3574a4861fc79680501b207d8596787e4ddc5b447 + languageName: node + linkType: hard + "@mantine/ssr@npm:6.0.19": version: 6.0.19 resolution: "@mantine/ssr@npm:6.0.19" @@ -6179,6 +6194,7 @@ __metadata: "@mantine/modals": ^6.0.0 "@mantine/next": ^6.0.0 "@mantine/notifications": ^6.0.0 + "@mantine/prism": ^6.0.19 "@mantine/tiptap": ^6.0.17 "@next-auth/prisma-adapter": ^1.0.5 "@next/bundle-analyzer": ^13.0.0 @@ -8460,6 +8476,15 @@ __metadata: languageName: node linkType: hard +"prism-react-renderer@npm:^1.2.1": + version: 1.3.5 + resolution: "prism-react-renderer@npm:1.3.5" + peerDependencies: + react: ">=0.14.9" + checksum: c18806dcbc4c0b4fd6fd15bd06b4f7c0a6da98d93af235c3e970854994eb9b59e23315abb6cfc29e69da26d36709a47e25da85ab27fed81b6812f0a52caf6dfa + languageName: node + linkType: hard + "prisma@npm:^5.0.0": version: 5.1.1 resolution: "prisma@npm:5.1.1" From 64764a253b7591cfbcd0e31fa083e5ca88e4a6b7 Mon Sep 17 00:00:00 2001 From: Manuel Date: Sat, 19 Aug 2023 12:16:38 +0200 Subject: [PATCH 2/7] =?UTF-8?q?=F0=9F=93=9D=20Update=20database=20mapping?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Onboarding/step-update-path-mappings.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/Onboarding/step-update-path-mappings.tsx b/src/components/Onboarding/step-update-path-mappings.tsx index 7a1ef2173..5ddbf7f92 100644 --- a/src/components/Onboarding/step-update-path-mappings.tsx +++ b/src/components/Onboarding/step-update-path-mappings.tsx @@ -9,7 +9,7 @@ const dockerRunCommand = `docker run \\ --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/data:/app/database \\ -v your-path/homarr/icons:/app/public/icons \\ -d ghcr.io/ajnart/homarr:latest`; @@ -24,7 +24,7 @@ services: restart: unless-stopped volumes: - ./homarr/configs:/app/data/configs - - ./homarr/data:/app/prisma + - ./homarr/data:/app/database - ./homarr/icons:/app/public/icons ports: - '7575:7575'`; @@ -139,7 +139,7 @@ export const StepUpdatePathMappings = ({ next }: { next: () => void }) => { You're lucky. For installation without Docker on Windows and Linux, there are no additional steps required. However, be advised that your backups should start to include - the files located at /prisma too, if you run automatic backups. + the files located at /database too, if you run automatic backups. @@ -148,14 +148,14 @@ export const StepUpdatePathMappings = ({ next }: { next: () => void }) => { Click on your Homarr application and click "Edit" Scroll down and click on the link "Add another path, port, variable or device" After the new modal has opened, make sure that "Path" has been selected at the top - In the container path, enter /app/prisma + In the container path, enter /app/database 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. /mnt/user/appdata/homarr/data) 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: - /app/prisma + /app/database From 3623d871f89066244a2ecd5fc32bf98d0826780e Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 21 Aug 2023 21:10:44 +0200 Subject: [PATCH 3/7] =?UTF-8?q?=F0=9F=92=84=20Improve=20design?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Onboarding/common-wrapper.tsx | 10 +++ .../Onboarding/step-create-account.tsx | 11 +-- .../Onboarding/step-docker-import.tsx | 8 ++- .../Onboarding/step-documentation.tsx | 12 ++-- .../Onboarding/step-update-path-mappings.tsx | 70 ++++++++++++++----- 5 files changed, 81 insertions(+), 30 deletions(-) create mode 100644 src/components/Onboarding/common-wrapper.tsx diff --git a/src/components/Onboarding/common-wrapper.tsx b/src/components/Onboarding/common-wrapper.tsx new file mode 100644 index 000000000..09df0005f --- /dev/null +++ b/src/components/Onboarding/common-wrapper.tsx @@ -0,0 +1,10 @@ +import { Card } from '@mantine/core'; +import { ReactNode } from 'react'; + +export const OnboardingStepWrapper = ({ children }: { children: ReactNode }) => { + return ( + + {children} + + ); +}; diff --git a/src/components/Onboarding/step-create-account.tsx b/src/components/Onboarding/step-create-account.tsx index 245be24f8..a2dc50fbb 100644 --- a/src/components/Onboarding/step-create-account.tsx +++ b/src/components/Onboarding/step-create-account.tsx @@ -1,4 +1,4 @@ -import { Button, Card, PasswordInput, Stack, TextInput, Title } from '@mantine/core'; +import { Button, PasswordInput, Stack, TextInput, Title } from '@mantine/core'; import { useForm } from '@mantine/form'; import { signIn } from 'next-auth/react'; import { useState } from 'react'; @@ -7,6 +7,8 @@ import { api } from '~/utils/api'; import { useI18nZodResolver } from '~/utils/i18n-zod-resolver'; import { signUpFormSchema } from '~/validations/user'; +import { OnboardingStepWrapper } from './common-wrapper'; + export const StepCreateAccount = ({ next }: { next: () => void }) => { const [isSigninIn, setIsSigninIn] = useState(false); const { mutateAsync } = api.user.createOwnerAccount.useMutation(); @@ -37,15 +39,14 @@ export const StepCreateAccount = ({ next }: { next: () => void }) => { }; return ( - + Create your administrator account
- + void }) => { -
+ ); }; diff --git a/src/components/Onboarding/step-docker-import.tsx b/src/components/Onboarding/step-docker-import.tsx index b2edd3e29..ac53983d7 100644 --- a/src/components/Onboarding/step-docker-import.tsx +++ b/src/components/Onboarding/step-docker-import.tsx @@ -1,9 +1,11 @@ -import { Button, Card, Stack, Title } from '@mantine/core'; +import { Button, Stack, Title } from '@mantine/core'; import { IconArrowRight } from '@tabler/icons-react'; +import { OnboardingStepWrapper } from './common-wrapper'; + export const StepDockerImport = ({ next }: { next: () => void }) => { return ( - + Automatic container import @@ -13,6 +15,6 @@ export const StepDockerImport = ({ next }: { next: () => void }) => { Next - + ); }; diff --git a/src/components/Onboarding/step-documentation.tsx b/src/components/Onboarding/step-documentation.tsx index 1b5117a23..0884e44dd 100644 --- a/src/components/Onboarding/step-documentation.tsx +++ b/src/components/Onboarding/step-documentation.tsx @@ -1,9 +1,11 @@ -import { Button, Card, Divider, Stack, Text, Title } from '@mantine/core'; +import { Button, Divider, Stack, Text, Title } from '@mantine/core'; import { IconArrowRight, IconLink } from '@tabler/icons-react'; +import { OnboardingStepWrapper } from './common-wrapper'; + export const StepDocumentation = ({ next }: { next: () => void }) => { return ( - + Documentation @@ -20,8 +22,10 @@ export const StepDocumentation = ({ next }: { next: () => void }) => { Open documentation - + - + ); }; diff --git a/src/components/Onboarding/step-update-path-mappings.tsx b/src/components/Onboarding/step-update-path-mappings.tsx index 5ddbf7f92..13419b770 100644 --- a/src/components/Onboarding/step-update-path-mappings.tsx +++ b/src/components/Onboarding/step-update-path-mappings.tsx @@ -1,9 +1,16 @@ -import { Button, Card, Code, Group, List, Tabs, TabsValue, Text } from '@mantine/core'; +import { Box, Button, Code, Group, List, Space, Tabs, TabsValue, Text, Title } from '@mantine/core'; import { Prism } from '@mantine/prism'; -import { IconArrowRight, IconBrandDebian, IconBrandDocker, IconInfoSquareRounded } from '@tabler/icons-react'; +import { + IconArrowRight, + IconBrandDebian, + IconBrandDocker, + IconInfoSquareRounded, +} from '@tabler/icons-react'; import Image from 'next/image'; import { useState } from 'react'; +import { OnboardingStepWrapper } from './common-wrapper'; + const dockerRunCommand = `docker run \\ --name homarr \\ --restart unless-stopped \\ @@ -34,18 +41,19 @@ const added = { color: 'green', label: '+' }; export const StepUpdatePathMappings = ({ next }: { next: () => void }) => { const [selectedTab, setSelectedTab] = useState(null); return ( - + + + Update path mappings + 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. - - What is your installation method? - + setSelectedTab(tab)} mt="xs"> - + }> Docker @@ -67,7 +75,7 @@ export const StepUpdatePathMappings = ({ next }: { next: () => void }) => { - + Back up your configuration. In case you didn't mount your configuration @@ -103,7 +111,7 @@ export const StepUpdatePathMappings = ({ next }: { next: () => void }) => { - + Back up your configuration. In case you didn't mount your configuration @@ -144,26 +152,52 @@ export const StepUpdatePathMappings = ({ next }: { next: () => void }) => { - + Click on your Homarr application and click "Edit" - Scroll down and click on the link "Add another path, port, variable or device" - After the new modal has opened, make sure that "Path" has been selected at the top - In the container path, enter /app/database - 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. /mnt/user/appdata/homarr/data) + + Scroll down and click on the link "Add another path, port, variable or device" + + + After the new modal has opened, make sure that "Path" has been selected at the top + + + In the container path, enter /app/database + + + 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.{' '} + /mnt/user/appdata/homarr/data) + - 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: + + 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: + /app/database - {selectedTab && ( + {selectedTab ? ( - + + ) : ( + + + Please select your installation method + + )} - + ); }; From 480b27fea7c60f5d8502973d2942dbf992b3566b Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 21 Aug 2023 21:15:56 +0200 Subject: [PATCH 4/7] =?UTF-8?q?=E2=9C=A8=20Add=20back=20button=20to=20crea?= =?UTF-8?q?te=20account=20step?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Onboarding/onboarding-steps.tsx | 2 +- .../Onboarding/step-create-account.tsx | 34 ++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/components/Onboarding/onboarding-steps.tsx b/src/components/Onboarding/onboarding-steps.tsx index 5b476c934..c475aa14f 100644 --- a/src/components/Onboarding/onboarding-steps.tsx +++ b/src/components/Onboarding/onboarding-steps.tsx @@ -24,7 +24,7 @@ export const OnboardingSteps = ({ isUpdate }: { isUpdate: boolean }) => { )} - + diff --git a/src/components/Onboarding/step-create-account.tsx b/src/components/Onboarding/step-create-account.tsx index a2dc50fbb..de7a8b3d8 100644 --- a/src/components/Onboarding/step-create-account.tsx +++ b/src/components/Onboarding/step-create-account.tsx @@ -1,5 +1,6 @@ -import { Button, PasswordInput, Stack, TextInput, Title } from '@mantine/core'; +import { Button, Group, PasswordInput, Stack, TextInput, Title } from '@mantine/core'; import { useForm } from '@mantine/form'; +import { IconArrowLeft, IconArrowRight } from '@tabler/icons-react'; import { signIn } from 'next-auth/react'; import { useState } from 'react'; import { z } from 'zod'; @@ -9,7 +10,13 @@ import { signUpFormSchema } from '~/validations/user'; import { OnboardingStepWrapper } from './common-wrapper'; -export const StepCreateAccount = ({ next }: { next: () => void }) => { +export const StepCreateAccount = ({ + previous, + next, +}: { + previous: () => void; + next: () => void; +}) => { const [isSigninIn, setIsSigninIn] = useState(false); const { mutateAsync } = api.user.createOwnerAccount.useMutation(); const { i18nZodResolver } = useI18nZodResolver(); @@ -43,14 +50,13 @@ export const StepCreateAccount = ({ next }: { next: () => void }) => { Create your administrator account -
+ @@ -59,6 +65,7 @@ export const StepCreateAccount = ({ next }: { next: () => void }) => { size="md" w="100%" label="Password" + variant="filled" withAsterisk {...form.getInputProps('password')} /> @@ -67,12 +74,23 @@ export const StepCreateAccount = ({ next }: { next: () => void }) => { size="md" w="100%" label="Confirm password" + variant="filled" withAsterisk {...form.getInputProps('passwordConfirmation')} /> - + + + +
From cfde1b6ece43aa2ecc06061d62ecc02498ffa59e Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 21 Aug 2023 21:23:28 +0200 Subject: [PATCH 5/7] =?UTF-8?q?=F0=9F=92=84=20Normalize=20onboarding=20ste?= =?UTF-8?q?ps=20design?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Onboarding/step-docker-import.tsx | 2 +- src/components/Onboarding/step-documentation.tsx | 10 +++++----- src/components/Onboarding/step-onboarding-finished.tsx | 8 +++++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/components/Onboarding/step-docker-import.tsx b/src/components/Onboarding/step-docker-import.tsx index ac53983d7..5d65e7466 100644 --- a/src/components/Onboarding/step-docker-import.tsx +++ b/src/components/Onboarding/step-docker-import.tsx @@ -11,7 +11,7 @@ export const StepDockerImport = ({ next }: { next: () => void }) => { - diff --git a/src/components/Onboarding/step-documentation.tsx b/src/components/Onboarding/step-documentation.tsx index 0884e44dd..6b2a32dd2 100644 --- a/src/components/Onboarding/step-documentation.tsx +++ b/src/components/Onboarding/step-documentation.tsx @@ -1,5 +1,5 @@ import { Button, Divider, Stack, Text, Title } from '@mantine/core'; -import { IconArrowRight, IconLink } from '@tabler/icons-react'; +import { IconArrowRight, IconExternalLink } from '@tabler/icons-react'; import { OnboardingStepWrapper } from './common-wrapper'; @@ -16,13 +16,13 @@ export const StepDocumentation = ({ next }: { next: () => void }) => { component="a" href="https://homarr.dev/docs/introduction/after-the-installation" target="_blank" - leftIcon={} - variant="light" + rightIcon={} + variant="default" > Open documentation - - diff --git a/src/components/Onboarding/step-onboarding-finished.tsx b/src/components/Onboarding/step-onboarding-finished.tsx index 0d74317e3..22f260459 100644 --- a/src/components/Onboarding/step-onboarding-finished.tsx +++ b/src/components/Onboarding/step-onboarding-finished.tsx @@ -1,4 +1,4 @@ -import { Box, Card, NavLink, Stack, Text, Title, createStyles } from '@mantine/core'; +import { NavLink, Stack, Text, Title, createStyles } from '@mantine/core'; import { IconChevronRight, IconDashboard, @@ -7,10 +7,12 @@ import { } from '@tabler/icons-react'; import Image from 'next/image'; +import { OnboardingStepWrapper } from './common-wrapper'; + export const StepOnboardingFinished = () => { const { classes } = useStyles(); return ( - + @@ -45,7 +47,7 @@ export const StepOnboardingFinished = () => { /> </Stack> </Stack> - </Card> + </OnboardingStepWrapper> ); }; From e8fa3b5e9a7f75184c8ec5fd1341181cbae8e27a Mon Sep 17 00:00:00 2001 From: Manuel <manuel.ruwe@bluewin.ch> Date: Mon, 21 Aug 2023 21:37:35 +0200 Subject: [PATCH 6/7] =?UTF-8?q?=F0=9F=90=9B=20Header=20scaling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Onboarding/onboarding-steps.tsx | 11 +- .../Onboarding/step-update-path-mappings.tsx | 4 + src/pages/onboard.tsx | 190 +----------------- 3 files changed, 21 insertions(+), 184 deletions(-) diff --git a/src/components/Onboarding/onboarding-steps.tsx b/src/components/Onboarding/onboarding-steps.tsx index c475aa14f..036f4fb31 100644 --- a/src/components/Onboarding/onboarding-steps.tsx +++ b/src/components/Onboarding/onboarding-steps.tsx @@ -1,11 +1,11 @@ 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'; +import { StepOnboardingFinished } from './step-onboarding-finished'; +import { StepUpdatePathMappings } from './step-update-path-mappings'; export const OnboardingSteps = ({ isUpdate }: { isUpdate: boolean }) => { const [currentStep, setCurrentStep] = useState(0); @@ -14,7 +14,12 @@ export const OnboardingSteps = ({ isUpdate }: { isUpdate: boolean }) => { return ( <Stack p="lg"> - <Stepper active={currentStep} onStepClick={setCurrentStep} breakpoint="sm"> + <Stepper + allowNextStepsSelect={false} + active={currentStep} + onStepClick={setCurrentStep} + breakpoint="sm" + > {isUpdate && ( <Stepper.Step label="Update your installation" diff --git a/src/components/Onboarding/step-update-path-mappings.tsx b/src/components/Onboarding/step-update-path-mappings.tsx index 13419b770..13803debb 100644 --- a/src/components/Onboarding/step-update-path-mappings.tsx +++ b/src/components/Onboarding/step-update-path-mappings.tsx @@ -140,6 +140,8 @@ export const StepUpdatePathMappings = ({ next }: { next: () => void }) => { {dockerComposeCommand} </Prism> </List.Item> + <List.Item>Run <Code>docker compose up</Code>.</List.Item> + <List.Item>Refresh this page and click on "continue"</List.Item> </List> </Tabs.Panel> @@ -168,6 +170,8 @@ export const StepUpdatePathMappings = ({ next }: { next: () => void }) => { innermost directory should be different, than your existing mounting points (eg.{' '} <Code>/mnt/user/appdata/homarr/data</Code>) </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> </Tabs.Panel> diff --git a/src/pages/onboard.tsx b/src/pages/onboard.tsx index 13effaced..c93ceb93b 100644 --- a/src/pages/onboard.tsx +++ b/src/pages/onboard.tsx @@ -1,41 +1,13 @@ -import { - Box, - Button, - 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 { Box, Button, Center, Image, Stack, Text, Title, useMantineTheme } from '@mantine/core'; +import { useDisclosure } from '@mantine/hooks'; +import { IconArrowRight } from '@tabler/icons-react'; import fs from 'fs'; -import { GetServerSideProps, GetServerSidePropsResult, InferGetServerSidePropsType } from 'next'; -import { signIn } from 'next-auth/react'; +import { GetServerSideProps, InferGetServerSidePropsType } from 'next'; 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 { prisma } from '~/server/db'; import { getConfig } from '~/tools/config/getConfig'; 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({ configSchemaVersions, @@ -54,7 +26,11 @@ export default function OnboardPage({ </Head> <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 }}> <Image width={70} src="/imgs/logo/logo-color.svg" alt="Homarr Logo" /> </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! - Welcome to Homarr! 👋 - - - Before you can use Homarr, you need to configure a few things. - - -
- ); -}; - -const SecondStepContent: StepContentComponent = ({ isMobile, next }) => { - const [isSigninIn, setIsSigninIn] = useState(false); - const { mutateAsync } = api.user.createOwnerAccount.useMutation(); - const { i18nZodResolver } = useI18nZodResolver(); - - const form = useForm>({ - validate: i18nZodResolver(signUpFormSchema), - validateInputOnBlur: true, - }); - const handleSubmit = (values: z.infer) => { - 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 ( - - Configure your credentials -
- - - - - - - - -
-
- ); -}; - -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 ( - - Get started! 🚀 - - {firstActions.map((action) => ( - - - - - - - {action.label} - - - - - - - - ))} - - - ); -}; - -const useStyles = createStyles((theme) => ({ - button: { - '&:hover': { - backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[1], - }, - }, -})); - export const getServerSideProps: GetServerSideProps = async (ctx) => { const userCount = await prisma.user.count(); if (userCount >= 1) { From 4d73395eaeadfbfa75282cf74c9163191e97f300 Mon Sep 17 00:00:00 2001 From: Thomas Camlong Date: Tue, 22 Aug 2023 12:41:11 +0200 Subject: [PATCH 7/7] =?UTF-8?q?=F0=9F=90=9B=20Update=20default=20selected?= =?UTF-8?q?=20option=20in=20path=20mappings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Onboarding/step-update-path-mappings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Onboarding/step-update-path-mappings.tsx b/src/components/Onboarding/step-update-path-mappings.tsx index 13803debb..02c32762b 100644 --- a/src/components/Onboarding/step-update-path-mappings.tsx +++ b/src/components/Onboarding/step-update-path-mappings.tsx @@ -39,7 +39,7 @@ services: const added = { color: 'green', label: '+' }; export const StepUpdatePathMappings = ({ next }: { next: () => void }) => { - const [selectedTab, setSelectedTab] = useState(null); + const [selectedTab, setSelectedTab] = useState("standard_docker"); return (