diff --git a/src/app/(main)/websites/[websiteId]/WebsiteChart.tsx b/src/app/(main)/websites/[websiteId]/WebsiteChart.tsx
index d36cdad6..48da2377 100644
--- a/src/app/(main)/websites/[websiteId]/WebsiteChart.tsx
+++ b/src/app/(main)/websites/[websiteId]/WebsiteChart.tsx
@@ -9,7 +9,7 @@ export function WebsiteChart({
compareMode = false,
}: {
websiteId: string;
- compareMode: boolean;
+ compareMode?: boolean;
}) {
const { dateRange, dateCompare } = useDateRange(websiteId);
const { startDate, endDate, unit } = dateRange;
@@ -27,13 +27,13 @@ export function WebsiteChart({
result['compare'] = {
pageviews: result.pageviews.map(({ x }, i) => ({
x,
- y: compare.pageviews[i].y,
- d: compare.pageviews[i].x,
+ y: compare.pageviews[i]?.y,
+ d: compare.pageviews[i]?.x,
})),
sessions: result.sessions.map(({ x }, i) => ({
x,
- y: compare.sessions[i].y,
- d: compare.pageviews[i].x,
+ y: compare.sessions[i]?.y,
+ d: compare.sessions[i]?.x,
})),
};
}
diff --git a/src/app/(main)/websites/[websiteId]/WebsiteDetails.tsx b/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx
similarity index 58%
rename from src/app/(main)/websites/[websiteId]/WebsiteDetails.tsx
rename to src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx
index 1fd6992f..2988494e 100644
--- a/src/app/(main)/websites/[websiteId]/WebsiteDetails.tsx
+++ b/src/app/(main)/websites/[websiteId]/WebsiteDetailsPage.tsx
@@ -1,25 +1,19 @@
'use client';
-import { Loading } from 'react-basics';
import { usePathname } from 'next/navigation';
-import Page from 'components/layout/Page';
import FilterTags from 'components/metrics/FilterTags';
-import { useNavigation, useWebsite } from 'components/hooks';
+import { useNavigation } from 'components/hooks';
import WebsiteChart from './WebsiteChart';
import WebsiteExpandedView from './WebsiteExpandedView';
import WebsiteHeader from './WebsiteHeader';
import WebsiteMetricsBar from './WebsiteMetricsBar';
import WebsiteTableView from './WebsiteTableView';
+import WebsiteProvider from './WebsiteProvider';
import { FILTER_COLUMNS } from 'lib/constants';
-export default function WebsiteDetails({ websiteId }: { websiteId: string }) {
- const { data: website, isLoading, error } = useWebsite(websiteId);
+export default function WebsiteDetailsPage({ websiteId }: { websiteId: string }) {
const pathname = usePathname();
const { query } = useNavigation();
- if (isLoading || error) {
- return ;
- }
-
const showLinks = !pathname.includes('/share/');
const { view } = query;
@@ -31,18 +25,13 @@ export default function WebsiteDetails({ websiteId }: { websiteId: string }) {
}, {});
return (
- <>
+
- {!website && }
- {website && (
- <>
- {!view && }
- {view && }
- >
- )}
- >
+ {!view && }
+ {view && }
+
);
}
diff --git a/src/app/(main)/websites/[websiteId]/WebsiteTableView.tsx b/src/app/(main)/websites/[websiteId]/WebsiteTableView.tsx
index 7cc415e5..e530f2ba 100644
--- a/src/app/(main)/websites/[websiteId]/WebsiteTableView.tsx
+++ b/src/app/(main)/websites/[websiteId]/WebsiteTableView.tsx
@@ -10,17 +10,10 @@ import CountriesTable from 'components/metrics/CountriesTable';
import EventsTable from 'components/metrics/EventsTable';
import EventsChart from 'components/metrics/EventsChart';
-export default function WebsiteTableView({
- websiteId,
- domainName,
-}: {
- websiteId: string;
- domainName: string;
-}) {
+export default function WebsiteTableView({ websiteId }: { websiteId: string }) {
const [countryData, setCountryData] = useState();
const tableProps = {
websiteId,
- domainName,
limit: 10,
};
diff --git a/src/app/(main)/websites/[websiteId]/compare/WebsiteComparePage.tsx b/src/app/(main)/websites/[websiteId]/compare/WebsiteComparePage.tsx
index da330691..092ebe94 100644
--- a/src/app/(main)/websites/[websiteId]/compare/WebsiteComparePage.tsx
+++ b/src/app/(main)/websites/[websiteId]/compare/WebsiteComparePage.tsx
@@ -5,6 +5,8 @@ import FilterTags from 'components/metrics/FilterTags';
import { useNavigation } from 'components/hooks';
import { FILTER_COLUMNS } from 'lib/constants';
import WebsiteChart from '../WebsiteChart';
+import WebsiteCompareTables from './WebsiteCompareTables';
+import WebsiteProvider from '../WebsiteProvider';
export function WebsiteComparePage({ websiteId }) {
const { query } = useNavigation();
@@ -17,12 +19,13 @@ export function WebsiteComparePage({ websiteId }) {
}, {});
return (
- <>
+
- >
+
+
);
}
diff --git a/src/app/(main)/websites/[websiteId]/compare/WebsiteCompareTables.module.css b/src/app/(main)/websites/[websiteId]/compare/WebsiteCompareTables.module.css
new file mode 100644
index 00000000..4595f573
--- /dev/null
+++ b/src/app/(main)/websites/[websiteId]/compare/WebsiteCompareTables.module.css
@@ -0,0 +1,7 @@
+.container {
+ margin-bottom: 60px;
+}
+
+.nav {
+ width: 200px;
+}
diff --git a/src/app/(main)/websites/[websiteId]/compare/WebsiteCompareTables.tsx b/src/app/(main)/websites/[websiteId]/compare/WebsiteCompareTables.tsx
new file mode 100644
index 00000000..f5819770
--- /dev/null
+++ b/src/app/(main)/websites/[websiteId]/compare/WebsiteCompareTables.tsx
@@ -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 (
+
+ {y} : {data[index]?.y} !
+
+ );
+ };
+
+ return (
+
+
+
+
+
+
+
+ );
+}
+
+export default WebsiteCompareTables;
diff --git a/src/app/(main)/websites/[websiteId]/page.tsx b/src/app/(main)/websites/[websiteId]/page.tsx
index ddb6c833..49bca9b6 100644
--- a/src/app/(main)/websites/[websiteId]/page.tsx
+++ b/src/app/(main)/websites/[websiteId]/page.tsx
@@ -1,8 +1,8 @@
-import WebsiteDetails from './WebsiteDetails';
+import WebsiteDetailsPage from './WebsiteDetailsPage';
import { Metadata } from 'next';
export default function WebsitePage({ params: { websiteId } }) {
- return ;
+ return ;
}
export const metadata: Metadata = {
diff --git a/src/app/share/[...shareId]/SharePage.tsx b/src/app/share/[...shareId]/SharePage.tsx
index b49d36ec..4ac6af37 100644
--- a/src/app/share/[...shareId]/SharePage.tsx
+++ b/src/app/share/[...shareId]/SharePage.tsx
@@ -1,5 +1,5 @@
'use client';
-import WebsiteDetails from 'app/(main)/websites/[websiteId]/WebsiteDetails';
+import WebsiteDetailsPage from '../../(main)/websites/[websiteId]/WebsiteDetailsPage';
import { useShareToken } from 'components/hooks';
import Page from 'components/layout/Page';
import Header from './Header';
@@ -17,7 +17,7 @@ export default function SharePage({ shareId }) {
diff --git a/src/components/charts/Chart.tsx b/src/components/charts/Chart.tsx
index 47d29c07..6ba60159 100644
--- a/src/components/charts/Chart.tsx
+++ b/src/components/charts/Chart.tsx
@@ -98,9 +98,9 @@ export function Chart({
// Allow config changes before update
onUpdate?.(chart.current);
- setLegendItems(chart.current.legend.legendItems);
-
chart.current.update(updateMode);
+
+ setLegendItems(chart.current.legend.legendItems);
};
useEffect(() => {
diff --git a/src/components/input/WebsiteDateFilter.tsx b/src/components/input/WebsiteDateFilter.tsx
index 12718b3d..4f2dee0a 100644
--- a/src/components/input/WebsiteDateFilter.tsx
+++ b/src/components/input/WebsiteDateFilter.tsx
@@ -23,6 +23,15 @@ export function WebsiteDateFilter({ websiteId }: { websiteId: string }) {
return (
+
{value !== 'all' && !value.startsWith('range') && (
)}
-
);
}
diff --git a/src/components/layout/Grid.module.css b/src/components/layout/Grid.module.css
index f72a5f12..de99b752 100644
--- a/src/components/layout/Grid.module.css
+++ b/src/components/layout/Grid.module.css
@@ -8,6 +8,10 @@
border-top: 1px solid var(--base300);
}
+.row.compare {
+ grid-template-columns: max-content 1fr 1fr;
+}
+
.col {
padding: 20px;
min-height: 430px;
diff --git a/src/components/layout/Grid.tsx b/src/components/layout/Grid.tsx
index 2a34fdc4..ec7f4fda 100644
--- a/src/components/layout/Grid.tsx
+++ b/src/components/layout/Grid.tsx
@@ -1,6 +1,7 @@
import { CSSProperties } from 'react';
import classNames from 'classnames';
import { mapChildren } from 'react-basics';
+// eslint-disable-next-line css-modules/no-unused-class
import styles from './Grid.module.css';
export interface GridProps {
@@ -19,13 +20,13 @@ export function Grid({ className, style, children }: GridProps) {
export function GridRow(props: {
[x: string]: any;
- columns?: 'one' | 'two' | 'three' | 'one-two' | 'two-one';
+ columns?: 'one' | 'two' | 'three' | 'one-two' | 'two-one' | 'compare';
className?: string;
children?: any;
}) {
const { columns = 'two', className, children, ...otherProps } = props;
return (
-
+
{mapChildren(children, child => {
return
{child}
;
})}
diff --git a/src/components/metrics/ListTable.tsx b/src/components/metrics/ListTable.tsx
index 133905e1..14f2c990 100644
--- a/src/components/metrics/ListTable.tsx
+++ b/src/components/metrics/ListTable.tsx
@@ -14,7 +14,7 @@ export interface ListTableProps {
title?: string;
metric?: string;
className?: string;
- renderLabel?: (row: any) => ReactNode;
+ renderLabel?: (row: any, index: number) => ReactNode;
animate?: boolean;
virtualize?: boolean;
showPercentage?: boolean;
@@ -34,13 +34,13 @@ export function ListTable({
}: ListTableProps) {
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;
return (
{
- return {getRow(data[index])}
;
+ return {getRow(data[index], index)}
;
};
return (
@@ -71,7 +71,7 @@ export function ListTable({
{Row}
) : (
- data.map(row => getRow(row))
+ data.map(getRow)
)}
@@ -97,9 +97,7 @@ const AnimatedRow = ({ label, value = 0, percent, animate, showPercentage = true
{showPercentage && (
`${n}%`) }} />
-
- {props.width.to(n => `${n?.toFixed?.(0)}%`)}
-
+ {props.width.to(n => `${n?.toFixed?.(0)}%`)}
)}
diff --git a/src/components/metrics/MetricsTable.tsx b/src/components/metrics/MetricsTable.tsx
index 857c136b..6da0e289 100644
--- a/src/components/metrics/MetricsTable.tsx
+++ b/src/components/metrics/MetricsTable.tsx
@@ -18,7 +18,6 @@ import styles from './MetricsTable.module.css';
export interface MetricsTableProps extends ListTableProps {
websiteId: string;
- domainName: string;
type?: string;
className?: string;
dataFilter?: (data: any) => any;
@@ -27,6 +26,7 @@ export interface MetricsTableProps extends ListTableProps {
onDataLoad?: (data: any) => void;
onSearch?: (search: string) => void;
allowSearch?: boolean;
+ showMore?: boolean;
children?: ReactNode;
}
@@ -39,6 +39,7 @@ export function MetricsTable({
onDataLoad,
delay = null,
allowSearch = false,
+ showMore = true,
children,
...props
}: MetricsTableProps) {
@@ -98,7 +99,7 @@ export function MetricsTable({
)}
{!data && isLoading && !isFetched && }
- {data && !error && limit && (
+ {showMore && data && !error && limit && (
{formatMessage(labels.more)}
diff --git a/src/components/metrics/PagesTable.tsx b/src/components/metrics/PagesTable.tsx
index b0da8080..ca3f6be5 100644
--- a/src/components/metrics/PagesTable.tsx
+++ b/src/components/metrics/PagesTable.tsx
@@ -4,18 +4,21 @@ import MetricsTable, { MetricsTableProps } from './MetricsTable';
import { useMessages } from 'components/hooks';
import { useNavigation } from 'components/hooks';
import { emptyFilter } from 'lib/filters';
+import { useContext } from 'react';
+import { WebsiteContext } from 'app/(main)/websites/[websiteId]/WebsiteProvider';
export interface PagesTableProps extends MetricsTableProps {
allowFilter?: boolean;
}
-export function PagesTable({ allowFilter, domainName, ...props }: PagesTableProps) {
+export function PagesTable({ allowFilter, ...props }: PagesTableProps) {
const {
router,
renderUrl,
query: { view = 'url' },
} = useNavigation();
const { formatMessage, labels } = useMessages();
+ const { domain } = useContext(WebsiteContext);
const handleSelect = (key: any) => {
router.push(renderUrl({ view: key }), { scroll: true });
@@ -39,9 +42,7 @@ export function PagesTable({ allowFilter, domainName, ...props }: PagesTableProp
value={x}
label={!x && formatMessage(labels.none)}
externalUrl={
- view === 'url'
- ? `${domainName.startsWith('http') ? domainName : `https://${domainName}`}${x}`
- : null
+ view === 'url' ? `${domain.startsWith('http') ? domain : `https://${domain}`}${x}` : null
}
/>
);
@@ -50,12 +51,11 @@ export function PagesTable({ allowFilter, domainName, ...props }: PagesTableProp
return (
{allowFilter && }