Move date range selection into redux.

This commit is contained in:
Mike Cao 2020-08-31 14:11:30 -07:00
parent d06c077019
commit c5cb19a3bf
21 changed files with 141 additions and 138 deletions

View file

@ -2,15 +2,13 @@ import React from 'react';
import MetricsTable from './MetricsTable';
import { browserFilter } from 'lib/filters';
export default function BrowsersTable({ websiteId, startDate, endDate, limit, onExpand }) {
export default function BrowsersTable({ websiteId, limit, onExpand }) {
return (
<MetricsTable
title="Browsers"
type="browser"
metric="Visitors"
websiteId={websiteId}
startDate={startDate}
endDate={endDate}
limit={limit}
dataFilter={browserFilter}
onExpand={onExpand}

View file

@ -2,22 +2,13 @@ import React from 'react';
import MetricsTable from './MetricsTable';
import { countryFilter, percentFilter } from 'lib/filters';
export default function CountriesTable({
websiteId,
startDate,
endDate,
limit,
onDataLoad,
onExpand,
}) {
export default function CountriesTable({ websiteId, limit, onDataLoad = () => {}, onExpand }) {
return (
<MetricsTable
title="Countries"
type="country"
metric="Visitors"
websiteId={websiteId}
startDate={startDate}
endDate={endDate}
limit={limit}
dataFilter={countryFilter}
onDataLoad={data => onDataLoad(percentFilter(data))}

View file

@ -2,15 +2,13 @@ import React from 'react';
import MetricsTable from './MetricsTable';
import { deviceFilter } from 'lib/filters';
export default function DevicesTable({ websiteId, startDate, endDate, limit, onExpand }) {
export default function DevicesTable({ websiteId, limit, onExpand }) {
return (
<MetricsTable
title="Devices"
type="device"
metric="Visitors"
websiteId={websiteId}
startDate={startDate}
endDate={endDate}
limit={limit}
dataFilter={deviceFilter}
onExpand={onExpand}

View file

@ -1,8 +1,9 @@
import React, { useMemo } from 'react';
import tinycolor from 'tinycolor2';
import BarChart from './BarChart';
import { getTimezone, getDateArray, getDateLength } from 'lib/date';
import { getTimezone, getDateArray, getDateLength, getDateRange } from 'lib/date';
import useFetch from 'hooks/useFetch';
import { useSelector } from 'react-redux';
const COLORS = [
'#2680eb',
@ -15,13 +16,19 @@ const COLORS = [
'#85d044',
];
export default function EventsChart({ websiteId, startDate, endDate, unit }) {
const { data } = useFetch(`/api/website/${websiteId}/events`, {
start_at: +startDate,
end_at: +endDate,
unit,
tz: getTimezone(),
});
export default function EventsChart({ websiteId, defaultDateRange = '7day' }) {
const dateRange = useSelector(state => state.websites[websiteId]?.dateRange);
const { startDate, endDate, unit, modified } = dateRange || getDateRange(defaultDateRange);
const { data } = useFetch(
`/api/website/${websiteId}/events`,
{
start_at: +startDate,
end_at: +endDate,
unit,
tz: getTimezone(),
},
{ update: [modified] },
);
const datasets = useMemo(() => {
if (!data) return [];

View file

@ -2,22 +2,13 @@ import React from 'react';
import MetricsTable from './MetricsTable';
import styles from './EventsTable.module.css';
export default function EventsTable({
websiteId,
startDate,
endDate,
limit,
onExpand,
onDataLoad,
}) {
export default function EventsTable({ websiteId, limit, onExpand, onDataLoad }) {
return (
<MetricsTable
title="Events"
type="event"
metric="Actions"
websiteId={websiteId}
startDate={startDate}
endDate={endDate}
limit={limit}
renderLabel={({ x }) => <Label value={x} />}
onExpand={onExpand}

View file

@ -5,12 +5,22 @@ import Loading from 'components/common/Loading';
import useFetch from 'hooks/useFetch';
import { formatShortTime, formatNumber, formatLongNumber } from 'lib/format';
import styles from './MetricsBar.module.css';
import { useSelector } from 'react-redux';
import { getDateRange } from '../../lib/date';
export default function MetricsBar({ websiteId, startDate, endDate, className }) {
const { data } = useFetch(`/api/website/${websiteId}/metrics`, {
start_at: +startDate,
end_at: +endDate,
});
export default function MetricsBar({ websiteId, className, defaultDateRange = '7day' }) {
const dateRange = useSelector(state => state.websites[websiteId]?.dateRange);
const { startDate, endDate, modified } = dateRange || getDateRange(defaultDateRange);
const { data } = useFetch(
`/api/website/${websiteId}/metrics`,
{
start_at: +startDate,
end_at: +endDate,
},
{
update: [modified],
},
);
const [format, setFormat] = useState(true);
const formatFunc = format ? formatLongNumber : formatNumber;

View file

@ -1,4 +1,5 @@
import React, { useState, useMemo } from 'react';
import { useSelector } from 'react-redux';
import { FixedSizeList } from 'react-window';
import { useSpring, animated, config } from 'react-spring';
import classNames from 'classnames';
@ -9,14 +10,13 @@ import Arrow from 'assets/arrow-right.svg';
import { percentFilter } from 'lib/filters';
import { formatNumber, formatLongNumber } from 'lib/format';
import styles from './MetricsTable.module.css';
import { getDateRange } from '../../lib/date';
export default function MetricsTable({
title,
metric,
websiteId,
websiteDomain,
startDate,
endDate,
title,
metric,
type,
className,
dataFilter,
@ -24,9 +24,12 @@ export default function MetricsTable({
limit,
headerComponent,
renderLabel,
defaultDateRange = '7day',
onDataLoad = () => {},
onExpand = () => {},
}) {
const dateRange = useSelector(state => state.websites[websiteId]?.dateRange);
const { startDate, endDate, modified } = dateRange || getDateRange(defaultDateRange);
const { data } = useFetch(
`/api/website/${websiteId}/rankings`,
{
@ -35,7 +38,7 @@ export default function MetricsTable({
end_at: +endDate,
domain: websiteDomain,
},
{ onDataLoad },
{ onDataLoad, delay: 300, update: [modified] },
);
const [format, setFormat] = useState(true);
const formatFunc = format ? formatLongNumber : formatNumber;

View file

@ -2,15 +2,13 @@ import React from 'react';
import MetricsTable from './MetricsTable';
import { osFilter } from 'lib/filters';
export default function OSTable({ websiteId, startDate, endDate, limit, onExpand }) {
export default function OSTable({ websiteId, limit, onExpand }) {
return (
<MetricsTable
title="Operating System"
type="os"
metric="Visitors"
websiteId={websiteId}
startDate={startDate}
endDate={endDate}
limit={limit}
dataFilter={osFilter}
onExpand={onExpand}

View file

@ -3,14 +3,7 @@ import MetricsTable from './MetricsTable';
import { urlFilter } from 'lib/filters';
import ButtonGroup from '../common/ButtonGroup';
export default function PagesTable({
websiteId,
websiteDomain,
startDate,
endDate,
limit,
onExpand,
}) {
export default function PagesTable({ websiteId, websiteDomain, limit, onExpand }) {
const [filter, setFilter] = useState('Combined');
return (
@ -20,8 +13,6 @@ export default function PagesTable({
metric="Views"
headerComponent={limit ? null : <FilterButtons selected={filter} onClick={setFilter} />}
websiteId={websiteId}
startDate={startDate}
endDate={endDate}
limit={limit}
dataFilter={urlFilter}
filterOptions={{ domain: websiteDomain, raw: filter === 'Raw' }}

View file

@ -1,9 +1,8 @@
import React from 'react';
import CheckVisible from 'components/helpers/CheckVisible';
import BarChart from './BarChart';
import { getDateLength } from '../../lib/date';
export default function PageviewsChart({ websiteId, data, startDate, endDate, unit, className }) {
export default function PageviewsChart({ websiteId, data, unit, records, className }) {
const handleUpdate = chart => {
const {
data: { datasets },
@ -44,7 +43,7 @@ export default function PageviewsChart({ websiteId, data, startDate, endDate, un
},
]}
unit={unit}
records={getDateLength(startDate, endDate, unit)}
records={records}
animationDuration={visible ? 300 : 0}
onUpdate={handleUpdate}
/>

View file

@ -12,8 +12,10 @@ const options = {
export default function QuickButtons({ value, onChange }) {
const selectedItem = Object.keys(options).find(key => options[key] === value);
function handleClick(value) {
onChange(getDateRange(options[value]));
function handleClick(selected) {
if (options[selected] !== value) {
onChange(getDateRange(options[selected]));
}
}
return (

View file

@ -1,16 +1,9 @@
import React, { useState } from 'react';
import MetricsTable from './MetricsTable';
import { refFilter } from 'lib/filters';
import ButtonGroup from '../common/ButtonGroup';
import ButtonGroup from 'components/common/ButtonGroup';
export default function Referrers({
websiteId,
websiteDomain,
startDate,
endDate,
limit,
onExpand = () => {},
}) {
export default function ReferrersTable({ websiteId, websiteDomain, limit, onExpand = () => {} }) {
const [filter, setFilter] = useState('Combined');
const renderLink = ({ x: url }) => {
@ -31,8 +24,6 @@ export default function Referrers({
headerComponent={limit ? null : <FilterButtons selected={filter} onClick={setFilter} />}
websiteId={websiteId}
websiteDomain={websiteDomain}
startDate={startDate}
endDate={endDate}
limit={limit}
dataFilter={refFilter}
filterOptions={{

View file

@ -1,4 +1,5 @@
import React, { useState, useMemo } from 'react';
import React, { useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import classNames from 'classnames';
import PageviewsChart from './PageviewsChart';
import MetricsBar from './MetricsBar';
@ -6,18 +7,23 @@ import QuickButtons from './QuickButtons';
import DateFilter from 'components/common/DateFilter';
import StickyHeader from 'components/helpers/StickyHeader';
import useFetch from 'hooks/useFetch';
import { getDateArray, getDateRange, getTimezone } from 'lib/date';
import { getDateArray, getDateLength, getDateRange, getTimezone } from 'lib/date';
import { setDateRange } from 'redux/actions/websites';
import styles from './WebsiteChart.module.css';
import WebsiteHeader from './WebsiteHeader';
export default function WebsiteChart({
websiteId,
title,
defaultDateRange = '7day',
stickyHeader = false,
showLink = false,
onDataLoad = () => {},
onDateChange = () => {},
}) {
const [dateRange, setDateRange] = useState(getDateRange(defaultDateRange));
const { startDate, endDate, unit, value } = dateRange;
const dispatch = useDispatch();
const dateRange = useSelector(state => state.websites[websiteId]?.dateRange);
const { startDate, endDate, unit, value, modified } = dateRange || getDateRange(defaultDateRange);
const { data } = useFetch(
`/api/website/${websiteId}/pageviews`,
{
@ -26,7 +32,7 @@ export default function WebsiteChart({
unit,
tz: getTimezone(),
},
{ onDataLoad },
{ onDataLoad, update: [modified] },
);
const [pageviews, uniques] = useMemo(() => {
@ -40,24 +46,19 @@ export default function WebsiteChart({
}, [data]);
function handleDateChange(values) {
setDateRange(values);
onDateChange(values);
dispatch(setDateRange(websiteId, values));
}
return (
<>
<WebsiteHeader websiteId={websiteId} title={title} showLink={showLink} />
<div className={classNames(styles.header, 'row')}>
<StickyHeader
className={classNames(styles.metrics, 'col row')}
stickyClassName={styles.sticky}
enabled={stickyHeader}
>
<MetricsBar
className="col-12 col-md-9 col-lg-10"
websiteId={websiteId}
startDate={startDate}
endDate={endDate}
/>
<MetricsBar className="col-12 col-md-9 col-lg-10" websiteId={websiteId} />
<DateFilter
className="col-12 col-md-3 col-lg-2"
value={value}
@ -67,7 +68,12 @@ export default function WebsiteChart({
</div>
<div className="row">
<div className="col">
<PageviewsChart websiteId={websiteId} data={{ pageviews, uniques }} unit={unit} />
<PageviewsChart
websiteId={websiteId}
data={{ pageviews, uniques }}
unit={unit}
records={getDateLength(startDate, endDate, unit)}
/>
<QuickButtons value={value} onChange={handleDateChange} />
</div>
</div>

View file

@ -8,7 +8,7 @@ import styles from './WebsiteHeader.module.css';
import RefreshButton from '../common/RefreshButton';
import ButtonLayout from '../layout/ButtonLayout';
export default function WebsiteHeader({ websiteId, title, showLink = false, onRefresh }) {
export default function WebsiteHeader({ websiteId, title, showLink = false }) {
const router = useRouter();
return (
@ -16,7 +16,7 @@ export default function WebsiteHeader({ websiteId, title, showLink = false, onRe
<div className={styles.title}>{title}</div>
<ActiveUsers className={styles.active} websiteId={websiteId} />
<ButtonLayout>
<RefreshButton onClick={onRefresh} />
<RefreshButton websiteId={websiteId} />
{showLink && (
<Button
icon={<Arrow />}