mirror of
https://github.com/kremalicious/umami.git
synced 2025-02-01 12:29:35 +01:00
Added tables to compare screen.
This commit is contained in:
parent
154b559315
commit
13e11ee371
@ -9,7 +9,7 @@ export function WebsiteChart({
|
|||||||
compareMode = false,
|
compareMode = false,
|
||||||
}: {
|
}: {
|
||||||
websiteId: string;
|
websiteId: string;
|
||||||
compareMode: boolean;
|
compareMode?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const { dateRange, dateCompare } = useDateRange(websiteId);
|
const { dateRange, dateCompare } = useDateRange(websiteId);
|
||||||
const { startDate, endDate, unit } = dateRange;
|
const { startDate, endDate, unit } = dateRange;
|
||||||
@ -27,13 +27,13 @@ export function WebsiteChart({
|
|||||||
result['compare'] = {
|
result['compare'] = {
|
||||||
pageviews: result.pageviews.map(({ x }, i) => ({
|
pageviews: result.pageviews.map(({ x }, i) => ({
|
||||||
x,
|
x,
|
||||||
y: compare.pageviews[i].y,
|
y: compare.pageviews[i]?.y,
|
||||||
d: compare.pageviews[i].x,
|
d: compare.pageviews[i]?.x,
|
||||||
})),
|
})),
|
||||||
sessions: result.sessions.map(({ x }, i) => ({
|
sessions: result.sessions.map(({ x }, i) => ({
|
||||||
x,
|
x,
|
||||||
y: compare.sessions[i].y,
|
y: compare.sessions[i]?.y,
|
||||||
d: compare.pageviews[i].x,
|
d: compare.sessions[i]?.x,
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,19 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import { Loading } from 'react-basics';
|
|
||||||
import { usePathname } from 'next/navigation';
|
import { usePathname } from 'next/navigation';
|
||||||
import Page from 'components/layout/Page';
|
|
||||||
import FilterTags from 'components/metrics/FilterTags';
|
import FilterTags from 'components/metrics/FilterTags';
|
||||||
import { useNavigation, useWebsite } from 'components/hooks';
|
import { useNavigation } from 'components/hooks';
|
||||||
import WebsiteChart from './WebsiteChart';
|
import WebsiteChart from './WebsiteChart';
|
||||||
import WebsiteExpandedView from './WebsiteExpandedView';
|
import WebsiteExpandedView from './WebsiteExpandedView';
|
||||||
import WebsiteHeader from './WebsiteHeader';
|
import WebsiteHeader from './WebsiteHeader';
|
||||||
import WebsiteMetricsBar from './WebsiteMetricsBar';
|
import WebsiteMetricsBar from './WebsiteMetricsBar';
|
||||||
import WebsiteTableView from './WebsiteTableView';
|
import WebsiteTableView from './WebsiteTableView';
|
||||||
|
import WebsiteProvider from './WebsiteProvider';
|
||||||
import { FILTER_COLUMNS } from 'lib/constants';
|
import { FILTER_COLUMNS } from 'lib/constants';
|
||||||
|
|
||||||
export default function WebsiteDetails({ websiteId }: { websiteId: string }) {
|
export default function WebsiteDetailsPage({ websiteId }: { websiteId: string }) {
|
||||||
const { data: website, isLoading, error } = useWebsite(websiteId);
|
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const { query } = useNavigation();
|
const { query } = useNavigation();
|
||||||
|
|
||||||
if (isLoading || error) {
|
|
||||||
return <Page isLoading={isLoading} error={error} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
const showLinks = !pathname.includes('/share/');
|
const showLinks = !pathname.includes('/share/');
|
||||||
const { view } = query;
|
const { view } = query;
|
||||||
|
|
||||||
@ -31,18 +25,13 @@ export default function WebsiteDetails({ websiteId }: { websiteId: string }) {
|
|||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<WebsiteProvider websiteId={websiteId}>
|
||||||
<WebsiteHeader websiteId={websiteId} showLinks={showLinks} />
|
<WebsiteHeader websiteId={websiteId} showLinks={showLinks} />
|
||||||
<FilterTags websiteId={websiteId} params={params} />
|
<FilterTags websiteId={websiteId} params={params} />
|
||||||
<WebsiteMetricsBar websiteId={websiteId} showChange={true} sticky={true} />
|
<WebsiteMetricsBar websiteId={websiteId} showChange={true} sticky={true} />
|
||||||
<WebsiteChart websiteId={websiteId} />
|
<WebsiteChart websiteId={websiteId} />
|
||||||
{!website && <Loading icon="dots" style={{ minHeight: 300 }} />}
|
{!view && <WebsiteTableView websiteId={websiteId} />}
|
||||||
{website && (
|
{view && <WebsiteExpandedView websiteId={websiteId} />}
|
||||||
<>
|
</WebsiteProvider>
|
||||||
{!view && <WebsiteTableView websiteId={websiteId} domainName={website.domain} />}
|
|
||||||
{view && <WebsiteExpandedView websiteId={websiteId} domainName={website.domain} />}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -10,17 +10,10 @@ import CountriesTable from 'components/metrics/CountriesTable';
|
|||||||
import EventsTable from 'components/metrics/EventsTable';
|
import EventsTable from 'components/metrics/EventsTable';
|
||||||
import EventsChart from 'components/metrics/EventsChart';
|
import EventsChart from 'components/metrics/EventsChart';
|
||||||
|
|
||||||
export default function WebsiteTableView({
|
export default function WebsiteTableView({ websiteId }: { websiteId: string }) {
|
||||||
websiteId,
|
|
||||||
domainName,
|
|
||||||
}: {
|
|
||||||
websiteId: string;
|
|
||||||
domainName: string;
|
|
||||||
}) {
|
|
||||||
const [countryData, setCountryData] = useState();
|
const [countryData, setCountryData] = useState();
|
||||||
const tableProps = {
|
const tableProps = {
|
||||||
websiteId,
|
websiteId,
|
||||||
domainName,
|
|
||||||
limit: 10,
|
limit: 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ import FilterTags from 'components/metrics/FilterTags';
|
|||||||
import { useNavigation } from 'components/hooks';
|
import { useNavigation } from 'components/hooks';
|
||||||
import { FILTER_COLUMNS } from 'lib/constants';
|
import { FILTER_COLUMNS } from 'lib/constants';
|
||||||
import WebsiteChart from '../WebsiteChart';
|
import WebsiteChart from '../WebsiteChart';
|
||||||
|
import WebsiteCompareTables from './WebsiteCompareTables';
|
||||||
|
import WebsiteProvider from '../WebsiteProvider';
|
||||||
|
|
||||||
export function WebsiteComparePage({ websiteId }) {
|
export function WebsiteComparePage({ websiteId }) {
|
||||||
const { query } = useNavigation();
|
const { query } = useNavigation();
|
||||||
@ -17,12 +19,13 @@ export function WebsiteComparePage({ websiteId }) {
|
|||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<WebsiteProvider websiteId={websiteId}>
|
||||||
<WebsiteHeader websiteId={websiteId} />
|
<WebsiteHeader websiteId={websiteId} />
|
||||||
<FilterTags websiteId={websiteId} params={params} />
|
<FilterTags websiteId={websiteId} params={params} />
|
||||||
<WebsiteMetricsBar websiteId={websiteId} compareMode={true} />
|
<WebsiteMetricsBar websiteId={websiteId} compareMode={true} />
|
||||||
<WebsiteChart websiteId={websiteId} compareMode={true} />
|
<WebsiteChart websiteId={websiteId} compareMode={true} />
|
||||||
</>
|
<WebsiteCompareTables websiteId={websiteId} />
|
||||||
|
</WebsiteProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
.container {
|
||||||
|
margin-bottom: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
width: 200px;
|
||||||
|
}
|
@ -0,0 +1,137 @@
|
|||||||
|
import SideNav from 'components/layout/SideNav';
|
||||||
|
import { useMessages, useNavigation } from 'components/hooks';
|
||||||
|
import PagesTable from 'components/metrics/PagesTable';
|
||||||
|
import ReferrersTable from 'components/metrics/ReferrersTable';
|
||||||
|
import BrowsersTable from 'components/metrics/BrowsersTable';
|
||||||
|
import OSTable from 'components/metrics/OSTable';
|
||||||
|
import DevicesTable from 'components/metrics/DevicesTable';
|
||||||
|
import ScreenTable from 'components/metrics/ScreenTable';
|
||||||
|
import CountriesTable from 'components/metrics/CountriesTable';
|
||||||
|
import RegionsTable from 'components/metrics/RegionsTable';
|
||||||
|
import CitiesTable from 'components/metrics/CitiesTable';
|
||||||
|
import LanguagesTable from 'components/metrics/LanguagesTable';
|
||||||
|
import EventsTable from 'components/metrics/EventsTable';
|
||||||
|
import QueryParametersTable from 'components/metrics/QueryParametersTable';
|
||||||
|
import { Grid, GridRow } from 'components/layout/Grid';
|
||||||
|
import styles from './WebsiteCompareTables.module.css';
|
||||||
|
import { useContext, useState } from 'react';
|
||||||
|
import MetricsTable from 'components/metrics/MetricsTable';
|
||||||
|
import FilterLink from 'components/common/FilterLink';
|
||||||
|
import { WebsiteContext } from '../WebsiteProvider';
|
||||||
|
|
||||||
|
const views = {
|
||||||
|
url: PagesTable,
|
||||||
|
title: PagesTable,
|
||||||
|
referrer: ReferrersTable,
|
||||||
|
browser: BrowsersTable,
|
||||||
|
os: OSTable,
|
||||||
|
device: DevicesTable,
|
||||||
|
screen: ScreenTable,
|
||||||
|
country: CountriesTable,
|
||||||
|
region: RegionsTable,
|
||||||
|
city: CitiesTable,
|
||||||
|
language: LanguagesTable,
|
||||||
|
event: EventsTable,
|
||||||
|
query: QueryParametersTable,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function WebsiteCompareTables({ websiteId }: { websiteId: string }) {
|
||||||
|
const { domain } = useContext(WebsiteContext);
|
||||||
|
const [data, setData] = useState([]);
|
||||||
|
const { formatMessage, labels } = useMessages();
|
||||||
|
const {
|
||||||
|
renderUrl,
|
||||||
|
query: { view },
|
||||||
|
} = useNavigation();
|
||||||
|
const Component: typeof MetricsTable = views[view] || (() => null);
|
||||||
|
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
key: 'url',
|
||||||
|
label: formatMessage(labels.pages),
|
||||||
|
url: renderUrl({ view: 'url' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'referrer',
|
||||||
|
label: formatMessage(labels.referrers),
|
||||||
|
url: renderUrl({ view: 'referrer' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'browser',
|
||||||
|
label: formatMessage(labels.browsers),
|
||||||
|
url: renderUrl({ view: 'browser' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'os',
|
||||||
|
label: formatMessage(labels.os),
|
||||||
|
url: renderUrl({ view: 'os' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'device',
|
||||||
|
label: formatMessage(labels.devices),
|
||||||
|
url: renderUrl({ view: 'device' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'country',
|
||||||
|
label: formatMessage(labels.countries),
|
||||||
|
url: renderUrl({ view: 'country' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'region',
|
||||||
|
label: formatMessage(labels.regions),
|
||||||
|
url: renderUrl({ view: 'region' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'city',
|
||||||
|
label: formatMessage(labels.cities),
|
||||||
|
url: renderUrl({ view: 'city' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'language',
|
||||||
|
label: formatMessage(labels.languages),
|
||||||
|
url: renderUrl({ view: 'language' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'screen',
|
||||||
|
label: formatMessage(labels.screens),
|
||||||
|
url: renderUrl({ view: 'screen' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'event',
|
||||||
|
label: formatMessage(labels.events),
|
||||||
|
url: renderUrl({ view: 'event' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'query',
|
||||||
|
label: formatMessage(labels.queryParameters),
|
||||||
|
url: renderUrl({ view: 'query' }),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const renderLabel = ({ x, y }, index) => {
|
||||||
|
return (
|
||||||
|
<FilterLink
|
||||||
|
id={view}
|
||||||
|
value={x}
|
||||||
|
label={!x && formatMessage(labels.none)}
|
||||||
|
externalUrl={
|
||||||
|
view === 'url' ? `${domain.startsWith('http') ? domain : `https://${domain}`}${x}` : null
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{y} : {data[index]?.y} !
|
||||||
|
</FilterLink>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid className={styles.container}>
|
||||||
|
<GridRow columns="compare">
|
||||||
|
<SideNav className={styles.nav} items={items} selectedKey={view} shallow={true} />
|
||||||
|
<Component websiteId={websiteId} limit={20} showMore={false} onDataLoad={setData} />
|
||||||
|
<Component websiteId={websiteId} limit={20} showMore={false} renderLabel={renderLabel} />
|
||||||
|
</GridRow>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WebsiteCompareTables;
|
@ -1,8 +1,8 @@
|
|||||||
import WebsiteDetails from './WebsiteDetails';
|
import WebsiteDetailsPage from './WebsiteDetailsPage';
|
||||||
import { Metadata } from 'next';
|
import { Metadata } from 'next';
|
||||||
|
|
||||||
export default function WebsitePage({ params: { websiteId } }) {
|
export default function WebsitePage({ params: { websiteId } }) {
|
||||||
return <WebsiteDetails websiteId={websiteId} />;
|
return <WebsiteDetailsPage websiteId={websiteId} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import WebsiteDetails from 'app/(main)/websites/[websiteId]/WebsiteDetails';
|
import WebsiteDetailsPage from '../../(main)/websites/[websiteId]/WebsiteDetailsPage';
|
||||||
import { useShareToken } from 'components/hooks';
|
import { useShareToken } from 'components/hooks';
|
||||||
import Page from 'components/layout/Page';
|
import Page from 'components/layout/Page';
|
||||||
import Header from './Header';
|
import Header from './Header';
|
||||||
@ -17,7 +17,7 @@ export default function SharePage({ shareId }) {
|
|||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<Page>
|
<Page>
|
||||||
<Header />
|
<Header />
|
||||||
<WebsiteDetails websiteId={shareToken.websiteId} />
|
<WebsiteDetailsPage websiteId={shareToken.websiteId} />
|
||||||
<Footer />
|
<Footer />
|
||||||
</Page>
|
</Page>
|
||||||
</div>
|
</div>
|
||||||
|
@ -98,9 +98,9 @@ export function Chart({
|
|||||||
// Allow config changes before update
|
// Allow config changes before update
|
||||||
onUpdate?.(chart.current);
|
onUpdate?.(chart.current);
|
||||||
|
|
||||||
setLegendItems(chart.current.legend.legendItems);
|
|
||||||
|
|
||||||
chart.current.update(updateMode);
|
chart.current.update(updateMode);
|
||||||
|
|
||||||
|
setLegendItems(chart.current.legend.legendItems);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -23,6 +23,15 @@ export function WebsiteDateFilter({ websiteId }: { websiteId: string }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
|
<DateFilter
|
||||||
|
className={styles.dropdown}
|
||||||
|
value={value}
|
||||||
|
startDate={startDate}
|
||||||
|
endDate={endDate}
|
||||||
|
offset={offset}
|
||||||
|
onChange={handleChange}
|
||||||
|
showAllTime={true}
|
||||||
|
/>
|
||||||
{value !== 'all' && !value.startsWith('range') && (
|
{value !== 'all' && !value.startsWith('range') && (
|
||||||
<div className={styles.buttons}>
|
<div className={styles.buttons}>
|
||||||
<Button onClick={() => handleIncrement(-1)}>
|
<Button onClick={() => handleIncrement(-1)}>
|
||||||
@ -37,15 +46,6 @@ export function WebsiteDateFilter({ websiteId }: { websiteId: string }) {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<DateFilter
|
|
||||||
className={styles.dropdown}
|
|
||||||
value={value}
|
|
||||||
startDate={startDate}
|
|
||||||
endDate={endDate}
|
|
||||||
offset={offset}
|
|
||||||
onChange={handleChange}
|
|
||||||
showAllTime={true}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
border-top: 1px solid var(--base300);
|
border-top: 1px solid var(--base300);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.row.compare {
|
||||||
|
grid-template-columns: max-content 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
.col {
|
.col {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
min-height: 430px;
|
min-height: 430px;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { CSSProperties } from 'react';
|
import { CSSProperties } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { mapChildren } from 'react-basics';
|
import { mapChildren } from 'react-basics';
|
||||||
|
// eslint-disable-next-line css-modules/no-unused-class
|
||||||
import styles from './Grid.module.css';
|
import styles from './Grid.module.css';
|
||||||
|
|
||||||
export interface GridProps {
|
export interface GridProps {
|
||||||
@ -19,13 +20,13 @@ export function Grid({ className, style, children }: GridProps) {
|
|||||||
|
|
||||||
export function GridRow(props: {
|
export function GridRow(props: {
|
||||||
[x: string]: any;
|
[x: string]: any;
|
||||||
columns?: 'one' | 'two' | 'three' | 'one-two' | 'two-one';
|
columns?: 'one' | 'two' | 'three' | 'one-two' | 'two-one' | 'compare';
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: any;
|
children?: any;
|
||||||
}) {
|
}) {
|
||||||
const { columns = 'two', className, children, ...otherProps } = props;
|
const { columns = 'two', className, children, ...otherProps } = props;
|
||||||
return (
|
return (
|
||||||
<div {...otherProps} className={classNames(styles.row, className)}>
|
<div {...otherProps} className={classNames(styles.row, className, { [styles[columns]]: true })}>
|
||||||
{mapChildren(children, child => {
|
{mapChildren(children, child => {
|
||||||
return <div className={classNames(styles.col, { [styles[columns]]: true })}>{child}</div>;
|
return <div className={classNames(styles.col, { [styles[columns]]: true })}>{child}</div>;
|
||||||
})}
|
})}
|
||||||
|
@ -14,7 +14,7 @@ export interface ListTableProps {
|
|||||||
title?: string;
|
title?: string;
|
||||||
metric?: string;
|
metric?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
renderLabel?: (row: any) => ReactNode;
|
renderLabel?: (row: any, index: number) => ReactNode;
|
||||||
animate?: boolean;
|
animate?: boolean;
|
||||||
virtualize?: boolean;
|
virtualize?: boolean;
|
||||||
showPercentage?: boolean;
|
showPercentage?: boolean;
|
||||||
@ -34,13 +34,13 @@ export function ListTable({
|
|||||||
}: ListTableProps) {
|
}: ListTableProps) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
||||||
const getRow = row => {
|
const getRow = (row: { x: any; y: any; z: any }, index: number) => {
|
||||||
const { x: label, y: value, z: percent } = row;
|
const { x: label, y: value, z: percent } = row;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AnimatedRow
|
<AnimatedRow
|
||||||
key={label}
|
key={label}
|
||||||
label={renderLabel ? renderLabel(row) : label ?? formatMessage(labels.unknown)}
|
label={renderLabel ? renderLabel(row, index) : label ?? formatMessage(labels.unknown)}
|
||||||
value={value}
|
value={value}
|
||||||
percent={percent}
|
percent={percent}
|
||||||
animate={animate && !virtualize}
|
animate={animate && !virtualize}
|
||||||
@ -50,7 +50,7 @@ export function ListTable({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Row = ({ index, style }) => {
|
const Row = ({ index, style }) => {
|
||||||
return <div style={style}>{getRow(data[index])}</div>;
|
return <div style={style}>{getRow(data[index], index)}</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -71,7 +71,7 @@ export function ListTable({
|
|||||||
{Row}
|
{Row}
|
||||||
</FixedSizeList>
|
</FixedSizeList>
|
||||||
) : (
|
) : (
|
||||||
data.map(row => getRow(row))
|
data.map(getRow)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -97,9 +97,7 @@ const AnimatedRow = ({ label, value = 0, percent, animate, showPercentage = true
|
|||||||
{showPercentage && (
|
{showPercentage && (
|
||||||
<div className={styles.percent}>
|
<div className={styles.percent}>
|
||||||
<animated.div className={styles.bar} style={{ width: props.width.to(n => `${n}%`) }} />
|
<animated.div className={styles.bar} style={{ width: props.width.to(n => `${n}%`) }} />
|
||||||
<animated.span className={styles.percentValue}>
|
<animated.span>{props.width.to(n => `${n?.toFixed?.(0)}%`)}</animated.span>
|
||||||
{props.width.to(n => `${n?.toFixed?.(0)}%`)}
|
|
||||||
</animated.span>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,7 +18,6 @@ import styles from './MetricsTable.module.css';
|
|||||||
|
|
||||||
export interface MetricsTableProps extends ListTableProps {
|
export interface MetricsTableProps extends ListTableProps {
|
||||||
websiteId: string;
|
websiteId: string;
|
||||||
domainName: string;
|
|
||||||
type?: string;
|
type?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
dataFilter?: (data: any) => any;
|
dataFilter?: (data: any) => any;
|
||||||
@ -27,6 +26,7 @@ export interface MetricsTableProps extends ListTableProps {
|
|||||||
onDataLoad?: (data: any) => void;
|
onDataLoad?: (data: any) => void;
|
||||||
onSearch?: (search: string) => void;
|
onSearch?: (search: string) => void;
|
||||||
allowSearch?: boolean;
|
allowSearch?: boolean;
|
||||||
|
showMore?: boolean;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,6 +39,7 @@ export function MetricsTable({
|
|||||||
onDataLoad,
|
onDataLoad,
|
||||||
delay = null,
|
delay = null,
|
||||||
allowSearch = false,
|
allowSearch = false,
|
||||||
|
showMore = true,
|
||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
}: MetricsTableProps) {
|
}: MetricsTableProps) {
|
||||||
@ -98,7 +99,7 @@ export function MetricsTable({
|
|||||||
)}
|
)}
|
||||||
{!data && isLoading && !isFetched && <Loading icon="dots" />}
|
{!data && isLoading && !isFetched && <Loading icon="dots" />}
|
||||||
<div className={styles.footer}>
|
<div className={styles.footer}>
|
||||||
{data && !error && limit && (
|
{showMore && data && !error && limit && (
|
||||||
<LinkButton href={renderUrl({ view: type })} variant="quiet">
|
<LinkButton href={renderUrl({ view: type })} variant="quiet">
|
||||||
<Text>{formatMessage(labels.more)}</Text>
|
<Text>{formatMessage(labels.more)}</Text>
|
||||||
<Icon size="sm" rotate={dir === 'rtl' ? 180 : 0}>
|
<Icon size="sm" rotate={dir === 'rtl' ? 180 : 0}>
|
||||||
|
@ -4,18 +4,21 @@ import MetricsTable, { MetricsTableProps } from './MetricsTable';
|
|||||||
import { useMessages } from 'components/hooks';
|
import { useMessages } from 'components/hooks';
|
||||||
import { useNavigation } from 'components/hooks';
|
import { useNavigation } from 'components/hooks';
|
||||||
import { emptyFilter } from 'lib/filters';
|
import { emptyFilter } from 'lib/filters';
|
||||||
|
import { useContext } from 'react';
|
||||||
|
import { WebsiteContext } from 'app/(main)/websites/[websiteId]/WebsiteProvider';
|
||||||
|
|
||||||
export interface PagesTableProps extends MetricsTableProps {
|
export interface PagesTableProps extends MetricsTableProps {
|
||||||
allowFilter?: boolean;
|
allowFilter?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PagesTable({ allowFilter, domainName, ...props }: PagesTableProps) {
|
export function PagesTable({ allowFilter, ...props }: PagesTableProps) {
|
||||||
const {
|
const {
|
||||||
router,
|
router,
|
||||||
renderUrl,
|
renderUrl,
|
||||||
query: { view = 'url' },
|
query: { view = 'url' },
|
||||||
} = useNavigation();
|
} = useNavigation();
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
const { domain } = useContext(WebsiteContext);
|
||||||
|
|
||||||
const handleSelect = (key: any) => {
|
const handleSelect = (key: any) => {
|
||||||
router.push(renderUrl({ view: key }), { scroll: true });
|
router.push(renderUrl({ view: key }), { scroll: true });
|
||||||
@ -39,9 +42,7 @@ export function PagesTable({ allowFilter, domainName, ...props }: PagesTableProp
|
|||||||
value={x}
|
value={x}
|
||||||
label={!x && formatMessage(labels.none)}
|
label={!x && formatMessage(labels.none)}
|
||||||
externalUrl={
|
externalUrl={
|
||||||
view === 'url'
|
view === 'url' ? `${domain.startsWith('http') ? domain : `https://${domain}`}${x}` : null
|
||||||
? `${domainName.startsWith('http') ? domainName : `https://${domainName}`}${x}`
|
|
||||||
: null
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -50,12 +51,11 @@ export function PagesTable({ allowFilter, domainName, ...props }: PagesTableProp
|
|||||||
return (
|
return (
|
||||||
<MetricsTable
|
<MetricsTable
|
||||||
{...props}
|
{...props}
|
||||||
domainName={domainName}
|
|
||||||
title={formatMessage(labels.pages)}
|
title={formatMessage(labels.pages)}
|
||||||
type={view}
|
type={view}
|
||||||
metric={formatMessage(labels.views)}
|
metric={formatMessage(labels.views)}
|
||||||
dataFilter={emptyFilter}
|
dataFilter={emptyFilter}
|
||||||
renderLabel={renderLink}
|
renderLabel={props.renderLabel || renderLink}
|
||||||
>
|
>
|
||||||
{allowFilter && <FilterButtons items={buttons} selectedKey={view} onSelect={handleSelect} />}
|
{allowFilter && <FilterButtons items={buttons} selectedKey={view} onSelect={handleSelect} />}
|
||||||
</MetricsTable>
|
</MetricsTable>
|
||||||
|
Loading…
Reference in New Issue
Block a user