mirror of
https://github.com/umami-software/umami.git
synced 2026-02-07 06:07:17 +01:00
Layout updates.
This commit is contained in:
parent
e4c5f42189
commit
476dd52875
23 changed files with 97 additions and 86 deletions
|
|
@ -2,13 +2,13 @@ import { Icon, Icons } from 'react-basics';
|
|||
import classNames from 'classnames';
|
||||
import Link from 'next/link';
|
||||
import { safeDecodeURI } from 'next-basics';
|
||||
import usePageQuery from 'components/hooks/usePageQuery';
|
||||
import useNavigation from 'components/hooks/useNavigation';
|
||||
import useMessages from 'components/hooks/useMessages';
|
||||
import styles from './FilterLink.module.css';
|
||||
|
||||
export function FilterLink({ id, value, label, externalUrl, children, className }) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { resolveUrl, query } = usePageQuery();
|
||||
const { makeUrl, query } = useNavigation();
|
||||
const active = query[id] !== undefined;
|
||||
const selected = query[id] === value;
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ export function FilterLink({ id, value, label, externalUrl, children, className
|
|||
{children}
|
||||
{!value && `(${label || formatMessage(labels.unknown)})`}
|
||||
{value && (
|
||||
<Link href={resolveUrl({ [id]: value })} className={styles.label} replace>
|
||||
<Link href={makeUrl({ [id]: value })} className={styles.label} replace>
|
||||
{safeDecodeURI(label || value)}
|
||||
</Link>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
import classNames from 'classnames';
|
||||
import Link from 'next/link';
|
||||
import { Icon, Icons, Text } from 'react-basics';
|
||||
import styles from './LinkButton.module.css';
|
||||
import { useLocale } from 'components/hooks';
|
||||
|
||||
export function LinkButton({ href, icon, className, children }) {
|
||||
const { dir } = useLocale();
|
||||
|
||||
export function LinkButton({ href, icon, children }) {
|
||||
return (
|
||||
<Link className={styles.button} href={href}>
|
||||
<Icon>{icon || <Icons.ArrowRight />}</Icon>
|
||||
<Link className={classNames(styles.button, className)} href={href}>
|
||||
<Icon rotate={dir === 'rtl' ? 0 : 180}>{icon || <Icons.ArrowRight />}</Icon>
|
||||
<Text>{children}</Text>
|
||||
</Link>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export * from './useFormat';
|
|||
export * from './useLanguageNames';
|
||||
export * from './useLocale';
|
||||
export * from './useMessages';
|
||||
export * from './usePageQuery';
|
||||
export * from './useNavigation';
|
||||
export * from './useReport';
|
||||
export * from './useReports';
|
||||
export * from './useRequireLogin';
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useMemo } from 'react';
|
|||
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
|
||||
import { buildUrl } from 'next-basics';
|
||||
|
||||
export function usePageQuery() {
|
||||
export function useNavigation() {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const params = useSearchParams();
|
||||
|
|
@ -17,11 +17,11 @@ export function usePageQuery() {
|
|||
return obj;
|
||||
}, [params]);
|
||||
|
||||
function resolveUrl(params, reset) {
|
||||
return buildUrl(pathname, { ...(reset ? {} : query) });
|
||||
function makeUrl(params, reset) {
|
||||
return reset ? pathname : buildUrl(pathname, { ...query, ...params });
|
||||
}
|
||||
|
||||
return { pathname, query, resolveUrl, router };
|
||||
return { pathname, query, router, makeUrl };
|
||||
}
|
||||
|
||||
export default usePageQuery;
|
||||
export default useNavigation;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import classNames from 'classnames';
|
||||
import styles from './Grid.module.css';
|
||||
import { mapChildren } from 'react-basics';
|
||||
import styles from './Grid.module.css';
|
||||
|
||||
export function Grid({ className, ...otherProps }) {
|
||||
return <div {...otherProps} className={classNames(styles.grid, className)} />;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
background: var(--base50);
|
||||
position: relative;
|
||||
max-width: 1320px;
|
||||
min-height: calc(100vh - 60px);
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
|
|
|||
31
src/components/layout/SideNav.js
Normal file
31
src/components/layout/SideNav.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import classNames from 'classnames';
|
||||
import { Menu, Item } from 'react-basics';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import Link from 'next/link';
|
||||
import styles from './SideNav.module.css';
|
||||
|
||||
export function SideNav({
|
||||
selectedKey,
|
||||
items,
|
||||
shallow = true,
|
||||
scroll = false,
|
||||
onSelect = () => {},
|
||||
}) {
|
||||
const pathname = usePathname();
|
||||
return (
|
||||
<Menu items={items} selectedKey={selectedKey} className={styles.menu} onSelect={onSelect}>
|
||||
{({ key, label, url }) => (
|
||||
<Item
|
||||
key={key}
|
||||
className={classNames(styles.item, { [styles.selected]: pathname.startsWith(url) })}
|
||||
>
|
||||
<Link href={url} shallow={shallow} scroll={scroll}>
|
||||
{label}
|
||||
</Link>
|
||||
</Item>
|
||||
)}
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
|
||||
export default SideNav;
|
||||
19
src/components/layout/SideNav.module.css
Normal file
19
src/components/layout/SideNav.module.css
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
.menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.item a {
|
||||
color: var(--font-color100);
|
||||
flex: 1;
|
||||
padding: var(--size300) var(--size600);
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 0;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.selected {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ import { Loading } from 'react-basics';
|
|||
import { colord } from 'colord';
|
||||
import BarChart from './BarChart';
|
||||
import { getDateArray } from 'lib/date';
|
||||
import { useApi, useLocale, useDateRange, useTimezone, usePageQuery } from 'components/hooks';
|
||||
import { useApi, useLocale, useDateRange, useTimezone, useNavigation } from 'components/hooks';
|
||||
import { EVENT_COLORS } from 'lib/constants';
|
||||
import { renderDateLabels, renderStatusTooltipPopup } from 'lib/charts';
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ export function EventsChart({ websiteId, className, token }) {
|
|||
const [timezone] = useTimezone();
|
||||
const {
|
||||
query: { url, event },
|
||||
} = usePageQuery();
|
||||
} = useNavigation();
|
||||
|
||||
const { data, isLoading } = useQuery(['events', websiteId, modified, event], () =>
|
||||
get(`/websites/${websiteId}/events`, {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { safeDecodeURI } from 'next-basics';
|
||||
import { Button, Icon, Icons, Text } from 'react-basics';
|
||||
import usePageQuery from 'components/hooks/usePageQuery';
|
||||
import useNavigation from 'components/hooks/useNavigation';
|
||||
import useMessages from 'components/hooks/useMessages';
|
||||
import styles from './FilterTags.module.css';
|
||||
|
||||
|
|
@ -8,9 +8,9 @@ export function FilterTags({ params }) {
|
|||
const { formatMessage, labels } = useMessages();
|
||||
const {
|
||||
router,
|
||||
resolveUrl,
|
||||
makeUrl,
|
||||
query: { view },
|
||||
} = usePageQuery();
|
||||
} = useNavigation();
|
||||
|
||||
if (Object.keys(params).filter(key => params[key]).length === 0) {
|
||||
return null;
|
||||
|
|
@ -18,9 +18,9 @@ export function FilterTags({ params }) {
|
|||
|
||||
function handleCloseFilter(param) {
|
||||
if (!param) {
|
||||
router.push(resolveUrl({ view }, true));
|
||||
router.push(makeUrl({ view }, true));
|
||||
} else {
|
||||
router.push(resolveUrl({ [param]: undefined }));
|
||||
router.push(makeUrl({ [param]: undefined }));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import classNames from 'classnames';
|
|||
import useApi from 'components/hooks/useApi';
|
||||
import { percentFilter } from 'lib/filters';
|
||||
import useDateRange from 'components/hooks/useDateRange';
|
||||
import usePageQuery from 'components/hooks/usePageQuery';
|
||||
import useNavigation from 'components/hooks/useNavigation';
|
||||
import ErrorMessage from 'components/common/ErrorMessage';
|
||||
import ListTable from './ListTable';
|
||||
import { DEFAULT_ANIMATION_DURATION } from 'lib/constants';
|
||||
|
|
@ -28,9 +28,9 @@ export function MetricsTable({
|
|||
}) {
|
||||
const [{ startDate, endDate, modified }] = useDateRange(websiteId);
|
||||
const {
|
||||
resolveUrl,
|
||||
makeUrl,
|
||||
query: { url, referrer, title, os, browser, device, country, region, city },
|
||||
} = usePageQuery();
|
||||
} = useNavigation();
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { get, useQuery } = useApi();
|
||||
const { dir } = useLocale();
|
||||
|
|
@ -103,7 +103,7 @@ export function MetricsTable({
|
|||
{data && !error && <ListTable {...props} data={filteredData} className={className} />}
|
||||
<div className={styles.footer}>
|
||||
{data && !error && limit && (
|
||||
<Link href={resolveUrl({ view: type })}>
|
||||
<Link href={makeUrl({ view: type })}>
|
||||
<Button variant="quiet">
|
||||
<Text>{formatMessage(labels.more)}</Text>
|
||||
<Icon size="sm" rotate={dir === 'rtl' ? 180 : 0}>
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@ import FilterLink from 'components/common/FilterLink';
|
|||
import FilterButtons from 'components/common/FilterButtons';
|
||||
import MetricsTable from './MetricsTable';
|
||||
import useMessages from 'components/hooks/useMessages';
|
||||
import usePageQuery from 'components/hooks/usePageQuery';
|
||||
import useNavigation from 'components/hooks/useNavigation';
|
||||
import { emptyFilter } from 'lib/filters';
|
||||
|
||||
export function PagesTable({ websiteId, showFilters, ...props }) {
|
||||
const {
|
||||
router,
|
||||
resolveUrl,
|
||||
makeUrl,
|
||||
query: { view = 'url' },
|
||||
} = usePageQuery();
|
||||
} = useNavigation();
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
||||
const handleSelect = key => {
|
||||
router.push(resolveUrl({ view: key }), null, { shallow: true });
|
||||
router.push(makeUrl({ view: key }), { scroll: true });
|
||||
};
|
||||
|
||||
const buttons = [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue