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,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