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.
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
@@ -0,0 +1,128 @@
1
+ class TypusController < ApplicationController
2
+
3
+ unloadable
4
+
5
+ layout :select_layout
6
+
7
+ include Typus::Authentication
8
+ include Typus::Locale
9
+ include Typus::QuickEdit
10
+ include Typus::Reloader
11
+
12
+ if Typus::Configuration.options[:ssl]
13
+ include SslRequirement
14
+ ssl_required :sign_in, :sign_out,
15
+ :dashboard,
16
+ :recover_password, :reset_password
17
+ end
18
+
19
+ filter_parameter_logging :password
20
+
21
+ before_filter :set_locale
22
+
23
+ before_filter :reload_config_et_roles
24
+ before_filter :require_login,
25
+ :except => [ :sign_up, :sign_in, :sign_out,
26
+ :recover_password, :reset_password,
27
+ :quick_edit ]
28
+
29
+ before_filter :check_if_user_can_perform_action_on_resource_without_model,
30
+ :except => [ :sign_up, :sign_in, :sign_out,
31
+ :dashboard,
32
+ :recover_password, :reset_password,
33
+ :quick_edit, :set_locale ]
34
+
35
+ before_filter :recover_password_disabled?,
36
+ :only => [ :recover_password, :reset_password ]
37
+
38
+ def dashboard
39
+ flash[:notice] = _("There are not defined applications in config/typus/*.yml.") if Typus.applications.empty?
40
+ end
41
+
42
+ def sign_in
43
+
44
+ redirect_to admin_sign_up_path and return if Typus.user_class.count.zero?
45
+
46
+ if request.post?
47
+ if user = Typus.user_class.authenticate(params[:user][:email], params[:user][:password])
48
+ session[:typus_user_id] = user.id
49
+ redirect_to params[:back_to] || admin_dashboard_path
50
+ else
51
+ flash[:error] = _("The email and/or password you entered is invalid.")
52
+ redirect_to admin_sign_in_path
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ def sign_out
59
+ session[:typus_user_id] = nil
60
+ redirect_to admin_sign_in_path
61
+ end
62
+
63
+ def recover_password
64
+ if request.post?
65
+ if user = Typus.user_class.find_by_email(params[:user][:email])
66
+ ActionMailer::Base.default_url_options[:host] = request.host_with_port
67
+ TypusMailer.deliver_reset_password_link(user)
68
+ flash[:success] = _("Password recovery link sent to your email.")
69
+ redirect_to admin_sign_in_path
70
+ else
71
+ redirect_to admin_recover_password_path
72
+ end
73
+ end
74
+ end
75
+
76
+ ##
77
+ # Available if Typus::Configuration.options[:recover_password] is enabled.
78
+ #
79
+ def reset_password
80
+ @user = Typus.user_class.find_by_token!(params[:token])
81
+ if request.post?
82
+ @user.password = params[:user][:password]
83
+ @user.password_confirmation = params[:user][:password_confirmation]
84
+ if @user.save
85
+ session[:typus_user_id] = @user.id
86
+ redirect_to admin_dashboard_path
87
+ else
88
+ render :action => 'reset_password'
89
+ end
90
+ end
91
+ end
92
+
93
+ def sign_up
94
+
95
+ redirect_to admin_sign_in_path and return unless Typus.user_class.count.zero?
96
+
97
+ if request.post?
98
+
99
+ email, password = params[:user][:email], 'columbia'
100
+ user = Typus.user_class.generate(email, password)
101
+
102
+ if user.save
103
+ session[:typus_user_id] = user.id
104
+ flash[:notice] = _("Password set to \"{{password}}\".", :password => password)
105
+ redirect_to admin_dashboard_path
106
+ else
107
+ flash[:error] = _("That doesn't seem like a valid email address.")
108
+ end
109
+
110
+ else
111
+
112
+ flash[:notice] = _("Enter your email below to create the first user.")
113
+
114
+ end
115
+
116
+ end
117
+
118
+ private
119
+
120
+ def recover_password_disabled?
121
+ redirect_to admin_sign_in_path unless Typus::Configuration.options[:recover_password]
122
+ end
123
+
124
+ def select_layout
125
+ %w( sign_up sign_in sign_out recover_password reset_password ).include?(action_name) ? 'typus' : 'admin'
126
+ end
127
+
128
+ end
@@ -0,0 +1,386 @@
1
+ module Admin::FormHelper
2
+
3
+ def build_form(fields)
4
+
5
+ options = { :start_year => @resource[:class].typus_options_for(:start_year),
6
+ :end_year => @resource[:class].typus_options_for(:end_year),
7
+ :minute_step => @resource[:class].typus_options_for(:minute_step) }
8
+
9
+ returning(String.new) do |html|
10
+ html << (error_messages_for :item, :header_tag => 'h3')
11
+ html << '<ul>'
12
+
13
+ fields.each do |key, value|
14
+ if template = @resource[:class].typus_template(key)
15
+ html << typus_template_field(key, template, options)
16
+ next
17
+ end
18
+ case value
19
+ when :belongs_to then html << typus_belongs_to_field(key)
20
+ when :boolean then html << typus_boolean_field(key)
21
+ when :date then html << typus_date_field(key, options)
22
+ when :datetime then html << typus_datetime_field(key, options)
23
+ when :file then html << typus_file_field(key)
24
+ when :password then html << typus_password_field(key)
25
+ when :selector then html << typus_selector_field(key)
26
+ when :text then html << typus_text_field(key)
27
+ when :tiny_mce then html << typus_tiny_mce_field(key)
28
+ when :time then html << typus_time_field(key, options)
29
+ when :tree then html << typus_tree_field(key)
30
+ else
31
+ html << typus_string_field(key)
32
+ end
33
+ end
34
+ html << '</ul>'
35
+ end
36
+ end
37
+
38
+ def typus_belongs_to_field(attribute)
39
+
40
+ ##
41
+ # We only can pass parameters to 'new' and 'edit', so this hack makes
42
+ # the work to replace the current action.
43
+ #
44
+ params[:action] = (params[:action] == 'create') ? 'new' : params[:action]
45
+
46
+ back_to = '/' + [ params[:controller], params[:action], params[:id] ].compact.join('/')
47
+
48
+ related = @resource[:class].reflect_on_association(attribute.to_sym).class_name.constantize
49
+ related_fk = @resource[:class].reflect_on_association(attribute.to_sym).primary_key_name
50
+
51
+ message = [ _("Are you sure you want to leave this page?"),
52
+ _("If you have made any changes to the fields without clicking the Save/Update entry button, your changes will be lost."),
53
+ _("Click OK to continue, or click Cancel to stay on this page.") ]
54
+
55
+ returning(String.new) do |html|
56
+
57
+ if related.respond_to?(:roots)
58
+ html << typus_tree_field(related_fk, related.roots, related_fk)
59
+ else
60
+ html << <<-HTML
61
+ <li><label for="item_#{attribute}">#{_(related_fk.humanize)}
62
+ <small>#{link_to _("Add"), { :controller => "admin/#{related.class_name.tableize}", :action => 'new', :back_to => back_to, :selected => related_fk }, :confirm => message.join("\n\n") if @current_user.can_perform?(related, 'create')}</small>
63
+ </label>
64
+ #{select :item, related_fk, related.find(:all, :order => related.typus_order_by).collect { |p| [p.typus_name, p.id] }, { :include_blank => true }, { :disabled => attribute_disabled?(attribute) } }</li>
65
+ HTML
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
72
+ def typus_boolean_field(attribute)
73
+ attribute_name = attribute.gsub(/\?$/,'')
74
+ custom_true = @resource[:class].typus_boolean(attribute)[:true]
75
+ custom_true = custom_true != 'True' ? custom_true : "Checked if active"
76
+ <<-HTML
77
+ <li><label>#{@resource[:class].human_attribute_name(attribute)}</label>
78
+ #{check_box :item, attribute_name} <label class="inline_label" for="item_#{attribute_name}">#{_(custom_true)}</label></li>
79
+ HTML
80
+ end
81
+
82
+ def typus_date_field(attribute, options)
83
+ <<-HTML
84
+ <li><label for="item_#{attribute}">#{@resource[:class].human_attribute_name(attribute)}</label>
85
+ #{date_select :item, attribute, options, { :disabled => attribute_disabled?(attribute)} }</li>
86
+ HTML
87
+ end
88
+
89
+ def typus_datetime_field(attribute, options)
90
+ <<-HTML
91
+ <li><label for="item_#{attribute}">#{@resource[:class].human_attribute_name(attribute)}</label>
92
+ #{datetime_select :item, attribute, options, {:disabled => attribute_disabled?(attribute)}}</li>
93
+ HTML
94
+ end
95
+
96
+ def typus_file_field(attribute)
97
+
98
+ attribute_display = attribute.split('_file_name').first
99
+
100
+ <<-HTML
101
+ <li><label for="item_#{attribute}">#{_(attribute_display.humanize)}</label>
102
+ #{file_field :item, attribute.split("_file_name").first, :disabled => attribute_disabled?(attribute)}</li>
103
+ HTML
104
+
105
+ end
106
+
107
+ def typus_password_field(attribute)
108
+ <<-HTML
109
+ <li><label for="item_#{attribute}">#{@resource[:class].human_attribute_name(attribute)}</label>
110
+ #{password_field :item, attribute, :class => 'text', :disabled => attribute_disabled?(attribute)}</li>
111
+ HTML
112
+ end
113
+
114
+ def typus_selector_field(attribute)
115
+ returning(String.new) do |html|
116
+ options = []
117
+ @resource[:class].send(attribute).each do |option|
118
+ case option.kind_of?(Array)
119
+ when true
120
+ selected = (@item.send(attribute).to_s == option.last.to_s) ? 'selected' : ''
121
+ options << "<option #{selected} value=\"#{option.last}\">#{option.first}</option>"
122
+ else
123
+ selected = (@item.send(attribute).to_s == option.to_s) ? 'selected' : ''
124
+ options << "<option #{selected} value=\"#{option}\">#{option}</option>"
125
+ end
126
+ end
127
+ html << <<-HTML
128
+ <li><label for="item_#{attribute}">#{@resource[:class].human_attribute_name(attribute)}</label>
129
+ <select id="item_#{attribute}" #{attribute_disabled?(attribute) ? 'disabled="disabled"' : ''} name="item[#{attribute}]">
130
+ <option value=""></option>
131
+ #{options.join("\n")}
132
+ </select></li>
133
+ HTML
134
+ end
135
+ end
136
+
137
+ def typus_text_field(attribute)
138
+ <<-HTML
139
+ <li><label for="item_#{attribute}">#{@resource[:class].human_attribute_name(attribute)}</label>
140
+ #{text_area :item, attribute, :class => 'text', :rows => @resource[:class].typus_options_for(:form_rows), :disabled => attribute_disabled?(attribute)}</li>
141
+ HTML
142
+ end
143
+
144
+ def typus_tiny_mce_field(attribute)
145
+ <<-HTML
146
+ <li><label for="item_#{attribute}">#{@resource[:class].human_attribute_name(attribute)}</label>
147
+ #{text_area :item, attribute, :class => 'mceEditor', :disabled => attribute_disabled?(attribute)}</li>
148
+ HTML
149
+ end
150
+
151
+ def typus_time_field(attribute, options)
152
+ <<-HTML
153
+ <li><label for="item_#{attribute}">#{@resource[:class].human_attribute_name(attribute)}</label>
154
+ #{time_select :item, attribute, options, {:disabled => attribute_disabled?(attribute)}}</li>
155
+ HTML
156
+ end
157
+
158
+ def typus_tree_field(attribute, items = @resource[:class].roots, attribute_virtual = 'parent_id')
159
+ <<-HTML
160
+ <li><label for="item_#{attribute}">#{@resource[:class].human_attribute_name(attribute)}</label>
161
+ <select id="item_#{attribute}" #{attribute_disabled?(attribute) ? 'disabled="disabled"' : ''} name="item[#{attribute}]">
162
+ <option value=""></option>
163
+ #{expand_tree_into_select_field(items, attribute_virtual)}
164
+ </select></li>
165
+ HTML
166
+ end
167
+
168
+ def typus_string_field(attribute)
169
+
170
+ # Read only fields.
171
+ if @resource[:class].typus_field_options_for(:read_only).include?(attribute)
172
+ value = 'read_only' if %w( edit ).include?(params[:action])
173
+ end
174
+
175
+ # Auto generated fields.
176
+ if @resource[:class].typus_field_options_for(:auto_generated).include?(attribute)
177
+ value = 'auto_generated' if %w( new edit ).include?(params[:action])
178
+ end
179
+
180
+ comment = %w( read_only auto_generated ).include?(value) ? "<small>#{value} field</small>".humanize : ''
181
+
182
+ attribute_humanized = @resource[:class].human_attribute_name(attribute)
183
+ attribute_humanized += " (#{attribute})" if attribute.include?('_id')
184
+
185
+ <<-HTML
186
+ <li><label for="item_#{attribute}">#{attribute_humanized}#{comment}</label>
187
+ #{text_field :item, attribute, :class => 'text', :disabled => attribute_disabled?(attribute) }</li>
188
+ HTML
189
+
190
+ end
191
+
192
+ def typus_relationships
193
+
194
+ # OPTIMIZE
195
+ @back_to = '/' + [ params[:controller], params[:action], params[:id] ].compact.join('/')
196
+
197
+ returning(String.new) do |html|
198
+ @resource[:class].typus_defaults_for(:relationships).each do |relationship|
199
+
200
+ association = @resource[:class].reflect_on_association(relationship.to_sym)
201
+
202
+ next if !@current_user.can_perform?(association.class_name.constantize, 'read')
203
+
204
+ case association.macro
205
+ when :has_and_belongs_to_many
206
+ html << typus_form_has_and_belongs_to_many(relationship)
207
+ when :has_many
208
+ html << typus_form_has_many(relationship)
209
+ when :has_one
210
+ html << typus_form_has_one(relationship)
211
+ end
212
+
213
+ end
214
+ end
215
+
216
+ end
217
+
218
+ def typus_form_has_many(field)
219
+ returning(String.new) do |html|
220
+
221
+ model_to_relate = @resource[:class].reflect_on_association(field.to_sym).class_name.constantize
222
+ model_to_relate_as_resource = model_to_relate.name.tableize
223
+
224
+ reflection = @resource[:class].reflect_on_association(field.to_sym)
225
+ association = reflection.macro
226
+ foreign_key = reflection.through_reflection ? reflection.primary_key_name.pluralize : reflection.primary_key_name
227
+
228
+ link_options = { :controller => "admin/#{field}",
229
+ :action => 'new',
230
+ :back_to => "#{@back_to}##{field}",
231
+ :resource => @resource[:self].singularize,
232
+ :resource_id => @item.id,
233
+ foreign_key => @item.id }
234
+
235
+ html << <<-HTML
236
+ <a name="#{field}"></a>
237
+ <div class="box_relationships">
238
+ <h2>
239
+ #{link_to model_to_relate.typus_human_name.pluralize, { :controller => "admin/#{model_to_relate_as_resource}", foreign_key => @item.id }, :title => _("{{model}} filtered by {{filtered_by}}", :model => model_to_relate.typus_human_name.pluralize, :filtered_by => @item.typus_name)}
240
+ <small>#{link_to _("Add new"), link_options if @current_user.can_perform?(model_to_relate, 'create')}</small>
241
+ </h2>
242
+ HTML
243
+
244
+ conditions = if model_to_relate.typus_options_for(:only_user_items) && !@current_user.is_root?
245
+ { Typus.user_fk => @current_user }
246
+ end
247
+
248
+ options = { :order => model_to_relate.typus_order_by, :conditions => conditions }
249
+ items_count = @resource[:class].find(params[:id]).send(field).count(:conditions => conditions)
250
+ items_per_page = model_to_relate.typus_options_for(:per_page).to_i
251
+
252
+ @pager = ::Paginator.new(items_count, items_per_page) do |offset, per_page|
253
+ options.merge!({:limit => per_page, :offset => offset})
254
+ items = @resource[:class].find(params[:id]).send(field).find(:all, options)
255
+ end
256
+
257
+ @items = @pager.page(params[:page])
258
+
259
+ unless @items.empty?
260
+ options = { :back_to => "#{@back_to}##{field}", :resource => @resource[:self], :resource_id => @item.id }
261
+ html << build_list(model_to_relate,
262
+ model_to_relate.typus_fields_for(:relationship),
263
+ @items,
264
+ model_to_relate_as_resource,
265
+ options,
266
+ association)
267
+ html << pagination(:anchor => model_to_relate.name.tableize) unless pagination.nil?
268
+ else
269
+ html << <<-HTML
270
+ <div id="flash" class="notice"><p>#{_("There are no {{records}}.", :records => model_to_relate.typus_human_name.pluralize.downcase)}</p></div>
271
+ HTML
272
+ end
273
+ html << <<-HTML
274
+ </div>
275
+ HTML
276
+ end
277
+ end
278
+
279
+ def typus_form_has_and_belongs_to_many(field)
280
+ returning(String.new) do |html|
281
+
282
+ model_to_relate = @resource[:class].reflect_on_association(field.to_sym).class_name.constantize
283
+ model_to_relate_as_resource = model_to_relate.name.tableize
284
+
285
+ reflection = @resource[:class].reflect_on_association(field.to_sym)
286
+ association = reflection.macro
287
+
288
+ html << <<-HTML
289
+ <a name="#{field}"></a>
290
+ <div class="box_relationships">
291
+ <h2>
292
+ #{link_to model_to_relate.typus_human_name.pluralize, :controller => "admin/#{model_to_relate_as_resource}"}
293
+ <small>#{link_to _("Add new"), :controller => field, :action => 'new', :back_to => @back_to, :resource => @resource[:self], :resource_id => @item.id if @current_user.can_perform?(model_to_relate, 'create')}</small>
294
+ </h2>
295
+ HTML
296
+ items_to_relate = (model_to_relate.find(:all) - @item.send(field))
297
+ unless items_to_relate.empty?
298
+ html << <<-HTML
299
+ #{form_tag :action => 'relate', :id => @item.id}
300
+ #{hidden_field :related, :model, :value => model_to_relate}
301
+ <p>#{ select :related, :id, items_to_relate.collect { |f| [f.typus_name, f.id] }.sort_by { |e| e.first } } &nbsp; #{submit_tag _("Add"), :class => 'button'}</p>
302
+ </form>
303
+ HTML
304
+ end
305
+ items = @resource[:class].find(params[:id]).send(field)
306
+ unless items.empty?
307
+ html << build_list(model_to_relate,
308
+ model_to_relate.typus_fields_for(:relationship),
309
+ items,
310
+ model_to_relate_as_resource,
311
+ {},
312
+ association)
313
+ else
314
+ html << <<-HTML
315
+ <div id="flash" class="notice"><p>#{_("There are no {{records}}.", :records => model_to_relate.typus_human_name.pluralize.downcase)}</p></div>
316
+ HTML
317
+ end
318
+ html << <<-HTML
319
+ </div>
320
+ HTML
321
+ end
322
+ end
323
+
324
+ def typus_form_has_one(field)
325
+ returning(String.new) do |html|
326
+
327
+ model_to_relate = @resource[:class].reflect_on_association(field.to_sym).class_name.constantize
328
+ model_to_relate_as_resource = model_to_relate.name.tableize
329
+
330
+ reflection = @resource[:class].reflect_on_association(field.to_sym)
331
+ association = reflection.macro
332
+
333
+ html << <<-HTML
334
+ <a name="#{field}"></a>
335
+ <div class="box_relationships">
336
+ <h2>
337
+ #{link_to model_to_relate.typus_human_name, :controller => "admin/#{model_to_relate_as_resource}"}
338
+ </h2>
339
+ HTML
340
+ items = Array.new
341
+ items << @resource[:class].find(params[:id]).send(field) unless @resource[:class].find(params[:id]).send(field).nil?
342
+ unless items.empty?
343
+ options = { :back_to => @back_to, :resource => @resource[:self], :resource_id => @item.id }
344
+ html << build_list(model_to_relate,
345
+ model_to_relate.typus_fields_for(:relationship),
346
+ items,
347
+ model_to_relate_as_resource,
348
+ options,
349
+ association)
350
+ else
351
+ html << <<-HTML
352
+ <div id="flash" class="notice"><p>#{_("There is no {{records}}.", :records => model_to_relate.typus_human_name.downcase)}</p></div>
353
+ HTML
354
+ end
355
+ html << <<-HTML
356
+ </div>
357
+ HTML
358
+ end
359
+ end
360
+
361
+ def typus_template_field(attribute, template, options = {})
362
+ folder = Typus::Configuration.options[:templates_folder]
363
+ template_name = File.join(folder, template)
364
+
365
+ output = render(:partial => template_name, :locals => { :resource => @resource, :attribute => attribute, :options => options } )
366
+ output || "#{attribute}: Can not find the template '#{template}'"
367
+ end
368
+
369
+ def attribute_disabled?(attribute)
370
+ accessible = @resource[:class].accessible_attributes
371
+ return accessible.nil? ? false : !accessible.include?(attribute)
372
+ end
373
+
374
+ ##
375
+ # Tree builder when model +acts_as_tree+
376
+ #
377
+ def expand_tree_into_select_field(items, attribute)
378
+ returning(String.new) do |html|
379
+ items.each do |item|
380
+ html << %{<option #{"selected" if @item.send(attribute) == item.id} value="#{item.id}">#{"&nbsp;" * item.ancestors.size * 8} &#92;_ #{item.typus_name}</option>\n}
381
+ html << expand_tree_into_select_field(item.children, attribute) unless item.children.empty?
382
+ end
383
+ end
384
+ end
385
+
386
+ end