cm-admin 0.7.6 → 0.7.8
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/Gemfile +6 -5
- data/Gemfile.lock +41 -20
- data/app/assets/stylesheets/cm_admin/base/table.scss +1 -1
- data/app/controllers/cm_admin/resource_controller.rb +7 -4
- data/app/javascript/packs/cm_admin/exports.js +0 -1
- data/app/views/cm_admin/main/_associated_table.html.slim +3 -0
- data/app/views/cm_admin/main/_table.html.slim +1 -1
- data/app/views/cm_admin/main/_tabs.html.slim +1 -1
- data/cm_admin.gemspec +2 -2
- data/lib/cm_admin/models/form_field.rb +1 -1
- data/lib/cm_admin/version.rb +1 -1
- data/lib/cm_admin/view_helpers/form_field_helper.rb +6 -4
- data/lib/cm_admin/view_helpers.rb +18 -18
- data/lib/generators/cm_admin/add_graphql_generator.rb +25 -0
- data/lib/generators/cm_admin/templates/concerns/attachable.rb +63 -0
- data/lib/generators/cm_admin/templates/concerns/filtered_list.rb +22 -0
- data/lib/generators/cm_admin/templates/concerns/paginator.rb +12 -0
- data/lib/generators/cm_admin/templates/constants.rb +3 -0
- data/lib/generators/cm_admin/templates/exceptions/base_exception.rb +9 -0
- data/lib/generators/cm_admin/templates/graphql/enums/base/sort_column.rb +7 -0
- data/lib/generators/cm_admin/templates/graphql/enums/base/sort_direction.rb +8 -0
- data/lib/generators/cm_admin/templates/graphql/graphql_schema.rb +55 -0
- data/lib/generators/cm_admin/templates/graphql/inputs/base/attachment.rb +15 -0
- data/lib/generators/cm_admin/templates/graphql/inputs/base/filter.rb +15 -0
- data/lib/generators/cm_admin/templates/graphql/inputs/base/paging.rb +15 -0
- data/lib/generators/cm_admin/templates/graphql/inputs/base/sort.rb +15 -0
- data/lib/generators/cm_admin/templates/graphql/mutations/base_mutation.rb +8 -0
- data/lib/generators/cm_admin/templates/graphql/objects/base/attachment_type.rb +31 -0
- data/lib/generators/cm_admin/templates/graphql/objects/base/paging_type.rb +9 -0
- data/lib/generators/cm_admin/templates/graphql/queries/base_query.rb +4 -0
- data/package-lock.json +1674 -1233
- data/package.json +2 -2
- data/tmp/cache/webpacker/last-compilation-digest-development +1 -1
- data/yarn.lock +393 -1331
- metadata +29 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a03ed809475bd54b0365e020bb5d3ff1be6a2c16d2e2a2bf82b175af9ee26b8
|
4
|
+
data.tar.gz: 454ea27724b9f6e8c6297a81af181ce9e365fba0bbd777c68c9c1fdb6d5f47d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6b7f5d92c8e26d67b3587fe3c1e0b674bf3bb49aca01d958495f1093b369ab1993383eda2ae744587dea723a8534a7bc3d4d51ef94cd0f6c9aa35bc2186525a
|
7
|
+
data.tar.gz: 2ccc66f2c64f05e584a4a33da9b0117868272d039e984e8822a90c6957fa48c2654ca3f9ad8b1a2a631a87f50bcd2c761de5d84e4f50b30915b1ad24f2c291ec
|
data/Gemfile
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
gem 'pagy', '~> 4.11.0'
|
4
|
-
gem 'slim'
|
5
|
-
gem "rake", "~> 12.0"
|
6
|
-
gem "rspec", "~> 3.0"
|
7
3
|
gem 'cocoon'
|
4
|
+
gem 'pagy', '~> 4.11.0'
|
8
5
|
gem 'pundit'
|
6
|
+
gem 'rake', '~> 12.0'
|
7
|
+
gem 'rspec', '~> 3.0'
|
8
|
+
gem 'rubocop'
|
9
|
+
gem 'slim'
|
9
10
|
|
10
11
|
# Specify your gem's dependencies in cm_admin.gemspec
|
11
12
|
gemspec
|
data/Gemfile.lock
CHANGED
@@ -1,52 +1,53 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cm-admin (0.7.
|
5
|
-
|
4
|
+
cm-admin (0.7.7)
|
5
|
+
caxlsx_rails
|
6
6
|
cocoon (~> 1.2.15)
|
7
7
|
local_time (~> 2.1.0)
|
8
8
|
pagy (~> 4.11.0)
|
9
9
|
pundit (~> 2.2.0)
|
10
10
|
slim (~> 4.1.0)
|
11
|
-
webpacker (~> 5.
|
11
|
+
webpacker (~> 5.4.3)
|
12
12
|
|
13
13
|
GEM
|
14
14
|
remote: https://rubygems.org/
|
15
15
|
specs:
|
16
|
-
actionpack (7.0.
|
17
|
-
actionview (= 7.0.
|
18
|
-
activesupport (= 7.0.
|
16
|
+
actionpack (7.0.3.1)
|
17
|
+
actionview (= 7.0.3.1)
|
18
|
+
activesupport (= 7.0.3.1)
|
19
19
|
rack (~> 2.0, >= 2.2.0)
|
20
20
|
rack-test (>= 0.6.3)
|
21
21
|
rails-dom-testing (~> 2.0)
|
22
22
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
23
|
-
actionview (7.0.
|
24
|
-
activesupport (= 7.0.
|
23
|
+
actionview (7.0.3.1)
|
24
|
+
activesupport (= 7.0.3.1)
|
25
25
|
builder (~> 3.1)
|
26
26
|
erubi (~> 1.4)
|
27
27
|
rails-dom-testing (~> 2.0)
|
28
28
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
29
|
-
activesupport (7.0.
|
29
|
+
activesupport (7.0.3.1)
|
30
30
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
31
31
|
i18n (>= 1.6, < 2)
|
32
32
|
minitest (>= 5.1)
|
33
33
|
tzinfo (~> 2.0)
|
34
|
-
|
35
|
-
actionpack (>= 3.1)
|
36
|
-
caxlsx (>= 3.0)
|
34
|
+
ast (2.4.2)
|
37
35
|
builder (3.2.4)
|
38
36
|
caxlsx (3.2.0)
|
39
37
|
htmlentities (~> 4.3, >= 4.3.4)
|
40
38
|
marcel (~> 1.0)
|
41
39
|
nokogiri (~> 1.10, >= 1.10.4)
|
42
40
|
rubyzip (>= 1.3.0, < 3)
|
41
|
+
caxlsx_rails (0.6.3)
|
42
|
+
actionpack (>= 3.1)
|
43
|
+
caxlsx (>= 3.0)
|
43
44
|
cocoon (1.2.15)
|
44
|
-
concurrent-ruby (1.1.
|
45
|
+
concurrent-ruby (1.1.10)
|
45
46
|
crass (1.0.6)
|
46
47
|
diff-lcs (1.4.4)
|
47
48
|
erubi (1.10.0)
|
48
49
|
htmlentities (4.3.4)
|
49
|
-
i18n (1.
|
50
|
+
i18n (1.11.0)
|
50
51
|
concurrent-ruby (~> 1.0)
|
51
52
|
local_time (2.1.0)
|
52
53
|
loofah (2.18.0)
|
@@ -55,11 +56,14 @@ GEM
|
|
55
56
|
marcel (1.0.2)
|
56
57
|
method_source (1.0.0)
|
57
58
|
mini_portile2 (2.8.0)
|
58
|
-
minitest (5.
|
59
|
-
nokogiri (1.13.
|
59
|
+
minitest (5.16.2)
|
60
|
+
nokogiri (1.13.7)
|
60
61
|
mini_portile2 (~> 2.8.0)
|
61
62
|
racc (~> 1.4)
|
62
63
|
pagy (4.11.0)
|
64
|
+
parallel (1.22.1)
|
65
|
+
parser (3.1.2.0)
|
66
|
+
ast (~> 2.4.1)
|
63
67
|
pundit (2.2.0)
|
64
68
|
activesupport (>= 3.0.0)
|
65
69
|
racc (1.6.0)
|
@@ -73,14 +77,17 @@ GEM
|
|
73
77
|
nokogiri (>= 1.6)
|
74
78
|
rails-html-sanitizer (1.4.3)
|
75
79
|
loofah (~> 2.3)
|
76
|
-
railties (7.0.
|
77
|
-
actionpack (= 7.0.
|
78
|
-
activesupport (= 7.0.
|
80
|
+
railties (7.0.3.1)
|
81
|
+
actionpack (= 7.0.3.1)
|
82
|
+
activesupport (= 7.0.3.1)
|
79
83
|
method_source
|
80
84
|
rake (>= 12.2)
|
81
85
|
thor (~> 1.0)
|
82
86
|
zeitwerk (~> 2.5)
|
87
|
+
rainbow (3.1.1)
|
83
88
|
rake (12.3.3)
|
89
|
+
regexp_parser (2.5.0)
|
90
|
+
rexml (3.2.5)
|
84
91
|
rspec (3.10.0)
|
85
92
|
rspec-core (~> 3.10.0)
|
86
93
|
rspec-expectations (~> 3.10.0)
|
@@ -94,6 +101,18 @@ GEM
|
|
94
101
|
diff-lcs (>= 1.2.0, < 2.0)
|
95
102
|
rspec-support (~> 3.10.0)
|
96
103
|
rspec-support (3.10.2)
|
104
|
+
rubocop (1.30.1)
|
105
|
+
parallel (~> 1.10)
|
106
|
+
parser (>= 3.1.0.0)
|
107
|
+
rainbow (>= 2.2.2, < 4.0)
|
108
|
+
regexp_parser (>= 1.8, < 3.0)
|
109
|
+
rexml (>= 3.2.5, < 4.0)
|
110
|
+
rubocop-ast (>= 1.18.0, < 2.0)
|
111
|
+
ruby-progressbar (~> 1.7)
|
112
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
113
|
+
rubocop-ast (1.18.0)
|
114
|
+
parser (>= 3.1.1.0)
|
115
|
+
ruby-progressbar (1.11.0)
|
97
116
|
rubyzip (2.3.2)
|
98
117
|
semantic_range (3.0.0)
|
99
118
|
slim (4.1.0)
|
@@ -104,7 +123,8 @@ GEM
|
|
104
123
|
tilt (2.0.10)
|
105
124
|
tzinfo (2.0.4)
|
106
125
|
concurrent-ruby (~> 1.0)
|
107
|
-
|
126
|
+
unicode-display_width (2.1.0)
|
127
|
+
webpacker (5.4.3)
|
108
128
|
activesupport (>= 5.2)
|
109
129
|
rack-proxy (>= 0.6.1)
|
110
130
|
railties (>= 5.2)
|
@@ -121,6 +141,7 @@ DEPENDENCIES
|
|
121
141
|
pundit
|
122
142
|
rake (~> 12.0)
|
123
143
|
rspec (~> 3.0)
|
144
|
+
rubocop
|
124
145
|
slim
|
125
146
|
|
126
147
|
BUNDLED WITH
|
@@ -77,7 +77,11 @@ module CmAdmin
|
|
77
77
|
respond_to do |format|
|
78
78
|
if @action.action_type == :custom
|
79
79
|
if @action.child_records
|
80
|
-
|
80
|
+
if request.xhr?
|
81
|
+
format.html { render partial: '/cm_admin/main/associated_table' }
|
82
|
+
else
|
83
|
+
format.html { render @action.layout }
|
84
|
+
end
|
81
85
|
elsif @action.display_type == :page
|
82
86
|
data = @action.parent == "index" ? @ar_object.data : @ar_object
|
83
87
|
format.html { render @action.partial }
|
@@ -137,7 +141,7 @@ module CmAdmin
|
|
137
141
|
child_records = @ar_object.send(@current_action.child_records)
|
138
142
|
@associated_model = CmAdmin::Model.find_by(name: @model.ar_model.reflect_on_association(@current_action.child_records).klass.name)
|
139
143
|
if child_records.is_a? ActiveRecord::Relation
|
140
|
-
@associated_ar_object = filter_by(params, child_records)
|
144
|
+
@associated_ar_object = filter_by(params, child_records, @associated_model.filter_params(params))
|
141
145
|
else
|
142
146
|
@associated_ar_object = child_records
|
143
147
|
end
|
@@ -155,8 +159,7 @@ module CmAdmin
|
|
155
159
|
|
156
160
|
records = "CmAdmin::#{@model.name}Policy::Scope".constantize.new(Current.user, @model.name.constantize).resolve if records.nil?
|
157
161
|
records = records.order("#{@current_action.sort_column} #{@current_action.sort_direction}")
|
158
|
-
|
159
|
-
final_data = CmAdmin::Models::Filter.filtered_data(filter_params, records, @model.filters)
|
162
|
+
final_data = CmAdmin::Models::Filter.filtered_data(filter_params, records, @associated_model ? @associated_model.filters : @model.filters)
|
160
163
|
pagy, records = pagy(final_data)
|
161
164
|
filtered_result.data = records
|
162
165
|
filtered_result.pagy = pagy
|
@@ -1,6 +1,5 @@
|
|
1
1
|
$(document).on('click', '.export-to-file-btn', function(e) {
|
2
2
|
e.preventDefault();
|
3
3
|
query_param = window.location.href.split("?")[1]
|
4
|
-
$('#export-to-file-form').get(0).setAttribute('action', '/cm_admin/export_to_file.js?' + query_param);
|
5
4
|
$("#export-to-file-form").submit();
|
6
5
|
});
|
@@ -1,5 +1,8 @@
|
|
1
1
|
.admin-table-index
|
2
2
|
.table-top
|
3
|
+
- if @associated_model.filters.present? && @action.partial.nil?
|
4
|
+
.index-page__filters
|
5
|
+
== render partial: 'cm_admin/main/filters', locals: { filters: @associated_model.filters }
|
3
6
|
p.table-top__total-count = "#{@associated_ar_object.pagy.count} #{@action.child_records.to_s.gsub('_', ' ')} found"
|
4
7
|
.table-top__column-action
|
5
8
|
- if @associated_model && @associated_model.available_actions.map(&:name).include?('new')
|
@@ -27,7 +27,7 @@
|
|
27
27
|
td.text-ellipsis
|
28
28
|
span class="#{column.field_type.to_s} #{column.cm_css_class} "
|
29
29
|
- if index == 0
|
30
|
-
= link_to ar_object.send(column.field_name), "
|
30
|
+
= link_to ar_object.send(column.field_name), cm_admin.send("#{ar_object.model_name.singular}_show_path", ar_object.id)
|
31
31
|
- else
|
32
32
|
= show_field_value(ar_object, column)
|
33
33
|
- if column.field_type == :drawer
|
@@ -4,4 +4,4 @@ ul.nav.nav-pills
|
|
4
4
|
- if nav_item.custom_action.empty? || (nav_item.custom_action.present? && policy([:cm_admin, @model.name.classify.constantize]).send(:"#{nav_item.custom_action}?"))
|
5
5
|
li.nav-item
|
6
6
|
- nav_item_action_name = nav_item.custom_action.present? ? nav_item.custom_action : 'show'
|
7
|
-
= link_to nav_item.nav_item_name.to_s.titleize, "
|
7
|
+
= link_to nav_item.nav_item_name.to_s.titleize, cm_admin.send("#{@ar_object.model_name.singular}_#{nav_item_action_name}_path", @ar_object.id), class: "nav-link #{ nav_item_action_name == action_name ? 'active' : ''}"
|
data/cm_admin.gemspec
CHANGED
@@ -26,11 +26,11 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.bindir = "exe"
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ["lib"]
|
29
|
-
spec.add_runtime_dependency '
|
29
|
+
spec.add_runtime_dependency 'caxlsx_rails'
|
30
30
|
spec.add_runtime_dependency 'cocoon', '~> 1.2.15'
|
31
31
|
spec.add_runtime_dependency 'local_time', '~> 2.1.0'
|
32
32
|
spec.add_runtime_dependency 'pagy', '~> 4.11.0'
|
33
33
|
spec.add_runtime_dependency 'pundit', '~> 2.2.0'
|
34
34
|
spec.add_runtime_dependency 'slim', '~> 4.1.0'
|
35
|
-
spec.add_runtime_dependency 'webpacker', '~> 5.
|
35
|
+
spec.add_runtime_dependency 'webpacker', '~> 5.4.3'
|
36
36
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module CmAdmin
|
2
2
|
module Models
|
3
3
|
class FormField
|
4
|
-
attr_accessor :field_name, :label, :header, :input_type, :collection, :
|
4
|
+
attr_accessor :field_name, :label, :header, :input_type, :collection, :disabled, :helper_method
|
5
5
|
VALID_INPUT_TYPES = [:integer, :decimal, :string, :single_select, :multi_select, :date, :date_time, :text, :single_file_upload, :multi_file_upload, :hidden, :rich_text].freeze
|
6
6
|
|
7
7
|
def initialize(field_name, input_type, attributes = {})
|
data/lib/cm_admin/version.rb
CHANGED
@@ -2,7 +2,7 @@ module CmAdmin
|
|
2
2
|
module ViewHelpers
|
3
3
|
module FormFieldHelper
|
4
4
|
def input_field_for_column(f, field)
|
5
|
-
value = field.
|
5
|
+
value = field.helper_method ? send(field.helper_method) : f.object.send(field.field_name)
|
6
6
|
is_required = f.object._validators[field.field_name].map(&:kind).include?(:presence)
|
7
7
|
required_class = is_required ? 'required' : ''
|
8
8
|
case field.input_type
|
@@ -29,13 +29,15 @@ module CmAdmin
|
|
29
29
|
when :multi_file_upload
|
30
30
|
return f.file_field field.field_name, multiple: true, class: "normal-input #{required_class}"
|
31
31
|
when :hidden
|
32
|
-
return f.hidden_field field.field_name, value:
|
32
|
+
return f.hidden_field field.field_name, value: value
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
# Refactor: Collection argument can be removed.
|
37
|
+
# helper_method argument will accept a method where value can be passed.
|
36
38
|
def select_collection_value(field)
|
37
|
-
if field.
|
38
|
-
collection = send(field.
|
39
|
+
if field.helper_method
|
40
|
+
collection = send(field.helper_method)
|
39
41
|
elsif field.collection
|
40
42
|
collection = field.collection
|
41
43
|
else
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module CmAdmin
|
2
2
|
module ViewHelpers
|
3
|
-
Dir[File.expand_path(
|
3
|
+
Dir[File.expand_path('view_helpers', __dir__) + '/*.rb'].each { |f| require f }
|
4
4
|
|
5
5
|
include ActionDropdownHelper
|
6
6
|
include FieldDisplayHelper
|
@@ -14,17 +14,17 @@ module CmAdmin
|
|
14
14
|
include ActionView::Helpers::FormTagHelper
|
15
15
|
include ActionView::Helpers::TagHelper
|
16
16
|
|
17
|
-
def exportable(
|
18
|
-
tag.a
|
17
|
+
def exportable(_klass, html_class: [])
|
18
|
+
tag.a 'Export as excel', class: html_class.append('filter-btn modal-btn mr-2'), data: { toggle: 'modal', target: '#exportmodal' } do
|
19
19
|
concat tag.i class: 'fa fa-download'
|
20
|
-
concat tag.span
|
20
|
+
concat tag.span ' Export'
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
def column_pop_up(klass, required_filters = nil)
|
25
|
-
tag.div class:
|
26
|
-
tag.div class:
|
27
|
-
tag.div class:
|
25
|
+
tag.div class: 'modal fade form-modal', id: 'exportmodal', role: 'dialog', aria: { labelledby: 'exportModal' } do
|
26
|
+
tag.div class: 'modal-dialog modal-lg', role: 'document' do
|
27
|
+
tag.div class: 'modal-content' do
|
28
28
|
concat pop_ups(klass, required_filters)
|
29
29
|
end
|
30
30
|
end
|
@@ -39,17 +39,17 @@ module CmAdmin
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def pop_up_header
|
42
|
-
tag.div class:
|
43
|
-
tag.button type:
|
44
|
-
tag.span
|
42
|
+
tag.div class: 'modal-header' do
|
43
|
+
tag.button type: 'button', class: 'close', data: { dismiss: 'modal' }, aria: { label: 'Close' } do
|
44
|
+
tag.span 'X', aria: { hidden: 'true' }
|
45
45
|
end
|
46
|
-
tag.h4
|
46
|
+
tag.h4 'Select columns to export', class: 'modal-title', id: 'exportModal'
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
def pop_up_body(klass,
|
51
|
-
tag.div class:
|
52
|
-
form_tag
|
50
|
+
def pop_up_body(klass, _required_filters)
|
51
|
+
tag.div class: 'modal-body' do
|
52
|
+
form_tag cm_admin.send('export_to_file_path'), id: 'export-to-file-form', style: 'width: 100%;', class: 'cm-admin-csv-export-form' do
|
53
53
|
concat hidden_field_tag 'class_name', klass.name.to_s, id: 'export-to-file-klass'
|
54
54
|
concat checkbox_row(klass)
|
55
55
|
concat tag.hr
|
@@ -59,7 +59,7 @@ module CmAdmin
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def checkbox_row(klass)
|
62
|
-
tag.div class:
|
62
|
+
tag.div class: 'row' do
|
63
63
|
CmAdmin::Models::Export.exportable_columns(klass).each do |column_path|
|
64
64
|
concat create_checkbox(column_path)
|
65
65
|
end
|
@@ -67,9 +67,9 @@ module CmAdmin
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def create_checkbox(column_path)
|
70
|
-
tag.div class:
|
71
|
-
concat check_box_tag
|
72
|
-
concat "
|
70
|
+
tag.div class: 'col-md-4' do
|
71
|
+
concat check_box_tag 'columns[]', column_path, id: column_path.to_s.gsub('/', '-')
|
72
|
+
concat " #{column_path.to_s.gsub('/', '_').humanize}"
|
73
73
|
end
|
74
74
|
end
|
75
75
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module CmAdmin
|
4
|
+
module Generators
|
5
|
+
class AddGraphqlGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path('templates', __dir__)
|
7
|
+
|
8
|
+
def add_graphql
|
9
|
+
gem 'graphql'
|
10
|
+
gem 'graphql-errors'
|
11
|
+
gem 'graphql-rails_logger'
|
12
|
+
generate 'graphql:install'
|
13
|
+
template 'graphql/graphql_schema.rb', "app/graphql/#{Rails.application.class.module_parent_name.underscore}_schema.rb"
|
14
|
+
directory 'graphql/inputs/base', 'app/graphql/types/inputs/base'
|
15
|
+
directory 'graphql/enums/base', 'app/graphql/types/enums/base'
|
16
|
+
directory 'graphql/objects/base', 'app/graphql/types/objects/base'
|
17
|
+
directory 'concerns', 'app/models/concerns'
|
18
|
+
copy_file 'graphql/mutations/base_mutation.rb', 'app/graphql/mutations/base_mutation.rb'
|
19
|
+
copy_file 'graphql/queries/base_query.rb', 'app/graphql/queries/base_query.rb'
|
20
|
+
copy_file 'exceptions/base_exception.rb', 'app/exceptions/base_exception.rb'
|
21
|
+
copy_file 'constants.rb', 'config/initializers/constants.rb'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Attachable
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
end
|
6
|
+
|
7
|
+
def save_with_attachments
|
8
|
+
save!
|
9
|
+
save_attachment
|
10
|
+
end
|
11
|
+
|
12
|
+
def update!(args)
|
13
|
+
add_accessors_for_attachment_types
|
14
|
+
super
|
15
|
+
save_attachment
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(args)
|
19
|
+
add_accessors_for_attachment_types
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def save_attachment
|
24
|
+
self.class.attachment_types.each do |attachment_type|
|
25
|
+
next if send("#{attachment_type}_file").blank?
|
26
|
+
|
27
|
+
arr = []
|
28
|
+
if send("#{attachment_type}_file").class.eql?(Array)
|
29
|
+
arr = send("#{attachment_type}_file")
|
30
|
+
else
|
31
|
+
arr << send("#{attachment_type}_file")
|
32
|
+
end
|
33
|
+
arr.each do |x|
|
34
|
+
regexp = %r{\Adata:([-\w]+\/[-\w\+\.]+)?;base64,(.*)}m
|
35
|
+
data_uri_parts = x[:content].match(regexp) || []
|
36
|
+
decoded_data = Base64.decode64(data_uri_parts[2])
|
37
|
+
filename = x[:filename]
|
38
|
+
filepath = "#{Rails.root}/tmp/#{filename}"
|
39
|
+
File.open(filepath, 'wb') do |f|
|
40
|
+
f.write(decoded_data)
|
41
|
+
end
|
42
|
+
send(attachment_type.to_s).attach(io: File.open(filepath), filename: filename, content_type: data_uri_parts[1])
|
43
|
+
File.delete(filepath)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def attached_url(attachment_type)
|
49
|
+
if send(attachment_type.to_s).attached? && send(attachment_type.to_s).class == ActiveStorage::Attached::One
|
50
|
+
Rails.application.routes.url_helpers.rails_blob_url(send(attachment_type.to_s))
|
51
|
+
elsif send(attachment_type.to_s).attached? && send(attachment_type.to_s).class == ActiveStorage::Attached::Many
|
52
|
+
send(attachment_type.to_s)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def add_accessors_for_attachment_types
|
59
|
+
self.class.attachment_types.each do |attachment_type|
|
60
|
+
singleton_class.class_eval { attr_accessor "#{attachment_type}_file" }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class FilteredList
|
2
|
+
attr_reader :data, :facets, :paging
|
3
|
+
|
4
|
+
def initialize(paginated_list)
|
5
|
+
self.data = paginated_list[:list]
|
6
|
+
self.paging = paginated_list
|
7
|
+
end
|
8
|
+
|
9
|
+
def data=(data)
|
10
|
+
@data = []
|
11
|
+
@data = data if data.present?
|
12
|
+
end
|
13
|
+
|
14
|
+
def paging=(paginated_list)
|
15
|
+
@paging = {
|
16
|
+
total_items: paginated_list[:list].total_count,
|
17
|
+
current_page: paginated_list[:list].current_page,
|
18
|
+
total_pages: paginated_list[:list].total_pages,
|
19
|
+
total_count: paginated_list[:total_count]
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Paginator
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
module ClassMethods
|
4
|
+
def list(per_page = DEFAULT_PER_PAGE, page = nil, _filter_params = nil, total_count = nil)
|
5
|
+
paginated_list = {}
|
6
|
+
per_page = DEFAULT_PER_PAGE if per_page == 0
|
7
|
+
paginated_list[:list] = self.page(page || 1).per(per_page)
|
8
|
+
paginated_list[:total_count] = total_count
|
9
|
+
FilteredList.new(paginated_list)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class <%= Rails.application.class.module_parent_name %>Schema < GraphQL::Schema
|
2
|
+
mutation(Types::MutationType)
|
3
|
+
query(Types::QueryType)
|
4
|
+
|
5
|
+
# Union and Interface Resolution
|
6
|
+
def self.resolve_type(abstract_type, obj, ctx)
|
7
|
+
# TODO: Implement this function
|
8
|
+
# to return the correct object type for `obj`
|
9
|
+
raise(GraphQL::RequiredImplementationMissingError)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Relay-style Object Identification:
|
13
|
+
|
14
|
+
# Return a string UUID for `object`
|
15
|
+
def self.id_from_object(object, type_definition, query_ctx)
|
16
|
+
# Here's a simple implementation which:
|
17
|
+
# - joins the type name & object.id
|
18
|
+
# - encodes it with base64:
|
19
|
+
# GraphQL::Schema::UniqueWithinType.encode(type_definition.name, object.id)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Given a string UUID, find the object
|
23
|
+
def self.object_from_id(id, query_ctx)
|
24
|
+
# For example, to decode the UUIDs generated above:
|
25
|
+
# type_name, item_id = GraphQL::Schema::UniqueWithinType.decode(id)
|
26
|
+
#
|
27
|
+
# Then, based on `type_name` and `id`
|
28
|
+
# find an object in your application
|
29
|
+
# ...
|
30
|
+
end
|
31
|
+
|
32
|
+
rescue_from ActiveRecord::RecordNotFound do |err, obj, args, ctx, field|
|
33
|
+
GraphQL::ExecutionError.new("#{field.type.unwrap.graphql_name} not found", extensions: {code: :unprocessable_entity, sub_code: :record_invalid, message: err.message})
|
34
|
+
end
|
35
|
+
|
36
|
+
rescue_from ActiveRecord::RecordInvalid do |err, obj, args, ctx, field|
|
37
|
+
GraphQL::ExecutionError.new(err.message, extensions: {code: :unprocessable_entity, sub_code: :record_invalid, message: err.message})
|
38
|
+
end
|
39
|
+
|
40
|
+
rescue_from BaseException do |err, obj, args, ctx, field|
|
41
|
+
GraphQL::ExecutionError.new(err.message, extensions: {code: err.code, sub_code: err.sub_code, message: err.message})
|
42
|
+
end
|
43
|
+
|
44
|
+
unless Rails.env.development?
|
45
|
+
rescue_from StandardError do |err, obj, args, ctx, field|
|
46
|
+
rollbar_error = Rollbar.error(err)
|
47
|
+
GraphQL::ExecutionError.new("Internal Server Error", extensions: {code: :internal_server_error, uuid: rollbar_error[:uuid]})
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.unauthorized_object(error)
|
52
|
+
raise Unauthorized, I18n.t("graphql.unauthorized", error_type: error.type.graphql_name)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Types
|
2
|
+
module Inputs
|
3
|
+
module Base
|
4
|
+
class Attachment < Types::BaseInputObject
|
5
|
+
graphql_name 'AttachmentInput'
|
6
|
+
|
7
|
+
description 'Attributes needed to attach a file'
|
8
|
+
|
9
|
+
argument :filename, String, nil, required: true
|
10
|
+
argument :content, String, nil, required: true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Types
|
2
|
+
module Inputs
|
3
|
+
module Base
|
4
|
+
class Filter < Types::BaseInputObject
|
5
|
+
graphql_name 'BaseFilterInput'
|
6
|
+
|
7
|
+
description 'Attributes needed for filtering items'
|
8
|
+
|
9
|
+
argument :ids, [Integer], nil, required: false
|
10
|
+
argument :q, String, nil, required: false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Types
|
2
|
+
module Inputs
|
3
|
+
module Base
|
4
|
+
class Paging < Types::BaseInputObject
|
5
|
+
graphql_name 'PagingInput'
|
6
|
+
|
7
|
+
description 'Attributes needed for paginating list of items'
|
8
|
+
|
9
|
+
argument :page_no, Integer, nil, required: true
|
10
|
+
argument :per_page, Integer, nil, required: false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|