mirror of
https://github.com/umami-software/umami.git
synced 2026-02-07 06:07:17 +01:00
Refactored layout. Added NavBar component.
This commit is contained in:
parent
fad38dc180
commit
1d9c3133f0
56 changed files with 601 additions and 429 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import { useRef, useState } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import TimezoneSetting from './TimezoneSetting';
|
||||
import DateRangeSetting from './DateRangeSetting';
|
||||
import TimezoneSetting from '../pages/settings/profile/TimezoneSetting';
|
||||
import DateRangeSetting from '../pages/settings/profile/DateRangeSetting';
|
||||
import { Button, Icon } from 'react-basics';
|
||||
import styles from './SettingsButton.module.css';
|
||||
import Gear from 'assets/gear.svg';
|
||||
|
|
@ -5,7 +5,7 @@ import { useIntl, defineMessages } from 'react-intl';
|
|||
import DatePickerForm from 'components/metrics/DatePickerForm';
|
||||
import useLocale from 'hooks/useLocale';
|
||||
import { dateFormat } from 'lib/date';
|
||||
import Calendar from 'assets/calendar-alt.svg';
|
||||
import Calendar from 'assets/calendar.svg';
|
||||
|
||||
const messages = defineMessages({
|
||||
today: { id: 'label.today', defaultMessage: 'Today' },
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ const menuItems = [
|
|||
},
|
||||
{ label: <FormattedMessage id="label.realtime" defaultMessage="Realtime" />, value: '/realtime' },
|
||||
{
|
||||
label: <FormattedMessage id="label.settings" defaultMessage="SettingsLayout" />,
|
||||
value: '/settings',
|
||||
label: <FormattedMessage id="label.settings" defaultMessage="AppLayout" />,
|
||||
value: '/buttons',
|
||||
},
|
||||
{
|
||||
label: <FormattedMessage id="label.profile" defaultMessage="Profile" />,
|
||||
value: '/settings/profile',
|
||||
value: '/buttons/profile',
|
||||
},
|
||||
{ label: <FormattedMessage id="label.logout" defaultMessage="Logout" />, value: '/logout' },
|
||||
];
|
||||
|
|
|
|||
13
components/icons.js
Normal file
13
components/icons.js
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import Calendar from 'assets/calendar.svg';
|
||||
import Clock from 'assets/clock.svg';
|
||||
import Dashboard from 'assets/dashboard.svg';
|
||||
import Gear from 'assets/gear.svg';
|
||||
import Globe from 'assets/globe.svg';
|
||||
import Logo from 'assets/logo.svg';
|
||||
import Moon from 'assets/moon.svg';
|
||||
import Profile from 'assets/profile.svg';
|
||||
import Sun from 'assets/sun.svg';
|
||||
import User from 'assets/user.svg';
|
||||
import Users from 'assets/users.svg';
|
||||
|
||||
export { Calendar, Clock, Dashboard, Gear, Globe, Logo, Moon, Profile, Sun, User, Users };
|
||||
|
|
@ -1,22 +1,25 @@
|
|||
import { Container } from 'react-basics';
|
||||
import Head from 'next/head';
|
||||
import Header from 'components/layout/Header';
|
||||
import Footer from 'components/layout/Footer';
|
||||
import useLocale from 'hooks/useLocale';
|
||||
import NavBar from 'components/layout/NavBar';
|
||||
import useRequireLogin from 'hooks/useRequireLogin';
|
||||
import styles from './AppLayout.module.css';
|
||||
|
||||
export default function AppLayout({ title, children }) {
|
||||
useRequireLogin();
|
||||
const { dir } = useLocale();
|
||||
|
||||
return (
|
||||
<Container dir={dir} style={{ maxWidth: 1140 }}>
|
||||
<div className={styles.layout}>
|
||||
<Head>
|
||||
<title>{title ? `${title} | umami` : 'umami'}</title>
|
||||
</Head>
|
||||
<Header />
|
||||
<main>{children}</main>
|
||||
<Footer />
|
||||
</Container>
|
||||
<div className={styles.nav}>
|
||||
<NavBar />
|
||||
</div>
|
||||
<div className={styles.body}>
|
||||
<Container>
|
||||
<main>{children}</main>
|
||||
</Container>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,16 @@
|
|||
.layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-columns: minmax(60px, 200px) 1fr;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.nav {
|
||||
grid-row: 1 / 3;
|
||||
}
|
||||
|
||||
.body {
|
||||
grid-area: 1 / 2;
|
||||
overflow: auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +1,38 @@
|
|||
import { Row, Column } from 'react-basics';
|
||||
import { useRouter } from 'next/router';
|
||||
import Script from 'next/script';
|
||||
import classNames from 'classnames';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { useIntl, defineMessages } from 'react-intl';
|
||||
import Link from 'components/common/Link';
|
||||
import styles from './Footer.module.css';
|
||||
import { CURRENT_VERSION, HOMEPAGE_URL, REPO_URL } from 'lib/constants';
|
||||
import styles from './Footer.module.css';
|
||||
|
||||
export default function Footer() {
|
||||
const messages = defineMessages({
|
||||
poweredBy: { id: 'message.powered-by', defaultMessage: 'Powered by {name}' },
|
||||
});
|
||||
|
||||
export default function Footer({ className }) {
|
||||
const { pathname } = useRouter();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
return (
|
||||
<footer className={classNames(styles.footer, 'row')}>
|
||||
<div className="col-12 col-md-4" />
|
||||
<div className="col-12 col-md-4">
|
||||
<FormattedMessage
|
||||
id="message.powered-by"
|
||||
defaultMessage="Powered by {name}"
|
||||
values={{
|
||||
name: (
|
||||
<Link href={HOMEPAGE_URL}>
|
||||
<b>umami</b>
|
||||
</Link>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={classNames(styles.version, 'col-12 col-md-4')}>
|
||||
<Link href={REPO_URL}>{`v${CURRENT_VERSION}`}</Link>
|
||||
</div>
|
||||
<footer className={classNames(styles.footer, className)}>
|
||||
<Row>
|
||||
<Column>
|
||||
<div>
|
||||
{formatMessage(messages.poweredBy, {
|
||||
name: (
|
||||
<Link href={HOMEPAGE_URL}>
|
||||
<b>umami</b>
|
||||
</Link>
|
||||
),
|
||||
})}
|
||||
</div>
|
||||
</Column>
|
||||
<Column className={styles.version}>
|
||||
<Link href={REPO_URL}>{`v${CURRENT_VERSION}`}</Link>
|
||||
</Column>
|
||||
</Row>
|
||||
{!pathname.includes('/share/') && <Script src={`/telemetry.js`} />}
|
||||
</footer>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,19 +1,17 @@
|
|||
import Logo from 'assets/logo.svg';
|
||||
import HamburgerButton from 'components/common/HamburgerButton';
|
||||
import Link from 'components/common/Link';
|
||||
import UpdateNotice from 'components/common/UpdateNotice';
|
||||
import LanguageButton from 'components/settings/LanguageButton';
|
||||
import ThemeButton from 'components/settings/ThemeButton';
|
||||
import UserButton from 'components/settings/UserButton';
|
||||
import LanguageButton from 'components/buttons/LanguageButton';
|
||||
import ThemeButton from 'components/buttons/ThemeButton';
|
||||
import UserButton from 'components/buttons/UserButton';
|
||||
import useConfig from 'hooks/useConfig';
|
||||
import useUser from 'hooks/useUser';
|
||||
import { HOMEPAGE_URL } from 'lib/constants';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Column, Icon, Row } from 'react-basics';
|
||||
import SettingsButton from '../settings/SettingsButton';
|
||||
import { Column, Row } from 'react-basics';
|
||||
import SettingsButton from '../buttons/SettingsButton';
|
||||
import styles from './Header.module.css';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export default function Header() {
|
||||
export default function Header({ className }) {
|
||||
const user = useUser();
|
||||
const { pathname } = useRouter();
|
||||
const { updatesDisabled, adminDisabled } = useConfig();
|
||||
|
|
@ -23,14 +21,9 @@ export default function Header() {
|
|||
return (
|
||||
<>
|
||||
{allowUpdate && <UpdateNotice />}
|
||||
<header className={styles.header}>
|
||||
<header className={classNames(styles.header, className)}>
|
||||
<Row>
|
||||
<Column className={styles.title}>
|
||||
<Icon size="lg" className={styles.logo}>
|
||||
<Logo />
|
||||
</Icon>
|
||||
<Link href={isSharePage ? HOMEPAGE_URL : '/'}>umami</Link>
|
||||
</Column>
|
||||
<Column className={styles.title}></Column>
|
||||
<HamburgerButton />
|
||||
<Column className={styles.buttons}>
|
||||
<ThemeButton />
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 100px;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
border-bottom: 1px solid var(--base300);
|
||||
}
|
||||
|
||||
.title {
|
||||
|
|
|
|||
48
components/layout/NavBar.js
Normal file
48
components/layout/NavBar.js
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import { useState } from 'react';
|
||||
import { Icon, Text, Icons } from 'react-basics';
|
||||
import classNames from 'classnames';
|
||||
import { Dashboard, Logo, Profile, User, Users, Clock, Globe } from 'components/icons';
|
||||
import NavGroup from './NavGroup';
|
||||
import styles from './NavBar.module.css';
|
||||
|
||||
const { ChevronDown, Search } = Icons;
|
||||
|
||||
const analytics = [
|
||||
{ key: 'dashboard', label: 'Dashboard', url: '/dashboard', icon: <Dashboard /> },
|
||||
{ key: 'realtime', label: 'Realtime', url: '/realtime', icon: <Clock /> },
|
||||
{ key: 'queries', label: 'Queries', url: '/queries', icon: <Search /> },
|
||||
];
|
||||
|
||||
const settings = [
|
||||
{ key: 'websites', label: 'Websites', url: '/settings/websites', icon: <Globe /> },
|
||||
{ key: 'users', label: 'Users', url: '/settings/users', icon: <User /> },
|
||||
{ key: 'teams', label: 'Teams', url: '/settings/teams', icon: <Users /> },
|
||||
];
|
||||
|
||||
export default function NavBar() {
|
||||
const [minimized, setMinimized] = useState(false);
|
||||
|
||||
const handleMinimize = () => setMinimized(state => !state);
|
||||
|
||||
return (
|
||||
<div className={classNames(styles.navbar, { [styles.minimized]: minimized })}>
|
||||
<div className={styles.header} onClick={handleMinimize}>
|
||||
<Icon size="lg">
|
||||
<Logo />
|
||||
</Icon>
|
||||
<Text className={styles.text}>umami</Text>
|
||||
<Icon size="sm" rotate={minimized ? -90 : 90} className={styles.icon}>
|
||||
<ChevronDown />
|
||||
</Icon>
|
||||
</div>
|
||||
<NavGroup title="Analytics" items={analytics} minimized={minimized} />
|
||||
<NavGroup title="Settings" items={settings} minimized={minimized} />
|
||||
<div className={styles.footer}>
|
||||
<Icon>
|
||||
<Profile />
|
||||
</Icon>
|
||||
<Text>Profile</Text>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
47
components/layout/NavBar.module.css
Normal file
47
components/layout/NavBar.module.css
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
.navbar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background: var(--base75);
|
||||
height: 100%;
|
||||
width: 200px;
|
||||
border-right: 2px solid var(--base200);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
padding: 20px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header:hover .icon {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.minimized.navbar {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.minimized .text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.footer {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
padding: 20px;
|
||||
}
|
||||
51
components/layout/NavGroup.js
Normal file
51
components/layout/NavGroup.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import { useState } from 'react';
|
||||
import { Icon, Text, Icons } from 'react-basics';
|
||||
import classNames from 'classnames';
|
||||
import { useRouter } from 'next/router';
|
||||
import Link from 'next/link';
|
||||
import styles from './NavGroup.module.css';
|
||||
|
||||
const { ChevronDown } = Icons;
|
||||
|
||||
export default function NavGroup({
|
||||
title,
|
||||
items,
|
||||
defaultExpanded = true,
|
||||
allowExpand = true,
|
||||
minimized = false,
|
||||
}) {
|
||||
const { pathname } = useRouter();
|
||||
const [expanded, setExpanded] = useState(defaultExpanded);
|
||||
|
||||
const handleExpand = () => setExpanded(state => !state);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.group, {
|
||||
[styles.expanded]: expanded,
|
||||
[styles.minimized]: minimized,
|
||||
})}
|
||||
>
|
||||
<div className={styles.header} onClick={allowExpand ? handleExpand : undefined}>
|
||||
<Text>{title}</Text>
|
||||
<Icon size="sm" rotate={expanded ? 0 : -90}>
|
||||
<ChevronDown />
|
||||
</Icon>
|
||||
</div>
|
||||
<div className={styles.body}>
|
||||
{items.map(({ key, label, url, icon }) => {
|
||||
return (
|
||||
<Link key={key} href={url}>
|
||||
<a
|
||||
className={classNames(styles.item, { [styles.selected]: pathname.startsWith(url) })}
|
||||
>
|
||||
<Icon>{icon}</Icon>
|
||||
<Text className={styles.text}>{label}</Text>
|
||||
</a>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
76
components/layout/NavGroup.module.css
Normal file
76
components/layout/NavGroup.module.css
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
.group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
color: var(--base600);
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
padding: 10px 20px;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.body {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.expanded .body {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.items {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
margin-right: -2px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
border-right: 2px solid var(--base200);
|
||||
padding: 1rem 2rem;
|
||||
gap: var(--size500);
|
||||
font-weight: 600;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.item.selected {
|
||||
color: var(--base900);
|
||||
border-right-color: var(--primary400);
|
||||
background: var(--blue100);
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
color: var(--base900);
|
||||
}
|
||||
|
||||
.item.disabled {
|
||||
color: var(--base500) !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
a.item {
|
||||
color: var(--base600);
|
||||
}
|
||||
|
||||
.minimized .text,
|
||||
.minimized .header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.minimized .item {
|
||||
width: 60px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import classNames from 'classnames';
|
||||
import { Button, Icon } from 'react-basics';
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
import classNames from 'classnames';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Icon, Item, Menu, Text } from 'react-basics';
|
||||
import useUser from 'hooks/useUser';
|
||||
import User from 'assets/user.svg';
|
||||
import Team from 'assets/users.svg';
|
||||
import Website from 'assets/website.svg';
|
||||
import Profile from 'assets/profile.svg';
|
||||
import styles from './Nav.module.css';
|
||||
|
||||
export default function Nav() {
|
||||
const user = useUser();
|
||||
const { pathname } = useRouter();
|
||||
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const handleSelect = () => {};
|
||||
|
||||
const items = [
|
||||
{ icon: <Website />, label: 'Websites', url: '/settings/websites' },
|
||||
{ icon: <User />, label: 'Users', url: '/settings/users' },
|
||||
{ icon: <Team />, label: 'Teams', url: '/settings/teams' },
|
||||
{ icon: <Profile />, label: 'Profile', url: '/settings/profile' },
|
||||
];
|
||||
|
||||
return (
|
||||
<Menu items={items} onSelect={handleSelect} className={styles.menu}>
|
||||
{({ icon, label, url, hidden }) =>
|
||||
!hidden && (
|
||||
<Item
|
||||
key={label}
|
||||
className={classNames(styles.item, { [styles.selected]: pathname.startsWith(url) })}
|
||||
>
|
||||
<Link href={url}>
|
||||
<a>
|
||||
<Icon size="lg">{icon}</Icon>
|
||||
<Text>{label}</Text>
|
||||
</a>
|
||||
</Link>
|
||||
</Item>
|
||||
)
|
||||
}
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
.menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 200px;
|
||||
gap: 10px;
|
||||
background: transparent;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.menu svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
font-weight: 600;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
background: var(--base100);
|
||||
}
|
||||
|
||||
.item a {
|
||||
color: var(--base600);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.item a:hover {
|
||||
color: var(--base900);
|
||||
}
|
||||
|
||||
.item.selected a {
|
||||
color: var(--base900);
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import { defineMessages, useIntl } from 'react-intl';
|
|||
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 DashboardSettingsButton from 'components/pages/dashboard/DashboardSettingsButton';
|
||||
import DashboardEdit from 'components/pages/dashboard/DashboardEdit';
|
||||
import styles from 'components/pages/websites/WebsiteList.module.css';
|
||||
import useUser from 'hooks/useUser';
|
||||
|
|
|
|||
|
|
@ -4,4 +4,5 @@
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
background: var(--base75);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
import AppLayout from 'components/layout/AppLayout';
|
||||
import Menu from 'components/nav/Nav';
|
||||
import styles from './SettingsLayout.module.css';
|
||||
import useConfig from 'hooks/useConfig';
|
||||
|
||||
export default function SettingsLayout({ children }) {
|
||||
const { adminDisabled } = useConfig();
|
||||
|
||||
if (adminDisabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<AppLayout>
|
||||
<div className={styles.dashboard}>
|
||||
<div className={styles.nav}>
|
||||
<Menu />
|
||||
</div>
|
||||
<div className={styles.content}>{children}</div>
|
||||
</div>
|
||||
</AppLayout>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
.dashboard {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.nav {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
background: var(--base50);
|
||||
flex: 1;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
@ -19,7 +19,13 @@ export default function LanguageSetting() {
|
|||
|
||||
return (
|
||||
<Flexbox width={400} gap={10}>
|
||||
<Dropdown items={options} value={locale} renderValue={renderValue} onChange={saveLocale}>
|
||||
<Dropdown
|
||||
items={options}
|
||||
value={locale}
|
||||
renderValue={renderValue}
|
||||
onChange={saveLocale}
|
||||
menuProps={{ style: { height: 300, width: 300 } }}
|
||||
>
|
||||
{item => <Item key={item}>{languages[item].label}</Item>}
|
||||
</Dropdown>
|
||||
<Button onClick={handleReset}>{formatMessage(messages.reset)}</Button>
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import { Form, FormRow } from 'react-basics';
|
||||
import { useIntl, defineMessages } from 'react-intl';
|
||||
import TimezoneSetting from 'components/settings/TimezoneSetting';
|
||||
import DateRangeSetting from 'components/settings/DateRangeSetting';
|
||||
import LanguageSetting from 'components/settings/LanguageSetting';
|
||||
import ThemeSetting from 'components/settings/ThemeSetting';
|
||||
import TimezoneSetting from 'components/pages/settings/profile/TimezoneSetting';
|
||||
import DateRangeSetting from 'components/pages/settings/profile/DateRangeSetting';
|
||||
import LanguageSetting from 'components/pages/settings/profile/LanguageSetting';
|
||||
import ThemeSetting from 'components/buttons/ThemeSetting';
|
||||
import useUser from 'hooks/useUser';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import Page from 'components/layout/Page';
|
||||
import PageHeader from 'components/layout/PageHeader';
|
||||
import ProfileDetails from 'components/settings/ProfileDetails';
|
||||
import ProfileDetails from 'components/pages/settings/profile/ProfileDetails';
|
||||
import { useState } from 'react';
|
||||
import { Breadcrumbs, Icon, Item, useToast, Modal, Button } from 'react-basics';
|
||||
import UserPasswordForm from 'components/pages/settings/users/UserPasswordForm';
|
||||
|
|
|
|||
|
|
@ -17,7 +17,12 @@ export default function TimezoneSetting() {
|
|||
|
||||
return (
|
||||
<Flexbox width={400} gap={10}>
|
||||
<Dropdown items={options} value={timezone} onChange={saveTimezone}>
|
||||
<Dropdown
|
||||
items={options}
|
||||
value={timezone}
|
||||
onChange={saveTimezone}
|
||||
menuProps={{ style: { height: 300, width: 300 } }}
|
||||
>
|
||||
{item => <Item key={item}>{item}</Item>}
|
||||
</Dropdown>
|
||||
<Button onClick={handleReset}>{formatMessage(messages.reset)}</Button>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState } from 'react';
|
||||
import { Button, Icon, Modal, useToast } from 'react-basics';
|
||||
import { Button, Icon, Text, Modal, useToast, Icons } from 'react-basics';
|
||||
import useApi from 'hooks/useApi';
|
||||
import EmptyPlaceholder from 'components/common/EmptyPlaceholder';
|
||||
import WebsiteAddForm from 'components/pages/settings/websites/WebsiteAddForm';
|
||||
|
|
@ -8,6 +8,8 @@ import WebsitesTable from 'components/pages/settings/websites/WebsitesTable';
|
|||
import Page from 'components/layout/Page';
|
||||
import useUser from 'hooks/useUser';
|
||||
|
||||
const { Plus } = Icons;
|
||||
|
||||
export default function WebsitesList() {
|
||||
const [edit, setEdit] = useState(false);
|
||||
const { get, useQuery } = useApi();
|
||||
|
|
@ -44,8 +46,11 @@ export default function WebsitesList() {
|
|||
<Page loading={isLoading} error={error}>
|
||||
{toast}
|
||||
<PageHeader title="Websites">
|
||||
<Button onClick={handleAdd}>
|
||||
<Icon icon="plus" /> Add website
|
||||
<Button variant="primary" onClick={handleAdd}>
|
||||
<Icon>
|
||||
<Plus />
|
||||
</Icon>
|
||||
<Text>Add website</Text>
|
||||
</Button>
|
||||
</PageHeader>
|
||||
|
||||
|
|
@ -53,7 +58,10 @@ export default function WebsitesList() {
|
|||
{!hasData && (
|
||||
<EmptyPlaceholder message="You don't have any websites configured.">
|
||||
<Button variant="primary" onClick={handleAdd}>
|
||||
<Icon icon="plus" /> Add website
|
||||
<Icon>
|
||||
<Plus />
|
||||
</Icon>
|
||||
<Text>Add website</Text>
|
||||
</Button>
|
||||
</EmptyPlaceholder>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -8,10 +8,12 @@ import {
|
|||
TableColumn,
|
||||
Button,
|
||||
Icon,
|
||||
Icons,
|
||||
} from 'react-basics';
|
||||
import ExternalLink from 'assets/external-link.svg';
|
||||
import styles from './WebsitesTable.module.css';
|
||||
|
||||
const { ArrowRight, External } = Icons;
|
||||
|
||||
export default function WebsitesTable({ columns = [], rows = [] }) {
|
||||
return (
|
||||
<Table className={styles.table} columns={columns} rows={rows}>
|
||||
|
|
@ -33,7 +35,9 @@ export default function WebsitesTable({ columns = [], rows = [] }) {
|
|||
<Link href={`/settings/websites/${id}`}>
|
||||
<a>
|
||||
<Button>
|
||||
<Icon icon="arrow-right" />
|
||||
<Icon>
|
||||
<ArrowRight />
|
||||
</Icon>
|
||||
Settings
|
||||
</Button>
|
||||
</a>
|
||||
|
|
@ -42,7 +46,7 @@ export default function WebsitesTable({ columns = [], rows = [] }) {
|
|||
<a>
|
||||
<Button>
|
||||
<Icon>
|
||||
<ExternalLink />
|
||||
<External />
|
||||
</Icon>
|
||||
View
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ const messages = defineMessages({
|
|||
defaultMessage: "You don't have any websites configured.",
|
||||
},
|
||||
goToSettngs: {
|
||||
id: 'message.go-to-settings',
|
||||
defaultMessage: 'Go to settings',
|
||||
id: 'message.go-to-buttons',
|
||||
defaultMessage: 'Go to buttons',
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue