paper_trail_viewer 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.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/test.yml +43 -0
  3. data/.gitignore +41 -0
  4. data/Appraisals +13 -0
  5. data/CHANGELOG.md +9 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +23 -0
  8. data/README.md +53 -0
  9. data/Rakefile +45 -0
  10. data/app/controllers/paper_trail_viewer/js_controller.rb +14 -0
  11. data/app/controllers/paper_trail_viewer/versions_controller.rb +119 -0
  12. data/app/controllers/paper_trail_viewer/viewer_controller.rb +4 -0
  13. data/app/views/paper_trail_viewer/viewer/index.html.erb +5 -0
  14. data/bin/setup +8 -0
  15. data/config/routes.rb +5 -0
  16. data/gemfiles/rails_6.0_paper_trail_11.1.gemfile +10 -0
  17. data/gemfiles/rails_6.0_paper_trail_12.2.gemfile +10 -0
  18. data/gemfiles/rails_7.0_paper_trail_12.2.gemfile +10 -0
  19. data/javascript/compiled.js +2 -0
  20. data/javascript/src/app.tsx +100 -0
  21. data/javascript/src/components/change_diff.tsx +57 -0
  22. data/javascript/src/components/config_modal.tsx +22 -0
  23. data/javascript/src/components/controls.tsx +62 -0
  24. data/javascript/src/components/full_object_modal.tsx +21 -0
  25. data/javascript/src/components/index.ts +3 -0
  26. data/javascript/src/components/modal.tsx +34 -0
  27. data/javascript/src/components/pagination.tsx +53 -0
  28. data/javascript/src/components/versions_list.tsx +142 -0
  29. data/javascript/src/index.ts +1 -0
  30. data/javascript/src/types.ts +42 -0
  31. data/lib/paper_trail_viewer/data_source/active_record.rb +30 -0
  32. data/lib/paper_trail_viewer/data_source/bigquery.rb +45 -0
  33. data/lib/paper_trail_viewer/engine.rb +5 -0
  34. data/lib/paper_trail_viewer/version.rb +3 -0
  35. data/lib/paper_trail_viewer.rb +11 -0
  36. data/package.json +43 -0
  37. data/paper_trail_viewer.gemspec +34 -0
  38. data/spec/app_template.rb +19 -0
  39. data/spec/rails_helper.rb +18 -0
  40. data/spec/support/factories.rb +13 -0
  41. data/spec/system/paper_trail_viewer_spec.rb +114 -0
  42. data/tsconfig.json +13 -0
  43. data/webpack.config.js +26 -0
  44. metadata +251 -0
