mirror of
https://github.com/kremalicious/umami.git
synced 2024-11-22 09:57:00 +01:00
Animated metric card.
This commit is contained in:
parent
f9a6f5f637
commit
da2d383b71
@ -10,7 +10,7 @@ export default function Layout({ title, children }) {
|
|||||||
<title>umami{title && ` - ${title}`}</title>
|
<title>umami{title && ` - ${title}`}</title>
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600&display=swap"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
</Head>
|
</Head>
|
||||||
|
@ -1,11 +1,20 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import { useSpring, animated } from 'react-spring';
|
||||||
import styles from './MetricCard.module.css';
|
import styles from './MetricCard.module.css';
|
||||||
|
|
||||||
const MetricCard = ({ value, label }) => (
|
function defaultFormat(n) {
|
||||||
<div className={styles.card}>
|
return Number(n).toFixed(0);
|
||||||
<div className={styles.value}>{value}</div>
|
}
|
||||||
<div className={styles.label}>{label}</div>
|
|
||||||
</div>
|
const MetricCard = ({ value = 0, label, format = defaultFormat }) => {
|
||||||
);
|
const props = useSpring({ x: value, from: { x: 0 } });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.card}>
|
||||||
|
<animated.div className={styles.value}>{props.x.interpolate(x => format(x))}</animated.div>
|
||||||
|
<div className={styles.label}>{label}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default MetricCard;
|
export default MetricCard;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-right: 50px;
|
width: 140px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
|
@ -26,7 +26,6 @@ export default function PageviewsChart({ data, unit }) {
|
|||||||
|
|
||||||
const renderTooltip = model => {
|
const renderTooltip = model => {
|
||||||
const { caretX, caretY, opacity, title, body, labelColors } = model;
|
const { caretX, caretY, opacity, title, body, labelColors } = model;
|
||||||
console.log(model);
|
|
||||||
|
|
||||||
if (!opacity) {
|
if (!opacity) {
|
||||||
setTooltip({ opacity });
|
setTooltip({ opacity });
|
||||||
|
@ -24,7 +24,11 @@ export default function WebsiteSummary({ websiteId, startDate, endDate }) {
|
|||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<MetricCard label="Views" value={pageviews} />
|
<MetricCard label="Views" value={pageviews} />
|
||||||
<MetricCard label="Visitors" value={uniques} />
|
<MetricCard label="Visitors" value={uniques} />
|
||||||
<MetricCard label="Bounce rate" value={`${~~((bounces / uniques) * 100)}%`} />
|
<MetricCard
|
||||||
|
label="Bounce rate"
|
||||||
|
value={uniques ? (bounces / uniques) * 100 : 0}
|
||||||
|
format={n => Number(n).toFixed(0) + '%'}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { parse } from 'cookie';
|
|||||||
import { verifySecureToken } from './crypto';
|
import { verifySecureToken } from './crypto';
|
||||||
|
|
||||||
export default async req => {
|
export default async req => {
|
||||||
const token = parse(req.headers.cookie)['umami.auth'];
|
const token = parse(req.headers.cookie || '')['umami.auth'];
|
||||||
|
|
||||||
return verifySecureToken(token);
|
return verifySecureToken(token);
|
||||||
};
|
};
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
"promise-polyfill": "^8.1.3",
|
"promise-polyfill": "^8.1.3",
|
||||||
"react": "16.13.1",
|
"react": "16.13.1",
|
||||||
"react-dom": "16.13.1",
|
"react-dom": "16.13.1",
|
||||||
|
"react-spring": "^8.0.27",
|
||||||
"request-ip": "^2.1.3",
|
"request-ip": "^2.1.3",
|
||||||
"unfetch": "^4.1.0",
|
"unfetch": "^4.1.0",
|
||||||
"uuid": "^8.2.0",
|
"uuid": "^8.2.0",
|
||||||
|
17
yarn.lock
17
yarn.lock
@ -1091,6 +1091,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.2"
|
regenerator-runtime "^0.13.2"
|
||||||
|
|
||||||
|
"@babel/runtime@^7.3.1":
|
||||||
|
version "7.10.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.5.tgz#303d8bd440ecd5a491eae6117fd3367698674c5c"
|
||||||
|
integrity sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==
|
||||||
|
dependencies:
|
||||||
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@babel/runtime@^7.8.4":
|
"@babel/runtime@^7.8.4":
|
||||||
version "7.10.4"
|
version "7.10.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99"
|
||||||
@ -6984,7 +6991,7 @@ prop-types-exact@1.2.0:
|
|||||||
object.assign "^4.1.0"
|
object.assign "^4.1.0"
|
||||||
reflect.ownkeys "^0.2.0"
|
reflect.ownkeys "^0.2.0"
|
||||||
|
|
||||||
prop-types@15.7.2, prop-types@^15.6.2, prop-types@^15.7.2:
|
prop-types@15.7.2, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||||
version "15.7.2"
|
version "15.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||||
@ -7128,6 +7135,14 @@ react-is@^16.7.0, react-is@^16.8.1:
|
|||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||||
|
|
||||||
|
react-spring@^8.0.27:
|
||||||
|
version "8.0.27"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-8.0.27.tgz#97d4dee677f41e0b2adcb696f3839680a3aa356a"
|
||||||
|
integrity sha512-nDpWBe3ZVezukNRandTeLSPcwwTMjNVu1IDq9qA/AMiUqHuRN4BeSWvKr3eIxxg1vtiYiOLy4FqdfCP5IoP77g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.3.1"
|
||||||
|
prop-types "^15.5.8"
|
||||||
|
|
||||||
react@16.13.1:
|
react@16.13.1:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
|
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
|
||||||
|
Loading…
Reference in New Issue
Block a user