adminable 0.0.1

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.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +91 -0
  4. data/Rakefile +22 -0
  5. data/app/assets/javascripts/adminable/application.js +18 -0
  6. data/app/assets/javascripts/adminable/scripts.js +20 -0
  7. data/app/assets/stylesheets/adminable/application.scss +3 -0
  8. data/app/controllers/adminable/application_controller.rb +7 -0
  9. data/app/controllers/adminable/resources_controller.rb +93 -0
  10. data/app/helpers/adminable/application_helper.rb +4 -0
  11. data/app/views/adminable/kaminari/_first_page.html.haml +2 -0
  12. data/app/views/adminable/kaminari/_last_page.html.haml +2 -0
  13. data/app/views/adminable/kaminari/_next_page.html.haml +2 -0
  14. data/app/views/adminable/kaminari/_page.html.haml +6 -0
  15. data/app/views/adminable/kaminari/_paginator.html.haml +10 -0
  16. data/app/views/adminable/kaminari/_prev_page.html.haml +2 -0
  17. data/app/views/adminable/resources/_form.html.haml +14 -0
  18. data/app/views/adminable/resources/_search.html.haml +9 -0
  19. data/app/views/adminable/resources/edit.html.haml +5 -0
  20. data/app/views/adminable/resources/form/_belongs_to.html.haml +3 -0
  21. data/app/views/adminable/resources/form/_boolean.html.haml +3 -0
  22. data/app/views/adminable/resources/form/_datetime.html.haml +2 -0
  23. data/app/views/adminable/resources/form/_decimal.html.haml +2 -0
  24. data/app/views/adminable/resources/form/_float.html.haml +2 -0
  25. data/app/views/adminable/resources/form/_has_many.html.haml +9 -0
  26. data/app/views/adminable/resources/form/_integer.html.haml +2 -0
  27. data/app/views/adminable/resources/form/_string.html.haml +2 -0
  28. data/app/views/adminable/resources/form/_text.html.haml +2 -0
  29. data/app/views/adminable/resources/index.html.haml +35 -0
  30. data/app/views/adminable/resources/index/_belongs_to.html.haml +5 -0
  31. data/app/views/adminable/resources/index/_boolean.html.haml +2 -0
  32. data/app/views/adminable/resources/index/_datetime.html.haml +2 -0
  33. data/app/views/adminable/resources/index/_decimal.html.haml +1 -0
  34. data/app/views/adminable/resources/index/_float.html.haml +1 -0
  35. data/app/views/adminable/resources/index/_has_many.html.haml +3 -0
  36. data/app/views/adminable/resources/index/_integer.html.haml +1 -0
  37. data/app/views/adminable/resources/index/_string.html.haml +1 -0
  38. data/app/views/adminable/resources/index/_text.html.haml +1 -0
  39. data/app/views/adminable/resources/new.html.haml +5 -0
  40. data/app/views/adminable/shared/_alert.html.haml +4 -0
  41. data/app/views/adminable/shared/_label.html.haml +5 -0
  42. data/app/views/layouts/adminable/application.html.haml +40 -0
  43. data/config/initializers/haml.rb +3 -0
  44. data/config/locales/adminable.en.yml +18 -0
  45. data/config/routes.rb +7 -0
  46. data/lib/adminable.rb +33 -0
  47. data/lib/adminable/attributes/association.rb +21 -0
  48. data/lib/adminable/attributes/base.rb +42 -0
  49. data/lib/adminable/attributes/collection.rb +77 -0
  50. data/lib/adminable/attributes/types/belongs_to.rb +13 -0
  51. data/lib/adminable/attributes/types/boolean.rb +8 -0
  52. data/lib/adminable/attributes/types/datetime.rb +8 -0
  53. data/lib/adminable/attributes/types/decimal.rb +8 -0
  54. data/lib/adminable/attributes/types/float.rb +8 -0
  55. data/lib/adminable/attributes/types/has_many.rb +21 -0
  56. data/lib/adminable/attributes/types/integer.rb +8 -0
  57. data/lib/adminable/attributes/types/string.rb +8 -0
  58. data/lib/adminable/attributes/types/text.rb +8 -0
  59. data/lib/adminable/configuration.rb +19 -0
  60. data/lib/adminable/engine.rb +9 -0
  61. data/lib/adminable/extensions/devise.rb +24 -0
  62. data/lib/adminable/resource.rb +37 -0
  63. data/lib/adminable/version.rb +3 -0
  64. data/lib/generators/cms/resource/templates/resource_controller.rb.erb +2 -0
  65. data/lib/generators/cms/resource_generator.rb +28 -0
  66. metadata +381 -0
