From d2871d7770a245d7b05a8100cbdda7f17e379fdc Mon Sep 17 00:00:00 2001 From: Julian Herrero Date: Mon, 16 Mar 2020 12:54:00 +0100 Subject: [PATCH] Include duration in budgets table --- .../stylesheets/admin/budgets/index.scss | 6 ++ .../budget_phases/phases_component.html.erb | 2 +- .../admin/budget_phases/phases_component.rb | 12 +--- .../admin/budgets/duration_component.rb | 29 ++++++++++ .../admin/budgets/index_component.html.erb | 8 ++- .../admin/budgets/index_component.rb | 20 +++++++ app/models/budget.rb | 8 +++ config/locales/en/admin.yml | 2 + config/locales/es/admin.yml | 2 + .../admin/budgets/duration_component_spec.rb | 57 +++++++++++++++++++ 10 files changed, 134 insertions(+), 12 deletions(-) create mode 100644 app/components/admin/budgets/duration_component.rb create mode 100644 spec/components/admin/budgets/duration_component_spec.rb diff --git a/app/assets/stylesheets/admin/budgets/index.scss b/app/assets/stylesheets/admin/budgets/index.scss index 183439343..1ce224b76 100644 --- a/app/assets/stylesheets/admin/budgets/index.scss +++ b/app/assets/stylesheets/admin/budgets/index.scss @@ -21,4 +21,10 @@ text-transform: uppercase; } } + + td time:last-of-type::after, + td small::before { + content: ""; + display: block; + } } diff --git a/app/components/admin/budget_phases/phases_component.html.erb b/app/components/admin/budget_phases/phases_component.html.erb index 3e5a2d069..a88cac38b 100644 --- a/app/components/admin/budget_phases/phases_component.html.erb +++ b/app/components/admin/budget_phases/phases_component.html.erb @@ -20,7 +20,7 @@ <% if phase.starts_at.present? || phase.ends_at.present? %> - <%= start_date(phase) %> - <%= end_date(phase) %> + <%= dates(phase) %> <% else %> <%= t("admin.budgets.edit.blank_dates") %> <% end %> diff --git a/app/components/admin/budget_phases/phases_component.rb b/app/components/admin/budget_phases/phases_component.rb index 59121182d..e0b1dfc71 100644 --- a/app/components/admin/budget_phases/phases_component.rb +++ b/app/components/admin/budget_phases/phases_component.rb @@ -11,15 +11,7 @@ class Admin::BudgetPhases::PhasesComponent < ApplicationComponent budget.phases.order(:id) end - def start_date(phase) - formatted_date(phase.starts_at) if phase.starts_at.present? - end - - def end_date(phase) - formatted_date(phase.ends_at - 1.second) if phase.ends_at.present? - end - - def formatted_date(time) - time_tag(time, format: :datetime) + def dates(phase) + Admin::Budgets::DurationComponent.new(phase).dates end end diff --git a/app/components/admin/budgets/duration_component.rb b/app/components/admin/budgets/duration_component.rb new file mode 100644 index 000000000..8af1a3ad0 --- /dev/null +++ b/app/components/admin/budgets/duration_component.rb @@ -0,0 +1,29 @@ +class Admin::Budgets::DurationComponent < ApplicationComponent + attr_reader :durable + + def initialize(durable) + @durable = durable + end + + def dates + safe_join([formatted_start_date, "-", formatted_end_date], " ") + end + + def duration + distance_of_time_in_words(durable.starts_at, durable.ends_at) + end + + private + + def formatted_start_date + formatted_date(durable.starts_at) if durable.starts_at.present? + end + + def formatted_end_date + formatted_date(durable.ends_at - 1.second) if durable.ends_at.present? + end + + def formatted_date(time) + time_tag(time, format: :datetime) + end +end diff --git a/app/components/admin/budgets/index_component.html.erb b/app/components/admin/budgets/index_component.html.erb index e5cb8b340..c371205f4 100644 --- a/app/components/admin/budgets/index_component.html.erb +++ b/app/components/admin/budgets/index_component.html.erb @@ -13,6 +13,7 @@ <%= t("admin.budgets.index.table_name") %> <%= t("admin.budgets.index.table_phase") %> + <%= t("admin.budgets.index.table_duration") %> <%= t("admin.actions.actions") %> @@ -27,8 +28,13 @@ <% end %> <%= budget.name %> - + <%= budget.current_phase.name %> + <%= phase_progress_text(budget) %> + + + <%= dates(budget) %> + <%= duration(budget) %> <%= render Admin::Budgets::TableActionsComponent.new(budget) %> diff --git a/app/components/admin/budgets/index_component.rb b/app/components/admin/budgets/index_component.rb index 6c653cc18..7523207da 100644 --- a/app/components/admin/budgets/index_component.rb +++ b/app/components/admin/budgets/index_component.rb @@ -9,4 +9,24 @@ class Admin::Budgets::IndexComponent < ApplicationComponent def title t("admin.budgets.index.title") end + + private + + def phase_progress_text(budget) + t("admin.budgets.index.table_phase_progress", + current_phase_number: current_enabled_phase_number(budget), + total_phases: budget.phases.enabled.count) + end + + def current_enabled_phase_number(budget) + budget.phases.enabled.order(:id).pluck(:kind).index(budget.phase) + 1 + end + + def dates(budget) + Admin::Budgets::DurationComponent.new(budget).dates + end + + def duration(budget) + Admin::Budgets::DurationComponent.new(budget).duration + end end diff --git a/app/models/budget.rb b/app/models/budget.rb index 601fabb1a..d6034c896 100644 --- a/app/models/budget.rb +++ b/app/models/budget.rb @@ -71,6 +71,14 @@ class Budget < ApplicationRecord phases.published.order(:id) end + def starts_at + phases.published.first.starts_at + end + + def ends_at + phases.published.last.ends_at + end + def description description_for_phase(phase) end diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml index a171f4b72..999d05c72 100644 --- a/config/locales/en/admin.yml +++ b/config/locales/en/admin.yml @@ -76,8 +76,10 @@ en: help: "Participatory budgets allow citizens to propose and decide directly how to spend part of the budget, with monitoring and rigorous evaluation of proposals by the institution." budget_investments: Manage projects table_completed: Completed + table_duration: "Duration" table_name: Name table_phase: Phase + table_phase_progress: "(%{current_phase_number}/%{total_phases})" edit_groups: Edit headings groups edit_budget: Edit budget admin_ballots: Admin ballots diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml index 92ff74816..fce3c768f 100644 --- a/config/locales/es/admin.yml +++ b/config/locales/es/admin.yml @@ -76,8 +76,10 @@ es: help: "Los presupuestos participativos permiten que los ciudadanos propongan y decidan de manera directa cómo gastar parte del presupuesto, con un seguimiento y evaluación riguroso de las propuestas por parte de la institución." budget_investments: Gestionar proyectos de gasto table_completed: Completado + table_duration: "Duración" table_name: Nombre table_phase: Fase + table_phase_progress: "(%{current_phase_number}/%{total_phases})" edit_groups: Editar grupos de partidas edit_budget: Editar presupuesto admin_ballots: Gestionar urnas diff --git a/spec/components/admin/budgets/duration_component_spec.rb b/spec/components/admin/budgets/duration_component_spec.rb new file mode 100644 index 000000000..193d45e7c --- /dev/null +++ b/spec/components/admin/budgets/duration_component_spec.rb @@ -0,0 +1,57 @@ +require "rails_helper" + +describe Admin::Budgets::DurationComponent, type: :component do + describe "#dates" do + it "shows both dates when both are defined" do + durable = double( + starts_at: Time.zone.local(2015, 8, 1, 12, 0, 0), + ends_at: Time.zone.local(2016, 9, 30, 16, 30, 00) + ) + + dates = Admin::Budgets::DurationComponent.new(durable).dates + + render dates + + expect(page.text).to eq "2015-08-01 12:00:00 - 2016-09-30 16:29:59" + expect(dates).to be_html_safe + end + + it "shows the start date when no end date is defined" do + durable = double(starts_at: Time.zone.local(2015, 8, 1, 12, 0, 0), ends_at: nil) + render Admin::Budgets::DurationComponent.new(durable).dates + + expect(page.text).to eq "2015-08-01 12:00:00 - " + end + + it "shows the end date when no start date is defined" do + durable = double(starts_at: nil, ends_at: Time.zone.local(2016, 9, 30, 16, 30, 00)) + + render Admin::Budgets::DurationComponent.new(durable).dates + + expect(page.text).to eq "- 2016-09-30 16:29:59" + end + end + + describe "#duration" do + it "describes the total duration in human language" do + durable = double( + starts_at: Time.zone.local(2015, 8, 1, 12, 0, 0), + ends_at: Time.zone.local(2016, 9, 30, 16, 30, 00) + ) + + render Admin::Budgets::DurationComponent.new(durable).duration + + expect(page.text).to eq "about 1 year" + end + end + + attr_reader :content + + def render(content) + @content = content + end + + def page + Capybara::Node::Simple.new(content) + end +end