adminable 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +91 -0
- data/Rakefile +22 -0
- data/app/assets/javascripts/adminable/application.js +18 -0
- data/app/assets/javascripts/adminable/scripts.js +20 -0
- data/app/assets/stylesheets/adminable/application.scss +3 -0
- data/app/controllers/adminable/application_controller.rb +7 -0
- data/app/controllers/adminable/resources_controller.rb +93 -0
- data/app/helpers/adminable/application_helper.rb +4 -0
- data/app/views/adminable/kaminari/_first_page.html.haml +2 -0
- data/app/views/adminable/kaminari/_last_page.html.haml +2 -0
- data/app/views/adminable/kaminari/_next_page.html.haml +2 -0
- data/app/views/adminable/kaminari/_page.html.haml +6 -0
- data/app/views/adminable/kaminari/_paginator.html.haml +10 -0
- data/app/views/adminable/kaminari/_prev_page.html.haml +2 -0
- data/app/views/adminable/resources/_form.html.haml +14 -0
- data/app/views/adminable/resources/_search.html.haml +9 -0
- data/app/views/adminable/resources/edit.html.haml +5 -0
- data/app/views/adminable/resources/form/_belongs_to.html.haml +3 -0
- data/app/views/adminable/resources/form/_boolean.html.haml +3 -0
- data/app/views/adminable/resources/form/_datetime.html.haml +2 -0
- data/app/views/adminable/resources/form/_decimal.html.haml +2 -0
- data/app/views/adminable/resources/form/_float.html.haml +2 -0
- data/app/views/adminable/resources/form/_has_many.html.haml +9 -0
- data/app/views/adminable/resources/form/_integer.html.haml +2 -0
- data/app/views/adminable/resources/form/_string.html.haml +2 -0
- data/app/views/adminable/resources/form/_text.html.haml +2 -0
- data/app/views/adminable/resources/index.html.haml +35 -0
- data/app/views/adminable/resources/index/_belongs_to.html.haml +5 -0
- data/app/views/adminable/resources/index/_boolean.html.haml +2 -0
- data/app/views/adminable/resources/index/_datetime.html.haml +2 -0
- data/app/views/adminable/resources/index/_decimal.html.haml +1 -0
- data/app/views/adminable/resources/index/_float.html.haml +1 -0
- data/app/views/adminable/resources/index/_has_many.html.haml +3 -0
- data/app/views/adminable/resources/index/_integer.html.haml +1 -0
- data/app/views/adminable/resources/index/_string.html.haml +1 -0
- data/app/views/adminable/resources/index/_text.html.haml +1 -0
- data/app/views/adminable/resources/new.html.haml +5 -0
- data/app/views/adminable/shared/_alert.html.haml +4 -0
- data/app/views/adminable/shared/_label.html.haml +5 -0
- data/app/views/layouts/adminable/application.html.haml +40 -0
- data/config/initializers/haml.rb +3 -0
- data/config/locales/adminable.en.yml +18 -0
- data/config/routes.rb +7 -0
- data/lib/adminable.rb +33 -0
- data/lib/adminable/attributes/association.rb +21 -0
- data/lib/adminable/attributes/base.rb +42 -0
- data/lib/adminable/attributes/collection.rb +77 -0
- data/lib/adminable/attributes/types/belongs_to.rb +13 -0
- data/lib/adminable/attributes/types/boolean.rb +8 -0
- data/lib/adminable/attributes/types/datetime.rb +8 -0
- data/lib/adminable/attributes/types/decimal.rb +8 -0
- data/lib/adminable/attributes/types/float.rb +8 -0
- data/lib/adminable/attributes/types/has_many.rb +21 -0
- data/lib/adminable/attributes/types/integer.rb +8 -0
- data/lib/adminable/attributes/types/string.rb +8 -0
- data/lib/adminable/attributes/types/text.rb +8 -0
- data/lib/adminable/configuration.rb +19 -0
- data/lib/adminable/engine.rb +9 -0
- data/lib/adminable/extensions/devise.rb +24 -0
- data/lib/adminable/resource.rb +37 -0
- data/lib/adminable/version.rb +3 -0
- data/lib/generators/cms/resource/templates/resource_controller.rb.erb +2 -0
- data/lib/generators/cms/resource_generator.rb +28 -0
- metadata +381 -0
@@ -0,0 +1 @@
|
|
1
|
+
= value
|
@@ -0,0 +1 @@
|
|
1
|
+
= value
|
@@ -0,0 +1 @@
|
|
1
|
+
= value
|
@@ -0,0 +1 @@
|
|
1
|
+
= value
|
@@ -0,0 +1 @@
|
|
1
|
+
= strip_tags(value.truncate(100)).squish
|
@@ -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,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."
|
data/config/routes.rb
ADDED
data/lib/adminable.rb
ADDED
@@ -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,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,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
|