@@ -0,0 +1,5 @@
1
+ - if value.present?
2
+ - if attribute.association.klass.exists?(value)
3
+ = link_to "##{ value }", edit_polymorphic_path(attribute.association.klass.find_by(id: value))
4
+ - else
5
+ = "##{ value }"
@@ -0,0 +1,2 @@
1
+ - if !!(value)
2
+ %i.fa.fa-check
@@ -0,0 +1,2 @@
1
+ - if value
2
+ = l value, format: '%H:%M:%S, %-d %b %Y'
@@ -0,0 +1,3 @@
1
+ - if entry
2
+ - entry.send(attribute.name).each do |resource|
3
+ = link_to "##{ resource.id }", edit_polymorphic_path(resource)
@@ -0,0 +1 @@
1
+ = strip_tags(value.truncate(100)).squish
@@ -0,0 +1,5 @@
1
+ .row
2
+ .col-md-8.col-md-offset-2
3
+ %h1.m-b-3
4
+ = t('adminable.titles.new', resource: @resource.model.model_name.human)
5
+ = render 'form'
@@ -0,0 +1,4 @@
1
+ .alert.alert-dismissible.fade.in.m-b-1{ :class => "alert-#{ type }" }
2
+ %button.close{ 'aria-label' => 'Close', 'data-dismiss' => :alert, :type => :button }
3
+ %span{ 'aria-hidden' => true } ×
4
+ = message
@@ -0,0 +1,5 @@
1
+ = label_tag attribute.name do
2
+ = @resource.model.human_attribute_name(attribute.name)
3
+ - if attribute.required?
4
+ %i.text-muted
5
+ (required)
@@ -0,0 +1,40 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title Adminable
5
+ %link{ :href => 'https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css', :rel => 'stylesheet' }/
6
+ %link{ :href => '//oss.maxcdn.com/clusterize.js/0.16.0/clusterize.css', :rel => 'stylesheet' }/
7
+ %script{ :src => '//oss.maxcdn.com/clusterize.js/0.16.0/clusterize.min.js' }
8
+ %script{ :src => '//cdn.tinymce.com/4/tinymce.min.js' }
9
+ %meta{ :content => 'width=device-width, initial-scale=1, shrink-to-fit=no', :name => 'viewport' }/
10
+ %meta{ :content => 'ie=edge', 'http-equiv' => 'x-ua-compatible' }/
11
+ = stylesheet_link_tag 'adminable/application', media: 'all'
12
+ = javascript_include_tag 'adminable/application'
13
+ = csrf_meta_tags
14
+ %body
15
+ #collapsing-nav.collapse.p-y-1
16
+ - Adminable::Configuration.resources.each do |resource|
17
+ = link_to resource.model.model_name.human.pluralize,
18
+ polymorphic_path(resource.route), class: 'btn btn-link btn-block'
19
+ .navbar.navbar-full.navbar-dark.bg-primary.m-b-3
20
+ .hidden-md-up
21
+ %button.navbar-toggler{ 'data-target' => '#collapsing-nav', 'data-toggle' => :collapse, :type => :button }
22
+ \☰
23
+ .container.hidden-sm-down
24
+ %ul.nav.navbar-nav
25
+ %li.nav-item
26
+ = link_to main_app.root_path, class: 'nav-link' do
27
+ %i.fa.fa-home
28
+ - Adminable::Configuration.resources.each do |resource|
29
+ %li.nav-item{ :class => ('active' if current_page?(File.join('/adminable/', resource.name))) }
30
+ = link_to resource.model.model_name.human.pluralize,
31
+ polymorphic_path(resource.route), class: 'nav-link'
32
+ .container.p-b-3
33
+ - if flash[:alert] || notice.present?
34
+ .p-b-2
35
+ - if flash[:alert]
36
+ - flash[:alert].each do |alert|
37
+ = render 'adminable/shared/alert', message: alert, type: 'danger'
38
+ - if notice.present?
39
+ = render 'adminable/shared/alert', message: notice, type: 'success'
40
+ = yield
@@ -0,0 +1,3 @@
1
+ require 'haml/template'
2
+
3
+ Haml::Template.options[:ugly] = true
@@ -0,0 +1,18 @@
1
+ ---
2
+ en:
3
+ adminable:
4
+ ui:
5
+ confirm: Are you sure?
6
+ not_selected: Not selected
7
+ buttons:
8
+ submit: Submit
9
+ back: Back
10
+ edit: Edit
11
+ new: New %{resource}
12
+ titles:
13
+ edit: Edit %{resource}
14
+ new: New %{resource}
15
+ resources:
16
+ created: "%{resource} has been successfully created."
17
+ updated: "%{resource} has been successfully updated."
18
+ deleted: "%{resource} has been successfully deleted."
@@ -0,0 +1,7 @@
1
+ Adminable::Engine.routes.draw do
2
+ Adminable::Configuration.resources.each do |r|
3
+ resources r.route, except: :show, path: r.name, controller: r.name
4
+ end
5
+
6
+ root 'application#welcome'
7
+ end
@@ -0,0 +1,33 @@
1
+ require 'adminable/engine'
2
+ require 'adminable/configuration'
3
+
4
+ require 'adminable/extensions/devise'
5
+
6
+ require 'adminable/resource'
7
+
8
+ require 'adminable/attributes/collection'
9
+ require 'adminable/attributes/association'
10
+
11
+ require 'adminable/attributes/base'
12
+
13
+ require 'adminable/attributes/types/belongs_to'
14
+ require 'adminable/attributes/types/boolean'
15
+ require 'adminable/attributes/types/datetime'
16
+ require 'adminable/attributes/types/decimal'
17
+ require 'adminable/attributes/types/float'
18
+ require 'adminable/attributes/types/has_many'
19
+ require 'adminable/attributes/types/integer'
20
+ require 'adminable/attributes/types/string'
21
+ require 'adminable/attributes/types/text'
22
+
23
+ require 'haml-rails'
24
+ require 'sass-rails'
25
+ require 'coffee-rails'
26
+ require 'jquery-rails'
27
+ require 'bootstrap'
28
+ require 'rails-assets-tether'
29
+ require 'babosa'
30
+ require 'kaminari'
31
+
32
+ module Adminable
33
+ end
@@ -0,0 +1,21 @@
1
+ module Adminable
2
+ module Attributes
3
+ module Association
4
+ attr_reader :options_for_select, :association
5
+
6
+ def options_for_select(entry)
7
+ @association.klass.all.reject { |e| e == entry }.collect do |e|
8
+ [association_option_name(e), e.id]
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def association_option_name(entry)
15
+ %i(email login name title id).each do |a|
16
+ return entry.try(a) unless entry.try(a).nil?
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,42 @@
1
+ module Adminable
2
+ module Attributes
3
+ class Base
4
+ attr_accessor :name, :required, :show, :center, :wysiwyg
5
+ attr_reader :key, :ransack_name
6
+
7
+ def initialize(name, options = {})
8
+ raise 'Base class cannot be initialized' if self.class == Base
9
+
10
+ @name = name
11
+ @key = options[:key] || @name
12
+ @ransack_name = "#{@name}_cont"
13
+ @association = options[:association]
14
+ @required = options[:required] || false
15
+ @show = true
16
+ @center = %w(integer boolean float decimal).include?(type)
17
+ @wysiwyg = %w(text).include?(type)
18
+ end
19
+
20
+ alias required? required
21
+ alias show? show
22
+ alias center? center
23
+ alias wysiwyg? wysiwyg
24
+
25
+ def type
26
+ self.class.name.demodulize.underscore
27
+ end
28
+
29
+ def strong_parameter
30
+ key
31
+ end
32
+
33
+ def index_partial_path
34
+ "index/#{type}"
35
+ end
36
+
37
+ def form_partial_path
38
+ "adminable/resources/form/#{type}"
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,77 @@
1
+ module Adminable
2
+ module Attributes
3
+ class Collection
4
+ attr_reader :model
5
+ attr_writer :index, :form
6
+
7
+ def initialize(model)
8
+ @model = model
9
+ end
10
+
11
+ def index
12
+ @index ||= all.except(:created_at, :updated_at)
13
+ end
14
+
15
+ def form
16
+ @form ||= all.except(:id, :created_at, :updated_at)
17
+ end
18
+
19
+ def ransack
20
+ @ransack ||= columns.except(:id, :created_at, :updated_at)
21
+ .select { |k, v| %w(string text).include?(v.type) }
22
+ end
23
+
24
+ def all
25
+ [columns, belongs_to, has_many].inject(&:merge)
26
+ end
27
+
28
+ def association
29
+ [belongs_to, has_many].inject(&:merge)
30
+ end
31
+
32
+ def columns
33
+ @columns ||= {}.tap do |attribute|
34
+ @model.columns.reject { |a| a.name.match(/_id$/) }.each do |column|
35
+ attribute[column.name] = "adminable/attributes/types/#{column.type}"
36
+ .classify.constantize.new(
37
+ column.name,
38
+ required: attribute_required?(column.name)
39
+ )
40
+ end
41
+ end.symbolize_keys
42
+ end
43
+
44
+ def belongs_to
45
+ @belongs_to ||= {}.tap do |attribute|
46
+ @model.reflect_on_all_associations(:belongs_to).each do |association|
47
+ attribute[association.name] = Adminable::Attributes::Types::BelongsTo.new(
48
+ association.name,
49
+ required: attribute_required?(association.name),
50
+ association: association
51
+ )
52
+ end
53
+ end.symbolize_keys
54
+ end
55
+
56
+ def has_many
57
+ @has_many ||= {}.tap do |attribute|
58
+ @model.reflect_on_all_associations(:has_many).each do |association|
59
+ attribute[association.name] = Adminable::Attributes::Types::HasMany.new(
60
+ association.name,
61
+ required: attribute_required?(association.name),
62
+ association: association
63
+ )
64
+ end
65
+ end.symbolize_keys
66
+ end
67
+
68
+ private
69
+
70
+ def attribute_required?(name)
71
+ @model.validators_on(name).any? do |validator|
72
+ validator.class == ActiveRecord::Validations::PresenceValidator
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,13 @@
1
+ module Adminable
2
+ module Attributes
3
+ module Types
4
+ class BelongsTo < Base
5
+ include Adminable::Attributes::Association
6
+
7
+ def key
8
+ @association.foreign_key
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ module Adminable
2
+ module Attributes
3
+ module Types
4
+ class Boolean < Base
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Adminable
2
+ module Attributes
3
+ module Types
4
+ class Datetime < Base
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Adminable
2
+ module Attributes
3
+ module Types
4
+ class Decimal < Base
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Adminable
2
+ module Attributes
3
+ module Types
4
+ class Float < Base
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,21 @@
1
+ module Adminable
2
+ module Attributes
3
+ module Types
4
+ class HasMany < Base
5
+ include Adminable::Attributes::Association
6
+
7
+ def key
8
+ @key = "#{@name.to_s.singularize}_ids"
9
+ end
10
+
11
+ def strong_parameter
12
+ { key => [] }
13
+ end
14
+
15
+ def show?
16
+ @association.klass.any?
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,8 @@
1
+ module Adminable
2
+ module Attributes
3
+ module Types
4
+ class Integer < Base
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Adminable
2
+ module Attributes
3
+ module Types
4
+ class String < Base
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Adminable
2
+ module Attributes
3
+ module Types
4
+ class Text < Base
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,19 @@
1
+ module Adminable
2
+ module Configuration
3
+ def self.resources
4
+ @resources ||= resources_paths.map do |resource_path|
5
+ Adminable::Resource.new(
6
+ resource_path.to_s.split('adminable/').last.sub(/_controller\.rb$/, '')
7
+ )
8
+ end
9
+ end
10
+
11
+ def self.find_resource(name)
12
+ resources.find { |resource| resource.name == name }
13
+ end
14
+
15
+ def self.resources_paths
16
+ Dir[Rails.root.join('app/controllers/adminable/**/*_controller.rb')]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ module Adminable
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Adminable
4
+
5
+ ActionDispatch::Reloader.to_prepare do
6
+ require_dependency Adminable::Engine.root.join('app/controllers/adminable/resources_controller.rb')
7
+ end
8
+ end
9
+ end