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

@ -3,10 +3,8 @@ import classNames from 'classnames';
import WebsiteChart from 'components/metrics/WebsiteChart'; import WebsiteChart from 'components/metrics/WebsiteChart';
import WorldMap from 'components/common/WorldMap'; import WorldMap from 'components/common/WorldMap';
import Page from 'components/layout/Page'; import Page from 'components/layout/Page';
import WebsiteHeader from 'components/metrics/WebsiteHeader';
import MenuLayout from 'components/layout/MenuLayout'; import MenuLayout from 'components/layout/MenuLayout';
import Button from 'components/common/Button'; import Button from 'components/common/Button';
import { getDateRange } from 'lib/date';
import Arrow from 'assets/arrow-right.svg'; import Arrow from 'assets/arrow-right.svg';
import styles from './WebsiteDetails.module.css'; import styles from './WebsiteDetails.module.css';
import PagesTable from './metrics/PagesTable'; import PagesTable from './metrics/PagesTable';
@ -20,15 +18,12 @@ import EventsChart from './metrics/EventsChart';
import useFetch from 'hooks/useFetch'; import useFetch from 'hooks/useFetch';
import Loading from 'components/common/Loading'; import Loading from 'components/common/Loading';
export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' }) { export default function WebsiteDetails({ websiteId }) {
const { data } = useFetch(`/api/website/${websiteId}`);
const [chartLoaded, setChartLoaded] = useState(false); const [chartLoaded, setChartLoaded] = useState(false);
const [countryData, setCountryData] = useState(); const [countryData, setCountryData] = useState();
const [eventsData, setEventsData] = useState(); const [eventsData, setEventsData] = useState();
const [expand, setExpand] = useState(); const [expand, setExpand] = useState();
const [refresh, setRefresh] = useState(0);
const [dateRange, setDateRange] = useState(getDateRange(defaultDateRange));
const { startDate, endDate, unit } = dateRange;
const { data } = useFetch(`/api/website/${websiteId}`);
const BackButton = () => ( const BackButton = () => (
<Button <Button
@ -50,23 +45,12 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
{ label: 'Browsers', value: 'browser', component: BrowsersTable }, { label: 'Browsers', value: 'browser', component: BrowsersTable },
{ label: 'Operating system', value: 'os', component: OSTable }, { label: 'Operating system', value: 'os', component: OSTable },
{ label: 'Devices', value: 'device', component: DevicesTable }, { label: 'Devices', value: 'device', component: DevicesTable },
{ { label: 'Countries', value: 'country', component: CountriesTable },
label: 'Countries',
value: 'country',
component: props => <CountriesTable {...props} onDataLoad={data => setCountryData(data)} />,
},
{ label: 'Events', value: 'event', component: EventsTable }, { label: 'Events', value: 'event', component: EventsTable },
]; ];
const dataProps = {
websiteId,
startDate,
endDate,
unit,
};
const tableProps = { const tableProps = {
...dataProps, websiteId,
websiteDomain: data?.domain, websiteDomain: data?.domain,
limit: 10, limit: 10,
onExpand: handleExpand, onExpand: handleExpand,
@ -79,11 +63,9 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
} }
function handleDataLoad() { function handleDataLoad() {
if (!chartLoaded) setTimeout(() => setChartLoaded(true), 300); if (!chartLoaded) {
} setTimeout(() => setChartLoaded(true), 300);
}
function handleDateChange(values) {
setTimeout(() => setDateRange(values), 300);
} }
function handleExpand(value) { function handleExpand(value) {
@ -94,10 +76,6 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
setExpand(getSelectedMenuOption(value)); setExpand(getSelectedMenuOption(value));
} }
function handleRefresh() {
setRefresh(state => state + 1);
}
if (!data) { if (!data) {
return null; return null;
} }
@ -106,17 +84,11 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
<Page> <Page>
<div className="row"> <div className="row">
<div className={classNames(styles.chart, 'col')}> <div className={classNames(styles.chart, 'col')}>
<WebsiteHeader <WebsiteChart
websiteId={websiteId} websiteId={websiteId}
title={data.name} title={data.name}
onRefresh={handleRefresh}
showLink={false}
/>
<WebsiteChart
key={refresh}
websiteId={websiteId}
onDataLoad={handleDataLoad} onDataLoad={handleDataLoad}
onDateChange={handleDateChange} showLink={false}
stickyHeader stickyHeader
/> />
</div> </div>
@ -158,7 +130,7 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
<EventsTable {...tableProps} onDataLoad={setEventsData} /> <EventsTable {...tableProps} onDataLoad={setEventsData} />
</div> </div>
<div className="col-12 col-md-12 col-lg-8 pt-5 pb-5"> <div className="col-12 col-md-12 col-lg-8 pt-5 pb-5">
<EventsChart {...dataProps} /> <EventsChart websiteId={websiteId} />
</div> </div>
</div> </div>
</> </>

