fesplugas-typus 0.9.0
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +80 -0
- data/Rakefile +61 -0
- data/VERSION +1 -0
- data/app/controllers/admin/master_controller.rb +324 -0
- data/app/controllers/typus_controller.rb +127 -0
- data/app/helpers/admin/form_helper.rb +351 -0
- data/app/helpers/admin/master_helper.rb +99 -0
- data/app/helpers/admin/public_helper.rb +24 -0
- data/app/helpers/admin/sidebar_helper.rb +259 -0
- data/app/helpers/admin/table_helper.rb +227 -0
- data/app/helpers/typus_helper.rb +169 -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 +29 -0
- data/app/views/admin/resources/index.html.erb +28 -0
- data/app/views/admin/resources/new.html.erb +27 -0
- data/app/views/admin/resources/show.html.erb +21 -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 +72 -0
- data/app/views/layouts/typus.html.erb +29 -0
- data/app/views/typus/dashboard.html.erb +13 -0
- data/app/views/typus/recover_password.html.erb +7 -0
- data/app/views/typus/reset_password.html.erb +13 -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/es.yml +106 -0
- data/config/locales/pt-BR.yml +108 -0
- data/config/locales/typus_hacks.yml +14 -0
- data/config/routes.rb +14 -0
- data/generators/typus/templates/config/initializers/typus.rb +27 -0
- data/generators/typus/templates/config/typus/application.yml +45 -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 +709 -0
- data/generators/typus/typus_generator.rb +141 -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/init.rb +19 -0
- data/lib/typus/active_record.rb +298 -0
- data/lib/typus/authentication.rb +155 -0
- data/lib/typus/configuration.rb +92 -0
- data/lib/typus/format.rb +56 -0
- data/lib/typus/generator.rb +173 -0
- data/lib/typus/hash.rb +10 -0
- data/lib/typus/locale.rb +17 -0
- data/lib/typus/object.rb +22 -0
- data/lib/typus/quick_edit.rb +33 -0
- data/lib/typus/reloader.rb +17 -0
- data/lib/typus/string.rb +11 -0
- data/lib/typus/user.rb +137 -0
- data/lib/typus.rb +133 -0
- data/lib/vendor/active_record.rb +15 -0
- data/lib/vendor/paginator.rb +143 -0
- data/tasks/typus_tasks.rake +26 -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 +67 -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_bottom.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_edit_sidebar.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_edit_top.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_index_bottom.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_index_sidebar.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_index_top.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_new_bottom.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_new_sidebar.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_new_top.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_show_bottom.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_show_sidebar.html.erb +1 -0
- data/test/fixtures/app/views/admin/comments/_show_top.html.erb +1 -0
- data/test/fixtures/app/views/admin/dashboard/_bottom.html.erb +1 -0
- data/test/fixtures/app/views/admin/dashboard/_sidebar.html.erb +1 -0
- data/test/fixtures/app/views/admin/dashboard/_top.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 +121 -0
- data/test/functional/admin/master_controller_test.rb +5 -0
- data/test/functional/admin/posts_controller_test.rb +278 -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 +315 -0
- data/test/helper.rb +51 -0
- data/test/helpers/admin/form_helper_test.rb +316 -0
- data/test/helpers/admin/master_helper_test.rb +65 -0
- data/test/helpers/admin/public_helper_test.rb +22 -0
- data/test/helpers/admin/sidebar_helper_test.rb +351 -0
- data/test/helpers/admin/table_helper_test.rb +255 -0
- data/test/helpers/typus_helper_test.rb +106 -0
- data/test/lib/active_record_test.rb +372 -0
- data/test/lib/configuration_test.rb +91 -0
- data/test/lib/hash_test.rb +11 -0
- data/test/lib/routes_test.rb +82 -0
- data/test/lib/string_test.rb +25 -0
- data/test/lib/typus_test.rb +105 -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 +138 -0
- data/typus.gemspec +225 -0
- metadata +241 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
class TypusGenerator < Rails::Generator::Base
|
|
2
|
+
|
|
3
|
+
def manifest
|
|
4
|
+
|
|
5
|
+
record do |m|
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Default name for our application.
|
|
9
|
+
#
|
|
10
|
+
|
|
11
|
+
application = Rails.root.basename
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# To create <tt>application.yml</tt> and <tt>application_roles.yml</tt> detect
|
|
15
|
+
# available AR models on the application.
|
|
16
|
+
#
|
|
17
|
+
|
|
18
|
+
models = Dir["#{Rails.root}/app/models/*.rb"].collect { |x| File.basename(x) }
|
|
19
|
+
ar_models = []
|
|
20
|
+
|
|
21
|
+
models.each do |model|
|
|
22
|
+
class_name = model.sub(/\.rb$/,'').classify
|
|
23
|
+
begin
|
|
24
|
+
klass = class_name.constantize
|
|
25
|
+
ar_models << klass if klass.superclass.equal?(ActiveRecord::Base)
|
|
26
|
+
rescue Exception => error
|
|
27
|
+
puts "=> [typus] #{error.message} on '#{class_name}'."
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Configuration files
|
|
33
|
+
#
|
|
34
|
+
|
|
35
|
+
config_folder = Typus::Configuration.options[:config_folder]
|
|
36
|
+
folder = "#{Rails.root}/#{config_folder}"
|
|
37
|
+
Dir.mkdir(folder) unless File.directory?(folder)
|
|
38
|
+
|
|
39
|
+
configuration = { :base => '', :roles => '' }
|
|
40
|
+
|
|
41
|
+
ar_models.each do |model|
|
|
42
|
+
|
|
43
|
+
# By default we don't want to show in our lists text fields and created_at
|
|
44
|
+
# and updated_at attributes.
|
|
45
|
+
list = model.columns.reject { |c| c.sql_type == 'text' || %w( created_at updated_at ).include?(c.name) }.map(&:name)
|
|
46
|
+
|
|
47
|
+
# By default we don't want to show in our forms created_at and updated_at
|
|
48
|
+
# attributes.
|
|
49
|
+
form = model.columns.reject { |c| %w( id created_at updated_at ).include?(c.name) }.map(&:name)
|
|
50
|
+
|
|
51
|
+
# By default we want to show all model columns in the show action.
|
|
52
|
+
show = model.columns.map(&:name)
|
|
53
|
+
|
|
54
|
+
# Detect relationships using reflection and remove the _id part from
|
|
55
|
+
# attributes when relationships is defined in ActiveRecord.
|
|
56
|
+
list.each do |i|
|
|
57
|
+
if i.include?('_id')
|
|
58
|
+
assoc_name = model.reflect_on_association(i.gsub(/_id/, '').to_sym).macro rescue nil
|
|
59
|
+
i.gsub!(/_id/, '') if assoc_name == :belongs_to
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Detect relationships using reflection.
|
|
64
|
+
relationships = [ :belongs_to, :has_and_belongs_to_many, :has_many, :has_one ].map do |relationship|
|
|
65
|
+
model.reflect_on_all_associations(relationship).map { |i| i.name.to_s }
|
|
66
|
+
end.flatten.sort
|
|
67
|
+
|
|
68
|
+
configuration[:base] << <<-CODE
|
|
69
|
+
#{model}:
|
|
70
|
+
fields:
|
|
71
|
+
list: #{list.join(', ')}
|
|
72
|
+
form: #{form.join(', ')}
|
|
73
|
+
show: #{show.join(', ')}
|
|
74
|
+
relationship:
|
|
75
|
+
options:
|
|
76
|
+
auto_generated:
|
|
77
|
+
read_only:
|
|
78
|
+
selectors:
|
|
79
|
+
actions:
|
|
80
|
+
index:
|
|
81
|
+
edit:
|
|
82
|
+
export:
|
|
83
|
+
order_by:
|
|
84
|
+
relationships: #{relationships.join(', ')}
|
|
85
|
+
filters:
|
|
86
|
+
search:
|
|
87
|
+
application: #{application}
|
|
88
|
+
description:
|
|
89
|
+
|
|
90
|
+
CODE
|
|
91
|
+
|
|
92
|
+
configuration[:roles] << <<-CODE
|
|
93
|
+
#{model}: create, read, update, delete
|
|
94
|
+
CODE
|
|
95
|
+
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
Dir["#{Typus.root}/generators/typus/templates/config/typus/*"].each do |f|
|
|
99
|
+
base = File.basename(f)
|
|
100
|
+
m.template "config/typus/#{base}", "#{config_folder}/#{base}",
|
|
101
|
+
:assigns => { :configuration => configuration }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
##
|
|
105
|
+
# Initializers
|
|
106
|
+
#
|
|
107
|
+
|
|
108
|
+
m.template 'config/initializers/typus.rb', 'config/initializers/typus.rb',
|
|
109
|
+
:assigns => { :application => application }
|
|
110
|
+
|
|
111
|
+
##
|
|
112
|
+
# Public folders
|
|
113
|
+
#
|
|
114
|
+
|
|
115
|
+
[ "#{Rails.root}/public/stylesheets/admin",
|
|
116
|
+
"#{Rails.root}/public/javascripts/admin",
|
|
117
|
+
"#{Rails.root}/public/images/admin" ].each do |folder|
|
|
118
|
+
Dir.mkdir(folder) unless File.directory?(folder)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
m.file 'public/stylesheets/admin/screen.css', 'public/stylesheets/admin/screen.css'
|
|
122
|
+
m.file 'public/stylesheets/admin/reset.css', 'public/stylesheets/admin/reset.css'
|
|
123
|
+
m.file 'public/javascripts/admin/application.js', 'public/javascripts/admin/application.js'
|
|
124
|
+
|
|
125
|
+
Dir["#{Typus.root}/generators/typus/templates/public/images/admin/*"].each do |f|
|
|
126
|
+
base = File.basename(f)
|
|
127
|
+
m.file "public/images/admin/#{base}", "public/images/admin/#{base}"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
##
|
|
131
|
+
# Migration file
|
|
132
|
+
#
|
|
133
|
+
|
|
134
|
+
m.migration_template 'db/create_typus_users.rb', 'db/migrate',
|
|
135
|
+
{ :migration_file_name => 'create_typus_users' }
|
|
136
|
+
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
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/init.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'typus'
|
|
2
|
+
require 'sha1'
|
|
3
|
+
|
|
4
|
+
if Typus.testing?
|
|
5
|
+
Typus::Configuration.options[:config_folder] = 'vendor/plugins/typus/test/config/working'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# Typus.enable and run the generator unless we are testing the plugin.
|
|
10
|
+
# Do not Typus.enable or generate files if we are running a rails
|
|
11
|
+
# generator.
|
|
12
|
+
#
|
|
13
|
+
|
|
14
|
+
scripts = %w( script/generate script/destroy )
|
|
15
|
+
|
|
16
|
+
unless scripts.include?($0)
|
|
17
|
+
Typus.enable
|
|
18
|
+
Typus.generator unless Typus.testing?
|
|
19
|
+
end
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
module Typus
|
|
2
|
+
|
|
3
|
+
def self.included(base)
|
|
4
|
+
base.extend ClassMethods
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
# Return model fields as a OrderedHash
|
|
11
|
+
#
|
|
12
|
+
def model_fields
|
|
13
|
+
hash = ActiveSupport::OrderedHash.new
|
|
14
|
+
columns.map { |u| hash[u.name.to_sym] = u.type.to_sym }
|
|
15
|
+
return hash
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def model_relationships
|
|
19
|
+
hash = ActiveSupport::OrderedHash.new
|
|
20
|
+
reflect_on_all_associations.map { |i| hash[i.name] = i.macro }
|
|
21
|
+
return hash
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# Form and list fields
|
|
26
|
+
#
|
|
27
|
+
def typus_fields_for(filter)
|
|
28
|
+
|
|
29
|
+
fields_with_type = ActiveSupport::OrderedHash.new
|
|
30
|
+
|
|
31
|
+
begin
|
|
32
|
+
fields = Typus::Configuration.config[name]['fields'][filter.to_s]
|
|
33
|
+
fields = fields.split(', ').collect { |f| f.to_sym }
|
|
34
|
+
rescue
|
|
35
|
+
return [] if filter == 'list'
|
|
36
|
+
filter = 'list'
|
|
37
|
+
retry
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
begin
|
|
41
|
+
|
|
42
|
+
fields.each do |field|
|
|
43
|
+
|
|
44
|
+
attribute_type = model_fields[field]
|
|
45
|
+
|
|
46
|
+
# Custom field_type depending on the attribute name.
|
|
47
|
+
case field.to_s
|
|
48
|
+
when 'parent_id': attribute_type = :tree
|
|
49
|
+
when /file_name/: attribute_type = :file
|
|
50
|
+
when /password/: attribute_type = :password
|
|
51
|
+
when 'position': attribute_type = :position
|
|
52
|
+
when /\?/: attribute_type = :boolean
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
if reflect_on_association(field)
|
|
56
|
+
attribute_type = reflect_on_association(field).macro
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if typus_field_options_for(:selectors).include?(field)
|
|
60
|
+
attribute_type = :selector
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# And finally insert the field and the attribute_type
|
|
64
|
+
# into the fields_with_type ordered hash.
|
|
65
|
+
fields_with_type[field.to_s] = attribute_type
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
rescue
|
|
70
|
+
fields = Typus::Configuration.config[name]['fields']['list'].split(', ')
|
|
71
|
+
retry
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
return fields_with_type
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
# Typus sidebar filters.
|
|
80
|
+
#
|
|
81
|
+
def typus_filters
|
|
82
|
+
|
|
83
|
+
fields_with_type = ActiveSupport::OrderedHash.new
|
|
84
|
+
|
|
85
|
+
data = Typus::Configuration.config[name]['filters']
|
|
86
|
+
return [] unless data
|
|
87
|
+
fields = data.split(', ').collect { |i| i.to_sym }
|
|
88
|
+
|
|
89
|
+
fields.each do |field|
|
|
90
|
+
attribute_type = model_fields[field.to_sym]
|
|
91
|
+
if reflect_on_association(field.to_sym)
|
|
92
|
+
attribute_type = reflect_on_association(field.to_sym).macro
|
|
93
|
+
end
|
|
94
|
+
fields_with_type[field.to_s] = attribute_type
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
return fields_with_type
|
|
98
|
+
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
##
|
|
102
|
+
# Extended actions for this model on Typus.
|
|
103
|
+
#
|
|
104
|
+
def typus_actions_for(filter)
|
|
105
|
+
Typus::Configuration.config[name]['actions'][filter.to_s].split(', ')
|
|
106
|
+
rescue
|
|
107
|
+
[]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
##
|
|
111
|
+
# Used for +search+, +relationships+
|
|
112
|
+
#
|
|
113
|
+
def typus_defaults_for(filter)
|
|
114
|
+
data = Typus::Configuration.config[name][filter.to_s]
|
|
115
|
+
return (!data.nil?) ? data.split(', ') : []
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
##
|
|
119
|
+
#
|
|
120
|
+
#
|
|
121
|
+
def typus_field_options_for(filter)
|
|
122
|
+
Typus::Configuration.config[name]['fields']['options'][filter.to_s].split(', ').collect { |i| i.to_sym }
|
|
123
|
+
rescue
|
|
124
|
+
[]
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
##
|
|
128
|
+
# We should be able to overwrite options by model.
|
|
129
|
+
#
|
|
130
|
+
def typus_options_for(filter)
|
|
131
|
+
|
|
132
|
+
data = Typus::Configuration.config[name]
|
|
133
|
+
unless data['options'].nil?
|
|
134
|
+
value = data['options'][filter.to_s] unless data['options'][filter.to_s].nil?
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
return (!value.nil?) ? value : Typus::Configuration.options[filter.to_sym]
|
|
138
|
+
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def typus_export_formats
|
|
142
|
+
data = Typus::Configuration.config[name]
|
|
143
|
+
!data['export'].nil? ? data['export'].split(', ') : []
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
##
|
|
147
|
+
# Used for order_by
|
|
148
|
+
#
|
|
149
|
+
def typus_order_by
|
|
150
|
+
|
|
151
|
+
fields = typus_defaults_for(:order_by)
|
|
152
|
+
return "#{table_name}.id ASC" if fields.empty?
|
|
153
|
+
|
|
154
|
+
order = fields.map do |field|
|
|
155
|
+
(field.include?('-')) ? "#{table_name}.#{field.delete('-')} DESC" : "#{table_name}.#{field} ASC"
|
|
156
|
+
end.join(', ')
|
|
157
|
+
|
|
158
|
+
return order
|
|
159
|
+
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
##
|
|
163
|
+
# We are able to define our own booleans.
|
|
164
|
+
#
|
|
165
|
+
def typus_boolean(attribute = :default)
|
|
166
|
+
|
|
167
|
+
boolean = Typus::Configuration.config[name]['fields']['options']['booleans'][attribute.to_s] rescue nil
|
|
168
|
+
boolean = 'true, false' if boolean.nil?
|
|
169
|
+
|
|
170
|
+
hash = ActiveSupport::OrderedHash.new
|
|
171
|
+
|
|
172
|
+
if boolean.kind_of?(Array)
|
|
173
|
+
hash[:true] = boolean.first.humanize
|
|
174
|
+
hash[:false] = boolean.last.humanize
|
|
175
|
+
else
|
|
176
|
+
hash[:true] = boolean.split(', ').first.humanize
|
|
177
|
+
hash[:false] = boolean.split(', ').last.humanize
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
return hash
|
|
181
|
+
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
##
|
|
185
|
+
# We are able to define how to display dates on Typus
|
|
186
|
+
#
|
|
187
|
+
def typus_date_format(attribute = :default)
|
|
188
|
+
date_format = Typus::Configuration.config[name]['fields']['options']['date_formats'][attribute.to_s] rescue nil
|
|
189
|
+
date_format = :db if date_format.nil?
|
|
190
|
+
return date_format.to_sym
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
##
|
|
194
|
+
# We are able to define which template to use to render the attribute
|
|
195
|
+
# within the form
|
|
196
|
+
#
|
|
197
|
+
def typus_template(attribute)
|
|
198
|
+
Typus::Configuration.config[name]['fields']['options']['templates'][attribute.to_s]
|
|
199
|
+
rescue
|
|
200
|
+
nil
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
##
|
|
204
|
+
# Build conditions
|
|
205
|
+
#
|
|
206
|
+
def build_conditions(params)
|
|
207
|
+
|
|
208
|
+
conditions, joins = merge_conditions, []
|
|
209
|
+
|
|
210
|
+
query_params = params.dup
|
|
211
|
+
%w( action controller ).each { |param| query_params.delete(param) }
|
|
212
|
+
|
|
213
|
+
# If a search is performed.
|
|
214
|
+
if query_params[:search]
|
|
215
|
+
search = typus_defaults_for(:search).map do |s|
|
|
216
|
+
["LOWER(#{s}) LIKE '%#{query_params[:search].downcase}%'"]
|
|
217
|
+
end
|
|
218
|
+
conditions = merge_conditions(conditions, search.join(' OR '))
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
query_params.each do |key, value|
|
|
222
|
+
|
|
223
|
+
filter_type = model_fields[key.to_sym] || model_relationships[key.to_sym]
|
|
224
|
+
|
|
225
|
+
##
|
|
226
|
+
# Sidebar filters:
|
|
227
|
+
#
|
|
228
|
+
# - Booleans: true, false
|
|
229
|
+
# - Datetime: today, past_7_days, this_month, this_year
|
|
230
|
+
# - Integer & String: *_id and "selectors" (P.ej. category_id)
|
|
231
|
+
#
|
|
232
|
+
case filter_type
|
|
233
|
+
when :boolean
|
|
234
|
+
condition = { key => (value == 'true') ? true : false }
|
|
235
|
+
conditions = merge_conditions(conditions, condition)
|
|
236
|
+
when :datetime
|
|
237
|
+
interval = case value
|
|
238
|
+
when 'today': Time.today..Time.today.tomorrow
|
|
239
|
+
when 'past_7_days': 6.days.ago.midnight..Time.today.tomorrow
|
|
240
|
+
when 'this_month': Time.today.last_month..Time.today.tomorrow
|
|
241
|
+
when 'this_year': Time.today.last_year..Time.today.tomorrow
|
|
242
|
+
end
|
|
243
|
+
condition = ["#{key} BETWEEN ? AND ?", interval.first.to_s(:db), interval.last.to_s(:db)]
|
|
244
|
+
conditions = merge_conditions(conditions, condition)
|
|
245
|
+
when :integer, :string
|
|
246
|
+
condition = { key => value }
|
|
247
|
+
conditions = merge_conditions(conditions, condition)
|
|
248
|
+
when :has_and_belongs_to_many
|
|
249
|
+
condition = { key => { :id => value } }
|
|
250
|
+
conditions = merge_conditions(conditions, condition)
|
|
251
|
+
joins << key.to_sym
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
return conditions, joins
|
|
257
|
+
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
module InstanceMethods
|
|
263
|
+
|
|
264
|
+
def previous_and_next(condition = {}, klass = self.class)
|
|
265
|
+
|
|
266
|
+
previous_conditions = "id < #{id}"
|
|
267
|
+
next_conditions = "id > #{id}"
|
|
268
|
+
|
|
269
|
+
if !condition.empty?
|
|
270
|
+
conditions, joins = klass.build_conditions(condition)
|
|
271
|
+
previous_conditions += " AND #{conditions}"
|
|
272
|
+
next_conditions += " AND #{conditions}"
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
previous_ = klass.find :first,
|
|
276
|
+
:select => [:id],
|
|
277
|
+
:order => "id DESC",
|
|
278
|
+
:conditions => previous_conditions
|
|
279
|
+
|
|
280
|
+
next_ = klass.find :first,
|
|
281
|
+
:select => [:id],
|
|
282
|
+
:order => "id ASC",
|
|
283
|
+
:conditions => next_conditions
|
|
284
|
+
|
|
285
|
+
return previous_, next_
|
|
286
|
+
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def typus_name
|
|
290
|
+
respond_to?(:name) ? name : "#{self.class}##{id}"
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
ActiveRecord::Base.send :include, Typus
|
|
298
|
+
ActiveRecord::Base.send :include, Typus::InstanceMethods
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
module Typus
|
|
2
|
+
|
|
3
|
+
module Authentication
|
|
4
|
+
|
|
5
|
+
protected
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Require login checks if the user is logged on Typus, otherwise
|
|
9
|
+
# is sent to the sign in page with a :back_to param to return where
|
|
10
|
+
# she tried to go.
|
|
11
|
+
#
|
|
12
|
+
# Use this for demo!
|
|
13
|
+
#
|
|
14
|
+
# session[:typus_user_id] = Typus.user_class.find(:first)
|
|
15
|
+
#
|
|
16
|
+
def require_login
|
|
17
|
+
if session[:typus_user_id]
|
|
18
|
+
set_current_user
|
|
19
|
+
else
|
|
20
|
+
back_to = (request.env['REQUEST_URI'] == '/admin') ? nil : request.env['REQUEST_URI']
|
|
21
|
+
redirect_to admin_sign_in_path(:back_to => back_to)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# Return the current user.
|
|
27
|
+
#
|
|
28
|
+
# NOTE: If role does not longer exist on the system the user will
|
|
29
|
+
# be signed out from Typus.
|
|
30
|
+
#
|
|
31
|
+
def set_current_user
|
|
32
|
+
|
|
33
|
+
@current_user = Typus.user_class.find(session[:typus_user_id])
|
|
34
|
+
|
|
35
|
+
unless @current_user.respond_to?(:role)
|
|
36
|
+
raise _("Run 'script/generate typus_update_schema_to_01 -f && rake db:migrate' to update database schema.")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
unless Typus::Configuration.roles.keys.include?(@current_user.role)
|
|
40
|
+
raise _("Role does no longer exists.")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
unless @current_user.status
|
|
44
|
+
back_to = (request.env['REQUEST_URI'] == '/admin') ? nil : request.env['REQUEST_URI']
|
|
45
|
+
raise _("Typus user has been disabled.")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
rescue Exception => error
|
|
49
|
+
flash[:notice] = error.message
|
|
50
|
+
session[:typus_user_id] = nil
|
|
51
|
+
redirect_to admin_sign_in_path(:back_to => back_to)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
##
|
|
55
|
+
# Action is available on:
|
|
56
|
+
#
|
|
57
|
+
# edit, update, toggle and destroy
|
|
58
|
+
#
|
|
59
|
+
def check_if_user_can_perform_action_on_user
|
|
60
|
+
|
|
61
|
+
return unless @item.kind_of?(Typus.user_class)
|
|
62
|
+
|
|
63
|
+
current_user = (@current_user == @item)
|
|
64
|
+
|
|
65
|
+
message = case params[:action]
|
|
66
|
+
when 'edit'
|
|
67
|
+
|
|
68
|
+
# Only admin and owner of Typus User can edit.
|
|
69
|
+
if !@current_user.is_root? && !current_user
|
|
70
|
+
_("As you're not the admin or the owner of this record you cannot edit it.")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
when 'update'
|
|
74
|
+
|
|
75
|
+
# current_user cannot change her role.
|
|
76
|
+
if current_user && !(@item.role == params[:item][:role])
|
|
77
|
+
_("You can't change your role.")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
when 'toggle'
|
|
81
|
+
|
|
82
|
+
# Only admin can toggle typus user status, but not herself.
|
|
83
|
+
if @current_user.is_root? && current_user
|
|
84
|
+
_("You can't toggle your status.")
|
|
85
|
+
elsif !@current_user.is_root?
|
|
86
|
+
_("You're not allowed to toggle status.")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
when 'destroy'
|
|
90
|
+
|
|
91
|
+
# Admin can remove anything except herself.
|
|
92
|
+
if @current_user.is_root? && current_user
|
|
93
|
+
_("You can't remove yourself.")
|
|
94
|
+
elsif !@current_user.is_root?
|
|
95
|
+
_("You're not allowed to remove Typus Users.")
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
if message
|
|
101
|
+
flash[:notice] = message
|
|
102
|
+
redirect_to :back rescue redirect_to admin_dashboard_path
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
##
|
|
108
|
+
# This method checks if the user can perform the requested action.
|
|
109
|
+
# It works on models, so its available on the admin_controller.
|
|
110
|
+
#
|
|
111
|
+
def check_if_user_can_perform_action_on_resource
|
|
112
|
+
|
|
113
|
+
message = case params[:action]
|
|
114
|
+
when 'index', 'show'
|
|
115
|
+
_("{{current_user_role}} can't display items.",
|
|
116
|
+
:current_user_role => @current_user.role.capitalize)
|
|
117
|
+
when 'edit', 'update', 'position', 'toggle', 'relate', 'unrelate'
|
|
118
|
+
when 'destroy'
|
|
119
|
+
_("{{current_user_role}} can't delete this item.",
|
|
120
|
+
:current_user_role => @current_user.role.capitalize)
|
|
121
|
+
else
|
|
122
|
+
_("{{current_user_role}} can't perform action ({{action}}).",
|
|
123
|
+
:current_user_role => @current_user.role.capitalize,
|
|
124
|
+
:action => params[:action])
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
unless @current_user.can_perform?(@resource[:class], params[:action])
|
|
128
|
+
flash[:notice] = message || _("{{current_user_role}} can't perform action. ({{action}}).",
|
|
129
|
+
:current_user_role => @current_user.role.capitalize,
|
|
130
|
+
:action => params[:action])
|
|
131
|
+
redirect_to :back rescue redirect_to admin_dashboard_path
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
##
|
|
137
|
+
# This method checks if the user can perform the requested action.
|
|
138
|
+
# It works on resources, which are not models, so its available on
|
|
139
|
+
# the typus_controller.
|
|
140
|
+
#
|
|
141
|
+
def check_if_user_can_perform_action_on_resource_without_model
|
|
142
|
+
controller = params[:controller].split('/').last
|
|
143
|
+
action = params[:action]
|
|
144
|
+
unless @current_user.can_perform?(controller.camelize, action, { :special => true })
|
|
145
|
+
flash[:notice] = _("{{current_user_role}} can't go to {{action}} on {{controller}}.",
|
|
146
|
+
:current_user_role => @current_user.role.capitalize,
|
|
147
|
+
:action => action,
|
|
148
|
+
:controller => controller.humanize.downcase)
|
|
149
|
+
redirect_to :back rescue redirect_to admin_dashboard_path
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
end
|