typus 0.9.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. data/.gitignore +8 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +86 -0
  4. data/Rakefile +61 -0
  5. data/VERSION +1 -0
  6. data/app/controllers/admin/master_controller.rb +354 -0
  7. data/app/controllers/typus_controller.rb +128 -0
  8. data/app/helpers/admin/form_helper.rb +386 -0
  9. data/app/helpers/admin/master_helper.rb +104 -0
  10. data/app/helpers/admin/public_helper.rb +27 -0
  11. data/app/helpers/admin/sidebar_helper.rb +236 -0
  12. data/app/helpers/admin/table_helper.rb +227 -0
  13. data/app/helpers/typus_helper.rb +194 -0
  14. data/app/models/typus_mailer.rb +14 -0
  15. data/app/models/typus_user.rb +5 -0
  16. data/app/views/admin/dashboard/_sidebar.html.erb +9 -0
  17. data/app/views/admin/resources/edit.html.erb +24 -0
  18. data/app/views/admin/resources/index.html.erb +23 -0
  19. data/app/views/admin/resources/new.html.erb +22 -0
  20. data/app/views/admin/resources/show.html.erb +18 -0
  21. data/app/views/admin/shared/_footer.html.erb +1 -0
  22. data/app/views/admin/shared/_pagination.html.erb +28 -0
  23. data/app/views/layouts/admin.html.erb +73 -0
  24. data/app/views/layouts/typus.html.erb +29 -0
  25. data/app/views/typus/dashboard.html.erb +9 -0
  26. data/app/views/typus/recover_password.html.erb +7 -0
  27. data/app/views/typus/reset_password.html.erb +15 -0
  28. data/app/views/typus/sign_in.html.erb +9 -0
  29. data/app/views/typus/sign_up.html.erb +7 -0
  30. data/app/views/typus_mailer/reset_password_link.erb +11 -0
  31. data/config/locales/typus/de.yml +109 -0
  32. data/config/locales/typus/es.yml +109 -0
  33. data/config/locales/typus/language.yml.template +113 -0
  34. data/config/locales/typus/pt-BR.yml +111 -0
  35. data/config/locales/typus/ru.yml +111 -0
  36. data/generators/typus/templates/config/initializers/typus.rb +33 -0
  37. data/generators/typus/templates/config/typus/README +51 -0
  38. data/generators/typus/templates/config/typus/application.yml +6 -0
  39. data/generators/typus/templates/config/typus/application_roles.yml +23 -0
  40. data/generators/typus/templates/config/typus/typus.yml +14 -0
  41. data/generators/typus/templates/config/typus/typus_roles.yml +2 -0
  42. data/generators/typus/templates/db/create_typus_users.rb +21 -0
  43. data/generators/typus/templates/public/images/admin/arrow_down.gif +0 -0
  44. data/generators/typus/templates/public/images/admin/arrow_up.gif +0 -0
  45. data/generators/typus/templates/public/images/admin/spinner.gif +0 -0
  46. data/generators/typus/templates/public/images/admin/status_false.gif +0 -0
  47. data/generators/typus/templates/public/images/admin/status_true.gif +0 -0
  48. data/generators/typus/templates/public/images/admin/trash.gif +0 -0
  49. data/generators/typus/templates/public/javascripts/admin/application.js +14 -0
  50. data/generators/typus/templates/public/stylesheets/admin/reset.css +68 -0
  51. data/generators/typus/templates/public/stylesheets/admin/screen.css +729 -0
  52. data/generators/typus/typus_generator.rb +122 -0
  53. data/generators/typus_update_schema_to_01/templates/config/typus.yml +14 -0
  54. data/generators/typus_update_schema_to_01/templates/migration.rb +11 -0
  55. data/generators/typus_update_schema_to_01/typus_update_schema_to_01_generator.rb +19 -0
  56. data/lib/typus.rb +122 -0
  57. data/lib/typus/active_record.rb +307 -0
  58. data/lib/typus/authentication.rb +142 -0
  59. data/lib/typus/configuration.rb +85 -0
  60. data/lib/typus/extensions/routes.rb +15 -0
  61. data/lib/typus/format.rb +55 -0
  62. data/lib/typus/generator.rb +81 -0
  63. data/lib/typus/hash.rb +8 -0
  64. data/lib/typus/locale.rb +17 -0
  65. data/lib/typus/object.rb +21 -0
  66. data/lib/typus/quick_edit.rb +40 -0
  67. data/lib/typus/reloader.rb +15 -0
  68. data/lib/typus/string.rb +11 -0
  69. data/lib/typus/templates/index.html.erb +11 -0
  70. data/lib/typus/templates/resource_controller.rb.erb +15 -0
  71. data/lib/typus/templates/resource_controller_test.rb.erb +10 -0
  72. data/lib/typus/templates/resources_controller.rb.erb +37 -0
  73. data/lib/typus/user.rb +134 -0
  74. data/lib/vendor/active_record.rb +15 -0
  75. data/lib/vendor/paginator.rb +143 -0
  76. data/rails/init.rb +3 -0
  77. data/tasks/typus_tasks.rake +32 -0
  78. data/test/config/broken/application.yml +68 -0
  79. data/test/config/broken/application_roles.yml +20 -0
  80. data/test/config/broken/empty.yml +0 -0
  81. data/test/config/broken/empty_roles.yml +0 -0
  82. data/test/config/broken/undefined.yml +3 -0
  83. data/test/config/broken/undefined_roles.yml +6 -0
  84. data/test/config/default/typus.yml +14 -0
  85. data/test/config/default/typus_roles.yml +2 -0
  86. data/test/config/empty/empty_01.yml +0 -0
  87. data/test/config/empty/empty_01_roles.yml +0 -0
  88. data/test/config/empty/empty_02.yml +0 -0
  89. data/test/config/empty/empty_02_roles.yml +0 -0
  90. data/test/config/locales/es.yml +10 -0
  91. data/test/config/ordered/001_roles.yml +2 -0
  92. data/test/config/ordered/002_roles.yml +2 -0
  93. data/test/config/unordered/app_one_roles.yml +2 -0
  94. data/test/config/unordered/app_two_roles.yml +2 -0
  95. data/test/config/working/application.yml +68 -0
  96. data/test/config/working/application_roles.yml +22 -0
  97. data/test/config/working/typus.yml +14 -0
  98. data/test/config/working/typus_roles.yml +2 -0
  99. data/test/fixtures/app/controllers/admin/assets_controller.rb +2 -0
  100. data/test/fixtures/app/controllers/admin/categories_controller.rb +2 -0
  101. data/test/fixtures/app/controllers/admin/comments_controller.rb +2 -0
  102. data/test/fixtures/app/controllers/admin/pages_controller.rb +2 -0
  103. data/test/fixtures/app/controllers/admin/posts_controller.rb +2 -0
  104. data/test/fixtures/app/controllers/admin/status_controller.rb +6 -0
  105. data/test/fixtures/app/controllers/admin/typus_users_controller.rb +2 -0
  106. data/test/fixtures/app/controllers/admin/watch_dog_controller.rb +6 -0
  107. data/test/fixtures/app/views/admin/comments/_edit.html.erb +1 -0
  108. data/test/fixtures/app/views/admin/comments/_index.html.erb +1 -0
  109. data/test/fixtures/app/views/admin/comments/_new.html.erb +1 -0
  110. data/test/fixtures/app/views/admin/comments/_show.html.erb +1 -0
  111. data/test/fixtures/app/views/admin/comments/_sidebar.html.erb +1 -0
  112. data/test/fixtures/app/views/admin/dashboard/_content.html.erb +1 -0
  113. data/test/fixtures/app/views/admin/dashboard/_sidebar.html.erb +1 -0
  114. data/test/fixtures/app/views/admin/resources/_sidebar.html.erb +1 -0
  115. data/test/fixtures/app/views/admin/shared/_footer.html.erb +1 -0
  116. data/test/fixtures/app/views/admin/status/index.html.erb +1 -0
  117. data/test/fixtures/app/views/admin/templates/_datepicker.html.erb +1 -0
  118. data/test/fixtures/assets.yml +11 -0
  119. data/test/fixtures/categories.yml +14 -0
  120. data/test/fixtures/comments.yml +27 -0
  121. data/test/fixtures/pages.yml +41 -0
  122. data/test/fixtures/posts.yml +37 -0
  123. data/test/fixtures/typus_users.yml +54 -0
  124. data/test/functional/admin/assets_controller_test.rb +57 -0
  125. data/test/functional/admin/categories_controller_test.rb +106 -0
  126. data/test/functional/admin/comments_controller_test.rb +120 -0
  127. data/test/functional/admin/master_controller_test.rb +5 -0
  128. data/test/functional/admin/posts_controller_test.rb +261 -0
  129. data/test/functional/admin/status_controller_test.rb +43 -0
  130. data/test/functional/admin/typus_users_controller_test.rb +239 -0
  131. data/test/functional/typus_controller_test.rb +321 -0
  132. data/test/helper.rb +51 -0
  133. data/test/helpers/admin/form_helper_test.rb +337 -0
  134. data/test/helpers/admin/master_helper_test.rb +69 -0
  135. data/test/helpers/admin/public_helper_test.rb +26 -0
  136. data/test/helpers/admin/sidebar_helper_test.rb +335 -0
  137. data/test/helpers/admin/table_helper_test.rb +239 -0
  138. data/test/helpers/typus_helper_test.rb +117 -0
  139. data/test/lib/active_record_test.rb +382 -0
  140. data/test/lib/configuration_test.rb +94 -0
  141. data/test/lib/hash_test.rb +11 -0
  142. data/test/lib/routes_test.rb +71 -0
  143. data/test/lib/string_test.rb +25 -0
  144. data/test/lib/typus_test.rb +85 -0
  145. data/test/models.rb +51 -0
  146. data/test/schema.rb +64 -0
  147. data/test/unit/typus_mailer_test.rb +33 -0
  148. data/test/unit/typus_test.rb +17 -0
  149. data/test/unit/typus_user_roles_test.rb +90 -0
  150. data/test/unit/typus_user_test.rb +177 -0
  151. data/test/vendor/active_record_test.rb +18 -0
  152. data/test/vendor/paginator_test.rb +136 -0
  153. data/typus.gemspec +228 -0
  154. metadata +241 -0
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.swp
2
+ *.db
3
+ *.log
4
+ _dashboard*
5
+ rdoc/*
6
+ *~
7
+ *.gem
8
+ SPECDOC
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007-2009 Francesc Esplugas Marti
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,86 @@
1
+ = Typus: Effortless admin interface for your Rails application
2
+
3
+ *Typus* is designed for a single activity:
4
+
5
+ Trusted users editing structured content.
6
+
7
+ *Typus* doesn't try to be all the things to all the people but it's
8
+ extensible enough to match lots of use cases.
9
+
10
+ - Project site and documentation http://intraducibles.com/projects/typus
11
+ - Plugin source http://github.com/fesplugas/typus/tree
12
+ - Google Group http://groups.google.es/group/typus
13
+ - Bugs http://typus.lighthouseapp.com/dashboard
14
+
15
+ == Impatients to see it working?
16
+
17
+ Step 1: Create a Rails application using a template.
18
+
19
+ $ rails example.com -m http://gist.github.com/86613.txt
20
+
21
+ Step 2: Start the server:
22
+
23
+ $ cd example.com && script/server
24
+
25
+ Step 3: Go to the admin area and enjoy it!
26
+
27
+ http://0.0.0.0:3000/admin
28
+
29
+ == Installing
30
+
31
+ Install from GitHub the latest version which it's compatible with Rails 2.3.2.
32
+
33
+ $ script/plugin install git://github.com/fesplugas/typus.git
34
+
35
+ Once *Typus* is installed, run the generator to create required files and migrate your
36
+ database. (<tt>typus_users</tt> table is created)
37
+
38
+ $ script/generate typus
39
+ $ rake db:migrate
40
+
41
+ To create the first user, start the application server, go to
42
+ http://0.0.0.0:3000/admin and follow the instructions.
43
+
44
+ == Support Typus
45
+
46
+ *Typus* is licensed under the MIT license. As an experiment we
47
+ encourage you to support this project by donating[http://intraducibles.com/projects/typus/donate]
48
+ 90 euros if you are a developer or studio. Donations do allow us to spend more
49
+ time working and supporting the project. All contributions are much appreciated!
50
+
51
+ Hire us to work on your next project. We build large and small websites.
52
+
53
+ Contribute your patches to the community & support people on the
54
+ mailing list.
55
+
56
+ Tell everybody about Typus, tell your friends and colleagues about
57
+ Typus and blog about Typus.
58
+
59
+ == Contributors
60
+
61
+ - Laia Gargallo (Lover and tea provider) http://azotacalles.net
62
+ - Isaac Feliu (Codereview on first public release) http://www.vesne.com
63
+ - Lluis Folch (Icons, feedback & crazy ideas) http://wet-floor.com
64
+ - Sergio Espeja (Code) http://github.com/spejman
65
+ - Eadz (Code) http://github.com/eadz
66
+ - Anthony Underwood (Code) http://github.com/aunderwo
67
+ - Felipe Talavera (Code) http://github.com/flype
68
+ - Erik Tigerholm (Code) http://github.com/eriktigerholm
69
+ - George Guimarães (Portuguese translation and code) http://github.com/georgeguimaraes
70
+ - José Valim (Code) http://github.com/josevalim
71
+ - Luqman Amjad (Code) http://github.com/snake
72
+ - Alexey Noskov (Russian translation and code) http://github.com/alno
73
+ - Andres Gutierres (Bugfixes & feedback) http://github.com/andresgutgon
74
+ - Komzák Nándor (Code, bugfixes & feedback) http://github.com/rubymood
75
+ - Michael Grunewalder (German translation) http://michael.grunewalder.com
76
+ - Tim Harvey (Code) http://www.timharvey.net/
77
+ - Ned Baldessin (Code) http://github.com/nedbaldessin
78
+ - Robert Rouse (Code) - Ruby 1.9 compatibility fixes.
79
+
80
+ == Acknowledgments
81
+
82
+ - *Typus* uses "Paginator" by Bruce Williams http://codefluency.com.
83
+ - *Typus* has been inspired by "Django Admin" http://www.djangoproject.com.
84
+
85
+ Copyright (c) 2007-2009 Francesc Esplugas Marti, released under the
86
+ MIT license
data/Rakefile ADDED
@@ -0,0 +1,61 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the typus plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the typus plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_files.add ['README.rdoc', 'MIT-LICENSE', 'lib/**/*.rb']
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'Typus documentation'
20
+ rdoc.main = 'README.rdoc'
21
+ rdoc.options << '--charset=UTF-8'
22
+ rdoc.options << '--inline-source'
23
+ rdoc.options << '--line-numbers'
24
+ end
25
+
26
+ desc 'Generate specdoc-style documentation from tests'
27
+ task :specs do
28
+
29
+ puts 'Started'
30
+ timer, count = Time.now, 0
31
+
32
+ File.open('SPECDOC', 'w') do |file|
33
+ Dir.glob('test/**/*_test.rb').each do |test|
34
+ test =~ /.*\/([^\/].*)_test.rb$/
35
+ file.puts "#{$1.gsub('_', ' ').capitalize} should:" if $1
36
+ File.read(test).map { |line| /test_(.*)$/.match line }.compact.each do |spec|
37
+ file.puts "- #{spec[1].gsub('_', ' ')}"
38
+ sleep 0.001; print '.'; $stdout.flush; count += 1
39
+ end
40
+ file.puts
41
+ end
42
+ end
43
+
44
+ puts "\nFinished in #{Time.now - timer} seconds.\n"
45
+ puts "#{count} specifications documented"
46
+
47
+ end
48
+
49
+ begin
50
+ require 'jeweler'
51
+ Jeweler::Tasks.new do |gemspec|
52
+ gemspec.name = "typus"
53
+ gemspec.summary = "Effortless backend interface for Ruby on Rails applications. (Admin scaffold generator.)"
54
+ gemspec.email = "francesc@intraducibles.com"
55
+ gemspec.homepage = "http://intraducibles.com/projects/typus"
56
+ gemspec.description = "Effortless backend interface for Ruby on Rails applications. (Admin scaffold generator.)"
57
+ gemspec.authors = ["Francesc Esplugas"]
58
+ end
59
+ rescue LoadError
60
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
61
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.9.17
@@ -0,0 +1,354 @@
1
+ class Admin::MasterController < ApplicationController
2
+
3
+ unloadable
4
+
5
+ layout 'admin'
6
+
7
+ include Typus::Authentication
8
+ include Typus::Format
9
+ include Typus::Locale
10
+ include Typus::Reloader
11
+
12
+ if Typus::Configuration.options[:ssl]
13
+ include SslRequirement
14
+ ssl_required :index, :new, :create, :edit, :show, :update, :destroy, :toggle, :position, :relate, :unrelate
15
+ end
16
+
17
+ filter_parameter_logging :password
18
+
19
+ before_filter :reload_config_et_roles
20
+
21
+ before_filter :require_login
22
+
23
+ before_filter :set_locale
24
+
25
+ before_filter :set_resource
26
+ before_filter :find_item,
27
+ :only => [ :show, :edit, :update, :destroy, :toggle, :position, :relate, :unrelate ]
28
+
29
+ before_filter :check_ownership_of_item,
30
+ :only => [ :edit, :update, :destroy, :toggle, :position, :relate, :unrelate ]
31
+
32
+ before_filter :check_if_user_can_perform_action_on_user,
33
+ :only => [ :edit, :update, :toggle, :destroy ]
34
+ before_filter :check_if_user_can_perform_action_on_resource
35
+
36
+ before_filter :set_order,
37
+ :only => [ :index ]
38
+ before_filter :set_fields,
39
+ :only => [ :index, :new, :edit, :create, :update, :show ]
40
+
41
+ before_filter :set_tiny_mce,
42
+ :only => [ :new, :edit, :create, :update ]
43
+
44
+ ##
45
+ # This is the main index of the model. With filters, conditions
46
+ # and more.
47
+ #
48
+ # By default application can respond_to html, csv and xml, but you
49
+ # can add your formats.
50
+ #
51
+ def index
52
+
53
+ @conditions, @joins = @resource[:class].build_conditions(params)
54
+
55
+ check_ownership_of_items if @resource[:class].typus_options_for(:only_user_items)
56
+
57
+ respond_to do |format|
58
+ format.html { generate_html }
59
+ @resource[:class].typus_export_formats.each do |f|
60
+ format.send(f) { send("generate_#{f}") }
61
+ end
62
+ end
63
+
64
+ rescue Exception => error
65
+ error_handler(error)
66
+ end
67
+
68
+ def new
69
+
70
+ item_params = params.dup
71
+ %w( controller action resource resource_id back_to selected ).each do |param|
72
+ item_params.delete(param)
73
+ end
74
+
75
+ @item = @resource[:class].new(item_params.symbolize_keys)
76
+
77
+ select_template :new
78
+
79
+ end
80
+
81
+ ##
82
+ # Create new items. There's an special case when we create an
83
+ # item from another item. In this case, after the item is
84
+ # created we also create the relationship between these items.
85
+ #
86
+ def create
87
+
88
+ @item = @resource[:class].new(params[:item])
89
+
90
+ if @item.attributes.include?(Typus.user_fk)
91
+ @item.attributes = { Typus.user_fk => session[:typus_user_id] }
92
+ end
93
+
94
+ if @item.valid?
95
+ create_with_back_to and return if params[:back_to]
96
+ @item.save
97
+ flash[:success] = _("{{model}} successfully created.", :model => @resource[:class].typus_human_name)
98
+ if @resource[:class].typus_options_for(:index_after_save)
99
+ redirect_to :action => 'index'
100
+ else
101
+ redirect_to :action => @resource[:class].typus_options_for(:default_action_on_item), :id => @item.id
102
+ end
103
+ else
104
+ select_template :new
105
+ end
106
+
107
+ end
108
+
109
+ def edit
110
+ item_params = params.dup
111
+ %w( action controller model model_id back_to id resource resource_id page ).each { |p| item_params.delete(p) }
112
+ # We assign the params passed trough the url
113
+ @item.attributes = item_params
114
+ @previous, @next = @item.previous_and_next(item_params)
115
+ select_template :edit
116
+ end
117
+
118
+ def show
119
+
120
+ @previous, @next = @item.previous_and_next
121
+
122
+ respond_to do |format|
123
+ format.html { select_template :show }
124
+ format.xml do
125
+ fields = @resource[:class].typus_fields_for(:xml).collect { |i| i.first }
126
+ render :xml => @item.to_xml(:only => fields)
127
+ end
128
+ end
129
+
130
+ end
131
+
132
+ def update
133
+ if @item.update_attributes(params[:item])
134
+ flash[:success] = _("{{model}} successfully updated.", :model => @resource[:class].typus_human_name)
135
+ path = if @resource[:class].typus_options_for(:index_after_save)
136
+ params[:back_to] ? "#{params[:back_to]}##{@resource[:self]}" : { :action => 'index' }
137
+ else
138
+ { :action => @resource[:class].typus_options_for(:default_action_on_item), :id => @item.id, :back_to => params[:back_to] }
139
+ end
140
+ redirect_to path
141
+ else
142
+ @previous, @next = @item.previous_and_next
143
+ select_template :edit
144
+ end
145
+ end
146
+
147
+ def destroy
148
+ @item.destroy
149
+ flash[:success] = _("{{model}} successfully removed.", :model => @resource[:class].typus_human_name)
150
+ redirect_to :back
151
+ rescue Exception => error
152
+ error_handler(error, params.merge(:action => 'index', :id => nil))
153
+ end
154
+
155
+ def toggle
156
+ if @resource[:class].typus_options_for(:toggle)
157
+ @item.toggle!(params[:field])
158
+ flash[:success] = _("{{model}} {{attribute}} changed.",
159
+ :model => @resource[:class].typus_human_name,
160
+ :attribute => params[:field].humanize.downcase)
161
+ else
162
+ flash[:notice] = _("Toggle is disabled.")
163
+ end
164
+ redirect_to :back
165
+ end
166
+
167
+ ##
168
+ # Change item position. This only works if acts_as_list is
169
+ # installed. We can then move items:
170
+ #
171
+ # params[:go] = 'move_to_top'
172
+ #
173
+ # Available positions are move_to_top, move_higher, move_lower,
174
+ # move_to_bottom.
175
+ #
176
+ def position
177
+ @item.send(params[:go])
178
+ flash[:success] = _("Record moved {{to}}.", :to => params[:go].gsub(/move_/, '').humanize.downcase)
179
+ redirect_to :back
180
+ end
181
+
182
+ ##
183
+ # Relate a model object to another, this action is used only by the
184
+ # has_and_belongs_to_many relationships.
185
+ #
186
+ def relate
187
+
188
+ resource_class = params[:related][:model].constantize
189
+ resource_tableized = params[:related][:model].tableize
190
+
191
+ @item.send(resource_tableized) << resource_class.find(params[:related][:id])
192
+
193
+ flash[:success] = _("{{model_a}} related to {{model_b}}.",
194
+ :model_a => resource_class.typus_human_name,
195
+ :model_b => @resource[:class].typus_human_name)
196
+
197
+ redirect_to :action => @resource[:class].typus_options_for(:default_action_on_item),
198
+ :id => @item.id,
199
+ :anchor => resource_tableized
200
+
201
+ end
202
+
203
+ ##
204
+ # Remove relationship between models.
205
+ #
206
+ def unrelate
207
+
208
+ resource_class = params[:resource].classify.constantize
209
+ resource = resource_class.find(params[:resource_id])
210
+
211
+ case params[:association]
212
+ when 'has_and_belongs_to_many'
213
+ @item.send(resource_class.table_name).delete(resource)
214
+ message = "{{model_a}} unrelated from {{model_b}}."
215
+ when 'has_many', 'has_one'
216
+ resource.destroy
217
+ message = "{{model_a}} removed from {{model_b}}."
218
+ end
219
+
220
+ flash[:success] = _(message, :model_a => resource_class.typus_human_name, :model_b => @resource[:class].typus_human_name)
221
+
222
+ redirect_to :controller => @resource[:self],
223
+ :action => @resource[:class].typus_options_for(:default_action_on_item),
224
+ :id => @item.id,
225
+ :anchor => resource_class.table_name
226
+
227
+ end
228
+
229
+ private
230
+
231
+ def set_resource
232
+ resource = params[:controller].split('/').last
233
+ @resource = { :self => resource, :class => resource.classify.constantize }
234
+ rescue Exception => error
235
+ error_handler(error)
236
+ end
237
+
238
+ ##
239
+ # Find model when performing an edit, update, destroy, relate,
240
+ # unrelate ...
241
+ #
242
+ def find_item
243
+ @item = @resource[:class].find(params[:id])
244
+ end
245
+
246
+ ##
247
+ # If item is owned by another user, we only can perform a
248
+ # show action on the item. Updated item is also blocked.
249
+ #
250
+ # before_filter :check_ownership_of_item, :only => [ :edit, :update, :destroy ]
251
+ #
252
+ def check_ownership_of_item
253
+
254
+ # If current_user is a root user, by-pass.
255
+ return if @current_user.is_root?
256
+
257
+ # OPTIMIZE: `typus_users` is currently hard-coded. We should find a good name for this option.
258
+ if @item.respond_to?('typus_users') && !@item.send('typus_users').include?(@current_user) ||
259
+ @item.respond_to?(Typus.user_fk) && !(@item.send(Typus.user_fk) == session[:typus_user_id])
260
+ flash[:notice] = _("You don't have permission to access this item.")
261
+ redirect_to :back
262
+ end
263
+
264
+ end
265
+
266
+ def check_ownership_of_items
267
+
268
+ # By-pass if current_user is root.
269
+ return if @current_user.is_root?
270
+
271
+ # If current user is not root and @resource has a foreign_key which
272
+ # is related to the logged user (Typus.user_fk) we only show the user
273
+ # related items.
274
+ if @resource[:class].columns.map { |u| u.name }.include?(Typus.user_fk)
275
+ condition = { Typus.user_fk => @current_user }
276
+ @conditions = @resource[:class].merge_conditions(@conditions, condition)
277
+ end
278
+
279
+ end
280
+
281
+ def set_fields
282
+ @fields = case params[:action]
283
+ when 'index'
284
+ @resource[:class].typus_fields_for(:list)
285
+ when 'new', 'edit', 'create', 'update'
286
+ @resource[:class].typus_fields_for(:form)
287
+ else
288
+ @resource[:class].typus_fields_for(params[:action])
289
+ end
290
+ end
291
+
292
+ def set_order
293
+ params[:sort_order] ||= 'desc'
294
+ @order = params[:order_by] ? "#{@resource[:class].table_name}.#{params[:order_by]} #{params[:sort_order]}" : @resource[:class].typus_order_by
295
+ end
296
+
297
+ def set_tiny_mce
298
+ if !@resource[:class].typus_tiny_mce_fields.empty? && defined?(TinyMCE)
299
+ options = @resource[:class].typus_tiny_mce_options
300
+ self.class.class_eval { uses_tiny_mce :options => options }
301
+ end
302
+ end
303
+
304
+ def select_template(template, resource = @resource[:self])
305
+ folder = (File.exist?("app/views/admin/#{resource}/#{template}.html.erb")) ? resource : 'resources'
306
+ render "admin/#{folder}/#{template}"
307
+ end
308
+
309
+ ##
310
+ # When <tt>params[:back_to]</tt> is defined this action is used.
311
+ #
312
+ # - <tt>has_and_belongs_to_many</tt> relationships.
313
+ # - <tt>has_many</tt> relationships (polymorphic ones).
314
+ #
315
+ def create_with_back_to
316
+
317
+ if params[:resource] && params[:resource_id]
318
+ resource_class = params[:resource].classify.constantize
319
+ resource_id = params[:resource_id]
320
+ resource = resource_class.find(resource_id)
321
+ association = @resource[:class].reflect_on_association(params[:resource].to_sym).macro rescue :polymorphic
322
+ else
323
+ association = :has_many
324
+ end
325
+
326
+ case association
327
+ when :belongs_to
328
+ @item.save
329
+ when :has_and_belongs_to_many
330
+ @item.save
331
+ @item.send(params[:resource]) << resource
332
+ when :has_many
333
+ @item.save
334
+ message = _("{{model}} successfully created.", :model => @resource[:class].typus_human_name)
335
+ path = "#{params[:back_to]}?#{params[:selected]}=#{@item.id}"
336
+ when :polymorphic
337
+ resource.send(@item.class.name.tableize).create(params[:item])
338
+ path = "#{params[:back_to]}##{@resource[:self]}"
339
+ end
340
+
341
+ flash[:success] = message || _("{{model_a}} successfully assigned to {{model_b}}.",
342
+ :model_a => @item.class.typus_human_name,
343
+ :model_b => resource_class.name)
344
+ redirect_to path || params[:back_to]
345
+
346
+ end
347
+
348
+ def error_handler(error, path = admin_dashboard_path)
349
+ raise error unless Rails.env.production?
350
+ flash[:error] = "#{error.message} (#{@resource[:class]})"
351
+ redirect_to path
352
+ end
353
+
354
+ end