cm-admin 0.7.7 → 0.7.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +6 -5
- data/Gemfile.lock +28 -5
- 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 +1 -1
- 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 +131 -35
- data/yarn.lock +5145 -6202
- metadata +27 -10
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
@@ -2,7 +2,7 @@ PATH
|
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
4
|
cm-admin (0.7.7)
|
5
|
-
|
5
|
+
caxlsx_rails
|
6
6
|
cocoon (~> 1.2.15)
|
7
7
|
local_time (~> 2.1.0)
|
8
8
|
pagy (~> 4.11.0)
|
@@ -31,15 +31,16 @@ GEM
|
|
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
45
|
concurrent-ruby (1.1.10)
|
45
46
|
crass (1.0.6)
|
@@ -54,10 +55,15 @@ GEM
|
|
54
55
|
nokogiri (>= 1.5.9)
|
55
56
|
marcel (1.0.2)
|
56
57
|
method_source (1.0.0)
|
58
|
+
mini_portile2 (2.8.0)
|
57
59
|
minitest (5.16.2)
|
58
|
-
nokogiri (1.13.7
|
60
|
+
nokogiri (1.13.7)
|
61
|
+
mini_portile2 (~> 2.8.0)
|
59
62
|
racc (~> 1.4)
|
60
63
|
pagy (4.11.0)
|
64
|
+
parallel (1.22.1)
|
65
|
+
parser (3.1.2.0)
|
66
|
+
ast (~> 2.4.1)
|
61
67
|
pundit (2.2.0)
|
62
68
|
activesupport (>= 3.0.0)
|
63
69
|
racc (1.6.0)
|
@@ -78,7 +84,10 @@ GEM
|
|
78
84
|
rake (>= 12.2)
|
79
85
|
thor (~> 1.0)
|
80
86
|
zeitwerk (~> 2.5)
|
87
|
+
rainbow (3.1.1)
|
81
88
|
rake (12.3.3)
|
89
|
+
regexp_parser (2.5.0)
|
90
|
+
rexml (3.2.5)
|
82
91
|
rspec (3.10.0)
|
83
92
|
rspec-core (~> 3.10.0)
|
84
93
|
rspec-expectations (~> 3.10.0)
|
@@ -92,6 +101,18 @@ GEM
|
|
92
101
|
diff-lcs (>= 1.2.0, < 2.0)
|
93
102
|
rspec-support (~> 3.10.0)
|
94
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)
|
95
116
|
rubyzip (2.3.2)
|
96
117
|
semantic_range (3.0.0)
|
97
118
|
slim (4.1.0)
|
@@ -102,6 +123,7 @@ GEM
|
|
102
123
|
tilt (2.0.10)
|
103
124
|
tzinfo (2.0.4)
|
104
125
|
concurrent-ruby (~> 1.0)
|
126
|
+
unicode-display_width (2.1.0)
|
105
127
|
webpacker (5.4.3)
|
106
128
|
activesupport (>= 5.2)
|
107
129
|
rack-proxy (>= 0.6.1)
|
@@ -119,6 +141,7 @@ DEPENDENCIES
|
|
119
141
|
pundit
|
120
142
|
rake (~> 12.0)
|
121
143
|
rspec (~> 3.0)
|
144
|
+
rubocop
|
122
145
|
slim
|
123
146
|
|
124
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,7 +26,7 @@ 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'
|
@@ -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
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Types
|
2
|
+
module Inputs
|
3
|
+
module Base
|
4
|
+
class Sort < Types::BaseInputObject
|
5
|
+
graphql_name 'SortInput'
|
6
|
+
|
7
|
+
description 'Attributes needed for sorting the list of items'
|
8
|
+
|
9
|
+
argument :column, Types::Enums::Base::SortColumn, nil, required: true
|
10
|
+
argument :direction, Types::Enums::Base::SortDirection, nil, required: true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Types::Objects::Base
|
2
|
+
class AttachmentType < Types::BaseObject
|
3
|
+
field :id, Int, nil, null: false
|
4
|
+
field :filename, String, nil, null: false
|
5
|
+
field :url, String, nil, null: false
|
6
|
+
|
7
|
+
def id
|
8
|
+
if object.class.eql?(ActiveStorage::Variant)
|
9
|
+
object.blob.id
|
10
|
+
else
|
11
|
+
object.id
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def filename
|
16
|
+
if object.class.eql?(ActiveStorage::Variant)
|
17
|
+
object.blob.filename.to_s + "-" + object.variation.transformations[:resize]
|
18
|
+
else
|
19
|
+
object.filename.to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def url
|
24
|
+
if object.class.eql?(ActiveStorage::Variant)
|
25
|
+
Rails.application.routes.url_helpers.rails_representation_url(object)
|
26
|
+
else
|
27
|
+
object.service_url
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|