typus 0.9.17
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.
- data/.gitignore +8 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +86 -0
- data/Rakefile +61 -0
- data/VERSION +1 -0
- data/app/controllers/admin/master_controller.rb +354 -0
- data/app/controllers/typus_controller.rb +128 -0
- data/app/helpers/admin/form_helper.rb +386 -0
- data/app/helpers/admin/master_helper.rb +104 -0
- data/app/helpers/admin/public_helper.rb +27 -0
- data/app/helpers/admin/sidebar_helper.rb +236 -0
- data/app/helpers/admin/table_helper.rb +227 -0
- data/app/helpers/typus_helper.rb +194 -0
- data/app/models/typus_mailer.rb +14 -0
- data/app/models/typus_user.rb +5 -0
- data/app/views/admin/dashboard/_sidebar.html.erb +9 -0
- data/app/views/admin/resources/edit.html.erb +24 -0
- data/app/views/admin/resources/index.html.erb +23 -0
- data/app/views/admin/resources/new.html.erb +22 -0
- data/app/views/admin/resources/show.html.erb +18 -0
- data/app/views/admin/shared/_footer.html.erb +1 -0
- data/app/views/admin/shared/_pagination.html.erb +28 -0
- data/app/views/layouts/admin.html.erb +73 -0
- data/app/views/layouts/typus.html.erb +29 -0
- data/app/views/typus/dashboard.html.erb +9 -0
- data/app/views/typus/recover_password.html.erb +7 -0
- data/app/views/typus/reset_password.html.erb +15 -0
- data/app/views/typus/sign_in.html.erb +9 -0
- data/app/views/typus/sign_up.html.erb +7 -0
- data/app/views/typus_mailer/reset_password_link.erb +11 -0
- data/config/locales/typus/de.yml +109 -0
- data/config/locales/typus/es.yml +109 -0
- data/config/locales/typus/language.yml.template +113 -0
- data/config/locales/typus/pt-BR.yml +111 -0
- data/config/locales/typus/ru.yml +111 -0
- data/generators/typus/templates/config/initializers/typus.rb +33 -0
- data/generators/typus/templates/config/typus/README +51 -0
- data/generators/typus/templates/config/typus/application.yml +6 -0
- data/generators/typus/templates/config/typus/application_roles.yml +23 -0
- data/generators/typus/templates/config/typus/typus.yml +14 -0
- data/generators/typus/templates/config/typus/typus_roles.yml +2 -0
- data/generators/typus/templates/db/create_typus_users.rb +21 -0
- data/generators/typus/templates/public/images/admin/arrow_down.gif +0 -0
- data/generators/typus/templates/public/images/admin/arrow_up.gif +0 -0
- data/generators/typus/templates/public/images/admin/spinner.gif +0 -0
- data/generators/typus/templates/public/images/admin/status_false.gif +0 -0
- data/generators/typus/templates/public/images/admin/status_true.gif +0 -0
- data/generators/typus/templates/public/images/admin/trash.gif +0 -0
- data/generators/typus/templates/public/javascripts/admin/application.js +14 -0
- data/generators/typus/templates/public/stylesheets/admin/reset.css +68 -0
- data/generators/typus/templates/public/stylesheets/admin/screen.css +729 -0
- data/generators/typus/typus_generator.rb +122 -0
- data/generators/typus_update_schema_to_01/templates/config/typus.yml +14 -0
- data/generators/typus_update_schema_to_01/templates/migration.rb +11 -0
- data/generators/typus_update_schema_to_01/typus_update_schema_to_01_generator.rb +19 -0
- data/lib/typus.rb +122 -0
- data/lib/typus/active_record.rb +307 -0
- data/lib/typus/authentication.rb +142 -0
- data/lib/typus/configuration.rb +85 -0
- data/lib/typus/extensions/routes.rb +15 -0
- data/lib/typus/format.rb +55 -0
- data/lib/typus/generator.rb +81 -0
- data/lib/typus/hash.rb +8 -0
- data/lib/typus/locale.rb +17 -0
- data/lib/typus/object.rb +21 -0
- data/lib/typus/quick_edit.rb +40 -0
- data/lib/typus/reloader.rb +15 -0
- data/lib/typus/string.rb +11 -0
- data/lib/typus/templates/index.html.erb +11 -0
- data/lib/typus/templates/resource_controller.rb.erb +15 -0
- data/lib/typus/templates/resource_controller_test.rb.erb +10 -0
- data/lib/typus/templates/resources_controller.rb.erb +37 -0
- data/lib/typus/user.rb +134 -0
- data/lib/vendor/active_record.rb +15 -0
- data/lib/vendor/paginator.rb +143 -0
- data/rails/init.rb +3 -0
- data/tasks/typus_tasks.rake +32 -0
- data/test/config/broken/application.yml +68 -0
- data/test/config/broken/application_roles.yml +20 -0
- data/test/config/broken/empty.yml +0 -0
- data/test/config/broken/empty_roles.yml +0 -0
- data/test/config/broken/undefined.yml +3 -0
- data/test/config/broken/undefined_roles.yml +6 -0
- data/test/config/default/typus.yml +14 -0
- data/test/config/default/typus_roles.yml +2 -0
- data/test/config/empty/empty_01.yml +0 -0
- data/test/config/empty/empty_01_roles.yml +0 -0
- data/test/config/empty/empty_02.yml +0 -0
- data/test/config/empty/empty_02_roles.yml +0 -0
- data/test/config/locales/es.yml +10 -0
- data/test/config/ordered/001_roles.yml +2 -0
- data/test/config/ordered/002_roles.yml +2 -0
- data/test/config/unordered/app_one_roles.yml +2 -0
- data/test/config/unordered/app_two_roles.yml +2 -0
- data/test/config/working/application.yml +68 -0
- data/test/config/working/application_roles.yml +22 -0
- data/test/config/working/typus.yml +14 -0
- data/test/config/working/typus_roles.yml +2 -0
- data/test/fixtures/app/controllers/admin/assets_controller.rb +2 -0
- data/test/fixtures/app/controllers/admin/categories_controller.rb +2 -0
- data/test/fixtures/app/controllers/admin/comments_controller.rb +2 -0
- data/test/fixtures/app/controllers/admin/pages_controller.rb +2 -0
- data/test/fixtures/app/controllers/admin/posts_controller.rb +2 -0
- data/test/fixtures/app/controllers/admin/status_controller.rb +6 -0
- data/test/fixtures/app/controllers/admin/typus_users_controller.rb +2 -0
- data/test/fixtures/app/controllers/admin/watch_dog_controller.rb +6 -0
- data/test/fixtures/app/views/admin/comments/_edit.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_index.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_new.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_show.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_sidebar.html.erb +1 -0
- data/test/fixtures/app/views/admin/dashboard/_content.html.erb +1 -0
- data/test/fixtures/app/views/admin/dashboard/_sidebar.html.erb +1 -0
- data/test/fixtures/app/views/admin/resources/_sidebar.html.erb +1 -0
- data/test/fixtures/app/views/admin/shared/_footer.html.erb +1 -0
- data/test/fixtures/app/views/admin/status/index.html.erb +1 -0
- data/test/fixtures/app/views/admin/templates/_datepicker.html.erb +1 -0
- data/test/fixtures/assets.yml +11 -0
- data/test/fixtures/categories.yml +14 -0
- data/test/fixtures/comments.yml +27 -0
- data/test/fixtures/pages.yml +41 -0
- data/test/fixtures/posts.yml +37 -0
- data/test/fixtures/typus_users.yml +54 -0
- data/test/functional/admin/assets_controller_test.rb +57 -0
- data/test/functional/admin/categories_controller_test.rb +106 -0
- data/test/functional/admin/comments_controller_test.rb +120 -0
- data/test/functional/admin/master_controller_test.rb +5 -0
- data/test/functional/admin/posts_controller_test.rb +261 -0
- data/test/functional/admin/status_controller_test.rb +43 -0
- data/test/functional/admin/typus_users_controller_test.rb +239 -0
- data/test/functional/typus_controller_test.rb +321 -0
- data/test/helper.rb +51 -0
- data/test/helpers/admin/form_helper_test.rb +337 -0
- data/test/helpers/admin/master_helper_test.rb +69 -0
- data/test/helpers/admin/public_helper_test.rb +26 -0
- data/test/helpers/admin/sidebar_helper_test.rb +335 -0
- data/test/helpers/admin/table_helper_test.rb +239 -0
- data/test/helpers/typus_helper_test.rb +117 -0
- data/test/lib/active_record_test.rb +382 -0
- data/test/lib/configuration_test.rb +94 -0
- data/test/lib/hash_test.rb +11 -0
- data/test/lib/routes_test.rb +71 -0
- data/test/lib/string_test.rb +25 -0
- data/test/lib/typus_test.rb +85 -0
- data/test/models.rb +51 -0
- data/test/schema.rb +64 -0
- data/test/unit/typus_mailer_test.rb +33 -0
- data/test/unit/typus_test.rb +17 -0
- data/test/unit/typus_user_roles_test.rb +90 -0
- data/test/unit/typus_user_test.rb +177 -0
- data/test/vendor/active_record_test.rb +18 -0
- data/test/vendor/paginator_test.rb +136 -0
- data/typus.gemspec +228 -0
- metadata +241 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
class TypusGenerator < Rails::Generator::Base
|
|
2
|
+
|
|
3
|
+
def manifest
|
|
4
|
+
|
|
5
|
+
record do |m|
|
|
6
|
+
|
|
7
|
+
# Default name for our application.
|
|
8
|
+
application = Rails.root.basename
|
|
9
|
+
|
|
10
|
+
# To create <tt>application.yml</tt> and <tt>application_roles.yml</tt>
|
|
11
|
+
# detect available AR models on the application.
|
|
12
|
+
models = Dir['app/models/*.rb'].collect { |x| File.basename(x).sub(/\.rb$/,'').camelize }
|
|
13
|
+
ar_models = []
|
|
14
|
+
|
|
15
|
+
models.each do |model|
|
|
16
|
+
begin
|
|
17
|
+
klass = model.constantize
|
|
18
|
+
active_record_model = klass.superclass.equal?(ActiveRecord::Base) && !klass.abstract_class?
|
|
19
|
+
active_record_model_with_sti = klass.superclass.superclass.equal?(ActiveRecord::Base)
|
|
20
|
+
ar_models << klass if active_record_model || active_record_model_with_sti
|
|
21
|
+
rescue Exception => error
|
|
22
|
+
puts "=> [typus] #{error.message} on '#{class_name}'."
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Configuration files
|
|
27
|
+
config_folder = Typus::Configuration.options[:config_folder]
|
|
28
|
+
Dir.mkdir(config_folder) unless File.directory?(config_folder)
|
|
29
|
+
|
|
30
|
+
configuration = { :base => '', :roles => '' }
|
|
31
|
+
|
|
32
|
+
ar_models.sort{ |x,y| x.class_name <=> y.class_name }.each do |model|
|
|
33
|
+
|
|
34
|
+
# Detect all relationships except polymorphic belongs_to using reflection.
|
|
35
|
+
relationships = [ :belongs_to, :has_and_belongs_to_many, :has_many, :has_one ].map do |relationship|
|
|
36
|
+
model.reflect_on_all_associations(relationship).reject { |i| i.options[:polymorphic] }.map { |i| i.name.to_s }
|
|
37
|
+
end.flatten.sort
|
|
38
|
+
|
|
39
|
+
# Remove foreign key and polymorphic type attributes
|
|
40
|
+
reject_columns = []
|
|
41
|
+
model.reflect_on_all_associations(:belongs_to).each do |i|
|
|
42
|
+
reject_columns << model.columns_hash[i.name.to_s + '_id']
|
|
43
|
+
reject_columns << model.columns_hash[i.name.to_s + '_type'] if i.options[:polymorphic]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
model_columns = model.columns - reject_columns
|
|
47
|
+
|
|
48
|
+
# Don't show `text` fields and timestamps in lists.
|
|
49
|
+
list = model_columns.reject { |c| c.sql_type == 'text' || %w( created_at updated_at ).include?(c.name) }.map(&:name)
|
|
50
|
+
# Don't show timestamps in forms.
|
|
51
|
+
form = model_columns.reject { |c| %w( id created_at updated_at ).include?(c.name) }.map(&:name)
|
|
52
|
+
# Show all model columns in the show action.
|
|
53
|
+
show = model_columns.map(&:name)
|
|
54
|
+
|
|
55
|
+
# We want attributes of belongs_to relationships to be shown in our
|
|
56
|
+
# field collections if those are not polymorphic.
|
|
57
|
+
[ list, form, show ].each do |fields|
|
|
58
|
+
fields << model.reflect_on_all_associations(:belongs_to).reject { |i| i.options[:polymorphic] }.map { |i| i.name.to_s }
|
|
59
|
+
fields.flatten!
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
configuration[:base] << <<-RAW
|
|
63
|
+
#{model}:
|
|
64
|
+
fields:
|
|
65
|
+
list: #{list.join(', ')}
|
|
66
|
+
form: #{form.join(', ')}
|
|
67
|
+
show: #{show.join(', ')}
|
|
68
|
+
actions:
|
|
69
|
+
index:
|
|
70
|
+
edit:
|
|
71
|
+
order_by:
|
|
72
|
+
relationships: #{relationships.join(', ')}
|
|
73
|
+
filters:
|
|
74
|
+
search:
|
|
75
|
+
application: #{application}
|
|
76
|
+
description:
|
|
77
|
+
|
|
78
|
+
RAW
|
|
79
|
+
|
|
80
|
+
configuration[:roles] << <<-RAW
|
|
81
|
+
#{model}: create, read, update, delete
|
|
82
|
+
RAW
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
Dir["#{Typus.root}/generators/typus/templates/config/typus/*"].each do |f|
|
|
87
|
+
base = File.basename(f)
|
|
88
|
+
m.template "config/typus/#{base}", "#{config_folder}/#{base}",
|
|
89
|
+
:assigns => { :configuration => configuration }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Initializer
|
|
93
|
+
|
|
94
|
+
[ 'config/initializers/typus.rb' ].each do |initializer|
|
|
95
|
+
m.template initializer, initializer, :assigns => { :application => application }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Assets
|
|
99
|
+
|
|
100
|
+
[ 'public/stylesheets/admin',
|
|
101
|
+
'public/javascripts/admin',
|
|
102
|
+
'public/images/admin' ].each { |f| Dir.mkdir(f) unless File.directory?(f) }
|
|
103
|
+
|
|
104
|
+
[ 'public/stylesheets/admin/screen.css',
|
|
105
|
+
'public/stylesheets/admin/reset.css',
|
|
106
|
+
'public/javascripts/admin/application.js' ].each { |f| m.file f, f }
|
|
107
|
+
|
|
108
|
+
Dir["#{Typus.root}/generators/typus/templates/public/images/admin/*"].each do |f|
|
|
109
|
+
file = "public/images/admin/#{File.basename(f)}"
|
|
110
|
+
m.file file, file
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Migration file
|
|
114
|
+
|
|
115
|
+
m.migration_template 'db/create_typus_users.rb', 'db/migrate',
|
|
116
|
+
{ :migration_file_name => 'create_typus_users' }
|
|
117
|
+
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
TypusUser:
|
|
2
|
+
fields:
|
|
3
|
+
list: email, role, status
|
|
4
|
+
form: first_name, last_name, role, email, password, password_confirmation
|
|
5
|
+
options:
|
|
6
|
+
selectors: role
|
|
7
|
+
booleans:
|
|
8
|
+
status: Active, Inactive
|
|
9
|
+
filters: status, role
|
|
10
|
+
search: first_name, last_name, email, role
|
|
11
|
+
application: Typus
|
|
12
|
+
description: System Users Administration
|
|
13
|
+
options:
|
|
14
|
+
icon_on_boolean: false
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class TypusUpdateSchemaTo01Generator < Rails::Generator::Base
|
|
2
|
+
|
|
3
|
+
def manifest
|
|
4
|
+
|
|
5
|
+
record do |m|
|
|
6
|
+
|
|
7
|
+
config_folder = Typus::Configuration.options[:config_folder]
|
|
8
|
+
Dir["#{Typus.root}/generators/typus_update_schema_to_01/templates/config/*"].each do |f|
|
|
9
|
+
base = File.basename(f)
|
|
10
|
+
m.template "config/#{base}", "#{config_folder}/#{base}"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
m.migration_template 'migration.rb', 'db/migrate', { :migration_file_name => 'update_typus_schema_to_01' }
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
data/lib/typus.rb
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
module Typus
|
|
2
|
+
|
|
3
|
+
class << self
|
|
4
|
+
|
|
5
|
+
def version
|
|
6
|
+
@@version ||= File.read("#{root}/VERSION").strip
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def root
|
|
10
|
+
File.dirname(__FILE__) + '/../'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def locales
|
|
14
|
+
Typus::Configuration.options[:locales]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def default_locale
|
|
18
|
+
locales.map(&:last).first
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def applications
|
|
22
|
+
Typus::Configuration.config.collect { |i| i.last['application'] }.compact.uniq.sort
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# List of the modules of an application.
|
|
26
|
+
def application(name)
|
|
27
|
+
Typus::Configuration.config.collect { |i| i.first if i.last['application'] == name }.compact.uniq.sort
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def models
|
|
31
|
+
Typus::Configuration.config.map { |i| i.first }.sort
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def models_on_header
|
|
35
|
+
models.collect { |m| m if m.constantize.typus_options_for(:on_header) }.compact
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# List of resources, which are tableless models.
|
|
39
|
+
def resources(models = get_model_names)
|
|
40
|
+
|
|
41
|
+
all_resources = Typus::Configuration.roles.keys.map do |key|
|
|
42
|
+
Typus::Configuration.roles[key].keys
|
|
43
|
+
end.flatten.sort.uniq
|
|
44
|
+
|
|
45
|
+
all_resources.delete_if { |x| models.include?(x) || x == 'TypusUser' } rescue []
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def get_model_names
|
|
50
|
+
Dir[ "#{Rails.root}/app/models/**/*.rb",
|
|
51
|
+
"#{Rails.root}/vendor/plugins/**/app/models/**/*.rb" ].collect { |m| File.basename(m).sub(/\.rb$/,'').camelize }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def user_class
|
|
55
|
+
Typus::Configuration.options[:user_class_name].constantize
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def user_fk
|
|
59
|
+
Typus::Configuration.options[:user_fk]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def testing?
|
|
63
|
+
Rails.env.test? && Dir.pwd == "#{Rails.root}/vendor/plugins/typus"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def plugin?
|
|
67
|
+
File.exist?("#{Rails.root}/vendor/plugins/typus")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def boot!
|
|
71
|
+
|
|
72
|
+
# return unless File.exists?("#{Rails.root}/config/initializers/typus.rb") || testing?
|
|
73
|
+
return if %w( script/generate script/destroy ).include?($0)
|
|
74
|
+
|
|
75
|
+
if testing?
|
|
76
|
+
Typus::Configuration.options[:config_folder] = 'vendor/plugins/typus/test/config/working'
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Ruby Extensions
|
|
80
|
+
require 'typus/hash'
|
|
81
|
+
require 'typus/object'
|
|
82
|
+
require 'typus/string'
|
|
83
|
+
|
|
84
|
+
# Load configuration and roles.
|
|
85
|
+
Typus::Configuration.config!
|
|
86
|
+
Typus::Configuration.roles!
|
|
87
|
+
|
|
88
|
+
# Load translation files from the plugin or the gem.
|
|
89
|
+
if plugin?
|
|
90
|
+
I18n.load_path += Dir[File.join(root, 'config', 'locales', '**', '*.{rb,yml}')]
|
|
91
|
+
else
|
|
92
|
+
Gem.path.each { |g| I18n.load_path += Dir[File.join("#{g}/gems/*typus-#{version}/config/locales/**/*.{rb,yml}")] }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Require the test/models on when testing.
|
|
96
|
+
require File.dirname(__FILE__) + '/../test/models' if testing?
|
|
97
|
+
|
|
98
|
+
# Rails Extensions.
|
|
99
|
+
require 'typus/active_record'
|
|
100
|
+
require 'typus/extensions/routes'
|
|
101
|
+
|
|
102
|
+
# Mixins.
|
|
103
|
+
require 'typus/authentication'
|
|
104
|
+
require 'typus/format'
|
|
105
|
+
require 'typus/generator'
|
|
106
|
+
require 'typus/locale'
|
|
107
|
+
require 'typus/reloader'
|
|
108
|
+
require 'typus/quick_edit'
|
|
109
|
+
require 'typus/user'
|
|
110
|
+
|
|
111
|
+
# Vendor.
|
|
112
|
+
require 'vendor/active_record'
|
|
113
|
+
require 'vendor/paginator'
|
|
114
|
+
|
|
115
|
+
# Run controllers generator ...
|
|
116
|
+
generator unless testing? || Rails.env.production?
|
|
117
|
+
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
end
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
module Typus
|
|
2
|
+
|
|
3
|
+
def self.included(base)
|
|
4
|
+
base.extend ClassMethods
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
|
|
9
|
+
# Return model fields as a OrderedHash
|
|
10
|
+
def model_fields
|
|
11
|
+
hash = ActiveSupport::OrderedHash.new
|
|
12
|
+
columns.map { |u| hash[u.name.to_sym] = u.type.to_sym }
|
|
13
|
+
return hash
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def model_relationships
|
|
17
|
+
hash = ActiveSupport::OrderedHash.new
|
|
18
|
+
reflect_on_all_associations.map { |i| hash[i.name] = i.macro }
|
|
19
|
+
return hash
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# This method is used to change a Rails behavior.
|
|
24
|
+
#
|
|
25
|
+
# typus $ script/console
|
|
26
|
+
# Loading development environment (Rails 2.3.2)
|
|
27
|
+
# >> TypusUser.human_name
|
|
28
|
+
# => "Typususer"
|
|
29
|
+
# >> TypusUser.typus_human_name
|
|
30
|
+
# => "Typus user"
|
|
31
|
+
#
|
|
32
|
+
def typus_human_name
|
|
33
|
+
human_name(:default => self.name.underscore.humanize)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def typus_description
|
|
37
|
+
Typus::Configuration.config[self.name]['description']
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Form and list fields
|
|
41
|
+
def typus_fields_for(filter)
|
|
42
|
+
|
|
43
|
+
fields_with_type = ActiveSupport::OrderedHash.new
|
|
44
|
+
|
|
45
|
+
begin
|
|
46
|
+
fields = Typus::Configuration.config[name]['fields'][filter.to_s]
|
|
47
|
+
fields = fields.split(', ').collect { |f| f.to_sym }
|
|
48
|
+
rescue
|
|
49
|
+
return [] if filter == 'list'
|
|
50
|
+
filter = 'list'
|
|
51
|
+
retry
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
begin
|
|
55
|
+
|
|
56
|
+
fields.each do |field|
|
|
57
|
+
|
|
58
|
+
attribute_type = model_fields[field]
|
|
59
|
+
|
|
60
|
+
# Custom field_type depending on the attribute name.
|
|
61
|
+
case field.to_s
|
|
62
|
+
when 'parent_id' then attribute_type = :tree
|
|
63
|
+
when /file_name/ then attribute_type = :file
|
|
64
|
+
when /password/ then attribute_type = :password
|
|
65
|
+
when 'position' then attribute_type = :position
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
if reflect_on_association(field)
|
|
69
|
+
attribute_type = reflect_on_association(field).macro
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
if typus_field_options_for(:selectors).include?(field)
|
|
73
|
+
attribute_type = :selector
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
if typus_tiny_mce_fields.include?(field.to_s)
|
|
77
|
+
attribute_type = :tiny_mce
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# And finally insert the field and the attribute_type
|
|
81
|
+
# into the fields_with_type ordered hash.
|
|
82
|
+
fields_with_type[field.to_s] = attribute_type
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
rescue
|
|
87
|
+
fields = Typus::Configuration.config[name]['fields']['list'].split(', ')
|
|
88
|
+
retry
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
return fields_with_type
|
|
92
|
+
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Return tiny_mce options of the model merged into the default options
|
|
96
|
+
def typus_tiny_mce_options
|
|
97
|
+
typus_options_for(:tiny_mce).merge(Typus::Configuration.config[name]['fields']['options']['tiny_mce']['options'].symbolize_keys.delete_if { |key,value| value == nil})
|
|
98
|
+
rescue
|
|
99
|
+
typus_options_for(:tiny_mce)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Tiny_mce fields of the model
|
|
103
|
+
def typus_tiny_mce_fields
|
|
104
|
+
Typus::Configuration.config[name]['fields']['options']['tiny_mce']['fields'].split(', ')
|
|
105
|
+
rescue
|
|
106
|
+
[]
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Typus sidebar filters.
|
|
110
|
+
def typus_filters
|
|
111
|
+
|
|
112
|
+
fields_with_type = ActiveSupport::OrderedHash.new
|
|
113
|
+
|
|
114
|
+
data = Typus::Configuration.config[name]['filters']
|
|
115
|
+
return [] unless data
|
|
116
|
+
fields = data.split(', ').collect { |i| i.to_sym }
|
|
117
|
+
|
|
118
|
+
fields.each do |field|
|
|
119
|
+
attribute_type = model_fields[field.to_sym]
|
|
120
|
+
if reflect_on_association(field.to_sym)
|
|
121
|
+
attribute_type = reflect_on_association(field.to_sym).macro
|
|
122
|
+
end
|
|
123
|
+
fields_with_type[field.to_s] = attribute_type
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
return fields_with_type
|
|
127
|
+
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Extended actions for this model on Typus.
|
|
131
|
+
def typus_actions_for(filter)
|
|
132
|
+
Typus::Configuration.config[name]['actions'][filter.to_s].split(', ')
|
|
133
|
+
rescue
|
|
134
|
+
[]
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Used for +search+, +relationships+
|
|
138
|
+
def typus_defaults_for(filter)
|
|
139
|
+
data = Typus::Configuration.config[name][filter.to_s]
|
|
140
|
+
return (!data.nil?) ? data.split(', ') : []
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def typus_field_options_for(filter)
|
|
144
|
+
Typus::Configuration.config[name]['fields']['options'][filter.to_s].split(', ').collect { |i| i.to_sym }
|
|
145
|
+
rescue
|
|
146
|
+
[]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# We should be able to overwrite options by model.
|
|
150
|
+
def typus_options_for(filter)
|
|
151
|
+
|
|
152
|
+
data = Typus::Configuration.config[name]
|
|
153
|
+
unless data['options'].nil?
|
|
154
|
+
value = data['options'][filter.to_s] unless data['options'][filter.to_s].nil?
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
return (!value.nil?) ? value : Typus::Configuration.options[filter.to_sym]
|
|
158
|
+
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def typus_export_formats
|
|
162
|
+
data = Typus::Configuration.config[name]
|
|
163
|
+
!data['export'].nil? ? data['export'].split(', ') : []
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Used for `order_by`.
|
|
167
|
+
def typus_order_by
|
|
168
|
+
|
|
169
|
+
fields = typus_defaults_for(:order_by)
|
|
170
|
+
return "#{table_name}.id ASC" if fields.empty?
|
|
171
|
+
|
|
172
|
+
order = fields.map do |field|
|
|
173
|
+
(field.include?('-')) ? "#{table_name}.#{field.delete('-')} DESC" : "#{table_name}.#{field} ASC"
|
|
174
|
+
end.join(', ')
|
|
175
|
+
|
|
176
|
+
return order
|
|
177
|
+
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# We are able to define our own booleans.
|
|
181
|
+
def typus_boolean(attribute = :default)
|
|
182
|
+
|
|
183
|
+
boolean = Typus::Configuration.config[name]['fields']['options']['booleans'][attribute.to_s] rescue nil
|
|
184
|
+
boolean = 'true, false' if boolean.nil?
|
|
185
|
+
|
|
186
|
+
hash = ActiveSupport::OrderedHash.new
|
|
187
|
+
|
|
188
|
+
if boolean.kind_of?(Array)
|
|
189
|
+
hash[:true] = boolean.first.humanize
|
|
190
|
+
hash[:false] = boolean.last.humanize
|
|
191
|
+
else
|
|
192
|
+
hash[:true] = boolean.split(', ').first.humanize
|
|
193
|
+
hash[:false] = boolean.split(', ').last.humanize
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
return hash
|
|
197
|
+
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# We are able to define how to display dates on Typus
|
|
201
|
+
def typus_date_format(attribute = :default)
|
|
202
|
+
date_format = Typus::Configuration.config[name]['fields']['options']['date_formats'][attribute.to_s].to_sym rescue nil
|
|
203
|
+
date_format = :db if date_format.nil?
|
|
204
|
+
return date_format
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# We are able to define which template to use to render the attribute
|
|
208
|
+
# within the form
|
|
209
|
+
def typus_template(attribute)
|
|
210
|
+
Typus::Configuration.config[name]['fields']['options']['templates'][attribute.to_s]
|
|
211
|
+
rescue
|
|
212
|
+
nil
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def build_conditions(params)
|
|
216
|
+
|
|
217
|
+
conditions, joins = merge_conditions, []
|
|
218
|
+
|
|
219
|
+
query_params = params.dup
|
|
220
|
+
%w( action controller ).each { |param| query_params.delete(param) }
|
|
221
|
+
|
|
222
|
+
# If a search is performed.
|
|
223
|
+
if query_params[:search]
|
|
224
|
+
search = typus_defaults_for(:search).map do |s|
|
|
225
|
+
["LOWER(#{s}) LIKE '%#{ActiveRecord::Base.connection.quote_string(query_params[:search].downcase)}%'"]
|
|
226
|
+
end
|
|
227
|
+
conditions = merge_conditions(conditions, search.join(' OR '))
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
query_params.each do |key, value|
|
|
231
|
+
|
|
232
|
+
filter_type = model_fields[key.to_sym] || model_relationships[key.to_sym]
|
|
233
|
+
|
|
234
|
+
##
|
|
235
|
+
# Sidebar filters:
|
|
236
|
+
#
|
|
237
|
+
# - Booleans: true, false
|
|
238
|
+
# - Datetime: today, past_7_days, this_month, this_year
|
|
239
|
+
# - Integer & String: *_id and "selectors" (p.ej. category_id)
|
|
240
|
+
#
|
|
241
|
+
case filter_type
|
|
242
|
+
when :boolean
|
|
243
|
+
condition = { key => (value == 'true') ? true : false }
|
|
244
|
+
conditions = merge_conditions(conditions, condition)
|
|
245
|
+
when :datetime
|
|
246
|
+
interval = case value
|
|
247
|
+
when 'today' then Time.new.midnight..Time.new.midnight.tomorrow
|
|
248
|
+
when 'past_7_days' then 6.days.ago.midnight..Time.new.midnight.tomorrow
|
|
249
|
+
when 'this_month' then Time.new.midnight.last_month..Time.new.midnight.tomorrow
|
|
250
|
+
when 'this_year' then Time.new.midnight.last_year..Time.new.midnight.tomorrow
|
|
251
|
+
end
|
|
252
|
+
condition = ["#{key} BETWEEN ? AND ?", interval.first.to_s(:db), interval.last.to_s(:db)]
|
|
253
|
+
conditions = merge_conditions(conditions, condition)
|
|
254
|
+
when :integer, :string
|
|
255
|
+
condition = { key => value }
|
|
256
|
+
conditions = merge_conditions(conditions, condition)
|
|
257
|
+
when :has_and_belongs_to_many
|
|
258
|
+
condition = { key => { :id => value } }
|
|
259
|
+
conditions = merge_conditions(conditions, condition)
|
|
260
|
+
joins << key.to_sym
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
return conditions, joins
|
|
266
|
+
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
module InstanceMethods
|
|
272
|
+
|
|
273
|
+
def previous_and_next(condition = {}, klass = self.class)
|
|
274
|
+
|
|
275
|
+
previous_conditions = "#{klass.primary_key} < #{id}"
|
|
276
|
+
next_conditions = "#{klass.primary_key} > #{id}"
|
|
277
|
+
|
|
278
|
+
if !condition.empty?
|
|
279
|
+
conditions, joins = klass.build_conditions(condition)
|
|
280
|
+
previous_conditions += " AND #{conditions}"
|
|
281
|
+
next_conditions += " AND #{conditions}"
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
previous_ = klass.find :first,
|
|
285
|
+
:select => [klass.primary_key],
|
|
286
|
+
:order => "#{klass.primary_key} DESC",
|
|
287
|
+
:conditions => previous_conditions
|
|
288
|
+
|
|
289
|
+
next_ = klass.find :first,
|
|
290
|
+
:select => [klass.primary_key],
|
|
291
|
+
:order => "#{klass.primary_key} ASC",
|
|
292
|
+
:conditions => next_conditions
|
|
293
|
+
|
|
294
|
+
return previous_, next_
|
|
295
|
+
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def typus_name
|
|
299
|
+
respond_to?(:name) ? name : "#{self.class}##{id}"
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
ActiveRecord::Base.send :include, Typus
|
|
307
|
+
ActiveRecord::Base.send :include, Typus::InstanceMethods
|