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>
|
||||
<legend><%= t("admin.budgets.edit.info.budget_settings") %></legend>
|
||||
<%= render "shared/globalize_locales", resource: budget %>
|
||||
@@ -37,17 +37,16 @@
|
||||
<%= render "/admin/budgets/association", assignable_type: "valuators", assignables: valuators, form: f %>
|
||||
</fieldset>
|
||||
|
||||
<% if budget.persisted? %>
|
||||
<fieldset>
|
||||
<legend><%= t("admin.budgets.edit.info.phases_settings") %></legend>
|
||||
<div class="small-12 medium-6 column">
|
||||
<%= f.select :phase, phases_select_options %>
|
||||
</div>
|
||||
|
||||
<%= render Admin::Budgets::HelpComponent.new("budget_phases") %>
|
||||
<%= render Admin::BudgetPhases::PhasesComponent.new(budget) %>
|
||||
</fieldset>
|
||||
|
||||
<% if budget.persisted? %>
|
||||
<%= render "admin/shared/show_results_fields", form: f %>
|
||||
<% end %>
|
||||
|
||||
|
||||
@@ -12,6 +12,14 @@ class Admin::Budgets::FormComponent < ApplicationComponent
|
||||
@budget = budget
|
||||
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
|
||||
Budget::VOTING_STYLES.map do |style|
|
||||
[Budget.human_attribute_name("voting_style_#{style}"), style]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<%= 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 %>
|
||||
|
||||
<%= 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
|
||||
|
||||
before_action :load_budget, except: [:index, :new, :create]
|
||||
before_action :load_budget, except: [:index]
|
||||
load_and_authorize_resource
|
||||
|
||||
def index
|
||||
@@ -17,9 +17,6 @@ class Admin::BudgetsController < Admin::BaseController
|
||||
render :edit
|
||||
end
|
||||
|
||||
def new
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
@@ -46,15 +43,6 @@ class Admin::BudgetsController < Admin::BaseController
|
||||
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
|
||||
if @budget.investments.any?
|
||||
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 (,)"
|
||||
undefined: Undefined
|
||||
search_unfeasible: Search unfeasible
|
||||
budgets_wizard:
|
||||
creation_timeline:
|
||||
budget: Budget
|
||||
milestones:
|
||||
index:
|
||||
table_id: "ID"
|
||||
|
||||
@@ -284,6 +284,9 @@ es:
|
||||
tags_placeholder: "Escribe las etiquetas que desees separadas por comas (,)"
|
||||
undefined: Sin definir
|
||||
search_unfeasible: Buscar inviables
|
||||
budgets_wizard:
|
||||
creation_timeline:
|
||||
budget: Presupuesto
|
||||
milestones:
|
||||
index:
|
||||
table_id: "ID"
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace :admin do
|
||||
end
|
||||
end
|
||||
|
||||
resources :budgets do
|
||||
resources :budgets, except: [:create, :new] do
|
||||
member do
|
||||
patch :publish
|
||||
put :calculate_winners
|
||||
@@ -72,6 +72,10 @@ namespace :admin do
|
||||
resources :budget_phases, only: [:edit, :update]
|
||||
end
|
||||
|
||||
namespace :budgets_wizard do
|
||||
resources :budgets, only: [:create, :new]
|
||||
end
|
||||
|
||||
resources :milestone_statuses, only: [:index, :new, :create, :update, :edit, :destroy]
|
||||
|
||||
resources :signature_sheets, only: [:index, :new, :create, :show]
|
||||
|
||||
@@ -84,88 +84,6 @@ describe "Admin budgets", :admin do
|
||||
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
|
||||
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