mirror of
https://github.com/kremalicious/umami.git
synced 2024-11-15 01:35:17 +01:00
Update rankings view.
This commit is contained in:
parent
ac2612924e
commit
65d44ff6a1
@ -1,6 +1,6 @@
|
|||||||
.dropdown {
|
.dropdown {
|
||||||
position: relative;
|
position: relative;
|
||||||
font-size: 12px;
|
font-size: 14px;
|
||||||
min-width: 140px;
|
min-width: 140px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +19,7 @@
|
|||||||
border: 1px solid #b3b3b3;
|
border: 1px solid #b3b3b3;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
z-index: 1;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.option {
|
.option {
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
z-index: 2;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
@ -10,12 +10,13 @@ export default function RankingsChart({
|
|||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
type,
|
type,
|
||||||
|
heading,
|
||||||
className,
|
className,
|
||||||
filterData,
|
dataFilter,
|
||||||
}) {
|
}) {
|
||||||
const [data, setData] = useState();
|
const [data, setData] = useState();
|
||||||
|
|
||||||
const rankings = useMemo(() => (data && filterData ? filterData(data) : data), [data]);
|
const rankings = useMemo(() => (data && dataFilter ? dataFilter(data) : data), [data]);
|
||||||
|
|
||||||
const total = useMemo(() => rankings?.reduce((n, { y }) => n + y, 0) || 0, [rankings]);
|
const total = useMemo(() => rankings?.reduce((n, { y }) => n + y, 0) || 0, [rankings]);
|
||||||
|
|
||||||
@ -41,14 +42,17 @@ export default function RankingsChart({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(styles.container, className)}>
|
<div className={classNames(styles.container, className)}>
|
||||||
|
<div className={styles.header}>
|
||||||
<div className={styles.title}>{title}</div>
|
<div className={styles.title}>{title}</div>
|
||||||
|
<div className={styles.heading}>{heading}</div>
|
||||||
|
</div>
|
||||||
{rankings.map(({ x, y }, i) => (i <= 10 ? <Row label={x} value={y} total={total} /> : null))}
|
{rankings.map(({ x, y }, i) => (i <= 10 ? <Row label={x} value={y} total={total} /> : null))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Row = ({ label, value, total }) => {
|
const Row = ({ label, value, total }) => {
|
||||||
const props = useSpring({ width: `${(value / total) * 100}%`, from: { width: '0%' } });
|
const props = useSpring({ width: (value / total) * 100, from: { width: 0 } });
|
||||||
const valueProps = useSpring({ y: value, from: { y: 0 } });
|
const valueProps = useSpring({ y: value, from: { y: 0 } });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -57,7 +61,10 @@ const Row = ({ label, value, total }) => {
|
|||||||
<animated.div className={styles.value}>
|
<animated.div className={styles.value}>
|
||||||
{valueProps.y.interpolate(y => y.toFixed(0))}
|
{valueProps.y.interpolate(y => y.toFixed(0))}
|
||||||
</animated.div>
|
</animated.div>
|
||||||
|
<div className={styles.percent}>
|
||||||
|
<animated.div>{props.width.interpolate(y => `${y.toFixed(0)}%`)}</animated.div>
|
||||||
<animated.div className={styles.bar} style={{ ...props }} />
|
<animated.div className={styles.bar} style={{ ...props }} />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,24 @@
|
|||||||
.container {
|
.container {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 390px;
|
min-height: 390px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
flex: 1;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: center;
|
||||||
|
width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
@ -13,25 +31,32 @@
|
|||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
|
||||||
font-weight: 600;
|
|
||||||
line-height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex: 1;
|
flex: 2;
|
||||||
z-index: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
|
width: 50px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
margin-right: 10px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.percent {
|
||||||
|
width: 50px;
|
||||||
|
color: #6e6e6e;
|
||||||
|
position: relative;
|
||||||
|
border-left: 1px solid #6e6e6e;
|
||||||
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bar {
|
.bar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
opacity: 0.1;
|
opacity: 0.1;
|
||||||
background: #2680eb;
|
background: #2680eb;
|
||||||
|
@ -18,22 +18,54 @@ const deviceFilter = data => {
|
|||||||
(obj, { x, y }) => {
|
(obj, { x, y }) => {
|
||||||
const [width] = x.split('x');
|
const [width] = x.split('x');
|
||||||
if (width >= 1920) {
|
if (width >= 1920) {
|
||||||
obj.desktop += +y;
|
obj.Desktop += +y;
|
||||||
} else if (width >= 1024) {
|
} else if (width >= 1024) {
|
||||||
obj.laptop += +y;
|
obj.Laptop += +y;
|
||||||
} else if (width >= 767) {
|
} else if (width >= 767) {
|
||||||
obj.tablet += +y;
|
obj.Tablet += +y;
|
||||||
} else {
|
} else {
|
||||||
obj.mobile += +y;
|
obj.Mobile += +y;
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
},
|
},
|
||||||
{ desktop: 0, laptop: 0, tablet: 0, mobile: 0 },
|
{ Desktop: 0, Laptop: 0, Tablet: 0, Mobile: 0 },
|
||||||
);
|
);
|
||||||
|
|
||||||
return Object.keys(devices).map(key => ({ x: key, y: devices[key] }));
|
return Object.keys(devices).map(key => ({ x: key, y: devices[key] }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const browsers = {
|
||||||
|
aol: 'AOL',
|
||||||
|
edge: 'Edge',
|
||||||
|
'edge-ios': 'Edge (iOS)',
|
||||||
|
yandexbrowser: 'Yandex',
|
||||||
|
kakaotalk: 'KKaoTalk',
|
||||||
|
samsung: 'Samsung',
|
||||||
|
silk: 'Silk',
|
||||||
|
miui: 'MIUI',
|
||||||
|
beaker: 'Beaker',
|
||||||
|
'edge-chromium': 'Edge (Chromium)',
|
||||||
|
chrome: 'Chrome',
|
||||||
|
'chromium-webview': 'Chrome (webview)',
|
||||||
|
phantomjs: 'PhantomJS',
|
||||||
|
crios: 'CriOS',
|
||||||
|
firefox: 'Firefox',
|
||||||
|
fxios: 'Firefox (iOS)',
|
||||||
|
'opera-mini': 'Opera Mini',
|
||||||
|
opera: 'Opera',
|
||||||
|
ie: 'IE',
|
||||||
|
bb10: 'BlackBerry 10',
|
||||||
|
android: 'Android',
|
||||||
|
ios: 'iOS',
|
||||||
|
safari: 'Safari',
|
||||||
|
facebook: 'Facebook',
|
||||||
|
instagram: 'Instagram',
|
||||||
|
'ios-webview': 'iOS (webview)',
|
||||||
|
searchbot: 'Searchbot',
|
||||||
|
};
|
||||||
|
|
||||||
|
const browserFilter = data => data.map(({ x, y }) => ({ x: browsers[x] || x, y }));
|
||||||
|
|
||||||
export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' }) {
|
export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' }) {
|
||||||
const [data, setData] = useState();
|
const [data, setData] = useState();
|
||||||
const [dateRange, setDateRange] = useState(getDateRange(defaultDateRange));
|
const [dateRange, setDateRange] = useState(getDateRange(defaultDateRange));
|
||||||
@ -69,48 +101,54 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
|
|||||||
<RankingsChart
|
<RankingsChart
|
||||||
title="Top URLs"
|
title="Top URLs"
|
||||||
type="url"
|
type="url"
|
||||||
|
heading="Views"
|
||||||
className="col-12 col-md-8 col-lg-6"
|
className="col-12 col-md-8 col-lg-6"
|
||||||
websiteId={data.website_id}
|
websiteId={data.website_id}
|
||||||
startDate={startDate}
|
startDate={startDate}
|
||||||
endDate={endDate}
|
endDate={endDate}
|
||||||
filterData={urlFilter}
|
dataFilter={urlFilter}
|
||||||
/>
|
/>
|
||||||
<RankingsChart
|
<RankingsChart
|
||||||
title="Top referrers"
|
title="Top referrers"
|
||||||
type="referrer"
|
type="referrer"
|
||||||
|
heading="Views"
|
||||||
className="col-12 col-md-8 col-lg-6"
|
className="col-12 col-md-8 col-lg-6"
|
||||||
websiteId={data.website_id}
|
websiteId={data.website_id}
|
||||||
startDate={startDate}
|
startDate={startDate}
|
||||||
endDate={endDate}
|
endDate={endDate}
|
||||||
filterData={refFilter}
|
dataFilter={refFilter}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={classNames(styles.row, 'row justify-content-between')}>
|
<div className={classNames(styles.row, 'row justify-content-between')}>
|
||||||
<RankingsChart
|
<RankingsChart
|
||||||
title="Browsers"
|
title="Browsers"
|
||||||
type="browser"
|
type="browser"
|
||||||
|
heading="Visitors"
|
||||||
className="col-12 col-md-8 col-lg-4"
|
className="col-12 col-md-8 col-lg-4"
|
||||||
websiteId={data.website_id}
|
websiteId={data.website_id}
|
||||||
startDate={startDate}
|
startDate={startDate}
|
||||||
endDate={endDate}
|
endDate={endDate}
|
||||||
|
dataFilter={browserFilter}
|
||||||
/>
|
/>
|
||||||
<RankingsChart
|
<RankingsChart
|
||||||
title="Operating system"
|
title="Operating system"
|
||||||
type="os"
|
type="os"
|
||||||
|
heading="Visitors"
|
||||||
className="col-12 col-md-8 col-lg-4"
|
className="col-12 col-md-8 col-lg-4"
|
||||||
websiteId={data.website_id}
|
websiteId={data.website_id}
|
||||||
startDate={startDate}
|
startDate={startDate}
|
||||||
endDate={endDate}
|
endDate={endDate}
|
||||||
filterData={osFilter}
|
dataFilter={osFilter}
|
||||||
/>
|
/>
|
||||||
<RankingsChart
|
<RankingsChart
|
||||||
title="Devices"
|
title="Devices"
|
||||||
type="screen"
|
type="screen"
|
||||||
|
heading="Visitors"
|
||||||
className="col-12 col-md-8 col-lg-4"
|
className="col-12 col-md-8 col-lg-4"
|
||||||
websiteId={data.website_id}
|
websiteId={data.website_id}
|
||||||
startDate={startDate}
|
startDate={startDate}
|
||||||
endDate={endDate}
|
endDate={endDate}
|
||||||
filterData={deviceFilter}
|
dataFilter={deviceFilter}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
Loading…
Reference in New Issue
Block a user