para 0.6.9 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/images/para/admin/tangram-mosaic.png +0 -0
- data/app/assets/images/para/admin/template-section.svg +23 -0
- data/app/assets/javascripts/para/admin.coffee +20 -0
- data/app/assets/javascripts/para/admin/tabs.coffee +22 -5
- data/app/assets/javascripts/para/admin/theme_actions.coffee +3 -3
- data/app/assets/javascripts/para/inputs/material-input.coffee +4 -0
- data/app/assets/javascripts/para/inputs/multi-select-input.coffee +173 -0
- data/app/assets/javascripts/para/inputs/nested_many.coffee +9 -9
- data/app/assets/stylesheets/para/admin.sass +5 -5
- data/app/assets/stylesheets/para/admin/main.sass +32 -0
- data/app/assets/stylesheets/para/admin/src/_alert.sass +17 -0
- data/app/assets/stylesheets/para/admin/src/_base.sass +51 -0
- data/app/assets/stylesheets/para/admin/src/_bootstrap-variables.scss +874 -0
- data/app/assets/stylesheets/para/admin/src/_breadcrumb.sass +22 -0
- data/app/assets/stylesheets/para/admin/src/_buttons.sass +107 -0
- data/app/assets/stylesheets/para/admin/src/_checkable.sass +94 -0
- data/app/assets/stylesheets/para/admin/src/_common.sass +203 -0
- data/app/assets/stylesheets/para/admin/src/_dropdown.sass +40 -0
- data/app/assets/stylesheets/para/admin/src/_form.sass +271 -0
- data/app/assets/stylesheets/para/admin/src/_list.sass +61 -0
- data/app/assets/stylesheets/para/admin/src/_mixins.sass +113 -0
- data/app/assets/stylesheets/para/admin/src/_multi-select.sass +91 -0
- data/app/assets/stylesheets/para/admin/src/_navigation.sass +150 -0
- data/app/assets/stylesheets/para/admin/src/_navtabs.sass +41 -0
- data/app/assets/stylesheets/para/admin/src/_nested-many.sass +69 -0
- data/app/assets/stylesheets/para/admin/src/_nested_one.sass +13 -0
- data/app/assets/stylesheets/para/admin/src/_orderable.sass +44 -0
- data/app/assets/stylesheets/para/admin/src/_page-loading.sass +39 -0
- data/app/assets/stylesheets/para/admin/src/_pagination.sass +34 -0
- data/app/assets/stylesheets/para/admin/src/_panel.sass +55 -0
- data/app/assets/stylesheets/para/admin/src/_responsive.sass +100 -0
- data/app/assets/stylesheets/para/admin/{theme → src}/_sorting.sass +11 -3
- data/app/assets/stylesheets/para/admin/src/_statcard.sass +41 -0
- data/app/assets/stylesheets/para/admin/src/_table.sass +33 -0
- data/app/assets/stylesheets/para/admin/src/_tree.sass +52 -0
- data/app/assets/stylesheets/para/admin/src/_variables.sass +37 -0
- data/app/assets/stylesheets/para/admin/src/_well.sass +12 -0
- data/app/assets/stylesheets/para/{admin/src → lib}/datetimepicker.sass +1 -3
- data/app/assets/stylesheets/para/{admin/src → lib}/fuelux.sass +3 -5
- data/app/assets/stylesheets/para/lib/jasny-bootstrap.sass +97 -0
- data/app/assets/stylesheets/para/{admin/src → lib}/redactor.sass +2 -5
- data/app/assets/stylesheets/para/lib/selectize.sass +112 -0
- data/app/assets/stylesheets/para/lib/slider.sass +12 -0
- data/app/controllers/concerns/para/admin/resource_controller_concerns.rb +14 -2
- data/app/controllers/para/admin/base_controller.rb +7 -0
- data/app/controllers/para/admin/crud_resources_controller.rb +13 -6
- data/app/controllers/para/admin/form_resources_controller.rb +5 -3
- data/app/controllers/para/admin/resources_controller.rb +9 -3
- data/app/controllers/para/admin/search_controller.rb +15 -0
- data/app/controllers/para/application_controller.rb +10 -2
- data/app/helpers/para/admin/page_helper.rb +9 -9
- data/app/helpers/para/application_helper.rb +1 -10
- data/app/helpers/para/form_helper.rb +5 -6
- data/app/helpers/para/model_helper.rb +13 -3
- data/app/helpers/para/ordering_helper.rb +1 -1
- data/app/helpers/para/search_results_helper.rb +16 -0
- data/app/helpers/para/tree_helper.rb +10 -6
- data/app/models/para/page.rb +5 -0
- data/app/models/para/page/section.rb +42 -0
- data/app/models/para/page/section_resource.rb +12 -0
- data/app/views/layouts/para/admin.html.haml +5 -8
- data/app/views/para/admin/dashboard.html.haml +21 -8
- data/app/views/para/admin/form_resources/show.html.haml +1 -1
- data/app/views/para/admin/imports/new.html.haml +2 -2
- data/app/views/para/admin/resources/_actions.html.haml +3 -3
- data/app/views/para/admin/resources/_add_button.html.haml +1 -1
- data/app/views/para/admin/resources/_exports_menu.html.haml +6 -6
- data/app/views/para/admin/resources/_filters.html.haml +7 -8
- data/app/views/para/admin/resources/_imports_menu.html.haml +6 -6
- data/app/views/para/admin/resources/_list.html.haml +14 -15
- data/app/views/para/admin/resources/_per_page_select.html.haml +4 -3
- data/app/views/para/admin/resources/_subclassable_add_button.html.haml +3 -3
- data/app/views/para/admin/resources/_tree.html.haml +7 -9
- data/app/views/para/admin/resources/_tree_item.html.haml +5 -6
- data/app/views/para/admin/resources/edit.html.haml +1 -1
- data/app/views/para/admin/resources/new.html.haml +1 -1
- data/app/views/para/admin/search/_result.html.haml +7 -0
- data/app/views/para/admin/search/index.html.haml +1 -0
- data/app/views/para/admin/settings_component/show.html.haml +1 -1
- data/app/views/para/admin/shared/_breadcrumbs.html.haml +2 -3
- data/app/views/para/admin/shared/_header.html.haml +16 -27
- data/app/views/para/admin/shared/_navigation.html.haml +20 -19
- data/app/views/para/form/_tabs.html.haml +6 -7
- data/app/views/para/inputs/_multi_select.html.haml +40 -0
- data/app/views/para/inputs/_nested_many.html.haml +4 -4
- data/app/views/para/inputs/multi_select/_no_items.html.haml +6 -0
- data/app/views/para/inputs/nested_many/_add.html.haml +1 -2
- data/app/views/para/inputs/nested_many/_add_with_subclasses.html.haml +4 -5
- data/app/views/para/inputs/nested_many/_container.html.haml +7 -8
- data/app/views/shared/_breadcrumbs.html.haml +4 -0
- data/config/locales/fr.yml +29 -4
- data/db/migrate/20170324125547_create_para_page_section_resources.rb +15 -0
- data/lib/generators/para/filters/templates/_filters.html.haml +3 -5
- data/lib/generators/para/install/templates/initializer.rb +12 -0
- data/lib/generators/para/page/section/section_generator.rb +13 -2
- data/lib/generators/para/page/section/templates/section.html.haml.erb +3 -0
- data/lib/generators/para/resource/resource_generator.rb +1 -1
- data/lib/para.rb +25 -21
- data/lib/para/attribute_field.rb +2 -0
- data/lib/para/attribute_field/base.rb +1 -1
- data/lib/para/attribute_field/belongs_to.rb +1 -1
- data/lib/para/attribute_field/boolean.rb +1 -1
- data/lib/para/attribute_field/friendly_id.rb +19 -0
- data/lib/para/attribute_field/has_many.rb +43 -4
- data/lib/para/attribute_field/nested_field.rb +46 -0
- data/lib/para/attribute_field/nested_many.rb +30 -9
- data/lib/para/attribute_field/nested_one.rb +28 -9
- data/lib/para/attribute_field/password.rb +1 -1
- data/lib/para/attribute_field/relation.rb +19 -1
- data/lib/para/attribute_field_mappings.rb +9 -3
- data/lib/para/breadcrumbs/breadcrumb.rb +57 -10
- data/lib/para/breadcrumbs/controller.rb +19 -6
- data/lib/para/breadcrumbs/manager.rb +9 -1
- data/lib/para/config.rb +3 -0
- data/lib/para/controller_resource.rb +34 -0
- data/lib/para/engine.rb +33 -14
- data/lib/para/exporter/base.rb +1 -1
- data/lib/para/ext.rb +1 -1
- data/lib/para/ext/active_record_nested_attributes.rb +51 -0
- data/lib/para/ext/paperclip.rb +2 -6
- data/lib/para/form_builder.rb +3 -0
- data/lib/para/form_builder/attributes_mappings_tracker.rb +45 -0
- data/lib/para/form_builder/containers.rb +13 -17
- data/lib/para/form_builder/nested_form.rb +2 -3
- data/lib/para/helpers.rb +8 -0
- data/lib/para/helpers/attributes_mappings.rb +13 -0
- data/lib/para/helpers/resource_name.rb +14 -0
- data/lib/para/inputs.rb +1 -0
- data/lib/para/inputs/multi_select_input.rb +90 -0
- data/lib/para/inputs/nested_many_input.rb +6 -1
- data/lib/para/markup/resources_table.rb +15 -11
- data/lib/para/model_field_parsers.rb +3 -2
- data/lib/para/model_field_parsers/base.rb +7 -2
- data/lib/para/model_field_parsers/friendly_id.rb +19 -0
- data/lib/para/model_field_parsers/relations.rb +20 -1
- data/lib/para/page/model.rb +3 -1
- data/lib/para/routes.rb +1 -0
- data/lib/para/simple_form_config.rb +85 -0
- data/lib/para/version.rb +1 -1
- data/lib/rails/routing_mapper.rb +5 -8
- data/vendor/assets/javascripts/jasny-bootstrap.js +577 -0
- data/vendor/assets/stylesheets/animate.css +3340 -0
- data/vendor/assets/stylesheets/hint.css +649 -0
- data/vendor/assets/stylesheets/jasny-bootstrap.css +287 -0
- metadata +114 -67
- data/app/assets/images/para/admin/bg.png +0 -0
- data/app/assets/javascripts/para/admin.js +0 -20
- data/app/assets/stylesheets/admin/theme.sass +0 -0
- data/app/assets/stylesheets/para/admin/src/jasny.bootstrap.sass +0 -40
- data/app/assets/stylesheets/para/admin/src/nested_many.sass +0 -5
- data/app/assets/stylesheets/para/admin/src/page-loading.sass +0 -24
- data/app/assets/stylesheets/para/admin/src/page-top-bar.sass +0 -9
- data/app/assets/stylesheets/para/admin/src/selectize.sass +0 -46
- data/app/assets/stylesheets/para/admin/src/slider.sass +0 -12
- data/app/assets/stylesheets/para/admin/theme.sass +0 -22
- data/app/assets/stylesheets/para/admin/theme/_base.sass +0 -176
- data/app/assets/stylesheets/para/admin/theme/_breadcrumb.sass +0 -75
- data/app/assets/stylesheets/para/admin/theme/_buttons.sass +0 -27
- data/app/assets/stylesheets/para/admin/theme/_checkable.sass +0 -108
- data/app/assets/stylesheets/para/admin/theme/_commonds.sass +0 -210
- data/app/assets/stylesheets/para/admin/theme/_dropdown.sass +0 -52
- data/app/assets/stylesheets/para/admin/theme/_form.sass +0 -150
- data/app/assets/stylesheets/para/admin/theme/_list.sass +0 -139
- data/app/assets/stylesheets/para/admin/theme/_navigation.sass +0 -229
- data/app/assets/stylesheets/para/admin/theme/_navtabs.sass +0 -151
- data/app/assets/stylesheets/para/admin/theme/_orderable.sass +0 -45
- data/app/assets/stylesheets/para/admin/theme/_panel.sass +0 -264
- data/app/assets/stylesheets/para/admin/theme/_responsive.sass +0 -123
- data/app/assets/stylesheets/para/admin/theme/_table.sass +0 -28
- data/app/assets/stylesheets/para/admin/theme/_tree.sass +0 -74
- data/app/assets/stylesheets/para/admin/theme/_variables.sass +0 -31
- data/app/assets/stylesheets/para/application.css +0 -15
- data/app/assets/stylesheets/para/lib/_variables.scss +0 -646
- data/app/assets/stylesheets/para/overrides/responsive.sass +0 -62
- data/app/assets/stylesheets/para/overrides/theme.sass +0 -172
- data/lib/para/ext/cancan.rb +0 -26
- data/vendor/assets/javascripts/jasny.bootstrap.min.js +0 -7
- data/vendor/assets/stylesheets/animate.min.css +0 -6
- data/vendor/assets/stylesheets/jasny.bootstrap.min.css +0 -7
@@ -19,7 +19,7 @@ module Para
|
|
19
19
|
reflection.klass.all
|
20
20
|
end
|
21
21
|
|
22
|
-
def parse_input(params)
|
22
|
+
def parse_input(params, resource)
|
23
23
|
if (id = params[reflection.foreign_key].presence) && !reflection.klass.exists?(id: id)
|
24
24
|
on_the_fly_creation(id) do |resource|
|
25
25
|
params[reflection.foreign_key] = resource.id
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Para
|
2
|
+
module AttributeField
|
3
|
+
class FriendlyId < Base
|
4
|
+
register :friendly_id, self
|
5
|
+
|
6
|
+
# Set empty string as nil to allow default friendly id methods to
|
7
|
+
# generate the slug when the field is empty
|
8
|
+
def parse_input(params, resource)
|
9
|
+
params[slug_column] = nil if slug_column && params[slug_column] == ''
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def slug_column
|
15
|
+
model.try(:friendly_id_config).try(:slug_column)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -13,21 +13,60 @@ module Para
|
|
13
13
|
end.join(', ')
|
14
14
|
end
|
15
15
|
|
16
|
-
def parse_input(params)
|
16
|
+
def parse_input(params, resource)
|
17
17
|
if (ids = params[plural_foreign_key].presence) && String === ids
|
18
18
|
# Format selectize value for Rails
|
19
|
-
ids = params[plural_foreign_key] = ids.split(',')
|
19
|
+
ids = params[plural_foreign_key] = ids.split(',').map(&:to_i)
|
20
20
|
|
21
|
-
on_the_fly_creation(ids) do |
|
21
|
+
on_the_fly_creation(ids) do |res, value|
|
22
22
|
params[plural_foreign_key].delete(value)
|
23
|
-
params[plural_foreign_key] <<
|
23
|
+
params[plural_foreign_key] << res.id
|
24
24
|
end
|
25
25
|
end
|
26
|
+
|
27
|
+
assign_ids(params, resource)
|
26
28
|
end
|
27
29
|
|
28
30
|
def plural_foreign_key
|
29
31
|
foreign_key.to_s.pluralize
|
30
32
|
end
|
33
|
+
|
34
|
+
def assign_ids(params, resource)
|
35
|
+
return unless Array === params[plural_foreign_key]
|
36
|
+
|
37
|
+
ids = params.delete(plural_foreign_key)
|
38
|
+
|
39
|
+
if through_reflection && through_reflection.klass.orderable?
|
40
|
+
assign_ordered_through_reflection_ids(through_reflection, resource, ids)
|
41
|
+
else
|
42
|
+
resource.assign_attributes(plural_foreign_key => ids)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def assign_ordered_through_reflection_ids(through_reflection, resource, ids)
|
47
|
+
association = resource.association(through_reflection.name)
|
48
|
+
join_resources = association.load_target
|
49
|
+
|
50
|
+
return association.replace([]) if ids.empty?
|
51
|
+
|
52
|
+
new_resources = ids.each_with_index.map do |id, position|
|
53
|
+
join_resource = join_resources.find do |res|
|
54
|
+
res.send(through_relation_source_foreign_key) == id &&
|
55
|
+
(!polymorphic_through_reflection? || res.send(reflection.foreign_type) == reflection.klass.name)
|
56
|
+
end
|
57
|
+
|
58
|
+
unless join_resource
|
59
|
+
attributes = { through_relation_source_foreign_key => id }
|
60
|
+
attributes[reflection.foreign_type] = reflection.klass.name if polymorphic_through_reflection?
|
61
|
+
join_resource = association.build(attributes)
|
62
|
+
end
|
63
|
+
|
64
|
+
join_resource.position = position
|
65
|
+
join_resource
|
66
|
+
end
|
67
|
+
|
68
|
+
association.replace(new_resources)
|
69
|
+
end
|
31
70
|
end
|
32
71
|
end
|
33
72
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Para
|
2
|
+
module AttributeField
|
3
|
+
module NestedField
|
4
|
+
def nested_model_mappings(nested_attributes)
|
5
|
+
model = if (type = nested_attributes[:type]).present?
|
6
|
+
nested_attributes[:type].try(:constantize)
|
7
|
+
else
|
8
|
+
reflection.klass
|
9
|
+
end
|
10
|
+
|
11
|
+
mappings = attributes_mappings_for(nested_attributes)
|
12
|
+
|
13
|
+
AttributeFieldMappings.new(model, mappings: mappings)
|
14
|
+
end
|
15
|
+
|
16
|
+
def nested_attributes_key
|
17
|
+
@nested_attributes_key ||= :"#{ name }_attributes"
|
18
|
+
end
|
19
|
+
|
20
|
+
# This method extends the current resource so its #id method returns a
|
21
|
+
# fake id based on the given attributes, but immediately returns to its
|
22
|
+
# standard behavior of returning nil as soon as the `#assign_attributes`
|
23
|
+
# method is called.
|
24
|
+
#
|
25
|
+
# During nested attributes assignation, the id of the resource is used
|
26
|
+
# to assign it its nested params. When it is nil, a new resource is
|
27
|
+
# created, but since we already need our resource to be created at the
|
28
|
+
# time we parse the input params, we fake the presence of an id while the
|
29
|
+
# nested attributes assignation is running, and remove that behavior as
|
30
|
+
# soon as we don't need it anymore.
|
31
|
+
#
|
32
|
+
def temporarily_extend_new_resource(resource, attributes)
|
33
|
+
resource.instance_variable_set(:@_waiting_for_attributes_assignation, true)
|
34
|
+
|
35
|
+
resource.define_singleton_method(:assign_attributes) do |*args|
|
36
|
+
@_waiting_for_attributes_assignation = false
|
37
|
+
super(*args)
|
38
|
+
end
|
39
|
+
|
40
|
+
resource.define_singleton_method(:id) do
|
41
|
+
@_waiting_for_attributes_assignation ? attributes['id'] : read_attribute(:id)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,28 +1,49 @@
|
|
1
1
|
module Para
|
2
2
|
module AttributeField
|
3
3
|
class NestedManyField < AttributeField::HasManyField
|
4
|
+
include Para::Helpers::AttributesMappings
|
5
|
+
include Para::AttributeField::NestedField
|
6
|
+
|
4
7
|
register :nested_many, self
|
5
8
|
|
6
|
-
def parse_input(params)
|
9
|
+
def parse_input(params, resource)
|
7
10
|
if (nested_attributes = params[nested_attributes_key])
|
8
11
|
nested_attributes.each do |index, attributes|
|
9
|
-
|
10
|
-
|
12
|
+
mappings = nested_model_mappings(attributes)
|
13
|
+
nested_resource = fetch_or_build_nested_resource_for(resource, index, attributes)
|
14
|
+
|
15
|
+
mappings.fields.each do |field|
|
16
|
+
field.parse_input(attributes, nested_resource)
|
11
17
|
end
|
12
18
|
|
13
19
|
params[nested_attributes_key][index] = attributes
|
14
20
|
end
|
15
21
|
else
|
16
|
-
super
|
22
|
+
super
|
17
23
|
end
|
18
24
|
end
|
19
25
|
|
20
|
-
|
21
|
-
|
22
|
-
|
26
|
+
private
|
27
|
+
|
28
|
+
# Force loading association and look for a resource matching the provided
|
29
|
+
# attributes. If no resource is found, one is created and a fake `id` is
|
30
|
+
# assigned to it to hack Rails' nested resources lookup from new
|
31
|
+
# attributes params.
|
32
|
+
#
|
33
|
+
# This is necessary to be able to provide a resource to the #parse_input
|
34
|
+
# method when called on the nested resources hash
|
35
|
+
#
|
36
|
+
def fetch_or_build_nested_resource_for(parent, index, attributes)
|
37
|
+
nested_resources = parent.association(name).load_target
|
23
38
|
|
24
|
-
|
25
|
-
|
39
|
+
if (id = attributes['id'].presence)
|
40
|
+
nested_resources.find { |res| res.id == id.to_i }
|
41
|
+
else
|
42
|
+
parent.association(name).build(attributes.slice('type')).tap do |resource|
|
43
|
+
attributes['id'] = "__#{ index }"
|
44
|
+
temporarily_extend_new_resource(resource, attributes)
|
45
|
+
end
|
46
|
+
end
|
26
47
|
end
|
27
48
|
end
|
28
49
|
end
|
@@ -1,26 +1,45 @@
|
|
1
1
|
module Para
|
2
2
|
module AttributeField
|
3
3
|
class NestedOneField < AttributeField::BelongsToField
|
4
|
+
include Para::Helpers::AttributesMappings
|
5
|
+
include Para::AttributeField::NestedField
|
6
|
+
|
4
7
|
register :nested_one, self
|
5
8
|
|
6
|
-
def parse_input(params)
|
9
|
+
def parse_input(params, resource)
|
7
10
|
if (nested_attributes = params[nested_attributes_key])
|
8
|
-
|
9
|
-
|
11
|
+
mappings = nested_model_mappings(nested_attributes)
|
12
|
+
nested_resource = fetch_or_build_nested_resource_for(resource, nested_attributes)
|
13
|
+
|
14
|
+
mappings.fields.each do |field|
|
15
|
+
field.parse_input(nested_attributes, nested_resource)
|
10
16
|
end
|
11
17
|
|
12
18
|
params[nested_attributes_key] = nested_attributes
|
13
19
|
else
|
14
|
-
super
|
20
|
+
super
|
15
21
|
end
|
16
22
|
end
|
17
23
|
|
18
|
-
|
19
|
-
@nested_model_mappings ||= AttributeFieldMappings.new(reflection.klass)
|
20
|
-
end
|
24
|
+
private
|
21
25
|
|
22
|
-
|
23
|
-
|
26
|
+
# Force loading association and look for a resource matching the provided
|
27
|
+
# attributes. If no resource is found, one is created and a fake `id` is
|
28
|
+
# assigned to it to hack Rails' nested resources lookup from new
|
29
|
+
# attributes params.
|
30
|
+
#
|
31
|
+
# This is necessary to be able to provide a resource to the #parse_input
|
32
|
+
# method when called on the nested resources hash
|
33
|
+
#
|
34
|
+
def fetch_or_build_nested_resource_for(parent, attributes)
|
35
|
+
if (nested_resource = parent.association(name).load_target)
|
36
|
+
return nested_resource
|
37
|
+
end
|
38
|
+
|
39
|
+
parent.association(name).build(attributes.slice('type')).tap do |resource|
|
40
|
+
attributes['id'] = "__#{ object_id }"
|
41
|
+
temporarily_extend_new_resource(resource, attributes)
|
42
|
+
end
|
24
43
|
end
|
25
44
|
end
|
26
45
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Para
|
2
2
|
module AttributeField
|
3
3
|
class RelationField < AttributeField::Base
|
4
|
-
|
4
|
+
include Para::Helpers::ResourceName
|
5
5
|
|
6
6
|
def reflection
|
7
7
|
@reflection ||= model.reflect_on_association(name)
|
@@ -15,6 +15,24 @@ module Para
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
def through_relation
|
19
|
+
@through_relation ||= reflection.options[:through]
|
20
|
+
end
|
21
|
+
|
22
|
+
def through_reflection
|
23
|
+
@through_reflection ||= through_relation && model.reflect_on_association(through_relation)
|
24
|
+
end
|
25
|
+
|
26
|
+
def through_relation_source_foreign_key
|
27
|
+
@through_relation_source_foreign_key ||= reflection.source_reflection.foreign_key
|
28
|
+
end
|
29
|
+
|
30
|
+
def polymorphic_through_reflection?
|
31
|
+
!!(through_relation && reflection.source_reflection.options[:polymorphic])
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
18
36
|
def resource_name(resource)
|
19
37
|
Para.config.resource_name_methods.each do |method|
|
20
38
|
return resource.send(method) if resource.respond_to?(method)
|
@@ -2,11 +2,17 @@ module Para
|
|
2
2
|
class AttributeFieldMappings
|
3
3
|
UNEDITABLE_ATTRIBUTES = %w(id component_id created_at updated_at type)
|
4
4
|
|
5
|
-
attr_reader :model, :fields_hash, :whitelist_attributes
|
5
|
+
attr_reader :model, :fields_hash, :whitelist_attributes, :mappings
|
6
6
|
|
7
|
-
|
7
|
+
# The mappings hash is a form provided hash of attributes and input types
|
8
|
+
# mapping that are automatically generated in the form builder and that
|
9
|
+
# allows our model field parsers to spot unregistered fields and process
|
10
|
+
# them when needed.
|
11
|
+
#
|
12
|
+
def initialize(model, whitelist_attributes: nil, mappings: nil)
|
8
13
|
@model = model
|
9
14
|
@whitelist_attributes = whitelist_attributes
|
15
|
+
@mappings = mappings || {}
|
10
16
|
|
11
17
|
process_fields!
|
12
18
|
end
|
@@ -52,7 +58,7 @@ module Para
|
|
52
58
|
end
|
53
59
|
end.with_indifferent_access
|
54
60
|
|
55
|
-
Para::ModelFieldParsers.parse!(model, fields_hash)
|
61
|
+
Para::ModelFieldParsers.parse!(model, fields_hash, mappings)
|
56
62
|
end
|
57
63
|
|
58
64
|
def build_field_for(attribute_name, type)
|
@@ -1,42 +1,89 @@
|
|
1
1
|
module Para
|
2
2
|
module Breadcrumbs
|
3
3
|
class Breadcrumb
|
4
|
-
|
4
|
+
include ActionDispatch::Routing::PolymorphicRoutes
|
5
|
+
include Para::Helpers::ResourceName
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
attr_reader :resource_or_identifier, :_path, :controller, :options
|
8
|
+
|
9
|
+
def initialize(resource_or_identifier, path, controller, *options)
|
10
|
+
@resource_or_identifier = resource_or_identifier
|
8
11
|
@_path = path
|
12
|
+
@controller = controller
|
9
13
|
@options = options
|
10
14
|
end
|
11
15
|
|
12
16
|
def title
|
13
|
-
@title ||= if Symbol
|
14
|
-
|
17
|
+
@title ||= if resource_or_identifier.is_a?(Symbol)
|
18
|
+
translate(resource_or_identifier)
|
19
|
+
elsif resource_or_identifier.is_a?(ActiveRecord::Base)
|
20
|
+
resource_name(resource_or_identifier)
|
15
21
|
else
|
16
|
-
|
22
|
+
resource_or_identifier
|
17
23
|
end
|
18
24
|
end
|
19
25
|
|
20
26
|
# Allow lazy evaluation of routes to define breadcrumbs before being
|
21
27
|
# able to access request or routes
|
28
|
+
#
|
22
29
|
def path
|
23
|
-
@path ||= if Symbol
|
30
|
+
@path ||= if _path.is_a?(Symbol)
|
24
31
|
find_route_for(_path, *options)
|
25
32
|
elsif _path
|
26
33
|
_path
|
27
34
|
else
|
28
|
-
|
35
|
+
begin
|
36
|
+
polymorphic_path(resource_or_identifier)
|
37
|
+
rescue
|
38
|
+
'#'
|
39
|
+
end
|
29
40
|
end
|
30
41
|
end
|
31
42
|
|
32
43
|
def active?(request)
|
33
|
-
path == request.path ||
|
44
|
+
path == request.path || path == '#'
|
34
45
|
end
|
35
46
|
|
36
47
|
private
|
37
48
|
|
49
|
+
def translate(key)
|
50
|
+
if controller.admin?
|
51
|
+
::I18n.t("admin.breadcrumbs.#{ resource_or_identifier }")
|
52
|
+
else
|
53
|
+
# Check if a specific translation has been defined
|
54
|
+
if (translation = ::I18n.t("breadcrumbs.#{ resource_or_identifier }", default: '')).present?
|
55
|
+
translation
|
56
|
+
else
|
57
|
+
# If no translation is defined, we check if there's a plural model
|
58
|
+
# translation associated to the given key
|
59
|
+
begin
|
60
|
+
klass = key.to_s.singularize.camelize.constantize
|
61
|
+
klass.try(:model_name).try(:human, count: 2) || key
|
62
|
+
rescue NameError
|
63
|
+
key
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
38
69
|
def find_route_for(path, *options)
|
39
|
-
|
70
|
+
path = path_method?(path) ? path.to_sym : :"#{ path }_path"
|
71
|
+
Rails.application.routes.url_helpers.send(path, *options)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Allow #polymorphic_path to work by delegating missing methods ending
|
75
|
+
# with _path or _url to be tried on url_helpers
|
76
|
+
#
|
77
|
+
def method_missing(method_name, *args, &block)
|
78
|
+
if path_method?(method_name)
|
79
|
+
Rails.application.routes.url_helpers.try(method_name, *args) || super
|
80
|
+
else
|
81
|
+
super
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def path_method?(path)
|
86
|
+
path.to_s.match(/_(path|url)\z/)
|
40
87
|
end
|
41
88
|
end
|
42
89
|
end
|
@@ -6,6 +6,8 @@ module Para
|
|
6
6
|
included do
|
7
7
|
class_attribute :_class_level_breadcrumbs
|
8
8
|
|
9
|
+
before_action :build_breadcrumbs_manager
|
10
|
+
|
9
11
|
helper_method :add_breadcrumb, :breadcrumbs
|
10
12
|
helper ViewHelper
|
11
13
|
end
|
@@ -15,11 +17,18 @@ module Para
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def breadcrumbs
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
build_breadcrumbs_manager
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def build_breadcrumbs_manager
|
26
|
+
Para.store['para.breadcrumbs'] ||=
|
27
|
+
Breadcrumbs::Manager.new(self).tap do |manager|
|
28
|
+
if _class_level_breadcrumbs
|
29
|
+
_class_level_breadcrumbs.each { |args| manager.add(*args) }
|
30
|
+
end
|
31
|
+
end
|
23
32
|
end
|
24
33
|
|
25
34
|
module ClassMethods
|
@@ -30,8 +39,12 @@ module Para
|
|
30
39
|
end
|
31
40
|
|
32
41
|
module ViewHelper
|
42
|
+
# Render the breadcrumbs view depending wether it is in the admin or
|
43
|
+
# in front, allowing the front view to be overriden in app
|
44
|
+
#
|
33
45
|
def render_breadcrumbs
|
34
|
-
|
46
|
+
prefix = controller.admin? ? 'para/admin/' : ''
|
47
|
+
render partial: "#{ prefix }shared/breadcrumbs"
|
35
48
|
end
|
36
49
|
end
|
37
50
|
end
|