data/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "paper_trail_viewer",
3
+ "version": "1.0.0",
4
+ "description": "Browse changes to records when using Ruby on Rails and the `paper_trail` gem.",
5
+ "main": "index.js",
6
+ "directories": {
7
+ "lib": "lib"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1",
11
+ "compile": "npx webpack"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/jaynetics/paper_trail_viewer.git"
16
+ },
17
+ "keywords": [],
18
+ "author": "",
19
+ "license": "MIT",
20
+ "bugs": {
21
+ "url": "https://github.com/jaynetics/paper_trail_viewer/issues"
22
+ },
23
+ "homepage": "https://github.com/jaynetics/paper_trail_viewer#readme",
24
+ "dependencies": {
25
+ "@babel/cli": "^7.17.6",
26
+ "@babel/core": "^7.17.8",
27
+ "@babel/preset-env": "^7.16.11",
28
+ "@babel/preset-react": "^7.16.7",
29
+ "@babel/preset-typescript": "^7.16.7",
30
+ "@types/react": "^17.0.41",
31
+ "@types/react-dom": "^17.0.14",
32
+ "@types/react-modal": "^3.13.1",
33
+ "babel-loader": "^8.2.4",
34
+ "react": "^16.14.0",
35
+ "react-diff-viewer": "^3.1.1",
36
+ "react-dom": "^16.14.0",
37
+ "react-hook-form": "^7.28.1",
38
+ "react-modal": "^3.14.4",
39
+ "ts-loader": "^9.2.8",
40
+ "webpack": "^5.70.0",
41
+ "webpack-cli": "^4.9.2"
42
+ }
43
+ }
@@ -0,0 +1,34 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require_relative 'lib/paper_trail_viewer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'paper_trail_viewer'
8
+ spec.version = PaperTrailViewer::VERSION
9
+ spec.authors = ['Janosch Müller', 'Igal Koshevoy']
10
+ spec.summary = 'A user interface for `paper_trail` versioning data in Ruby on Rails applications.'
11
+ spec.description = 'Browse, view and revert changes to records when using Ruby on Rails and the `paper_trail` gem.'
12
+ spec.homepage = 'https://github.com/jaynetics/paper_trail_viewer'
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0") + %w[javascript/compiled.js]
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.required_ruby_version = '>= 2.7'
21
+
22
+ spec.add_dependency 'kaminari'
23
+ spec.add_dependency 'paper_trail', ['>= 11.1']
24
+ spec.add_dependency 'rails', ['>= 6.0', '< 8.0']
25
+
26
+ spec.add_development_dependency 'appraisal', '~> 1.0'
27
+ spec.add_development_dependency 'capybara', '~> 3.0'
28
+ spec.add_development_dependency 'factory_bot_rails', '~> 6.0'
29
+ spec.add_development_dependency 'puma', '~> 5.0'
30
+ spec.add_development_dependency 'rake', '~> 13.0'
31
+ spec.add_development_dependency 'rspec-rails', '~> 5.0'
32
+ spec.add_development_dependency 'sqlite3', '>= 1.3.6'
33
+ spec.add_development_dependency 'webdrivers', '~> 5.0'
34
+ end
@@ -0,0 +1,19 @@
1
+ gem 'paper_trail_viewer', path: __FILE__ + '/../../../'
2
+
3
+ generate 'paper_trail:install'
4
+ generate 'resource', 'entity name:string status:string --no-test-framework'
5
+ generate 'resource', 'platform name:string status:string --no-test-framework'
6
+
7
+ model_body = <<-RUBY
8
+ has_paper_trail
9
+
10
+ validates_presence_of :name
11
+ validates_presence_of :status
12
+ RUBY
13
+
14
+ inject_into_class 'app/models/entity.rb', 'Entity', model_body
15
+ inject_into_class 'app/models/platform.rb', 'Platform', model_body
16
+
17
+ route 'mount PaperTrailViewer::Engine => "/changes"'
18
+
19
+ rake 'db:migrate db:test:prepare'
@@ -0,0 +1,18 @@
1
+ ENV['RAILS_ENV'] ||= 'test'
2
+ require File.expand_path('dummy/config/environment', __dir__)
3
+ require 'rspec/rails'
4
+
5
+ require 'selenium/webdriver'
6
+ require 'webdrivers/chromedriver'
7
+
8
+ Capybara.server = :puma, { Silent: true }
9
+
10
+ Dir['spec/support/**/*.rb'].each { |f| require File.expand_path(f) }
11
+
12
+ RSpec.configure do |config|
13
+ config.use_transactional_fixtures = true
14
+ config.infer_spec_type_from_file_location!
15
+ config.before(:each, type: :system) do
16
+ driven_by :selenium_chrome_headless
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ require 'factory_bot_rails'
2
+
3
+ FactoryBot.define do
4
+ factory :entity do
5
+ sequence(:name) { |n| "name_#{n}" }
6
+ sequence(:status) { |n| "status_#{n}" }
7
+ end
8
+
9
+ factory :platform do
10
+ sequence(:name) { |n| "name_#{n}" }
11
+ sequence(:status) { |n| "status_#{n}" }
12
+ end
13
+ end
@@ -0,0 +1,114 @@
1
+ require 'rails_helper'
2
+
3
+ describe PaperTrailViewer, versioning: true do
4
+ let(:engine_urls) { PaperTrailViewer::Engine.routes.url_helpers }
5
+
6
+ context 'without changes' do
7
+ context 'when fetching the index' do
8
+ it 'has no changes by default' do
9
+ visit engine_urls.root_path
10
+
11
+ expect(page).to have_content('No versions found')
12
+ end
13
+ end
14
+ end
15
+
16
+ context 'with changes' do
17
+ let(:reimu) { FactoryBot.create(:entity, name: 'Miko Hakurei Reimu', status: 'Highly Responsive to Prayers') }
18
+ let(:flanchan) { FactoryBot.create(:entity, name: 'Flandre Scarlet', status: 'The Embodiment of Scarlet Devil') }
19
+ let(:sakuya) { FactoryBot.create(:entity, name: 'Sakuya Izayoi', status: 'Flowering Night') }
20
+ let(:kyuu_hachi) { FactoryBot.create(:platform, name: 'PC-9801', status: 'SUGOI!!1!') }
21
+ let!(:uinodouzu) { FactoryBot.create(:platform, name: 'Mikorusofto Uinodouzu', status: 'o-O') }
22
+
23
+ let!(:flanchan_id) { flanchan.id }
24
+
25
+ before do
26
+ sakuya
27
+ reimu.update(name: 'Hakurei Reimu', status: 'Phantasmagoria of Dimensional Dream')
28
+ reimu.update(status: 'Perfect Cherry Blossom')
29
+ flanchan.destroy
30
+ kyuu_hachi.update(status: 'Kimochi warui.')
31
+ kyuu_hachi.destroy
32
+ uinodouzu
33
+ end
34
+
35
+ describe 'index' do
36
+ context 'when getting all changes' do
37
+ context 'with authorization' do
38
+ context 'when getting default index' do
39
+ before { visit engine_urls.root_path }
40
+
41
+ it 'has all changes' do
42
+ expect(page).to have_selector('[data-ci-type="version-row"]', count: 10)
43
+ end
44
+
45
+ it 'has changes for all changed item types' do
46
+ within('table') do
47
+ expect(page).to have_content('Entity')
48
+ expect(page).to have_content('Platform')
49
+ end
50
+ end
51
+
52
+ it 'orders changes with newest and highest id at the top' do
53
+ ids = PaperTrail::Version.pluck(:id)
54
+ expect(page).to have_content(/#{ids.sort.reverse.join('.+')}/m)
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ context 'when getting changes for a specific type' do
61
+ context 'when changes exist' do
62
+ before { visit engine_urls.root_path(item_type: 'Entity') }
63
+
64
+ it 'shows a subset of the changes' do
65
+ expect(page).to have_selector('[data-ci-type="version-row"]', count: 6)
66
+ end
67
+ end
68
+ end
69
+
70
+ context 'when getting changes for a specific record' do
71
+ context 'when changes exist' do
72
+ before { visit engine_urls.root_path(item_type: 'Entity', item_id: reimu.id) }
73
+
74
+ it 'shows a subset of the changes' do
75
+ expect(page).to have_selector('[data-ci-type="version-row"]', count: 3)
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ describe 'rolling back changes' do
82
+ context 'when changes exist' do
83
+ context 'when authorized' do
84
+ it 'rollbacks a newly-created record by deleting it' do
85
+ expect(Entity).to exist(reimu.id)
86
+
87
+ put engine_urls.version_path(reimu.versions.first)
88
+
89
+ expect(Entity).not_to exist(reimu.id)
90
+ end
91
+
92
+ it 'rollbacks an edit by reverting to the previous state' do
93
+ reimu.reload
94
+ expect(reimu.status).to eq 'Perfect Cherry Blossom'
95
+
96
+ put engine_urls.version_path(reimu.versions.last)
97
+
98
+ reimu.reload
99
+ expect(reimu.status).to eq 'Phantasmagoria of Dimensional Dream'
100
+ end
101
+
102
+ it 'rollbacks a delete by restoring the record' do
103
+ expect(Entity.exists?(flanchan_id)).to eq false
104
+
105
+ put engine_urls.version_path(PaperTrail::Version.where(item_id: flanchan_id, item_type: 'Entity').last)
106
+
107
+ found = Entity.find(flanchan_id)
108
+ expect(found.status).to eq 'The Embodiment of Scarlet Devil'
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
data/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "allowSyntheticDefaultImports": true,
4
+ "downlevelIteration": true,
5
+ "outDir": "./javascript/",
6
+ "noImplicitAny": true,
7
+ "module": "es6",
8
+ "target": "es5",
9
+ "jsx": "react",
10
+ "allowJs": true,
11
+ "moduleResolution": "node"
12
+ }
13
+ }
data/webpack.config.js ADDED
@@ -0,0 +1,26 @@
1
+ const path = require('path')
2
+
3
+ module.exports = {
4
+ entry: './javascript/src/index.ts',
5
+ mode: 'production',
6
+ module: {
7
+ rules: [
8
+ {
9
+ rules: [
10
+ {
11
+ test: /\.tsx?$/,
12
+ use: 'ts-loader',
13
+ exclude: /node_modules/,
14
+ },
15
+ ],
16
+ }
17
+ ]
18
+ },
19
+ resolve: {
20
+ extensions: ['.tsx', '.ts', '.js'],
21
+ },
22
+ output: {
23
+ filename: 'compiled.js',
24
+ path: path.resolve(__dirname, 'javascript'),
25
+ },
26
+ }
metadata ADDED
@@ -0,0 +1,251 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: paper_trail_viewer
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Janosch Müller
8
+ - Igal Koshevoy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2022-03-26 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: kaminari
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: paper_trail
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '11.1'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '11.1'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rails
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '6.0'
49
+ - - "<"
50
+ - !ruby/object:Gem::Version
51
+ version: '8.0'
52
+ type: :runtime
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '6.0'
59
+ - - "<"
60
+ - !ruby/object:Gem::Version
61
+ version: '8.0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: appraisal
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ - !ruby/object:Gem::Dependency
77
+ name: capybara
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ - !ruby/object:Gem::Dependency
91
+ name: factory_bot_rails
92
+ requirement: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '6.0'
97
+ type: :development
98
+ prerelease: false
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '6.0'
104
+ - !ruby/object:Gem::Dependency
105
+ name: puma
106
+ requirement: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '5.0'
111
+ type: :development
112
+ prerelease: false
113
+ version_requirements: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '5.0'
118
+ - !ruby/object:Gem::Dependency
119
+ name: rake
120
+ requirement: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '13.0'
125
+ type: :development
126
+ prerelease: false
127
+ version_requirements: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '13.0'
132
+ - !ruby/object:Gem::Dependency
133
+ name: rspec-rails
134
+ requirement: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '5.0'
139
+ type: :development
140
+ prerelease: false
141
+ version_requirements: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '5.0'
146
+ - !ruby/object:Gem::Dependency
147
+ name: sqlite3
148
+ requirement: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: 1.3.6
153
+ type: :development
154
+ prerelease: false
155
+ version_requirements: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: 1.3.6
160
+ - !ruby/object:Gem::Dependency
161
+ name: webdrivers
162
+ requirement: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '5.0'
167
+ type: :development
168
+ prerelease: false
169
+ version_requirements: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '5.0'
174
+ description: Browse, view and revert changes to records when using Ruby on Rails and
175
+ the `paper_trail` gem.
176
+ email:
177
+ executables:
178
+ - setup
179
+ extensions: []
180
+ extra_rdoc_files: []
181
+ files:
182
+ - ".github/workflows/test.yml"
183
+ - ".gitignore"
184
+ - Appraisals
185
+ - CHANGELOG.md
186
+ - Gemfile
187
+ - LICENSE.txt
188
+ - README.md
189
+ - Rakefile
190
+ - app/controllers/paper_trail_viewer/js_controller.rb
191
+ - app/controllers/paper_trail_viewer/versions_controller.rb
192
+ - app/controllers/paper_trail_viewer/viewer_controller.rb
193
+ - app/views/paper_trail_viewer/viewer/index.html.erb
194
+ - bin/setup
195
+ - config/routes.rb
196
+ - gemfiles/rails_6.0_paper_trail_11.1.gemfile
197
+ - gemfiles/rails_6.0_paper_trail_12.2.gemfile
198
+ - gemfiles/rails_7.0_paper_trail_12.2.gemfile
199
+ - javascript/compiled.js
200
+ - javascript/src/app.tsx
201
+ - javascript/src/components/change_diff.tsx
202
+ - javascript/src/components/config_modal.tsx
203
+ - javascript/src/components/controls.tsx
204
+ - javascript/src/components/full_object_modal.tsx
205
+ - javascript/src/components/index.ts
206
+ - javascript/src/components/modal.tsx
207
+ - javascript/src/components/pagination.tsx
208
+ - javascript/src/components/versions_list.tsx
209
+ - javascript/src/index.ts
210
+ - javascript/src/types.ts
211
+ - lib/paper_trail_viewer.rb
212
+ - lib/paper_trail_viewer/data_source/active_record.rb
213
+ - lib/paper_trail_viewer/data_source/bigquery.rb
214
+ - lib/paper_trail_viewer/engine.rb
215
+ - lib/paper_trail_viewer/version.rb
216
+ - package.json
217
+ - paper_trail_viewer.gemspec
218
+ - spec/app_template.rb
219
+ - spec/rails_helper.rb
220
+ - spec/support/factories.rb
221
+ - spec/system/paper_trail_viewer_spec.rb
222
+ - tsconfig.json
223
+ - webpack.config.js
224
+ homepage: https://github.com/jaynetics/paper_trail_viewer
225
+ licenses:
226
+ - MIT
227
+ metadata: {}
228
+ post_install_message:
229
+ rdoc_options: []
230
+ require_paths:
231
+ - lib
232
+ required_ruby_version: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: '2.7'
237
+ required_rubygems_version: !ruby/object:Gem::Requirement
238
+ requirements:
239
+ - - ">="
240
+ - !ruby/object:Gem::Version
241
+ version: '0'
242
+ requirements: []
243
+ rubygems_version: 3.3.3
244
+ signing_key:
245
+ specification_version: 4
246
+ summary: A user interface for `paper_trail` versioning data in Ruby on Rails applications.
247
+ test_files:
248
+ - spec/app_template.rb
249
+ - spec/rails_helper.rb
250
+ - spec/support/factories.rb
251
+ - spec/system/paper_trail_viewer_spec.rb