Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Brian Cao 2023-01-12 00:02:17 -08:00
commit fad38dc180
18 changed files with 103 additions and 106 deletions

View File

@ -3,8 +3,10 @@ import Head from 'next/head';
import Header from 'components/layout/Header';
import Footer from 'components/layout/Footer';
import useLocale from 'hooks/useLocale';
import useRequireLogin from 'hooks/useRequireLogin';
export default function Layout({ title, children, header = true, footer = true }) {
export default function AppLayout({ title, children }) {
useRequireLogin();
const { dir } = useLocale();
return (
@ -12,9 +14,9 @@ export default function Layout({ title, children, header = true, footer = true }
<Head>
<title>{title ? `${title} | umami` : 'umami'}</title>
</Head>
{header && <Header />}
<Header />
<main>{children}</main>
{footer && <Footer />}
<Footer />
</Container>
);
}

View File

@ -5,11 +5,11 @@ import Page from 'components/layout/Page';
import PageHeader from 'components/layout/PageHeader';
import WebsiteChartList from 'components/pages/websites/WebsiteChartList';
import DashboardSettingsButton from 'components/settings/DashboardSettingsButton';
import DashboardEdit from 'components/pages/dashboard/DashboardEdit';
import styles from 'components/pages/websites/WebsiteList.module.css';
import useUser from 'hooks/useUser';
import useApi from 'hooks/useApi';
import useRequireLogin from 'hooks/useRequireLogin';
import useDashboard from 'store/dashboard';
import DashboardEdit from './DashboardEdit';
import styles from '../websites/WebsiteList.module.css';
const messages = defineMessages({
dashboard: { id: 'label.dashboard', defaultMessage: 'Dashboard' },
@ -17,7 +17,7 @@ const messages = defineMessages({
});
export default function Dashboard({ userId }) {
const { user } = useRequireLogin();
const { user } = useUser();
const dashboard = useDashboard();
const { showCharts, limit, editing } = dashboard;
const [max, setMax] = useState(limit);

View File

@ -14,6 +14,7 @@ import useApi from 'hooks/useApi';
import { setUser } from 'store/app';
import { setClientAuthToken } from 'lib/client';
import Logo from 'assets/logo.svg';
import styles from './LoginForm.module.css';
export default function LoginForm() {
const router = useRouter();
@ -26,20 +27,18 @@ export default function LoginForm() {
setClientAuthToken(token);
setUser(user);
await router.push('/settings/websites');
await router.push('/dashboard');
},
});
};
return (
<>
<div>
<Icon size="xl">
<Logo />
</Icon>
<p>umami</p>
</div>
<Form onSubmit={handleSubmit} error={error}>
<div className={styles.login}>
<Icon className={styles.icon} size="xl">
<Logo />
</Icon>
<div className={styles.title}>umami</div>
<Form className={styles.form} onSubmit={handleSubmit} error={error}>
<FormRow label="Username">
<FormInput name="username" rules={{ required: 'Required' }}>
<TextField autoComplete="off" />
@ -51,11 +50,11 @@ export default function LoginForm() {
</FormInput>
</FormRow>
<FormButtons>
<SubmitButton variant="primary" disabled={isLoading}>
<SubmitButton className={styles.button} variant="primary" disabled={isLoading}>
Log in
</SubmitButton>
</FormButtons>
</Form>
</>
</div>
);
}

View File

@ -1,23 +1,31 @@
.login {
display: flex;
flex-direction: column;
margin-top: 80px;
width: 300px;
margin: auto;
transform: translateY(-25%);
}
.login form {
margin: 0 auto;
.form {
display: flex;
flex-direction: column;
}
.title {
font-size: 24px;
font-weight: 700;
text-align: center;
margin: 30px 0;
}
.icon {
display: flex;
width: 100%;
}
.icon svg {
width: 32px;
height: 32px;
}
.button {
flex: 1;
justify-content: center;
margin: 0 auto;
}
.header {
margin-bottom: 30px;
}
.header h1 {
margin: 12px 0;
}

View File

@ -0,0 +1,16 @@
import Head from 'next/head';
import useLocale from 'hooks/useLocale';
import styles from './LoginLayout.module.css';
export default function LoginLayout({ children }) {
const { dir } = useLocale();
return (
<div className={styles.layout} dir={dir}>
<Head>
<title>{`Login | umami`}</title>
</Head>
{children}
</div>
);
}

View File

@ -0,0 +1,7 @@
.layout {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}

View File

@ -1,23 +1,23 @@
import Layout from 'components/layout/Layout';
import AppLayout from 'components/layout/AppLayout';
import Menu from 'components/nav/Nav';
import useRequireLogin from 'hooks/useRequireLogin';
import styles from './SettingsLayout.module.css';
import useConfig from 'hooks/useConfig';
export default function SettingsLayout({ children }) {
const { user } = useRequireLogin();
const { adminDisabled } = useConfig();
if (!user) {
if (adminDisabled) {
return null;
}
return (
<Layout>
<AppLayout>
<div className={styles.dashboard}>
<div className={styles.nav}>
<Menu />
</div>
<div className={styles.content}>{children}</div>
</div>
</Layout>
</AppLayout>
);
}

View File

@ -12,8 +12,10 @@ export default function WebsitesList() {
const [edit, setEdit] = useState(false);
const { get, useQuery } = useApi();
const { user } = useUser();
const { data, isLoading, error, refetch } = useQuery(['websites', user.id], () =>
get(`/users/${user.id}/websites`),
const { data, isLoading, error, refetch } = useQuery(
['websites', user?.id],
() => get(`/users/${user?.id}/websites`),
{ enabled: !!user },
);
const hasData = data && data.length !== 0;
const { toast, showToast } = useToast();

View File

@ -1,11 +1,10 @@
import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { setItem } from 'next-basics';
import { get, setItem } from 'next-basics';
import { LOCALE_CONFIG } from 'lib/constants';
import { getDateLocale, getTextDirection } from 'lib/lang';
import useStore, { setLocale } from 'store/app';
import useForceUpdate from 'hooks/useForceUpdate';
import useApi from 'hooks/useApi';
import enUS from 'public/intl/messages/en-US.json';
const messages = {
@ -20,12 +19,11 @@ export default function useLocale() {
const forceUpdate = useForceUpdate();
const dir = getTextDirection(locale);
const dateLocale = getDateLocale(locale);
const { get } = useApi();
async function loadMessages(locale) {
const data = await get(`${basePath}/intl/messages/${locale}.json`);
const { ok, data } = await get(`${basePath}/intl/messages/${locale}.json`);
if (data) {
if (ok) {
messages[locale] = data;
}
}

View File

@ -1,4 +1,4 @@
import Layout from 'components/layout/Layout';
import AppLayout from 'components/layout/AppLayout';
import { useIntl, defineMessages } from 'react-intl';
const messages = defineMessages({
@ -9,10 +9,10 @@ export default function Custom404() {
const { formatMessage } = useIntl();
return (
<Layout>
<AppLayout>
<div className="row justify-content-center">
<h1 style={{ textAlign: 'center' }}>{formatMessage(messages.notFound)}</h1>
</div>
</Layout>
</AppLayout>
);
}

View File

@ -1,18 +1,18 @@
import Layout from 'components/layout/Layout';
import AppLayout from 'components/layout/AppLayout';
import TestConsole from 'components/pages/console/TestConsole';
import useRequireLogin from 'hooks/useRequireLogin';
import useUser from 'hooks/useUser';
export default function ConsolePage({ pageDisabled }) {
const { user } = useRequireLogin();
const { user } = useUser();
if (pageDisabled || !user || !user.isAdmin) {
return null;
}
return (
<Layout>
<AppLayout>
<TestConsole />
</Layout>
</AppLayout>
);
}

View File

@ -1,27 +1,10 @@
import { useRouter } from 'next/router';
import Layout from 'components/layout/Layout';
import AppLayout from 'components/layout/AppLayout';
import Dashboard from 'components/pages/dashboard/Dashboard';
import useConfig from 'hooks/useConfig';
import useRequireLogin from 'hooks/useRequireLogin';
export default function DashboardPage() {
const {
query: { id },
isReady,
asPath,
} = useRouter();
const { user } = useRequireLogin();
const { adminDisabled } = useConfig();
if (adminDisabled || !user || !isReady) {
return null;
}
const userId = id?.[0];
return (
<Layout>
<Dashboard key={asPath} userId={user.id || userId} />
</Layout>
<AppLayout>
<Dashboard />
</AppLayout>
);
}

View File

@ -1,4 +1,4 @@
import Layout from 'components/layout/Layout';
import LoginLayout from 'components/pages/login/LoginLayout';
import LoginForm from 'components/pages/login/LoginForm';
export default function LoginPage({ pageDisabled }) {
@ -7,9 +7,9 @@ export default function LoginPage({ pageDisabled }) {
}
return (
<Layout title="login" header={false} footer={false} center>
<LoginLayout title="login">
<LoginForm />
</Layout>
</LoginLayout>
);
}

View File

@ -1,17 +1,10 @@
import Layout from 'components/layout/Layout';
import AppLayout from 'components/layout/AppLayout';
import RealtimeDashboard from 'components/pages/realtime/RealtimeDashboard';
import useRequireLogin from 'hooks/useRequireLogin';
export default function RealtimePage() {
const { user } = useRequireLogin();
if (!user) {
return null;
}
return (
<Layout>
<AppLayout>
<RealtimeDashboard />
</Layout>
</AppLayout>
);
}

View File

@ -1,16 +1,7 @@
import SettingsLayout from 'components/pages/settings/SettingsLayout';
import useConfig from 'hooks/useConfig';
import useRequireLogin from 'hooks/useRequireLogin';
import WebsitesList from 'components/pages/settings/websites/WebsitesList';
export default function WebsitesPage() {
const { user } = useRequireLogin();
const { adminDisabled } = useConfig();
if (adminDisabled || !user) {
return null;
}
return (
<SettingsLayout>
<WebsitesList />

View File

@ -1,5 +1,5 @@
import { useRouter } from 'next/router';
import Layout from 'components/layout/Layout';
import AppLayout from 'components/layout/AppLayout';
import WebsiteDetails from 'components/pages/websites/WebsiteDetails';
import useShareToken from 'hooks/useShareToken';
@ -14,8 +14,8 @@ export default function SharePage() {
}
return (
<Layout>
<AppLayout>
<WebsiteDetails websiteId={shareToken.websiteId} />
</Layout>
</AppLayout>
);
}

View File

@ -1,20 +1,18 @@
import { useRouter } from 'next/router';
import Layout from 'components/layout/Layout';
import AppLayout from 'components/layout/AppLayout';
import WebsiteDetails from 'components/pages/websites/WebsiteDetails';
import useRequireLogin from 'hooks/useRequireLogin';
export default function DetailsPage() {
const { user } = useRequireLogin();
const router = useRouter();
const { id } = router.query;
if (!id || !user) {
if (!id) {
return null;
}
return (
<Layout>
<AppLayout>
<WebsiteDetails websiteId={id} />
</Layout>
</AppLayout>
);
}