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:
Julian Herrero
2020-03-15 06:51:52 +01:00
committed by Javi Martín
parent 82e8de094b
commit 2115eb5274
17 changed files with 205 additions and 115 deletions

View File

@@ -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;
}
}
}
}

View File

@@ -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>
<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? %>
<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::BudgetPhases::PhasesComponent.new(budget) %>
</fieldset>
<%= render "admin/shared/show_results_fields", form: f %>
<% end %>

View File

@@ -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]

View File

@@ -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") %>

View File

@@ -0,0 +1,6 @@
<%= back_link_to admin_budgets_path %>
<%= header %>
<%= render Admin::BudgetsWizard::CreationTimelineComponent.new %>
<%= render Admin::Budgets::FormComponent.new(budget) %>

View 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

View File

@@ -0,0 +1,5 @@
<ol class="creation-timeline">
<li aria-current="step">
<%= t("admin.budgets_wizard.creation_timeline.budget") %>
</li>
</ol>

View File

@@ -0,0 +1,2 @@
class Admin::BudgetsWizard::CreationTimelineComponent < ApplicationComponent
end

View File

@@ -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")

View 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

View File

@@ -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) %>

View File

@@ -0,0 +1 @@
<%= render Admin::BudgetsWizard::Budgets::NewComponent.new(@budget) %>

View File

@@ -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"

View File

@@ -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"

View File

@@ -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]

View File

@@ -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) }

View 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