Allow creating budgets step by step
We introduce the first step (creating the budget). Co-Authored-By: decabeza <alberto@decabeza.es>
This commit is contained in:
committed by
Javi Martín
parent
82e8de094b
commit
2115eb5274
@@ -0,0 +1,34 @@
|
|||||||
|
.creation-timeline {
|
||||||
|
display: flex;
|
||||||
|
list-style-type: none;
|
||||||
|
margin: $line-height * 2 0;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
li {
|
||||||
|
border-top: 4px solid $admin-border-color;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: $small-font-size;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: $line-height / 2 $line-height * 3 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
background: $admin-border-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
content: "";
|
||||||
|
height: 20px;
|
||||||
|
margin-left: $line-height / 2;
|
||||||
|
position: absolute;
|
||||||
|
top: -8px;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[aria-current] {
|
||||||
|
border-color: $brand;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
background: $brand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<%= translatable_form_for [:admin, budget], html: { class: "budgets-form" } do |f| %>
|
<%= translatable_form_for [namespace, budget], html: { class: "budgets-form" } do |f| %>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend><%= t("admin.budgets.edit.info.budget_settings") %></legend>
|
<legend><%= t("admin.budgets.edit.info.budget_settings") %></legend>
|
||||||
<%= render "shared/globalize_locales", resource: budget %>
|
<%= render "shared/globalize_locales", resource: budget %>
|
||||||
@@ -37,17 +37,16 @@
|
|||||||
<%= render "/admin/budgets/association", assignable_type: "valuators", assignables: valuators, form: f %>
|
<%= render "/admin/budgets/association", assignable_type: "valuators", assignables: valuators, form: f %>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<% if budget.persisted? %>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend><%= t("admin.budgets.edit.info.phases_settings") %></legend>
|
<legend><%= t("admin.budgets.edit.info.phases_settings") %></legend>
|
||||||
<div class="small-12 medium-6 column">
|
<div class="small-12 medium-6 column">
|
||||||
<%= f.select :phase, phases_select_options %>
|
<%= f.select :phase, phases_select_options %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= render Admin::Budgets::HelpComponent.new("budget_phases") %>
|
|
||||||
<%= render Admin::BudgetPhases::PhasesComponent.new(budget) %>
|
<%= render Admin::BudgetPhases::PhasesComponent.new(budget) %>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<% if budget.persisted? %>
|
|
||||||
<%= render "admin/shared/show_results_fields", form: f %>
|
<%= render "admin/shared/show_results_fields", form: f %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,14 @@ class Admin::Budgets::FormComponent < ApplicationComponent
|
|||||||
@budget = budget
|
@budget = budget
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def namespace
|
||||||
|
if controller.class.name.starts_with?("Admin::BudgetsWizard")
|
||||||
|
:admin_budgets_wizard
|
||||||
|
else
|
||||||
|
helpers.namespace.to_sym
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def voting_styles_select_options
|
def voting_styles_select_options
|
||||||
Budget::VOTING_STYLES.map do |style|
|
Budget::VOTING_STYLES.map do |style|
|
||||||
[Budget.human_attribute_name("voting_style_#{style}"), style]
|
[Budget.human_attribute_name("voting_style_#{style}"), style]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<%= header do %>
|
<%= header do %>
|
||||||
<%= link_to t("admin.budgets.index.new_link"), new_admin_budget_path %>
|
<%= link_to t("admin.budgets.index.new_link"), new_admin_budgets_wizard_budget_path %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= render Admin::Budgets::HelpComponent.new("budgets") %>
|
<%= render Admin::Budgets::HelpComponent.new("budgets") %>
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<%= back_link_to admin_budgets_path %>
|
||||||
|
|
||||||
|
<%= header %>
|
||||||
|
|
||||||
|
<%= render Admin::BudgetsWizard::CreationTimelineComponent.new %>
|
||||||
|
<%= render Admin::Budgets::FormComponent.new(budget) %>
|
||||||
12
app/components/admin/budgets_wizard/budgets/new_component.rb
Normal file
12
app/components/admin/budgets_wizard/budgets/new_component.rb
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
class Admin::BudgetsWizard::Budgets::NewComponent < ApplicationComponent
|
||||||
|
include Header
|
||||||
|
attr_reader :budget
|
||||||
|
|
||||||
|
def initialize(budget)
|
||||||
|
@budget = budget
|
||||||
|
end
|
||||||
|
|
||||||
|
def title
|
||||||
|
t("admin.budgets.new.title")
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<ol class="creation-timeline">
|
||||||
|
<li aria-current="step">
|
||||||
|
<%= t("admin.budgets_wizard.creation_timeline.budget") %>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
class Admin::BudgetsWizard::CreationTimelineComponent < ApplicationComponent
|
||||||
|
end
|
||||||
@@ -6,7 +6,7 @@ class Admin::BudgetsController < Admin::BaseController
|
|||||||
|
|
||||||
has_filters %w[all open finished], only: :index
|
has_filters %w[all open finished], only: :index
|
||||||
|
|
||||||
before_action :load_budget, except: [:index, :new, :create]
|
before_action :load_budget, except: [:index]
|
||||||
load_and_authorize_resource
|
load_and_authorize_resource
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@@ -17,9 +17,6 @@ class Admin::BudgetsController < Admin::BaseController
|
|||||||
render :edit
|
render :edit
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
|
||||||
end
|
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -46,15 +43,6 @@ class Admin::BudgetsController < Admin::BaseController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
|
||||||
@budget = Budget.new(budget_params.merge(published: false))
|
|
||||||
if @budget.save
|
|
||||||
redirect_to edit_admin_budget_path(@budget), notice: t("admin.budgets.create.notice")
|
|
||||||
else
|
|
||||||
render :new
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
if @budget.investments.any?
|
if @budget.investments.any?
|
||||||
redirect_to admin_budgets_path, alert: t("admin.budgets.destroy.unable_notice")
|
redirect_to admin_budgets_path, alert: t("admin.budgets.destroy.unable_notice")
|
||||||
|
|||||||
32
app/controllers/admin/budgets_wizard/budgets_controller.rb
Normal file
32
app/controllers/admin/budgets_wizard/budgets_controller.rb
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
class Admin::BudgetsWizard::BudgetsController < Admin::BaseController
|
||||||
|
include Translatable
|
||||||
|
include FeatureFlags
|
||||||
|
feature_flag :budgets
|
||||||
|
|
||||||
|
load_and_authorize_resource
|
||||||
|
|
||||||
|
def new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@budget.published = false
|
||||||
|
|
||||||
|
if @budget.save
|
||||||
|
redirect_to edit_admin_budget_path(@budget), notice: t("admin.budgets.create.notice")
|
||||||
|
else
|
||||||
|
render :new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def budget_params
|
||||||
|
params.require(:budget).permit(*allowed_params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def allowed_params
|
||||||
|
valid_attributes = [:currency_symbol, :voting_style, administrator_ids: [], valuator_ids: []]
|
||||||
|
|
||||||
|
valid_attributes + [translation_params(Budget)]
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<%= back_link_to admin_budgets_path %>
|
|
||||||
|
|
||||||
<header>
|
|
||||||
<h2><%= t("admin.budgets.new.title") %></h2>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<%= render Admin::Budgets::FormComponent.new(@budget) %>
|
|
||||||
1
app/views/admin/budgets_wizard/budgets/new.html.erb
Normal file
1
app/views/admin/budgets_wizard/budgets/new.html.erb
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<%= render Admin::BudgetsWizard::Budgets::NewComponent.new(@budget) %>
|
||||||
@@ -284,6 +284,9 @@ en:
|
|||||||
tags_placeholder: "Write the tags you want separated by commas (,)"
|
tags_placeholder: "Write the tags you want separated by commas (,)"
|
||||||
undefined: Undefined
|
undefined: Undefined
|
||||||
search_unfeasible: Search unfeasible
|
search_unfeasible: Search unfeasible
|
||||||
|
budgets_wizard:
|
||||||
|
creation_timeline:
|
||||||
|
budget: Budget
|
||||||
milestones:
|
milestones:
|
||||||
index:
|
index:
|
||||||
table_id: "ID"
|
table_id: "ID"
|
||||||
|
|||||||
@@ -284,6 +284,9 @@ es:
|
|||||||
tags_placeholder: "Escribe las etiquetas que desees separadas por comas (,)"
|
tags_placeholder: "Escribe las etiquetas que desees separadas por comas (,)"
|
||||||
undefined: Sin definir
|
undefined: Sin definir
|
||||||
search_unfeasible: Buscar inviables
|
search_unfeasible: Buscar inviables
|
||||||
|
budgets_wizard:
|
||||||
|
creation_timeline:
|
||||||
|
budget: Presupuesto
|
||||||
milestones:
|
milestones:
|
||||||
index:
|
index:
|
||||||
table_id: "ID"
|
table_id: "ID"
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace :admin do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :budgets do
|
resources :budgets, except: [:create, :new] do
|
||||||
member do
|
member do
|
||||||
patch :publish
|
patch :publish
|
||||||
put :calculate_winners
|
put :calculate_winners
|
||||||
@@ -72,6 +72,10 @@ namespace :admin do
|
|||||||
resources :budget_phases, only: [:edit, :update]
|
resources :budget_phases, only: [:edit, :update]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
namespace :budgets_wizard do
|
||||||
|
resources :budgets, only: [:create, :new]
|
||||||
|
end
|
||||||
|
|
||||||
resources :milestone_statuses, only: [:index, :new, :create, :update, :edit, :destroy]
|
resources :milestone_statuses, only: [:index, :new, :create, :update, :edit, :destroy]
|
||||||
|
|
||||||
resources :signature_sheets, only: [:index, :new, :create, :show]
|
resources :signature_sheets, only: [:index, :new, :create, :show]
|
||||||
|
|||||||
@@ -84,88 +84,6 @@ describe "Admin budgets", :admin do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "New" do
|
|
||||||
scenario "Create budget - Knapsack voting (default)" 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_field "Name", with: "M30 - Summer campaign"
|
|
||||||
expect(page).to have_select "Final voting style", selected: "Knapsack"
|
|
||||||
end
|
|
||||||
|
|
||||||
scenario "Create budget - Approval voting" do
|
|
||||||
admin = Administrator.first
|
|
||||||
|
|
||||||
visit admin_budgets_path
|
|
||||||
click_link "Create new budget"
|
|
||||||
|
|
||||||
fill_in "Name", with: "M30 - Summer campaign"
|
|
||||||
select "Accepting projects", from: "budget[phase]"
|
|
||||||
select "Approval", from: "Final voting style"
|
|
||||||
click_button "Create Budget"
|
|
||||||
|
|
||||||
expect(page).to have_content "New participatory budget created successfully!"
|
|
||||||
expect(page).to have_field "Name", with: "M30 - Summer campaign"
|
|
||||||
expect(page).to have_select "Final voting style", selected: "Approval"
|
|
||||||
|
|
||||||
click_link "Select administrators"
|
|
||||||
|
|
||||||
expect(page).to have_field admin.name
|
|
||||||
end
|
|
||||||
|
|
||||||
scenario "Name is mandatory" do
|
|
||||||
visit new_admin_budget_path
|
|
||||||
click_button "Create Budget"
|
|
||||||
|
|
||||||
expect(page).not_to have_content "New participatory budget created successfully!"
|
|
||||||
expect(page).to have_css(".is-invalid-label", text: "Name")
|
|
||||||
end
|
|
||||||
|
|
||||||
scenario "Name should be unique" do
|
|
||||||
create(:budget, name: "Existing Name")
|
|
||||||
|
|
||||||
visit new_admin_budget_path
|
|
||||||
fill_in "Name", with: "Existing Name"
|
|
||||||
click_button "Create Budget"
|
|
||||||
|
|
||||||
expect(page).not_to have_content "New participatory budget created successfully!"
|
|
||||||
expect(page).to have_css(".is-invalid-label", text: "Name")
|
|
||||||
expect(page).to have_css("small.form-error", text: "has already been taken")
|
|
||||||
end
|
|
||||||
|
|
||||||
scenario "Do not show results and stats settings on new budget" do
|
|
||||||
visit new_admin_budget_path
|
|
||||||
|
|
||||||
expect(page).not_to have_content "Show results and stats"
|
|
||||||
expect(page).not_to have_field "Show results"
|
|
||||||
expect(page).not_to have_field "Show stats"
|
|
||||||
expect(page).not_to have_field "Show advanced stats"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "Create" 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" do
|
context "Publish" do
|
||||||
let(:budget) { create(:budget, :drafting) }
|
let(:budget) { create(:budget, :drafting) }
|
||||||
|
|
||||||
|
|||||||
82
spec/system/admin/budgets_wizard/budgets_spec.rb
Normal file
82
spec/system/admin/budgets_wizard/budgets_spec.rb
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
describe "Budgets wizard, first step", :admin do
|
||||||
|
describe "New" do
|
||||||
|
scenario "Create budget - Knapsack voting (default)" do
|
||||||
|
visit admin_budgets_path
|
||||||
|
click_link "Create new budget"
|
||||||
|
|
||||||
|
fill_in "Name", with: "M30 - Summer campaign"
|
||||||
|
click_button "Create Budget"
|
||||||
|
|
||||||
|
expect(page).to have_content "New participatory budget created successfully!"
|
||||||
|
expect(page).to have_field "Name", with: "M30 - Summer campaign"
|
||||||
|
expect(page).to have_select "Final voting style", selected: "Knapsack"
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Create budget - Approval voting" do
|
||||||
|
admin = Administrator.first
|
||||||
|
|
||||||
|
visit admin_budgets_path
|
||||||
|
click_link "Create new budget"
|
||||||
|
|
||||||
|
fill_in "Name", with: "M30 - Summer campaign"
|
||||||
|
select "Approval", from: "Final voting style"
|
||||||
|
click_button "Create Budget"
|
||||||
|
|
||||||
|
expect(page).to have_content "New participatory budget created successfully!"
|
||||||
|
expect(page).to have_field "Name", with: "M30 - Summer campaign"
|
||||||
|
expect(page).to have_select "Final voting style", selected: "Approval"
|
||||||
|
|
||||||
|
click_link "Select administrators"
|
||||||
|
|
||||||
|
expect(page).to have_field admin.name
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Submit the form with errors" do
|
||||||
|
visit new_admin_budgets_wizard_budget_path
|
||||||
|
click_button "Create Budget"
|
||||||
|
|
||||||
|
expect(page).not_to have_content "New participatory budget created successfully!"
|
||||||
|
expect(page).to have_css ".is-invalid-label", text: "Name"
|
||||||
|
expect(page).to have_css ".creation-timeline"
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Name should be unique" do
|
||||||
|
create(:budget, name: "Existing Name")
|
||||||
|
|
||||||
|
visit new_admin_budgets_wizard_budget_path
|
||||||
|
fill_in "Name", with: "Existing Name"
|
||||||
|
click_button "Create Budget"
|
||||||
|
|
||||||
|
expect(page).not_to have_content "New participatory budget created successfully!"
|
||||||
|
expect(page).to have_css(".is-invalid-label", text: "Name")
|
||||||
|
expect(page).to have_css("small.form-error", text: "has already been taken")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Do not show results and stats settings on new budget" do
|
||||||
|
visit new_admin_budgets_wizard_budget_path
|
||||||
|
|
||||||
|
expect(page).not_to have_content "Show results and stats"
|
||||||
|
expect(page).not_to have_field "Show results"
|
||||||
|
expect(page).not_to have_field "Show stats"
|
||||||
|
expect(page).not_to have_field "Show advanced stats"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Create" 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"
|
||||||
|
|
||||||
|
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
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user