paper_trail_manager 0.8.0 → 1.0.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 +4 -4
- data/.gitignore +1 -0
- data/{CHANGES.md → CHANGELOG.md} +17 -0
- data/README.md +17 -1
- data/app/assets/stylesheets/paper_trail_manager/changes.css +256 -0
- data/app/controllers/paper_trail_manager/changes_controller.rb +8 -8
- data/app/views/paper_trail_manager/changes/_version.html.erb +5 -5
- data/app/views/paper_trail_manager/changes/index.html.erb +11 -10
- data/app/views/paper_trail_manager/changes/show.html.erb +3 -3
- data/config/locales/en.yml +30 -0
- data/lib/generators/paper_trail_manager/install/install_generator.rb +36 -0
- data/lib/generators/paper_trail_manager/install/templates/initializer.rb +35 -0
- data/lib/paper_trail_manager.rb +4 -0
- data/paper_trail_manager.gemspec +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5f28e3a746ba34c98e03d86d36e05e5588ceeed50ad478f9736084722950d08d
|
|
4
|
+
data.tar.gz: 6d0746fb02ce9a984387078763c77b54580bb6efa63b2ed0ca72117a7e6fd083
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 43f7cac000943029af95ee1c1b3544708afb6bf2ac47d61c0e56aea025d15c32d9b9d1d2fdd1a3f730b0d2c78e120f7c79cc02a9c075fa37e3db875fe0a0ad46
|
|
7
|
+
data.tar.gz: 30f45eb5c5b25386daaea0f89fad1405045ca80dd67d27fb1082061139614e5d0fe327ef3c3f2425f62fe7f94d83296d8e8a64ba1583f8985dfdce8da6460e85
|
data/.gitignore
CHANGED
data/{CHANGES.md → CHANGELOG.md}
RENAMED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
Changes to `paper_trail_manager`
|
|
2
2
|
================================
|
|
3
3
|
|
|
4
|
+
* 1.0.0
|
|
5
|
+
* Ship default stylesheet for changes views (table formatting, event color coding, diff highlighting, rollback button, date filter form)
|
|
6
|
+
* Include via `stylesheet_link_tag` or `require` in application.css
|
|
7
|
+
* Low-specificity selectors for easy overriding by host apps
|
|
8
|
+
* Add `.gitignore` for `.gem` build artifacts
|
|
9
|
+
|
|
10
|
+
* 0.9.0
|
|
11
|
+
* Add date range filtering to changes index via `from` and `to` query parameters
|
|
12
|
+
* Add date filter UI with date inputs, filter button, and clear link
|
|
13
|
+
* Add Rails install generator (`rails generate paper_trail_manager:install`)
|
|
14
|
+
* Add I18n support for all UI strings (30 translation keys, default English locale)
|
|
15
|
+
* Add authorization integration tests (unauthorized index/show/revert, non-existent records)
|
|
16
|
+
* Add unit tests for ChangesHelper methods (text_or_nil, changes_for, change_item_types, version_reify)
|
|
17
|
+
* Add specs for JSON and Atom response formats with filter coverage
|
|
18
|
+
* Host apps can override any translation key in their own locale files
|
|
19
|
+
* Test count: 19 → 50
|
|
20
|
+
|
|
4
21
|
* 0.8.0
|
|
5
22
|
* Fix `allow_show?` calling `allow_index_block` instead of `allow_show_block` — `allow_show_when` configuration was previously silently ignored (security fix)
|
|
6
23
|
* Fix gemspec `authors` field being overwritten by misplaced `email` assignment
|
data/README.md
CHANGED
|
@@ -45,6 +45,22 @@ resources :changes, controller: 'paper_trail_manager/changes'
|
|
|
45
45
|
|
|
46
46
|
Restart your server and visit `/changes` to browse, view, and revert your changes.
|
|
47
47
|
|
|
48
|
+
### Stylesheet (optional)
|
|
49
|
+
|
|
50
|
+
A default stylesheet is included. Add to your layout or application CSS:
|
|
51
|
+
|
|
52
|
+
```erb
|
|
53
|
+
<%= stylesheet_link_tag 'paper_trail_manager/changes' %>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Or require it in `app/assets/stylesheets/application.css`:
|
|
57
|
+
|
|
58
|
+
```css
|
|
59
|
+
/*= require paper_trail_manager/changes */
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The styles are low-specificity and easy to override in your own stylesheet.
|
|
63
|
+
|
|
48
64
|
## Configuration
|
|
49
65
|
|
|
50
66
|
Create an initializer (e.g. `config/initializers/paper_trail_manager.rb`) to customize behavior.
|
|
@@ -162,7 +178,7 @@ CI runs each combination across Ruby 3.1, 3.2, and 3.3 (18 jobs total).
|
|
|
162
178
|
- **Tests:** Added unit tests for authorization block delegation
|
|
163
179
|
- Modernized for Ruby 3.1–3.3 and Rails 7.0–7.1
|
|
164
180
|
|
|
165
|
-
See [
|
|
181
|
+
See [CHANGELOG.md](CHANGELOG.md) for full history.
|
|
166
182
|
|
|
167
183
|
## License
|
|
168
184
|
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* PaperTrailManager — Default Stylesheet
|
|
3
|
+
*
|
|
4
|
+
* Include in your layout:
|
|
5
|
+
* <%= stylesheet_link_tag 'paper_trail_manager/changes' %>
|
|
6
|
+
*
|
|
7
|
+
* Or import in your application.css:
|
|
8
|
+
* *= require paper_trail_manager/changes
|
|
9
|
+
*
|
|
10
|
+
* Override any styles in your own stylesheet — these are intentionally
|
|
11
|
+
* low-specificity so your app's styles take precedence.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/* ── Table ────────────────────────────────────────────────── */
|
|
15
|
+
|
|
16
|
+
.changes_table {
|
|
17
|
+
width: 100%;
|
|
18
|
+
border-collapse: collapse;
|
|
19
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
20
|
+
font-size: 14px;
|
|
21
|
+
line-height: 1.5;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.changes_table thead {
|
|
25
|
+
border-bottom: 2px solid #dee2e6;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.changes_table th {
|
|
29
|
+
padding: 10px 12px;
|
|
30
|
+
text-align: left;
|
|
31
|
+
font-weight: 600;
|
|
32
|
+
color: #495057;
|
|
33
|
+
background-color: #f8f9fa;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.changes_table td {
|
|
37
|
+
padding: 10px 12px;
|
|
38
|
+
vertical-align: top;
|
|
39
|
+
border-bottom: 1px solid #e9ecef;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.changes_table tfoot td {
|
|
43
|
+
padding: 12px;
|
|
44
|
+
border-bottom: none;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* ── Change Row ───────────────────────────────────────────── */
|
|
48
|
+
|
|
49
|
+
.change_row {
|
|
50
|
+
transition: background-color 0.15s ease;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.change_row:hover {
|
|
54
|
+
background-color: #f8f9fa;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Event-specific row colors */
|
|
58
|
+
.change_event_create {
|
|
59
|
+
border-left: 3px solid #28a745;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.change_event_update {
|
|
63
|
+
border-left: 3px solid #007bff;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.change_event_destroy {
|
|
67
|
+
border-left: 3px solid #dc3545;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* ── Time Column ──────────────────────────────────────────── */
|
|
71
|
+
|
|
72
|
+
.change_time {
|
|
73
|
+
width: 140px;
|
|
74
|
+
white-space: nowrap;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.change_id {
|
|
78
|
+
display: block;
|
|
79
|
+
font-size: 12px;
|
|
80
|
+
color: #868e96;
|
|
81
|
+
margin-bottom: 2px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.change_time .date {
|
|
85
|
+
font-weight: 500;
|
|
86
|
+
color: #343a40;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.change_time .time {
|
|
90
|
+
font-size: 13px;
|
|
91
|
+
color: #868e96;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* ── Details Column ───────────────────────────────────────── */
|
|
95
|
+
|
|
96
|
+
.change_details_description {
|
|
97
|
+
margin: 0 0 8px 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.change_details_description .event {
|
|
101
|
+
display: inline-block;
|
|
102
|
+
padding: 2px 8px;
|
|
103
|
+
border-radius: 3px;
|
|
104
|
+
font-size: 12px;
|
|
105
|
+
font-weight: 600;
|
|
106
|
+
text-transform: uppercase;
|
|
107
|
+
letter-spacing: 0.5px;
|
|
108
|
+
margin-right: 4px;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.change_event_create .event {
|
|
112
|
+
background-color: #d4edda;
|
|
113
|
+
color: #155724;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.change_event_update .event {
|
|
117
|
+
background-color: #cce5ff;
|
|
118
|
+
color: #004085;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.change_event_destroy .event {
|
|
122
|
+
background-color: #f8d7da;
|
|
123
|
+
color: #721c24;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.change_item {
|
|
127
|
+
color: #007bff;
|
|
128
|
+
text-decoration: none;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.change_item:hover {
|
|
132
|
+
text-decoration: underline;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* ── Diff Table ───────────────────────────────────────────── */
|
|
136
|
+
|
|
137
|
+
.change_details_table {
|
|
138
|
+
width: 100%;
|
|
139
|
+
border-collapse: collapse;
|
|
140
|
+
font-size: 13px;
|
|
141
|
+
margin-top: 6px;
|
|
142
|
+
background-color: #f8f9fa;
|
|
143
|
+
border-radius: 4px;
|
|
144
|
+
overflow: hidden;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.change_details_table td {
|
|
148
|
+
padding: 4px 8px;
|
|
149
|
+
border-bottom: 1px solid #e9ecef;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.change_detail_key {
|
|
153
|
+
font-weight: 500;
|
|
154
|
+
color: #495057;
|
|
155
|
+
width: 20%;
|
|
156
|
+
white-space: nowrap;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.change_detail_value.previous {
|
|
160
|
+
color: #dc3545;
|
|
161
|
+
background-color: #fff5f5;
|
|
162
|
+
word-break: break-word;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.change_detail_value.current {
|
|
166
|
+
color: #28a745;
|
|
167
|
+
background-color: #f0fff4;
|
|
168
|
+
word-break: break-word;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.change_detail_spacer {
|
|
172
|
+
text-align: center;
|
|
173
|
+
width: 30px;
|
|
174
|
+
color: #868e96;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.change_details_table .even {
|
|
178
|
+
background-color: #f8f9fa;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.change_details_table .odd {
|
|
182
|
+
background-color: #ffffff;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* ── Rollback Button ──────────────────────────────────────── */
|
|
186
|
+
|
|
187
|
+
.rollback {
|
|
188
|
+
display: inline-block;
|
|
189
|
+
padding: 3px 10px;
|
|
190
|
+
font-size: 12px;
|
|
191
|
+
font-weight: 500;
|
|
192
|
+
color: #856404;
|
|
193
|
+
background-color: #fff3cd;
|
|
194
|
+
border: 1px solid #ffc107;
|
|
195
|
+
border-radius: 3px;
|
|
196
|
+
cursor: pointer;
|
|
197
|
+
margin-left: 8px;
|
|
198
|
+
transition: background-color 0.15s ease;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.rollback:hover {
|
|
202
|
+
background-color: #ffc107;
|
|
203
|
+
color: #533f03;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* ── Date Filter Form ─────────────────────────────────────── */
|
|
207
|
+
|
|
208
|
+
.changes_date_filter {
|
|
209
|
+
display: flex;
|
|
210
|
+
align-items: center;
|
|
211
|
+
gap: 8px;
|
|
212
|
+
margin-bottom: 16px;
|
|
213
|
+
flex-wrap: wrap;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.changes_date_filter label {
|
|
217
|
+
font-size: 13px;
|
|
218
|
+
font-weight: 500;
|
|
219
|
+
color: #495057;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.changes_date_filter input[type="date"] {
|
|
223
|
+
padding: 4px 8px;
|
|
224
|
+
border: 1px solid #ced4da;
|
|
225
|
+
border-radius: 4px;
|
|
226
|
+
font-size: 13px;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.changes_date_filter input[type="submit"] {
|
|
230
|
+
padding: 4px 12px;
|
|
231
|
+
font-size: 13px;
|
|
232
|
+
font-weight: 500;
|
|
233
|
+
color: #fff;
|
|
234
|
+
background-color: #007bff;
|
|
235
|
+
border: 1px solid #007bff;
|
|
236
|
+
border-radius: 4px;
|
|
237
|
+
cursor: pointer;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.changes_date_filter input[type="submit"]:hover {
|
|
241
|
+
background-color: #0056b3;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.clear_filter {
|
|
245
|
+
font-size: 13px;
|
|
246
|
+
color: #868e96;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* ── Empty State ──────────────────────────────────────────── */
|
|
250
|
+
|
|
251
|
+
.changes_table tbody td[colspan] {
|
|
252
|
+
text-align: center;
|
|
253
|
+
color: #868e96;
|
|
254
|
+
padding: 24px;
|
|
255
|
+
font-style: italic;
|
|
256
|
+
}
|
|
@@ -15,7 +15,7 @@ class PaperTrailManager
|
|
|
15
15
|
# List changes
|
|
16
16
|
def index
|
|
17
17
|
unless change_index_allowed?
|
|
18
|
-
flash[:error] = '
|
|
18
|
+
flash[:error] = t('paper_trail_manager.flash.index_denied')
|
|
19
19
|
return(redirect_to root_url)
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -54,12 +54,12 @@ class PaperTrailManager
|
|
|
54
54
|
begin
|
|
55
55
|
@version = PaperTrail::Version.find(params[:id])
|
|
56
56
|
rescue ActiveRecord::RecordNotFound
|
|
57
|
-
flash[:error] = '
|
|
57
|
+
flash[:error] = t('paper_trail_manager.flash.not_found')
|
|
58
58
|
return(redirect_to action: :index)
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
unless change_show_allowed?(@version)
|
|
62
|
-
flash[:error] = '
|
|
62
|
+
flash[:error] = t('paper_trail_manager.flash.show_denied')
|
|
63
63
|
return(redirect_to action: :index)
|
|
64
64
|
end
|
|
65
65
|
|
|
@@ -74,12 +74,12 @@ class PaperTrailManager
|
|
|
74
74
|
begin
|
|
75
75
|
@version = PaperTrail::Version.find(params[:id])
|
|
76
76
|
rescue ActiveRecord::RecordNotFound
|
|
77
|
-
flash[:error] = '
|
|
77
|
+
flash[:error] = t('paper_trail_manager.flash.not_found')
|
|
78
78
|
return(redirect_to(changes_path))
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
unless change_revert_allowed?(@version)
|
|
82
|
-
flash[:error] = '
|
|
82
|
+
flash[:error] = t('paper_trail_manager.flash.revert_denied')
|
|
83
83
|
return(redirect_to changes_path)
|
|
84
84
|
end
|
|
85
85
|
|
|
@@ -93,14 +93,14 @@ class PaperTrailManager
|
|
|
93
93
|
|
|
94
94
|
if @result
|
|
95
95
|
if @version.event == 'create'
|
|
96
|
-
flash[:notice] = '
|
|
96
|
+
flash[:notice] = t('paper_trail_manager.flash.rollback_create')
|
|
97
97
|
redirect_to changes_path
|
|
98
98
|
else
|
|
99
|
-
flash[:notice] = '
|
|
99
|
+
flash[:notice] = t('paper_trail_manager.flash.rollback_update')
|
|
100
100
|
redirect_to change_item_url(@version)
|
|
101
101
|
end
|
|
102
102
|
else
|
|
103
|
-
flash[:error] =
|
|
103
|
+
flash[:error] = t('paper_trail_manager.flash.rollback_failed')
|
|
104
104
|
redirect_to changes_path
|
|
105
105
|
end
|
|
106
106
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<tr class='change_row <%= "change_event_#{version.event} #{version.event} #{version.event}, #{version.item_type.downcase}" %>'>
|
|
2
2
|
<td class='change_time'>
|
|
3
|
-
<span class='change_id'
|
|
3
|
+
<span class='change_id'><%= t('paper_trail_manager.changes.version.change_id', id: version.id) %></span>
|
|
4
4
|
<div class='date'> <%= version.created_at.strftime('%Y-%m-%d') %> </div>
|
|
5
5
|
<div class='time'> <%= version.created_at.strftime('%H:%M:%S') %> </div>
|
|
6
6
|
</td>
|
|
@@ -11,16 +11,16 @@
|
|
|
11
11
|
<% if PaperTrailManager.whodunnit_class && version.whodunnit %>
|
|
12
12
|
<% if user = PaperTrailManager.whodunnit_class.find(version.whodunnit) rescue nil %>
|
|
13
13
|
<% if PaperTrailManager.user_path_method && user %>
|
|
14
|
-
by <%= link_to(h(user.send(PaperTrailManager.whodunnit_name_method)), send(:user_path_method, user)) %>
|
|
14
|
+
<%= t('paper_trail_manager.changes.version.by') %> <%= link_to(h(user.send(PaperTrailManager.whodunnit_name_method)), send(:user_path_method, user)) %>
|
|
15
15
|
<% else %>
|
|
16
|
-
by <%= h(user.send(PaperTrailManager.whodunnit_name_method)) %>
|
|
16
|
+
<%= t('paper_trail_manager.changes.version.by') %> <%= h(user.send(PaperTrailManager.whodunnit_name_method)) %>
|
|
17
17
|
<% end %>
|
|
18
18
|
<% else %>
|
|
19
|
-
by <%= version.whodunnit %>
|
|
19
|
+
<%= t('paper_trail_manager.changes.version.by') %> <%= version.whodunnit %>
|
|
20
20
|
<% end %>
|
|
21
21
|
<% end %>
|
|
22
22
|
<% if change_revert_allowed?(version) %>
|
|
23
|
-
<%= button_to '
|
|
23
|
+
<%= button_to t('paper_trail_manager.changes.version.roll_back'), change_path(version), method: :put, class: 'rollback', form: { data: { turbo_confirm: t('paper_trail_manager.changes.version.confirm_rollback') } } %>
|
|
24
24
|
<% end %>
|
|
25
25
|
</p>
|
|
26
26
|
<% if version.event == 'update' or version.event == 'create' %>
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
<h1
|
|
1
|
+
<h1><%= t('paper_trail_manager.changes.index.title') %></h1>
|
|
2
2
|
|
|
3
3
|
<p>
|
|
4
|
-
|
|
5
|
-
<%= ([link_to('
|
|
4
|
+
<%= t('paper_trail_manager.changes.index.show_label') %>
|
|
5
|
+
<%= ([link_to(t('paper_trail_manager.changes.index.all'), changes_path)] + change_item_types.map { |type| link_to(type.pluralize, changes_path(type: type)) }).join(' | ').html_safe %>
|
|
6
6
|
</p>
|
|
7
7
|
|
|
8
8
|
<%= form_tag changes_path, method: :get, class: 'changes_date_filter' do %>
|
|
9
9
|
<%= hidden_field_tag :type, params[:type] if params[:type] %>
|
|
10
10
|
<%= hidden_field_tag :id, params[:id] if params[:id] %>
|
|
11
|
-
<label for="from"
|
|
11
|
+
<label for="from"><%= t('paper_trail_manager.changes.filter.from') %></label>
|
|
12
12
|
<%= date_field_tag :from, params[:from], id: 'from' %>
|
|
13
|
-
<label for="to"
|
|
13
|
+
<label for="to"><%= t('paper_trail_manager.changes.filter.to') %></label>
|
|
14
14
|
<%= date_field_tag :to, params[:to], id: 'to' %>
|
|
15
|
-
<%= submit_tag '
|
|
15
|
+
<%= submit_tag t('paper_trail_manager.changes.filter.submit'), name: nil %>
|
|
16
16
|
<% if params[:from].present? || params[:to].present? %>
|
|
17
|
-
<%= link_to '
|
|
17
|
+
<%= link_to t('paper_trail_manager.changes.filter.clear'), changes_path(type: params[:type], id: params[:id]), class: 'clear_filter' %>
|
|
18
18
|
<% end %>
|
|
19
19
|
<% end %>
|
|
20
|
+
|
|
20
21
|
<div class="table-responsive">
|
|
21
22
|
<table class='changes_table table table-bordered'>
|
|
22
23
|
<tfoot>
|
|
@@ -28,8 +29,8 @@
|
|
|
28
29
|
</tfoot>
|
|
29
30
|
<thead>
|
|
30
31
|
<tr class='changes_header'>
|
|
31
|
-
<th class='change_time'
|
|
32
|
-
<th class='change_details'
|
|
32
|
+
<th class='change_time'><%= t('paper_trail_manager.changes.index.time') %></th>
|
|
33
|
+
<th class='change_details'><%= t('paper_trail_manager.changes.index.details') %></th>
|
|
33
34
|
</tr>
|
|
34
35
|
</thead>
|
|
35
36
|
<tbody>
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
<% end %>
|
|
41
42
|
<% else %>
|
|
42
43
|
<tr>
|
|
43
|
-
<td colspan='2'> —
|
|
44
|
+
<td colspan='2'> — <%= t('paper_trail_manager.changes.index.no_changes') %> — </td>
|
|
44
45
|
</tr>
|
|
45
46
|
<% end %>
|
|
46
47
|
</tbody>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
<h1
|
|
1
|
+
<h1><%= t('paper_trail_manager.changes.show.title', id: @version.id) %></h1>
|
|
2
2
|
|
|
3
3
|
<table class='changes_table'>
|
|
4
4
|
<thead>
|
|
5
5
|
<tr class='changes_header'>
|
|
6
|
-
<th class='change_time'
|
|
7
|
-
<th class='change_details'
|
|
6
|
+
<th class='change_time'><%= t('paper_trail_manager.changes.index.time') %></th>
|
|
7
|
+
<th class='change_details'><%= t('paper_trail_manager.changes.index.details') %></th>
|
|
8
8
|
</tr>
|
|
9
9
|
</thead>
|
|
10
10
|
<tbody>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
en:
|
|
2
|
+
paper_trail_manager:
|
|
3
|
+
changes:
|
|
4
|
+
index:
|
|
5
|
+
title: "Changes"
|
|
6
|
+
show_label: "Show:"
|
|
7
|
+
all: "All"
|
|
8
|
+
no_changes: "No changes found"
|
|
9
|
+
time: "Time"
|
|
10
|
+
details: "Attribute with previous and current values"
|
|
11
|
+
show:
|
|
12
|
+
title: "Change %{id}"
|
|
13
|
+
filter:
|
|
14
|
+
from: "From:"
|
|
15
|
+
to: "To:"
|
|
16
|
+
submit: "Filter"
|
|
17
|
+
clear: "Clear"
|
|
18
|
+
version:
|
|
19
|
+
change_id: "Change #%{id}"
|
|
20
|
+
roll_back: "Roll back"
|
|
21
|
+
confirm_rollback: "Are you sure?"
|
|
22
|
+
by: "by"
|
|
23
|
+
flash:
|
|
24
|
+
index_denied: "You do not have permission to list changes."
|
|
25
|
+
show_denied: "You do not have permission to show that change."
|
|
26
|
+
revert_denied: "You do not have permission to revert this change."
|
|
27
|
+
not_found: "No such version."
|
|
28
|
+
rollback_create: "Rolled back newly-created record by destroying it."
|
|
29
|
+
rollback_update: "Rolled back changes to this record."
|
|
30
|
+
rollback_failed: "Couldn't rollback. Sorry."
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
|
|
5
|
+
class PaperTrailManager
|
|
6
|
+
class InstallGenerator < Rails::Generators::Base
|
|
7
|
+
source_root File.expand_path('templates', __dir__)
|
|
8
|
+
desc 'Install PaperTrailManager: add route and create initializer'
|
|
9
|
+
|
|
10
|
+
def add_route
|
|
11
|
+
route_string = "resources :changes, controller: 'paper_trail_manager/changes'"
|
|
12
|
+
routes_file = File.join(destination_root, 'config/routes.rb')
|
|
13
|
+
|
|
14
|
+
if File.exist?(routes_file) && File.read(routes_file).include?(route_string)
|
|
15
|
+
say_status :skip, 'Route already exists', :yellow
|
|
16
|
+
else
|
|
17
|
+
route route_string
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def create_initializer
|
|
22
|
+
template 'initializer.rb', 'config/initializers/paper_trail_manager.rb'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def show_post_install
|
|
26
|
+
say ''
|
|
27
|
+
say '✅ PaperTrailManager installed!', :green
|
|
28
|
+
say ''
|
|
29
|
+
say 'Next steps:'
|
|
30
|
+
say ' 1. Restart your Rails server'
|
|
31
|
+
say ' 2. Visit /changes to browse your PaperTrail version history'
|
|
32
|
+
say ' 3. Edit config/initializers/paper_trail_manager.rb to customize authorization'
|
|
33
|
+
say ''
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# PaperTrailManager configuration
|
|
4
|
+
# See: https://github.com/DamageLabs/paper_trail_manager
|
|
5
|
+
|
|
6
|
+
# Control who can view the changes index.
|
|
7
|
+
# PaperTrailManager.allow_index_when do |controller|
|
|
8
|
+
# controller.current_user.present?
|
|
9
|
+
# end
|
|
10
|
+
|
|
11
|
+
# Control who can view individual change details.
|
|
12
|
+
# Defaults to the allow_index rules if not set separately.
|
|
13
|
+
# PaperTrailManager.allow_show_when do |controller, version|
|
|
14
|
+
# controller.current_user.present?
|
|
15
|
+
# end
|
|
16
|
+
|
|
17
|
+
# Control who can revert changes.
|
|
18
|
+
# PaperTrailManager.allow_revert_when do |controller, version|
|
|
19
|
+
# controller.current_user&.admin?
|
|
20
|
+
# end
|
|
21
|
+
|
|
22
|
+
# Configure how to look up users referenced in PaperTrail's whodunnit column.
|
|
23
|
+
# PaperTrailManager.whodunnit_class = User
|
|
24
|
+
# PaperTrailManager.whodunnit_name_method = :name
|
|
25
|
+
|
|
26
|
+
# Specify a method to identify items on the index page.
|
|
27
|
+
# PaperTrailManager.item_name_method = :name
|
|
28
|
+
|
|
29
|
+
# Customize the user path helper (set to nil to disable user links).
|
|
30
|
+
# PaperTrailManager.user_path_method = :user_path
|
|
31
|
+
|
|
32
|
+
# When embedding inside another Rails engine:
|
|
33
|
+
# PaperTrailManager.base_controller = 'MyEngine::ApplicationController'
|
|
34
|
+
# PaperTrailManager.route_helpers = MyEngine::Engine.routes.url_helpers
|
|
35
|
+
# PaperTrailManager.layout = 'my_engine/application'
|
data/lib/paper_trail_manager.rb
CHANGED
|
@@ -14,6 +14,10 @@ rescue LoadError
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
class PaperTrailManager < Rails::Engine
|
|
17
|
+
initializer 'paper_trail_manager.i18n' do
|
|
18
|
+
config.i18n.load_path += Dir[root.join('config', 'locales', '*.yml')]
|
|
19
|
+
end
|
|
20
|
+
|
|
17
21
|
initializer 'paper_trail_manager.pagination' do
|
|
18
22
|
if defined?(WillPaginate)
|
|
19
23
|
::ActionView::Base.define_method(:paginate) { |*args, **kwargs, &block| will_paginate(*args, **kwargs, &block) }
|
data/paper_trail_manager.gemspec
CHANGED
|
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = 'paper_trail_manager'
|
|
8
|
-
spec.version = '0.
|
|
8
|
+
spec.version = '1.0.0'
|
|
9
9
|
spec.authors = ['Igal Koshevoy', 'Reid Beels']
|
|
10
10
|
spec.email = ['mail@reidbeels.com']
|
|
11
11
|
spec.summary = 'A user interface for `paper_trail` versioning data in Rails applications.'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: paper_trail_manager
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Igal Koshevoy
|
|
@@ -197,17 +197,19 @@ files:
|
|
|
197
197
|
- ".rubocop.yml"
|
|
198
198
|
- ".ruby-version"
|
|
199
199
|
- Appraisals
|
|
200
|
-
-
|
|
200
|
+
- CHANGELOG.md
|
|
201
201
|
- Gemfile
|
|
202
202
|
- LICENSE.txt
|
|
203
203
|
- README.md
|
|
204
204
|
- Rakefile
|
|
205
|
+
- app/assets/stylesheets/paper_trail_manager/changes.css
|
|
205
206
|
- app/controllers/paper_trail_manager/changes_controller.rb
|
|
206
207
|
- app/helpers/paper_trail_manager/changes_helper.rb
|
|
207
208
|
- app/views/paper_trail_manager/changes/_version.html.erb
|
|
208
209
|
- app/views/paper_trail_manager/changes/index.atom.builder
|
|
209
210
|
- app/views/paper_trail_manager/changes/index.html.erb
|
|
210
211
|
- app/views/paper_trail_manager/changes/show.html.erb
|
|
212
|
+
- config/locales/en.yml
|
|
211
213
|
- gemfiles/rails_6.1_paper_trail_12.0_kaminari.gemfile
|
|
212
214
|
- gemfiles/rails_6.1_paper_trail_12.0_will_paginate.gemfile
|
|
213
215
|
- gemfiles/rails_7.0_paper_trail_12.0_kaminari.gemfile
|
|
@@ -216,6 +218,8 @@ files:
|
|
|
216
218
|
- gemfiles/rails_7.0_paper_trail_15.0_will_paginate.gemfile
|
|
217
219
|
- gemfiles/rails_7.1_paper_trail_15.0_kaminari.gemfile
|
|
218
220
|
- gemfiles/rails_7.1_paper_trail_15.0_will_paginate.gemfile
|
|
221
|
+
- lib/generators/paper_trail_manager/install/install_generator.rb
|
|
222
|
+
- lib/generators/paper_trail_manager/install/templates/initializer.rb
|
|
219
223
|
- lib/paper_trail_manager.rb
|
|
220
224
|
- paper_trail_manager.gemspec
|
|
221
225
|
- spec/app_template.rb
|