Merge pull request #3456 from LextrendIT/3433_change_log_participatory_budget
Add change log in investment participatory budget
This commit is contained in:
@@ -595,6 +595,17 @@ code {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.log-value {
|
||||||
|
max-height: rem-calc(65);
|
||||||
|
overflow: hidden;
|
||||||
|
max-width: rem-calc(200);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
max-height: rem-calc(1000);
|
||||||
|
transition: max-height 0.9s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 04. Stats
|
// 04. Stats
|
||||||
// ---------
|
// ---------
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,19 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
|
|||||||
include FeatureFlags
|
include FeatureFlags
|
||||||
include CommentableActions
|
include CommentableActions
|
||||||
include DownloadSettingsHelper
|
include DownloadSettingsHelper
|
||||||
|
include ChangeLogHelper
|
||||||
|
|
||||||
feature_flag :budgets
|
feature_flag :budgets
|
||||||
|
|
||||||
has_orders %w[oldest], only: [:show, :edit]
|
has_orders %w[oldest], only: [:show, :edit]
|
||||||
has_filters %w[all], only: [:index, :toggle_selection]
|
has_filters %w[all], only: [:index, :toggle_selection]
|
||||||
|
|
||||||
before_action :load_budget
|
before_action :load_budget, except: :show_investment_log
|
||||||
before_action :load_investment, only: [:show, :edit, :update, :toggle_selection]
|
before_action :load_investment, only: [:show, :edit, :update, :toggle_selection]
|
||||||
before_action :load_ballot, only: [:show, :index]
|
before_action :load_ballot, only: [:show, :index]
|
||||||
before_action :parse_valuation_filters
|
before_action :parse_valuation_filters
|
||||||
before_action :load_investments, only: [:index, :toggle_selection]
|
before_action :load_investments, only: [:index, :toggle_selection]
|
||||||
|
before_action :load_change_log, only: [:show]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
@@ -129,4 +131,8 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def load_change_log
|
||||||
|
@logs = Budget::Investment::ChangeLog.by_investment(@investment.id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ class ApplicationController < ActionController::Base
|
|||||||
before_action :set_locale
|
before_action :set_locale
|
||||||
before_action :track_email_campaign
|
before_action :track_email_campaign
|
||||||
before_action :set_return_url
|
before_action :set_return_url
|
||||||
|
before_action :set_current_user
|
||||||
before_action :set_fallbacks_to_all_available_locales
|
before_action :set_fallbacks_to_all_available_locales
|
||||||
|
|
||||||
check_authorization unless: :devise_controller?
|
check_authorization unless: :devise_controller?
|
||||||
@@ -120,6 +121,10 @@ class ApplicationController < ActionController::Base
|
|||||||
Budget.current
|
Budget.current
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_current_user
|
||||||
|
User.current_user = current_user
|
||||||
|
end
|
||||||
|
|
||||||
def set_fallbacks_to_all_available_locales
|
def set_fallbacks_to_all_available_locales
|
||||||
Globalize.set_fallbacks_to_all_available_locales
|
Globalize.set_fallbacks_to_all_available_locales
|
||||||
end
|
end
|
||||||
|
|||||||
8
app/helpers/change_log_helper.rb
Normal file
8
app/helpers/change_log_helper.rb
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
module ChangeLogHelper
|
||||||
|
|
||||||
|
def show_investment_log
|
||||||
|
@log = Budget::Investment::ChangeLog.find_by(id: params[:id])
|
||||||
|
render "admin/change_logs/show"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -3,6 +3,7 @@ class Budget
|
|||||||
class Investment < ApplicationRecord
|
class Investment < ApplicationRecord
|
||||||
SORTING_OPTIONS = {id: "id", title: "title", supports: "cached_votes_up"}.freeze
|
SORTING_OPTIONS = {id: "id", title: "title", supports: "cached_votes_up"}.freeze
|
||||||
|
|
||||||
|
include ActiveModel::Dirty
|
||||||
include Rails.application.routes.url_helpers
|
include Rails.application.routes.url_helpers
|
||||||
include Measurable
|
include Measurable
|
||||||
include Sanitizable
|
include Sanitizable
|
||||||
@@ -100,6 +101,7 @@ class Budget
|
|||||||
after_save :recalculate_heading_winners
|
after_save :recalculate_heading_winners
|
||||||
before_validation :set_responsible_name
|
before_validation :set_responsible_name
|
||||||
before_validation :set_denormalized_ids
|
before_validation :set_denormalized_ids
|
||||||
|
after_update :change_log
|
||||||
|
|
||||||
def comments_count
|
def comments_count
|
||||||
comments.count
|
comments.count
|
||||||
@@ -391,5 +393,18 @@ class Budget
|
|||||||
self.budget_id ||= heading.try(:group).try(:budget_id)
|
self.budget_id ||= heading.try(:group).try(:budget_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def change_log
|
||||||
|
self.changed.each do |field|
|
||||||
|
unless field == "updated_at"
|
||||||
|
log = Budget::Investment::ChangeLog.new
|
||||||
|
log.field = field
|
||||||
|
log.author_id = User.current_user.id unless User.current_user.nil?
|
||||||
|
log.investment_id = self.id
|
||||||
|
log.new_value = self.send field
|
||||||
|
log.old_value = self.send "#{field}_was"
|
||||||
|
!log.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
10
app/models/budget/investment/change_log.rb
Normal file
10
app/models/budget/investment/change_log.rb
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
class Budget::Investment::ChangeLog < ActiveRecord::Base
|
||||||
|
belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id", required: false
|
||||||
|
|
||||||
|
validates :old_value, presence: true
|
||||||
|
validates :new_value, presence: true
|
||||||
|
validates :field, presence: true
|
||||||
|
|
||||||
|
scope :by_investment, ->(investment_id) { where(investment_id: investment_id) }
|
||||||
|
|
||||||
|
end
|
||||||
@@ -350,6 +350,15 @@ class User < ApplicationRecord
|
|||||||
followables.compact.map { |followable| followable.tags.map(&:name) }.flatten.compact.uniq
|
followables.compact.map { |followable| followable.tags.map(&:name) }.flatten.compact.uniq
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def self.current_user
|
||||||
|
Thread.current[:user]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.current_user=(user)
|
||||||
|
Thread.current[:user] = user
|
||||||
|
end
|
||||||
|
|
||||||
def send_devise_notification(notification, *args)
|
def send_devise_notification(notification, *args)
|
||||||
devise_mailer.send(notification, self, *args).deliver_later
|
devise_mailer.send(notification, self, *args).deliver_later
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -67,3 +67,5 @@
|
|||||||
<%= render "valuation/budget_investments/valuation_comments" %>
|
<%= render "valuation/budget_investments/valuation_comments" %>
|
||||||
|
|
||||||
<%= render "admin/milestones/milestones", milestoneable: @investment %>
|
<%= render "admin/milestones/milestones", milestoneable: @investment %>
|
||||||
|
|
||||||
|
<%= render "admin/change_logs/change_log", logs: @logs %>
|
||||||
|
|||||||
44
app/views/admin/change_logs/_change_log.html.erb
Normal file
44
app/views/admin/change_logs/_change_log.html.erb
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<h2 class="inline-block"><%= t("admin.change_log.title") %></h2>
|
||||||
|
|
||||||
|
<% if logs.empty? %>
|
||||||
|
<label><%= t("admin.change_log.empty") %></label>
|
||||||
|
<% else %>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><%= t("admin.change_log.id") %></th>
|
||||||
|
<th><%= t("admin.change_log.field") %></th>
|
||||||
|
<th><%= t("admin.change_log.old_value") %></th>
|
||||||
|
<th><%= t("admin.change_log.new_value") %></th>
|
||||||
|
<th><%= t("admin.change_log.edited_at") %></th>
|
||||||
|
<th><%= t("admin.change_log.edited_by") %></th>
|
||||||
|
<th><%= t("admin.change_log.actions") %></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% logs.each do |log| %>
|
||||||
|
<tr id="log_<%= log.id %>">
|
||||||
|
<td class="text-center"><%= log.id %></td>
|
||||||
|
<td class="small"><%= log.field.capitalize %></td>
|
||||||
|
<td class="small">
|
||||||
|
<div class="log-value"><%= log.old_value %></div>
|
||||||
|
</td>
|
||||||
|
<td class="small">
|
||||||
|
<div class="log-value"><%= log.new_value %></div>
|
||||||
|
</td>
|
||||||
|
<td class="small">
|
||||||
|
<%= log.created_at.to_date %>
|
||||||
|
</td>
|
||||||
|
<td class="small">
|
||||||
|
<%= log.author.name unless log.author.nil? %>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<%= link_to admin_change_log_path(id: log) do %>
|
||||||
|
<button class="button hollow primary"><%= t("shared.show") %></button>
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<% end %>
|
||||||
12
app/views/admin/change_logs/show.html.erb
Normal file
12
app/views/admin/change_logs/show.html.erb
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<h2 class="inline-block"><%= t("admin.change_log.title") %></h2>
|
||||||
|
|
||||||
|
<label><strong><%= t("admin.change_log.id") %></strong></label>
|
||||||
|
<p><%= @log.id %></p>
|
||||||
|
<label><strong><%= t("admin.change_log.old_value") %></strong></label>
|
||||||
|
<p><%= @log.old_value %></p>
|
||||||
|
<label><strong><%= t("admin.change_log.new_value") %></strong></label>
|
||||||
|
<p><%= @log.new_value %></p>
|
||||||
|
<label><strong><%= t("admin.change_log.edited_at") %></strong></label>
|
||||||
|
<p><%= @log.created_at.to_date %></p>
|
||||||
|
<label><strong><%= t("admin.change_log.edited_by") %></strong></label>
|
||||||
|
<p><%= @log.author.name unless @log.author.nil? %></p>
|
||||||
@@ -1638,3 +1638,13 @@ en:
|
|||||||
translations:
|
translations:
|
||||||
remove_language: Remove language
|
remove_language: Remove language
|
||||||
add_language: Add language
|
add_language: Add language
|
||||||
|
change_log:
|
||||||
|
title: "Change Log"
|
||||||
|
id: "ID"
|
||||||
|
field: "Field"
|
||||||
|
new_value: "New Value"
|
||||||
|
old_value: "Old Value"
|
||||||
|
edited_at: "Edited at"
|
||||||
|
edited_by: "Edited by"
|
||||||
|
actions: "Actions"
|
||||||
|
empty: "There are not changes logged"
|
||||||
|
|||||||
@@ -1636,3 +1636,13 @@ es:
|
|||||||
translations:
|
translations:
|
||||||
remove_language: Eliminar idioma
|
remove_language: Eliminar idioma
|
||||||
add_language: Añadir idioma
|
add_language: Añadir idioma
|
||||||
|
change_log:
|
||||||
|
title: "Historial"
|
||||||
|
id: "ID"
|
||||||
|
field: "Campo"
|
||||||
|
new_value: "Valor nuevo"
|
||||||
|
old_value: "Valor anterior"
|
||||||
|
edited_at: "Editado el"
|
||||||
|
edited_by: "Editado por"
|
||||||
|
actions: "Acciones"
|
||||||
|
empty: "No hay cambios registrados"
|
||||||
|
|||||||
@@ -245,6 +245,10 @@ namespace :admin do
|
|||||||
resources :actions, only: [:index, :new, :create, :edit, :update, :destroy]
|
resources :actions, only: [:index, :new, :create, :edit, :update, :destroy]
|
||||||
resources :administrator_tasks, only: [:index, :edit, :update]
|
resources :administrator_tasks, only: [:index, :edit, :update]
|
||||||
end
|
end
|
||||||
|
|
||||||
get 'download_settings/:resource', to: 'download_settings#edit', as: 'edit_download_settings'
|
get 'download_settings/:resource', to: 'download_settings#edit', as: 'edit_download_settings'
|
||||||
put 'download_settings/:resource', to: 'download_settings#update', as: 'update_download_settings'
|
put 'download_settings/:resource', to: 'download_settings#update', as: 'update_download_settings'
|
||||||
|
|
||||||
|
get "/change_log/:id", to: "budget_investments#show_investment_log", as: "change_log"
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
class CreateBudgetInvestmentChangeLogs < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :budget_investment_change_logs do |t|
|
||||||
|
t.integer :investment_id
|
||||||
|
t.integer :author_id
|
||||||
|
t.string :field
|
||||||
|
t.string :new_value
|
||||||
|
t.string :old_value
|
||||||
|
|
||||||
|
t.timestamps null: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
14
db/schema.rb
14
db/schema.rb
@@ -134,9 +134,9 @@ ActiveRecord::Schema.define(version: 20190607160900) do
|
|||||||
t.integer "budget_id"
|
t.integer "budget_id"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.integer "ballot_lines_count", default: 0
|
|
||||||
t.boolean "physical", default: false
|
t.boolean "physical", default: false
|
||||||
t.integer "poll_ballot_id"
|
t.integer "poll_ballot_id"
|
||||||
|
t.integer "ballot_lines_count", default: 0
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "budget_content_blocks", force: :cascade do |t|
|
create_table "budget_content_blocks", force: :cascade do |t|
|
||||||
@@ -188,6 +188,16 @@ ActiveRecord::Schema.define(version: 20190607160900) do
|
|||||||
t.index ["group_id"], name: "index_budget_headings_on_group_id", using: :btree
|
t.index ["group_id"], name: "index_budget_headings_on_group_id", using: :btree
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "budget_investment_change_logs", force: :cascade do |t|
|
||||||
|
t.integer "investment_id"
|
||||||
|
t.integer "author_id"
|
||||||
|
t.string "field"
|
||||||
|
t.string "new_value"
|
||||||
|
t.string "old_value"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
end
|
||||||
|
|
||||||
create_table "budget_investment_milestone_translations", force: :cascade do |t|
|
create_table "budget_investment_milestone_translations", force: :cascade do |t|
|
||||||
t.integer "budget_investment_milestone_id", null: false
|
t.integer "budget_investment_milestone_id", null: false
|
||||||
t.string "locale", null: false
|
t.string "locale", null: false
|
||||||
@@ -1177,12 +1187,12 @@ ActiveRecord::Schema.define(version: 20190607160900) do
|
|||||||
t.integer "comments_count", default: 0
|
t.integer "comments_count", default: 0
|
||||||
t.integer "author_id"
|
t.integer "author_id"
|
||||||
t.datetime "hidden_at"
|
t.datetime "hidden_at"
|
||||||
t.string "slug"
|
|
||||||
t.boolean "results_enabled", default: false
|
t.boolean "results_enabled", default: false
|
||||||
t.boolean "stats_enabled", default: false
|
t.boolean "stats_enabled", default: false
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.integer "budget_id"
|
t.integer "budget_id"
|
||||||
|
t.string "slug"
|
||||||
t.string "related_type"
|
t.string "related_type"
|
||||||
t.integer "related_id"
|
t.integer "related_id"
|
||||||
t.index ["budget_id"], name: "index_polls_on_budget_id", unique: true, using: :btree
|
t.index ["budget_id"], name: "index_polls_on_budget_id", unique: true, using: :btree
|
||||||
|
|||||||
71
spec/features/admin/change_log_spec.rb
Normal file
71
spec/features/admin/change_log_spec.rb
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
feature "Admin change log" do
|
||||||
|
let(:budget) {create(:budget)}
|
||||||
|
let(:administrator) do
|
||||||
|
create(:administrator, user: create(:user, username: "Ana", email: "ana@admins.org"))
|
||||||
|
end
|
||||||
|
|
||||||
|
context "Investments Participatory Budgets" do
|
||||||
|
|
||||||
|
background do
|
||||||
|
@admin = create(:administrator)
|
||||||
|
login_as(@admin.user)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "No changes" do
|
||||||
|
budget_investment = create(:budget_investment,
|
||||||
|
price: 1234,
|
||||||
|
price_first_year: 1000,
|
||||||
|
feasibility: "unfeasible",
|
||||||
|
unfeasibility_explanation: "It is impossible",
|
||||||
|
administrator: administrator)
|
||||||
|
|
||||||
|
visit admin_budget_budget_investments_path(budget_investment.budget)
|
||||||
|
|
||||||
|
click_link budget_investment.title
|
||||||
|
|
||||||
|
expect(page).to have_content(budget_investment.title)
|
||||||
|
expect(page).to have_content(budget_investment.description)
|
||||||
|
expect(page).to have_content(budget_investment.author.name)
|
||||||
|
expect(page).to have_content(budget_investment.heading.name)
|
||||||
|
expect(page).to have_content("There are not changes logged")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Changes" do
|
||||||
|
budget_investment = create(:budget_investment,
|
||||||
|
price: 1234,
|
||||||
|
price_first_year: 1000,
|
||||||
|
feasibility: "unfeasible",
|
||||||
|
unfeasibility_explanation: "It is impossible",
|
||||||
|
administrator: administrator)
|
||||||
|
|
||||||
|
visit admin_budget_budget_investments_path(budget_investment.budget)
|
||||||
|
|
||||||
|
click_link budget_investment.title
|
||||||
|
|
||||||
|
expect(page).to have_content(budget_investment.title)
|
||||||
|
expect(page).to have_content(budget_investment.description)
|
||||||
|
expect(page).to have_content(budget_investment.author.name)
|
||||||
|
expect(page).to have_content(budget_investment.heading.name)
|
||||||
|
expect(page).to have_content("There are not changes logged")
|
||||||
|
|
||||||
|
budget_investment.update(title: "test")
|
||||||
|
|
||||||
|
visit admin_budget_budget_investments_path(budget_investment.budget)
|
||||||
|
|
||||||
|
click_link budget_investment.title
|
||||||
|
|
||||||
|
expect(page).not_to have_content("There are not changes logged")
|
||||||
|
expect(page).to have_content("Change Log")
|
||||||
|
expect(page).to have_content("Title")
|
||||||
|
expect(page).to have_content("test")
|
||||||
|
expect(page).to have_content("Field")
|
||||||
|
expect(page).to have_content("Old Value")
|
||||||
|
expect(page).to have_content("New Value")
|
||||||
|
expect(page).to have_content("Edited at")
|
||||||
|
expect(page).to have_content("Edited by")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user