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
|
||||
// ---------
|
||||
|
||||
|
||||
@@ -2,17 +2,19 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
|
||||
include FeatureFlags
|
||||
include CommentableActions
|
||||
include DownloadSettingsHelper
|
||||
include ChangeLogHelper
|
||||
|
||||
feature_flag :budgets
|
||||
|
||||
has_orders %w[oldest], only: [:show, :edit]
|
||||
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_ballot, only: [:show, :index]
|
||||
before_action :parse_valuation_filters
|
||||
before_action :load_investments, only: [:index, :toggle_selection]
|
||||
before_action :load_change_log, only: [:show]
|
||||
|
||||
def index
|
||||
respond_to do |format|
|
||||
@@ -129,4 +131,8 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def load_change_log
|
||||
@logs = Budget::Investment::ChangeLog.by_investment(@investment.id)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,6 +13,7 @@ class ApplicationController < ActionController::Base
|
||||
before_action :set_locale
|
||||
before_action :track_email_campaign
|
||||
before_action :set_return_url
|
||||
before_action :set_current_user
|
||||
before_action :set_fallbacks_to_all_available_locales
|
||||
|
||||
check_authorization unless: :devise_controller?
|
||||
@@ -120,6 +121,10 @@ class ApplicationController < ActionController::Base
|
||||
Budget.current
|
||||
end
|
||||
|
||||
def set_current_user
|
||||
User.current_user = current_user
|
||||
end
|
||||
|
||||
def set_fallbacks_to_all_available_locales
|
||||
Globalize.set_fallbacks_to_all_available_locales
|
||||
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
|
||||
SORTING_OPTIONS = {id: "id", title: "title", supports: "cached_votes_up"}.freeze
|
||||
|
||||
include ActiveModel::Dirty
|
||||
include Rails.application.routes.url_helpers
|
||||
include Measurable
|
||||
include Sanitizable
|
||||
@@ -100,6 +101,7 @@ class Budget
|
||||
after_save :recalculate_heading_winners
|
||||
before_validation :set_responsible_name
|
||||
before_validation :set_denormalized_ids
|
||||
after_update :change_log
|
||||
|
||||
def comments_count
|
||||
comments.count
|
||||
@@ -391,5 +393,18 @@ class Budget
|
||||
self.budget_id ||= heading.try(:group).try(:budget_id)
|
||||
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
|
||||
|
||||
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
|
||||
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)
|
||||
devise_mailer.send(notification, self, *args).deliver_later
|
||||
end
|
||||
|
||||
@@ -67,3 +67,5 @@
|
||||
<%= render "valuation/budget_investments/valuation_comments" %>
|
||||
|
||||
<%= 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:
|
||||
remove_language: Remove 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:
|
||||
remove_language: Eliminar 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 :administrator_tasks, only: [:index, :edit, :update]
|
||||
end
|
||||
|
||||
get 'download_settings/:resource', to: 'download_settings#edit', as: 'edit_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
|
||||
|
||||
@@ -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.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "ballot_lines_count", default: 0
|
||||
t.boolean "physical", default: false
|
||||
t.integer "poll_ballot_id"
|
||||
t.integer "ballot_lines_count", default: 0
|
||||
end
|
||||
|
||||
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
|
||||
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|
|
||||
t.integer "budget_investment_milestone_id", 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 "author_id"
|
||||
t.datetime "hidden_at"
|
||||
t.string "slug"
|
||||
t.boolean "results_enabled", default: false
|
||||
t.boolean "stats_enabled", default: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "budget_id"
|
||||
t.string "slug"
|
||||
t.string "related_type"
|
||||
t.integer "related_id"
|
||||
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