mirror of
https://github.com/umami-software/umami.git
synced 2026-02-11 16:17:13 +01:00
Website edit functionality.
This commit is contained in:
parent
30b87bc4c4
commit
00e232fee8
63 changed files with 301 additions and 94 deletions
11
components/layout/Footer.js
Normal file
11
components/layout/Footer.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import styles from './Footer.module.css';
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className={classNames(styles.footer, 'container mt-5 mb-5')}>
|
||||
umami - deliciously simple web stats
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
3
components/layout/Footer.module.css
Normal file
3
components/layout/Footer.module.css
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
.footer {
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
21
components/layout/FormLayout.js
Normal file
21
components/layout/FormLayout.js
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { ErrorMessage } from 'formik';
|
||||
import styles from './FormLayout.module.css';
|
||||
|
||||
export default function FormLayout({ className, children }) {
|
||||
return <div className={classNames(styles.form, className)}>{children}</div>;
|
||||
}
|
||||
|
||||
export const FormButtons = ({ className, children }) => (
|
||||
<div className={classNames(styles.buttons, className)}>{children}</div>
|
||||
);
|
||||
|
||||
export const FormError = ({ name }) => (
|
||||
<ErrorMessage name={name}>{msg => <div className={styles.error}>{msg}</div>}</ErrorMessage>
|
||||
);
|
||||
|
||||
export const FormRow = ({ children }) => <div className={styles.row}>{children}</div>;
|
||||
|
||||
export const FormMessage = ({ children }) =>
|
||||
children ? <div className={styles.message}>{children}</div> : null;
|
||||
61
components/layout/FormLayout.module.css
Normal file
61
components/layout/FormLayout.module.css
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.form label {
|
||||
display: inline-block;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: var(--gray50);
|
||||
background: var(--color-error);
|
||||
font-size: var(--font-size-small);
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
bottom: 0;
|
||||
margin-left: 16px;
|
||||
padding: 4px 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.error:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -5px;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: var(--color-error);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.message {
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
color: var(--gray50);
|
||||
background: var(--gray800);
|
||||
}
|
||||
34
components/layout/Header.js
Normal file
34
components/layout/Header.js
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import classNames from 'classnames';
|
||||
import Link from 'components/interface/Link';
|
||||
import UserButton from '../interface/UserButton';
|
||||
import Icon from '../interface/Icon';
|
||||
import Logo from 'assets/logo.svg';
|
||||
import styles from './Header.module.css';
|
||||
|
||||
export default function Header() {
|
||||
const user = useSelector(state => state.user);
|
||||
|
||||
return (
|
||||
<header className={classNames(styles.header, 'container')}>
|
||||
<div className="row align-items-center">
|
||||
<div className="col">
|
||||
<div className={styles.title}>
|
||||
<Icon icon={<Logo />} size="L" className={styles.logo} />
|
||||
{user ? <Link href="/">umami</Link> : 'umami'}
|
||||
</div>
|
||||
</div>
|
||||
{user && (
|
||||
<div className="col">
|
||||
<div className={styles.nav}>
|
||||
<Link href="/dashboard">Dashboard</Link>
|
||||
<Link href="/settings">Settings</Link>
|
||||
<UserButton />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
29
components/layout/Header.module.css
Normal file
29
components/layout/Header.module.css
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
.header {
|
||||
display: flex;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.header > div {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: var(--font-size-large);
|
||||
}
|
||||
|
||||
.nav {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav > * {
|
||||
font-size: var(--font-size-normal);
|
||||
font-weight: 600;
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
margin-right: 12px;
|
||||
}
|
||||
38
components/layout/Layout.js
Normal file
38
components/layout/Layout.js
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import Head from 'next/head';
|
||||
import Header from 'components/layout/Header';
|
||||
import Footer from 'components/layout/Footer';
|
||||
import styles from './Layout.module.css';
|
||||
|
||||
export default function Layout({
|
||||
title,
|
||||
children,
|
||||
header = true,
|
||||
footer = true,
|
||||
center = false,
|
||||
middle = false,
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>umami{title && ` - ${title}`}</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</Head>
|
||||
{header && <Header />}
|
||||
<main
|
||||
className={classNames(styles.layout, 'container', {
|
||||
[styles.center]: center,
|
||||
[styles.middle]: middle,
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</main>
|
||||
{footer && <Footer />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
12
components/layout/Layout.module.css
Normal file
12
components/layout/Layout.module.css
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
.layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.middle {
|
||||
justify-content: center;
|
||||
}
|
||||
6
components/layout/Page.js
Normal file
6
components/layout/Page.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import React from 'react';
|
||||
import styles from './Page.module.css';
|
||||
|
||||
export default function Page({ children }) {
|
||||
return <div className={styles.container}>{children}</div>;
|
||||
}
|
||||
8
components/layout/Page.module.css
Normal file
8
components/layout/Page.module.css
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
.container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 30px;
|
||||
background: var(--gray50);
|
||||
height: 100%;
|
||||
}
|
||||
12
components/layout/PageHeader.js
Normal file
12
components/layout/PageHeader.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import React, { Children } from 'react';
|
||||
import styles from './PageHeader.module.css';
|
||||
|
||||
export default function PageHeader({ children }) {
|
||||
const [firstChild, ...otherChildren] = Children.toArray(children);
|
||||
return (
|
||||
<div className={styles.header}>
|
||||
<div className={styles.title}> {firstChild}</div>
|
||||
{otherChildren && <div>{otherChildren}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
10
components/layout/PageHeader.module.css
Normal file
10
components/layout/PageHeader.module.css
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
line-height: 80px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: var(--font-size-large);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue