FIX: Prevent 'NaN' display by hiding visitor stats on /about until they're ready (#29334)
The visitor stats on the /about page were previously showing as `NaN` immediately after enabling the `display_eu_visitor_stats` site setting because the stats for the /about page are cached and updated once every 30 minutes in a sidekiq job. The `NaN` would go away upon the next run of the relevant sidekiq job, but it's not good UX to display a cryptic `NaN` until the job runs. So, this commit ensures that the visitor stats is not displayed at all until the visitor stats is calculated and available. Internal topic: t/128480.
This commit is contained in:
parent
856182c7c6
commit
91c674f0bc
|
@ -120,7 +120,7 @@ export default class AboutPage extends Component {
|
|||
},
|
||||
];
|
||||
|
||||
if (this.siteSettings.display_eu_visitor_stats) {
|
||||
if (this.displayVisitorStats) {
|
||||
list.splice(2, 0, {
|
||||
icon: "user-secret",
|
||||
class: "visitors",
|
||||
|
@ -137,6 +137,14 @@ export default class AboutPage extends Component {
|
|||
return list.concat(this.siteActivitiesFromPlugins());
|
||||
}
|
||||
|
||||
get displayVisitorStats() {
|
||||
return (
|
||||
this.siteSettings.display_eu_visitor_stats &&
|
||||
typeof this.args.model.stats.eu_visitors_7_days === "number" &&
|
||||
typeof this.args.model.stats.visitors_7_days === "number"
|
||||
);
|
||||
}
|
||||
|
||||
get contactInfo() {
|
||||
const url = escape(this.args.model.contact_url || "");
|
||||
const email = escape(this.args.model.contact_email || "");
|
||||
|
@ -292,7 +300,7 @@ export default class AboutPage extends Component {
|
|||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{#if this.siteSettings.display_eu_visitor_stats}}
|
||||
{{#if this.displayVisitorStats}}
|
||||
<p class="about traffic-info-footer"><small
|
||||
>{{this.trafficInfoFooter}}</small></p>
|
||||
{{/if}}
|
||||
|
|
|
@ -54,4 +54,17 @@ export default class AboutController extends Controller {
|
|||
}
|
||||
return Array.from(set);
|
||||
}
|
||||
|
||||
@discourseComputed(
|
||||
"model.stats.visitors_7_days",
|
||||
"model.stats.eu_visitors_7_days",
|
||||
"siteSettings.display_eu_visitor_stats"
|
||||
)
|
||||
displayVisitorStats(visitors, euVisitors, displayEuVisitorStats) {
|
||||
return (
|
||||
displayEuVisitorStats &&
|
||||
typeof euVisitors === "number" &&
|
||||
typeof visitors === "number"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@
|
|||
<td>{{number this.model.stats.active_users_30_days}}</td>
|
||||
<td>—</td>
|
||||
</tr>
|
||||
{{#if this.siteSettings.display_eu_visitor_stats}}
|
||||
{{#if this.displayVisitorStats}}
|
||||
<tr class="about-visitor-count">
|
||||
<td>{{i18n "about.visitor_count"}}</td>
|
||||
<td>{{number this.model.stats.visitors_last_day}}</td>
|
||||
|
@ -183,7 +183,7 @@
|
|||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{#if this.siteSettings.display_eu_visitor_stats}}
|
||||
{{#if this.displayVisitorStats}}
|
||||
<p class="about stats-table-footer"><small
|
||||
>{{this.statsTableFooter}}</small></p>
|
||||
{{/if}}
|
||||
|
|
|
@ -3,6 +3,7 @@ import { module, test } from "qunit";
|
|||
import AboutPage from "discourse/components/about-page";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
function createModelObject({
|
||||
title = "My Forums",
|
||||
|
@ -61,4 +62,40 @@ module("Integration | Component | about-page", function (hooks) {
|
|||
)
|
||||
.hasText("in the last 3 weeks");
|
||||
});
|
||||
|
||||
test("visitor stats are not rendered if they're not available in the model", async function (assert) {
|
||||
this.siteSettings.display_eu_visitor_stats = true;
|
||||
let model = createModelObject({
|
||||
stats: {},
|
||||
});
|
||||
|
||||
await render(<template><AboutPage @model={{model}} /></template>);
|
||||
assert
|
||||
.dom(".about__activities-item.visitors")
|
||||
.doesNotExist("visitors stats item is not rendered");
|
||||
|
||||
model = createModelObject({
|
||||
stats: {
|
||||
eu_visitors_7_days: 13,
|
||||
eu_visitors_30_days: 30,
|
||||
visitors_7_days: 33,
|
||||
visitors_30_days: 103,
|
||||
},
|
||||
});
|
||||
|
||||
await render(<template><AboutPage @model={{model}} /></template>);
|
||||
assert
|
||||
.dom(".about__activities-item.visitors")
|
||||
.exists("visitors stats item is rendered");
|
||||
assert
|
||||
.dom(".about__activities-item.visitors .about__activities-item-count")
|
||||
.hasText(
|
||||
I18n.messageFormat("about.activities.visitors_MF", {
|
||||
total_count: 33,
|
||||
eu_count: 13,
|
||||
total_formatted_number: "33",
|
||||
eu_formatted_number: "13",
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2263,7 +2263,7 @@ en:
|
|||
tos_url: "If you have a Terms of Service document hosted elsewhere that you want to use, provide the full URL here."
|
||||
privacy_policy_url: "If you have a Privacy Policy document hosted elsewhere that you want to use, provide the full URL here."
|
||||
log_anonymizer_details: "Whether to keep a user's details in the log after being anonymized."
|
||||
display_eu_visitor_stats: "Show number of global and EU visitors on the /about page."
|
||||
display_eu_visitor_stats: "Show number of global and EU visitors on the /about page. It may take a few minutes for the stats to appear after turning on this setting."
|
||||
|
||||
newuser_spam_host_threshold: "How many times a new user can post a link to the same host within their `newuser_spam_host_threshold` posts before being considered spam."
|
||||
|
||||
|
|
Loading…
Reference in New Issue