fesplugas-typus 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. data/.gitignore +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +80 -0
  4. data/Rakefile +61 -0
  5. data/VERSION +1 -0
  6. data/app/controllers/admin/master_controller.rb +324 -0
  7. data/app/controllers/typus_controller.rb +127 -0
  8. data/app/helpers/admin/form_helper.rb +351 -0
  9. data/app/helpers/admin/master_helper.rb +99 -0
  10. data/app/helpers/admin/public_helper.rb +24 -0
  11. data/app/helpers/admin/sidebar_helper.rb +259 -0
  12. data/app/helpers/admin/table_helper.rb +227 -0
  13. data/app/helpers/typus_helper.rb +169 -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 +29 -0
  18. data/app/views/admin/resources/index.html.erb +28 -0
  19. data/app/views/admin/resources/new.html.erb +27 -0
  20. data/app/views/admin/resources/show.html.erb +21 -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 +72 -0
  24. data/app/views/layouts/typus.html.erb +29 -0
  25. data/app/views/typus/dashboard.html.erb +13 -0
  26. data/app/views/typus/recover_password.html.erb +7 -0
  27. data/app/views/typus/reset_password.html.erb +13 -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/es.yml +106 -0
  32. data/config/locales/pt-BR.yml +108 -0
  33. data/config/locales/typus_hacks.yml +14 -0
  34. data/config/routes.rb +14 -0
  35. data/generators/typus/templates/config/initializers/typus.rb +27 -0
  36. data/generators/typus/templates/config/typus/application.yml +45 -0
  37. data/generators/typus/templates/config/typus/application_roles.yml +23 -0
  38. data/generators/typus/templates/config/typus/typus.yml +14 -0
  39. data/generators/typus/templates/config/typus/typus_roles.yml +2 -0
  40. data/generators/typus/templates/db/create_typus_users.rb +21 -0
  41. data/generators/typus/templates/public/images/admin/arrow_down.gif +0 -0
  42. data/generators/typus/templates/public/images/admin/arrow_up.gif +0 -0
  43. data/generators/typus/templates/public/images/admin/spinner.gif +0 -0
  44. data/generators/typus/templates/public/images/admin/status_false.gif +0 -0
  45. data/generators/typus/templates/public/images/admin/status_true.gif +0 -0
  46. data/generators/typus/templates/public/images/admin/trash.gif +0 -0
  47. data/generators/typus/templates/public/javascripts/admin/application.js +14 -0
  48. data/generators/typus/templates/public/stylesheets/admin/reset.css +68 -0
  49. data/generators/typus/templates/public/stylesheets/admin/screen.css +709 -0
  50. data/generators/typus/typus_generator.rb +141 -0
  51. data/generators/typus_update_schema_to_01/templates/config/typus.yml +14 -0
  52. data/generators/typus_update_schema_to_01/templates/migration.rb +11 -0
  53. data/generators/typus_update_schema_to_01/typus_update_schema_to_01_generator.rb +19 -0
  54. data/init.rb +19 -0
  55. data/lib/typus/active_record.rb +298 -0
  56. data/lib/typus/authentication.rb +155 -0
  57. data/lib/typus/configuration.rb +92 -0
  58. data/lib/typus/format.rb +56 -0
  59. data/lib/typus/generator.rb +173 -0
  60. data/lib/typus/hash.rb +10 -0
  61. data/lib/typus/locale.rb +17 -0
  62. data/lib/typus/object.rb +22 -0
  63. data/lib/typus/quick_edit.rb +33 -0
  64. data/lib/typus/reloader.rb +17 -0
  65. data/lib/typus/string.rb +11 -0
  66. data/lib/typus/user.rb +137 -0
  67. data/lib/typus.rb +133 -0
  68. data/lib/vendor/active_record.rb +15 -0
  69. data/lib/vendor/paginator.rb +143 -0
  70. data/tasks/typus_tasks.rake +26 -0
  71. data/test/config/broken/application.yml +68 -0
  72. data/test/config/broken/application_roles.yml +20 -0
  73. data/test/config/broken/empty.yml +0 -0
  74. data/test/config/broken/empty_roles.yml +0 -0
  75. data/test/config/broken/undefined.yml +3 -0
  76. data/test/config/broken/undefined_roles.yml +6 -0
  77. data/test/config/default/typus.yml +14 -0
  78. data/test/config/default/typus_roles.yml +2 -0
  79. data/test/config/empty/empty_01.yml +0 -0
  80. data/test/config/empty/empty_01_roles.yml +0 -0
  81. data/test/config/empty/empty_02.yml +0 -0
  82. data/test/config/empty/empty_02_roles.yml +0 -0
  83. data/test/config/locales/es.yml +10 -0
  84. data/test/config/ordered/001_roles.yml +2 -0
  85. data/test/config/ordered/002_roles.yml +2 -0
  86. data/test/config/unordered/app_one_roles.yml +2 -0
  87. data/test/config/unordered/app_two_roles.yml +2 -0
  88. data/test/config/working/application.yml +67 -0
  89. data/test/config/working/application_roles.yml +22 -0
  90. data/test/config/working/typus.yml +14 -0
  91. data/test/config/working/typus_roles.yml +2 -0
  92. data/test/fixtures/app/controllers/admin/assets_controller.rb +2 -0
  93. data/test/fixtures/app/controllers/admin/categories_controller.rb +2 -0
  94. data/test/fixtures/app/controllers/admin/comments_controller.rb +2 -0
  95. data/test/fixtures/app/controllers/admin/pages_controller.rb +2 -0
  96. data/test/fixtures/app/controllers/admin/posts_controller.rb +2 -0
  97. data/test/fixtures/app/controllers/admin/status_controller.rb +6 -0
  98. data/test/fixtures/app/controllers/admin/typus_users_controller.rb +2 -0
  99. data/test/fixtures/app/controllers/admin/watch_dog_controller.rb +6 -0
  100. data/test/fixtures/app/views/admin/comments/_edit_bottom.html.erb +1 -0
  101. data/test/fixtures/app/views/admin/comments/_edit_sidebar.html.erb +1 -0
  102. data/test/fixtures/app/views/admin/comments/_edit_top.html.erb +1 -0
  103. data/test/fixtures/app/views/admin/comments/_index_bottom.html.erb +1 -0
  104. data/test/fixtures/app/views/admin/comments/_index_sidebar.html.erb +1 -0
  105. data/test/fixtures/app/views/admin/comments/_index_top.html.erb +1 -0
  106. data/test/fixtures/app/views/admin/comments/_new_bottom.html.erb +1 -0
  107. data/test/fixtures/app/views/admin/comments/_new_sidebar.html.erb +1 -0
  108. data/test/fixtures/app/views/admin/comments/_new_top.html.erb +1 -0
  109. data/test/fixtures/app/views/admin/comments/_show_bottom.html.erb +1 -0
  110. data/test/fixtures/app/views/admin/comments/_show_sidebar.html.erb +1 -0
  111. data/test/fixtures/app/views/admin/comments/_show_top.html.erb +1 -0
  112. data/test/fixtures/app/views/admin/dashboard/_bottom.html.erb +1 -0
  113. data/test/fixtures/app/views/admin/dashboard/_sidebar.html.erb +1 -0
  114. data/test/fixtures/app/views/admin/dashboard/_top.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 +121 -0
  127. data/test/functional/admin/master_controller_test.rb +5 -0
  128. data/test/functional/admin/posts_controller_test.rb +278 -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 +315 -0
  132. data/test/helper.rb +51 -0
  133. data/test/helpers/admin/form_helper_test.rb +316 -0
  134. data/test/helpers/admin/master_helper_test.rb +65 -0
  135. data/test/helpers/admin/public_helper_test.rb +22 -0
  136. data/test/helpers/admin/sidebar_helper_test.rb +351 -0
  137. data/test/helpers/admin/table_helper_test.rb +255 -0
  138. data/test/helpers/typus_helper_test.rb +106 -0
  139. data/test/lib/active_record_test.rb +372 -0
  140. data/test/lib/configuration_test.rb +91 -0
  141. data/test/lib/hash_test.rb +11 -0
  142. data/test/lib/routes_test.rb +82 -0
  143. data/test/lib/string_test.rb +25 -0
  144. data/test/lib/typus_test.rb +105 -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 +138 -0
  153. data/typus.gemspec +225 -0
  154. metadata +241 -0
