para 0.4.0 → 0.5.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/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
|