Use a switch to enable/disable budget phases
In the past it would have been confusing to add a way to directly enable/disable a phase in the phases table because it was in the middle of the form. So we would have had next to each other controls that don't do anything until the form is sent and controls which modify the database immediately. That's why we couldn't add the checkboxes we used when using the wizard. Now the phases aren't on the same page as the budget form, so we can edit them independently. We're using a switch, so it's consistent with the way we enable/disable features. We could have used checkboxes, but with checkboxes, users expect they aren't changing anything until they click on a button to send the form, so we'd have to add a button, and it might be missed since we're going to add "buttons" for headings and groups to this page which won't send a form but will be links. Since we're changing the element with JavaScript after an AJAX call, we need a way to find the button we're changing. The easiest way is adding an ID attribute to all admin actions buttons/links.
This commit is contained in:
@@ -1,27 +1,7 @@
|
|||||||
.budget-phases-table {
|
.budget-phases-table {
|
||||||
|
|
||||||
.budget-phase-enabled {
|
[aria-pressed] {
|
||||||
@include has-fa-icon(check, solid);
|
@include switch;
|
||||||
color: $check;
|
margin-bottom: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.budget-phase-disabled {
|
|
||||||
@include has-fa-icon(times, solid);
|
|
||||||
color: $black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.budget-phase-enabled,
|
|
||||||
.budget-phase-disabled {
|
|
||||||
display: block;
|
|
||||||
font-size: 1px;
|
|
||||||
left: $off-screen-left;
|
|
||||||
line-height: 1;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
font-size: $base-font-size;
|
|
||||||
left: -1 * $off-screen-left;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class Admin::ActionComponent < ApplicationComponent
|
|||||||
def html_options
|
def html_options
|
||||||
{
|
{
|
||||||
class: html_class,
|
class: html_class,
|
||||||
|
id: (dom_id(record, action) if record.respond_to?(:to_key)),
|
||||||
"aria-label": label,
|
"aria-label": label,
|
||||||
data: {
|
data: {
|
||||||
confirm: confirmation_text,
|
confirm: confirmation_text,
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
class Admin::BudgetPhases::PhasesComponent < ApplicationComponent
|
class Admin::BudgetPhases::PhasesComponent < ApplicationComponent
|
||||||
attr_reader :budget, :form
|
attr_reader :budget
|
||||||
|
|
||||||
def initialize(budget, form: nil)
|
def initialize(budget)
|
||||||
@budget = budget
|
@budget = budget
|
||||||
@form = form
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -17,25 +16,7 @@ class Admin::BudgetPhases::PhasesComponent < ApplicationComponent
|
|||||||
end
|
end
|
||||||
|
|
||||||
def enabled_cell(phase)
|
def enabled_cell(phase)
|
||||||
if form
|
render Admin::BudgetPhases::ToggleEnabledComponent.new(phase)
|
||||||
form.fields_for :phases, phase do |phase_fields|
|
|
||||||
phase_fields.check_box :enabled,
|
|
||||||
label: false,
|
|
||||||
aria: {
|
|
||||||
label: t("admin.budgets.edit.enable_phase", phase: phase.name)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
else
|
|
||||||
enabled_text(phase)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def enabled_text(phase)
|
|
||||||
if phase.enabled?
|
|
||||||
tag.span t("shared.yes"), class: "budget-phase-enabled"
|
|
||||||
else
|
|
||||||
tag.span t("shared.no"), class: "budget-phase-disabled"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit_path(phase)
|
def edit_path(phase)
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
<%= render Admin::ActionComponent.new(:toggle_enabled, phase, options) %>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
class Admin::BudgetPhases::ToggleEnabledComponent < ApplicationComponent
|
||||||
|
attr_reader :phase
|
||||||
|
|
||||||
|
def initialize(phase)
|
||||||
|
@phase = phase
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def options
|
||||||
|
{
|
||||||
|
text: text,
|
||||||
|
method: :patch,
|
||||||
|
remote: true,
|
||||||
|
"aria-label": t("admin.budgets.edit.enable_phase", phase: phase.name),
|
||||||
|
"aria-pressed": phase.enabled?
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def text
|
||||||
|
if phase.enabled?
|
||||||
|
t("shared.yes")
|
||||||
|
else
|
||||||
|
t("shared.no")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -5,7 +5,5 @@
|
|||||||
<%= render Admin::Budgets::HelpComponent.new("phases") %>
|
<%= render Admin::Budgets::HelpComponent.new("phases") %>
|
||||||
<%= render Admin::BudgetsWizard::CreationTimelineComponent.new("phases") %>
|
<%= render Admin::BudgetsWizard::CreationTimelineComponent.new("phases") %>
|
||||||
|
|
||||||
<%= form_for budget, url: update_all_admin_budgets_wizard_budget_budget_phases_path(budget) do |f| %>
|
<%= render Admin::BudgetPhases::PhasesComponent.new(budget) %>
|
||||||
<%= render Admin::BudgetPhases::PhasesComponent.new(budget, form: f) %>
|
<%= link_to t("admin.budgets_wizard.phases.continue"), admin_budgets_path, class: "button success" %>
|
||||||
<%= f.submit t("admin.budgets_wizard.phases.continue"), class: "button success" %>
|
|
||||||
<% end %>
|
|
||||||
|
|||||||
@@ -4,23 +4,9 @@ class Admin::BudgetsWizard::PhasesController < Admin::BudgetsWizard::BaseControl
|
|||||||
def index
|
def index
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_all
|
|
||||||
@budget.update!(phases_params)
|
|
||||||
|
|
||||||
redirect_to admin_budgets_path, notice: t("admin.budgets_wizard.phases.update_all.notice")
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def phases_index
|
def phases_index
|
||||||
admin_budgets_wizard_budget_budget_phases_path(@phase.budget, url_params)
|
admin_budgets_wizard_budget_budget_phases_path(@phase.budget, url_params)
|
||||||
end
|
end
|
||||||
|
|
||||||
def phases_params
|
|
||||||
params.require(:budget).permit(allowed_phases_params)
|
|
||||||
end
|
|
||||||
|
|
||||||
def allowed_phases_params
|
|
||||||
{ phases_attributes: [:id, :enabled] }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ module Admin::BudgetPhasesActions
|
|||||||
include ImageAttributes
|
include ImageAttributes
|
||||||
|
|
||||||
before_action :load_budget
|
before_action :load_budget
|
||||||
before_action :load_phase, only: [:edit, :update]
|
before_action :load_phase, only: [:edit, :update, :toggle_enabled]
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@@ -20,6 +20,15 @@ module Admin::BudgetPhasesActions
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def toggle_enabled
|
||||||
|
@phase.update!(enabled: !@phase.enabled)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to phases_index, notice: t("flash.actions.save_changes.notice") }
|
||||||
|
format.js
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_budget
|
def load_budget
|
||||||
|
|||||||
1
app/views/admin/budget_phases/toggle_enabled.js.erb
Normal file
1
app/views/admin/budget_phases/toggle_enabled.js.erb
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<%= render template: "admin/budgets_wizard/phases/toggle_enabled" %>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
var replacement = $("<%= j render Admin::BudgetPhases::ToggleEnabledComponent.new(@phase) %>");
|
||||||
|
var form = $("#" + replacement.find("[type='submit']").attr("id")).closest("form");
|
||||||
|
|
||||||
|
form.html(replacement.html()).find("[type='submit']").focus();
|
||||||
@@ -340,8 +340,6 @@ en:
|
|||||||
back: "Go back to headings"
|
back: "Go back to headings"
|
||||||
single:
|
single:
|
||||||
back: "Go back to edit heading"
|
back: "Go back to edit heading"
|
||||||
update_all:
|
|
||||||
notice: "Phases configured successfully"
|
|
||||||
milestones:
|
milestones:
|
||||||
index:
|
index:
|
||||||
table_id: "ID"
|
table_id: "ID"
|
||||||
|
|||||||
@@ -340,8 +340,6 @@ es:
|
|||||||
back: "Volver a partidas"
|
back: "Volver a partidas"
|
||||||
single:
|
single:
|
||||||
back: "Volver a editar partida"
|
back: "Volver a editar partida"
|
||||||
update_all:
|
|
||||||
notice: "Fases configuradas con éxito"
|
|
||||||
milestones:
|
milestones:
|
||||||
index:
|
index:
|
||||||
table_id: "ID"
|
table_id: "ID"
|
||||||
|
|||||||
@@ -69,7 +69,9 @@ namespace :admin do
|
|||||||
resources :progress_bars, except: :show, controller: "budget_investment_progress_bars"
|
resources :progress_bars, except: :show, controller: "budget_investment_progress_bars"
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :budget_phases, only: [:edit, :update]
|
resources :budget_phases, only: [:edit, :update] do
|
||||||
|
member { patch :toggle_enabled }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
namespace :budgets_wizard do
|
namespace :budgets_wizard do
|
||||||
@@ -79,7 +81,7 @@ namespace :admin do
|
|||||||
end
|
end
|
||||||
|
|
||||||
resources :phases, as: "budget_phases", only: [:index, :edit, :update] do
|
resources :phases, as: "budget_phases", only: [:index, :edit, :update] do
|
||||||
collection { patch :update_all }
|
member { patch :toggle_enabled }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,6 +16,31 @@ describe Admin::ActionComponent do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "HTML id" do
|
||||||
|
it "is not rendered for non-ActiveModel records" do
|
||||||
|
render_inline Admin::ActionComponent.new(:edit, double, path: "/")
|
||||||
|
|
||||||
|
expect(page).not_to have_css "[id]"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "includes an id based on the model and the action by default" do
|
||||||
|
record = double(model_name: double(param_key: "computer"), to_key: [1])
|
||||||
|
|
||||||
|
render_inline Admin::ActionComponent.new(:edit, record, path: "/")
|
||||||
|
|
||||||
|
expect(page).to have_css "a.edit-link#edit_computer_1"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can be overwritten" do
|
||||||
|
record = double(model_name: double(param_key: "computer"), to_key: [1])
|
||||||
|
|
||||||
|
render_inline Admin::ActionComponent.new(:edit, record, path: "/", id: "my_id")
|
||||||
|
|
||||||
|
expect(page).to have_css "a.edit-link#my_id"
|
||||||
|
expect(page).not_to have_css "#edit_computer_1"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "aria-label attribute" do
|
describe "aria-label attribute" do
|
||||||
it "is not rendered by default" do
|
it "is not rendered by default" do
|
||||||
record = double(human_name: "Stay home")
|
record = double(human_name: "Stay home")
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
describe Admin::BudgetPhases::ToggleEnabledComponent, controller: Admin::BaseController do
|
||||||
|
let(:phase) { create(:budget).phases.informing }
|
||||||
|
let(:component) { Admin::BudgetPhases::ToggleEnabledComponent.new(phase) }
|
||||||
|
|
||||||
|
it "is pressed when the phase is enabled" do
|
||||||
|
phase.update!(enabled: true)
|
||||||
|
|
||||||
|
render_inline component
|
||||||
|
|
||||||
|
expect(page).to have_button count: 1
|
||||||
|
expect(page).to have_button exact_text: "Yes"
|
||||||
|
expect(page).to have_button "Enable Information phase"
|
||||||
|
expect(page).to have_css "button[aria-pressed='true']"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is not pressed when the phase is disabled" do
|
||||||
|
phase.update!(enabled: false)
|
||||||
|
|
||||||
|
render_inline component
|
||||||
|
|
||||||
|
expect(page).to have_button count: 1
|
||||||
|
expect(page).to have_button exact_text: "No"
|
||||||
|
expect(page).to have_button "Enable Information phase"
|
||||||
|
expect(page).to have_css "button[aria-pressed='false']"
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -23,29 +23,42 @@ describe "Budgets wizard, phases step", :admin do
|
|||||||
scenario "Enable and disable phases" do
|
scenario "Enable and disable phases" do
|
||||||
visit admin_budgets_wizard_budget_budget_phases_path(budget)
|
visit admin_budgets_wizard_budget_budget_phases_path(budget)
|
||||||
|
|
||||||
uncheck "Enable Information phase"
|
|
||||||
uncheck "Enable Reviewing voting phase"
|
|
||||||
|
|
||||||
click_button "Finish"
|
|
||||||
|
|
||||||
expect(page).to have_content "Phases configured successfully"
|
|
||||||
|
|
||||||
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_content "Yes"
|
||||||
|
|
||||||
|
click_button "Enable Information phase"
|
||||||
|
|
||||||
|
expect(page).to have_content "No"
|
||||||
|
expect(page).not_to have_content "Yes"
|
||||||
end
|
end
|
||||||
|
|
||||||
within "tr", text: "Reviewing voting" do
|
within "tr", text: "Reviewing voting" do
|
||||||
expect(page).to have_css ".budget-phase-disabled", visible: :all
|
expect(page).to have_content "Yes"
|
||||||
|
|
||||||
|
click_button "Enable Reviewing voting phase"
|
||||||
|
|
||||||
|
expect(page).to have_content "No"
|
||||||
|
expect(page).not_to have_content "Yes"
|
||||||
|
end
|
||||||
|
|
||||||
|
click_link "Finish"
|
||||||
|
|
||||||
|
within("tr", text: budget.name) { click_link "Edit" }
|
||||||
|
|
||||||
|
within "tr", text: "Information" do
|
||||||
|
expect(page).to have_content "No"
|
||||||
|
end
|
||||||
|
|
||||||
|
within "tr", text: "Reviewing voting" do
|
||||||
|
expect(page).to have_content "No"
|
||||||
end
|
end
|
||||||
|
|
||||||
within "tr", text: "Accepting projects" do
|
within "tr", text: "Accepting projects" do
|
||||||
expect(page).to have_css ".budget-phase-enabled", visible: :all
|
expect(page).to have_content "Yes"
|
||||||
end
|
end
|
||||||
|
|
||||||
within "tr", text: "Voting projects" do
|
within "tr", text: "Voting projects" do
|
||||||
expect(page).to have_css ".budget-phase-enabled", visible: :all
|
expect(page).to have_content "Yes"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -22,9 +22,7 @@ describe "Budgets creation wizard", :admin do
|
|||||||
|
|
||||||
expect(page).to have_css ".budget-phases-table"
|
expect(page).to have_css ".budget-phases-table"
|
||||||
|
|
||||||
click_button "Finish"
|
click_link "Finish"
|
||||||
|
|
||||||
expect(page).to have_content "Phases configured successfully"
|
|
||||||
|
|
||||||
within "tr", text: "Single heading budget" do
|
within "tr", text: "Single heading budget" do
|
||||||
click_link "Heading groups"
|
click_link "Heading groups"
|
||||||
@@ -119,9 +117,7 @@ describe "Budgets creation wizard", :admin do
|
|||||||
expect(page).not_to have_content "Voting projects"
|
expect(page).not_to have_content "Voting projects"
|
||||||
end
|
end
|
||||||
|
|
||||||
click_button "Finish"
|
click_link "Finish"
|
||||||
|
|
||||||
expect(page).to have_content "Phases configured successfully"
|
|
||||||
|
|
||||||
within "tr", text: "Multiple headings budget" do
|
within "tr", text: "Multiple headings budget" do
|
||||||
click_link "Heading groups"
|
click_link "Heading groups"
|
||||||
|
|||||||
Reference in New Issue
Block a user