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
@@ -0,0 +1,104 @@
1
+ module Admin::MasterHelper
2
+
3
+ include TypusHelper
4
+
5
+ include Admin::SidebarHelper
6
+ include Admin::FormHelper
7
+ include Admin::TableHelper
8
+
9
+ def display_link_to_previous # (_params = params)
10
+
11
+ options = {}
12
+ options[:resource_from] = @resource[:class].typus_human_name
13
+ options[:resource_to] = params[:resource].classify.humanize if params[:resource]
14
+
15
+ editing = %w( edit update ).include?(params[:action])
16
+
17
+ message = case
18
+ when params[:resource] && editing
19
+ _("You're updating a {{resource_from}} for {{resource_to}}.",
20
+ :resource_from => options[:resource_from],
21
+ :resource_to => options[:resource_to])
22
+ when editing
23
+ _("You're updating a {{resource_from}}.",
24
+ :resource_from => options[:resource_from])
25
+ when params[:resource]
26
+ _("You're adding a new {{resource_from}} to {{resource_to}}.",
27
+ :resource_from => options[:resource_from],
28
+ :resource_to => options[:resource_to])
29
+ else
30
+ _("You're adding a new {{resource_from}}.",
31
+ :resource_from => options[:resource_from] )
32
+ end
33
+
34
+ returning(String.new) do |html|
35
+ html << <<-HTML
36
+ <div id="flash" class="notice">
37
+ <p>#{message} #{link_to _("Do you want to cancel it?"), params[:back_to]}</p>
38
+ </div>
39
+ HTML
40
+ end
41
+
42
+ end
43
+
44
+ def remove_filter_link(filter = request.env['QUERY_STRING'])
45
+ return unless filter && !filter.blank?
46
+ <<-HTML
47
+ <small>#{link_to _("Remove filter")}</small>
48
+ HTML
49
+ end
50
+
51
+ ##
52
+ # If there's a partial with a "microformat" of the data we want to
53
+ # display, this will be used, otherwise we use a default table which
54
+ # it's build from the options defined on the yaml configuration file.
55
+ #
56
+ def build_list(model, fields, items, resource = @resource[:self], link_options = {}, association = nil)
57
+
58
+ template = "app/views/admin/#{resource}/_#{resource.singularize}.html.erb"
59
+
60
+ if File.exist?(template)
61
+ render :partial => template.gsub('/_', '/'), :collection => items, :as => :item
62
+ else
63
+ build_typus_table(model, fields, items, link_options, association)
64
+ end
65
+
66
+ end
67
+
68
+ def pagination(*args)
69
+ @options = args.extract_options!
70
+ render 'admin/shared/pagination' if @items.prev || @items.next
71
+ end
72
+
73
+ ##
74
+ # Simple and clean pagination links
75
+ #
76
+ def build_pagination(pager, options = {})
77
+
78
+ options[:link_to_current_page] ||= true
79
+ options[:always_show_anchors] ||= true
80
+
81
+ # Calculate the window start and end pages
82
+ options[:padding] ||= 2
83
+ options[:padding] = options[:padding] < 0 ? 0 : options[:padding]
84
+
85
+ page = params[:page].blank? ? 1 : params[:page].to_i
86
+ current_page = pager.page(page)
87
+
88
+ first = pager.first.number <= (current_page.number - options[:padding]) && pager.last.number >= (current_page.number - options[:padding]) ? current_page.number - options[:padding] : 1
89
+ last = pager.first.number <= (current_page.number + options[:padding]) && pager.last.number >= (current_page.number + options[:padding]) ? current_page.number + options[:padding] : pager.last.number
90
+
91
+ returning(String.new) do |html|
92
+ # Print start page if anchors are enabled
93
+ html << yield(1) if options[:always_show_anchors] and not first == 1
94
+ # Print window pages
95
+ first.upto(last) do |page|
96
+ (current_page.number == page && !options[:link_to_current_page]) ? html << page.to_s : html << (yield(page)).to_s
97
+ end
98
+ # Print end page if anchors are enabled
99
+ html << yield(pager.last.number).to_s if options[:always_show_anchors] and not last == pager.last.number
100
+ end
101
+
102
+ end
103
+
104
+ end
@@ -0,0 +1,27 @@
1
+ module Admin
2
+
3
+ module PublicHelper
4
+
5
+ ##
6
+ # Quick edit usage:
7
+ #
8
+ # <%= quick_edit(:message => "Edit this article", :path => "articles/edit/#{@article.id}") %>
9
+ #
10
+ # If user is logged in Typus, a link will appear on the top/right of
11
+ # the pages where you insert this helper.
12
+ #
13
+ def quick_edit(*args)
14
+
15
+ options = args.extract_options!
16
+
17
+ <<-HTML
18
+ <script type="text/javascript">
19
+ document.write('<script type="text/javascript" src="#{admin_quick_edit_path}?#{options.to_query}" />');
20
+ </script>
21
+ HTML
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,236 @@
1
+ module Admin::SidebarHelper
2
+
3
+ def actions
4
+
5
+ returning(String.new) do |html|
6
+
7
+ html << <<-HTML
8
+ #{build_typus_list(default_actions, :header => 'actions')}
9
+ #{build_typus_list(previous_and_next, :header => 'go_to')}
10
+ HTML
11
+
12
+ html << <<-HTML
13
+ #{build_typus_list(export, :header => 'export')}
14
+ HTML
15
+
16
+ end
17
+
18
+ end
19
+
20
+ def default_actions
21
+
22
+ items = []
23
+
24
+ case params[:action]
25
+ when 'index', 'edit', 'show', 'update'
26
+ if @current_user.can_perform?(@resource[:class], 'create')
27
+ items << (link_to _("Add entry"), :action => 'new')
28
+ end
29
+ end
30
+
31
+ case params[:action]
32
+ when 'show'
33
+ if @current_user.can_perform?(@resource[:class], 'update')
34
+ items << (link_to _("Edit entry"), :action => 'edit', :id => @item.id)
35
+ end
36
+ end
37
+
38
+ @resource[:class].typus_actions_for(params[:action]).each do |action|
39
+ if @current_user.can_perform?(@resource[:class], action)
40
+ items << (link_to _(action.humanize), params.merge(:action => action))
41
+ end
42
+ end
43
+
44
+ case params[:action]
45
+ when 'new', 'create', 'edit', 'show', 'update'
46
+ items << (link_to _("Back to list"), :action => 'index')
47
+ end
48
+
49
+ return items
50
+
51
+ end
52
+
53
+ def export
54
+ return [] unless params[:action] == 'index'
55
+ returning(Array.new) do |format|
56
+ @resource[:class].typus_export_formats.each do |f|
57
+ format << (link_to f.upcase, params.merge(:format => f))
58
+ end
59
+ end
60
+ end
61
+
62
+ def build_typus_list(items, *args)
63
+
64
+ options = args.extract_options!
65
+
66
+ header = if options[:header]
67
+ _(options[:header].humanize)
68
+ elsif options[:attribute]
69
+ @resource[:class].human_attribute_name(options[:attribute])
70
+ end
71
+
72
+ return String.new if items.empty?
73
+ returning(String.new) do |html|
74
+ html << "<h2>#{header}</h2>\n" unless header.nil?
75
+ next unless options[:selector].nil?
76
+ html << "<ul>\n"
77
+ items.each do |item|
78
+ html << "<li>#{item}</li>\n"
79
+ end
80
+ html << "</ul>\n"
81
+ end
82
+
83
+ end
84
+
85
+ def previous_and_next
86
+ return [] unless %w( edit show update ).include?(params[:action])
87
+ returning(Array.new) do |items|
88
+ items << (link_to _("Next"), params.merge(:id => @next.id)) if @next
89
+ items << (link_to _("Previous"), params.merge(:id => @previous.id)) if @previous
90
+ end
91
+ end
92
+
93
+ def search
94
+
95
+ typus_search = @resource[:class].typus_defaults_for(:search)
96
+ return if typus_search.empty?
97
+
98
+ search_by = typus_search.collect { |x| @resource[:class].human_attribute_name(x) }.to_sentence
99
+
100
+ search_params = params.dup
101
+ %w( action controller search page ).each { |p| search_params.delete(p) }
102
+
103
+ hidden_params = search_params.map { |key, value| hidden_field_tag(key, value) }
104
+
105
+ <<-HTML
106
+ <h2>#{_("Search")}</h2>
107
+ <form action="" method="get">
108
+ <p><input id="search" name="search" type="text" value="#{params[:search]}"/></p>
109
+ #{hidden_params.sort.join("\n")}
110
+ </form>
111
+ <p class="tip">#{_("Search by")} #{search_by.downcase}.</p>
112
+ HTML
113
+
114
+ end
115
+
116
+ def filters
117
+
118
+ typus_filters = @resource[:class].typus_filters
119
+ return if typus_filters.empty?
120
+
121
+ current_request = request.env['QUERY_STRING'] || []
122
+
123
+ returning(String.new) do |html|
124
+ typus_filters.each do |key, value|
125
+ case value
126
+ when :boolean then html << boolean_filter(current_request, key)
127
+ when :string then html << string_filter(current_request, key)
128
+ when :datetime then html << datetime_filter(current_request, key)
129
+ when :belongs_to then html << relationship_filter(current_request, key)
130
+ when :has_and_belongs_to_many then
131
+ html << relationship_filter(current_request, key, true)
132
+ else
133
+ html << "<p>#{_("Unknown")}</p>"
134
+ end
135
+ end
136
+ end
137
+
138
+ end
139
+
140
+ def relationship_filter(request, filter, habtm = false)
141
+
142
+ model = (habtm) ? filter.classify.constantize : filter.capitalize.camelize.constantize
143
+ related_fk = (habtm) ? filter : @resource[:class].reflect_on_association(filter.to_sym).primary_key_name
144
+
145
+ params_without_filter = params.dup
146
+ %w( controller action page ).each { |p| params_without_filter.delete(p) }
147
+ params_without_filter.delete(related_fk)
148
+
149
+ items = []
150
+
151
+ returning(String.new) do |html|
152
+ related_items = model.find(:all, :order => model.typus_order_by)
153
+ if related_items.size > model.typus_options_for(:sidebar_selector)
154
+ related_items.each do |item|
155
+ switch = request.include?("#{related_fk}=#{item.id}") ? 'selected' : ''
156
+ items << <<-HTML
157
+ <option #{switch} value="#{url_for params.merge(related_fk => item.id, :page => nil)}">#{item.typus_name}</option>
158
+ HTML
159
+ end
160
+ model_pluralized = model.name.downcase.pluralize
161
+ form = <<-HTML
162
+ <!-- Embedded JS -->
163
+ <script>
164
+ function surfto_#{model_pluralized}(form) {
165
+ var myindex = form.#{model_pluralized}.selectedIndex
166
+ if (form.#{model_pluralized}.options[myindex].value != "0") {
167
+ top.location.href = form.#{model_pluralized}.options[myindex].value;
168
+ }
169
+ }
170
+ </script>
171
+ <!-- /Embedded JS -->
172
+ <form class="form" action="#"><p>
173
+ <select name="#{model_pluralized}" onChange="surfto_#{model_pluralized}(this.form)">
174
+ <option value="#{url_for params_without_filter}">#{_("filter by")} #{_(model.typus_human_name)}</option>
175
+ #{items.join("\n")}
176
+ </select>
177
+ </p></form>
178
+ HTML
179
+ else
180
+ related_items.each do |item|
181
+ switch = request.include?("#{related_fk}=#{item.id}") ? 'on' : 'off'
182
+ items << (link_to item.typus_name, params.merge(related_fk => item.id, :page => nil), :class => switch)
183
+ end
184
+ end
185
+
186
+ if form
187
+ html << build_typus_list(items, :attribute => filter, :selector => true)
188
+ html << form
189
+ else
190
+ html << build_typus_list(items, :attribute => filter)
191
+ end
192
+
193
+ end
194
+
195
+ end
196
+
197
+ ##
198
+ # Thinking in update datetime_filters to ...
199
+ #
200
+ # %w( today last_few_days last_7_days last_30_days )
201
+ #
202
+ # ... which are the ones used by 'exception_logger'.
203
+ #
204
+ def datetime_filter(request, filter)
205
+ items = []
206
+ %w( today past_7_days this_month this_year ).each do |timeline|
207
+ switch = request.include?("#{filter}=#{timeline}") ? 'on' : 'off'
208
+ options = { filter.to_sym => timeline, :page => nil }
209
+ items << (link_to _(timeline.humanize), params.merge(options), :class => switch)
210
+ end
211
+ build_typus_list(items, :attribute => filter)
212
+ end
213
+
214
+ def boolean_filter(request, filter)
215
+ items = []
216
+ @resource[:class].typus_boolean(filter).each do |key, value|
217
+ switch = request.include?("#{filter}=#{key}") ? 'on' : 'off'
218
+ options = { filter.to_sym => key, :page => nil }
219
+ items << (link_to _(value), params.merge(options), :class => switch)
220
+ end
221
+ build_typus_list(items, :attribute => filter)
222
+ end
223
+
224
+ def string_filter(request, filter)
225
+ values = @resource[:class].send(filter)
226
+ items = []
227
+ values.each do |item|
228
+ link_name, link_filter = (values.first.kind_of?(Array)) ? [ item.first, item.last ] : [ item, item ]
229
+ switch = request.include?("#{filter}=#{link_filter}") ? 'on' : 'off'
230
+ options = { filter.to_sym => link_filter, :page => nil }
231
+ items << (link_to link_name.capitalize, params.merge(options), :class => switch)
232
+ end
233
+ build_typus_list(items, :attribute => filter)
234
+ end
235
+
236
+ end
@@ -0,0 +1,227 @@
1
+ module Admin::TableHelper
2
+
3
+ def build_typus_table(model, fields, items, link_options = {}, association = nil)
4
+
5
+ returning(String.new) do |html|
6
+
7
+ html << <<-HTML
8
+ <table class="typus">
9
+ HTML
10
+
11
+ html << typus_table_header(model, fields)
12
+
13
+ items.each do |item|
14
+
15
+ html << <<-HTML
16
+ <tr class="#{cycle('even', 'odd')}" id="item_#{item.id}">
17
+ HTML
18
+
19
+ fields.each do |key, value|
20
+ case value
21
+ when :boolean then html << typus_table_boolean_field(key, item)
22
+ when :datetime then html << typus_table_datetime_field(key, item, fields.keys.first, link_options)
23
+ when :date then html << typus_table_datetime_field(key, item, fields.keys.first, link_options)
24
+ when :time then html << typus_table_datetime_field(key, item, fields.keys.first, link_options)
25
+ when :belongs_to then html << typus_table_belongs_to_field(key, item)
26
+ when :tree then html << typus_table_tree_field(key, item)
27
+ when :position then html << typus_table_position_field(key, item)
28
+ when :has_and_belongs_to_many then
29
+ html << typus_table_has_and_belongs_to_many_field(key, item)
30
+ else
31
+ html << typus_table_string_field(key, item, fields.keys.first, link_options)
32
+ end
33
+ end
34
+
35
+ ##
36
+ # This controls the action to perform. If we are on a model list we
37
+ # will remove the entry, but if we inside a model we will remove the
38
+ # relationship between the models.
39
+ #
40
+ # Only shown is the user can destroy items.
41
+ #
42
+
43
+ if @current_user.can_perform?(model, 'delete')
44
+
45
+ case params[:action]
46
+ when 'index'
47
+ perform = link_to image_tag('admin/trash.gif'), { :action => 'destroy',
48
+ :id => item.id },
49
+ :confirm => _("Remove entry?"),
50
+ :method => :delete
51
+ else
52
+ perform = link_to image_tag('admin/trash.gif'), { :action => 'unrelate',
53
+ :id => params[:id],
54
+ :association => association,
55
+ :resource => model,
56
+ :resource_id => item.id },
57
+ :confirm => _("Unrelate {{unrelate_model}} from {{unrelate_model_from}}?",
58
+ :unrelate_model => model.typus_human_name,
59
+ :unrelate_model_from => @resource[:class].typus_human_name)
60
+ end
61
+
62
+ html << <<-HTML
63
+ <td width="10px">#{perform}</td>
64
+ HTML
65
+
66
+ end
67
+
68
+ html << <<-HTML
69
+ </tr>
70
+ HTML
71
+
72
+ end
73
+
74
+ html << "</table>"
75
+
76
+ end
77
+
78
+ end
79
+
80
+ ##
81
+ # Header of the table
82
+ #
83
+ def typus_table_header(model, fields)
84
+ returning(String.new) do |html|
85
+ headers = []
86
+ fields.each do |key, value|
87
+
88
+ content = model.human_attribute_name(key)
89
+ content += " (#{key})" if key.include?('_id')
90
+
91
+ if (model.model_fields.map(&:first).collect { |i| i.to_s }.include?(key) || model.reflect_on_all_associations(:belongs_to).map(&:name).include?(key.to_sym)) && params[:action] == 'index'
92
+ sort_order = case params[:sort_order]
93
+ when 'asc' then 'desc'
94
+ when 'desc' then 'asc'
95
+ end
96
+ order_by = model.reflect_on_association(key.to_sym).primary_key_name rescue key
97
+ switch = (params[:order_by] == key) ? sort_order : ''
98
+ options = { :order_by => order_by, :sort_order => sort_order }
99
+ content = (link_to "<div class=\"#{switch}\">#{content}</div>", params.merge(options))
100
+ end
101
+
102
+ headers << "<th>#{content}</th>"
103
+
104
+ end
105
+ headers << "<th>&nbsp;</th>" if @current_user.can_perform?(model, 'delete')
106
+ html << <<-HTML
107
+ <tr>
108
+ #{headers.join("\n")}
109
+ </tr>
110
+ HTML
111
+ end
112
+ end
113
+
114
+ def typus_table_belongs_to_field(attribute, item)
115
+
116
+ action = item.send(attribute).class.typus_options_for(:default_action_on_item) rescue 'edit'
117
+
118
+ content = if !item.send(attribute).kind_of?(NilClass)
119
+ link_to item.send(attribute).typus_name, :controller => "admin/#{attribute.pluralize}", :action => action, :id => item.send(attribute).id
120
+ end
121
+
122
+ <<-HTML
123
+ <td>#{content}</td>
124
+ HTML
125
+
126
+ end
127
+
128
+ def typus_table_has_and_belongs_to_many_field(attribute, item)
129
+ <<-HTML
130
+ <td>#{item.send(attribute).map { |i| i.typus_name }.join('<br />')}</td>
131
+ HTML
132
+ end
133
+
134
+ ##
135
+ # When detection of the attributes is made a default attribute
136
+ # type is set. From the string_field we display other content
137
+ # types.
138
+ #
139
+ def typus_table_string_field(attribute, item, first_field, link_options = {})
140
+
141
+ action = item.class.typus_options_for(:default_action_on_item)
142
+
143
+ content = if first_field == attribute
144
+ link_to item.send(attribute) || item.class.typus_options_for(:nil), link_options.merge(:controller => "admin/#{item.class.name.tableize}", :action => action, :id => item.id)
145
+ else
146
+ item.send(attribute)
147
+ end
148
+ <<-HTML
149
+ <td>#{content}</td>
150
+ HTML
151
+ end
152
+
153
+ def typus_table_tree_field(attribute, item)
154
+ <<-HTML
155
+ <td>#{item.parent.typus_name if item.parent}</td>
156
+ HTML
157
+ end
158
+
159
+ def typus_table_position_field(attribute, item)
160
+
161
+ html_position = []
162
+
163
+ [['Up', 'move_higher'], ['Down', 'move_lower']].each do |position|
164
+
165
+ options = { :controller => item.class.name.tableize,
166
+ :action => 'position',
167
+ :id => item.id,
168
+ :go => position.last }
169
+
170
+ html_position << <<-HTML
171
+ #{link_to _(position.first), params.merge(options)}
172
+ HTML
173
+
174
+ end
175
+
176
+ <<-HTML
177
+ <td>#{html_position.join('/ ')}</td>
178
+ HTML
179
+
180
+ end
181
+
182
+ def typus_table_datetime_field(attribute, item, first_field = nil, link_options = {} )
183
+
184
+ action = item.class.typus_options_for(:default_action_on_item)
185
+
186
+ date_format = item.class.typus_date_format(attribute)
187
+ value = !item.send(attribute).nil? ? item.send(attribute).to_s(date_format) : item.class.typus_options_for(:nil)
188
+ content = if first_field == attribute
189
+ link_to value, link_options.merge(:controller => "admin/#{item.class.name.tableize}", :action => action, :id => item.id )
190
+ else
191
+ value
192
+ end
193
+
194
+ <<-HTML
195
+ <td>#{content}</td>
196
+ HTML
197
+
198
+ end
199
+
200
+ def typus_table_boolean_field(attribute, item)
201
+
202
+ boolean_icon = item.class.typus_options_for(:icon_on_boolean)
203
+ boolean_hash = item.class.typus_boolean(attribute)
204
+
205
+ status = item.send(attribute)
206
+
207
+ link_text = unless item.send(attribute).nil?
208
+ (boolean_icon) ? image_tag("admin/status_#{status}.gif") : boolean_hash["#{status}".to_sym]
209
+ else
210
+ item.class.typus_options_for(:nil) # Content is nil, so we show nil.
211
+ end
212
+
213
+ options = { :controller => item.class.name.tableize, :action => 'toggle', :field => attribute.gsub(/\?$/,''), :id => item.id }
214
+
215
+ content = if item.class.typus_options_for(:toggle) && !item.send(attribute).nil?
216
+ link_to link_text, params.merge(options), :confirm => _("Change {{attribute}}?", :attribute => item.class.human_attribute_name(attribute).downcase)
217
+ else
218
+ link_text
219
+ end
220
+
221
+ <<-HTML
222
+ <td align="center">#{content}</td>
223
+ HTML
224
+
225
+ end
226
+
227
+ end