diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index e45a792f311..cf2758b78fa 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -94,7 +94,6 @@ var initialize_modules = function() {
App.LegislationAnnotatable.initialize();
App.WatchFormChanges.initialize();
App.TreeNavigator.initialize();
- App.Followable.initialize();
};
$(function(){
diff --git a/app/assets/javascripts/followable.js.coffee b/app/assets/javascripts/followable.js.coffee
index 69ea61bacdb..9fa9aa319b1 100644
--- a/app/assets/javascripts/followable.js.coffee
+++ b/app/assets/javascripts/followable.js.coffee
@@ -1,10 +1,8 @@
App.Followable =
- initialize: ->
- $('.followable-content a[data-toggle]').on 'click', (event) ->
- event.preventDefault()
-
- update: (followable_id, button) ->
+ update: (followable_id, button, notice) ->
$("#" + followable_id + " .js-follow").html(button)
- # Temporary line. Waiting for issue resolution: https://github.com/consul/consul/issues/1736
- initialize_modules()
+ if ($('[data-alert]').length > 0)
+ $('[data-alert]').replaceWith(notice)
+ else
+ $("body").append(notice)
diff --git a/app/assets/stylesheets/layout.scss b/app/assets/stylesheets/layout.scss
index b4ea0cca344..25d569ff704 100644
--- a/app/assets/stylesheets/layout.scss
+++ b/app/assets/stylesheets/layout.scss
@@ -1932,8 +1932,39 @@ table {
.activity {
margin-bottom: $line-height * 2;
+ .accordion li {
+ margin-bottom: $line-height / 2;
+
+ .accordion-title {
+ border-bottom: 1px solid $border;
+ background: #f8f9fb;
+ font-size: $small-font-size;
+ padding: $line-height / 2;
+ }
+
+ .accordion-content {
+ padding: 0;
+ }
+ }
+
+ .accordion .title {
+ display: block;
+ line-height: $line-height;
+ }
+
+ .accordion .icon {
+ font-size: rem-calc(20);
+ float: left;
+ margin-right: $line-height / 3;
+
+ &.icon-debates {
+ margin-top: rem-calc(3);
+ }
+ }
+
table {
border: 0;
+ margin-bottom: 0;
}
td {
diff --git a/app/controllers/follows_controller.rb b/app/controllers/follows_controller.rb
index 9cec999fa73..05f0e8f96ca 100644
--- a/app/controllers/follows_controller.rb
+++ b/app/controllers/follows_controller.rb
@@ -3,15 +3,15 @@ class FollowsController < ApplicationController
load_and_authorize_resource
def create
- @followable = find_followable
- @follow = Follow.create(user: current_user, followable: @followable)
+ @follow = Follow.create(user: current_user, followable: find_followable)
+ flash.now[:notice] = t("shared.followable.#{followable_translation_key(@follow.followable)}.create.notice_html")
render :refresh_follow_button
end
def destroy
@follow = Follow.find(params[:id])
- @followable = @follow.followable
@follow.destroy
+ flash.now[:notice] = t("shared.followable.#{followable_translation_key(@follow.followable)}.destroy.notice_html")
render :refresh_follow_button
end
@@ -20,4 +20,9 @@ def destroy
def find_followable
params[:followable_type].constantize.find(params[:followable_id])
end
+
+ def followable_translation_key(followable)
+ followable.class.name.parameterize("_")
+ end
+
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 6ef59fb60ce..ae3ce36925d 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -1,13 +1,12 @@
class UsersController < ApplicationController
- has_filters %w{proposals debates budget_investments comments}, only: :show
+ has_filters %w{proposals debates budget_investments comments follows}, only: :show
load_and_authorize_resource
helper_method :author?
- helper_method :author_or_admin?
+ helper_method :valid_interests_access?
def show
load_filtered_activity if valid_access?
- load_interests if valid_interests_access?
end
private
@@ -17,7 +16,8 @@ def set_activity_counts
proposals: Proposal.where(author_id: @user.id).count,
debates: (Setting['feature.debates'] ? Debate.where(author_id: @user.id).count : 0),
budget_investments: (Setting['feature.budgets'] ? Budget::Investment.where(author_id: @user.id).count : 0),
- comments: only_active_commentables.count)
+ comments: only_active_commentables.count,
+ follows: @user.follows.count)
end
def load_filtered_activity
@@ -26,7 +26,8 @@ def load_filtered_activity
when "proposals" then load_proposals
when "debates" then load_debates
when "budget_investments" then load_budget_investments
- when "comments" then load_comments
+ when "comments" then load_comments
+ when "follows" then load_follows
else load_available_activity
end
end
@@ -44,6 +45,9 @@ def load_available_activity
elsif @activity_counts[:comments] > 0
load_comments
@current_filter = "comments"
+ elsif @activity_counts[:follows] > 0
+ load_follows
+ @current_filter = "follows"
end
end
@@ -63,8 +67,8 @@ def load_budget_investments
@budget_investments = Budget::Investment.where(author_id: @user.id).order(created_at: :desc).page(params[:page])
end
- def load_interests
- @user.interests
+ def load_follows
+ @follows = @user.follows.group_by(&:followable_type)
end
def valid_access?
@@ -75,12 +79,8 @@ def valid_interests_access?
@user.public_interests || authorized_current_user?
end
- def author?
- @author ||= current_user && (current_user == @user)
- end
-
- def author_or_admin?
- @author_or_admin ||= current_user && (author? || current_user.administrator?)
+ def author?(proposal)
+ proposal.author_id == current_user.id if current_user
end
def authorized_current_user?
diff --git a/app/helpers/followables_helper.rb b/app/helpers/followables_helper.rb
new file mode 100644
index 00000000000..b7fe1f1992a
--- /dev/null
+++ b/app/helpers/followables_helper.rb
@@ -0,0 +1,30 @@
+module FollowablesHelper
+
+ def followable_type_title(followable_type)
+ t("activerecord.models.#{followable_type.underscore}.other")
+ end
+
+ def followable_icon(followable)
+ {
+ proposals: 'Proposal',
+ budget: 'Budget::Investment'
+ }.invert[followable]
+ end
+
+ def render_follow(follow)
+ followable = follow.followable
+ partial = followable_class_name(followable)
+ locals = {followable_class_name(followable).to_sym => followable}
+
+ render partial, locals
+ end
+
+ def followable_class_name(followable)
+ followable.class.to_s.parameterize.gsub('-', '_')
+ end
+
+ def find_or_build_follow(user, followable)
+ Follow.find_or_initialize_by(user: user, followable: followable)
+ end
+
+end
diff --git a/app/helpers/follows_helper.rb b/app/helpers/follows_helper.rb
index 63f50f7be6d..b3426df1258 100644
--- a/app/helpers/follows_helper.rb
+++ b/app/helpers/follows_helper.rb
@@ -1,61 +1,13 @@
module FollowsHelper
- def show_follow_action?(followable)
- current_user && !followed?(followable)
- end
-
- def show_unfollow_action?(followable)
- current_user && followed?(followable)
- end
-
- def follow_entity_text(followable)
- entity = followable.class.name.gsub('::', '/').downcase
+ def follow_text(followable)
+ entity = followable.class.name.underscore
t('shared.follow_entity', entity: t("activerecord.models.#{entity}.one").downcase)
end
- def follow_entity_title(followable)
- entity = followable.class.name.gsub('::', '/').downcase
- t('shared.follow_entity_title', entity: t("activerecord.models.#{entity}.one").downcase)
- end
-
- def unfollow_entity_text(followable)
- entity = followable.class.name.gsub('::', '/').downcase
+ def unfollow_text(followable)
+ entity = followable.class.name.underscore
t('shared.unfollow_entity', entity: t("activerecord.models.#{entity}.one").downcase)
end
- def entity_full_name(followable)
- name = followable.class.name
- name.downcase.gsub("::", "-")
- end
-
- def follow_link_wrapper_id(followable)
- "follow-expand-#{entity_full_name(followable)}-#{followable.id}"
- end
-
- def unfollow_link_wrapper_id(followable)
- "unfollow-expand-#{entity_full_name(followable)}-#{followable.id}"
- end
-
- def follow_link_id(followable)
- "follow-#{entity_full_name(followable)}-#{followable.id}"
- end
-
- def unfollow_link_id(followable)
- "unfollow-#{entity_full_name(followable)}-#{followable.id}"
- end
-
- def follow_drop_id(followable)
- "follow-drop-#{entity_full_name(followable)}-#{followable.id}"
- end
-
- def unfollow_drop_id(followable)
- "unfollow-drop-#{entity_full_name(followable)}-#{followable.id}"
- end
-
- private
-
- def followed?(followable)
- Follow.followed?(current_user, followable)
- end
-
end
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 9c13e8ef849..968fa6e6689 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -41,4 +41,4 @@ def current_administrator?
current_user && current_user.administrator?
end
-end
\ No newline at end of file
+end
diff --git a/app/models/abilities/common.rb b/app/models/abilities/common.rb
index cf183ec5306..33a9d50f6cd 100644
--- a/app/models/abilities/common.rb
+++ b/app/models/abilities/common.rb
@@ -50,7 +50,7 @@ def initialize(user)
can :create, Budget::Investment, budget: { phase: "accepting" }
can :suggest, Budget::Investment, budget: { phase: "accepting" }
can :destroy, Budget::Investment, budget: { phase: ["accepting", "reviewing"] }, author_id: user.id
- can :vote, Budget::Investment, budget: { phase: "selecting" }
+ can :vote, Budget::Investment, budget: { phase: "selecting" }
can [:show, :create], Budget::Ballot, budget: { phase: "balloting" }
can [:create, :destroy], Budget::Ballot::Line, budget: { phase: "balloting" }
diff --git a/app/models/concerns/followable.rb b/app/models/concerns/followable.rb
index 51469698eb1..6231a24f449 100644
--- a/app/models/concerns/followable.rb
+++ b/app/models/concerns/followable.rb
@@ -6,4 +6,8 @@ module Followable
has_many :followers, through: :follows, source: :user
end
+ def followed_by?(user)
+ followers.include?(user)
+ end
+
end
diff --git a/app/models/follow.rb b/app/models/follow.rb
index 6c2c62e99d5..2da52127f37 100644
--- a/app/models/follow.rb
+++ b/app/models/follow.rb
@@ -6,15 +6,4 @@ class Follow < ActiveRecord::Base
validates :followable_id, presence: true
validates :followable_type, presence: true
- scope(:by_user_and_followable, lambda do |user, followable|
- where(user_id: user.id,
- followable_type: followable.class.to_s,
- followable_id: followable.id)
- end)
-
- def self.followed?(user, followable)
- return false unless user
- !! by_user_and_followable(user, followable).try(:first)
- end
-
end
diff --git a/app/views/budgets/investments/_investment_show.html.erb b/app/views/budgets/investments/_investment_show.html.erb
index 950b93b6aee..434934c7e63 100644
--- a/app/views/budgets/investments/_investment_show.html.erb
+++ b/app/views/budgets/investments/_investment_show.html.erb
@@ -113,7 +113,9 @@
url: budget_investment_url(budget_id: investment.budget_id, id: investment.id)
} %>
- <%= render 'follows/followable_button', followable: investment if current_user %>
+ <% if current_user %>
+ <%= render 'follows/follow_button', follow: find_or_build_follow(current_user, investment) %>
+ <% end %>
diff --git a/app/views/follows/_follow_button.html.erb b/app/views/follows/_follow_button.html.erb
new file mode 100644
index 00000000000..547e880b9ae
--- /dev/null
+++ b/app/views/follows/_follow_button.html.erb
@@ -0,0 +1,24 @@
+
+
+
+ <% if follow.followable.followed_by?(current_user) %>
+
+ <%= link_to t('shared.unfollow'),
+ follow_path(follow),
+ method: :delete, remote: true,
+ title: unfollow_text(follow.followable),
+ class: 'button hollow' %>
+
+ <% else %>
+
+ <%= link_to t('shared.follow'),
+ follows_path(followable_id: follow.followable.id,
+ followable_type: follow.followable.class.name),
+ method: :post, remote: true,
+ title: follow_text(follow.followable),
+ class: 'button hollow' %>
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/follows/_followable_button.html.erb b/app/views/follows/_followable_button.html.erb
deleted file mode 100644
index 527a7e02973..00000000000
--- a/app/views/follows/_followable_button.html.erb
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
- <% if show_follow_action? followable %>
-
- <%= link_to "##{follow_link_wrapper_id(followable)}",
- id: follow_link_wrapper_id(followable),
- title: follow_entity_text(followable),
- data: { toggle: follow_drop_id(followable) },
- class: 'button hollow' do %>
- <%= t('shared.follow') %>
- <% end %>
-
- <%= link_to budget_investment.title, budget_investment_path(budget_investment.budget, budget_investment) %> - | -- <% if can? :destroy, budget_investment %> - <%= link_to t('shared.delete'), budget_investment_path(budget_investment.budget, budget_investment), - method: :delete, class: "button hollow alert" %> - <% end %> - | -
- <%= link_to proposal.title, proposal, proposal.retired? ? {class: 'retired'} : {} %>
- - <%= proposal.summary %> - |
-
- <% if author? %>
- - <%= link_to t("users.proposals.send_notification"), new_proposal_notification_path(proposal_id: proposal.id), - class: 'button hollow' %> - | - -- <% if proposal.retired? %> - <%= t('users.proposals.retired') %> - <% else %> - <%= link_to t('users.proposals.retire'), - retire_form_proposal_path(proposal), - class: 'button hollow alert' %> - <% end %> - | - <% end %> - -
<%= t('users.show.private_activity') %>
<% end %> - <% if @user.public_interests || @authorized_current_user %> + <% if valid_interests_access? %>