Merge pull request #3567 from consul/select_proposals_by_admins
Make proposals to be selected by administrators
This commit is contained in:
@@ -6,8 +6,22 @@ class Admin::ProposalsController < Admin::BaseController
|
||||
|
||||
has_orders %w[created_at]
|
||||
|
||||
before_action :load_proposal, except: :index
|
||||
|
||||
def show
|
||||
@proposal = Proposal.find(params[:id])
|
||||
end
|
||||
|
||||
def update
|
||||
if @proposal.update(proposal_params)
|
||||
redirect_to admin_proposal_path(@proposal), notice: t("admin.proposals.update.notice")
|
||||
else
|
||||
render :show
|
||||
end
|
||||
end
|
||||
|
||||
def toggle_selection
|
||||
@proposal.toggle :selected
|
||||
@proposal.save!
|
||||
end
|
||||
|
||||
private
|
||||
@@ -15,4 +29,13 @@ class Admin::ProposalsController < Admin::BaseController
|
||||
def resource_model
|
||||
Proposal
|
||||
end
|
||||
|
||||
def load_proposal
|
||||
@proposal = Proposal.find(params[:id])
|
||||
end
|
||||
|
||||
def proposal_params
|
||||
params.require(:proposal).permit(:selected)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -51,7 +51,9 @@ class ProposalsController < ApplicationController
|
||||
discard_draft
|
||||
discard_archived
|
||||
load_retired
|
||||
load_selected
|
||||
load_featured
|
||||
remove_archived_from_order_links
|
||||
end
|
||||
|
||||
def vote
|
||||
@@ -127,7 +129,9 @@ class ProposalsController < ApplicationController
|
||||
end
|
||||
|
||||
def discard_archived
|
||||
@resources = @resources.not_archived unless @current_order == "archival_date"
|
||||
unless @current_order == "archival_date" || params[:selected].present?
|
||||
@resources = @resources.not_archived
|
||||
end
|
||||
end
|
||||
|
||||
def load_retired
|
||||
@@ -139,6 +143,14 @@ class ProposalsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def load_selected
|
||||
if params[:selected].present?
|
||||
@resources = @resources.selected
|
||||
else
|
||||
@resources = @resources.not_selected
|
||||
end
|
||||
end
|
||||
|
||||
def load_featured
|
||||
return unless !@advanced_search_terms && @search_terms.blank? && @tag_filter.blank? && params[:retired].blank? && @current_order != "recommendations"
|
||||
if Setting["feature.featured_proposals"]
|
||||
@@ -151,6 +163,10 @@ class ProposalsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def remove_archived_from_order_links
|
||||
@valid_orders.delete("archival_date")
|
||||
end
|
||||
|
||||
def set_view
|
||||
@view = (params[:view] == "minimal") ? "minimal" : "default"
|
||||
end
|
||||
|
||||
@@ -11,22 +11,6 @@ module LegislationHelper
|
||||
t("proposals.index.start_proposal")
|
||||
end
|
||||
|
||||
def link_to_toggle_legislation_proposal_selection(proposal)
|
||||
if proposal.selected?
|
||||
button_text = t("admin.legislation.proposals.index.selected")
|
||||
html_class = "button expanded"
|
||||
else
|
||||
button_text = t("admin.legislation.proposals.index.select")
|
||||
html_class = "button hollow expanded"
|
||||
end
|
||||
|
||||
link_to button_text,
|
||||
toggle_selection_admin_legislation_process_proposal_path(proposal.process, proposal),
|
||||
remote: true,
|
||||
method: :patch,
|
||||
class: html_class
|
||||
end
|
||||
|
||||
def legislation_process_tabs(process)
|
||||
{
|
||||
"info" => edit_admin_legislation_process_path(process),
|
||||
|
||||
@@ -64,4 +64,50 @@ module ProposalsHelper
|
||||
proposals_current_view == "default" ? "minimal" : "default"
|
||||
end
|
||||
|
||||
def link_to_toggle_proposal_selection(proposal)
|
||||
if proposal.selected?
|
||||
button_text = t("admin.proposals.index.selected")
|
||||
html_class = "button expanded"
|
||||
else
|
||||
button_text = t("admin.proposals.index.select")
|
||||
html_class = "button hollow expanded"
|
||||
end
|
||||
|
||||
case proposal.class.to_s
|
||||
when "Proposal"
|
||||
path = toggle_selection_admin_proposal_path(proposal)
|
||||
when "Legislation::Proposal"
|
||||
path = toggle_selection_admin_legislation_process_proposal_path(proposal.process, proposal)
|
||||
end
|
||||
|
||||
link_to button_text, path, remote: true, method: :patch, class: html_class
|
||||
end
|
||||
|
||||
def css_for_proposal_info_row(proposal)
|
||||
if proposal.image.present?
|
||||
if params[:selected].present?
|
||||
"small-12 medium-9 column"
|
||||
else
|
||||
"small-12 medium-6 large-7 column"
|
||||
end
|
||||
else
|
||||
if params[:selected].present?
|
||||
"small-12 column"
|
||||
else
|
||||
"small-12 medium-9 column"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def show_proposal_votes?
|
||||
params[:selected].blank?
|
||||
end
|
||||
|
||||
def show_featured_proposals?
|
||||
params[:selected].blank? && @featured_proposals.present?
|
||||
end
|
||||
|
||||
def show_recommended_proposals?
|
||||
params[:selected].blank? && feature?("user.recommendations") && @recommended_proposals.present?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -74,6 +74,8 @@ class Proposal < ApplicationRecord
|
||||
scope :successful, -> { where("cached_votes_up >= ?", Proposal.votes_needed_for_success) }
|
||||
scope :unsuccessful, -> { where("cached_votes_up < ?", Proposal.votes_needed_for_success) }
|
||||
scope :public_for_api, -> { all }
|
||||
scope :selected, -> { where(selected: true) }
|
||||
scope :not_selected, -> { where(selected: false) }
|
||||
scope :not_supported_by_user, ->(user) { where.not(id: user.find_voted_items(votable_type: "Proposal").compact.map(&:id)) }
|
||||
scope :published, -> { where.not(published_at: nil) }
|
||||
scope :draft, -> { where(published_at: nil) }
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<th class="text-center"><%= t("admin.legislation.proposals.index.id") %></th>
|
||||
<th><%= t("admin.legislation.proposals.index.title") %></th>
|
||||
<th class="text-center"><%= t("admin.legislation.proposals.index.supports") %></th>
|
||||
<th><%= t("admin.legislation.proposals.index.selected") %></th>
|
||||
<th><%= t("admin.proposals.index.selected") %></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
<%= link_to_toggle_legislation_proposal_selection(proposal) %>
|
||||
<%= link_to_toggle_proposal_selection(proposal) %>
|
||||
|
||||
9
app/views/admin/proposals/_form.html.erb
Normal file
9
app/views/admin/proposals/_form.html.erb
Normal file
@@ -0,0 +1,9 @@
|
||||
<%= form_for [:admin, @proposal] do |f| %>
|
||||
|
||||
<%= render "shared/errors", resource: @proposal %>
|
||||
|
||||
<%= f.check_box :selected %>
|
||||
|
||||
<%= f.submit t("admin.proposals.form.update"), class: "button success" %>
|
||||
|
||||
<% end %>
|
||||
1
app/views/admin/proposals/_select_proposal.html.erb
Normal file
1
app/views/admin/proposals/_select_proposal.html.erb
Normal file
@@ -0,0 +1 @@
|
||||
<%= link_to_toggle_proposal_selection(proposal) %>
|
||||
@@ -16,6 +16,7 @@
|
||||
<th><%= t("admin.proposals.index.title") %></th>
|
||||
<th><%= t("admin.proposals.index.author") %></th>
|
||||
<th><%= t("admin.proposals.index.milestones") %></th>
|
||||
<th><%= t("admin.proposals.index.selected") %></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -26,6 +27,7 @@
|
||||
<td><%= link_to proposal.title, admin_proposal_path(proposal) %></td>
|
||||
<td><%= proposal.author.username %></td>
|
||||
<td><%= proposal.milestones.count %></td>
|
||||
<td class="js-select"><%= render "select_proposal", proposal: proposal %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
|
||||
@@ -26,4 +26,10 @@
|
||||
<%= render "proposals/info", proposal: @proposal %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 column">
|
||||
<hr>
|
||||
<%= render "form" %>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<%= render "admin/milestones/milestones", milestoneable: @proposal %>
|
||||
|
||||
1
app/views/admin/proposals/toggle_selection.js.erb
Normal file
1
app/views/admin/proposals/toggle_selection.js.erb
Normal file
@@ -0,0 +1 @@
|
||||
$("#<%= dom_id(@proposal) %> .js-select").html('<%= j render("select_proposal", proposal: @proposal) %>');
|
||||
@@ -1,6 +0,0 @@
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2 class="sidebar-title"><%= t("proposals.index.top") %></h2>
|
||||
|
||||
<p>
|
||||
<%= link_to t("proposals.index.top_link_proposals"), summary_proposals_path, class: "small" %><br>
|
||||
</p>
|
||||
@@ -12,10 +12,10 @@
|
||||
alt: proposal.image.title.unicode_normalize %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-6 large-7 column">
|
||||
<div class="<%= css_for_proposal_info_row(proposal) %>">
|
||||
<% else %>
|
||||
<div class="row">
|
||||
<div class="small-12 medium-9 column">
|
||||
<div class="<%= css_for_proposal_info_row(proposal) %>">
|
||||
<% end %>
|
||||
<div class="proposal-content">
|
||||
<% cache [locale_and_user_status(proposal), "index", proposal, proposal.author] do %>
|
||||
@@ -62,24 +62,27 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="<%= dom_id(proposal) %>_votes"
|
||||
class="small-12 medium-3 column supports-container">
|
||||
<% if proposal.successful? %>
|
||||
<div class="padding text-center">
|
||||
<p>
|
||||
<%= t("proposals.proposal.successful") %>
|
||||
</p>
|
||||
</div>
|
||||
<% elsif proposal.archived? %>
|
||||
<div class="padding text-center">
|
||||
<strong><%= t("proposals.proposal.supports", count: proposal.total_votes) %></strong>
|
||||
<p><%= t("proposals.proposal.archived") %></p>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= render "votes",
|
||||
{ proposal: proposal, vote_url: vote_proposal_path(proposal, value: "yes") } %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% if show_proposal_votes? %>
|
||||
<div id="<%= dom_id(proposal) %>_votes"
|
||||
class="small-12 medium-3 column supports-container">
|
||||
<% if proposal.successful? %>
|
||||
<div class="padding">
|
||||
<div class="supports text-center">
|
||||
<%= render "proposals/supports", proposal: proposal %>
|
||||
</div>
|
||||
</div>
|
||||
<% elsif proposal.archived? %>
|
||||
<div class="padding text-center">
|
||||
<strong><%= t("proposals.proposal.supports", count: proposal.total_votes) %></strong>
|
||||
<p><%= t("proposals.proposal.archived") %></p>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= render "votes",
|
||||
{ proposal: proposal, vote_url: vote_proposal_path(proposal, value: "yes") } %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
16
app/views/proposals/_proposals_lists.html.erb
Normal file
16
app/views/proposals/_proposals_lists.html.erb
Normal file
@@ -0,0 +1,16 @@
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2 class="sidebar-title"><%= t("proposals.index.proposals_lists") %></h2>
|
||||
|
||||
<p>
|
||||
<%= link_to t("proposals.index.top_link_proposals"),
|
||||
summary_proposals_path,
|
||||
class: "small" %>
|
||||
<br>
|
||||
<%= link_to t("proposals.index.archived_proposals"),
|
||||
proposals_path(order: "archival_date"),
|
||||
class: "small" %>
|
||||
<br>
|
||||
<%= link_to t("proposals.index.retired_proposals_link"),
|
||||
proposals_path(retired: "all"),
|
||||
class: "small" %>
|
||||
</p>
|
||||
@@ -1,9 +1,7 @@
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2 class="sidebar-title"><%= t("proposals.index.retired_proposals") %></h2>
|
||||
<% if params[:retired].present? %>
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2 class="sidebar-title"><%= t("proposals.index.retired_proposals") %></h2>
|
||||
|
||||
<% if params[:retired].blank? %>
|
||||
<p><%= link_to t("proposals.index.retired_proposals_link"), proposals_path(retired: "all"), class: "small" %></p>
|
||||
<% else %>
|
||||
<div class="sidebar-links">
|
||||
<%= link_to t("proposals.index.retired_links.all"), proposals_path(retired: "all") %>
|
||||
<% Proposal::RETIRE_OPTIONS.each do |option| %>
|
||||
|
||||
16
app/views/proposals/_supports.html.erb
Normal file
16
app/views/proposals/_supports.html.erb
Normal file
@@ -0,0 +1,16 @@
|
||||
<div class="progress small-12 round">
|
||||
<span class="meter" style="width: <%= progress_bar_percentage(proposal) %>%;"></span>
|
||||
<span class="percentage">
|
||||
<%= supports_percentage(proposal) %> / <%= t("proposals.proposal.total_percent") %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<span class="total-supports">
|
||||
<%= t("proposals.proposal.supports", count: proposal.total_votes) %>
|
||||
<span>
|
||||
<abbr title="<%= t("proposals.proposal.reason_for_supports_necessary") %>">
|
||||
<%= t("proposals.proposal.supports_necessary",
|
||||
number: number_with_delimiter(Proposal.votes_needed_for_success)) %>
|
||||
</abbr>
|
||||
</span>
|
||||
</span>
|
||||
@@ -1,20 +1,5 @@
|
||||
<div class="supports text-center">
|
||||
<div class="progress small-12 round">
|
||||
<span class="meter" style="width: <%= progress_bar_percentage(proposal) %>%;"></span>
|
||||
<span class="percentage">
|
||||
<%= supports_percentage(proposal) %> / <%= t("proposals.proposal.total_percent") %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<span class="total-supports">
|
||||
<%= t("proposals.proposal.supports", count: proposal.total_votes) %>
|
||||
<span>
|
||||
<abbr>
|
||||
<%= t("proposals.proposal.supports_necessary",
|
||||
number: number_with_delimiter(Proposal.votes_needed_for_success)) %>
|
||||
</abbr>
|
||||
</span>
|
||||
</span>
|
||||
<%= render "proposals/supports", proposal: proposal %>
|
||||
|
||||
<div class="in-favor">
|
||||
<% if voted_for?(@proposal_votes, proposal) %>
|
||||
|
||||
@@ -9,7 +9,13 @@
|
||||
<% end %>
|
||||
|
||||
<main>
|
||||
<% if @search_terms || @advanced_search_terms || @tag_filter || params[:retired].present? %>
|
||||
<% if [
|
||||
@search_terms,
|
||||
@advanced_search_terms,
|
||||
@tag_filter,
|
||||
params[:retired].present?,
|
||||
params[:selected].present?
|
||||
].any? %>
|
||||
<div class="highlight no-margin-top padding margin-bottom">
|
||||
<div class="row">
|
||||
<div class="small-12 column">
|
||||
@@ -29,6 +35,8 @@
|
||||
</p>
|
||||
<% elsif params[:retired].present? %>
|
||||
<h2><%= t("proposals.index.retired_proposals") %></h2>
|
||||
<% elsif params[:selected].present? %>
|
||||
<h2><%= t("proposals.index.selected_proposals") %></h2>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -37,7 +45,7 @@
|
||||
<%= render "shared/section_header", i18n_namespace: "proposals.index.section_header", image: "proposals" %>
|
||||
<% end %>
|
||||
|
||||
<% if feature?("user.recommendations") && @recommended_proposals.present? %>
|
||||
<% if show_recommended_proposals? %>
|
||||
<%= render "shared/recommended_index", recommended: @recommended_proposals,
|
||||
disable_recommendations_path: recommendations_disable_proposals_path,
|
||||
namespace: "proposals" %>
|
||||
@@ -50,7 +58,7 @@
|
||||
<%= render "shared/banner" %>
|
||||
<% end %>
|
||||
|
||||
<% if @featured_proposals.present? %>
|
||||
<% if show_featured_proposals? %>
|
||||
<div id="featured-proposals" class="row featured-proposals">
|
||||
<div class="small-12 column">
|
||||
<h2>
|
||||
@@ -69,9 +77,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render("shared/advanced_search", search_path: proposals_path(page: 1)) unless params[:retired].present? %>
|
||||
<% unless params[:retired].present? || params[:selected].present? %>
|
||||
<%= render "shared/advanced_search",
|
||||
search_path: proposals_path(page: 1) %>
|
||||
<% end %>
|
||||
|
||||
<%= render "shared/order_links", i18n_namespace: "proposals.index" %>
|
||||
<% unless params[:selected].present? %>
|
||||
<%= render "shared/order_links", i18n_namespace: "proposals.index" %>
|
||||
<% end %>
|
||||
|
||||
<% if @proposals.any? %>
|
||||
<div class="show-for-small-only">
|
||||
@@ -111,13 +124,21 @@
|
||||
<%= link_to t("proposals.index.start_proposal"),
|
||||
new_proposal_path,
|
||||
class: "button expanded" %>
|
||||
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2 class="sidebar-title"><%= t("proposals.index.selected_proposals") %></h2>
|
||||
<br>
|
||||
<p class="small">
|
||||
<%= link_to t("proposals.index.selected_proposals_link"), proposals_path(selected: "all") %>
|
||||
</p>
|
||||
|
||||
<% if params[:retired].blank? %>
|
||||
<%= render "categories" %>
|
||||
<%= render "shared/tag_cloud", taggable: "proposal" %>
|
||||
<%= render "geozones" %>
|
||||
<%= render "popular" %>
|
||||
<% end %>
|
||||
<%= render "retired" %>
|
||||
<%= render "proposals_lists" %>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -62,44 +62,50 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div id="proposal_sticky" data-sticky-container>
|
||||
<div class="sticky fixed-mobile-content"
|
||||
data-sticky
|
||||
data-stick-to="bottom"
|
||||
data-sticky-on="small"
|
||||
data-top-anchor="0"
|
||||
data-btm-anchor="sticky_stop"
|
||||
data-check-every="0">
|
||||
<div class="fixed-mobile-content">
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("votes.supports") %></h2>
|
||||
<% if @proposal.selected? %>
|
||||
<div class="callout success">
|
||||
<strong><%= t("proposals.proposal.selected") %></strong>
|
||||
</div>
|
||||
<% else %>
|
||||
<div id="proposal_sticky" data-sticky-container>
|
||||
<div class="sticky fixed-mobile-content"
|
||||
data-sticky
|
||||
data-stick-to="bottom"
|
||||
data-sticky-on="small"
|
||||
data-top-anchor="0"
|
||||
data-btm-anchor="sticky_stop"
|
||||
data-check-every="0">
|
||||
<div class="fixed-mobile-content">
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("votes.supports") %></h2>
|
||||
|
||||
<div id="<%= dom_id(@proposal) %>_votes">
|
||||
<% if @proposal.draft? %>
|
||||
<div class="callout primary">
|
||||
<p class=text-center><strong><%= t('.draft') %></strong></p>
|
||||
</div>
|
||||
<% elsif @proposal.successful? %>
|
||||
<p>
|
||||
<%= t("proposals.proposal.successful") %>
|
||||
</p>
|
||||
<% elsif @proposal.archived? %>
|
||||
<div class="padding text-center">
|
||||
<p>
|
||||
<strong><%= t("proposals.proposal.supports", count: @proposal.total_votes) %></strong>
|
||||
</p>
|
||||
<p><%= t("proposals.proposal.archived") %></p>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= render "votes",
|
||||
{ proposal: @proposal, vote_url: vote_proposal_path(@proposal, value: "yes") } %>
|
||||
<% end %>
|
||||
<div id="<%= dom_id(@proposal) %>_votes">
|
||||
<% if @proposal.draft? %>
|
||||
<div class="callout primary">
|
||||
<p class=text-center><strong><%= t(".draft") %></strong></p>
|
||||
</div>
|
||||
<% elsif @proposal.successful? %>
|
||||
<div class="supports text-center">
|
||||
<%= render "supports", proposal: @proposal %>
|
||||
</div>
|
||||
<% elsif @proposal.archived? %>
|
||||
<div class="padding text-center">
|
||||
<p>
|
||||
<strong><%= t("proposals.proposal.supports", count: @proposal.total_votes) %></strong>
|
||||
</p>
|
||||
<p><%= t("proposals.proposal.archived") %></p>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= render "votes",
|
||||
{ proposal: @proposal, vote_url: vote_proposal_path(@proposal, value: "yes") } %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="sticky_stop"></div>
|
||||
<div id="sticky_stop"></div>
|
||||
<% end %>
|
||||
|
||||
<%= render "proposals/social_share", proposal: @proposal, share_title: t("proposals.show.share") %>
|
||||
|
||||
|
||||
@@ -187,6 +187,7 @@ en:
|
||||
title: "Title"
|
||||
question: "Question"
|
||||
description: "Description"
|
||||
selected: "Mark as selected"
|
||||
terms_of_service: "Terms of service"
|
||||
user:
|
||||
login: "Email or username"
|
||||
|
||||
@@ -556,8 +556,6 @@ en:
|
||||
id: Id
|
||||
title: Title
|
||||
supports: Total supports
|
||||
select: Select
|
||||
selected: Selected
|
||||
form:
|
||||
custom_categories: Categories
|
||||
custom_categories_description: Categories that users can select creating the proposal. Max 160 characteres.
|
||||
@@ -1239,10 +1237,16 @@ en:
|
||||
title: Proposals
|
||||
id: ID
|
||||
author: Author
|
||||
select: Select
|
||||
selected: Selected
|
||||
milestones: Milestones
|
||||
no_proposals: There are no proposals.
|
||||
show:
|
||||
create_question: Add this proposal to a poll to be voted
|
||||
form:
|
||||
update: Update proposal
|
||||
update:
|
||||
notice: Proposal updated successfully
|
||||
hidden_proposals:
|
||||
index:
|
||||
filter: Filter
|
||||
|
||||
@@ -376,6 +376,10 @@ en:
|
||||
error: "An error has occured. Please go to 'My account' page to manually disable recommendations for proposals"
|
||||
retired_proposals: Retired proposals
|
||||
retired_proposals_link: "Proposals retired by the author"
|
||||
selected_proposals: Selected proposals
|
||||
selected_proposals_link: View selected proposals
|
||||
archived_proposals: Archived proposals
|
||||
proposals_lists: Proposals lists
|
||||
retired_links:
|
||||
all: All
|
||||
duplicated: Duplicated
|
||||
@@ -437,9 +441,11 @@ en:
|
||||
other: "%{count} votes"
|
||||
zero: No votes
|
||||
supports_necessary: "%{number} supports needed"
|
||||
reason_for_supports_necessary: ""
|
||||
total_percent: 100%
|
||||
archived: "This proposal has been archived and can't collect supports."
|
||||
successful: "This proposal has reached the required supports."
|
||||
selected: "Selected proposal"
|
||||
show:
|
||||
author_deleted: User deleted
|
||||
code: "Proposal code:"
|
||||
|
||||
@@ -187,6 +187,7 @@ es:
|
||||
title: "Título"
|
||||
question: "Pregunta"
|
||||
description: "Descripción"
|
||||
selected: "Marcar como seleccionada"
|
||||
terms_of_service: "Términos de servicio"
|
||||
user:
|
||||
login: "Email o nombre de usuario"
|
||||
|
||||
@@ -555,8 +555,6 @@ es:
|
||||
back: Volver
|
||||
id: Id
|
||||
supports: Apoyos totales
|
||||
select: Seleccionar
|
||||
selected: Seleccionada
|
||||
form:
|
||||
custom_categories: Categorías
|
||||
custom_categories_description: Categorías que el usuario puede seleccionar al crear la propuesta. Máximo 160 caracteres.
|
||||
@@ -1239,9 +1237,15 @@ es:
|
||||
id: ID
|
||||
author: Autor
|
||||
milestones: Hitos
|
||||
select: Seleccionar
|
||||
selected: Seleccionada
|
||||
no_proposals: No hay propuestas.
|
||||
show:
|
||||
create_question: Añadir esta propuesta a una votación para ser votada
|
||||
form:
|
||||
update: Actualizar propuesta ciudadana
|
||||
update:
|
||||
notice: Propuesta actualizada correctamente
|
||||
hidden_proposals:
|
||||
index:
|
||||
filter: Filtro
|
||||
|
||||
@@ -376,6 +376,10 @@ es:
|
||||
error: "Ha ocurrido un error. Por favor dirígete al apartado 'Mi cuenta' para desactivar las recomendaciones manualmente"
|
||||
retired_proposals: Propuestas retiradas
|
||||
retired_proposals_link: "Propuestas retiradas por sus autores"
|
||||
selected_proposals: Propuestas seleccionadas
|
||||
selected_proposals_link: Ver propuestas seleccionadas
|
||||
archived_proposals: Propuestas archivadas
|
||||
proposals_lists: Listas de propuestas
|
||||
retired_links:
|
||||
all: Todas
|
||||
duplicated: Duplicadas
|
||||
@@ -437,9 +441,11 @@ es:
|
||||
one: 1 voto
|
||||
other: "%{count} votos"
|
||||
supports_necessary: "%{number} apoyos necesarios"
|
||||
reason_for_supports_necessary: ""
|
||||
total_percent: 100%
|
||||
archived: "Esta propuesta ha sido archivada y ya no puede recoger apoyos."
|
||||
successful: "Esta propuesta ha alcanzado los apoyos necesarios."
|
||||
selected: "Propuesta seleccionada"
|
||||
show:
|
||||
author_deleted: Usuario eliminado
|
||||
code: "Código de la propuesta:"
|
||||
|
||||
@@ -29,7 +29,8 @@ namespace :admin do
|
||||
end
|
||||
end
|
||||
|
||||
resources :proposals, only: [:index, :show] do
|
||||
resources :proposals, only: [:index, :show, :update] do
|
||||
member { patch :toggle_selection }
|
||||
resources :milestones, controller: "proposal_milestones"
|
||||
resources :progress_bars, except: :show, controller: "proposal_progress_bars"
|
||||
end
|
||||
|
||||
5
db/migrate/20190410132842_add_selected_to_proposal.rb
Normal file
5
db/migrate/20190410132842_add_selected_to_proposal.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
class AddSelectedToProposal < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :proposals, :selected, :bool, default: false, index: true
|
||||
end
|
||||
end
|
||||
@@ -1194,6 +1194,7 @@ ActiveRecord::Schema.define(version: 20190429125842) do
|
||||
t.text "retired_explanation"
|
||||
t.integer "community_id"
|
||||
t.datetime "published_at"
|
||||
t.boolean "selected", default: false
|
||||
t.index ["author_id", "hidden_at"], name: "index_proposals_on_author_id_and_hidden_at", using: :btree
|
||||
t.index ["author_id"], name: "index_proposals_on_author_id", using: :btree
|
||||
t.index ["cached_votes_up"], name: "index_proposals_on_cached_votes_up", using: :btree
|
||||
|
||||
@@ -33,6 +33,10 @@ FactoryBot.define do
|
||||
created_at { 25.months.ago }
|
||||
end
|
||||
|
||||
trait :selected do
|
||||
selected true
|
||||
end
|
||||
|
||||
trait :with_hot_score do
|
||||
before(:save) { |d| d.calculate_hot_score }
|
||||
end
|
||||
|
||||
@@ -10,6 +10,7 @@ describe "Admin proposals" do
|
||||
"admin_proposal_path"
|
||||
|
||||
context "Index" do
|
||||
|
||||
scenario "Search" do
|
||||
create(:proposal, title: "Make Pluto a planet again")
|
||||
create(:proposal, title: "Build a monument to honour CONSUL developers")
|
||||
@@ -26,6 +27,29 @@ describe "Admin proposals" do
|
||||
expect(page).to have_content "Make Pluto a planet again"
|
||||
expect(page).not_to have_content "Build a monument"
|
||||
end
|
||||
|
||||
scenario "Select a proposal", :js do
|
||||
proposal = create(:proposal)
|
||||
|
||||
visit admin_proposals_path
|
||||
|
||||
within("#proposal_#{proposal.id}") { click_link "Select" }
|
||||
|
||||
within("#proposal_#{proposal.id}") { expect(page).to have_link "Selected" }
|
||||
expect(proposal.reload.selected?).to be true
|
||||
end
|
||||
|
||||
scenario "Unselect a proposal", :js do
|
||||
proposal = create(:proposal, :selected)
|
||||
|
||||
visit admin_proposals_path
|
||||
|
||||
within("#proposal_#{proposal.id}") { click_link "Selected" }
|
||||
|
||||
within("#proposal_#{proposal.id}") { expect(page).to have_link "Select" }
|
||||
expect(proposal.reload.selected?).to be false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "Show" do
|
||||
@@ -55,5 +79,32 @@ describe "Admin proposals" do
|
||||
expect(page).to have_link "Add this proposal to a poll to be voted"
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Select a proposal" do
|
||||
proposal = create(:proposal)
|
||||
|
||||
visit admin_proposal_path(proposal)
|
||||
|
||||
check "Mark as selected"
|
||||
click_button "Update proposal"
|
||||
|
||||
expect(page).to have_content "Proposal updated successfully"
|
||||
expect(find_field("Mark as selected")).to be_checked
|
||||
expect(proposal.reload.selected?).to be true
|
||||
end
|
||||
|
||||
scenario "Unselect a proposal" do
|
||||
proposal = create(:proposal, :selected)
|
||||
|
||||
visit admin_proposal_path(proposal)
|
||||
|
||||
uncheck "Mark as selected"
|
||||
click_button "Update proposal"
|
||||
|
||||
expect(page).to have_content "Proposal updated successfully"
|
||||
expect(find_field("Mark as selected")).not_to be_checked
|
||||
expect(proposal.reload.selected?).to be false
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,8 +9,8 @@ describe "Proposal ballots" do
|
||||
visit proposals_path
|
||||
|
||||
successful_proposals.each do |proposal|
|
||||
within("#proposal_#{proposal.id}_votes") do
|
||||
expect(page).to have_content "This proposal has reached the required supports"
|
||||
within("#proposal_#{proposal.id}_votes .supports .progress") do
|
||||
expect(page).to have_content "100% / 100%"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -20,8 +20,8 @@ describe "Proposal ballots" do
|
||||
|
||||
successful_proposals.each do |proposal|
|
||||
visit proposal_path(proposal)
|
||||
within("#proposal_#{proposal.id}_votes") do
|
||||
expect(page).to have_content "This proposal has reached the required supports"
|
||||
within("#proposal_#{proposal.id}_votes .supports .progress") do
|
||||
expect(page).to have_content "100% / 100%"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -833,12 +833,12 @@ describe "Proposals" do
|
||||
|
||||
describe "Archived proposals" do
|
||||
|
||||
scenario "show on archived tab" do
|
||||
scenario "show on proposals list" do
|
||||
create_featured_proposals
|
||||
archived_proposals = create_archived_proposals
|
||||
|
||||
visit proposals_path
|
||||
click_link "archived"
|
||||
click_link "Archived proposals"
|
||||
|
||||
within("#proposals-list") do
|
||||
archived_proposals.each do |proposal|
|
||||
@@ -906,7 +906,7 @@ describe "Proposals" do
|
||||
expect(page).not_to have_content(archived_proposal.title)
|
||||
end
|
||||
|
||||
click_link "archived"
|
||||
click_link "Archived proposals"
|
||||
|
||||
within("#featured-proposals") do
|
||||
expect(page).to have_content(featured_proposal.title)
|
||||
@@ -924,7 +924,7 @@ describe "Proposals" do
|
||||
create(:proposal, :archived, title: "Some votes").update_column(:confidence_score, 25)
|
||||
|
||||
visit proposals_path
|
||||
click_link "archived"
|
||||
click_link "Archived proposals"
|
||||
|
||||
within("#proposals-list") do
|
||||
expect(all(".proposal")[0].text).to match "Most voted"
|
||||
@@ -935,6 +935,96 @@ describe "Proposals" do
|
||||
|
||||
end
|
||||
|
||||
context "Selected Proposals" do
|
||||
let!(:selected_proposal) { create(:proposal, :selected) }
|
||||
let!(:not_selected_proposal) { create(:proposal) }
|
||||
|
||||
scenario "do not show in index by default" do
|
||||
visit proposals_path
|
||||
|
||||
expect(page).to have_selector("#proposals .proposal", count: 1)
|
||||
expect(page).to have_content not_selected_proposal.title
|
||||
expect(page).not_to have_content selected_proposal.title
|
||||
end
|
||||
|
||||
scenario "show in selected proposals list" do
|
||||
visit proposals_path
|
||||
click_link "View selected proposals"
|
||||
|
||||
expect(page).to have_selector("#proposals .proposal", count: 1)
|
||||
expect(page).to have_content selected_proposal.title
|
||||
expect(page).not_to have_content not_selected_proposal.title
|
||||
end
|
||||
|
||||
scenario "show a selected proposal message in show view" do
|
||||
visit proposal_path(selected_proposal)
|
||||
|
||||
within("aside") { expect(page).not_to have_content "SUPPORTS" }
|
||||
within("aside") { expect(page).to have_content "Selected proposal" }
|
||||
end
|
||||
|
||||
scenario "do not show featured proposal in selected proposals list" do
|
||||
Setting["feature.featured_proposals"] = true
|
||||
create_featured_proposals
|
||||
|
||||
visit proposals_path
|
||||
|
||||
expect(page).to have_selector("#proposals .proposal-featured")
|
||||
expect(page).to have_selector("#featured-proposals")
|
||||
|
||||
click_link "View selected proposals"
|
||||
|
||||
expect(page).not_to have_selector("#proposals .proposal-featured")
|
||||
expect(page).not_to have_selector("#featured-proposals")
|
||||
end
|
||||
|
||||
scenario "do not show recommented proposal in selected proposals list" do
|
||||
create(:proposal, title: "Recommended", cached_votes_up: 10, tag_list: "Economy")
|
||||
|
||||
user = create(:user)
|
||||
create(:follow, followable: create(:proposal, tag_list: "Economy"), user: user)
|
||||
|
||||
login_as(user)
|
||||
visit proposals_path
|
||||
|
||||
expect(page).to have_css(".recommendation", count: 1)
|
||||
expect(page).to have_link "Recommended"
|
||||
expect(page).to have_link "See more recommendations"
|
||||
|
||||
click_link "View selected proposals"
|
||||
|
||||
expect(page).not_to have_css ".recommendation"
|
||||
expect(page).not_to have_link "Recommended"
|
||||
expect(page).not_to have_link "See more recommendations"
|
||||
end
|
||||
|
||||
scenario "do not show order links in selected proposals list" do
|
||||
visit proposals_path
|
||||
|
||||
expect(page).to have_css "ul.submenu"
|
||||
expect(page).to have_link "most active"
|
||||
expect(page).to have_link "highest rated"
|
||||
expect(page).to have_link "newest"
|
||||
|
||||
click_link "View selected proposals"
|
||||
|
||||
expect(page).not_to have_css "ul.submenu"
|
||||
expect(page).not_to have_link "most active"
|
||||
expect(page).not_to have_link "highest rated"
|
||||
expect(page).not_to have_link "newest"
|
||||
end
|
||||
|
||||
scenario "show archived proposals in selected proposals list" do
|
||||
archived_proposal = create(:proposal, :selected, :archived)
|
||||
|
||||
visit proposals_path
|
||||
expect(page).not_to have_content archived_proposal.title
|
||||
|
||||
click_link "View selected proposals"
|
||||
expect(page).to have_content archived_proposal.title
|
||||
end
|
||||
end
|
||||
|
||||
context "Search" do
|
||||
|
||||
context "Basic search" do
|
||||
@@ -1754,8 +1844,8 @@ describe "Successful proposals" do
|
||||
|
||||
successful_proposals.each do |proposal|
|
||||
within("#proposal_#{proposal.id}_votes") do
|
||||
expect(page).not_to have_css(".supports")
|
||||
expect(page).to have_content "This proposal has reached the required supports"
|
||||
expect(page).not_to have_link "Support"
|
||||
expect(page).to have_content "100% / 100%"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1766,8 +1856,8 @@ describe "Successful proposals" do
|
||||
successful_proposals.each do |proposal|
|
||||
visit proposal_path(proposal)
|
||||
within("#proposal_#{proposal.id}_votes") do
|
||||
expect(page).not_to have_css(".supports")
|
||||
expect(page).to have_content "This proposal has reached the required supports"
|
||||
expect(page).not_to have_link "Support"
|
||||
expect(page).to have_content "100% / 100%"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -866,6 +866,30 @@ describe Proposal do
|
||||
end
|
||||
end
|
||||
|
||||
describe "selected" do
|
||||
let!(:not_selected_proposal) { create(:proposal) }
|
||||
let!(:selected_proposal) { create(:proposal, :selected) }
|
||||
|
||||
it "selected? is true" do
|
||||
expect(not_selected_proposal.selected?).to be false
|
||||
expect(selected_proposal.selected?).to be true
|
||||
end
|
||||
|
||||
it "scope selected" do
|
||||
selected = Proposal.selected
|
||||
|
||||
expect(selected.size).to be 1
|
||||
expect(selected.first).to eq selected_proposal
|
||||
end
|
||||
|
||||
it "scope not_selected" do
|
||||
not_selected = Proposal.not_selected
|
||||
|
||||
expect(not_selected.size).to be 1
|
||||
expect(not_selected.first).to eq not_selected_proposal
|
||||
end
|
||||
end
|
||||
|
||||
describe "public_for_api scope" do
|
||||
it "returns proposals" do
|
||||
proposal = create(:proposal)
|
||||
|
||||
Reference in New Issue
Block a user