From 5238a95efb596cb0666868507aa34e33abf55868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Mon, 16 Jun 2014 18:28:07 +0200 Subject: [PATCH] add make/remove banner topic actions --- .../discourse/controllers/topic_controller.js | 12 +++-- .../javascripts/discourse/models/topic.js | 29 +++++------ .../templates/topic_admin_menu.js.handlebars | 38 ++++++++------ app/controllers/topics_controller.rb | 33 ++++++++++-- config/locales/client.en.yml | 3 +- config/locales/server.en.yml | 5 +- config/routes.rb | 2 + spec/controllers/topics_controller_spec.rb | 52 +++++++++++++++++++ 8 files changed, 130 insertions(+), 44 deletions(-) diff --git a/app/assets/javascripts/discourse/controllers/topic_controller.js b/app/assets/javascripts/discourse/controllers/topic_controller.js index 6b1220677c9..73c68545ca3 100644 --- a/app/assets/javascripts/discourse/controllers/topic_controller.js +++ b/app/assets/javascripts/discourse/controllers/topic_controller.js @@ -302,6 +302,14 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected this.get('content').toggleStatus('closed'); }, + makeBanner: function() { + this.get('content').makeBanner(); + }, + + removeBanner: function() { + this.get('content').removeBanner(); + }, + togglePinned: function() { // Note that this is different than clearPin this.get('content').setStatus('pinned', this.get('pinned_at') ? false : true); @@ -316,10 +324,6 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected this.get('content').toggleStatus('archived'); }, - convertToRegular: function() { - this.get('content').convertArchetype('regular'); - }, - // Toggle the star on the topic toggleStar: function() { this.get('content').toggleStar(); diff --git a/app/assets/javascripts/discourse/models/topic.js b/app/assets/javascripts/discourse/models/topic.js index 45cc59ec537..b766e5120b6 100644 --- a/app/assets/javascripts/discourse/models/topic.js +++ b/app/assets/javascripts/discourse/models/topic.js @@ -19,22 +19,6 @@ Discourse.Topic = Discourse.Model.extend({ invisible: Em.computed.not('visible'), deleted: Em.computed.notEmpty('deleted_at'), - canConvertToRegular: function() { - var a = this.get('archetype'); - return a !== 'regular' && a !== 'private_message'; - }.property('archetype'), - - convertArchetype: function() { - var a = this.get('archetype'); - if (a !== 'regular' && a !== 'private_message') { - this.set('archetype', 'regular'); - return Discourse.ajax(this.get('url'), { - type: 'PUT', - data: {archetype: 'regular'} - }); - } - }, - searchContext: function() { return ({ type: 'topic', id: this.get('id') }); }.property('id'), @@ -131,6 +115,7 @@ Discourse.Topic = Discourse.Model.extend({ }.property('archetype'), isPrivateMessage: Em.computed.equal('archetype', 'private_message'), + isBanner: Em.computed.equal('archetype', 'banner'), toggleStatus: function(property) { this.toggleProperty(property); @@ -155,6 +140,18 @@ Discourse.Topic = Discourse.Model.extend({ }); }, + makeBanner: function() { + var self = this; + return Discourse.ajax('/t/' + this.get('id') + '/make-banner', { type: 'PUT' }) + .then(function () { self.set('archetype', 'banner'); }) + }, + + removeBanner: function() { + var self = this; + return Discourse.ajax('/t/' + this.get('id') + '/remove-banner', { type: 'PUT' }) + .then(function () { self.set('archetype', 'regular'); }) + }, + starTooltipKey: function() { return this.get('starred') ? 'starred.help.unstar' : 'starred.help.star'; }.property('starred'), diff --git a/app/assets/javascripts/discourse/templates/topic_admin_menu.js.handlebars b/app/assets/javascripts/discourse/templates/topic_admin_menu.js.handlebars index 24186ce776b..78a5e645bdd 100644 --- a/app/assets/javascripts/discourse/templates/topic_admin_menu.js.handlebars +++ b/app/assets/javascripts/discourse/templates/topic_admin_menu.js.handlebars @@ -28,14 +28,24 @@ {{/if}} -
  • - {{#if pinned_at}} - - {{else}} - - - {{/if}} -
  • + {{#unless isPrivateMessage}} +
  • + {{#if isBanner}} + + {{else}} + + {{/if}} +
  • + +
  • + {{#if pinned_at}} + + {{else}} + + + {{/if}} +
  • + {{/unless}}
  • {{#if archived}} @@ -53,16 +63,10 @@ {{/if}}
  • - {{#if canConvertToRegular}} -
  • - -
  • - {{/if}} - {{#if currentUser.staff}} -
  • - -
  • +
  • + +
  • {{/if}} diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 7c617514e14..16335f2e299 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -75,6 +75,7 @@ class TopicsController < ApplicationController params.require(:best) params.require(:topic_id) params.permit(:min_trust_level, :min_score, :min_replies, :bypass_trust_level_score, :only_moderator_liked) + opts = { best: params[:best].to_i, min_trust_level: params[:min_trust_level] ? 1 : params[:min_trust_level].to_i, min_score: params[:min_score].to_i, @@ -105,13 +106,9 @@ class TopicsController < ApplicationController def update topic = Topic.find_by(id: params[:topic_id]) - title, archetype = params[:title], params[:archetype] guardian.ensure_can_edit!(topic) - topic.title = params[:title] if title.present? - # TODO: we may need smarter rules about converting archetypes - topic.archetype = "regular" if current_user.admin? && archetype == 'regular' - + topic.title = params[:title] if params[:title].present? topic.acting_user = current_user success = false @@ -176,6 +173,32 @@ class TopicsController < ApplicationController end end + def make_banner + topic = Topic.find_by(id: params[:topic_id].to_i) + guardian.ensure_can_moderate!(topic) + + # TODO: only one banner at the same time + + topic.archetype = Archetype.banner + topic.add_moderator_post(current_user, I18n.t("archetypes.banner.message.make")) + + topic.save + + render nothing: true + end + + def remove_banner + topic = Topic.find_by(id: params[:topic_id].to_i) + guardian.ensure_can_moderate!(topic) + + topic.archetype = Archetype.default + topic.add_moderator_post(current_user, I18n.t("archetypes.banner.message.remove")) + + topic.save + + render nothing: true + end + def destroy topic = Topic.find_by(id: params[:id]) guardian.ensure_can_delete!(topic) diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 946a2b32c4b..6ebca8c8814 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -837,6 +837,8 @@ en: open: "Open Topic" close: "Close Topic" auto_close: "Auto Close" + make_banner: "Banner Topic" + remove_banner: "Remove Banner Topic" unpin: "Un-Pin Topic" pin: "Pin Topic" pin_globally: "Pin Topic Globally" @@ -846,7 +848,6 @@ en: visible: "Make Visible" reset_read: "Reset Read Data" multi_select: "Select Posts" - convert_to_topic: "Convert to Regular Topic" reply: title: 'Reply' diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index e33219821d0..314e682ffba 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -423,6 +423,10 @@ en: archetypes: regular: title: "Regular Topic" + banner: + message: + make: "This topic is now a banner topic. It will appear at the top of every pages until it is dismissed by the users." + remove: "This topic is not a banner topic anymore. It will no longer appear at the top of every pages." unsubscribed: title: 'Unsubscribed' @@ -989,7 +993,6 @@ en: autoclosed_disabled: "This topic is now opened. New replies are allowed." pinned_enabled: "This topic is now pinned. It will appear at the top of its category until it is unpinned by staff for everyone, or by individual users for themselves." pinned_disabled: "This topic is now unpinned. It will no longer appear at the top of its category." - pinned_globally_enabled: "This topic is now pinned globally. It will appear at the top of its category and all topic lists until it is unpinned by staff for everyone, or by individual users for themselves." pinned_globally_disabled: "This topic is now unpinned. It will no longer appear at the top of its category." visible_enabled: "This topic is now visible. It will be displayed in topic lists." diff --git a/config/routes.rb b/config/routes.rb index b26263e8b06..ab2a09911d7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -340,6 +340,8 @@ Discourse::Application.routes.draw do put "t/:topic_id/mute" => "topics#mute", constraints: {topic_id: /\d+/} put "t/:topic_id/unmute" => "topics#unmute", constraints: {topic_id: /\d+/} put "t/:topic_id/autoclose" => "topics#autoclose", constraints: {topic_id: /\d+/} + put "t/:topic_id/make-banner" => "topics#make_banner", constraints: {topic_id: /\d+/} + put "t/:topic_id/remove-banner" => "topics#remove_banner", constraints: {topic_id: /\d+/} put "t/:topic_id/remove-allowed-user" => "topics#remove_allowed_user", constraints: {topic_id: /\d+/} put "t/:topic_id/recover" => "topics#recover", constraints: {topic_id: /\d+/} get "t/:topic_id/:post_number" => "topics#show", constraints: {topic_id: /\d+/, post_number: /\d+/} diff --git a/spec/controllers/topics_controller_spec.rb b/spec/controllers/topics_controller_spec.rb index 7be236f0896..69692a818e8 100644 --- a/spec/controllers/topics_controller_spec.rb +++ b/spec/controllers/topics_controller_spec.rb @@ -847,6 +847,58 @@ describe TopicsController do end + describe 'make_banner' do + + it 'needs you to be a staff member' do + log_in + xhr :put, :make_banner, topic_id: 99 + response.should be_forbidden + end + + describe 'when logged in' do + + before do + @admin = log_in(:admin) + @topic = Fabricate(:topic, user: @admin) + end + + it "changes the topic archetype to 'banner'" do + Topic.any_instance.expects(:archetype=).with(Archetype.banner) + Topic.any_instance.expects(:add_moderator_post) + xhr :put, :make_banner, topic_id: @topic.id + response.should be_success + end + + end + + end + + describe 'remove_banner' do + + it 'needs you to be a staff member' do + log_in + xhr :put, :remove_banner, topic_id: 99 + response.should be_forbidden + end + + describe 'when logged in' do + + before do + @admin = log_in(:admin) + @topic = Fabricate(:topic, user: @admin) + end + + it "resets the topic archetype" do + Topic.any_instance.expects(:archetype=).with(Archetype.default) + Topic.any_instance.expects(:add_moderator_post) + xhr :put, :remove_banner, topic_id: @topic.id + response.should be_success + end + + end + + end + describe "bulk" do it 'needs you to be logged in' do lambda { xhr :put, :bulk }.should raise_error(Discourse::NotLoggedIn)