diff --git a/app/assets/javascripts/discourse/components/discourse-banner.js.es6 b/app/assets/javascripts/discourse/components/discourse-banner.js.es6
new file mode 100644
index 00000000000..42da49aa90e
--- /dev/null
+++ b/app/assets/javascripts/discourse/components/discourse-banner.js.es6
@@ -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") });
+ }
+ }
+ }
+
+});
diff --git a/app/assets/javascripts/discourse/models/user.js b/app/assets/javascripts/discourse/models/user.js
index e178c38f7b8..277dc379c6c 100644
--- a/app/assets/javascripts/discourse/models/user.js
+++ b/app/assets/javascripts/discourse/models/user.js
@@ -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 }
+ });
}
});
diff --git a/app/assets/javascripts/discourse/templates/components/discourse-banner.js.handlebars b/app/assets/javascripts/discourse/templates/components/discourse-banner.js.handlebars
new file mode 100644
index 00000000000..ea8107c06e1
--- /dev/null
+++ b/app/assets/javascripts/discourse/templates/components/discourse-banner.js.handlebars
@@ -0,0 +1,9 @@
+{{#if visible}}
+
{{custom-html "top"}}
{{Discourse.globalNotice}}
+ {{discourse-banner user=currentUser banner=Discourse.banner}}
diff --git a/app/assets/javascripts/discourse/templates/topic.js.handlebars b/app/assets/javascripts/discourse/templates/topic.js.handlebars
index 8a7627a2d3a..d3c7c26dee2 100644
--- a/app/assets/javascripts/discourse/templates/topic.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/topic.js.handlebars
@@ -1,6 +1,7 @@
{{custom-html "top"}}
{{Discourse.globalNotice}}
+ {{discourse-banner user=currentUser banner=Discourse.banner}}
{{#if postStream.loaded}}
diff --git a/app/assets/stylesheets/common/components/banner.css.scss b/app/assets/stylesheets/common/components/banner.css.scss
new file mode 100644
index 00000000000..d7f50d8ff83
--- /dev/null
+++ b/app/assets/stylesheets/common/components/banner.css.scss
@@ -0,0 +1,14 @@
+// --------------------------------------------------
+// Banner
+// --------------------------------------------------
+
+#banner {
+ margin-bottom: 10px;
+ .close {
+ font-size: 25px !important;
+ margin-top: 0 !important;
+ }
+ .meta {
+ display: none;
+ }
+}
diff --git a/app/assets/stylesheets/desktop/modal.scss b/app/assets/stylesheets/desktop/modal.scss
index 01c2f729ab1..3ac8fc3b633 100644
--- a/app/assets/stylesheets/desktop/modal.scss
+++ b/app/assets/stylesheets/desktop/modal.scss
@@ -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;
}
}
diff --git a/app/assets/stylesheets/mobile/modal.scss b/app/assets/stylesheets/mobile/modal.scss
index bc6d084ed04..fa436db22e6 100644
--- a/app/assets/stylesheets/mobile/modal.scss
+++ b/app/assets/stylesheets/mobile/modal.scss
@@ -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 {
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 2da42748a20..ea08909f7e3 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -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={})
diff --git a/app/models/topic.rb b/app/models/topic.rb
index 0da1ad8a38a..23efb66a293 100644
--- a/app/models/topic.rb
+++ b/app/models/topic.rb
@@ -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)
diff --git a/app/serializers/current_user_serializer.rb b/app/serializers/current_user_serializer.rb
index d8b78a06cf6..1cdb4df6c40 100644
--- a/app/serializers/current_user_serializer.rb
+++ b/app/serializers/current_user_serializer.rb
@@ -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
diff --git a/app/services/user_updater.rb b/app/services/user_updater.rb
index eeaeb1adae8..f1f7a24412e 100644
--- a/app/services/user_updater.rb
+++ b/app/services/user_updater.rb
@@ -19,7 +19,8 @@ class UserUpdater
]
PROFILE_ATTR = [
- :location
+ :location,
+ :dismissed_banner_key
]
def initialize(actor, user)
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 6ebca8c8814..9be4a236d16 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -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:
diff --git a/db/migrate/20140618163511_add_dismissed_banner_key_to_user_profile.rb b/db/migrate/20140618163511_add_dismissed_banner_key_to_user_profile.rb
new file mode 100644
index 00000000000..f84c1f9a928
--- /dev/null
+++ b/db/migrate/20140618163511_add_dismissed_banner_key_to_user_profile.rb
@@ -0,0 +1,5 @@
+class AddDismissedBannerKeyToUserProfile < ActiveRecord::Migration
+ def change
+ add_column :user_profiles, :dismissed_banner_key, :integer, nullable: true
+ end
+end
diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb
index aea4dad51ca..273a553ba02 100644
--- a/spec/models/topic_spec.rb
+++ b/spec/models/topic_spec.rb
@@ -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: "
BANNER
", 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