@@ -7,6 +7,7 @@
|
||||
@import 'layout';
|
||||
@import 'participation';
|
||||
@import 'pages';
|
||||
@import 'proposal';
|
||||
@import 'legislation';
|
||||
@import 'legislation_process';
|
||||
@import 'community';
|
||||
|
||||
11
app/assets/stylesheets/proposal.scss
Normal file
11
app/assets/stylesheets/proposal.scss
Normal file
@@ -0,0 +1,11 @@
|
||||
.proposal-show {
|
||||
p.centered {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.centered {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,21 @@ class Management::ProposalsController < Management::BaseController
|
||||
has_orders %w{confidence_score hot_score created_at most_commented random}, only: [:index, :print]
|
||||
has_orders %w{most_voted newest}, only: :show
|
||||
|
||||
def create
|
||||
@resource = resource_model.new(strong_params.merge(author: current_user, published_at: Time.now))
|
||||
|
||||
if @resource.save
|
||||
track_event
|
||||
redirect_path = url_for(controller: controller_name, action: :show, id: @resource.id)
|
||||
redirect_to redirect_path, notice: t("flash.actions.create.#{resource_name.underscore}")
|
||||
else
|
||||
load_categories
|
||||
load_geozones
|
||||
set_resource_instance
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
super
|
||||
@notifications = @proposal.notifications
|
||||
@@ -37,7 +52,8 @@ class Management::ProposalsController < Management::BaseController
|
||||
|
||||
def proposal_params
|
||||
params.require(:proposal).permit(:title, :question, :summary, :description, :external_url, :video_url,
|
||||
:responsible_name, :tag_list, :terms_of_service, :geozone_id)
|
||||
:responsible_name, :tag_list, :terms_of_service, :geozone_id, :skip_map,
|
||||
map_location_attributes: [:latitude, :longitude, :zoom])
|
||||
end
|
||||
|
||||
def resource_model
|
||||
|
||||
@@ -35,13 +35,16 @@ class ProposalsController < ApplicationController
|
||||
@proposal = Proposal.new(proposal_params.merge(author: current_user))
|
||||
|
||||
if @proposal.save
|
||||
redirect_to share_proposal_path(@proposal), notice: I18n.t('flash.actions.create.proposal')
|
||||
redirect_to created_proposal_path(@proposal), notice: I18n.t('flash.actions.create.proposal')
|
||||
else
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def created; end
|
||||
|
||||
def index_customization
|
||||
discard_draft
|
||||
discard_archived
|
||||
load_retired
|
||||
load_successful_proposals
|
||||
@@ -88,6 +91,11 @@ class ProposalsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def publish
|
||||
@proposal.publish
|
||||
redirect_to share_proposal_path(@proposal), notice: t('proposals.notice.published')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def proposal_params
|
||||
@@ -116,6 +124,10 @@ class ProposalsController < ApplicationController
|
||||
@featured_proposals_votes = current_user ? current_user.proposal_votes(proposals) : {}
|
||||
end
|
||||
|
||||
def discard_draft
|
||||
@resources = @resources.published
|
||||
end
|
||||
|
||||
def discard_archived
|
||||
@resources = @resources.not_archived unless @current_order == "archival_date"
|
||||
end
|
||||
@@ -158,5 +170,4 @@ class ProposalsController < ApplicationController
|
||||
@recommended_proposals = Proposal.recommendations(current_user).sort_by_random.limit(3)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -13,7 +13,7 @@ class UsersController < ApplicationController
|
||||
|
||||
def set_activity_counts
|
||||
@activity_counts = HashWithIndifferentAccess.new(
|
||||
proposals: Proposal.where(author_id: @user.id).count,
|
||||
proposals: Proposal.created_by(@user).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,
|
||||
@@ -52,7 +52,7 @@ class UsersController < ApplicationController
|
||||
end
|
||||
|
||||
def load_proposals
|
||||
@proposals = Proposal.where(author_id: @user.id).order(created_at: :desc).page(params[:page])
|
||||
@proposals = Proposal.created_by(@user).order(created_at: :desc).page(params[:page])
|
||||
end
|
||||
|
||||
def load_debates
|
||||
|
||||
@@ -5,7 +5,7 @@ module Abilities
|
||||
def initialize(user)
|
||||
merge Abilities::Everyone.new(user)
|
||||
|
||||
can [:read, :update], User, id: user.id
|
||||
can %i[read update], User, id: user.id
|
||||
|
||||
can :read, Debate
|
||||
can :update, Debate do |debate|
|
||||
@@ -16,6 +16,10 @@ module Abilities
|
||||
can :update, Proposal do |proposal|
|
||||
proposal.editable_by?(user)
|
||||
end
|
||||
can :publish, Proposal do |proposal|
|
||||
proposal.draft? && proposal.author.id == user.id
|
||||
end
|
||||
|
||||
can [:retire_form, :retire], Proposal, author_id: user.id
|
||||
|
||||
can :read, Legislation::Proposal
|
||||
@@ -26,7 +30,7 @@ module Abilities
|
||||
|
||||
can :create, Comment
|
||||
can :create, Debate
|
||||
can :create, Proposal
|
||||
can %i[create created], Proposal
|
||||
can :create, Legislation::Proposal
|
||||
|
||||
can :suggest, Debate
|
||||
@@ -60,7 +64,9 @@ module Abilities
|
||||
end
|
||||
|
||||
if user.level_two_or_three_verified?
|
||||
can :vote, Proposal
|
||||
can :vote, Proposal do |proposal|
|
||||
proposal.published?
|
||||
end
|
||||
can :vote_featured, Proposal
|
||||
can :vote, SpendingProposal
|
||||
can :create, SpendingProposal
|
||||
|
||||
@@ -71,11 +71,26 @@ class Proposal < ActiveRecord::Base
|
||||
scope :unsuccessful, -> { where("cached_votes_up < ?", Proposal.votes_needed_for_success) }
|
||||
scope :public_for_api, -> { all }
|
||||
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) }
|
||||
scope :created_by, ->(author) { unscoped.where(hidden_at: nil, author: author) }
|
||||
|
||||
def url
|
||||
proposal_path(self)
|
||||
end
|
||||
|
||||
def publish
|
||||
update(published_at: Time.now)
|
||||
end
|
||||
|
||||
def published?
|
||||
!published_at.nil?
|
||||
end
|
||||
|
||||
def draft?
|
||||
published_at.nil?
|
||||
end
|
||||
|
||||
def self.recommendations(user)
|
||||
tagged_with(user.interests, any: true)
|
||||
.where("author_id != ?", user.id)
|
||||
|
||||
12
app/views/proposals/created.html.erb
Normal file
12
app/views/proposals/created.html.erb
Normal file
@@ -0,0 +1,12 @@
|
||||
<div class=proposal-created>
|
||||
<div id="<%= dom_id(@proposal) %>" class="row">
|
||||
<div class="small-12 medium-12 column">
|
||||
<h1><%= t '.title' %></h1>
|
||||
|
||||
<%= raw t '.motivation' %>
|
||||
|
||||
<%= link_to t('.dashboard'), '#', class: 'button' %>
|
||||
<%= link_to t('.publish'), publish_proposal_path(@proposal), method: :patch, class: 'button' if can? :publish, @proposal %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -27,6 +27,15 @@
|
||||
description: @proposal.summary
|
||||
} %>
|
||||
|
||||
<div class="callout light">
|
||||
<p class="centered">
|
||||
<strong><%= t '.improve_it' %></strong>
|
||||
</p>
|
||||
<div class="centered">
|
||||
<%= link_to t('.dashboard'), '#', class: 'button' %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if @proposal_improvement_path.present? %>
|
||||
<div class="callout highlight margin-top text-center">
|
||||
<p class="lead"><strong><%= t("proposals.proposal.improve_info") %></strong></p>
|
||||
|
||||
@@ -165,34 +165,35 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("votes.supports") %></h2>
|
||||
<div id="<%= dom_id(@proposal) %>_votes">
|
||||
|
||||
<% if @proposal.successful? %>
|
||||
<p>
|
||||
<%= t("proposals.proposal.successful",
|
||||
voting: link_to(t("proposals.proposal.voting"), polls_path)).html_safe %>
|
||||
</p>
|
||||
<% if can? :create, Poll::Question %>
|
||||
<p class="text-center">
|
||||
<%= link_to t('poll_questions.create_question'),
|
||||
new_admin_question_path(proposal_id: @proposal.id),
|
||||
class: "button hollow expanded" %>
|
||||
</p>
|
||||
<% end %>
|
||||
<% elsif @proposal.archived? %>
|
||||
<div class="padding text-center">
|
||||
<% if @proposal.published? %>
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("votes.supports") %></h2>
|
||||
<div id="<%= dom_id(@proposal) %>_votes">
|
||||
<% if @proposal.successful? %>
|
||||
<p>
|
||||
<strong><%= t("proposals.proposal.supports", count: @proposal.total_votes) %></strong>
|
||||
<%= t("proposals.proposal.successful",
|
||||
voting: link_to(t("proposals.proposal.voting"), polls_path)).html_safe %>
|
||||
</p>
|
||||
<p><%= t("proposals.proposal.archived") %></p>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= render 'votes',
|
||||
{ proposal: @proposal, vote_url: vote_proposal_path(@proposal, value: 'yes') } %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% if can? :create, Poll::Question %>
|
||||
<p class="text-center">
|
||||
<%= link_to t('poll_questions.create_question'),
|
||||
new_admin_question_path(proposal_id: @proposal.id),
|
||||
class: "button hollow expanded" %>
|
||||
</p>
|
||||
<% end %>
|
||||
<% 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>
|
||||
<% end %>
|
||||
<%= render partial: 'shared/social_share', locals: {
|
||||
share_title: t("proposals.show.share"),
|
||||
title: @proposal.title,
|
||||
|
||||
@@ -312,6 +312,22 @@ en:
|
||||
create:
|
||||
form:
|
||||
submit_button: Create proposal
|
||||
created:
|
||||
title: Congratulations! You have taken the first step.
|
||||
motivation: |
|
||||
<p>
|
||||
It is important to have at least 100 supports on the first day of the campaign to be able to
|
||||
boost your proposal.
|
||||
</p>
|
||||
<p>
|
||||
Do you think you need help to achieve this goal? If so, leave your proposal
|
||||
as a draft and we will guide you.
|
||||
</p>
|
||||
publish: No, I want to publish the proposal
|
||||
dashboard: Yes, I want help and I'll publish later
|
||||
share:
|
||||
improve_it: Improve your campaign and get more support.
|
||||
dashboard: See more information
|
||||
edit:
|
||||
editing: Edit proposal
|
||||
form:
|
||||
@@ -415,6 +431,7 @@ en:
|
||||
start_new: Create new proposal
|
||||
notice:
|
||||
retired: Proposal retired
|
||||
published: The proposal has been published
|
||||
proposal:
|
||||
created: "You've created a proposal!"
|
||||
share:
|
||||
|
||||
@@ -312,6 +312,22 @@ es:
|
||||
create:
|
||||
form:
|
||||
submit_button: Crear propuesta
|
||||
created:
|
||||
title: ¡Enhorabuena! Has dado el primer paso.
|
||||
motivation: |
|
||||
<p>
|
||||
Es importante contar al menos con 100 apoyos el primer día de campaña para poder
|
||||
impulsar tu propuesta.
|
||||
</p>
|
||||
<p>
|
||||
¿Crees que necesitas ayuda para alcanzar esta meta? Si es así, deja tu propuesta
|
||||
como borrador y te guiaremos.
|
||||
</p>
|
||||
publish: No, quiero publicar la propuesta ya
|
||||
dashboard: Si, quiero ayuda y publicaré mas tarde
|
||||
share:
|
||||
improve_it: Mejora tu campaña y consigue mas apoyos.
|
||||
dashboard: Ver mas información
|
||||
edit:
|
||||
editing: Editar propuesta
|
||||
form:
|
||||
@@ -415,6 +431,7 @@ es:
|
||||
start_new: Crear una propuesta
|
||||
notice:
|
||||
retired: Propuesta retirada
|
||||
published: La propuesta ha sido publicada
|
||||
proposal:
|
||||
created: "¡Has creado una propuesta!"
|
||||
share:
|
||||
|
||||
@@ -6,7 +6,9 @@ resources :proposals do
|
||||
put :unflag
|
||||
get :retire_form
|
||||
get :share
|
||||
get :created
|
||||
patch :retire
|
||||
patch :publish
|
||||
end
|
||||
|
||||
collection do
|
||||
|
||||
@@ -37,7 +37,8 @@ section "Creating Proposals" do
|
||||
tag_list: tags.sample(3).join(','),
|
||||
geozone: Geozone.all.sample,
|
||||
skip_map: "1",
|
||||
terms_of_service: "1")
|
||||
terms_of_service: "1",
|
||||
published_at: Time.now)
|
||||
add_image_to proposal
|
||||
end
|
||||
end
|
||||
@@ -58,7 +59,8 @@ section "Creating Archived Proposals" do
|
||||
geozone: Geozone.all.sample,
|
||||
skip_map: "1",
|
||||
terms_of_service: "1",
|
||||
created_at: Setting["months_to_archive_proposals"].to_i.months.ago)
|
||||
created_at: Setting["months_to_archive_proposals"].to_i.months.ago,
|
||||
published_at: Setting["months_to_archive_proposals"].to_i.months.ago)
|
||||
add_image_to proposal
|
||||
end
|
||||
end
|
||||
@@ -80,7 +82,8 @@ section "Creating Successful Proposals" do
|
||||
geozone: Geozone.all.sample,
|
||||
skip_map: "1",
|
||||
terms_of_service: "1",
|
||||
cached_votes_up: Setting["votes_for_proposal_success"])
|
||||
cached_votes_up: Setting["votes_for_proposal_success"],
|
||||
published_at: Time.now)
|
||||
add_image_to proposal
|
||||
end
|
||||
|
||||
@@ -99,7 +102,8 @@ section "Creating Successful Proposals" do
|
||||
tag_list: tags.sample(3).join(','),
|
||||
geozone: Geozone.all.sample,
|
||||
skip_map: "1",
|
||||
terms_of_service: "1")
|
||||
terms_of_service: "1",
|
||||
published_at: Time.now)
|
||||
add_image_to proposal
|
||||
end
|
||||
end
|
||||
@@ -110,5 +114,6 @@ section "Creating proposal notifications" do
|
||||
body: "Proposal notification body #{i}",
|
||||
author: User.all.sample,
|
||||
proposal: Proposal.all.sample)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
class AddPublishedAtToProposal < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :proposals, :published_at, :datetime, null: true
|
||||
|
||||
Proposal.draft.find_each do |proposal|
|
||||
proposal.update(published_at: proposal.created_at)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -916,6 +916,7 @@ ActiveRecord::Schema.define(version: 20180711224810) do
|
||||
t.string "retired_reason"
|
||||
t.text "retired_explanation"
|
||||
t.integer "community_id"
|
||||
t.datetime "published_at"
|
||||
end
|
||||
|
||||
add_index "proposals", ["author_id", "hidden_at"], name: "index_proposals_on_author_id_and_hidden_at", using: :btree
|
||||
|
||||
@@ -170,6 +170,7 @@ FactoryBot.define do
|
||||
responsible_name 'John Snow'
|
||||
terms_of_service '1'
|
||||
skip_map '1'
|
||||
published_at { Time.now }
|
||||
association :author, factory: :user
|
||||
|
||||
trait :hidden do
|
||||
@@ -212,6 +213,10 @@ FactoryBot.define do
|
||||
trait :successful do
|
||||
cached_votes_up { Proposal.votes_needed_for_success + 100 }
|
||||
end
|
||||
|
||||
trait :draft do
|
||||
published_at nil
|
||||
end
|
||||
end
|
||||
|
||||
factory :spending_proposal do
|
||||
|
||||
Reference in New Issue
Block a user