From cc2dc4d5502253a34d0bf68d96808004143a6867 Mon Sep 17 00:00:00 2001 From: Neil Lalonde Date: Thu, 27 Aug 2015 17:28:33 -0400 Subject: [PATCH] FEATURE: the notice asking admins to get discussion started will update with live counts of topics and posts --- .../components/create-topics-notice.js.es6 | 78 +++++++++++++++++++ .../discourse/components/global-notice.js.es6 | 14 ---- .../discourse/models/live-post-counts.es6 | 9 +++ .../discourse/templates/application.hbs | 1 + .../components/create-topics-notice.hbs | 7 ++ app/controllers/about_controller.rb | 11 +++ config/locales/client.en.yml | 2 +- config/routes.rb | 6 +- 8 files changed, 112 insertions(+), 16 deletions(-) create mode 100644 app/assets/javascripts/discourse/components/create-topics-notice.js.es6 create mode 100644 app/assets/javascripts/discourse/models/live-post-counts.es6 create mode 100644 app/assets/javascripts/discourse/templates/components/create-topics-notice.hbs diff --git a/app/assets/javascripts/discourse/components/create-topics-notice.js.es6 b/app/assets/javascripts/discourse/components/create-topics-notice.js.es6 new file mode 100644 index 00000000000..9f502ec7ceb --- /dev/null +++ b/app/assets/javascripts/discourse/components/create-topics-notice.js.es6 @@ -0,0 +1,78 @@ +import computed from 'ember-addons/ember-computed-decorators'; +import { observes } from 'ember-addons/ember-computed-decorators'; +import LivePostCounts from 'discourse/models/live-post-counts'; + +export default Ember.Component.extend({ + classNameBindings: ['hidden:hidden',':create-topics-notice'], + + enabled: false, + + publicTopicCount: null, + publicPostCount: null, + + requiredTopics: 5, + requiredPosts: Ember.computed.alias('siteSettings.tl1_requires_read_posts'), + + init() { + this._super(); + if (this.get('shouldSee')) { + let topicCount = 0, + postCount = 0; + + // Use data we already have before fetching live stats + _.each(this.site.get('categories'), function(c) { + if (!c.get('read_restricted')) { + topicCount += c.get('topic_count'); + postCount += c.get('post_count'); + } + }); + + if (topicCount < this.get('requiredTopics') || postCount < this.get('requiredPosts')) { + this.set('enabled', true); + this.fetchLiveStats(); + } + } + }, + + @computed() + shouldSee() { + return Discourse.User.currentProp('admin') && this.siteSettings.show_create_topics_notice; + }, + + @computed('enabled', 'shouldSee', 'publicTopicCount', 'publicPostCount') + hidden() { + return !this.get('enabled') || !this.get('shouldSee') || this.get('publicTopicCount') == null || this.get('publicPostCount') == null; + }, + + @computed('publicTopicCount', 'publicPostCount', 'topicTrackingState.incomingCount') + message() { + return new Handlebars.SafeString(I18n.t('too_few_topics_notice', { + requiredTopics: this.get('requiredTopics'), + requiredPosts: this.get('requiredPosts'), + currentTopics: this.get('publicTopicCount'), + currentPosts: this.get('publicPostCount') + })); + }, + + @computed() + topicTrackingState() { + return Discourse.TopicTrackingState.current(); + }, + + @observes('topicTrackingState.incomingCount') + fetchLiveStats() { + if (!this.get('enabled')) { return; } + + var self = this; + LivePostCounts.find().then(function(stats) { + if(stats) { + self.set('publicTopicCount', stats.get('public_topic_count')); + self.set('publicPostCount', stats.get('public_post_count')); + if (self.get('publicTopicCount') >= self.get('requiredTopics') + && self.get('publicPostCount') >= self.get('requiredPosts')) { + self.set('enabled', false); // No more checks + } + } + }); + } +}); diff --git a/app/assets/javascripts/discourse/components/global-notice.js.es6 b/app/assets/javascripts/discourse/components/global-notice.js.es6 index 6e5d5fc31fd..080427d80f3 100644 --- a/app/assets/javascripts/discourse/components/global-notice.js.es6 +++ b/app/assets/javascripts/discourse/components/global-notice.js.es6 @@ -14,20 +14,6 @@ export default Ember.Component.extend(StringBuffer, { notices.push([I18n.t("emails_are_disabled"), 'alert-emails-disabled']); } - if (Discourse.User.currentProp('admin') && this.siteSettings.show_create_topics_notice) { - let topic_count = 0, - post_count = 0; - _.each(this.site.get('categories'), function(c) { - if (!c.get('read_restricted')) { - topic_count += c.get('topic_count'); - post_count += c.get('post_count'); - } - }); - if (topic_count < 5 || post_count < this.siteSettings.tl1_requires_read_posts) { - notices.push([I18n.t("too_few_topics_notice", { posts: this.siteSettings.tl1_requires_read_posts }), 'alert-too-few-topics']); - } - } - if (!_.isEmpty(this.siteSettings.global_notice)) { notices.push([this.siteSettings.global_notice, 'alert-global-notice']); } diff --git a/app/assets/javascripts/discourse/models/live-post-counts.es6 b/app/assets/javascripts/discourse/models/live-post-counts.es6 new file mode 100644 index 00000000000..678aecbf595 --- /dev/null +++ b/app/assets/javascripts/discourse/models/live-post-counts.es6 @@ -0,0 +1,9 @@ +const LivePostCounts = Discourse.Model.extend({}); + +LivePostCounts.reopenClass({ + find() { + return Discourse.ajax("/about/live_post_counts.json").then(result => LivePostCounts.create(result)); + } +}); + +export default LivePostCounts; diff --git a/app/assets/javascripts/discourse/templates/application.hbs b/app/assets/javascripts/discourse/templates/application.hbs index cd89910d140..c9a5681dff4 100644 --- a/app/assets/javascripts/discourse/templates/application.hbs +++ b/app/assets/javascripts/discourse/templates/application.hbs @@ -6,6 +6,7 @@ {{custom-html "top"}} {{/if}} {{global-notice}} + {{create-topics-notice}} {{outlet}} {{render "user-card"}} diff --git a/app/assets/javascripts/discourse/templates/components/create-topics-notice.hbs b/app/assets/javascripts/discourse/templates/components/create-topics-notice.hbs new file mode 100644 index 00000000000..a508a69b396 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/create-topics-notice.hbs @@ -0,0 +1,7 @@ +{{#unless hidden}} +
+
+ {{message}} +
+
+{{/unless}} \ No newline at end of file diff --git a/app/controllers/about_controller.rb b/app/controllers/about_controller.rb index d1a0b3d0338..cc65c36e89f 100644 --- a/app/controllers/about_controller.rb +++ b/app/controllers/about_controller.rb @@ -1,3 +1,5 @@ +require_dependency 'rate_limiter' + class AboutController < ApplicationController skip_before_filter :check_xhr, only: [:show] @@ -5,4 +7,13 @@ class AboutController < ApplicationController @about = About.new render_serialized(@about, AboutSerializer) end + + def live_post_counts + RateLimiter.new(current_user, "live_post_counts", 1, 10.minutes).performed! unless current_user.staff? + category_topic_ids = Category.pluck(:topic_id).compact! + public_topics = Topic.listable_topics.visible.secured(Guardian.new(nil)).where.not(id: category_topic_ids) + stats = { public_topic_count: public_topics.count } + stats[:public_post_count] = public_topics.sum(:posts_count) - stats[:public_topic_count] + render json: stats + end end diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 264c8b92996..7f9ed5c31d4 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -686,7 +686,7 @@ en: read_only_mode: enabled: "Read-only mode is enabled. You can continue to browse the site but interactions may not work." login_disabled: "Login is disabled while the site is in read only mode." - too_few_topics_notice: "Create at least 5 public topics and %{posts} public replies to get discussion started. New users cannot earn trust levels unless there's content for them to read. This message appears only to staff." + too_few_topics_notice: "Get discussion started by creating %{requiredTopics} public topics and %{requiredPosts} posts. There are currently %{currentTopics} / %{requiredTopics} topics and %{currentPosts} / %{requiredPosts} posts. New users cannot earn trust levels unless there's content for them to read. This message appears only to staff." learn_more: "learn more..." diff --git a/config/routes.rb b/config/routes.rb index 67bfa0f5514..86553f03284 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -23,7 +23,11 @@ Discourse::Application.routes.draw do mount Logster::Web => "/logs", constraints: AdminConstraint.new end - resources :about + resources :about do + collection do + get "live_post_counts" + end + end resources :directory_items