Added visited URL column on visits table for orphan visits

This commit is contained in:
Alejandro Celaya 2021-03-28 15:57:22 +02:00
parent 205e3ffb90
commit eabd7d9ecb
3 changed files with 39 additions and 12 deletions

View file

@ -33,6 +33,7 @@ export const OrphanVisits = ({ exportVisits }: VisitsExporter) => boundToMercure
baseUrl={url}
settings={settings}
exportCsv={exportCsv}
isOrphanVisits
>
<OrphanVisitsHeader orphanVisits={orphanVisits} goBack={goBack} />
</VisitsStats>

View file

@ -6,6 +6,7 @@ import { faCalendarAlt, faMapMarkedAlt, faList, faChartPie, faFileDownload } fro
import { IconDefinition } from '@fortawesome/fontawesome-common-types';
import { Route, Switch, NavLink as RouterNavLink, Redirect } from 'react-router-dom';
import { Location } from 'history';
import classNames from 'classnames';
import { DateRangeSelector } from '../utils/dates/DateRangeSelector';
import Message from '../utils/Message';
import { formatIsoDate } from '../utils/helpers/date';
@ -31,6 +32,7 @@ export interface VisitsStatsProps {
baseUrl: string;
domain?: string;
exportCsv: (visits: NormalizedVisit[]) => void;
isOrphanVisits?: boolean;
}
interface VisitsNavLinkProps {
@ -77,7 +79,7 @@ const VisitsNavLink: FC<VisitsNavLinkProps & { to: string }> = ({ subPath, title
);
const VisitsStats: FC<VisitsStatsProps> = (
{ children, visitsInfo, getVisits, cancelGetVisits, baseUrl, domain, settings, exportCsv },
{ children, visitsInfo, getVisits, cancelGetVisits, baseUrl, domain, settings, exportCsv, isOrphanVisits = false },
) => {
const initialInterval: DateInterval = settings.visits?.defaultInterval ?? 'last30Days';
const [ dateRange, setDateRange ] = useState<DateRange>(intervalToDateRange(initialInterval));
@ -171,13 +173,13 @@ const VisitsStats: FC<VisitsStatsProps> = (
</Route>
<Route exact path={`${baseUrl}${sections.byContext.subPath}`}>
<div className="col-xl-4 col-lg-6 mt-4">
<div className={classNames('mt-4 col-lg-6', { 'col-xl-4': !isOrphanVisits })}>
<GraphCard title="Operating systems" stats={os} />
</div>
<div className="col-xl-4 col-lg-6 mt-4">
<div className={classNames('mt-4 col-lg-6', { 'col-xl-4': !isOrphanVisits })}>
<GraphCard title="Browsers" stats={browsers} />
</div>
<div className="col-xl-4 mt-4">
<div className={classNames('mt-4', { 'col-xl-4': !isOrphanVisits, 'col-lg-6': isOrphanVisits })}>
<SortableBarGraph
title="Referrers"
stats={referrers}
@ -191,6 +193,18 @@ const VisitsStats: FC<VisitsStatsProps> = (
onClick={highlightVisitsForProp('referer')}
/>
</div>
{isOrphanVisits && (
<div className="mt-4 col-lg-6">
<SortableBarGraph
title="Visited URLs"
stats={{}}
sortingItems={{
visitedUrl: 'Visited URL',
amount: 'Visits amount',
}}
/>
</div>
)}
</Route>
<Route exact path={`${baseUrl}${sections.byLocation.subPath}`}>
@ -232,6 +246,7 @@ const VisitsStats: FC<VisitsStatsProps> = (
visits={normalizedVisits}
selectedVisits={highlightedVisits}
setSelectedVisits={setSelectedVisits}
isOrphanVisits={isOrphanVisits}
/>
</div>
</Route>

View file

@ -12,7 +12,7 @@ import SimplePaginator from '../common/SimplePaginator';
import SearchField from '../utils/SearchField';
import { determineOrderDir, OrderDir } from '../utils/utils';
import { prettify } from '../utils/helpers/numbers';
import { NormalizedVisit } from './types';
import { NormalizedOrphanVisit, NormalizedVisit } from './types';
import './VisitsTable.scss';
interface VisitsTableProps {
@ -20,9 +20,10 @@ interface VisitsTableProps {
selectedVisits?: NormalizedVisit[];
setSelectedVisits: (visits: NormalizedVisit[]) => void;
matchMedia?: (query: string) => MediaQueryList;
isOrphanVisits?: boolean;
}
type OrderableFields = 'date' | 'country' | 'city' | 'browser' | 'os' | 'referer';
type OrderableFields = 'date' | 'country' | 'city' | 'browser' | 'os' | 'referer' | 'visitedUrl';
interface Order {
field?: OrderableFields;
@ -30,8 +31,10 @@ interface Order {
}
const PAGE_SIZE = 20;
const visitMatchesSearch = ({ browser, os, referer, country, city }: NormalizedVisit, searchTerm: string) =>
`${browser} ${os} ${referer} ${country} ${city}`.toLowerCase().includes(searchTerm.toLowerCase());
const visitMatchesSearch = ({ browser, os, referer, country, city, ...rest }: NormalizedVisit, searchTerm: string) =>
`${browser} ${os} ${referer} ${country} ${city} ${(rest as NormalizedOrphanVisit).visitedUrl}`.toLowerCase().includes(
searchTerm.toLowerCase(),
);
const searchVisits = (searchTerm: string, visits: NormalizedVisit[]) =>
visits.filter((visit) => visitMatchesSearch(visit, searchTerm));
const sortVisits = ({ field, dir }: Order, visits: NormalizedVisit[]) => !field || !dir ? visits : visits.sort(
@ -39,7 +42,7 @@ const sortVisits = ({ field, dir }: Order, visits: NormalizedVisit[]) => !field
const greaterThan = dir === 'ASC' ? 1 : -1;
const smallerThan = dir === 'ASC' ? -1 : 1;
return a[field] > b[field] ? greaterThan : smallerThan;
return (a as NormalizedOrphanVisit)[field] > (b as NormalizedOrphanVisit)[field] ? greaterThan : smallerThan;
},
);
const calculateVisits = (allVisits: NormalizedVisit[], searchTerm: string | undefined, order: Order) => {
@ -56,6 +59,7 @@ const VisitsTable = ({
selectedVisits = [],
setSelectedVisits,
matchMedia = window.matchMedia,
isOrphanVisits = false,
}: VisitsTableProps) => {
const headerCellsClass = 'visits-table__header-cell visits-table__sticky';
const matchMobile = () => matchMedia('(max-width: 767px)').matches;
@ -132,9 +136,15 @@ const VisitsTable = ({
Referrer
{renderOrderIcon('referer')}
</th>
{isOrphanVisits && (
<th className={headerCellsClass} onClick={orderByColumn('visitedUrl')}>
Visited URL
{renderOrderIcon('visitedUrl')}
</th>
)}
</tr>
<tr>
<td colSpan={7} className="p-0">
<td colSpan={isOrphanVisits ? 8 : 7} className="p-0">
<SearchField noBorder large={false} onChange={setSearchTerm} />
</td>
</tr>
@ -142,7 +152,7 @@ const VisitsTable = ({
<tbody>
{(!resultSet.visitsGroups[page - 1] || resultSet.visitsGroups[page - 1].length === 0) && (
<tr>
<td colSpan={7} className="text-center">
<td colSpan={isOrphanVisits ? 8 : 7} className="text-center">
No visits found with current filtering
</td>
</tr>
@ -170,6 +180,7 @@ const VisitsTable = ({
<td>{visit.browser}</td>
<td>{visit.os}</td>
<td>{visit.referer}</td>
{isOrphanVisits && <td>{(visit as NormalizedOrphanVisit).visitedUrl}</td>}
</tr>
);
})}
@ -177,7 +188,7 @@ const VisitsTable = ({
{resultSet.total > PAGE_SIZE && (
<tfoot>
<tr>
<td colSpan={7} className="visits-table__footer-cell visits-table__sticky">
<td colSpan={isOrphanVisits ? 8 : 7} className="visits-table__footer-cell visits-table__sticky">
<div className="row">
<div className="col-md-6">
<SimplePaginator