audited-ui 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2c4ee9704d19ebb0589a889be19d2bde64db1310a61b55a26003801a2e989b7c
4
+ data.tar.gz: 222f4b7330f41c5981cf52d63b9e655cdcc0fb356bcfe193f1aee79ece60f7d3
5
+ SHA512:
6
+ metadata.gz: 35402dbe3579a018f56ef253e677df749ead37180aefabc684f585523cfdf1fb15865a92fc99ed58259db0619288ffbe7fe7b4b55faac83bbbfc2a32aae7e9a4
7
+ data.tar.gz: 49f637a6035ac6bf2881d7feda2fc5cb6986f4b05a59aaf71ff599c087df732f7ce0ec8af98b7b1106f4b0dcc87ec0de9d75e72e9464bdf9aa5a8780c7fb0869
data/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # Audited::Ui
2
+
3
+ A UI for [audited](https://github.com/collectiveidea/audited), a [Ruby on Rails](https://rubyonrails.org) extension for auditing models.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem "audited-ui"
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+
21
+ ```bash
22
+ $ gem install audited-ui
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ By just installing it, audited-ui will add the following routes:
28
+
29
+ ```
30
+ /audited/audits
31
+ /audited/audits/:auditable_type
32
+ /audited/audits/:auditable_type/:auditable_id
33
+ ```
34
+
35
+ that will allow you to audit all records of all types, all records of a given auditable type, or all records of a given auditable object, respectively.
36
+
37
+ Audit all records by linking to `audited_audits_path`, like this:
38
+
39
+ ```erb
40
+ <%= link_to "Audit all records", audited_audits_path %>
41
+ ```
42
+
43
+ Or just a specific auditable type, using `audited_auditable_type_audits_path`, like this:
44
+
45
+ ```erb
46
+ <%= link_to "Audit all people records", audited_auditable_type_audits_path(auditable_type: "person") %>
47
+ ```
48
+
49
+ Or a specific record, using `audited_auditable_audits_path`, like this:
50
+
51
+ ```erb
52
+ <%= link_to "Audit this person", audited_auditable_audits_path(auditable_type: "person", auditable_id: person.id) %>
53
+ ```
54
+
55
+ ### Customizing views
56
+
57
+ If you already set it up, you'll notice that audited-ui comes with a barebone UI that you can use. But, purposedly, the UI is very simple. The idea is that you can use it if it's good enough, but in most cases you should customize it to match your application's UI.
58
+
59
+ To generate the views simply run:
60
+
61
+ ```bash
62
+ $ bundle exec rails g audited:ui:views
63
+ ```
64
+
65
+ ### I18n
66
+
67
+ Every string is I18ned, even class and attributes names. See [this guide](https://guides.rubyonrails.org/i18n.html#translations-for-active-record-models) if you want to translate your audited models and attributes.
68
+
69
+ By default only english and spanish are supported. You can add other locales by copying the content of [this file](https://github.com/sinaptia/audited-ui/blob/main/config/locales/en.yml) into your app's `config/locale/yourlocale.yml` and translating the given strings. And if you do that send a PR :P .
70
+
71
+ If you need to customize just one string, copy that string in your app's locale file:
72
+
73
+ ```yml
74
+ en:
75
+ audited:
76
+ ui:
77
+ audits:
78
+ index:
79
+ title:
80
+ all: Auditing everything
81
+ ```
82
+
83
+ ## TODO
84
+
85
+ - [x] Mount the engine with a method, similar to `devise_for`, so we can have more and better control on routes.
86
+ - [ ] AuditedUI configuration, if we need to configure anything.
87
+ - [ ] Ready to use views (tailwind/bootstrap), if it makes sense.
88
+ - [x] Filters (by user, by dates, by changed attribute).
89
+ - [x] Sort by column.
90
+ - [ ] Revert to a specific version.
91
+ - [ ] Tests.
92
+
93
+ ## License
94
+
95
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
@@ -0,0 +1,39 @@
1
+ module Audited
2
+ module Ui
3
+ class AuditsController < ::ApplicationController
4
+ before_action :set_auditable_type
5
+ before_action :set_auditable
6
+ before_action :set_audits
7
+
8
+ def index
9
+ @q = @audits.ransack params[:q]
10
+ @q.sorts = "created_at desc" if @q.sorts.none?
11
+ @audits = @q.result(distinct: true).includes(:auditable, :user).page params[:page]
12
+ end
13
+
14
+ private
15
+
16
+ def set_auditable
17
+ @auditable = if @auditable_type.present? && params[:auditable_id].present?
18
+ @auditable_type.find params[:auditable_id]
19
+ end
20
+ end
21
+
22
+ def set_auditable_type
23
+ @auditable_type = if params[:auditable_type].present?
24
+ params[:auditable_type].camelize.constantize
25
+ end
26
+ end
27
+
28
+ def set_audits
29
+ @audits = if @auditable.present?
30
+ @auditable.audits
31
+ elsif @auditable_type.present?
32
+ Audited::Audit.where(auditable_type: @auditable_type.to_s)
33
+ else
34
+ Audited::Audit.all
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,15 @@
1
+ module Audited
2
+ module Ui
3
+ module AuditsHelper
4
+ def title(auditable, auditable_type)
5
+ if auditable.present?
6
+ I18n.t "audited.ui.audits.index.title.auditable", auditable: auditable.to_s
7
+ elsif auditable_type.present?
8
+ I18n.t "audited.ui.audits.index.title.auditable_type", auditable_type: auditable_type.to_s.humanize.pluralize.downcase
9
+ else
10
+ I18n.t "audited.ui.audits.index.title.all"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ <%= search_form_for @q, url: request.path do |f| %>
2
+ <div>
3
+ <%= f.label t("activerecord.attributes.audit.user") %>
4
+ <%= f.collection_select :user_id_eq, User.all, :id, :email, include_blank: true %>
5
+ </div>
6
+
7
+ <div>
8
+ <%= f.label t("activerecord.attributes.audit.created_at") %>
9
+ <%= f.date_field :created_at_gteq %>
10
+ <%= f.date_field :created_at_lteq %>
11
+ </div>
12
+
13
+ <div>
14
+ <%= f.label t("activerecord.attributes.audit.audited_changes") %>
15
+ <%= f.text_field :raw_audited_changes_cont %>
16
+ </div>
17
+
18
+ <div>
19
+ <%= f.submit %>
20
+ </div>
21
+ <% end %>
@@ -0,0 +1,70 @@
1
+ <h1><%= title @auditable, @auditable_type %></h1>
2
+
3
+ <%= render "search_form" %>
4
+
5
+ <table>
6
+ <thead>
7
+ <tr>
8
+ <% if @auditable_type.blank? %>
9
+ <th><%=t "activerecord.attributes.audit.auditable_type" %></th>
10
+ <% end %>
11
+ <% if @auditable.blank? %>
12
+ <th><%=t "activerecord.attributes.audit.auditable" %></th>
13
+ <% end %>
14
+ <th><%= sort_link @q, :version, t("activerecord.attributes.audit.version") %></th>
15
+ <th><%= sort_link @q, :created_at, t("activerecord.attributes.audit.created_at") %></th>
16
+ <th><%=t "activerecord.attributes.audit.action" %></th>
17
+ <th><%=t "activerecord.attributes.audit.user" %></th>
18
+ <th colspan="3"><%=t "activerecord.attributes.audit.audited_changes" %></th>
19
+ <th><%=t "activerecord.attributes.audit.comment" %></th>
20
+ </tr>
21
+ <tr>
22
+ <th colspan="<%= 6 - [@auditable_type, @auditable].compact.size %>"></th>
23
+ <th><%=t ".attribute" %></th>
24
+ <th><%=t ".before" %></th>
25
+ <th><%=t ".after" %></th>
26
+ <th></th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <% if @audits.any? %>
31
+ <% @audits.each do |audit| %>
32
+ <% audit.audited_changes.each_with_index do |(attribute, change), i| %>
33
+ <tr>
34
+ <% if i.zero? %>
35
+ <% if @auditable_type.blank? %>
36
+ <td rowspan="<%= audit.audited_changes.size %>">
37
+ <%= link_to t("activerecord.models.#{audit.auditable_type.underscore.downcase}"), audited_auditable_type_audits_path(audit.auditable_type.underscore.downcase) %>
38
+ </td>
39
+ <% end %>
40
+ <% if @auditable.blank? %>
41
+ <td rowspan="<%= audit.audited_changes.size %>">
42
+ <%= link_to audit.auditable, audited_auditable_audits_path(auditable_type: audit.auditable_type.underscore.downcase, auditable_id: audit.auditable_id) %>
43
+ </td>
44
+ <% end %>
45
+ <td rowspan="<%= audit.audited_changes.size %>"><%= audit.version %></td>
46
+ <td rowspan="<%= audit.audited_changes.size %>"><%= audit.created_at %></td>
47
+ <td rowspan="<%= audit.audited_changes.size %>"><%=t ".actions.#{audit.action}" %></td>
48
+ <td rowspan="<%= audit.audited_changes.size %>"><%= audit.user.try(:email) || t(".system") %></td>
49
+ <% end %>
50
+ <td><%=t "activerecord.attributes.#{audit.auditable_type.underscore.downcase}.#{attribute}" %></td>
51
+ <% if change.is_a? Array %>
52
+ <td><%= change.first %></td>
53
+ <td><%= change.last %></td>
54
+ <% else %>
55
+ <td></td>
56
+ <td><%= change %></td>
57
+ <% end %>
58
+ <td><%= audit.comment %></td>
59
+ </tr>
60
+ <% end %>
61
+ <% end %>
62
+ <% else %>
63
+ <tr>
64
+ <td colspan="8"><%=t ".empty" %></td>
65
+ </tr>
66
+ <% end %>
67
+ </tbody>
68
+ </table>
69
+
70
+ <%= paginate @audits %>
@@ -0,0 +1,28 @@
1
+ en:
2
+ activerecord:
3
+ attributes:
4
+ audit:
5
+ action: Action
6
+ auditable: Auditable
7
+ auditable_type: Auditable type
8
+ audited_changes: Changes
9
+ comment: Comment
10
+ created_at: Created at
11
+ user: User
12
+ version: Version
13
+ audited:
14
+ ui:
15
+ audits:
16
+ index:
17
+ actions:
18
+ create: Create
19
+ update: Update
20
+ after: After
21
+ attribute: Attribute
22
+ before: Before
23
+ empty: There are no audit records yet.
24
+ system: System
25
+ title:
26
+ all: Auditing all records
27
+ auditable: Auditing %{auditable}
28
+ auditable_type: Auditing all %{auditable_type}
@@ -0,0 +1,28 @@
1
+ es:
2
+ activerecord:
3
+ attributes:
4
+ audit:
5
+ action: Acción
6
+ auditable: Registro auditado
7
+ auditable_type: Tipo de registro
8
+ audited_changes: Cambios
9
+ comment: Comentario
10
+ created_at: Fecha de creación
11
+ user: Usuario
12
+ version: Versión
13
+ audited:
14
+ ui:
15
+ audits:
16
+ index:
17
+ actions:
18
+ create: Creación
19
+ update: Actualización
20
+ after: Después
21
+ attribute: Atributo
22
+ before: Antes
23
+ empty: No hay registros de auditoría aún.
24
+ system: Sistema
25
+ title:
26
+ all: Auditoría
27
+ auditable: Auditando %{auditable}
28
+ auditable_type: Auditando todos los %{auditable_type}
data/config/routes.rb ADDED
@@ -0,0 +1,8 @@
1
+ Rails.application.routes.draw do
2
+ scope "audited", module: "audited/ui" do
3
+ resources :audits, only: :index, as: "audited_audits"
4
+
5
+ get "audits/:auditable_type", to: "audits#index", as: "audited_auditable_type_audits"
6
+ get "audits/:auditable_type/:auditable_id", to: "audits#index", as: "audited_auditable_audits"
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ module Audited
2
+ module Ui
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Audited
2
+ module Ui
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
data/lib/audited/ui.rb ADDED
@@ -0,0 +1,43 @@
1
+ require "audited/ui/version"
2
+ require "audited/ui/engine"
3
+ require "ransack"
4
+
5
+ module Audited
6
+ module Ui
7
+ end
8
+
9
+ class Audit < ::ActiveRecord::Base
10
+ ransacker :raw_audited_changes, type: :text do
11
+ Arel.sql "audited_changes::text"
12
+ end
13
+
14
+ def self.ransackable_associations(auth_object = nil)
15
+ [
16
+ "associated",
17
+ "auditable",
18
+ "user"
19
+ ]
20
+ end
21
+
22
+ def self.ransackable_attributes(auth_object = nil)
23
+ [
24
+ "action",
25
+ "associated_id",
26
+ "associated_type",
27
+ "auditable_id",
28
+ "auditable_type",
29
+ "audited_changes",
30
+ "comment",
31
+ "created_at",
32
+ "id",
33
+ "raw_audited_changes",
34
+ "remote_address",
35
+ "request_uuid",
36
+ "user_id",
37
+ "user_type",
38
+ "username",
39
+ "version"
40
+ ]
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,11 @@
1
+ module Audited
2
+ module Ui
3
+ class ViewsGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../../../../../app/views/audited/ui", __FILE__)
5
+
6
+ def copy_views
7
+ directory :audits, "app/views/audited/ui/audits"
8
+ end
9
+ end
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: audited-ui
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Patricio Mac Adden
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-08-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: audited
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 5.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: kaminari
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 5.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 5.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: ransack
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: standardrb
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: A UI for Audited.
84
+ email:
85
+ - patriciomacadden@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - README.md
91
+ - Rakefile
92
+ - app/controllers/audited/ui/audits_controller.rb
93
+ - app/helpers/audited/ui/audits_helper.rb
94
+ - app/views/audited/ui/audits/_search_form.html.erb
95
+ - app/views/audited/ui/audits/index.html.erb
96
+ - config/locales/en.yml
97
+ - config/locales/es.yml
98
+ - config/routes.rb
99
+ - lib/audited/ui.rb
100
+ - lib/audited/ui/engine.rb
101
+ - lib/audited/ui/version.rb
102
+ - lib/generators/audited/ui/views_generator.rb
103
+ homepage: https://github.com/sinaptia/audited_ui
104
+ licenses: []
105
+ metadata:
106
+ homepage_uri: https://github.com/sinaptia/audited_ui
107
+ source_code_uri: https://github.com/sinaptia/audited_ui
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubygems_version: 3.4.10
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: A UI for Audited.
127
+ test_files: []