paper_trail_viewer 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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