superuser 0.2.2
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/lib/generators/superuser/USAGE +8 -0
- data/lib/generators/superuser/superuser_generator.rb +205 -0
- data/lib/generators/superuser/templates/base_controller.rb +54 -0
- data/lib/generators/superuser/templates/controller_template.rb +102 -0
- data/lib/generators/superuser/templates/dashboard_controller.rb +10 -0
- data/lib/generators/superuser/templates/superuser_base.js +0 -0
- data/lib/generators/superuser/templates/superuser_base.scss +311 -0
- data/lib/generators/superuser/templates/views/_form.html.erb +25 -0
- data/lib/generators/superuser/templates/views/_search.html.erb +31 -0
- data/lib/generators/superuser/templates/views/dashboard_index.html.erb +1 -0
- data/lib/generators/superuser/templates/views/edit.html.erb +11 -0
- data/lib/generators/superuser/templates/views/index.html.erb +64 -0
- data/lib/generators/superuser/templates/views/layouts/application.html.erb +90 -0
- data/lib/generators/superuser/templates/views/new.html.erb +13 -0
- data/lib/generators/superuser/templates/views/show.html.erb +17 -0
- data/lib/superuser.rb +5 -0
- data/lib/superuser/version.rb +3 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ca5f9b99d69ab6be91c64b8b59d81a8c3e6c4b09d6a339371e3fa8c30db8175c
|
4
|
+
data.tar.gz: c006c02556167bf7271cf35419f9715fdcc26c75ac94860678cc3e3ec50870e9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b5af5cc4a9b5bfcf1e162fd6e3d52f1fa2b50b873c20d306dabae5e11d7758d788e7fc745f0741ff7995b968ac88141e2b2713c186fb18f422d09240facde2f9
|
7
|
+
data.tar.gz: a766b2a731841dad2bbbffc95e779543322f88fa0172e5c1c79f5a213f7d816f398ed589cf44dad5286d0f3703a42ad3f6e2b4ddd3ac96878cdc70dc1fb2b296
|
@@ -0,0 +1,205 @@
|
|
1
|
+
class SuperuserGenerator < Rails::Generators::Base
|
2
|
+
|
3
|
+
source_root File.expand_path('../templates', __FILE__)
|
4
|
+
argument :resources_name, type: :string
|
5
|
+
attr_accessor :attributes
|
6
|
+
|
7
|
+
# NOTE: the order of the following methods is important!
|
8
|
+
|
9
|
+
def generate_css_file
|
10
|
+
|
11
|
+
if !File.exist?("app/assets/stylesheets/superuser/application.scss")
|
12
|
+
copy_file "superuser_base.scss", "app/assets/stylesheets/superuser/application.scss"
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_js_file
|
18
|
+
|
19
|
+
if !File.exist?("app/assets/javascripts/superuser/application.js")
|
20
|
+
copy_file "superuser_base.js", "app/assets/javascripts/superuser/application.js"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def generate_layout
|
26
|
+
|
27
|
+
if !File.exist?("app/views/layouts/superuser/application.html.erb")
|
28
|
+
template "views/layouts/application.html.erb", "app/views/layouts/superuser/application.html.erb"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def generate_controller
|
34
|
+
|
35
|
+
if !File.exist?("app/controllers/superuser/base_controller.rb")
|
36
|
+
copy_file "base_controller.rb", "app/controllers/superuser/base_controller.rb"
|
37
|
+
end
|
38
|
+
if !File.exist?("app/controllers/superuser/dashboard_controller.rb")
|
39
|
+
copy_file "dashboard_controller.rb", "app/controllers/superuser/dashboard_controller.rb"
|
40
|
+
copy_file "views/dashboard_index.html.erb", "app/views/superuser/dashboard/index.html.erb"
|
41
|
+
route "\tnamespace :superuser do\n\t\troot to: 'dashboard#index'\n\tend"
|
42
|
+
add_layout_links 'app/views/layouts/superuser/application.html.erb', search = '<div class="sidebar_dashboard_link">', "<%= link_to 'dashboard', [:superuser, :root] %>"
|
43
|
+
end
|
44
|
+
template "controller_template.rb", "app/controllers/superuser/#{naming(:resources)}_controller.rb"
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
def generate_route_and_link
|
49
|
+
|
50
|
+
# add resources to route if not exists
|
51
|
+
route_replacement = "resources :#{resources}"
|
52
|
+
r = add_resources_route 'config/routes.rb', search = 'namespace :superuser do', route_replacement
|
53
|
+
|
54
|
+
# add link to resources in the layout if not exists
|
55
|
+
link = "<%= link_to '#{resources}', [:superuser, :#{resources}] %>"
|
56
|
+
add_layout_links 'app/views/layouts/superuser/application.html.erb', search = '<div class="sidebar_item">', link
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
def generate_views
|
61
|
+
|
62
|
+
template "views/_form.html.erb", "app/views/superuser/#{naming(:resources)}/_form.html.erb"
|
63
|
+
template "views/index.html.erb", "app/views/superuser/#{naming(:resources)}/index.html.erb"
|
64
|
+
template "views/show.html.erb", "app/views/superuser/#{naming(:resources)}/show.html.erb"
|
65
|
+
template "views/new.html.erb", "app/views/superuser/#{naming(:resources)}/new.html.erb"
|
66
|
+
template "views/edit.html.erb", "app/views/superuser/#{naming(:resources)}/edit.html.erb"
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
def generate_search_form
|
71
|
+
|
72
|
+
template "views/_search.html.erb", "app/views/shared/_search.html.erb"
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def replace(file_path)
|
79
|
+
|
80
|
+
gsub_file file_path, 'resources', "#{naming(:resources)}"
|
81
|
+
gsub_file file_path, 'resource', "#{naming(:resource)}"
|
82
|
+
gsub_file file_path, 'ControllerName', "#{naming(:controller_name)}"
|
83
|
+
gsub_file file_path, 'ModelName', "#{naming(:model_name)}"
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
def resources
|
88
|
+
|
89
|
+
resources_name.underscore
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
def resource
|
94
|
+
|
95
|
+
resources_name.singularize.underscore
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
def get_controller_name
|
100
|
+
|
101
|
+
resources_name.camelize
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
def naming(key)
|
106
|
+
|
107
|
+
map = {
|
108
|
+
resources: resources_name.underscore,
|
109
|
+
resource: resources_name.singularize.underscore,
|
110
|
+
controller_name: resources_name.camelize,
|
111
|
+
model_name: resources_name.classify
|
112
|
+
}
|
113
|
+
return map[key]
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
def model_columns_for_attributes
|
118
|
+
|
119
|
+
resources_name.classify.constantize.columns.reject do |column|
|
120
|
+
column.name.to_s =~ /^(id|user_id|created_at|updated_at)$/
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
def editable_attributes
|
126
|
+
|
127
|
+
attributes ||= model_columns_for_attributes.map do |column|
|
128
|
+
{name: column.name.to_s, type: column.type.to_s}
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
def get_model
|
134
|
+
|
135
|
+
resources_name.classify.constantize
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
def get_resource_attributes
|
140
|
+
|
141
|
+
editable_attributes.map { |a| a.name.prepend(':') }.join(', ')
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
def field_type(db_type)
|
146
|
+
|
147
|
+
matching_type = {
|
148
|
+
decimal: "text_field",
|
149
|
+
float: "text_field",
|
150
|
+
datetime: "text_field",
|
151
|
+
string: "text_field",
|
152
|
+
integer: "text_field",
|
153
|
+
text: "text_area",
|
154
|
+
json: "text_area",
|
155
|
+
jsonb: "text_area"
|
156
|
+
}
|
157
|
+
matching_type[db_type.to_sym] || "text_field"
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
def destination_path(path)
|
162
|
+
|
163
|
+
File.join(destination_root, path)
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
# sub_file modified
|
168
|
+
def add_resources_route(relative_file, search_text, replace_text)
|
169
|
+
|
170
|
+
path = destination_path(relative_file)
|
171
|
+
file_content = File.read(path)
|
172
|
+
|
173
|
+
# if namespace for :superuser don't exists then create it
|
174
|
+
unless file_content.include? 'namespace :superuser do'
|
175
|
+
route "\tnamespace :superuser do\n\t\tresources :#{resources}\n\tend"
|
176
|
+
return
|
177
|
+
end
|
178
|
+
|
179
|
+
# the regular expression string should be between single quotes not double quotes
|
180
|
+
# the regular expression string should not include delimiters
|
181
|
+
# the matching will stop when find the first occurence of 'end'
|
182
|
+
regex_string = 'namespace \:superuser do[^end]*' + replace_text
|
183
|
+
regex = Regexp.new(regex_string)
|
184
|
+
|
185
|
+
#unless file_content.include? replace_text
|
186
|
+
unless regex.match file_content
|
187
|
+
content = file_content.sub(/(#{Regexp.escape(search_text)})/mi, "#{search_text}\n\t\t#{replace_text}")
|
188
|
+
File.open(path, 'wb') { |file| file.write(content) }
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
def add_layout_links(relative_file, search_text, replace_text)
|
194
|
+
|
195
|
+
path = destination_path(relative_file)
|
196
|
+
file_content = File.read(path)
|
197
|
+
|
198
|
+
unless file_content.include? replace_text
|
199
|
+
content = file_content.sub(/(#{Regexp.escape(search_text)})/mi, "#{search_text}\n\t\t\t\t#{replace_text}")
|
200
|
+
File.open(path, 'wb') { |file| file.write(content) }
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Superuser
|
2
|
+
|
3
|
+
class BaseController < ApplicationController
|
4
|
+
|
5
|
+
layout 'superuser/application'
|
6
|
+
|
7
|
+
before_action :authenticated_superuser
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def authenticated_superuser
|
12
|
+
# SET YOUR CONDITION HERE TO PREVENT ACCESSING THE ADMIN AREA FROM ANYONE
|
13
|
+
# example: redirect_to root_url if !current_user || current_user.role != 'admin'
|
14
|
+
end
|
15
|
+
|
16
|
+
def run_search(model)
|
17
|
+
|
18
|
+
search_map = {'gt': '>', 'lt': '<', 'gte': '>=', 'lte': '<=', 'equal': '=', 'like': 'LIKE'}
|
19
|
+
|
20
|
+
operator = search_map[params[:operator].downcase.to_sym]
|
21
|
+
|
22
|
+
val = (operator == 'LIKE' ? "%#{params[:search_value]}%" : params[:search_value])
|
23
|
+
|
24
|
+
results = model
|
25
|
+
.where("cast(#{params[:search_field]} as text) #{operator} ?", val)
|
26
|
+
.page(params[:page]).per(10)
|
27
|
+
|
28
|
+
flash.now[:warning] = "Sorry! cannot find any #{params[:search_field].upcase} with the value #{operator} '#{params[:search_value]}' :(" if results.blank?
|
29
|
+
|
30
|
+
return results
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def flash_class(key)
|
35
|
+
|
36
|
+
case key
|
37
|
+
|
38
|
+
when "success" then "alert alert-success"
|
39
|
+
|
40
|
+
when "warning" then "alert alert-warning"
|
41
|
+
|
42
|
+
when "notice" then "alert alert-info"
|
43
|
+
|
44
|
+
when "alert" then "alert alert-danger"
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
helper_method :flash_class
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Superuser
|
2
|
+
|
3
|
+
class <%= get_controller_name %>Controller < BaseController
|
4
|
+
|
5
|
+
# List all the (only) actions so it won't be applied to user's custom actions
|
6
|
+
|
7
|
+
before_action :set_resource, only: [:show, :edit, :update, :destroy]
|
8
|
+
|
9
|
+
# GET /<%= resources %>
|
10
|
+
def index
|
11
|
+
|
12
|
+
if params[:search]
|
13
|
+
|
14
|
+
@<%= resources %> = run_search(<%= get_model %>)
|
15
|
+
|
16
|
+
else
|
17
|
+
|
18
|
+
@<%= resources %> = <%= get_model %>.page(params[:page]).per(10)
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
# GET /<%= resources %>/1
|
25
|
+
def show
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
# GET /<%= resources %>/new
|
30
|
+
def new
|
31
|
+
|
32
|
+
@<%= resource %> = <%= get_model %>.new
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
# GET /<%= resources %>/1/edit
|
37
|
+
def edit
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
# POST /<%= resources %>
|
42
|
+
def create
|
43
|
+
|
44
|
+
@<%= resource %> = <%= get_model %>.new(resource_params)
|
45
|
+
|
46
|
+
if @<%= resource %>.save
|
47
|
+
|
48
|
+
redirect_to [:superuser, @<%= resource %>], notice: "<%= resource %> was successfully created."
|
49
|
+
|
50
|
+
else
|
51
|
+
|
52
|
+
render :new
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
# PATCH/PUT /<%= resources %>/1
|
59
|
+
def update
|
60
|
+
|
61
|
+
if @<%= resource %>.update(resource_params)
|
62
|
+
|
63
|
+
redirect_to [:superuser, @<%= resource %>], notice: "<%= resource %> was successfully updated."
|
64
|
+
|
65
|
+
else
|
66
|
+
|
67
|
+
render :edit
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
# DELETE /<%= resources %>/1
|
74
|
+
def destroy
|
75
|
+
|
76
|
+
@<%= resource %>.destroy
|
77
|
+
|
78
|
+
redirect_to [:superuser, :<%= resources %>], notice: "<%= resource %> was successfully destroyed."
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
# Use callbacks to share common setup or constraints between actions.
|
84
|
+
|
85
|
+
|
86
|
+
# Only allow a trusted parameter "white list" through.
|
87
|
+
def resource_params
|
88
|
+
|
89
|
+
params.require(:<%= resource %>).permit(<%= editable_attributes.map { |a| ":" + a[:name] }.join(', ') %>)
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
def set_resource
|
95
|
+
|
96
|
+
@<%= resource %> = <%= get_model %>.find(params[:id])
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
File without changes
|
@@ -0,0 +1,311 @@
|
|
1
|
+
$navbar-height: 68px;
|
2
|
+
|
3
|
+
html{
|
4
|
+
height: 100%;
|
5
|
+
}
|
6
|
+
body{
|
7
|
+
background: #F2F2F2;
|
8
|
+
}
|
9
|
+
|
10
|
+
.attribute-line{
|
11
|
+
padding: 0.8rem;
|
12
|
+
|
13
|
+
&:nth-child(even){
|
14
|
+
background: #EFEFEF;
|
15
|
+
}
|
16
|
+
|
17
|
+
&:nth-child(odd){
|
18
|
+
background: #FAFAFA;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
|
23
|
+
.footer{
|
24
|
+
padding: 16px;
|
25
|
+
// height: 40px;
|
26
|
+
// line-height: 40px;
|
27
|
+
// font-size: 1rem;
|
28
|
+
// bottom: 0;
|
29
|
+
// color: #67757c;
|
30
|
+
// left: 0px;
|
31
|
+
// position: absolute;
|
32
|
+
// right: 0;
|
33
|
+
border-top: 1px solid rgba(120, 130, 140, 0.13);
|
34
|
+
background: #ffffff;
|
35
|
+
}
|
36
|
+
a{
|
37
|
+
color: #17a2b8;
|
38
|
+
&:hover{
|
39
|
+
color: #2C8199;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
.alert{
|
43
|
+
text-transform: capitalize;
|
44
|
+
}
|
45
|
+
.alert-danger{
|
46
|
+
color: #EC005F;
|
47
|
+
border-color: #EC005F;
|
48
|
+
background-color: #fff9f9;
|
49
|
+
border-radius: 0;
|
50
|
+
}
|
51
|
+
|
52
|
+
// ======== Form Errors ==========
|
53
|
+
.error_title{
|
54
|
+
font-size: 1.2rem;
|
55
|
+
padding-bottom: 0.6rem;
|
56
|
+
border-bottom: 1px solid #F46770;
|
57
|
+
}
|
58
|
+
// ======== End Form Errors ======
|
59
|
+
// ======== Navbar ==========
|
60
|
+
.navbar{
|
61
|
+
background: #FFF;
|
62
|
+
height: $navbar-height;
|
63
|
+
// line-height: 68px;
|
64
|
+
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.06);
|
65
|
+
}
|
66
|
+
|
67
|
+
.navbar-brand{
|
68
|
+
font-size: 1.6rem;
|
69
|
+
font-weight: 700;
|
70
|
+
text-transform: capitalize;
|
71
|
+
}
|
72
|
+
|
73
|
+
.navbar-brand .logo_part_1{
|
74
|
+
color: #F24D68;
|
75
|
+
}
|
76
|
+
|
77
|
+
.navbar-brand .logo_part_2{
|
78
|
+
color: #424534;
|
79
|
+
}
|
80
|
+
|
81
|
+
.navbar-light .navbar-brand:hover{
|
82
|
+
color: #fff;
|
83
|
+
}
|
84
|
+
|
85
|
+
.navbar .navbar-toggler{
|
86
|
+
|
87
|
+
font-size: .9rem;
|
88
|
+
padding: .2rem;
|
89
|
+
}
|
90
|
+
.navbar-light .navbar-toggler{
|
91
|
+
border: 0 none;
|
92
|
+
}
|
93
|
+
|
94
|
+
// ======== End Navbar ==========
|
95
|
+
|
96
|
+
|
97
|
+
// ======== Sidebar ==========
|
98
|
+
.sidebar{
|
99
|
+
width: 240px;
|
100
|
+
position: fixed;
|
101
|
+
top:68px;
|
102
|
+
left: 0;
|
103
|
+
height: 100%;
|
104
|
+
/*background: #242a33;*/
|
105
|
+
background: #fff;
|
106
|
+
background: #F46770;
|
107
|
+
|
108
|
+
}
|
109
|
+
|
110
|
+
.sidebar .sidebar_title{
|
111
|
+
color: #F2F2F2;
|
112
|
+
border-bottom: 1px solid #EFEFEF;
|
113
|
+
padding: 0.8rem;
|
114
|
+
font-weight: 600;
|
115
|
+
font-size: 1.2rem;
|
116
|
+
}
|
117
|
+
|
118
|
+
.sidebar .sidebar_item, .sidebar .sidebar_dashboard_link{
|
119
|
+
text-transform: capitalize;
|
120
|
+
a{
|
121
|
+
transition: 0.3s;
|
122
|
+
color: #F2F2F2;
|
123
|
+
padding: 0.6rem 1.2rem;
|
124
|
+
display: block;
|
125
|
+
text-decoration: none;
|
126
|
+
&:hover, &:focus, &:active{
|
127
|
+
background: #FFF;
|
128
|
+
color: #F46770;
|
129
|
+
}
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
// ======== End Sidebar ==========
|
134
|
+
|
135
|
+
|
136
|
+
// ======== Main content ==========
|
137
|
+
.main-content{
|
138
|
+
position: relative;
|
139
|
+
margin-left: 240px;
|
140
|
+
margin-top: 68px;
|
141
|
+
padding: 15px 0 15px;
|
142
|
+
}
|
143
|
+
|
144
|
+
.main-content .content{
|
145
|
+
background: white;
|
146
|
+
padding: 2rem;
|
147
|
+
|
148
|
+
h1{
|
149
|
+
font-weight: normal;
|
150
|
+
margin-top: 0;
|
151
|
+
margin-bottom: 0.4rem;
|
152
|
+
color: #455A65;
|
153
|
+
font-size: 1.5rem;
|
154
|
+
text-transform: capitalize;
|
155
|
+
}
|
156
|
+
|
157
|
+
.card{
|
158
|
+
display: block;
|
159
|
+
margin-top: 1rem;
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
// ======== End Main content ==========
|
164
|
+
|
165
|
+
|
166
|
+
// ======== Bootstrap button ===========
|
167
|
+
.btn{
|
168
|
+
border-radius: 0.2rem;
|
169
|
+
}
|
170
|
+
.btn-group-lg>.btn, .btn-lg{
|
171
|
+
font-size: 1.1rem;
|
172
|
+
}
|
173
|
+
// ======== End Bootstrap button ==========
|
174
|
+
|
175
|
+
|
176
|
+
.form-control:focus{
|
177
|
+
border-color: #e5d200;
|
178
|
+
box-shadow: none;
|
179
|
+
}
|
180
|
+
|
181
|
+
.dropdown button{
|
182
|
+
font-size: 0.9rem;
|
183
|
+
}
|
184
|
+
|
185
|
+
// .dropdown-menu{
|
186
|
+
// left: auto;
|
187
|
+
// right: 0;
|
188
|
+
// float: right;
|
189
|
+
// }
|
190
|
+
|
191
|
+
.dropdown-item:focus{
|
192
|
+
background-color: #E9EAEF;
|
193
|
+
color: #333;
|
194
|
+
}
|
195
|
+
|
196
|
+
// ======= Table =========
|
197
|
+
.table{
|
198
|
+
thead th{
|
199
|
+
text-transform: capitalize;
|
200
|
+
font-weight: 700;
|
201
|
+
padding: 0.9rem 0.75rem;
|
202
|
+
}
|
203
|
+
td{
|
204
|
+
padding: 0.9rem 0.75rem;
|
205
|
+
vertical-align: middle;
|
206
|
+
}
|
207
|
+
|
208
|
+
tr{
|
209
|
+
cursor: default;
|
210
|
+
transition: 0.3s;
|
211
|
+
}
|
212
|
+
tr:hover{
|
213
|
+
background-color: #F8F9FA !important;
|
214
|
+
}
|
215
|
+
}
|
216
|
+
// ===== End Table ======
|
217
|
+
|
218
|
+
|
219
|
+
// ======== Search Form ====================
|
220
|
+
|
221
|
+
.search_form{
|
222
|
+
input[type=text], select, textarea{
|
223
|
+
width: auto;
|
224
|
+
margin-bottom: 0.4rem;
|
225
|
+
}
|
226
|
+
.btn{
|
227
|
+
margin-top: -0.1rem;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
// ======= End Search Form =================
|
232
|
+
|
233
|
+
|
234
|
+
// ======== Kaminari Pagination ===========
|
235
|
+
.pagination{
|
236
|
+
.page-link{
|
237
|
+
color: #444;
|
238
|
+
}
|
239
|
+
.page-item.active .page-link{
|
240
|
+
color: #FFFFFF;
|
241
|
+
background-color: #F46770;
|
242
|
+
border-color: #F46770;
|
243
|
+
}
|
244
|
+
}
|
245
|
+
|
246
|
+
.kaminari_pagination nav{
|
247
|
+
display: inline-block;
|
248
|
+
ul{
|
249
|
+
margin-bottom: 0;
|
250
|
+
}
|
251
|
+
}
|
252
|
+
// ======= End Kaminari Pagination =========
|
253
|
+
|
254
|
+
@media (max-width: 1064px) {
|
255
|
+
.search_form{
|
256
|
+
.condition-label{
|
257
|
+
display: block;
|
258
|
+
}
|
259
|
+
}
|
260
|
+
}
|
261
|
+
|
262
|
+
@media (max-width: 960px) {
|
263
|
+
.search_form{
|
264
|
+
input[type=text], select, textarea{
|
265
|
+
width: 100% !important;
|
266
|
+
display: block !important;
|
267
|
+
margin-bottom: 0.4rem;
|
268
|
+
}
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
@media (max-width: 768px) {
|
273
|
+
|
274
|
+
.sidebar{
|
275
|
+
left: 0;
|
276
|
+
width: 180px;
|
277
|
+
}
|
278
|
+
|
279
|
+
.main-content{
|
280
|
+
margin-left: 180px;
|
281
|
+
}
|
282
|
+
}
|
283
|
+
|
284
|
+
@media (max-width: 576px) {
|
285
|
+
|
286
|
+
.search_form{
|
287
|
+
margin-top: 1rem;
|
288
|
+
}
|
289
|
+
|
290
|
+
.sidebar{
|
291
|
+
// display: none;
|
292
|
+
// position: absolute;
|
293
|
+
// width: 240px;
|
294
|
+
//left: -240px;
|
295
|
+
transform: translateX(-240px);
|
296
|
+
transition-duration: 0.3s;
|
297
|
+
z-index: 99999;
|
298
|
+
}
|
299
|
+
|
300
|
+
.main-content{
|
301
|
+
margin-left: auto;
|
302
|
+
|
303
|
+
}
|
304
|
+
|
305
|
+
.open-sidebar{
|
306
|
+
.sidebar{
|
307
|
+
transform: translateX(0px);
|
308
|
+
|
309
|
+
}
|
310
|
+
}
|
311
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<%= "<%= form_for [:superuser, #{resource}] do |f| %%>" %>
|
2
|
+
|
3
|
+
<%= "<% if #{resource}.errors.any? %%>" %>
|
4
|
+
<div id="error_explanation" class="alert alert-danger">
|
5
|
+
<h3 class="error_title"><%= "<%= pluralize(#{resource}.errors.count, 'error') %%>" %> prohibited this resource from being saved:</h3>
|
6
|
+
|
7
|
+
<ul>
|
8
|
+
<%= "<% #{resource}.errors.full_messages.each do |message| %%>" %>
|
9
|
+
<li><%= "<%= message %%>" %></li>
|
10
|
+
<%= "<% end %%>" %>
|
11
|
+
</ul>
|
12
|
+
</div>
|
13
|
+
<%= "<% end %%>" %>
|
14
|
+
|
15
|
+
<% editable_attributes.each do |attribute| %>
|
16
|
+
<div class="form-group">
|
17
|
+
<%= "<%= f.label :#{attribute[:name]} %%>" %>
|
18
|
+
<%= "<%= f.#{field_type(attribute[:type])} :#{attribute[:name]}, class: \"form-control\" %%>" %>
|
19
|
+
</div>
|
20
|
+
<% end -%>
|
21
|
+
|
22
|
+
<%= "<%= f.submit (#{resource}.new_record? ? 'Create resource' : 'Update resource'), class: 'btn btn-info btn-lg' %%>" %>
|
23
|
+
|
24
|
+
|
25
|
+
<%= "<% end %%>" %>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<div class="card p-2 p-md-4">
|
2
|
+
|
3
|
+
<div class="card-title">
|
4
|
+
Search :
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<div class="text-center">
|
8
|
+
|
9
|
+
<%= "<%= form_tag [:superuser, obj], method: :get, class: 'search_form' do %%>" %>
|
10
|
+
|
11
|
+
<span class="condition-label">Condition :</span>
|
12
|
+
|
13
|
+
<%= """
|
14
|
+
<%
|
15
|
+
options = []
|
16
|
+
obj.classify.constantize.column_names.each do |column_name|
|
17
|
+
options << column_name
|
18
|
+
end
|
19
|
+
%%>
|
20
|
+
""" %>
|
21
|
+
<%= "<%= hidden_field_tag :search, 'true' %%>" %>
|
22
|
+
<%= "<%= select_tag :search_field, options_for_select(options, params[:search_field]), class: 'form-control d-inline-block' %%>" %>
|
23
|
+
<%= "<%= select_tag :operator, options_for_select({'Equal': 'equal', 'Like': 'like', '>': 'gt', '<': 'lt', '>=': 'gte', '<=': 'lte'}, params[:operator]), class: 'form-control d-inline-block' %%>" %>
|
24
|
+
<%= "<%= text_field_tag :search_value, params[:search_value], placeholder: 'Search Value...', class: 'form-control d-inline-block' %%>" %>
|
25
|
+
<%= "<%= submit_tag :Search, class: 'btn btn-success' %%>" %>
|
26
|
+
|
27
|
+
<%= "<% end %%>" %>
|
28
|
+
|
29
|
+
|
30
|
+
</div>
|
31
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1>Welcome to your Dashboard</h1>
|
@@ -0,0 +1,64 @@
|
|
1
|
+
<h1 class="d-sm-inline-block"><%= resources %></h1>
|
2
|
+
|
3
|
+
<%#= without method_messing available as helper, it should be [main_app, :new, :superuser, @model.table_name.singularize] %>
|
4
|
+
<%= "<%= link_to 'Add new #{resource}', [:new, :superuser, :#{resource}], class: 'btn btn-info float-sm-right' %%>" %>
|
5
|
+
|
6
|
+
<%= "<%= render 'shared/search', obj: '#{resources}' %%>" %>
|
7
|
+
|
8
|
+
<div class="table-responsive">
|
9
|
+
|
10
|
+
<table class="table my-3">
|
11
|
+
|
12
|
+
<thead class="thead-light">
|
13
|
+
|
14
|
+
<tr>
|
15
|
+
<% editable_attributes.each do |attribute| -%>
|
16
|
+
<th><%= attribute[:name] %></th>
|
17
|
+
<% end -%>
|
18
|
+
<th></th>
|
19
|
+
|
20
|
+
</tr>
|
21
|
+
|
22
|
+
</thead>
|
23
|
+
|
24
|
+
<tbody>
|
25
|
+
|
26
|
+
<%= "<% @#{resources}.each do |#{resource}| %%>" %>
|
27
|
+
|
28
|
+
<tr>
|
29
|
+
|
30
|
+
<% editable_attributes.each do |attribute| -%>
|
31
|
+
<td><%= "<%= #{resource}[:#{attribute[:name]}] %%>" %></td>
|
32
|
+
<% end -%>
|
33
|
+
|
34
|
+
<td class="text-right">
|
35
|
+
|
36
|
+
|
37
|
+
<div class="dropdown">
|
38
|
+
<button class="btn btn-secondary dropdown-toggle p-1 px-2" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
39
|
+
Actions
|
40
|
+
</button>
|
41
|
+
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenuButton">
|
42
|
+
<div><%= "<%= link_to 'Show', [:superuser, #{resource}], class: 'dropdown-item' %%>" %></div>
|
43
|
+
<div><%= "<%= link_to 'Edit', [:edit, :superuser, #{resource}], class: 'dropdown-item' %%>" %></div>
|
44
|
+
<div><%= "<%= link_to 'Delete', [:superuser, #{resource}], method: :delete, data: { confirm: 'Are you sure?' }, class: 'dropdown-item' %%>" %></div>
|
45
|
+
</div>
|
46
|
+
</div>
|
47
|
+
|
48
|
+
</td>
|
49
|
+
|
50
|
+
</tr>
|
51
|
+
|
52
|
+
<%= '<% end %%>' %>
|
53
|
+
|
54
|
+
</tbody>
|
55
|
+
|
56
|
+
</table>
|
57
|
+
|
58
|
+
</div>
|
59
|
+
|
60
|
+
<hr class="mb-4">
|
61
|
+
|
62
|
+
<div class="kaminari_pagination text-center">
|
63
|
+
<%= "<%= paginate @#{resources} %%>" %>
|
64
|
+
</div>
|
@@ -0,0 +1,90 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
|
4
|
+
<head>
|
5
|
+
<title>Super User <%= '<%= controller_name %%>' %>#<%= '<%= action_name %%>' %></title>
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
7
|
+
|
8
|
+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
|
9
|
+
<%= '<%= stylesheet_link_tag "superuser/application", media: "all" %%>' %>
|
10
|
+
<%= '<%= javascript_include_tag "superuser/application" %%>' %>
|
11
|
+
<!-- CDN for flatpickr.css -->
|
12
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
|
13
|
+
<!-- end CDN for flatpickr.css -->
|
14
|
+
<%= '<%= csrf_meta_tags %%>' %>
|
15
|
+
|
16
|
+
</head>
|
17
|
+
|
18
|
+
<body>
|
19
|
+
|
20
|
+
<header>
|
21
|
+
<nav class="navbar navbar-expand-sm navbar-light fixed-top">
|
22
|
+
|
23
|
+
<%= '<%= link_to [:superuser, :root], class: "navbar-brand" do %%>' %>
|
24
|
+
<span class="logo_part_1">Super</span><span class="logo_part_2">user</span>
|
25
|
+
<%= '<% end %%>' %>
|
26
|
+
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
27
|
+
<span class="navbar-toggler-icon"></span>
|
28
|
+
</button>
|
29
|
+
</nav>
|
30
|
+
</header>
|
31
|
+
|
32
|
+
<aside class="sidebar">
|
33
|
+
<div class="">
|
34
|
+
<h2 class="sidebar_title">Resources</h2>
|
35
|
+
<div class="sidebar_dashboard_link">
|
36
|
+
</div>
|
37
|
+
<div class="sidebar_item">
|
38
|
+
<%#= link_to resources_name, [:superuser, :resources_name] %>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
</aside>
|
42
|
+
|
43
|
+
<div class="main-content">
|
44
|
+
<div class="container-fluid">
|
45
|
+
<div class="row">
|
46
|
+
<div class="col">
|
47
|
+
<div class="content">
|
48
|
+
<%= "<% flash.each do |key, value| %%>" %>
|
49
|
+
<div class="alert alert-<%= '<%= flash_class(key) %%>' %>"><%= '<%= value %%>' %></div>
|
50
|
+
<%= "<% end %%>" %>
|
51
|
+
<%= '<%= yield %%>' %>
|
52
|
+
</div>
|
53
|
+
</div>
|
54
|
+
</div>
|
55
|
+
</div>
|
56
|
+
</div>
|
57
|
+
|
58
|
+
|
59
|
+
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
60
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
|
61
|
+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
|
62
|
+
|
63
|
+
<!-- CDN for flatpickr.js -->
|
64
|
+
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
|
65
|
+
<!-- end CDN for flatpickr.js -->
|
66
|
+
|
67
|
+
<script type="text/javascript">
|
68
|
+
|
69
|
+
(function() {
|
70
|
+
|
71
|
+
document.querySelector('.navbar-toggler').addEventListener('click', function(){
|
72
|
+
body = document.getElementsByTagName('body')[0];
|
73
|
+
body.classList.toggle('open-sidebar');
|
74
|
+
});
|
75
|
+
|
76
|
+
// if input has class 'isdate' : show flatpickr < date without time >
|
77
|
+
$(".date-field").flatpickr();
|
78
|
+
// if input has class 'isdatetime' : show flatpickr < date with time (Hours + Minutes + Seconds) >
|
79
|
+
$(".datetime-field").flatpickr({
|
80
|
+
enableTime: true,
|
81
|
+
enableSeconds: true
|
82
|
+
});
|
83
|
+
|
84
|
+
})();
|
85
|
+
|
86
|
+
</script>
|
87
|
+
|
88
|
+
</body>
|
89
|
+
|
90
|
+
</html>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<h1>New <%= resource %></h1>
|
2
|
+
|
3
|
+
<br>
|
4
|
+
|
5
|
+
<%= "<%= render 'form', #{resource}: @#{resource} %%>" %>
|
6
|
+
|
7
|
+
<br>
|
8
|
+
|
9
|
+
<hr>
|
10
|
+
|
11
|
+
<div class="text-center">
|
12
|
+
<%= "<%= link_to 'Back', [:superuser, :#{resources}], class: 'btn btn-outline-secondary' %%>" %>
|
13
|
+
</div>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<h1 class="d-sm-inline-block"><%= resource %></h1>
|
2
|
+
|
3
|
+
<hr>
|
4
|
+
|
5
|
+
<% editable_attributes.each do |attribute| -%>
|
6
|
+
<div class="attribute-line">
|
7
|
+
<%= attribute[:name].capitalize %> :
|
8
|
+
<%= "<%= @#{resource}.#{attribute[:name]} %%>" %>
|
9
|
+
</div>
|
10
|
+
<% end -%>
|
11
|
+
|
12
|
+
|
13
|
+
<hr>
|
14
|
+
|
15
|
+
<%= "<%= link_to 'Edit', [:edit, :superuser, @#{resource}], class: 'btn btn-primary' %%>" %>
|
16
|
+
|
17
|
+
<%= "<%= link_to 'Back', [:superuser, :#{resources}], class: 'btn btn-secondary' %%>" %>
|
data/lib/superuser.rb
ADDED
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: superuser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- mody
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-05-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: kaminari
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
55
|
+
description: This gem will help you scaffold an admin area very quickly so you can
|
56
|
+
have full control over your code when you need customization
|
57
|
+
email:
|
58
|
+
- hello@scratchoo.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- lib/generators/superuser/USAGE
|
64
|
+
- lib/generators/superuser/superuser_generator.rb
|
65
|
+
- lib/generators/superuser/templates/base_controller.rb
|
66
|
+
- lib/generators/superuser/templates/controller_template.rb
|
67
|
+
- lib/generators/superuser/templates/dashboard_controller.rb
|
68
|
+
- lib/generators/superuser/templates/superuser_base.js
|
69
|
+
- lib/generators/superuser/templates/superuser_base.scss
|
70
|
+
- lib/generators/superuser/templates/views/_form.html.erb
|
71
|
+
- lib/generators/superuser/templates/views/_search.html.erb
|
72
|
+
- lib/generators/superuser/templates/views/dashboard_index.html.erb
|
73
|
+
- lib/generators/superuser/templates/views/edit.html.erb
|
74
|
+
- lib/generators/superuser/templates/views/index.html.erb
|
75
|
+
- lib/generators/superuser/templates/views/layouts/application.html.erb
|
76
|
+
- lib/generators/superuser/templates/views/new.html.erb
|
77
|
+
- lib/generators/superuser/templates/views/show.html.erb
|
78
|
+
- lib/superuser.rb
|
79
|
+
- lib/superuser/version.rb
|
80
|
+
homepage: https://github.com/scratchoo/superuser
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.7.7
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: Build An Admin Area Easily.
|
104
|
+
test_files: []
|