Commit 45c0df82cf8ce0fa3d49810da8f225415f7da412
Committed by
Rodrigo Souto
1 parent
c95e0983
Exists in
master
and in
12 other branches
Add feature: Article Followers
- Every article can be followed so the user can receive notifications without having to comment on it Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com> Signed-off-by: Marcos Ramos <ms.ramos@outlook.com> Signed-off-by: Gustavo Coelho <gust.rod.coelho@gmail.com> Signed-off-by: Joenio Costa <joenio@colivre.coop.br> Signed-off-by: Carlos Purificacao <carloseugenio@gmail.com> Signed-off-by: Victor Costa <vfcosta@gmail.com> Signed-off-by: Caio SBA <caio@colivre.coop.br> Signed-off-by: Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> Signed-off-by: Michel Felipe de Oliveira Ferreira <michel.ferreira@serpro.gov.br> Signed-off-by: Evandro Jr <evandrojr@gmail.com>
Showing
21 changed files
with
269 additions
and
43 deletions
Show diff stats
app/controllers/public/profile_controller.rb
@@ -155,6 +155,18 @@ class ProfileController < PublicController | @@ -155,6 +155,18 @@ class ProfileController < PublicController | ||
155 | end | 155 | end |
156 | end | 156 | end |
157 | 157 | ||
158 | + def follow_article | ||
159 | + article = profile.environment.articles.find params[:article_id] | ||
160 | + article.person_followers << user | ||
161 | + redirect_to article.url | ||
162 | + end | ||
163 | + | ||
164 | + def unfollow_article | ||
165 | + article = profile.environment.articles.find params[:article_id] | ||
166 | + article.person_followers.delete(user) | ||
167 | + redirect_to article.url | ||
168 | + end | ||
169 | + | ||
158 | def unblock | 170 | def unblock |
159 | if current_user.person.is_admin?(profile.environment) | 171 | if current_user.person.is_admin?(profile.environment) |
160 | profile.unblock | 172 | profile.unblock |
app/helpers/article_helper.rb
@@ -155,4 +155,30 @@ module ArticleHelper | @@ -155,4 +155,30 @@ module ArticleHelper | ||
155 | _('Edit') | 155 | _('Edit') |
156 | end | 156 | end |
157 | 157 | ||
158 | + def follow_button_text(article) | ||
159 | + if article.event? | ||
160 | + _('Attend') | ||
161 | + else | ||
162 | + _('Follow') | ||
163 | + end | ||
164 | + end | ||
165 | + | ||
166 | + def unfollow_button_text(article) | ||
167 | + if article.event? | ||
168 | + _('Unattend') | ||
169 | + else | ||
170 | + _('Unfollow') | ||
171 | + end | ||
172 | + end | ||
173 | + | ||
174 | + def following_button(page, user) | ||
175 | + if !user.blank? and user != page.author | ||
176 | + if page.is_followed_by? user | ||
177 | + button :cancel, unfollow_button_text(page), {:controller => 'profile', :action => 'unfollow_article', :article_id => page.id} | ||
178 | + else | ||
179 | + button :add, follow_button_text(page), {:controller => 'profile', :action => 'follow_article', :article_id => page.id} | ||
180 | + end | ||
181 | + end | ||
182 | + end | ||
183 | + | ||
158 | end | 184 | end |
app/models/article.rb
@@ -9,7 +9,7 @@ class Article < ActiveRecord::Base | @@ -9,7 +9,7 @@ class Article < ActiveRecord::Base | ||
9 | :highlighted, :notify_comments, :display_hits, :slug, | 9 | :highlighted, :notify_comments, :display_hits, :slug, |
10 | :external_feed_builder, :display_versions, :external_link, | 10 | :external_feed_builder, :display_versions, :external_link, |
11 | :image_builder, :show_to_followers, | 11 | :image_builder, :show_to_followers, |
12 | - :author, :display_preview, :published_at | 12 | + :author, :display_preview, :published_at, :person_followers |
13 | 13 | ||
14 | acts_as_having_image | 14 | acts_as_having_image |
15 | 15 | ||
@@ -77,8 +77,15 @@ class Article < ActiveRecord::Base | @@ -77,8 +77,15 @@ class Article < ActiveRecord::Base | ||
77 | belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' | 77 | belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' |
78 | belongs_to :created_by, :class_name => 'Person', :foreign_key => 'created_by_id' | 78 | belongs_to :created_by, :class_name => 'Person', :foreign_key => 'created_by_id' |
79 | 79 | ||
80 | +<<<<<<< 6fa2f904983046ed816efe293ba9dcad19a67a4b | ||
80 | has_many :comments, :class_name => 'Comment', :as => 'source', :dependent => :destroy, :order => 'created_at asc' | 81 | has_many :comments, :class_name => 'Comment', :as => 'source', :dependent => :destroy, :order => 'created_at asc' |
81 | 82 | ||
83 | +======= | ||
84 | + has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc' | ||
85 | + has_many :article_followers, :dependent => :destroy | ||
86 | + has_many :person_followers, :class_name => 'Person', :through => :article_followers, :source => :person | ||
87 | + has_many :person_followers_emails, :class_name => 'User', :through => :person_followers, :source => :user, :select => :email | ||
88 | +>>>>>>> Add feature: Article Followers | ||
82 | has_many :article_categorizations, -> { where 'articles_categories.virtual = ?', false } | 89 | has_many :article_categorizations, -> { where 'articles_categories.virtual = ?', false } |
83 | has_many :categories, :through => :article_categorizations | 90 | has_many :categories, :through => :article_categorizations |
84 | 91 | ||
@@ -91,7 +98,6 @@ class Article < ActiveRecord::Base | @@ -91,7 +98,6 @@ class Article < ActiveRecord::Base | ||
91 | settings_items :author_name, :type => :string, :default => "" | 98 | settings_items :author_name, :type => :string, :default => "" |
92 | settings_items :allow_members_to_edit, :type => :boolean, :default => false | 99 | settings_items :allow_members_to_edit, :type => :boolean, :default => false |
93 | settings_items :moderate_comments, :type => :boolean, :default => false | 100 | settings_items :moderate_comments, :type => :boolean, :default => false |
94 | - settings_items :followers, :type => Array, :default => [] | ||
95 | has_and_belongs_to_many :article_privacy_exceptions, :class_name => 'Person', :join_table => 'article_privacy_exceptions' | 101 | has_and_belongs_to_many :article_privacy_exceptions, :class_name => 'Person', :join_table => 'article_privacy_exceptions' |
96 | 102 | ||
97 | belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id' | 103 | belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id' |
@@ -167,7 +173,6 @@ class Article < ActiveRecord::Base | @@ -167,7 +173,6 @@ class Article < ActiveRecord::Base | ||
167 | end | 173 | end |
168 | end | 174 | end |
169 | 175 | ||
170 | - | ||
171 | def is_trackable? | 176 | def is_trackable? |
172 | self.published? && self.notifiable? && self.advertise? && self.profile.public_profile | 177 | self.published? && self.notifiable? && self.advertise? && self.profile.public_profile |
173 | end | 178 | end |
@@ -368,6 +373,10 @@ class Article < ActiveRecord::Base | @@ -368,6 +373,10 @@ class Article < ActiveRecord::Base | ||
368 | self.parent and self.parent.forum? | 373 | self.parent and self.parent.forum? |
369 | end | 374 | end |
370 | 375 | ||
376 | + def person_followers_email_list | ||
377 | + person_followers_emails.map{|p|p.email} | ||
378 | + end | ||
379 | + | ||
371 | def info_from_last_update | 380 | def info_from_last_update |
372 | last_comment = comments.last | 381 | last_comment = comments.last |
373 | if last_comment | 382 | if last_comment |
@@ -407,6 +416,10 @@ class Article < ActiveRecord::Base | @@ -407,6 +416,10 @@ class Article < ActiveRecord::Base | ||
407 | (not self.uploaded_file? and self.mime_type != 'text/html') | 416 | (not self.uploaded_file? and self.mime_type != 'text/html') |
408 | end | 417 | end |
409 | 418 | ||
419 | + def is_followed_by?(user) | ||
420 | + self.person_followers.include? user | ||
421 | + end | ||
422 | + | ||
410 | def download_headers | 423 | def download_headers |
411 | {} | 424 | {} |
412 | end | 425 | end |
app/models/comment.rb
@@ -6,13 +6,14 @@ class Comment < ActiveRecord::Base | @@ -6,13 +6,14 @@ class Comment < ActiveRecord::Base | ||
6 | :body => {:label => _('Content'), :weight => 2}, | 6 | :body => {:label => _('Content'), :weight => 2}, |
7 | } | 7 | } |
8 | 8 | ||
9 | - attr_accessible :body, :author, :name, :email, :title, :reply_of_id, :source | 9 | + attr_accessible :body, :author, :name, :email, :title, :reply_of_id, :source, :follow_article |
10 | 10 | ||
11 | validates_presence_of :body | 11 | validates_presence_of :body |
12 | 12 | ||
13 | belongs_to :source, :counter_cache => true, :polymorphic => true | 13 | belongs_to :source, :counter_cache => true, :polymorphic => true |
14 | alias :article :source | 14 | alias :article :source |
15 | alias :article= :source= | 15 | alias :article= :source= |
16 | + attr_accessor :follow_article | ||
16 | 17 | ||
17 | belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id' | 18 | belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id' |
18 | has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy | 19 | has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy |
@@ -100,10 +101,9 @@ class Comment < ActiveRecord::Base | @@ -100,10 +101,9 @@ class Comment < ActiveRecord::Base | ||
100 | 101 | ||
101 | after_create :new_follower | 102 | after_create :new_follower |
102 | def new_follower | 103 | def new_follower |
103 | - if source.kind_of?(Article) | ||
104 | - article.followers += [author_email] | ||
105 | - article.followers -= article.profile.notification_emails | ||
106 | - article.followers.uniq! | 104 | + if source.kind_of?(Article) and !author.nil? and @follow_article |
105 | + article.person_followers += [author] | ||
106 | + article.person_followers.uniq! | ||
107 | article.save | 107 | article.save |
108 | end | 108 | end |
109 | end | 109 | end |
@@ -145,7 +145,7 @@ class Comment < ActiveRecord::Base | @@ -145,7 +145,7 @@ class Comment < ActiveRecord::Base | ||
145 | if !notification_emails.empty? | 145 | if !notification_emails.empty? |
146 | CommentNotifier.notification(self).deliver | 146 | CommentNotifier.notification(self).deliver |
147 | end | 147 | end |
148 | - emails = article.followers - [author_email] | 148 | + emails = article.person_followers_email_list - [author_email] |
149 | if !emails.empty? | 149 | if !emails.empty? |
150 | CommentNotifier.mail_to_followers(self, emails).deliver | 150 | CommentNotifier.mail_to_followers(self, emails).deliver |
151 | end | 151 | end |
app/models/person.rb
1 | # A person is the profile of an user holding all relationships with the rest of the system | 1 | # A person is the profile of an user holding all relationships with the rest of the system |
2 | class Person < Profile | 2 | class Person < Profile |
3 | 3 | ||
4 | - attr_accessible :organization, :contact_information, :sex, :birth_date, :cell_phone, :comercial_phone, :jabber_id, :personal_website, :nationality, :address_reference, :district, :schooling, :schooling_status, :formation, :custom_formation, :area_of_study, :custom_area_of_study, :professional_activity, :organization_website | 4 | + attr_accessible :organization, :contact_information, :sex, :birth_date, :cell_phone, :comercial_phone, :jabber_id, :personal_website, :nationality, :address_reference, :district, :schooling, :schooling_status, :formation, :custom_formation, :area_of_study, :custom_area_of_study, :professional_activity, :organization_website, :following_articles |
5 | 5 | ||
6 | SEARCH_FILTERS = { | 6 | SEARCH_FILTERS = { |
7 | :order => %w[more_recent more_popular more_active], | 7 | :order => %w[more_recent more_popular more_active], |
@@ -84,7 +84,8 @@ class Person < Profile | @@ -84,7 +84,8 @@ class Person < Profile | ||
84 | end | 84 | end |
85 | 85 | ||
86 | has_many :comments, :foreign_key => :author_id | 86 | has_many :comments, :foreign_key => :author_id |
87 | - | 87 | + has_many :article_followers, :dependent => :destroy |
88 | + has_many :following_articles, :class_name => 'Article', :through => :article_followers, :source => :article | ||
88 | has_many :friendships, :dependent => :destroy | 89 | has_many :friendships, :dependent => :destroy |
89 | has_many :friends, :class_name => 'Person', :through => :friendships | 90 | has_many :friends, :class_name => 'Person', :through => :friendships |
90 | 91 |
app/views/comment/_comment_form.html.erb
@@ -77,6 +77,10 @@ function check_captcha(button, confirm_action) { | @@ -77,6 +77,10 @@ function check_captcha(button, confirm_action) { | ||
77 | <%= labelled_form_field(_('Title'), f.text_field(:title)) %> | 77 | <%= labelled_form_field(_('Title'), f.text_field(:title)) %> |
78 | <%= required labelled_form_field(_('Enter your comment'), f.text_area(:body, :rows => 5)) %> | 78 | <%= required labelled_form_field(_('Enter your comment'), f.text_area(:body, :rows => 5)) %> |
79 | 79 | ||
80 | + <% if logged_in? %> | ||
81 | + <%= labelled_form_field check_box(:comment, :follow_article, {}, true, false) + _('Follow this article'), '' %> | ||
82 | + <% end%> | ||
83 | + | ||
80 | <%= hidden_field_tag(:confirm, 'false') %> | 84 | <%= hidden_field_tag(:confirm, 'false') %> |
81 | <%= hidden_field_tag(:view, params[:view])%> | 85 | <%= hidden_field_tag(:view, params[:view])%> |
82 | <%= f.hidden_field(:reply_of_id) %> | 86 | <%= f.hidden_field(:reply_of_id) %> |
app/views/content_viewer/_article_toolbar.html.erb
@@ -55,6 +55,8 @@ | @@ -55,6 +55,8 @@ | ||
55 | <%= button plugin_button[:icon], plugin_button[:title], plugin_button[:url], plugin_button[:html_options] %> | 55 | <%= button plugin_button[:icon], plugin_button[:title], plugin_button[:url], plugin_button[:html_options] %> |
56 | <% end %> | 56 | <% end %> |
57 | 57 | ||
58 | + <%= following_button @page, user %> | ||
59 | + | ||
58 | <%= report_abuse(profile, :link, @page) %> | 60 | <%= report_abuse(profile, :link, @page) %> |
59 | 61 | ||
60 | </div> | 62 | </div> |
app/views/content_viewer/_publishing_info.html.erb
@@ -10,6 +10,24 @@ | @@ -10,6 +10,24 @@ | ||
10 | <%= (" - %s") % link_to_comments(@page)%> | 10 | <%= (" - %s") % link_to_comments(@page)%> |
11 | </span> | 11 | </span> |
12 | <% end %> | 12 | <% end %> |
13 | + | ||
14 | +<span class="followers-count"> | ||
15 | +| | ||
16 | +<% if @page.event? %> | ||
17 | + <% if @page.person_followers.size > 0 %> | ||
18 | + <%= _("%s will attend this event.") % [ pluralize(@page.person_followers.size, _("person"))]%> | ||
19 | + <% else %> | ||
20 | + <%= _("No one attending this event yet.") %> | ||
21 | + <% end %> | ||
22 | +<% else %> | ||
23 | + <% if @page.person_followers.size > 0 %> | ||
24 | + <%= _("%s following this article.") % [ pluralize(@page.person_followers.size, _("person"))]%> | ||
25 | + <% else %> | ||
26 | + <%= _("No one following this article yet.") %> | ||
27 | + <% end %> | ||
28 | +<% end %> | ||
29 | +</span> | ||
30 | + | ||
13 | </span> | 31 | </span> |
14 | 32 | ||
15 | <% if @page.display_hits? || @page.license.present? %> | 33 | <% if @page.display_hits? || @page.license.present? %> |
db/migrate/20151210230319_add_followers_count_to_article.rb
0 → 100644
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +class AddFollowersCountToArticle < ActiveRecord::Migration | ||
2 | + | ||
3 | + def self.up | ||
4 | + add_column :articles, :followers_count, :integer, :default => 0 | ||
5 | + | ||
6 | + execute "update articles set followers_count = (select count(*) from article_followers where article_followers.article_id = articles.id)" | ||
7 | + end | ||
8 | + | ||
9 | + def self.down | ||
10 | + remove_column :articles, :followers_count | ||
11 | + end | ||
12 | + | ||
13 | +end |
db/schema.rb
@@ -51,6 +51,18 @@ ActiveRecord::Schema.define(version: 20160202142247) do | @@ -51,6 +51,18 @@ ActiveRecord::Schema.define(version: 20160202142247) do | ||
51 | add_index "action_tracker_notifications", ["profile_id", "action_tracker_id"], name: "index_action_tracker_notif_on_prof_id_act_tracker_id", unique: true, using: :btree | 51 | add_index "action_tracker_notifications", ["profile_id", "action_tracker_id"], name: "index_action_tracker_notif_on_prof_id_act_tracker_id", unique: true, using: :btree |
52 | add_index "action_tracker_notifications", ["profile_id"], name: "index_action_tracker_notifications_on_profile_id", using: :btree | 52 | add_index "action_tracker_notifications", ["profile_id"], name: "index_action_tracker_notifications_on_profile_id", using: :btree |
53 | 53 | ||
54 | + create_table "article_followers", force: :cascade do |t| | ||
55 | + t.integer "person_id", null: false | ||
56 | + t.integer "article_id", null: false | ||
57 | + t.datetime "since" | ||
58 | + t.datetime "created_at" | ||
59 | + t.datetime "updated_at" | ||
60 | + end | ||
61 | + | ||
62 | + add_index "article_followers", ["article_id"], name: "index_article_followers_on_article_id", using: :btree | ||
63 | + add_index "article_followers", ["person_id", "article_id"], name: "index_article_followers_on_person_id_and_article_id", unique: true, using: :btree | ||
64 | + add_index "article_followers", ["person_id"], name: "index_article_followers_on_person_id", using: :btree | ||
65 | + | ||
54 | create_table "article_privacy_exceptions", id: false, force: :cascade do |t| | 66 | create_table "article_privacy_exceptions", id: false, force: :cascade do |t| |
55 | t.integer "article_id" | 67 | t.integer "article_id" |
56 | t.integer "person_id" | 68 | t.integer "person_id" |
@@ -101,6 +113,7 @@ ActiveRecord::Schema.define(version: 20160202142247) do | @@ -101,6 +113,7 @@ ActiveRecord::Schema.define(version: 20160202142247) do | ||
101 | t.integer "spam_comments_count", default: 0 | 113 | t.integer "spam_comments_count", default: 0 |
102 | t.integer "author_id" | 114 | t.integer "author_id" |
103 | t.integer "created_by_id" | 115 | t.integer "created_by_id" |
116 | + t.integer "followers_count" | ||
104 | end | 117 | end |
105 | 118 | ||
106 | add_index "article_versions", ["article_id"], name: "index_article_versions_on_article_id", using: :btree | 119 | add_index "article_versions", ["article_id"], name: "index_article_versions_on_article_id", using: :btree |
@@ -154,6 +167,7 @@ ActiveRecord::Schema.define(version: 20160202142247) do | @@ -154,6 +167,7 @@ ActiveRecord::Schema.define(version: 20160202142247) do | ||
154 | t.integer "author_id" | 167 | t.integer "author_id" |
155 | t.integer "created_by_id" | 168 | t.integer "created_by_id" |
156 | t.boolean "show_to_followers", default: true | 169 | t.boolean "show_to_followers", default: true |
170 | + t.integer "followers_count", default: 0 | ||
157 | end | 171 | end |
158 | 172 | ||
159 | add_index "articles", ["comments_count"], name: "index_articles_on_comments_count", using: :btree | 173 | add_index "articles", ["comments_count"], name: "index_articles_on_comments_count", using: :btree |
lib/noosfero/api/entities.rb
@@ -148,6 +148,7 @@ module Noosfero | @@ -148,6 +148,7 @@ module Noosfero | ||
148 | expose :children_count | 148 | expose :children_count |
149 | expose :slug, :documentation => {:type => "String", :desc => "Trimmed and parsed name of a article"} | 149 | expose :slug, :documentation => {:type => "String", :desc => "Trimmed and parsed name of a article"} |
150 | expose :path | 150 | expose :path |
151 | + expose :followers_count | ||
151 | end | 152 | end |
152 | 153 | ||
153 | class Article < ArticleBase | 154 | class Article < ArticleBase |
lib/noosfero/api/v1/articles.rb
@@ -112,6 +112,37 @@ module Noosfero | @@ -112,6 +112,37 @@ module Noosfero | ||
112 | {:vote => vote.save} | 112 | {:vote => vote.save} |
113 | end | 113 | end |
114 | 114 | ||
115 | + desc "Returns the total followers for the article" do | ||
116 | + detail 'Get the followers of a specific article by id' | ||
117 | + failure [[403, 'Forbidden']] | ||
118 | + named 'ArticleFollowers' | ||
119 | + end | ||
120 | + get ':id/followers' do | ||
121 | + article = find_article(environment.articles, params[:id]) | ||
122 | + total = article.person_followers.count | ||
123 | + {:total_followers => total} | ||
124 | + end | ||
125 | + | ||
126 | + desc "Add a follower for the article" do | ||
127 | + detail 'Add the current user identified by private token, like a follower of a article' | ||
128 | + params Noosfero::API::Entities::UserLogin.documentation | ||
129 | + failure [[401, 'Unauthorized']] | ||
130 | + named 'ArticleFollow' | ||
131 | + end | ||
132 | + post ':id/follow' do | ||
133 | + authenticate! | ||
134 | + article = find_article(environment.articles, params[:id]) | ||
135 | + if article.article_followers.exists?(:person_id => current_person.id) | ||
136 | + {:success => false, :already_follow => true} | ||
137 | + else | ||
138 | + article_follower = ArticleFollower.new | ||
139 | + article_follower.article = article | ||
140 | + article_follower.person = current_person | ||
141 | + article_follower.save! | ||
142 | + {:success => true} | ||
143 | + end | ||
144 | + end | ||
145 | + | ||
115 | desc 'Return the children of a article identified by id' do | 146 | desc 'Return the children of a article identified by id' do |
116 | detail 'Get all children articles of a specific article' | 147 | detail 'Get all children articles of a specific article' |
117 | params Noosfero::API::Entities::Article.documentation | 148 | params Noosfero::API::Entities::Article.documentation |
test/functional/comment_controller_test.rb
@@ -387,10 +387,26 @@ class CommentControllerTest < ActionController::TestCase | @@ -387,10 +387,26 @@ class CommentControllerTest < ActionController::TestCase | ||
387 | Article.record_timestamps = true | 387 | Article.record_timestamps = true |
388 | 388 | ||
389 | login_as @profile.identifier | 389 | login_as @profile.identifier |
390 | - xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => { :title => 'crap!', :body => 'I think that this article is crap' }, :confirm => 'true' | 390 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => {:title => 'crap!', :body => 'I think that this article is crap' }, :confirm => 'true' |
391 | assert_not_equal yesterday, page.reload.updated_at | 391 | assert_not_equal yesterday, page.reload.updated_at |
392 | end | 392 | end |
393 | 393 | ||
394 | + should 'follow article when commenting' do | ||
395 | + page = create(Article, :profile => profile, :name => 'myarticle', :body => 'the body of the text') | ||
396 | + login_as @profile.identifier | ||
397 | + | ||
398 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => {:title => 'crap!', :body => 'I think that this article is crap', :follow_article => true}, :confirm => 'true' | ||
399 | + assert_includes page.person_followers, @profile | ||
400 | + end | ||
401 | + | ||
402 | + should 'not follow article when commenting' do | ||
403 | + page = create(Article, :profile => profile, :name => 'myarticle', :body => 'the body of the text') | ||
404 | + login_as @profile.identifier | ||
405 | + | ||
406 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => {:title => 'crap!', :body => 'I think that this article is crap', :follow_article => false }, :confirm => 'true' | ||
407 | + assert_not_includes page.person_followers, @profile | ||
408 | + end | ||
409 | + | ||
394 | should 'be able to mark comments as spam' do | 410 | should 'be able to mark comments as spam' do |
395 | login_as profile.identifier | 411 | login_as profile.identifier |
396 | article = fast_create(Article, :profile_id => profile.id) | 412 | article = fast_create(Article, :profile_id => profile.id) |
test/functional/content_viewer_controller_test.rb
@@ -1278,18 +1278,6 @@ class ContentViewerControllerTest < ActionController::TestCase | @@ -1278,18 +1278,6 @@ class ContentViewerControllerTest < ActionController::TestCase | ||
1278 | assert_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :title => 'This button is expired.', :class => 'button with-text icon-edit disabled' } } | 1278 | assert_tag :tag => 'div', :attributes => { :id => 'article-actions' }, :descendant => { :tag => 'a', :attributes => { :title => 'This button is expired.', :class => 'button with-text icon-edit disabled' } } |
1279 | end | 1279 | end |
1280 | 1280 | ||
1281 | - should 'remove email from article followers when unfollow' do | ||
1282 | - profile = create_user('testuser').person | ||
1283 | - follower_email = 'john@doe.br' | ||
1284 | - article = profile.articles.create(:name => 'test') | ||
1285 | - article.followers = [follower_email] | ||
1286 | - article.save | ||
1287 | - | ||
1288 | - assert_includes Article.find(article.id).followers, follower_email | ||
1289 | - post :view_page, :profile => profile.identifier, :page => [article.name], :unfollow => 'commit', :email => follower_email | ||
1290 | - assert_not_includes Article.find(article.id).followers, follower_email | ||
1291 | - end | ||
1292 | - | ||
1293 | should 'not display comments marked as spam' do | 1281 | should 'not display comments marked as spam' do |
1294 | article = fast_create(Article, :profile_id => profile.id) | 1282 | article = fast_create(Article, :profile_id => profile.id) |
1295 | ham = fast_create(Comment, :source_id => article.id, :source_type => 'Article', :title => 'some content') | 1283 | ham = fast_create(Comment, :source_id => article.id, :source_type => 'Article', :title => 'some content') |
test/functional/profile_controller_test.rb
@@ -18,6 +18,19 @@ class ProfileControllerTest < ActionController::TestCase | @@ -18,6 +18,19 @@ class ProfileControllerTest < ActionController::TestCase | ||
18 | assert assigns(:friends) | 18 | assert assigns(:friends) |
19 | end | 19 | end |
20 | 20 | ||
21 | + should 'remove person from article followers when unfollow' do | ||
22 | + profile = create_user('testuser').person | ||
23 | + follower = create_user('follower').person | ||
24 | + article = profile.articles.create(:name => 'test') | ||
25 | + article.person_followers = [follower] | ||
26 | + article.save | ||
27 | + login_as('follower') | ||
28 | + article.reload | ||
29 | + assert_includes Article.find(article.id).person_followers, follower | ||
30 | + post :unfollow_article, :article_id => article.id | ||
31 | + assert_not_includes Article.find(article.id).person_followers, follower | ||
32 | + end | ||
33 | + | ||
21 | should 'point to manage friends in user is seeing his own friends' do | 34 | should 'point to manage friends in user is seeing his own friends' do |
22 | login_as('testuser') | 35 | login_as('testuser') |
23 | get :friends | 36 | get :friends |
@@ -1338,6 +1351,24 @@ class ProfileControllerTest < ActionController::TestCase | @@ -1338,6 +1351,24 @@ class ProfileControllerTest < ActionController::TestCase | ||
1338 | assert_equivalent [scrap,activity], assigns(:activities).map(&:activity) | 1351 | assert_equivalent [scrap,activity], assigns(:activities).map(&:activity) |
1339 | end | 1352 | end |
1340 | 1353 | ||
1354 | + should "follow an article" do | ||
1355 | + article = TinyMceArticle.create!(:profile => profile, :name => 'An article about free software') | ||
1356 | + login_as(@profile.identifier) | ||
1357 | + post :follow_article, :profile => profile.identifier, :article_id => article.id | ||
1358 | + assert_includes article.person_followers, @profile | ||
1359 | + end | ||
1360 | + | ||
1361 | + should "unfollow an article" do | ||
1362 | + article = TinyMceArticle.create!(:profile => profile, :name => 'An article about free software') | ||
1363 | + article.person_followers << @profile | ||
1364 | + article.save! | ||
1365 | + assert_includes article.person_followers, @profile | ||
1366 | + | ||
1367 | + login_as(@profile.identifier) | ||
1368 | + post :unfollow_article, :profile => profile.identifier, :article_id => article.id | ||
1369 | + assert_not_includes article.person_followers, @profile | ||
1370 | + end | ||
1371 | + | ||
1341 | should "be logged in to leave comment on an activity" do | 1372 | should "be logged in to leave comment on an activity" do |
1342 | article = TinyMceArticle.create!(:profile => profile, :name => 'An article about free software') | 1373 | article = TinyMceArticle.create!(:profile => profile, :name => 'An article about free software') |
1343 | activity = ActionTracker::Record.last | 1374 | activity = ActionTracker::Record.last |
test/unit/api/articles_test.rb
@@ -39,6 +39,41 @@ class ArticlesTest < ActiveSupport::TestCase | @@ -39,6 +39,41 @@ class ArticlesTest < ActiveSupport::TestCase | ||
39 | assert_equal 403, last_response.status | 39 | assert_equal 403, last_response.status |
40 | end | 40 | end |
41 | 41 | ||
42 | + should 'follow a article identified by id' do | ||
43 | + article = fast_create(Article, :profile_id => @person.id, :name => "Some thing") | ||
44 | + post "/api/v1/articles/#{article.id}/follow?#{params.to_query}" | ||
45 | + json = JSON.parse(last_response.body) | ||
46 | + | ||
47 | + assert_not_equal 401, last_response.status | ||
48 | + assert_equal true, json['success'] | ||
49 | + end | ||
50 | + | ||
51 | + should 'return the followers count of an article' do | ||
52 | + article = fast_create(Article, :profile_id => @person.id, :name => "Some thing") | ||
53 | + article.person_followers << @person | ||
54 | + | ||
55 | + get "/api/v1/articles/#{article.id}?#{params.to_query}" | ||
56 | + json = JSON.parse(last_response.body) | ||
57 | + | ||
58 | + assert_equal 200, last_response.status | ||
59 | + assert_equal 1, json['article']['followers_count'] | ||
60 | + end | ||
61 | + | ||
62 | + should 'return the followers of a article identified by id' do | ||
63 | + article = fast_create(Article, :profile_id => @person.id, :name => "Some thing") | ||
64 | + | ||
65 | + article_follower = ArticleFollower.new | ||
66 | + article_follower.article = article | ||
67 | + article_follower.person = @person | ||
68 | + article_follower.save! | ||
69 | + | ||
70 | + get "/api/v1/articles/#{article.id}/followers?#{params.to_query}" | ||
71 | + json = JSON.parse(last_response.body) | ||
72 | + | ||
73 | + assert_equal 200, last_response.status | ||
74 | + assert_equal 1, json['total_followers'] | ||
75 | + end | ||
76 | + | ||
42 | should 'list article children' do | 77 | should 'list article children' do |
43 | article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") | 78 | article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") |
44 | child1 = fast_create(Article, :parent_id => article.id, :profile_id => user.person.id, :name => "Some thing") | 79 | child1 = fast_create(Article, :parent_id => article.id, :profile_id => user.person.id, :name => "Some thing") |
test/unit/article_test.rb
@@ -22,6 +22,21 @@ class ArticleTest < ActiveSupport::TestCase | @@ -22,6 +22,21 @@ class ArticleTest < ActiveSupport::TestCase | ||
22 | refute a.errors[:profile_id.to_s].present? | 22 | refute a.errors[:profile_id.to_s].present? |
23 | end | 23 | end |
24 | 24 | ||
25 | + should 'keep unique users in list of followers' do | ||
26 | + person1 = create_user('article_owner').person | ||
27 | + person2 = create_user('article_follower').person | ||
28 | + | ||
29 | + article = fast_create(Article, :profile_id => person1.id) | ||
30 | + | ||
31 | + article.person_followers=[person2] | ||
32 | + article.save | ||
33 | + article.reload | ||
34 | + article.person_followers=[person2] | ||
35 | + article.save | ||
36 | + | ||
37 | + assert_equal 1, article.reload.person_followers.size | ||
38 | + end | ||
39 | + | ||
25 | should 'require value for name' do | 40 | should 'require value for name' do |
26 | a = Article.new | 41 | a = Article.new |
27 | a.valid? | 42 | a.valid? |
@@ -1700,7 +1715,7 @@ class ArticleTest < ActiveSupport::TestCase | @@ -1700,7 +1715,7 @@ class ArticleTest < ActiveSupport::TestCase | ||
1700 | 1715 | ||
1701 | should 'has a empty list of followers by default' do | 1716 | should 'has a empty list of followers by default' do |
1702 | a = Article.new | 1717 | a = Article.new |
1703 | - assert_equal [], a.followers | 1718 | + assert_equal [], a.person_followers |
1704 | end | 1719 | end |
1705 | 1720 | ||
1706 | should 'get first image from lead' do | 1721 | should 'get first image from lead' do |
test/unit/comment_notifier_test.rb
@@ -60,7 +60,7 @@ class CommentNotifierTest < ActiveSupport::TestCase | @@ -60,7 +60,7 @@ class CommentNotifierTest < ActiveSupport::TestCase | ||
60 | should "deliver mail to followers" do | 60 | should "deliver mail to followers" do |
61 | author = create_user('follower_author').person | 61 | author = create_user('follower_author').person |
62 | follower = create_user('follower').person | 62 | follower = create_user('follower').person |
63 | - @article.followers += [follower.email] | 63 | + @article.person_followers += [follower] |
64 | @article.save! | 64 | @article.save! |
65 | create_comment_and_notify(:source => @article, :author => author, :title => 'comment title', :body => 'comment body') | 65 | create_comment_and_notify(:source => @article, :author => author, :title => 'comment title', :body => 'comment body') |
66 | assert_includes ActionMailer::Base.deliveries.map(&:bcc).flatten, follower.email | 66 | assert_includes ActionMailer::Base.deliveries.map(&:bcc).flatten, follower.email |
test/unit/comment_test.rb
@@ -328,34 +328,27 @@ class CommentTest < ActiveSupport::TestCase | @@ -328,34 +328,27 @@ class CommentTest < ActiveSupport::TestCase | ||
328 | assert c.rejected? | 328 | assert c.rejected? |
329 | end | 329 | end |
330 | 330 | ||
331 | - should 'subscribe user as follower of an article on new comment' do | 331 | + should 'not subscribe user as follower of an article automatically on new comment' do |
332 | owner = create_user('owner_of_article').person | 332 | owner = create_user('owner_of_article').person |
333 | person = create_user('follower').person | 333 | person = create_user('follower').person |
334 | article = fast_create(Article, :profile_id => owner.id) | 334 | article = fast_create(Article, :profile_id => owner.id) |
335 | - assert_not_includes article.followers, person.email | 335 | + assert_not_includes article.person_followers, person |
336 | create(Comment, :source => article, :author => person, :title => 'new comment', :body => 'new comment') | 336 | create(Comment, :source => article, :author => person, :title => 'new comment', :body => 'new comment') |
337 | - assert_includes article.reload.followers, person.email | 337 | + assert_not_includes article.reload.person_followers, person |
338 | end | 338 | end |
339 | 339 | ||
340 | - should 'subscribe guest user as follower of an article on new comment' do | 340 | + should 'not subscribe guest user as follower of an article on new comment' do |
341 | article = fast_create(Article, :profile_id => create_user('article_owner').person.id) | 341 | article = fast_create(Article, :profile_id => create_user('article_owner').person.id) |
342 | - assert_not_includes article.followers, 'follower@example.com' | 342 | + old_num_followers = article.reload.person_followers.size |
343 | create(Comment, :source => article, :name => 'follower', :email => 'follower@example.com', :title => 'new comment', :body => 'new comment') | 343 | create(Comment, :source => article, :name => 'follower', :email => 'follower@example.com', :title => 'new comment', :body => 'new comment') |
344 | - assert_includes article.reload.followers, 'follower@example.com' | ||
345 | - end | ||
346 | - | ||
347 | - should 'keep unique emails in list of followers' do | ||
348 | - article = fast_create(Article, :profile_id => create_user('article_owner').person.id) | ||
349 | - create(Comment, :source => article, :name => 'follower one', :email => 'follower@example.com', :title => 'new comment', :body => 'new comment') | ||
350 | - create(Comment, :source => article, :name => 'follower two', :email => 'follower@example.com', :title => 'another comment', :body => 'new comment') | ||
351 | - assert_equal 1, article.reload.followers.select{|v| v == 'follower@example.com'}.count | 344 | + assert_equal old_num_followers, article.reload.person_followers.size |
352 | end | 345 | end |
353 | 346 | ||
354 | should 'not subscribe owner as follower of an article on new comment' do | 347 | should 'not subscribe owner as follower of an article on new comment' do |
355 | owner = create_user('owner_of_article').person | 348 | owner = create_user('owner_of_article').person |
356 | article = fast_create(Article, :profile_id => owner.id) | 349 | article = fast_create(Article, :profile_id => owner.id) |
357 | create(Comment, :source => article, :author => owner, :title => 'new comment', :body => 'new comment') | 350 | create(Comment, :source => article, :author => owner, :title => 'new comment', :body => 'new comment') |
358 | - assert_not_includes article.reload.followers, owner.email | 351 | + assert_not_includes article.reload.person_followers, owner |
359 | end | 352 | end |
360 | 353 | ||
361 | should 'not subscribe admins as follower of an article on new comment' do | 354 | should 'not subscribe admins as follower of an article on new comment' do |
@@ -366,8 +359,13 @@ class CommentTest < ActiveSupport::TestCase | @@ -366,8 +359,13 @@ class CommentTest < ActiveSupport::TestCase | ||
366 | article = fast_create(Article, :profile_id => owner.id) | 359 | article = fast_create(Article, :profile_id => owner.id) |
367 | create(Comment, :source => article, :author => follower, :title => 'new comment', :body => 'new comment') | 360 | create(Comment, :source => article, :author => follower, :title => 'new comment', :body => 'new comment') |
368 | create(Comment, :source => article, :author => admin, :title => 'new comment', :body => 'new comment') | 361 | create(Comment, :source => article, :author => admin, :title => 'new comment', :body => 'new comment') |
369 | - assert_not_includes article.reload.followers, admin.email | ||
370 | - assert_includes article.followers, follower.email | 362 | + |
363 | + article.person_followers += [follower] | ||
364 | + article.save! | ||
365 | + article.reload | ||
366 | + | ||
367 | + assert_not_includes article.reload.person_followers, admin | ||
368 | + assert_includes article.reload.person_followers, follower | ||
371 | end | 369 | end |
372 | 370 | ||
373 | should 'update article activity when add a comment' do | 371 | should 'update article activity when add a comment' do |
test/unit/person_notifier_test.rb
@@ -49,7 +49,8 @@ class PersonNotifierTest < ActiveSupport::TestCase | @@ -49,7 +49,8 @@ class PersonNotifierTest < ActiveSupport::TestCase | ||
49 | should 'display author name in delivered mail' do | 49 | should 'display author name in delivered mail' do |
50 | @community.add_member(@member) | 50 | @community.add_member(@member) |
51 | User.current = @admin.user | 51 | User.current = @admin.user |
52 | - Comment.create!(:author => @admin, :title => 'test comment', :body => 'body!', :source => @article) | 52 | + comment = Comment.create!(:author => @admin, :title => 'test comment', :body => 'body!', :source => @article) |
53 | + comment.save! | ||
53 | process_delayed_job_queue | 54 | process_delayed_job_queue |
54 | notify | 55 | notify |
55 | sent = ActionMailer::Base.deliveries.last | 56 | sent = ActionMailer::Base.deliveries.last |