para 0.6.9 → 0.7.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 +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
|