Move phases and actions out of the budget form

Having links in the middle of a form distracts users from the task of
filling in the form, and following a link before submitting the form
will mean whatever has been filled in is lost.

And the budgets form is already very long and hard to fill in. Having
the phases table in the middle of it made it even harder. And, since
we're planning to add the option to manage groups and headings from the
same page, it's better to have a dedicated page for the form.
This commit is contained in:
Javi Martín
2021-08-23 01:00:05 +02:00
parent 8aa6f29d6b
commit 349dbb74d7
22 changed files with 158 additions and 73 deletions

View File

@@ -9,27 +9,12 @@
margin-top: $gap; margin-top: $gap;
} }
+ * {
margin-top: $line-height;
}
a,
button { button {
margin-bottom: 0;
}
.preview-link {
@include has-fa-icon(eye, regular);
@include hollow-button;
margin-left: $gap;
margin-top: $gap;
&::before {
margin-#{$global-right}: $font-icon-margin;
}
}
.delete {
cursor: pointer; cursor: pointer;
} }
.calculate-winners-link {
@include hollow-button;
margin-bottom: 0;
}
} }

View File

@@ -0,0 +1,40 @@
.admin .budgets-links {
$gap: $line-height;
@include flex-with-gap($gap);
align-items: baseline;
flex-wrap: wrap;
margin-top: -$gap;
> * {
margin-top: $gap;
}
+ * {
margin-top: $line-height;
}
.preview-link {
@include has-fa-icon(eye, regular);
@include hollow-button;
}
.edit-link {
@include has-fa-icon(edit, regular);
@include hollow-button;
}
.results-link {
@include hollow-button;
}
.edit-link,
.preview-link,
.results-link {
margin-left: $gap;
margin-top: $gap;
&::before {
margin-#{$global-right}: $font-icon-margin;
}
}
}

View File

@@ -0,0 +1,12 @@
.admin-budgets-show {
h3 {
margin-top: $line-height * 1.5;
@each $size, $headers in $header-styles {
@include breakpoint($size) {
font-size: (rem-calc(map-get(map-get($headers, h2), font-size)) + rem-calc(map-get(map-get($headers, h3), font-size))) / 2;
}
}
}
}

View File

