FEATURE: dismissable banner topic

This commit is contained in:
Régis Hanol 2014-06-18 20:04:10 +02:00
parent 39aa87dedf
commit 00117c18c3
15 changed files with 153 additions and 55 deletions

View file

@ -0,0 +1,25 @@
export default Ember.Component.extend({
visible: function () {
var bannerKey = this.get("banner.key"),
dismissedBannerKey = this.get("user.dismissed_banner_key") ||
Discourse.KeyValueStore.get("dismissed_banner_key");
if (bannerKey) { bannerKey = parseInt(bannerKey, 10); }
if (dismissedBannerKey) { dismissedBannerKey = parseInt(dismissedBannerKey, 10); }
return bannerKey && dismissedBannerKey !== bannerKey;
}.property("user.dismissed_banner_key", "banner.key"),
actions: {
dismiss: function () {
if (this.get("user")) {
this.get("user").dismissBanner(this.get("banner.key"));
} else {
this.set("visible", false);
Discourse.KeyValueStore.set({ key: "dismissed_banner_key", value: this.get("banner.key") });
}
}
}
});

View file

@ -411,6 +411,14 @@ Discourse.User = Discourse.Model.extend({
} else {
return Ember.RSVP.reject(I18n.t('user.delete_yourself_not_allowed'));
}
},
dismissBanner: function (bannerKey) {
this.set("dismissed_banner_key", bannerKey);
Discourse.ajax("/users/" + this.get('username'), {
type: 'PUT',
data: { dismissed_banner_key: bannerKey }
});
}
});

View file

@ -0,0 +1,9 @@
{{#if visible}}
<div id="banner">
<div id="banner-content">
<div class="close" {{action dismiss}}><i class="fa fa-times" title="{{i18n banner.close}}"></i></div>
{{{banner.html}}}
</div>
<a href="{{unbound banner.url}}" class="btn" title="{{i18n banner.read_more.title}}">{{i18n banner.read_more.text}}</a>
</div>
{{/if}}

View file

@ -1,6 +1,7 @@
<div class='container'>
{{custom-html "top"}}
{{Discourse.globalNotice}}
{{discourse-banner user=currentUser banner=Discourse.banner}}
</div>
<div class='list-controls'>

View file

@ -1,6 +1,7 @@
<div class='container'>
{{custom-html "top"}}
{{Discourse.globalNotice}}
{{discourse-banner user=currentUser banner=Discourse.banner}}
</div>
{{#if postStream.loaded}}

View file

@ -0,0 +1,14 @@
// --------------------------------------------------
// Banner
// --------------------------------------------------
#banner {
margin-bottom: 10px;
.close {
font-size: 25px !important;
margin-top: 0 !important;
}
.meta {
display: none;
}
}

View file

@ -63,16 +63,16 @@ animation: modal .25s;
font-size: 20px;
padding: 10px 15px 7px;
}
.close {
float: right;
font-size: 20px;
margin: 10px 10px 0;
text-decoration: none;
color: scale-color($primary, $lightness: 35%);
cursor: pointer;
&:hover {
color: $primary;
}
}
.close {
float: right;
font-size: 20px;
margin: 10px 10px 0;
text-decoration: none;
color: scale-color($primary, $lightness: 35%);
cursor: pointer;
&:hover {
color: $primary;
}
}

View file

@ -54,18 +54,16 @@
font-size: 15px;
padding: 0 0 0 20px;
}
.close {
float: right;
font-size: 24px;
padding: 15px; // more pixels to touch
margin: -15px 0 0 0;
text-decoration: none;
color: $primary;
cursor: pointer;
}
}
.close {
float: right;
font-size: 24px;
padding: 15px; // more pixels to touch
margin: -15px 0 0 0;
text-decoration: none;
color: $primary;
cursor: pointer;
}
#move-selected {
p {

View file

@ -234,6 +234,7 @@ class ApplicationController < ActionController::Base
store_preloaded("site", Site.json_for(guardian))
store_preloaded("siteSettings", SiteSetting.client_settings_json)
store_preloaded("customHTML", custom_html_json)
store_preloaded("banner", banner_json)
end
def preload_current_user_data
@ -259,16 +260,23 @@ class ApplicationController < ActionController::Base
MultiJson.dump(data)
end
def banner_json
topic = Topic.where(archetype: Archetype.banner).limit(1).first
banner = topic.present? ? topic.banner : {}
MultiJson.dump(banner)
end
def render_json_error(obj)
render json: MultiJson.dump(create_errors_json(obj)), status: 422
end
def success_json
{success: 'OK'}
{ success: 'OK' }
end
def failed_json
{failed: 'FAILED'}
{ failed: 'FAILED' }
end
def json_result(obj, opts={})

View file

@ -634,12 +634,26 @@ class Topic < ActiveRecord::Base
self.archetype = Archetype.banner
self.add_moderator_post(user, I18n.t("archetypes.banner.message.make"))
self.save
MessageBus.publish('/site/banner', banner)
end
def remove_banner!(user)
self.archetype = Archetype.default
self.add_moderator_post(user, I18n.t("archetypes.banner.message.remove"))
self.save
MessageBus.publish('/site/banner', nil)
end
def banner
post = self.posts.order(:post_number).limit(1).first
{
html: post.cooked,
url: self.url,
key: self.id
}
end
def self.starred_counts_per_day(sinceDaysAgo=30)

View file

@ -23,7 +23,8 @@ class CurrentUserSerializer < BasicUserSerializer
:redirected_to_top_reason,
:disable_jump_reply,
:custom_fields,
:muted_category_ids
:muted_category_ids,
:dismissed_banner_key
def include_site_flagged_posts_count?
object.staff?
@ -100,4 +101,8 @@ class CurrentUserSerializer < BasicUserSerializer
.pluck(:category_id)
end
def dismissed_banner_key
object.user_profile.dismissed_banner_key
end
end

View file

@ -19,7 +19,8 @@ class UserUpdater
]
PROFILE_ATTR = [
:location
:location,
:dismissed_banner_key
]
def initialize(actor, user)

