audited-timeline 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: d4653647ba75b773e777546fe904aac57d540b7655da9a789ad38e5e514f6365
4
+ data.tar.gz: 445e18c24d7411fdc7b23993df0209ce4500d84fbb6fa9eb16169f575cbef7c2
5
+ SHA512:
6
+ metadata.gz: '0339cfec236473d6d8351e3500dd56b12e23897f07350d3c6640ef2eab29bdf31b6868670431b4334afcaf9bf03eee06340d2447a663bc5efc015d151affa8bb'
7
+ data.tar.gz: 4068c83fad885a04e2ce21adec50adde14429c0d8a439f178f53d4e099127348e87b425e43bdc9d0f982128d09a236907e7d8d215037bacdf5a4e7135cee0e67
@@ -0,0 +1,10 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "monthly"
7
+ - package-ecosystem: "docker"
8
+ directory: "/"
9
+ schedule:
10
+ interval: "monthly"
@@ -0,0 +1,27 @@
1
+ name: "CodeQL"
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: [master]
8
+ schedule:
9
+ - cron: "25 2 * * 6"
10
+
11
+ jobs:
12
+ analyze:
13
+ name: Analyze
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ actions: read
17
+ contents: read
18
+ security-events: write
19
+ steps:
20
+ - name: Checkout repository
21
+ uses: actions/checkout@v3
22
+ - name: Initialize CodeQL
23
+ uses: github/codeql-action/init@v2
24
+ - name: Autobuild
25
+ uses: github/codeql-action/autobuild@v2
26
+ - name: Perform CodeQL Analysis
27
+ uses: github/codeql-action/analyze@v2
@@ -0,0 +1,18 @@
1
+ name: Build Ruby Gem
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [master]
6
+
7
+ jobs:
8
+ build:
9
+ name: Build
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v2
13
+ with:
14
+ fetch-depth: 0
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: 3.0
18
+ - run: gem build *.gemspec
@@ -0,0 +1,27 @@
1
+ name: Build + Publish Ruby Gem
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "*"
7
+
8
+ jobs:
9
+ build:
10
+ name: Build + Publish
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+ - uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: 3.0
17
+ - name: Publish to RubyGems
18
+ run: |
19
+ mkdir -p $HOME/.gem
20
+ touch $HOME/.gem/credentials
21
+ chmod 0600 $HOME/.gem/credentials
22
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
23
+ gem build *.gemspec
24
+ gem push *.gem
25
+ env:
26
+ GEM_VERSION: ${{ vars.GITHUB_REF_NAME }}
27
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ audited-timeline
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.0.0
data/Dockerfile ADDED
@@ -0,0 +1,14 @@
1
+ FROM ruby:3.0-alpine
2
+
3
+ WORKDIR /app
4
+
5
+ RUN apk add -U \
6
+ bash less tzdata shared-mime-info build-base libc6-compat git && \
7
+ gem install bundler bundler-audit
8
+
9
+ COPY *.gemspec Gemfile Gemfile.lock VERSION ./
10
+ RUN BUNDLER_VERSION=$(grep -A 1 "BUNDLED WITH" Gemfile.lock | grep -v "BUNDLED WITH" | tr -d '[:space:]') && \
11
+ gem install "bundler:$BUNDLER_VERSION" && \
12
+ bundle install --jobs $(nproc)
13
+
14
+ COPY . ./
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in customer_client.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,177 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ audited-timeline (1.1.1)
5
+ audited (~> 4.3)
6
+ draper (>= 2.1.0)
7
+ rails (>= 4.0.0)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ actioncable (6.1.7.2)
13
+ actionpack (= 6.1.7.2)
14
+ activesupport (= 6.1.7.2)
15
+ nio4r (~> 2.0)
16
+ websocket-driver (>= 0.6.1)
17
+ actionmailbox (6.1.7.2)
18
+ actionpack (= 6.1.7.2)
19
+ activejob (= 6.1.7.2)
20
+ activerecord (= 6.1.7.2)
21
+ activestorage (= 6.1.7.2)
22
+ activesupport (= 6.1.7.2)
23
+ mail (>= 2.7.1)
24
+ actionmailer (6.1.7.2)
25
+ actionpack (= 6.1.7.2)
26
+ actionview (= 6.1.7.2)
27
+ activejob (= 6.1.7.2)
28
+ activesupport (= 6.1.7.2)
29
+ mail (~> 2.5, >= 2.5.4)
30
+ rails-dom-testing (~> 2.0)
31
+ actionpack (6.1.7.2)
32
+ actionview (= 6.1.7.2)
33
+ activesupport (= 6.1.7.2)
34
+ rack (~> 2.0, >= 2.0.9)
35
+ rack-test (>= 0.6.3)
36
+ rails-dom-testing (~> 2.0)
37
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
38
+ actiontext (6.1.7.2)
39
+ actionpack (= 6.1.7.2)
40
+ activerecord (= 6.1.7.2)
41
+ activestorage (= 6.1.7.2)
42
+ activesupport (= 6.1.7.2)
43
+ nokogiri (>= 1.8.5)
44
+ actionview (6.1.7.2)
45
+ activesupport (= 6.1.7.2)
46
+ builder (~> 3.1)
47
+ erubi (~> 1.4)
48
+ rails-dom-testing (~> 2.0)
49
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
50
+ activejob (6.1.7.2)
51
+ activesupport (= 6.1.7.2)
52
+ globalid (>= 0.3.6)
53
+ activemodel (6.1.7.2)
54
+ activesupport (= 6.1.7.2)
55
+ activemodel-serializers-xml (1.0.2)
56
+ activemodel (> 5.x)
57
+ activesupport (> 5.x)
58
+ builder (~> 3.1)
59
+ activerecord (6.1.7.2)
60
+ activemodel (= 6.1.7.2)
61
+ activesupport (= 6.1.7.2)
62
+ activestorage (6.1.7.2)
63
+ actionpack (= 6.1.7.2)
64
+ activejob (= 6.1.7.2)
65
+ activerecord (= 6.1.7.2)
66
+ activesupport (= 6.1.7.2)
67
+ marcel (~> 1.0)
68
+ mini_mime (>= 1.1.0)
69
+ activesupport (6.1.7.2)
70
+ concurrent-ruby (~> 1.0, >= 1.0.2)
71
+ i18n (>= 1.6, < 2)
72
+ minitest (>= 5.1)
73
+ tzinfo (~> 2.0)
74
+ zeitwerk (~> 2.3)
75
+ audited (4.10.0)
76
+ activerecord (>= 4.2, < 6.2)
77
+ builder (3.2.4)
78
+ concurrent-ruby (1.2.0)
79
+ crass (1.0.6)
80
+ date (3.3.3)
81
+ draper (4.0.2)
82
+ actionpack (>= 5.0)
83
+ activemodel (>= 5.0)
84
+ activemodel-serializers-xml (>= 1.0)
85
+ activesupport (>= 5.0)
86
+ request_store (>= 1.0)
87
+ ruby2_keywords
88
+ erubi (1.12.0)
89
+ globalid (1.1.0)
90
+ activesupport (>= 5.0)
91
+ i18n (1.12.0)
92
+ concurrent-ruby (~> 1.0)
93
+ loofah (2.19.1)
94
+ crass (~> 1.0.2)
95
+ nokogiri (>= 1.5.9)
96
+ mail (2.8.0.1)
97
+ mini_mime (>= 0.1.1)
98
+ net-imap
99
+ net-pop
100
+ net-smtp
101
+ marcel (1.0.2)
102
+ method_source (1.0.0)
103
+ mini_mime (1.1.2)
104
+ mini_portile2 (2.8.1)
105
+ minitest (5.17.0)
106
+ net-imap (0.3.4)
107
+ date
108
+ net-protocol
109
+ net-pop (0.1.2)
110
+ net-protocol
111
+ net-protocol (0.2.1)
112
+ timeout
113
+ net-smtp (0.3.3)
114
+ net-protocol
115
+ nio4r (2.5.8)
116
+ nokogiri (1.14.1)
117
+ mini_portile2 (~> 2.8.0)
118
+ racc (~> 1.4)
119
+ racc (1.6.2)
120
+ rack (2.2.6.2)
121
+ rack-test (2.0.2)
122
+ rack (>= 1.3)
123
+ rails (6.1.7.2)
124
+ actioncable (= 6.1.7.2)
125
+ actionmailbox (= 6.1.7.2)
126
+ actionmailer (= 6.1.7.2)
127
+ actionpack (= 6.1.7.2)
128
+ actiontext (= 6.1.7.2)
129
+ actionview (= 6.1.7.2)
130
+ activejob (= 6.1.7.2)
131
+ activemodel (= 6.1.7.2)
132
+ activerecord (= 6.1.7.2)
133
+ activestorage (= 6.1.7.2)
134
+ activesupport (= 6.1.7.2)
135
+ bundler (>= 1.15.0)
136
+ railties (= 6.1.7.2)
137
+ sprockets-rails (>= 2.0.0)
138
+ rails-dom-testing (2.0.3)
139
+ activesupport (>= 4.2.0)
140
+ nokogiri (>= 1.6)
141
+ rails-html-sanitizer (1.5.0)
142
+ loofah (~> 2.19, >= 2.19.1)
143
+ railties (6.1.7.2)
144
+ actionpack (= 6.1.7.2)
145
+ activesupport (= 6.1.7.2)
146
+ method_source
147
+ rake (>= 12.2)
148
+ thor (~> 1.0)
149
+ rake (13.0.6)
150
+ request_store (1.5.1)
151
+ rack (>= 1.4)
152
+ ruby2_keywords (0.0.5)
153
+ sprockets (4.2.0)
154
+ concurrent-ruby (~> 1.0)
155
+ rack (>= 2.2.4, < 4)
156
+ sprockets-rails (3.4.2)
157
+ actionpack (>= 5.2)
158
+ activesupport (>= 5.2)
159
+ sprockets (>= 3.0.0)
160
+ thor (1.2.1)
161
+ timeout (0.3.1)
162
+ tzinfo (2.0.6)
163
+ concurrent-ruby (~> 1.0)
164
+ websocket-driver (0.7.5)
165
+ websocket-extensions (>= 0.1.0)
166
+ websocket-extensions (0.1.5)
167
+ zeitwerk (2.6.6)
168
+
169
+ PLATFORMS
170
+ ruby
171
+
172
+ DEPENDENCIES
173
+ audited-timeline!
174
+ bundler
175
+
176
+ BUNDLED WITH
177
+ 2.4.6
data/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # Audited Timeline
2
+
3
+ This gem provides a frontend to the [audited](https://github.com/collectiveidea/audited) gem.
4
+
5
+ ![Screenshot](https://raw.githubusercontent.com/ninech/audited-timeline/master/images/screenshot.png?token=AAHmGTc4OGjO-QUvWWENxW-aR7QQu0Q2ks5VYuTjwA%3D%3D)
6
+
7
+ ## Setup
8
+
9
+ Add the gem to your `Gemfile` and run `bundle install`.
10
+
11
+ ```ruby
12
+ gem 'audited-timeline'
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Rendering the timeline
18
+
19
+ Render the `audited_timeline/list` partial and provide it the audits to be
20
+ rendered:
21
+
22
+ ```erb
23
+ <%= render 'audited_timeline/list', audits: @user.all_audits %>
24
+ ```
25
+
26
+ ### Add CSS Styles
27
+
28
+ Include `audited-timeline` in your `application.scss`:
29
+
30
+ ```sass
31
+ @import "audited-timeline";
32
+ ```
33
+
34
+ ### Rendering associated audits
35
+
36
+ To ease rendering a timeline which includes associated audits, there is a
37
+ `AuditedTimeline::AuditedConcern`. Include it in your model along with `audited` and
38
+ `has_associated_audits`:
39
+
40
+ ```ruby
41
+ class User < ActiveRecord::Base
42
+ include AuditedTimeline::AuditedConcern
43
+ audited
44
+ has_associated_audits
45
+ end
46
+ ```
47
+
48
+ ### Overriding an audit diff
49
+
50
+ It is possible to easily override an audit diff.
51
+
52
+ In development environment, each audit which has been rendered with the default
53
+ partial contains a HTML comment which points you to the partial you would have
54
+ to create.
55
+
56
+ ```html
57
+ <div class="audited-timeline-body">
58
+ <!-- create partial audits/user.create to override this table -->
59
+ <h1>User</h1>
60
+ <table class="diff">
61
+ ...
62
+ </table>
63
+ </div>
64
+ ```
65
+
66
+ In this case, create in your application `app/views/audits/_user.create.html.erb`
67
+ to override this audit type.
68
+
69
+ audited-timeline will provide a locale called `audit` to your partial.
70
+
71
+ ### Readable object names
72
+
73
+ audited-timeline will simply call `#to_s` on your model name. To prevent having
74
+ `#<User:0x007fe2e8a25f58>` in your timeline, define `#to_s` on your `User`
75
+ model:
76
+
77
+ ```ruby
78
+ class User < ActiveRecord::Base
79
+ alias_attribute :to_s, :fullname
80
+ end
81
+ ```
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc 'Run RSpec'
5
+ RSpec::Core::RakeTask.new do |t|
6
+ t.verbose = false
7
+ end
8
+ task default: :spec
@@ -0,0 +1,10 @@
1
+ .audited-timeline-audit {
2
+ i.action {
3
+ font-size: 0.8em;
4
+ margin-left: 0.5em;
5
+
6
+ &.create { color: $green; }
7
+ &.update { color: $blue; }
8
+ &.destroy { color: $red; }
9
+ }
10
+ }
@@ -0,0 +1,135 @@
1
+ .audited-timeline-list .audited-timeline-wrapper:first-child {
2
+ margin-top: 0;
3
+ }
4
+
5
+ .audited-timeline-wrapper {
6
+ margin-bottom: $base-spacing;
7
+ margin-top: $base-spacing;
8
+ padding: 2px 0px 2px;
9
+ position: relative;
10
+
11
+ &:first-child {
12
+ margin-top: 0;
13
+ }
14
+
15
+ .avatar {
16
+ float: left;
17
+ margin-left: -64px;
18
+ border-radius: $base-border-radius;
19
+ }
20
+
21
+ .with-avatars {
22
+ padding-left: 64px;
23
+ }
24
+ }
25
+
26
+ .audited-timeline-wrapper .with-avatars .audited-timeline-item {
27
+ position: relative;
28
+
29
+ &:before, &:after {
30
+ border-color: transparent;
31
+ border-style: solid solid outset;
32
+ content: ' ';
33
+ display: block;
34
+ height: 0;
35
+ left: -16px;
36
+ position: absolute;
37
+ right: 100%;
38
+ top: 11px;
39
+ width: 0;
40
+ }
41
+
42
+ &:before {
43
+ border-right-color: $base-border-color;
44
+ border-width: 8px;
45
+ }
46
+
47
+ &:after {
48
+ border-right-color: #f2f8fa;
49
+ border-width: 7px;
50
+ margin-left: 2px;
51
+ margin-top: 1px;
52
+ }
53
+ }
54
+
55
+ .audited-timeline-item {
56
+ border: $base-border;
57
+ border-radius: $base-border-radius;
58
+
59
+ &:hover .audited-timeline-header .audited-timeline-actions {
60
+ visibility: visible;
61
+ }
62
+ }
63
+
64
+ .audited-timeline-header {
65
+ background-color: lighten($light-gray, 15%);
66
+ border-bottom: 1px solid #eee;
67
+ border-top-left-radius: $base-border-radius;
68
+ border-top-right-radius: $base-border-radius;
69
+ padding: $base-spacing/3 $base-spacing/1.5;
70
+
71
+ .audited-timeline-user {
72
+ font-weight: bold;
73
+ margin-right: 0.5em;
74
+ }
75
+
76
+ .audited-timeline-date {
77
+ color: $dark-gray;
78
+ font-size: 0.8em;
79
+ }
80
+
81
+ .audited-timeline-actions {
82
+ float: right;
83
+ visibility: hidden;
84
+ a { color: $light-gray; }
85
+ a:hover { color: $blue; }
86
+ }
87
+ }
88
+
89
+ .audited-timeline-body {
90
+ background: #fff;
91
+ padding: $base-spacing/1.5;
92
+
93
+ p {
94
+ margin-bottom: 0;
95
+ }
96
+
97
+ form.simple_form {
98
+ float: none;
99
+ margin: 0;
100
+ width: 100%;
101
+ }
102
+
103
+ table {
104
+ margin: 0;
105
+
106
+ th {
107
+ padding: 0 0 .25em;
108
+ }
109
+
110
+ th:first-child {
111
+ width: 12em;
112
+ }
113
+
114
+ td {
115
+ font-size: .9em;
116
+ padding: .25em 0;
117
+ }
118
+
119
+ tr:last-child td {
120
+ border-bottom: 0;
121
+ }
122
+
123
+ tr th:first-child,
124
+ tr td:first-child {
125
+ white-space: nowrap;
126
+ }
127
+ }
128
+
129
+ h1 {
130
+ font-size: 1.2em;
131
+ height: auto !important;
132
+ margin: 0 0 .5em;
133
+ padding: 0;
134
+ }
135
+ }
@@ -0,0 +1,12 @@
1
+ $green: #27AE60 !default;
2
+ $red: #E74C3C !default;
3
+ $blue: #009ad7 !default;
4
+ $light-gray: #CDCFCE !default;
5
+ $dark-gray: #333 !default;
6
+
7
+ $base-line-height: 1.5 !default;
8
+ $base-spacing: $base-line-height * 1em !default;
9
+
10
+ $base-border-color: $light-gray !default;
11
+ $base-border: 1px solid $base-border-color !default;
12
+ $base-border-radius: 3px !default;
@@ -0,0 +1,3 @@
1
+ @import "audited-timeline/variables";
2
+ @import "audited-timeline/timeline";
3
+ @import "audited-timeline/audits";
@@ -0,0 +1,25 @@
1
+ <%= cache [audit, I18n.locale, :diff] do %>
2
+ <h1><%= audit.audited_title %></h1>
3
+ <table class="diff">
4
+ <thead>
5
+ <tr>
6
+ <th><%= t '.attribute' %></th>
7
+ <% if audit.action == 'update' %>
8
+ <th><%= t '.from' %></th>
9
+ <th><%= t '.to' %></th>
10
+ <% else %>
11
+ <th><%= t '.value' %></th>
12
+ <% end %>
13
+ </tr>
14
+ </thead>
15
+ <tbody>
16
+ <% audit.human_audited_changes.each_pair do |field, value| %>
17
+ <% next if [value].flatten.join.blank? %>
18
+ <tr>
19
+ <td><%= audit.auditable_class.human_attribute_name field %></td>
20
+ <%= render "audited_timeline/diff_#{audit.action}", field: field, value: value %>
21
+ </tr>
22
+ <% end %>
23
+ </tbody>
24
+ </table>
25
+ <% end %>
@@ -0,0 +1 @@
1
+ <td><%= value[0] %></td>
@@ -0,0 +1 @@
1
+ <td><%= value[0] %></td>
@@ -0,0 +1,2 @@
1
+ <td><%= value[0] %></td>
2
+ <td><%= value[1] %></td>
@@ -0,0 +1,34 @@
1
+ <% with_avatars = local_assigns[:with_avatars] == true ? true : false %>
2
+ <% sort = local_assigns[:sort] || 'desc' %>
3
+ <% limit = local_assigns[:limit] || 25 %>
4
+ <div class="audited-timeline-list">
5
+ <% audits.reorder("created_at #{sort}").limit(limit).decorate.each do |audit| %>
6
+ <div id="<%= dom_id audit %>" class="audited-timeline-wrapper <%= 'with-avatars' if with_avatars == true %> ">
7
+ <% if with_avatars == true && audit.user.present? %>
8
+ <%= audited_timeline_user_gravatar audit.user %>
9
+ <% end %>
10
+
11
+ <div class="audited-timeline-item audited-timeline-audit <%= audit.action %>">
12
+ <div class="audited-timeline-header">
13
+ <span class="audited-timeline-user">
14
+ <%= audit.user %>
15
+ <%= audited_timeline_action_icon audit %>
16
+ </span>
17
+ <span class="audited-timeline-date">
18
+ <%= l audit.created_at, format: :audited_timeline %>
19
+ </span>
20
+ </div>
21
+ <div class="audited-timeline-body">
22
+ <% if lookup_context.template_exists?(audited_timeline_partial_for(audit), [], true) %>
23
+ <%= render audited_timeline_partial_for(audit), audit: audit %>
24
+ <% else %>
25
+ <% if Rails.env.development? %>
26
+ <!-- create partial <%= audited_timeline_partial_for(audit) %> to override this table -->
27
+ <% end %>
28
+ <%= render 'audited_timeline/diff', audit: audit %>
29
+ <% end %>
30
+ </div>
31
+ </div>
32
+ </div>
33
+ <% end %>
34
+ </div>
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'audited-timeline'
8
+ spec.version = ENV.fetch("GEM_VERSION", [`git describe --tags --abbrev=0`, `git rev-parse --short HEAD`].map(&:chomp).join(".")).delete_prefix("v")
9
+ spec.authors = ['nine.ch Development']
10
+ spec.email = ['development@nine.ch']
11
+ spec.summary = 'Frontent to audited'
12
+ spec.homepage = 'https://github.com/ninech/audited-timeline'
13
+ spec.license = 'MIT'
14
+ spec.description = 'audited-timeline provides timeline frontend to audited'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency "bundler"
22
+
23
+ spec.add_runtime_dependency 'audited', '~> 4.3'
24
+ spec.add_runtime_dependency 'rails', '>= 4.0.0'
25
+ spec.add_runtime_dependency 'draper', '>= 2.1.0'
26
+ end
@@ -0,0 +1,13 @@
1
+ ---
2
+ de:
3
+ audited_timeline:
4
+ diff:
5
+ attribute: Attribut
6
+ from: Bisher
7
+ to: Neu
8
+ value: Wert
9
+ 'yes': Ja
10
+ 'no': Nein
11
+ time:
12
+ formats:
13
+ audited_timeline: "%Y-%m-%d %H:%M"
@@ -0,0 +1,13 @@
1
+ ---
2
+ en:
3
+ audited_timeline:
4
+ diff:
5
+ attribute: Attribute
6
+ from: Old
7
+ to: New
8
+ value: Value
9
+ 'yes': Yes
10
+ 'no': No
11
+ time:
12
+ formats:
13
+ audited_timeline: "%Y-%m-%d %H:%M"
@@ -0,0 +1,7 @@
1
+ version: "3"
2
+ services:
3
+ app:
4
+ build:
5
+ context: .
6
+ volumes:
7
+ - .:/app:cached
Binary file
@@ -0,0 +1 @@
1
+ require 'audited_timeline'
@@ -0,0 +1,9 @@
1
+ module AuditedTimeline
2
+ class Audit < Audited::Audit
3
+ delegate :name, to: :user, allow_nil: true, prefix: true
4
+
5
+ def auditable_class
6
+ auditable_type.constantize
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,78 @@
1
+ require 'draper'
2
+
3
+ module AuditedTimeline
4
+ class AuditDecorator < ::Draper::Decorator
5
+ delegate_all
6
+
7
+ def human_audited_changes
8
+ human_changes = {}
9
+ audited_changes.each_pair do |field, value|
10
+ value = [value].flatten
11
+ if field.end_with?('_id')
12
+ human_changes[field] = value.map { |v| object_name_by_field_and_value(field, v) }
13
+ else
14
+ human_changes[field] = value.map { |v| human_value(field, v) }
15
+ end
16
+ end
17
+ human_changes
18
+ end
19
+
20
+ def audited_title
21
+ [
22
+ auditable_type.constantize.model_name.human,
23
+ object_name_by_type_and_value(auditable_type, auditable_id)
24
+ ].join(' ')
25
+ end
26
+
27
+ private
28
+
29
+ def human_value(field, value)
30
+ return I18n.t('audited_timeline.yes') if value == true
31
+ return I18n.t('audited_timeline.no') if value == false
32
+ if enum_values(field)
33
+ return I18n.t("#{audited_class.table_name.singularize}.#{field}.#{enum_value(field, value)}")
34
+ end
35
+ value
36
+ end
37
+
38
+ def object_name_by_field_and_value(field, value)
39
+ return nil unless value
40
+ begin
41
+ obj= associated_class_name(auditable_type, field).unscoped.find(value)
42
+ "#{obj} (#{value})"
43
+ rescue
44
+ "unknown (#{value})"
45
+ end
46
+ end
47
+
48
+ def object_name_by_type_and_value(type, value)
49
+ return nil unless value
50
+ begin
51
+ type.constantize.unscoped.find(value)
52
+ rescue
53
+ nil
54
+ end
55
+ end
56
+
57
+ def enum_value(field, value)
58
+ if value.kind_of?(Integer)
59
+ enum_values(field).key(value)
60
+ else
61
+ value
62
+ end
63
+ end
64
+
65
+ def enum_values(field)
66
+ audited_class.send(field.pluralize) if audited_class.respond_to?(field.pluralize)
67
+ end
68
+
69
+ def audited_class
70
+ object.auditable.class
71
+ end
72
+
73
+ def associated_class_name(model, associated_field)
74
+ association = associated_field.sub('_id', '').to_sym
75
+ model.constantize.reflect_on_association(association).class_name.constantize
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,9 @@
1
+ module AuditedTimeline
2
+ module AuditedConcern
3
+ extend ActiveSupport::Concern
4
+
5
+ def all_audits
6
+ AuditedTimeline::Audit.where(id: audit_ids + associated_audit_ids).reorder('created_at asc')
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ require 'audited_timeline/view_helpers'
2
+
3
+ module AuditedTimeline
4
+ class Engine < Rails::Engine
5
+ initializer 'audited_timeline.view_helpers' do
6
+ ActionView::Base.send :include, ViewHelpers
7
+ end
8
+
9
+ initializer 'audited_timeline.add_view_paths', after: :add_view_paths do
10
+ ActiveSupport.on_load(:action_controller) do
11
+ append_view_path "#{Gem.loaded_specs['audited-timeline'].full_gem_path}/app/views"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ module AuditedTimeline
2
+ module ViewHelpers
3
+ def audited_timeline_action_icon(audit)
4
+ case audit.action
5
+ when 'create'
6
+ fa_icon 'plus-circle', class: 'action create'
7
+ when 'update'
8
+ fa_icon 'pencil', class: 'action update'
9
+ when 'destroy'
10
+ fa_icon 'trash-o', class: 'action destroy'
11
+ end
12
+ end
13
+
14
+ def audited_timeline_gravatar_url(email)
15
+ email_hash = Digest::MD5.hexdigest(email.to_s)
16
+ "https://www.gravatar.com/avatar/#{email_hash}"
17
+ end
18
+
19
+ def audited_timeline_user_gravatar(user, options = {})
20
+ options.reverse_merge! class: 'avatar', alt: user.to_s, size: '48x48'
21
+ image_tag audited_timeline_gravatar_url(user.email), options
22
+ end
23
+
24
+ def audited_timeline_partial_for(audit)
25
+ "audits/#{audit.auditable_type.underscore}_#{audit.action}"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ module AuditedTimeline
2
+ end
3
+
4
+ require 'audited_timeline/railtie'
5
+ require 'audited_timeline/audit'
6
+ require 'audited_timeline/audit_decorator'
7
+ require 'audited_timeline/audited_concern'
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: audited-timeline
3
+ version: !ruby/object:Gem::Version
4
+ version: '0'
5
+ platform: ruby
6
+ authors:
7
+ - nine.ch Development
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-02-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: audited
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 4.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: 4.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: draper
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 2.1.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 2.1.0
69
+ description: audited-timeline provides timeline frontend to audited
70
+ email:
71
+ - development@nine.ch
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".github/dependabot.yml"
77
+ - ".github/workflows/codeql-analysis.yml"
78
+ - ".github/workflows/gem-build.yml"
79
+ - ".github/workflows/gem-push.yml"
80
+ - ".ruby-gemset"
81
+ - ".ruby-version"
82
+ - Dockerfile
83
+ - Gemfile
84
+ - Gemfile.lock
85
+ - README.md
86
+ - Rakefile
87
+ - app/assets/stylesheets/audited-timeline.scss
88
+ - app/assets/stylesheets/audited-timeline/_audits.scss
89
+ - app/assets/stylesheets/audited-timeline/_timeline.scss
90
+ - app/assets/stylesheets/audited-timeline/_variables.scss
91
+ - app/views/audited_timeline/_diff.html.erb
92
+ - app/views/audited_timeline/_diff_create.html.erb
93
+ - app/views/audited_timeline/_diff_destroy.html.erb
94
+ - app/views/audited_timeline/_diff_update.html.erb
95
+ - app/views/audited_timeline/_list.html.erb
96
+ - audited_timeline.gemspec
97
+ - config/locales/audited_timeline.de.yml
98
+ - config/locales/audited_timeline.en.yml
99
+ - docker-compose.yml
100
+ - images/screenshot.png
101
+ - lib/audited-timeline.rb
102
+ - lib/audited_timeline.rb
103
+ - lib/audited_timeline/audit.rb
104
+ - lib/audited_timeline/audit_decorator.rb
105
+ - lib/audited_timeline/audited_concern.rb
106
+ - lib/audited_timeline/railtie.rb
107
+ - lib/audited_timeline/view_helpers.rb
108
+ homepage: https://github.com/ninech/audited-timeline
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubygems_version: 3.4.1
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: Frontent to audited
131
+ test_files: []