mirror of
https://github.com/kremalicious/umami.git
synced 2024-11-15 09:45:04 +01:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
fad38dc180
@ -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>
|
||||
);
|
||||
}
|
@ -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);
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
16
components/pages/login/LoginLayout.js
Normal file
16
components/pages/login/LoginLayout.js
Normal 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>
|
||||
);
|
||||
}
|
7
components/pages/login/LoginLayout.module.css
Normal file
7
components/pages/login/LoginLayout.module.css
Normal file
@ -0,0 +1,7 @@
|
||||
.layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
}
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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 />
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user