Use token authentication for API requests.

This commit is contained in:
Mike Cao 2020-09-17 22:52:20 -07:00
parent bff8806b61
commit 96bd7e5b47
34 changed files with 198 additions and 153 deletions

View file

@ -30,16 +30,19 @@ const views = {
event: EventsTable,
};
export default function WebsiteDetails({ websiteId, shareId }) {
export default function WebsiteDetails({ websiteId, token }) {
const router = useRouter();
const { data } = useFetch(`/api/website/${websiteId}`, { share_id: shareId });
const { data } = useFetch(`/api/website/${websiteId}`, { token });
const [chartLoaded, setChartLoaded] = useState(false);
const [countryData, setCountryData] = useState();
const [eventsData, setEventsData] = useState();
const {
query: { id, view },
basePath,
asPath,
} = router;
const path = `/website/${id.join('/')}`;
const path = `${basePath}/${asPath.split('/')[1]}/${id.join('/')}`;
const BackButton = () => (
<Button
@ -91,6 +94,7 @@ export default function WebsiteDetails({ websiteId, shareId }) {
const tableProps = {
websiteId,
token,
websiteDomain: data?.domain,
limit: 10,
onExpand: handleExpand,
@ -118,6 +122,7 @@ export default function WebsiteDetails({ websiteId, shareId }) {
<div className={classNames(styles.chart, 'col')}>
<WebsiteChart
websiteId={websiteId}
token={token}
title={data.name}
onDataLoad={handleDataLoad}
showLink={false}
@ -162,13 +167,18 @@ export default function WebsiteDetails({ websiteId, shareId }) {
<EventsTable {...tableProps} onDataLoad={setEventsData} />
</div>
<div className="col-12 col-md-12 col-lg-8 pt-5 pb-5">
<EventsChart websiteId={websiteId} />
<EventsChart websiteId={websiteId} token={token} />
</div>
</div>
</>
)}
{view && (
<MenuLayout className={styles.view} menuClassName={styles.menu} menu={menuOptions}>
<MenuLayout
className={styles.view}
menuClassName={styles.menu}
contentClassName={styles.content}
menu={menuOptions}
>
<DetailsComponent {...tableProps} limit={false} />
</MenuLayout>
)}

View file

@ -10,6 +10,10 @@
font-size: var(--font-size-small);
}
.content {
min-height: 600px;
}
.backButton {
align-self: flex-start;
margin-bottom: 16px;

View file

@ -5,7 +5,7 @@ import { setDateRange } from 'redux/actions/websites';
import Button from './Button';
import Refresh from 'assets/redo.svg';
import Dots from 'assets/ellipsis-h.svg';
import { useDateRange } from 'hooks/useDateRange';
import useDateRange from 'hooks/useDateRange';
import { getDateRange } from '../../lib/date';
export default function RefreshButton({ websiteId }) {

View file

@ -4,8 +4,8 @@ import useFetch from 'hooks/useFetch';
import styles from './ActiveUsers.module.css';
import { FormattedMessage } from 'react-intl';
export default function ActiveUsers({ websiteId, className }) {
const { data } = useFetch(`/api/website/${websiteId}/active`, {}, { interval: 60000 });
export default function ActiveUsers({ websiteId, token, className }) {
const { data } = useFetch(`/api/website/${websiteId}/active`, { token }, { interval: 60000 });
const count = useMemo(() => {
return data?.[0]?.x || 0;
}, [data]);

View file

@ -3,13 +3,14 @@ import { FormattedMessage } from 'react-intl';
import MetricsTable from './MetricsTable';
import { browserFilter } from 'lib/filters';
export default function BrowsersTable({ websiteId, limit, onExpand }) {
export default function BrowsersTable({ websiteId, token, limit, onExpand }) {
return (
<MetricsTable
title={<FormattedMessage id="metrics.browsers" defaultMessage="Browsers" />}
type="browser"
metric={<FormattedMessage id="metrics.visitors" defaultMessage="Visitors" />}
websiteId={websiteId}
token={token}
limit={limit}
dataFilter={browserFilter}
onExpand={onExpand}

View file

@ -3,13 +3,20 @@ import MetricsTable from './MetricsTable';
import { countryFilter, percentFilter } from 'lib/filters';
import { FormattedMessage } from 'react-intl';
export default function CountriesTable({ websiteId, limit, onDataLoad = () => {}, onExpand }) {
export default function CountriesTable({
websiteId,
token,
limit,
onDataLoad = () => {},
onExpand,
}) {
return (
<MetricsTable
title={<FormattedMessage id="metrics.countries" defaultMessage="Countries" />}
type="country"
metric={<FormattedMessage id="metrics.visitors" defaultMessage="Visitors" />}
websiteId={websiteId}
token={token}
limit={limit}
dataFilter={countryFilter}
onDataLoad={data => onDataLoad(percentFilter(data))}

View file

@ -4,13 +4,14 @@ import { deviceFilter } from 'lib/filters';
import { FormattedMessage } from 'react-intl';
import { getDeviceMessage } from 'components/messages';
export default function DevicesTable({ websiteId, limit, onExpand }) {
export default function DevicesTable({ websiteId, token, limit, onExpand }) {
return (
<MetricsTable
title={<FormattedMessage id="metrics.devices" defaultMessage="Devices" />}
type="device"
metric={<FormattedMessage id="metrics.visitors" defaultMessage="Visitors" />}
websiteId={websiteId}
token={token}
limit={limit}
dataFilter={deviceFilter}
renderLabel={({ x }) => getDeviceMessage(x)}

View file

@ -3,7 +3,7 @@ import tinycolor from 'tinycolor2';
import BarChart from './BarChart';
import { getTimezone, getDateArray, getDateLength } from 'lib/date';
import useFetch from 'hooks/useFetch';
import { useDateRange } from 'hooks/useDateRange';
import useDateRange from 'hooks/useDateRange';
const COLORS = [
'#2680eb',
@ -16,7 +16,7 @@ const COLORS = [
'#85d044',
];
export default function EventsChart({ websiteId }) {
export default function EventsChart({ websiteId, token }) {
const dateRange = useDateRange(websiteId);
const { startDate, endDate, unit, modified } = dateRange;
const { data } = useFetch(
@ -26,6 +26,7 @@ export default function EventsChart({ websiteId }) {
end_at: +endDate,
unit,
tz: getTimezone(),
token,
},
{ update: [modified] },
);

View file

@ -3,13 +3,14 @@ import { FormattedMessage } from 'react-intl';
import MetricsTable from './MetricsTable';
import styles from './EventsTable.module.css';
export default function EventsTable({ websiteId, limit, onExpand, onDataLoad }) {
export default function EventsTable({ websiteId, token, limit, onExpand, onDataLoad }) {
return (
<MetricsTable
title={<FormattedMessage id="metrics.events" defaultMessage="Events" />}
type="event"
metric={<FormattedMessage id="metrics.actions" defaultMessage="Actions" />}
websiteId={websiteId}
token={token}
limit={limit}
renderLabel={({ x }) => <Label value={x} />}
onExpand={onExpand}

View file

@ -3,12 +3,12 @@ import { FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import Loading from 'components/common/Loading';
import useFetch from 'hooks/useFetch';
import { useDateRange } from 'hooks/useDateRange';
import useDateRange from 'hooks/useDateRange';
import { formatShortTime, formatNumber, formatLongNumber } from 'lib/format';
import MetricCard from './MetricCard';
import styles from './MetricsBar.module.css';
export default function MetricsBar({ websiteId, className }) {
export default function MetricsBar({ websiteId, token, className }) {
const dateRange = useDateRange(websiteId);
const { startDate, endDate, modified } = dateRange;
const { data } = useFetch(
@ -16,6 +16,7 @@ export default function MetricsBar({ websiteId, className }) {
{
start_at: +startDate,
end_at: +endDate,
token,
},
{
update: [modified],

View file

@ -10,12 +10,13 @@ import useFetch from 'hooks/useFetch';
import Arrow from 'assets/arrow-right.svg';
import { percentFilter } from 'lib/filters';
import { formatNumber, formatLongNumber } from 'lib/format';
import { useDateRange } from 'hooks/useDateRange';
import useDateRange from 'hooks/useDateRange';
import styles from './MetricsTable.module.css';
export default function MetricsTable({
websiteId,
websiteDomain,
token,
title,
metric,
type,
@ -37,6 +38,7 @@ export default function MetricsTable({
start_at: +startDate,
end_at: +endDate,
domain: websiteDomain,
token,
},
{ onDataLoad, delay: 300, update: [modified] },
);

View file

@ -3,13 +3,14 @@ import MetricsTable from './MetricsTable';
import { osFilter } from 'lib/filters';
import { FormattedMessage } from 'react-intl';
export default function OSTable({ websiteId, limit, onExpand }) {
export default function OSTable({ websiteId, token, limit, onExpand }) {
return (
<MetricsTable
title={<FormattedMessage id="metrics.operating-systems" defaultMessage="Operating system" />}
type="os"
metric={<FormattedMessage id="metrics.visitors" defaultMessage="Visitors" />}
websiteId={websiteId}
token={token}
limit={limit}
dataFilter={osFilter}
onExpand={onExpand}

View file

@ -5,7 +5,7 @@ import { urlFilter } from 'lib/filters';
import { FILTER_COMBINED, FILTER_RAW } from 'lib/constants';
import MetricsTable from './MetricsTable';
export default function PagesTable({ websiteId, websiteDomain, limit, onExpand }) {
export default function PagesTable({ websiteId, token, websiteDomain, limit, onExpand }) {
const [filter, setFilter] = useState(FILTER_COMBINED);
const buttons = [
@ -25,6 +25,7 @@ export default function PagesTable({ websiteId, websiteDomain, limit, onExpand }
limit ? null : <FilterButtons buttons={buttons} selected={filter} onClick={setFilter} />
}
websiteId={websiteId}
token={token}
limit={limit}
dataFilter={urlFilter}
filterOptions={{ domain: websiteDomain, raw: filter === FILTER_RAW }}

View file

@ -1,30 +0,0 @@
import React from 'react';
import ButtonGroup from 'components/common/ButtonGroup';
import { getDateRange } from 'lib/date';
import styles from './QuickButtons.module.css';
const options = [
{ label: '24h', value: '24hour' },
{ label: '7d', value: '7day' },
{ label: '30d', value: '30day' },
];
export default function QuickButtons({ value, onChange }) {
const selectedItem = options.find(item => item.value === value)?.value;
function handleClick(selected) {
if (selected !== value) {
onChange(getDateRange(selected));
}
}
return (
<ButtonGroup
size="xsmall"
className={styles.buttons}
items={options}
selectedItem={selectedItem}
onClick={handleClick}
/>
);
}

View file

@ -1,33 +0,0 @@
.buttons {
display: flex;
align-content: center;
position: absolute;
top: 0;
right: 0;
margin: auto;
}
.buttons button + button {
margin-left: 10px;
}
.buttons .button {
font-size: var(--font-size-xsmall);
padding: 4px 8px;
}
.active {
font-weight: 600;
}
@media only screen and (max-width: 768px) {
.buttons button:last-child {
display: none;
}
}
@media only screen and (max-width: 576px) {
.buttons {
display: none;
}
}

View file

@ -5,7 +5,13 @@ import { refFilter } from 'lib/filters';
import ButtonGroup from 'components/common/ButtonGroup';
import { FILTER_DOMAIN_ONLY, FILTER_COMBINED, FILTER_RAW } from 'lib/constants';
export default function ReferrersTable({ websiteId, websiteDomain, limit, onExpand = () => {} }) {
export default function ReferrersTable({
websiteId,
websiteDomain,
token,
limit,
onExpand = () => {},
}) {
const [filter, setFilter] = useState(FILTER_COMBINED);
const buttons = [
@ -40,6 +46,7 @@ export default function ReferrersTable({ websiteId, websiteDomain, limit, onExpa
}
websiteId={websiteId}
websiteDomain={websiteDomain}
token={token}
limit={limit}
dataFilter={refFilter}
filterOptions={{

View file

@ -3,17 +3,18 @@ import { useDispatch } from 'react-redux';
import classNames from 'classnames';
import PageviewsChart from './PageviewsChart';
import MetricsBar from './MetricsBar';
import WebsiteHeader from './WebsiteHeader';
import DateFilter from 'components/common/DateFilter';
import StickyHeader from 'components/helpers/StickyHeader';
import useFetch from 'hooks/useFetch';
import useDateRange from 'hooks/useDateRange';
import { getDateArray, getDateLength, getTimezone } from 'lib/date';
import { setDateRange } from 'redux/actions/websites';
import styles from './WebsiteChart.module.css';
import WebsiteHeader from './WebsiteHeader';
import { useDateRange } from '../../hooks/useDateRange';
export default function WebsiteChart({
websiteId,
token,
title,
stickyHeader = false,
showLink = false,
@ -30,6 +31,7 @@ export default function WebsiteChart({
end_at: +endDate,
unit,
tz: getTimezone(),
token,
},
{ onDataLoad, update: [modified] },
);
@ -50,7 +52,7 @@ export default function WebsiteChart({
return (
<>
<WebsiteHeader websiteId={websiteId} title={title} showLink={showLink} />
<WebsiteHeader websiteId={websiteId} token={token} title={title} showLink={showLink} />
<div className={classNames(styles.header, 'row')}>
<StickyHeader
className={classNames(styles.metrics, 'col row')}
@ -58,7 +60,7 @@ export default function WebsiteChart({
enabled={stickyHeader}
>
<div className="col-12 col-lg-9">
<MetricsBar websiteId={websiteId} />
<MetricsBar websiteId={websiteId} token={token} />
</div>
<div className={classNames(styles.filter, 'col-12 col-lg-3')}>
<DateFilter

View file

@ -2,18 +2,18 @@ import React from 'react';
import { FormattedMessage } from 'react-intl';
import Link from 'components/common/Link';
import PageHeader from 'components/layout/PageHeader';
import RefreshButton from 'components/common/RefreshButton';
import ButtonLayout from 'components/layout/ButtonLayout';
import Icon from 'components/common/Icon';
import ActiveUsers from './ActiveUsers';
import Arrow from 'assets/arrow-right.svg';
import styles from './WebsiteHeader.module.css';
import RefreshButton from '../common/RefreshButton';
import ButtonLayout from '../layout/ButtonLayout';
import Icon from '../common/Icon';
export default function WebsiteHeader({ websiteId, title, showLink = false }) {
export default function WebsiteHeader({ websiteId, token, title, showLink = false }) {
return (
<PageHeader>
<div className={styles.title}>{title}</div>
<ActiveUsers className={styles.active} websiteId={websiteId} />
<ActiveUsers className={styles.active} websiteId={websiteId} token={token} />
<ButtonLayout>
<RefreshButton websiteId={websiteId} />
{showLink && (

View file

@ -10,7 +10,7 @@ import DateFilter from 'components/common/DateFilter';
import Dots from 'assets/ellipsis-h.svg';
import { getTimezone } from 'lib/date';
import { setItem } from 'lib/web';
import { useDateRange } from 'hooks/useDateRange';
import useDateRange from 'hooks/useDateRange';
import { setDateRange } from 'redux/actions/websites';
import styles from './ProfileSettings.module.css';