mirror of
https://github.com/kremalicious/umami.git
synced 2024-11-15 17:55:08 +01:00
Toggle formatting on click. Renamed charts folder to metrics.
This commit is contained in:
parent
d9f3c385fb
commit
e75593443a
@ -1,10 +1,10 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import WebsiteChart from 'components/charts/WebsiteChart';
|
import WebsiteChart from 'components/metrics/WebsiteChart';
|
||||||
import RankingsChart from 'components/charts/RankingsChart';
|
import RankingsChart from 'components/metrics/RankingsChart';
|
||||||
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/charts/WebsiteHeader';
|
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 { getDateRange } from 'lib/date';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import WebsiteHeader from 'components/charts/WebsiteHeader';
|
import WebsiteHeader from 'components/metrics/WebsiteHeader';
|
||||||
import WebsiteChart from 'components/charts/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';
|
||||||
import EmptyPlaceholder from 'components/common/EmptyPlaceholder';
|
import EmptyPlaceholder from 'components/common/EmptyPlaceholder';
|
||||||
|
@ -25,6 +25,7 @@ export default function RankingsChart({
|
|||||||
const [data, setData] = useState();
|
const [data, setData] = useState();
|
||||||
const [format, setFormat] = useState(true);
|
const [format, setFormat] = useState(true);
|
||||||
const formatFunc = format ? formatLongNumber : formatNumber;
|
const formatFunc = format ? formatLongNumber : formatNumber;
|
||||||
|
const shouldAnimate = limit > 0;
|
||||||
|
|
||||||
const rankings = useMemo(() => {
|
const rankings = useMemo(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
@ -54,13 +55,23 @@ export default function RankingsChart({
|
|||||||
setFormat(state => !state);
|
setFormat(state => !state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getRow(x, y, z) {
|
||||||
|
return (
|
||||||
|
<AnimatedRow
|
||||||
|
key={x}
|
||||||
|
label={x}
|
||||||
|
value={y}
|
||||||
|
percent={z}
|
||||||
|
animate={shouldAnimate}
|
||||||
|
format={formatFunc}
|
||||||
|
onClick={handleSetFormat}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const Row = ({ index, style }) => {
|
const Row = ({ index, style }) => {
|
||||||
const { x, y, z } = rankings[index];
|
const { x, y, z } = rankings[index];
|
||||||
return (
|
return <div style={style}>{getRow(x, y, z)}</div>;
|
||||||
<div style={style}>
|
|
||||||
<AnimatedRow key={x} label={x} value={y} percent={z} animate={limit} format={formatFunc} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -75,22 +86,15 @@ export default function RankingsChart({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(styles.container, className)}>
|
<div className={classNames(styles.container, className)}>
|
||||||
<div className={styles.header} onClick={handleSetFormat}>
|
<div className={styles.header}>
|
||||||
<div className={styles.title}>{title}</div>
|
<div className={styles.title}>{title}</div>
|
||||||
<div className={styles.heading}>{heading}</div>
|
<div className={styles.heading} onClick={handleSetFormat}>
|
||||||
|
{heading}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.body}>
|
<div className={styles.body}>
|
||||||
{limit ? (
|
{limit ? (
|
||||||
rankings.map(({ x, y, z }) => (
|
rankings.map(({ x, y, z }) => getRow(x, y, z))
|
||||||
<AnimatedRow
|
|
||||||
key={x}
|
|
||||||
label={x}
|
|
||||||
value={y}
|
|
||||||
percent={z}
|
|
||||||
animate={limit}
|
|
||||||
format={formatFunc}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
) : (
|
) : (
|
||||||
<FixedSizeList height={600} itemCount={rankings.length} itemSize={30}>
|
<FixedSizeList height={600} itemCount={rankings.length} itemSize={30}>
|
||||||
{Row}
|
{Row}
|
||||||
@ -108,7 +112,7 @@ export default function RankingsChart({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const AnimatedRow = ({ label, value = 0, percent, animate, format }) => {
|
const AnimatedRow = ({ label, value = 0, percent, animate, format, onClick }) => {
|
||||||
const props = useSpring({
|
const props = useSpring({
|
||||||
width: percent,
|
width: percent,
|
||||||
y: value,
|
y: value,
|
||||||
@ -117,7 +121,7 @@ const AnimatedRow = ({ label, value = 0, percent, animate, format }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.row}>
|
<div className={styles.row} onClick={onClick}>
|
||||||
<div className={styles.label}>{label}</div>
|
<div className={styles.label}>{label}</div>
|
||||||
<animated.div className={styles.value}>{props.y?.interpolate(format)}</animated.div>
|
<animated.div className={styles.value}>{props.y?.interpolate(format)}</animated.div>
|
||||||
<div className={styles.percent}>
|
<div className={styles.percent}>
|
@ -10,7 +10,6 @@
|
|||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
@ -23,6 +22,7 @@
|
|||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
@ -56,6 +56,7 @@
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.percent {
|
.percent {
|
@ -13,8 +13,8 @@ export default function WebsiteHeader({ websiteId, name, showLink = false }) {
|
|||||||
return (
|
return (
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
{showLink ? (
|
{showLink ? (
|
||||||
<Link href="/website/[...id]" as={`/website/${websiteId}/${name}`}>
|
<Link href="/website/[...id]" as={`/website/${websiteId}/${name}`} className={styles.title}>
|
||||||
<a className={styles.title}>{name}</a>
|
{name}
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<div className={styles.title}>{name}</div>
|
<div className={styles.title}>{name}</div>
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "umami",
|
"name": "umami",
|
||||||
"version": "0.13.0",
|
"version": "0.14.0",
|
||||||
"description": "A simple, fast, website analytics alternative to Google Analytics. ",
|
"description": "A simple, fast, website analytics alternative to Google Analytics. ",
|
||||||
"author": "Mike Cao <mike@mikecao.com>",
|
"author": "Mike Cao <mike@mikecao.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
Loading…
Reference in New Issue
Block a user