Merge pull request #2706 from consul/milestone_status

Investment milestone's project status
This commit is contained in:
Alberto
2018-06-28 11:34:06 +02:00
committed by GitHub
18 changed files with 128 additions and 5 deletions

View File

@@ -627,6 +627,15 @@
}
}
.milestone-status {
background: $budget;
border-radius: rem-calc(4);
color: #fff;
display: inline-block;
margin-top: $line-height / 6;
padding: $line-height / 4 $line-height / 2;
}
.show-actions-menu {
[class^="icon-"] {

View File

@@ -3,6 +3,7 @@ class Admin::BudgetInvestmentMilestonesController < Admin::BaseController
before_action :load_budget_investment, only: [:index, :new, :create, :edit, :update, :destroy]
before_action :load_budget_investment_milestone, only: [:edit, :update, :destroy]
before_action :load_statuses, only: [:index, :new, :create, :edit, :update]
def index
end
@@ -45,7 +46,7 @@ class Admin::BudgetInvestmentMilestonesController < Admin::BaseController
def milestone_params
image_attributes = [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
documents_attributes = [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
attributes = [:title, :description, :publication_date, :budget_investment_id,
attributes = [:title, :description, :publication_date, :budget_investment_id, :status_id,
image_attributes: image_attributes, documents_attributes: documents_attributes]
params.require(:budget_investment_milestone).permit(*attributes, translation_params(params[:budget_investment_milestone]))
@@ -71,4 +72,8 @@ class Admin::BudgetInvestmentMilestonesController < Admin::BaseController
get_milestone
end
def load_statuses
@statuses = Budget::Investment::Status.all
end
end

View File

@@ -11,11 +11,12 @@ class Budget
globalize_accessors locales: [:en, :es, :fr, :nl, :val, :pt_br]
belongs_to :investment
belongs_to :status, class_name: 'Budget::Investment::Status'
validates :title, presence: true
validates :description, presence: true
validates :investment, presence: true
validates :publication_date, presence: true
validate :description_or_status_present?
scope :order_by_publication_date, -> { order(publication_date: :asc) }
@@ -23,6 +24,11 @@ class Budget
80
end
def description_or_status_present?
unless description.present? || status_id.present?
errors.add(:description)
end
end
end
end
end

View File

@@ -5,6 +5,15 @@
<%= f.hidden_field :title, value: l(Time.current, format: :datetime),
maxlength: Budget::Investment::Milestone.title_max_length %>
<div class="small-12 medium-6 margin-bottom">
<%= f.select :status_id,
@statuses.collect { |s| [s.name, s.id] },
{ include_blank: @statuses.any? ? '' : t('admin.milestones.form.no_statuses_defined') },
{ disabled: @statuses.blank? } %>
<%= link_to t('admin.milestones.form.admin_statuses'),
admin_budget_investment_statuses_path %>
</div>
<%= f.label :description, t("admin.milestones.new.description") %>
<% @milestone.globalize_locales.each do |locale| %>
<%= hidden_field_tag "delete_translations[#{locale}]", 0 %>

View File

@@ -6,6 +6,7 @@
<th><%= t("admin.milestones.index.table_title") %></th>
<th><%= t("admin.milestones.index.table_description") %></th>
<th><%= t("admin.milestones.index.table_publication_date") %></th>
<th><%= t("admin.milestones.index.table_status") %></th>
<th><%= t("admin.milestones.index.image") %></th>
<th><%= t("admin.milestones.index.documents") %></th>
<th><%= t("admin.milestones.index.table_actions") %></th>
@@ -25,6 +26,9 @@
<td class="small">
<%= l(milestone.publication_date.to_date) if milestone.publication_date.present? %>
</td>
<td class="small">
<%= milestone.status.present? ? milestone.status.name : '' %>
</td>
<td class="small">
<%= link_to t("admin.milestones.index.show_image"),
milestone.image_url(:large),

View File

@@ -10,6 +10,18 @@
</span>
<% end %>
<% if milestone.status.present? %>
<p>
<strong>
<%= t("budgets.investments.show.milestone_status_changed") %>
</strong>
<br>
<span class="milestone-status">
<%= milestone.status.name %>
</span>
</p>
<% end %>
<%= image_tag(milestone.image_url(:large), { id: "image_#{milestone.id}", alt: milestone.image.title, class: "margin" }) if milestone.image.present? %>
<% globalize(neutral_locale(locale)) do %>

View File

@@ -126,8 +126,9 @@ en:
image: "Proposal descriptive image"
image_title: "Image title"
budget/investment/milestone:
status_id: "Current investment status (optional)"
title: "Title"
description: "Description"
description: "Description (optional if there's an status assigned)"
publication_date: "Publication date"
budget/investment/status:
name: "Name"

View File

@@ -251,6 +251,7 @@ en:
table_title: "Title"
table_description: "Description"
table_publication_date: "Publication date"
table_status: Status
table_actions: "Actions"
delete: "Delete milestone"
no_milestones: "Don't have defined milestones"
@@ -260,6 +261,8 @@ en:
form:
add_language: Add language
remove_language: Remove language
admin_statuses: Admin investment statuses
no_statuses_defined: There are no defined investment statuses yet
new:
creating: Create milestone
date: Date

View File

@@ -124,6 +124,7 @@ en:
milestones_tab: Milestones
no_milestones: Don't have defined milestones
milestone_publication_date: "Published %{publication_date}"
milestone_status_changed: Investment status changed to
author: Author
project_unfeasible_html: 'This investment project <strong>has been marked as not feasible</strong> and will not go to balloting phase.'
project_not_selected_html: 'This investment project <strong>has not been selected</strong> for balloting phase.'

View File

@@ -126,8 +126,9 @@ es:
image: "Imagen descriptiva del proyecto de gasto"
image_title: "Título de la imagen"
budget/investment/milestone:
status_id: "Estado actual del proyecto (opcional)"
title: "Título"
description: "Descripción"
description: "Descripción (opcional si se ha asignado un estado de proyecto)"
publication_date: "Fecha de publicación"
budget/investment/status:
name: "Nombre"

View File

@@ -251,6 +251,7 @@ es:
table_title: "Título"
table_description: "Descripción"
table_publication_date: "Fecha de publicación"
table_status: Estado
table_actions: "Acciones"
delete: "Eliminar hito"
no_milestones: "No hay hitos definidos"
@@ -260,6 +261,8 @@ es:
form:
add_language: Añadir idioma
remove_language: Eliminar idioma
admin_statuses: Gestionar estados de proyectos
no_statuses_defined: No hay estados definidos
new:
creating: Crear hito
date: Fecha

View File

@@ -124,6 +124,7 @@ es:
milestones_tab: Seguimiento
no_milestones: No hay hitos definidos
milestone_publication_date: "Publicado el %{publication_date}"
milestone_status_changed: El proyecto ha cambiado al estado
author: Autor
project_unfeasible_html: 'Este proyecto de inversión <strong>ha sido marcado como inviable</strong> y no pasará a la fase de votación.'
project_not_selected_html: 'Este proyecto de inversión <strong>no ha sido seleccionado</strong> para la fase de votación.'

View File

@@ -0,0 +1,8 @@
class AddStatusToMilestones < ActiveRecord::Migration
disable_ddl_transaction!
def change
add_column :budget_investment_milestones, :status_id, :integer
add_index :budget_investment_milestones, :status_id, algorithm: :concurrently
end
end

View File

@@ -137,8 +137,11 @@ ActiveRecord::Schema.define(version: 20180519132610) do
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "publication_date"
t.integer "status_id"
end
add_index "budget_investment_milestones", ["status_id"], name: "index_budget_investment_milestones_on_status_id", using: :btree
create_table "budget_investment_statuses", force: :cascade do |t|
t.string "name"
t.text "description"

View File

@@ -411,6 +411,7 @@ FactoryBot.define do
factory :budget_investment_milestone, class: 'Budget::Investment::Milestone' do
association :investment, factory: :budget_investment
association :status, factory: :budget_investment_status
sequence(:title) { |n| "Budget investment milestone #{n} title" }
description 'Milestone description'
publication_date Date.current

View File

@@ -21,6 +21,7 @@ feature 'Admin budget investment milestones' do
expect(page).to have_content(milestone.title)
expect(page).to have_content(milestone.id)
expect(page).to have_content(milestone.publication_date.to_date)
expect(page).to have_content(milestone.status.name)
expect(page).to have_link 'Show image'
expect(page).to have_link document.title
end
@@ -35,10 +36,12 @@ feature 'Admin budget investment milestones' do
context "New" do
scenario "Add milestone" do
status = create(:budget_investment_status)
visit admin_budget_budget_investment_path(@investment.budget, @investment)
click_link 'Create new milestone'
select status.name, from: 'budget_investment_milestone_status_id'
fill_in 'budget_investment_milestone_description_en', with: 'New description milestone'
fill_in 'budget_investment_milestone_publication_date', with: Date.current
@@ -46,6 +49,14 @@ feature 'Admin budget investment milestones' do
expect(page).to have_content 'New description milestone'
expect(page).to have_content Date.current
expect(page).to have_content status.name
end
scenario "Status select is disabled if there are no statuses available" do
visit admin_budget_budget_investment_path(@investment.budget, @investment)
click_link 'Create new milestone'
expect(find("#budget_investment_milestone_status_id").disabled?).to be true
end
scenario "Show validation errors on milestone form" do

View File

@@ -1017,6 +1017,7 @@ feature 'Budget Investments' do
expect(page.find("#image_#{first_milestone.id}")['alt']).to have_content(image.title)
expect(page).to have_link(document.title)
expect(page).to have_link("https://consul.dev")
expect(page).to have_content(first_milestone.status.name)
end
select('Español', from: 'locale-switcher')

View File

@@ -14,15 +14,59 @@ describe Budget::Investment::Milestone do
expect(milestone).not_to be_valid
end
it "is not valid without a description" do
it "is not valid without a description if status is empty" do
milestone.status = nil
milestone.description = nil
expect(milestone).not_to be_valid
end
it "is valid without a description if status is present" do
milestone.description = nil
expect(milestone).to be_valid
end
it "is not valid without an investment" do
milestone.investment_id = nil
expect(milestone).not_to be_valid
end
it "is not valid if description and status are not present" do
milestone.description = nil
milestone.status_id = nil
expect(milestone).not_to be_valid
end
it "is valid without status if description is present" do
milestone.status_id = nil
expect(milestone).to be_valid
end
it "is valid without description if status is present" do
milestone.description = nil
expect(milestone).to be_valid
end
end
describe "#description_or_status_present?" do
let(:milestone) { build(:budget_investment_milestone) }
it "is not valid when status is removed and there's no description" do
milestone.update(description: nil)
expect(milestone.update(status_id: nil)).to be false
end
it "is not valid when description is removed and there's no status" do
milestone.update(status_id: nil)
expect(milestone.update(description: nil)).to be false
end
it "is valid when description is removed and there is a status" do
expect(milestone.update(description: nil)).to be true
end
it "is valid when status is removed and there is a description" do
expect(milestone.update(status_id: nil)).to be true
end
end
end