adminpanel 1.2.9 → 1.2.10
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/adminpanel.gemspec +1 -0
- data/app/controllers/adminpanel/analytics_controller.rb +1 -1
- data/app/controllers/adminpanel/application_controller.rb +6 -6
- data/app/controllers/adminpanel/categories_controller.rb +17 -8
- data/app/controllers/adminpanel/galleries_controller.rb +2 -0
- data/app/controllers/adminpanel/sections_controller.rb +2 -0
- data/app/controllers/adminpanel/sessions_controller.rb +2 -2
- data/app/controllers/adminpanel/users_controller.rb +2 -0
- data/app/helpers/adminpanel/custom_form_builder.rb +24 -0
- data/app/helpers/adminpanel/rest_actions_helper.rb +26 -9
- data/app/helpers/adminpanel/shared_pages_helper.rb +2 -1
- data/app/models/adminpanel/group.rb +6 -0
- data/app/models/adminpanel/user.rb +48 -5
- data/app/views/adminpanel/categories/_categories_table.html.erb +3 -2
- data/app/views/adminpanel/categories/_category_form.html.erb +4 -4
- data/app/views/adminpanel/categories/create.js.erb +2 -1
- data/app/views/adminpanel/categories/index.html.erb +1 -1
- data/app/views/adminpanel/categories/new.js.erb +2 -1
- data/app/views/layouts/_side_menu.html.erb +20 -18
- data/app/views/layouts/_top_bar.html.erb +1 -1
- data/app/views/shared/_form_fields.html.erb +57 -5
- data/app/views/shared/_modal.html.erb +8 -0
- data/app/views/shared/_remote_form_fields.html.erb +12 -0
- data/app/views/shared/create_belongs_to.js.erb +5 -0
- data/app/views/shared/create_has_many.js.erb +5 -0
- data/app/views/shared/edit.html.erb +1 -0
- data/app/views/shared/new.html.erb +15 -4
- data/app/views/shared/new.js.erb +2 -0
- data/config/locales/es.yml +5 -3
- data/lib/adminpanel.rb +1 -0
- data/lib/adminpanel/active_record/adminpanel_extension.rb +0 -4
- data/lib/adminpanel/version.rb +1 -1
- data/lib/generators/adminpanel/initialize/initialize_generator.rb +11 -0
- data/lib/generators/adminpanel/initialize/templates/ability.rb +31 -0
- data/lib/generators/adminpanel/initialize/templates/adminpanel_setup.rb +7 -7
- data/lib/generators/adminpanel/initialize/templates/create_adminpanel_tables.rb +9 -1
- data/lib/tasks/adminpanel/adminpanel.rake +2 -1
- data/spec/dummy/app/models/ability.rb +31 -0
- data/spec/dummy/app/models/adminpanel/category.rb +4 -1
- data/spec/features/authentication_pages_spec.rb +6 -5
- data/spec/features/galleries_pages_spec.rb +3 -1
- data/spec/features/section_pages_spec.rb +2 -1
- data/spec/features/shared_pages_spec.rb +66 -22
- data/spec/generators/gallery_generator_spec.rb +3 -3
- data/spec/generators/resource_generator_spec.rb +3 -3
- data/spec/models/gallery_spec.rb +3 -1
- data/spec/models/section_spec.rb +12 -11
- data/spec/models/user_spec.rb +6 -2
- data/spec/spec_helper.rb +5 -2
- data/spec/support/define_factory_models.rb +6 -0
- data/spec/support/helper_methods.rb +2 -1
- data/spec/support/test_database.rb +7 -0
- data/spec/tasks/adminpanel_rake_spec.rb +1 -0
- metadata +53 -32
- data/spec/dummy/app/controllers/adminpanel/categories_controller.rb +0 -4
- data/spec/models/product_spec.rb +0 -39
@@ -13,30 +13,82 @@
|
|
13
13
|
<% end %>
|
14
14
|
|
15
15
|
<% elsif properties["type"] == "adminpanel_file_field" %>
|
16
|
+
<% if !defined? remote_request %>
|
16
17
|
<%= f.fields_for(attribute) do |builder| %>
|
17
18
|
<%= render 'shared/image_fields', :f => builder %>
|
18
19
|
<% end -%>
|
19
20
|
<%= link_to_add_fields t("Add Image"), f, attribute %>
|
20
21
|
|
22
|
+
<% end %>
|
21
23
|
<% elsif properties["type"] == "belongs_to" %>
|
24
|
+
<% if !defined? remote_request %>
|
22
25
|
<% args = properties.except("type", "name", "model") %>
|
23
26
|
<% args.symbolize_keys! %>
|
24
27
|
<%= f.select(attribute, (@collections["#{properties["model"]}"].collect{|resource| [resource.name, resource.id]}), args) %>
|
25
28
|
|
26
|
-
|
27
|
-
|
29
|
+
|
30
|
+
<% if(properties['remote_resource'].nil? || properties['remote_resource']) %>
|
31
|
+
<!-- Button to create a new of this belongs_to resource -->
|
32
|
+
<% model_name = properties['model'].classify.constantize.model_name.demodulize.downcase %>
|
33
|
+
<%=
|
34
|
+
link_to(
|
35
|
+
I18n.t('other.add',
|
36
|
+
:model => properties['model'].classify.constantize.display_name
|
37
|
+
),
|
38
|
+
polymorphic_path(
|
39
|
+
[:new, :"#{model_name}"],
|
40
|
+
:model => @model.display_name,
|
41
|
+
:model_name => @model.name.demodulize.downcase,
|
42
|
+
:belongs_request => true
|
43
|
+
),
|
44
|
+
:class => 'btn btn-info',
|
45
|
+
:id => "#{model_name}-modal-link",
|
46
|
+
:'data-target' => "#new-modal",
|
47
|
+
:'data-toggle' => 'modal',
|
48
|
+
:remote => true
|
49
|
+
)
|
50
|
+
%>
|
51
|
+
<% end %>
|
52
|
+
|
53
|
+
|
54
|
+
<% end %>
|
55
|
+
<% elsif properties['type'] == 'has_many' %>
|
56
|
+
<% if !defined? remote_request %>
|
28
57
|
<div class="control-group">
|
29
58
|
<div class="control-label">
|
30
|
-
<%= I18n.t('other.choose', :model => pluralize_es(properties[
|
59
|
+
<%= I18n.t('other.choose', :model => pluralize_es(properties['model'].classify.constantize.display_name)) %>
|
31
60
|
</div>
|
32
61
|
<%= hidden_field_tag("#{class_name_downcase(f.object)}[#{relationship_ids(properties["model"])}][]", nil) %>
|
33
|
-
<div class="controls">
|
34
|
-
<% @collections["#{properties[
|
62
|
+
<div class="controls" id="<%= properties['model'].demodulize.downcase %>-relation">
|
63
|
+
<% @collections["#{properties['model']}"].each do |resource| %>
|
35
64
|
<%= f.checkbox(resource, class_name_downcase(f.object) ,relationship_ids(properties["model"])) %>
|
36
65
|
<% end %>
|
37
66
|
</div>
|
38
67
|
</div>
|
39
68
|
|
69
|
+
<% if properties['remote_resource'].nil? || propeties['remote_resource'] %>
|
70
|
+
<!-- Button to create a new of this has_many resource -->
|
71
|
+
<% model_name = properties['model'].classify.constantize.model_name.demodulize.downcase %>
|
72
|
+
<%=
|
73
|
+
link_to(
|
74
|
+
I18n.t('other.add',
|
75
|
+
:model => properties['model'].classify.constantize.display_name
|
76
|
+
),
|
77
|
+
polymorphic_path(
|
78
|
+
[:new, :"#{model_name}"],
|
79
|
+
:model => @model.display_name,
|
80
|
+
:model_name => @model.name.demodulize.downcase
|
81
|
+
),
|
82
|
+
:class => 'btn btn-info',
|
83
|
+
:id => "#{model_name}-modal-link",
|
84
|
+
:'data-target' => "#new-modal",
|
85
|
+
:'data-toggle' => 'modal',
|
86
|
+
:remote => true
|
87
|
+
)
|
88
|
+
%>
|
89
|
+
<% end %>
|
90
|
+
<% end %>
|
91
|
+
|
40
92
|
<% else %>
|
41
93
|
<% type = properties["type"] %>
|
42
94
|
<% args = properties.except("type", "name") %>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<div id="new-modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
2
|
+
<div class="modal-header" id="modal-header">
|
3
|
+
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
4
|
+
<h3 id="modal-title"></h3>
|
5
|
+
</div>
|
6
|
+
<div id="modal-container">
|
7
|
+
</div>
|
8
|
+
</div>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%= custom_form_for(resource, :url => {:action => :create, :model => params[:model], :model_name => params[:model_name], :belongs_request => params[:belongs_request] }, :remote => true, :html => {:class => "form-horizontal", :id => "new_resource"}) do |f| -%>
|
2
|
+
<div class="row-fluid">
|
3
|
+
<div class="modal-body">
|
4
|
+
<%= render 'shared/error_messages', :object => resource %>
|
5
|
+
<%= render 'shared/form_fields', :f => f, :remote_request => true %>
|
6
|
+
</div>
|
7
|
+
</div>
|
8
|
+
<div class="modal-footer">
|
9
|
+
<button id="modal-button" class="btn" data-dismiss="modal" aria-hidden="true"><%= I18n.t('action.close') %></button>
|
10
|
+
<%= f.submit t("action.add") + " " + @model.display_name, :disable_with => t("action.submitting"), :id =>"new-resource-button" %>
|
11
|
+
</div>
|
12
|
+
<% end -%>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
var model_name = "<%= params[:model_name] %>";
|
2
|
+
var new_model = "<%= @model.name.demodulize.downcase %>";
|
3
|
+
var option = '<option value="<%= resource.id %>" selected="selected"><%= resource.name %></option>';
|
4
|
+
$("#" + model_name + "_" + new_model + "_id").append(option);
|
5
|
+
$("#new-modal").modal('toggle');
|
@@ -0,0 +1,5 @@
|
|
1
|
+
var model_name = "<%= params[:model_name] %>";
|
2
|
+
var new_model = "<%= @model.name.demodulize.downcase %>";
|
3
|
+
row = '<label class="checkbox"><input checked="checked" id="' + model_name + '_' + new_model + '_ids_" name="' + model_name + '[' + new_model + '_ids][]" type="checkbox" value="<%= resource.id %>"><%= resource.name %></label>';
|
4
|
+
$("#" + new_model + "-relation").append(row);
|
5
|
+
$("#new-modal").modal('toggle');
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<% provide(:page_title, t("action.create") + " #{@model.display_name.capitalize}") -%>
|
2
2
|
<% breadcrumb_add(
|
3
|
-
@model.display_name.capitalize.pluralize,
|
3
|
+
@model.display_name.capitalize.pluralize,
|
4
4
|
{
|
5
5
|
:controller => params[:controller],
|
6
6
|
:action => "index"
|
@@ -15,14 +15,25 @@
|
|
15
15
|
</div>
|
16
16
|
<div class = "widget-body">
|
17
17
|
<div class = "widget-forms clearfix">
|
18
|
-
<%=
|
18
|
+
<%=
|
19
|
+
custom_form_for(
|
20
|
+
resource, :html => {
|
21
|
+
:class => "form-horizontal",
|
22
|
+
:id => "new_resource"
|
23
|
+
}
|
24
|
+
) do |f| -%>
|
19
25
|
<%= render 'shared/error_messages', :object => resource %>
|
20
26
|
<%= render 'shared/form_fields', :f => f %>
|
21
27
|
</div>
|
22
28
|
</div>
|
23
29
|
<div class = "widget-footer">
|
24
|
-
<%=
|
30
|
+
<%=
|
31
|
+
f.submit t("action.add") + " " + @model.display_name,
|
32
|
+
:disable_with => t("action.submitting"),
|
33
|
+
:id =>"new-#{@model.name.demodulize}-button"
|
34
|
+
%>
|
25
35
|
</div>
|
26
36
|
<% end -%>
|
27
37
|
</div>
|
28
|
-
</div>
|
38
|
+
</div>
|
39
|
+
<%= render 'shared/modal' %>
|
data/config/locales/es.yml
CHANGED
@@ -8,10 +8,10 @@ es:
|
|
8
8
|
brief: "Pequeña descripción"
|
9
9
|
category_id: "Categoría"
|
10
10
|
client_id: "Cliente"
|
11
|
-
adminproject_id: "Proyecto"
|
12
11
|
description: "Descripción"
|
13
12
|
email: "Correo electrónico"
|
14
13
|
file: "Imagen"
|
14
|
+
group_id: "Rol de usuario"
|
15
15
|
name: "Nombre"
|
16
16
|
password: "Contraseña"
|
17
17
|
password_confirmation: "Confirmar contraseña"
|
@@ -55,8 +55,9 @@ es:
|
|
55
55
|
delete confirmation: "Estás seguro que desea eliminar?"
|
56
56
|
authentication:
|
57
57
|
welcome: "Bienvenido! Inicia Sesión"
|
58
|
-
|
59
|
-
|
58
|
+
signin_error: "Correo y/o Contraseña incorrecta."
|
59
|
+
signin_success: "Bienvenido!"
|
60
|
+
not_authorized: 'No tienes permisos para acceder'
|
60
61
|
gallery:
|
61
62
|
new: "Agregar Imagen"
|
62
63
|
success: "La imagen ha sido guardada"
|
@@ -79,6 +80,7 @@ es:
|
|
79
80
|
password: "Contraseña"
|
80
81
|
email: "Correo electrónico"
|
81
82
|
other:
|
83
|
+
add : "Agregar %{model}"
|
82
84
|
choose: "Selecciona %{model} pertenecientes"
|
83
85
|
no description: "No tiene descripción aún"
|
84
86
|
key:
|
data/lib/adminpanel.rb
CHANGED
data/lib/adminpanel/version.rb
CHANGED
@@ -25,6 +25,11 @@ module Adminpanel
|
|
25
25
|
:aliases => '-p',
|
26
26
|
:default => false,
|
27
27
|
:desc => 'Skip setup if true'
|
28
|
+
class_option :'skip-setup',
|
29
|
+
:type => :boolean,
|
30
|
+
:aliases => '-y',
|
31
|
+
:default => false,
|
32
|
+
:desc => 'Skip cancan\'s ability.rb'
|
28
33
|
|
29
34
|
def create_initializers
|
30
35
|
if !options[:'skip-setup']
|
@@ -32,6 +37,12 @@ module Adminpanel
|
|
32
37
|
end
|
33
38
|
end
|
34
39
|
|
40
|
+
def create_ability
|
41
|
+
if !options[:'skip-ability']
|
42
|
+
copy_file 'ability.rb', 'app/models/ability.rb'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
35
46
|
def create_categories
|
36
47
|
if !options[:'skip-category']
|
37
48
|
# puts "including category files"
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Ability
|
2
|
+
include CanCan::Ability
|
3
|
+
|
4
|
+
def initialize(user)
|
5
|
+
|
6
|
+
if user.group.name == "Admin"
|
7
|
+
can :manage, :all
|
8
|
+
else
|
9
|
+
# cannot :manage, Adminpanel::User
|
10
|
+
# can :manage, Adminpanel::Analytic
|
11
|
+
# can :manage, Adminpanel::Section
|
12
|
+
# can :manage, Adminpanel::Gallery
|
13
|
+
# can :manage, Adminpanel::Category
|
14
|
+
end
|
15
|
+
|
16
|
+
# The first argument to `can` is the action you are giving the user
|
17
|
+
# permission to do.
|
18
|
+
# If you pass :manage it will apply to every action. Other common actions
|
19
|
+
# here are :read, :create, :update and :destroy.
|
20
|
+
#
|
21
|
+
# The second argument is the resource the user can perform the action on.
|
22
|
+
# If you pass :all it will apply to every resource. Otherwise pass a Ruby
|
23
|
+
# class of the resource.
|
24
|
+
#
|
25
|
+
# The third argument is an optional hash of conditions to further filter the
|
26
|
+
# objects.
|
27
|
+
# For example, here the user can only update published articles.
|
28
|
+
#
|
29
|
+
# can :update, Article, :published => true
|
30
|
+
end
|
31
|
+
end
|
@@ -11,11 +11,11 @@ Adminpanel.setup do |config|
|
|
11
11
|
# config.analytics_key_path = "config/analytics"
|
12
12
|
|
13
13
|
# # This are the modules that are going to be displayed and order that are going to be displayed
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
config.displayable_resources = [
|
15
|
+
:analytics,
|
16
|
+
:users,
|
17
|
+
:galleries,
|
18
|
+
:sections,
|
19
|
+
:categories
|
20
|
+
]
|
21
21
|
end
|
@@ -4,8 +4,11 @@ class CreateAdminpanelTables < ActiveRecord::Migration
|
|
4
4
|
# Create a default user
|
5
5
|
if direction == :up
|
6
6
|
if Rails.env.development?
|
7
|
-
Adminpanel::
|
7
|
+
group = Adminpanel::Group.new(:name => "Admin")
|
8
|
+
group.save
|
9
|
+
Adminpanel::User.new(:email => 'admin@admin.com', :name => "Admin", :password => 'password', :password_confirmation => 'password', :group_id => group.object_id).save
|
8
10
|
puts "The password for admin@admin.com is: password"
|
11
|
+
|
9
12
|
end
|
10
13
|
end
|
11
14
|
end
|
@@ -33,6 +36,11 @@ class CreateAdminpanelTables < ActiveRecord::Migration
|
|
33
36
|
t.timestamps
|
34
37
|
end
|
35
38
|
|
39
|
+
create_table :adminpanel_groups do |t|
|
40
|
+
t.string :name
|
41
|
+
t.timestamps
|
42
|
+
end
|
43
|
+
|
36
44
|
create_table :adminpanel_sections do |t|
|
37
45
|
t.string :name
|
38
46
|
t.boolean :has_description
|
@@ -45,7 +45,8 @@ namespace :adminpanel do
|
|
45
45
|
:email => 'admin@codn.com',
|
46
46
|
:name => 'CoDN',
|
47
47
|
:password => password,
|
48
|
-
:password_confirmation => password
|
48
|
+
:password_confirmation => password,
|
49
|
+
:group_id => Adminpanel::Group.find_by_name("Admin").object_id
|
49
50
|
).save
|
50
51
|
end
|
51
52
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Ability
|
2
|
+
include CanCan::Ability
|
3
|
+
|
4
|
+
def initialize(user)
|
5
|
+
|
6
|
+
if user.group.name == "Admin"
|
7
|
+
can :manage, :all
|
8
|
+
else
|
9
|
+
# cannot :manage, Adminpanel::User
|
10
|
+
# can :manage, Adminpanel::Analytic
|
11
|
+
# can :manage, Adminpanel::Section
|
12
|
+
# can :manage, Adminpanel::Gallery
|
13
|
+
# can :manage, Adminpanel::Category
|
14
|
+
end
|
15
|
+
|
16
|
+
# The first argument to `can` is the action you are giving the user
|
17
|
+
# permission to do.
|
18
|
+
# If you pass :manage it will apply to every action. Other common actions
|
19
|
+
# here are :read, :create, :update and :destroy.
|
20
|
+
#
|
21
|
+
# The second argument is the resource the user can perform the action on.
|
22
|
+
# If you pass :all it will apply to every resource. Otherwise pass a Ruby
|
23
|
+
# class of the resource.
|
24
|
+
#
|
25
|
+
# The third argument is an optional hash of conditions to further filter the
|
26
|
+
# objects.
|
27
|
+
# For example, here the user can only update published articles.
|
28
|
+
#
|
29
|
+
# can :update, Article, :published => true
|
30
|
+
end
|
31
|
+
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Adminpanel
|
2
2
|
class Category < ActiveRecord::Base
|
3
|
-
attr_accessible :product_ids, :name
|
3
|
+
attr_accessible :product_ids, :name, :model
|
4
|
+
|
5
|
+
validates_presence_of :model
|
4
6
|
|
5
7
|
has_many :categorizations
|
6
8
|
has_many :products, :through => :categorizations, :dependent => :destroy
|
@@ -9,6 +11,7 @@ module Adminpanel
|
|
9
11
|
def self.form_attributes
|
10
12
|
[
|
11
13
|
{"name" => {"type" => "text_field", "name" => "name", "label" => "name", "placeholder" => "name"}},
|
14
|
+
# {'model' => {"type" => "text_field", "name" => "name", "label" => "name", "placeholder" => "name", 'show' => 'false'}},
|
12
15
|
{"product_ids" => {"type" => "has_many", "model" => "Adminpanel::Product", "name" => "product_ids"}},
|
13
16
|
]
|
14
17
|
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'support/test_database'
|
2
3
|
|
3
4
|
describe "Authentication" do
|
4
5
|
|
5
6
|
subject { page }
|
6
|
-
|
7
|
+
|
7
8
|
describe "sign in page" do
|
8
9
|
before { visit adminpanel.signin_path }
|
9
10
|
|
@@ -20,7 +21,7 @@ describe "Authentication" do
|
|
20
21
|
|
21
22
|
it { expect(page).to have_title(I18n.t("Panel title")) }
|
22
23
|
|
23
|
-
it { should have_selector('div.alert.alert-error', :text => I18n.t("authentication.
|
24
|
+
it { should have_selector('div.alert.alert-error', :text => I18n.t("authentication.signin_error")) }
|
24
25
|
end
|
25
26
|
|
26
27
|
describe "with valid information" do
|
@@ -29,7 +30,7 @@ describe "Authentication" do
|
|
29
30
|
valid_signin(user)
|
30
31
|
end
|
31
32
|
|
32
|
-
it { should have_selector('div.alert.alert-success', :text => I18n.t("authentication.
|
33
|
+
it { should have_selector('div.alert.alert-success', :text => I18n.t("authentication.signin_success")) }
|
33
34
|
it { should have_selector('i.icon-off') }
|
34
35
|
|
35
36
|
describe "signing out" do
|
@@ -37,8 +38,8 @@ describe "Authentication" do
|
|
37
38
|
|
38
39
|
it { current_path.should == adminpanel.signin_path }
|
39
40
|
it { expect(page).to have_title(I18n.t("Panel title")) }
|
40
|
-
|
41
|
+
|
41
42
|
end
|
42
43
|
end
|
43
44
|
end
|
44
|
-
end
|
45
|
+
end
|