mirror of https://github.com/renzynx/bliss.git
restructure file tree
This commit is contained in:
parent
d96d7582c5
commit
a85753aa03
|
@ -1,101 +0,0 @@
|
|||
import LoadingPage from '@components/LoadingPage';
|
||||
import { ROUTES } from '@lib/constants';
|
||||
import { useRegister } from '@lib/hooks';
|
||||
import { ServerSettings } from '@lib/types';
|
||||
import {
|
||||
Paper,
|
||||
Stack,
|
||||
Group,
|
||||
TextInput,
|
||||
PasswordInput,
|
||||
Anchor,
|
||||
Button,
|
||||
Text,
|
||||
} from '@mantine/core';
|
||||
import { IconUser } from '@tabler/icons';
|
||||
|
||||
function SignUpForm({ settings }: { settings: ServerSettings }) {
|
||||
const { form, loading, register } = useRegister();
|
||||
|
||||
if (!settings) {
|
||||
return <LoadingPage />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Paper
|
||||
w={{
|
||||
base: '95%',
|
||||
lg: 450,
|
||||
md: 420,
|
||||
sm: 450,
|
||||
xs: 450,
|
||||
}}
|
||||
pt="xl"
|
||||
pb="xl"
|
||||
pr="lg"
|
||||
pl="lg"
|
||||
withBorder={true}
|
||||
>
|
||||
{!settings.REGISTRATION_ENABLED ? (
|
||||
<Text size="xl" weight={500} align="center">
|
||||
Registration is currently closed, please check back later.
|
||||
</Text>
|
||||
) : (
|
||||
<>
|
||||
<Text size="xl" weight={500} mb="xl">
|
||||
Welcome to Bliss V2, sign up with
|
||||
</Text>
|
||||
<form onSubmit={form.onSubmit((values) => register(values))}>
|
||||
<Stack spacing={10}>
|
||||
<Group spacing={5}>
|
||||
<Text weight="bold">Credentials</Text>
|
||||
<IconUser size={20} />
|
||||
</Group>
|
||||
{settings.INVITE_MODE && (
|
||||
<TextInput
|
||||
{...form.getInputProps('invite')}
|
||||
withAsterisk
|
||||
id="invite"
|
||||
label="Invite Code"
|
||||
/>
|
||||
)}
|
||||
<TextInput
|
||||
{...form.getInputProps('username')}
|
||||
id="username"
|
||||
label="Username"
|
||||
description="Leave empty to get a random username"
|
||||
/>
|
||||
<TextInput
|
||||
{...form.getInputProps('email')}
|
||||
id="email"
|
||||
withAsterisk
|
||||
label="Email Address"
|
||||
/>
|
||||
<PasswordInput
|
||||
{...form.getInputProps('password')}
|
||||
withAsterisk
|
||||
id="password"
|
||||
label="Password"
|
||||
/>
|
||||
<Group pt="lg" position="apart" align="center">
|
||||
<Anchor href={ROUTES.SIGN_IN} size="xs" color="dimmed">
|
||||
Already have an account?
|
||||
</Anchor>
|
||||
<Button
|
||||
variant="light"
|
||||
color="violet"
|
||||
type="submit"
|
||||
loading={loading}
|
||||
>
|
||||
Sign up
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</form>
|
||||
</>
|
||||
)}
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
export default SignUpForm;
|
|
@ -1,4 +0,0 @@
|
|||
import SignInForm from './SignInForm';
|
||||
import SignUpForm from './SignUpForm';
|
||||
|
||||
export { SignInForm, SignUpForm };
|
|
@ -0,0 +1,32 @@
|
|||
import LoadingPage from '@components/pages/LoadingPage';
|
||||
import { ROUTES } from '@lib/constants';
|
||||
import { useIsAuth } from '@lib/hooks';
|
||||
import React, { FC, Suspense } from 'react';
|
||||
import dynamic from 'next/dynamic';
|
||||
const Layout = dynamic(() => import('..'), { suspense: true });
|
||||
|
||||
const ProtectedWrapper: FC<{ children: any; withLayout?: boolean }> = ({
|
||||
children,
|
||||
withLayout,
|
||||
}) => {
|
||||
const currentUrl =
|
||||
typeof window !== 'undefined'
|
||||
? `${window.location.protocol}//${window.location.host}${window.location.pathname}`
|
||||
: '';
|
||||
const { data, isLoading } = useIsAuth({
|
||||
redirectTo: ROUTES.SIGN_IN,
|
||||
callbackUrl: encodeURIComponent(currentUrl),
|
||||
});
|
||||
|
||||
if (isLoading) return <LoadingPage color="yellow" />;
|
||||
|
||||
return withLayout ? (
|
||||
<Suspense fallback={<LoadingPage color="yellow" />}>
|
||||
<Layout user={data!}>{children}</Layout>
|
||||
</Suspense>
|
||||
) : (
|
||||
children
|
||||
);
|
||||
};
|
||||
|
||||
export default ProtectedWrapper;
|
|
@ -0,0 +1,38 @@
|
|||
import { useCreateInvite } from '@lib/hooks/useInviteCode';
|
||||
import { Invite } from '@lib/types';
|
||||
import { Stack, Button, Group, PasswordInput, CopyButton } from '@mantine/core';
|
||||
import React, { FC } from 'react';
|
||||
|
||||
const InvitePage: FC<{ invites: Invite[] }> = ({ invites }) => {
|
||||
const { create, isLoading } = useCreateInvite();
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Button
|
||||
loading={isLoading}
|
||||
w={{ base: '100%', lg: '12rem', md: '12rem', sm: '12rem' }}
|
||||
color="teal"
|
||||
onClick={() => create()}
|
||||
>
|
||||
Create invite
|
||||
</Button>
|
||||
{invites.map((invite, idx) => (
|
||||
<Group key={idx} sx={{ width: '100%' }} spacing={5}>
|
||||
<PasswordInput
|
||||
w={{ base: '100%', lg: 420, md: 400, sm: 400 }}
|
||||
value={invite.token}
|
||||
/>
|
||||
<CopyButton value={invite.token}>
|
||||
{({ copied, copy }) => (
|
||||
<Button color={copied ? 'teal' : 'blue'} onClick={copy}>
|
||||
{copied ? 'Copied invite' : 'Copy invite'}
|
||||
</Button>
|
||||
)}
|
||||
</CopyButton>
|
||||
</Group>
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default InvitePage;
|
|
@ -1,21 +1,11 @@
|
|||
import { useSetServerSettings } from '@lib/hooks/useSetServerSettings';
|
||||
import { ServerSettings } from '@lib/types';
|
||||
import {
|
||||
Stack,
|
||||
SegmentedControl,
|
||||
Button,
|
||||
Text,
|
||||
SimpleGrid,
|
||||
} from '@mantine/core';
|
||||
import { Stack, Button, SimpleGrid, Switch } from '@mantine/core';
|
||||
import { showNotification } from '@mantine/notifications';
|
||||
import React from 'react';
|
||||
|
||||
const AdminForm = ({ REGISTRATION_ENABLED, INVITE_MODE }: ServerSettings) => {
|
||||
const { isLoading, update, form } = useSetServerSettings({
|
||||
INVITE_MODE: INVITE_MODE.toString(),
|
||||
REGISTRATION_ENABLED: REGISTRATION_ENABLED.toString(),
|
||||
});
|
||||
|
||||
const ServerPage = (data: ServerSettings) => {
|
||||
const { isLoading, update, form } = useSetServerSettings(data);
|
||||
return (
|
||||
<form
|
||||
onSubmit={form.onSubmit((values) => {
|
||||
|
@ -40,23 +30,23 @@ const AdminForm = ({ REGISTRATION_ENABLED, INVITE_MODE }: ServerSettings) => {
|
|||
]}
|
||||
>
|
||||
<Stack spacing={0}>
|
||||
<Text fw="bold">Turn on or off site registration </Text>
|
||||
<SegmentedControl
|
||||
<Switch
|
||||
label="Turn on or off user registration."
|
||||
size="lg"
|
||||
radius="lg"
|
||||
onLabel="ON"
|
||||
offLabel="OFF"
|
||||
checked={form.values.REGISTRATION_ENABLED}
|
||||
{...form.getInputProps('REGISTRATION_ENABLED')}
|
||||
data={[
|
||||
{ label: 'On', value: 'true' },
|
||||
{ label: 'Off', value: 'false' },
|
||||
]}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack spacing={0}>
|
||||
<Text fw="bold">Enable or disable invite mode on the site</Text>
|
||||
<SegmentedControl
|
||||
<Switch
|
||||
label="Turn on or off invite mode."
|
||||
size="lg"
|
||||
radius="lg"
|
||||
onLabel="ON"
|
||||
offLabel="OFF"
|
||||
checked={form.values.INVITE_MODE}
|
||||
{...form.getInputProps('INVITE_MODE')}
|
||||
data={[
|
||||
{ label: 'Enable', value: 'true' },
|
||||
{ label: 'Disable', value: 'false' },
|
||||
]}
|
||||
/>
|
||||
</Stack>
|
||||
</SimpleGrid>
|
||||
|
@ -73,4 +63,4 @@ const AdminForm = ({ REGISTRATION_ENABLED, INVITE_MODE }: ServerSettings) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default AdminForm;
|
||||
export default ServerPage;
|
|
@ -0,0 +1,129 @@
|
|||
import LoadingPage from '@components/pages/LoadingPage';
|
||||
import { ROUTES } from '@lib/constants';
|
||||
import { useRegister } from '@lib/hooks';
|
||||
import { ServerSettings } from '@lib/types';
|
||||
import {
|
||||
Paper,
|
||||
Stack,
|
||||
Group,
|
||||
TextInput,
|
||||
PasswordInput,
|
||||
Anchor,
|
||||
Button,
|
||||
Text,
|
||||
Center,
|
||||
Tooltip,
|
||||
UnstyledButton,
|
||||
} from '@mantine/core';
|
||||
import { IconArrowBack, IconUser } from '@tabler/icons';
|
||||
import router from 'next/router';
|
||||
|
||||
function SignUpPage({ settings }: { settings: ServerSettings }) {
|
||||
const { form, loading, register } = useRegister();
|
||||
|
||||
if (!settings) {
|
||||
return <LoadingPage />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip label="Home page">
|
||||
<UnstyledButton
|
||||
sx={(t) => ({
|
||||
position: 'absolute',
|
||||
top: 15,
|
||||
left: 15,
|
||||
background: t.colors.dark[5],
|
||||
padding: 13,
|
||||
display: 'grid',
|
||||
placeItems: 'center',
|
||||
borderRadius: t.radius.md,
|
||||
':hover': {
|
||||
background: t.colors.dark[4],
|
||||
},
|
||||
})}
|
||||
onClick={() => router.push(ROUTES.HOME)}
|
||||
>
|
||||
<IconArrowBack />
|
||||
</UnstyledButton>
|
||||
</Tooltip>
|
||||
<Center sx={{ height: '100vh', width: '100vw' }}>
|
||||
<Paper
|
||||
w={{
|
||||
base: '95%',
|
||||
lg: 450,
|
||||
md: 420,
|
||||
sm: 450,
|
||||
xs: 450,
|
||||
}}
|
||||
pt="xl"
|
||||
pb="xl"
|
||||
pr="lg"
|
||||
pl="lg"
|
||||
withBorder={true}
|
||||
>
|
||||
{!settings.REGISTRATION_ENABLED ? (
|
||||
<Text size="xl" weight={500} align="center">
|
||||
Registration is currently closed, please check back later.
|
||||
</Text>
|
||||
) : (
|
||||
<>
|
||||
<Text size="xl" weight={500} mb="xl">
|
||||
Welcome to Bliss V2, sign up with
|
||||
</Text>
|
||||
<form onSubmit={form.onSubmit((values) => register(values))}>
|
||||
<Stack spacing={10}>
|
||||
<Group spacing={5}>
|
||||
<Text weight="bold">Credentials</Text>
|
||||
<IconUser size={20} />
|
||||
</Group>
|
||||
{settings.INVITE_MODE && (
|
||||
<TextInput
|
||||
{...form.getInputProps('invite')}
|
||||
withAsterisk
|
||||
id="invite"
|
||||
label="Invite Code"
|
||||
/>
|
||||
)}
|
||||
<TextInput
|
||||
{...form.getInputProps('username')}
|
||||
id="username"
|
||||
label="Username"
|
||||
description="Leave empty to get a random username"
|
||||
/>
|
||||
<TextInput
|
||||
{...form.getInputProps('email')}
|
||||
id="email"
|
||||
withAsterisk
|
||||
label="Email Address"
|
||||
/>
|
||||
<PasswordInput
|
||||
{...form.getInputProps('password')}
|
||||
withAsterisk
|
||||
id="password"
|
||||
label="Password"
|
||||
/>
|
||||
<Group pt="lg" position="apart" align="center">
|
||||
<Anchor href={ROUTES.SIGN_IN} size="xs" color="dimmed">
|
||||
Already have an account?
|
||||
</Anchor>
|
||||
<Button
|
||||
variant="light"
|
||||
color="violet"
|
||||
type="submit"
|
||||
loading={loading}
|
||||
>
|
||||
Sign up
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</form>
|
||||
</>
|
||||
)}
|
||||
</Paper>
|
||||
</Center>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default SignUpPage;
|
|
@ -0,0 +1,4 @@
|
|||
import SignInForm from './SignInForm';
|
||||
import SignUpPage from './SignUpPage';
|
||||
|
||||
export { SignInForm, SignUpPage };
|
|
@ -1,4 +1,4 @@
|
|||
import LoadingPage from '@components/LoadingPage';
|
||||
import LoadingPage from '@components/pages/LoadingPage';
|
||||
import { useGetUserFiles } from '@lib/hooks';
|
||||
import { IFile } from '@lib/types';
|
||||
import {
|
|
@ -0,0 +1,18 @@
|
|||
import Navbar from '@layouts/Navbar';
|
||||
import Hero from './Hero';
|
||||
import { FC } from 'react';
|
||||
import { SessionUser } from '@lib/types';
|
||||
import dynamic from 'next/dynamic';
|
||||
const Sidebar = dynamic(() => import('@layouts/Sidebar'));
|
||||
|
||||
const HomePage: FC<{ user?: SessionUser }> = ({ user }) => {
|
||||
return (
|
||||
<>
|
||||
<Navbar user={user} />
|
||||
{user && <Sidebar />}
|
||||
<Hero />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default HomePage;
|
|
@ -4,12 +4,13 @@ import { IconCheck, IconCloudUpload, IconDownload, IconX } from '@tabler/icons';
|
|||
import dynamic from 'next/dynamic';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { uploadStyles } from './styles';
|
||||
import { API_ROUTES, API_URL, CHUNK_SIZE } from '@lib/constants';
|
||||
import { API_ROUTES, API_URL, CHUNK_SIZE, USER_LIMIT } from '@lib/constants';
|
||||
import axios from 'axios';
|
||||
import { useAtom } from 'jotai';
|
||||
import { userAtom } from '@lib/atoms';
|
||||
import { showNotification } from '@mantine/notifications';
|
||||
const ProgressCard = dynamic(() => import('./ProgressCard'));
|
||||
import { ACCEPT_TYPE } from '@lib/constants';
|
||||
|
||||
const UploadZone = () => {
|
||||
const [user] = useAtom(userAtom);
|
||||
|
@ -129,8 +130,14 @@ const UploadZone = () => {
|
|||
}}
|
||||
className={classes.dropzone}
|
||||
radius="md"
|
||||
// accept={MIME_TYPES}
|
||||
maxSize={5000 * 1024 ** 2}
|
||||
accept={ACCEPT_TYPE}
|
||||
maxSize={
|
||||
USER_LIMIT(
|
||||
!!user?.createdAt,
|
||||
user?.role === 'OWNER' || user?.role === 'ADMIN'
|
||||
) *
|
||||
1024 ** 2
|
||||
}
|
||||
>
|
||||
<div style={{ pointerEvents: 'none' }}>
|
||||
<Group position="center">
|
|
@ -1,4 +1,4 @@
|
|||
import { serializeURL } from './utils';
|
||||
import { MIME_TYPES } from '@mantine/dropzone';
|
||||
|
||||
export enum ROUTES {
|
||||
HOME = '/',
|
||||
|
@ -28,7 +28,7 @@ export enum API_ROUTES {
|
|||
CHANGE_USERNAME = '/users/change-username',
|
||||
SEND_VERIFICATION_EMAIL = '/users/verify/send',
|
||||
VERIFY_EMAIL = '/users/verify',
|
||||
CHECK_CLOSED = '/auth/check-register',
|
||||
SERVER_SETTINGS = '/server-settings',
|
||||
UPDATE_SERVER_SETTINGS = '/admin/server-settings',
|
||||
INVITE_CODE = '/admin/invites',
|
||||
}
|
||||
|
@ -59,9 +59,7 @@ export const flameshotScript = (token: string) => `
|
|||
IMAGEPATH="$HOME/Pictures/"
|
||||
IMAGENAME="$name-$(date +%s%N | sha256sum | base64 | head -c 32 ; echo)"
|
||||
KEY="${token}"
|
||||
DOMAIN="${serializeURL(
|
||||
process.env.NEXT_PUBLIC_API_URL!
|
||||
)}" # Your upload domain (without http:// or https://)
|
||||
DOMAIN="${process.env.NEXT_PUBLIC_API_URL}/upload"
|
||||
|
||||
flameshot config -f "$IMAGENAME"
|
||||
flameshot gui -r -p "$IMAGEPATH" > /dev/null
|
||||
|
@ -76,28 +74,61 @@ if [ -f "$FILE" ]; then
|
|||
-H "Accept: application/json" \
|
||||
-H "User-Agent: ShareX/13.4.0" \
|
||||
-H "Authorization: $KEY" \
|
||||
-F "file=@$IMAGEPATH$IMAGENAME.png" "https://$DOMAIN/" | grep -Po '(?<="resource":")[^"]+')
|
||||
# printf instead of echo as echo appends a newline
|
||||
-F "file=@$IMAGEPATH$IMAGENAME.png" "$DOMAIN" | grep -Po '(?<="resource":")[^"]+')
|
||||
printf "%s" "$URL" | xclip -sel clip
|
||||
rm "$IMAGEPATH$IMAGENAME.png" # Delete the image locally
|
||||
rm "$IMAGEPATH$IMAGENAME.png"
|
||||
else
|
||||
echo "Aborted."
|
||||
fi
|
||||
`;
|
||||
|
||||
export const MIME_TYPES = [
|
||||
'image/png',
|
||||
'image/gif',
|
||||
'image/jpeg',
|
||||
'image/svg+xml',
|
||||
'image/webp',
|
||||
'audio/ogg',
|
||||
'audio/wave',
|
||||
'audio/wav',
|
||||
'audio/x-wav',
|
||||
'audio/x-pn-wav',
|
||||
// export const MIME_TYPES = [
|
||||
// 'image/png',
|
||||
// 'image/gif',
|
||||
// 'image/jpeg',
|
||||
// 'image/svg+xml',
|
||||
// 'image/webp',
|
||||
// 'audio/ogg',
|
||||
// 'audio/wave',
|
||||
// 'audio/wav',
|
||||
// 'audio/x-wav',
|
||||
// 'audio/x-pn-wav',
|
||||
// 'audio/mp3',
|
||||
// 'audio/mpeg',
|
||||
|
||||
// ];
|
||||
|
||||
export const ACCEPT_TYPE = [
|
||||
MIME_TYPES.png,
|
||||
MIME_TYPES.jpeg,
|
||||
MIME_TYPES.mp4,
|
||||
MIME_TYPES.svg,
|
||||
MIME_TYPES.webp,
|
||||
MIME_TYPES.gif,
|
||||
MIME_TYPES.zip,
|
||||
MIME_TYPES.pdf,
|
||||
MIME_TYPES.docx,
|
||||
MIME_TYPES.pptx,
|
||||
MIME_TYPES.xlsx,
|
||||
'text/plain',
|
||||
'audio/mp3',
|
||||
'audio/wav',
|
||||
'audio/ogg',
|
||||
'audio/flac',
|
||||
'audio/aac',
|
||||
'audio/m4a',
|
||||
'audio/mp4',
|
||||
'audio/mpeg',
|
||||
'audio/webm',
|
||||
'audio/3gpp',
|
||||
'audio/3gpp2',
|
||||
'audio/aac',
|
||||
'audio/aiff',
|
||||
'audio/amr',
|
||||
'audio/basic',
|
||||
'audio/midi',
|
||||
'audio/mid',
|
||||
'audio/m4a',
|
||||
'video/mp4',
|
||||
'video/quicktime',
|
||||
'video/ogg',
|
||||
|
@ -114,5 +145,13 @@ export const MIME_TYPES = [
|
|||
'multipart/x-zip',
|
||||
];
|
||||
|
||||
export const USER_LIMIT = (verified: boolean, admin = false) => {
|
||||
if (admin) return Infinity;
|
||||
|
||||
return verified
|
||||
? +(process.env.NEXT_PUBLIC_USER_VERIFED_LIMIT ?? 2000)
|
||||
: +(process.env.NEXT_PUBLIC_USER_NOT_VERIFED_LIMIT ?? 500);
|
||||
};
|
||||
|
||||
export const CHUNK_SIZE =
|
||||
+(process.env.NEXT_PUBLIC_CHUNK_SIZE ?? 10) * 1024 ** 2; // default: 10mb
|
||||
|
|
|
@ -7,17 +7,19 @@ import axios from 'axios';
|
|||
import { useForm } from '@mantine/form';
|
||||
import { toErrorMap } from '@lib/utils';
|
||||
|
||||
export const useSetServerSettings = (initialData: ServerSettings) => {
|
||||
const form = useForm<ServerSettings>({
|
||||
initialValues: initialData,
|
||||
});
|
||||
export const useSetServerSettings = (initialValues: ServerSettings) => {
|
||||
const form = useForm<ServerSettings>({ initialValues });
|
||||
const { data, mutate, isLoading, error } = useMutation(
|
||||
['server-settings'],
|
||||
(data: Partial<ServerSettings>) =>
|
||||
axios
|
||||
.post(API_URL + API_ROUTES.UPDATE_SERVER_SETTINGS, data, {
|
||||
withCredentials: true,
|
||||
})
|
||||
.post<ServerSettings>(
|
||||
API_URL + API_ROUTES.UPDATE_SERVER_SETTINGS,
|
||||
data,
|
||||
{
|
||||
withCredentials: true,
|
||||
}
|
||||
)
|
||||
.then((res) => {
|
||||
updateNotification({
|
||||
id: 'server-settings',
|
||||
|
@ -27,10 +29,7 @@ export const useSetServerSettings = (initialData: ServerSettings) => {
|
|||
icon: <IconCheck />,
|
||||
});
|
||||
|
||||
form.setValues({
|
||||
INVITE_MODE: res.data.INVITE_MODE.toString(),
|
||||
REGISTRATION_ENABLED: res.data.REGISTRATION_ENABLED.toString(),
|
||||
});
|
||||
form.setValues({ ...res.data });
|
||||
|
||||
return res.data;
|
||||
})
|
||||
|
|
|
@ -116,8 +116,8 @@ export interface EmbedSettings {
|
|||
}
|
||||
|
||||
export interface ServerSettings {
|
||||
REGISTRATION_ENABLED: string;
|
||||
INVITE_MODE: string;
|
||||
REGISTRATION_ENABLED: boolean;
|
||||
INVITE_MODE: boolean;
|
||||
}
|
||||
|
||||
type Token = 'INVITE_CODE' | 'EMAIL_VERIFICATION';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { NotFoundTitle } from '@components/404Page';
|
||||
import { NotFoundTitle } from '@pages/404Page';
|
||||
import React from 'react';
|
||||
|
||||
const NotFound = () => {
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
import { ROUTES } from '@lib/constants';
|
||||
import { useIsAuth } from '@lib/hooks';
|
||||
import { CustomAppProps } from '@lib/types';
|
||||
import { MantineProvider } from '@mantine/core';
|
||||
import { NotificationsProvider } from '@mantine/notifications';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import dynamic from 'next/dynamic';
|
||||
import Head from 'next/head';
|
||||
import { Suspense } from 'react';
|
||||
const LoadingPage = dynamic(() => import('@components/LoadingPage'));
|
||||
const Layout = dynamic(() => import('@components/Layout'), { suspense: true });
|
||||
const ProtectedWrapper = dynamic(() => import('@layouts/ProtectedWrapper'));
|
||||
|
||||
export default function App({ Component, pageProps }: CustomAppProps) {
|
||||
const queryClient = new QueryClient();
|
||||
|
@ -34,9 +30,9 @@ export default function App({ Component, pageProps }: CustomAppProps) {
|
|||
<QueryClientProvider client={queryClient}>
|
||||
<NotificationsProvider>
|
||||
{Component.options?.auth ? (
|
||||
<Auth withLayout={Component.options.withLayout}>
|
||||
<ProtectedWrapper withLayout={Component.options.withLayout}>
|
||||
<Component {...pageProps} />
|
||||
</Auth>
|
||||
</ProtectedWrapper>
|
||||
) : (
|
||||
<Component {...pageProps} />
|
||||
)}
|
||||
|
@ -46,30 +42,3 @@ export default function App({ Component, pageProps }: CustomAppProps) {
|
|||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function Auth({
|
||||
children,
|
||||
withLayout,
|
||||
}: {
|
||||
children: any;
|
||||
withLayout?: boolean;
|
||||
}) {
|
||||
const currentUrl =
|
||||
typeof window !== 'undefined'
|
||||
? `${window.location.protocol}//${window.location.host}${window.location.pathname}`
|
||||
: '';
|
||||
const { data, isLoading } = useIsAuth({
|
||||
redirectTo: ROUTES.SIGN_IN,
|
||||
callbackUrl: encodeURIComponent(currentUrl),
|
||||
});
|
||||
|
||||
if (isLoading) return <LoadingPage color="yellow" />;
|
||||
|
||||
return withLayout ? (
|
||||
<Suspense fallback={<LoadingPage color="yellow" />}>
|
||||
<Layout user={data!}>{children}</Layout>
|
||||
</Suspense>
|
||||
) : (
|
||||
children
|
||||
);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
//! fix weird hydration issue
|
||||
// TODO: find a better way to fix hydration issue
|
||||
const SignInForm = dynamic(
|
||||
() => import('@components/Authentication').then((mod) => mod.SignInForm),
|
||||
() => import('@components/pages/AuthPage').then((mod) => mod.SignInForm),
|
||||
{ ssr: false }
|
||||
);
|
||||
|
||||
|
|
|
@ -1,47 +1,22 @@
|
|||
import { SignUpForm } from '@components/Authentication';
|
||||
import { API_ROUTES, API_URL, ROUTES } from '@lib/constants';
|
||||
import { SignUpPage } from '@pages/AuthPage';
|
||||
import { API_ROUTES, API_URL } from '@lib/constants';
|
||||
import { ServerSettings } from '@lib/types';
|
||||
import { Center, Tooltip, UnstyledButton } from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons';
|
||||
import axios from 'axios';
|
||||
import { InferGetServerSidePropsType, NextPage } from 'next';
|
||||
import router from 'next/router';
|
||||
|
||||
const SignUp: NextPage<
|
||||
InferGetServerSidePropsType<typeof getServerSideProps>
|
||||
> = (data) => {
|
||||
return (
|
||||
<>
|
||||
<Tooltip label="Home page">
|
||||
<UnstyledButton
|
||||
sx={(t) => ({
|
||||
position: 'absolute',
|
||||
top: 15,
|
||||
left: 15,
|
||||
background: t.colors.dark[5],
|
||||
padding: 13,
|
||||
display: 'grid',
|
||||
placeItems: 'center',
|
||||
borderRadius: t.radius.md,
|
||||
':hover': {
|
||||
background: t.colors.dark[4],
|
||||
},
|
||||
})}
|
||||
onClick={() => router.push(ROUTES.HOME)}
|
||||
>
|
||||
<IconArrowBack />
|
||||
</UnstyledButton>
|
||||
</Tooltip>
|
||||
<Center sx={{ height: '100vh', width: '100vw' }}>
|
||||
<SignUpForm settings={data} />
|
||||
</Center>
|
||||
<SignUpPage settings={data} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const getServerSideProps = async () => {
|
||||
const resp = await axios.get<ServerSettings>(
|
||||
API_URL + API_ROUTES.CHECK_CLOSED
|
||||
API_URL + API_ROUTES.SERVER_SETTINGS
|
||||
);
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import InvitePage from '@components/pages/AdminPage/InvitePage';
|
||||
import { API_ROUTES, API_URL, APP_NAME } from '@lib/constants';
|
||||
import { useCreateInvite } from '@lib/hooks/useInviteCode';
|
||||
import {
|
||||
CustomNextPage,
|
||||
Invite,
|
||||
ServerSettings,
|
||||
SessionUser,
|
||||
} from '@lib/types';
|
||||
import { Button, CopyButton, Group, PasswordInput, Stack } from '@mantine/core';
|
||||
import axios from 'axios';
|
||||
import { GetServerSidePropsContext } from 'next';
|
||||
import Head from 'next/head';
|
||||
|
@ -14,39 +13,13 @@ import Head from 'next/head';
|
|||
const AdminDash: CustomNextPage<ServerSettings & { invites: Invite[] }> = (
|
||||
data
|
||||
) => {
|
||||
const { create, isLoading } = useCreateInvite();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{APP_NAME} | Admin</title>
|
||||
</Head>
|
||||
|
||||
<Stack>
|
||||
<Button
|
||||
loading={isLoading}
|
||||
w={{ base: '100%', lg: '12rem', md: '12rem', sm: '12rem' }}
|
||||
color="teal"
|
||||
onClick={() => create()}
|
||||
>
|
||||
Create invite
|
||||
</Button>
|
||||
{data.invites.map((invite, idx) => (
|
||||
<Group key={idx} sx={{ width: '100%' }} spacing={5}>
|
||||
<PasswordInput
|
||||
w={{ base: '100%', lg: 420, md: 400, sm: 400 }}
|
||||
value={invite.token}
|
||||
/>
|
||||
<CopyButton value={invite.token}>
|
||||
{({ copied, copy }) => (
|
||||
<Button color={copied ? 'teal' : 'blue'} onClick={copy}>
|
||||
{copied ? 'Copied invite' : 'Copy invite'}
|
||||
</Button>
|
||||
)}
|
||||
</CopyButton>
|
||||
</Group>
|
||||
))}
|
||||
</Stack>
|
||||
<InvitePage invites={data.invites} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import AdminForm from '@components/Authentication/AdminForm';
|
||||
import ServerPage from '@pages/AdminPage/ServerPage';
|
||||
import { API_ROUTES, API_URL } from '@lib/constants';
|
||||
import { CustomNextPage, SessionUser } from '@lib/types';
|
||||
import { CustomNextPage, ServerSettings, SessionUser } from '@lib/types';
|
||||
import axios from 'axios';
|
||||
import { GetServerSidePropsContext, InferGetServerSidePropsType } from 'next';
|
||||
|
||||
const Owner: CustomNextPage<
|
||||
InferGetServerSidePropsType<typeof getServerSideProps>
|
||||
> = ({ data }) => {
|
||||
return <AdminForm {...data} />;
|
||||
return <ServerPage {...data} />;
|
||||
};
|
||||
|
||||
export default Owner;
|
||||
|
@ -29,7 +29,9 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
|
|||
};
|
||||
}
|
||||
|
||||
const serverData = await axios.get(API_URL + API_ROUTES.CHECK_CLOSED);
|
||||
const serverData = await axios.get<ServerSettings>(
|
||||
API_URL + API_ROUTES.SERVER_SETTINGS
|
||||
);
|
||||
|
||||
return {
|
||||
props: { data: serverData.data },
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import QuickActions from '@components/QuickActions';
|
||||
import StatisticCard from '@components/StatisticCard';
|
||||
import QuickActions from '@pages/DashboardPage';
|
||||
import StatisticCard from '@layouts/StatisticCard';
|
||||
import { API_ROUTES, API_URL, APP_NAME } from '@lib/constants';
|
||||
import { CustomNextPage } from '@lib/types';
|
||||
import { Group } from '@mantine/core';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import UploadZone from '@components/Upload';
|
||||
import UploadZone from '@pages/UploadPage';
|
||||
import { APP_NAME } from '@lib/constants';
|
||||
import { CustomNextPage } from '@lib/types';
|
||||
import Head from 'next/head';
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
import Hero from '@components/Hero';
|
||||
import Navbar from '@components/Layout/Navbar';
|
||||
import HomePage from '@pages/HomePage';
|
||||
import { API_ROUTES, API_URL } from '@lib/constants';
|
||||
import { SessionUser } from '@lib/types';
|
||||
import axios from 'axios';
|
||||
import { GetServerSidePropsContext, InferGetServerSidePropsType } from 'next';
|
||||
import dynamic from 'next/dynamic';
|
||||
const Sidebar = dynamic(() => import('@components/Layout/Sidebar'));
|
||||
|
||||
const Home = (
|
||||
props: InferGetServerSidePropsType<typeof getServerSideProps>
|
||||
) => {
|
||||
return (
|
||||
<>
|
||||
<Navbar user={props?.user} />
|
||||
{props.user && <Sidebar />}
|
||||
<Hero />
|
||||
<HomePage {...props} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import ProfilePage from '@components/ProfilePage';
|
||||
import ProfilePage from '@pages/ProfilePage';
|
||||
import { APP_NAME } from '@lib/constants';
|
||||
import { CustomNextPage } from '@lib/types';
|
||||
import Head from 'next/head';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import EmbedForm from '@components/Settings/EmbedForm';
|
||||
import EmbedPreview from '@components/Settings/EmbedPreview';
|
||||
import EmbedForm from '@pages/SettingPage/EmbedForm';
|
||||
import EmbedPreview from '@pages/SettingPage/EmbedPreview';
|
||||
import { API_URL, API_ROUTES } from '@lib/constants';
|
||||
import { useUpdateEmbedSettings } from '@lib/hooks';
|
||||
import { CustomNextPage, EmbedSettings } from '@lib/types';
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
"paths": {
|
||||
"@lib/*": ["lib/*"],
|
||||
"@components/*": ["components/*"],
|
||||
"@pages/*": ["pages/*"]
|
||||
"@pages/*": ["components/pages/*"],
|
||||
"@layouts/*": ["components/layouts/*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
|
|
Loading…
Reference in New Issue