Merge pull request #633 from AyuntamientoMadrid/add-featured-proposals
Adds featured proposals
This commit is contained in:
BIN
app/assets/images/featured_proposals.jpg
Normal file
BIN
app/assets/images/featured_proposals.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
@@ -4,6 +4,7 @@
|
||||
// 02. New participation
|
||||
// 03. Show participation
|
||||
// 04. List participation
|
||||
// 05. Featured proposals
|
||||
//
|
||||
|
||||
// 01. Votes and supports
|
||||
@@ -819,3 +820,156 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 05. Featured proposals
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
.featured-proposals-container {
|
||||
background: #FED900;
|
||||
margin: 0 !important;
|
||||
|
||||
@media (min-width: $medium-breakpoint) {
|
||||
margin-left: 0 !important;
|
||||
margin-right: rem-calc(-15) !important;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: $text;
|
||||
font-size: rem-calc(24);
|
||||
margin: rem-calc(12) 0 0;
|
||||
position: relative;
|
||||
text-transform: uppercase;
|
||||
|
||||
@media (min-width: $medium-breakpoint) {
|
||||
margin-bottom: rem-calc(27);
|
||||
}
|
||||
|
||||
.icon-proposals {
|
||||
font-size: rem-calc(20);
|
||||
position: absolute;
|
||||
right: -26px;
|
||||
top: -5px;
|
||||
}
|
||||
}
|
||||
|
||||
.proposals-list {
|
||||
margin: rem-calc(6) 0;
|
||||
|
||||
@media (min-width: $medium-breakpoint) {
|
||||
border-left: 1px solid #D2B400;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: none;
|
||||
position: absolute;
|
||||
display: block;
|
||||
border-style: solid;
|
||||
border-color: #C9AF00 transparent transparent transparent;
|
||||
bottom: rem-calc(-20);
|
||||
border-left-width: 0;
|
||||
border-right-color: transparent;
|
||||
right: rem-calc(1);
|
||||
border-width: rem-calc(14) rem-calc(14) 0 0;
|
||||
|
||||
@media (min-width: $medium-breakpoint) {
|
||||
content: " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.proposal-featured {
|
||||
background: #FED900;
|
||||
margin-bottom: 0;
|
||||
margin-top: 0;
|
||||
padding-left: 0;
|
||||
|
||||
.panel {
|
||||
background: none;
|
||||
border: 0;
|
||||
margin-bottom: 0;
|
||||
padding: 0 rem-calc(12);
|
||||
|
||||
h3 {
|
||||
font-weight: bold;
|
||||
margin: rem-calc(8) 0 0 0;
|
||||
min-height: auto;
|
||||
|
||||
a {
|
||||
clear: both;
|
||||
color: $text;
|
||||
display: block;
|
||||
font-size: rem-calc(14);
|
||||
line-height: $line-height;
|
||||
text-transform: lowercase;
|
||||
|
||||
&:first-letter {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
height: rem-calc(60);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.info {
|
||||
color: #806C00 !important;
|
||||
}
|
||||
|
||||
.supports {
|
||||
@include supports;
|
||||
background: none;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
padding-left: rem-calc(13);
|
||||
margin-right: rem-calc(-26);
|
||||
|
||||
&:after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
.total-supports {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.not-logged, .organizations-votes {
|
||||
background: #FED900;
|
||||
line-height: rem-calc(24);
|
||||
padding-top: rem-calc(6);
|
||||
}
|
||||
|
||||
.organizations-votes p {
|
||||
color: $text;
|
||||
line-height: rem-calc(24);
|
||||
padding-top: rem-calc(6);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.button-support {
|
||||
margin-top: rem-calc(4);
|
||||
}
|
||||
|
||||
.supported {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.share-supported {
|
||||
|
||||
.social-share-button-twitter,
|
||||
.social-share-button-facebook,
|
||||
.social-share-button-google_plus {
|
||||
height: rem-calc(33);
|
||||
}
|
||||
|
||||
.social-share-button-twitter:before,
|
||||
.social-share-button-facebook:before,
|
||||
.social-share-button-google_plus:before {
|
||||
font-size: rem-calc(18);
|
||||
line-height: rem-calc(33);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ module CommentableActions
|
||||
@resources = @search_terms.present? ? resource_model.search(@search_terms) : resource_model.all
|
||||
@resources = @resources.tagged_with(@tag_filter) if @tag_filter
|
||||
@resources = @resources.page(params[:page]).for_render.send("sort_by_#{@current_order}")
|
||||
index_customization if index_customization.present?
|
||||
@tag_cloud = tag_cloud
|
||||
|
||||
set_resource_votes(@resources)
|
||||
@@ -86,4 +87,8 @@ module CommentableActions
|
||||
def set_resource_votes(instance)
|
||||
send("set_#{resource_name}_votes", instance)
|
||||
end
|
||||
|
||||
def index_customization
|
||||
nil
|
||||
end
|
||||
end
|
||||
@@ -11,11 +11,24 @@ class ProposalsController < ApplicationController
|
||||
load_and_authorize_resource
|
||||
respond_to :html, :js
|
||||
|
||||
def index_customization
|
||||
@featured_proposals = Proposal.all.sort_by_confidence_score.limit(3) if @search_terms.blank?
|
||||
if @featured_proposals.present?
|
||||
set_featured_proposal_votes(@featured_proposals)
|
||||
@resources = @resources.where('proposals.id NOT IN (?)', @featured_proposals.map(&:id))
|
||||
end
|
||||
end
|
||||
|
||||
def vote
|
||||
@proposal.register_vote(current_user, 'yes')
|
||||
set_proposal_votes(@proposal)
|
||||
end
|
||||
|
||||
def vote_featured
|
||||
@proposal.register_vote(current_user, 'yes')
|
||||
set_featured_proposal_votes(@proposal)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def proposal_params
|
||||
@@ -25,4 +38,8 @@ class ProposalsController < ApplicationController
|
||||
def resource_model
|
||||
Proposal
|
||||
end
|
||||
|
||||
def set_featured_proposal_votes(proposals)
|
||||
@featured_proposals_votes = current_user ? current_user.proposal_votes(proposals) : {}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,6 +37,7 @@ module Abilities
|
||||
|
||||
if user.level_two_or_three_verified?
|
||||
can :vote, Proposal
|
||||
can :vote_featured, Proposal
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
22
app/views/proposals/_featured_proposal.html.erb
Normal file
22
app/views/proposals/_featured_proposal.html.erb
Normal file
@@ -0,0 +1,22 @@
|
||||
<div id="<%= dom_id(proposal) %>" class="proposal-featured small-12 column">
|
||||
<div class="panel">
|
||||
<div class="content small-12 medium-9 left">
|
||||
<h3><%= link_to proposal.title, proposal %></h3>
|
||||
<div class="info">
|
||||
<span class="author">
|
||||
<% if proposal.author.hidden? || proposal.author.erased? %>
|
||||
<%= t("proposals.show.author_deleted") %>
|
||||
<% else %>
|
||||
<%= proposal.author.name %>
|
||||
<% end %>
|
||||
</span>
|
||||
<span> • </span>
|
||||
<%= t("proposals.proposal.supports", count: proposal.total_votes) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="<%= dom_id(proposal) %>_votes" class="small-12 medium-3 left">
|
||||
<%= render 'featured_votes', proposal: proposal %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
42
app/views/proposals/_featured_votes.html.erb
Normal file
42
app/views/proposals/_featured_votes.html.erb
Normal file
@@ -0,0 +1,42 @@
|
||||
<div class="supports">
|
||||
<div class="in-favor">
|
||||
<% if voted_for?(@featured_proposals_votes, proposal) %>
|
||||
<div class="supported">
|
||||
<%= t("proposals.proposal.already_supported") %>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= link_to vote_featured_proposal_path(proposal, value: 'yes'),
|
||||
class: "button button-support tiny radius expand",
|
||||
title: t('proposals.proposal.support_title'), method: "post", remote: true do %>
|
||||
<%= t("proposals.proposal.support") %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if user_signed_in? && current_user.organization? %>
|
||||
<div class="organizations-votes" style='display:none'>
|
||||
<p>
|
||||
<%= t("votes.organizations") %>
|
||||
</p>
|
||||
</div>
|
||||
<% elsif user_signed_in? && !proposal.votable_by?(current_user)%>
|
||||
<div class="anonymous-votes" style='display:none'>
|
||||
<p>
|
||||
<%= t("votes.verified_only",
|
||||
verify_account: link_to(t("votes.verify_account"), verification_path )).html_safe %>
|
||||
</p>
|
||||
</div>
|
||||
<% elsif !user_signed_in? %>
|
||||
<div class="not-logged" style='display:none'>
|
||||
<%= t("votes.unauthenticated",
|
||||
signin: link_to(t("votes.signin"), new_user_session_path),
|
||||
signup: link_to(t("votes.signup"), new_user_registration_path)).html_safe %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if voted_for?(@featured_proposals_votes, proposal) %>
|
||||
<div class="share-supported">
|
||||
<%= social_share_button_tag(proposal.title, url: proposal_url(proposal), via: "AbriendoMadrid") %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -44,6 +44,24 @@
|
||||
<%= link_to t("proposals.index.start_proposal"), new_proposal_path, class: 'button radius expand' %>
|
||||
</div>
|
||||
|
||||
<% if @featured_proposals.present? %>
|
||||
<div id="featured-proposals" class="row featured-proposals-container">
|
||||
<div class="small-12 medium-3 column">
|
||||
<h2>
|
||||
<%= t("proposals.index.featured_proposals_html") %>
|
||||
</h2>
|
||||
<span class="show-for-medium-up">
|
||||
<%= image_tag("featured_proposals.jpg", size: "210x135") %>
|
||||
</span>
|
||||
</div>
|
||||
<div class="small-12 medium-9 column proposals-list">
|
||||
<% @featured_proposals.each do |featured_proposal| %>
|
||||
<%= render "featured_proposal", proposal: featured_proposal %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render partial: 'proposals/proposal', collection: @proposals %>
|
||||
<%= paginate @proposals %>
|
||||
</div>
|
||||
|
||||
1
app/views/proposals/vote_featured.js.erb
Normal file
1
app/views/proposals/vote_featured.js.erb
Normal file
@@ -0,0 +1 @@
|
||||
$("#<%= dom_id(@proposal) %>_votes").html('<%= j render("proposals/featured_votes", proposal: @proposal) %>');
|
||||
@@ -155,6 +155,7 @@ en:
|
||||
proposals:
|
||||
index:
|
||||
title: Proposals
|
||||
featured_proposals_html: "Featured<br>proposals"
|
||||
start_proposal: Start a proposal
|
||||
select_order: Order by
|
||||
select_order_long: Order proposals by
|
||||
|
||||
@@ -155,6 +155,7 @@ es:
|
||||
proposals:
|
||||
index:
|
||||
title: Propuestas ciudadanas
|
||||
featured_proposals_html: "Propuestas<br>destacadas"
|
||||
start_proposal: Crea una propuesta
|
||||
select_order: Ordenar por
|
||||
select_order_long: Estás viendo las propuestas
|
||||
|
||||
@@ -47,6 +47,7 @@ Rails.application.routes.draw do
|
||||
resources :proposals do
|
||||
member do
|
||||
post :vote
|
||||
post :vote_featured
|
||||
put :flag
|
||||
put :unflag
|
||||
end
|
||||
|
||||
@@ -3,10 +3,19 @@ require 'rails_helper'
|
||||
feature 'Proposals' do
|
||||
|
||||
scenario 'Index' do
|
||||
featured_proposals = create_featured_proposals
|
||||
proposals = [create(:proposal), create(:proposal), create(:proposal)]
|
||||
|
||||
visit proposals_path
|
||||
|
||||
expect(page).to have_selector('#proposals .proposal-featured', count: 3)
|
||||
featured_proposals.each do |featured_proposal|
|
||||
within('#featured-proposals') do
|
||||
expect(page).to have_content featured_proposal.title
|
||||
expect(page).to have_css("a[href='#{proposal_path(featured_proposal)}']")
|
||||
end
|
||||
end
|
||||
|
||||
expect(page).to have_selector('#proposals .proposal', count: 3)
|
||||
proposals.each do |proposal|
|
||||
within('#proposals') do
|
||||
@@ -18,7 +27,7 @@ feature 'Proposals' do
|
||||
|
||||
scenario 'Paginated Index' do
|
||||
per_page = Kaminari.config.default_per_page
|
||||
(per_page + 2).times { create(:proposal) }
|
||||
(per_page + 5).times { create(:proposal) }
|
||||
|
||||
visit proposals_path
|
||||
|
||||
@@ -422,6 +431,7 @@ feature 'Proposals' do
|
||||
|
||||
describe 'Limiting tags shown' do
|
||||
scenario 'Index page shows up to 5 tags per proposal' do
|
||||
create_featured_proposals
|
||||
tag_list = ["Hacienda", "Economía", "Medio Ambiente", "Corrupción", "Fiestas populares", "Prensa"]
|
||||
create :proposal, tag_list: tag_list
|
||||
|
||||
@@ -433,6 +443,7 @@ feature 'Proposals' do
|
||||
end
|
||||
|
||||
scenario 'Index page shows 3 tags with no plus link' do
|
||||
create_featured_proposals
|
||||
tag_list = ["Medio Ambiente", "Corrupción", "Fiestas populares"]
|
||||
create :proposal, tag_list: tag_list
|
||||
|
||||
@@ -450,6 +461,8 @@ feature 'Proposals' do
|
||||
feature 'Proposal index order filters' do
|
||||
|
||||
scenario 'Default order is hot_score', :js do
|
||||
create_featured_proposals
|
||||
|
||||
create(:proposal, title: 'Best proposal').update_column(:hot_score, 10)
|
||||
create(:proposal, title: 'Worst proposal').update_column(:hot_score, 2)
|
||||
create(:proposal, title: 'Medium proposal').update_column(:hot_score, 5)
|
||||
@@ -461,6 +474,8 @@ feature 'Proposals' do
|
||||
end
|
||||
|
||||
scenario 'Proposals are ordered by confidence_score', :js do
|
||||
create_featured_proposals
|
||||
|
||||
create(:proposal, title: 'Best proposal').update_column(:confidence_score, 10)
|
||||
create(:proposal, title: 'Worst proposal').update_column(:confidence_score, 2)
|
||||
create(:proposal, title: 'Medium proposal').update_column(:confidence_score, 5)
|
||||
@@ -480,6 +495,8 @@ feature 'Proposals' do
|
||||
end
|
||||
|
||||
scenario 'Proposals are ordered by most commented', :js do
|
||||
create_featured_proposals
|
||||
|
||||
create(:proposal, title: 'Best proposal', comments_count: 10)
|
||||
create(:proposal, title: 'Medium proposal', comments_count: 5)
|
||||
create(:proposal, title: 'Worst proposal', comments_count: 2)
|
||||
@@ -499,6 +516,8 @@ feature 'Proposals' do
|
||||
end
|
||||
|
||||
scenario 'Proposals are ordered by newest', :js do
|
||||
create_featured_proposals
|
||||
|
||||
create(:proposal, title: 'Best proposal', created_at: Time.now)
|
||||
create(:proposal, title: 'Medium proposal', created_at: Time.now - 1.hour)
|
||||
create(:proposal, title: 'Worst proposal', created_at: Time.now - 1.day)
|
||||
@@ -518,6 +537,8 @@ feature 'Proposals' do
|
||||
end
|
||||
|
||||
scenario 'Proposals are ordered randomly', :js do
|
||||
create_featured_proposals
|
||||
|
||||
create_list(:proposal, 12)
|
||||
visit proposals_path
|
||||
|
||||
@@ -616,5 +637,10 @@ feature 'Proposals' do
|
||||
|
||||
visit proposal_path(proposal)
|
||||
expect(page).to have_content('Deleted user')
|
||||
|
||||
create_featured_proposals
|
||||
|
||||
visit proposals_path
|
||||
expect(page).to have_content('Deleted user')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -250,10 +250,11 @@ feature 'Votes' do
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Create in index', :js do
|
||||
scenario 'Create in listed proposal in index', :js do
|
||||
create_featured_proposals
|
||||
visit proposals_path
|
||||
|
||||
within("#proposals") do
|
||||
within("#proposal_#{@proposal.id}") do
|
||||
find('.in-favor a').click
|
||||
|
||||
expect(page).to have_content "1 support"
|
||||
@@ -261,6 +262,17 @@ feature 'Votes' do
|
||||
end
|
||||
expect(URI.parse(current_url).path).to eq(proposals_path)
|
||||
end
|
||||
|
||||
scenario 'Create in featured proposal in index', :js do
|
||||
visit proposals_path
|
||||
|
||||
within("#proposal_#{@proposal.id}") do
|
||||
find('.in-favor a').click
|
||||
|
||||
expect(page).to have_content "You already supported this proposal, share it!"
|
||||
end
|
||||
expect(URI.parse(current_url).path).to eq(proposals_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ describe "Abilities::Common" do
|
||||
it { should be_able_to(:index, Proposal) }
|
||||
it { should be_able_to(:show, proposal) }
|
||||
it { should_not be_able_to(:vote, Proposal) }
|
||||
it { should_not be_able_to(:vote_featured, Proposal) }
|
||||
|
||||
it { should_not be_able_to(:comment_as_administrator, debate) }
|
||||
it { should_not be_able_to(:comment_as_moderator, debate) }
|
||||
@@ -82,11 +83,13 @@ describe "Abilities::Common" do
|
||||
before{ user.update(residence_verified_at: Time.now, confirmed_phone: "1") }
|
||||
|
||||
it { should be_able_to(:vote, Proposal) }
|
||||
it { should be_able_to(:vote_featured, Proposal) }
|
||||
end
|
||||
|
||||
describe "when level 3 verified" do
|
||||
before{ user.update(verified_at: Time.now) }
|
||||
|
||||
it { should be_able_to(:vote, Proposal) }
|
||||
it { should be_able_to(:vote_featured, Proposal) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -161,4 +161,10 @@ module CommonActions
|
||||
expect(page).to have_selector('.in-favor a', visible: false)
|
||||
end
|
||||
|
||||
def create_featured_proposals
|
||||
[create(:proposal, :with_confidence_score, cached_votes_up: 100),
|
||||
create(:proposal, :with_confidence_score, cached_votes_up: 90),
|
||||
create(:proposal, :with_confidence_score, cached_votes_up: 80)]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user