Commit 4ef79c2dbe9eb60b91a367e48cfb5a4bcc0f7834
Exists in
master
and in
29 other branches
Merge branch 'master' into move-article-folder
Conflicts: app/helpers/forms_helper.rb
Showing
159 changed files
with
5612 additions
and
622 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 159 files displayed.
app/controllers/application_controller.rb
@@ -114,7 +114,9 @@ class ApplicationController < ActionController::Base | @@ -114,7 +114,9 @@ class ApplicationController < ActionController::Base | ||
114 | # plugin to the current controller being initialized. | 114 | # plugin to the current controller being initialized. |
115 | def init_noosfero_plugins_controller_filters | 115 | def init_noosfero_plugins_controller_filters |
116 | plugins.each do |plugin| | 116 | plugins.each do |plugin| |
117 | - plugin.send(self.class.name.underscore + '_filters').each do |plugin_filter| | 117 | + filters = plugin.send(self.class.name.underscore + '_filters') |
118 | + filters = [filters] if !filters.kind_of?(Array) | ||
119 | + filters.each do |plugin_filter| | ||
118 | self.class.send(plugin_filter[:type], plugin.class.name.underscore + '_' + plugin_filter[:method_name], (plugin_filter[:options] || {})) | 120 | self.class.send(plugin_filter[:type], plugin.class.name.underscore + '_' + plugin_filter[:method_name], (plugin_filter[:options] || {})) |
119 | self.class.send(:define_method, plugin.class.name.underscore + '_' + plugin_filter[:method_name], plugin_filter[:block]) | 121 | self.class.send(:define_method, plugin.class.name.underscore + '_' + plugin_filter[:method_name], plugin_filter[:block]) |
120 | end | 122 | end |
app/controllers/box_organizer_controller.rb
@@ -68,7 +68,8 @@ class BoxOrganizerController < ApplicationController | @@ -68,7 +68,8 @@ class BoxOrganizerController < ApplicationController | ||
68 | raise ArgumentError.new("Type %s is not allowed. Go away." % type) | 68 | raise ArgumentError.new("Type %s is not allowed. Go away." % type) |
69 | end | 69 | end |
70 | else | 70 | else |
71 | - @block_types = available_blocks | 71 | + @center_block_types = Box.acceptable_center_blocks & available_blocks |
72 | + @side_block_types = Box.acceptable_side_blocks & available_blocks | ||
72 | @boxes = boxes_holder.boxes | 73 | @boxes = boxes_holder.boxes |
73 | render :action => 'add_block', :layout => false | 74 | render :action => 'add_block', :layout => false |
74 | end | 75 | end |
app/controllers/my_profile/profile_design_controller.rb
@@ -5,7 +5,7 @@ class ProfileDesignController < BoxOrganizerController | @@ -5,7 +5,7 @@ class ProfileDesignController < BoxOrganizerController | ||
5 | protect 'edit_profile_design', :profile | 5 | protect 'edit_profile_design', :profile |
6 | 6 | ||
7 | def available_blocks | 7 | def available_blocks |
8 | - blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock ] | 8 | + blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ] |
9 | 9 | ||
10 | # blocks exclusive for organizations | 10 | # blocks exclusive for organizations |
11 | if profile.has_members? | 11 | if profile.has_members? |
app/controllers/public/account_controller.rb
@@ -25,11 +25,13 @@ class AccountController < ApplicationController | @@ -25,11 +25,13 @@ class AccountController < ApplicationController | ||
25 | 25 | ||
26 | # action to perform login to the application | 26 | # action to perform login to the application |
27 | def login | 27 | def login |
28 | - @user = User.new | ||
29 | - @person = @user.build_person | ||
30 | store_location(request.referer) unless session[:return_to] | 28 | store_location(request.referer) unless session[:return_to] |
31 | return unless request.post? | 29 | return unless request.post? |
32 | - self.current_user = User.authenticate(params[:user][:login], params[:user][:password], environment) if params[:user] | 30 | + |
31 | + self.current_user = plugins_alternative_authentication | ||
32 | + | ||
33 | + self.current_user ||= User.authenticate(params[:user][:login], params[:user][:password], environment) if params[:user] | ||
34 | + | ||
33 | if logged_in? | 35 | if logged_in? |
34 | if params[:remember_me] == "1" | 36 | if params[:remember_me] == "1" |
35 | self.current_user.remember_me | 37 | self.current_user.remember_me |
@@ -41,7 +43,6 @@ class AccountController < ApplicationController | @@ -41,7 +43,6 @@ class AccountController < ApplicationController | ||
41 | end | 43 | end |
42 | else | 44 | else |
43 | session[:notice] = _('Incorrect username or password') if redirect? | 45 | session[:notice] = _('Incorrect username or password') if redirect? |
44 | - redirect_to :back if redirect? | ||
45 | end | 46 | end |
46 | end | 47 | end |
47 | 48 | ||
@@ -56,6 +57,11 @@ class AccountController < ApplicationController | @@ -56,6 +57,11 @@ class AccountController < ApplicationController | ||
56 | 57 | ||
57 | # action to register an user to the application | 58 | # action to register an user to the application |
58 | def signup | 59 | def signup |
60 | + if @plugins.dispatch(:allow_user_registration).include?(false) | ||
61 | + redirect_back_or_default(:controller => 'home') | ||
62 | + session[:notice] = _("This environment doesn't allow user registration.") | ||
63 | + end | ||
64 | + | ||
59 | @invitation_code = params[:invitation_code] | 65 | @invitation_code = params[:invitation_code] |
60 | begin | 66 | begin |
61 | if params[:user] | 67 | if params[:user] |
@@ -125,6 +131,10 @@ class AccountController < ApplicationController | @@ -125,6 +131,10 @@ class AccountController < ApplicationController | ||
125 | # | 131 | # |
126 | # Posts back. | 132 | # Posts back. |
127 | def forgot_password | 133 | def forgot_password |
134 | + if @plugins.dispatch(:allow_password_recovery).include?(false) | ||
135 | + redirect_back_or_default(:controller => 'home') | ||
136 | + session[:notice] = _("This environment doesn't allow password recovery.") | ||
137 | + end | ||
128 | @change_password = ChangePassword.new(params[:change_password]) | 138 | @change_password = ChangePassword.new(params[:change_password]) |
129 | 139 | ||
130 | if request.post? | 140 | if request.post? |
@@ -316,4 +326,13 @@ class AccountController < ApplicationController | @@ -316,4 +326,13 @@ class AccountController < ApplicationController | ||
316 | end | 326 | end |
317 | end | 327 | end |
318 | 328 | ||
329 | + def plugins_alternative_authentication | ||
330 | + user = nil | ||
331 | + @plugins.each do |plugin| | ||
332 | + user = plugin.alternative_authentication | ||
333 | + break unless user.nil? | ||
334 | + end | ||
335 | + user | ||
336 | + end | ||
337 | + | ||
319 | end | 338 | end |
app/controllers/public/content_viewer_controller.rb
@@ -2,6 +2,8 @@ class ContentViewerController < ApplicationController | @@ -2,6 +2,8 @@ class ContentViewerController < ApplicationController | ||
2 | 2 | ||
3 | needs_profile | 3 | needs_profile |
4 | 4 | ||
5 | + before_filter :comment_author, :only => :edit_comment | ||
6 | + | ||
5 | helper ProfileHelper | 7 | helper ProfileHelper |
6 | helper TagsHelper | 8 | helper TagsHelper |
7 | 9 | ||
@@ -121,6 +123,27 @@ class ContentViewerController < ApplicationController | @@ -121,6 +123,27 @@ class ContentViewerController < ApplicationController | ||
121 | end | 123 | end |
122 | end | 124 | end |
123 | 125 | ||
126 | + def edit_comment | ||
127 | + path = params[:page].join('/') | ||
128 | + @page = profile.articles.find_by_path(path) | ||
129 | + @form_div = 'opened' | ||
130 | + @comment = @page.comments.find_by_id(params[:id]) | ||
131 | + if @comment | ||
132 | + if request.post? | ||
133 | + begin | ||
134 | + @comment.update_attributes(params[:comment]) | ||
135 | + session[:notice] = _('Comment succesfully updated') | ||
136 | + redirect_to :action => 'view_page', :profile => profile.identifier, :page => @comment.article.explode_path | ||
137 | + rescue | ||
138 | + session[:notice] = _('Comment could not be updated') | ||
139 | + end | ||
140 | + end | ||
141 | + else | ||
142 | + redirect_to @page.view_url | ||
143 | + session[:notice] = _('Could not find the comment in the article') | ||
144 | + end | ||
145 | + end | ||
146 | + | ||
124 | protected | 147 | protected |
125 | 148 | ||
126 | def add_comment | 149 | def add_comment |
@@ -198,4 +221,13 @@ class ContentViewerController < ApplicationController | @@ -198,4 +221,13 @@ class ContentViewerController < ApplicationController | ||
198 | end | 221 | end |
199 | end | 222 | end |
200 | 223 | ||
224 | + def comment_author | ||
225 | + comment = Comment.find_by_id(params[:id]) | ||
226 | + if comment | ||
227 | + render_access_denied if comment.author.blank? || comment.author != user | ||
228 | + else | ||
229 | + render_not_found | ||
230 | + end | ||
231 | + end | ||
232 | + | ||
201 | end | 233 | end |
app/helpers/application_helper.rb
@@ -265,9 +265,9 @@ module ApplicationHelper | @@ -265,9 +265,9 @@ module ApplicationHelper | ||
265 | 265 | ||
266 | VIEW_EXTENSIONS = %w[.rhtml .html.erb] | 266 | VIEW_EXTENSIONS = %w[.rhtml .html.erb] |
267 | 267 | ||
268 | - def partial_for_class_in_view_path(klass, view_path) | 268 | + def partial_for_class_in_view_path(klass, view_path, suffix = nil) |
269 | return nil if klass.nil? | 269 | return nil if klass.nil? |
270 | - name = klass.name.underscore | 270 | + name = [klass.name.underscore, suffix].compact.map(&:to_s).join('_') |
271 | 271 | ||
272 | search_name = String.new(name) | 272 | search_name = String.new(name) |
273 | if search_name.include?("/") | 273 | if search_name.include?("/") |
@@ -285,28 +285,17 @@ module ApplicationHelper | @@ -285,28 +285,17 @@ module ApplicationHelper | ||
285 | partial_for_class_in_view_path(klass.superclass, view_path) | 285 | partial_for_class_in_view_path(klass.superclass, view_path) |
286 | end | 286 | end |
287 | 287 | ||
288 | - def partial_for_class(klass) | 288 | + def partial_for_class(klass, suffix=nil) |
289 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? | 289 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? |
290 | name = klass.name.underscore | 290 | name = klass.name.underscore |
291 | @controller.view_paths.each do |view_path| | 291 | @controller.view_paths.each do |view_path| |
292 | - partial = partial_for_class_in_view_path(klass, view_path) | 292 | + partial = partial_for_class_in_view_path(klass, view_path, suffix) |
293 | return partial if partial | 293 | return partial if partial |
294 | end | 294 | end |
295 | 295 | ||
296 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' | 296 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' |
297 | end | 297 | end |
298 | 298 | ||
299 | - def partial_for_task_class(klass, action) | ||
300 | - raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? | ||
301 | - | ||
302 | - name = "#{klass.name.underscore}_#{action.to_s}" | ||
303 | - VIEW_EXTENSIONS.each do |ext| | ||
304 | - return name if File.exists?(File.join(RAILS_ROOT, 'app', 'views', params[:controller], '_'+name+ext)) | ||
305 | - end | ||
306 | - | ||
307 | - partial_for_task_class(klass.superclass, action) | ||
308 | - end | ||
309 | - | ||
310 | def view_for_profile_actions(klass) | 299 | def view_for_profile_actions(klass) |
311 | raise ArgumentError, 'No profile actions view for this class.' if klass.nil? | 300 | raise ArgumentError, 'No profile actions view for this class.' if klass.nil? |
312 | 301 | ||
@@ -1323,6 +1312,19 @@ module ApplicationHelper | @@ -1323,6 +1312,19 @@ module ApplicationHelper | ||
1323 | end | 1312 | end |
1324 | end | 1313 | end |
1325 | 1314 | ||
1315 | + def expirable_link_to(expired, content, url, options = {}) | ||
1316 | + if expired | ||
1317 | + options[:class] = (options[:class] || '') + ' disabled' | ||
1318 | + content_tag('a', ' '+content_tag('span', content), options) | ||
1319 | + else | ||
1320 | + link_to content, url, options | ||
1321 | + end | ||
1322 | + end | ||
1323 | + | ||
1324 | + def remove_content_button(action) | ||
1325 | + @plugins.dispatch("content_remove_#{action.to_s}", @page).include?(true) | ||
1326 | + end | ||
1327 | + | ||
1326 | def template_options(klass, field_name) | 1328 | def template_options(klass, field_name) |
1327 | return '' if klass.templates.count == 0 | 1329 | return '' if klass.templates.count == 0 |
1328 | return hidden_field_tag("#{field_name}[template_id]", klass.templates.first.id) if klass.templates.count == 1 | 1330 | return hidden_field_tag("#{field_name}[template_id]", klass.templates.first.id) if klass.templates.count == 1 |
@@ -1388,4 +1390,19 @@ module ApplicationHelper | @@ -1388,4 +1390,19 @@ module ApplicationHelper | ||
1388 | result | 1390 | result |
1389 | end | 1391 | end |
1390 | 1392 | ||
1393 | + def expirable_content_reference(content, action, text, url, options = {}) | ||
1394 | + reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first | ||
1395 | + options[:title] = reason | ||
1396 | + expirable_link_to reason.present?, text, url, options | ||
1397 | + end | ||
1398 | + | ||
1399 | + def expirable_button(content, action, text, url, options = {}) | ||
1400 | + options[:class] = "button with-text icon-#{action.to_s}" | ||
1401 | + expirable_content_reference content, action, text, url, options | ||
1402 | + end | ||
1403 | + | ||
1404 | + def expirable_comment_link(content, action, text, url, options = {}) | ||
1405 | + options[:class] = "comment-footer comment-footer-link comment-footer-hide" | ||
1406 | + expirable_content_reference content, action, text, url, options | ||
1407 | + end | ||
1391 | end | 1408 | end |
app/helpers/boxes_helper.rb
@@ -162,9 +162,6 @@ module BoxesHelper | @@ -162,9 +162,6 @@ module BoxesHelper | ||
162 | # | 162 | # |
163 | # +box+ is always needed | 163 | # +box+ is always needed |
164 | def block_target(box, block = nil) | 164 | def block_target(box, block = nil) |
165 | - # FIXME hardcoded | ||
166 | - return '' if box.position == 1 | ||
167 | - | ||
168 | id = | 165 | id = |
169 | if block.nil? | 166 | if block.nil? |
170 | "end-of-box-#{box.id}" | 167 | "end-of-box-#{box.id}" |
@@ -172,14 +169,11 @@ module BoxesHelper | @@ -172,14 +169,11 @@ module BoxesHelper | ||
172 | "before-block-#{block.id}" | 169 | "before-block-#{block.id}" |
173 | end | 170 | end |
174 | 171 | ||
175 | - content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => 'block', :hoverclass => 'block-target-hover') | 172 | + content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover') |
176 | end | 173 | end |
177 | 174 | ||
178 | # makes the given block draggable so it can be moved away. | 175 | # makes the given block draggable so it can be moved away. |
179 | def block_handle(block) | 176 | def block_handle(block) |
180 | - # FIXME hardcoded | ||
181 | - return '' if block.box.position == 1 | ||
182 | - | ||
183 | draggable_element("block-#{block.id}", :revert => true) | 177 | draggable_element("block-#{block.id}", :revert => true) |
184 | end | 178 | end |
185 | 179 | ||
@@ -211,7 +205,7 @@ module BoxesHelper | @@ -211,7 +205,7 @@ module BoxesHelper | ||
211 | end | 205 | end |
212 | 206 | ||
213 | if block.editable? | 207 | if block.editable? |
214 | - buttons << lightbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) | 208 | + buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) |
215 | end | 209 | end |
216 | 210 | ||
217 | if !block.main? | 211 | if !block.main? |
app/helpers/cms_helper.rb
@@ -42,13 +42,25 @@ module CmsHelper | @@ -42,13 +42,25 @@ module CmsHelper | ||
42 | 42 | ||
43 | def display_spread_button(profile, article) | 43 | def display_spread_button(profile, article) |
44 | if profile.person? | 44 | if profile.person? |
45 | - button_without_text :spread, _('Spread this'), :action => 'publish', :id => article.id | 45 | + expirable_button article, :spread, _('Spread this'), :action => 'publish', :id => article.id |
46 | elsif profile.community? && environment.portal_community | 46 | elsif profile.community? && environment.portal_community |
47 | - button_without_text :spread, _('Spread this'), :action => 'publish_on_portal_community', :id => article.id | 47 | + expirable_button article, :spread, _('Spread this'), :action => 'publish_on_portal_community', :id => article.id |
48 | end | 48 | end |
49 | end | 49 | end |
50 | 50 | ||
51 | def display_delete_button(article) | 51 | def display_delete_button(article) |
52 | - button_without_text :delete, _('Delete'), { :action => 'destroy', :id => article.id }, :method => :post, :confirm => delete_article_message(article) | 52 | + expirable_button article, :delete, _('Delete'), { :action => 'destroy', :id => article.id }, :method => :post, :confirm => delete_article_message(article) |
53 | + end | ||
54 | + | ||
55 | + def expirable_button(content, action, title, url, options = {}) | ||
56 | + reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first | ||
57 | + if reason.present? | ||
58 | + options[:class] = (options[:class] || '') + ' disabled' | ||
59 | + options[:disabled] = 'disabled' | ||
60 | + options.delete(:confirm) | ||
61 | + options.delete(:method) | ||
62 | + title = reason | ||
63 | + end | ||
64 | + button_without_text action.to_sym, title, url, options | ||
53 | end | 65 | end |
54 | end | 66 | end |
app/helpers/colorbox_helper.rb
@@ -8,6 +8,10 @@ module ColorboxHelper | @@ -8,6 +8,10 @@ module ColorboxHelper | ||
8 | button(type, label, url, colorbox_options(options)) | 8 | button(type, label, url, colorbox_options(options)) |
9 | end | 9 | end |
10 | 10 | ||
11 | + def colorbox_icon_button(type, label, url, options = {}) | ||
12 | + icon_button(type, label, url, colorbox_options(options)) | ||
13 | + end | ||
14 | + | ||
11 | # options must be an HTML options hash as passed to link_to etc. | 15 | # options must be an HTML options hash as passed to link_to etc. |
12 | # | 16 | # |
13 | # returns a new hash with colorbox class added. Keeps existing classes. | 17 | # returns a new hash with colorbox class added. Keeps existing classes. |
app/helpers/forms_helper.rb
@@ -155,6 +155,119 @@ module FormsHelper | @@ -155,6 +155,119 @@ module FormsHelper | ||
155 | return result | 155 | return result |
156 | end | 156 | end |
157 | 157 | ||
158 | + def date_field(name, value, format = '%Y-%m-%d', datepicker_options = {}, html_options = {}) | ||
159 | + datepicker_options[:disabled] ||= false | ||
160 | + datepicker_options[:alt_field] ||= '' | ||
161 | + datepicker_options[:alt_format] ||= '' | ||
162 | + datepicker_options[:append_text] ||= '' | ||
163 | + datepicker_options[:auto_size] ||= false | ||
164 | + datepicker_options[:button_image] ||= '' | ||
165 | + datepicker_options[:button_image_only] ||= false | ||
166 | + datepicker_options[:button_text] ||= '...' | ||
167 | + datepicker_options[:calculate_week] ||= 'jQuery.datepicker.iso8601Week' | ||
168 | + datepicker_options[:change_month] ||= false | ||
169 | + datepicker_options[:change_year] ||= false | ||
170 | + datepicker_options[:close_text] ||= _('Done') | ||
171 | + datepicker_options[:constrain_input] ||= true | ||
172 | + datepicker_options[:current_text] ||= _('Today') | ||
173 | + datepicker_options[:date_format] ||= 'mm/dd/yy' | ||
174 | + datepicker_options[:day_names] ||= [_('Sunday'), _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday')] | ||
175 | + datepicker_options[:day_names_min] ||= [_('Su'), _('Mo'), _('Tu'), _('We'), _('Th'), _('Fr'), _('Sa')] | ||
176 | + datepicker_options[:day_names_short] ||= [_('Sun'), _('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat')] | ||
177 | + datepicker_options[:default_date] ||= nil | ||
178 | + datepicker_options[:duration] ||= 'normal' | ||
179 | + datepicker_options[:first_day] ||= 0 | ||
180 | + datepicker_options[:goto_current] ||= false | ||
181 | + datepicker_options[:hide_if_no_prev_next] ||= false | ||
182 | + datepicker_options[:is_rtl] ||= false | ||
183 | + datepicker_options[:max_date] ||= nil | ||
184 | + datepicker_options[:min_date] ||= nil | ||
185 | + datepicker_options[:month_names] ||= [_('January'), _('February'), _('March'), _('April'), _('May'), _('June'), _('July'), _('August'), _('September'), _('October'), _('November'), _('December')] | ||
186 | + datepicker_options[:month_names_short] ||= [_('Jan'), _('Feb'), _('Mar'), _('Apr'), _('May'), _('Jun'), _('Jul'), _('Aug'), _('Sep'), _('Oct'), _('Nov'), _('Dec')] | ||
187 | + datepicker_options[:navigation_as_date_format] ||= false | ||
188 | + datepicker_options[:next_text] ||= _('Next') | ||
189 | + datepicker_options[:number_of_months] ||= 1 | ||
190 | + datepicker_options[:prev_text] ||= _('Prev') | ||
191 | + datepicker_options[:select_other_months] ||= false | ||
192 | + datepicker_options[:short_year_cutoff] ||= '+10' | ||
193 | + datepicker_options[:show_button_panel] ||= false | ||
194 | + datepicker_options[:show_current_at_pos] ||= 0 | ||
195 | + datepicker_options[:show_month_after_year] ||= false | ||
196 | + datepicker_options[:show_on] ||= 'focus' | ||
197 | + datepicker_options[:show_options] ||= {} | ||
198 | + datepicker_options[:show_other_months] ||= false | ||
199 | + datepicker_options[:show_week] ||= false | ||
200 | + datepicker_options[:step_months] ||= 1 | ||
201 | + datepicker_options[:week_header] ||= _('Wk') | ||
202 | + datepicker_options[:year_range] ||= 'c-10:c+10' | ||
203 | + datepicker_options[:year_suffix] ||= '' | ||
204 | + | ||
205 | + element_id = html_options[:id] || 'datepicker-date' | ||
206 | + value = value.strftime(format) if value.present? | ||
207 | + method = datepicker_options[:time] ? 'datetimepicker' : 'datepicker' | ||
208 | + result = text_field_tag(name, value, html_options) | ||
209 | + result += | ||
210 | + " | ||
211 | + <script type='text/javascript'> | ||
212 | + jQuery('##{element_id}').#{method}({ | ||
213 | + disabled: #{datepicker_options[:disabled].to_json}, | ||
214 | + altField: #{datepicker_options[:alt_field].to_json}, | ||
215 | + altFormat: #{datepicker_options[:alt_format].to_json}, | ||
216 | + appendText: #{datepicker_options[:append_text].to_json}, | ||
217 | + autoSize: #{datepicker_options[:auto_size].to_json}, | ||
218 | + buttonImage: #{datepicker_options[:button_image].to_json}, | ||
219 | + buttonImageOnly: #{datepicker_options[:button_image_only].to_json}, | ||
220 | + buttonText: #{datepicker_options[:button_text].to_json}, | ||
221 | + calculateWeek: #{datepicker_options[:calculate_week].to_json}, | ||
222 | + changeMonth: #{datepicker_options[:change_month].to_json}, | ||
223 | + changeYear: #{datepicker_options[:change_year].to_json}, | ||
224 | + closeText: #{datepicker_options[:close_text].to_json}, | ||
225 | + constrainInput: #{datepicker_options[:constrain_input].to_json}, | ||
226 | + currentText: #{datepicker_options[:current_text].to_json}, | ||
227 | + dateFormat: #{datepicker_options[:date_format].to_json}, | ||
228 | + dayNames: #{datepicker_options[:day_names].to_json}, | ||
229 | + dayNamesMin: #{datepicker_options[:day_names_min].to_json}, | ||
230 | + dayNamesShort: #{datepicker_options[:day_names_short].to_json}, | ||
231 | + defaultDate: #{datepicker_options[:default_date].to_json}, | ||
232 | + duration: #{datepicker_options[:duration].to_json}, | ||
233 | + firstDay: #{datepicker_options[:first_day].to_json}, | ||
234 | + gotoCurrent: #{datepicker_options[:goto_current].to_json}, | ||
235 | + hideIfNoPrevNext: #{datepicker_options[:hide_if_no_prev_next].to_json}, | ||
236 | + isRTL: #{datepicker_options[:is_rtl].to_json}, | ||
237 | + maxDate: #{datepicker_options[:max_date].to_json}, | ||
238 | + minDate: #{datepicker_options[:min_date].to_json}, | ||
239 | + monthNames: #{datepicker_options[:month_names].to_json}, | ||
240 | + monthNamesShort: #{datepicker_options[:month_names_short].to_json}, | ||
241 | + navigationAsDateFormat: #{datepicker_options[:navigation_as_date_format].to_json}, | ||
242 | + nextText: #{datepicker_options[:next_text].to_json}, | ||
243 | + numberOfMonths: #{datepicker_options[:number_of_months].to_json}, | ||
244 | + prevText: #{datepicker_options[:prev_text].to_json}, | ||
245 | + selectOtherMonths: #{datepicker_options[:select_other_months].to_json}, | ||
246 | + shortYearCutoff: #{datepicker_options[:short_year_cutoff].to_json}, | ||
247 | + showButtonPanel: #{datepicker_options[:show_button_panel].to_json}, | ||
248 | + showCurrentAtPos: #{datepicker_options[:show_current_at_pos].to_json}, | ||
249 | + showMonthAfterYear: #{datepicker_options[:show_month_after_year].to_json}, | ||
250 | + showOn: #{datepicker_options[:show_on].to_json}, | ||
251 | + showOptions: #{datepicker_options[:show_options].to_json}, | ||
252 | + showOtherMonths: #{datepicker_options[:show_other_months].to_json}, | ||
253 | + showWeek: #{datepicker_options[:show_week].to_json}, | ||
254 | + stepMonths: #{datepicker_options[:step_months].to_json}, | ||
255 | + weekHeader: #{datepicker_options[:week_header].to_json}, | ||
256 | + yearRange: #{datepicker_options[:year_range].to_json}, | ||
257 | + yearSuffix: #{datepicker_options[:year_suffix].to_json} | ||
258 | + }) | ||
259 | + </script> | ||
260 | + " | ||
261 | + result | ||
262 | + end | ||
263 | + | ||
264 | + def date_range_field(from_name, to_name, from_value, to_value, format = '%Y-%m-%d', datepicker_options = {}, html_options = {}) | ||
265 | + from_id = html_options[:from_id] || 'datepicker-from-date' | ||
266 | + to_id = html_options[:to_id] || 'datepicker-to-date' | ||
267 | + return _('From') +' '+ date_field(from_name, from_value, format, datepicker_options, html_options.merge({:id => from_id})) + | ||
268 | + ' ' + _('until') +' '+ date_field(to_name, to_value, format, datepicker_options, html_options.merge({:id => to_id})) | ||
269 | + end | ||
270 | + | ||
158 | protected | 271 | protected |
159 | def self.next_id_number | 272 | def self.next_id_number |
160 | if defined? @@id_num | 273 | if defined? @@id_num |
app/models/box.rb
@@ -2,4 +2,76 @@ class Box < ActiveRecord::Base | @@ -2,4 +2,76 @@ class Box < ActiveRecord::Base | ||
2 | belongs_to :owner, :polymorphic => true | 2 | belongs_to :owner, :polymorphic => true |
3 | acts_as_list :scope => 'owner_id = #{owner_id} and owner_type = \'#{owner_type}\'' | 3 | acts_as_list :scope => 'owner_id = #{owner_id} and owner_type = \'#{owner_type}\'' |
4 | has_many :blocks, :dependent => :destroy, :order => 'position' | 4 | has_many :blocks, :dependent => :destroy, :order => 'position' |
5 | + | ||
6 | + def acceptable_blocks | ||
7 | + to_css_class_name central? ? Box.acceptable_center_blocks : Box.acceptable_side_blocks | ||
8 | + end | ||
9 | + | ||
10 | + def central? | ||
11 | + position == 1 | ||
12 | + end | ||
13 | + | ||
14 | + def self.acceptable_center_blocks | ||
15 | + [ ArticleBlock, | ||
16 | + BlogArchivesBlock, | ||
17 | + CategoriesBlock, | ||
18 | + CommunitiesBlock, | ||
19 | + EnterprisesBlock, | ||
20 | + EnvironmentStatisticsBlock, | ||
21 | + FansBlock, | ||
22 | + FavoriteEnterprisesBlock, | ||
23 | + FeedReaderBlock, | ||
24 | + FriendsBlock, | ||
25 | + HighlightsBlock, | ||
26 | + LinkListBlock, | ||
27 | + LoginBlock, | ||
28 | + MainBlock, | ||
29 | + MembersBlock, | ||
30 | + MyNetworkBlock, | ||
31 | + PeopleBlock, | ||
32 | + ProfileImageBlock, | ||
33 | + RawHTMLBlock, | ||
34 | + RecentDocumentsBlock, | ||
35 | + SellersSearchBlock, | ||
36 | + TagsBlock ] | ||
37 | + end | ||
38 | + | ||
39 | + def self.acceptable_side_blocks | ||
40 | + [ ArticleBlock, | ||
41 | + BlogArchivesBlock, | ||
42 | + CategoriesBlock, | ||
43 | + CommunitiesBlock, | ||
44 | + DisabledEnterpriseMessageBlock, | ||
45 | + EnterprisesBlock, | ||
46 | + EnvironmentStatisticsBlock, | ||
47 | + FansBlock, | ||
48 | + FavoriteEnterprisesBlock, | ||
49 | + FeaturedProductsBlock, | ||
50 | + FeedReaderBlock, | ||
51 | + FriendsBlock, | ||
52 | + HighlightsBlock, | ||
53 | + LinkListBlock, | ||
54 | + LocationBlock, | ||
55 | + LoginBlock, | ||
56 | + MembersBlock, | ||
57 | + MyNetworkBlock, | ||
58 | + PeopleBlock, | ||
59 | + ProductsBlock, | ||
60 | + ProfileImageBlock, | ||
61 | + ProfileInfoBlock, | ||
62 | + ProfileSearchBlock, | ||
63 | + RawHTMLBlock, | ||
64 | + RecentDocumentsBlock, | ||
65 | + SellersSearchBlock, | ||
66 | + SlideshowBlock, | ||
67 | + TagsBlock | ||
68 | + ] | ||
69 | + end | ||
70 | + | ||
71 | + private | ||
72 | + | ||
73 | + def to_css_class_name(blocks) | ||
74 | + blocks.map{ |block| block.to_s.underscore.tr('_', '-') } | ||
75 | + end | ||
76 | + | ||
5 | end | 77 | end |
app/models/comment.rb
@@ -28,6 +28,8 @@ class Comment < ActiveRecord::Base | @@ -28,6 +28,8 @@ class Comment < ActiveRecord::Base | ||
28 | 28 | ||
29 | xss_terminate :only => [ :body, :title, :name ], :on => 'validation' | 29 | xss_terminate :only => [ :body, :title, :name ], :on => 'validation' |
30 | 30 | ||
31 | + delegate :environment, :to => :source | ||
32 | + | ||
31 | def action_tracker_target | 33 | def action_tracker_target |
32 | self.article.profile | 34 | self.article.profile |
33 | end | 35 | end |
app/models/person.rb
@@ -71,10 +71,7 @@ class Person < Profile | @@ -71,10 +71,7 @@ class Person < Profile | ||
71 | Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy } | 71 | Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy } |
72 | end | 72 | end |
73 | 73 | ||
74 | - after_destroy :destroy_user | ||
75 | - def destroy_user | ||
76 | - self.user.destroy if self.user | ||
77 | - end | 74 | + belongs_to :user, :dependent => :delete |
78 | 75 | ||
79 | def can_control_scrap?(scrap) | 76 | def can_control_scrap?(scrap) |
80 | begin | 77 | begin |
app/models/task.rb
@@ -31,7 +31,7 @@ class Task < ActiveRecord::Base | @@ -31,7 +31,7 @@ class Task < ActiveRecord::Base | ||
31 | end | 31 | end |
32 | end | 32 | end |
33 | 33 | ||
34 | - belongs_to :requestor, :class_name => 'Person', :foreign_key => :requestor_id | 34 | + belongs_to :requestor, :class_name => 'Profile', :foreign_key => :requestor_id |
35 | belongs_to :target, :foreign_key => :target_id, :polymorphic => true | 35 | belongs_to :target, :foreign_key => :target_id, :polymorphic => true |
36 | 36 | ||
37 | validates_uniqueness_of :code, :on => :create | 37 | validates_uniqueness_of :code, :on => :create |
app/models/user.rb
@@ -30,7 +30,7 @@ class User < ActiveRecord::Base | @@ -30,7 +30,7 @@ class User < ActiveRecord::Base | ||
30 | 30 | ||
31 | after_create do |user| | 31 | after_create do |user| |
32 | user.person ||= Person.new | 32 | user.person ||= Person.new |
33 | - user.person.attributes = user.person_data.merge(:identifier => user.login, :user_id => user.id, :environment_id => user.environment_id) | 33 | + user.person.attributes = user.person_data.merge(:identifier => user.login, :user => user, :environment_id => user.environment_id) |
34 | user.person.name ||= user.login | 34 | user.person.name ||= user.login |
35 | user.person.visible = false unless user.activated? | 35 | user.person.visible = false unless user.activated? |
36 | user.person.save! | 36 | user.person.save! |
@@ -88,13 +88,13 @@ class User < ActiveRecord::Base | @@ -88,13 +88,13 @@ class User < ActiveRecord::Base | ||
88 | attr_protected :activated_at | 88 | attr_protected :activated_at |
89 | 89 | ||
90 | # Virtual attribute for the unencrypted password | 90 | # Virtual attribute for the unencrypted password |
91 | - attr_accessor :password | 91 | + attr_accessor :password, :name |
92 | 92 | ||
93 | validates_presence_of :login, :email | 93 | validates_presence_of :login, :email |
94 | validates_format_of :login, :with => Profile::IDENTIFIER_FORMAT, :if => (lambda {|user| !user.login.blank?}) | 94 | validates_format_of :login, :with => Profile::IDENTIFIER_FORMAT, :if => (lambda {|user| !user.login.blank?}) |
95 | validates_presence_of :password, :if => :password_required? | 95 | validates_presence_of :password, :if => :password_required? |
96 | - validates_presence_of :password_confirmation, :if => :password_required?, :if => (lambda {|user| !user.password.blank?}) | ||
97 | - validates_length_of :password, :within => 4..40, :if => :password_required?, :if => (lambda {|user| !user.password.blank?}) | 96 | + validates_presence_of :password_confirmation, :if => :password_required? |
97 | + validates_length_of :password, :within => 4..40, :if => :password_required? | ||
98 | validates_confirmation_of :password, :if => :password_required? | 98 | validates_confirmation_of :password, :if => :password_required? |
99 | validates_length_of :login, :within => 2..40, :if => (lambda {|user| !user.login.blank?}) | 99 | validates_length_of :login, :within => 2..40, :if => (lambda {|user| !user.login.blank?}) |
100 | validates_length_of :email, :within => 3..100, :if => (lambda {|user| !user.email.blank?}) | 100 | validates_length_of :email, :within => 3..100, :if => (lambda {|user| !user.email.blank?}) |
@@ -228,7 +228,12 @@ class User < ActiveRecord::Base | @@ -228,7 +228,12 @@ class User < ActiveRecord::Base | ||
228 | end | 228 | end |
229 | 229 | ||
230 | def name | 230 | def name |
231 | - person ? person.name : login | 231 | + name = (self[:name] || login) |
232 | + person.nil? ? name : (person.name || name) | ||
233 | + end | ||
234 | + | ||
235 | + def name= name | ||
236 | + self[:name] = name | ||
232 | end | 237 | end |
233 | 238 | ||
234 | def enable_email! | 239 | def enable_email! |
@@ -274,6 +279,11 @@ class User < ActiveRecord::Base | @@ -274,6 +279,11 @@ class User < ActiveRecord::Base | ||
274 | 15 # in minutes | 279 | 15 # in minutes |
275 | end | 280 | end |
276 | 281 | ||
282 | + | ||
283 | + def not_require_password! | ||
284 | + @is_password_required = false | ||
285 | + end | ||
286 | + | ||
277 | protected | 287 | protected |
278 | # before filter | 288 | # before filter |
279 | def encrypt_password | 289 | def encrypt_password |
@@ -282,9 +292,13 @@ class User < ActiveRecord::Base | @@ -282,9 +292,13 @@ class User < ActiveRecord::Base | ||
282 | self.password_type ||= User.system_encryption_method.to_s | 292 | self.password_type ||= User.system_encryption_method.to_s |
283 | self.crypted_password = encrypt(password) | 293 | self.crypted_password = encrypt(password) |
284 | end | 294 | end |
285 | - | 295 | + |
286 | def password_required? | 296 | def password_required? |
287 | - crypted_password.blank? || !password.blank? | 297 | + (crypted_password.blank? || !password.blank?) && is_password_required? |
298 | + end | ||
299 | + | ||
300 | + def is_password_required? | ||
301 | + @is_password_required.nil? ? true : @is_password_required | ||
288 | end | 302 | end |
289 | 303 | ||
290 | def make_activation_code | 304 | def make_activation_code |
@@ -292,6 +306,7 @@ class User < ActiveRecord::Base | @@ -292,6 +306,7 @@ class User < ActiveRecord::Base | ||
292 | end | 306 | end |
293 | 307 | ||
294 | def deliver_activation_code | 308 | def deliver_activation_code |
309 | + return if person.is_template? | ||
295 | User::Mailer.deliver_activation_code(self) unless self.activation_code.blank? | 310 | User::Mailer.deliver_activation_code(self) unless self.activation_code.blank? |
296 | end | 311 | end |
297 | 312 |
app/views/account/login.rhtml
@@ -13,6 +13,8 @@ | @@ -13,6 +13,8 @@ | ||
13 | 13 | ||
14 | <%= f.password_field :password %> | 14 | <%= f.password_field :password %> |
15 | 15 | ||
16 | + <%= @plugins.dispatch(:login_extra_contents).collect { |content| instance_eval(&content) }.join("") %> | ||
17 | + | ||
16 | <% button_bar do %> | 18 | <% button_bar do %> |
17 | <%= submit_button( 'login', _('Log in') )%> | 19 | <%= submit_button( 'login', _('Log in') )%> |
18 | <% if is_thickbox %> | 20 | <% if is_thickbox %> |
@@ -23,8 +25,13 @@ | @@ -23,8 +25,13 @@ | ||
23 | <% end %> | 25 | <% end %> |
24 | 26 | ||
25 | <% button_bar do %> | 27 | <% button_bar do %> |
26 | - <%= button :add, _("New user"), :controller => 'account', :action => 'signup' %> | ||
27 | - <%= button :help, _("I forgot my password!"), :controller => 'account', :action => 'forgot_password' %> | 28 | + <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> |
29 | + <%= button :add, _("New user"), :controller => 'account', :action => 'signup' %> | ||
30 | + <% end %> | ||
31 | + | ||
32 | + <% unless @plugins.dispatch(:allow_password_recovery).include?(false) %> | ||
33 | + <%= button :help, _("I forgot my password!"), :controller => 'account', :action => 'forgot_password' %> | ||
34 | + <% end %> | ||
28 | <% end %> | 35 | <% end %> |
29 | 36 | ||
30 | </div><!-- end class="login-box" --> | 37 | </div><!-- end class="login-box" --> |
app/views/account/login_block.rhtml
@@ -9,25 +9,30 @@ | @@ -9,25 +9,30 @@ | ||
9 | @user ||= User.new | 9 | @user ||= User.new |
10 | %> | 10 | %> |
11 | 11 | ||
12 | - <% labelled_form_for :user, @user, | ||
13 | - :url => login_url do |f| %> | 12 | + <% labelled_form_for :user, @user, :url => login_url do |f| %> |
14 | 13 | ||
15 | - <%= f.text_field :login, :onchange => 'this.value = convToValidLogin( this.value )' %> | 14 | + <%= f.text_field :login, :onchange => 'this.value = convToValidLogin( this.value )' %> |
16 | 15 | ||
17 | - <%= f.password_field :password %> | 16 | + <%= f.password_field :password %> |
17 | + | ||
18 | + <%= @plugins.dispatch(:login_extra_contents).collect { |content| instance_eval(&content) }.join("") %> | ||
18 | 19 | ||
19 | <% button_bar do %> | 20 | <% button_bar do %> |
20 | <%= submit_button( 'login', _('Log in') )%> | 21 | <%= submit_button( 'login', _('Log in') )%> |
21 | - <%= link_to content_tag( 'span', _('New user') ), | ||
22 | - { :controller => 'account', :action => 'signup' }, | ||
23 | - :class => 'button with-text icon-add' %> | 22 | + <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> |
23 | + <%= link_to content_tag( 'span', _('New user') ), | ||
24 | + { :controller => 'account', :action => 'signup' }, | ||
25 | + :class => 'button with-text icon-add' %> | ||
26 | + <% end %> | ||
24 | <% end %> | 27 | <% end %> |
25 | 28 | ||
26 | <% end %> | 29 | <% end %> |
27 | 30 | ||
28 | - <p class="forgot-passwd"> | ||
29 | - <%= link_to _("I forgot my password!"), :controller => 'account', :action => 'forgot_password' %> | ||
30 | - </p> | 31 | + <% unless @plugins.dispatch(:allow_password_recovery).include?(false) %> |
32 | + <p class="forgot-passwd"> | ||
33 | + <%= link_to _("I forgot my password!"), :controller => 'account', :action => 'forgot_password' %> | ||
34 | + </p> | ||
35 | + <% end %> | ||
31 | 36 | ||
32 | </div> | 37 | </div> |
33 | 38 |
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +<% block_types.in_groups_of(2) do |block1, block2| %> | ||
2 | + <div style='float: left; width: 48%; padding-top: 2px;'> | ||
3 | + <%= labelled_radio_button(block1.description, :type, block1.name) %> | ||
4 | + </div> | ||
5 | + <% if block2 %> | ||
6 | + <div style='float: left; width: 48%; padding-top: 2px;'> | ||
7 | + <%= labelled_radio_button(block2.description, :type, block2.name) %> | ||
8 | + </div> | ||
9 | + <% end %> | ||
10 | +<% end %> |
app/views/box_organizer/_highlights_block.rhtml
1 | <strong><%= _('Highlights') %></strong> | 1 | <strong><%= _('Highlights') %></strong> |
2 | -<div id='edit-highlights-block'> | 2 | +<div id='edit-highlights-block' style='width:450px'> |
3 | <table id='highlights' class='noborder'> | 3 | <table id='highlights' class='noborder'> |
4 | <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th><th><%= _('Title') %></th></tr> | 4 | <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th><th><%= _('Title') %></th></tr> |
5 | <% for image in @block.images do %> | 5 | <% for image in @block.images do %> |
app/views/box_organizer/_link_list_block.rhtml
1 | <strong><%= _('Links') %></strong> | 1 | <strong><%= _('Links') %></strong> |
2 | -<div id='edit-link-list-block'> | 2 | +<div id='edit-link-list-block' style='width:450px'> |
3 | <table id='links' class='noborder'> | 3 | <table id='links' class='noborder'> |
4 | <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th></tr> | 4 | <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th></tr> |
5 | <% for link in @block.links do %> | 5 | <% for link in @block.links do %> |
app/views/box_organizer/_raw_html_block.rhtml
app/views/box_organizer/add_block.rhtml
1 | -<% form_tag do %> | ||
2 | - | ||
3 | - <p><%= _('In what area do you want to put your new block?') %></p> | ||
4 | - | ||
5 | - <%# FIXME hardcoded stuff %> | ||
6 | - <%= select_tag('box_id', options_for_select(@boxes.select { |item| item.position != 1 }.map {|item| [ _("Area %d") % item.position, item.id]})) %> | ||
7 | - | ||
8 | - <p><%= _('Select the type of block you want to add to your page.') %></p> | ||
9 | - | ||
10 | - <% @block_types.in_groups_of(2) do |block1, block2| %> | ||
11 | - <div style='float: left; width: 48%; padding-top: 2px;'> | ||
12 | - <%= radio_button_tag('type', block1.name) %> | ||
13 | - <%= label_tag "type_#{block1.name.downcase}", block1.description %> | 1 | +<div style='height:350px'> |
2 | + <% form_tag do %> | ||
3 | + | ||
4 | + <p><%= _('In what area do you want to put your new block?') %></p> | ||
5 | + | ||
6 | + <% @boxes.each do |box| %> | ||
7 | + <%= labelled_radio_button(_("Area %d") % box.position, :box_id, box.id, box.central?, { :class => 'box-position', 'data-position' => box.position }) %> | ||
8 | + <% end %> | ||
9 | + | ||
10 | + <script type="text/javascript"> | ||
11 | + (function ($) { | ||
12 | + $(document).ready(function () { | ||
13 | + $(".box-position").live('change', function () { | ||
14 | + if ($(this).attr('data-position') == '1') { | ||
15 | + $('#center-block-types').show(); | ||
16 | + $('#side-block-types').hide(); | ||
17 | + } else { | ||
18 | + $('#center-block-types').hide(); | ||
19 | + $('#side-block-types').show(); | ||
20 | + }; | ||
21 | + }); | ||
22 | + })})(jQuery); | ||
23 | + </script> | ||
24 | + | ||
25 | + <p><%= _('Select the type of block you want to add to your page.') %></p> | ||
26 | + | ||
27 | + <div id='center-block-types'> | ||
28 | + <%= render :partial => 'block_types', :locals => { :block_types => @center_block_types } %> | ||
14 | </div> | 29 | </div> |
15 | - <% if block2 %> | ||
16 | - <div style='float: left; width: 48%; padding-top: 2px;'> | ||
17 | - <%= radio_button_tag('type', block2.name) %> | ||
18 | - <%= label_tag "type_#{block2.name.downcase}", block2.description %> | ||
19 | - </div> | 30 | + |
31 | + <div id='side-block-types' style='display:none'> | ||
32 | + <%= render :partial => 'block_types', :locals => { :block_types => @side_block_types } %> | ||
33 | + </div> | ||
34 | + | ||
35 | + <br style='clear: both'/> | ||
36 | + | ||
37 | + <% button_bar do %> | ||
38 | + <%= submit_button(:add, _("Add")) %> | ||
39 | + <%= colorbox_close_button(_('Close')) %> | ||
20 | <% end %> | 40 | <% end %> |
21 | - <% end %> | ||
22 | - <br style='clear: both'/> | ||
23 | - | ||
24 | - <% button_bar do %> | ||
25 | - <%= submit_button(:add, _("Add")) %> | ||
26 | - <%= lightbox_close_button(_('Close')) %> | ||
27 | - <% end %> | ||
28 | 41 | ||
29 | -<% end %> | 42 | + <% end %> |
43 | +</div> |
app/views/box_organizer/edit.rhtml
1 | -<h2><%= _('Editing block') %></h2> | 1 | +<div style='width: 500px;'> |
2 | + <h2><%= _('Editing block') %></h2> | ||
2 | 3 | ||
3 | -<% form_tag(:action => 'save', :id => @block.id) do %> | 4 | + <% form_tag(:action => 'save', :id => @block.id) do %> |
4 | 5 | ||
5 | - <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %> | 6 | + <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %> |
6 | 7 | ||
7 | - <%= render :partial => partial_for_class(@block.class) %> | 8 | + <%= render :partial => partial_for_class(@block.class) %> |
8 | 9 | ||
9 | - <%= labelled_form_field _('Display this block:'), '' %> | ||
10 | - <div style='margin-left: 10px'> | ||
11 | - <%= radio_button(:block, :display, 'always') %> | ||
12 | - <%= label_tag('block_display_always', _('In all pages')) %> | ||
13 | - <br/> | ||
14 | - <%= radio_button(:block, :display, 'home_page_only') %> | ||
15 | - <%= label_tag('block_display_home_page_only', _('Only in the homepage')) %> | ||
16 | - <br/> | ||
17 | - <%= radio_button(:block, :display, 'except_home_page') %> | ||
18 | - <%= label_tag('block_display_except_home_page', _('In all pages, except in the homepage')) %> | ||
19 | - <br/> | ||
20 | - <%= radio_button(:block, :display, 'never') %> | ||
21 | - <%= label_tag('block_display_never', _("Don't display")) %> | ||
22 | - </div> | 10 | + <%= labelled_form_field _('Display this block:'), '' %> |
11 | + <div style='margin-left: 10px'> | ||
12 | + <%= radio_button(:block, :display, 'always') %> | ||
13 | + <%= label_tag('block_display_always', _('In all pages')) %> | ||
14 | + <br/> | ||
15 | + <%= radio_button(:block, :display, 'home_page_only') %> | ||
16 | + <%= label_tag('block_display_home_page_only', _('Only in the homepage')) %> | ||
17 | + <br/> | ||
18 | + <%= radio_button(:block, :display, 'except_home_page') %> | ||
19 | + <%= label_tag('block_display_except_home_page', _('In all pages, except in the homepage')) %> | ||
20 | + <br/> | ||
21 | + <%= radio_button(:block, :display, 'never') %> | ||
22 | + <%= label_tag('block_display_never', _("Don't display")) %> | ||
23 | + </div> | ||
23 | 24 | ||
24 | - <%= labelled_form_field(_('Show for:'), select(:block, :language, [ [ _('all languages'), 'all']] + Noosfero.locales.map {|key, value| [value, key]} )) %> | 25 | + <%= labelled_form_field(_('Show for:'), select(:block, :language, [ [ _('all languages'), 'all']] + Noosfero.locales.map {|key, value| [value, key]} )) %> |
25 | 26 | ||
26 | - <% button_bar do %> | ||
27 | - <%= submit_button(:save, _('Save')) %> | ||
28 | - <%= lightbox_close_button(_('Cancel')) %> | ||
29 | - <% end %> | 27 | + <% button_bar do %> |
28 | + <%= submit_button(:save, _('Save')) %> | ||
29 | + <%= colorbox_close_button(_('Cancel')) %> | ||
30 | + <% end %> | ||
30 | 31 | ||
31 | -<% end %> | 32 | + <% end %> |
33 | +</div> |
app/views/box_organizer/index.rhtml
1 | <h1><%= _('Editing sideboxes')%></h1> | 1 | <h1><%= _('Editing sideboxes')%></h1> |
2 | 2 | ||
3 | <% button_bar do %> | 3 | <% button_bar do %> |
4 | - <%= lightbox_button('add', _('Add a block'), { :action => 'add_block' }) %> | 4 | + <%= colorbox_button('add', _('Add a block'), { :action => 'add_block' }) %> |
5 | <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %> | 5 | <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %> |
6 | <% end %> | 6 | <% end %> |
app/views/cms/view.rhtml
@@ -49,13 +49,13 @@ | @@ -49,13 +49,13 @@ | ||
49 | <%= article.class.short_description %> | 49 | <%= article.class.short_description %> |
50 | </td> | 50 | </td> |
51 | <td class="article-controls"> | 51 | <td class="article-controls"> |
52 | - <%= button_without_text :edit, _('Edit'), :action => 'edit', :id => article.id %> | 52 | + <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %> |
53 | <%= button_without_text :eyes, _('Public view'), article.view_url %> | 53 | <%= button_without_text :eyes, _('Public view'), article.view_url %> |
54 | - <%= display_spread_button(profile, article) unless article.folder? %> | ||
55 | - <% if !environment.enabled?('cant_change_homepage') %> | ||
56 | - <%= button_without_text :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> | 54 | + <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%> |
55 | + <% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %> | ||
56 | + <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> | ||
57 | <% end %> | 57 | <% end %> |
58 | - <%= display_delete_button(article) %> | 58 | + <%= display_delete_button(article) if !remove_content_button(:delete) %> |
59 | </td> | 59 | </td> |
60 | </tr> | 60 | </tr> |
61 | <% end %> | 61 | <% end %> |
app/views/content_viewer/_article_toolbar.rhtml
1 | <div<%= user && " class='logged-in'" %>> | 1 | <div<%= user && " class='logged-in'" %>> |
2 | <div id="article-actions"> | 2 | <div id="article-actions"> |
3 | 3 | ||
4 | - <% if @page.allow_edit?(user) %> | ||
5 | - <%= link_to content_tag( 'span', label_for_edit_article(@page) ), | ||
6 | - profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id }), | ||
7 | - :class => 'button with-text icon-edit' %> | 4 | + |
5 | + <% if @page.allow_edit?(user) && !remove_content_button(:edit) %> | ||
6 | + <% content = content_tag('span', label_for_edit_article(@page)) %> | ||
7 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id }) %> | ||
8 | + <%= expirable_button @page, :edit, content, url %> | ||
8 | <% end %> | 9 | <% end %> |
9 | 10 | ||
10 | - <% if @page != profile.home_page && !@page.has_posts? && @page.allow_delete?(user) %> | ||
11 | - <%= link_to content_tag( 'span', _('Delete') ), | ||
12 | - profile.admin_url.merge({ :controller => 'cms', :action => 'destroy', :id => @page}), | ||
13 | - :method => :post, | ||
14 | - :class => 'button with-text icon-delete', | ||
15 | - :confirm => delete_article_message(@page) %> | 11 | + <% if @page != profile.home_page && !@page.has_posts? && @page.allow_delete?(user) && !remove_content_button(:delete)%> |
12 | + <% content = content_tag( 'span', _('Delete') ) %> | ||
13 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'destroy', :id => @page}) %> | ||
14 | + <% options = {:method => :post, :confirm => delete_article_message(@page)} %> | ||
15 | + <%= expirable_button @page, :delete, content, url, options %> | ||
16 | <% end %> | 16 | <% end %> |
17 | 17 | ||
18 | - <% if !@page.folder? && @page.allow_spread?(user) %> | 18 | + <% if !@page.folder? && @page.allow_spread?(user) && !remove_content_button(:spread) %> |
19 | + <% content = content_tag( 'span', _('Spread this') ) %> | ||
20 | + <% url = nil %> | ||
19 | <% if profile.kind_of?(Person) %> | 21 | <% if profile.kind_of?(Person) %> |
20 | - <%= link_to content_tag( 'span', _('Spread this') ), | ||
21 | - profile.admin_url.merge({ :controller => 'cms', :action => 'publish', :id => @page }), | ||
22 | - :class => 'button with-text icon-spread' %> | 22 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'publish', :id => @page }) %> |
23 | <% elsif profile.kind_of?(Community) && environment.portal_community %> | 23 | <% elsif profile.kind_of?(Community) && environment.portal_community %> |
24 | - <%= link_to content_tag( 'span', _('Spread this') ), | ||
25 | - profile.admin_url.merge({ :controller => 'cms', :action => 'publish_on_portal_community', :id => @page }), | ||
26 | - :class => 'button with-text icon-spread' %> | 24 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'publish_on_portal_community', :id => @page }) %> |
27 | <% end %> | 25 | <% end %> |
26 | + <%= expirable_button @page, :spread, content, url if url %> | ||
28 | <% end %> | 27 | <% end %> |
29 | 28 | ||
30 | <% if !@page.gallery? && @page.allow_create?(user) %> | 29 | <% if !@page.gallery? && @page.allow_create?(user) %> |
31 | - <%= link_to _('Add translation'), | ||
32 | - profile.admin_url.merge(:controller => 'cms', :action => 'new', | ||
33 | - :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)), | ||
34 | - :type => @page.type, :article => { :translation_of_id => @page.native_translation.id }), | ||
35 | - :class => 'button with-text icon-locale' if @page.translatable? && !@page.native_translation.language.blank? %> | 30 | + <% if @page.translatable? && !@page.native_translation.language.blank? && !remove_content_button(:locale) %> |
31 | + <% content = _('Add translation') %> | ||
32 | + <% parent_id = (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)) %> | ||
33 | + <% url = profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => parent_id, :type => @page.type, :article => { :translation_of_id => @page.native_translation.id })%> | ||
34 | + <%= expirable_button @page, :locale, content, url %> | ||
35 | + <% end %> | ||
36 | + | ||
36 | <%= colorbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) %> | 37 | <%= colorbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) %> |
37 | <% end %> | 38 | <% end %> |
38 | 39 | ||
@@ -40,8 +41,11 @@ | @@ -40,8 +41,11 @@ | ||
40 | <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) %> | 41 | <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) %> |
41 | <% end %> | 42 | <% end %> |
42 | 43 | ||
43 | - <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) %> | ||
44 | - <%= link_to content_tag( 'span', _('Suggest an article') ), profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}), :id => 'suggest-article-link', :class => 'button with-text icon-new' %> | 44 | + <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest) %> |
45 | + <% content = content_tag( 'span', _('Suggest an article') ) %> | ||
46 | + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}) %> | ||
47 | + <% options = {:id => 'suggest-article-link'} %> | ||
48 | + <%= expirable_button @page, :suggest, content, url, options %> | ||
45 | <% end %> | 49 | <% end %> |
46 | 50 | ||
47 | <%= report_abuse(profile, :link, @page) %> | 51 | <%= report_abuse(profile, :link, @page) %> |
app/views/content_viewer/_comment.rhtml
@@ -63,6 +63,11 @@ | @@ -63,6 +63,11 @@ | ||
63 | <% end %> | 63 | <% end %> |
64 | <% end %> | 64 | <% end %> |
65 | 65 | ||
66 | + <% if comment.author && comment.author == user %> | ||
67 | + | ||
68 | + <%= expirable_comment_link comment, :edit, _('Edit'), {:action => 'edit_comment', :id => comment.id, :profile => profile.identifier} %> | ||
69 | + <% end %> | ||
70 | + | ||
66 | <% if logged_in? && (user == profile || user == comment.author || user.has_permission?(:moderate_comments, profile)) %> | 71 | <% if logged_in? && (user == profile || user == comment.author || user.has_permission?(:moderate_comments, profile)) %> |
67 | | 72 | |
68 | <%= link_to_function(_('Remove'), 'remove_comment(this, %s, %s); return false ;' % [url_for(:profile => params[:profile], :remove_comment => comment.id, :view => params[:view]).to_json, _('Are you sure you want to remove this comment and all its replies?').to_json], :class => 'comment-footer comment-footer-link comment-footer-hide remove-children') %> | 73 | <%= link_to_function(_('Remove'), 'remove_comment(this, %s, %s); return false ;' % [url_for(:profile => params[:profile], :remove_comment => comment.id, :view => params[:view]).to_json, _('Are you sure you want to remove this comment and all its replies?').to_json], :class => 'comment-footer comment-footer-link comment-footer-hide remove-children') %> |
app/views/content_viewer/_comment_form.rhtml
@@ -32,15 +32,17 @@ function submit_comment_form(button) { | @@ -32,15 +32,17 @@ function submit_comment_form(button) { | ||
32 | 32 | ||
33 | <div class="post_comment_box <%= @form_div %>"> | 33 | <div class="post_comment_box <%= @form_div %>"> |
34 | 34 | ||
35 | -<h4 onclick="var d = jQuery(this).parent('.post_comment_box'); | ||
36 | - if (d.hasClass('closed')) { | ||
37 | - d.removeClass('closed'); | ||
38 | - d.addClass('opened'); | ||
39 | - d.find('input[name=comment[title]], textarea').val(''); | ||
40 | - d.find('.comment_form input[name=comment[<%= focus_on %>]]').focus(); | ||
41 | - }"> | ||
42 | - <%= content_tag('a', '', :name => 'comment_form') + _('Post a comment') %> | ||
43 | -</h4> | 35 | +<% if display_link %> |
36 | + <h4 onclick="var d = jQuery(this).parent('.post_comment_box'); | ||
37 | + if (d.hasClass('closed')) { | ||
38 | + d.removeClass('closed'); | ||
39 | + d.addClass('opened'); | ||
40 | + d.find('input[name=comment[title]], textarea').val(''); | ||
41 | + d.find('.comment_form input[name=comment[<%= focus_on %>]]').focus(); | ||
42 | + }"> | ||
43 | + <%= content_tag('a', '', :name => 'comment_form') + _('Post a comment') %> | ||
44 | + </h4> | ||
45 | +<% end %> | ||
44 | 46 | ||
45 | <% unless pass_without_comment_captcha? %> | 47 | <% unless pass_without_comment_captcha? %> |
46 | <div id="recaptcha-container" style="display: none"> | 48 | <div id="recaptcha-container" style="display: none"> |
@@ -59,7 +61,7 @@ function submit_comment_form(button) { | @@ -59,7 +61,7 @@ function submit_comment_form(button) { | ||
59 | </script> | 61 | </script> |
60 | <% end %> | 62 | <% end %> |
61 | 63 | ||
62 | -<% form_tag( url_for(@page.view_url.merge({:only_path => true})), { :class => 'comment_form' } ) do %> | 64 | +<% form_tag( url, { :class => 'comment_form' } ) do %> |
63 | <%= hidden_field_tag(:confirm, 'false') %> | 65 | <%= hidden_field_tag(:confirm, 'false') %> |
64 | 66 | ||
65 | <%= required_fields_message %> | 67 | <%= required_fields_message %> |
@@ -84,7 +86,11 @@ function submit_comment_form(button) { | @@ -84,7 +86,11 @@ function submit_comment_form(button) { | ||
84 | 86 | ||
85 | <% button_bar do %> | 87 | <% button_bar do %> |
86 | <%= submit_button('add', _('Post comment'), :onclick => "submit_comment_form(this); return false") %> | 88 | <%= submit_button('add', _('Post comment'), :onclick => "submit_comment_form(this); return false") %> |
87 | - <%= button_to_function :cancel, _('Cancel'), "f=jQuery(this).parents('.post_comment_box'); f.removeClass('opened'); f.addClass('closed'); return false" %> | 89 | + <% if cancel_triggers_hide %> |
90 | + <%= button_to_function :cancel, _('Cancel'), "f=jQuery(this).parents('.post_comment_box'); f.removeClass('opened'); f.addClass('closed'); return false" %> | ||
91 | + <% else %> | ||
92 | + <%= button('cancel', _('Cancel'), {:action => 'view_page', :profile => profile.identifier, :page => @comment.article.explode_path})%> | ||
93 | + <% end %> | ||
88 | <% end %> | 94 | <% end %> |
89 | <% end %> | 95 | <% end %> |
90 | 96 |
app/views/content_viewer/view_page.rhtml
@@ -98,7 +98,7 @@ | @@ -98,7 +98,7 @@ | ||
98 | </ul> | 98 | </ul> |
99 | 99 | ||
100 | <% if @page.accept_comments? %> | 100 | <% if @page.accept_comments? %> |
101 | - <div id="page-comment-form"><%= render :partial => 'comment_form' %></div> | 101 | + <div id="page-comment-form"><%= render :partial => 'comment_form', :locals => {:url => url_for(@page.view_url.merge({:only_path => true})), :display_link => true, :cancel_triggers_hide => true}%></div> |
102 | <% end %> | 102 | <% end %> |
103 | </div><!-- end class="comments" --> | 103 | </div><!-- end class="comments" --> |
104 | 104 |
app/views/layouts/_javascript.rhtml
@@ -2,7 +2,8 @@ | @@ -2,7 +2,8 @@ | ||
2 | 'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'colorbox', | 2 | 'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'colorbox', |
3 | 'jquery-ui-1.8.2.custom.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate', | 3 | 'jquery-ui-1.8.2.custom.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate', |
4 | 'jquery.cookie', 'jquery.ba-bbq.min.js', 'reflection', 'jquery.tokeninput', | 4 | 'jquery.cookie', 'jquery.ba-bbq.min.js', 'reflection', 'jquery.tokeninput', |
5 | -'add-and-join', 'report-abuse', 'catalog', 'manage-products', :cache => 'cache-general' %> | 5 | +'add-and-join', 'report-abuse', 'catalog', 'manage-products', |
6 | +'jquery-ui-timepicker-addon', :cache => 'cache-general' %> | ||
6 | 7 | ||
7 | <% language = FastGettext.locale %> | 8 | <% language = FastGettext.locale %> |
8 | <% %w{messages methods}.each do |type| %> | 9 | <% %w{messages methods}.each do |type| %> |
app/views/layouts/application-ng.rhtml
@@ -56,10 +56,18 @@ | @@ -56,10 +56,18 @@ | ||
56 | <%= usermenu_logged_in %> | 56 | <%= usermenu_logged_in %> |
57 | </span> | 57 | </span> |
58 | <span class='not-logged-in' style='display: none'> | 58 | <span class='not-logged-in' style='display: none'> |
59 | - <%= _("<span class='login'>%s</span> <span class='or'>or</span> <span class='signup'>%s</span>") % [thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login'), link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup') ] %> | 59 | + |
60 | + <%= _("<span class='login'>%s</span>") % thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login') %> | ||
61 | + <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_eval(&content) }.join("") %> | ||
62 | + | ||
60 | <div id='inlineLoginBox' style='display: none;'> | 63 | <div id='inlineLoginBox' style='display: none;'> |
61 | <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> | 64 | <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> |
62 | </div> | 65 | </div> |
66 | + | ||
67 | + <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> | ||
68 | + <%= _("<span class='or'>or</span> <span class='signup'>%s</span>") % link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup')%> | ||
69 | + <% end %> | ||
70 | + | ||
63 | </span> | 71 | </span> |
64 | <form action="/search" class="search_form" method="get" class="clean"> | 72 | <form action="/search" class="search_form" method="get" class="clean"> |
65 | <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" /> | 73 | <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" /> |
app/views/profile/_comment.rhtml
@@ -62,6 +62,10 @@ | @@ -62,6 +62,10 @@ | ||
62 | </script> | 62 | </script> |
63 | <% end %> | 63 | <% end %> |
64 | <%= report_abuse(comment.author, :comment_link, comment) if comment.author %> | 64 | <%= report_abuse(comment.author, :comment_link, comment) if comment.author %> |
65 | + <% if comment.author && comment.author == user %> | ||
66 | + <%= expirable_comment_link comment, :edit, _('Edit'), {:action => 'edit_comment', :id => comment.id, :profile => profile.identifier} %> | ||
67 | + <%= content_tag('span', ' | ', :class => 'comment-footer comment-footer-hide') %> | ||
68 | + <% end %> | ||
65 | <%= link_to_function _('Reply'), | 69 | <%= link_to_function _('Reply'), |
66 | "var f = add_comment_reply_form(this, %s); f.find('input[name=comment[title]], textarea').val(''); return false" % comment.id, | 70 | "var f = add_comment_reply_form(this, %s); f.find('input[name=comment[title]], textarea').val(''); return false" % comment.id, |
67 | :class => 'comment-footer comment-footer-link comment-footer-hide', | 71 | :class => 'comment-footer comment-footer-link comment-footer-hide', |
app/views/tasks/_task.rhtml
@@ -50,13 +50,13 @@ | @@ -50,13 +50,13 @@ | ||
50 | <% fields_for "tasks[#{task.id}][task]", task do |f| %> | 50 | <% fields_for "tasks[#{task.id}][task]", task do |f| %> |
51 | <% if task.accept_details %> | 51 | <% if task.accept_details %> |
52 | <div id="on-accept-information-<%=task.id%>" style="display: none"> | 52 | <div id="on-accept-information-<%=task.id%>" style="display: none"> |
53 | - <%= render :partial => partial_for_task_class(task.class, :accept_details), :locals => {:task => task, :f => f} %> | 53 | + <%= render :partial => partial_for_class(task.class, :accept_details), :locals => {:task => task, :f => f} %> |
54 | </div> | 54 | </div> |
55 | <% end %> | 55 | <% end %> |
56 | 56 | ||
57 | <% if task.reject_details %> | 57 | <% if task.reject_details %> |
58 | <div id="on-reject-information-<%=task.id%>" style="display: none"> | 58 | <div id="on-reject-information-<%=task.id%>" style="display: none"> |
59 | - <%= render :partial => partial_for_task_class(task.class, :reject_details), :locals => {:task => task, :f => f} %> | 59 | + <%= render :partial => partial_for_class(task.class, :reject_details), :locals => {:task => task, :f => f} %> |
60 | </div> | 60 | </div> |
61 | <% end %> | 61 | <% end %> |
62 | <% end %> | 62 | <% end %> |
config/routes.rb
@@ -19,6 +19,7 @@ ActionController::Routing::Routes.draw do |map| | @@ -19,6 +19,7 @@ ActionController::Routing::Routes.draw do |map| | ||
19 | 19 | ||
20 | # -- just remember to delete public/index.html. | 20 | # -- just remember to delete public/index.html. |
21 | # You can have the root of your site routed by hooking up '' | 21 | # You can have the root of your site routed by hooking up '' |
22 | + map.root :controller => "home", :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } | ||
22 | map.connect '', :controller => "home", :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } | 23 | map.connect '', :controller => "home", :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } |
23 | map.home 'site/:action', :controller => 'home' | 24 | map.home 'site/:action', :controller => 'home' |
24 | 25 | ||
@@ -121,9 +122,12 @@ ActionController::Routing::Routes.draw do |map| | @@ -121,9 +122,12 @@ ActionController::Routing::Routes.draw do |map| | ||
121 | # cache stuff - hack | 122 | # cache stuff - hack |
122 | map.cache 'public/:action/:id', :controller => 'public' | 123 | map.cache 'public/:action/:id', :controller => 'public' |
123 | 124 | ||
125 | + map.connect ':profile/edit_comment/:id/*page', :controller => 'content_viewer', :action => 'edit_comment', :profile => /#{Noosfero.identifier_format}/ | ||
126 | + | ||
124 | # match requests for profiles that don't have a custom domain | 127 | # match requests for profiles that don't have a custom domain |
125 | map.homepage ':profile/*page', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } | 128 | map.homepage ':profile/*page', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } |
126 | 129 | ||
130 | + | ||
127 | # match requests for content in domains hosted for profiles | 131 | # match requests for content in domains hosted for profiles |
128 | map.connect '*page', :controller => 'content_viewer', :action => 'view_page' | 132 | map.connect '*page', :controller => 'content_viewer', :action => 'view_page' |
129 | 133 |
debian/noosfero-console
lib/noosfero/plugin.rb
@@ -12,7 +12,11 @@ class Noosfero::Plugin | @@ -12,7 +12,11 @@ class Noosfero::Plugin | ||
12 | end | 12 | end |
13 | 13 | ||
14 | def init_system | 14 | def init_system |
15 | - Dir.glob(File.join(Rails.root, 'config', 'plugins', '*')).select do |entry| | 15 | + enabled_plugins = Dir.glob(File.join(Rails.root, 'config', 'plugins', '*')) |
16 | + if Rails.env.test? && !enabled_plugins.include?(File.join(Rails.root, 'config', 'plugins', 'foo')) | ||
17 | + enabled_plugins << File.join(Rails.root, 'plugins', 'foo') | ||
18 | + end | ||
19 | + enabled_plugins.select do |entry| | ||
16 | File.directory?(entry) | 20 | File.directory?(entry) |
17 | end.each do |dir| | 21 | end.each do |dir| |
18 | plugin_name = File.basename(dir) | 22 | plugin_name = File.basename(dir) |
@@ -31,6 +35,11 @@ class Noosfero::Plugin | @@ -31,6 +35,11 @@ class Noosfero::Plugin | ||
31 | if plugin_dependencies_ok | 35 | if plugin_dependencies_ok |
32 | Rails.configuration.controller_paths << File.join(dir, 'controllers') | 36 | Rails.configuration.controller_paths << File.join(dir, 'controllers') |
33 | ActiveSupport::Dependencies.load_paths << File.join(dir, 'controllers') | 37 | ActiveSupport::Dependencies.load_paths << File.join(dir, 'controllers') |
38 | + controllers_folders = %w[public profile myprofile admin] | ||
39 | + controllers_folders.each do |folder| | ||
40 | + Rails.configuration.controller_paths << File.join(dir, 'controllers', folder) | ||
41 | + ActiveSupport::Dependencies.load_paths << File.join(dir, 'controllers', folder) | ||
42 | + end | ||
34 | [ ActiveSupport::Dependencies.load_paths, $:].each do |path| | 43 | [ ActiveSupport::Dependencies.load_paths, $:].each do |path| |
35 | path << File.join(dir, 'models') | 44 | path << File.join(dir, 'models') |
36 | path << File.join(dir, 'lib') | 45 | path << File.join(dir, 'lib') |
@@ -211,28 +220,6 @@ class Noosfero::Plugin | @@ -211,28 +220,6 @@ class Noosfero::Plugin | ||
211 | nil | 220 | nil |
212 | end | 221 | end |
213 | 222 | ||
214 | - # This is a generic hotspot for all controllers on Noosfero. | ||
215 | - # If any plugin wants to define filters to run on any controller, the name of | ||
216 | - # the hotspot must be in the following form: <underscored_controller_name>_filters. | ||
217 | - # Example: for ProfileController the hotspot is profile_controller_filters | ||
218 | - # | ||
219 | - # -> Adds a filter to a controller | ||
220 | - # returns = { :type => type, | ||
221 | - # :method_name => method_name, | ||
222 | - # :options => {:opt1 => opt1, :opt2 => opt2}, | ||
223 | - # :block => Proc or lambda block} | ||
224 | - # type = 'before_filter' or 'after_filter' | ||
225 | - # method_name = The name of the filter | ||
226 | - # option = Filter options, like :only or :except | ||
227 | - # block = Block that the filter will call | ||
228 | - def method_missing(method, *args, &block) | ||
229 | - if method.to_s =~ /^(.+)_controller_filters$/ | ||
230 | - [] | ||
231 | - else | ||
232 | - super | ||
233 | - end | ||
234 | - end | ||
235 | - | ||
236 | # This method will be called just before a comment is saved to the database. | 223 | # This method will be called just before a comment is saved to the database. |
237 | # | 224 | # |
238 | # It can modify the comment in several ways. In special, a plugin can call | 225 | # It can modify the comment in several ways. In special, a plugin can call |
@@ -333,4 +320,71 @@ class Noosfero::Plugin | @@ -333,4 +320,71 @@ class Noosfero::Plugin | ||
333 | nil | 320 | nil |
334 | end | 321 | end |
335 | 322 | ||
323 | + # -> Add an alternative authentication method. | ||
324 | + # Your plugin have to make the access control and return the logged user. | ||
325 | + # returns = User | ||
326 | + def alternative_authentication | ||
327 | + nil | ||
328 | + end | ||
329 | + | ||
330 | + # -> Adds adicional link to make the user authentication | ||
331 | + # returns = lambda block that creates html code | ||
332 | + def alternative_authentication_link | ||
333 | + nil | ||
334 | + end | ||
335 | + | ||
336 | + # -> Allow or not user registration | ||
337 | + # returns = boolean | ||
338 | + def allow_user_registration | ||
339 | + true | ||
340 | + end | ||
341 | + | ||
342 | + # -> Allow or not password recovery by users | ||
343 | + # returns = boolean | ||
344 | + def allow_password_recovery | ||
345 | + true | ||
346 | + end | ||
347 | + | ||
348 | + # -> Adds fields to the login form | ||
349 | + # returns = lambda block that creates html code | ||
350 | + def login_extra_contents | ||
351 | + nil | ||
352 | + end | ||
353 | + | ||
354 | + def method_missing(method, *args, &block) | ||
355 | + # This is a generic hotspot for all controllers on Noosfero. | ||
356 | + # If any plugin wants to define filters to run on any controller, the name of | ||
357 | + # the hotspot must be in the following form: <underscored_controller_name>_filters. | ||
358 | + # Example: for ProfileController the hotspot is profile_controller_filters | ||
359 | + # | ||
360 | + # -> Adds a filter to a controller | ||
361 | + # returns = { :type => type, | ||
362 | + # :method_name => method_name, | ||
363 | + # :options => {:opt1 => opt1, :opt2 => opt2}, | ||
364 | + # :block => Proc or lambda block} | ||
365 | + # type = 'before_filter' or 'after_filter' | ||
366 | + # method_name = The name of the filter | ||
367 | + # option = Filter options, like :only or :except | ||
368 | + # block = Block that the filter will call | ||
369 | + if method.to_s =~ /^(.+)_controller_filters$/ | ||
370 | + [] | ||
371 | + # -> Removes the action button from the content | ||
372 | + # returns = boolean | ||
373 | + elsif method.to_s =~ /^content_remove_(#{content_actions.join('|')})$/ | ||
374 | + nil | ||
375 | + # -> Expire the action button from the content | ||
376 | + # returns = string with reason of expiration | ||
377 | + elsif method.to_s =~ /^content_expire_(#{content_actions.join('|')})$/ | ||
378 | + nil | ||
379 | + else | ||
380 | + super | ||
381 | + end | ||
382 | + end | ||
383 | + | ||
384 | + private | ||
385 | + | ||
386 | + def content_actions | ||
387 | + %w[edit delete spread locale suggest home] | ||
388 | + end | ||
389 | + | ||
336 | end | 390 | end |
lib/noosfero/plugin/routes.rb
1 | -Dir.glob(File.join(Rails.root, 'config', 'plugins', '*', 'controllers')) do |dir| | ||
2 | - plugin_name = File.basename(File.dirname(dir)) | 1 | +plugins_root = Rails.env.test? ? 'plugins' : File.join('config', 'plugins') |
2 | + | ||
3 | +Dir.glob(File.join(Rails.root, plugins_root, '*', 'controllers')) do |controllers_dir| | ||
4 | + prefixes_by_folder = {'public' => 'plugin', | ||
5 | + 'profile' => 'profile/:profile/plugin', | ||
6 | + 'myprofile' => 'myprofile/:profile/plugin', | ||
7 | + 'admin' => 'admin/plugin'} | ||
8 | + | ||
9 | + controllers_by_folder = prefixes_by_folder.keys.inject({}) do |hash, folder| | ||
10 | + hash.merge!({folder => Dir.glob(File.join(controllers_dir, folder, '*')).map {|full_names| File.basename(full_names).gsub(/_controller.rb$/,'')}}) | ||
11 | + end | ||
12 | + | ||
13 | + plugin_name = File.basename(File.dirname(controllers_dir)) | ||
14 | + | ||
15 | + controllers_by_folder.each do |folder, controllers| | ||
16 | + controllers.each do |controller| | ||
17 | + controller_name = controller.gsub("#{plugin_name}_plugin_",'') | ||
18 | + map.connect "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}/:action/:id", :controller => controller | ||
19 | + end | ||
20 | + end | ||
21 | + | ||
3 | map.connect 'plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin' | 22 | map.connect 'plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin' |
4 | - map.connect 'profile/:profile/plugins/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_profile' | 23 | + map.connect 'profile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_profile' |
5 | map.connect 'myprofile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_myprofile' | 24 | map.connect 'myprofile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_myprofile' |
6 | map.connect 'admin/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_admin' | 25 | map.connect 'admin/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_admin' |
7 | end | 26 | end |
8 | - |
plugins/custom_forms/controllers/custom_forms_plugin_myprofile_controller.rb
0 → 100644
@@ -0,0 +1,147 @@ | @@ -0,0 +1,147 @@ | ||
1 | +class CustomFormsPluginMyprofileController < MyProfileController | ||
2 | + | ||
3 | + protect 'post_content', :profile | ||
4 | + def index | ||
5 | + @forms = CustomFormsPlugin::Form.from(profile) | ||
6 | + end | ||
7 | + | ||
8 | + def create | ||
9 | + @form = CustomFormsPlugin::Form.new(:profile => profile) | ||
10 | + @fields = [] | ||
11 | + @empty_field = CustomFormsPlugin::Field.new | ||
12 | + if request.post? | ||
13 | + begin | ||
14 | + @form.update_attributes!(params[:form]) | ||
15 | + params[:fields] = format_kind(params[:fields]) | ||
16 | + params[:fields] = format_choices(params[:fields]) | ||
17 | + params[:fields] = set_form_id(params[:fields], @form.id) | ||
18 | + create_fields(new_fields(params)) | ||
19 | + session['notice'] = _('Form created') | ||
20 | + redirect_to :action => 'index' | ||
21 | + rescue Exception => exception | ||
22 | + logger.error(exception.to_s) | ||
23 | + session['notice'] = _('Form could not be created') | ||
24 | + end | ||
25 | + end | ||
26 | + end | ||
27 | + | ||
28 | + def edit | ||
29 | + @form = CustomFormsPlugin::Form.find(params[:id]) | ||
30 | + @fields = @form.fields | ||
31 | + @empty_field = CustomFormsPlugin::TextField.new | ||
32 | + if request.post? | ||
33 | + begin | ||
34 | + @form.update_attributes!(params[:form]) | ||
35 | + params[:fields] = format_kind(params[:fields]) | ||
36 | + params[:fields] = format_choices(params[:fields]) | ||
37 | + remove_fields(params, @form) | ||
38 | + create_fields(new_fields(params)) | ||
39 | + update_fields(edited_fields(params)) | ||
40 | + session['notice'] = _('Form updated') | ||
41 | + redirect_to :action => 'index' | ||
42 | + rescue Exception => exception | ||
43 | + logger.error(exception.to_s) | ||
44 | + session['notice'] = _('Form could not be updated') | ||
45 | + end | ||
46 | + end | ||
47 | + end | ||
48 | + | ||
49 | + def remove | ||
50 | + @form = CustomFormsPlugin::Form.find(params[:id]) | ||
51 | + begin | ||
52 | + @form.destroy | ||
53 | + session[:notice] = _('Form removed') | ||
54 | + rescue | ||
55 | + session[:notice] = _('Form could not be removed') | ||
56 | + end | ||
57 | + redirect_to :action => 'index' | ||
58 | + end | ||
59 | + | ||
60 | + def submissions | ||
61 | + @form = CustomFormsPlugin::Form.find(params[:id]) | ||
62 | + @submissions = @form.submissions | ||
63 | + end | ||
64 | + | ||
65 | + def show_submission | ||
66 | + @submission = CustomFormsPlugin::Submission.find(params[:id]) | ||
67 | + @form = @submission.form | ||
68 | + end | ||
69 | + | ||
70 | + private | ||
71 | + | ||
72 | + def new_fields(params) | ||
73 | + result = params[:fields].map {|id, hash| hash.has_key?(:real_id) ? nil : hash}.compact | ||
74 | + result.delete_if {|field| field[:name].blank?} | ||
75 | + result | ||
76 | + end | ||
77 | + | ||
78 | + def edited_fields(params) | ||
79 | + params[:fields].map {|id, hash| hash.has_key?(:real_id) ? hash : nil}.compact | ||
80 | + end | ||
81 | + | ||
82 | + def create_fields(fields) | ||
83 | + fields.each do |field| | ||
84 | + case field[:type] | ||
85 | + when 'text_field' | ||
86 | + CustomFormsPlugin::TextField.create!(field) | ||
87 | + when 'select_field' | ||
88 | + CustomFormsPlugin::SelectField.create!(field) | ||
89 | + else | ||
90 | + CustomFormsPlugin::Field.create!(field) | ||
91 | + end | ||
92 | + end | ||
93 | + end | ||
94 | + | ||
95 | + def update_fields(fields) | ||
96 | + fields.each do |field_attrs| | ||
97 | + field = CustomFormsPlugin::Field.find(field_attrs.delete(:real_id)) | ||
98 | + field.attributes = field_attrs | ||
99 | + field.save! if field.changed? | ||
100 | + end | ||
101 | + end | ||
102 | + | ||
103 | + def format_kind(fields) | ||
104 | + fields.each do |id, field| | ||
105 | + next if field[:kind].blank? | ||
106 | + kind = field.delete(:kind) | ||
107 | + case kind | ||
108 | + when 'radio' | ||
109 | + field[:list] = false | ||
110 | + field[:multiple] = false | ||
111 | + when 'check_box' | ||
112 | + field[:list] = false | ||
113 | + field[:multiple] = true | ||
114 | + when 'select' | ||
115 | + field[:list] = true | ||
116 | + field[:multiple] = false | ||
117 | + when 'multiple_select' | ||
118 | + field[:list] = true | ||
119 | + field[:multiple] = true | ||
120 | + end | ||
121 | + end | ||
122 | + fields | ||
123 | + end | ||
124 | + | ||
125 | + def format_choices(fields) | ||
126 | + fields.each do |id, field| | ||
127 | + next if !field.has_key?(:choices) | ||
128 | + field[:choices] = field[:choices].map {|key, value| value}.inject({}) do |result, choice| | ||
129 | + hash = (choice[:name].blank? || choice[:value].blank?) ? {} : {choice[:name] => choice[:value]} | ||
130 | + result.merge!(hash) | ||
131 | + end | ||
132 | + end | ||
133 | + fields | ||
134 | + end | ||
135 | + | ||
136 | + def remove_fields(params, form) | ||
137 | + present_fields = params[:fields].map{|id, value| value}.collect {|field| field[:real_id]}.compact | ||
138 | + form.fields.each {|field| field.destroy if !present_fields.include?(field.id.to_s) } | ||
139 | + end | ||
140 | + | ||
141 | + def set_form_id(fields, form_id) | ||
142 | + fields.each do |id, field| | ||
143 | + field[:form_id] = form_id | ||
144 | + end | ||
145 | + fields | ||
146 | + end | ||
147 | +end |
plugins/custom_forms/controllers/custom_forms_plugin_profile_controller.rb
0 → 100644
@@ -0,0 +1,45 @@ | @@ -0,0 +1,45 @@ | ||
1 | +class CustomFormsPluginProfileController < ProfileController | ||
2 | + | ||
3 | + before_filter :has_access, :show | ||
4 | + | ||
5 | + def show | ||
6 | + @form = CustomFormsPlugin::Form.find(params[:id]) | ||
7 | + if user | ||
8 | + @submission ||= CustomFormsPlugin::Submission.find_by_form_id_and_profile_id(@form.id,user.id) | ||
9 | + @submission ||= CustomFormsPlugin::Submission.new(:form_id => @form.id, :profile_id => user.id) | ||
10 | + else | ||
11 | + @submission ||= CustomFormsPlugin::Submission.new(:form_id => @form.id) | ||
12 | + end | ||
13 | + if request.post? | ||
14 | + begin | ||
15 | + extend(CustomFormsPlugin::Helper) | ||
16 | + answers = build_answers(params[:submission], @form) | ||
17 | + failed_answers = answers.select {|answer| !answer.valid? } | ||
18 | + if failed_answers.empty? | ||
19 | + if !user | ||
20 | + @submission.author_name = params[:author_name] | ||
21 | + @submission.author_email = params[:author_email] | ||
22 | + end | ||
23 | + @submission.save! | ||
24 | + answers.map {|answer| answer.submission = @submission; answer.save!} | ||
25 | + else | ||
26 | + @submission.valid? | ||
27 | + failed_answers.each do |answer| | ||
28 | + @submission.errors.add(answer.field.name.to_sym, answer.errors[answer.field.slug.to_sym]) | ||
29 | + end | ||
30 | + end | ||
31 | + session[:notice] = _('Submission saved') | ||
32 | + redirect_to :action => 'show' | ||
33 | + rescue | ||
34 | + session[:notice] = _('Submission could not be saved') | ||
35 | + end | ||
36 | + end | ||
37 | + end | ||
38 | + | ||
39 | + private | ||
40 | + | ||
41 | + def has_access | ||
42 | + form = CustomFormsPlugin::Form.find(params[:id]) | ||
43 | + render_access_denied if !form.accessible_to(user) | ||
44 | + end | ||
45 | +end |
plugins/custom_forms/db/migrate/20120727162444_create_custom_forms_plugin_forms.rb
0 → 100644
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +class CreateCustomFormsPluginForms < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :custom_forms_plugin_forms do |t| | ||
4 | + t.string :name | ||
5 | + t.string :slug | ||
6 | + t.text :description | ||
7 | + t.references :profile | ||
8 | + t.datetime :begining | ||
9 | + t.datetime :ending | ||
10 | + t.boolean :report_submissions, :default => false | ||
11 | + t.boolean :on_membership, :default => false | ||
12 | + t.string :access | ||
13 | + t.timestamps | ||
14 | + end | ||
15 | + end | ||
16 | + | ||
17 | + def self.down | ||
18 | + drop_table :custom_forms_plugin_forms | ||
19 | + end | ||
20 | +end |
plugins/custom_forms/db/migrate/20120727174506_create_custom_forms_plugin_fields.rb
0 → 100644
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +class CreateCustomFormsPluginFields < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :custom_forms_plugin_fields do |t| | ||
4 | + t.string :name | ||
5 | + t.string :slug | ||
6 | + t.string :type | ||
7 | + t.string :default_value | ||
8 | + t.string :choices | ||
9 | + t.float :minimum | ||
10 | + t.float :maximum | ||
11 | + t.references :form | ||
12 | + t.boolean :mandatory, :default => false | ||
13 | + t.boolean :multiple | ||
14 | + t.boolean :list | ||
15 | + end | ||
16 | + end | ||
17 | + | ||
18 | + def self.down | ||
19 | + drop_table :custom_forms_plugin_fields | ||
20 | + end | ||
21 | +end |
plugins/custom_forms/db/migrate/20120727175250_create_custom_forms_plugin_answers.rb
0 → 100644
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +class CreateCustomFormsPluginAnswers < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :custom_forms_plugin_answers do |t| | ||
4 | + t.text :value | ||
5 | + t.references :field | ||
6 | + t.references :submission | ||
7 | + end | ||
8 | + end | ||
9 | + | ||
10 | + def self.down | ||
11 | + drop_table :custom_forms_plugin_answers | ||
12 | + end | ||
13 | +end |
plugins/custom_forms/db/migrate/20120727180512_create_custom_forms_plugin_submissions.rb
0 → 100644
@@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
1 | +class CreateCustomFormsPluginSubmissions < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :custom_forms_plugin_submissions do |t| | ||
4 | + t.string :author_name | ||
5 | + t.string :author_email | ||
6 | + t.references :profile | ||
7 | + t.references :form | ||
8 | + t.timestamps | ||
9 | + end | ||
10 | + end | ||
11 | + | ||
12 | + def self.down | ||
13 | + drop_table :custom_forms_plugin_submissions | ||
14 | + end | ||
15 | +end |
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +require 'ext/role_assignment_trigger' | ||
2 | + | ||
3 | +class CustomFormsPlugin < Noosfero::Plugin | ||
4 | + | ||
5 | + def self.plugin_name | ||
6 | + "Custom Forms" | ||
7 | + end | ||
8 | + | ||
9 | + def self.plugin_description | ||
10 | + _("Enables the creation of forms.") | ||
11 | + end | ||
12 | + | ||
13 | + def stylesheet? | ||
14 | + true | ||
15 | + end | ||
16 | + | ||
17 | + def control_panel_buttons | ||
18 | + {:title => _('Manage Forms'), :icon => 'custom-forms', :url => {:controller => 'custom_forms_plugin_myprofile'}} | ||
19 | + end | ||
20 | + | ||
21 | +end |
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +class CustomFormsPlugin::Answer < Noosfero::Plugin::ActiveRecord | ||
2 | + belongs_to :field, :class_name => 'CustomFormsPlugin::Field' | ||
3 | + belongs_to :submission, :class_name => 'CustomFormsPlugin::Submission' | ||
4 | + | ||
5 | + validates_presence_of :field | ||
6 | + validate :value_mandatory, :if => 'field.present?' | ||
7 | + | ||
8 | + def value_mandatory | ||
9 | + if field.mandatory && value.blank? | ||
10 | + errors.add(field.slug.to_sym, _("is mandatory.").fix_i18n) | ||
11 | + end | ||
12 | + end | ||
13 | +end | ||
14 | + |
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +class CustomFormsPlugin::Field < ActiveRecord::Base | ||
2 | + set_table_name :custom_forms_plugin_fields | ||
3 | + | ||
4 | + validates_presence_of :form, :name | ||
5 | + validates_uniqueness_of :slug, :scope => :form_id | ||
6 | + | ||
7 | + belongs_to :form, :class_name => 'CustomFormsPlugin::Form', :dependent => :destroy | ||
8 | + has_many :answers, :class_name => 'CustomFormsPlugin::Answer' | ||
9 | + | ||
10 | + serialize :choices, Hash | ||
11 | + | ||
12 | + before_validation do |field| | ||
13 | + field.slug = field.name.to_slug if field.name.present? | ||
14 | + end | ||
15 | +end | ||
16 | + |
@@ -0,0 +1,70 @@ | @@ -0,0 +1,70 @@ | ||
1 | +class CustomFormsPlugin::Form < Noosfero::Plugin::ActiveRecord | ||
2 | + belongs_to :profile | ||
3 | + | ||
4 | + has_many :fields, :class_name => 'CustomFormsPlugin::Field' | ||
5 | + has_many :submissions, :class_name => 'CustomFormsPlugin::Submission' | ||
6 | + | ||
7 | + serialize :access | ||
8 | + | ||
9 | + validates_presence_of :profile, :name | ||
10 | + validates_uniqueness_of :slug, :scope => :profile_id | ||
11 | + validate :access_format | ||
12 | + | ||
13 | + before_validation do |form| | ||
14 | + form.slug = form.name.to_slug if form.name.present? | ||
15 | + form.access = nil if form.access.blank? | ||
16 | + end | ||
17 | + | ||
18 | + named_scope :from, lambda {|profile| {:conditions => {:profile_id => profile.id}}} | ||
19 | + named_scope :on_memberships, {:conditions => {:on_membership => true}} | ||
20 | +=begin | ||
21 | + named_scope :accessible_to lambda do |profile| | ||
22 | + #TODO should verify is profile is associated with the form owner | ||
23 | + profile_associated = ??? | ||
24 | + {:conditions => [" | ||
25 | + access IS NULL OR | ||
26 | + (access='logged' AND :profile_present) OR | ||
27 | + (access='associated' AND :profile_associated) OR | ||
28 | + :profile_id in access | ||
29 | + ", {:profile_present => profile.present?, :profile_associated => ???, :profile_id => profile.id}]} | ||
30 | + end | ||
31 | +=end | ||
32 | + | ||
33 | + def expired? | ||
34 | + (begining.present? && Time.now < begining) || (ending.present? && Time.now > ending) | ||
35 | + end | ||
36 | + | ||
37 | + def accessible_to(target) | ||
38 | + return true if access.nil? || target == profile | ||
39 | + return false if target.nil? | ||
40 | + return true if access == 'logged' | ||
41 | + return true if access == 'associated' && ((profile.organization? && profile.members.include?(target)) || (profile.person? && profile.friends.include?(target))) | ||
42 | + return true if access.kind_of?(Integer) && target.id == access | ||
43 | + return true if access.kind_of?(Array) && access.include?(target.id) | ||
44 | + end | ||
45 | + | ||
46 | + private | ||
47 | + | ||
48 | + def access_format | ||
49 | + if access.present? | ||
50 | + if access.kind_of?(String) | ||
51 | + if access != 'logged' && access != 'associated' | ||
52 | + errors.add(:access, _('Invalid string format of access.')) | ||
53 | + end | ||
54 | + elsif access.kind_of?(Integer) | ||
55 | + if !Profile.exists?(access) | ||
56 | + errors.add(:access, _('There is no profile with the provided id.')) | ||
57 | + end | ||
58 | + elsif access.kind_of?(Array) | ||
59 | + access.each do |value| | ||
60 | + if !value.kind_of?(Integer) || !Profile.exists?(value) | ||
61 | + errors.add(:access, _('There is no profile with the provided id.')) | ||
62 | + break | ||
63 | + end | ||
64 | + end | ||
65 | + else | ||
66 | + errors.add(:access, _('Invalid type format of access.')) | ||
67 | + end | ||
68 | + end | ||
69 | + end | ||
70 | +end |
@@ -0,0 +1,119 @@ | @@ -0,0 +1,119 @@ | ||
1 | +module CustomFormsPlugin::Helper | ||
2 | + def access_text(form) | ||
3 | + return _('Public') if form.access.nil? | ||
4 | + return _('Logged users') if form.access == 'logged' | ||
5 | + if form.access == 'associated' | ||
6 | + return _('Members') if form.profile.organization? | ||
7 | + return _('Friends') if form.profile.person? | ||
8 | + end | ||
9 | + return _('Custom') | ||
10 | + end | ||
11 | + | ||
12 | + def period_range(form) | ||
13 | + if form.begining.blank? && form.ending.blank? | ||
14 | + _('Always') | ||
15 | + elsif form.begining.present? && form.ending.blank? | ||
16 | + ('From %s') % time_format(form.begining) | ||
17 | + elsif form.begining.blank? && form.ending.present? | ||
18 | + _('Until %s') % time_format(form.ending) | ||
19 | + elsif form.begining.present? && form.ending.present? | ||
20 | + _('From %s until %s') % [time_format(form.begining), time_format(form.ending)] | ||
21 | + end | ||
22 | + end | ||
23 | + | ||
24 | + def time_format(time) | ||
25 | + minutes = (time.min == 0) ? '' : ':%M' | ||
26 | + hour = (time.hour == 0 && minutes.blank?) ? '' : ' %H' | ||
27 | + h = hour.blank? ? '' : 'h' | ||
28 | + time.strftime("%Y-%m-%d#{hour+minutes+h}") | ||
29 | + end | ||
30 | + | ||
31 | + # TODO add the custom option that should offer the user the hability to | ||
32 | + # choose the profiles one by one, using something like tokeninput | ||
33 | + def access_options(profile) | ||
34 | + associated = profile.organization? ? _('Members') : _('Friends') | ||
35 | + [ | ||
36 | + [_('Public'), nil ], | ||
37 | + [_('Logged users'), 'logged' ], | ||
38 | + [ associated, 'associated'], | ||
39 | + ] | ||
40 | + end | ||
41 | + | ||
42 | + def type_options | ||
43 | + [ | ||
44 | + [_('Text'), 'text_field' ], | ||
45 | + [_('Select'), 'select_field'] | ||
46 | + ] | ||
47 | + end | ||
48 | + | ||
49 | + def type_to_label(type) | ||
50 | + map = { | ||
51 | + 'text_field' => _('Text'), | ||
52 | + 'select_field' => _('Select') | ||
53 | + } | ||
54 | + map[type_for_options(type)] | ||
55 | + end | ||
56 | + | ||
57 | + def type_for_options(type) | ||
58 | + type.to_s.split(':').last.underscore | ||
59 | + end | ||
60 | + | ||
61 | + def display_custom_field(field, submission, form) | ||
62 | + answer = submission.answers.select{|answer| answer.field == field}.first | ||
63 | + field_tag = send("display_#{type_for_options(field.class)}",field, answer, form) | ||
64 | + if field.mandatory? && !radio_button?(field) && !check_box?(field) && submission.id.nil? | ||
65 | + required(labelled_form_field(field.name, field_tag)) | ||
66 | + else | ||
67 | + labelled_form_field(field.name, field_tag) | ||
68 | + end | ||
69 | + end | ||
70 | + | ||
71 | + def display_text_field(field, answer, form) | ||
72 | + value = answer.present? ? answer.value : field.default_value | ||
73 | + text_field(form, field.name.to_slug, :value => value, :disabled => answer.present?) | ||
74 | + end | ||
75 | + | ||
76 | + def display_select_field(field, answer, form) | ||
77 | + if field.list && field.multiple | ||
78 | + selected = answer.present? ? answer.value.split(',') : [] | ||
79 | + select_tag "#{form}[#{field.name.to_slug}]", options_for_select(field.choices.to_a, selected), :multiple => true, :size => field.choices.size, :disabled => answer.present? | ||
80 | + elsif !field.list && field.multiple | ||
81 | + field.choices.map do |name, value| | ||
82 | + default = answer.present? ? answer.value.split(',').include?(value) : false | ||
83 | + labelled_check_box name, "#{form}[#{field.name.to_slug}][#{value}]", '1', default, :disabled => answer.present? | ||
84 | + end.join("\n") | ||
85 | + elsif field.list && !field.multiple | ||
86 | + selected = answer.present? ? answer.value.split(',') : [] | ||
87 | + select_tag "#{form}[#{field.name.to_slug}]", options_for_select([['','']] + field.choices.to_a, selected), :disabled => answer.present? | ||
88 | + elsif !field.list && !field.multiple | ||
89 | + field.choices.map do |name, value| | ||
90 | + default = answer.present? ? answer.value == value : true | ||
91 | + labelled_radio_button name, "#{form}[#{field.name.to_slug}]", value, default, :disabled => answer.present? | ||
92 | + end.join("\n") | ||
93 | + end | ||
94 | + end | ||
95 | + | ||
96 | + def radio_button?(field) | ||
97 | + type_for_options(field.class) == 'select_field' && !field.list && !field.multiple | ||
98 | + end | ||
99 | + | ||
100 | + def check_box?(field) | ||
101 | + type_for_options(field.class) == 'select_field' && !field.list && field.multiple | ||
102 | + end | ||
103 | + | ||
104 | + def build_answers(submission, form) | ||
105 | + answers = [] | ||
106 | + submission.each do |slug, value| | ||
107 | + field = form.fields.select {|field| field.slug==slug}.first | ||
108 | + if value.kind_of?(String) | ||
109 | + final_value = value | ||
110 | + elsif value.kind_of?(Array) | ||
111 | + final_value = value.join(',') | ||
112 | + elsif value.kind_of?(Hash) | ||
113 | + final_value = value.map {|option, present| present == '1' ? option : nil}.compact.join(',') | ||
114 | + end | ||
115 | + answers << CustomFormsPlugin::Answer.new(:field => field, :value => final_value) | ||
116 | + end | ||
117 | + answers | ||
118 | + end | ||
119 | +end |
plugins/custom_forms/lib/custom_forms_plugin/membership_survey.rb
0 → 100644
@@ -0,0 +1,47 @@ | @@ -0,0 +1,47 @@ | ||
1 | +class CustomFormsPlugin::MembershipSurvey < Task | ||
2 | + | ||
3 | + settings_items :form_id, :submission | ||
4 | + validates_presence_of :form_id | ||
5 | + | ||
6 | + include CustomFormsPlugin::Helper | ||
7 | + | ||
8 | + def perform | ||
9 | + form = CustomFormsPlugin::Form.find(form_id) | ||
10 | + answers = build_answers(submission, form) | ||
11 | + s = CustomFormsPlugin::Submission.create!(:form => form, :profile => target) | ||
12 | + answers.map {|answer| answer.submission = s; answer.save!} | ||
13 | + end | ||
14 | + | ||
15 | + def title | ||
16 | + _("Membership survey") | ||
17 | + end | ||
18 | + | ||
19 | + def subject | ||
20 | + nil | ||
21 | + end | ||
22 | + | ||
23 | + def linked_subject | ||
24 | + nil | ||
25 | + end | ||
26 | + | ||
27 | + def information | ||
28 | + {:message => _('%{requestor} wants you to fill in some information.')} | ||
29 | + end | ||
30 | + | ||
31 | + def accept_details | ||
32 | + true | ||
33 | + end | ||
34 | + | ||
35 | + def icon | ||
36 | + {:type => :profile_image, :profile => requestor, :url => requestor.url} | ||
37 | + end | ||
38 | + | ||
39 | + def target_notification_message | ||
40 | + _('After joining %{requestor}, the administrators of this organization | ||
41 | + wants you to fill in some further information.') % {:requestor => requestor.name} | ||
42 | + end | ||
43 | + | ||
44 | + def target_notification_description | ||
45 | + _('%{requestor} wants to fill in some further information.') % {:requestor => requestor.name} | ||
46 | + end | ||
47 | +end |
plugins/custom_forms/lib/custom_forms_plugin/select_field.rb
0 → 100644
plugins/custom_forms/lib/custom_forms_plugin/submission.rb
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +class CustomFormsPlugin::Submission < Noosfero::Plugin::ActiveRecord | ||
2 | + belongs_to :form, :class_name => 'CustomFormsPlugin::Form' | ||
3 | + belongs_to :profile | ||
4 | + | ||
5 | + has_many :answers, :class_name => 'CustomFormsPlugin::Answer' | ||
6 | + | ||
7 | + validates_presence_of :form | ||
8 | + validates_presence_of :author_name, :author_email, :if => lambda {|submission| submission.profile.nil?} | ||
9 | + validates_uniqueness_of :author_email, :scope => :form_id, :allow_nil => true | ||
10 | + validates_format_of :author_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|submission| !submission.author_email.blank?}) | ||
11 | +end | ||
12 | + |
plugins/custom_forms/lib/custom_forms_plugin/text_field.rb
0 → 100644
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +module RoleAssignmentTrigger | ||
2 | + def self.included(base) | ||
3 | + base.class_eval do | ||
4 | + before_create do |ra| | ||
5 | + profile = ra.resource | ||
6 | + person = ra.accessor | ||
7 | + ok = !profile.nil? && !person.nil? && profile.environment.present? | ||
8 | + if ok && profile.environment.plugin_enabled?(CustomFormsPlugin) && !person.is_member_of?(profile) | ||
9 | + CustomFormsPlugin::Form.from(profile).on_memberships.each do |form| | ||
10 | + CustomFormsPlugin::MembershipSurvey.create!(:requestor => profile, :target => person, :form_id => form.id) | ||
11 | + end | ||
12 | + end | ||
13 | + end | ||
14 | + | ||
15 | + after_destroy do |ra| | ||
16 | + profile = ra.resource | ||
17 | + person = ra.accessor | ||
18 | + ok = !profile.nil? && !person.nil? && profile.environment.present? | ||
19 | + if ok && profile.environment.plugin_enabled?(CustomFormsPlugin) && !person.is_member_of?(profile) | ||
20 | + CustomFormsPlugin::Form.from(profile).on_memberships.each do |form| | ||
21 | + task = person.tasks.pending.select {|task| task.kind_of?(CustomFormsPlugin::MembershipSurvey) && task.form_id == form.id}.first | ||
22 | + task.cancel if task | ||
23 | + end | ||
24 | + end | ||
25 | + end | ||
26 | + end | ||
27 | + end | ||
28 | +end | ||
29 | + | ||
30 | +RoleAssignment.send :include, RoleAssignmentTrigger |
@@ -0,0 +1,141 @@ | @@ -0,0 +1,141 @@ | ||
1 | +jQuery('.icon-edit').live('click', function() { | ||
2 | + elem = this; | ||
3 | + jQuery.fn.colorbox({ | ||
4 | + overlayClose: false, | ||
5 | + escKey: false, | ||
6 | + inline: true, | ||
7 | + href: function(){ | ||
8 | + id = jQuery(elem).attr('field_id'); | ||
9 | + type = jQuery('#fields_'+id+'_type').val().split('_')[0]; | ||
10 | + selector = '#edit-'+type+'-'+id | ||
11 | + jQuery(selector).show(); | ||
12 | + return selector | ||
13 | + } | ||
14 | + }); | ||
15 | + return false; | ||
16 | +}); | ||
17 | + | ||
18 | +jQuery('.remove-field').live('click', function(){ | ||
19 | + id = jQuery(this).attr('field_id'); | ||
20 | + jQuery('#field-'+id).slideDown(function(){ | ||
21 | + jQuery('#field-'+id).remove(); | ||
22 | + }); | ||
23 | + return false | ||
24 | +}); | ||
25 | + | ||
26 | +jQuery('.remove-option').live('click', function(){ | ||
27 | + field_id = jQuery(this).attr('field_id'); | ||
28 | + option_id = jQuery(this).attr('option_id'); | ||
29 | + selector = '#field-'+field_id+'-option-'+option_id | ||
30 | + jQuery(selector).slideDown(function(){ | ||
31 | + jQuery(selector).remove(); | ||
32 | + jQuery.colorbox.resize(); | ||
33 | + }); | ||
34 | + return false | ||
35 | +}); | ||
36 | + | ||
37 | +function updateEditText(id){ | ||
38 | + new_id = id+1 | ||
39 | + jQuery('#edit-text-'+id).attr('id', 'edit-text-'+new_id); | ||
40 | + input = jQuery('#edit-text-'+new_id+' input'); | ||
41 | + jQuery('#edit-text-'+new_id+' .colorbox-ok-button').attr('div_id', 'edit-text-'+new_id); | ||
42 | + input.attr('id', input.attr('id').replace(id,new_id)); | ||
43 | + input.attr('name', input.attr('name').replace(id,new_id)); | ||
44 | + label = jQuery('#edit-text-'+new_id+' label'); | ||
45 | + label.attr('for', label.attr('for').replace(id,new_id)); | ||
46 | +} | ||
47 | + | ||
48 | +function updateEditSelect(id){ | ||
49 | + new_id = id+1 | ||
50 | + jQuery('#edit-select-'+id).attr('id', 'edit-select-'+new_id); | ||
51 | + jQuery('#edit-select-'+new_id+' .colorbox-ok-button').attr('div_id', 'edit-select-'+new_id); | ||
52 | + jQuery('tr[id^=field-'+id+'-option').each(function(id, element){ | ||
53 | + jQuery(element).attr('id', jQuery(element).attr('id').replace('field-'+id,'field-'+new_id)); | ||
54 | + }); | ||
55 | + jQuery('#edit-select-'+new_id+' label').each(function(index, element){ | ||
56 | + label = jQuery(element); | ||
57 | + label.attr('for', label.attr('for').replace(id,new_id)); | ||
58 | + }); | ||
59 | + jQuery('#edit-select-'+new_id+' input').each(function(index, element){ | ||
60 | + input = jQuery(element); | ||
61 | + input.attr('id', input.attr('id').replace(id,new_id)); | ||
62 | + input.attr('name', input.attr('name').replace(id,new_id)); | ||
63 | + }); | ||
64 | + jQuery('#edit-select-'+new_id+' .remove-option').each(function(index, element){ | ||
65 | + jQuery(element).attr('field_id',new_id); | ||
66 | + }); | ||
67 | + jQuery('#edit-select-'+new_id+' .new-option').attr('field_id',new_id); | ||
68 | + jQuery('#edit-select-'+new_id+' #empty-option-'+id).attr('id','empty-option-'+new_id); | ||
69 | +} | ||
70 | + | ||
71 | +function updateEmptyField(id){ | ||
72 | + id = parseInt(id); | ||
73 | + empty_field = jQuery('#empty-field'); | ||
74 | + empty_field.attr('last_id', (id + 1).toString()); | ||
75 | + jQuery('#empty-field input').each(function(index, element){ | ||
76 | + new_id = jQuery(element).attr('id').replace(id,id+1); | ||
77 | + jQuery(element).attr('id', new_id); | ||
78 | + new_name = jQuery(element).attr('name').replace(id,id+1); | ||
79 | + jQuery(element).attr('name', new_name); | ||
80 | + }); | ||
81 | + jQuery('#empty-field select').each(function(index, element){ | ||
82 | + new_id = jQuery(element).attr('id').replace(id,id+1); | ||
83 | + jQuery(element).attr('id', new_id); | ||
84 | + new_name = jQuery(element).attr('name').replace(id,id+1); | ||
85 | + jQuery(element).attr('name', new_name); | ||
86 | + }); | ||
87 | + jQuery('#empty-field a').each(function(index, element){ | ||
88 | + jQuery(element).attr('field_id', id+1); | ||
89 | + }); | ||
90 | + updateEditText(id); | ||
91 | + updateEditSelect(id); | ||
92 | +} | ||
93 | + | ||
94 | +function updateEmptyOption(field_id, option_id){ | ||
95 | + field_id = parseInt(field_id); | ||
96 | + option_id = parseInt(option_id); | ||
97 | + new_option_id = option_id+1; | ||
98 | + empty_option = jQuery('#empty-option-'+field_id); | ||
99 | + empty_option.attr('option_id',new_option_id); | ||
100 | + jQuery('#empty-option-'+field_id+' .remove-option').attr('option_id', new_option_id); | ||
101 | + | ||
102 | + name_id = ' #fields_'+field_id+'_choices_'+option_id+'_name'; | ||
103 | + jQuery('#empty-option-'+field_id+name_id).attr('name', 'fields['+field_id+'][choices]['+new_option_id+'][name]'); | ||
104 | + jQuery('#empty-option-'+field_id+name_id).attr('id', 'fields_'+field_id+'_choices_'+new_option_id+'_name'); | ||
105 | + | ||
106 | + value_id = ' #fields_'+field_id+'_choices_'+option_id+'_value'; | ||
107 | + jQuery('#empty-option-'+field_id+value_id).attr('name', 'fields['+field_id+'][choices]['+new_option_id+'][value]'); | ||
108 | + jQuery('#empty-option-'+field_id+value_id).attr('id', 'fields_'+field_id+'_choices_'+new_option_id+'_value'); | ||
109 | +} | ||
110 | + | ||
111 | +jQuery('#new-field').live('click', function(){ | ||
112 | + empty_field = jQuery('#empty-field'); | ||
113 | + id = empty_field.attr('last_id'); | ||
114 | + edit_text = jQuery('#edit-text-'+id); | ||
115 | + edit_select = jQuery('#edit-select-'+id); | ||
116 | + new_field = empty_field.clone(); | ||
117 | + new_field.attr('id','field-'+id); | ||
118 | + new_field.insertBefore(empty_field).slideDown(); | ||
119 | + edit_text.clone().insertAfter(edit_text); | ||
120 | + edit_select.clone().insertAfter(edit_select); | ||
121 | + updateEmptyField(id); | ||
122 | + return false | ||
123 | +}); | ||
124 | + | ||
125 | +jQuery('.new-option').live('click', function(){ | ||
126 | + field_id = jQuery(this).attr('field_id'); | ||
127 | + empty_option = jQuery('#empty-option-'+field_id); | ||
128 | + option_id = empty_option.attr('option_id'); | ||
129 | + new_option = empty_option.clone(); | ||
130 | + new_option.attr('id','field-'+field_id+'-option-'+option_id); | ||
131 | + new_option.insertBefore(empty_option).slideDown(); | ||
132 | + jQuery.colorbox.resize(); | ||
133 | + updateEmptyOption(field_id, option_id); | ||
134 | + return false | ||
135 | +}); | ||
136 | + | ||
137 | +jQuery('.colorbox-ok-button').live('click', function(){ | ||
138 | + jQuery('#'+jQuery(this).attr('div_id')).hide(); | ||
139 | + jQuery.colorbox.close(); | ||
140 | + return false | ||
141 | +}); |
4.05 KB
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +.controller-profile_editor a.control-panel-custom-forms, | ||
2 | +.controller-profile_editor .msie6 a.control-panel-custom-forms { | ||
3 | + background-image: url(/plugins/custom_forms/icons/custom-forms.png) | ||
4 | +} | ||
5 | + | ||
6 | +.action-table { | ||
7 | + width: 100%; | ||
8 | + overflow: hidden; | ||
9 | +} | ||
10 | + | ||
11 | +.action-table th, | ||
12 | +.action-table td{ | ||
13 | + text-align: center; | ||
14 | +} | ||
15 | + | ||
16 | +.action-table td{ | ||
17 | + cursor: move; | ||
18 | +} | ||
19 | + | ||
20 | +.action-table .actions{ | ||
21 | + white-space: nowrap; | ||
22 | +} | ||
23 | + | ||
24 | +.action-table .new-item{ | ||
25 | + background-color: #EEE; | ||
26 | +} | ||
27 | + | ||
28 | +.edit-information { | ||
29 | + display: none; | ||
30 | +} |
plugins/custom_forms/test/functional/custom_forms_plugin_myprofile_controller_test.rb
0 → 100644
@@ -0,0 +1,114 @@ | @@ -0,0 +1,114 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
2 | +require File.dirname(__FILE__) + '/../../controllers/custom_forms_plugin_myprofile_controller' | ||
3 | + | ||
4 | +# Re-raise errors caught by the controller. | ||
5 | +class CustomFormsPluginMyprofileController; def rescue_action(e) raise e end; end | ||
6 | + | ||
7 | +class CustomFormsPluginMyprofileControllerTest < ActionController::TestCase | ||
8 | + def setup | ||
9 | + @controller = CustomFormsPluginMyprofileController.new | ||
10 | + @request = ActionController::TestRequest.new | ||
11 | + @response = ActionController::TestResponse.new | ||
12 | + @profile = create_user('profile').person | ||
13 | + login_as(@profile.identifier) | ||
14 | + environment = Environment.default | ||
15 | + environment.enable_plugin(CustomFormsPlugin) | ||
16 | + end | ||
17 | + | ||
18 | + attr_reader :profile | ||
19 | + | ||
20 | + should 'list forms associated with profile' do | ||
21 | + another_profile = fast_create(Profile) | ||
22 | + f1 = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software') | ||
23 | + f2 = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Open Source') | ||
24 | + f3 = CustomFormsPlugin::Form.create!(:profile => another_profile, :name => 'Open Source') | ||
25 | + | ||
26 | + get :index, :profile => profile.identifier | ||
27 | + | ||
28 | + assert_includes assigns(:forms), f1 | ||
29 | + assert_includes assigns(:forms), f2 | ||
30 | + assert_not_includes assigns(:forms), f3 | ||
31 | + end | ||
32 | + | ||
33 | + should 'destroy form' do | ||
34 | + form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software') | ||
35 | + assert CustomFormsPlugin::Form.exists?(form.id) | ||
36 | + post :remove, :profile => profile.identifier, :id => form.id | ||
37 | + assert !CustomFormsPlugin::Form.exists?(form.id) | ||
38 | + end | ||
39 | + | ||
40 | + should 'create a form' do | ||
41 | + format = '%Y-%m-%d %H:%M' | ||
42 | + begining = Time.now.strftime(format) | ||
43 | + ending = (Time.now + 1.day).strftime('%Y-%m-%d %H:%M') | ||
44 | + assert_difference CustomFormsPlugin::Form, :count, 1 do | ||
45 | + post :create, :profile => profile.identifier, | ||
46 | + :form => { | ||
47 | + :name => 'My Form', | ||
48 | + :access => 'logged', | ||
49 | + :begining => begining, | ||
50 | + :ending => ending, | ||
51 | + :description => 'Cool form'}, | ||
52 | + :fields => { | ||
53 | + 1 => { | ||
54 | + :name => 'Name', | ||
55 | + :default_value => 'Jack', | ||
56 | + :type => 'text_field' | ||
57 | + }, | ||
58 | + 2 => { | ||
59 | + :name => 'Color', | ||
60 | + :list => '1', | ||
61 | + :type => 'select_field', | ||
62 | + :choices => { | ||
63 | + 1 => {:name => 'Red', :value => 'red'}, | ||
64 | + 2 => {:name => 'Blue', :value => 'blue'}, | ||
65 | + 3 => {:name => 'Black', :value => 'black'} | ||
66 | + } | ||
67 | + } | ||
68 | + } | ||
69 | + end | ||
70 | + | ||
71 | + form = CustomFormsPlugin::Form.find_by_name('My Form') | ||
72 | + assert_equal 'logged', form.access | ||
73 | + assert_equal begining, form.begining.strftime(format) | ||
74 | + assert_equal ending, form.ending.strftime(format) | ||
75 | + assert_equal 'Cool form', form.description | ||
76 | + assert_equal 2, form.fields.count | ||
77 | + | ||
78 | + f1 = form.fields.first | ||
79 | + f2 = form.fields.last | ||
80 | + | ||
81 | + assert_equal 'Name', f1.name | ||
82 | + assert_equal 'Jack', f1.default_value | ||
83 | + assert f1.kind_of?(CustomFormsPlugin::TextField) | ||
84 | + | ||
85 | + assert_equal 'Color', f2.name | ||
86 | + assert_equal 'red', f2.choices['Red'] | ||
87 | + assert_equal 'blue', f2.choices['Blue'] | ||
88 | + assert_equal 'black', f2.choices['Black'] | ||
89 | + assert f2.list | ||
90 | + assert f2.kind_of?(CustomFormsPlugin::SelectField) | ||
91 | + end | ||
92 | + | ||
93 | + should 'edit a form' do | ||
94 | + form = CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software') | ||
95 | + field = CustomFormsPlugin::TextField.create!(:form => form, :name => 'License') | ||
96 | + format = '%Y-%m-%d %H:%M' | ||
97 | + begining = Time.now.strftime(format) | ||
98 | + ending = (Time.now + 1.day).strftime('%Y-%m-%d %H:%M') | ||
99 | + | ||
100 | + post :edit, :profile => profile.identifier, :id => form.id, | ||
101 | + :form => {:name => 'My Form', :access => 'logged', :begining => begining, :ending => ending, :description => 'Cool form'}, | ||
102 | + :fields => {1 => {:real_id => field.id.to_s, :name => 'Source'}} | ||
103 | + | ||
104 | + form.reload | ||
105 | + field.reload | ||
106 | + | ||
107 | + assert_equal 'logged', form.access | ||
108 | + assert_equal begining, form.begining.strftime(format) | ||
109 | + assert_equal ending, form.ending.strftime(format) | ||
110 | + assert_equal 'Cool form', form.description | ||
111 | + assert_equal 'Source', field.name | ||
112 | + end | ||
113 | +end | ||
114 | + |
plugins/custom_forms/test/unit/custom_forms_plugin/answer_test.rb
0 → 100644
@@ -0,0 +1,38 @@ | @@ -0,0 +1,38 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class CustomFormsPlugin::AnswerTest < ActiveSupport::TestCase | ||
4 | + should 'validates presence of field' do | ||
5 | + answer = CustomFormsPlugin::Answer.new | ||
6 | + answer.valid? | ||
7 | + assert answer.errors.invalid?(:field) | ||
8 | + | ||
9 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | ||
10 | + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) | ||
11 | + answer.field = field | ||
12 | + answer.valid? | ||
13 | + assert !answer.errors.invalid?(:field) | ||
14 | + end | ||
15 | + | ||
16 | + should 'belong to a submission' do | ||
17 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | ||
18 | + submission = CustomFormsPlugin::Submission.create!(:form => form, :profile => fast_create(Profile)) | ||
19 | + answer = CustomFormsPlugin::Answer.new | ||
20 | + answer.submission = submission | ||
21 | + | ||
22 | + assert_equal submission, answer.submission | ||
23 | + end | ||
24 | + | ||
25 | + should 'require presence of value if field is mandatory' do | ||
26 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | ||
27 | + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form, :mandatory => true) | ||
28 | + answer = CustomFormsPlugin::Answer.new(:field => field) | ||
29 | + answer.valid? | ||
30 | + assert answer.errors.invalid?(field.slug.to_sym) | ||
31 | + | ||
32 | + answer.value = "GPL" | ||
33 | + answer.valid? | ||
34 | + assert !answer.errors.invalid?(field.slug.to_sym) | ||
35 | + end | ||
36 | + | ||
37 | +end | ||
38 | + |
plugins/custom_forms/test/unit/custom_forms_plugin/field_test.rb
0 → 100644
@@ -0,0 +1,64 @@ | @@ -0,0 +1,64 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class CustomFormsPlugin::FieldTest < ActiveSupport::TestCase | ||
4 | + should 'validate presence of form' do | ||
5 | + field = CustomFormsPlugin::Field.new | ||
6 | + field.valid? | ||
7 | + assert field.errors.invalid?(:form) | ||
8 | + assert field.errors.invalid?(:name) | ||
9 | + | ||
10 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | ||
11 | + field.form = form | ||
12 | + field.name = 'License' | ||
13 | + field.valid? | ||
14 | + assert !field.errors.invalid?(:form) | ||
15 | + assert !field.errors.invalid?(:name) | ||
16 | + end | ||
17 | + | ||
18 | + should 'set slug before validation based on name' do | ||
19 | + field = CustomFormsPlugin::Field.new(:name => 'Name') | ||
20 | + field.valid? | ||
21 | + assert_equal field.name.to_slug, field.slug | ||
22 | + end | ||
23 | + | ||
24 | + should 'validate uniqueness of slug scoped on the form' do | ||
25 | + form1 = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | ||
26 | + form2 = CustomFormsPlugin::Form.create!(:name => 'Open Source', :profile => fast_create(Profile)) | ||
27 | + f1 = CustomFormsPlugin::Field.create!(:name => 'License', :form => form1) | ||
28 | + f2 = CustomFormsPlugin::Field.new(:name => 'License', :form => form1) | ||
29 | + f3 = CustomFormsPlugin::Field.new(:name => 'License', :form => form2) | ||
30 | + | ||
31 | + f2.valid? | ||
32 | + f3.valid? | ||
33 | + | ||
34 | + assert f2.errors.invalid?(:slug) | ||
35 | + assert !f3.errors.invalid?(:slug) | ||
36 | + end | ||
37 | + | ||
38 | + should 'set mandatory field as false by default' do | ||
39 | + field = CustomFormsPlugin::Field.new | ||
40 | + assert !field.mandatory | ||
41 | + end | ||
42 | + | ||
43 | + should 'have answers' do | ||
44 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | ||
45 | + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) | ||
46 | + a1 = CustomFormsPlugin::Answer.create!(:field => field) | ||
47 | + a2 = CustomFormsPlugin::Answer.create!(:field => field) | ||
48 | + | ||
49 | + assert_includes field.answers, a1 | ||
50 | + assert_includes field.answers, a2 | ||
51 | + end | ||
52 | + | ||
53 | + should 'serialize choices into a hash' do | ||
54 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | ||
55 | + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) | ||
56 | + field.choices = {'First' => 1, 'Second' => 2, 'Third' => 3} | ||
57 | + field.save! | ||
58 | + | ||
59 | + assert_equal 1, field.choices['First'] | ||
60 | + assert_equal 2, field.choices['Second'] | ||
61 | + assert_equal 3, field.choices['Third'] | ||
62 | + end | ||
63 | +end | ||
64 | + |
plugins/custom_forms/test/unit/custom_forms_plugin/form_test.rb
0 → 100644
@@ -0,0 +1,172 @@ | @@ -0,0 +1,172 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class CustomFormsPlugin::FormTest < ActiveSupport::TestCase | ||
4 | + should 'validates presence of a profile and a name' do | ||
5 | + form = CustomFormsPlugin::Form.new | ||
6 | + form.valid? | ||
7 | + assert form.errors.invalid?(:profile) | ||
8 | + assert form.errors.invalid?(:name) | ||
9 | + | ||
10 | + form.profile = fast_create(Profile) | ||
11 | + form.name = 'Free Software' | ||
12 | + form.valid? | ||
13 | + assert !form.errors.invalid?(:profile) | ||
14 | + assert !form.errors.invalid?(:name) | ||
15 | + end | ||
16 | + | ||
17 | + should 'have many fields including fields subclasses' do | ||
18 | + form = CustomFormsPlugin::Form.create!(:profile => fast_create(Profile), :name => 'Free Software') | ||
19 | + f1 = CustomFormsPlugin::Field.create!(:form => form, :name => 'License') | ||
20 | + f2 = CustomFormsPlugin::Field.create!(:form => form, :name => 'Code') | ||
21 | + f3 = CustomFormsPlugin::TextField.create!(:form => form, :name => 'Developer') | ||
22 | + | ||
23 | + assert_includes form.fields, f1 | ||
24 | + assert_includes form.fields, f2 | ||
25 | + assert_includes form.fields, f3 | ||
26 | + end | ||
27 | + | ||
28 | + should 'have many submissions' do | ||
29 | + form = CustomFormsPlugin::Form.create!(:profile => fast_create(Profile), :name => 'Free Software') | ||
30 | + s1 = CustomFormsPlugin::Submission.create!(:form => form, :profile => fast_create(Profile)) | ||
31 | + s2 = CustomFormsPlugin::Submission.create!(:form => form, :profile => fast_create(Profile)) | ||
32 | + | ||
33 | + assert_includes form.submissions, s1 | ||
34 | + assert_includes form.submissions, s2 | ||
35 | + end | ||
36 | + | ||
37 | + should 'set slug before validation based on name' do | ||
38 | + form = CustomFormsPlugin::Form.new(:name => 'Name') | ||
39 | + form.valid? | ||
40 | + assert_equal form.name.to_slug, form.slug | ||
41 | + end | ||
42 | + | ||
43 | + should 'validates uniqueness of slug scoped on profile' do | ||
44 | + profile = fast_create(Profile) | ||
45 | + another_profile = fast_create(Profile) | ||
46 | + CustomFormsPlugin::Form.create!(:profile => profile, :name => 'Free Software') | ||
47 | + form = CustomFormsPlugin::Form.new(:profile => profile, :name => 'Free Software') | ||
48 | + form.valid? | ||
49 | + assert form.errors.invalid?(:slug) | ||
50 | + | ||
51 | + form.profile = another_profile | ||
52 | + form.valid? | ||
53 | + assert !form.errors.invalid?(:slug) | ||
54 | + end | ||
55 | + | ||
56 | + should 'define form expiration' do | ||
57 | + form = CustomFormsPlugin::Form.new | ||
58 | + assert !form.expired? | ||
59 | + | ||
60 | + form.begining = Time.now + 1.day | ||
61 | + assert form.expired? | ||
62 | + | ||
63 | + form.begining = Time.now - 1.day | ||
64 | + assert !form.expired? | ||
65 | + | ||
66 | + form.begining = nil | ||
67 | + form.ending = Time.now + 1.day | ||
68 | + assert !form.expired? | ||
69 | + | ||
70 | + form.ending = Time.now - 1.day | ||
71 | + assert form.expired? | ||
72 | + | ||
73 | + form.begining = Time.now - 1.day | ||
74 | + form.ending = Time.now + 1.day | ||
75 | + assert !form.expired? | ||
76 | + end | ||
77 | + | ||
78 | + should 'validates format of access' do | ||
79 | + form = CustomFormsPlugin::Form.new | ||
80 | + form.valid? | ||
81 | + assert !form.errors.invalid?(:access) | ||
82 | + | ||
83 | + form.access = 'bli' | ||
84 | + form.valid? | ||
85 | + assert form.errors.invalid?(:access) | ||
86 | + | ||
87 | + form.access = 'logged' | ||
88 | + form.valid? | ||
89 | + assert !form.errors.invalid?(:access) | ||
90 | + | ||
91 | + form.access = 'associated' | ||
92 | + form.valid? | ||
93 | + assert !form.errors.invalid?(:access) | ||
94 | + | ||
95 | + form.access = {:bli => 1} | ||
96 | + form.valid? | ||
97 | + assert form.errors.invalid?(:access) | ||
98 | + | ||
99 | + form.access = 999 | ||
100 | + form.valid? | ||
101 | + assert form.errors.invalid?(:access) | ||
102 | + | ||
103 | + p1 = fast_create(Profile) | ||
104 | + form.access = p1.id | ||
105 | + form.valid? | ||
106 | + assert !form.errors.invalid?(:access) | ||
107 | + | ||
108 | + p2 = fast_create(Profile) | ||
109 | + p3 = fast_create(Profile) | ||
110 | + form.access = [p1,p2,p3].map(&:id) | ||
111 | + form.valid? | ||
112 | + assert !form.errors.invalid?(:access) | ||
113 | + end | ||
114 | + | ||
115 | + should 'defines who is able to access the form' do | ||
116 | + owner = fast_create(Community) | ||
117 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => owner) | ||
118 | + assert form.accessible_to(nil) | ||
119 | + | ||
120 | + form.access = 'logged' | ||
121 | + assert !form.accessible_to(nil) | ||
122 | + person = fast_create(Person) | ||
123 | + assert form.accessible_to(person) | ||
124 | + | ||
125 | + form.access = 'associated' | ||
126 | + assert !form.accessible_to(person) | ||
127 | + owner.add_member(person) | ||
128 | + assert form.accessible_to(person) | ||
129 | + | ||
130 | + p1 = fast_create(Profile) | ||
131 | + form.access = p1.id | ||
132 | + assert !form.accessible_to(person) | ||
133 | + assert form.accessible_to(p1) | ||
134 | + | ||
135 | + p2 = fast_create(Profile) | ||
136 | + form.access = [person.id, p1.id] | ||
137 | + assert form.accessible_to(person) | ||
138 | + assert form.accessible_to(p1) | ||
139 | + assert !form.accessible_to(p2) | ||
140 | + form.access << p2.id | ||
141 | + assert form.accessible_to(p2) | ||
142 | + | ||
143 | + assert form.accessible_to(owner) | ||
144 | + end | ||
145 | + | ||
146 | + should 'have a named_scope that retrieve forms from a profile' do | ||
147 | + profile = fast_create(Profile) | ||
148 | + another_profile = fast_create(Profile) | ||
149 | + f1 = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => profile) | ||
150 | + f2 = CustomFormsPlugin::Form.create!(:name => 'Open Source', :profile => profile) | ||
151 | + f3 = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => another_profile) | ||
152 | + scope = CustomFormsPlugin::Form.from(profile) | ||
153 | + | ||
154 | + assert_equal ActiveRecord::NamedScope::Scope, scope.class | ||
155 | + assert_includes scope, f1 | ||
156 | + assert_includes scope, f2 | ||
157 | + assert_not_includes scope, f3 | ||
158 | + end | ||
159 | + | ||
160 | + should 'have a named_scope that retrieves all forms that are triggered on membership' do | ||
161 | + profile = fast_create(Profile) | ||
162 | + f1 = CustomFormsPlugin::Form.create!(:name => 'On membership 1', :profile => profile, :on_membership => true) | ||
163 | + f2 = CustomFormsPlugin::Form.create!(:name => 'On membership 2', :profile => profile, :on_membership => true) | ||
164 | + f3 = CustomFormsPlugin::Form.create!(:name => 'Not on memberhsip', :profile => profile, :on_membership => false) | ||
165 | + scope = CustomFormsPlugin::Form.from(profile).on_memberships | ||
166 | + | ||
167 | + assert_equal ActiveRecord::NamedScope::Scope, scope.class | ||
168 | + assert_includes scope, f1 | ||
169 | + assert_includes scope, f2 | ||
170 | + assert_not_includes scope, f3 | ||
171 | + end | ||
172 | +end |
plugins/custom_forms/test/unit/custom_forms_plugin/membership_survey_test.rb
0 → 100644
@@ -0,0 +1,31 @@ | @@ -0,0 +1,31 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class CustomFormsPlugin::MembershipSurveyTest < ActiveSupport::TestCase | ||
4 | + should 'validates presence of form_id' do | ||
5 | + task = CustomFormsPlugin::MembershipSurvey.new | ||
6 | + task.valid? | ||
7 | + assert task.errors.invalid?(:form_id) | ||
8 | + | ||
9 | + task.form_id = 1 | ||
10 | + task.valid? | ||
11 | + assert !task.errors.invalid?(:form_id) | ||
12 | + end | ||
13 | + | ||
14 | + should 'create submission with answers on perform' do | ||
15 | + profile = fast_create(Profile) | ||
16 | + person = fast_create(Person) | ||
17 | + form = CustomFormsPlugin::Form.create!(:name => 'Simple Form', :profile => profile) | ||
18 | + field = CustomFormsPlugin::Field.create!(:name => 'Name', :form => form) | ||
19 | + task = CustomFormsPlugin::MembershipSurvey.create!(:form_id => form.id, :submission => {'name' => 'Jack'}, :target => person, :requestor => profile) | ||
20 | + | ||
21 | + assert_difference CustomFormsPlugin::Submission, :count, 1 do | ||
22 | + task.finish | ||
23 | + end | ||
24 | + | ||
25 | + submission = CustomFormsPlugin::Submission.last | ||
26 | + assert_equal submission.answers.count, 1 | ||
27 | + | ||
28 | + answer = submission.answers.first | ||
29 | + assert_equal answer.value, 'Jack' | ||
30 | + end | ||
31 | +end |
plugins/custom_forms/test/unit/custom_forms_plugin/select_field_test.rb
0 → 100644
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class CustomFormsPlugin::SelectFieldTest < ActiveSupport::TestCase | ||
4 | + should 'validate presence of choices, multiple and list' do | ||
5 | + select = CustomFormsPlugin::SelectField.new | ||
6 | + select.valid? | ||
7 | + assert select.errors.invalid?(:choices) | ||
8 | + | ||
9 | + select.choices = {'label' => 'value'} | ||
10 | + select.valid? | ||
11 | + assert !select.errors.invalid?(:choices) | ||
12 | + end | ||
13 | +end |
plugins/custom_forms/test/unit/custom_forms_plugin/submission_test.rb
0 → 100644
@@ -0,0 +1,46 @@ | @@ -0,0 +1,46 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class CustomFormsPlugin::SubmissionTest < ActiveSupport::TestCase | ||
4 | + should 'validates presence of form' do | ||
5 | + submission = CustomFormsPlugin::Submission.new | ||
6 | + submission.valid? | ||
7 | + assert submission.errors.invalid?(:form) | ||
8 | + | ||
9 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | ||
10 | + submission.form = form | ||
11 | + submission.valid? | ||
12 | + assert !submission.errors.invalid?(:form) | ||
13 | + end | ||
14 | + | ||
15 | + should 'belong to a profile' do | ||
16 | + profile = fast_create(Profile) | ||
17 | + submission = CustomFormsPlugin::Submission.new | ||
18 | + submission.profile = profile | ||
19 | + assert_equal profile, submission.profile | ||
20 | + end | ||
21 | + | ||
22 | + should 'require presence of author name and email if profile is nil' do | ||
23 | + submission = CustomFormsPlugin::Submission.new | ||
24 | + submission.valid? | ||
25 | + assert submission.errors.invalid?(:author_name) | ||
26 | + assert submission.errors.invalid?(:author_email) | ||
27 | + | ||
28 | + submission.author_name = 'Jack Sparrow' | ||
29 | + submission.author_email = 'jack@black-pearl.com' | ||
30 | + submission.valid? | ||
31 | + assert !submission.errors.invalid?(:author_name) | ||
32 | + assert !submission.errors.invalid?(:author_email) | ||
33 | + end | ||
34 | + | ||
35 | + should 'have answers' do | ||
36 | + form = CustomFormsPlugin::Form.create!(:name => 'Free Software', :profile => fast_create(Profile)) | ||
37 | + field = CustomFormsPlugin::Field.create!(:name => 'License', :form => form) | ||
38 | + submission = CustomFormsPlugin::Submission.create!(:form => form, :profile => fast_create(Profile)) | ||
39 | + a1 = CustomFormsPlugin::Answer.create!(:field => field, :submission => submission) | ||
40 | + a2 = CustomFormsPlugin::Answer.create!(:field => field, :submission => submission) | ||
41 | + | ||
42 | + assert_includes submission.answers, a1 | ||
43 | + assert_includes submission.answers, a2 | ||
44 | + end | ||
45 | +end | ||
46 | + |
plugins/custom_forms/test/unit/ext/role_assingment_test.rb
0 → 100644
@@ -0,0 +1,51 @@ | @@ -0,0 +1,51 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class RoleAssignmentsTest < ActiveSupport::TestCase | ||
4 | + should 'create membership_surveys on membership creation' do | ||
5 | + environment = Environment.default | ||
6 | + environment.enable_plugin(CustomFormsPlugin) | ||
7 | + organization = fast_create(Organization) | ||
8 | + person = fast_create(Person) | ||
9 | + f1 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 1', :on_membership => true) | ||
10 | + f2 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 2', :on_membership => true) | ||
11 | + f3 = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form 3', :on_membership => false) | ||
12 | + | ||
13 | + assert_difference CustomFormsPlugin::MembershipSurvey, :count, 2 do | ||
14 | + organization.add_member(person) | ||
15 | + end | ||
16 | + end | ||
17 | + | ||
18 | + should 'create membership_survey on membership creation with form accessible to members only' do | ||
19 | + environment = Environment.default | ||
20 | + environment.enable_plugin(CustomFormsPlugin) | ||
21 | + organization = fast_create(Organization) | ||
22 | + person = fast_create(Person) | ||
23 | + form = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form', :on_membership => true, :access => 'associated') | ||
24 | + | ||
25 | + assert_difference CustomFormsPlugin::MembershipSurvey, :count, 1 do | ||
26 | + organization.add_member(person) | ||
27 | + end | ||
28 | + end | ||
29 | + | ||
30 | + should 'cancel membership_surveys if membership is undone and task is active' do | ||
31 | + environment = Environment.default | ||
32 | + environment.enable_plugin(CustomFormsPlugin) | ||
33 | + organization = fast_create(Organization) | ||
34 | + person = fast_create(Person) | ||
35 | + form = CustomFormsPlugin::Form.create!(:profile => organization, :name => 'Form', :on_membership => true) | ||
36 | + organization.add_member(person) | ||
37 | + | ||
38 | + assert_difference CustomFormsPlugin::MembershipSurvey.pending, :count, -1 do | ||
39 | + organization.remove_member(person) | ||
40 | + end | ||
41 | + | ||
42 | + organization.add_member(person) | ||
43 | + task = CustomFormsPlugin::MembershipSurvey.last | ||
44 | + task.status = Task::Status::FINISHED | ||
45 | + task.save! | ||
46 | + assert_no_difference CustomFormsPlugin::MembershipSurvey.finished, :count do | ||
47 | + organization.remove_member(person) | ||
48 | + end | ||
49 | + end | ||
50 | +end | ||
51 | + |
plugins/custom_forms/views/custom_forms_plugin_myprofile/_edit_select.html.erb
0 → 100644
@@ -0,0 +1,33 @@ | @@ -0,0 +1,33 @@ | ||
1 | +<% elem_id = "edit-select-#{counter}" %> | ||
2 | +<div id=<%= elem_id %> class='edit-information'> | ||
3 | + <h2><%= _('Options') %></h2> | ||
4 | + <table class='action-table' style='width: 420px'> | ||
5 | + <tr> | ||
6 | + <th style='width: 40%'><%= _('Name') %></th> | ||
7 | + <th style='width: 40%'><%= _('Value') %></th> | ||
8 | + <th style='width: 20%'><%= _('Actions') %></th> | ||
9 | + </tr> | ||
10 | + <% option_counter = 1 %> | ||
11 | + <% (field.choices || {}).each do |name, value| %> | ||
12 | + <%= render :partial => 'option', :locals => {:name => name, :value => value, :counter => counter, :option_counter => option_counter} %> | ||
13 | + <% option_counter += 1 %> | ||
14 | + <% end %> | ||
15 | + <%= render :partial => 'empty_option', :locals => {:counter => counter, :option_counter => option_counter} %> | ||
16 | + <tr class='new-item'> | ||
17 | + <td colspan='3'> | ||
18 | + <%= button(:add, _('Add a new option'), '#', :class => 'new-option', :field_id => counter)%> | ||
19 | + </td> | ||
20 | + </tr> | ||
21 | + </table> | ||
22 | + | ||
23 | + <h3><%= _('Type') %></h3> | ||
24 | + <%= labelled_radio_button 'Radio', "fields[#{counter}][kind]", 'radio', !field.multiple && !field.list %><br /> | ||
25 | + <%= labelled_radio_button 'Checkbox', "fields[#{counter}][kind]", 'check_box', field.multiple && !field.list %><br /> | ||
26 | + <%= labelled_radio_button 'Select', "fields[#{counter}][kind]", 'select', !field.multiple && field.list %><br /> | ||
27 | + <%= labelled_radio_button 'Multiple Select', "fields[#{counter}][kind]", 'multiple_select', field.multiple && field.list %><br /> | ||
28 | + | ||
29 | + <% button_bar do %> | ||
30 | + <%= button :ok, _('Ok'), '#', :class => 'colorbox-ok-button', :div_id => elem_id %> | ||
31 | + <% end %> | ||
32 | +</div> | ||
33 | + |
plugins/custom_forms/views/custom_forms_plugin_myprofile/_edit_text.html.erb
0 → 100644
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +<% elem_id = "edit-text-#{counter}" %> | ||
2 | +<div id=<%= elem_id %> class='edit-information'> | ||
3 | + <h2><%= _('Default value') %></h2> | ||
4 | + <%= labelled_form_field _('Default value'), text_field("fields[#{counter}]", :default_value, :value => field.default_value) %> | ||
5 | + | ||
6 | + <% button_bar do %> | ||
7 | + <%= button :ok, _('Ok'), '#', :class => 'colorbox-ok-button', :div_id => elem_id %> | ||
8 | + <% end %> | ||
9 | +</div> | ||
10 | + |
plugins/custom_forms/views/custom_forms_plugin_myprofile/_empty_field.html.erb
0 → 100644
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +<tr id="empty-field" style='display: none' last_id=<%= counter %>> | ||
2 | + <td style="text-align: left"><%= text_field "fields[#{counter}]", :name, :size => 25 %></td> | ||
3 | + <td><%= select "fields[#{counter}]", :type, type_options, :selected => type_for_options(field.class) %></td> | ||
4 | + <td><%= check_box "fields[#{counter}]", :mandatory %></td> | ||
5 | + <%= hidden_field "fields[#{counter}]", :form_id, :value => @form.id %> | ||
6 | + <td class='actions'> | ||
7 | + <%= button_without_text :edit, _('Edit'), '', :field_id => counter %> | ||
8 | + <%= button_without_text :remove, _('Remove'), '#', :class => 'remove-field', :field_id => counter, :confirm => _('Are you sure you want to remove this field?') %> | ||
9 | + </td> | ||
10 | +</tr> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/_empty_option.html.erb
0 → 100644
@@ -0,0 +1,8 @@ | @@ -0,0 +1,8 @@ | ||
1 | +<tr id=<%= "empty-option-#{counter}" %> option_id=<%= option_counter %> style="display: none;"> | ||
2 | + <td><%= text_field_tag("fields[#{counter}][choices][#{option_counter}][name]") %></td> | ||
3 | + <td><%= text_field_tag("fields[#{counter}][choices][#{option_counter}][value]", nil, :size => 15) %></td> | ||
4 | + <td class='actions'> | ||
5 | + <%= button_without_text :remove, _('Remove'), '#', :class => 'remove-option', :field_id => counter, :option_id => option_counter, :confirm => _('Are you sure you want to remove this option?') %> | ||
6 | + </td> | ||
7 | +</tr> | ||
8 | + |
plugins/custom_forms/views/custom_forms_plugin_myprofile/_field.html.erb
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +<tr id=<%= "field-#{counter}" %>> | ||
2 | + <td style="text-align: left"><%= text_field "fields[#{counter}]", :name, :value => field.name, :size => 25 %></td> | ||
3 | + <td><%= type_to_label(field.type) %></td> | ||
4 | + <%= hidden_field "fields[#{counter}]", :type, :value => type_for_options(field.class) %> | ||
5 | + <td><%= check_box "fields[#{counter}]", :mandatory, :checked => field.mandatory %></td> | ||
6 | + <%= hidden_field "fields[#{counter}]", :real_id, :value => field.id %> | ||
7 | + <%= hidden_field "fields[#{counter}]", :form_id, :value => @form.id %> | ||
8 | + <td class='actions'> | ||
9 | + <%= button_without_text :edit, _('Edit'), '#', :field_id => counter %> | ||
10 | + <%= button_without_text :remove, _('Remove'), '#', :class => 'remove-field', :field_id => counter, :confirm => _('Are you sure you want to remove this field?') %> | ||
11 | + </td> | ||
12 | +</tr> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/_form.html.erb
0 → 100644
@@ -0,0 +1,56 @@ | @@ -0,0 +1,56 @@ | ||
1 | +<% self.extend(CustomFormsPlugin::Helper) %> | ||
2 | + | ||
3 | +<%= error_messages_for :form %> | ||
4 | + | ||
5 | +<% form_for :form, @form do |f| %> | ||
6 | + <%= required labelled_form_field _('Name'), f.text_field(:name) %> | ||
7 | + <%= labelled_form_field(_('Período'), ( | ||
8 | + date_range_field('form[begining]', 'form[ending]', @form.begining, @form.ending, | ||
9 | + '%Y-%m-%d %H:%M', | ||
10 | + { :time => true, :change_month => true, :change_year => true, | ||
11 | + :date_format => 'yy-mm-dd', :time_format => 'hh:mm' }, | ||
12 | + { :size => 14 }) | ||
13 | + )) %> | ||
14 | + <%= labelled_form_field _('Access'), f.select(:access, access_options(profile))%> | ||
15 | + <% if profile.organization? %> | ||
16 | + <%= labelled_form_field _('Triggered on membership'), f.check_box(:on_membership) %> | ||
17 | + <% end %> | ||
18 | + <%= labelled_form_field _('Description'), f.text_area(:description, :style => 'width: 100%') %> | ||
19 | + | ||
20 | + <h2><%= _('Fields') %></h2> | ||
21 | + <table class="action-table" id='fields-table'> | ||
22 | + <tr> | ||
23 | + <th style='width: 40%'><%= _('Name') %></th> | ||
24 | + <th style='width: 30%'><%= _('Type') %></th> | ||
25 | + <th style='width: 10%'><%= _('Mandatory') %></th> | ||
26 | + <th style='width: 20%'><%= _('Actions') %></th> | ||
27 | + </tr> | ||
28 | + <% counter = 1 %> | ||
29 | + <% @fields.each do |field| %> | ||
30 | + <%= render :partial => 'field', :locals => {:field => field, :counter => counter} %> | ||
31 | + <% counter += 1 %> | ||
32 | + <% end %> | ||
33 | + <%= render :partial => 'empty_field', :locals => {:field => @empty_field, :counter => counter} %> | ||
34 | + <tr class='new-item'> | ||
35 | + <td colspan='5'> | ||
36 | + <%= button(:add, _('Add a new field'), '#', :id => 'new-field')%> | ||
37 | + </td> | ||
38 | + </tr> | ||
39 | + </table> | ||
40 | + | ||
41 | + <% counter = 1 %> | ||
42 | + <% @fields.each do |field| %> | ||
43 | + <%= render :partial => 'edit_text', :locals => {:field => field, :counter => counter} %> | ||
44 | + <%= render :partial => 'edit_select', :locals => {:field => field, :counter => counter} %> | ||
45 | + <% counter += 1 %> | ||
46 | + <% end %> | ||
47 | + | ||
48 | + <%= render :partial => 'edit_text', :locals => {:field => @empty_field, :counter => counter} %> | ||
49 | + <%= render :partial => 'edit_select', :locals => {:field => @empty_field, :counter => counter} %> | ||
50 | + | ||
51 | + <% button_bar do %> | ||
52 | + <%= submit_button :save, _('Save'), :cancel => {:action => 'index'}%> | ||
53 | + <% end %> | ||
54 | +<% end %> | ||
55 | + | ||
56 | +<%= javascript_include_tag '../plugins/custom_forms/field' %> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/_option.html.erb
0 → 100644
@@ -0,0 +1,7 @@ | @@ -0,0 +1,7 @@ | ||
1 | +<tr id=<%= "field-#{counter}-option-#{option_counter}" %> style="display: auto;"> | ||
2 | + <td><%= text_field_tag("fields[#{counter}][choices][#{option_counter}][name]", name) %></td> | ||
3 | + <td><%= text_field_tag("fields[#{counter}][choices][#{option_counter}][value]", value) %></td> | ||
4 | + <td class='actions'> | ||
5 | + <%= button_without_text :remove, _('Remove'), '#', :class => 'remove-option', :field_id => counter, :option_id => option_counter, :confirm => _('Are you sure you want to remove this option?') %> | ||
6 | + </td> | ||
7 | +</tr> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/create.html.erb
0 → 100644
plugins/custom_forms/views/custom_forms_plugin_myprofile/edit.html.erb
0 → 100644
plugins/custom_forms/views/custom_forms_plugin_myprofile/index.html.erb
0 → 100644
@@ -0,0 +1,28 @@ | @@ -0,0 +1,28 @@ | ||
1 | +<% self.extend CustomFormsPlugin::Helper %> | ||
2 | + | ||
3 | +<h1><%= _('Manage forms') %></h1> | ||
4 | +<table class="action-table"> | ||
5 | + <tr> | ||
6 | + <th style='width: 40%'><%= _('Name') %></th> | ||
7 | + <th style='width: 30%'><%= _('Period') %></th> | ||
8 | + <th style='width: 10%'><%= _('Submissions') %></th> | ||
9 | + <th style='width: 10%'><%= _('Access') %></th> | ||
10 | + <th style='width: 10%'><%= _('Actions') %></th> | ||
11 | + </tr> | ||
12 | + <% @forms.each do |form| %> | ||
13 | + <tr> | ||
14 | + <td><%= link_to form.name, {:controller => 'custom_forms_plugin_profile', :action => 'show', :id => form.id} %></td> | ||
15 | + <td><%= period_range(form) %></td> | ||
16 | + <td><%= form.submissions.count > 0 ? link_to(form.submissions.count, {:action => 'submissions', :id => form.id}) : 0 %></td> | ||
17 | + <td><%= access_text(form) %></td> | ||
18 | + <td class="actions"> | ||
19 | + <%= button_without_text :edit, _('Edit'), :action => 'edit', :id => form.id %> | ||
20 | + <%= button_without_text :remove, _('Remove'), {:action => 'remove', :id => form.id}, :confirm => _('Are you sure you want to remove this form?') %></td> | ||
21 | + </tr> | ||
22 | + <% end %> | ||
23 | + <tr id="new-item"> | ||
24 | + <td colspan='5'> | ||
25 | + <%= button(:add, _('Add a new form'), :action => 'create')%> | ||
26 | + </td> | ||
27 | + </tr> | ||
28 | +</table> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/show_submission.html.erb
0 → 100644
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +<h1><%= @form.name %></h1> | ||
2 | +<p><%= @form.description %></p> | ||
3 | + | ||
4 | +<% fields_for :submission, @submission do |f| %> | ||
5 | + <%= render :partial => 'shared/form_submission', :locals => {:f => f} %> | ||
6 | +<% end %> | ||
7 | + | ||
8 | +<% button_bar do %> | ||
9 | + <%= button :back, _('Back to submissions'), :action => 'submissions', :id => @form.id %> | ||
10 | +<% end %> |
plugins/custom_forms/views/custom_forms_plugin_myprofile/submissions.html.erb
0 → 100644
@@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
1 | +<% self.extend CustomFormsPlugin::Helper %> | ||
2 | + | ||
3 | +<h1><%= _('Submissions for %s') % @form.name %></h1> | ||
4 | + | ||
5 | +<% if @form.submissions.empty? %> | ||
6 | + <%= _('There are no submissions for this form.') %> | ||
7 | +<% else %> | ||
8 | + <table class="action-table"> | ||
9 | + <tr> | ||
10 | + <th style='width: 50%'><%= _('Author') %></th> | ||
11 | + <th style='width: 50%'><%= _('Time') %></th> | ||
12 | + </tr> | ||
13 | + <% @submissions.each do |submission| %> | ||
14 | + <tr> | ||
15 | + <% author = submission.profile.present? ? submission.profile.name : submission.author_name %> | ||
16 | + <td><%= link_to(author, {:action => 'show_submission', :id => submission.id}) %></td> | ||
17 | + <td><%= time_format(submission.created_at) %></td> | ||
18 | + </tr> | ||
19 | + <% end %> | ||
20 | + </table> | ||
21 | +<% end %> | ||
22 | + | ||
23 | +<% button_bar do %> | ||
24 | + <%= button :back, _('Back to forms'), :action => 'index' %> | ||
25 | +<% end %> |
plugins/custom_forms/views/custom_forms_plugin_profile/show.html.erb
0 → 100644
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +<h1><%= @form.name %></h1> | ||
2 | +<p><%= @form.description %></p> | ||
3 | + | ||
4 | +<% if @submission.id.nil? %> | ||
5 | + <%= error_messages_for :submission %> | ||
6 | + | ||
7 | + <% form_for :submission, @submission do |f| %> | ||
8 | + <% if !user %> | ||
9 | + <%= required labelled_form_field _('Author name'), text_field_tag(:author_name, @submission.author_name) %> | ||
10 | + <%= required labelled_form_field _('Author email'), text_field_tag(:author_email, @submission.author_email) %> | ||
11 | + <% end %> | ||
12 | + | ||
13 | + <%= render :partial => 'shared/form_submission', :locals => {:f => f} %> | ||
14 | + | ||
15 | + <% button_bar do %> | ||
16 | + <%= submit_button :save, _('Save'), :cancel => {:action => 'index'} %> | ||
17 | + <% end %> | ||
18 | + <% end %> | ||
19 | +<% else %> | ||
20 | + <% fields_for :submission, @submission do |f| %> | ||
21 | + <%= render :partial => 'shared/form_submission', :locals => {:f => f} %> | ||
22 | + <% end %> | ||
23 | +<% end %> |
plugins/custom_forms/views/shared/_form_submission.html.erb
0 → 100644
plugins/custom_forms/views/tasks/_membership_survey_accept_details.html.erb
0 → 100644
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +<%= f.object_name.to_s %> |
plugins/custom_forms/views/tasks/custom_forms_plugin/_membership_survey_accept_details.html.erb
0 → 100644
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +<% @form = CustomFormsPlugin::Form.find(task.form_id) %> | ||
2 | +<% @submission = CustomFormsPlugin::Submission.new(:form_id => @form.id, :profile_id => user.id) %> | ||
3 | + | ||
4 | +<h2><%= @form.name %></h2> | ||
5 | +<p><%= @form.description %></p> | ||
6 | + | ||
7 | +<% f.fields_for :submission do |fi| %> | ||
8 | + <%#= fi.error_messages_for :submission %> | ||
9 | + <%= render :partial => 'shared/form_submission', :locals => {:f => fi} %> | ||
10 | +<% end %> |
plugins/foo/controllers/admin/foo_plugin_admin_bar_controller.rb
0 → 100644
plugins/foo/controllers/myprofile/foo_plugin_myprofile_bar_controller.rb
0 → 100644
plugins/foo/controllers/profile/foo_plugin_profile_bar_controller.rb
0 → 100644
plugins/foo/controllers/public/foo_plugin_public_bar_controller.rb
0 → 100644
plugins/mezuro/controllers/mezuro_plugin_myprofile_controller.rb
@@ -2,7 +2,15 @@ class MezuroPluginMyprofileController < ProfileController | @@ -2,7 +2,15 @@ class MezuroPluginMyprofileController < ProfileController | ||
2 | 2 | ||
3 | append_view_path File.join(File.dirname(__FILE__) + '/../views') | 3 | append_view_path File.join(File.dirname(__FILE__) + '/../views') |
4 | 4 | ||
5 | - | 5 | + rescue_from Exception do |exception| |
6 | + message = URI.escape(CGI.escape(exception.message),'.') | ||
7 | + redirect_to_error_page message | ||
8 | + end | ||
9 | + | ||
10 | + def error_page | ||
11 | + @message = params[:message] | ||
12 | + end | ||
13 | + | ||
6 | def choose_base_tool | 14 | def choose_base_tool |
7 | @configuration_content = profile.articles.find(params[:id]) | 15 | @configuration_content = profile.articles.find(params[:id]) |
8 | @base_tools = Kalibro::BaseTool.all_names | 16 | @base_tools = Kalibro::BaseTool.all_names |
@@ -11,19 +19,23 @@ class MezuroPluginMyprofileController < ProfileController | @@ -11,19 +19,23 @@ class MezuroPluginMyprofileController < ProfileController | ||
11 | def choose_metric | 19 | def choose_metric |
12 | @configuration_content = profile.articles.find(params[:id]) | 20 | @configuration_content = profile.articles.find(params[:id]) |
13 | @base_tool = params[:base_tool] | 21 | @base_tool = params[:base_tool] |
14 | - @supported_metrics = Kalibro::BaseTool.find_by_name(@base_tool).supported_metrics | 22 | + base_tool = Kalibro::BaseTool.find_by_name(@base_tool) |
23 | + @supported_metrics = base_tool.nil? ? [] : base_tool.supported_metrics | ||
15 | end | 24 | end |
16 | - | 25 | + |
17 | def new_metric_configuration | 26 | def new_metric_configuration |
18 | @configuration_content = profile.articles.find(params[:id]) | 27 | @configuration_content = profile.articles.find(params[:id]) |
19 | @metric = Kalibro::BaseTool.find_by_name(params[:base_tool]).metric params[:metric_name] | 28 | @metric = Kalibro::BaseTool.find_by_name(params[:base_tool]).metric params[:metric_name] |
20 | end | 29 | end |
21 | - | 30 | + |
22 | def new_compound_metric_configuration | 31 | def new_compound_metric_configuration |
23 | @configuration_content = profile.articles.find(params[:id]) | 32 | @configuration_content = profile.articles.find(params[:id]) |
24 | @metric_configurations = @configuration_content.metric_configurations | 33 | @metric_configurations = @configuration_content.metric_configurations |
34 | + if configuration_content_has_errors? | ||
35 | + redirect_to_error_page @configuration_content.errors[:base] | ||
36 | + end | ||
25 | end | 37 | end |
26 | - | 38 | + |
27 | def edit_metric_configuration | 39 | def edit_metric_configuration |
28 | @configuration_content = profile.articles.find(params[:id]) | 40 | @configuration_content = profile.articles.find(params[:id]) |
29 | @metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(@configuration_content.name, params[:metric_name]) | 41 | @metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(@configuration_content.name, params[:metric_name]) |
@@ -36,19 +48,29 @@ class MezuroPluginMyprofileController < ProfileController | @@ -36,19 +48,29 @@ class MezuroPluginMyprofileController < ProfileController | ||
36 | @metric_configurations = @configuration_content.metric_configurations | 48 | @metric_configurations = @configuration_content.metric_configurations |
37 | @metric = @metric_configuration.metric | 49 | @metric = @metric_configuration.metric |
38 | end | 50 | end |
39 | - | 51 | + |
40 | def create_metric_configuration | 52 | def create_metric_configuration |
41 | id = params[:id] | 53 | id = params[:id] |
42 | metric_name = params[:metric_configuration][:metric][:name] | 54 | metric_name = params[:metric_configuration][:metric][:name] |
43 | - (Kalibro::MetricConfiguration.new(params[:metric_configuration])).save | ||
44 | - redirect_to "/myprofile/#{profile.identifier}/plugin/mezuro/edit_metric_configuration?id=#{id}&metric_name=#{metric_name.gsub(/\s/, '+')}" | 55 | + metric_configuration = Kalibro::MetricConfiguration.new(params[:metric_configuration]) |
56 | + metric_configuration.save | ||
57 | + if metric_configuration_has_errors? metric_configuration | ||
58 | + redirect_to_error_page metric_configuration.errors[0].message | ||
59 | + else | ||
60 | + redirect_to "/myprofile/#{profile.identifier}/plugin/mezuro/edit_metric_configuration?id=#{id}&metric_name=#{metric_name.gsub(/\s/, '+')}" | ||
61 | + end | ||
45 | end | 62 | end |
46 | - | 63 | + |
47 | def create_compound_metric_configuration | 64 | def create_compound_metric_configuration |
48 | id = params[:id] | 65 | id = params[:id] |
49 | metric_name = params[:metric_configuration][:metric][:name] | 66 | metric_name = params[:metric_configuration][:metric][:name] |
50 | - Kalibro::MetricConfiguration.new(params[:metric_configuration]).save | ||
51 | - redirect_to "/myprofile/#{profile.identifier}/plugin/mezuro/edit_compound_metric_configuration?id=#{id}&metric_name=#{metric_name.gsub(/\s/, '+')}" | 67 | + metric_configuration = Kalibro::MetricConfiguration.new(params[:metric_configuration]) |
68 | + metric_configuration.save | ||
69 | + if metric_configuration_has_errors? metric_configuration | ||
70 | + redirect_to_error_page metric_configuration.errors[0].message | ||
71 | + else | ||
72 | + redirect_to "/myprofile/#{profile.identifier}/plugin/mezuro/edit_compound_metric_configuration?id=#{id}&metric_name=#{metric_name.gsub(/\s/, '+')}" | ||
73 | + end | ||
52 | end | 74 | end |
53 | 75 | ||
54 | def update_metric_configuration | 76 | def update_metric_configuration |
@@ -56,7 +78,11 @@ class MezuroPluginMyprofileController < ProfileController | @@ -56,7 +78,11 @@ class MezuroPluginMyprofileController < ProfileController | ||
56 | metric_name = params[:metric_configuration][:metric][:name] | 78 | metric_name = params[:metric_configuration][:metric][:name] |
57 | metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(@configuration_content.name, metric_name) | 79 | metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(@configuration_content.name, metric_name) |
58 | metric_configuration.update_attributes params[:metric_configuration] | 80 | metric_configuration.update_attributes params[:metric_configuration] |
59 | - redirect_to "/#{profile.identifier}/#{@configuration_content.slug}" | 81 | + if metric_configuration_has_errors? metric_configuration |
82 | + redirect_to_error_page metric_configuration.errors[0].message | ||
83 | + else | ||
84 | + redirect_to "/#{profile.identifier}/#{@configuration_content.slug}" | ||
85 | + end | ||
60 | end | 86 | end |
61 | 87 | ||
62 | def update_compound_metric_configuration | 88 | def update_compound_metric_configuration |
@@ -64,7 +90,11 @@ class MezuroPluginMyprofileController < ProfileController | @@ -64,7 +90,11 @@ class MezuroPluginMyprofileController < ProfileController | ||
64 | metric_name = params[:metric_configuration][:metric][:name] | 90 | metric_name = params[:metric_configuration][:metric][:name] |
65 | metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(@configuration_content.name, metric_name) | 91 | metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(@configuration_content.name, metric_name) |
66 | metric_configuration.update_attributes params[:metric_configuration] | 92 | metric_configuration.update_attributes params[:metric_configuration] |
67 | - redirect_to "/#{profile.identifier}/#{@configuration_content.slug}" | 93 | + if metric_configuration_has_errors? metric_configuration |
94 | + redirect_to_error_page metric_configuration.errors[0].message | ||
95 | + else | ||
96 | + redirect_to "/#{profile.identifier}/#{@configuration_content.slug}" | ||
97 | + end | ||
68 | end | 98 | end |
69 | 99 | ||
70 | def remove_metric_configuration | 100 | def remove_metric_configuration |
@@ -72,32 +102,41 @@ class MezuroPluginMyprofileController < ProfileController | @@ -72,32 +102,41 @@ class MezuroPluginMyprofileController < ProfileController | ||
72 | metric_name = params[:metric_name] | 102 | metric_name = params[:metric_name] |
73 | metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(configuration_content.name, metric_name) | 103 | metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(configuration_content.name, metric_name) |
74 | metric_configuration.destroy | 104 | metric_configuration.destroy |
75 | - redirect_to "/#{profile.identifier}/#{configuration_content.slug}" | 105 | + if metric_configuration_has_errors? metric_configuration |
106 | + redirect_to_error_page metric_configuration.errors[0].message | ||
107 | + else | ||
108 | + redirect_to "/#{profile.identifier}/#{configuration_content.slug}" | ||
109 | + end | ||
76 | end | 110 | end |
77 | - | 111 | + |
78 | def new_range | 112 | def new_range |
79 | @configuration_content = profile.articles.find(params[:id]) | 113 | @configuration_content = profile.articles.find(params[:id]) |
80 | @metric_name = params[:metric_name] | 114 | @metric_name = params[:metric_name] |
81 | @range = Kalibro::Range.new | 115 | @range = Kalibro::Range.new |
116 | + @range_color = "#000000" | ||
82 | end | 117 | end |
83 | - | 118 | + |
84 | def edit_range | 119 | def edit_range |
85 | @configuration_content = profile.articles.find(params[:id]) | 120 | @configuration_content = profile.articles.find(params[:id]) |
86 | @metric_name = params[:metric_name] | 121 | @metric_name = params[:metric_name] |
87 | @beginning_id = params[:beginning_id] | 122 | @beginning_id = params[:beginning_id] |
88 | metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(@configuration_content.name, @metric_name) | 123 | metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(@configuration_content.name, @metric_name) |
89 | @range = metric_configuration.ranges.find{|range| range.beginning == @beginning_id.to_f || @beginning_id =="-INF" } | 124 | @range = metric_configuration.ranges.find{|range| range.beginning == @beginning_id.to_f || @beginning_id =="-INF" } |
125 | + @range_color = "#" + @range.color.to_s.gsub(/^ff/, "") | ||
90 | end | 126 | end |
91 | 127 | ||
92 | def create_range | 128 | def create_range |
93 | @configuration_content = profile.articles.find(params[:id]) | 129 | @configuration_content = profile.articles.find(params[:id]) |
94 | @range = Kalibro::Range.new params[:range] | 130 | @range = Kalibro::Range.new params[:range] |
95 | metric_name = params[:metric_name] | 131 | metric_name = params[:metric_name] |
96 | - metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(@configuration_content.name, metric_name) | 132 | + metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(@configuration_content.name, metric_name) |
97 | metric_configuration.add_range(@range) | 133 | metric_configuration.add_range(@range) |
98 | metric_configuration.save | 134 | metric_configuration.save |
135 | + if metric_configuration_has_errors? metric_configuration | ||
136 | + redirect_to_error_page metric_configuration.errors[0].message | ||
137 | + end | ||
99 | end | 138 | end |
100 | - | 139 | + |
101 | def update_range | 140 | def update_range |
102 | configuration_content = profile.articles.find(params[:id]) | 141 | configuration_content = profile.articles.find(params[:id]) |
103 | metric_name = params[:metric_name] | 142 | metric_name = params[:metric_name] |
@@ -106,8 +145,11 @@ class MezuroPluginMyprofileController < ProfileController | @@ -106,8 +145,11 @@ class MezuroPluginMyprofileController < ProfileController | ||
106 | index = metric_configuration.ranges.index{ |range| range.beginning == beginning_id.to_f || beginning_id == "-INF" } | 145 | index = metric_configuration.ranges.index{ |range| range.beginning == beginning_id.to_f || beginning_id == "-INF" } |
107 | metric_configuration.ranges[index] = Kalibro::Range.new params[:range] | 146 | metric_configuration.ranges[index] = Kalibro::Range.new params[:range] |
108 | metric_configuration.save | 147 | metric_configuration.save |
148 | + if metric_configuration_has_errors? metric_configuration | ||
149 | + redirect_to_error_page metric_configuration.errors[0].message | ||
150 | + end | ||
109 | end | 151 | end |
110 | - | 152 | + |
111 | def remove_range | 153 | def remove_range |
112 | configuration_content = profile.articles.find(params[:id]) | 154 | configuration_content = profile.articles.find(params[:id]) |
113 | metric_name = params[:metric_name] | 155 | metric_name = params[:metric_name] |
@@ -115,12 +157,31 @@ class MezuroPluginMyprofileController < ProfileController | @@ -115,12 +157,31 @@ class MezuroPluginMyprofileController < ProfileController | ||
115 | metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(configuration_content.name, metric_name) | 157 | metric_configuration = Kalibro::MetricConfiguration.find_by_configuration_name_and_metric_name(configuration_content.name, metric_name) |
116 | metric_configuration.ranges.delete_if { |range| range.beginning == beginning_id.to_f || beginning_id == "-INF" } | 158 | metric_configuration.ranges.delete_if { |range| range.beginning == beginning_id.to_f || beginning_id == "-INF" } |
117 | metric_configuration.save | 159 | metric_configuration.save |
118 | - formatted_metric_name = metric_name.gsub(/\s/, '+') | ||
119 | - if metric_configuration.metric.class == Kalibro::CompoundMetric | ||
120 | - redirect_to "/myprofile/#{profile.identifier}/plugin/mezuro/edit_compound_metric_configuration?id=#{configuration_content.id}&metric_name=#{formatted_metric_name}" | 160 | + if metric_configuration_has_errors? metric_configuration |
161 | + redirect_to_error_page metric_configuration.errors[0].message | ||
121 | else | 162 | else |
122 | - redirect_to "/myprofile/#{profile.identifier}/plugin/mezuro/edit_metric_configuration?id=#{configuration_content.id}&metric_name=#{formatted_metric_name}" | 163 | + formatted_metric_name = metric_name.gsub(/\s/, '+') |
164 | + if metric_configuration.metric.class == Kalibro::CompoundMetric | ||
165 | + redirect_to "/myprofile/#{profile.identifier}/plugin/mezuro/edit_compound_metric_configuration?id=#{configuration_content.id}&metric_name=#{formatted_metric_name}" | ||
166 | + else | ||
167 | + redirect_to "/myprofile/#{profile.identifier}/plugin/mezuro/edit_metric_configuration?id=#{configuration_content.id}&metric_name=#{formatted_metric_name}" | ||
168 | + end | ||
123 | end | 169 | end |
124 | end | 170 | end |
125 | 171 | ||
172 | + private | ||
173 | + | ||
174 | + def redirect_to_error_page(message) | ||
175 | + message = URI.escape(CGI.escape(message),'.') | ||
176 | + redirect_to "/myprofile/#{profile.identifier}/plugin/mezuro/error_page?message=#{message}" | ||
177 | + end | ||
178 | + | ||
179 | + def configuration_content_has_errors? | ||
180 | + not @configuration_content.errors[:base].nil? | ||
181 | + end | ||
182 | + | ||
183 | + def metric_configuration_has_errors? metric_configuration | ||
184 | + not metric_configuration.errors.empty? | ||
185 | + end | ||
186 | + | ||
126 | end | 187 | end |
plugins/mezuro/controllers/mezuro_plugin_profile_controller.rb
1 | class MezuroPluginProfileController < ProfileController | 1 | class MezuroPluginProfileController < ProfileController |
2 | 2 | ||
3 | append_view_path File.join(File.dirname(__FILE__) + '/../views') | 3 | append_view_path File.join(File.dirname(__FILE__) + '/../views') |
4 | - | 4 | + |
5 | + def error_page | ||
6 | + @message = params[:message] | ||
7 | + end | ||
8 | + | ||
5 | def project_state | 9 | def project_state |
6 | @content = profile.articles.find(params[:id]) | 10 | @content = profile.articles.find(params[:id]) |
7 | project = @content.project | 11 | project = @content.project |
8 | - state = project.error.nil? ? project.state : "ERROR" | ||
9 | - render :text => state | 12 | + if project_content_has_errors? |
13 | + redirect_to_error_page(@content.errors[:base]) | ||
14 | + else | ||
15 | + state = project.kalibro_error.nil? ? project.state : "ERROR" | ||
16 | + render :text => state | ||
17 | + end | ||
10 | end | 18 | end |
11 | 19 | ||
12 | def project_error | 20 | def project_error |
13 | @content = profile.articles.find(params[:id]) | 21 | @content = profile.articles.find(params[:id]) |
14 | @project = @content.project | 22 | @project = @content.project |
15 | - render :partial => 'content_viewer/project_error' | 23 | + if project_content_has_errors? |
24 | + redirect_to_error_page(@content.errors[:base]) | ||
25 | + else | ||
26 | + render :partial => 'content_viewer/project_error' | ||
27 | + end | ||
16 | end | 28 | end |
17 | 29 | ||
18 | def project_result | 30 | def project_result |
19 | @content = profile.articles.find(params[:id]) | 31 | @content = profile.articles.find(params[:id]) |
20 | date = params[:date] | 32 | date = params[:date] |
21 | @project_result = date.nil? ? @content.project_result : @content.project_result_with_date(date) | 33 | @project_result = date.nil? ? @content.project_result : @content.project_result_with_date(date) |
22 | - render :partial => 'content_viewer/project_result' | ||
23 | - end | 34 | + if project_content_has_errors? |
35 | + redirect_to_error_page(@content.errors[:base]) | ||
36 | + else | ||
37 | + render :partial => 'content_viewer/project_result' | ||
38 | + end | ||
39 | + end | ||
24 | 40 | ||
25 | def module_result | 41 | def module_result |
26 | @content = profile.articles.find(params[:id]) | 42 | @content = profile.articles.find(params[:id]) |
27 | @module_result = @content.module_result(params) | 43 | @module_result = @content.module_result(params) |
28 | - render :partial => 'content_viewer/module_result' | 44 | + @module = @module_result.module |
45 | + @module_label = "#{@module.name} (#{@module.granularity})" | ||
46 | + if project_content_has_errors? | ||
47 | + redirect_to_error_page(@content.errors[:base]) | ||
48 | + else | ||
49 | + render :partial => 'content_viewer/module_result' | ||
50 | + end | ||
29 | end | 51 | end |
30 | 52 | ||
31 | def project_tree | 53 | def project_tree |
32 | @content = profile.articles.find(params[:id]) | 54 | @content = profile.articles.find(params[:id]) |
33 | date = params[:date] | 55 | date = params[:date] |
34 | project_result = date.nil? ? @content.project_result : @content.project_result_with_date(date) | 56 | project_result = date.nil? ? @content.project_result : @content.project_result_with_date(date) |
35 | - @project_name = @content.project.name | ||
36 | - @source_tree = project_result.node_of(params[:module_name]) | ||
37 | - render :partial =>'content_viewer/source_tree' | 57 | + @project_name = @content.project.name if not @content.project.nil? |
58 | + if project_content_has_errors? | ||
59 | + redirect_to_error_page(@content.errors[:base]) | ||
60 | + else | ||
61 | + @source_tree = project_result.node(params[:module_name]) | ||
62 | + render :partial =>'content_viewer/source_tree' | ||
63 | + end | ||
38 | end | 64 | end |
39 | 65 | ||
40 | def module_metrics_history | 66 | def module_metrics_history |
41 | metric_name = params[:metric_name] | 67 | metric_name = params[:metric_name] |
42 | @content = profile.articles.find(params[:id]) | 68 | @content = profile.articles.find(params[:id]) |
43 | module_history = @content.result_history(params[:module_name]) | 69 | module_history = @content.result_history(params[:module_name]) |
44 | - @score_history = filtering_metric_history(metric_name, module_history) | ||
45 | - render :partial => 'content_viewer/score_history' | 70 | + if project_content_has_errors? |
71 | + redirect_to_error_page(@content.errors[:base]) | ||
72 | + else | ||
73 | + @score_history = filtering_metric_history(metric_name, module_history) | ||
74 | + render :partial => 'content_viewer/score_history' | ||
75 | + end | ||
46 | end | 76 | end |
47 | 77 | ||
48 | def module_grade_history | 78 | def module_grade_history |
49 | @content = profile.articles.find(params[:id]) | 79 | @content = profile.articles.find(params[:id]) |
50 | modules_results = @content.result_history(params[:module_name]) | 80 | modules_results = @content.result_history(params[:module_name]) |
51 | - @score_history = modules_results.collect { |module_result| module_result.grade } | ||
52 | - render :partial => 'content_viewer/score_history' | 81 | + if project_content_has_errors? |
82 | + redirect_to_error_page(@content.errors[:base]) | ||
83 | + else | ||
84 | + @score_history = modules_results.map do |module_result| | ||
85 | + [module_result.grade, format_date_to_simple_form(module_result.date)] | ||
86 | + end | ||
87 | + render :partial => 'content_viewer/score_history' | ||
88 | + end | ||
53 | end | 89 | end |
54 | - | 90 | + |
55 | private | 91 | private |
56 | - | 92 | + |
57 | def filtering_metric_history(metric_name, module_history) | 93 | def filtering_metric_history(metric_name, module_history) |
58 | metrics_history = module_history.map do |module_result| | 94 | metrics_history = module_history.map do |module_result| |
59 | - module_result.metric_results | 95 | + [module_result.metric_results, format_date_to_simple_form(module_result.date)] |
60 | end | 96 | end |
61 | - metric_history = metrics_history.map do |array_of_metric_result| | ||
62 | - (array_of_metric_result.select do |metric_result| | 97 | + metric_history = metrics_history.map do |metric_results_with_date| |
98 | + [(metric_results_with_date.first.select do |metric_result| | ||
63 | metric_result.metric.name.delete("() ") == metric_name | 99 | metric_result.metric.name.delete("() ") == metric_name |
64 | - end).first | 100 | + end).first, metric_results_with_date.last] |
65 | end | 101 | end |
66 | - metric_history.map do |metric_result| | ||
67 | - metric_result.value | 102 | + metric_history.map do |metric_result_with_date| |
103 | + [metric_result_with_date.first.value, metric_result_with_date.last] | ||
68 | end | 104 | end |
69 | end | 105 | end |
106 | + | ||
107 | + def redirect_to_error_page(message) | ||
108 | + message = URI.escape(CGI.escape(message),'.') | ||
109 | + redirect_to "/profile/#{profile.identifier}/plugins/mezuro/error_page?message=#{message}" | ||
110 | + end | ||
111 | + | ||
112 | + def project_content_has_errors? | ||
113 | + not @content.errors[:base].nil? | ||
114 | + end | ||
115 | + | ||
116 | + def format_date_to_simple_form date | ||
117 | + date.to_s[0..9] | ||
118 | + end | ||
119 | + | ||
70 | end | 120 | end |
plugins/mezuro/lib/kalibro/configuration.rb
@@ -7,11 +7,7 @@ class Kalibro::Configuration < Kalibro::Model | @@ -7,11 +7,7 @@ class Kalibro::Configuration < Kalibro::Model | ||
7 | end | 7 | end |
8 | 8 | ||
9 | def metric_configurations | 9 | def metric_configurations |
10 | - if @metric_configuration != nil | ||
11 | - @metric_configuration | ||
12 | - else | ||
13 | - [] | ||
14 | - end | 10 | + @metric_configuration.nil? ? [] : @metric_configuration |
15 | end | 11 | end |
16 | 12 | ||
17 | def metric_configurations=(metric_configurations) | 13 | def metric_configurations=(metric_configurations) |
@@ -19,19 +15,11 @@ class Kalibro::Configuration < Kalibro::Model | @@ -19,19 +15,11 @@ class Kalibro::Configuration < Kalibro::Model | ||
19 | end | 15 | end |
20 | 16 | ||
21 | def self.find_by_name(configuration_name) | 17 | def self.find_by_name(configuration_name) |
22 | - begin | ||
23 | - new request("Configuration", :get_configuration, {:configuration_name => configuration_name})[:configuration] | ||
24 | - rescue Exception => error | ||
25 | - nil | ||
26 | - end | 18 | + new request("Configuration", :get_configuration, {:configuration_name => configuration_name})[:configuration] |
27 | end | 19 | end |
28 | 20 | ||
29 | def self.all_names | 21 | def self.all_names |
30 | - begin | ||
31 | - request("Configuration", :get_configuration_names)[:configuration_name] | ||
32 | - rescue Exception | ||
33 | - [] | ||
34 | - end | 22 | + request("Configuration", :get_configuration_names)[:configuration_name] |
35 | end | 23 | end |
36 | 24 | ||
37 | def update_attributes(attributes={}) | 25 | def update_attributes(attributes={}) |
plugins/mezuro/lib/kalibro/metric_configuration.rb
@@ -49,10 +49,14 @@ class Kalibro::MetricConfiguration < Kalibro::Model | @@ -49,10 +49,14 @@ class Kalibro::MetricConfiguration < Kalibro::Model | ||
49 | end | 49 | end |
50 | 50 | ||
51 | def destroy | 51 | def destroy |
52 | - self.class.request("MetricConfiguration", :remove_metric_configuration, { | 52 | + begin |
53 | + self.class.request("MetricConfiguration", :remove_metric_configuration, { | ||
53 | :configuration_name => configuration_name, | 54 | :configuration_name => configuration_name, |
54 | :metric_name=> metric.name | 55 | :metric_name=> metric.name |
55 | }) | 56 | }) |
57 | + rescue Exception => exception | ||
58 | + add_error exception | ||
59 | + end | ||
56 | end | 60 | end |
57 | 61 | ||
58 | def to_hash | 62 | def to_hash |
plugins/mezuro/lib/kalibro/model.rb
1 | class Kalibro::Model | 1 | class Kalibro::Model |
2 | 2 | ||
3 | + attr_accessor :errors | ||
4 | + | ||
3 | def initialize(attributes={}) | 5 | def initialize(attributes={}) |
4 | attributes.each { |field, value| send("#{field}=", value) if self.class.is_valid?(field) } | 6 | attributes.each { |field, value| send("#{field}=", value) if self.class.is_valid?(field) } |
7 | + @errors = [] | ||
5 | end | 8 | end |
6 | 9 | ||
7 | def to_hash(options={}) | 10 | def to_hash(options={}) |
8 | hash = Hash.new | 11 | hash = Hash.new |
9 | excepts = !options[:except].nil? ? options[:except] : [] | 12 | excepts = !options[:except].nil? ? options[:except] : [] |
13 | + excepts << :errors | ||
10 | fields.each do |field| | 14 | fields.each do |field| |
11 | if(!excepts.include?(field)) | 15 | if(!excepts.include?(field)) |
12 | field_value = send(field) | 16 | field_value = send(field) |
@@ -46,15 +50,17 @@ class Kalibro::Model | @@ -46,15 +50,17 @@ class Kalibro::Model | ||
46 | begin | 50 | begin |
47 | self.class.request(save_endpoint, save_action, save_params) | 51 | self.class.request(save_endpoint, save_action, save_params) |
48 | true | 52 | true |
49 | - rescue Exception => error | ||
50 | - false | 53 | + rescue Exception => exception |
54 | + add_error exception | ||
55 | + false | ||
51 | end | 56 | end |
52 | end | 57 | end |
53 | 58 | ||
54 | def destroy | 59 | def destroy |
55 | begin | 60 | begin |
56 | self.class.request(destroy_endpoint, destroy_action, destroy_params) | 61 | self.class.request(destroy_endpoint, destroy_action, destroy_params) |
57 | - rescue Exception | 62 | + rescue Exception => exception |
63 | + add_error exception | ||
58 | end | 64 | end |
59 | end | 65 | end |
60 | 66 | ||
@@ -123,4 +129,9 @@ class Kalibro::Model | @@ -123,4 +129,9 @@ class Kalibro::Model | ||
123 | {"#{class_name.underscore}_name".to_sym => self.name} | 129 | {"#{class_name.underscore}_name".to_sym => self.name} |
124 | end | 130 | end |
125 | 131 | ||
132 | + def add_error(exception) | ||
133 | + @errors << exception | ||
134 | + end | ||
135 | + | ||
126 | end | 136 | end |
137 | + |
plugins/mezuro/lib/kalibro/project.rb
1 | class Kalibro::Project < Kalibro::Model | 1 | class Kalibro::Project < Kalibro::Model |
2 | 2 | ||
3 | - attr_accessor :name, :license, :description, :repository, :configuration_name, :state, :error | 3 | + attr_accessor :name, :license, :description, :repository, :configuration_name, :state, :kalibro_error |
4 | 4 | ||
5 | def self.all_names | 5 | def self.all_names |
6 | request("Project", :get_project_names)[:project_name] | 6 | request("Project", :get_project_names)[:project_name] |
@@ -15,23 +15,35 @@ class Kalibro::Project < Kalibro::Model | @@ -15,23 +15,35 @@ class Kalibro::Project < Kalibro::Model | ||
15 | end | 15 | end |
16 | 16 | ||
17 | def error=(value) | 17 | def error=(value) |
18 | - @error = Kalibro::Error.to_object value | 18 | + @kalibro_error = Kalibro::Error.to_object value |
19 | end | 19 | end |
20 | 20 | ||
21 | def process_project(days = '0') | 21 | def process_project(days = '0') |
22 | - if days.to_i.zero? | ||
23 | - self.class.request("Kalibro", :process_project, {:project_name => name}) | ||
24 | - else | ||
25 | - self.class.request("Kalibro", :process_periodically, {:project_name => name, :period_in_days => days}) | ||
26 | - end | 22 | + begin |
23 | + if days.to_i.zero? | ||
24 | + self.class.request("Kalibro", :process_project, {:project_name => name}) | ||
25 | + else | ||
26 | + self.class.request("Kalibro", :process_periodically, {:project_name => name, :period_in_days => days}) | ||
27 | + end | ||
28 | + rescue Exception => exception | ||
29 | + add_error exception | ||
30 | + end | ||
27 | end | 31 | end |
28 | 32 | ||
29 | def process_period | 33 | def process_period |
30 | - self.class.request("Kalibro", :get_process_period, {:project_name => name})[:period] | 34 | + begin |
35 | + self.class.request("Kalibro", :get_process_period, {:project_name => name})[:period] | ||
36 | + rescue Exception => exception | ||
37 | + add_error exception | ||
38 | + end | ||
31 | end | 39 | end |
32 | 40 | ||
33 | def cancel_periodic_process | 41 | def cancel_periodic_process |
34 | - self.class.request("Kalibro", :cancel_periodic_process, {:project_name => name}) | 42 | + begin |
43 | + self.class.request("Kalibro", :cancel_periodic_process, {:project_name => name}) | ||
44 | + rescue Exception => exception | ||
45 | + add_error exception | ||
46 | + end | ||
35 | end | 47 | end |
36 | 48 | ||
37 | end | 49 | end |
plugins/mezuro/lib/kalibro/project_result.rb
@@ -75,21 +75,17 @@ class Kalibro::ProjectResult < Kalibro::Model | @@ -75,21 +75,17 @@ class Kalibro::ProjectResult < Kalibro::Model | ||
75 | ('%2d' % amount).sub(/\s/, '0') | 75 | ('%2d' % amount).sub(/\s/, '0') |
76 | end | 76 | end |
77 | 77 | ||
78 | - def node_of(module_name) | 78 | + def node(module_name) |
79 | if module_name.nil? or module_name == project.name | 79 | if module_name.nil? or module_name == project.name |
80 | node = source_tree | 80 | node = source_tree |
81 | else | 81 | else |
82 | - node = get_node(module_name) | ||
83 | - end | ||
84 | - end | ||
85 | - | ||
86 | - def get_node(module_name) | ||
87 | - path = Kalibro::Module.parent_names(module_name) | ||
88 | - parent = @source_tree | ||
89 | - path.each do |node_name| | ||
90 | - parent = get_leaf_from(parent, node_name) | ||
91 | - end | ||
92 | - return parent | 82 | + path = Kalibro::Module.parent_names(module_name) |
83 | + parent = @source_tree | ||
84 | + path.each do |node_name| | ||
85 | + parent = get_leaf_from(parent, node_name) | ||
86 | + end | ||
87 | + parent | ||
88 | + end | ||
93 | end | 89 | end |
94 | 90 | ||
95 | private | 91 | private |
plugins/mezuro/lib/kalibro/range.rb
@@ -34,4 +34,12 @@ class Kalibro::Range < Kalibro::Model | @@ -34,4 +34,12 @@ class Kalibro::Range < Kalibro::Model | ||
34 | @grade = value.to_f | 34 | @grade = value.to_f |
35 | end | 35 | end |
36 | 36 | ||
37 | + def mezuro_color | ||
38 | + @color.nil? ? "#e4ca2d" : @color.gsub(/^ff/, "#") | ||
39 | + end | ||
40 | + | ||
41 | + def color=(new_color) | ||
42 | + @color = new_color.gsub(/^#/, "ff") | ||
43 | + end | ||
44 | + | ||
37 | end | 45 | end |
plugins/mezuro/lib/mezuro_plugin/configuration_content.rb
@@ -3,8 +3,8 @@ class MezuroPlugin::ConfigurationContent < Article | @@ -3,8 +3,8 @@ class MezuroPlugin::ConfigurationContent < Article | ||
3 | 3 | ||
4 | settings_items :description, :configuration_to_clone_name | 4 | settings_items :description, :configuration_to_clone_name |
5 | 5 | ||
6 | - after_save :send_configuration_to_service | ||
7 | - after_destroy :remove_configuration_from_service | 6 | + after_save :send_kalibro_configuration_to_service |
7 | + after_destroy :remove_kalibro_configuration_from_service | ||
8 | 8 | ||
9 | def self.short_description | 9 | def self.short_description |
10 | 'Kalibro configuration' | 10 | 'Kalibro configuration' |
@@ -21,54 +21,60 @@ class MezuroPlugin::ConfigurationContent < Article | @@ -21,54 +21,60 @@ class MezuroPlugin::ConfigurationContent < Article | ||
21 | end | 21 | end |
22 | end | 22 | end |
23 | 23 | ||
24 | - def configuration | ||
25 | - @configuration ||= Kalibro::Configuration.find_by_name(self.name) | ||
26 | - if @configuration.nil? | ||
27 | - errors.add_to_base("Kalibro Configuration not found") | 24 | + def kalibro_configuration |
25 | + begin | ||
26 | + @kalibro_configuration ||= Kalibro::Configuration.find_by_name(self.name) | ||
27 | + rescue Exception => exception | ||
28 | + errors.add_to_base(exception.message) | ||
28 | end | 29 | end |
29 | - @configuration | 30 | + @kalibro_configuration |
30 | end | 31 | end |
31 | 32 | ||
32 | def metric_configurations | 33 | def metric_configurations |
33 | - configuration.metric_configurations | 34 | + kalibro_configuration.metric_configurations |
34 | end | 35 | end |
35 | 36 | ||
36 | - def configuration_names | ||
37 | - ["None"] + Kalibro::Configuration.all_names.sort | 37 | + def kalibro_configuration_names |
38 | + begin | ||
39 | + ["None"] + Kalibro::Configuration.all_names.sort | ||
40 | + rescue Exception => exception | ||
41 | + errors.add_to_base(exception.message) | ||
42 | + ["None"] | ||
43 | + end | ||
38 | end | 44 | end |
39 | 45 | ||
40 | private | 46 | private |
41 | 47 | ||
42 | def validate_kalibro_configuration_name | 48 | def validate_kalibro_configuration_name |
43 | - existing = configuration_names.map { |a| a.downcase} | 49 | + existing = kalibro_configuration_names.map { |a| a.downcase} |
44 | 50 | ||
45 | if existing.include?(name.downcase) | 51 | if existing.include?(name.downcase) |
46 | errors.add_to_base("Configuration name already exists in Kalibro") | 52 | errors.add_to_base("Configuration name already exists in Kalibro") |
47 | end | 53 | end |
48 | end | 54 | end |
49 | 55 | ||
50 | - def send_configuration_to_service | ||
51 | - if editing_configuration? | ||
52 | - configuration.update_attributes({:description => description}) | 56 | + def send_kalibro_configuration_to_service |
57 | + if editing_kalibro_configuration? | ||
58 | + kalibro_configuration.update_attributes({:description => description}) | ||
53 | else | 59 | else |
54 | create_kalibro_configuration | 60 | create_kalibro_configuration |
55 | end | 61 | end |
56 | end | 62 | end |
57 | 63 | ||
58 | - def remove_configuration_from_service | ||
59 | - configuration.destroy | 64 | + def remove_kalibro_configuration_from_service |
65 | + kalibro_configuration.destroy unless kalibro_configuration.nil? | ||
60 | end | 66 | end |
61 | 67 | ||
62 | def create_kalibro_configuration | 68 | def create_kalibro_configuration |
63 | attributes = {:name => name, :description => description} | 69 | attributes = {:name => name, :description => description} |
64 | - if cloning_configuration? | 70 | + if cloning_kalibro_configuration? |
65 | attributes[:metric_configuration] = configuration_to_clone.metric_configurations_hash | 71 | attributes[:metric_configuration] = configuration_to_clone.metric_configurations_hash |
66 | end | 72 | end |
67 | Kalibro::Configuration.create attributes | 73 | Kalibro::Configuration.create attributes |
68 | end | 74 | end |
69 | 75 | ||
70 | - def editing_configuration? | ||
71 | - configuration.present? | 76 | + def editing_kalibro_configuration? |
77 | + kalibro_configuration.present? | ||
72 | end | 78 | end |
73 | 79 | ||
74 | def configuration_to_clone | 80 | def configuration_to_clone |
@@ -76,10 +82,10 @@ class MezuroPlugin::ConfigurationContent < Article | @@ -76,10 +82,10 @@ class MezuroPlugin::ConfigurationContent < Article | ||
76 | end | 82 | end |
77 | 83 | ||
78 | def find_configuration_to_clone | 84 | def find_configuration_to_clone |
79 | - configuration_to_clone_name.nil? ? nil : Kalibro::Configuration.find_by_name(configuration_to_clone_name) | 85 | + (configuration_to_clone_name == "None") ? nil : Kalibro::Configuration.find_by_name(configuration_to_clone_name) |
80 | end | 86 | end |
81 | 87 | ||
82 | - def cloning_configuration? | 88 | + def cloning_kalibro_configuration? |
83 | configuration_to_clone.present? | 89 | configuration_to_clone.present? |
84 | end | 90 | end |
85 | 91 |
plugins/mezuro/lib/mezuro_plugin/helpers/content_viewer_helper.rb
1 | class MezuroPlugin::Helpers::ContentViewerHelper | 1 | class MezuroPlugin::Helpers::ContentViewerHelper |
2 | + | ||
3 | + MAX_NUMBER_OF_LABELS = 5 | ||
4 | + | ||
2 | def self.format_grade(grade) | 5 | def self.format_grade(grade) |
3 | sprintf("%.2f", grade.to_f) | 6 | sprintf("%.2f", grade.to_f) |
4 | end | 7 | end |
@@ -6,15 +9,31 @@ class MezuroPlugin::Helpers::ContentViewerHelper | @@ -6,15 +9,31 @@ class MezuroPlugin::Helpers::ContentViewerHelper | ||
6 | def self.create_periodicity_options | 9 | def self.create_periodicity_options |
7 | [["Not Periodically", 0], ["1 day", 1], ["2 days", 2], ["Weekly", 7], ["Biweeky", 15], ["Monthly", 30]] | 10 | [["Not Periodically", 0], ["1 day", 1], ["2 days", 2], ["Weekly", 7], ["Biweeky", 15], ["Monthly", 30]] |
8 | end | 11 | end |
9 | - | ||
10 | - def self.generate_chart(values) | ||
11 | - Gchart.line( | 12 | + |
13 | + def self.create_license_options | ||
14 | + options = YAML.load_file("#{RAILS_ROOT}/plugins/mezuro/licenses.yaml") | ||
15 | + options = options.split(";") | ||
16 | + formated_options = [] | ||
17 | + options.each { |option| formated_options << [option, option] } | ||
18 | + formated_options | ||
19 | + end | ||
20 | + | ||
21 | + def self.generate_chart(score_history) | ||
22 | + values = [] | ||
23 | + labels = [] | ||
24 | + score_history.each do |score_data| | ||
25 | + values << score_data.first | ||
26 | + labels << score_data.last | ||
27 | + end | ||
28 | + labels = discretize_array labels | ||
29 | + Gchart.line( | ||
12 | :title_color => 'FF0000', | 30 | :title_color => 'FF0000', |
13 | :size => '600x180', | 31 | :size => '600x180', |
14 | :bg => {:color => 'efefef', :type => 'stripes'}, | 32 | :bg => {:color => 'efefef', :type => 'stripes'}, |
15 | :line_colors => 'c4a000', | 33 | :line_colors => 'c4a000', |
16 | :data => values, | 34 | :data => values, |
17 | - :axis_with_labels => 'y', | 35 | + :labels => labels, |
36 | + :axis_with_labels => ['y','x'], | ||
18 | :max_value => values.max, | 37 | :max_value => values.max, |
19 | :min_value => values.min | 38 | :min_value => values.min |
20 | ) | 39 | ) |
@@ -25,8 +44,33 @@ class MezuroPlugin::Helpers::ContentViewerHelper | @@ -25,8 +44,33 @@ class MezuroPlugin::Helpers::ContentViewerHelper | ||
25 | selected_option = options.find { |option| option.last == index.to_i } | 44 | selected_option = options.find { |option| option.last == index.to_i } |
26 | selected_option.first | 45 | selected_option.first |
27 | end | 46 | end |
28 | - | 47 | + |
29 | def self.format_name(metric_result) | 48 | def self.format_name(metric_result) |
30 | metric_result.metric.name.delete("() ") | 49 | metric_result.metric.name.delete("() ") |
31 | end | 50 | end |
51 | + | ||
52 | + def self.get_license_option(selected) | ||
53 | + options = YAML.load_file("#{RAILS_ROOT}/plugins/mezuro/licenses.yaml") | ||
54 | + options.split(";") | ||
55 | + selected_option = options.find { |license| license == selected } | ||
56 | + end | ||
57 | + | ||
58 | + private | ||
59 | + | ||
60 | + def self.discretize_array(array) | ||
61 | + if array.size > MAX_NUMBER_OF_LABELS | ||
62 | + range_array.map { |i| discrete_element(array, i)} | ||
63 | + else | ||
64 | + array | ||
65 | + end | ||
66 | + end | ||
67 | + | ||
68 | + def self.range_array | ||
69 | + (0..(MAX_NUMBER_OF_LABELS - 1)).to_a | ||
70 | + end | ||
71 | + | ||
72 | + def self.discrete_element(array, i) | ||
73 | + array[(i*(array.size - 1))/(MAX_NUMBER_OF_LABELS - 1)] | ||
74 | + end | ||
75 | + | ||
32 | end | 76 | end |
plugins/mezuro/lib/mezuro_plugin/project_content.rb
1 | class MezuroPlugin::ProjectContent < Article | 1 | class MezuroPlugin::ProjectContent < Article |
2 | include ActionView::Helpers::TagHelper | 2 | include ActionView::Helpers::TagHelper |
3 | 3 | ||
4 | - settings_items :license, :description, :repository_type, :repository_url, :configuration_name, :periodicity_in_days | 4 | + settings_items :project_license, :description, :repository_type, :repository_url, :configuration_name, :periodicity_in_days |
5 | 5 | ||
6 | validate_on_create :validate_kalibro_project_name | 6 | validate_on_create :validate_kalibro_project_name |
7 | validate_on_create :validate_repository_url | 7 | validate_on_create :validate_repository_url |
@@ -26,6 +26,7 @@ class MezuroPlugin::ProjectContent < Article | @@ -26,6 +26,7 @@ class MezuroPlugin::ProjectContent < Article | ||
26 | rescue Exception => error | 26 | rescue Exception => error |
27 | errors.add_to_base(error.message) | 27 | errors.add_to_base(error.message) |
28 | end | 28 | end |
29 | + @project | ||
29 | end | 30 | end |
30 | 31 | ||
31 | def project_result | 32 | def project_result |
@@ -34,6 +35,7 @@ class MezuroPlugin::ProjectContent < Article | @@ -34,6 +35,7 @@ class MezuroPlugin::ProjectContent < Article | ||
34 | rescue Exception => error | 35 | rescue Exception => error |
35 | errors.add_to_base(error.message) | 36 | errors.add_to_base(error.message) |
36 | end | 37 | end |
38 | + @project_result | ||
37 | end | 39 | end |
38 | 40 | ||
39 | def project_result_with_date(date) | 41 | def project_result_with_date(date) |
@@ -43,6 +45,7 @@ Kalibro::ProjectResult.first_result_after(name, date) | @@ -43,6 +45,7 @@ Kalibro::ProjectResult.first_result_after(name, date) | ||
43 | rescue Exception => error | 45 | rescue Exception => error |
44 | errors.add_to_base(error.message) | 46 | errors.add_to_base(error.message) |
45 | end | 47 | end |
48 | + @project_result | ||
46 | end | 49 | end |
47 | 50 | ||
48 | def module_result(attributes) | 51 | def module_result(attributes) |
@@ -53,6 +56,7 @@ Kalibro::ProjectResult.first_result_after(name, date) | @@ -53,6 +56,7 @@ Kalibro::ProjectResult.first_result_after(name, date) | ||
53 | rescue Exception => error | 56 | rescue Exception => error |
54 | errors.add_to_base(error.message) | 57 | errors.add_to_base(error.message) |
55 | end | 58 | end |
59 | + @module_result | ||
56 | end | 60 | end |
57 | 61 | ||
58 | def result_history(module_name) | 62 | def result_history(module_name) |
@@ -73,6 +77,7 @@ Kalibro::ProjectResult.first_result_after(name, date) | @@ -73,6 +77,7 @@ Kalibro::ProjectResult.first_result_after(name, date) | ||
73 | existing = Kalibro::Project.all_names | 77 | existing = Kalibro::Project.all_names |
74 | rescue Exception => error | 78 | rescue Exception => error |
75 | errors.add_to_base(error.message) | 79 | errors.add_to_base(error.message) |
80 | + existing = [] | ||
76 | end | 81 | end |
77 | 82 | ||
78 | if existing.any?{|existing_name| existing_name.casecmp(name)==0} # existing.include?(name) + case insensitive | 83 | if existing.any?{|existing_name| existing_name.casecmp(name)==0} # existing.include?(name) + case insensitive |
@@ -94,7 +99,7 @@ Kalibro::ProjectResult.first_result_after(name, date) | @@ -94,7 +99,7 @@ Kalibro::ProjectResult.first_result_after(name, date) | ||
94 | def create_kalibro_project | 99 | def create_kalibro_project |
95 | Kalibro::Project.create( | 100 | Kalibro::Project.create( |
96 | :name => name, | 101 | :name => name, |
97 | - :license => license, | 102 | + :license => project_license, |
98 | :description => description, | 103 | :description => description, |
99 | :repository => { | 104 | :repository => { |
100 | :type => repository_type, | 105 | :type => repository_type, |
@@ -105,7 +110,7 @@ Kalibro::ProjectResult.first_result_after(name, date) | @@ -105,7 +110,7 @@ Kalibro::ProjectResult.first_result_after(name, date) | ||
105 | end | 110 | end |
106 | 111 | ||
107 | def destroy_project_from_service | 112 | def destroy_project_from_service |
108 | - project.destroy | 113 | + project.destroy unless project.nil? |
109 | end | 114 | end |
110 | 115 | ||
111 | end | 116 | end |
@@ -0,0 +1,69 @@ | @@ -0,0 +1,69 @@ | ||
1 | +Academic Free License 3.0 (AFL-3.0); | ||
2 | +Affero GNU Public License (AGPL-3.0); | ||
3 | +Adaptive Public License (APL-1.0); | ||
4 | +Apache License 2.0 (Apache-2.0); | ||
5 | +Apple Public Source License (APSL-2.0); | ||
6 | +Artistic license 2.0 (Artistic-2.0); | ||
7 | +Attribution Assurance Licenses (AAL); | ||
8 | +BSD 3-Clause "New" or "Revised" License (BSD-3-Clause); | ||
9 | +BSD 2-Clause "Simplified" or "FreeBSD" License (BSD-2-Clause); | ||
10 | +Boost Software License (BSL-1.0); | ||
11 | +Computer Associates Trusted Open Source License 1.1 (CATOSL-1.1); | ||
12 | +Common Development and Distribution License 1.0 (CDDL-1.0); | ||
13 | +Common Public Attribution License 1.0 (CPAL-1.0); | ||
14 | +CUA Office Public License Version 1.0 (CUA-OPL-1.0); | ||
15 | +EU DataGrid Software License (EUDatagrid); | ||
16 | +Eclipse Public License 1.0 (EPL-1.0); | ||
17 | +Educational Community License, Version 2.0 (ECL-2.0); | ||
18 | +Eiffel Forum License V2.0 (EFL-2.0); | ||
19 | +Entessa Public License (Entessa); | ||
20 | +European Union Public License, Version 1.1 (EUPL-1.1); | ||
21 | +Fair License (FAIR); | ||
22 | +Frameworx License (Frameworx-1.0); | ||
23 | +GNU Affero General Public License v3 (AGPL-3.0); | ||
24 | +GNU General Public License version 2.0 (GPL-2.0); | ||
25 | +GNU General Public License version 3.0 (GPL-3.0); | ||
26 | +GNU Library or "Lesser" General Public License version 2.1 (LGPL-2.1); | ||
27 | +GNU Library or "Lesser" General Public License version 3.0 (LGPL-3.0); | ||
28 | +Historical Permission Notice and Disclaimer (HPND); | ||
29 | +IBM Public License 1.0 (IPL-1.0); | ||
30 | +IPA Font License (IPA); | ||
31 | +ISC License (ISC); | ||
32 | +LaTeX Project Public License 1.3c (LPPL-1.3c); | ||
33 | +Lucent Public License Version 1.02 (LPL-1.02); | ||
34 | +MirOS Licence (MirOS); | ||
35 | +Microsoft Public License (Ms-PL); | ||
36 | +Microsoft Reciprocal License (Ms-RL); | ||
37 | +MIT license (MIT); | ||
38 | +Motosoto License (Motosoto); | ||
39 | +Mozilla Public License 2.0 (MPL-2.0); | ||
40 | +Multics License (Multics); | ||
41 | +NASA Open Source Agreement 1.3 (NASA 1.3); | ||
42 | +NTP License (NTP); | ||
43 | +Naumen Public License (Naumen); | ||
44 | +Nethack General Public License (NGPL); | ||
45 | +Nokia Open Source License (Nokia); | ||
46 | +Non-Profit Open Software License 3.0 (NPOSL-3.0); | ||
47 | +OCLC Research Public License 2.0 (OCLC-2.0); | ||
48 | +Open Font License 1.1 (OFL 1.1); | ||
49 | +Open Group Test Suite License (OGTSL); | ||
50 | +Open Software License 3.0 (OSL-3.0); | ||
51 | +PHP License 3.0 (PHP-3.0); | ||
52 | +The PostgreSQL License (PostgreSQL); | ||
53 | +Python License (Python-2.0); | ||
54 | +CNRI Python license (CNRI-Python); | ||
55 | +Q Public License (QPL-1.0); | ||
56 | +RealNetworks Public Source License V1.0 (RPSL-1.0); | ||
57 | +Reciprocal Public License 1.5 (RPL-1.5); | ||
58 | +Ricoh Source Code Public License (RSCPL); | ||
59 | +Simple Public License 2.0 (SimPL-2.0); | ||
60 | +Sleepycat License (Sleepycat); | ||
61 | +Sun Public License 1.0 (SPL-1.0); | ||
62 | +Sybase Open Watcom Public License 1.0 (Watcom-1.0); | ||
63 | +University of Illinois/NCSA Open Source License (NCSA); | ||
64 | +Vovida Software License v. 1.0 (VSL-1.0); | ||
65 | +W3C License (W3C); | ||
66 | +wxWindows Library License (WXwindows); | ||
67 | +X.Net License (Xnet); | ||
68 | +Zope Public License 2.0 (ZPL-2.0); | ||
69 | +zlib/libpng license (Zlib); |
@@ -0,0 +1,31 @@ | @@ -0,0 +1,31 @@ | ||
1 | +div.colorPicker-picker { | ||
2 | + height: 16px; | ||
3 | + width: 16px; | ||
4 | + padding: 0 !important; | ||
5 | + border: 1px solid #ccc; | ||
6 | + background: url(arrow.gif) no-repeat top right; | ||
7 | + cursor: pointer; | ||
8 | + line-height: 16px; | ||
9 | +} | ||
10 | + | ||
11 | +div.colorPicker-palette { | ||
12 | + width: 110px; | ||
13 | + position: absolute; | ||
14 | + border: 1px solid #598FEF; | ||
15 | + background-color: #EFEFEF; | ||
16 | + padding: 2px; | ||
17 | + z-index: 9999; | ||
18 | +} | ||
19 | + div.colorPicker_hexWrap {width: 100%; float:left } | ||
20 | + div.colorPicker_hexWrap label {font-size: 95%; color: #2F2F2F; margin: 5px 2px; width: 25%} | ||
21 | + div.colorPicker_hexWrap input {margin: 5px 2px; padding: 0; font-size: 95%; border: 1px solid #000; width: 65%; } | ||
22 | + | ||
23 | +div.colorPicker-swatch { | ||
24 | + height: 12px; | ||
25 | + width: 12px; | ||
26 | + border: 1px solid #000; | ||
27 | + margin: 2px; | ||
28 | + float: left; | ||
29 | + cursor: pointer; | ||
30 | + line-height: 12px; | ||
31 | +} |
@@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
1 | +Copyright (c) 2012 Lakshan Perera | ||
2 | + | ||
3 | +Permission is hereby granted, free of charge, to any person | ||
4 | +obtaining a copy of this software and associated documentation | ||
5 | +files (the "Software"), to deal in the Software without | ||
6 | +restriction, including without limitation the rights to use, | ||
7 | +copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
8 | +copies of the Software, and to permit persons to whom the | ||
9 | +Software is furnished to do so, subject to the following | ||
10 | +conditions: | ||
11 | + | ||
12 | +The above copyright notice and this permission notice shall be | ||
13 | +included in all copies or substantial portions of the Software. | ||
14 | + | ||
15 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
16 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
17 | +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
18 | +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
19 | +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
20 | +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
21 | +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
22 | +OTHER DEALINGS IN THE SOFTWARE. |