tennpipes-su 3.6.6
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/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
|