diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss
index caf81b40b..f08d14fda 100644
--- a/app/assets/stylesheets/admin.scss
+++ b/app/assets/stylesheets/admin.scss
@@ -284,10 +284,6 @@ $sidebar-active: #f4fcd0;
.proposal-form {
padding-top: 0;
}
-
- .proposal-show {
- padding-top: rem-calc(54);
- }
}
.is-featured {
diff --git a/app/controllers/admin/proposal_milestones_controller.rb b/app/controllers/admin/proposal_milestones_controller.rb
new file mode 100644
index 000000000..3dec8463b
--- /dev/null
+++ b/app/controllers/admin/proposal_milestones_controller.rb
@@ -0,0 +1,8 @@
+class Admin::ProposalMilestonesController < Admin::MilestonesController
+
+ private
+
+ def milestoneable
+ Proposal.find(params[:proposal_id])
+ end
+end
diff --git a/app/controllers/admin/proposals_controller.rb b/app/controllers/admin/proposals_controller.rb
new file mode 100644
index 000000000..e76efce21
--- /dev/null
+++ b/app/controllers/admin/proposals_controller.rb
@@ -0,0 +1,18 @@
+class Admin::ProposalsController < Admin::BaseController
+ include HasOrders
+ include CommentableActions
+ include FeatureFlags
+ feature_flag :proposals
+
+ has_orders %w[created_at]
+
+ def show
+ @proposal = Proposal.find(params[:id])
+ end
+
+ private
+
+ def resource_model
+ Proposal
+ end
+end
diff --git a/app/models/proposal.rb b/app/models/proposal.rb
index fff616626..aa54827c6 100644
--- a/app/models/proposal.rb
+++ b/app/models/proposal.rb
@@ -20,6 +20,7 @@ class Proposal < ActiveRecord::Base
accepted_content_types: [ "application/pdf" ]
include EmbedVideosHelper
include Relationable
+ include Milestoneable
acts_as_votable
acts_as_paranoid column: :hidden_at
diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb
index 5344c06f8..6e393e805 100644
--- a/app/views/admin/_menu.html.erb
+++ b/app/views/admin/_menu.html.erb
@@ -79,6 +79,15 @@
<% end %>
+ <% if feature?(:proposals) %>
+
+ <%= link_to admin_proposals_path do %>
+
+ <%= t("admin.menu.proposals") %>
+ <% end %>
+
+ <% end %>
+
<% messages_sections = %w(newsletters emails_download admin_notifications system_emails) %>
<% messages_menu_active = messages_sections.include?(controller_name) %>
>
diff --git a/app/views/admin/proposals/index.html.erb b/app/views/admin/proposals/index.html.erb
new file mode 100644
index 000000000..8a8372713
--- /dev/null
+++ b/app/views/admin/proposals/index.html.erb
@@ -0,0 +1,39 @@
+<% provide(:title) do %>
+ <%= t("admin.header.title") %> - <%= t("admin.proposals.index.title") %>
+<% end %>
+
+<%= t("admin.proposals.index.title") %>
+
+<% if @proposals.any? %>
+ <%= render "/admin/shared/proposal_search", url: admin_proposals_path %>
+
+ <%= page_entries_info @proposals %>
+
+
+
+
+ | <%= t("admin.proposals.index.id") %> |
+ <%= t("admin.proposals.index.title") %> |
+ <%= t("admin.proposals.index.author") %> |
+ <%= t("admin.proposals.index.milestones") %> |
+
+
+
+
+ <% @proposals.each do |proposal| %>
+
+ | <%= proposal.id %> |
+ <%= link_to proposal.title, admin_proposal_path(proposal) %> |
+ <%= proposal.author.username %> |
+ <%= proposal.milestones.count %> |
+
+ <% end %>
+
+
+
+ <%= paginate @proposals %>
+<% else %>
+
+ <%= t("admin.proposals.index.no_proposals") %>
+
+<% end %>
diff --git a/app/views/admin/proposals/show.html.erb b/app/views/admin/proposals/show.html.erb
new file mode 100644
index 000000000..762c65592
--- /dev/null
+++ b/app/views/admin/proposals/show.html.erb
@@ -0,0 +1,11 @@
+<% provide :title do %>
+ <%= t("admin.header.title") %> - <%= t("admin.menu.proposals") %> - <%= @proposal.title %>
+<% end %>
+
+
+
<%= @proposal.title %>
+
+ <%= render "proposals/info", proposal: @proposal %>
+
+
+<%= render "admin/milestones/milestones", milestoneable: @proposal %>
diff --git a/app/views/proposals/_filter_subnav.html.erb b/app/views/proposals/_filter_subnav.html.erb
index 47709c8aa..642d21535 100644
--- a/app/views/proposals/_filter_subnav.html.erb
+++ b/app/views/proposals/_filter_subnav.html.erb
@@ -21,4 +21,12 @@
<% end %>
+
+ <%= link_to "#tab-milestones" do %>
+
+ <%= t("proposals.show.milestones_tab") %>
+ (<%= @proposal.milestones.count %>)
+
+ <% end %>
+
diff --git a/app/views/proposals/_info.html.erb b/app/views/proposals/_info.html.erb
new file mode 100644
index 000000000..44d5b76f3
--- /dev/null
+++ b/app/views/proposals/_info.html.erb
@@ -0,0 +1,84 @@
+
+ <%= render '/shared/author_info', resource: @proposal %>
+
+ •
+ <%= l @proposal.created_at.to_date %>
+ •
+
+ <%= link_to t("proposals.show.comments", count: @proposal.comments_count), "#comments" %>
+
+ <% if current_user %>
+ •
+
+ <%= render 'proposals/flag_actions', proposal: @proposal %>
+
+ <% end %>
+
+
+
+<%= render_image(@proposal.image, :large, true) if @proposal.image.present? %>
+
+
+
+ <%= t("proposals.show.code") %>
+ <%= @proposal.code %>
+
+
+<%= @proposal.summary %>
+
+<% if @proposal.video_url.present? %>
+
+<% end %>
+
+<%= safe_html_with_links @proposal.description %>
+
+<% if feature?(:map) && map_location_available?(@proposal.map_location) %>
+
+ <%= render_map(@proposal.map_location, "proposal", false, nil) %>
+
+<% end %>
+
+<% if @proposal.external_url.present? %>
+
+
+
+ <%= t('proposals.show.title_external_url') %>
+
+ <%= text_with_links @proposal.external_url %>
+
+<% end %>
+
+<% if @proposal.video_url.present? %>
+
+
+
+ <%= t('proposals.show.title_video_url') %>
+
+ <%= text_with_links @proposal.video_url %>
+
+
+<% end %>
+
+<%= @proposal.question %>
+
+<% if @proposal.retired? %>
+
+
+ <%= t("proposals.show.retired") %>:
+ <%= t("proposals.retire_options.#{@proposal.retired_reason}") unless @proposal.retired_reason == 'other' %>
+
+ <%= simple_format text_with_links(@proposal.retired_explanation), {}, sanitize: false %>
+
+<% end %>
+
+<% if feature?(:allow_attached_documents) %>
+ <%= render 'documents/documents',
+ documents: @proposal.documents,
+ max_documents_allowed: Proposal.max_documents_allowed %>
+<% end %>
+
+<%= render 'shared/tags', taggable: @proposal %>
diff --git a/app/views/proposals/show.html.erb b/app/views/proposals/show.html.erb
index 2c40a7075..cd9ba74f0 100644
--- a/app/views/proposals/show.html.erb
+++ b/app/views/proposals/show.html.erb
@@ -37,93 +37,8 @@
<% end %>
-
- <%= render '/shared/author_info', resource: @proposal %>
-
- •
- <%= l @proposal.created_at.to_date %>
- •
-
- <%= link_to t("proposals.show.comments", count: @proposal.comments_count), "#comments" %>
-
- <% if current_user %>
- •
-
- <%= render 'proposals/flag_actions', proposal: @proposal %>
-
- <% end %>
-
-
-
- <%= render_image(@proposal.image, :large, true) if @proposal.image.present? %>
-
-
-
- <%= t("proposals.show.code") %>
- <%= @proposal.code %>
-
-
- <%= @proposal.summary %>
-
- <% if @proposal.video_url.present? %>
-
- <% end %>
-
- <%= safe_html_with_links @proposal.description %>
-
- <% if feature?(:map) && map_location_available?(@proposal.map_location) %>
-
- <%= render_map(@proposal.map_location, "proposal", false, nil) %>
-
- <% end %>
-
- <% if @proposal.external_url.present? %>
-
-
-
- <%= t('proposals.show.title_external_url') %>
-
- <%= text_with_links @proposal.external_url %>
-
- <% end %>
-
- <% if @proposal.video_url.present? %>
-
-
-
- <%= t('proposals.show.title_video_url') %>
-
- <%= text_with_links @proposal.video_url %>
-
-
- <% end %>
-
- <%= @proposal.question %>
-
- <% if @proposal.retired? %>
-
-
- <%= t("proposals.show.retired") %>:
- <%= t("proposals.retire_options.#{@proposal.retired_reason}") unless @proposal.retired_reason == 'other' %>
-
- <%= simple_format text_with_links(@proposal.retired_explanation), {}, sanitize: false %>
-
- <% end %>
-
- <% if feature?(:allow_attached_documents) %>
- <%= render 'documents/documents',
- documents: @proposal.documents,
- max_documents_allowed: Proposal.max_documents_allowed %>
- <% end %>
-
- <%= render 'shared/tags', taggable: @proposal %>
-
+ <%= render "proposals/info", proposal: @proposal %>
<%= render 'shared/geozone', geozonable: @proposal %>
-
<%= render 'relationable/related_content', relationable: @proposal %>
@@ -225,4 +140,5 @@
<%= render "proposals/notifications" %>
+ <%= render "milestones/milestones", milestoneable: @proposal %>
diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml
index 0fd2a0d56..cd99283ce 100644
--- a/config/locales/en/admin.yml
+++ b/config/locales/en/admin.yml
@@ -536,6 +536,7 @@ en:
admin: Admin menu
banner: Manage banners
poll_questions: Questions
+ proposals: Proposals
proposals_topics: Proposals topics
budgets: Participatory budgets
geozones: Manage geozones
@@ -1040,6 +1041,13 @@ en:
search:
title: Search Organisations
no_results: No organizations found.
+ proposals:
+ index:
+ title: Proposals
+ id: ID
+ author: Author
+ milestones: Milestones
+ no_proposals: There are no proposals.
hidden_proposals:
index:
filter: Filter
diff --git a/config/locales/en/general.yml b/config/locales/en/general.yml
index 25136eecb..20f843999 100644
--- a/config/locales/en/general.yml
+++ b/config/locales/en/general.yml
@@ -437,6 +437,7 @@ en:
flag: This proposal has been flagged as inappropriate by several users.
login_to_comment: You must %{signin} or %{signup} to leave a comment.
notifications_tab: Notifications
+ milestones_tab: Milestones
retired_warning: "The author considers this proposal should not receive more supports."
retired_warning_link_to_explanation: Read the explanation before voting for it.
retired: Proposal retired by the author
diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml
index 5798dd0b1..cc0d99b7e 100644
--- a/config/locales/es/admin.yml
+++ b/config/locales/es/admin.yml
@@ -532,6 +532,7 @@ es:
admin: Menú de administración
banner: Gestionar banners
poll_questions: Preguntas
+ proposals: Propuestas
proposals_topics: Temas de propuestas
budgets: Presupuestos participativos
geozones: Gestionar distritos
@@ -1036,6 +1037,13 @@ es:
search:
title: Buscar Organizaciones
no_results: No se han encontrado organizaciones.
+ proposals:
+ index:
+ title: Propuestas
+ id: ID
+ author: Autor
+ milestones: Hitos
+ no_proposals: No hay propuestas.
hidden_proposals:
index:
filter: Filtro
diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml
index 8c2212dae..52308497b 100644
--- a/config/locales/es/general.yml
+++ b/config/locales/es/general.yml
@@ -437,6 +437,7 @@ es:
flag: Esta propuesta ha sido marcada como inapropiada por varios usuarios.
login_to_comment: Necesitas %{signin} o %{signup} para comentar.
notifications_tab: Notificaciones
+ milestones_tab: Seguimiento
retired_warning: "El autor de esta propuesta considera que ya no debe seguir recogiendo apoyos."
retired_warning_link_to_explanation: Revisa su explicación antes de apoyarla.
retired: Propuesta retirada por el autor
diff --git a/config/locales/val/general.yml b/config/locales/val/general.yml
index aa35f48d5..bc014d401 100644
--- a/config/locales/val/general.yml
+++ b/config/locales/val/general.yml
@@ -434,6 +434,7 @@ val:
flag: Esta proposta ha sigut marcada com inapropiada per diversos usuaris.
login_to_comment: Necessites %{signin} o %{signup} per a comentar.
notifications_tab: Notificacions
+ milestones_tab: Seguiments
retired_warning: "L'autor d'esta proposta considera que ja no ha de seguir recollint avals."
retired_warning_link_to_explanation: Revisa la seua explicació abans d'avalar-la.
retired: Proposta retirada per l'autor
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index a6ccf2de3..b37714f47 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -29,6 +29,10 @@ namespace :admin do
end
end
+ resources :proposals, only: [:index, :show] do
+ resources :milestones, controller: "proposal_milestones"
+ end
+
resources :hidden_proposals, only: :index do
member do
put :restore
diff --git a/db/dev_seeds/milestones.rb b/db/dev_seeds/milestones.rb
index d3e2ced68..41b3f40ab 100644
--- a/db/dev_seeds/milestones.rb
+++ b/db/dev_seeds/milestones.rb
@@ -6,17 +6,20 @@ section "Creating default Milestone Statuses" do
end
section "Creating investment milestones" do
- Budget::Investment.find_each do |investment|
- rand(1..5).times do
- milestone = investment.milestones.build(
- publication_date: rand(Date.tomorrow..(Date.current + 3.weeks)),
- status_id: Milestone::Status.all.sample
- )
- I18n.available_locales.map do |locale|
- Globalize.with_locale(locale) do
- milestone.description = "Description for locale #{locale}"
- milestone.title = I18n.l(Time.current, format: :datetime)
- milestone.save!
+ [Budget::Investment, Proposal].each do |model|
+ model.find_each do |record|
+ rand(1..5).times do
+ milestone = record.milestones.build(
+ publication_date: Date.tomorrow,
+ status_id: Milestone::Status.all.sample
+ )
+
+ I18n.available_locales.map do |locale|
+ Globalize.with_locale(locale) do
+ milestone.description = "Description for locale #{locale}"
+ milestone.title = I18n.l(Time.current, format: :datetime)
+ milestone.save!
+ end
end
end
end
diff --git a/spec/features/admin/proposals_spec.rb b/spec/features/admin/proposals_spec.rb
new file mode 100644
index 000000000..ddad53d9c
--- /dev/null
+++ b/spec/features/admin/proposals_spec.rb
@@ -0,0 +1,39 @@
+require "rails_helper"
+
+feature "Admin proposals" do
+ background do
+ login_as create(:administrator).user
+ end
+
+ it_behaves_like "admin_milestoneable",
+ :proposal,
+ "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")
+
+ visit admin_root_path
+ within("#side_menu") { click_link "Proposals" }
+
+ expect(page).to have_content "Make Pluto a planet again"
+ expect(page).to have_content "Build a monument"
+
+ fill_in "search", with: "Pluto"
+ click_button "Search"
+
+ expect(page).to have_content "Make Pluto a planet again"
+ expect(page).not_to have_content "Build a monument"
+ end
+ end
+
+ scenario "Show" do
+ create(:proposal, title: "Create a chaotic future", summary: "Chaos isn't controlled")
+
+ visit admin_proposals_path
+ click_link "Create a chaotic future"
+
+ expect(page).to have_content "Chaos isn't controlled"
+ end
+end
diff --git a/spec/features/admin/site_customization/information_texts_spec.rb b/spec/features/admin/site_customization/information_texts_spec.rb
index 454a83526..83e4edb9a 100644
--- a/spec/features/admin/site_customization/information_texts_spec.rb
+++ b/spec/features/admin/site_customization/information_texts_spec.rb
@@ -21,7 +21,7 @@ feature "Admin custom information texts" do
click_link 'Community'
expect(page).to have_content 'Access the community'
- click_link 'Proposals'
+ within("#information-texts-tabs") { click_link "Proposals" }
expect(page).to have_content 'Create proposal'
within "#information-texts-tabs" do
@@ -49,7 +49,7 @@ feature "Admin custom information texts" do
scenario 'check that tabs are highlight when click it' do
visit admin_site_customization_information_texts_path
- click_link 'Proposals'
+ within("#information-texts-tabs") { click_link "Proposals" }
expect(find("a[href=\"/admin/site_customization/information_texts?tab=proposals\"].is-active"))
.to have_content "Proposals"
end
diff --git a/spec/features/proposals_spec.rb b/spec/features/proposals_spec.rb
index eb8b5c0de..8beb35549 100644
--- a/spec/features/proposals_spec.rb
+++ b/spec/features/proposals_spec.rb
@@ -3,6 +3,10 @@ require 'rails_helper'
feature 'Proposals' do
+ it_behaves_like "milestoneable",
+ :proposal,
+ "proposal_path"
+
scenario 'Disabled with a feature flag' do
Setting['feature.proposals'] = nil
expect{ visit proposals_path }.to raise_exception(FeatureFlags::FeatureDisabled)