wallaby 4.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +29 -0
- data/app/assets/javascripts/wallaby/application.js +15 -0
- data/app/assets/javascripts/wallaby/form.js +8 -0
- data/app/assets/stylesheets/wallaby/application.scss +51 -0
- data/app/assets/stylesheets/wallaby/base/_functions.scss +0 -0
- data/app/assets/stylesheets/wallaby/base/_layout.scss +14 -0
- data/app/assets/stylesheets/wallaby/base/_mixins.scss +0 -0
- data/app/assets/stylesheets/wallaby/base/_normalize.scss +0 -0
- data/app/assets/stylesheets/wallaby/base/_reset.scss +0 -0
- data/app/assets/stylesheets/wallaby/base/_vars.scss +5 -0
- data/app/assets/stylesheets/wallaby/components/_forms.scss +53 -0
- data/app/assets/stylesheets/wallaby/components/_nav.scss +19 -0
- data/app/assets/stylesheets/wallaby/components/_pagination.scss +105 -0
- data/app/assets/stylesheets/wallaby/components/_tables.scss +78 -0
- data/app/assets/stylesheets/wallaby/components/_text.scss +11 -0
- data/app/assets/stylesheets/wallaby/form.scss +11 -0
- data/app/assets/stylesheets/wallaby/summernote.scss.erb +7 -0
- data/app/controllers/wallaby/application_controller.rb +21 -0
- data/app/controllers/wallaby/core_controller.rb +28 -0
- data/app/controllers/wallaby/resources_controller.rb +134 -0
- data/app/controllers/wallaby/secure_controller.rb +42 -0
- data/app/routes/wallaby/resources_router.rb +52 -0
- data/app/security/ability.rb +33 -0
- data/app/views/layouts/wallaby/_footer.html.erb +2 -0
- data/app/views/layouts/wallaby/_header.html.erb +57 -0
- data/app/views/layouts/wallaby/_navs.html.erb +1 -0
- data/app/views/layouts/wallaby/application.html.erb +22 -0
- data/app/views/layouts/wallaby/error.html.erb +20 -0
- data/app/views/wallaby/core/home.html.erb +5 -0
- data/app/views/wallaby/errors/access_denied.html.erb +1 -0
- data/app/views/wallaby/errors/not_authenticated.html.erb +1 -0
- data/app/views/wallaby/errors/not_found.html.erb +6 -0
- data/app/views/wallaby/errors/unprocessable_entity.erb +1 -0
- data/app/views/wallaby/resources/_form.html.erb +12 -0
- data/app/views/wallaby/resources/_index_actions.html.erb +1 -0
- data/app/views/wallaby/resources/_resource_actions.html.erb +3 -0
- data/app/views/wallaby/resources/edit.html.erb +14 -0
- data/app/views/wallaby/resources/form/_belongs_to.html.erb +21 -0
- data/app/views/wallaby/resources/form/_bigint.html.erb +9 -0
- data/app/views/wallaby/resources/form/_binary.html.erb +12 -0
- data/app/views/wallaby/resources/form/_bit.html.erb +9 -0
- data/app/views/wallaby/resources/form/_bit_varying.html.erb +9 -0
- data/app/views/wallaby/resources/form/_boolean.html.erb +14 -0
- data/app/views/wallaby/resources/form/_cidr.html.erb +9 -0
- data/app/views/wallaby/resources/form/_citext.html.erb +21 -0
- data/app/views/wallaby/resources/form/_color.html.erb +20 -0
- data/app/views/wallaby/resources/form/_date.html.erb +29 -0
- data/app/views/wallaby/resources/form/_daterange.html.erb +37 -0
- data/app/views/wallaby/resources/form/_datetime.html.erb +30 -0
- data/app/views/wallaby/resources/form/_decimal.html.erb +9 -0
- data/app/views/wallaby/resources/form/_email.html.erb +5 -0
- data/app/views/wallaby/resources/form/_float.html.erb +9 -0
- data/app/views/wallaby/resources/form/_has_and_belongs_to_many.html.erb +13 -0
- data/app/views/wallaby/resources/form/_has_many.html.erb +13 -0
- data/app/views/wallaby/resources/form/_has_one.html.erb +7 -0
- data/app/views/wallaby/resources/form/_hstore.html.erb +25 -0
- data/app/views/wallaby/resources/form/_inet.html.erb +9 -0
- data/app/views/wallaby/resources/form/_int4range.html.erb +18 -0
- data/app/views/wallaby/resources/form/_int8range.html.erb +18 -0
- data/app/views/wallaby/resources/form/_integer.html.erb +9 -0
- data/app/views/wallaby/resources/form/_json.html.erb +23 -0
- data/app/views/wallaby/resources/form/_jsonb.html.erb +23 -0
- data/app/views/wallaby/resources/form/_ltree.html.erb +5 -0
- data/app/views/wallaby/resources/form/_macaddr.html.erb +9 -0
- data/app/views/wallaby/resources/form/_money.html.erb +12 -0
- data/app/views/wallaby/resources/form/_numrange.html.erb +18 -0
- data/app/views/wallaby/resources/form/_password.html.erb +5 -0
- data/app/views/wallaby/resources/form/_point.html.erb +18 -0
- data/app/views/wallaby/resources/form/_string.html.erb +5 -0
- data/app/views/wallaby/resources/form/_text.html.erb +21 -0
- data/app/views/wallaby/resources/form/_time.html.erb +29 -0
- data/app/views/wallaby/resources/form/_tsrange.html.erb +38 -0
- data/app/views/wallaby/resources/form/_tstzrange.html.erb +38 -0
- data/app/views/wallaby/resources/form/_tsvector.html.erb +5 -0
- data/app/views/wallaby/resources/form/_uuid.html.erb +9 -0
- data/app/views/wallaby/resources/form/_xml.html.erb +23 -0
- data/app/views/wallaby/resources/index/_belongs_to.html.erb +1 -0
- data/app/views/wallaby/resources/index/_bigint.html.erb +1 -0
- data/app/views/wallaby/resources/index/_binary.html.erb +1 -0
- data/app/views/wallaby/resources/index/_bit.html.erb +5 -0
- data/app/views/wallaby/resources/index/_bit_varying.html.erb +5 -0
- data/app/views/wallaby/resources/index/_boolean.html.erb +5 -0
- data/app/views/wallaby/resources/index/_cidr.html.erb +6 -0
- data/app/views/wallaby/resources/index/_citext.html.erb +12 -0
- data/app/views/wallaby/resources/index/_color.html.erb +5 -0
- data/app/views/wallaby/resources/index/_date.html.erb +7 -0
- data/app/views/wallaby/resources/index/_daterange.html.erb +8 -0
- data/app/views/wallaby/resources/index/_datetime.html.erb +7 -0
- data/app/views/wallaby/resources/index/_decimal.html.erb +1 -0
- data/app/views/wallaby/resources/index/_email.html.erb +1 -0
- data/app/views/wallaby/resources/index/_float.html.erb +1 -0
- data/app/views/wallaby/resources/index/_has_and_belongs_to_many.html.erb +11 -0
- data/app/views/wallaby/resources/index/_has_many.html.erb +11 -0
- data/app/views/wallaby/resources/index/_has_one.html.erb +1 -0
- data/app/views/wallaby/resources/index/_hstore.html.erb +12 -0
- data/app/views/wallaby/resources/index/_inet.html.erb +6 -0
- data/app/views/wallaby/resources/index/_int4range.html.erb +7 -0
- data/app/views/wallaby/resources/index/_int8range.html.erb +7 -0
- data/app/views/wallaby/resources/index/_integer.html.erb +1 -0
- data/app/views/wallaby/resources/index/_json.html.erb +12 -0
- data/app/views/wallaby/resources/index/_jsonb.html.erb +12 -0
- data/app/views/wallaby/resources/index/_ltree.html.erb +12 -0
- data/app/views/wallaby/resources/index/_macaddr.html.erb +5 -0
- data/app/views/wallaby/resources/index/_money.html.erb +1 -0
- data/app/views/wallaby/resources/index/_numrange.html.erb +7 -0
- data/app/views/wallaby/resources/index/_point.html.erb +6 -0
- data/app/views/wallaby/resources/index/_string.html.erb +12 -0
- data/app/views/wallaby/resources/index/_text.html.erb +12 -0
- data/app/views/wallaby/resources/index/_time.html.erb +6 -0
- data/app/views/wallaby/resources/index/_tsrange.html.erb +8 -0
- data/app/views/wallaby/resources/index/_tstzrange.html.erb +8 -0
- data/app/views/wallaby/resources/index/_tsvector.html.erb +12 -0
- data/app/views/wallaby/resources/index/_uuid.html.erb +12 -0
- data/app/views/wallaby/resources/index/_xml.html.erb +12 -0
- data/app/views/wallaby/resources/index.html.erb +66 -0
- data/app/views/wallaby/resources/new.html.erb +14 -0
- data/app/views/wallaby/resources/shared/_resource_nav.html.erb +29 -0
- data/app/views/wallaby/resources/show/_belongs_to.html.erb +7 -0
- data/app/views/wallaby/resources/show/_bigint.html.erb +1 -0
- data/app/views/wallaby/resources/show/_binary.html.erb +1 -0
- data/app/views/wallaby/resources/show/_bit.html.erb +5 -0
- data/app/views/wallaby/resources/show/_bit_varying.html.erb +5 -0
- data/app/views/wallaby/resources/show/_boolean.html.erb +5 -0
- data/app/views/wallaby/resources/show/_cidr.html.erb +6 -0
- data/app/views/wallaby/resources/show/_citext.html.erb +1 -0
- data/app/views/wallaby/resources/show/_color.html.erb +5 -0
- data/app/views/wallaby/resources/show/_date.html.erb +7 -0
- data/app/views/wallaby/resources/show/_daterange.html.erb +7 -0
- data/app/views/wallaby/resources/show/_datetime.html.erb +6 -0
- data/app/views/wallaby/resources/show/_decimal.html.erb +1 -0
- data/app/views/wallaby/resources/show/_email.html.erb +1 -0
- data/app/views/wallaby/resources/show/_float.html.erb +1 -0
- data/app/views/wallaby/resources/show/_has_and_belongs_to_many.html.erb +5 -0
- data/app/views/wallaby/resources/show/_has_many.html.erb +5 -0
- data/app/views/wallaby/resources/show/_has_one.html.erb +1 -0
- data/app/views/wallaby/resources/show/_hstore.html.erb +5 -0
- data/app/views/wallaby/resources/show/_inet.html.erb +6 -0
- data/app/views/wallaby/resources/show/_int4range.html.erb +7 -0
- data/app/views/wallaby/resources/show/_int8range.html.erb +7 -0
- data/app/views/wallaby/resources/show/_integer.html.erb +1 -0
- data/app/views/wallaby/resources/show/_json.html.erb +5 -0
- data/app/views/wallaby/resources/show/_jsonb.html.erb +5 -0
- data/app/views/wallaby/resources/show/_ltree.html.erb +1 -0
- data/app/views/wallaby/resources/show/_macaddr.html.erb +5 -0
- data/app/views/wallaby/resources/show/_money.html.erb +1 -0
- data/app/views/wallaby/resources/show/_numrange.html.erb +7 -0
- data/app/views/wallaby/resources/show/_point.html.erb +6 -0
- data/app/views/wallaby/resources/show/_string.html.erb +1 -0
- data/app/views/wallaby/resources/show/_text.html.erb +1 -0
- data/app/views/wallaby/resources/show/_time.html.erb +6 -0
- data/app/views/wallaby/resources/show/_tsrange.html.erb +7 -0
- data/app/views/wallaby/resources/show/_tstzrange.html.erb +7 -0
- data/app/views/wallaby/resources/show/_tsvector.html.erb +1 -0
- data/app/views/wallaby/resources/show/_uuid.html.erb +5 -0
- data/app/views/wallaby/resources/show/_xml.html.erb +5 -0
- data/app/views/wallaby/resources/show.html.erb +31 -0
- data/app/views/wallaby/shared/_flash_messages.html.erb +13 -0
- data/config/locales/en.yml +29 -0
- data/config/routes.rb +34 -0
- data/lib/adaptors/wallaby/active_record/model_decorator/fields_builder.rb +105 -0
- data/lib/adaptors/wallaby/active_record/model_decorator/title_field_finder.rb +18 -0
- data/lib/adaptors/wallaby/active_record/model_decorator.rb +81 -0
- data/lib/adaptors/wallaby/active_record/model_finder.rb +12 -0
- data/lib/adaptors/wallaby/active_record/model_operator/normalizer.rb +44 -0
- data/lib/adaptors/wallaby/active_record/model_operator/permitter.rb +50 -0
- data/lib/adaptors/wallaby/active_record/model_operator/querier.rb +47 -0
- data/lib/adaptors/wallaby/active_record/model_operator/validator.rb +16 -0
- data/lib/adaptors/wallaby/active_record/model_operator.rb +82 -0
- data/lib/adaptors/wallaby/active_record.rb +2 -0
- data/lib/decorators/wallaby/resource_decorator.rb +78 -0
- data/lib/errors/wallaby/deprecated.rb +4 -0
- data/lib/errors/wallaby/general_error.rb +4 -0
- data/lib/errors/wallaby/invalid_error.rb +4 -0
- data/lib/errors/wallaby/model_not_found.rb +4 -0
- data/lib/errors/wallaby/not_authenticated.rb +4 -0
- data/lib/errors/wallaby/not_implemented.rb +4 -0
- data/lib/errors/wallaby/operation_not_found.rb +4 -0
- data/lib/errors/wallaby/resource_not_found.rb +4 -0
- data/lib/forms/wallaby/form_builder.rb +30 -0
- data/lib/handlers/wallaby/cached_compiled_erb.rb +14 -0
- data/lib/helpers/wallaby/application_helper.rb +30 -0
- data/lib/helpers/wallaby/core_helper.rb +50 -0
- data/lib/helpers/wallaby/form_helper.rb +21 -0
- data/lib/helpers/wallaby/links_helper.rb +83 -0
- data/lib/helpers/wallaby/paginatable_helper.rb +9 -0
- data/lib/helpers/wallaby/resources_helper.rb +55 -0
- data/lib/helpers/wallaby/secure_helper.rb +25 -0
- data/lib/helpers/wallaby/sorting_helper.rb +43 -0
- data/lib/helpers/wallaby/styling_helper.rb +57 -0
- data/lib/interfaces/wallaby/mode.rb +18 -0
- data/lib/interfaces/wallaby/model_decorator.rb +58 -0
- data/lib/interfaces/wallaby/model_finder.rb +5 -0
- data/lib/interfaces/wallaby/model_operator.rb +31 -0
- data/lib/services/wallaby/decorator_finder.rb +16 -0
- data/lib/services/wallaby/lookup_context_wrapper.rb +40 -0
- data/lib/services/wallaby/map.rb +53 -0
- data/lib/services/wallaby/model_servicer.rb +38 -0
- data/lib/services/wallaby/servicer_finder.rb +5 -0
- data/lib/tasks/wallaby_tasks.rake +4 -0
- data/lib/utils/wallaby/utils.rb +31 -0
- data/lib/wallaby/configuration/models.rb +17 -0
- data/lib/wallaby/configuration/security.rb +30 -0
- data/lib/wallaby/configuration.rb +49 -0
- data/lib/wallaby/engine.rb +89 -0
- data/lib/wallaby/version.rb +3 -0
- data/lib/wallaby.rb +5 -0
- metadata +459 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module Wallaby::LinksHelper
|
|
2
|
+
def index_path(model_class = nil, extra_params = nil)
|
|
3
|
+
model_class ||= current_model_class
|
|
4
|
+
extra_params ||= {}
|
|
5
|
+
wallaby_engine.resources_path to_resources_name(model_class), extra_params
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def new_path(model_class = nil)
|
|
9
|
+
model_class ||= current_model_class
|
|
10
|
+
wallaby_engine.new_resource_path to_resources_name model_class
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def show_path(resource)
|
|
14
|
+
decorated = decorate resource
|
|
15
|
+
wallaby_engine.resource_path decorated.resources_name, decorated.primary_key_value
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def edit_path(resource)
|
|
19
|
+
decorated = decorate resource
|
|
20
|
+
wallaby_engine.edit_resource_path decorated.resources_name, decorated.primary_key_value
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def index_link(model_class = nil, html_options = {}, &block)
|
|
24
|
+
model_class ||= current_model_class
|
|
25
|
+
return if cannot? :index, model_class
|
|
26
|
+
block ||= -> { to_model_label model_class }
|
|
27
|
+
|
|
28
|
+
link_to index_path(model_class, html_options.delete(:extra_params)), html_options, &block
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def new_link(model_class = nil, html_options = {}, &block)
|
|
32
|
+
model_class ||= current_model_class
|
|
33
|
+
return if cannot? :new, model_class
|
|
34
|
+
|
|
35
|
+
block ||= -> { "#{ ct 'link.new' } #{ to_model_label model_class }" }
|
|
36
|
+
html_options[:class] = 'text-success' unless html_options.has_key? :class
|
|
37
|
+
|
|
38
|
+
prepend_if html_options
|
|
39
|
+
link_to new_path(model_class), html_options, &block
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def show_link(resource, html_options = {}, &block)
|
|
43
|
+
return if cannot? :show, extract(resource)
|
|
44
|
+
|
|
45
|
+
# NOTE: to_s is a must
|
|
46
|
+
# if a block is returning integer (e.g. `{ 1 }`)
|
|
47
|
+
# `link_to` will render blank text note inside hyper link
|
|
48
|
+
block ||= -> { decorate(resource).to_label.to_s }
|
|
49
|
+
|
|
50
|
+
link_to show_path(resource), html_options, &block
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def edit_link(resource, html_options = {}, &block)
|
|
54
|
+
return if cannot? :edit, extract(resource)
|
|
55
|
+
|
|
56
|
+
block ||= -> { "#{ ct 'link.edit' } #{ decorate(resource).to_label }" }
|
|
57
|
+
html_options[:class] = 'text-warning' unless html_options.has_key? :class
|
|
58
|
+
|
|
59
|
+
link_to edit_path(resource), html_options, &block
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def delete_link(resource, html_options = {}, &block)
|
|
63
|
+
return if cannot? :destroy, extract(resource)
|
|
64
|
+
|
|
65
|
+
block ||= -> { ct 'link.delete' }
|
|
66
|
+
html_options[:class] = 'text-danger' unless html_options.has_key? :class
|
|
67
|
+
html_options[:method] ||= :delete
|
|
68
|
+
html_options[:data] ||= {}
|
|
69
|
+
html_options[:data][:confirm] ||= ct('link.confirm.delete')
|
|
70
|
+
|
|
71
|
+
link_to show_path(resource), html_options, &block
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def cancel_link(html_options = {}, &block)
|
|
75
|
+
block ||= -> { ct 'link.cancel' }
|
|
76
|
+
link_to :back, html_options, &block
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def prepend_if(html_options = {})
|
|
80
|
+
prepend = html_options.delete :prepend
|
|
81
|
+
concat "#{ prepend } " if prepend.present?
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module Wallaby::PaginatableHelper
|
|
2
|
+
def paginatable?(collection)
|
|
3
|
+
defined?(Kaminari) && collection.present? && collection.respond_to?(:total_pages)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def custom_pagination_stats(collection)
|
|
7
|
+
"Showing #{ content_tag :b, collection.size }".html_safe
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Wallaby::ResourcesHelper
|
|
2
|
+
include Wallaby::FormHelper
|
|
3
|
+
include Wallaby::SortingHelper
|
|
4
|
+
include Wallaby::PaginatableHelper
|
|
5
|
+
|
|
6
|
+
def decorate(resource)
|
|
7
|
+
if resource.respond_to? :map # collection
|
|
8
|
+
decorator = Wallaby::DecoratorFinder.find_resource resource.first.class
|
|
9
|
+
resource.map do |item|
|
|
10
|
+
decorator.decorate item
|
|
11
|
+
end
|
|
12
|
+
else
|
|
13
|
+
decorator = Wallaby::DecoratorFinder.find_resource resource.class
|
|
14
|
+
decorator.decorate resource
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def extract(resource)
|
|
19
|
+
if resource.is_a? Wallaby::ResourceDecorator
|
|
20
|
+
resource.resource
|
|
21
|
+
else
|
|
22
|
+
resource
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def model_decorator(model_class)
|
|
27
|
+
Wallaby::DecoratorFinder.find_model model_class
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def model_servicer(model_decorator)
|
|
31
|
+
model_class = model_decorator.model_class
|
|
32
|
+
Wallaby::ServicerFinder.find(model_class).new model_class, model_decorator
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def type_partial_render(options = {}, locals = {}, metadata_method = :show_metadata_of, &block)
|
|
36
|
+
decorated = locals[:object]
|
|
37
|
+
field_name = locals[:field_name].to_s
|
|
38
|
+
|
|
39
|
+
fail ArgumentError unless field_name.present? && decorated.is_a?(Wallaby::ResourceDecorator)
|
|
40
|
+
|
|
41
|
+
locals[:metadata] = decorated.send metadata_method, field_name
|
|
42
|
+
locals[:value] = decorated.public_send field_name
|
|
43
|
+
|
|
44
|
+
render(options, locals, &block) or render('string', locals, &block)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def index_type_partial_render(options = {}, locals = {}, &block)
|
|
48
|
+
type_partial_render options, locals, :index_metadata_of
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def show_title(decorated)
|
|
52
|
+
fail ArgumentError unless decorated.is_a? Wallaby::ResourceDecorator
|
|
53
|
+
[ to_model_label(decorated.model_class), decorated.to_label ].compact.join ': '
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Wallaby::SecureHelper
|
|
2
|
+
def user_portrait(user = current_user)
|
|
3
|
+
if user.respond_to? :email
|
|
4
|
+
image_source = "http#{ request.ssl? ? 's' : '' }://www.gravatar.com/avatar/#{ Digest::MD5.hexdigest user.email.downcase }"
|
|
5
|
+
image_tag image_source, class: 'hidden-xs user-portrait'
|
|
6
|
+
else
|
|
7
|
+
content_tag :i, nil, class: 'glyphicon glyphicon-user user-portrait'
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def logout_path(user = current_user, app = main_app)
|
|
12
|
+
path = if defined? Devise
|
|
13
|
+
scope = Devise::Mapping.find_scope! user
|
|
14
|
+
"destroy_#{ scope }_session_path"
|
|
15
|
+
else
|
|
16
|
+
'logout_path'
|
|
17
|
+
end
|
|
18
|
+
app.public_send path if app.respond_to? path
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def logout_method
|
|
22
|
+
method = Array(Devise.sign_out_via).first if defined? Devise
|
|
23
|
+
method || :delete
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Wallaby::SortingHelper
|
|
2
|
+
def sort_link(field_name, model_decorator = current_model_decorator)
|
|
3
|
+
metadata = model_decorator.index_metadata_of field_name
|
|
4
|
+
|
|
5
|
+
if metadata[:is_origin] && !metadata[:is_association] || metadata[:sort_field_name]
|
|
6
|
+
sort_field_name = metadata[:sort_field_name] || field_name
|
|
7
|
+
extra_params = next_sort_param sort_field_name
|
|
8
|
+
index_link(model_decorator.model_class, extra_params: extra_params) { metadata[:label] }
|
|
9
|
+
else
|
|
10
|
+
metadata[:label]
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def sort_hash
|
|
15
|
+
@sort_hash ||= begin
|
|
16
|
+
array = params[:sort].to_s.split(%r(\s*,\s*)).map{ |v| v.split %r(\s+) }
|
|
17
|
+
Wallaby::Utils.to_hash array
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def next_sort_param(field_name)
|
|
22
|
+
field_name = field_name.to_s
|
|
23
|
+
orders = [ 'asc', 'desc', nil ]
|
|
24
|
+
clean_params.tap do |hash|
|
|
25
|
+
sortings = sort_hash.dup
|
|
26
|
+
next_index = (orders.index(sortings[field_name]) + 1) % orders.length
|
|
27
|
+
if orders[next_index].nil?
|
|
28
|
+
sortings.delete field_name
|
|
29
|
+
else
|
|
30
|
+
sortings[field_name] = orders[next_index]
|
|
31
|
+
end
|
|
32
|
+
if sortings.present?
|
|
33
|
+
hash[:sort] = sortings.to_a.map{ |v| v.join ' ' }.join ','
|
|
34
|
+
else
|
|
35
|
+
hash.delete :sort
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def sort_class(field_name)
|
|
41
|
+
sort_hash[ field_name.to_s ]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Wallaby::StylingHelper
|
|
2
|
+
def icon(icon_suffix, html_options = {}, &block)
|
|
3
|
+
html_options[:class] = Array html_options[:class]
|
|
4
|
+
html_options[:class] << "glyphicon glyphicon-#{ icon_suffix }"
|
|
5
|
+
|
|
6
|
+
content_tag :i, nil, html_options, &block
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def itooltip(title, icon_suffix = 'info-sign', html_options = {})
|
|
10
|
+
html_options[:title] = title
|
|
11
|
+
(html_options[:data] ||= {}).merge! toggle: "tooltip", placement: "top"
|
|
12
|
+
|
|
13
|
+
icon icon_suffix, html_options
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def ilink_to(options = nil, html_options = {})
|
|
17
|
+
icon_suffix = html_options.delete(:icon) || 'info-sign'
|
|
18
|
+
link_to options, html_options do
|
|
19
|
+
icon icon_suffix
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def imodal(title, body, html_options = {})
|
|
24
|
+
uuid = random_uuid
|
|
25
|
+
label ||= html_options.delete(:label) ||
|
|
26
|
+
html_options.delete(:icon) ||
|
|
27
|
+
icon('circle-arrow-up')
|
|
28
|
+
link_to(label, 'javascript:;', data: { toggle: 'modal', target: "##{ uuid }" }) +
|
|
29
|
+
content_tag(:div, id: uuid, class: 'modal fade', tabindex: -1, role: 'dialog') do
|
|
30
|
+
content_tag :div, class: 'modal-dialog modal-lg' do
|
|
31
|
+
content_tag :div, class: 'modal-content' do
|
|
32
|
+
content_tag(:div, class: 'modal-header') do
|
|
33
|
+
button_tag(type: 'button', class: 'close', data: { dismiss: 'modal' }, aria: { label: 'Close' }) do
|
|
34
|
+
content_tag :span, raw('×'), aria: { hidden: true }
|
|
35
|
+
end +
|
|
36
|
+
content_tag(:h4, title, class: 'modal-title')
|
|
37
|
+
end +
|
|
38
|
+
content_tag(:div, class: 'modal-body') do
|
|
39
|
+
body
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def null
|
|
47
|
+
muted 'null'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def na
|
|
51
|
+
muted 'n/a'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def muted(content)
|
|
55
|
+
content_tag :i, "<#{ content }>", class: 'text-muted'
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class Wallaby::Mode
|
|
2
|
+
INTERFACE_METHODS = %w( model_decorator model_finder model_operator )
|
|
3
|
+
|
|
4
|
+
INTERFACE_METHODS.each do |method_id|
|
|
5
|
+
define_singleton_method method_id do
|
|
6
|
+
begin
|
|
7
|
+
method_class = __callee__.to_s.classify
|
|
8
|
+
class_name = "#{ name }::#{ method_class }"
|
|
9
|
+
parent_class = "Wallaby::#{ method_class }".constantize
|
|
10
|
+
class_name.constantize.tap do |klass|
|
|
11
|
+
fail Wallaby::InvalidError, "#{ klass } must inherit #{ parent_class }" unless klass < parent_class
|
|
12
|
+
end
|
|
13
|
+
rescue NameError
|
|
14
|
+
fail Wallaby::NotImplemented, class_name
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
class Wallaby::ModelDecorator
|
|
2
|
+
attr_reader :model_class
|
|
3
|
+
|
|
4
|
+
def initialize(model_class)
|
|
5
|
+
@model_class = model_class
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
[ '', 'index_', 'show_', 'form_' ].each do |prefix|
|
|
9
|
+
class_eval <<-RUBY
|
|
10
|
+
def #{ prefix }fields
|
|
11
|
+
fail Wallaby::NotImplemented
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def #{ prefix }fields=(#{ prefix }fields)
|
|
15
|
+
@#{ prefix }fields = #{ prefix }fields.with_indifferent_access
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def #{ prefix }field_names
|
|
19
|
+
@#{ prefix }field_names ||= #{ prefix }fields.keys.tap do |names|
|
|
20
|
+
names.delete primary_key
|
|
21
|
+
names.unshift primary_key
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def #{ prefix }field_names=(#{ prefix }field_names)
|
|
26
|
+
@#{ prefix }field_names = #{ prefix }field_names
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def #{ prefix }metadata_of(field_name)
|
|
30
|
+
#{ prefix }fields[field_name] || {}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def #{ prefix }label_of(field_name)
|
|
34
|
+
#{ prefix }metadata_of(field_name)[:label]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def #{ prefix }type_of(field_name)
|
|
38
|
+
#{ prefix }metadata_of(field_name)[:type]
|
|
39
|
+
end
|
|
40
|
+
RUBY
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def form_active_errors(resource)
|
|
44
|
+
fail Wallaby::NotImplemented
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def primary_key
|
|
48
|
+
fail Wallaby::NotImplemented
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def guess_title(resource)
|
|
52
|
+
fail Wallaby::NotImplemented
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def resources_name
|
|
56
|
+
Wallaby::Utils.to_resources_name @model_class
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
class Wallaby::ModelOperator
|
|
2
|
+
def initialize(model_class, model_decorator = nil)
|
|
3
|
+
fail ArgumentError, 'model class required' unless model_class
|
|
4
|
+
@model_class = model_class
|
|
5
|
+
@model_decorator = model_decorator || Wallaby::DecoratorFinder.find_model(@model_class)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def collection(params, ability)
|
|
9
|
+
fail Wallaby::NotImplemented
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def new(params)
|
|
13
|
+
fail Wallaby::NotImplemented
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def find(id, params)
|
|
17
|
+
fail Wallaby::NotImplemented
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def create(params, ability)
|
|
21
|
+
fail Wallaby::NotImplemented
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def update(resource, params, ability)
|
|
25
|
+
fail Wallaby::NotImplemented
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def destroy(resource, params)
|
|
29
|
+
fail Wallaby::NotImplemented
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class Wallaby::DecoratorFinder
|
|
2
|
+
DEFAULT_DECORATOR = Wallaby::ResourceDecorator
|
|
3
|
+
|
|
4
|
+
def self.find_model(model_class)
|
|
5
|
+
Wallaby::Map.decorator_map[model_class] || new_model(model_class)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.find_resource(model_class)
|
|
9
|
+
Wallaby::Map.decorator_map[model_class] || DEFAULT_DECORATOR
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.new_model(model_class)
|
|
13
|
+
mode = Wallaby::ActiveRecord
|
|
14
|
+
mode.model_decorator.new model_class
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
class Wallaby::LookupContextWrapper
|
|
2
|
+
delegate *begin # origin methods
|
|
3
|
+
ActionView::LookupContext.instance_methods \
|
|
4
|
+
- Object.instance_methods - %i( find_template )
|
|
5
|
+
end, to: :@lookup_context
|
|
6
|
+
|
|
7
|
+
def initialize(lookup_context)
|
|
8
|
+
@lookup_context = lookup_context
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def find_template(*args)
|
|
12
|
+
key = args.join '/'
|
|
13
|
+
caching key do
|
|
14
|
+
@lookup_context.find_template *args
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
protected
|
|
19
|
+
def caching(key)
|
|
20
|
+
@templates ||= {}
|
|
21
|
+
unless @templates.has_key? key
|
|
22
|
+
@templates[key] = begin
|
|
23
|
+
yield
|
|
24
|
+
rescue ActionView::MissingTemplate
|
|
25
|
+
raise if Rails.env.development?
|
|
26
|
+
BlankTemplate.new
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
@templates[key]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class BlankTemplate < ActionView::Template::HTML
|
|
33
|
+
def initialize
|
|
34
|
+
super nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def render(*args)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
class Wallaby::Map
|
|
2
|
+
def self.mode_map(modes = nil)
|
|
3
|
+
Rails.cache.fetch 'wallaby/map/mode_map' do
|
|
4
|
+
{}.tap do |map|
|
|
5
|
+
(modes || Wallaby::Mode.subclasses).each do |mode_class|
|
|
6
|
+
mode_class.model_finder.new.all.each do |model_class|
|
|
7
|
+
map[model_class] = mode_class
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.model_classes(configuration = nil)
|
|
15
|
+
Rails.cache.fetch 'wallaby/map/model_classes' do
|
|
16
|
+
models = (configuration || Wallaby.configuration).models
|
|
17
|
+
full_list = mode_map.keys
|
|
18
|
+
configed_models = models.presence
|
|
19
|
+
|
|
20
|
+
return full_list - models.excludes unless configed_models
|
|
21
|
+
|
|
22
|
+
invalid_models = configed_models - full_list
|
|
23
|
+
if invalid_models.length > 0
|
|
24
|
+
fail Wallaby::InvalidError, "#{ invalid_models.to_sentence } are invalid models."
|
|
25
|
+
end
|
|
26
|
+
configed_models
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.controller_map
|
|
31
|
+
model_class_map Wallaby::ResourcesController, __callee__
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.decorator_map
|
|
35
|
+
model_class_map Wallaby::ResourceDecorator, __callee__
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.servicer_map
|
|
39
|
+
model_class_map Wallaby::ModelServicer, __callee__
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.model_class_map(base_class, method_id)
|
|
43
|
+
Rails.cache.fetch "wallaby/map/#{ method_id }" do
|
|
44
|
+
{}.tap do |map|
|
|
45
|
+
base_class.subclasses
|
|
46
|
+
.reject{ |klass| klass.name.blank? }
|
|
47
|
+
.each do |klass|
|
|
48
|
+
map[klass.model_class] = klass
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
class Wallaby::ModelServicer
|
|
2
|
+
def self.model_class
|
|
3
|
+
if self < Wallaby::ModelServicer
|
|
4
|
+
Wallaby::Utils.to_model_class name.gsub('Servicer', ''), name
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def initialize(model_class = nil, model_decorator = nil)
|
|
9
|
+
@model_class = model_class || self.class.model_class
|
|
10
|
+
fail ArgumentError, 'model class required' unless @model_class
|
|
11
|
+
@model_decorator = model_decorator || Wallaby::DecoratorFinder.find_model(@model_class)
|
|
12
|
+
@delegator = Wallaby.adaptor.model_operator.new @model_class, @model_decorator
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def collection(params, ability)
|
|
16
|
+
@delegator.collection params, ability
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def new(params)
|
|
20
|
+
@delegator.new params
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def find(id, params)
|
|
24
|
+
@delegator.find id, params
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def create(params, ability)
|
|
28
|
+
@delegator.create params, ability
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def update(resource, params, ability)
|
|
32
|
+
@delegator.update resource, params, ability
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def destroy(resource, params)
|
|
36
|
+
@delegator.destroy resource, params
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Wallaby::Utils
|
|
2
|
+
def self.to_resources_name(model_class)
|
|
3
|
+
return '' if model_class.blank?
|
|
4
|
+
model_class.to_s.underscore.gsub('/', '::').pluralize
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.to_model_label(model_class)
|
|
8
|
+
model_class_name = to_model_name model_class
|
|
9
|
+
model_class_name.titleize.gsub '/', ' / '
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.to_model_name(resources_name)
|
|
13
|
+
return '' if resources_name.blank?
|
|
14
|
+
resources_name.to_s.singularize.gsub('::', '/').camelize
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.to_model_class(resources_name, source = nil)
|
|
18
|
+
return if resources_name.blank?
|
|
19
|
+
begin
|
|
20
|
+
class_name = to_model_name resources_name
|
|
21
|
+
class_name.constantize
|
|
22
|
+
rescue
|
|
23
|
+
message = [ class_name, source ].compact.join(' from ')
|
|
24
|
+
fail Wallaby::ModelNotFound, message
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.to_hash(array)
|
|
29
|
+
Hash[ *array.flatten(1) ]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
class Wallaby::Configuration::Security
|
|
2
|
+
# by default, current_user returns nil
|
|
3
|
+
DEFAULT_CURRENT_USER = -> {}
|
|
4
|
+
# by default, authenticate returns true not to stop the before_action chain
|
|
5
|
+
DEFAULT_AUTHENTICATE = -> { true }
|
|
6
|
+
|
|
7
|
+
def current_user(&block)
|
|
8
|
+
if block_given?
|
|
9
|
+
@current_user = block
|
|
10
|
+
else
|
|
11
|
+
@current_user ||= DEFAULT_CURRENT_USER
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def current_user?
|
|
16
|
+
current_user != DEFAULT_CURRENT_USER
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def authenticate(&block)
|
|
20
|
+
if block_given?
|
|
21
|
+
@authenticate = block
|
|
22
|
+
else
|
|
23
|
+
@authenticate ||= DEFAULT_AUTHENTICATE
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def authenticate?
|
|
28
|
+
authenticate != DEFAULT_AUTHENTICATE
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Wallaby
|
|
2
|
+
class Configuration
|
|
3
|
+
def adaptor
|
|
4
|
+
@adaptor ||= Wallaby::ActiveRecord
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def adaptor=(adaptor)
|
|
8
|
+
if @adaptor
|
|
9
|
+
fail 'Adaptor has been initialized. Please place adaptor assignment at the top of configuration.'
|
|
10
|
+
end
|
|
11
|
+
@adaptor = adaptor
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def models
|
|
15
|
+
@models ||= Models.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def models=(models)
|
|
19
|
+
self.models.set models
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def security
|
|
23
|
+
@security ||= Security.new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def base_controller
|
|
27
|
+
@base_controller ||= ::ApplicationController
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def base_controller=(base_controller)
|
|
31
|
+
@base_controller = base_controller
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.configuration
|
|
36
|
+
@configuration ||= Configuration.new
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.config
|
|
40
|
+
yield configuration
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.adaptor
|
|
44
|
+
configuration.adaptor
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
require 'wallaby/configuration/models'
|
|
49
|
+
require 'wallaby/configuration/security'
|