mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 09:42:02 +08:00
DEV: Add site age and site activities section to the redesigned about page (#28214)
This commit continues on work laid out by 6039b513fe
to redesign the /about page. In this commit, we add the site age and a section on the right hand side to show site activities/statistics such as topics, posts, sign-ups, likes etc.
This commit is contained in:
parent
1a09d6b246
commit
5dbf812d32
|
@ -2,6 +2,7 @@ import Component from "@glimmer/component";
|
|||
import { hash } from "@ember/helper";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import PluginOutlet from "discourse/components/plugin-outlet";
|
||||
import { number } from "discourse/lib/formatter";
|
||||
import dIcon from "discourse-common/helpers/d-icon";
|
||||
import i18n from "discourse-common/helpers/i18n";
|
||||
import escape from "discourse-common/lib/escape";
|
||||
|
@ -46,6 +47,61 @@ export default class AboutPage extends Component {
|
|||
}),
|
||||
}),
|
||||
},
|
||||
{
|
||||
class: "site-creation-date",
|
||||
icon: "calendar-alt",
|
||||
text: this.siteAgeString,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
get siteActivities() {
|
||||
return [
|
||||
{
|
||||
icon: "scroll",
|
||||
class: "topics",
|
||||
activityText: I18n.t("about.activities.topics", {
|
||||
count: this.args.model.stats.topics_7_days,
|
||||
formatted_number: number(this.args.model.stats.topics_7_days),
|
||||
}),
|
||||
period: I18n.t("about.activities.periods.last_7_days"),
|
||||
},
|
||||
{
|
||||
icon: "pencil-alt",
|
||||
class: "posts",
|
||||
activityText: I18n.t("about.activities.posts", {
|
||||
count: this.args.model.stats.posts_last_day,
|
||||
formatted_number: number(this.args.model.stats.posts_last_day),
|
||||
}),
|
||||
period: I18n.t("about.activities.periods.today"),
|
||||
},
|
||||
{
|
||||
icon: "user-friends",
|
||||
class: "active-users",
|
||||
activityText: I18n.t("about.activities.active_users", {
|
||||
count: this.args.model.stats.active_users_7_days,
|
||||
formatted_number: number(this.args.model.stats.active_users_7_days),
|
||||
}),
|
||||
period: I18n.t("about.activities.periods.last_7_days"),
|
||||
},
|
||||
{
|
||||
icon: "user-plus",
|
||||
class: "sign-ups",
|
||||
activityText: I18n.t("about.activities.sign_ups", {
|
||||
count: this.args.model.stats.users_7_days,
|
||||
formatted_number: number(this.args.model.stats.users_7_days),
|
||||
}),
|
||||
period: I18n.t("about.activities.periods.last_7_days"),
|
||||
},
|
||||
{
|
||||
icon: "heart",
|
||||
class: "likes",
|
||||
activityText: I18n.t("about.activities.likes", {
|
||||
count: this.args.model.stats.likes_count,
|
||||
formatted_number: number(this.args.model.stats.likes_count),
|
||||
}),
|
||||
period: I18n.t("about.activities.periods.all_time"),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -66,6 +122,22 @@ export default class AboutPage extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
get siteAgeString() {
|
||||
const creationDate = new Date(this.args.model.site_creation_date);
|
||||
|
||||
let diff = new Date() - creationDate;
|
||||
diff /= 1000 * 3600 * 24 * 30;
|
||||
|
||||
if (diff < 1) {
|
||||
return I18n.t("about.site_age.less_than_one_month");
|
||||
} else if (diff < 12) {
|
||||
return I18n.t("about.site_age.month", { count: Math.round(diff) });
|
||||
} else {
|
||||
diff /= 12;
|
||||
return I18n.t("about.site_age.year", { count: Math.round(diff) });
|
||||
}
|
||||
}
|
||||
|
||||
<template>
|
||||
<section class="about__header">
|
||||
<img class="about__banner" src={{@model.banner_image}} />
|
||||
|
@ -91,11 +163,29 @@ export default class AboutPage extends Component {
|
|||
<div>{{htmlSafe @model.extended_site_description}}</div>
|
||||
</section>
|
||||
<section class="about__right-side">
|
||||
<h4>{{i18n "about.contact"}}</h4>
|
||||
<h3>{{i18n "about.contact"}}</h3>
|
||||
{{#if this.contactInfo}}
|
||||
<p>{{htmlSafe this.contactInfo}}</p>
|
||||
{{/if}}
|
||||
<p>{{i18n "about.report_inappropriate_content"}}</p>
|
||||
<h3>{{i18n "about.site_activity"}}</h3>
|
||||
<div class="about__activities">
|
||||
{{#each this.siteActivities as |activity|}}
|
||||
<div class="about__activities-item {{activity.class}}">
|
||||
<span class="about__activities-item-icon">{{dIcon
|
||||
activity.icon
|
||||
}}</span>
|
||||
<span class="about__activities-item-type">
|
||||
<div
|
||||
class="about__activities-item-count"
|
||||
>{{activity.activityText}}</div>
|
||||
<div
|
||||
class="about__activities-item-period"
|
||||
>{{activity.period}}</div>
|
||||
</span>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.about {
|
||||
&__main-content {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr;
|
||||
grid-template-columns: 2.5fr 1fr;
|
||||
column-gap: 4em;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,20 @@
|
|||
min-height: 300px;
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
&__activities-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
&__activities-item-icon {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
&__activities-item-period {
|
||||
font-size: var(--font-down-2);
|
||||
}
|
||||
}
|
||||
|
||||
section.about {
|
||||
|
|
|
@ -64,6 +64,10 @@ class About
|
|||
GlobalPath.full_cdn_url(url)
|
||||
end
|
||||
|
||||
def site_creation_date
|
||||
Discourse.site_creation_date
|
||||
end
|
||||
|
||||
def moderators
|
||||
@moderators ||= User.where(moderator: true, admin: false).human_users.order("last_seen_at DESC")
|
||||
end
|
||||
|
|
|
@ -22,6 +22,7 @@ class AboutSerializer < ApplicationSerializer
|
|||
:description,
|
||||
:extended_site_description,
|
||||
:banner_image,
|
||||
:site_creation_date,
|
||||
:title,
|
||||
:locale,
|
||||
:version,
|
||||
|
@ -62,6 +63,10 @@ class AboutSerializer < ApplicationSerializer
|
|||
render_redesigned_about_page?
|
||||
end
|
||||
|
||||
def include_site_creation_date?
|
||||
render_redesigned_about_page?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def can_see_about_stats
|
||||
|
|
|
@ -345,6 +345,27 @@ en:
|
|||
active_user_count: "Active users"
|
||||
contact: "Contact us"
|
||||
contact_info: "In the event of a critical issue or urgent matter affecting this site, please contact us at %{contact_info}."
|
||||
site_activity: "Site activity"
|
||||
activities:
|
||||
topics:
|
||||
one: "%{formatted_number} topic"
|
||||
other: "%{formatted_number} topics"
|
||||
posts:
|
||||
one: "%{formatted_number} post"
|
||||
other: "%{formatted_number} posts"
|
||||
active_users:
|
||||
one: "%{formatted_number} active user"
|
||||
other: "%{formatted_number} active users"
|
||||
sign_ups:
|
||||
one: "%{formatted_number} sign-up"
|
||||
other: "%{formatted_number} sign-ups"
|
||||
likes:
|
||||
one: "%{formatted_number} like"
|
||||
other: "%{formatted_number} likes"
|
||||
periods:
|
||||
last_7_days: "in the last 7 days"
|
||||
today: "today"
|
||||
all_time: "all time"
|
||||
member_count:
|
||||
one: "%{formatted_number} Member"
|
||||
other: "%{formatted_number} Members"
|
||||
|
@ -355,6 +376,14 @@ en:
|
|||
one: "%{formatted_number} Moderator"
|
||||
other: "%{formatted_number} Moderators"
|
||||
report_inappropriate_content: "If you come across any inappropriate content, don't hesitate to start a conversation with our moderators and admins. Remember to log in before reaching out."
|
||||
site_age:
|
||||
less_than_one_month: "Created < 1 month ago"
|
||||
month:
|
||||
one: "Created %{count} month ago"
|
||||
other: "Created %{count} months ago"
|
||||
year:
|
||||
one: "Created %{count} year ago"
|
||||
other: "Created %{count} years ago"
|
||||
|
||||
bookmarked:
|
||||
title: "Bookmark"
|
||||
|
|
|
@ -1034,6 +1034,24 @@ module Discourse
|
|||
[SiteSetting.tos_topic_id, SiteSetting.guidelines_topic_id, SiteSetting.privacy_topic_id]
|
||||
end
|
||||
|
||||
def self.site_creation_date
|
||||
@creation_dates ||= {}
|
||||
current_db = RailsMultisite::ConnectionManagement.current_db
|
||||
@creation_dates[current_db] ||= begin
|
||||
result = DB.query_single <<~SQL
|
||||
SELECT created_at
|
||||
FROM schema_migration_details
|
||||
ORDER BY created_at
|
||||
LIMIT 1
|
||||
SQL
|
||||
result.first
|
||||
end
|
||||
end
|
||||
|
||||
def self.clear_site_creation_date_cache
|
||||
@creation_dates = {}
|
||||
end
|
||||
|
||||
cattr_accessor :last_ar_cache_reset
|
||||
|
||||
def self.reset_active_record_cache_if_needed(e)
|
||||
|
|
|
@ -201,6 +201,7 @@ module SvgSprite
|
|||
reply
|
||||
robot
|
||||
rocket
|
||||
scroll
|
||||
search
|
||||
search-plus
|
||||
search-minus
|
||||
|
|
|
@ -63,5 +63,113 @@ describe "About page", type: :system do
|
|||
expect(about_page).to have_admins_count(1, "1")
|
||||
expect(about_page).to have_moderators_count(1, "1")
|
||||
end
|
||||
|
||||
describe "displayed site age" do
|
||||
it "says less than 1 month if the site is less than 1 month old" do
|
||||
Discourse.stubs(:site_creation_date).returns(1.week.ago)
|
||||
|
||||
about_page.visit
|
||||
|
||||
expect(about_page).to have_site_created_less_than_1_month_ago
|
||||
end
|
||||
|
||||
it "says how many months old the site is if the site is less than 1 year old" do
|
||||
Discourse.stubs(:site_creation_date).returns(2.months.ago)
|
||||
|
||||
about_page.visit
|
||||
|
||||
expect(about_page).to have_site_created_in_months_ago(2)
|
||||
end
|
||||
|
||||
it "says how many years old the site is if the site is more than 1 year old" do
|
||||
Discourse.stubs(:site_creation_date).returns(5.years.ago)
|
||||
|
||||
about_page.visit
|
||||
|
||||
expect(about_page).to have_site_created_in_years_ago(5)
|
||||
end
|
||||
end
|
||||
|
||||
describe "the site activity section" do
|
||||
describe "topics" do
|
||||
before do
|
||||
Fabricate(:topic, created_at: 2.days.ago)
|
||||
Fabricate(:topic, created_at: 3.days.ago)
|
||||
Fabricate(:topic, created_at: 8.days.ago)
|
||||
end
|
||||
|
||||
it "shows the count of topics created in the last 7 days" do
|
||||
about_page.visit
|
||||
expect(about_page.site_activities.topics).to have_count(2, "2")
|
||||
expect(about_page.site_activities.topics).to have_7_days_period
|
||||
end
|
||||
end
|
||||
|
||||
describe "posts" do
|
||||
before do
|
||||
Fabricate(:post, created_at: 2.days.ago)
|
||||
Fabricate(:post, created_at: 1.hour.ago)
|
||||
Fabricate(:post, created_at: 3.hours.ago)
|
||||
Fabricate(:post, created_at: 23.hours.ago)
|
||||
end
|
||||
|
||||
it "shows the count of topics created in the last day" do
|
||||
about_page.visit
|
||||
expect(about_page.site_activities.posts).to have_count(3, "3")
|
||||
expect(about_page.site_activities.posts).to have_1_day_period
|
||||
end
|
||||
end
|
||||
|
||||
describe "active users" do
|
||||
before do
|
||||
User.update_all(last_seen_at: 1.month.ago)
|
||||
|
||||
Fabricate(:user, last_seen_at: 1.hour.ago)
|
||||
Fabricate(:user, last_seen_at: 1.day.ago)
|
||||
Fabricate(:user, last_seen_at: 3.days.ago)
|
||||
Fabricate(:user, last_seen_at: 6.days.ago)
|
||||
Fabricate(:user, last_seen_at: 8.days.ago)
|
||||
end
|
||||
|
||||
it "shows the count of active users in the last 7 days" do
|
||||
about_page.visit
|
||||
expect(about_page.site_activities.active_users).to have_count(5, "5") # 4 fabricated above + 1 for the current user
|
||||
expect(about_page.site_activities.active_users).to have_7_days_period
|
||||
end
|
||||
end
|
||||
|
||||
describe "sign ups" do
|
||||
before do
|
||||
User.update_all(created_at: 1.month.ago)
|
||||
|
||||
Fabricate(:user, created_at: 3.hours.ago)
|
||||
Fabricate(:user, created_at: 3.days.ago)
|
||||
Fabricate(:user, created_at: 8.days.ago)
|
||||
end
|
||||
|
||||
it "shows the count of signups in the last 7 days" do
|
||||
about_page.visit
|
||||
expect(about_page.site_activities.sign_ups).to have_count(2, "2")
|
||||
expect(about_page.site_activities.sign_ups).to have_7_days_period
|
||||
end
|
||||
end
|
||||
|
||||
describe "likes" do
|
||||
before do
|
||||
UserAction.destroy_all
|
||||
|
||||
Fabricate(:user_action, created_at: 1.hour.ago, action_type: UserAction::LIKE)
|
||||
Fabricate(:user_action, created_at: 1.day.ago, action_type: UserAction::LIKE)
|
||||
Fabricate(:user_action, created_at: 1.month.ago, action_type: UserAction::LIKE)
|
||||
Fabricate(:user_action, created_at: 10.years.ago, action_type: UserAction::LIKE)
|
||||
end
|
||||
|
||||
it "shows the count of likes of all time" do
|
||||
about_page.visit
|
||||
expect(about_page.site_activities.likes).to have_count(4, "4")
|
||||
expect(about_page.site_activities.likes).to have_all_time_period
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module PageObjects
|
||||
module Components
|
||||
class AboutPageSiteActivity < PageObjects::Components::Base
|
||||
attr_reader :container
|
||||
|
||||
def initialize(container)
|
||||
@container = container
|
||||
end
|
||||
|
||||
def topics
|
||||
AboutPageSiteActivityItem.new(
|
||||
container.find(".about__activities-item.topics"),
|
||||
translation_key: "about.activities.topics",
|
||||
)
|
||||
end
|
||||
|
||||
def posts
|
||||
AboutPageSiteActivityItem.new(
|
||||
container.find(".about__activities-item.posts"),
|
||||
translation_key: "about.activities.posts",
|
||||
)
|
||||
end
|
||||
|
||||
def active_users
|
||||
AboutPageSiteActivityItem.new(
|
||||
container.find(".about__activities-item.active-users"),
|
||||
translation_key: "about.activities.active_users",
|
||||
)
|
||||
end
|
||||
|
||||
def sign_ups
|
||||
AboutPageSiteActivityItem.new(
|
||||
container.find(".about__activities-item.sign-ups"),
|
||||
translation_key: "about.activities.sign_ups",
|
||||
)
|
||||
end
|
||||
|
||||
def likes
|
||||
AboutPageSiteActivityItem.new(
|
||||
container.find(".about__activities-item.likes"),
|
||||
translation_key: "about.activities.likes",
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,38 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module PageObjects
|
||||
module Components
|
||||
class AboutPageSiteActivityItem < PageObjects::Components::Base
|
||||
attr_reader :container
|
||||
|
||||
def initialize(container, translation_key:)
|
||||
@container = container
|
||||
@translation_key = translation_key
|
||||
end
|
||||
|
||||
def has_count?(count, formatted_number)
|
||||
container.find(".about__activities-item-count").has_text?(
|
||||
I18n.t("js.#{@translation_key}", count: count, formatted_number:),
|
||||
)
|
||||
end
|
||||
|
||||
def has_1_day_period?
|
||||
period_element.has_text?(I18n.t("js.about.activities.periods.today"))
|
||||
end
|
||||
|
||||
def has_7_days_period?
|
||||
period_element.has_text?(I18n.t("js.about.activities.periods.last_7_days"))
|
||||
end
|
||||
|
||||
def has_all_time_period?
|
||||
period_element.has_text?(I18n.t("js.about.activities.periods.all_time"))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def period_element
|
||||
container.find(".about__activities-item-period")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -33,6 +33,28 @@ module PageObjects
|
|||
element = find(".about__stats-item.moderators span")
|
||||
element.has_text?(I18n.t("js.about.moderator_count", count:, formatted_number:))
|
||||
end
|
||||
|
||||
def has_site_created_less_than_1_month_ago?
|
||||
site_age_stat_element.has_text?(I18n.t("js.about.site_age.less_than_one_month"))
|
||||
end
|
||||
|
||||
def has_site_created_in_months_ago?(months)
|
||||
site_age_stat_element.has_text?(I18n.t("js.about.site_age.month", count: months))
|
||||
end
|
||||
|
||||
def has_site_created_in_years_ago?(years)
|
||||
site_age_stat_element.has_text?(I18n.t("js.about.site_age.year", count: years))
|
||||
end
|
||||
|
||||
def site_activities
|
||||
PageObjects::Components::AboutPageSiteActivity.new(find(".about__activities"))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def site_age_stat_element
|
||||
find(".about__stats-item.site-creation-date span")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue
Block a user