Refactor participatory budgets in draft mode
Previously the draft mode was a phase of the PB, but that had some limitations. Now the phase drafting disappears and therefore the PB can have the status published or not published (in draft mode). That will give more flexibility in order to navigate through the different phases and see how it looks for administrators before publishing the PB and everybody can see. By default, the PB is always created in draft mode, so it gives you the flexibility to adjust and modify anything before publishing it.
This commit is contained in:
committed by
Javi Martín
parent
0b2b8b557d
commit
28caabecdf
@@ -657,6 +657,7 @@ code {
|
|||||||
.admin-content > header {
|
.admin-content > header {
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@include regular-button;
|
@include regular-button;
|
||||||
|
|||||||
37
app/assets/stylesheets/admin/budgets/drafting.scss
Normal file
37
app/assets/stylesheets/admin/budgets/drafting.scss
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
.admin .drafting {
|
||||||
|
margin-bottom: 2 * $line-height / 3;
|
||||||
|
margin-left: auto;
|
||||||
|
|
||||||
|
@include breakpoint(large) {
|
||||||
|
align-items: flex-start;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.callout {
|
||||||
|
flex: 1;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include breakpoint(small medium only) {
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
.callout {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-link {
|
||||||
|
@include has-fa-icon(eye, regular);
|
||||||
|
@include hollow-button;
|
||||||
|
}
|
||||||
|
|
||||||
|
.publish-link {
|
||||||
|
@include regular-button;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-link,
|
||||||
|
.publish-link {
|
||||||
|
margin-left: $line-height / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
16
app/components/admin/budgets/drafting_component.html.erb
Normal file
16
app/components/admin/budgets/drafting_component.html.erb
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<div class="drafting">
|
||||||
|
<% if can? :publish, budget %>
|
||||||
|
<div class="callout warning">
|
||||||
|
<strong><%= t("admin.budgets.edit.drafting") %></strong>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= link_to t("admin.budgets.edit.preview"), budget_path(budget), class: "preview-link", target: "_blank" %>
|
||||||
|
|
||||||
|
<% if can? :publish, budget %>
|
||||||
|
<%= link_to t("admin.budgets.edit.publish"),
|
||||||
|
publish_admin_budget_path(budget),
|
||||||
|
method: :patch, class: "publish-link",
|
||||||
|
data: { confirm: t("admin.actions.confirm") } %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
8
app/components/admin/budgets/drafting_component.rb
Normal file
8
app/components/admin/budgets/drafting_component.rb
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
class Admin::Budgets::DraftingComponent < ApplicationComponent
|
||||||
|
delegate :can?, to: :controller
|
||||||
|
attr_reader :budget
|
||||||
|
|
||||||
|
def initialize(budget)
|
||||||
|
@budget = budget
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -15,6 +15,7 @@ class Admin::BudgetsController < Admin::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
render :edit
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@@ -23,6 +24,11 @@ class Admin::BudgetsController < Admin::BaseController
|
|||||||
def edit
|
def edit
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def publish
|
||||||
|
@budget.publish!
|
||||||
|
redirect_to edit_admin_budget_path(@budget), notice: t("admin.budgets.publish.notice")
|
||||||
|
end
|
||||||
|
|
||||||
def calculate_winners
|
def calculate_winners
|
||||||
return unless @budget.balloting_process?
|
return unless @budget.balloting_process?
|
||||||
|
|
||||||
@@ -42,9 +48,9 @@ class Admin::BudgetsController < Admin::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@budget = Budget.new(budget_params)
|
@budget = Budget.new(budget_params.merge(published: false))
|
||||||
if @budget.save
|
if @budget.save
|
||||||
redirect_to admin_budget_path(@budget), notice: t("admin.budgets.create.notice")
|
redirect_to edit_admin_budget_path(@budget), notice: t("admin.budgets.create.notice")
|
||||||
else
|
else
|
||||||
render :new
|
render :new
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ module BudgetsHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
def budget_published?(budget)
|
def budget_published?(budget)
|
||||||
!budget.drafting? || current_user&.administrator?
|
budget.published? || current_user&.administrator?
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_budget_map_locations
|
def current_budget_map_locations
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ module Abilities
|
|||||||
can :manage, Dashboard::Action
|
can :manage, Dashboard::Action
|
||||||
|
|
||||||
can [:index, :read, :new, :create, :update, :destroy, :calculate_winners], Budget
|
can [:index, :read, :new, :create, :update, :destroy, :calculate_winners], Budget
|
||||||
|
can :publish, Budget, id: Budget.drafting.ids
|
||||||
can [:read, :create, :update, :destroy], Budget::Group
|
can [:read, :create, :update, :destroy], Budget::Group
|
||||||
can [:read, :create, :update, :destroy], Budget::Heading
|
can [:read, :create, :update, :destroy], Budget::Heading
|
||||||
can [:hide, :admin_update, :toggle_selection], Budget::Investment
|
can [:hide, :admin_update, :toggle_selection], Budget::Investment
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ class Budget < ApplicationRecord
|
|||||||
|
|
||||||
after_create :generate_phases
|
after_create :generate_phases
|
||||||
|
|
||||||
scope :drafting, -> { where(phase: "drafting") }
|
scope :published, -> { where(published: true) }
|
||||||
|
scope :drafting, -> { where.not(id: published) }
|
||||||
scope :informing, -> { where(phase: "informing") }
|
scope :informing, -> { where(phase: "informing") }
|
||||||
scope :accepting, -> { where(phase: "accepting") }
|
scope :accepting, -> { where(phase: "accepting") }
|
||||||
scope :reviewing, -> { where(phase: "reviewing") }
|
scope :reviewing, -> { where(phase: "reviewing") }
|
||||||
@@ -59,7 +60,7 @@ class Budget < ApplicationRecord
|
|||||||
scope :open, -> { where.not(phase: "finished") }
|
scope :open, -> { where.not(phase: "finished") }
|
||||||
|
|
||||||
def self.current
|
def self.current
|
||||||
where.not(phase: "drafting").order(:created_at).last
|
published.order(:created_at).last
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_phase
|
def current_phase
|
||||||
@@ -86,8 +87,12 @@ class Budget < ApplicationRecord
|
|||||||
80
|
80
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def publish!
|
||||||
|
update!(published: true)
|
||||||
|
end
|
||||||
|
|
||||||
def drafting?
|
def drafting?
|
||||||
phase == "drafting"
|
!published?
|
||||||
end
|
end
|
||||||
|
|
||||||
def informing?
|
def informing?
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class Budget
|
class Budget
|
||||||
class Phase < ApplicationRecord
|
class Phase < ApplicationRecord
|
||||||
PHASE_KINDS = %w[drafting informing accepting reviewing selecting valuating publishing_prices balloting
|
PHASE_KINDS = %w[informing accepting reviewing selecting valuating publishing_prices balloting
|
||||||
reviewing_ballots finished].freeze
|
reviewing_ballots finished].freeze
|
||||||
PUBLISHED_PRICES_PHASES = %w[publishing_prices balloting reviewing_ballots finished].freeze
|
PUBLISHED_PRICES_PHASES = %w[publishing_prices balloting reviewing_ballots finished].freeze
|
||||||
SUMMARY_MAX_LENGTH = 1000
|
SUMMARY_MAX_LENGTH = 1000
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
<%= back_link_to admin_budgets_path %>
|
<%= back_link_to admin_budgets_path %>
|
||||||
|
|
||||||
<h2><%= t("admin.budgets.edit.title") %></h2>
|
<header>
|
||||||
|
<h2><%= t("admin.budgets.edit.title") %></h2>
|
||||||
|
<%= render Admin::Budgets::DraftingComponent.new(@budget) %>
|
||||||
|
</header>
|
||||||
|
|
||||||
<%= render "/admin/budgets/form" %>
|
<%= render "/admin/budgets/form" %>
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
<%= back_link_to admin_budgets_path %>
|
|
||||||
|
|
||||||
<h2><%= @budget.name %></h2>
|
|
||||||
|
|
||||||
<%= render "form" %>
|
|
||||||
@@ -82,8 +82,13 @@ en:
|
|||||||
notice: New participatory budget created successfully!
|
notice: New participatory budget created successfully!
|
||||||
update:
|
update:
|
||||||
notice: Participatory budget updated successfully
|
notice: Participatory budget updated successfully
|
||||||
|
publish:
|
||||||
|
notice: "Participatory budget published successfully"
|
||||||
edit:
|
edit:
|
||||||
title: Edit Participatory budget
|
title: Edit Participatory budget
|
||||||
|
drafting: "This participatory budget is in draft mode, only administrators can see it in the public site. Once it's published it cannot be changed to draft mode again."
|
||||||
|
preview: "Preview budget"
|
||||||
|
publish: "Publish budget"
|
||||||
delete: Delete budget
|
delete: Delete budget
|
||||||
phase: Phase
|
phase: Phase
|
||||||
dates: Dates
|
dates: Dates
|
||||||
|
|||||||
@@ -82,8 +82,13 @@ es:
|
|||||||
notice: '¡Presupuestos participativos creados con éxito!'
|
notice: '¡Presupuestos participativos creados con éxito!'
|
||||||
update:
|
update:
|
||||||
notice: Presupuestos participativos actualizados
|
notice: Presupuestos participativos actualizados
|
||||||
|
publish:
|
||||||
|
notice: "Presupuestos participativos actualizados"
|
||||||
edit:
|
edit:
|
||||||
title: Editar presupuestos participativos
|
title: Editar presupuestos participativos
|
||||||
|
drafting: "Este presupuesto participativo está en modo borrador, solo los administradores pueden verlo desde la parte pública de la página. Una vez se haya publicado, no se podrá volver a poner en modo borrador otra vez."
|
||||||
|
preview: "Previsualizar presupuesto"
|
||||||
|
publish: "Publicar presupuesto"
|
||||||
delete: Eliminar presupuesto
|
delete: Eliminar presupuesto
|
||||||
phase: Fase
|
phase: Fase
|
||||||
dates: Fechas
|
dates: Fechas
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ namespace :admin do
|
|||||||
|
|
||||||
resources :budgets do
|
resources :budgets do
|
||||||
member do
|
member do
|
||||||
|
patch :publish
|
||||||
put :calculate_winners
|
put :calculate_winners
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class AddPublishedStatusToBudgets < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :budgets, :published, :boolean
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -360,6 +360,7 @@ ActiveRecord::Schema.define(version: 2021_01_23_100638) do
|
|||||||
t.text "description_publishing_prices"
|
t.text "description_publishing_prices"
|
||||||
t.text "description_informing"
|
t.text "description_informing"
|
||||||
t.string "voting_style", default: "knapsack"
|
t.string "voting_style", default: "knapsack"
|
||||||
|
t.boolean "published"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "campaigns", id: :serial, force: :cascade do |t|
|
create_table "campaigns", id: :serial, force: :cascade do |t|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ FactoryBot.define do
|
|||||||
factory :budget do
|
factory :budget do
|
||||||
sequence(:name) { |n| "#{Faker::Lorem.word} #{n}" }
|
sequence(:name) { |n| "#{Faker::Lorem.word} #{n}" }
|
||||||
currency_symbol { "€" }
|
currency_symbol { "€" }
|
||||||
|
published { true }
|
||||||
phase { "accepting" }
|
phase { "accepting" }
|
||||||
description_drafting { "This budget is drafting" }
|
description_drafting { "This budget is drafting" }
|
||||||
description_informing { "This budget is informing" }
|
description_informing { "This budget is informing" }
|
||||||
@@ -15,7 +16,7 @@ FactoryBot.define do
|
|||||||
description_finished { "This budget is finished" }
|
description_finished { "This budget is finished" }
|
||||||
|
|
||||||
trait :drafting do
|
trait :drafting do
|
||||||
phase { "drafting" }
|
published { false }
|
||||||
end
|
end
|
||||||
|
|
||||||
trait :informing do
|
trait :informing do
|
||||||
|
|||||||
@@ -2,11 +2,10 @@ require "rails_helper"
|
|||||||
|
|
||||||
describe Budget::Phase do
|
describe Budget::Phase do
|
||||||
let(:budget) { create(:budget) }
|
let(:budget) { create(:budget) }
|
||||||
let(:first_phase) { budget.phases.drafting }
|
let(:informing_phase) { budget.phases.informing }
|
||||||
let(:second_phase) { budget.phases.informing }
|
let(:accepting_phase) { budget.phases.accepting }
|
||||||
let(:third_phase) { budget.phases.accepting }
|
let(:reviewing_phase) { budget.phases.reviewing }
|
||||||
let(:fourth_phase) { budget.phases.reviewing }
|
let(:finished_phase) { budget.phases.finished }
|
||||||
let(:final_phase) { budget.phases.finished }
|
|
||||||
|
|
||||||
it_behaves_like "globalizable", :budget_phase
|
it_behaves_like "globalizable", :budget_phase
|
||||||
|
|
||||||
@@ -31,54 +30,53 @@ describe Budget::Phase do
|
|||||||
|
|
||||||
describe "#dates_range_valid?" do
|
describe "#dates_range_valid?" do
|
||||||
it "is valid when start & end dates are different & consecutive" do
|
it "is valid when start & end dates are different & consecutive" do
|
||||||
first_phase.assign_attributes(starts_at: Date.current, ends_at: Date.tomorrow)
|
informing_phase.assign_attributes(starts_at: Date.current, ends_at: Date.tomorrow)
|
||||||
|
|
||||||
expect(first_phase).to be_valid
|
expect(informing_phase).to be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is not valid when dates are equal" do
|
it "is not valid when dates are equal" do
|
||||||
first_phase.assign_attributes(starts_at: Date.current, ends_at: Date.current)
|
informing_phase.assign_attributes(starts_at: Date.current, ends_at: Date.current)
|
||||||
|
|
||||||
expect(first_phase).not_to be_valid
|
expect(informing_phase).not_to be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is not valid when start date is later than end date" do
|
it "is not valid when start date is later than end date" do
|
||||||
first_phase.assign_attributes(starts_at: Date.tomorrow, ends_at: Date.current)
|
informing_phase.assign_attributes(starts_at: Date.tomorrow, ends_at: Date.current)
|
||||||
|
|
||||||
expect(first_phase).not_to be_valid
|
expect(informing_phase).not_to be_valid
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#prev_phase_dates_valid?" do
|
describe "#prev_phase_dates_valid?" do
|
||||||
let(:error) do
|
let(:error) do
|
||||||
"Start date must be later than the start date of the previous enabled phase"\
|
"Start date must be later than the start date of the previous enabled phase (Information)"
|
||||||
" (Draft (Not visible to the public))"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is invalid when start date is same as previous enabled phase start date" do
|
it "is invalid when start date is same as previous enabled phase start date" do
|
||||||
second_phase.assign_attributes(starts_at: second_phase.prev_enabled_phase.starts_at)
|
accepting_phase.assign_attributes(starts_at: accepting_phase.prev_enabled_phase.starts_at)
|
||||||
|
|
||||||
expect(second_phase).not_to be_valid
|
expect(accepting_phase).not_to be_valid
|
||||||
expect(second_phase.errors.messages[:starts_at]).to include(error)
|
expect(accepting_phase.errors.messages[:starts_at]).to include(error)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is invalid when start date is earlier than previous enabled phase start date" do
|
it "is invalid when start date is earlier than previous enabled phase start date" do
|
||||||
second_phase.assign_attributes(starts_at: second_phase.prev_enabled_phase.starts_at - 1.day)
|
accepting_phase.assign_attributes(starts_at: accepting_phase.prev_enabled_phase.starts_at - 1.day)
|
||||||
|
|
||||||
expect(second_phase).not_to be_valid
|
expect(accepting_phase).not_to be_valid
|
||||||
expect(second_phase.errors.messages[:starts_at]).to include(error)
|
expect(accepting_phase.errors.messages[:starts_at]).to include(error)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is valid when start date is in between previous enabled phase start & end dates" do
|
it "is valid when start date is in between previous enabled phase start & end dates" do
|
||||||
second_phase.assign_attributes(starts_at: second_phase.prev_enabled_phase.starts_at + 1.day)
|
accepting_phase.assign_attributes(starts_at: accepting_phase.prev_enabled_phase.starts_at + 1.day)
|
||||||
|
|
||||||
expect(second_phase).to be_valid
|
expect(accepting_phase).to be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is valid when start date is later than previous enabled phase end date" do
|
it "is valid when start date is later than previous enabled phase end date" do
|
||||||
second_phase.assign_attributes(starts_at: second_phase.prev_enabled_phase.ends_at + 1.day)
|
accepting_phase.assign_attributes(starts_at: accepting_phase.prev_enabled_phase.ends_at + 1.day)
|
||||||
|
|
||||||
expect(second_phase).to be_valid
|
expect(accepting_phase).to be_valid
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -88,29 +86,29 @@ describe Budget::Phase do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "is invalid when end date is same as next enabled phase end date" do
|
it "is invalid when end date is same as next enabled phase end date" do
|
||||||
second_phase.assign_attributes(ends_at: second_phase.next_enabled_phase.ends_at)
|
informing_phase.assign_attributes(ends_at: informing_phase.next_enabled_phase.ends_at)
|
||||||
|
|
||||||
expect(second_phase).not_to be_valid
|
expect(informing_phase).not_to be_valid
|
||||||
expect(second_phase.errors.messages[:ends_at]).to include(error)
|
expect(informing_phase.errors.messages[:ends_at]).to include(error)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is invalid when end date is later than next enabled phase end date" do
|
it "is invalid when end date is later than next enabled phase end date" do
|
||||||
second_phase.assign_attributes(ends_at: second_phase.next_enabled_phase.ends_at + 1.day)
|
informing_phase.assign_attributes(ends_at: informing_phase.next_enabled_phase.ends_at + 1.day)
|
||||||
|
|
||||||
expect(second_phase).not_to be_valid
|
expect(informing_phase).not_to be_valid
|
||||||
expect(second_phase.errors.messages[:ends_at]).to include(error)
|
expect(informing_phase.errors.messages[:ends_at]).to include(error)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is valid when end date is in between next enabled phase start & end dates" do
|
it "is valid when end date is in between next enabled phase start & end dates" do
|
||||||
second_phase.assign_attributes(ends_at: second_phase.next_enabled_phase.ends_at - 1.day)
|
informing_phase.assign_attributes(ends_at: informing_phase.next_enabled_phase.ends_at - 1.day)
|
||||||
|
|
||||||
expect(second_phase).to be_valid
|
expect(informing_phase).to be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is valid when end date is earlier than next enabled phase start date" do
|
it "is valid when end date is earlier than next enabled phase start date" do
|
||||||
second_phase.assign_attributes(ends_at: second_phase.next_enabled_phase.starts_at - 1.day)
|
informing_phase.assign_attributes(ends_at: informing_phase.next_enabled_phase.starts_at - 1.day)
|
||||||
|
|
||||||
expect(second_phase).to be_valid
|
expect(informing_phase).to be_valid
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -128,50 +126,50 @@ describe Budget::Phase do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe "#adjust_date_ranges" do
|
describe "#adjust_date_ranges" do
|
||||||
let(:prev_enabled_phase) { second_phase.prev_enabled_phase }
|
let(:prev_enabled_phase) { accepting_phase.prev_enabled_phase }
|
||||||
let(:next_enabled_phase) { second_phase.next_enabled_phase }
|
let(:next_enabled_phase) { accepting_phase.next_enabled_phase }
|
||||||
|
|
||||||
describe "when enabled" do
|
describe "when enabled" do
|
||||||
it "adjusts previous enabled phase end date to its own start date" do
|
it "adjusts previous enabled phase end date to its own start date" do
|
||||||
expect(prev_enabled_phase.ends_at).to eq(second_phase.starts_at)
|
expect(prev_enabled_phase.ends_at).to eq(accepting_phase.starts_at)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "adjusts next enabled phase start date to its own end date" do
|
it "adjusts next enabled phase start date to its own end date" do
|
||||||
expect(next_enabled_phase.starts_at).to eq(second_phase.ends_at)
|
expect(next_enabled_phase.starts_at).to eq(accepting_phase.ends_at)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "when being enabled" do
|
describe "when being enabled" do
|
||||||
before do
|
before do
|
||||||
second_phase.update!(enabled: false,
|
accepting_phase.update!(enabled: false,
|
||||||
starts_at: Date.current,
|
starts_at: Date.current,
|
||||||
ends_at: Date.current + 2.days)
|
ends_at: Date.current + 2.days)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "adjusts previous enabled phase end date to its own start date" do
|
it "adjusts previous enabled phase end date to its own start date" do
|
||||||
expect { second_phase.update(enabled: true) }
|
expect { accepting_phase.update(enabled: true) }
|
||||||
.to change { prev_enabled_phase.ends_at.to_date }.to(Date.current)
|
.to change { prev_enabled_phase.ends_at.to_date }.to(Date.current)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "adjusts next enabled phase start date to its own end date" do
|
it "adjusts next enabled phase start date to its own end date" do
|
||||||
expect do
|
expect do
|
||||||
second_phase.update(enabled: true)
|
accepting_phase.update(enabled: true)
|
||||||
end.to change { next_enabled_phase.starts_at.to_date }.to(Date.current + 2.days)
|
end.to change { next_enabled_phase.starts_at.to_date }.to(Date.current + 2.days)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "when disabled" do
|
describe "when disabled" do
|
||||||
before do
|
before do
|
||||||
second_phase.update!(enabled: false)
|
accepting_phase.update!(enabled: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't change previous enabled phase end date" do
|
it "doesn't change previous enabled phase end date" do
|
||||||
expect { second_phase.update(starts_at: Date.current, ends_at: Date.current + 2.days) }
|
expect { accepting_phase.update(starts_at: Date.current, ends_at: Date.current + 2.days) }
|
||||||
.not_to change { prev_enabled_phase.ends_at }
|
.not_to change { prev_enabled_phase.ends_at }
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't change next enabled phase start date" do
|
it "doesn't change next enabled phase start date" do
|
||||||
expect { second_phase.update(starts_at: Date.current, ends_at: Date.current + 2.days) }
|
expect { accepting_phase.update(starts_at: Date.current, ends_at: Date.current + 2.days) }
|
||||||
.not_to change { next_enabled_phase.starts_at }
|
.not_to change { next_enabled_phase.starts_at }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -179,7 +177,7 @@ describe Budget::Phase do
|
|||||||
describe "when being disabled" do
|
describe "when being disabled" do
|
||||||
it "doesn't adjust previous enabled phase end date to its own start date" do
|
it "doesn't adjust previous enabled phase end date to its own start date" do
|
||||||
expect do
|
expect do
|
||||||
second_phase.update(enabled: false,
|
accepting_phase.update(enabled: false,
|
||||||
starts_at: Date.current,
|
starts_at: Date.current,
|
||||||
ends_at: Date.current + 2.days)
|
ends_at: Date.current + 2.days)
|
||||||
end.not_to change { prev_enabled_phase.ends_at }
|
end.not_to change { prev_enabled_phase.ends_at }
|
||||||
@@ -187,7 +185,7 @@ describe Budget::Phase do
|
|||||||
|
|
||||||
it "adjusts next enabled phase start date to its own start date" do
|
it "adjusts next enabled phase start date to its own start date" do
|
||||||
expect do
|
expect do
|
||||||
second_phase.update(enabled: false,
|
accepting_phase.update(enabled: false,
|
||||||
starts_at: Date.current,
|
starts_at: Date.current,
|
||||||
ends_at: Date.current + 2.days)
|
ends_at: Date.current + 2.days)
|
||||||
end.to change { next_enabled_phase.starts_at.to_date }.to(Date.current)
|
end.to change { next_enabled_phase.starts_at.to_date }.to(Date.current)
|
||||||
@@ -197,22 +195,25 @@ describe Budget::Phase do
|
|||||||
|
|
||||||
describe "next & prev enabled phases" do
|
describe "next & prev enabled phases" do
|
||||||
before do
|
before do
|
||||||
second_phase.update(enabled: false)
|
accepting_phase.update!(enabled: false)
|
||||||
|
%w[selecting reviewing_ballots balloting publishing_prices valuating].each do |phase|
|
||||||
|
budget.phases.send(phase).update(enabled: false)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#next_enabled_phase" do
|
describe "#next_enabled_phase" do
|
||||||
it "returns the right next enabled phase" do
|
it "returns the right next enabled phase" do
|
||||||
expect(first_phase.reload.next_enabled_phase).to eq(third_phase)
|
expect(informing_phase.reload.next_enabled_phase).to eq(reviewing_phase)
|
||||||
expect(third_phase.reload.next_enabled_phase).to eq(fourth_phase)
|
expect(reviewing_phase.reload.next_enabled_phase).to eq(finished_phase)
|
||||||
expect(final_phase.reload.next_enabled_phase).to eq(nil)
|
expect(finished_phase.reload.next_enabled_phase).to eq(nil)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#prev_enabled_phase" do
|
describe "#prev_enabled_phase" do
|
||||||
it "returns the right previous enabled phase" do
|
it "returns the right previous enabled phase" do
|
||||||
expect(first_phase.reload.prev_enabled_phase).to eq(nil)
|
expect(informing_phase.reload.prev_enabled_phase).to eq(nil)
|
||||||
expect(third_phase.reload.prev_enabled_phase).to eq(first_phase)
|
expect(reviewing_phase.reload.prev_enabled_phase).to eq(informing_phase)
|
||||||
expect(fourth_phase.reload.prev_enabled_phase).to eq(third_phase)
|
expect(finished_phase.reload.prev_enabled_phase).to eq(reviewing_phase)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -32,6 +32,36 @@ describe Budget do
|
|||||||
expect(Budget.valuating_or_later).to be_empty
|
expect(Budget.valuating_or_later).to be_empty
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe ".drafting" do
|
||||||
|
it "returns unpublished budgets" do
|
||||||
|
undefined = create(:budget, published: nil)
|
||||||
|
drafting = create(:budget, published: false)
|
||||||
|
|
||||||
|
expect(Budget.drafting).to match_array([undefined, drafting])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not return published budgets" do
|
||||||
|
create(:budget, published: true)
|
||||||
|
|
||||||
|
expect(Budget.drafting).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".published" do
|
||||||
|
it "does not return unpublished budgets" do
|
||||||
|
create(:budget, published: nil)
|
||||||
|
create(:budget, published: false)
|
||||||
|
|
||||||
|
expect(Budget.published).to be_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns published budgets" do
|
||||||
|
published = create(:budget, published: true)
|
||||||
|
|
||||||
|
expect(Budget.published).to eq [published]
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "name" do
|
describe "name" do
|
||||||
@@ -96,9 +126,6 @@ describe Budget do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "produces auxiliary methods" do
|
it "produces auxiliary methods" do
|
||||||
budget.phase = "drafting"
|
|
||||||
expect(budget).to be_drafting
|
|
||||||
|
|
||||||
budget.phase = "accepting"
|
budget.phase = "accepting"
|
||||||
expect(budget).to be_accepting
|
expect(budget).to be_accepting
|
||||||
|
|
||||||
@@ -248,7 +275,6 @@ describe Budget do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe "#generate_phases" do
|
describe "#generate_phases" do
|
||||||
let(:drafting_phase) { budget.phases.drafting }
|
|
||||||
let(:informing_phase) { budget.phases.informing }
|
let(:informing_phase) { budget.phases.informing }
|
||||||
let(:accepting_phase) { budget.phases.accepting }
|
let(:accepting_phase) { budget.phases.accepting }
|
||||||
let(:reviewing_phase) { budget.phases.reviewing }
|
let(:reviewing_phase) { budget.phases.reviewing }
|
||||||
@@ -262,7 +288,6 @@ describe Budget do
|
|||||||
it "generates all phases linked in correct order" do
|
it "generates all phases linked in correct order" do
|
||||||
expect(budget.phases.count).to eq(Budget::Phase::PHASE_KINDS.count)
|
expect(budget.phases.count).to eq(Budget::Phase::PHASE_KINDS.count)
|
||||||
|
|
||||||
expect(drafting_phase.next_phase).to eq(informing_phase)
|
|
||||||
expect(informing_phase.next_phase).to eq(accepting_phase)
|
expect(informing_phase.next_phase).to eq(accepting_phase)
|
||||||
expect(accepting_phase.next_phase).to eq(reviewing_phase)
|
expect(accepting_phase.next_phase).to eq(reviewing_phase)
|
||||||
expect(reviewing_phase.next_phase).to eq(selecting_phase)
|
expect(reviewing_phase.next_phase).to eq(selecting_phase)
|
||||||
@@ -273,8 +298,7 @@ describe Budget do
|
|||||||
expect(reviewing_ballots_phase.next_phase).to eq(finished_phase)
|
expect(reviewing_ballots_phase.next_phase).to eq(finished_phase)
|
||||||
expect(finished_phase.next_phase).to eq(nil)
|
expect(finished_phase.next_phase).to eq(nil)
|
||||||
|
|
||||||
expect(drafting_phase.prev_phase).to eq(nil)
|
expect(informing_phase.prev_phase).to eq(nil)
|
||||||
expect(informing_phase.prev_phase).to eq(drafting_phase)
|
|
||||||
expect(accepting_phase.prev_phase).to eq(informing_phase)
|
expect(accepting_phase.prev_phase).to eq(informing_phase)
|
||||||
expect(reviewing_phase.prev_phase).to eq(accepting_phase)
|
expect(reviewing_phase.prev_phase).to eq(accepting_phase)
|
||||||
expect(selecting_phase.prev_phase).to eq(reviewing_phase)
|
expect(selecting_phase.prev_phase).to eq(reviewing_phase)
|
||||||
|
|||||||
@@ -15,19 +15,20 @@ describe "Admin budgets", :admin do
|
|||||||
let!(:budget) { create(:budget, slug: "budget_slug") }
|
let!(:budget) { create(:budget, slug: "budget_slug") }
|
||||||
|
|
||||||
scenario "finds budget by slug" do
|
scenario "finds budget by slug" do
|
||||||
visit admin_budget_path("budget_slug")
|
visit edit_admin_budget_path("budget_slug")
|
||||||
expect(page).to have_content(budget.name)
|
|
||||||
|
expect(page).to have_content("Edit Participatory budget")
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "raises an error if budget slug is not found" do
|
scenario "raises an error if budget slug is not found" do
|
||||||
expect do
|
expect do
|
||||||
visit admin_budget_path("wrong_budget")
|
visit edit_admin_budget_path("wrong_budget")
|
||||||
end.to raise_error ActiveRecord::RecordNotFound
|
end.to raise_error ActiveRecord::RecordNotFound
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "raises an error if budget id is not found" do
|
scenario "raises an error if budget id is not found" do
|
||||||
expect do
|
expect do
|
||||||
visit admin_budget_path(0)
|
visit edit_admin_budget_path(0)
|
||||||
end.to raise_error ActiveRecord::RecordNotFound
|
end.to raise_error ActiveRecord::RecordNotFound
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -107,8 +108,8 @@ describe "Admin budgets", :admin do
|
|||||||
click_button "Create Budget"
|
click_button "Create Budget"
|
||||||
|
|
||||||
expect(page).to have_content "New participatory budget created successfully!"
|
expect(page).to have_content "New participatory budget created successfully!"
|
||||||
expect(page).to have_content "M30 - Summer campaign"
|
expect(page).to have_field "Name", with: "M30 - Summer campaign"
|
||||||
expect(Budget.last.voting_style).to eq "knapsack"
|
expect(page).to have_select "Final voting style", selected: "Knapsack"
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario "Create budget - Approval voting", :js do
|
scenario "Create budget - Approval voting", :js do
|
||||||
@@ -161,6 +162,49 @@ describe "Admin budgets", :admin do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "Create", :js do
|
||||||
|
scenario "A new budget is always created in draft mode" do
|
||||||
|
visit admin_budgets_path
|
||||||
|
click_link "Create new budget"
|
||||||
|
|
||||||
|
fill_in "Name", with: "M30 - Summer campaign"
|
||||||
|
select "Accepting projects", from: "budget[phase]"
|
||||||
|
|
||||||
|
click_button "Create Budget"
|
||||||
|
|
||||||
|
expect(page).to have_content "New participatory budget created successfully!"
|
||||||
|
expect(page).to have_content "This participatory budget is in draft mode"
|
||||||
|
expect(page).to have_link "Preview budget"
|
||||||
|
expect(page).to have_link "Publish budget"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "Publish", :js do
|
||||||
|
let(:budget) { create(:budget, :drafting) }
|
||||||
|
|
||||||
|
scenario "Can preview budget before it is published" do
|
||||||
|
visit edit_admin_budget_path(budget)
|
||||||
|
|
||||||
|
within_window(window_opened_by { click_link "Preview budget" }) do
|
||||||
|
expect(page).to have_current_path budget_path(budget)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Can preview a budget after it is published" do
|
||||||
|
visit edit_admin_budget_path(budget)
|
||||||
|
|
||||||
|
accept_confirm { click_link "Publish budget" }
|
||||||
|
|
||||||
|
expect(page).to have_content "Participatory budget published successfully"
|
||||||
|
expect(page).not_to have_content "This participatory budget is in draft mode"
|
||||||
|
expect(page).not_to have_link "Publish budget"
|
||||||
|
|
||||||
|
within_window(window_opened_by { click_link "Preview budget" }) do
|
||||||
|
expect(page).to have_current_path budget_path(budget)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "Destroy" do
|
context "Destroy" do
|
||||||
let!(:budget) { create(:budget) }
|
let!(:budget) { create(:budget) }
|
||||||
let(:heading) { create(:budget_heading, budget: budget) }
|
let(:heading) { create(:budget_heading, budget: budget) }
|
||||||
@@ -242,7 +286,7 @@ describe "Admin budgets", :admin do
|
|||||||
end
|
end
|
||||||
|
|
||||||
scenario "Changing name for current locale will update the slug if budget is in draft phase", :js do
|
scenario "Changing name for current locale will update the slug if budget is in draft phase", :js do
|
||||||
budget.update!(phase: "drafting")
|
budget.update!(published: false)
|
||||||
old_slug = budget.slug
|
old_slug = budget.slug
|
||||||
|
|
||||||
visit edit_admin_budget_path(budget)
|
visit edit_admin_budget_path(budget)
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ describe "Budgets" do
|
|||||||
scenario "Not show investment links earlier of balloting " do
|
scenario "Not show investment links earlier of balloting " do
|
||||||
budget = create(:budget)
|
budget = create(:budget)
|
||||||
create(:budget_heading, budget: budget)
|
create(:budget_heading, budget: budget)
|
||||||
phases_without_links = ["drafting", "informing"]
|
phases_without_links = ["informing"]
|
||||||
not_allowed_phase_list = Budget::Phase::PHASE_KINDS -
|
not_allowed_phase_list = Budget::Phase::PHASE_KINDS -
|
||||||
phases_without_links -
|
phases_without_links -
|
||||||
allowed_phase_list
|
allowed_phase_list
|
||||||
@@ -205,9 +205,10 @@ describe "Budgets" do
|
|||||||
scenario "Index shows only published phases" do
|
scenario "Index shows only published phases" do
|
||||||
budget.update!(phase: :finished)
|
budget.update!(phase: :finished)
|
||||||
phases = budget.phases
|
phases = budget.phases
|
||||||
phases.drafting.update!(starts_at: "30-12-2017", ends_at: "31-12-2017", enabled: true,
|
|
||||||
description: "Description of drafting phase",
|
phases.informing.update!(starts_at: "30-12-2017", ends_at: "31-12-2017", enabled: true,
|
||||||
summary: "<p>This is the summary for drafting phase</p>")
|
description: "Description of informing phase",
|
||||||
|
summary: "<p>This is the summary for informing phase</p>")
|
||||||
|
|
||||||
phases.accepting.update!(starts_at: "01-01-2018", ends_at: "10-01-2018", enabled: true,
|
phases.accepting.update!(starts_at: "01-01-2018", ends_at: "10-01-2018", enabled: true,
|
||||||
description: "Description of accepting phase",
|
description: "Description of accepting phase",
|
||||||
@@ -243,8 +244,6 @@ describe "Budgets" do
|
|||||||
|
|
||||||
visit budgets_path
|
visit budgets_path
|
||||||
|
|
||||||
expect(page).not_to have_content "This is the summary for drafting phase"
|
|
||||||
expect(page).not_to have_content "December 30, 2017 - December 31, 2017"
|
|
||||||
expect(page).not_to have_content "This is the summary for reviewing phase"
|
expect(page).not_to have_content "This is the summary for reviewing phase"
|
||||||
expect(page).not_to have_content "January 11, 2018 - January 20, 2018"
|
expect(page).not_to have_content "January 11, 2018 - January 20, 2018"
|
||||||
expect(page).not_to have_content "This is the summary for valuating phase"
|
expect(page).not_to have_content "This is the summary for valuating phase"
|
||||||
@@ -254,6 +253,8 @@ describe "Budgets" do
|
|||||||
expect(page).not_to have_content "This is the summary for reviewing_ballots phase"
|
expect(page).not_to have_content "This is the summary for reviewing_ballots phase"
|
||||||
expect(page).not_to have_content "March 11, 2018 - March 20, 2018"
|
expect(page).not_to have_content "March 11, 2018 - March 20, 2018"
|
||||||
|
|
||||||
|
expect(page).to have_content "This is the summary for informing phase"
|
||||||
|
expect(page).to have_content "December 30, 2017 - December 31, 2017"
|
||||||
expect(page).to have_content "This is the summary for accepting phase"
|
expect(page).to have_content "This is the summary for accepting phase"
|
||||||
expect(page).to have_content "January 01, 2018 - January 20, 2018"
|
expect(page).to have_content "January 01, 2018 - January 20, 2018"
|
||||||
expect(page).to have_content "This is the summary for selecting phase"
|
expect(page).to have_content "This is the summary for selecting phase"
|
||||||
@@ -478,7 +479,7 @@ describe "Budgets" do
|
|||||||
|
|
||||||
before do
|
before do
|
||||||
logout
|
logout
|
||||||
budget.update!(phase: "drafting")
|
budget.update!(published: false)
|
||||||
create(:budget)
|
create(:budget)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user