View File

@ -1,6 +1,5 @@
import React from 'react'; import React from 'react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import WebsiteHeader from 'components/metrics/WebsiteHeader';
import WebsiteChart from 'components/metrics/WebsiteChart'; import WebsiteChart from 'components/metrics/WebsiteChart';
import Page from 'components/layout/Page'; import Page from 'components/layout/Page';
import Button from 'components/common/Button'; import Button from 'components/common/Button';
@ -21,8 +20,7 @@ export default function WebsiteList() {
<Page> <Page>
{data.map(({ website_id, name }) => ( {data.map(({ website_id, name }) => (
<div key={website_id} className={styles.website}> <div key={website_id} className={styles.website}>
<WebsiteHeader websiteId={website_id} title={name} showLink /> <WebsiteChart websiteId={website_id} title={name} showLink />
<WebsiteChart websiteId={website_id} />
</div> </div>
))} ))}
{data.length === 0 && ( {data.length === 0 && (

View File

@ -20,10 +20,12 @@ export default function DropDown({
setShowMenu(state => !state); setShowMenu(state => !state);
} }
function handleSelect(value, e) { function handleSelect(selected, e) {
e.stopPropagation(); e.stopPropagation();
setShowMenu(false); setShowMenu(false);
onChange(value); if (selected !== value) {
onChange(selected);
}
} }
useDocumentClick(e => { useDocumentClick(e => {

View File

@ -1,7 +1,18 @@
import React from 'react'; import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { setDateRange } from 'redux/actions/websites';
import Button from './Button'; import Button from './Button';
import Refresh from 'assets/redo.svg'; import Refresh from 'assets/redo.svg';
export default function RefreshButton({ onClick }) { export default function RefreshButton({ websiteId }) {
return <Button icon={<Refresh />} size="small" onClick={onClick} />; const dispatch = useDispatch();
const dateRange = useSelector(state => state.websites[websiteId]?.dateRange);
function handleClick() {
if (dateRange) {
dispatch(setDateRange(websiteId, { ...dateRange }));
}
}
return <Button icon={<Refresh />} size="small" onClick={handleClick} />;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,16 +1,9 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import MetricsTable from './MetricsTable'; import MetricsTable from './MetricsTable';
import { refFilter } from 'lib/filters'; import { refFilter } from 'lib/filters';
import ButtonGroup from '../common/ButtonGroup'; import ButtonGroup from 'components/common/ButtonGroup';
export default function Referrers({ export default function ReferrersTable({ websiteId, websiteDomain, limit, onExpand = () => {} }) {
websiteId,
websiteDomain,
startDate,
endDate,
limit,
onExpand = () => {},
}) {
const [filter, setFilter] = useState('Combined'); const [filter, setFilter] = useState('Combined');
const renderLink = ({ x: url }) => { const renderLink = ({ x: url }) => {
@ -31,8 +24,6 @@ export default function Referrers({
headerComponent={limit ? null : <FilterButtons selected={filter} onClick={setFilter} />} headerComponent={limit ? null : <FilterButtons selected={filter} onClick={setFilter} />}
websiteId={websiteId} websiteId={websiteId}
websiteDomain={websiteDomain} websiteDomain={websiteDomain}
startDate={startDate}
endDate={endDate}
limit={limit} limit={limit}
dataFilter={refFilter} dataFilter={refFilter}
filterOptions={{ 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 classNames from 'classnames';
import PageviewsChart from './PageviewsChart'; import PageviewsChart from './PageviewsChart';
import MetricsBar from './MetricsBar'; import MetricsBar from './MetricsBar';
@ -6,18 +7,23 @@ import QuickButtons from './QuickButtons';
import DateFilter from 'components/common/DateFilter'; import DateFilter from 'components/common/DateFilter';
import StickyHeader from 'components/helpers/StickyHeader'; import StickyHeader from 'components/helpers/StickyHeader';
import useFetch from 'hooks/useFetch'; 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 styles from './WebsiteChart.module.css';
import WebsiteHeader from './WebsiteHeader';
export default function WebsiteChart({ export default function WebsiteChart({
websiteId, websiteId,
title,
defaultDateRange = '7day', defaultDateRange = '7day',
stickyHeader = false, stickyHeader = false,
showLink = false,
onDataLoad = () => {}, onDataLoad = () => {},
onDateChange = () => {},
}) { }) {
const [dateRange, setDateRange] = useState(getDateRange(defaultDateRange)); const dispatch = useDispatch();
const { startDate, endDate, unit, value } = dateRange; const dateRange = useSelector(state => state.websites[websiteId]?.dateRange);
const { startDate, endDate, unit, value, modified } = dateRange || getDateRange(defaultDateRange);
const { data } = useFetch( const { data } = useFetch(
`/api/website/${websiteId}/pageviews`, `/api/website/${websiteId}/pageviews`,
{ {
@ -26,7 +32,7 @@ export default function WebsiteChart({
unit, unit,
tz: getTimezone(), tz: getTimezone(),
}, },
{ onDataLoad }, { onDataLoad, update: [modified] },
); );
const [pageviews, uniques] = useMemo(() => { const [pageviews, uniques] = useMemo(() => {
@ -40,24 +46,19 @@ export default function WebsiteChart({
}, [data]); }, [data]);
function handleDateChange(values) { function handleDateChange(values) {
setDateRange(values); dispatch(setDateRange(websiteId, values));
onDateChange(values);
} }
return ( return (
<> <>
<WebsiteHeader websiteId={websiteId} title={title} showLink={showLink} />
<div className={classNames(styles.header, 'row')}> <div className={classNames(styles.header, 'row')}>
<StickyHeader <StickyHeader
className={classNames(styles.metrics, 'col row')} className={classNames(styles.metrics, 'col row')}
stickyClassName={styles.sticky} stickyClassName={styles.sticky}
enabled={stickyHeader} enabled={stickyHeader}
> >
<MetricsBar <MetricsBar className="col-12 col-md-9 col-lg-10" websiteId={websiteId} />
className="col-12 col-md-9 col-lg-10"
websiteId={websiteId}
startDate={startDate}
endDate={endDate}
/>
<DateFilter <DateFilter
className="col-12 col-md-3 col-lg-2" className="col-12 col-md-3 col-lg-2"
value={value} value={value}
@ -67,7 +68,12 @@ export default function WebsiteChart({
</div> </div>
<div className="row"> <div className="row">
<div className="col"> <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} /> <QuickButtons value={value} onChange={handleDateChange} />
</div> </div>
</div> </div>

View File

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

View File

@ -23,9 +23,9 @@ export default function useFetch(url, params = {}, options = {}) {
useEffect(() => { useEffect(() => {
if (url) { if (url) {
const { interval } = options; const { interval, delay = 0 } = options;
loadData(); setTimeout(() => loadData(), delay);
const id = interval ? setInterval(() => loadData(), interval) : null; const id = interval ? setInterval(() => loadData(), interval) : null;

34
redux/actions/websites.js Normal file
View File

@ -0,0 +1,34 @@
import { createSlice } from '@reduxjs/toolkit';
import produce from 'immer';
const websites = createSlice({
name: 'user',
initialState: {},
reducers: {
updateWebsites(state, action) {
state = action.payload;
return state;
},
},
});
export const { updateWebsites } = websites.actions;
export default websites.reducer;
export function setDateRange(websiteId, dateRange) {
return (dispatch, getState) => {
const state = getState();
let { websites = {} } = state;
websites = produce(websites, draft => {
if (!draft[websiteId]) {
draft[websiteId] = {};
}
dateRange.modified = Date.now();
draft[websiteId].dateRange = dateRange;
});
return dispatch(updateWebsites(websites));
};
}

View File

@ -1,4 +1,5 @@
import { combineReducers } from 'redux'; import { combineReducers } from 'redux';
import user from './actions/user'; import user from './actions/user';
import websites from './actions/websites';
export default combineReducers({ user }); export default combineReducers({ user, websites });