@@ -7,6 +7,7 @@
|
|||||||
@import 'layout';
|
@import 'layout';
|
||||||
@import 'participation';
|
@import 'participation';
|
||||||
@import 'pages';
|
@import 'pages';
|
||||||
|
@import 'proposal';
|
||||||
@import 'legislation';
|
@import 'legislation';
|
||||||
@import 'legislation_process';
|
@import 'legislation_process';
|
||||||
@import 'community';
|
@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{confidence_score hot_score created_at most_commented random}, only: [:index, :print]
|
||||||
has_orders %w{most_voted newest}, only: :show
|
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
|
def show
|
||||||
super
|
super
|
||||||
@notifications = @proposal.notifications
|
@notifications = @proposal.notifications
|
||||||
@@ -37,7 +52,8 @@ class Management::ProposalsController < Management::BaseController
|
|||||||
|
|
||||||
def proposal_params
|
def proposal_params
|
||||||
params.require(:proposal).permit(:title, :question, :summary, :description, :external_url, :video_url,
|
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
|
end
|
||||||
|
|
||||||
def resource_model
|
def resource_model
|
||||||
|
|||||||
@@ -35,13 +35,16 @@ class ProposalsController < ApplicationController
|
|||||||
@proposal = Proposal.new(proposal_params.merge(author: current_user))
|
@proposal = Proposal.new(proposal_params.merge(author: current_user))
|
||||||
|
|
||||||
if @proposal.save
|
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
|
else
|
||||||
render :new
|
render :new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def created; end
|
||||||
|
|
||||||
def index_customization
|
def index_customization
|
||||||
|
discard_draft
|
||||||
discard_archived
|
discard_archived
|
||||||
load_retired
|
load_retired
|
||||||
load_successful_proposals
|
load_successful_proposals
|
||||||
@@ -88,6 +91,11 @@ class ProposalsController < ApplicationController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def publish
|
||||||
|
@proposal.publish
|
||||||
|
redirect_to share_proposal_path(@proposal), notice: t('proposals.notice.published')
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def proposal_params
|
def proposal_params
|
||||||
@@ -116,6 +124,10 @@ class ProposalsController < ApplicationController
|
|||||||
@featured_proposals_votes = current_user ? current_user.proposal_votes(proposals) : {}
|
@featured_proposals_votes = current_user ? current_user.proposal_votes(proposals) : {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def discard_draft
|
||||||
|
@resources = @resources.published
|
||||||
|
end
|
||||||
|
|
||||||
def discard_archived
|
def discard_archived
|
||||||
@resources = @resources.not_archived unless @current_order == "archival_date"
|
@resources = @resources.not_archived unless @current_order == "archival_date"
|
||||||
end
|
end
|
||||||
@@ -158,5 +170,4 @@ class ProposalsController < ApplicationController
|
|||||||
@recommended_proposals = Proposal.recommendations(current_user).sort_by_random.limit(3)
|
@recommended_proposals = Proposal.recommendations(current_user).sort_by_random.limit(3)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class UsersController < ApplicationController
|
|||||||
|
|
||||||
def set_activity_counts
|
def set_activity_counts
|
||||||
@activity_counts = HashWithIndifferentAccess.new(
|
@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),
|
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,
|
||||||
@@ -52,7 +52,7 @@ class UsersController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def load_proposals
|
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
|
end
|
||||||
|
|
||||||
def load_debates
|
def load_debates
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ module Abilities
|
|||||||
def initialize(user)
|
def initialize(user)
|
||||||
merge Abilities::Everyone.new(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 :read, Debate
|
||||||
can :update, Debate do |debate|
|
can :update, Debate do |debate|
|
||||||
@@ -16,6 +16,10 @@ module Abilities
|
|||||||
can :update, Proposal do |proposal|
|
can :update, Proposal do |proposal|
|
||||||
proposal.editable_by?(user)
|
proposal.editable_by?(user)
|
||||||
end
|
end
|
||||||
|
can :publish, Proposal do |proposal|
|
||||||
|
proposal.draft? && proposal.author.id == user.id
|
||||||
|
end
|
||||||
|
|
||||||
can [:retire_form, :retire], Proposal, author_id: user.id
|
can [:retire_form, :retire], Proposal, author_id: user.id
|
||||||
|
|
||||||
can :read, Legislation::Proposal
|
can :read, Legislation::Proposal
|
||||||
@@ -26,7 +30,7 @@ module Abilities
|
|||||||
|
|
||||||
can :create, Comment
|
can :create, Comment
|
||||||
can :create, Debate
|
can :create, Debate
|
||||||
can :create, Proposal
|
can %i[create created], Proposal
|
||||||
can :create, Legislation::Proposal
|
can :create, Legislation::Proposal
|
||||||
|
|
||||||
can :suggest, Debate
|
can :suggest, Debate
|
||||||
@@ -60,7 +64,9 @@ module Abilities
|
|||||||
end
|
end
|
||||||
|
|
||||||
if user.level_two_or_three_verified?
|
if user.level_two_or_three_verified?
|
||||||
can :vote, Proposal
|
can :vote, Proposal do |proposal|
|
||||||
|
proposal.published?
|
||||||
|
end
|
||||||
can :vote_featured, Proposal
|
can :vote_featured, Proposal
|
||||||
can :vote, SpendingProposal
|
can :vote, SpendingProposal
|
||||||
can :create, SpendingProposal
|
can :create, SpendingProposal
|
||||||
|
|||||||
@@ -71,11 +71,26 @@ class Proposal < ActiveRecord::Base
|
|||||||
scope :unsuccessful, -> { 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 :public_for_api, -> { all }
|
||||||
scope :not_supported_by_user, ->(user) { where.not(id: user.find_voted_items(votable_type: "Proposal").compact.map(&:id)) }
|
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
|
def url
|
||||||
proposal_path(self)
|
proposal_path(self)
|
||||||
end
|
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)
|
def self.recommendations(user)
|
||||||
tagged_with(user.interests, any: true)
|
tagged_with(user.interests, any: true)
|
||||||
.where("author_id != ?", user.id)
|
.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
|
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? %>
|
<% if @proposal_improvement_path.present? %>
|
||||||
<div class="callout highlight margin-top text-center">
|
<div class="callout highlight margin-top text-center">
|
||||||
<p class="lead"><strong><%= t("proposals.proposal.improve_info") %></strong></p>
|
<p class="lead"><strong><%= t("proposals.proposal.improve_info") %></strong></p>
|
||||||
|
|||||||
@@ -165,10 +165,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<% if @proposal.published? %>
|
||||||
<div class="sidebar-divider"></div>
|
<div class="sidebar-divider"></div>
|
||||||
<h2><%= t("votes.supports") %></h2>
|
<h2><%= t("votes.supports") %></h2>
|
||||||
<div id="<%= dom_id(@proposal) %>_votes">
|
<div id="<%= dom_id(@proposal) %>_votes">
|
||||||
|
|
||||||
<% if @proposal.successful? %>
|
<% if @proposal.successful? %>
|
||||||
<p>
|
<p>
|
||||||
<%= t("proposals.proposal.successful",
|
<%= t("proposals.proposal.successful",
|
||||||
@@ -193,6 +193,7 @@
|
|||||||
{ proposal: @proposal, vote_url: vote_proposal_path(@proposal, value: 'yes') } %>
|
{ proposal: @proposal, vote_url: vote_proposal_path(@proposal, value: 'yes') } %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
<% end %>
|
||||||
<%= render partial: 'shared/social_share', locals: {
|
<%= render partial: 'shared/social_share', locals: {
|
||||||
share_title: t("proposals.show.share"),
|
share_title: t("proposals.show.share"),
|
||||||
title: @proposal.title,
|
title: @proposal.title,
|
||||||
|
|||||||
@@ -312,6 +312,22 @@ en:
|
|||||||
create:
|
create:
|
||||||
form:
|
form:
|
||||||
submit_button: Create proposal
|
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:
|
edit:
|
||||||
editing: Edit proposal
|
editing: Edit proposal
|
||||||
form:
|
form:
|
||||||
@@ -415,6 +431,7 @@ en:
|
|||||||
start_new: Create new proposal
|
start_new: Create new proposal
|
||||||
notice:
|
notice:
|
||||||
retired: Proposal retired
|
retired: Proposal retired
|
||||||
|
published: The proposal has been published
|
||||||
proposal:
|
proposal:
|
||||||
created: "You've created a proposal!"
|
created: "You've created a proposal!"
|
||||||
share:
|
share:
|
||||||
|
|||||||
@@ -312,6 +312,22 @@ es:
|
|||||||
create:
|
create:
|
||||||
form:
|
form:
|
||||||
submit_button: Crear propuesta
|
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:
|
edit:
|
||||||
editing: Editar propuesta
|
editing: Editar propuesta
|
||||||
form:
|
form:
|
||||||
@@ -415,6 +431,7 @@ es:
|
|||||||
start_new: Crear una propuesta
|
start_new: Crear una propuesta
|
||||||
notice:
|
notice:
|
||||||
retired: Propuesta retirada
|
retired: Propuesta retirada
|
||||||
|
published: La propuesta ha sido publicada
|
||||||
proposal:
|
proposal:
|
||||||
created: "¡Has creado una propuesta!"
|
created: "¡Has creado una propuesta!"
|
||||||
share:
|
share:
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ resources :proposals do
|
|||||||
put :unflag
|
put :unflag
|
||||||
get :retire_form
|
get :retire_form
|
||||||
get :share
|
get :share
|
||||||
|
get :created
|
||||||
patch :retire
|
patch :retire
|
||||||
|
patch :publish
|
||||||
end
|
end
|
||||||
|
|
||||||
collection do
|
collection do
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ section "Creating Proposals" do
|
|||||||
tag_list: tags.sample(3).join(','),
|
tag_list: tags.sample(3).join(','),
|
||||||
geozone: Geozone.all.sample,
|
geozone: Geozone.all.sample,
|
||||||
skip_map: "1",
|
skip_map: "1",
|
||||||
terms_of_service: "1")
|
terms_of_service: "1",
|
||||||
|
published_at: Time.now)
|
||||||
add_image_to proposal
|
add_image_to proposal
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -58,7 +59,8 @@ section "Creating Archived Proposals" do
|
|||||||
geozone: Geozone.all.sample,
|
geozone: Geozone.all.sample,
|
||||||
skip_map: "1",
|
skip_map: "1",
|
||||||
terms_of_service: "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
|
add_image_to proposal
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -80,7 +82,8 @@ section "Creating Successful Proposals" do
|
|||||||
geozone: Geozone.all.sample,
|
geozone: Geozone.all.sample,
|
||||||
skip_map: "1",
|
skip_map: "1",
|
||||||
terms_of_service: "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
|
add_image_to proposal
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -99,7 +102,8 @@ section "Creating Successful Proposals" do
|
|||||||
tag_list: tags.sample(3).join(','),
|
tag_list: tags.sample(3).join(','),
|
||||||
geozone: Geozone.all.sample,
|
geozone: Geozone.all.sample,
|
||||||
skip_map: "1",
|
skip_map: "1",
|
||||||
terms_of_service: "1")
|
terms_of_service: "1",
|
||||||
|
published_at: Time.now)
|
||||||
add_image_to proposal
|
add_image_to proposal
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -110,5 +114,6 @@ section "Creating proposal notifications" do
|
|||||||
body: "Proposal notification body #{i}",
|
body: "Proposal notification body #{i}",
|
||||||
author: User.all.sample,
|
author: User.all.sample,
|
||||||
proposal: Proposal.all.sample)
|
proposal: Proposal.all.sample)
|
||||||
|
|
||||||
end
|
end
|
||||||
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.string "retired_reason"
|
||||||
t.text "retired_explanation"
|
t.text "retired_explanation"
|
||||||
t.integer "community_id"
|
t.integer "community_id"
|
||||||
|
t.datetime "published_at"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "proposals", ["author_id", "hidden_at"], name: "index_proposals_on_author_id_and_hidden_at", using: :btree
|
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'
|
responsible_name 'John Snow'
|
||||||
terms_of_service '1'
|
terms_of_service '1'
|
||||||
skip_map '1'
|
skip_map '1'
|
||||||
|
published_at { Time.now }
|
||||||
association :author, factory: :user
|
association :author, factory: :user
|
||||||
|
|
||||||
trait :hidden do
|
trait :hidden do
|
||||||
@@ -212,6 +213,10 @@ FactoryBot.define do
|
|||||||
trait :successful do
|
trait :successful do
|
||||||
cached_votes_up { Proposal.votes_needed_for_success + 100 }
|
cached_votes_up { Proposal.votes_needed_for_success + 100 }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
trait :draft do
|
||||||
|
published_at nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :spending_proposal do
|
factory :spending_proposal do
|
||||||
|
|||||||
Reference in New Issue
Block a user