diff --git a/README.md b/README.md
index 3d08a1fd..18ec0a38 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,18 @@
# umami
+Umami is a simple, fast, website analytics alternative to Google Analytics.
+
+## Getting started
+
+A detailed getting started guide can be found at [https://umami.is/docs/](https://umami.is/docs/)
+
## Installation
+### Requirements
+
+- A server with Node.js 10.13 or newer
+- A database (MySQL or Postgresql)
+
### Get the source code
```
diff --git a/components/charts/MetricCard.js b/components/charts/MetricCard.js
index 4ebbe28a..ad6c62eb 100644
--- a/components/charts/MetricCard.js
+++ b/components/charts/MetricCard.js
@@ -1,12 +1,9 @@
import React from 'react';
import { useSpring, animated } from 'react-spring';
+import { formatNumber } from '../../lib/format';
import styles from './MetricCard.module.css';
-function defaultFormat(n) {
- return Number(n).toFixed(0);
-}
-
-const MetricCard = ({ value = 0, label, format = defaultFormat }) => {
+const MetricCard = ({ value = 0, label, format = formatNumber }) => {
const props = useSpring({ x: value, from: { x: 0 } });
return (
diff --git a/components/charts/MetricCard.module.css b/components/charts/MetricCard.module.css
index 96adad3c..7f03049a 100644
--- a/components/charts/MetricCard.module.css
+++ b/components/charts/MetricCard.module.css
@@ -2,7 +2,7 @@
display: flex;
flex-direction: column;
justify-content: center;
- width: 140px;
+ min-width: 140px;
}
.value {
diff --git a/components/charts/MetricsBar.js b/components/charts/MetricsBar.js
index 6a6c20a1..18a1a43b 100644
--- a/components/charts/MetricsBar.js
+++ b/components/charts/MetricsBar.js
@@ -2,13 +2,16 @@ import React, { useState, useEffect } from 'react';
import classNames from 'classnames';
import MetricCard from './MetricCard';
import { get } from 'lib/web';
-import { formatShortTime } from 'lib/format';
+import { formatShortTime, formatNumber, formatLongNumber } from 'lib/format';
import styles from './MetricsBar.module.css';
export default function MetricsBar({ websiteId, startDate, endDate, className }) {
const [data, setData] = useState({});
+ const [format, setFormat] = useState(true);
const { pageviews, uniques, bounces, totaltime } = data;
+ const formatFunc = format ? formatLongNumber : formatNumber;
+
async function loadData() {
setData(
await get(`/api/website/${websiteId}/metrics`, {
@@ -18,14 +21,18 @@ export default function MetricsBar({ websiteId, startDate, endDate, className })
);
}
+ function handleSetFormat() {
+ setFormat(state => !state);
+ }
+
useEffect(() => {
loadData();
}, [websiteId, startDate, endDate]);
return (
-
-
-
+
+
+
div:last-child {
display: none;
}
diff --git a/components/charts/RankingsChart.js b/components/charts/RankingsChart.js
index 54a7b4bb..89de63a3 100644
--- a/components/charts/RankingsChart.js
+++ b/components/charts/RankingsChart.js
@@ -2,11 +2,11 @@ import React, { useState, useEffect, useMemo } from 'react';
import { FixedSizeList } from 'react-window';
import { useSpring, animated, config } from 'react-spring';
import classNames from 'classnames';
-import CheckVisible from 'components/helpers/CheckVisible';
import Button from 'components/common/Button';
import Arrow from 'assets/arrow-right.svg';
import { get } from 'lib/web';
import { percentFilter } from 'lib/filters';
+import { formatNumber, formatLongNumber } from 'lib/format';
import styles from './RankingsChart.module.css';
export default function RankingsChart({
@@ -23,6 +23,8 @@ export default function RankingsChart({
onExpand = () => {},
}) {
const [data, setData] = useState();
+ const [format, setFormat] = useState(true);
+ const formatFunc = format ? formatLongNumber : formatNumber;
const rankings = useMemo(() => {
if (data) {
@@ -48,14 +50,8 @@ export default function RankingsChart({
onDataLoad(updated);
}
- useEffect(() => {
- if (websiteId) {
- loadData();
- }
- }, [websiteId, startDate, endDate, type]);
-
- if (!data) {
- return null;
+ function handleSetFormat() {
+ setFormat(state => !state);
}
const Row = ({ index, style }) => {
@@ -67,16 +63,33 @@ export default function RankingsChart({
);
};
+ useEffect(() => {
+ if (websiteId) {
+ loadData();
+ }
+ }, [websiteId, startDate, endDate, type]);
+
+ if (!data) {
+ return null;
+ }
+
return (
-
+
{limit ? (
rankings.map(({ x, y, z }) => (
-
+
))
) : (
@@ -95,7 +108,7 @@ export default function RankingsChart({
);
}
-const AnimatedRow = ({ label, value, percent, animate }) => {
+const AnimatedRow = ({ label, value, percent, animate, format }) => {
const props = useSpring({
width: percent,
y: value,
@@ -106,7 +119,7 @@ const AnimatedRow = ({ label, value, percent, animate }) => {
return (
{label}
-
{props.y.interpolate(n => n.toFixed(0))}
+
{props.y.interpolate(format)}
= 1000000) {
+ return `${(n / 1000000).toFixed(1)}m`;
+ }
+ if (n >= 100000) {
+ return `${(n / 1000).toFixed(0)}k`;
+ }
+ if (n >= 10000) {
+ return `${(n / 1000).toFixed(1)}k`;
+ }
+ if (n >= 1000) {
+ return `${(n / 1000).toFixed(2)}k`;
+ }
+ return formatNumber(n);
+}
diff --git a/package.json b/package.json
index 66a9a59d..d661b553 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "umami",
- "version": "0.9.0",
+ "version": "0.10.0",
"description": "A simple, fast, website analytics alternative to Google Analytics. ",
"author": "Mike Cao ",
"license": "MIT",