mirror of
https://github.com/umami-software/umami.git
synced 2026-02-09 07: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
|
|
@ -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';
|
||||
|
|
|
|||
42
components/pages/dashboard/DashboardSettingsButton.js
Normal file
42
components/pages/dashboard/DashboardSettingsButton.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import MenuButton from 'components/common/MenuButton';
|
||||
import Gear from 'assets/gear.svg';
|
||||
import { saveDashboard } from 'store/dashboard';
|
||||
import { Icon } from 'react-basics';
|
||||
|
||||
const messages = defineMessages({
|
||||
toggleCharts: { id: 'message.toggle-charts', defaultMessage: 'Toggle charts' },
|
||||
editDashboard: { id: 'message.edit-dashboard', defaultMessage: 'Edit dashboard' },
|
||||
});
|
||||
|
||||
export default function DashboardSettingsButton() {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const menuOptions = [
|
||||
{
|
||||
label: formatMessage(messages.toggleCharts),
|
||||
value: 'charts',
|
||||
},
|
||||
{
|
||||
label: formatMessage(messages.editDashboard),
|
||||
value: 'order',
|
||||
},
|
||||
];
|
||||
|
||||
function handleSelect(value) {
|
||||
if (value === 'charts') {
|
||||
saveDashboard(state => ({ showCharts: !state.showCharts }));
|
||||
}
|
||||
if (value === 'order') {
|
||||
saveDashboard({ editing: true });
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<MenuButton options={menuOptions} onSelect={handleSelect} hideLabel>
|
||||
<Icon>
|
||||
<Gear />
|
||||
</Icon>
|
||||
</MenuButton>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
.buttonGroup {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
21
components/pages/settings/profile/DateRangeSetting.js
Normal file
21
components/pages/settings/profile/DateRangeSetting.js
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
import DateFilter from 'components/common/DateFilter';
|
||||
import { Button, Flexbox } from 'react-basics';
|
||||
import useDateRange from 'hooks/useDateRange';
|
||||
import { DEFAULT_DATE_RANGE } from 'lib/constants';
|
||||
|
||||
export default function DateRangeSetting() {
|
||||
const [dateRange, setDateRange] = useDateRange();
|
||||
const { startDate, endDate, value } = dateRange;
|
||||
|
||||
const handleReset = () => setDateRange(DEFAULT_DATE_RANGE);
|
||||
|
||||
return (
|
||||
<Flexbox width={400} gap={10}>
|
||||
<DateFilter value={value} startDate={startDate} endDate={endDate} onChange={setDateRange} />
|
||||
<Button onClick={handleReset}>
|
||||
<FormattedMessage id="label.reset" defaultMessage="Reset" />
|
||||
</Button>
|
||||
</Flexbox>
|
||||
);
|
||||
}
|
||||
34
components/pages/settings/profile/LanguageSetting.js
Normal file
34
components/pages/settings/profile/LanguageSetting.js
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import { useIntl, defineMessages } from 'react-intl';
|
||||
import { Button, Dropdown, Item, Flexbox } from 'react-basics';
|
||||
import useLocale from 'hooks/useLocale';
|
||||
import { DEFAULT_LOCALE } from 'lib/constants';
|
||||
import { languages } from 'lib/lang';
|
||||
|
||||
const messages = defineMessages({
|
||||
reset: { id: 'label.reset', defaultMessage: 'Reset' },
|
||||
});
|
||||
|
||||
export default function LanguageSetting() {
|
||||
const { formatMessage } = useIntl();
|
||||
const { locale, saveLocale } = useLocale();
|
||||
const options = Object.keys(languages);
|
||||
|
||||
const handleReset = () => saveLocale(DEFAULT_LOCALE);
|
||||
|
||||
const renderValue = value => languages[value].label;
|
||||
|
||||
return (
|
||||
<Flexbox width={400} gap={10}>
|
||||
<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>
|
||||
</Flexbox>
|
||||
);
|
||||
}
|
||||
46
components/pages/settings/profile/ProfileDetails.js
Normal file
46
components/pages/settings/profile/ProfileDetails.js
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import { Form, FormRow } from 'react-basics';
|
||||
import { useIntl, defineMessages } from 'react-intl';
|
||||
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({
|
||||
username: { id: 'label.username', defaultMessage: 'Username' },
|
||||
role: { id: 'label.role', defaultMessage: 'Role' },
|
||||
timezone: { id: 'label.timezone', defaultMessage: 'Timezone' },
|
||||
dateRange: { id: 'label.default-date-range', defaultMessage: 'Default date range' },
|
||||
language: { id: 'label.language', defaultMessage: 'Language' },
|
||||
theme: { id: 'label.theme', defaultMessage: 'Theme' },
|
||||
});
|
||||
|
||||
export default function ProfileDetails() {
|
||||
const { user } = useUser();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { username, role } = user;
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<FormRow label={formatMessage(messages.username)}>{username}</FormRow>
|
||||
<FormRow label={formatMessage(messages.role)}>{role}</FormRow>
|
||||
<FormRow label={formatMessage(messages.language)} inline>
|
||||
<LanguageSetting />
|
||||
</FormRow>
|
||||
<FormRow label={formatMessage(messages.timezone)} inline>
|
||||
<TimezoneSetting />
|
||||
</FormRow>
|
||||
<FormRow label={formatMessage(messages.dateRange)} inline>
|
||||
<DateRangeSetting />
|
||||
</FormRow>
|
||||
<FormRow label={formatMessage(messages.theme)}>
|
||||
<ThemeSetting />
|
||||
</FormRow>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
.list dd {
|
||||
display: flex;
|
||||
}
|
||||
|
|
@ -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';
|
||||
|
|
|
|||
31
components/pages/settings/profile/TimezoneSetting.js
Normal file
31
components/pages/settings/profile/TimezoneSetting.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import { Dropdown, Item, Button, Flexbox } from 'react-basics';
|
||||
import { useIntl, defineMessages } from 'react-intl';
|
||||
import { listTimeZones } from 'timezone-support';
|
||||
import useTimezone from 'hooks/useTimezone';
|
||||
import { getTimezone } from 'lib/date';
|
||||
|
||||
const messages = defineMessages({
|
||||
reset: { id: 'label.reset', defaultMessage: 'Reset' },
|
||||
});
|
||||
|
||||
export default function TimezoneSetting() {
|
||||
const { formatMessage } = useIntl();
|
||||
const [timezone, saveTimezone] = useTimezone();
|
||||
const options = listTimeZones();
|
||||
|
||||
const handleReset = () => saveTimezone(getTimezone());
|
||||
|
||||
return (
|
||||
<Flexbox width={400} gap={10}>
|
||||
<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>
|
||||
</Flexbox>
|
||||
);
|
||||
}
|
||||
|
|
@ -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