slash_admin 0.1.0 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +38 -12
- data/app/assets/images/slash_admin/favicon.png +0 -0
- data/app/assets/images/slash_admin/logo.png +0 -0
- data/app/assets/javascripts/slash_admin/application.js +33 -25
- data/app/assets/stylesheets/slash_admin/application.scss +271 -146
- data/app/assets/stylesheets/slash_admin/colors.scss +16 -13
- data/app/controllers/slash_admin/models_controller.rb +166 -32
- data/app/controllers/slash_admin/security/sessions_controller.rb +1 -1
- data/app/controllers/slash_admin/selectize_controller.rb +21 -1
- data/app/helpers/slash_admin/application_helper.rb +45 -4
- data/app/helpers/slash_admin/widgets_helper.rb +1 -0
- data/app/views/layouts/slash_admin/application.html.erb +1 -1
- data/app/views/slash_admin/base/_data_belongs_to.html.erb +14 -16
- data/app/views/slash_admin/base/_data_list.html.erb +118 -121
- data/app/views/slash_admin/base/_data_nestable.html.erb +2 -2
- data/app/views/slash_admin/base/_data_new.html.erb +4 -1
- data/app/views/slash_admin/base/_filters.html.erb +63 -55
- data/app/views/slash_admin/base/index.html.erb +3 -3
- data/app/views/slash_admin/custom_fields/_google_map.html.erb +14 -11
- data/app/views/slash_admin/custom_fields/_select.html.erb +5 -1
- data/app/views/slash_admin/custom_fields/_timezone.html.erb +2 -0
- data/app/views/slash_admin/dashboard/widgets/_statistic_progress_tile.html.erb +1 -1
- data/app/views/slash_admin/fields/_belongs_to.html.erb +2 -2
- data/app/views/slash_admin/fields/_carrierwave.html.erb +107 -10
- data/app/views/slash_admin/fields/_has_many.html.erb +2 -2
- data/app/views/slash_admin/fields/_has_one.html.erb +9 -24
- data/app/views/slash_admin/fields/_json.html.erb +1 -1
- data/app/views/slash_admin/fields/_jsonb.html.erb +14 -0
- data/app/views/slash_admin/{custom_fields → fields}/_nested_belongs_to.html.erb +11 -10
- data/app/views/slash_admin/fields/_nested_has_one.html.erb +23 -0
- data/app/views/slash_admin/security/sessions/new.html.erb +6 -3
- data/app/views/slash_admin/shared/_batch_actions.html.erb +1 -1
- data/app/views/slash_admin/shared/_header.html.erb +2 -3
- data/app/views/slash_admin/shared/_menu.html.erb +33 -30
- data/app/views/slash_admin/shared/_new_form_buttons.html.erb +2 -2
- data/config/initializers/validators.rb +4 -0
- data/config/locales/{slash_admin.en.yml → en.yml} +3 -0
- data/config/locales/{slash_admin.fr.yml → fr.yml} +4 -1
- data/lib/batch_translation.rb +1 -1
- data/lib/generators/slash_admin/override_admin/override_admin_generator.rb +1 -0
- data/lib/generators/slash_admin/override_session/templates/session.erb +2 -2
- data/lib/slash_admin.rb +1 -3
- data/lib/slash_admin/version.rb +1 -1
- data/vendor/assets/javascripts/bootstrap-datepicker.fr.min.js +1 -0
- data/vendor/assets/javascripts/bootstrap-datepicker.min.js +8 -0
- data/vendor/assets/stylesheets/bootstrap-datepicker.min.css +7 -0
- metadata +19 -69
@@ -1,17 +1,20 @@
|
|
1
1
|
// Bootstrap override
|
2
|
-
$blue: #
|
3
|
-
$yellow: #
|
4
|
-
$green: #
|
5
|
-
$red: #
|
2
|
+
$blue: #6798ff !default;
|
3
|
+
$yellow: #fad961 !default;
|
4
|
+
$green: #57ca85 !default;
|
5
|
+
$red: #F36265 !default;
|
6
|
+
$pink: #ff3466 !default;
|
6
7
|
|
7
|
-
$
|
8
|
-
$
|
9
|
-
$
|
10
|
-
$
|
8
|
+
$info: #6798ff;
|
9
|
+
$notice: #fad961;
|
10
|
+
$success: #57ca85;
|
11
|
+
$error: #F36265;
|
11
12
|
|
12
|
-
|
13
|
-
$
|
14
|
-
$secondary: #
|
15
|
-
$
|
16
|
-
$
|
13
|
+
$primary: #2e5bff;
|
14
|
+
$blueIcon: #9ddbff;
|
15
|
+
$secondary: #120731;
|
16
|
+
$sidebar: #33375b;
|
17
|
+
$textColor: #c5a6ee;
|
18
|
+
$tertiary: #f8f8fd;
|
19
|
+
$grey: #7985A6;
|
17
20
|
$lightgrey: #e1e5ec;
|
@@ -2,6 +2,7 @@ require 'csv'
|
|
2
2
|
|
3
3
|
module SlashAdmin
|
4
4
|
class ModelsController < SlashAdmin::BaseController
|
5
|
+
skip_before_action :verify_authenticity_token, only: :nestable
|
5
6
|
before_action :handle_internal_default
|
6
7
|
before_action :handle_default
|
7
8
|
before_action :nestable_config
|
@@ -21,7 +22,16 @@ module SlashAdmin
|
|
21
22
|
column = @model_class.arel_table[params[:order_field].to_sym]
|
22
23
|
order = params[:order].downcase
|
23
24
|
if %w(asc desc).include?(order)
|
24
|
-
|
25
|
+
if @models_export.is_a? Array
|
26
|
+
if order == 'asc'
|
27
|
+
@models = @models_export.sort { |m1, m2| m1.send(params[:order_field]) <=> m2.send(params[:order_field]) }
|
28
|
+
else
|
29
|
+
@models = @models_export.sort { |m1, m2| m2.send(params[:order_field]) <=> m1.send(params[:order_field]) }
|
30
|
+
end
|
31
|
+
@models = Kaminari.paginate_array(@models).page(params[:page]).per(params[:per])
|
32
|
+
else
|
33
|
+
@models = @models_export.order(column.send(params[:order].downcase)).page(params[:page]).per(params[:per])
|
34
|
+
end
|
25
35
|
end
|
26
36
|
|
27
37
|
@fields = if @use_export_params
|
@@ -32,8 +42,8 @@ module SlashAdmin
|
|
32
42
|
|
33
43
|
respond_to do |format|
|
34
44
|
format.html
|
35
|
-
format.csv {
|
36
|
-
format.xls { send_data render_to_string, filename: "#{@model_name.
|
45
|
+
format.csv { stream_csv_report }
|
46
|
+
format.xls { send_data render_to_string, filename: "#{@model_class.model_name.plural.upcase}_#{Date.today}.xls" }
|
37
47
|
format.js { @models }
|
38
48
|
end
|
39
49
|
end
|
@@ -44,25 +54,31 @@ module SlashAdmin
|
|
44
54
|
end
|
45
55
|
|
46
56
|
def before_validate_on_create; end
|
57
|
+
def after_save_on_create; end
|
47
58
|
def create
|
48
59
|
authorize! :new, @model_class
|
60
|
+
handle_has_one
|
61
|
+
|
49
62
|
@model = @model_class.new(permit_params)
|
50
63
|
|
51
64
|
before_validate_on_create
|
65
|
+
handle_specific_fields
|
52
66
|
|
53
67
|
if @model.valid?
|
54
68
|
if @model.save!
|
69
|
+
after_save_on_create
|
55
70
|
respond_to do |format|
|
56
71
|
format.html do
|
57
72
|
flash[:success] = t('slash_admin.controller.create.success', model_name: @model_name)
|
58
73
|
redirect_to handle_redirect_after_submit and return
|
59
74
|
end
|
60
|
-
format.js { render json: @model and return }
|
75
|
+
format.js { render json: { id: @model.id, name: helpers.show_object(@model) } and return }
|
61
76
|
end
|
62
77
|
end
|
63
78
|
else
|
64
79
|
flash[:error] = t('slash_admin.controller.create.error', model_name: @model_name)
|
65
80
|
end
|
81
|
+
|
66
82
|
respond_to do |format|
|
67
83
|
format.html { render :new }
|
68
84
|
format.js { render json: { errors: @model.errors.full_messages } }
|
@@ -74,23 +90,30 @@ module SlashAdmin
|
|
74
90
|
@model = @model_class.find(params[:id])
|
75
91
|
end
|
76
92
|
|
77
|
-
def before_validate_on_update; end
|
78
93
|
def update
|
79
94
|
authorize! :edit, @model_class
|
80
95
|
@model = @model_class.find(params[:id])
|
81
96
|
|
97
|
+
handle_has_one
|
98
|
+
|
99
|
+
@model.assign_attributes(permit_params)
|
100
|
+
|
82
101
|
before_validate_on_update
|
102
|
+
handle_specific_fields
|
83
103
|
|
84
|
-
if @model.
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
format
|
104
|
+
if @model.valid?
|
105
|
+
if @model.save!
|
106
|
+
after_save_on_update
|
107
|
+
flash[:success] = t('slash_admin.controller.update.success', model_name: @model_name)
|
108
|
+
respond_to do |format|
|
109
|
+
format.html { redirect_to handle_redirect_after_submit and return }
|
110
|
+
format.js
|
111
|
+
end
|
89
112
|
end
|
90
113
|
else
|
91
114
|
flash[:error] = t('slash_admin.controller.update.error', model_name: @model_name)
|
92
115
|
end
|
93
|
-
render :edit
|
116
|
+
render :edit
|
94
117
|
end
|
95
118
|
|
96
119
|
def show
|
@@ -112,6 +135,49 @@ module SlashAdmin
|
|
112
135
|
end
|
113
136
|
end
|
114
137
|
|
138
|
+
def before_validate_on_update; end
|
139
|
+
def after_save_on_update; end
|
140
|
+
|
141
|
+
def handle_has_one
|
142
|
+
@has_one = {}
|
143
|
+
Array.wrap(update_params + create_params).uniq.each do |p|
|
144
|
+
if helpers.guess_field_type(@model_class.new, p) == 'has_one' && !@model_class.nested_attributes_options.key?(p.to_sym)
|
145
|
+
@has_one[p] = permit_params[p]
|
146
|
+
permit_params.delete(p)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def handle_specific_fields
|
152
|
+
# has_one
|
153
|
+
if @has_one.present?
|
154
|
+
@has_one.each do |k, v|
|
155
|
+
if v.present?
|
156
|
+
@model.send("#{k}=", helpers.class_name_from_association(@model, k).constantize.find(v))
|
157
|
+
else
|
158
|
+
@model.send("#{k}=", nil)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# JSON
|
164
|
+
@model_class.columns_hash.each do |k, v|
|
165
|
+
if permit_params[k].is_a? String
|
166
|
+
if v.type == :json || v.type == :jsonb || helpers.serialized_json_field?(@model_class, k.to_s)
|
167
|
+
begin
|
168
|
+
@model.send("#{k}=", JSON.parse(permit_params[k]))
|
169
|
+
rescue
|
170
|
+
# Handle case when single string passed, we transform it into array to have a valid json
|
171
|
+
json = permit_params[k].split(',').to_json
|
172
|
+
@model.send("#{k}=", JSON.parse(json))
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# Other
|
179
|
+
end
|
180
|
+
|
115
181
|
def nestable
|
116
182
|
unless @is_nestable
|
117
183
|
flash[:error] = t('slash_admin.controller.nestable.error', model_name: @model_name)
|
@@ -135,16 +201,39 @@ module SlashAdmin
|
|
135
201
|
end
|
136
202
|
|
137
203
|
def handle_filtered_search
|
138
|
-
|
204
|
+
if @model_class.respond_to? :translated_attribute_names
|
205
|
+
search = @model_class.with_translations(I18n.locale).all
|
206
|
+
else
|
207
|
+
search = @model_class.all
|
208
|
+
end
|
209
|
+
|
210
|
+
virtual_fields = []
|
139
211
|
|
140
212
|
params[:filters].each do |attr, query|
|
141
213
|
unless query.blank?
|
142
|
-
|
143
|
-
|
214
|
+
attr_type = helpers.guess_field_type(@model_class, attr)
|
215
|
+
if @model_class.respond_to?(:translated_attribute_names) && @model_class.translated_attribute_names.include?(attr.to_sym)
|
216
|
+
attr = "#{@model_class.name.singularize.underscore}_translations.#{attr}"
|
217
|
+
end
|
218
|
+
case attr_type
|
219
|
+
when 'belongs_to'
|
220
|
+
search = search.eager_load(attr.to_s)
|
221
|
+
search = search.where(attr.to_s + '_id IN (' + query.join(',') + ')')
|
222
|
+
when 'has_one'
|
223
|
+
search = search.eager_load(attr.to_s)
|
224
|
+
search = search.where(attr.to_s.pluralize + '.id IN (' + query.join(',') + ')')
|
144
225
|
when 'string', 'text'
|
145
|
-
|
146
|
-
|
147
|
-
|
226
|
+
query.strip! unless query.strip!.nil?
|
227
|
+
attributes = @model_class.new.attributes.keys
|
228
|
+
if !attributes.include?(attr.to_s) && @model_class.method_defined?(attr.to_s)
|
229
|
+
virtual_fields << attr.to_s
|
230
|
+
else
|
231
|
+
begin
|
232
|
+
search = search.where("unaccent(lower(#{attr})) LIKE unaccent(lower(:query))", query: "%#{query}%")
|
233
|
+
rescue
|
234
|
+
search = search.where("lower(#{attr}) LIKE lower(:query)", query: "%#{query}%")
|
235
|
+
end
|
236
|
+
end
|
148
237
|
when 'date', 'datetime'
|
149
238
|
if query.is_a?(String)
|
150
239
|
search = search.where("#{attr} = :query", query: query)
|
@@ -163,12 +252,31 @@ module SlashAdmin
|
|
163
252
|
end
|
164
253
|
end
|
165
254
|
when 'decimal', 'number', 'integer'
|
166
|
-
|
167
|
-
|
255
|
+
if query.instance_of?(ActionController::Parameters)
|
256
|
+
if query['from'].present? || query['to'].present?
|
257
|
+
search = search.where("#{attr} >= :query", query: query['from']) if query['from'].present?
|
258
|
+
search = search.where("#{attr} <= :query", query: query['to']) if query['to'].present?
|
259
|
+
end
|
260
|
+
else
|
261
|
+
if attr_type == 'decimal' || attr_type == 'number'
|
262
|
+
query = query.to_f
|
263
|
+
elsif attr_type == 'integer'
|
264
|
+
query = query.to_i
|
265
|
+
end
|
266
|
+
search = search.where("#{attr} = :query", query: query)
|
267
|
+
end
|
168
268
|
when 'boolean'
|
169
269
|
search = search.where("#{attr} = :query", query: to_boolean(query))
|
170
|
-
|
171
|
-
|
270
|
+
else
|
271
|
+
raise Exception.new("Unable to query for attribute_type : #{attr_type}")
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
params[:filters].each do |attr, query|
|
277
|
+
unless query.blank?
|
278
|
+
if virtual_fields.present? && virtual_fields.include?(attr.to_s)
|
279
|
+
search = search.select { |s| s.send(attr).present? ? s.send(attr).downcase.include?(query.downcase) : nil }
|
172
280
|
end
|
173
281
|
end
|
174
282
|
end
|
@@ -178,14 +286,7 @@ module SlashAdmin
|
|
178
286
|
|
179
287
|
# Export CSV
|
180
288
|
def export_csv(options = {})
|
181
|
-
|
182
|
-
header = @fields.map { |f| @model_class.human_attribute_name(f) }
|
183
|
-
csv << header
|
184
|
-
@models_export.each do |m|
|
185
|
-
csv << m.attributes.values_at(*@fields)
|
186
|
-
end
|
187
|
-
csv
|
188
|
-
end
|
289
|
+
@models_export.to_sql
|
189
290
|
end
|
190
291
|
|
191
292
|
def update_params(options = {})
|
@@ -228,9 +329,9 @@ module SlashAdmin
|
|
228
329
|
def handle_default
|
229
330
|
@title = @model_name.present? ? @model_class.model_name.human(count: 2) : nil
|
230
331
|
@sub_title = nil
|
231
|
-
@per =
|
332
|
+
@per = 20
|
232
333
|
@page = 1
|
233
|
-
@per_values = [
|
334
|
+
@per_values = [20, 30, 50, 100, 150]
|
234
335
|
@use_export_params = false
|
235
336
|
@order_field = :id
|
236
337
|
@order = 'DESC'
|
@@ -312,7 +413,31 @@ module SlashAdmin
|
|
312
413
|
|
313
414
|
# Exclude default params for edit and create
|
314
415
|
def exclude_default_params(params)
|
315
|
-
params - %w(id created_at updated_at slug position)
|
416
|
+
params = params - %w(id created_at updated_at slug position)
|
417
|
+
if @model_class.try(:translated_attribute_names).present?
|
418
|
+
params = params - @model_class.translated_attribute_names.map(&:to_s)
|
419
|
+
end
|
420
|
+
params
|
421
|
+
end
|
422
|
+
|
423
|
+
def stream_file(filename, extension)
|
424
|
+
response.headers['Content-Type'] = 'application/octet-stream'
|
425
|
+
response.headers['Content-Disposition'] = "attachment; filename=#{filename}.#{extension}"
|
426
|
+
|
427
|
+
yield response.stream
|
428
|
+
ensure
|
429
|
+
response.stream.close
|
430
|
+
end
|
431
|
+
|
432
|
+
def stream_csv_report
|
433
|
+
query = @models_export.limit(5000).to_sql
|
434
|
+
query_options = 'WITH CSV HEADER'
|
435
|
+
|
436
|
+
stream_file("#{@model_class.model_name.plural.upcase}_#{Date.today}", 'csv') do |stream|
|
437
|
+
stream_query_rows(query, query_options) do |row_from_db|
|
438
|
+
stream.write row_from_db
|
439
|
+
end
|
440
|
+
end
|
316
441
|
end
|
317
442
|
|
318
443
|
private
|
@@ -321,5 +446,14 @@ module SlashAdmin
|
|
321
446
|
def export_params
|
322
447
|
list_params
|
323
448
|
end
|
449
|
+
|
450
|
+
def stream_query_rows(sql_query, options = 'WITH CSV HEADER')
|
451
|
+
conn = ActiveRecord::Base.connection.raw_connection
|
452
|
+
conn.copy_data "COPY (#{sql_query}) TO STDOUT #{options};" do
|
453
|
+
while row = conn.get_copy_data
|
454
|
+
yield row
|
455
|
+
end
|
456
|
+
end
|
457
|
+
end
|
324
458
|
end
|
325
459
|
end
|
@@ -12,7 +12,7 @@ module SlashAdmin
|
|
12
12
|
admin = Admin.where('username = :value OR lower(email) = lower(:value)', value: params[:admin][:login]).first
|
13
13
|
if admin&.authenticate(params[:admin][:password])
|
14
14
|
session[:admin_id] = admin.id
|
15
|
-
flash[:
|
15
|
+
flash[:success] = 'Vous êtes à présent connecté.'
|
16
16
|
redirect_to slash_admin.dashboard_path
|
17
17
|
else
|
18
18
|
@error_messages = 'Merci de vérifier vos identifiants'
|
@@ -16,20 +16,40 @@ module SlashAdmin
|
|
16
16
|
|
17
17
|
duplicate_for_orwhere = results
|
18
18
|
|
19
|
+
virtual_fields = []
|
20
|
+
|
19
21
|
params[:fields].each_with_index do |f, index|
|
20
22
|
if model_class.respond_to? :translated_attribute_names
|
21
23
|
if model_class.translated_attribute_names.include?(f.to_sym)
|
22
24
|
f = "#{params[:model_class].singularize.underscore}_translations.#{f}"
|
23
25
|
end
|
26
|
+
else
|
27
|
+
unless model_class.column_names.include?(f) || model_class.respond_to?(f)
|
28
|
+
raise Exception.new("Unable to find attribute: #{f} in model_column: #{model_class}, you may need to override autocomplete_params in you target's model controller")
|
29
|
+
end
|
24
30
|
end
|
25
31
|
|
26
32
|
if index == 0
|
27
|
-
|
33
|
+
if model_class.column_names.include?(f)
|
34
|
+
results = results.where("lower(#{f}) LIKE lower(:query)", query: "%#{params[:q]}%")
|
35
|
+
else
|
36
|
+
virtual_fields << f
|
37
|
+
end
|
28
38
|
else
|
29
39
|
results = results.or(duplicate_for_orwhere.where("lower(#{f}) LIKE lower(:query)", query: "%#{params[:q]}%"))
|
30
40
|
end
|
31
41
|
end
|
32
42
|
|
43
|
+
params[:fields].each do |f|
|
44
|
+
unless params[:q].blank?
|
45
|
+
if virtual_fields.present? && virtual_fields.include?(f)
|
46
|
+
results = results.select { |s| s.send(f).present? ? s.send(f).downcase.include?(params[:q].downcase) : nil }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
|
33
53
|
formatted_result = []
|
34
54
|
results.each do |r|
|
35
55
|
formatted_result << { id: r.id, name: helpers.show_object(r) }
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module SlashAdmin
|
3
4
|
module ApplicationHelper
|
4
5
|
def page_title(content)
|
@@ -18,10 +19,17 @@ module SlashAdmin
|
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
|
-
# Direct Link temp TODO
|
22
22
|
if s[:path].present?
|
23
|
-
|
23
|
+
if can? s[:role], s[:role]
|
24
|
+
access = true
|
25
|
+
end
|
26
|
+
if s[:role].present?
|
27
|
+
if can? s[:role], s[:role]
|
28
|
+
access = true
|
29
|
+
end
|
30
|
+
end
|
24
31
|
end
|
32
|
+
|
25
33
|
access
|
26
34
|
end
|
27
35
|
|
@@ -79,6 +87,7 @@ module SlashAdmin
|
|
79
87
|
return true unless object.errors.messages[field_name].blank?
|
80
88
|
end
|
81
89
|
|
90
|
+
# Type must be 'warning' or 'success' or 'error'
|
82
91
|
def toastr_bootstrap
|
83
92
|
flash_messages = []
|
84
93
|
flash.each do |type, message|
|
@@ -150,6 +159,8 @@ module SlashAdmin
|
|
150
159
|
has_many_fields = object_class.reflect_on_all_associations(:has_many).map(&:name)
|
151
160
|
has_one_fields = object_class.reflect_on_all_associations(:has_one).map(&:name)
|
152
161
|
|
162
|
+
return if attr.is_a? Hash
|
163
|
+
|
153
164
|
type = if object_class&.uploaders&.key?(attr.to_sym)
|
154
165
|
'image'
|
155
166
|
elsif belongs_to_fields.include?(attr.to_sym)
|
@@ -170,6 +181,28 @@ module SlashAdmin
|
|
170
181
|
type
|
171
182
|
end
|
172
183
|
|
184
|
+
# From shoulda-matchers https://github.com/thoughtbot/shoulda-matchers/blob/da4e6ddd06de54016e7c2afd953120f0f6529c70/lib/shoulda/matchers/rails_shim.rb
|
185
|
+
# @param model @model_class
|
186
|
+
def serialized_attributes_for(model)
|
187
|
+
serialized_columns = model.columns.select do |column|
|
188
|
+
model.type_for_attribute(column.name).is_a?(
|
189
|
+
::ActiveRecord::Type::Serialized,
|
190
|
+
)
|
191
|
+
end
|
192
|
+
|
193
|
+
serialized_columns.inject({}) do |hash, column|
|
194
|
+
hash[column.name.to_s] = model.type_for_attribute(column.name).coder
|
195
|
+
hash
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# @param model @model_class
|
200
|
+
# @param attribute String
|
201
|
+
def serialized_json_field?(model, attribute)
|
202
|
+
hash = serialized_attributes_for(model)
|
203
|
+
hash.key?(attribute) && hash[attribute] == ::ActiveRecord::Coders::JSON
|
204
|
+
end
|
205
|
+
|
173
206
|
def admin_custom_field(form, attribute)
|
174
207
|
type = attribute[attribute.keys.first][:type].to_s
|
175
208
|
render partial: "slash_admin/custom_fields/#{type}", locals: { f: form, a: attribute }
|
@@ -186,7 +219,11 @@ module SlashAdmin
|
|
186
219
|
if attribute.is_a?(Hash)
|
187
220
|
admin_custom_field(form, attribute)
|
188
221
|
elsif belongs_to_fields.include?(attribute.to_sym)
|
189
|
-
|
222
|
+
if form.object.class.nested_attributes_options.key?(attribute.to_sym)
|
223
|
+
render partial: 'slash_admin/fields/nested_belongs_to', locals: { f: form, a: attribute }
|
224
|
+
else
|
225
|
+
render partial: 'slash_admin/fields/belongs_to', locals: { f: form, a: attribute }
|
226
|
+
end
|
190
227
|
elsif has_many_fields.include?(attribute.to_sym)
|
191
228
|
# if has nested_attributes_options for has_many field
|
192
229
|
if form.object.class.nested_attributes_options.key?(attribute.to_sym)
|
@@ -195,7 +232,11 @@ module SlashAdmin
|
|
195
232
|
render partial: 'slash_admin/fields/has_many', locals: { f: form, a: attribute }
|
196
233
|
end
|
197
234
|
elsif has_one_fields.include?(attribute.to_sym)
|
198
|
-
|
235
|
+
if form.object.class.nested_attributes_options.key?(attribute.to_sym)
|
236
|
+
render partial: 'slash_admin/fields/nested_has_one', locals: { f: form, a: attribute }
|
237
|
+
else
|
238
|
+
render partial: 'slash_admin/fields/has_one', locals: { f: form, a: attribute }
|
239
|
+
end
|
199
240
|
elsif form.object.class&.uploaders&.key?(attribute.to_sym)
|
200
241
|
render partial: 'slash_admin/fields/carrierwave', locals: { f: form, a: attribute }
|
201
242
|
else
|