mirror of
https://github.com/kremalicious/umami.git
synced 2024-06-28 16:57:52 +02:00
Refactor components and styles.
This commit is contained in:
parent
c5599f1e20
commit
a2db27894f
|
@ -66,16 +66,16 @@ export default function PageviewsChart({
|
||||||
label: 'unique visitors',
|
label: 'unique visitors',
|
||||||
data: data.uniques,
|
data: data.uniques,
|
||||||
lineTension: 0,
|
lineTension: 0,
|
||||||
backgroundColor: 'rgb(146, 86, 217, 0.4)',
|
backgroundColor: 'rgb(38, 128, 235, 0.4)',
|
||||||
borderColor: 'rgb(122, 66, 191, 0.4)',
|
borderColor: 'rgb(13, 102, 208, 0.4)',
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'page views',
|
label: 'page views',
|
||||||
data: data.pageviews,
|
data: data.pageviews,
|
||||||
lineTension: 0,
|
lineTension: 0,
|
||||||
backgroundColor: 'rgb(38, 128, 235, 0.4)',
|
backgroundColor: 'rgb(38, 128, 235, 0.2)',
|
||||||
borderColor: 'rgb(13, 102, 208, 0.4)',
|
borderColor: 'rgb(13, 102, 208, 0.2)',
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -165,7 +165,9 @@ const Tooltip = ({ title, value, label, labelColor }) => (
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
<div className={styles.title}>{title}</div>
|
<div className={styles.title}>{title}</div>
|
||||||
<div className={styles.metric}>
|
<div className={styles.metric}>
|
||||||
<div className={styles.dot} style={{ backgroundColor: labelColor }} />
|
<div className={styles.dot}>
|
||||||
|
<div className={styles.color} style={{ backgroundColor: labelColor }} />
|
||||||
|
</div>
|
||||||
{value} {label}
|
{value} {label}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -30,9 +30,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.dot {
|
.dot {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 100%;
|
||||||
|
margin-right: 8px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color {
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
border-radius: 100%;
|
|
||||||
border: 1px solid #b3b3b3;
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { useState, useEffect, useMemo } from 'react';
|
import React, { useState, useEffect, useMemo } from 'react';
|
||||||
import { useSpring, animated } from 'react-spring';
|
import { useSpring, animated, config } from 'react-spring';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import CheckVisible from './CheckVisible';
|
||||||
import { get } from 'lib/web';
|
import { get } from 'lib/web';
|
||||||
import { percentFilter } from 'lib/filters';
|
import { percentFilter } from 'lib/filters';
|
||||||
import styles from './RankingsChart.module.css';
|
import styles from './RankingsChart.module.css';
|
||||||
|
@ -14,7 +15,6 @@ export default function RankingsChart({
|
||||||
heading,
|
heading,
|
||||||
className,
|
className,
|
||||||
dataFilter,
|
dataFilter,
|
||||||
animate = true,
|
|
||||||
onDataLoad = () => {},
|
onDataLoad = () => {},
|
||||||
}) {
|
}) {
|
||||||
const [data, setData] = useState();
|
const [data, setData] = useState();
|
||||||
|
@ -50,43 +50,42 @@ export default function RankingsChart({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(styles.container, className)}>
|
<CheckVisible>
|
||||||
<div className={styles.header}>
|
{visible => (
|
||||||
<div className={styles.title}>{title}</div>
|
<div className={classNames(styles.container, className)}>
|
||||||
<div className={styles.heading}>{heading}</div>
|
<div className={styles.header}>
|
||||||
</div>
|
<div className={styles.title}>{title}</div>
|
||||||
{rankings.map(({ x, y, z }) =>
|
<div className={styles.heading}>{heading}</div>
|
||||||
animate ? (
|
</div>
|
||||||
<AnimatedRow key={x} label={x} value={y} percent={z} />
|
{rankings.map(({ x, y, z }) => (
|
||||||
) : (
|
<Row key={x} label={x} value={y} percent={z} animate={visible} />
|
||||||
<Row key={x} label={x} value={y} percent={z} />
|
))}
|
||||||
),
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</CheckVisible>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Row = ({ label, value, percent }) => (
|
const Row = ({ label, value, percent, animate }) => {
|
||||||
<div className={styles.row}>
|
const props = useSpring({
|
||||||
<div className={styles.label}>{label}</div>
|
width: percent,
|
||||||
<div className={styles.value}>{value.toFixed(0)}</div>
|
y: value,
|
||||||
<div className={styles.percent}>
|
from: { width: 0, y: 0 },
|
||||||
<div>{`${percent.toFixed(0)}%`}</div>
|
config: animate ? config.default : { duration: 0 },
|
||||||
<div className={styles.bar} style={{ width: percent }} />
|
});
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const AnimatedRow = ({ label, value, percent }) => {
|
|
||||||
const props = useSpring({ width: percent, y: value, from: { width: 0, y: 0 } });
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.row}>
|
<div className={styles.row}>
|
||||||
<div className={styles.label}>{label}</div>
|
<div className={styles.label}>{label}</div>
|
||||||
<animated.div className={styles.value}>{props.y.interpolate(n => n.toFixed(0))}</animated.div>
|
<animated.div className={styles.value}>{props.y.interpolate(n => n.toFixed(0))}</animated.div>
|
||||||
<div className={styles.percent}>
|
<div className={styles.percent}>
|
||||||
<animated.div>{props.width.interpolate(n => `${n.toFixed(0)}%`)}</animated.div>
|
<animated.div
|
||||||
<animated.div className={styles.bar} style={{ width: props.width }} />
|
className={styles.bar}
|
||||||
|
style={{ width: props.width.interpolate(n => `${n}%`) }}
|
||||||
|
/>
|
||||||
|
<animated.span className={styles.percentValue}>
|
||||||
|
{props.width.interpolate(n => `${n.toFixed(0)}%`)}
|
||||||
|
</animated.span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -56,11 +56,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.percent {
|
.percent {
|
||||||
|
position: relative;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
color: #6e6e6e;
|
color: #6e6e6e;
|
||||||
position: relative;
|
|
||||||
border-left: 1px solid #8e8e8e;
|
border-left: 1px solid #8e8e8e;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bar {
|
.bar {
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
import React, { useState, useEffect, useMemo, useRef } from 'react';
|
import React, { useState, useEffect, useMemo, useRef } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import PageviewsChart from './PageviewsChart';
|
import PageviewsChart from './PageviewsChart';
|
||||||
import { get } from 'lib/web';
|
import CheckVisible from './CheckVisible';
|
||||||
import { getDateArray, getDateRange, getTimezone } from 'lib/date';
|
|
||||||
import MetricsBar from './MetricsBar';
|
import MetricsBar from './MetricsBar';
|
||||||
import QuickButtons from './QuickButtons';
|
import QuickButtons from './QuickButtons';
|
||||||
import styles from './WebsiteChart.module.css';
|
|
||||||
import DateFilter from './DateFilter';
|
import DateFilter from './DateFilter';
|
||||||
import useSticky from './hooks/useSticky';
|
import useSticky from './hooks/useSticky';
|
||||||
|
import { get } from 'lib/web';
|
||||||
|
import { getDateArray, getDateRange, getTimezone } from 'lib/date';
|
||||||
|
import styles from './WebsiteChart.module.css';
|
||||||
|
|
||||||
export default function WebsiteChart({
|
export default function WebsiteChart({
|
||||||
websiteId,
|
websiteId,
|
||||||
defaultDateRange = '7day',
|
defaultDateRange = '7day',
|
||||||
stickHeader = false,
|
stickHeader = false,
|
||||||
animate = true,
|
|
||||||
onDateChange = () => {},
|
onDateChange = () => {},
|
||||||
}) {
|
}) {
|
||||||
const [data, setData] = useState();
|
const [data, setData] = useState();
|
||||||
const [dateRange, setDateRange] = useState(getDateRange(defaultDateRange));
|
const [dateRange, setDateRange] = useState(getDateRange(defaultDateRange));
|
||||||
const { startDate, endDate, unit, value } = dateRange;
|
const { startDate, endDate, unit, value } = dateRange;
|
||||||
const [ref, sticky] = useSticky(stickHeader);
|
const [ref, sticky] = useSticky(stickHeader);
|
||||||
const width = useRef();
|
const container = useRef();
|
||||||
|
|
||||||
const [pageviews, uniques] = useMemo(() => {
|
const [pageviews, uniques] = useMemo(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
|
@ -52,16 +52,12 @@ export default function WebsiteChart({
|
||||||
loadData();
|
loadData();
|
||||||
}, [websiteId, startDate, endDate, unit]);
|
}, [websiteId, startDate, endDate, unit]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
width.current = document.querySelector('main').offsetWidth;
|
|
||||||
}, [sticky]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div ref={container}>
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={classNames(styles.header, 'row', { [styles.sticky]: sticky })}
|
className={classNames(styles.header, 'row', { [styles.sticky]: sticky })}
|
||||||
style={{ width: sticky ? width.current : 'auto' }}
|
style={{ width: sticky ? container.current.clientWidth : 'auto' }}
|
||||||
>
|
>
|
||||||
<MetricsBar
|
<MetricsBar
|
||||||
className="col-12 col-md-9 col-lg-10"
|
className="col-12 col-md-9 col-lg-10"
|
||||||
|
@ -76,16 +72,20 @@ export default function WebsiteChart({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<PageviewsChart
|
<CheckVisible>
|
||||||
className="col"
|
{visible => (
|
||||||
websiteId={websiteId}
|
<PageviewsChart
|
||||||
data={{ pageviews, uniques }}
|
className="col"
|
||||||
unit={unit}
|
websiteId={websiteId}
|
||||||
animationDuration={animate ? 300 : 0}
|
data={{ pageviews, uniques }}
|
||||||
>
|
unit={unit}
|
||||||
<QuickButtons value={value} onChange={handleDateChange} />
|
animationDuration={visible ? 300 : 0}
|
||||||
</PageviewsChart>
|
>
|
||||||
|
<QuickButtons value={value} onChange={handleDateChange} />
|
||||||
|
</PageviewsChart>
|
||||||
|
)}
|
||||||
|
</CheckVisible>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 10px;
|
padding: 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sticky {
|
.sticky {
|
||||||
|
@ -21,7 +21,6 @@
|
||||||
top: 0;
|
top: 0;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 10px 0;
|
|
||||||
border-bottom: 1px solid #e1e1e1;
|
border-bottom: 1px solid #e1e1e1;
|
||||||
z-index: 1;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,103 +37,69 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className={styles.container}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className={classNames(styles.chart, 'col')}>
|
<div className={classNames(styles.chart, 'col')}>
|
||||||
<h1>{data.label}</h1>
|
<h2>{data.label}</h2>
|
||||||
<CheckVisible>
|
<WebsiteChart websiteId={websiteId} onDateChange={handleDateChange} stickHeader />
|
||||||
{visible => (
|
|
||||||
<WebsiteChart
|
|
||||||
websiteId={data.website_id}
|
|
||||||
onDateChange={handleDateChange}
|
|
||||||
animate={visible}
|
|
||||||
stickHeader
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</CheckVisible>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classNames(styles.row, 'row')}>
|
<div className={classNames(styles.row, 'row')}>
|
||||||
<div className={pageviewClasses}>
|
<div className={pageviewClasses}>
|
||||||
<CheckVisible>
|
<RankingsChart
|
||||||
{visible => (
|
title="Pages"
|
||||||
<RankingsChart
|
type="url"
|
||||||
title="Pages"
|
heading="Views"
|
||||||
type="url"
|
websiteId={websiteId}
|
||||||
heading="Views"
|
startDate={startDate}
|
||||||
websiteId={data.website_id}
|
endDate={endDate}
|
||||||
startDate={startDate}
|
dataFilter={urlFilter}
|
||||||
endDate={endDate}
|
/>
|
||||||
dataFilter={urlFilter}
|
|
||||||
animate={visible}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</CheckVisible>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={pageviewClasses}>
|
<div className={pageviewClasses}>
|
||||||
<CheckVisible>
|
<RankingsChart
|
||||||
{visible => (
|
title="Referrers"
|
||||||
<RankingsChart
|
type="referrer"
|
||||||
title="Referrers"
|
heading="Views"
|
||||||
type="referrer"
|
websiteId={websiteId}
|
||||||
heading="Views"
|
startDate={startDate}
|
||||||
websiteId={data.website_id}
|
endDate={endDate}
|
||||||
startDate={startDate}
|
dataFilter={refFilter}
|
||||||
endDate={endDate}
|
/>
|
||||||
dataFilter={refFilter}
|
|
||||||
animate={visible}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</CheckVisible>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classNames(styles.row, 'row')}>
|
<div className={classNames(styles.row, 'row')}>
|
||||||
<div className={sessionClasses}>
|
<div className={sessionClasses}>
|
||||||
<CheckVisible>
|
<RankingsChart
|
||||||
{visible => (
|
title="Browsers"
|
||||||
<RankingsChart
|
type="browser"
|
||||||
title="Browsers"
|
heading="Visitors"
|
||||||
type="browser"
|
websiteId={websiteId}
|
||||||
heading="Visitors"
|
startDate={startDate}
|
||||||
websiteId={data.website_id}
|
endDate={endDate}
|
||||||
startDate={startDate}
|
dataFilter={browserFilter}
|
||||||
endDate={endDate}
|
/>
|
||||||
dataFilter={browserFilter}
|
|
||||||
animate={visible}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</CheckVisible>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={sessionClasses}>
|
<div className={sessionClasses}>
|
||||||
<CheckVisible>
|
<RankingsChart
|
||||||
{visible => (
|
title="Operating system"
|
||||||
<RankingsChart
|
type="os"
|
||||||
title="Operating system"
|
heading="Visitors"
|
||||||
type="os"
|
websiteId={websiteId}
|
||||||
heading="Visitors"
|
startDate={startDate}
|
||||||
websiteId={data.website_id}
|
endDate={endDate}
|
||||||
startDate={startDate}
|
/>
|
||||||
endDate={endDate}
|
|
||||||
animate={visible}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</CheckVisible>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={sessionClasses}>
|
<div className={sessionClasses}>
|
||||||
<CheckVisible>
|
<RankingsChart
|
||||||
{visible => (
|
title="Devices"
|
||||||
<RankingsChart
|
type="screen"
|
||||||
title="Devices"
|
heading="Visitors"
|
||||||
type="screen"
|
websiteId={websiteId}
|
||||||
heading="Visitors"
|
startDate={startDate}
|
||||||
websiteId={data.website_id}
|
endDate={endDate}
|
||||||
startDate={startDate}
|
dataFilter={deviceFilter}
|
||||||
endDate={endDate}
|
/>
|
||||||
dataFilter={deviceFilter}
|
|
||||||
animate={visible}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</CheckVisible>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classNames(styles.row, 'row')}>
|
<div className={classNames(styles.row, 'row')}>
|
||||||
|
@ -141,23 +107,18 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
|
||||||
<WorldMap data={countryData} />
|
<WorldMap data={countryData} />
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12 col-md-12 col-lg-4">
|
<div className="col-12 col-md-12 col-lg-4">
|
||||||
<CheckVisible>
|
<RankingsChart
|
||||||
{visible => (
|
title="Countries"
|
||||||
<RankingsChart
|
type="country"
|
||||||
title="Countries"
|
heading="Visitors"
|
||||||
type="country"
|
websiteId={websiteId}
|
||||||
heading="Visitors"
|
startDate={startDate}
|
||||||
websiteId={data.website_id}
|
endDate={endDate}
|
||||||
startDate={startDate}
|
dataFilter={countryFilter}
|
||||||
endDate={endDate}
|
onDataLoad={data => setCountryData(data)}
|
||||||
dataFilter={countryFilter}
|
/>
|
||||||
onDataLoad={data => setCountryData(data)}
|
|
||||||
animate={visible}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</CheckVisible>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,10 @@ export default function WebsiteList() {
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
{data &&
|
{data &&
|
||||||
data.websites.map(({ website_id, website_uuid, label }) => (
|
data.websites.map(({ website_id, label }) => (
|
||||||
<div key={website_id}>
|
<div key={website_id}>
|
||||||
<h2>
|
<h2>
|
||||||
<Link href={`/${website_uuid}`}>
|
<Link href={`/website/${website_id}/${label}`}>
|
||||||
<a>{label}</a>
|
<a>{label}</a>
|
||||||
</Link>
|
</Link>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
|
@ -1,3 +1,32 @@
|
||||||
.container > div {
|
.container > div {
|
||||||
|
padding-bottom: 30px;
|
||||||
|
border-bottom: 1px solid #e1e1e1;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container > div:last-child {
|
||||||
|
border-bottom: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container a {
|
||||||
|
position: relative;
|
||||||
|
color: #2c2c2c;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container a:before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: -2px;
|
||||||
|
width: 0;
|
||||||
|
height: 2px;
|
||||||
|
background: #2680eb;
|
||||||
|
opacity: 0.5;
|
||||||
|
transition: width 100ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container a:hover:before {
|
||||||
|
width: 100%;
|
||||||
|
transition: width 100ms;
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
.container {
|
.container {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
10
lib/db.js
10
lib/db.js
|
@ -39,11 +39,12 @@ export async function runQuery(query) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getWebsite(website_uuid) {
|
export async function getWebsite({ website_id, website_uuid }) {
|
||||||
return runQuery(
|
return runQuery(
|
||||||
prisma.website.findOne({
|
prisma.website.findOne({
|
||||||
where: {
|
where: {
|
||||||
website_uuid,
|
...(website_id && { website_id }),
|
||||||
|
...(website_uuid && { website_uuid }),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -77,11 +78,12 @@ export async function createSession(website_id, data) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getSession(session_uuid) {
|
export async function getSession({ session_id, session_uuid }) {
|
||||||
return runQuery(
|
return runQuery(
|
||||||
prisma.session.findOne({
|
prisma.session.findOne({
|
||||||
where: {
|
where: {
|
||||||
session_uuid,
|
...(session_id && { session_id }),
|
||||||
|
...(session_uuid && { session_uuid }),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
|
@ -18,13 +18,13 @@ export default async req => {
|
||||||
const country = await getCountry(req, ip);
|
const country = await getCountry(req, ip);
|
||||||
|
|
||||||
if (website_uuid) {
|
if (website_uuid) {
|
||||||
const website = await getWebsite(website_uuid);
|
const website = await getWebsite({ website_uuid });
|
||||||
|
|
||||||
if (website) {
|
if (website) {
|
||||||
const { website_id } = website;
|
const { website_id } = website;
|
||||||
const session_uuid = uuid(website_id, hostname, ip, userAgent, os);
|
const session_uuid = uuid(website_id, hostname, ip, userAgent, os);
|
||||||
|
|
||||||
let session = await getSession(session_uuid);
|
let session = await getSession({ session_uuid });
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
session = await createSession(website_id, {
|
session = await createSession(website_id, {
|
||||||
|
|
|
@ -6,7 +6,7 @@ export default async (req, res) => {
|
||||||
|
|
||||||
const { id } = req.query;
|
const { id } = req.query;
|
||||||
|
|
||||||
const website = await getWebsite(id);
|
const website = await getWebsite({ website_id: +id });
|
||||||
|
|
||||||
return res.status(200).json(website);
|
return res.status(200).json(website);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,26 +1,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Link from 'next/link';
|
|
||||||
import { parse } from 'cookie';
|
import { parse } from 'cookie';
|
||||||
import Layout from 'components/Layout';
|
import Layout from 'components/Layout';
|
||||||
import PageviewsChart from 'components/PageviewsChart';
|
|
||||||
import { verifySecureToken } from 'lib/crypto';
|
import { verifySecureToken } from 'lib/crypto';
|
||||||
import { subDays, endOfDay } from 'date-fns';
|
|
||||||
import WebsiteList from '../components/WebsiteList';
|
import WebsiteList from '../components/WebsiteList';
|
||||||
|
|
||||||
export default function HomePage({ username }) {
|
export default function HomePage({ username }) {
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<WebsiteList />
|
<WebsiteList />
|
||||||
<div>
|
|
||||||
<PageviewsChart
|
|
||||||
websiteId={3}
|
|
||||||
startDate={subDays(endOfDay(new Date()), 6)}
|
|
||||||
endDate={endOfDay(new Date())}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Link href="/logout">
|
|
||||||
<a>Logout 🡒</a>
|
|
||||||
</Link>
|
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import Layout from 'components/Layout';
|
import Layout from 'components/Layout';
|
||||||
import WebsiteDetails from '../components/WebsiteDetails';
|
import WebsiteDetails from '../../components/WebsiteDetails';
|
||||||
|
|
||||||
export default function DetailsPage() {
|
export default function DetailsPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { id } = router.query;
|
const { id } = router.query;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<WebsiteDetails websiteId={id} />
|
<WebsiteDetails websiteId={+id[0]} />
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -9,6 +9,7 @@ body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
background: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
|
@ -24,8 +25,14 @@ body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a,
|
||||||
|
a:active,
|
||||||
|
a:visited {
|
||||||
|
color: #2680eb;
|
||||||
|
}
|
||||||
|
|
||||||
header a {
|
header a {
|
||||||
color: #000;
|
color: #000 !important;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +51,14 @@ select {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user