audited-timeline 0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/dependabot.yml +10 -0
- data/.github/workflows/codeql-analysis.yml +27 -0
- data/.github/workflows/gem-build.yml +18 -0
- data/.github/workflows/gem-push.yml +27 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Dockerfile +14 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +177 -0
- data/README.md +81 -0
- data/Rakefile +8 -0
- data/app/assets/stylesheets/audited-timeline/_audits.scss +10 -0
- data/app/assets/stylesheets/audited-timeline/_timeline.scss +135 -0
- data/app/assets/stylesheets/audited-timeline/_variables.scss +12 -0
- data/app/assets/stylesheets/audited-timeline.scss +3 -0
- data/app/views/audited_timeline/_diff.html.erb +25 -0
- data/app/views/audited_timeline/_diff_create.html.erb +1 -0
- data/app/views/audited_timeline/_diff_destroy.html.erb +1 -0
- data/app/views/audited_timeline/_diff_update.html.erb +2 -0
- data/app/views/audited_timeline/_list.html.erb +34 -0
- data/audited_timeline.gemspec +26 -0
- data/config/locales/audited_timeline.de.yml +13 -0
- data/config/locales/audited_timeline.en.yml +13 -0
- data/docker-compose.yml +7 -0
- data/images/screenshot.png +0 -0
- data/lib/audited-timeline.rb +1 -0
- data/lib/audited_timeline/audit.rb +9 -0
- data/lib/audited_timeline/audit_decorator.rb +78 -0
- data/lib/audited_timeline/audited_concern.rb +9 -0
- data/lib/audited_timeline/railtie.rb +15 -0
- data/lib/audited_timeline/view_helpers.rb +28 -0
- data/lib/audited_timeline.rb +7 -0
- metadata +131 -0
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,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
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
|
+

|
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,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,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,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
|
data/docker-compose.yml
ADDED
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'audited_timeline'
|
@@ -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,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
|
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: []
|