para 0.4.0 → 0.5.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/loading-spinner.gif +0 -0
- data/app/assets/javascripts/para/admin/theme_actions.coffee +0 -1
- data/app/assets/javascripts/para/lib/turbolinks-forms.coffee +23 -0
- data/app/assets/javascripts/para/lib/turbolinks-loading.coffee +25 -0
- data/app/assets/stylesheets/para/{overrides → admin/src}/datetimepicker.sass +1 -3
- data/app/assets/stylesheets/para/{overrides → admin/src}/fuelux.sass +5 -8
- data/app/assets/stylesheets/para/{overrides → admin/src}/jasny.bootstrap.sass +1 -2
- data/app/assets/stylesheets/para/admin/src/page-loading.sass +24 -0
- data/app/assets/stylesheets/para/{overrides → admin/src}/redactor.sass +5 -7
- data/app/assets/stylesheets/para/{overrides → admin/src}/selectize.sass +4 -6
- data/app/assets/stylesheets/para/{overrides → admin/src}/slider.sass +0 -1
- data/app/assets/stylesheets/para/admin/theme/_base.sass +5 -3
- data/app/assets/stylesheets/para/admin/theme/_breadcrumb.sass +54 -16
- data/app/assets/stylesheets/para/admin/theme/_buttons.sass +0 -1
- data/app/assets/stylesheets/para/admin/theme/_checkable.sass +5 -6
- data/app/assets/stylesheets/para/admin/theme/_commonds.sass +10 -16
- data/app/assets/stylesheets/para/admin/theme/_dropdown.sass +1 -4
- data/app/assets/stylesheets/para/admin/theme/_form.sass +11 -3
- data/app/assets/stylesheets/para/admin/theme/_list.sass +5 -6
- data/app/assets/stylesheets/para/admin/theme/_navigation.sass +105 -109
- data/app/assets/stylesheets/para/admin/theme/_navtabs.sass +35 -15
- data/app/assets/stylesheets/para/admin/theme/_orderable.sass +2 -5
- data/app/assets/stylesheets/para/admin/theme/_panel.sass +20 -50
- data/app/assets/stylesheets/para/admin/theme/_sorting.sass +5 -7
- data/app/assets/stylesheets/para/admin/theme/_tree.sass +2 -4
- data/app/assets/stylesheets/para/admin.sass +1 -0
- data/app/assets/stylesheets/para/lib/_variables.scss +12 -12
- data/app/assets/stylesheets/para/overrides/responsive.sass +1 -2
- data/app/assets/stylesheets/para/overrides/theme.sass +10 -17
- data/app/controllers/para/admin/base_controller.rb +16 -5
- data/app/controllers/para/admin/crud_resources_controller.rb +43 -2
- data/app/controllers/para/admin/main_controller.rb +1 -1
- data/app/controllers/para/admin/resources_controller.rb +1 -1
- data/app/controllers/para/admin/settings_component_controller.rb +1 -3
- data/app/controllers/para/application_controller.rb +3 -3
- data/app/decorators/para/component/crud_decorator.rb +6 -2
- data/app/decorators/para/component/singleton_resource_decorator.rb +5 -1
- data/app/helpers/para/admin/base_helper.rb +9 -4
- data/app/helpers/para/admin/components_helper.rb +7 -0
- data/app/helpers/para/form_helper.rb +10 -2
- data/app/helpers/para/tag_helper.rb +12 -0
- data/app/models/para/ability.rb +12 -0
- data/app/models/para/component/base.rb +15 -7
- data/app/models/para/component/crud.rb +3 -1
- data/app/models/para/component/singleton_resource.rb +1 -1
- data/app/views/para/admin/crud_resources/index.html.haml +4 -0
- data/app/views/para/admin/dashboard.html.haml +10 -8
- data/app/views/para/admin/resources/_actions.html.haml +7 -0
- data/app/views/para/admin/resources/_add_button.html.haml +1 -0
- data/app/views/para/admin/resources/_filters.html.haml +1 -1
- data/app/views/para/admin/resources/_imports_menu.html.haml +22 -0
- data/app/views/para/admin/resources/_list.html.haml +8 -5
- data/app/views/para/admin/resources/_subclassable_add_button.html.haml +10 -0
- data/app/views/para/admin/resources/_tree.html.haml +1 -1
- data/app/views/para/admin/resources/_tree_item.html.haml +1 -1
- data/app/views/para/admin/resources/new.html.haml +1 -1
- data/app/views/para/admin/shared/_breadcrumbs.html.haml +8 -0
- data/app/views/para/admin/shared/_header.html.haml +26 -24
- data/app/views/para/admin/shared/_navigation.html.haml +5 -3
- data/app/views/para/form/_tabs.html.haml +13 -0
- data/app/views/para/inputs/_nested_many.html.haml +2 -2
- data/app/views/para/inputs/_nested_many_container.html.haml +1 -3
- data/config/locales/en.yml +10 -0
- data/config/locales/fr.yml +30 -15
- data/db/migrate/20160304113055_add_json_equality_operator_patch_to_postgres.rb +38 -0
- data/lib/generators/para/component/component_generator.rb +9 -29
- data/lib/generators/para/component/crud/crud_generator.rb +41 -0
- data/lib/generators/para/component/templates/component.rb +1 -1
- data/lib/generators/para/component/templates/decorator.rb +3 -0
- data/lib/generators/para/component/templates/resources_controller.rb +4 -0
- data/lib/generators/para/exporter/templates/base_exporter.rb +2 -0
- data/lib/generators/para/exporter/templates/csv_exporter.rb +2 -0
- data/lib/generators/para/filters/filters_generator.rb +16 -0
- data/lib/generators/para/filters/templates/_filters.html.haml +9 -0
- data/lib/generators/para/importer/importer_generator.rb +20 -0
- data/lib/generators/para/importer/templates/base_importer.rb +5 -0
- data/lib/generators/para/install/install_generator.rb +6 -25
- data/lib/generators/para/nested_fields/nested_fields_generator.rb +9 -0
- data/lib/para/attribute_field/base.rb +28 -0
- data/lib/para/attribute_field/belongs_to.rb +2 -0
- data/lib/para/attribute_field/boolean.rb +2 -0
- data/lib/para/attribute_field/datetime.rb +2 -0
- data/lib/para/attribute_field/enum.rb +22 -0
- data/lib/para/attribute_field/file.rb +2 -0
- data/lib/para/attribute_field/has_many.rb +2 -0
- data/lib/para/attribute_field/image.rb +2 -0
- data/lib/para/attribute_field/nested_many.rb +3 -0
- data/lib/para/attribute_field/nested_one.rb +6 -6
- data/lib/para/attribute_field/password.rb +2 -0
- data/lib/para/attribute_field/redactor.rb +2 -0
- data/lib/para/attribute_field/translation.rb +2 -0
- data/lib/para/attribute_field.rb +19 -0
- data/lib/para/attribute_field_mappings.rb +15 -29
- data/lib/para/breadcrumbs/breadcrumb.rb +43 -0
- data/lib/para/breadcrumbs/controller.rb +39 -0
- data/lib/para/breadcrumbs/manager.rb +19 -0
- data/lib/para/breadcrumbs.rb +9 -0
- data/lib/para/component/importable.rb +25 -0
- data/lib/para/component/subclassable.rb +27 -0
- data/lib/para/component.rb +5 -3
- data/lib/para/components_configuration.rb +18 -2
- data/lib/para/config.rb +25 -1
- data/lib/para/exporter/base.rb +13 -0
- data/lib/para/exporter/csv.rb +1 -1
- data/lib/para/form_builder/tabs.rb +56 -0
- data/lib/para/form_builder.rb +2 -0
- data/lib/para/generators/component_helpers.rb +57 -0
- data/lib/para/generators.rb +1 -0
- data/lib/para/importer/base.rb +23 -0
- data/lib/para/importer.rb +10 -0
- data/lib/para/inputs/nested_one_input.rb +13 -3
- data/lib/para/markup/resources_table.rb +48 -24
- data/lib/para/markup/resources_tree.rb +36 -0
- data/lib/para/model_field_parsers/store.rb +23 -0
- data/lib/para/model_field_parsers.rb +1 -0
- data/lib/para/orderable.rb +6 -3
- data/lib/para/plugins/routes.rb +25 -0
- data/lib/para/plugins.rb +11 -0
- data/lib/para/routes.rb +2 -25
- data/lib/para/version.rb +1 -1
- data/lib/para.rb +4 -2
- data/lib/rails/routing_mapper.rb +64 -5
- metadata +50 -64
- data/app/controllers/para/admin/crud_component_controller.rb +0 -17
- data/app/controllers/para/admin/singleton_resource_component_controller.rb +0 -14
- data/app/views/para/admin/component_sections/_form.html.haml +0 -10
- data/app/views/para/admin/component_sections/edit.html.haml +0 -5
- data/app/views/para/admin/component_sections/new.html.haml +0 -5
- data/app/views/para/admin/components/_form.html.haml +0 -15
- data/app/views/para/admin/components/new.html.haml +0 -4
- data/app/views/para/admin/shared/_breadcrumb.html.haml +0 -3
- /data/app/views/para/admin/{singleton_resource_component → singleton_resources}/show.html.haml +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Para
|
|
2
|
+
module AttributeField
|
|
3
|
+
class EnumField < AttributeField::Base
|
|
4
|
+
register :enum, self
|
|
5
|
+
|
|
6
|
+
def value_for(instance)
|
|
7
|
+
if (raw_value = instance.send(name)) &&
|
|
8
|
+
path = enum_path_for(instance, raw_value)
|
|
9
|
+
translation = I18n.t("activerecord.#{ path }", default: false)
|
|
10
|
+
|
|
11
|
+
translation || raw_value
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def enum_path_for(instance, key)
|
|
18
|
+
['enums', instance.class.model_name.i18n_key, name, key].join('.')
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
module Para
|
|
2
2
|
module AttributeField
|
|
3
3
|
class NestedManyField < AttributeField::HasManyField
|
|
4
|
+
register :nested_many, self
|
|
5
|
+
|
|
4
6
|
def parse_input(params)
|
|
5
7
|
if (nested_attributes = params[nested_attributes_key])
|
|
6
8
|
nested_attributes.each do |index, attributes|
|
|
7
9
|
nested_model_mappings.fields.each do |field|
|
|
8
10
|
field.parse_input(attributes)
|
|
9
11
|
end
|
|
12
|
+
|
|
10
13
|
params[nested_attributes_key][index] = attributes
|
|
11
14
|
end
|
|
12
15
|
else
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
module Para
|
|
2
2
|
module AttributeField
|
|
3
3
|
class NestedOneField < AttributeField::BelongsToField
|
|
4
|
+
register :nested_one, self
|
|
5
|
+
|
|
4
6
|
def parse_input(params)
|
|
5
7
|
if (nested_attributes = params[nested_attributes_key])
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
field.parse_input(attributes)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
params[nested_attributes_key][index] = attributes
|
|
8
|
+
nested_model_mappings.fields.each do |field|
|
|
9
|
+
field.parse_input(nested_attributes)
|
|
12
10
|
end
|
|
11
|
+
|
|
12
|
+
params[nested_attributes_key] = nested_attributes
|
|
13
13
|
else
|
|
14
14
|
super(params)
|
|
15
15
|
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Para
|
|
2
|
+
module AttributeField
|
|
3
|
+
end
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
require 'para/attribute_field/base'
|
|
7
|
+
require 'para/attribute_field/boolean'
|
|
8
|
+
require 'para/attribute_field/datetime'
|
|
9
|
+
require 'para/attribute_field/password'
|
|
10
|
+
require 'para/attribute_field/file'
|
|
11
|
+
require 'para/attribute_field/image'
|
|
12
|
+
require 'para/attribute_field/enum'
|
|
13
|
+
require 'para/attribute_field/relation'
|
|
14
|
+
require 'para/attribute_field/belongs_to'
|
|
15
|
+
require 'para/attribute_field/has_many'
|
|
16
|
+
require 'para/attribute_field/nested_one'
|
|
17
|
+
require 'para/attribute_field/nested_many'
|
|
18
|
+
require 'para/attribute_field/redactor'
|
|
19
|
+
require 'para/attribute_field/translation'
|
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
require 'para/attribute_field/base'
|
|
2
|
-
require 'para/attribute_field/boolean'
|
|
3
|
-
require 'para/attribute_field/datetime'
|
|
4
|
-
require 'para/attribute_field/password'
|
|
5
|
-
require 'para/attribute_field/file'
|
|
6
|
-
require 'para/attribute_field/image'
|
|
7
|
-
require 'para/attribute_field/relation'
|
|
8
|
-
require 'para/attribute_field/belongs_to'
|
|
9
|
-
require 'para/attribute_field/has_many'
|
|
10
|
-
require 'para/attribute_field/nested_one'
|
|
11
|
-
require 'para/attribute_field/nested_many'
|
|
12
|
-
require 'para/attribute_field/redactor'
|
|
13
|
-
require 'para/attribute_field/translation'
|
|
14
|
-
|
|
15
1
|
module Para
|
|
16
2
|
class AttributeFieldMappings
|
|
17
3
|
UNEDITABLE_ATTRIBUTES = %w(id component_id created_at updated_at type)
|
|
@@ -30,13 +16,19 @@ module Para
|
|
|
30
16
|
end
|
|
31
17
|
|
|
32
18
|
def field_for(field_name, type = nil)
|
|
33
|
-
fields_hash[field_name]
|
|
34
|
-
|
|
19
|
+
existing_field = fields_hash[field_name]
|
|
20
|
+
|
|
21
|
+
if !existing_field || (type && !existing_field.type?(type))
|
|
22
|
+
fields_hash[field_name] = if model.new.respond_to?(field_name)
|
|
23
|
+
build_field_for(field_name, type)
|
|
24
|
+
else
|
|
25
|
+
raise NoMethodError.new(
|
|
26
|
+
"No attribute or method correspond to ##{ field_name } " +
|
|
27
|
+
"in the model #{ model.name }. No field could be created."
|
|
28
|
+
)
|
|
29
|
+
end
|
|
35
30
|
else
|
|
36
|
-
|
|
37
|
-
"No attribute or method correspond to ##{ field_name } " +
|
|
38
|
-
"in the model #{ model.name }. No field could be created."
|
|
39
|
-
)
|
|
31
|
+
existing_field
|
|
40
32
|
end
|
|
41
33
|
end
|
|
42
34
|
|
|
@@ -65,18 +57,12 @@ module Para
|
|
|
65
57
|
|
|
66
58
|
def build_field_for(attribute_name, type)
|
|
67
59
|
field_class = field_class_for(type)
|
|
68
|
-
|
|
69
|
-
field_class.new(
|
|
70
|
-
model, name: attribute_name, type: type
|
|
71
|
-
)
|
|
60
|
+
field_class.new(model, name: attribute_name, type: type)
|
|
72
61
|
end
|
|
73
62
|
|
|
74
63
|
def field_class_for(type)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
when :date, :datetime then AttributeField::DatetimeField
|
|
78
|
-
else AttributeField::Base
|
|
79
|
-
end
|
|
64
|
+
attribute_class = type && AttributeField::Base.field_types[type.to_sym]
|
|
65
|
+
attribute_class || AttributeField::Base
|
|
80
66
|
end
|
|
81
67
|
end
|
|
82
68
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Para
|
|
2
|
+
module Breadcrumbs
|
|
3
|
+
class Breadcrumb
|
|
4
|
+
attr_reader :identifier, :_path, :options
|
|
5
|
+
|
|
6
|
+
def initialize(identifier, path, *options)
|
|
7
|
+
@identifier = identifier
|
|
8
|
+
@_path = path
|
|
9
|
+
@options = options
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def title
|
|
13
|
+
@title ||= if Symbol === identifier
|
|
14
|
+
I18n.t("admin.breadcrumbs.#{ identifier }")
|
|
15
|
+
else
|
|
16
|
+
identifier
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Allow lazy evaluation of routes to define breadcrumbs before being
|
|
21
|
+
# able to access request or routes
|
|
22
|
+
def path
|
|
23
|
+
@path ||= if Symbol === _path
|
|
24
|
+
find_route_for(_path, *options)
|
|
25
|
+
elsif _path
|
|
26
|
+
_path
|
|
27
|
+
else
|
|
28
|
+
'#'
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def active?(request)
|
|
33
|
+
path == request.path || !_path
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def find_route_for(path, *options)
|
|
39
|
+
Rails.application.routes.url_helpers.send(:"#{ path }_path", *options)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Para
|
|
2
|
+
module Breadcrumbs
|
|
3
|
+
module Controller
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
class_attribute :_class_level_breadcrumbs
|
|
8
|
+
|
|
9
|
+
helper_method :add_breadcrumb, :breadcrumbs
|
|
10
|
+
helper ViewHelper
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def add_breadcrumb(*args)
|
|
14
|
+
breadcrumbs.add(*args)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def breadcrumbs
|
|
18
|
+
Para.store[:breadcrumbs] ||= begin
|
|
19
|
+
manager = Breadcrumbs::Manager.new
|
|
20
|
+
_class_level_breadcrumbs.each { |args| manager.add(*args) }
|
|
21
|
+
manager
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module ClassMethods
|
|
26
|
+
def add_breadcrumb(*args)
|
|
27
|
+
self._class_level_breadcrumbs ||= []
|
|
28
|
+
self._class_level_breadcrumbs += [args]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
module ViewHelper
|
|
33
|
+
def render_breadcrumbs
|
|
34
|
+
render partial: 'para/admin/shared/breadcrumbs'
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Para
|
|
2
|
+
module Breadcrumbs
|
|
3
|
+
class Manager
|
|
4
|
+
include Enumerable
|
|
5
|
+
|
|
6
|
+
def add(identifier, path = nil, *args)
|
|
7
|
+
breadcrumbs << Breadcrumb.new(identifier, path, *args)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def breadcrumbs
|
|
11
|
+
@breadcrumbs ||= []
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def each(&block)
|
|
15
|
+
breadcrumbs.each(&block)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Para
|
|
2
|
+
module Component
|
|
3
|
+
module Importable
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
configurable_on :importers
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def importable?
|
|
11
|
+
@importable ||= imports.length > 0
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# TODO : Move :configuration column store to JSON instead of HStore
|
|
15
|
+
# which handles more data types and will help us avoid eval here
|
|
16
|
+
def imports
|
|
17
|
+
@imports ||= if importers.present?
|
|
18
|
+
eval(importers)
|
|
19
|
+
else
|
|
20
|
+
[]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Para
|
|
2
|
+
module Component
|
|
3
|
+
module Subclassable
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
configurable_on :subclasses
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def subclassable?
|
|
11
|
+
@subclassable ||= subclass_names.length > 0
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def subclassable_with?(class_name)
|
|
15
|
+
subclassable? && class_name.in?(subclass_names)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def subclass_names
|
|
19
|
+
@subclass_names ||= if subclasses.present?
|
|
20
|
+
eval(subclasses)
|
|
21
|
+
else
|
|
22
|
+
[]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lib/para/component.rb
CHANGED
|
@@ -4,9 +4,9 @@ module Para
|
|
|
4
4
|
@registered_components ||= {}
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
-
def self.registered_component?(
|
|
8
|
-
registered_components.any? do |
|
|
9
|
-
|
|
7
|
+
def self.registered_component?(identifier)
|
|
8
|
+
registered_components.any? do |component_identifier, _|
|
|
9
|
+
component_identifier == identifier
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
|
|
@@ -18,6 +18,8 @@ end
|
|
|
18
18
|
|
|
19
19
|
# Require concerns
|
|
20
20
|
require 'para/component/exportable'
|
|
21
|
+
require 'para/component/importable'
|
|
22
|
+
require 'para/component/subclassable'
|
|
21
23
|
|
|
22
24
|
# Require models
|
|
23
25
|
require 'para/component/base'
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
module Para
|
|
2
2
|
class ComponentsConfiguration
|
|
3
|
+
class UndefinedComponentTypeError < StandardError
|
|
4
|
+
end
|
|
5
|
+
|
|
3
6
|
def draw(&block)
|
|
4
7
|
return unless components_installed?
|
|
5
8
|
eager_load_components!
|
|
@@ -85,6 +88,12 @@ module Para
|
|
|
85
88
|
tables_exist
|
|
86
89
|
end
|
|
87
90
|
|
|
91
|
+
# Eager loads every file ending with _component.rb that's included in a
|
|
92
|
+
# $LOAD_PATH directory which ends in "/components"
|
|
93
|
+
#
|
|
94
|
+
# Note : This allows not to process too many folders, but makes it harder to
|
|
95
|
+
# plug gems into the components system
|
|
96
|
+
#
|
|
88
97
|
def eager_load_components!
|
|
89
98
|
$LOAD_PATH.each do |path|
|
|
90
99
|
next unless path.match(/\/components$/)
|
|
@@ -127,10 +136,17 @@ module Para
|
|
|
127
136
|
class Component
|
|
128
137
|
attr_accessor :identifier, :type, :options, :model
|
|
129
138
|
|
|
130
|
-
def initialize(identifier,
|
|
139
|
+
def initialize(identifier, type_identifier, options = {})
|
|
131
140
|
self.identifier = identifier.to_s
|
|
132
|
-
self.type = Para::Component.registered_components[
|
|
141
|
+
self.type = Para::Component.registered_components[type_identifier]
|
|
133
142
|
self.options = options
|
|
143
|
+
|
|
144
|
+
unless type
|
|
145
|
+
raise UndefinedComponentTypeError.new(
|
|
146
|
+
"Undefined Para component : #{ type_identifier }. " +
|
|
147
|
+
"Please ensure that your app or gems define this component type."
|
|
148
|
+
)
|
|
149
|
+
end
|
|
134
150
|
end
|
|
135
151
|
|
|
136
152
|
def refresh(attributes = {})
|
data/lib/para/config.rb
CHANGED
|
@@ -16,6 +16,30 @@ module Para
|
|
|
16
16
|
@@default_tree_max_depth = 3
|
|
17
17
|
|
|
18
18
|
mattr_accessor :resource_name_methods
|
|
19
|
-
@@resource_name_methods = [:name, :title]
|
|
19
|
+
@@resource_name_methods = [:admin_name, :admin_title, :name, :title]
|
|
20
|
+
|
|
21
|
+
mattr_accessor :ability_class_name
|
|
22
|
+
@@ability_class_name = 'Para::Ability'
|
|
23
|
+
|
|
24
|
+
mattr_accessor :plugins
|
|
25
|
+
@@plugins = []
|
|
26
|
+
|
|
27
|
+
# Allows accessing plugins root module to configure them through a method
|
|
28
|
+
# from the Para::Config class.
|
|
29
|
+
#
|
|
30
|
+
# Example :
|
|
31
|
+
#
|
|
32
|
+
# Para.config do |config|
|
|
33
|
+
# config.my_plugin.my_var = 'foo'
|
|
34
|
+
# end
|
|
35
|
+
#
|
|
36
|
+
def self.method_missing(method_name, *args, &block)
|
|
37
|
+
if plugins.include?(method_name)
|
|
38
|
+
plugin = Para::Plugins.module_name_for(method_name).constantize
|
|
39
|
+
block ? block.call(plugin) : plugin
|
|
40
|
+
else
|
|
41
|
+
super
|
|
42
|
+
end
|
|
43
|
+
end
|
|
20
44
|
end
|
|
21
45
|
end
|
data/lib/para/exporter/base.rb
CHANGED
|
@@ -2,11 +2,24 @@ module Para
|
|
|
2
2
|
module Exporter
|
|
3
3
|
class Base
|
|
4
4
|
attr_reader :resources
|
|
5
|
+
class_attribute :model_name
|
|
5
6
|
|
|
6
7
|
def initialize(resources)
|
|
7
8
|
@resources = resources
|
|
8
9
|
end
|
|
9
10
|
|
|
11
|
+
def model
|
|
12
|
+
@model ||= if (model_name = self.class.model_name)
|
|
13
|
+
model_name.constantize
|
|
14
|
+
else
|
|
15
|
+
raise 'You must define model to export in your exporter as following: `exports \'YourModelName\'`'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.exports model_name
|
|
20
|
+
self.model_name = model_name
|
|
21
|
+
end
|
|
22
|
+
|
|
10
23
|
def disposition
|
|
11
24
|
'inline'
|
|
12
25
|
end
|
data/lib/para/exporter/csv.rb
CHANGED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module Para
|
|
2
|
+
module FormBuilder
|
|
3
|
+
module Tabs
|
|
4
|
+
def tabs(&block)
|
|
5
|
+
tabs_manager = TabsManager.new(template, object)
|
|
6
|
+
block.call(tabs_manager)
|
|
7
|
+
|
|
8
|
+
template.render partial: 'para/form/tabs', locals: { tabs: tabs_manager.tabs }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class TabsManager
|
|
12
|
+
attr_reader :template, :object
|
|
13
|
+
|
|
14
|
+
def initialize(template, object)
|
|
15
|
+
@template = template
|
|
16
|
+
@object = object
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def tab(identifier, options = {}, &block)
|
|
20
|
+
tabs << Tab.new(template, object, identifier, options, &block)
|
|
21
|
+
nil
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def tabs
|
|
25
|
+
@tabs ||= []
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class Tab
|
|
30
|
+
attr_reader :template, :object, :identifier, :icon, :content
|
|
31
|
+
|
|
32
|
+
delegate :capture, to: :template
|
|
33
|
+
|
|
34
|
+
def initialize(template, object, identifier, options, &content_block)
|
|
35
|
+
@template = template
|
|
36
|
+
@object = object
|
|
37
|
+
@identifier = identifier
|
|
38
|
+
@content = capture { content_block.call }
|
|
39
|
+
@icon = options[:icon]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def title
|
|
43
|
+
if Symbol === identifier
|
|
44
|
+
I18n.t("forms.tabs.#{ object.class.model_name.i18n_key }.#{ identifier }")
|
|
45
|
+
else
|
|
46
|
+
identifier
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def dom_id
|
|
51
|
+
@dom_id = identifier.to_s.parameterize
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/para/form_builder.rb
CHANGED
|
@@ -5,6 +5,7 @@ require 'para/form_builder/field_mappings'
|
|
|
5
5
|
require 'para/form_builder/nested_form'
|
|
6
6
|
require 'para/form_builder/ordering'
|
|
7
7
|
require 'para/form_builder/settings'
|
|
8
|
+
require 'para/form_builder/tabs'
|
|
8
9
|
|
|
9
10
|
# We'll implement our own form builder later, but for now it would need to
|
|
10
11
|
# patch or override Cocoon to allow creating nested fields with our custom
|
|
@@ -17,6 +18,7 @@ SimpleForm::FormBuilder.class_eval do
|
|
|
17
18
|
include Para::FormBuilder::NestedForm
|
|
18
19
|
include Para::FormBuilder::Ordering
|
|
19
20
|
include Para::FormBuilder::Settings
|
|
21
|
+
include Para::FormBuilder::Tabs
|
|
20
22
|
end
|
|
21
23
|
|
|
22
24
|
SimpleForm::FormBuilder.map_type(:inet, to: SimpleForm::Inputs::StringInput)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Para
|
|
2
|
+
module Generators
|
|
3
|
+
module ComponentHelpers
|
|
4
|
+
private
|
|
5
|
+
|
|
6
|
+
def add_component_to_routes(component_type, name)
|
|
7
|
+
route_file = File.read(Rails.root.join('config/routes.rb'))
|
|
8
|
+
|
|
9
|
+
unless route_file.match /^\s+namespace :admin do/
|
|
10
|
+
route "namespace :admin do\n end\n"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
inject_into_file 'config/routes.rb', after: ' namespace :admin do' do
|
|
14
|
+
"\n #{ component_type } :#{ name }"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def component_name
|
|
19
|
+
if class_name.match(/Component/i)
|
|
20
|
+
class_name
|
|
21
|
+
else
|
|
22
|
+
"#{ class_name }Component"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def component_file_name
|
|
27
|
+
if file_name.match(/component/i)
|
|
28
|
+
file_name
|
|
29
|
+
else
|
|
30
|
+
"#{ file_name }_component"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def decorator_parent_name
|
|
35
|
+
@decorator_parent_name ||= [component_parent_name, 'Decorator'].join
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def resources_controller_name
|
|
39
|
+
@resources_name ||= [
|
|
40
|
+
singular_name.singularize, 'resources', 'controller'
|
|
41
|
+
].join('_')
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def controller_name
|
|
45
|
+
@controller_name ||= resources_controller_name.camelize
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def decorator_file_name
|
|
49
|
+
@decorator_file_name ||= [component_file_name, 'decorator'].join('_')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def decorator_name
|
|
53
|
+
@decorator_name ||= decorator_file_name.camelize
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
data/lib/para/generators.rb
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Para
|
|
2
|
+
module Importer
|
|
3
|
+
class Base
|
|
4
|
+
attr_reader :sheet
|
|
5
|
+
|
|
6
|
+
def initialize(file)
|
|
7
|
+
@sheet = Roo::Spreadsheet.open(file.path)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def run
|
|
11
|
+
ActiveRecord::Base.transaction do
|
|
12
|
+
(2..(sheet.last_row)).each do |index|
|
|
13
|
+
import_from_row(sheet.row(index))
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def import_from_row(row)
|
|
19
|
+
raise '#import_from_row(row) must be defined'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|