@@ -0,0 +1,259 @@
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
+ %w( parent_module submodules ).each do |block|
17
+ html << <<-HTML
18
+ #{build_typus_list(modules(block), :header => block)}
19
+ HTML
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+
26
+ def default_actions
27
+
28
+ items = []
29
+
30
+ case params[:action]
31
+ when 'index', 'edit', 'show', 'update'
32
+ if @current_user.can_perform?(@resource[:class], 'create')
33
+ items << (link_to _('Add entry'), :action => 'new')
34
+ end
35
+ end
36
+
37
+ case params[:action]
38
+ when 'show'
39
+ if @current_user.can_perform?(@resource[:class], 'update')
40
+ items << (link_to _('Edit entry'), :action => 'edit', :id => @item.id)
41
+ end
42
+ end
43
+
44
+ @resource[:class].typus_actions_for(params[:action]).each do |action|
45
+ if @current_user.can_perform?(@resource[:class], action)
46
+ items << (link_to action.humanize, params.merge(:action => action))
47
+ end
48
+ end
49
+
50
+ case params[:action]
51
+ when 'new', 'create', 'edit', 'show', 'update'
52
+ items << (link_to _('Back to list'), :action => 'index')
53
+ end
54
+
55
+ return items
56
+
57
+ end
58
+
59
+ def export
60
+ return [] unless params[:action] == 'index'
61
+ returning(Array.new) do |format|
62
+ @resource[:class].typus_export_formats.each do |f|
63
+ format << (link_to f.upcase, params.merge(:format => f))
64
+ end
65
+ end
66
+ end
67
+
68
+ def build_typus_list(items, *args)
69
+
70
+ options = args.extract_options!
71
+
72
+ header = if options[:header]
73
+ _(options[:header].humanize)
74
+ elsif options[:attribute]
75
+ @resource[:class].human_attribute_name(options[:attribute])
76
+ end
77
+
78
+ return String.new if items.empty?
79
+ returning(String.new) do |html|
80
+ html << "<h2>#{header}</h2>\n" unless header.nil?
81
+ next unless options[:selector].nil?
82
+ html << "<ul>\n"
83
+ items.each do |item|
84
+ html << "<li>#{item}</li>\n"
85
+ end
86
+ html << "</ul>\n"
87
+ end
88
+
89
+ end
90
+
91
+ def modules(name)
92
+
93
+ models = case name
94
+ when 'parent_module': Typus.parent(@resource[:class], 'module')
95
+ when 'submodules': Typus.module(@resource[:class])
96
+ end
97
+
98
+ return [] if models.empty?
99
+
100
+ returning(Array.new) do |items|
101
+ models.each do |model|
102
+ items << (link_to model.humanize, :controller => model.tableize)
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ def previous_and_next
109
+ return [] unless %w( edit show update ).include?(params[:action])
110
+ returning(Array.new) do |items|
111
+ items << (link_to _('Next'), params.merge(:id => @next.id)) if @next
112
+ items << (link_to _('Previous'), params.merge(:id => @previous.id)) if @previous
113
+ end
114
+ end
115
+
116
+ def search
117
+
118
+ typus_search = @resource[:class].typus_defaults_for(:search)
119
+ return if typus_search.empty?
120
+
121
+ search_by = typus_search.collect { |x| @resource[:class].human_attribute_name(x) }.to_sentence
122
+
123
+ search_params = params.dup
124
+ %w( action controller search page ).each { |p| search_params.delete(p) }
125
+
126
+ hidden_params = search_params.map { |key, value| hidden_field_tag(key, value) }
127
+
128
+ <<-HTML
129
+ <h2>#{_('Search')}</h2>
130
+ <form action="" method="get">
131
+ <p><input id="search" name="search" type="text" value="#{params[:search]}"/></p>
132
+ #{hidden_params.sort.join("\n")}
133
+ </form>
134
+ <p class="tip">#{_('Search by')} #{search_by.downcase}.</p>
135
+ HTML
136
+
137
+ end
138
+
139
+ def filters
140
+
141
+ typus_filters = @resource[:class].typus_filters
142
+ return if typus_filters.empty?
143
+
144
+ current_request = request.env['QUERY_STRING'] || []
145
+
146
+ returning(String.new) do |html|
147
+ typus_filters.each do |key, value|
148
+ case value
149
+ when :boolean: html << boolean_filter(current_request, key)
150
+ when :string: html << string_filter(current_request, key)
151
+ when :datetime: html << datetime_filter(current_request, key)
152
+ when :belongs_to: html << relationship_filter(current_request, key)
153
+ when :has_and_belongs_to_many:
154
+ html << relationship_filter(current_request, key, true)
155
+ else
156
+ html << "<p>#{_('Unknown')}</p>"
157
+ end
158
+ end
159
+ end
160
+
161
+ end
162
+
163
+ def relationship_filter(request, filter, habtm = false)
164
+
165
+ model = (habtm) ? filter.classify.constantize : filter.capitalize.camelize.constantize
166
+ related_fk = (habtm) ? filter : @resource[:class].reflect_on_association(filter.to_sym).primary_key_name
167
+
168
+ params_without_filter = params.dup
169
+ %w( controller action page ).each { |p| params_without_filter.delete(p) }
170
+ params_without_filter.delete(related_fk)
171
+
172
+ items = []
173
+
174
+ returning(String.new) do |html|
175
+ related_items = model.find(:all, :order => model.typus_order_by)
176
+ if related_items.size > model.typus_options_for(:sidebar_selector)
177
+ related_items.each do |item|
178
+ switch = request.include?("#{related_fk}=#{item.id}") ? 'selected' : ''
179
+ items << <<-HTML
180
+ <option #{switch} value="#{url_for params.merge(related_fk => item.id, :page => nil)}">#{item.typus_name}</option>
181
+ HTML
182
+ end
183
+ model_pluralized = model.name.downcase.pluralize
184
+ form = <<-HTML
185
+ <!-- Embedded JS -->
186
+ <script>
187
+ function surfto_#{model_pluralized}(form) {
188
+ var myindex = form.#{model_pluralized}.selectedIndex
189
+ if (form.#{model_pluralized}.options[myindex].value != "0") {
190
+ top.location.href = form.#{model_pluralized}.options[myindex].value;
191
+ }
192
+ }
193
+ </script>
194
+ <!-- /Embedded JS -->
195
+ <p><form class="form" action="#">
196
+ <select name="#{model_pluralized}" onChange="surfto_#{model_pluralized}(this.form)">
197
+ <option value="#{url_for params_without_filter}">#{_('filter by')} #{_(model.human_name)}</option>
198
+ #{items.join("\n")}
199
+ </select>
200
+ </form></p>
201
+ HTML
202
+ else
203
+ related_items.each do |item|
204
+ switch = request.include?("#{related_fk}=#{item.id}") ? 'on' : 'off'
205
+ items << (link_to item.typus_name, params.merge(related_fk => item.id, :page => nil), :class => switch)
206
+ end
207
+ end
208
+
209
+ if form
210
+ html << build_typus_list(items, :attribute => filter, :selector => true)
211
+ html << form
212
+ else
213
+ html << build_typus_list(items, :attribute => filter)
214
+ end
215
+
216
+ end
217
+
218
+ end
219
+
220
+ ##
221
+ # Thinking in update datetime_filters to ...
222
+ #
223
+ # %w( today last_few_days last_7_days last_30_days )
224
+ #
225
+ # ... which are the ones used by 'exception_logger'.
226
+ #
227
+ def datetime_filter(request, filter)
228
+ items = []
229
+ %w( today past_7_days this_month this_year ).each do |timeline|
230
+ switch = request.include?("#{filter}=#{timeline}") ? 'on' : 'off'
231
+ options = { filter.to_sym => timeline, :page => nil }
232
+ items << (link_to _(timeline.humanize), params.merge(options), :class => switch)
233
+ end
234
+ build_typus_list(items, :attribute => filter)
235
+ end
236
+
237
+ def boolean_filter(request, filter)
238
+ items = []
239
+ @resource[:class].typus_boolean(filter).each do |key, value|
240
+ switch = request.include?("#{filter}=#{key}") ? 'on' : 'off'
241
+ options = { filter.to_sym => key, :page => nil }
242
+ items << (link_to _(value), params.merge(options), :class => switch)
243
+ end
244
+ build_typus_list(items, :attribute => filter)
245
+ end
246
+
247
+ def string_filter(request, filter)
248
+ values = @resource[:class].send(filter)
249
+ items = []
250
+ values.each do |item|
251
+ link_name, link_filter = (values.first.kind_of?(Array)) ? [ item.first, item.last ] : [ item, item ]
252
+ switch = request.include?("#{filter}=#{link_filter}") ? 'on' : 'off'
253
+ options = { filter.to_sym => link_filter, :page => nil }
254
+ items << (link_to link_name.capitalize, params.merge(options), :class => switch)
255
+ end
256
+ build_typus_list(items, :attribute => filter)
257
+ end
258
+
259
+ 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>
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: html << typus_table_boolean_field(key, item)
22
+ when :datetime: html << typus_table_datetime_field(key, item, fields.keys.first, link_options)
23
+ when :date: html << typus_table_datetime_field(key, item, fields.keys.first, link_options)
24
+ when :time: html << typus_table_datetime_field(key, item, fields.keys.first, link_options)
25
+ when :belongs_to: html << typus_table_belongs_to_field(key, item)
26
+ when :tree: html << typus_table_tree_field(key, item)
27
+ when :position: html << typus_table_position_field(key, item)
28
+ when :has_and_belongs_to_many:
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.human_name,
59
+ :unrelate_model_from => @resource[:class].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': 'desc'
94
+ when 'desc': '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, :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
@@ -0,0 +1,169 @@
1
+ module TypusHelper
2
+
3
+ ##
4
+ # Applications list on the dashboard
5
+ #
6
+ def applications
7
+
8
+ returning(String.new) do |html|
9
+
10
+ Typus.applications.each do |app|
11
+
12
+ available = Typus.application(app).map do |resource|
13
+ resource if @current_user.resources.include?(resource)
14
+ end
15
+ next if available.compact.empty?
16
+
17
+ html << <<-HTML
18
+ <table>
19
+ <tr>
20
+ <th colspan="2">#{app}</th>
21
+ </tr>
22
+ HTML
23
+
24
+ available.compact.each do |model|
25
+ description = Typus.module_description(model)
26
+ admin_items_path = { :controller => "admin/#{model.tableize}" }
27
+ new_admin_item_path = { :controller => "admin/#{model.tableize}", :action => 'new'}
28
+ html << <<-HTML
29
+ <tr class="#{cycle('even', 'odd')}">
30
+ <td>#{link_to _(model.constantize.human_name.pluralize), admin_items_path}<br /><small>#{description}</small></td>
31
+ <td class="right"><small>
32
+ #{link_to _('Add'), new_admin_item_path if @current_user.can_perform?(model, 'create')}
33
+ </small></td>
34
+ </tr>
35
+ HTML
36
+ end
37
+
38
+ html << <<-HTML
39
+ </table>
40
+ HTML
41
+
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+
48
+ ##
49
+ # Resources (wich are not models) on the dashboard.
50
+ #
51
+ def resources
52
+
53
+ available = Typus.resources.map do |resource|
54
+ resource if @current_user.resources.include?(resource)
55
+ end
56
+ return if available.compact.empty?
57
+
58
+ returning(String.new) do |html|
59
+
60
+ html << <<-HTML
61
+ <table>
62
+ <tr>
63
+ <th colspan="2">#{_("Resources")}</th>
64
+ </tr>
65
+ HTML
66
+
67
+ available.compact.each do |resource|
68
+
69
+ resource_path = { :controller => "admin/#{resource.underscore}" }
70
+
71
+ html << <<-HTML
72
+ <tr class="#{cycle('even', 'odd')}">
73
+ <td>#{link_to _(resource.humanize), resource_path}</td>
74
+ <td align="right" style="vertical-align: bottom;"></td>
75
+ </tr>
76
+ HTML
77
+
78
+ end
79
+
80
+ html << <<-HTML
81
+ </table>
82
+ HTML
83
+
84
+ end
85
+
86
+ end
87
+
88
+ def typus_block(*args)
89
+
90
+ options = args.extract_options!
91
+ template = [ 'admin', options[:resource], options[:location], "_#{options[:partial]}.html.erb" ].compact.join('/')
92
+
93
+ exists = ActionController::Base.view_paths.map { |vp| File.exists?("#{vp}/#{template}") }
94
+
95
+ return unless exists.include?(true)
96
+ render :partial => template.gsub('/_', '/')
97
+
98
+ end
99
+
100
+ def page_title(action = params[:action])
101
+ crumbs = [ Typus::Configuration.options[:app_name] ]
102
+ crumbs << @resource[:class].human_name.pluralize if @resource
103
+ crumbs << _(action.humanize) unless %w( index ).include?(action)
104
+ return crumbs.compact.map { |x| x }.join(' &rsaquo; ')
105
+ end
106
+
107
+ def header
108
+
109
+ if ActionController::Routing::Routes.named_routes.routes.keys.include?(:root)
110
+ link_to_site = <<-HTML
111
+ <small>#{link_to _('View site'), root_path, :target => 'blank'}</small>
112
+ HTML
113
+ end
114
+
115
+ <<-HTML
116
+ <h1>#{Typus::Configuration.options[:app_name]} #{link_to_site}</h1>
117
+ HTML
118
+
119
+ end
120
+
121
+ def login_info(user = @current_user)
122
+
123
+ admin_edit_typus_user_path = { :controller => "admin/#{Typus::Configuration.options[:user_class_name].tableize}",
124
+ :action => 'edit',
125
+ :id => user.id }
126
+
127
+ <<-HTML
128
+ <ul>
129
+ <li>#{_('Logged as')} #{link_to user.full_name(:display_role => true), admin_edit_typus_user_path}</li>
130
+ <li>#{link_to _('Sign out'), admin_sign_out_path }</li>
131
+ </ul>
132
+ HTML
133
+
134
+ end
135
+
136
+ def display_flash_message(message = flash)
137
+
138
+ return if message.empty?
139
+ flash_type = message.keys.first
140
+
141
+ <<-HTML
142
+ <div id="flash" class="#{flash_type}">
143
+ <p>#{message[flash_type]}</p>
144
+ </div>
145
+ HTML
146
+
147
+ end
148
+
149
+ def typus_message(message, html_class = 'notice')
150
+ <<-HTML
151
+ <div id="flash" class="#{html_class}">
152
+ <p>#{message}</p>
153
+ </div>
154
+ HTML
155
+ end
156
+
157
+ def locales(uri = admin_set_locale_path)
158
+
159
+ return unless Typus.locales.many?
160
+
161
+ locale_links = Typus.locales.map { |l| "<a href=\"#{uri}?locale=#{l.last}\">#{l.first.downcase}</a>" }
162
+
163
+ <<-HTML
164
+ <p>#{_('Set language to')} #{locale_links.join(', ')}.</p>
165
+ HTML
166
+
167
+ end
168
+
169
+ end
@@ -0,0 +1,14 @@
1
+ class TypusMailer < ActionMailer::Base
2
+
3
+ self.template_root = "#{File.dirname(__FILE__)}/../views"
4
+
5
+ def reset_password_link(user)
6
+ @subject = "[#{Typus::Configuration.options[:app_name]}] #{_('Reset password')}"
7
+ @body = { :user => user }
8
+ @recipients = user.email
9
+ @from = Typus::Configuration.options[:email]
10
+ @sent_on = Time.now
11
+ @headers = {}
12
+ end
13
+
14
+ end
@@ -0,0 +1,5 @@
1
+ class TypusUser < ActiveRecord::Base
2
+
3
+ enable_as_typus_user
4
+
5
+ end
@@ -0,0 +1,9 @@
1
+ <h2>Welcome to Typus!</h2>
2
+
3
+ <p>Documentation is available <a href="http://intraducibles.com/projects/typus">here</a>.</p>
4
+
5
+ <p>If you need help don't hesitate in joining the <a href="http://groups.google.com/group/typus" rel="external">Typus</a> mailing list.</p>
6
+
7
+ <p>Replace this message adding a <code>_sidebar.html.erb</code> file on the <code>app/views/admin/dashboard</code> folder.</p>
8
+
9
+ <p>Have a nice day!</p>