Various formatting improvements

* Format numbers over 1B
* Show full number when hovering
This commit is contained in:
Uku Taht 2021-03-24 12:08:05 +02:00
parent 2e16cdb15b
commit c4c0bb2095
7 changed files with 53 additions and 17 deletions

View File

@ -3,6 +3,8 @@ const HUNDRED_THOUSAND = 100000
const MILLION = 1000000
const HUNDRED_MILLION = 100000000
const BILLION = 1000000000
const HUNDRED_BILLION = 100000000000
const TRILLION = 1000000000000
export default function numberFormatter(num) {
if (num >= THOUSAND && num < MILLION) {
@ -19,6 +21,13 @@ export default function numberFormatter(num) {
} else {
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 {
return num
}

View File

@ -246,9 +246,9 @@ class LineGraph extends React.Component {
}
}
renderTopStatNumber(stat) {
if (stat.name === 'Visit duration') {
return durationFormatter(stat.count)
topStatNumberShort(stat) {
if (typeof(stat.duration) == 'number') {
return durationFormatter(stat.duration)
} else if (typeof(stat.count) == 'number') {
return numberFormatter(stat.count)
} else {
@ -256,6 +256,12 @@ class LineGraph extends React.Component {
}
}
topStatTooltip(stat) {
if (typeof(stat.count) == 'number') {
return stat.count.toLocaleString() + ' ' + stat.name
}
}
renderTopStats() {
const {graphData} = this.props
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="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">
<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)}
</div>
</div>

View File

@ -98,7 +98,7 @@ defmodule PlausibleWeb.Api.StatsController do
%{
name: "Visit duration",
count: duration,
duration: duration,
change: percent_change(prev_duration, duration)
}
end

View File

@ -28,9 +28,18 @@ defmodule PlausibleWeb.StatsView do
millions = trunc(n / 100_000) / 10
if millions == trunc(millions) || n > 100_000_000 do
"#{trunc(millions)}m"
"#{trunc(millions)}M"
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
true ->

View File

@ -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")
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

View File

@ -32,19 +32,31 @@ defmodule PlausibleWeb.StatsView.Test do
end
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
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
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
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

View File

@ -117,35 +117,35 @@ defmodule Plausible.Workers.SendTrialNotificationsTest do
user = insert(:user)
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
test "suggests 2m/mo plan" do
user = insert(:user)
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
test "suggests 5m/mo plan" do
user = insert(:user)
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
test "suggests 10m/mo plan" do
user = insert(:user)
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
test "suggests 20m/mo plan" do
user = insert(:user)
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
test "does not suggest a plan above that" do