rails_admin_next 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.
- checksums.yaml +7 -0
- data/Gemfile +46 -0
- data/LICENSE.md +21 -0
- data/README.md +317 -0
- data/Rakefile +25 -0
- data/app/assets/javascripts/rails_admin/custom/ui.js +1 -0
- data/app/assets/stylesheets/rails_admin/framework.css +2375 -0
- data/app/assets/stylesheets/rails_admin/skin.css +472 -0
- data/app/assets/stylesheets/rails_admin/tokens.css +281 -0
- data/app/assets/stylesheets/rails_admin.css +47 -0
- data/app/controllers/rails_admin_next/application_controller.rb +98 -0
- data/app/controllers/rails_admin_next/main_controller.rb +185 -0
- data/app/helpers/rails_admin_next/application_helper.rb +254 -0
- data/app/helpers/rails_admin_next/form_builder.rb +173 -0
- data/app/helpers/rails_admin_next/main_helper.rb +63 -0
- data/app/views/layouts/rails_admin_next/_head.html.erb +29 -0
- data/app/views/layouts/rails_admin_next/_navigation.html.erb +18 -0
- data/app/views/layouts/rails_admin_next/_secondary_navigation.html.erb +27 -0
- data/app/views/layouts/rails_admin_next/_sidebar_navigation.html.erb +6 -0
- data/app/views/layouts/rails_admin_next/application.html.erb +42 -0
- data/app/views/layouts/rails_admin_next/content.html.erb +22 -0
- data/app/views/layouts/rails_admin_next/modal.js.erb +7 -0
- data/app/views/rails_admin_next/main/_dashboard_history.html.erb +46 -0
- data/app/views/rails_admin_next/main/_delete_notice.html.erb +36 -0
- data/app/views/rails_admin_next/main/_form_action_text.html.erb +2 -0
- data/app/views/rails_admin_next/main/_form_boolean.html.erb +15 -0
- data/app/views/rails_admin_next/main/_form_colorpicker.html.erb +6 -0
- data/app/views/rails_admin_next/main/_form_datetime.html.erb +14 -0
- data/app/views/rails_admin_next/main/_form_enumeration.html.erb +26 -0
- data/app/views/rails_admin_next/main/_form_field.html.erb +2 -0
- data/app/views/rails_admin_next/main/_form_file_upload.html.erb +18 -0
- data/app/views/rails_admin_next/main/_form_filtering_multiselect.html.erb +20 -0
- data/app/views/rails_admin_next/main/_form_filtering_select.html.erb +22 -0
- data/app/views/rails_admin_next/main/_form_multiple_file_upload.html.erb +21 -0
- data/app/views/rails_admin_next/main/_form_nested_many.html.erb +20 -0
- data/app/views/rails_admin_next/main/_form_nested_one.html.erb +19 -0
- data/app/views/rails_admin_next/main/_form_polymorphic_association.html.erb +24 -0
- data/app/views/rails_admin_next/main/_form_text.html.erb +2 -0
- data/app/views/rails_admin_next/main/_pagination.html.erb +54 -0
- data/app/views/rails_admin_next/main/_submit_buttons.html.erb +26 -0
- data/app/views/rails_admin_next/main/bulk_delete.html.erb +19 -0
- data/app/views/rails_admin_next/main/dashboard.html.erb +64 -0
- data/app/views/rails_admin_next/main/delete.html.erb +21 -0
- data/app/views/rails_admin_next/main/edit.html.erb +3 -0
- data/app/views/rails_admin_next/main/export.html.erb +149 -0
- data/app/views/rails_admin_next/main/history.html.erb +80 -0
- data/app/views/rails_admin_next/main/index.html.erb +186 -0
- data/app/views/rails_admin_next/main/new.html.erb +3 -0
- data/app/views/rails_admin_next/main/show.html.erb +30 -0
- data/config/brakeman.ignore +145 -0
- data/config/importmap.rails_admin.rb +29 -0
- data/config/initializers/active_record_extensions.rb +21 -0
- data/config/locales/rails_admin_next.en.yml +158 -0
- data/config/routes.rb +14 -0
- data/lib/generators/rails_admin_next/install_generator.rb +39 -0
- data/lib/generators/rails_admin_next/templates/initializer.erb +40 -0
- data/lib/generators/rails_admin_next/utils.rb +21 -0
- data/lib/rails_admin_next/abstract_model.rb +266 -0
- data/lib/rails_admin_next/adapters/active_record/association.rb +130 -0
- data/lib/rails_admin_next/adapters/active_record/object_extension.rb +13 -0
- data/lib/rails_admin_next/adapters/active_record/property.rb +58 -0
- data/lib/rails_admin_next/adapters/active_record.rb +371 -0
- data/lib/rails_admin_next/config/actions/base.rb +160 -0
- data/lib/rails_admin_next/config/actions/bulk_delete.rb +67 -0
- data/lib/rails_admin_next/config/actions/dashboard.rb +62 -0
- data/lib/rails_admin_next/config/actions/delete.rb +58 -0
- data/lib/rails_admin_next/config/actions/edit.rb +56 -0
- data/lib/rails_admin_next/config/actions/export.rb +47 -0
- data/lib/rails_admin_next/config/actions/history_index.rb +40 -0
- data/lib/rails_admin_next/config/actions/history_show.rb +40 -0
- data/lib/rails_admin_next/config/actions/index.rb +108 -0
- data/lib/rails_admin_next/config/actions/new.rb +69 -0
- data/lib/rails_admin_next/config/actions/show.rb +36 -0
- data/lib/rails_admin_next/config/actions/show_in_app.rb +37 -0
- data/lib/rails_admin_next/config/actions.rb +122 -0
- data/lib/rails_admin_next/config/configurable.rb +107 -0
- data/lib/rails_admin_next/config/const_load_suppressor.rb +78 -0
- data/lib/rails_admin_next/config/fields/association.rb +169 -0
- data/lib/rails_admin_next/config/fields/base.rb +391 -0
- data/lib/rails_admin_next/config/fields/collection_association.rb +90 -0
- data/lib/rails_admin_next/config/fields/factories/action_text.rb +14 -0
- data/lib/rails_admin_next/config/fields/factories/active_storage.rb +34 -0
- data/lib/rails_admin_next/config/fields/factories/association.rb +32 -0
- data/lib/rails_admin_next/config/fields/factories/encrypted_password.rb +28 -0
- data/lib/rails_admin_next/config/fields/factories/enum.rb +23 -0
- data/lib/rails_admin_next/config/fields/factories/password.rb +19 -0
- data/lib/rails_admin_next/config/fields/group.rb +77 -0
- data/lib/rails_admin_next/config/fields/singular_association.rb +62 -0
- data/lib/rails_admin_next/config/fields/types/action_text.rb +20 -0
- data/lib/rails_admin_next/config/fields/types/active_record_enum.rb +62 -0
- data/lib/rails_admin_next/config/fields/types/active_storage.rb +70 -0
- data/lib/rails_admin_next/config/fields/types/all.rb +32 -0
- data/lib/rails_admin_next/config/fields/types/belongs_to_association.rb +48 -0
- data/lib/rails_admin_next/config/fields/types/boolean.rb +70 -0
- data/lib/rails_admin_next/config/fields/types/citext.rb +15 -0
- data/lib/rails_admin_next/config/fields/types/color.rb +43 -0
- data/lib/rails_admin_next/config/fields/types/date.rb +38 -0
- data/lib/rails_admin_next/config/fields/types/datetime.rb +79 -0
- data/lib/rails_admin_next/config/fields/types/decimal.rb +23 -0
- data/lib/rails_admin_next/config/fields/types/enum.rb +52 -0
- data/lib/rails_admin_next/config/fields/types/file_upload.rb +87 -0
- data/lib/rails_admin_next/config/fields/types/float.rb +23 -0
- data/lib/rails_admin_next/config/fields/types/has_and_belongs_to_many_association.rb +16 -0
- data/lib/rails_admin_next/config/fields/types/has_many_association.rb +16 -0
- data/lib/rails_admin_next/config/fields/types/has_one_association.rb +35 -0
- data/lib/rails_admin_next/config/fields/types/hidden.rb +31 -0
- data/lib/rails_admin_next/config/fields/types/inet.rb +15 -0
- data/lib/rails_admin_next/config/fields/types/integer.rb +20 -0
- data/lib/rails_admin_next/config/fields/types/json.rb +37 -0
- data/lib/rails_admin_next/config/fields/types/multiple_active_storage.rb +82 -0
- data/lib/rails_admin_next/config/fields/types/multiple_file_upload.rb +134 -0
- data/lib/rails_admin_next/config/fields/types/numeric.rb +24 -0
- data/lib/rails_admin_next/config/fields/types/password.rb +45 -0
- data/lib/rails_admin_next/config/fields/types/polymorphic_association.rb +118 -0
- data/lib/rails_admin_next/config/fields/types/serialized.rb +28 -0
- data/lib/rails_admin_next/config/fields/types/string.rb +50 -0
- data/lib/rails_admin_next/config/fields/types/string_like.rb +25 -0
- data/lib/rails_admin_next/config/fields/types/text.rb +28 -0
- data/lib/rails_admin_next/config/fields/types/time.rb +39 -0
- data/lib/rails_admin_next/config/fields/types/timestamp.rb +16 -0
- data/lib/rails_admin_next/config/fields/types/uuid.rb +15 -0
- data/lib/rails_admin_next/config/fields/types.rb +29 -0
- data/lib/rails_admin_next/config/fields.rb +88 -0
- data/lib/rails_admin_next/config/groupable.rb +20 -0
- data/lib/rails_admin_next/config/has_description.rb +14 -0
- data/lib/rails_admin_next/config/has_fields.rb +144 -0
- data/lib/rails_admin_next/config/has_groups.rb +27 -0
- data/lib/rails_admin_next/config/hideable.rb +30 -0
- data/lib/rails_admin_next/config/inspectable.rb +39 -0
- data/lib/rails_admin_next/config/lazy_model.rb +74 -0
- data/lib/rails_admin_next/config/model.rb +126 -0
- data/lib/rails_admin_next/config/proxyable/proxy.rb +42 -0
- data/lib/rails_admin_next/config/proxyable.rb +26 -0
- data/lib/rails_admin_next/config/sections/base.rb +36 -0
- data/lib/rails_admin_next/config/sections/create.rb +13 -0
- data/lib/rails_admin_next/config/sections/edit.rb +13 -0
- data/lib/rails_admin_next/config/sections/export.rb +13 -0
- data/lib/rails_admin_next/config/sections/list.rb +63 -0
- data/lib/rails_admin_next/config/sections/modal.rb +12 -0
- data/lib/rails_admin_next/config/sections/nested.rb +12 -0
- data/lib/rails_admin_next/config/sections/show.rb +12 -0
- data/lib/rails_admin_next/config/sections/update.rb +12 -0
- data/lib/rails_admin_next/config/sections.rb +39 -0
- data/lib/rails_admin_next/config.rb +436 -0
- data/lib/rails_admin_next/engine.rb +91 -0
- data/lib/rails_admin_next/extension.rb +35 -0
- data/lib/rails_admin_next/extensions/cancancan/authorization_adapter.rb +90 -0
- data/lib/rails_admin_next/extensions/cancancan.rb +5 -0
- data/lib/rails_admin_next/extensions/controller_extension.rb +8 -0
- data/lib/rails_admin_next/extensions/paper_trail/auditing_adapter.rb +192 -0
- data/lib/rails_admin_next/extensions/paper_trail.rb +5 -0
- data/lib/rails_admin_next/extensions/pundit/authorization_adapter.rb +72 -0
- data/lib/rails_admin_next/extensions/pundit.rb +5 -0
- data/lib/rails_admin_next/extensions/url_for_extension.rb +15 -0
- data/lib/rails_admin_next/icons.rb +143 -0
- data/lib/rails_admin_next/support/composite_keys_serializer.rb +15 -0
- data/lib/rails_admin_next/support/csv_converter.rb +100 -0
- data/lib/rails_admin_next/support/hash_helper.rb +31 -0
- data/lib/rails_admin_next/support/paginated_collection.rb +79 -0
- data/lib/rails_admin_next/version.rb +17 -0
- data/lib/rails_admin_next.rb +72 -0
- data/lib/tasks/rails_admin.rake +40 -0
- data/src/rails_admin/application.js +15 -0
- data/src/rails_admin/base.js +12 -0
- data/src/rails_admin/controllers/alert_controller.js +28 -0
- data/src/rails_admin/controllers/collapse_controller.js +16 -0
- data/src/rails_admin/controllers/dropdown_controller.js +110 -0
- data/src/rails_admin/controllers/feedback_controller.js +73 -0
- data/src/rails_admin/controllers/filter_box_controller.js +346 -0
- data/src/rails_admin/controllers/filtering_multiselect_controller.js +386 -0
- data/src/rails_admin/controllers/filtering_select_controller.js +509 -0
- data/src/rails_admin/controllers/index.js +31 -0
- data/src/rails_admin/controllers/modal_controller.js +142 -0
- data/src/rails_admin/controllers/nested_form_controller.js +117 -0
- data/src/rails_admin/controllers/polymorphic_controller.js +26 -0
- data/src/rails_admin/controllers/remote_form_controller.js +173 -0
- data/src/rails_admin/controllers/sidescroll_controller.js +23 -0
- data/src/rails_admin/dom-ready.js +20 -0
- data/src/rails_admin/dom.js +19 -0
- data/src/rails_admin/i18n.js +20 -0
- data/src/rails_admin/icons.js +64 -0
- data/src/rails_admin/interactions.js +221 -0
- data/src/rails_admin/select_query.js +65 -0
- metadata +346 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_admin_next/config/fields/types/belongs_to_association"
|
|
4
|
+
|
|
5
|
+
module RailsAdminNext
|
|
6
|
+
module Config
|
|
7
|
+
module Fields
|
|
8
|
+
module Types
|
|
9
|
+
class PolymorphicAssociation < RailsAdminNext::Config::Fields::Types::BelongsToAssociation
|
|
10
|
+
# Register field type for the type loader
|
|
11
|
+
RailsAdminNext::Config::Fields::Types.register(self)
|
|
12
|
+
|
|
13
|
+
register_instance_option :partial do
|
|
14
|
+
:form_polymorphic_association
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Accessor whether association is visible or not. By default
|
|
18
|
+
# association checks that any of the child models are included in
|
|
19
|
+
# configuration.
|
|
20
|
+
register_instance_option :visible? do
|
|
21
|
+
associated_model_config.any?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
register_instance_option :formatted_value do
|
|
25
|
+
(o = value) && o.send(RailsAdminNext.config(o).object_label_method)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
register_instance_option :sortable do
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
register_instance_option :searchable do
|
|
33
|
+
false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# TODO: not supported yet
|
|
37
|
+
register_instance_option :associated_collection_cache_all do
|
|
38
|
+
false
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# TODO: not supported yet
|
|
42
|
+
register_instance_option :associated_collection_scope do
|
|
43
|
+
nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
register_instance_option :allowed_methods do
|
|
47
|
+
[children_fields]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
register_instance_option :eager_load do
|
|
51
|
+
false
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def associated_model_config
|
|
55
|
+
@associated_model_config ||= association.klass.collect { |type| RailsAdminNext.config(type) }.reject(&:excluded?)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def collection(_scope = nil)
|
|
59
|
+
if value
|
|
60
|
+
[[formatted_value, selected_id]]
|
|
61
|
+
else
|
|
62
|
+
[[]]
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def type_column
|
|
67
|
+
association.foreign_type.to_s
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def type_collection
|
|
71
|
+
associated_model_config.collect do |config|
|
|
72
|
+
[config.label, config.abstract_model.model.name]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def type_urls
|
|
77
|
+
types = associated_model_config.collect do |config|
|
|
78
|
+
[config.abstract_model.model.name, config.abstract_model.to_param]
|
|
79
|
+
end
|
|
80
|
+
::Hash[*types.collect { |v| [v[0], bindings[:view].index_path(v[1])] }.flatten]
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Reader for field's value
|
|
84
|
+
def value
|
|
85
|
+
bindings[:object].send(association.name)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def widget_options_for_types
|
|
89
|
+
type_collection.inject({}) do |options, model|
|
|
90
|
+
options.merge(
|
|
91
|
+
model.second.downcase.gsub("::", "-") => {
|
|
92
|
+
xhr: true,
|
|
93
|
+
remote_source: bindings[:view].index_path(model.second.underscore, source_object_id: bindings[:object].id, source_abstract_model: abstract_model.to_param, current_action: bindings[:view].current_action, compact: true),
|
|
94
|
+
float_left: false
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def widget_options
|
|
101
|
+
widget_options_for_types[selected_type.try(:downcase)] || {float_left: false}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def selected_type
|
|
105
|
+
bindings[:object].send(type_column)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def parse_input(params)
|
|
109
|
+
if (type_value = params[association.foreign_type.to_sym]).present?
|
|
110
|
+
config = associated_model_config.find { |c| type_value == c.abstract_model.model.name }
|
|
111
|
+
params[association.foreign_type.to_sym] = config.abstract_model.base_class.name if config
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_admin_next/config/fields/types/text"
|
|
4
|
+
|
|
5
|
+
module RailsAdminNext
|
|
6
|
+
module Config
|
|
7
|
+
module Fields
|
|
8
|
+
module Types
|
|
9
|
+
class Serialized < RailsAdminNext::Config::Fields::Types::Text
|
|
10
|
+
# Register field type for the type loader
|
|
11
|
+
RailsAdminNext::Config::Fields::Types.register(self)
|
|
12
|
+
|
|
13
|
+
register_instance_option :formatted_value do
|
|
14
|
+
RailsAdminNext.yaml_dump(value) unless value.nil?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def parse_value(value)
|
|
18
|
+
value.present? ? (RailsAdminNext.yaml_load(value) || nil) : nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def parse_input(params)
|
|
22
|
+
params[name] = parse_value(params[name]) if params[name].is_a?(::String)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_admin_next/config/fields/types/string_like"
|
|
4
|
+
|
|
5
|
+
module RailsAdminNext
|
|
6
|
+
module Config
|
|
7
|
+
module Fields
|
|
8
|
+
module Types
|
|
9
|
+
class String < StringLike
|
|
10
|
+
RailsAdminNext::Config::Fields::Types.register(self)
|
|
11
|
+
|
|
12
|
+
def input_size
|
|
13
|
+
[50, length.to_i].reject(&:zero?).min
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
register_instance_option :html_attributes do
|
|
17
|
+
{
|
|
18
|
+
required: required?,
|
|
19
|
+
maxlength: length,
|
|
20
|
+
size: input_size
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def generic_help
|
|
25
|
+
text = "#{required? ? I18n.translate("admin.form.required") : I18n.translate("admin.form.optional")}. "
|
|
26
|
+
if valid_length.present? && valid_length[:is].present?
|
|
27
|
+
text += "#{I18n.translate("admin.form.char_length_of").capitalize} #{valid_length[:is]}."
|
|
28
|
+
else
|
|
29
|
+
max_length = [length, valid_length[:maximum] || nil].compact.min
|
|
30
|
+
min_length = [0, valid_length[:minimum] || nil].compact.max
|
|
31
|
+
if max_length
|
|
32
|
+
text +=
|
|
33
|
+
if min_length == 0
|
|
34
|
+
"#{I18n.translate("admin.form.char_length_up_to").capitalize} #{max_length}."
|
|
35
|
+
else
|
|
36
|
+
"#{I18n.translate("admin.form.char_length_of").capitalize} #{min_length}-#{max_length}."
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
text
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
register_instance_option :partial do
|
|
44
|
+
:form_field
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_admin_next/config/fields/base"
|
|
4
|
+
|
|
5
|
+
module RailsAdminNext
|
|
6
|
+
module Config
|
|
7
|
+
module Fields
|
|
8
|
+
module Types
|
|
9
|
+
class StringLike < RailsAdminNext::Config::Fields::Base
|
|
10
|
+
register_instance_option :filter_operators do
|
|
11
|
+
%w[_discard like not_like is starts_with ends_with] + (required? ? [] : %w[_separator _present _blank])
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
register_instance_option :treat_empty_as_nil? do
|
|
15
|
+
properties.try(:nullable?)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def parse_input(params)
|
|
19
|
+
params[name] = params[name].presence if params.key?(name) && treat_empty_as_nil?
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_admin_next/config/fields/types/string_like"
|
|
4
|
+
|
|
5
|
+
module RailsAdminNext
|
|
6
|
+
module Config
|
|
7
|
+
module Fields
|
|
8
|
+
module Types
|
|
9
|
+
class Text < StringLike
|
|
10
|
+
# Register field type for the type loader
|
|
11
|
+
RailsAdminNext::Config::Fields::Types.register(self)
|
|
12
|
+
|
|
13
|
+
register_instance_option :html_attributes do
|
|
14
|
+
{
|
|
15
|
+
required: required?,
|
|
16
|
+
cols: "48",
|
|
17
|
+
rows: "3"
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
register_instance_option :partial do
|
|
22
|
+
:form_text
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_admin_next/config/fields/types/datetime"
|
|
4
|
+
|
|
5
|
+
module RailsAdminNext
|
|
6
|
+
module Config
|
|
7
|
+
module Fields
|
|
8
|
+
module Types
|
|
9
|
+
class Time < RailsAdminNext::Config::Fields::Types::Datetime
|
|
10
|
+
RailsAdminNext::Config::Fields::Types.register(self)
|
|
11
|
+
|
|
12
|
+
def parse_value(value)
|
|
13
|
+
parsed = super
|
|
14
|
+
return unless parsed
|
|
15
|
+
|
|
16
|
+
# Anchor to the dummy date in the zone *before* serializing so the wall-clock time is
|
|
17
|
+
# preserved at that date's UTC offset. A native <input type="time"> submits a bare
|
|
18
|
+
# %H:%M:%S, which Time.zone.parse resolves against today — whose DST offset can differ
|
|
19
|
+
# from the time column's 2000-01-01 storage date and would otherwise shift the hour.
|
|
20
|
+
abstract_model.model.type_for_attribute(name.to_s).serialize(parsed.change(year: 2000, month: 1, day: 1))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
register_instance_option :filter_operators do
|
|
24
|
+
%w[default between] + (required? ? [] : %w[_separator _not_null _null])
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
register_instance_option :strftime_format do
|
|
28
|
+
"%H:%M"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# The native <input type="time" step="1"> control accepts and emits %H:%M:%S.
|
|
32
|
+
def form_value
|
|
33
|
+
value&.in_time_zone&.strftime("%H:%M:%S") || form_default_value
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_admin_next/config/fields/types/datetime"
|
|
4
|
+
|
|
5
|
+
module RailsAdminNext
|
|
6
|
+
module Config
|
|
7
|
+
module Fields
|
|
8
|
+
module Types
|
|
9
|
+
class Timestamp < RailsAdminNext::Config::Fields::Types::Datetime
|
|
10
|
+
# Register field type for the type loader
|
|
11
|
+
RailsAdminNext::Config::Fields::Types.register(self)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_admin_next/config/fields/types/string"
|
|
4
|
+
|
|
5
|
+
module RailsAdminNext
|
|
6
|
+
module Config
|
|
7
|
+
module Fields
|
|
8
|
+
module Types
|
|
9
|
+
class Uuid < RailsAdminNext::Config::Fields::Types::String
|
|
10
|
+
RailsAdminNext::Config::Fields::Types.register(self)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/core_ext/string/inflections"
|
|
4
|
+
require "rails_admin_next/config/fields"
|
|
5
|
+
require "rails_admin_next/config/fields/association"
|
|
6
|
+
|
|
7
|
+
module RailsAdminNext
|
|
8
|
+
module Config
|
|
9
|
+
module Fields
|
|
10
|
+
module Types
|
|
11
|
+
@@registry = {}
|
|
12
|
+
|
|
13
|
+
def self.load(type)
|
|
14
|
+
@@registry.fetch(type.to_sym) { raise "Unsupported field datatype: #{type}" }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.register(type, klass = nil)
|
|
18
|
+
if klass.nil? && type.is_a?(Class)
|
|
19
|
+
klass = type
|
|
20
|
+
type = klass.name.to_s.demodulize.underscore
|
|
21
|
+
end
|
|
22
|
+
@@registry[type.to_sym] = klass
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
require "rails_admin_next/config/fields/types/all"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsAdminNext
|
|
4
|
+
module Config
|
|
5
|
+
module Fields
|
|
6
|
+
# Default field factory loads fields based on their property type or
|
|
7
|
+
# association type.
|
|
8
|
+
#
|
|
9
|
+
# @see RailsAdminNext::Config::Fields.registry
|
|
10
|
+
mattr_reader :default_factory
|
|
11
|
+
@@default_factory = proc do |parent, properties, fields|
|
|
12
|
+
# If it's an association
|
|
13
|
+
if properties.association?
|
|
14
|
+
association = parent.abstract_model.associations.detect { |a| a.name.to_s == properties.name.to_s }
|
|
15
|
+
field = RailsAdminNext::Config::Fields::Types.load("#{association.polymorphic? ? :polymorphic : properties.type}_association").new(parent, properties.name, association)
|
|
16
|
+
else
|
|
17
|
+
field = RailsAdminNext::Config::Fields::Types.load(properties.type).new(parent, properties.name, properties)
|
|
18
|
+
end
|
|
19
|
+
fields << field
|
|
20
|
+
field
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Registry of field factories.
|
|
24
|
+
#
|
|
25
|
+
# Field factory is an anonymous function that receives the parent object,
|
|
26
|
+
# an array of field properties and an array of fields already instantiated.
|
|
27
|
+
#
|
|
28
|
+
# If the factory returns true then that property will not be run through
|
|
29
|
+
# the rest of the registered factories. If it returns false then the
|
|
30
|
+
# arguments will be passed to the next factory.
|
|
31
|
+
#
|
|
32
|
+
# By default a basic factory is registered which loads fields by their
|
|
33
|
+
# database column type. Also a password factory is registered which
|
|
34
|
+
# loads fields if their name is password. A third factory handles
|
|
35
|
+
# encrypted_password columns (used by Devise and similar libs).
|
|
36
|
+
#
|
|
37
|
+
# @see RailsAdminNext::Config::Fields.register_factory
|
|
38
|
+
# @see rails_admin_next/config/fields/factories/password.rb
|
|
39
|
+
# @see rails_admin_next/config/fields/factories/encrypted_password.rb
|
|
40
|
+
@@registry = [@@default_factory]
|
|
41
|
+
|
|
42
|
+
# Build an array of fields by the provided parent object's abstract_model's
|
|
43
|
+
# property and association information. Each property and association is
|
|
44
|
+
# passed to the registered field factories which will populate the fields
|
|
45
|
+
# array that will be returned.
|
|
46
|
+
#
|
|
47
|
+
# @see RailsAdminNext::Config::Fields.registry
|
|
48
|
+
def self.factory(parent)
|
|
49
|
+
fields = []
|
|
50
|
+
# Load fields for all properties (columns)
|
|
51
|
+
|
|
52
|
+
parent.abstract_model.properties.each do |properties|
|
|
53
|
+
# Unless a previous factory has already loaded current field as well
|
|
54
|
+
next if fields.detect { |f| f.name == properties.name }
|
|
55
|
+
|
|
56
|
+
# Loop through factories until one returns true
|
|
57
|
+
@@registry.detect { |factory| factory.call(parent, properties, fields) }
|
|
58
|
+
end
|
|
59
|
+
# Load fields for all associations (relations)
|
|
60
|
+
parent.abstract_model.associations.reject { |a| a.type == :belongs_to }.each do |association| # :belongs_to are created by factory for belongs_to fields
|
|
61
|
+
# Unless a previous factory has already loaded current field as well
|
|
62
|
+
next if fields.detect { |f| f.name == association.name }
|
|
63
|
+
|
|
64
|
+
# Loop through factories until one returns true
|
|
65
|
+
@@registry.detect { |factory| factory.call(parent, association, fields) }
|
|
66
|
+
end
|
|
67
|
+
fields
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Register a field factory to be included in the factory stack.
|
|
71
|
+
#
|
|
72
|
+
# Factories are invoked lifo (last in first out).
|
|
73
|
+
#
|
|
74
|
+
# @see RailsAdminNext::Config::Fields.registry
|
|
75
|
+
def self.register_factory(&block)
|
|
76
|
+
@@registry.unshift(block)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
require "rails_admin_next/config/fields/types"
|
|
83
|
+
require "rails_admin_next/config/fields/factories/password"
|
|
84
|
+
require "rails_admin_next/config/fields/factories/enum"
|
|
85
|
+
require "rails_admin_next/config/fields/factories/encrypted_password"
|
|
86
|
+
require "rails_admin_next/config/fields/factories/active_storage"
|
|
87
|
+
require "rails_admin_next/config/fields/factories/action_text"
|
|
88
|
+
require "rails_admin_next/config/fields/factories/association"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_admin_next/config/fields/group"
|
|
4
|
+
|
|
5
|
+
module RailsAdminNext
|
|
6
|
+
module Config
|
|
7
|
+
module Groupable
|
|
8
|
+
# Register a group instance variable and accessor methods for objects
|
|
9
|
+
# extending the has groups mixin. The extended objects must implement
|
|
10
|
+
# reader for a parent object which includes this module.
|
|
11
|
+
#
|
|
12
|
+
# @see RailsAdminNext::Config::HasGroups.group
|
|
13
|
+
# @see RailsAdminNext::Config::Fields::Group
|
|
14
|
+
def group(name = nil)
|
|
15
|
+
@group = parent.group(name) unless name.nil? # setter
|
|
16
|
+
@group ||= parent.group(:default) # getter
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsAdminNext
|
|
4
|
+
module Config
|
|
5
|
+
# Provides accessor and autoregistering of model's description.
|
|
6
|
+
module HasDescription
|
|
7
|
+
attr_reader :description
|
|
8
|
+
|
|
9
|
+
def desc(description, &_block)
|
|
10
|
+
@description ||= description
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsAdminNext
|
|
4
|
+
module Config
|
|
5
|
+
# Provides accessors and autoregistering of model's fields.
|
|
6
|
+
module HasFields
|
|
7
|
+
# Defines a configuration for a field.
|
|
8
|
+
def field(name, type = nil, add_to_section = true, &block)
|
|
9
|
+
field = _fields.detect { |f| name == f.name }
|
|
10
|
+
|
|
11
|
+
# some fields are hidden by default (belongs_to keys, has_many associations in list views.)
|
|
12
|
+
# unhide them if config specifically defines them
|
|
13
|
+
field.show if field && !field.instance_variable_get("@#{field.name}_registered").is_a?(Proc)
|
|
14
|
+
# Specify field as virtual if type is not specifically set and field was not
|
|
15
|
+
# found in default stack
|
|
16
|
+
if field.nil? && type.nil?
|
|
17
|
+
field = (_fields << RailsAdminNext::Config::Fields::Types.load(:string).new(self, name, nil)).last
|
|
18
|
+
|
|
19
|
+
# Register a custom field type if one is provided and it is different from
|
|
20
|
+
# one found in default stack
|
|
21
|
+
elsif type && type != (field.nil? ? nil : field.type)
|
|
22
|
+
if field
|
|
23
|
+
properties = field.properties
|
|
24
|
+
field = _fields[_fields.index(field)] = RailsAdminNext::Config::Fields::Types.load(type).new(self, name, properties)
|
|
25
|
+
else
|
|
26
|
+
properties = abstract_model.properties.detect { |p| name == p.name }
|
|
27
|
+
field = (_fields << RailsAdminNext::Config::Fields::Types.load(type).new(self, name, properties)).last
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# If field has not been yet defined add some default properties
|
|
32
|
+
if add_to_section && !field.defined
|
|
33
|
+
field.defined = true
|
|
34
|
+
field.order = _fields.count(&:defined)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# If a block has been given evaluate it and sort fields after that
|
|
38
|
+
field.instance_eval(&block) if block
|
|
39
|
+
field
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# configure field(s) from the default group in a section without changing the original order.
|
|
43
|
+
def configure(name, type = nil, &)
|
|
44
|
+
[*name].each { |field_name| field(field_name, type, false, &) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# include fields by name and apply an optional block to each (through a call to fields),
|
|
48
|
+
# or include fields by conditions if no field names
|
|
49
|
+
def include_fields(*field_names, &)
|
|
50
|
+
if field_names.empty?
|
|
51
|
+
_fields.select { |f| f.instance_eval(&) }.each do |f|
|
|
52
|
+
next if f.defined
|
|
53
|
+
|
|
54
|
+
f.defined = true
|
|
55
|
+
f.order = _fields.count(&:defined)
|
|
56
|
+
end
|
|
57
|
+
else
|
|
58
|
+
fields(*field_names, &)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# exclude fields by name or by condition (block)
|
|
63
|
+
def exclude_fields(*field_names, &block)
|
|
64
|
+
block ||= proc { |f| field_names.include?(f.name) }
|
|
65
|
+
_fields.each { |f| f.defined = true } if _fields.select(&:defined).empty?
|
|
66
|
+
_fields.select { |f| f.instance_eval(&block) }.each { |f| f.defined = false }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# API candy
|
|
70
|
+
alias_method :exclude_fields_if, :exclude_fields
|
|
71
|
+
alias_method :include_fields_if, :include_fields
|
|
72
|
+
|
|
73
|
+
def include_all_fields
|
|
74
|
+
include_fields_if { true }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Returns all field configurations for the model configuration instance. If no fields
|
|
78
|
+
# have been defined returns all fields. Defined fields are sorted to match their
|
|
79
|
+
# order property. If order was not specified it will match the order in which fields
|
|
80
|
+
# were defined.
|
|
81
|
+
#
|
|
82
|
+
# If a block is passed it will be evaluated in the context of each field
|
|
83
|
+
def fields(*field_names, &block)
|
|
84
|
+
return all_fields if field_names.empty? && !block
|
|
85
|
+
|
|
86
|
+
if field_names.empty?
|
|
87
|
+
defined = _fields.select(&:defined)
|
|
88
|
+
defined = _fields if defined.empty?
|
|
89
|
+
else
|
|
90
|
+
defined = field_names.collect { |field_name| _fields.detect { |f| f.name == field_name } }
|
|
91
|
+
end
|
|
92
|
+
defined.collect do |f|
|
|
93
|
+
unless f.defined
|
|
94
|
+
f.defined = true
|
|
95
|
+
f.order = _fields.count(&:defined)
|
|
96
|
+
end
|
|
97
|
+
f.instance_eval(&block) if block
|
|
98
|
+
f
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Defines configuration for fields by their type.
|
|
103
|
+
def fields_of_type(type, &block)
|
|
104
|
+
_fields.select { |f| type == f.type }.map! { |f| f.instance_eval(&block) } if block
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Accessor for all fields
|
|
108
|
+
def all_fields
|
|
109
|
+
((ro_fields = _fields(true)).select(&:defined).presence || ro_fields).collect do |f|
|
|
110
|
+
f.section = self
|
|
111
|
+
f
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Get all fields defined as visible, in the correct order.
|
|
116
|
+
def visible_fields
|
|
117
|
+
i = 0
|
|
118
|
+
all_fields.collect { |f| f.with(bindings) }.select(&:visible?).sort_by { |f| [f.order, i += 1] } # stable sort, damn
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def possible_fields
|
|
122
|
+
_fields(true)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
protected
|
|
126
|
+
|
|
127
|
+
# Raw fields.
|
|
128
|
+
# Recursively returns parent section's raw fields
|
|
129
|
+
# Duping it if accessed for modification.
|
|
130
|
+
def _fields(readonly = false)
|
|
131
|
+
return @_fields if @_fields
|
|
132
|
+
return @_ro_fields if readonly && @_ro_fields
|
|
133
|
+
|
|
134
|
+
if instance_of?(RailsAdminNext::Config::Sections::Base)
|
|
135
|
+
@_ro_fields = @_fields = RailsAdminNext::Config::Fields.factory(self)
|
|
136
|
+
else
|
|
137
|
+
# parent is RailsAdminNext::Config::Model, recursion is on Section's classes
|
|
138
|
+
@_ro_fields ||= parent.send(self.class.superclass.to_s.underscore.split("/").last)._fields(true).clone.freeze
|
|
139
|
+
end
|
|
140
|
+
readonly ? @_ro_fields : (@_fields ||= @_ro_fields.collect(&:clone))
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_admin_next/config/fields/group"
|
|
4
|
+
|
|
5
|
+
module RailsAdminNext
|
|
6
|
+
module Config
|
|
7
|
+
module HasGroups
|
|
8
|
+
# Accessor for a group
|
|
9
|
+
#
|
|
10
|
+
# If group with given name does not yet exist it will be created. If a
|
|
11
|
+
# block is passed it will be evaluated in the context of the group
|
|
12
|
+
def group(name, &block)
|
|
13
|
+
group = parent.groups.detect { |g| name == g.name }
|
|
14
|
+
group ||= (parent.groups << RailsAdminNext::Config::Fields::Group.new(self, name)).last
|
|
15
|
+
group.tap { |g| g.section = self }.instance_eval(&block) if block
|
|
16
|
+
group
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Reader for groups that are marked as visible
|
|
20
|
+
def visible_groups
|
|
21
|
+
parent.groups.collect { |f| f.section = self; f.with(bindings) }.select(&:visible?).select do |g| # rubocop:disable Style/Semicolon
|
|
22
|
+
g.visible_fields.present?
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsAdminNext
|
|
4
|
+
module Config
|
|
5
|
+
# Defines a visibility configuration
|
|
6
|
+
module Hideable
|
|
7
|
+
# Visibility defaults to true.
|
|
8
|
+
def self.included(klass)
|
|
9
|
+
klass.register_instance_option :visible? do
|
|
10
|
+
!root.try :excluded?
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Reader whether object is hidden.
|
|
15
|
+
def hidden?
|
|
16
|
+
!visible
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Writer to hide object.
|
|
20
|
+
def hide(&block)
|
|
21
|
+
visible block ? proc { instance_eval(&block) == false } : false
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Writer to show field.
|
|
25
|
+
def show(&block)
|
|
26
|
+
visible block || true
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|