Merge pull request #1750 from rockandror/followable-user-activity
User page: new following section
This commit is contained in:
@@ -94,7 +94,6 @@ var initialize_modules = function() {
|
|||||||
App.LegislationAnnotatable.initialize();
|
App.LegislationAnnotatable.initialize();
|
||||||
App.WatchFormChanges.initialize();
|
App.WatchFormChanges.initialize();
|
||||||
App.TreeNavigator.initialize();
|
App.TreeNavigator.initialize();
|
||||||
App.Followable.initialize();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$(function(){
|
$(function(){
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
App.Followable =
|
App.Followable =
|
||||||
|
|
||||||
initialize: ->
|
update: (followable_id, button, notice) ->
|
||||||
$('.followable-content a[data-toggle]').on 'click', (event) ->
|
|
||||||
event.preventDefault()
|
|
||||||
|
|
||||||
update: (followable_id, button) ->
|
|
||||||
$("#" + followable_id + " .js-follow").html(button)
|
$("#" + followable_id + " .js-follow").html(button)
|
||||||
# Temporary line. Waiting for issue resolution: https://github.com/consul/consul/issues/1736
|
if ($('[data-alert]').length > 0)
|
||||||
initialize_modules()
|
$('[data-alert]').replaceWith(notice)
|
||||||
|
else
|
||||||
|
$("body").append(notice)
|
||||||
|
|||||||
@@ -1965,8 +1965,39 @@ table {
|
|||||||
.activity {
|
.activity {
|
||||||
margin-bottom: $line-height * 2;
|
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 {
|
table {
|
||||||
border: 0;
|
border: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
td {
|
td {
|
||||||
|
|||||||
@@ -3,15 +3,15 @@ class FollowsController < ApplicationController
|
|||||||
load_and_authorize_resource
|
load_and_authorize_resource
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@followable = find_followable
|
@follow = Follow.create(user: current_user, followable: find_followable)
|
||||||
@follow = Follow.create(user: current_user, followable: @followable)
|
flash.now[:notice] = t("shared.followable.#{followable_translation_key(@follow.followable)}.create.notice_html")
|
||||||
render :refresh_follow_button
|
render :refresh_follow_button
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@follow = Follow.find(params[:id])
|
@follow = Follow.find(params[:id])
|
||||||
@followable = @follow.followable
|
|
||||||
@follow.destroy
|
@follow.destroy
|
||||||
|
flash.now[:notice] = t("shared.followable.#{followable_translation_key(@follow.followable)}.destroy.notice_html")
|
||||||
render :refresh_follow_button
|
render :refresh_follow_button
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -20,4 +20,9 @@ class FollowsController < ApplicationController
|
|||||||
def find_followable
|
def find_followable
|
||||||
params[:followable_type].constantize.find(params[:followable_id])
|
params[:followable_type].constantize.find(params[:followable_id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def followable_translation_key(followable)
|
||||||
|
followable.class.name.parameterize("_")
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
class UsersController < ApplicationController
|
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
|
load_and_authorize_resource
|
||||||
helper_method :author?
|
helper_method :author?
|
||||||
helper_method :author_or_admin?
|
helper_method :valid_interests_access?
|
||||||
|
|
||||||
def show
|
def show
|
||||||
load_filtered_activity if valid_access?
|
load_filtered_activity if valid_access?
|
||||||
load_interests if valid_interests_access?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -17,7 +16,8 @@ class UsersController < ApplicationController
|
|||||||
proposals: Proposal.where(author_id: @user.id).count,
|
proposals: Proposal.where(author_id: @user.id).count,
|
||||||
debates: (Setting['feature.debates'] ? Debate.where(author_id: @user.id).count : 0),
|
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),
|
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
|
end
|
||||||
|
|
||||||
def load_filtered_activity
|
def load_filtered_activity
|
||||||
@@ -27,6 +27,7 @@ class UsersController < ApplicationController
|
|||||||
when "debates" then load_debates
|
when "debates" then load_debates
|
||||||
when "budget_investments" then load_budget_investments
|
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
|
else load_available_activity
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -44,6 +45,9 @@ class UsersController < ApplicationController
|
|||||||
elsif @activity_counts[:comments] > 0
|
elsif @activity_counts[:comments] > 0
|
||||||
load_comments
|
load_comments
|
||||||
@current_filter = "comments"
|
@current_filter = "comments"
|
||||||
|
elsif @activity_counts[:follows] > 0
|
||||||
|
load_follows
|
||||||
|
@current_filter = "follows"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -63,8 +67,8 @@ class UsersController < ApplicationController
|
|||||||
@budget_investments = Budget::Investment.where(author_id: @user.id).order(created_at: :desc).page(params[:page])
|
@budget_investments = Budget::Investment.where(author_id: @user.id).order(created_at: :desc).page(params[:page])
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_interests
|
def load_follows
|
||||||
@user.interests
|
@follows = @user.follows.group_by(&:followable_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid_access?
|
def valid_access?
|
||||||
@@ -75,12 +79,8 @@ class UsersController < ApplicationController
|
|||||||
@user.public_interests || authorized_current_user?
|
@user.public_interests || authorized_current_user?
|
||||||
end
|
end
|
||||||
|
|
||||||
def author?
|
def author?(proposal)
|
||||||
@author ||= current_user && (current_user == @user)
|
proposal.author_id == current_user.id if current_user
|
||||||
end
|
|
||||||
|
|
||||||
def author_or_admin?
|
|
||||||
@author_or_admin ||= current_user && (author? || current_user.administrator?)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorized_current_user?
|
def authorized_current_user?
|
||||||
|
|||||||
30
app/helpers/followables_helper.rb
Normal file
30
app/helpers/followables_helper.rb
Normal file
@@ -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
|
||||||
@@ -1,61 +1,13 @@
|
|||||||
module FollowsHelper
|
module FollowsHelper
|
||||||
|
|
||||||
def show_follow_action?(followable)
|
def follow_text(followable)
|
||||||
current_user && !followed?(followable)
|
entity = followable.class.name.underscore
|
||||||
end
|
|
||||||
|
|
||||||
def show_unfollow_action?(followable)
|
|
||||||
current_user && followed?(followable)
|
|
||||||
end
|
|
||||||
|
|
||||||
def follow_entity_text(followable)
|
|
||||||
entity = followable.class.name.gsub('::', '/').downcase
|
|
||||||
t('shared.follow_entity', entity: t("activerecord.models.#{entity}.one").downcase)
|
t('shared.follow_entity', entity: t("activerecord.models.#{entity}.one").downcase)
|
||||||
end
|
end
|
||||||
|
|
||||||
def follow_entity_title(followable)
|
def unfollow_text(followable)
|
||||||
entity = followable.class.name.gsub('::', '/').downcase
|
entity = followable.class.name.underscore
|
||||||
t('shared.follow_entity_title', entity: t("activerecord.models.#{entity}.one").downcase)
|
|
||||||
end
|
|
||||||
|
|
||||||
def unfollow_entity_text(followable)
|
|
||||||
entity = followable.class.name.gsub('::', '/').downcase
|
|
||||||
t('shared.unfollow_entity', entity: t("activerecord.models.#{entity}.one").downcase)
|
t('shared.unfollow_entity', entity: t("activerecord.models.#{entity}.one").downcase)
|
||||||
end
|
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
|
end
|
||||||
|
|||||||
@@ -6,4 +6,8 @@ module Followable
|
|||||||
has_many :followers, through: :follows, source: :user
|
has_many :followers, through: :follows, source: :user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def followed_by?(user)
|
||||||
|
followers.include?(user)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,15 +6,4 @@ class Follow < ActiveRecord::Base
|
|||||||
validates :followable_id, presence: true
|
validates :followable_id, presence: true
|
||||||
validates :followable_type, 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
|
end
|
||||||
|
|||||||
@@ -113,7 +113,9 @@
|
|||||||
url: budget_investment_url(budget_id: investment.budget_id, id: investment.id)
|
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 %>
|
||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
24
app/views/follows/_follow_button.html.erb
Normal file
24
app/views/follows/_follow_button.html.erb
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<span class="js-follow">
|
||||||
|
<span class="followable-content">
|
||||||
|
|
||||||
|
<% 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 %>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<span class="js-follow">
|
|
||||||
<span class="followable-content">
|
|
||||||
|
|
||||||
<% 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 %>
|
|
||||||
<div class="dropdown-pane" id="<%= follow_drop_id(followable) %>"
|
|
||||||
data-dropdown data-auto-focus="true">
|
|
||||||
<%= link_to follow_entity_text(followable),
|
|
||||||
follows_path(followable_id: followable.id,
|
|
||||||
followable_type: followable.class.name),
|
|
||||||
method: :post, remote: true,
|
|
||||||
id: follow_link_id(followable) %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<% if show_unfollow_action? followable %>
|
|
||||||
|
|
||||||
<% follow = followable.follows.where(user: current_user).first %>
|
|
||||||
<%= link_to "##{unfollow_link_wrapper_id(followable)}",
|
|
||||||
id: unfollow_link_wrapper_id(followable),
|
|
||||||
title: unfollow_entity_text(followable),
|
|
||||||
data: { toggle: unfollow_drop_id(followable) },
|
|
||||||
class: 'button hollow' do %>
|
|
||||||
<%= t('shared.unfollow') %>
|
|
||||||
<% end %>
|
|
||||||
<div class="dropdown-pane" id="<%= unfollow_drop_id(followable) %>"
|
|
||||||
data-dropdown data-auto-focus="true">
|
|
||||||
<%= link_to unfollow_entity_text(followable),
|
|
||||||
follow_path(follow),
|
|
||||||
method: :delete, remote: true,
|
|
||||||
id: unfollow_link_id(followable) %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
App.Followable.update("<%= dom_id(@followable) %>",
|
App.Followable.update("<%= dom_id(@follow.followable) %>",
|
||||||
"<%= j render('followable_button', followable: @followable) %>")
|
"<%= j render('follow_button', follow: @follow) %>",
|
||||||
|
"<%= j render('layouts/flash') %>")
|
||||||
|
|||||||
@@ -140,7 +140,9 @@
|
|||||||
url: proposal_url(@proposal)
|
url: proposal_url(@proposal)
|
||||||
} %>
|
} %>
|
||||||
|
|
||||||
<%= render 'follows/followable_button', followable: @proposal if current_user %>
|
<% if current_user %>
|
||||||
|
<%= render 'follows/follow_button', follow: find_or_build_follow(current_user, @proposal) %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<%= render "following" if @follows.present? %>
|
||||||
<%= render "proposals" if @proposals.present? %>
|
<%= render "proposals" if @proposals.present? %>
|
||||||
<%= render "debates" if @debates.present? && feature?(:debates) %>
|
<%= render "debates" if @debates.present? && feature?(:debates) %>
|
||||||
<%= render "budget_investments" if @budget_investments.present? && feature?(:budgets) %>
|
<%= render "budget_investments" if @budget_investments.present? && feature?(:budgets) %>
|
||||||
|
|||||||
11
app/views/users/_budget_investment.html.erb
Normal file
11
app/views/users/_budget_investment.html.erb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<tr id="budget_investment_<%= budget_investment.id %>">
|
||||||
|
<td>
|
||||||
|
<%= link_to budget_investment.title, budget_investment_path(budget_investment.budget, budget_investment) %>
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<% 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 %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
@@ -1,16 +1,6 @@
|
|||||||
<table id="budget_investments_list" class="clear activity-budget-investments">
|
<table id="budget_investments_list" class="clear activity-budget-investments">
|
||||||
<% @budget_investments.each do |budget_investment| %>
|
<% @budget_investments.each do |budget_investment| %>
|
||||||
<tr id="budget_investment_<%= budget_investment.id %>">
|
<%= render "budget_investment", budget_investment: budget_investment %>
|
||||||
<td>
|
|
||||||
<%= link_to budget_investment.title, budget_investment_path(budget_investment.budget, budget_investment) %>
|
|
||||||
</td>
|
|
||||||
<td class="text-right">
|
|
||||||
<% 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 %>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
30
app/views/users/_following.html.erb
Normal file
30
app/views/users/_following.html.erb
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<ul class="accordion" data-accordion data-allow-all-closed="true">
|
||||||
|
|
||||||
|
<% @follows.each do |followable_type, follows| %>
|
||||||
|
|
||||||
|
<li class="accordion-item" data-accordion-item>
|
||||||
|
|
||||||
|
<a href="#" class="accordion-title">
|
||||||
|
<span class="icon">
|
||||||
|
<i class="icon icon-<%= followable_icon(followable_type) %>"></i>
|
||||||
|
</span>
|
||||||
|
<span class="title">
|
||||||
|
<strong><%= followable_type_title(followable_type) %></strong>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="accordion-content" data-tab-content>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<% follows.each do |follow| %>
|
||||||
|
<%= render_follow(follow) %>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
</ul>
|
||||||
34
app/views/users/_proposal.html.erb
Normal file
34
app/views/users/_proposal.html.erb
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<tr id="proposal_<%= proposal.id %>">
|
||||||
|
<td>
|
||||||
|
<%= link_to proposal.title, proposal, proposal.retired? ? { class: 'retired' } : {} %>
|
||||||
|
<br>
|
||||||
|
<%= proposal.summary %>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<% if proposal.retired? %>
|
||||||
|
|
||||||
|
<td class="text-center">
|
||||||
|
<span class="label alert"><%= t('users.proposals.retired') %></span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<% elsif author?(proposal) %>
|
||||||
|
|
||||||
|
<td class="text-center">
|
||||||
|
<%= link_to t("users.proposals.send_notification"),
|
||||||
|
new_proposal_notification_path(proposal_id: proposal.id),
|
||||||
|
class: 'button hollow' %>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="text-center">
|
||||||
|
<% if proposal.retired? %>
|
||||||
|
<span class="label alert"><%= t('users.proposals.retired') %></span>
|
||||||
|
<% else %>
|
||||||
|
<%= link_to t('users.proposals.retire'),
|
||||||
|
retire_form_proposal_path(proposal),
|
||||||
|
class: 'button hollow alert' %>
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
</tr>
|
||||||
@@ -1,30 +1,6 @@
|
|||||||
<table class="clear activity-proposals">
|
<table class="clear activity-proposals">
|
||||||
<% @proposals.each do |proposal| %>
|
<% @proposals.each do |proposal| %>
|
||||||
<tr id="proposal_<%= proposal.id %>">
|
<%= render "proposal", proposal: proposal %>
|
||||||
<td>
|
|
||||||
<%= link_to proposal.title, proposal, proposal.retired? ? {class: 'retired'} : {} %>
|
|
||||||
<br>
|
|
||||||
<%= proposal.summary %>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<% if author? %>
|
|
||||||
<td class="text-center">
|
|
||||||
<%= link_to t("users.proposals.send_notification"), new_proposal_notification_path(proposal_id: proposal.id),
|
|
||||||
class: 'button hollow' %>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="text-center">
|
|
||||||
<% if proposal.retired? %>
|
|
||||||
<span class="label alert"><%= t('users.proposals.retired') %></span>
|
|
||||||
<% else %>
|
|
||||||
<%= link_to t('users.proposals.retire'),
|
|
||||||
retire_form_proposal_path(proposal),
|
|
||||||
class: 'button hollow alert' %>
|
|
||||||
<% end %>
|
|
||||||
</td>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
<p><%= t('users.show.private_activity') %></p>
|
<p><%= t('users.show.private_activity') %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @user.public_interests || @authorized_current_user %>
|
<% if valid_interests_access? %>
|
||||||
<div id="public_interests" class="public-interests">
|
<div id="public_interests" class="public-interests">
|
||||||
<h4><%= t('account.show.public_interests_title_list') %></h4>
|
<h4><%= t('account.show.public_interests_title_list') %></h4>
|
||||||
<% @user.interests.in_groups_of(10, false) do |interests_group| %>
|
<% @user.interests.in_groups_of(10, false) do |interests_group| %>
|
||||||
|
|||||||
@@ -505,7 +505,17 @@ en:
|
|||||||
flag: Flag as inappropriate
|
flag: Flag as inappropriate
|
||||||
follow: "Follow"
|
follow: "Follow"
|
||||||
follow_entity: "Follow %{entity}"
|
follow_entity: "Follow %{entity}"
|
||||||
follow_entity_title: "Follow %{entity}: You can participate and receive notifications of any related events."
|
followable:
|
||||||
|
budget_investment:
|
||||||
|
create:
|
||||||
|
notice_html: "You are now following this investment project! </br> We will notify you of changes as they occur so that you are up-to-date."
|
||||||
|
destroy:
|
||||||
|
notice_html: "You have stopped following this investment project! </br> You will no longer receive notifications related to this project."
|
||||||
|
proposal:
|
||||||
|
create:
|
||||||
|
notice_html: "Now you are following this citizen proposal! </br> We will notify you of changes as they occur so that you are up-to-date."
|
||||||
|
destroy:
|
||||||
|
notice_html: "You have stopped following this citizen proposal! </br> You will no longer receive notifications related to this proposal."
|
||||||
hide: Hide
|
hide: Hide
|
||||||
print:
|
print:
|
||||||
print_button: Print this info
|
print_button: Print this info
|
||||||
|
|||||||
@@ -505,7 +505,17 @@ es:
|
|||||||
flag: Denunciar como inapropiado
|
flag: Denunciar como inapropiado
|
||||||
follow: "Seguir"
|
follow: "Seguir"
|
||||||
follow_entity: "Seguir %{entity}"
|
follow_entity: "Seguir %{entity}"
|
||||||
follow_entity_title: "Seguir %{entity}: Podrás participar y recibir notificaciones de cualquier suceso relacionado."
|
followable:
|
||||||
|
budget_investment:
|
||||||
|
create:
|
||||||
|
notice_html: "¡Ahora estás siguiendo este proyecto de inversión! </br> Te notificaremos los cambios a medida que se produzcan para que estés al día."
|
||||||
|
destroy:
|
||||||
|
notice_html: "¡Has dejado de seguir este proyecto de inverisión! </br> Ya no recibirás más notificaciones relacionadas con este proyecto."
|
||||||
|
proposal:
|
||||||
|
create:
|
||||||
|
notice_html: "¡Ahora estás siguiendo esta propuesta ciudadana! </br> Te notificaremos los cambios a medida que se produzcan para que estés al día."
|
||||||
|
destroy:
|
||||||
|
notice_html: "¡Has dejado de seguir esta propuesta ciudadana! </br> Ya no recibirás más notificaciones relacionadas con esta propuesta."
|
||||||
hide: Ocultar
|
hide: Ocultar
|
||||||
print:
|
print:
|
||||||
print_button: Imprimir esta información
|
print_button: Imprimir esta información
|
||||||
|
|||||||
@@ -357,4 +357,159 @@ feature 'Users' do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature 'Following (public page)' do
|
||||||
|
|
||||||
|
before do
|
||||||
|
@user = create(:user)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Not display following tab when user is not following any followable' do
|
||||||
|
visit user_path(@user)
|
||||||
|
|
||||||
|
expect(page).not_to have_content('0 Following')
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Active following tab by default when follows filters selected', :js do
|
||||||
|
proposal = create(:proposal, author: @user)
|
||||||
|
create(:follow, followable: proposal, user: @user)
|
||||||
|
|
||||||
|
visit user_path(@user, filter: "follows")
|
||||||
|
|
||||||
|
expect(page).to have_selector(".activity li.active", text: "1 Following" )
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'Proposals' do
|
||||||
|
|
||||||
|
scenario 'Display following tab when user is following one proposal at least' do
|
||||||
|
proposal = create(:proposal)
|
||||||
|
create(:follow, followable: proposal, user: @user)
|
||||||
|
|
||||||
|
visit user_path(@user)
|
||||||
|
|
||||||
|
expect(page).to have_content('1 Following')
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Display accordion proposal tab when user is following one proposal at least' do
|
||||||
|
proposal = create(:proposal)
|
||||||
|
create(:follow, followable: proposal, user: @user)
|
||||||
|
|
||||||
|
visit user_path(@user, filter: "follows")
|
||||||
|
|
||||||
|
expect(page).to have_link('Citizen proposals', href: "#")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Not display accordion proposal tab when user is not following any proposal' do
|
||||||
|
visit user_path(@user, filter: "follows")
|
||||||
|
|
||||||
|
expect(page).not_to have_link('Citizen proposals', href: "#")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Display proposal with action buttons inside accordion proposal tab when current user is proposal author', :js do
|
||||||
|
proposal = create(:proposal, author: @user)
|
||||||
|
create(:follow, followable: proposal, user: @user)
|
||||||
|
login_as @user
|
||||||
|
|
||||||
|
visit user_path(@user, filter: "follows")
|
||||||
|
click_link 'Citizen proposals'
|
||||||
|
|
||||||
|
expect(page).to have_content proposal.title
|
||||||
|
expect(page).to have_link "Send notification"
|
||||||
|
expect(page).to have_link "Retire"
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Display proposal with action buttons inside accordion proposal tab when there is no logged user', :js do
|
||||||
|
proposal = create(:proposal, author: @user)
|
||||||
|
create(:follow, followable: proposal, user: @user)
|
||||||
|
|
||||||
|
visit user_path(@user, filter: "follows")
|
||||||
|
click_link 'Citizen proposals'
|
||||||
|
|
||||||
|
expect(page).to have_content proposal.title
|
||||||
|
expect(page).not_to have_link "Send notification"
|
||||||
|
expect(page).not_to have_link "Retire"
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Display proposal without action buttons inside accordion proposal tab when current user is not proposal author', :js do
|
||||||
|
proposal = create(:proposal)
|
||||||
|
create(:follow, followable: proposal, user: @user)
|
||||||
|
login_as @user
|
||||||
|
|
||||||
|
visit user_path(@user, filter: "follows")
|
||||||
|
click_link 'Citizen proposals'
|
||||||
|
|
||||||
|
expect(page).to have_content proposal.title
|
||||||
|
expect(page).not_to have_link "Send notification"
|
||||||
|
expect(page).not_to have_link "Retire"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'Budget Investments' do
|
||||||
|
|
||||||
|
scenario 'Display following tab when user is following one budget investment at least' do
|
||||||
|
budget_investment = create(:budget_investment)
|
||||||
|
create(:follow, followable: budget_investment, user: @user)
|
||||||
|
|
||||||
|
visit user_path(@user)
|
||||||
|
|
||||||
|
expect(page).to have_content('1 Following')
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Display accordion budget investment tab when user is following one budget investment at least' do
|
||||||
|
budget_investment = create(:budget_investment)
|
||||||
|
create(:follow, followable: budget_investment, user: @user)
|
||||||
|
|
||||||
|
visit user_path(@user, filter: "follow")
|
||||||
|
|
||||||
|
expect(page).to have_link('Investments', href: "#")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Not display accordion budget investment tab when user is not following any budget investment' do
|
||||||
|
visit user_path(@user, filter: "follow")
|
||||||
|
|
||||||
|
expect(page).not_to have_link('Investments', href: "#")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Display budget investment with action buttons inside accordion budget investment tab when current user is a verified user and author', :js do
|
||||||
|
user = create(:user, :level_two)
|
||||||
|
budget_investment = create(:budget_investment, author: user)
|
||||||
|
create(:follow, followable: budget_investment, user: user)
|
||||||
|
login_as user
|
||||||
|
|
||||||
|
visit user_path(user, filter: "follows")
|
||||||
|
click_link 'Investments'
|
||||||
|
|
||||||
|
expect(page).to have_link budget_investment.title
|
||||||
|
expect(page).to have_link "Delete"
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Display budget investment with action buttons inside accordion budget investment tab when there is no logged user', :js do
|
||||||
|
user = create(:user, :level_two)
|
||||||
|
budget_investment = create(:budget_investment, author: user)
|
||||||
|
create(:follow, followable: budget_investment, user: user)
|
||||||
|
|
||||||
|
visit user_path(user, filter: "follows")
|
||||||
|
click_link 'Investments'
|
||||||
|
|
||||||
|
expect(page).to have_link budget_investment.title
|
||||||
|
expect(page).not_to have_link "Delete"
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Display budget investment without action buttons inside accordion budget investment tab when current user is not budget investment author', :js do
|
||||||
|
user = create(:user, :level_two)
|
||||||
|
budget_investment = create(:budget_investment)
|
||||||
|
create(:follow, followable: budget_investment, user: user)
|
||||||
|
login_as user
|
||||||
|
|
||||||
|
visit user_path(user, filter: "follows")
|
||||||
|
click_link 'Investments'
|
||||||
|
|
||||||
|
expect(page).to have_link budget_investment.title
|
||||||
|
expect(page).not_to have_link "Delete"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -41,19 +41,31 @@ shared_examples "followable" do |followable_class_name, followable_path, followa
|
|||||||
expect(page).to have_link("Follow")
|
expect(page).to have_link("Follow")
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "Should display unfollow button when click on follow button", :js do
|
scenario "Should display unfollow after user clicks on follow button", :js do
|
||||||
user = create(:user)
|
user = create(:user)
|
||||||
login_as(user)
|
login_as(user)
|
||||||
|
|
||||||
visit send(followable_path, arguments)
|
visit send(followable_path, arguments)
|
||||||
within "##{dom_id(followable)}" do
|
within "##{dom_id(followable)}" do
|
||||||
click_link "Follow"
|
click_link "Follow"
|
||||||
page.find("#follow-#{followable_dom_name}-#{followable.id}").click
|
|
||||||
|
|
||||||
expect(page).to have_css("#unfollow-expand-#{followable_dom_name}-#{followable.id}")
|
expect(page).not_to have_link "Follow"
|
||||||
|
expect(page).to have_link "Unfollow"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scenario "Should display new follower notice after user clicks on follow button", :js do
|
||||||
|
user = create(:user)
|
||||||
|
login_as(user)
|
||||||
|
|
||||||
|
visit send(followable_path, arguments)
|
||||||
|
within "##{dom_id(followable)}" do
|
||||||
|
click_link "Follow"
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(page).to have_content strip_tags(t("shared.followable.#{followable_class_name}.create.notice_html"))
|
||||||
|
end
|
||||||
|
|
||||||
scenario "Display unfollow button when user already following" do
|
scenario "Display unfollow button when user already following" do
|
||||||
user = create(:user)
|
user = create(:user)
|
||||||
follow = create(:follow, user: user, followable: followable)
|
follow = create(:follow, user: user, followable: followable)
|
||||||
@@ -64,7 +76,7 @@ shared_examples "followable" do |followable_class_name, followable_path, followa
|
|||||||
expect(page).to have_link("Unfollow")
|
expect(page).to have_link("Unfollow")
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "Should display follow button when click on unfollow button", :js do
|
scenario "Should update follow button and show destroy notice after user clicks on unfollow button", :js do
|
||||||
user = create(:user)
|
user = create(:user)
|
||||||
follow = create(:follow, user: user, followable: followable)
|
follow = create(:follow, user: user, followable: followable)
|
||||||
login_as(user)
|
login_as(user)
|
||||||
@@ -72,12 +84,25 @@ shared_examples "followable" do |followable_class_name, followable_path, followa
|
|||||||
visit send(followable_path, arguments)
|
visit send(followable_path, arguments)
|
||||||
within "##{dom_id(followable)}" do
|
within "##{dom_id(followable)}" do
|
||||||
click_link "Unfollow"
|
click_link "Unfollow"
|
||||||
page.find("#unfollow-#{followable_dom_name}-#{followable.id}").click
|
|
||||||
|
|
||||||
expect(page).to have_css("#follow-expand-#{followable_dom_name}-#{followable.id}")
|
expect(page).not_to have_link "Unfollow"
|
||||||
|
expect(page).to have_link "Follow"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scenario "Should display destroy follower notice after user clicks on unfollow button", :js do
|
||||||
|
user = create(:user)
|
||||||
|
follow = create(:follow, user: user, followable: followable)
|
||||||
|
login_as(user)
|
||||||
|
|
||||||
|
visit send(followable_path, arguments)
|
||||||
|
within "##{dom_id(followable)}" do
|
||||||
|
click_link "Unfollow"
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(page).to have_content strip_tags(t("shared.followable.#{followable_class_name}.destroy.notice_html"))
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user