qadmin 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +9 -0
- data/LICENSE +20 -0
- data/Manifest.txt +52 -0
- data/PostInstall.txt +1 -0
- data/README.rdoc +39 -0
- data/Rakefile +31 -0
- data/init.rb +1 -0
- data/lib/qadmin.rb +20 -0
- data/lib/qadmin/assets/form_builder.rb +36 -0
- data/lib/qadmin/configuration.rb +48 -0
- data/lib/qadmin/controller.rb +139 -0
- data/lib/qadmin/form_builder.rb +23 -0
- data/lib/qadmin/helper.rb +128 -0
- data/lib/qadmin/option_set.rb +48 -0
- data/lib/qadmin/overlay.rb +31 -0
- data/lib/qadmin/page_titles.rb +34 -0
- data/lib/qadmin/templates.rb +52 -0
- data/lib/qadmin/views/content_forms/_attachments_form.erb +0 -0
- data/lib/qadmin/views/content_forms/_photos_form.erb +4 -0
- data/lib/qadmin/views/content_forms/_videos_form.erb +0 -0
- data/lib/qadmin/views/default/edit.erb +12 -0
- data/lib/qadmin/views/default/index.erb +9 -0
- data/lib/qadmin/views/default/new.erb +12 -0
- data/lib/qadmin/views/default/show.erb +7 -0
- data/rails/init.rb +5 -0
- data/rails_generators/qadmin/USAGE +5 -0
- data/rails_generators/qadmin/qadmin_generator.rb +111 -0
- data/rails_generators/qadmin/templates/_form.html.erb +7 -0
- data/rails_generators/qadmin/templates/_instance.html.erb +8 -0
- data/rails_generators/qadmin/templates/controller.rb +6 -0
- data/rails_generators/qadmin/templates/functional_test.rb +114 -0
- data/rails_generators/qadmin/templates/images/icon_asc.gif +0 -0
- data/rails_generators/qadmin/templates/images/icon_desc.gif +0 -0
- data/rails_generators/qadmin/templates/images/icon_destroy.png +0 -0
- data/rails_generators/qadmin/templates/images/icon_edit.png +0 -0
- data/rails_generators/qadmin/templates/images/icon_export.png +0 -0
- data/rails_generators/qadmin/templates/images/icon_find.png +0 -0
- data/rails_generators/qadmin/templates/images/icon_import.png +0 -0
- data/rails_generators/qadmin/templates/images/icon_list.png +0 -0
- data/rails_generators/qadmin/templates/images/icon_new.png +0 -0
- data/rails_generators/qadmin/templates/images/icon_next.gif +0 -0
- data/rails_generators/qadmin/templates/images/icon_prev.gif +0 -0
- data/rails_generators/qadmin/templates/images/icon_show.png +0 -0
- data/rails_generators/qadmin/templates/images/icon_sort.png +0 -0
- data/rails_generators/qadmin/templates/images/indicator_medium.gif +0 -0
- data/rails_generators/qadmin/templates/layout.html.erb +45 -0
- data/rails_generators/qadmin/templates/style.css +683 -0
- data/test/test_generator_helper.rb +29 -0
- data/test/test_helper.rb +83 -0
- data/test/test_qadmin_controller.rb +148 -0
- data/test/test_qadmin_generator.rb +76 -0
- data/test/test_qadmin_option_set.rb +86 -0
- metadata +162 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
module Qadmin
|
2
|
+
class OptionSet < Array
|
3
|
+
|
4
|
+
def initialize(*args)
|
5
|
+
first = args.shift
|
6
|
+
if first.is_a?(Array)
|
7
|
+
self.default = first
|
8
|
+
options = args.shift
|
9
|
+
else
|
10
|
+
options = first
|
11
|
+
end
|
12
|
+
if options.is_a?(Hash)
|
13
|
+
options.each do |option, value|
|
14
|
+
self.send("#{option}=", value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def current
|
20
|
+
[self].flatten.dup
|
21
|
+
end
|
22
|
+
|
23
|
+
[:exclude, :only, :default].each do |meth|
|
24
|
+
class_eval <<-EOT
|
25
|
+
def #{meth}
|
26
|
+
@#{meth} ||= []
|
27
|
+
end
|
28
|
+
|
29
|
+
def #{meth}=(#{meth})
|
30
|
+
@#{meth} = [#{meth}].flatten if #{meth}
|
31
|
+
reset_current
|
32
|
+
end
|
33
|
+
EOT
|
34
|
+
end
|
35
|
+
alias_method :except, :exclude
|
36
|
+
alias_method :except=, :exclude=
|
37
|
+
|
38
|
+
protected
|
39
|
+
def reset_current
|
40
|
+
new_current = if !only.empty?
|
41
|
+
only
|
42
|
+
else
|
43
|
+
default - exclude
|
44
|
+
end
|
45
|
+
self.replace(new_current)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Qadmin
|
2
|
+
module Overlay
|
3
|
+
|
4
|
+
def self.included(other)
|
5
|
+
other.module_eval do
|
6
|
+
helper_method :overlay?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
def layout_or_overlay(options = {})
|
12
|
+
@_overlay = false
|
13
|
+
fallback_layout = options[:default] || 'admin'
|
14
|
+
if (options[:only] && !Array(options[:only]).include?(action_name)) || (options[:except] && Array(options[:except]).include?(action_name))
|
15
|
+
return fallback_layout
|
16
|
+
end
|
17
|
+
if params[:_overlay]
|
18
|
+
@_overlay = true
|
19
|
+
false
|
20
|
+
else
|
21
|
+
fallback_layout
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
def overlay?
|
27
|
+
@_overlay && @_overlay == true
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Qadmin
|
2
|
+
module PageTitles
|
3
|
+
|
4
|
+
def self.included(other)
|
5
|
+
other.module_eval do
|
6
|
+
include ControllerMethods
|
7
|
+
extend MacroMethods
|
8
|
+
helper_method :get_page_title, :set_page_title
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module MacroMethods
|
13
|
+
def page_title(add_title)
|
14
|
+
before_filter do |controller|
|
15
|
+
controller.set_page_title(add_title)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module ControllerMethods
|
21
|
+
|
22
|
+
def get_page_title(delimeter = ' : ')
|
23
|
+
@page_title ||= []
|
24
|
+
@page_title.join(delimeter)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def set_page_title(add_this)
|
29
|
+
get_page_title
|
30
|
+
@page_title << "#{add_this}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Qadmin
|
2
|
+
module Templates
|
3
|
+
|
4
|
+
def self.included(klass)
|
5
|
+
if klass.respond_to?(:helper_method)
|
6
|
+
klass.module_eval do
|
7
|
+
helper_method :template_for_section, :partial_for_section
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
def render_template_for_section(action = nil, options = {})
|
14
|
+
action ||= action_name
|
15
|
+
render({:template => template_for_section(action)}.merge(options))
|
16
|
+
end
|
17
|
+
|
18
|
+
def template_for_section(template_name, file_name = nil, options = {})
|
19
|
+
file_name ||= template_name
|
20
|
+
section_specific_template?(file_name, options) ? section_specific_template(template_name, options) : default_section_template(template_name, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def partial_for_section(partial_name, options = {})
|
24
|
+
template_for_section(partial_name, "_#{partial_name}", options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def section_specific_template?(template_name, options = {})
|
28
|
+
template_exists?(section_specific_template(template_name, options))
|
29
|
+
end
|
30
|
+
|
31
|
+
def section_specific_template(template_name, options = {})
|
32
|
+
"#{current_section_name(options)}/#{template_name}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def default_section_template(template_name, options = {})
|
36
|
+
"default/#{template_name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def current_section_name(options = {})
|
40
|
+
options[:section_name] ? options[:section_name] : (@section ? @section.name : controller_name)
|
41
|
+
end
|
42
|
+
|
43
|
+
def template_exists?(template_path)
|
44
|
+
logger.info "Checking for template: #{template_path}"
|
45
|
+
self.view_paths.find_template(template_path)
|
46
|
+
rescue ActionView::MissingTemplate
|
47
|
+
logger.info "Template not found: #{template_path}"
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
File without changes
|
File without changes
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<h2><%= model_human_name %>: Edit</h2>
|
2
|
+
|
3
|
+
<%= admin_controls model_collection_name, :for => :edit %>
|
4
|
+
|
5
|
+
<%= error_messages_for model_instance_name %>
|
6
|
+
|
7
|
+
<% form_for(@model_instance, :html => {:multipart => qadmin_configuration.multipart_forms}) do |f| %>
|
8
|
+
<%= render :partial => 'form', :locals => {:f => f, model_instance_name.to_sym => @model_instance} %>
|
9
|
+
<p><%= f.submit "Update" %></p>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<%= admin_controls model_collection_name, :for => :edit %>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<h2><%= model_human_name.pluralize %></h2>
|
2
|
+
|
3
|
+
<%= admin_controls model_collection_name, :for => :index, :ports => qadmin_configuration.ports, :controls => qadmin_configuration.controls %>
|
4
|
+
|
5
|
+
<%= will_paginate(@model_collection) %>
|
6
|
+
<%= admin_table(@model_collection) %>
|
7
|
+
<%= will_paginate(@model_collection) %>
|
8
|
+
|
9
|
+
<%= admin_controls model_collection_name, :for => :index, :ports => qadmin_configuration.ports, :controls => qadmin_configuration.controls %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<h2><%= model_human_name %>: New</h2>
|
2
|
+
|
3
|
+
<%= admin_controls model_collection_name, :for => :new %>
|
4
|
+
|
5
|
+
<%= error_messages_for model_instance_name %>
|
6
|
+
|
7
|
+
<% form_for(@model_instance, :html => {:multipart => qadmin_configuration.multipart_forms}) do |f| %>
|
8
|
+
<%= render :partial => 'form', :locals => {:f => f, model_instance_name.to_sym => @model_instance} %>
|
9
|
+
<p><%= f.submit "Create" %></p>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<%= admin_controls model_collection_name, :for => :new %>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<h2><%= model_human_name.pluralize %>: <%= @model_instance.to_s %></h2>
|
2
|
+
|
3
|
+
<%= admin_controls model_collection_name, :for => :show, :object => @model_instance %>
|
4
|
+
|
5
|
+
<%= render :partial => model_instance_name, :object => @model_instance %>
|
6
|
+
|
7
|
+
<%= admin_controls model_collection_name, :for => :show, :object => @model_instance %>
|
data/rails/init.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
class QadminGenerator < Rails::Generator::NamedBase
|
2
|
+
attr_reader :controller_name,
|
3
|
+
:controller_class_path,
|
4
|
+
:controller_file_path,
|
5
|
+
:controller_class_nesting,
|
6
|
+
:controller_class_nesting_depth,
|
7
|
+
:controller_class_name,
|
8
|
+
:controller_singular_name,
|
9
|
+
:controller_plural_name
|
10
|
+
alias_method :controller_file_name, :controller_singular_name
|
11
|
+
alias_method :controller_table_name, :controller_plural_name
|
12
|
+
|
13
|
+
attr_accessor :after_scaffold
|
14
|
+
|
15
|
+
def initialize(runtime_args, runtime_options = {})
|
16
|
+
super
|
17
|
+
|
18
|
+
@controller_name = @args.shift || @name.pluralize
|
19
|
+
|
20
|
+
base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@controller_name)
|
21
|
+
@controller_class_name_without_nesting, @controller_singular_name, @controller_plural_name = inflect_names(base_name)
|
22
|
+
|
23
|
+
if @controller_class_nesting.empty?
|
24
|
+
@controller_class_name = @controller_class_name_without_nesting
|
25
|
+
else
|
26
|
+
@controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}"
|
27
|
+
end
|
28
|
+
extract_options
|
29
|
+
end
|
30
|
+
|
31
|
+
def manifest
|
32
|
+
record do |m|
|
33
|
+
klass # checks for class definition
|
34
|
+
# Check for class naming collisions.
|
35
|
+
m.class_collisions(controller_class_path, "#{controller_class_name}Controller")
|
36
|
+
|
37
|
+
# Controller, helper, views, and test directories.
|
38
|
+
if !after_scaffold
|
39
|
+
m.directory(File.join('app','controllers', controller_class_path))
|
40
|
+
m.directory(File.join('app', 'helpers', controller_class_path))
|
41
|
+
m.directory(File.join('public','images','admin'))
|
42
|
+
end
|
43
|
+
|
44
|
+
m.directory(File.join('app', 'views', controller_class_path, controller_file_name))
|
45
|
+
m.directory(File.join('test', 'functional', controller_class_path))
|
46
|
+
|
47
|
+
#copy form over too
|
48
|
+
m.template("_form.html.erb",File.join('app','views', controller_class_path, controller_file_name, "_form.html.erb"))
|
49
|
+
m.template("_instance.html.erb", File.join('app','views', controller_class_path, controller_file_name, "_#{file_name}.html.erb"))
|
50
|
+
|
51
|
+
if !after_scaffold
|
52
|
+
# Layout and stylesheet.
|
53
|
+
m.template('layout.html.erb', File.join('app','views','layouts', "admin.erb"))
|
54
|
+
m.template('style.css', 'public/stylesheets/admin.css')
|
55
|
+
|
56
|
+
m.template('controller.rb', File.join('app','controllers', controller_class_path, "#{controller_file_name}_controller.rb"))
|
57
|
+
end
|
58
|
+
|
59
|
+
m.template('functional_test.rb', File.join('test','functional', controller_class_path, "#{controller_file_name}_controller_test.rb"))
|
60
|
+
|
61
|
+
if !after_scaffold
|
62
|
+
m.route_resources controller_file_name
|
63
|
+
|
64
|
+
# Copy Icons
|
65
|
+
Dir[File.join(File.dirname(__FILE__),'templates','images/*')].each do |image|
|
66
|
+
m.file File.join('images',File.basename(image)), File.join('public','images','admin',File.basename(image))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
protected
|
74
|
+
# Override with your own usage banner.
|
75
|
+
def banner
|
76
|
+
"Usage: #{$0} qadmin ModelName"
|
77
|
+
end
|
78
|
+
|
79
|
+
def scaffold_views
|
80
|
+
%w[ index show new edit ]
|
81
|
+
end
|
82
|
+
|
83
|
+
def model_name
|
84
|
+
class_name.demodulize
|
85
|
+
end
|
86
|
+
|
87
|
+
def klass
|
88
|
+
begin
|
89
|
+
require "#{file_name}" unless defined?(model_name.constantize)
|
90
|
+
rescue
|
91
|
+
raise "You must define the class #{model_name} before running qscaffold"
|
92
|
+
end
|
93
|
+
model_name.constantize
|
94
|
+
end
|
95
|
+
|
96
|
+
def attributes
|
97
|
+
klass.content_columns
|
98
|
+
end
|
99
|
+
|
100
|
+
def ignore_attributes
|
101
|
+
%w{created_at updated_at}.push klass.protected_attributes
|
102
|
+
end
|
103
|
+
|
104
|
+
def add_options!(opts)
|
105
|
+
opts.on('--after-scaffold', "For use after generating a scaffold, generates the _form and the functional test") {|o| options[:after_scaffold] = o }
|
106
|
+
end
|
107
|
+
|
108
|
+
def extract_options
|
109
|
+
self.after_scaffold = options[:after_scaffold]
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class <%= controller_class_name %>ControllerTest < ActionController::TestCase
|
4
|
+
|
5
|
+
context "<%= controller_class_name %>" do
|
6
|
+
setup do
|
7
|
+
@<%= file_name %> = <%= table_name %>(!!FIXTURE_NAME)
|
8
|
+
@<%= file_name %>_params = {
|
9
|
+
<%= attributes.collect { |a| ":#{a.name} => '#{a.default}'" }.join(",\n\t") %>
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
context "html" do
|
14
|
+
context "GET index" do
|
15
|
+
setup do
|
16
|
+
get :index
|
17
|
+
end
|
18
|
+
|
19
|
+
should_respond_with :success
|
20
|
+
|
21
|
+
should "load paginated collection of <%= table_name %>" do
|
22
|
+
assert assigns(:<%= table_name %>)
|
23
|
+
assert assigns(:<%= table_name %>).respond_to?(:next_page)
|
24
|
+
end
|
25
|
+
|
26
|
+
should "display <%= file_name %>" do
|
27
|
+
assert_select "#<%= file_name %>_#{@<%= file_name %>.id}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "GET show" do
|
32
|
+
setup do
|
33
|
+
get :show, :id => @<%= file_name %>.id
|
34
|
+
end
|
35
|
+
|
36
|
+
should_respond_with :success
|
37
|
+
should_assign_to :<%= file_name %>
|
38
|
+
|
39
|
+
should "load <%= file_name %>" do
|
40
|
+
assert_equal @<%= file_name %>, assigns(:<%= file_name %>)
|
41
|
+
end
|
42
|
+
|
43
|
+
should "display <%= file_name %>" do
|
44
|
+
assert_select "#<%= file_name %>_#{@<%= file_name %>.id}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "GET new" do
|
49
|
+
setup do
|
50
|
+
get :new
|
51
|
+
end
|
52
|
+
|
53
|
+
should_respond_with :success
|
54
|
+
should_assign_to :<%= file_name %>
|
55
|
+
|
56
|
+
should "display form" do
|
57
|
+
assert_select 'form'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "POST create with valid <%= file_name %>" do
|
62
|
+
setup do
|
63
|
+
post :create, :<%= file_name %> => @<%= file_name %>_params
|
64
|
+
end
|
65
|
+
|
66
|
+
should_change '<%= model_name %>.count', :by => 1
|
67
|
+
should_redirect_to "<%= file_name %>_path(@<%= file_name %>)"
|
68
|
+
should_assign_to :<%= file_name %>
|
69
|
+
end
|
70
|
+
|
71
|
+
context "GET edit" do
|
72
|
+
setup do
|
73
|
+
get :edit, :id => @<%= file_name %>.id
|
74
|
+
end
|
75
|
+
|
76
|
+
should_respond_with :success
|
77
|
+
should_assign_to :<%= file_name %>
|
78
|
+
|
79
|
+
should "load <%= file_name %>" do
|
80
|
+
assert_equal @<%= file_name %>, assigns(:<%= file_name %>)
|
81
|
+
end
|
82
|
+
|
83
|
+
should "display form" do
|
84
|
+
assert_select 'form'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "PUT update" do
|
89
|
+
setup do
|
90
|
+
put :update, :id => @<%= file_name %>.id, :<%= file_name %> => @<%= file_name %>_params
|
91
|
+
end
|
92
|
+
|
93
|
+
should_not_change '<%= model_name %>.count'
|
94
|
+
should_redirect_to "<%= file_name %>_path(@<%= file_name %>)"
|
95
|
+
should_assign_to :<%= file_name %>
|
96
|
+
|
97
|
+
should "load <%= file_name %>" do
|
98
|
+
assert_equal @<%= file_name %>, assigns(:<%= file_name %>)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "DELETE destroy" do
|
103
|
+
setup do
|
104
|
+
delete :destroy, :id => @<%= file_name %>.id
|
105
|
+
end
|
106
|
+
|
107
|
+
should_change '<%= model_name %>.count', :by => -1
|
108
|
+
should_redirect_to "<%= table_name %>_path"
|
109
|
+
should_assign_to :<%= file_name %>
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|