mirror of
https://github.com/plausible/analytics.git
synced 2024-12-23 17:44:43 +03:00
Various formatting improvements
* Format numbers over 1B * Show full number when hovering
This commit is contained in:
parent
2e16cdb15b
commit
c4c0bb2095
@ -3,6 +3,8 @@ const HUNDRED_THOUSAND = 100000
|
|||||||
const MILLION = 1000000
|
const MILLION = 1000000
|
||||||
const HUNDRED_MILLION = 100000000
|
const HUNDRED_MILLION = 100000000
|
||||||
const BILLION = 1000000000
|
const BILLION = 1000000000
|
||||||
|
const HUNDRED_BILLION = 100000000000
|
||||||
|
const TRILLION = 1000000000000
|
||||||
|
|
||||||
export default function numberFormatter(num) {
|
export default function numberFormatter(num) {
|
||||||
if (num >= THOUSAND && num < MILLION) {
|
if (num >= THOUSAND && num < MILLION) {
|
||||||
@ -19,6 +21,13 @@ export default function numberFormatter(num) {
|
|||||||
} else {
|
} else {
|
||||||
return (Math.floor(millions * 10) / 10) + 'M'
|
return (Math.floor(millions * 10) / 10) + 'M'
|
||||||
}
|
}
|
||||||
|
} else if (num >= BILLION && num < TRILLION) {
|
||||||
|
const billions = num / BILLION
|
||||||
|
if (billions === Math.floor(billions) || num >= HUNDRED_BILLION) {
|
||||||
|
return Math.floor(billions) + 'B'
|
||||||
|
} else {
|
||||||
|
return (Math.floor(billions * 10) / 10) + 'B'
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return num
|
return num
|
||||||
}
|
}
|
||||||
|
@ -246,9 +246,9 @@ class LineGraph extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderTopStatNumber(stat) {
|
topStatNumberShort(stat) {
|
||||||
if (stat.name === 'Visit duration') {
|
if (typeof(stat.duration) == 'number') {
|
||||||
return durationFormatter(stat.count)
|
return durationFormatter(stat.duration)
|
||||||
} else if (typeof(stat.count) == 'number') {
|
} else if (typeof(stat.count) == 'number') {
|
||||||
return numberFormatter(stat.count)
|
return numberFormatter(stat.count)
|
||||||
} else {
|
} else {
|
||||||
@ -256,6 +256,12 @@ class LineGraph extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
topStatTooltip(stat) {
|
||||||
|
if (typeof(stat.count) == 'number') {
|
||||||
|
return stat.count.toLocaleString() + ' ' + stat.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderTopStats() {
|
renderTopStats() {
|
||||||
const {graphData} = this.props
|
const {graphData} = this.props
|
||||||
const stats = this.props.graphData.top_stats.map((stat, index) => {
|
const stats = this.props.graphData.top_stats.map((stat, index) => {
|
||||||
@ -266,7 +272,7 @@ class LineGraph extends React.Component {
|
|||||||
<div className={`px-8 w-1/2 my-4 lg:w-auto ${border}`} key={stat.name}>
|
<div className={`px-8 w-1/2 my-4 lg:w-auto ${border}`} key={stat.name}>
|
||||||
<div className="text-xs font-bold tracking-wide text-gray-500 uppercase dark:text-gray-400">{stat.name}</div>
|
<div className="text-xs font-bold tracking-wide text-gray-500 uppercase dark:text-gray-400">{stat.name}</div>
|
||||||
<div className="flex items-center justify-between my-1">
|
<div className="flex items-center justify-between my-1">
|
||||||
<b className="mr-4 text-2xl dark:text-gray-100">{ this.renderTopStatNumber(stat) }</b>
|
<b className="mr-4 text-2xl dark:text-gray-100" tooltip={this.topStatTooltip(stat)}>{ this.topStatNumberShort(stat) }</b>
|
||||||
{this.renderComparison(stat.name, stat.change)}
|
{this.renderComparison(stat.name, stat.change)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -98,7 +98,7 @@ defmodule PlausibleWeb.Api.StatsController do
|
|||||||
|
|
||||||
%{
|
%{
|
||||||
name: "Visit duration",
|
name: "Visit duration",
|
||||||
count: duration,
|
duration: duration,
|
||||||
change: percent_change(prev_duration, duration)
|
change: percent_change(prev_duration, duration)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
@ -28,9 +28,18 @@ defmodule PlausibleWeb.StatsView do
|
|||||||
millions = trunc(n / 100_000) / 10
|
millions = trunc(n / 100_000) / 10
|
||||||
|
|
||||||
if millions == trunc(millions) || n > 100_000_000 do
|
if millions == trunc(millions) || n > 100_000_000 do
|
||||||
"#{trunc(millions)}m"
|
"#{trunc(millions)}M"
|
||||||
else
|
else
|
||||||
"#{millions}m"
|
"#{millions}M"
|
||||||
|
end
|
||||||
|
|
||||||
|
n >= 1_000_000_000 && n < 1_000_000_000_000 ->
|
||||||
|
billions = trunc(n / 100_000_000) / 10
|
||||||
|
|
||||||
|
if billions == trunc(billions) || n > 100_000_000_000 do
|
||||||
|
"#{trunc(billions)}B"
|
||||||
|
else
|
||||||
|
"#{billions}B"
|
||||||
end
|
end
|
||||||
|
|
||||||
true ->
|
true ->
|
||||||
|
@ -104,7 +104,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
|||||||
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=day&date=2019-01-01")
|
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=day&date=2019-01-01")
|
||||||
|
|
||||||
res = json_response(conn, 200)
|
res = json_response(conn, 200)
|
||||||
assert %{"name" => "Visit duration", "count" => 67, "change" => 100} in res["top_stats"]
|
assert %{"name" => "Visit duration", "duration" => 67, "change" => 100} in res["top_stats"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -32,19 +32,31 @@ defmodule PlausibleWeb.StatsView.Test do
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "1_000_000 becomes 1m" do
|
test "1_000_000 becomes 1m" do
|
||||||
assert StatsView.large_number_format(1_000_000) == "1m"
|
assert StatsView.large_number_format(1_000_000) == "1M"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "2_590_000 becomes 2.5m" do
|
test "2_590_000 becomes 2.5m" do
|
||||||
assert StatsView.large_number_format(2_590_000) == "2.5m"
|
assert StatsView.large_number_format(2_590_000) == "2.5M"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "99_999_999 becomes 99.9m" do
|
test "99_999_999 becomes 99.9m" do
|
||||||
assert StatsView.large_number_format(99_999_999) == "99.9m"
|
assert StatsView.large_number_format(99_999_999) == "99.9M"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "101_000_000 becomes 101m" do
|
test "101_000_000 becomes 101m" do
|
||||||
assert StatsView.large_number_format(101_000_000) == "101m"
|
assert StatsView.large_number_format(101_000_000) == "101M"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "2_500_000_000 becomes 2.5bn" do
|
||||||
|
assert StatsView.large_number_format(2_500_000_000) == "2.5B"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "25_500_000_000 becomes 25bn" do
|
||||||
|
assert StatsView.large_number_format(25_500_000_000) == "25.5B"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "250_500_000_000 becomes 250bn" do
|
||||||
|
assert StatsView.large_number_format(250_500_000_000) == "250B"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -117,35 +117,35 @@ defmodule Plausible.Workers.SendTrialNotificationsTest do
|
|||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
email = PlausibleWeb.Email.trial_upgrade_email(user, "today", {900_000, 0})
|
email = PlausibleWeb.Email.trial_upgrade_email(user, "today", {900_000, 0})
|
||||||
assert email.html_body =~ "we recommend you select the 1m/mo plan which runs at $48/mo."
|
assert email.html_body =~ "we recommend you select the 1M/mo plan which runs at $48/mo."
|
||||||
end
|
end
|
||||||
|
|
||||||
test "suggests 2m/mo plan" do
|
test "suggests 2m/mo plan" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
email = PlausibleWeb.Email.trial_upgrade_email(user, "today", {1_800_000, 0})
|
email = PlausibleWeb.Email.trial_upgrade_email(user, "today", {1_800_000, 0})
|
||||||
assert email.html_body =~ "we recommend you select the 2m/mo plan which runs at $69/mo."
|
assert email.html_body =~ "we recommend you select the 2M/mo plan which runs at $69/mo."
|
||||||
end
|
end
|
||||||
|
|
||||||
test "suggests 5m/mo plan" do
|
test "suggests 5m/mo plan" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
email = PlausibleWeb.Email.trial_upgrade_email(user, "today", {4_500_000, 0})
|
email = PlausibleWeb.Email.trial_upgrade_email(user, "today", {4_500_000, 0})
|
||||||
assert email.html_body =~ "we recommend you select the 5m/mo plan which runs at $99/mo."
|
assert email.html_body =~ "we recommend you select the 5M/mo plan which runs at $99/mo."
|
||||||
end
|
end
|
||||||
|
|
||||||
test "suggests 10m/mo plan" do
|
test "suggests 10m/mo plan" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
email = PlausibleWeb.Email.trial_upgrade_email(user, "today", {9_000_000, 0})
|
email = PlausibleWeb.Email.trial_upgrade_email(user, "today", {9_000_000, 0})
|
||||||
assert email.html_body =~ "we recommend you select the 10m/mo plan which runs at $150/mo."
|
assert email.html_body =~ "we recommend you select the 10M/mo plan which runs at $150/mo."
|
||||||
end
|
end
|
||||||
|
|
||||||
test "suggests 20m/mo plan" do
|
test "suggests 20m/mo plan" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
email = PlausibleWeb.Email.trial_upgrade_email(user, "today", {19_000_000, 0})
|
email = PlausibleWeb.Email.trial_upgrade_email(user, "today", {19_000_000, 0})
|
||||||
assert email.html_body =~ "we recommend you select the 20m/mo plan which runs at $225/mo."
|
assert email.html_body =~ "we recommend you select the 20M/mo plan which runs at $225/mo."
|
||||||
end
|
end
|
||||||
|
|
||||||
test "does not suggest a plan above that" do
|
test "does not suggest a plan above that" do
|
||||||
|
Loading…
Reference in New Issue
Block a user