tennpipes-su 3.6.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +70 -0
- data/Rakefile +22 -0
- data/lib/tennpipes-su.rb +35 -0
- data/lib/tennpipes-su/access_control.rb +191 -0
- data/lib/tennpipes-su/bootstrap-less/alerts.less +67 -0
- data/lib/tennpipes-su/bootstrap-less/badges.less +55 -0
- data/lib/tennpipes-su/bootstrap-less/bootstrap.less +49 -0
- data/lib/tennpipes-su/bootstrap-less/breadcrumbs.less +26 -0
- data/lib/tennpipes-su/bootstrap-less/button-groups.less +226 -0
- data/lib/tennpipes-su/bootstrap-less/buttons.less +155 -0
- data/lib/tennpipes-su/bootstrap-less/carousel.less +232 -0
- data/lib/tennpipes-su/bootstrap-less/close.less +33 -0
- data/lib/tennpipes-su/bootstrap-less/code.less +63 -0
- data/lib/tennpipes-su/bootstrap-less/component-animations.less +29 -0
- data/lib/tennpipes-su/bootstrap-less/dropdowns.less +213 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/bordered-pulled.less +16 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/core.less +12 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/fixed-width.less +6 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/font-awesome.less +17 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/icons.less +412 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/larger.less +13 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/list.less +19 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/mixins.less +20 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/path.less +14 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/rotated-flipped.less +9 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/spinning.less +30 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/stacked.less +20 -0
- data/lib/tennpipes-su/bootstrap-less/font-awesome/variables.less +381 -0
- data/lib/tennpipes-su/bootstrap-less/forms.less +419 -0
- data/lib/tennpipes-su/bootstrap-less/glyphicons.less +233 -0
- data/lib/tennpipes-su/bootstrap-less/grid.less +100 -0
- data/lib/tennpipes-su/bootstrap-less/input-groups.less +157 -0
- data/lib/tennpipes-su/bootstrap-less/jumbotron.less +44 -0
- data/lib/tennpipes-su/bootstrap-less/labels.less +64 -0
- data/lib/tennpipes-su/bootstrap-less/list-group.less +110 -0
- data/lib/tennpipes-su/bootstrap-less/media.less +56 -0
- data/lib/tennpipes-su/bootstrap-less/mixins.less +926 -0
- data/lib/tennpipes-su/bootstrap-less/modals.less +138 -0
- data/lib/tennpipes-su/bootstrap-less/navbar.less +616 -0
- data/lib/tennpipes-su/bootstrap-less/navs.less +242 -0
- data/lib/tennpipes-su/bootstrap-less/normalize.less +423 -0
- data/lib/tennpipes-su/bootstrap-less/pager.less +55 -0
- data/lib/tennpipes-su/bootstrap-less/pagination.less +88 -0
- data/lib/tennpipes-su/bootstrap-less/panels.less +230 -0
- data/lib/tennpipes-su/bootstrap-less/popovers.less +133 -0
- data/lib/tennpipes-su/bootstrap-less/print.less +101 -0
- data/lib/tennpipes-su/bootstrap-less/progress-bars.less +80 -0
- data/lib/tennpipes-su/bootstrap-less/responsive-utilities.less +93 -0
- data/lib/tennpipes-su/bootstrap-less/scaffolding.less +134 -0
- data/lib/tennpipes-su/bootstrap-less/tables.less +233 -0
- data/lib/tennpipes-su/bootstrap-less/tennpipes-su.less +18 -0
- data/lib/tennpipes-su/bootstrap-less/theme.less +247 -0
- data/lib/tennpipes-su/bootstrap-less/thumbnails.less +36 -0
- data/lib/tennpipes-su/bootstrap-less/tooltip.less +95 -0
- data/lib/tennpipes-su/bootstrap-less/type.less +296 -0
- data/lib/tennpipes-su/bootstrap-less/utilities.less +56 -0
- data/lib/tennpipes-su/bootstrap-less/variables.less +827 -0
- data/lib/tennpipes-su/bootstrap-less/wells.less +29 -0
- data/lib/tennpipes-su/generators/actions.rb +78 -0
- data/lib/tennpipes-su/generators/admin_app.rb +169 -0
- data/lib/tennpipes-su/generators/admin_page.rb +68 -0
- data/lib/tennpipes-su/generators/orm.rb +172 -0
- data/lib/tennpipes-su/generators/templates/account/activerecord.rb.tt +41 -0
- data/lib/tennpipes-su/generators/templates/account/couchrest.rb.tt +67 -0
- data/lib/tennpipes-su/generators/templates/account/datamapper.rb.tt +56 -0
- data/lib/tennpipes-su/generators/templates/account/dynamoid.rb.tt +55 -0
- data/lib/tennpipes-su/generators/templates/account/minirecord.rb.tt +44 -0
- data/lib/tennpipes-su/generators/templates/account/mongoid.rb.tt +54 -0
- data/lib/tennpipes-su/generators/templates/account/mongomapper.rb.tt +47 -0
- data/lib/tennpipes-su/generators/templates/account/ohm.rb.tt +70 -0
- data/lib/tennpipes-su/generators/templates/account/seeds.rb.tt +29 -0
- data/lib/tennpipes-su/generators/templates/account/sequel.rb.tt +53 -0
- data/lib/tennpipes-su/generators/templates/app.rb.tt +42 -0
- data/lib/tennpipes-su/generators/templates/app/controllers/base.rb.tt +5 -0
- data/lib/tennpipes-su/generators/templates/app/controllers/sessions.rb.tt +29 -0
- data/lib/tennpipes-su/generators/templates/assets/images/favicon.ico +0 -0
- data/lib/tennpipes-su/generators/templates/assets/images/font/FontAwesome.otf +0 -0
- data/lib/tennpipes-su/generators/templates/assets/images/font/fontawesome-webfont.eot +0 -0
- data/lib/tennpipes-su/generators/templates/assets/images/font/fontawesome-webfont.svg +414 -0
- data/lib/tennpipes-su/generators/templates/assets/images/font/fontawesome-webfont.ttf +0 -0
- data/lib/tennpipes-su/generators/templates/assets/images/font/fontawesome-webfont.woff +0 -0
- data/lib/tennpipes-su/generators/templates/assets/images/logo.png +0 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/application.js +118 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/affix.js +137 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/alert.js +88 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/bootstrap.min.js +6 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/button.js +107 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/carousel.js +205 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/collapse.js +170 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/dropdown.js +147 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/modal.js +243 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/popover.js +110 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/scrollspy.js +153 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/tab.js +125 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/tooltip.js +399 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/bootstrap/transition.js +48 -0
- data/lib/tennpipes-su/generators/templates/assets/javascripts/jquery-1.11.0.min.js +4 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/application.css +353 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/bootstrap.css +4 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/fonts/FontAwesome.otf +0 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/fonts/fontawesome-webfont.eot +0 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/fonts/fontawesome-webfont.svg +414 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/fonts/fontawesome-webfont.ttf +0 -0
- data/lib/tennpipes-su/generators/templates/assets/stylesheets/fonts/fontawesome-webfont.woff +0 -0
- data/lib/tennpipes-su/generators/templates/erb/app/base/index.erb.tt +15 -0
- data/lib/tennpipes-su/generators/templates/erb/app/errors/403.erb.tt +3 -0
- data/lib/tennpipes-su/generators/templates/erb/app/errors/404.erb.tt +3 -0
- data/lib/tennpipes-su/generators/templates/erb/app/errors/500.erb.tt +3 -0
- data/lib/tennpipes-su/generators/templates/erb/app/layouts/application.erb.tt +64 -0
- data/lib/tennpipes-su/generators/templates/erb/app/layouts/error.erb.tt +23 -0
- data/lib/tennpipes-su/generators/templates/erb/app/sessions/new.erb.tt +44 -0
- data/lib/tennpipes-su/generators/templates/erb/page/_form.erb.tt +18 -0
- data/lib/tennpipes-su/generators/templates/erb/page/edit.erb.tt +10 -0
- data/lib/tennpipes-su/generators/templates/erb/page/index.erb.tt +81 -0
- data/lib/tennpipes-su/generators/templates/erb/page/new.erb.tt +9 -0
- data/lib/tennpipes-su/generators/templates/haml/app/base/index.haml.tt +12 -0
- data/lib/tennpipes-su/generators/templates/haml/app/errors/403.haml.tt +3 -0
- data/lib/tennpipes-su/generators/templates/haml/app/errors/404.haml.tt +3 -0
- data/lib/tennpipes-su/generators/templates/haml/app/errors/500.haml.tt +3 -0
- data/lib/tennpipes-su/generators/templates/haml/app/layouts/application.haml.tt +49 -0
- data/lib/tennpipes-su/generators/templates/haml/app/layouts/error.haml.tt +18 -0
- data/lib/tennpipes-su/generators/templates/haml/app/sessions/new.haml.tt +38 -0
- data/lib/tennpipes-su/generators/templates/haml/page/_form.haml.tt +16 -0
- data/lib/tennpipes-su/generators/templates/haml/page/edit.haml.tt +8 -0
- data/lib/tennpipes-su/generators/templates/haml/page/index.haml.tt +58 -0
- data/lib/tennpipes-su/generators/templates/haml/page/new.haml.tt +7 -0
- data/lib/tennpipes-su/generators/templates/page/controller.rb.tt +92 -0
- data/lib/tennpipes-su/generators/templates/slim/app/base/index.slim.tt +12 -0
- data/lib/tennpipes-su/generators/templates/slim/app/errors/403.slim.tt +3 -0
- data/lib/tennpipes-su/generators/templates/slim/app/errors/404.slim.tt +3 -0
- data/lib/tennpipes-su/generators/templates/slim/app/errors/500.slim.tt +3 -0
- data/lib/tennpipes-su/generators/templates/slim/app/layouts/application.slim.tt +48 -0
- data/lib/tennpipes-su/generators/templates/slim/app/layouts/error.slim.tt +19 -0
- data/lib/tennpipes-su/generators/templates/slim/app/sessions/new.slim.tt +37 -0
- data/lib/tennpipes-su/generators/templates/slim/page/_form.slim.tt +16 -0
- data/lib/tennpipes-su/generators/templates/slim/page/edit.slim.tt +8 -0
- data/lib/tennpipes-su/generators/templates/slim/page/index.slim.tt +56 -0
- data/lib/tennpipes-su/generators/templates/slim/page/new.slim.tt +7 -0
- data/lib/tennpipes-su/helpers/authentication_helpers.rb +108 -0
- data/lib/tennpipes-su/helpers/view_helpers.rb +87 -0
- data/lib/tennpipes-su/locale/admin/cs.yml +56 -0
- data/lib/tennpipes-su/locale/admin/da.yml +56 -0
- data/lib/tennpipes-su/locale/admin/de.yml +56 -0
- data/lib/tennpipes-su/locale/admin/en.yml +56 -0
- data/lib/tennpipes-su/locale/admin/es.yml +56 -0
- data/lib/tennpipes-su/locale/admin/fr.yml +56 -0
- data/lib/tennpipes-su/locale/admin/hu.yml +56 -0
- data/lib/tennpipes-su/locale/admin/it.yml +56 -0
- data/lib/tennpipes-su/locale/admin/ja.yml +57 -0
- data/lib/tennpipes-su/locale/admin/lv.yml +56 -0
- data/lib/tennpipes-su/locale/admin/nl.yml +56 -0
- data/lib/tennpipes-su/locale/admin/no.yml +56 -0
- data/lib/tennpipes-su/locale/admin/pl.yml +56 -0
- data/lib/tennpipes-su/locale/admin/pt_br.yml +56 -0
- data/lib/tennpipes-su/locale/admin/ro.yml +56 -0
- data/lib/tennpipes-su/locale/admin/ru.yml +57 -0
- data/lib/tennpipes-su/locale/admin/sv.yml +56 -0
- data/lib/tennpipes-su/locale/admin/tr.yml +56 -0
- data/lib/tennpipes-su/locale/admin/uk.yml +56 -0
- data/lib/tennpipes-su/locale/admin/zh_cn.yml +56 -0
- data/lib/tennpipes-su/locale/admin/zh_tw.yml +56 -0
- data/lib/tennpipes-su/locale/orm/cs.yml +12 -0
- data/lib/tennpipes-su/locale/orm/da.yml +12 -0
- data/lib/tennpipes-su/locale/orm/de.yml +12 -0
- data/lib/tennpipes-su/locale/orm/en.yml +12 -0
- data/lib/tennpipes-su/locale/orm/es.yml +12 -0
- data/lib/tennpipes-su/locale/orm/fr.yml +12 -0
- data/lib/tennpipes-su/locale/orm/hu.yml +12 -0
- data/lib/tennpipes-su/locale/orm/it.yml +12 -0
- data/lib/tennpipes-su/locale/orm/ja.yml +12 -0
- data/lib/tennpipes-su/locale/orm/lv.yml +12 -0
- data/lib/tennpipes-su/locale/orm/nl.yml +12 -0
- data/lib/tennpipes-su/locale/orm/no.yml +12 -0
- data/lib/tennpipes-su/locale/orm/pl.yml +38 -0
- data/lib/tennpipes-su/locale/orm/pt_br.yml +12 -0
- data/lib/tennpipes-su/locale/orm/ro.yml +12 -0
- data/lib/tennpipes-su/locale/orm/ru.yml +12 -0
- data/lib/tennpipes-su/locale/orm/sv.yml +12 -0
- data/lib/tennpipes-su/locale/orm/tr.yml +12 -0
- data/lib/tennpipes-su/locale/orm/uk.yml +12 -0
- data/lib/tennpipes-su/locale/orm/zh_cn.yml +12 -0
- data/lib/tennpipes-su/locale/orm/zh_tw.yml +12 -0
- data/test/fixtures/sequel.rb +72 -0
- data/test/generators/test_account_model_generator.rb +108 -0
- data/test/generators/test_admin_app_generator.rb +218 -0
- data/test/generators/test_admin_page_generator.rb +140 -0
- data/test/helper.rb +47 -0
- data/test/test_admin_application.rb +271 -0
- data/test/test_locale.rb +25 -0
- metadata +298 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
//
|
2
|
+
// Wells
|
3
|
+
// --------------------------------------------------
|
4
|
+
|
5
|
+
|
6
|
+
// Base class
|
7
|
+
.well {
|
8
|
+
min-height: 20px;
|
9
|
+
padding: 19px;
|
10
|
+
margin-bottom: 20px;
|
11
|
+
background-color: @well-bg;
|
12
|
+
border: 1px solid @well-border;
|
13
|
+
border-radius: @border-radius-base;
|
14
|
+
.box-shadow(inset 0 1px 1px rgba(0,0,0,.05));
|
15
|
+
blockquote {
|
16
|
+
border-color: #ddd;
|
17
|
+
border-color: rgba(0,0,0,.15);
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
// Sizes
|
22
|
+
.well-lg {
|
23
|
+
padding: 24px;
|
24
|
+
border-radius: @border-radius-large;
|
25
|
+
}
|
26
|
+
.well-sm {
|
27
|
+
padding: 9px;
|
28
|
+
border-radius: @border-radius-small;
|
29
|
+
}
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Tennpipes
|
2
|
+
module Generators
|
3
|
+
##
|
4
|
+
# Generator action definitions for the admin panel.
|
5
|
+
#
|
6
|
+
module Admin
|
7
|
+
##
|
8
|
+
# Important tasks for setting up or configuring the admin application.
|
9
|
+
#
|
10
|
+
module Actions
|
11
|
+
##
|
12
|
+
# Tell us which orm we are using.
|
13
|
+
#
|
14
|
+
def orm
|
15
|
+
fetch_component_choice(:orm).to_sym rescue :activerecord
|
16
|
+
end
|
17
|
+
alias :adapter :orm
|
18
|
+
|
19
|
+
##
|
20
|
+
# Tell us which rendering engine you are using.
|
21
|
+
#
|
22
|
+
def ext
|
23
|
+
fetch_component_choice(:admin_renderer).to_sym rescue :haml
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Tell us for now which orm we support
|
28
|
+
#
|
29
|
+
def supported_orm
|
30
|
+
[:minirecord, :datamapper, :activerecord, :mongomapper, :mongoid, :couchrest, :sequel, :ohm, :dynamoid]
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Tell us for now which rendering engine we support.
|
35
|
+
#
|
36
|
+
def supported_ext
|
37
|
+
[:haml, :slim, :erb]
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Add access_control permission in our app.rb.
|
42
|
+
#
|
43
|
+
def add_project_module(controller)
|
44
|
+
permission = " role.project_module :#{controller}, '/#{controller}'\n"
|
45
|
+
inject_into_file destination_root(@admin_path+'/app.rb'), permission, :after => "access_control.roles_for :admin do |role|\n"
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Remove from access_control permissions.
|
50
|
+
#
|
51
|
+
def remove_project_module(controller)
|
52
|
+
path = destination_root(@admin_path+'/app.rb')
|
53
|
+
say_status :replace, @admin_path+'/app.rb', :red
|
54
|
+
content = File.binread(path)
|
55
|
+
content.gsub!(/^\s+role\.project_module :#{controller}, '\/#{controller}'\n/, '')
|
56
|
+
File.open(path, 'wb') { |f| f.write content }
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Returns the app_name for the application at root.
|
61
|
+
#
|
62
|
+
# @param [String] app
|
63
|
+
# folder name of application.
|
64
|
+
#
|
65
|
+
# @return [String] module name for application.
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# fetch_app_name('subapp')
|
69
|
+
#
|
70
|
+
# @api public
|
71
|
+
def fetch_app_name(app='app')
|
72
|
+
app_path = destination_root(app, 'app.rb')
|
73
|
+
@app_name ||= File.read(app_path).scan(/module\s(.*?)\n/).flatten[0]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module Tennpipes
|
3
|
+
module Generators
|
4
|
+
##
|
5
|
+
# Defines the generator for creating a new admin app.
|
6
|
+
#
|
7
|
+
class AdminApp < Thor::Group
|
8
|
+
|
9
|
+
# Add this generator to our tennpipes-init
|
10
|
+
Tennpipes::Generators.add_generator(:admin, self)
|
11
|
+
|
12
|
+
# Define the source template root
|
13
|
+
def self.source_root; File.expand_path(File.dirname(__FILE__)); end
|
14
|
+
# Defines the "banner" text for the CLI.
|
15
|
+
def self.banner; "tennpipes-init admin"; end
|
16
|
+
|
17
|
+
# Include related modules.
|
18
|
+
include Thor::Actions
|
19
|
+
include Tennpipes::Generators::Actions
|
20
|
+
include Tennpipes::Generators::Admin::Actions
|
21
|
+
|
22
|
+
# Look for custom template files in a generators folder under the project root.
|
23
|
+
def source_paths
|
24
|
+
if File.exist? destination_root('generators', 'templates')
|
25
|
+
["#{destination_root('generators')}", File.expand_path(File.dirname(__FILE__))]
|
26
|
+
else
|
27
|
+
[File.expand_path(File.dirname(__FILE__))]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Description:\n\n\ttennpipes-init admin generates a new Tennpipes Admin application"
|
32
|
+
|
33
|
+
class_option :skip_migration, :aliases => "-s", :default => false, :type => :boolean
|
34
|
+
# class_option :models_path, :desc => 'The models destination path', :default => '.', :type => :string
|
35
|
+
class_option :root, :desc => "The root destination", :aliases => '-r', :default => ".", :type => :string
|
36
|
+
class_option :destroy, :aliases => '-d', :default => false, :type => :boolean
|
37
|
+
class_option :renderer, :aliases => '-e', :desc => "Rendering engine (erb, haml, slim)", :type => :string
|
38
|
+
class_option :admin_model, :aliases => '-m', :desc => "The name of model for access controlling", :default => 'Account', :type => :string
|
39
|
+
class_option :admin_name, :aliases => '-a', :desc => 'The admin application name and path', :default => 'admin', :type => :string
|
40
|
+
|
41
|
+
# Copies over the Tennpipes base admin application.
|
42
|
+
def create_admin
|
43
|
+
self.destination_root = options[:root]
|
44
|
+
if in_app_root?
|
45
|
+
unless supported_orm.include?(orm)
|
46
|
+
say "<= At the moment, Tennpipes only supports #{supported_orm.join(" or ")}. Sorry!", :yellow
|
47
|
+
raise SystemExit
|
48
|
+
end
|
49
|
+
|
50
|
+
tmp_ext = options[:renderer] || fetch_component_choice(:renderer)
|
51
|
+
unless supported_ext.include?(tmp_ext.to_sym)
|
52
|
+
say "<= Your are using '#{tmp_ext}' and for admin we only support '#{supported_ext.join(', ')}'. Please use -e haml or -e erb or -e slim", :yellow
|
53
|
+
raise SystemExit
|
54
|
+
end
|
55
|
+
|
56
|
+
# Get the app's namespace.
|
57
|
+
@app_name = fetch_app_name
|
58
|
+
|
59
|
+
# setup admin app name
|
60
|
+
@admin_name = options[:admin_name].classify
|
61
|
+
@admin_path = options[:admin_name].underscore
|
62
|
+
|
63
|
+
store_component_choice(:admin_renderer, tmp_ext)
|
64
|
+
|
65
|
+
self.behavior = :revoke if options[:destroy]
|
66
|
+
|
67
|
+
empty_directory destination_root(@admin_path)
|
68
|
+
|
69
|
+
# Setup Admin Model
|
70
|
+
@model_name = options[:admin_model].classify
|
71
|
+
@model_singular = @model_name.underscore
|
72
|
+
@model_plural = @model_singular.pluralize
|
73
|
+
|
74
|
+
directory "templates/app", destination_root(@admin_path)
|
75
|
+
directory "templates/assets", destination_root("public", @admin_path)
|
76
|
+
template "templates/app.rb.tt", destination_root(@admin_path + "/app.rb")
|
77
|
+
inject_into_file destination_root('config/apps.rb'), "\nTennpipes.mount(\"#{@app_name}::#{@admin_name}\", :app_file => Tennpipes.root('#{@admin_path}/app.rb')).to(\"/#{@admin_path}\")\n", :before => /^Tennpipes.mount.*\.to\('\/'\)$/
|
78
|
+
unless options[:destroy]
|
79
|
+
insert_middleware 'ActiveRecord::ConnectionAdapters::ConnectionManagement', @admin_path if [:minirecord, :activerecord].include?(orm)
|
80
|
+
end
|
81
|
+
|
82
|
+
params = [
|
83
|
+
@model_singular, "name:string", "surname:string", "email:string", "crypted_password:string", "role:string",
|
84
|
+
"-a=#{options[:models_path]}",
|
85
|
+
"-r=#{options[:root]}"
|
86
|
+
]
|
87
|
+
params << "-s" if options[:skip_migration]
|
88
|
+
params << "-d" if options[:destroy]
|
89
|
+
|
90
|
+
Tennpipes::Generators::Model.start(params)
|
91
|
+
column = Struct.new(:name, :type)
|
92
|
+
columns = [:id, :name, :surname, :email].map { |col| column.new(col) }
|
93
|
+
column_fields = [
|
94
|
+
{ :name => :name, :field_type => :text_field },
|
95
|
+
{ :name => :surname, :field_type => :text_field },
|
96
|
+
{ :name => :email, :field_type => :text_field },
|
97
|
+
{ :name => :password, :field_type => :password_field },
|
98
|
+
{ :name => :password_confirmation, :field_type => :password_field },
|
99
|
+
{ :name => :role, :field_type => :text_field }
|
100
|
+
]
|
101
|
+
|
102
|
+
unless options[:destroy]
|
103
|
+
admin_app = Tennpipes::Generators::AdminPage.new([@model_singular], :root => options[:root], :destroy => options[:destroy], :admin_model => @model_singular, :admin_name => @admin_name)
|
104
|
+
admin_app.default_orm = Tennpipes::Admin::Generators::Orm.new(@model_singular, orm, columns, column_fields)
|
105
|
+
admin_app.invoke_all
|
106
|
+
end
|
107
|
+
|
108
|
+
# TODO See this, there's something wrong it's not being applied properly or something because test_account_model_generator last test fails.
|
109
|
+
template "templates/account/#{orm}.rb.tt", destination_root("models", "#{@model_singular}.rb"), :force => true
|
110
|
+
|
111
|
+
if File.exist?(destination_root("db/seeds.rb"))
|
112
|
+
run "mv #{destination_root('db/seeds.rb')} #{destination_root('db/seeds.old')}"
|
113
|
+
end
|
114
|
+
template "templates/account/seeds.rb.tt", destination_root("db/seeds.rb")
|
115
|
+
|
116
|
+
empty_directory destination_root(@admin_path+"/controllers")
|
117
|
+
empty_directory destination_root(@admin_path+"/views")
|
118
|
+
empty_directory destination_root(@admin_path+"/views/base")
|
119
|
+
empty_directory destination_root(@admin_path+"/views/layouts")
|
120
|
+
empty_directory destination_root(@admin_path+"/views/sessions")
|
121
|
+
empty_directory destination_root(@admin_path+"/views/errors")
|
122
|
+
|
123
|
+
template "templates/#{ext}/app/base/index.#{ext}.tt", destination_root(@admin_path+"/views/base/index.#{ext}")
|
124
|
+
template "templates/#{ext}/app/layouts/application.#{ext}.tt", destination_root(@admin_path+"/views/layouts/application.#{ext}")
|
125
|
+
template "templates/#{ext}/app/layouts/error.#{ext}.tt", destination_root(@admin_path+"/views/layouts/error.#{ext}")
|
126
|
+
template "templates/#{ext}/app/sessions/new.#{ext}.tt", destination_root(@admin_path+"/views/sessions/new.#{ext}")
|
127
|
+
# Custom error.
|
128
|
+
template "templates/#{ext}/app/errors/403.#{ext}.tt", destination_root(@admin_path+"/views/errors/403.#{ext}")
|
129
|
+
template "templates/#{ext}/app/errors/404.#{ext}.tt", destination_root(@admin_path+"/views/errors/404.#{ext}")
|
130
|
+
template "templates/#{ext}/app/errors/500.#{ext}.tt", destination_root(@admin_path+"/views/errors/500.#{ext}")
|
131
|
+
|
132
|
+
unless options[:destroy]
|
133
|
+
add_project_module @model_plural
|
134
|
+
require_dependencies('bcrypt')
|
135
|
+
end
|
136
|
+
|
137
|
+
# A nicer select box.
|
138
|
+
# TODO FIXME This doesn't make much sense in here. Review.
|
139
|
+
# gsub_file destination_root("admin/views/#{@model_plural}/_form.#{ext}"), "f.text_field :role, :class => :text_field", "f.select :role, :options => access_control.roles"
|
140
|
+
|
141
|
+
# Destroy account only if not logged in.
|
142
|
+
gsub_file destination_root(@admin_path+"/controllers/#{@model_plural}.rb"), "if #{@model_singular}.destroy", "if #{@model_singular} != current_account && #{@model_singular}.destroy"
|
143
|
+
return if self.behavior == :revoke
|
144
|
+
|
145
|
+
instructions = []
|
146
|
+
instructions << "Run 'bundle'"
|
147
|
+
if [:activerecord, :datamapper, :sequel].include?(orm)
|
148
|
+
instructions << "Run 'bundle exec rake db:create' if you have not created a database yet"
|
149
|
+
instructions << "Run 'bundle exec rake db:migrate'"
|
150
|
+
end
|
151
|
+
instructions << "Now repeat after me... 'ohm mani padme hum', 'ohm mani padme hum'... :)" if orm == :ohm
|
152
|
+
instructions << "Run 'bundle exec rake db:seed'"
|
153
|
+
instructions << "Visit the admin panel in the browser at '/#{@admin_path}'"
|
154
|
+
instructions.map! { |i| " #{instructions.index(i)+1}) #{i}" }
|
155
|
+
|
156
|
+
say
|
157
|
+
say "="*65, :green
|
158
|
+
say "The admin panel has been mounted! Next, follow these steps:", :green
|
159
|
+
say "="*65, :green
|
160
|
+
say instructions.join("\n")
|
161
|
+
say "="*65, :green
|
162
|
+
say
|
163
|
+
else
|
164
|
+
say "You are not at the root of a Tennpipes application! (config/boot.rb not found)"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module Tennpipes
|
3
|
+
module Generators
|
4
|
+
##
|
5
|
+
# Defines the generator for creating a new admin page.
|
6
|
+
#
|
7
|
+
class AdminPage < Thor::Group
|
8
|
+
attr_accessor :default_orm
|
9
|
+
|
10
|
+
# Add this generator to our tennpipes-init.
|
11
|
+
Tennpipes::Generators.add_generator(:admin_page, self)
|
12
|
+
|
13
|
+
# Define the source template root.
|
14
|
+
def self.source_root; File.expand_path(File.dirname(__FILE__)); end
|
15
|
+
# Defines the "banner" text for the CLI.
|
16
|
+
def self.banner; "tennpipes-init admin_page [model]"; end
|
17
|
+
|
18
|
+
# Include related modules.
|
19
|
+
include Thor::Actions
|
20
|
+
include Tennpipes::Generators::Actions
|
21
|
+
include Tennpipes::Generators::Admin::Actions
|
22
|
+
|
23
|
+
# Look for custom template files in a generators folder under the project root.
|
24
|
+
def source_paths
|
25
|
+
if File.exist? destination_root('generators')
|
26
|
+
["#{destination_root('generators')}", File.expand_path(File.dirname(__FILE__))]
|
27
|
+
else
|
28
|
+
[File.expand_path(File.dirname(__FILE__))]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Description:\n\n\ttennpipes-init admin_page model(s)"
|
33
|
+
argument :models, :desc => "The name(s) of your model(s)", :type => :array
|
34
|
+
class_option :skip_migration, :aliases => "-s", :default => false, :type => :boolean
|
35
|
+
class_option :root, :desc => "The root destination", :aliases => '-r', :type => :string
|
36
|
+
class_option :destroy, :aliases => '-d', :default => false, :type => :boolean
|
37
|
+
class_option :admin_name, :aliases => '-a', :desc => 'The admin application name and path', :default => 'admin', :type => :string
|
38
|
+
# Show help if no argv given.
|
39
|
+
require_arguments!
|
40
|
+
|
41
|
+
# Create controller for admin.
|
42
|
+
def create_controller
|
43
|
+
self.destination_root = options[:root]
|
44
|
+
if in_app_root?
|
45
|
+
@app_name = fetch_app_name
|
46
|
+
@admin_name = options[:admin_name].classify
|
47
|
+
@admin_path = options[:admin_name].underscore
|
48
|
+
@admin_model = options[:admin_model]
|
49
|
+
models.each do |model|
|
50
|
+
@orm = default_orm || Tennpipes::Admin::Generators::Orm.new(model, adapter)
|
51
|
+
self.behavior = :revoke if options[:destroy]
|
52
|
+
empty_directory destination_root(@admin_path+"/views/#{@orm.name_plural}")
|
53
|
+
|
54
|
+
template "templates/page/controller.rb.tt", destination_root(@admin_path+"/controllers/#{@orm.name_plural}.rb")
|
55
|
+
template "templates/#{ext}/page/_form.#{ext}.tt", destination_root(@admin_path+"/views/#{@orm.name_plural}/_form.#{ext}")
|
56
|
+
template "templates/#{ext}/page/edit.#{ext}.tt", destination_root(@admin_path+"/views/#{@orm.name_plural}/edit.#{ext}")
|
57
|
+
template "templates/#{ext}/page/index.#{ext}.tt", destination_root(@admin_path+"/views/#{@orm.name_plural}/index.#{ext}")
|
58
|
+
template "templates/#{ext}/page/new.#{ext}.tt", destination_root(@admin_path+"/views/#{@orm.name_plural}/new.#{ext}")
|
59
|
+
|
60
|
+
options[:destroy] ? remove_project_module(@orm.name_plural) : add_project_module(@orm.name_plural)
|
61
|
+
end
|
62
|
+
else
|
63
|
+
say "You are not at the root of a Tennpipes application! (config/boot.rb not found)"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
module Tennpipes
|
2
|
+
module Admin
|
3
|
+
##
|
4
|
+
# Contains all admin related generator functionality.
|
5
|
+
#
|
6
|
+
module Generators
|
7
|
+
# Defines a generic exception for the admin ORM handler.
|
8
|
+
class OrmError < StandardError; end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Defines the generic ORM management functions used to manipulate data for admin.
|
12
|
+
class Orm
|
13
|
+
attr_reader :klass_name, :klass, :name_plural, :name_singular, :orm, :name_param
|
14
|
+
|
15
|
+
def initialize(name, orm, columns=nil, column_fields=nil)
|
16
|
+
name = name.to_s
|
17
|
+
@klass_name = name.underscore.camelize
|
18
|
+
@klass = @klass_name.constantize rescue nil
|
19
|
+
@name_param = name.underscore.gsub(/\//, '_')
|
20
|
+
@name_singular = name.underscore.gsub(/^.*\//, '') # convert submodules i.e. FooBar::Jank.all # => jank
|
21
|
+
@name_plural = @name_singular.pluralize
|
22
|
+
@orm = orm.to_sym
|
23
|
+
@columns = columns
|
24
|
+
@column_fields = column_fields
|
25
|
+
raise OrmError, "Model '#{klass_name}' could not be found!\nPerhaps you would like to run 'bundle exec tennpipes g model #{klass_name}' to create it first?" if @columns.nil? && @klass.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def activerecord?
|
29
|
+
case orm
|
30
|
+
when :activerecord, :minirecord then true
|
31
|
+
else false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def field_type(type)
|
36
|
+
type = :string if type.nil? # couchrest-Hack to avoid the next line to fail
|
37
|
+
type = type.to_s.demodulize.downcase.to_sym unless type.is_a?(Symbol)
|
38
|
+
case type
|
39
|
+
when :integer, :float, :decimal then :text_field
|
40
|
+
when :string then :text_field
|
41
|
+
when :text then :text_area
|
42
|
+
when :boolean then :check_box
|
43
|
+
else :text_field
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Column = Struct.new(:name, :type) # for compatibility
|
48
|
+
|
49
|
+
def columns
|
50
|
+
@columns ||= case orm
|
51
|
+
when :activerecord then @klass.columns
|
52
|
+
when :minirecord then @klass.columns
|
53
|
+
when :datamapper then @klass.properties.map { |p| dm_column(p) }
|
54
|
+
when :couchrest then @klass.properties
|
55
|
+
when :mongoid then @klass.fields.values.reject { |col| %w[_id _type].include?(col.name) }
|
56
|
+
when :mongomapper then @klass.keys.values.reject { |key| key.name == "_id" } # On MongoMapper keys are an hash
|
57
|
+
when :sequel then @klass.db_schema.map { |k,v| v[:type] = :text if v[:db_type] =~ /^text/i; Column.new(k, v[:type]) }
|
58
|
+
when :ohm then @klass.attributes.map { |a| Column.new(a.to_s, :string) } # ohm has strings
|
59
|
+
when :dynamoid then @klass.attributes.map { |k,v| Column.new(k.to_s, v[:type]) }
|
60
|
+
else raise OrmError, "Adapter #{orm} is not yet supported!"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def dm_column(p)
|
65
|
+
case p
|
66
|
+
when DataMapper::Property::Text
|
67
|
+
Column.new(p.name, :text)
|
68
|
+
when DataMapper::Property::Boolean
|
69
|
+
Column.new(p.name, :boolean)
|
70
|
+
when DataMapper::Property::Integer
|
71
|
+
Column.new(p.name, :integer)
|
72
|
+
when DataMapper::Property::Decimal
|
73
|
+
Column.new(p.name, :decimal)
|
74
|
+
when DataMapper::Property::Float
|
75
|
+
Column.new(p.name, :float)
|
76
|
+
when DataMapper::Property::String
|
77
|
+
Column.new(p.name, :string)
|
78
|
+
else #if all fails, lets assume its stringish
|
79
|
+
Column.new(p.name, :string)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def column_fields
|
84
|
+
excluded_columns = %w[created_at updated_at]
|
85
|
+
case orm
|
86
|
+
when :mongoid then excluded_columns << '_id'
|
87
|
+
else excluded_columns << 'id'
|
88
|
+
end
|
89
|
+
|
90
|
+
column_fields = columns.dup
|
91
|
+
column_fields.reject! { |column| excluded_columns.include?(column.name.to_s) }
|
92
|
+
@column_fields ||= column_fields.map do |column|
|
93
|
+
{ :name => column.name, :field_type => field_type(column.type) }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def all
|
98
|
+
"#{klass_name}.all"
|
99
|
+
end
|
100
|
+
|
101
|
+
def find(params=nil)
|
102
|
+
case orm
|
103
|
+
when :activerecord, :minirecord, :mongomapper, :mongoid, :dynamoid then "#{klass_name}.find(#{params})"
|
104
|
+
when :datamapper, :couchrest then "#{klass_name}.get(#{params})"
|
105
|
+
when :sequel, :ohm then "#{klass_name}[#{params}]"
|
106
|
+
else raise OrmError, "Adapter #{orm} is not yet supported!"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def build(params=nil)
|
111
|
+
if params
|
112
|
+
"#{klass_name}.new(#{params})"
|
113
|
+
else
|
114
|
+
"#{klass_name}.new"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def save
|
119
|
+
case orm
|
120
|
+
when :sequel then "(@#{name_singular}.save rescue false)"
|
121
|
+
else "@#{name_singular}.save"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def update_attributes(params=nil)
|
126
|
+
case orm
|
127
|
+
when :activerecord, :minirecord, :mongomapper, :mongoid, :couchrest, :dynamoid then "@#{name_singular}.update_attributes(#{params})"
|
128
|
+
when :datamapper, :ohm then "@#{name_singular}.update(#{params})"
|
129
|
+
when :sequel then "@#{name_singular}.modified! && @#{name_singular}.update(#{params})"
|
130
|
+
else raise OrmError, "Adapter #{orm} is not yet supported!"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def destroy
|
135
|
+
case orm
|
136
|
+
when :ohm then "#{name_singular}.delete"
|
137
|
+
else "#{name_singular}.destroy"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def find_by_ids(params=nil)
|
142
|
+
case orm
|
143
|
+
when :ohm then "#{klass_name}.fetch(#{params})"
|
144
|
+
when :datamapper then "#{klass_name}.all(:id => #{params})"
|
145
|
+
when :sequel then "#{klass_name}.where(:id => #{params})"
|
146
|
+
when :mongoid then "#{klass_name}.find(#{params})"
|
147
|
+
when :couchrest then "#{klass_name}.all(:keys => #{params})"
|
148
|
+
when :dynamoid then "#{klass_name}.find(#{params})"
|
149
|
+
else find(params)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def multiple_destroy(params=nil)
|
154
|
+
case orm
|
155
|
+
when :ohm then "#{params}.each(&:delete)"
|
156
|
+
when :sequel then "#{params}.destroy"
|
157
|
+
when :datamapper then "#{params}.destroy"
|
158
|
+
when :couchrest, :mongoid, :mongomapper, :dynamoid then "#{params}.each(&:destroy)"
|
159
|
+
else "#{klass_name}.destroy #{params}"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def has_error(field)
|
164
|
+
case orm
|
165
|
+
when :datamapper, :ohm, :sequel then "@#{name_singular}.errors.key?(:#{field}) && @#{name_singular}.errors[:#{field}].count > 0"
|
166
|
+
else "@#{name_singular}.errors.include?(:#{field})"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|