@@ -1,12 +1,5 @@
<div class="budgets-actions"> <div class="budgets-actions">
<%= render Admin::Budgets::CalculateWinnersButtonComponent.new(budget) %> <%= render Admin::Budgets::CalculateWinnersButtonComponent.new(budget) %>
<% if budget.has_winning_investments? %>
<%= link_to t("budgets.show.see_results"),
budget_results_path(budget),
class: "button hollow" %>
<% end %>
<%= link_to t("admin.budgets.actions.preview"), budget_path(budget), class: "preview-link", target: "_blank" %>
<%= action(:destroy, <%= action(:destroy,
text: t("admin.budgets.edit.delete"), text: t("admin.budgets.edit.delete"),

View File

@@ -21,10 +21,6 @@ class Admin::Budgets::CalculateWinnersButtonComponent < ApplicationComponent
end end
def html_class def html_class
if from_investments "button hollow float-right clear" if from_investments
"button hollow float-right clear"
else
"button hollow"
end
end end
end end

View File

@@ -39,6 +39,12 @@
</div> </div>
</div> </div>
<% unless wizard? %>
<div class="small-12 medium-6 column">
<%= f.select :phase, phases_select_options %>
</div>
<% end %>
<% if feature?(:allow_images) %> <% if feature?(:allow_images) %>
<div class="images small-12 column"> <div class="images small-12 column">
<%= render "/images/nested_image", f: f %> <%= render "/images/nested_image", f: f %>
@@ -64,15 +70,6 @@
</fieldset> </fieldset>
<% unless wizard? %> <% unless wizard? %>
<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 %> <%= render "admin/shared/show_results_fields", form: f %>
<% end %> <% end %>

View File

@@ -0,0 +1,11 @@
<div class="budgets-links">
<% if budget.has_winning_investments? %>
<%= action(:results,
text: t("budgets.show.see_results"),
path: budget_results_path(budget)) %>
<% end %>
<%= action(:preview, text: t("admin.budgets.actions.preview"), path: budget_path(budget), target: "_blank") %>
<%= action(:edit, text: t("admin.budgets.actions.edit")) %>
</div>

View File

@@ -0,0 +1,13 @@
class Admin::Budgets::LinksComponent < ApplicationComponent
attr_reader :budget
def initialize(budget)
@budget = budget
end
private
def action(action_name, **options)
render Admin::ActionComponent.new(action_name, budget, **options)
end
end

View File

@@ -0,0 +1,18 @@
<main class="admin-budgets-show">
<%= back_link_to admin_budgets_path %>
<%= header %>
<%= render Admin::Budgets::DraftingComponent.new(budget) %>
<%= render Admin::Budgets::LinksComponent.new(budget) %>
<section aria-labelledby="phases_header">
<h3 id="phases_header"><%= t("admin.budgets.edit.phases_caption") %></h3>
<%= render Admin::BudgetPhases::PhasesComponent.new(budget) %>
</section>
<section aria-labelledby="actions_header">
<h3 id="actions_header"><%= t("admin.budgets.edit.actions") %></h3>
<%= render Admin::Budgets::ActionsComponent.new(budget) %>
</section>
</main>

View File

@@ -0,0 +1,14 @@
class Admin::Budgets::ShowComponent < ApplicationComponent
include Header
attr_reader :budget
def initialize(budget)
@budget = budget
end
private
def title
budget.name
end
end

View File

@@ -1,4 +1,4 @@
<%= render Admin::TableActionsComponent.new(budget) do |actions| %> <%= render Admin::TableActionsComponent.new(budget, edit_path: admin_budget_path(budget)) do |actions| %>
<%= actions.action(:investments, <%= actions.action(:investments,
text: t("admin.budgets.index.budget_investments"), text: t("admin.budgets.index.budget_investments"),
path: admin_budget_budget_investments_path(budget_id: budget.id)) %> path: admin_budget_budget_investments_path(budget_id: budget.id)) %>

View File

@@ -4,6 +4,6 @@ class Admin::BudgetPhasesController < Admin::BaseController
private private
def phases_index def phases_index
edit_admin_budget_path(@phase.budget) admin_budget_path(@phase.budget)
end end
end end

View File

@@ -15,7 +15,6 @@ class Admin::BudgetsController < Admin::BaseController
end end
def show def show
render :edit
end end
def edit def edit
@@ -23,7 +22,7 @@ class Admin::BudgetsController < Admin::BaseController
def publish def publish
@budget.publish! @budget.publish!
redirect_to edit_admin_budget_path(@budget), notice: t("admin.budgets.publish.notice") redirect_to admin_budget_path(@budget), notice: t("admin.budgets.publish.notice")
end end
def calculate_winners def calculate_winners
@@ -38,7 +37,7 @@ class Admin::BudgetsController < Admin::BaseController
def update def update
if @budget.update(budget_params) if @budget.update(budget_params)
redirect_to admin_budgets_path, notice: t("admin.budgets.update.notice") redirect_to admin_budget_path(@budget), notice: t("admin.budgets.update.notice")
else else
render :edit render :edit
end end

View File

@@ -1,9 +1,7 @@
<%= back_link_to admin_budgets_path %> <%= back_link_to admin_budget_path(@budget) %>
<header> <header>
<h2><%= t("admin.budgets.edit.title") %></h2> <h2><%= t("admin.budgets.edit.title") %></h2>
<%= render Admin::Budgets::DraftingComponent.new(@budget) %>
</header> </header>
<%= render Admin::Budgets::ActionsComponent.new(@budget) %>
<%= render Admin::Budgets::FormComponent.new(@budget) %> <%= render Admin::Budgets::FormComponent.new(@budget) %>

View File

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

View File

@@ -69,6 +69,7 @@ en:
no_activity: There are no moderators activity. no_activity: There are no moderators activity.
budgets: budgets:
actions: actions:
edit: "Edit budget"
preview: "Preview" preview: "Preview"
index: index:
title: Participatory budgets title: Participatory budgets
@@ -127,7 +128,6 @@ en:
main_call_to_action_description: "This link will appear on main banner of this participatory budget and encourages your user to perform a specific action like creating a proposal, voting for existing ones, or learn more about the process." main_call_to_action_description: "This link will appear on main banner of this participatory budget and encourages your user to perform a specific action like creating a proposal, voting for existing ones, or learn more about the process."
info: info:
budget_settings: "General participatory budget settings" budget_settings: "General participatory budget settings"
phases_settings: "Phases settings"
staff_settings: "Administrators and Valuators assigned to the budget" staff_settings: "Administrators and Valuators assigned to the budget"
destroy: destroy:
success_notice: Budget deleted successfully success_notice: Budget deleted successfully

View File

@@ -69,6 +69,7 @@ es:
no_activity: No hay actividad de moderadores. no_activity: No hay actividad de moderadores.
budgets: budgets:
actions: actions:
edit: "Editar presupuesto"
preview: "Previsualizar" preview: "Previsualizar"
index: index:
title: Presupuestos participativos title: Presupuestos participativos
@@ -127,7 +128,6 @@ es:
main_call_to_action_description: "Este enlace aparecerá en la cabecera de este presupuesto participativo y permite al usuario ejecutar una acción específica como crear una nueva propuesta, votar las existentes, o leer más sobre el funcionamiento de los presupuestos participativos." main_call_to_action_description: "Este enlace aparecerá en la cabecera de este presupuesto participativo y permite al usuario ejecutar una acción específica como crear una nueva propuesta, votar las existentes, o leer más sobre el funcionamiento de los presupuestos participativos."
info: info:
budget_settings: "Configuración genérica del presupuesto participativo" budget_settings: "Configuración genérica del presupuesto participativo"
phases_settings: "Configuración de las fases"
staff_settings: "Administradores y Evaluadores asigandos al presupuesto" staff_settings: "Administradores y Evaluadores asigandos al presupuesto"
destroy: destroy:
success_notice: Presupuesto eliminado correctamente success_notice: Presupuesto eliminado correctamente

View File

@@ -10,7 +10,7 @@ describe Admin::Budgets::TableActionsComponent, controller: Admin::BaseControlle
expect(page).to have_link count: 4 expect(page).to have_link count: 4
expect(page).to have_link "Investment projects", href: /investments/ expect(page).to have_link "Investment projects", href: /investments/
expect(page).to have_link "Heading groups", href: /groups/ expect(page).to have_link "Heading groups", href: /groups/
expect(page).to have_link "Edit", href: /edit/ expect(page).to have_link "Edit", href: /#{budget.id}\Z/
expect(page).to have_link "Preview", href: /budgets/ expect(page).to have_link "Preview", href: /budgets/
expect(page).to have_button count: 2 expect(page).to have_button count: 2

View File

@@ -498,10 +498,11 @@ describe "Admin budget investments", :admin do
expect(page).to have_button "Calculate Winner Investments" expect(page).to have_button "Calculate Winner Investments"
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
expect(page).to have_button "Calculate Winner Investments" expect(page).to have_button "Calculate Winner Investments"
click_link "Edit budget"
select "Accepting projects", from: "Active phase" select "Accepting projects", from: "Active phase"
click_button "Update Budget" click_button "Update Budget"
@@ -518,7 +519,7 @@ describe "Admin budget investments", :admin do
'"Reviewing Ballots" or "Finished budget" in order '\ '"Reviewing Ballots" or "Finished budget" in order '\
"to calculate winners projects" "to calculate winners projects"
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
expect(page).not_to have_button "Calculate Winner Investments" expect(page).not_to have_button "Calculate Winner Investments"
end end

View File

@@ -13,7 +13,7 @@ describe "Admin budget phases" do
uncheck "budget_phase_enabled" uncheck "budget_phase_enabled"
click_button "Save changes" click_button "Save changes"
expect(page).to have_current_path(edit_admin_budget_path(budget)) expect(page).to have_current_path(admin_budget_path(budget))
expect(page).to have_content "Changes saved" expect(page).to have_content "Changes saved"
expect(budget.current_phase.starts_at.to_date).to eq((Date.current + 1.day).to_date) expect(budget.current_phase.starts_at.to_date).to eq((Date.current + 1.day).to_date)
@@ -23,7 +23,7 @@ describe "Admin budget phases" do
end end
scenario "Show default phase name or custom if present" do scenario "Show default phase name or custom if present" do
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
within_table "Phases" do within_table "Phases" do
expect(page).to have_content "Accepting projects" expect(page).to have_content "Accepting projects"

View File

@@ -114,7 +114,7 @@ describe "Admin budgets", :admin do
let(:budget) { create(:budget, :drafting) } let(:budget) { create(:budget, :drafting) }
scenario "Can preview budget before it is published" do scenario "Can preview budget before it is published" do
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
within_window(window_opened_by { click_link "Preview" }) do within_window(window_opened_by { click_link "Preview" }) do
expect(page).to have_current_path budget_path(budget) expect(page).to have_current_path budget_path(budget)
@@ -122,7 +122,7 @@ describe "Admin budgets", :admin do
end end
scenario "Can preview a budget after it is published" do scenario "Can preview a budget after it is published" do
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
accept_confirm { click_button "Publish budget" } accept_confirm { click_button "Publish budget" }
@@ -141,7 +141,7 @@ describe "Admin budgets", :admin do
let(:heading) { create(:budget_heading, budget: budget) } let(:heading) { create(:budget_heading, budget: budget) }
scenario "Destroy a budget without investments" do scenario "Destroy a budget without investments" do
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
click_button "Delete budget" click_button "Delete budget"
expect(page).to have_content("Budget deleted successfully") expect(page).to have_content("Budget deleted successfully")
@@ -152,7 +152,7 @@ describe "Admin budgets", :admin do
budget.administrators << Administrator.first budget.administrators << Administrator.first
budget.valuators << create(:valuator) budget.valuators << create(:valuator)
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
click_button "Delete budget" click_button "Delete budget"
expect(page).to have_content "Budget deleted successfully" expect(page).to have_content "Budget deleted successfully"
@@ -162,7 +162,7 @@ describe "Admin budgets", :admin do
scenario "Try to destroy a budget with investments" do scenario "Try to destroy a budget with investments" do
create(:budget_investment, heading: heading) create(:budget_investment, heading: heading)
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
click_button "Delete budget" click_button "Delete budget"
expect(page).to have_content("You cannot delete a budget that has associated investments") expect(page).to have_content("You cannot delete a budget that has associated investments")
@@ -172,7 +172,7 @@ describe "Admin budgets", :admin do
scenario "Try to destroy a budget with polls" do scenario "Try to destroy a budget with polls" do
create(:poll, budget: budget) create(:poll, budget: budget)
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
click_button "Delete budget" click_button "Delete budget"
expect(page).to have_content("You cannot delete a budget that has an associated poll") expect(page).to have_content("You cannot delete a budget that has an associated poll")
@@ -188,9 +188,7 @@ describe "Admin budgets", :admin do
budget.update!(phase: "selecting") budget.update!(phase: "selecting")
budget.phases.valuating.update!(enabled: false) budget.phases.valuating.update!(enabled: false)
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
expect(page).to have_select "Active phase", selected: "Selecting projects"
expect(page).to have_table "Phases", with_cols: [ expect(page).to have_table "Phases", with_cols: [
[ [
@@ -230,6 +228,10 @@ describe "Admin budgets", :admin do
expect(page).to have_link "Edit" expect(page).to have_link "Edit"
end end
end end
click_link "Edit budget"
expect(page).to have_select "Active phase", selected: "Selecting projects"
end end
end end
@@ -289,13 +291,16 @@ describe "Admin budgets", :admin do
context "Update" do context "Update" do
scenario "Update budget" do scenario "Update budget" do
visit edit_admin_budget_path(create(:budget)) budget = create(:budget)
visit edit_admin_budget_path(budget)
fill_in "Name", with: "More trees on the streets" fill_in "Name", with: "More trees on the streets"
click_button "Update Budget" click_button "Update Budget"
expect(page).to have_content "Participatory budget updated successfully"
expect(page).to have_content("More trees on the streets") expect(page).to have_content("More trees on the streets")
expect(page).to have_current_path(admin_budgets_path) expect(page).to have_current_path(admin_budget_path(budget))
end end
scenario "Deselect all selected staff" do scenario "Deselect all selected staff" do
@@ -333,7 +338,8 @@ describe "Admin budgets", :admin do
ballot_lines_count: 2) ballot_lines_count: 2)
selected = create(:budget_investment, :selected, heading: heading, price: 2, ballot_lines_count: 1) selected = create(:budget_investment, :selected, heading: heading, price: 2, ballot_lines_count: 1)
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
expect(page).not_to have_content "See results" expect(page).not_to have_content "See results"
click_button "Calculate Winner Investments" click_button "Calculate Winner Investments"
@@ -343,15 +349,16 @@ describe "Admin budgets", :admin do
expect(page).not_to have_content unselected.title expect(page).not_to have_content unselected.title
expect(page).not_to have_content selected.title expect(page).not_to have_content selected.title
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
expect(page).to have_content "See results"
expect(page).to have_link "See results"
end end
scenario "For a finished Budget" do scenario "For a finished Budget" do
budget = create(:budget, :finished) budget = create(:budget, :finished)
allow_any_instance_of(Budget).to receive(:has_winning_investments?).and_return(true) allow_any_instance_of(Budget).to receive(:has_winning_investments?).and_return(true)
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
expect(page).to have_content "Calculate Winner Investments" expect(page).to have_content "Calculate Winner Investments"
expect(page).to have_content "See results" expect(page).to have_content "See results"
@@ -361,7 +368,7 @@ describe "Admin budgets", :admin do
budget = create(:budget, :finished) budget = create(:budget, :finished)
create(:budget_investment, :winner, budget: budget) create(:budget_investment, :winner, budget: budget)
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
expect(page).to have_content "Recalculate Winner Investments" expect(page).to have_content "Recalculate Winner Investments"
expect(page).to have_content "See results" expect(page).to have_content "See results"

View File

@@ -30,7 +30,7 @@ describe "Budgets wizard, phases step", :admin do
expect(page).to have_content "Phases configured successfully" expect(page).to have_content "Phases configured successfully"
visit edit_admin_budget_path(budget) visit admin_budget_path(budget)
within "tr", text: "Information" do within "tr", text: "Information" do
expect(page).to have_css ".budget-phase-disabled", visible: :all expect(page).to have_css ".budget-phase-disabled", visible: :all