View file

@ -166,6 +166,12 @@ en:
undo: "Undo"
revert: "Revert"
banner:
close: "Dismiss this banner."
read_more:
title: "Click to go to the topic."
text: "Read more"
choose_topic:
none_found: "No topics found."
title:

View file

@ -0,0 +1,5 @@
class AddDismissedBannerKeyToUserProfile < ActiveRecord::Migration
def change
add_column :user_profiles, :dismissed_banner_key, :integer, nullable: true
end
end

View file

@ -638,41 +638,44 @@ describe Topic do
end
end
describe "make_banner!" do
describe "banner" do
let(:topic) { Fabricate(:topic) }
let(:user) { topic.user }
let(:banner) { { html: "<p>BANNER</p>", url: topic.url, key: topic.id } }
before { topic.stubs(:banner).returns(banner) }
describe "make_banner!" do
it "changes the topic archetype to 'banner'" do
topic.expects(:add_moderator_post)
MessageBus.expects(:publish).with("/site/banner", banner)
topic.make_banner!(user)
topic.archetype.should == Archetype.banner
end
it "ensures only one banner topic at all time" do
banner_topic = Fabricate(:banner_topic)
Topic.where(archetype: Archetype.banner).count.should == 1
topic.make_banner!(user)
Topic.where(archetype: Archetype.banner).count.should == 1
end
before do
@topic = Fabricate(:topic)
@user = @topic.user
end
it "changes the topic archetype to 'banner'" do
@topic.expects(:add_moderator_post)
@topic.make_banner!(@user)
@topic.archetype.should == Archetype.banner
describe "remove_banner!" do
it "resets the topic archetype" do
topic.expects(:add_moderator_post)
MessageBus.expects(:publish).with("/site/banner", nil)
topic.remove_banner!(user)
topic.archetype.should == Archetype.default
end
end
it "ensures only one banner topic at all time" do
banner_topic = Fabricate(:banner_topic)
Topic.where(archetype: Archetype.banner).count.should == 1
@topic.make_banner!(@user)
Topic.where(archetype: Archetype.banner).count.should == 1
end
end
describe "remove_banner!" do
before do
@topic = Fabricate(:topic)
@user = @topic.user
end
it "resets the topic archetype" do
@topic.expects(:add_moderator_post)
@topic.remove_banner!(@user)
@topic.archetype.should == Archetype.default
end
end