Commit 527ee37971f8b42854adbce04e3bd97be06d6361

Authored by Rodrigo Souto
2 parents 4eae3f9b ffb7fba6

Merge branch 'stable'

Basically html_safe in some places that the stable branch had.

Conflicts:
	app/models/article_block.rb
	app/models/tags_block.rb
Showing 45 changed files with 373 additions and 193 deletions   Show diff stats
AUTHORS
... ... @@ -148,6 +148,7 @@ Rodrigo Souto <rodrigo@colivre.coop.br>
148 148 Ronny Kursawe <kursawe.ronny@googlemail.com>
149 149 Samuel R. C. Vale <srcvale@holoscopio.com>
150 150 Valessio Brito <valessio@gmail.com>
  151 +Visita <visita@debian.(none)>
151 152 Yann Lugrin <yann.lugrin@liquid-concept.ch>
152 153  
153 154 Ideas, specifications and incentive
... ...
app/controllers/admin/users_controller.rb
  1 +require 'csv'
  2 +
1 3 class UsersController < AdminController
2 4  
3 5 protect 'manage_environment_users', :environment
... ... @@ -15,8 +17,16 @@ class UsersController &lt; AdminController
15 17 :disposition => "attachment; filename=users.xml"
16 18 end
17 19 format.csv do
18   - @users = User.find(:all, :conditions => {:environment_id => environment.id}, :include => [:person])
19   - render :template => "users/index_csv.rhtml", :content_type => 'text/csv', :layout => false
  20 + # using a direct connection with the dbms to optimize
  21 + command = User.send(:sanitize_sql, ["SELECT profiles.name, users.email FROM profiles
  22 + INNER JOIN users ON profiles.user_id=users.id
  23 + WHERE profiles.environment_id = ?", environment.id])
  24 + users = User.connection.execute(command)
  25 + csv_content = "name;email\n"
  26 + users.each { |u|
  27 + CSV.generate_row([u['name'], u['email']], 2, csv_content, fs=';')
  28 + }
  29 + render :text => csv_content, :content_type => 'text/csv', :layout => false
20 30 end
21 31 end
22 32 end
... ...
app/controllers/my_profile/profile_members_controller.rb
... ... @@ -32,7 +32,6 @@ class ProfileMembersController &lt; MyProfileController
32 32  
33 33 def last_admin
34 34 @roles = [Profile::Roles.admin(environment.id)]
35   - @pre_population = [].to_json
36 35 end
37 36  
38 37 def add_role
... ...
app/helpers/application_helper.rb
... ... @@ -495,23 +495,24 @@ module ApplicationHelper
495 495  
496 496 def profile_cat_icons( profile )
497 497 if profile.class == Enterprise
498   - icons =
499   - profile.product_categories.map{ |c| c.size > 1 ? c[1] : nil }.
500   - compact.uniq.map{ |c|
501   - cat_name = c.gsub( /[-_\s,.;'"]+/, '_' )
502   - cat_icon = "/images/icons-cat/#{cat_name}.png"
503   - if ! File.exists? RAILS_ROOT.to_s() + '/public/' + cat_icon
504   - cat_icon = '/images/icons-cat/undefined.png'
505   - end
506   - content_tag 'span',
507   - content_tag( 'span', c ),
508   - :title => c,
509   - :class => 'product-cat-icon cat_icon_' + cat_name,
510   - :style => "background-image:url(#{cat_icon})"
511   - }.join "\n"
512   - content_tag 'div',
513   - content_tag( 'span', _('Principal Product Categories'), :class => 'header' ) +"\n"+ icons,
514   - :class => 'product-category-icons'
  498 + icons = profile.product_categories.map{ |c| c.size > 1 ? c[1] : nil }.
  499 + compact.uniq.map do |c|
  500 + cat_name = c.gsub( /[-_\s,.;'"]+/, '_' )
  501 + cat_icon = "/images/icons-cat/#{cat_name}.png"
  502 + if ! File.exists? RAILS_ROOT.to_s() + '/public/' + cat_icon
  503 + cat_icon = '/images/icons-cat/undefined.png'
  504 + end
  505 + content_tag('span',
  506 + content_tag( 'span', c ),
  507 + :title => c,
  508 + :class => 'product-cat-icon cat_icon_' + cat_name,
  509 + :style => "background-image:url(#{cat_icon})"
  510 + )
  511 + end.join("\n").html_safe
  512 + content_tag('div',
  513 + content_tag( 'span', _('Principal Product Categories'), :class => 'header' ) +"\n"+ icons,
  514 + :class => 'product-category-icons'
  515 + )
515 516 else
516 517 ''
517 518 end
... ... @@ -635,10 +636,10 @@ module ApplicationHelper
635 636 # FIXME
636 637 ([toplevel] + toplevel.children_for_menu).each do |cat|
637 638 if cat.top_level?
638   - result << '<div class="categorie_box">'
  639 + result << '<div class="categorie_box">'.html_safe
639 640 result << icon_button( :down, _('open'), '#', :onclick => 'open_close_cat(this); return false' )
640 641 result << content_tag('h5', toplevel.name)
641   - result << '<div style="display:none"><ul class="categories">'
  642 + result << '<div style="display:none"><ul class="categories">'.html_safe
642 643 else
643 644 checkbox_id = "#{object_name}_#{cat.full_name.downcase.gsub(/\s+|\//, '_')}"
644 645 result << content_tag('li', labelled_check_box(
... ... @@ -649,7 +650,7 @@ module ApplicationHelper
649 650 :class => ( object.category_ids.include?(cat.id) ? 'cat_checked' : '' ) ) + "\n"
650 651 end
651 652 end
652   - result << '</ul></div></div>'
  653 + result << '</ul></div></div>'.html_safe
653 654 end
654 655  
655 656 content_tag('div', result)
... ... @@ -789,10 +790,10 @@ module ApplicationHelper
789 790 :class => 'lineitem' + (line_item+=1).to_s() ) +"\n"
790 791 if line_item == line_size
791 792 line_item = 0
792   - html += "<br />\n"
  793 + html += "<br />\n".html_safe
793 794 end
794 795 }
795   - html += "<br />\n" if line_size == 0 || ( values.size % line_size ) > 0
  796 + html += "<br />\n".html_safe if line_size == 0 || ( values.size % line_size ) > 0
796 797 column = object.class.columns_hash[method.to_s]
797 798 text =
798 799 ( column ?
... ... @@ -930,7 +931,7 @@ module ApplicationHelper
930 931 end
931 932  
932 933 def link_to_email(email)
933   - javascript_tag('var array = ' + email.split('@').to_json + '; document.write("<a href=\'mailto:" + array.join("@") + "\'>" + array.join("@") + "</a>")')
  934 + javascript_tag('var array = ' + email.split('@').to_json + '; document.write("<a href=\'mailto:" + array.join("@") + "\'>" + array.join("@") + "</a>")'.html_safe)
934 935 end
935 936  
936 937 def stylesheet(*args)
... ... @@ -940,7 +941,7 @@ module ApplicationHelper
940 941 def article_to_html(article, options = {})
941 942 options.merge!(:page => params[:npage])
942 943 content = article.to_html(options)
943   - content = content.kind_of?(Proc) ? self.instance_eval(&content) : content
  944 + content = content.kind_of?(Proc) ? self.instance_eval(&content).html_safe : content.html_safe
944 945 @plugins && @plugins.each do |plugin|
945 946 content = plugin.parse_content(content)
946 947 end
... ... @@ -986,7 +987,7 @@ module ApplicationHelper
986 987 end
987 988  
988 989 def ui_icon(icon_class, extra_class = '')
989   - "<span class='ui-icon #{icon_class} #{extra_class}' style='float:left; margin-right:7px;'></span>"
  990 + "<span class='ui-icon #{icon_class} #{extra_class}' style='float:left; margin-right:7px;'></span>".html_safe
990 991 end
991 992  
992 993 def ui_button(label, url, html_options = {})
... ... @@ -1014,13 +1015,13 @@ module ApplicationHelper
1014 1015 end
1015 1016  
1016 1017 def collapsed_item_icon
1017   - "<span class='ui-icon ui-icon-circlesmall-plus' style='float:left;'></span>"
  1018 + "<span class='ui-icon ui-icon-circlesmall-plus' style='float:left;'></span>".html_safe
1018 1019 end
1019 1020 def expanded_item_icon
1020   - "<span class='ui-icon ui-icon-circlesmall-minus' style='float:left;'></span>"
  1021 + "<span class='ui-icon ui-icon-circlesmall-minus' style='float:left;'></span>".html_safe
1021 1022 end
1022 1023 def leaf_item_icon
1023   - "<span class='ui-icon ui-icon-arrow-1-e' style='float:left;'></span>"
  1024 + "<span class='ui-icon ui-icon-arrow-1-e' style='float:left;'></span>".html_safe
1024 1025 end
1025 1026  
1026 1027 def display_category_menu(block, categories, root = true)
... ... @@ -1279,9 +1280,7 @@ module ApplicationHelper
1279 1280 titles = tabs.inject(''){ |result, tab| result << content_tag(:li, link_to(tab[:title], '#'+tab[:id]), :class => 'tab') }
1280 1281 contents = tabs.inject(''){ |result, tab| result << content_tag(:div, tab[:content], :id => tab[:id]) }
1281 1282  
1282   - content_tag :div, :class => 'ui-tabs' do
1283   - content_tag(:ul, titles) + contents
1284   - end
  1283 + content_tag(:div, content_tag(:ul, titles) + raw(contents), :class => 'ui-tabs')
1285 1284 end
1286 1285  
1287 1286 def jquery_token_input_messages_json(hintText = _('Type in an keyword'), noResultsText = _('No results'), searchingText = _('Searching...'))
... ... @@ -1310,11 +1309,12 @@ module ApplicationHelper
1310 1309 end
1311 1310  
1312 1311 def template_options(klass, field_name)
1313   - return '' if klass.templates.count == 0
1314   - return hidden_field_tag("#{field_name}[template_id]", klass.templates.first.id) if klass.templates.count == 1
  1312 + templates = klass.templates(environment)
  1313 + return '' if templates.count == 0
  1314 + return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1
1315 1315  
1316 1316 counter = 0
1317   - radios = klass.templates.map do |template|
  1317 + radios = templates.map do |template|
1318 1318 counter += 1
1319 1319 content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, counter==1))
1320 1320 end.join("\n")
... ...
app/helpers/block_helper.rb
... ... @@ -3,7 +3,7 @@ module BlockHelper
3 3 def block_title(title)
4 4 tag_class = 'block-title'
5 5 tag_class += ' empty' if title.empty?
6   - content_tag 'h3', content_tag('span', title), :class => tag_class
  6 + content_tag 'h3', content_tag('span', h(title)), :class => tag_class
7 7 end
8 8  
9 9 end
... ...
app/helpers/content_viewer_helper.rb
... ... @@ -46,7 +46,7 @@ module ContentViewerHelper
46 46 { article.environment.locales[translation.language] => { :href => url_for(translation.url) } }
47 47 end
48 48 content_tag(:div, link_to(_('Translations'), '#',
49   - :onclick => "toggleSubmenu(this, '#{_('Translations')}', #{links.to_json}); return false",
  49 + :onmouseover => "toggleSubmenu(this, '#{_('Translations')}', #{links.to_json}); return false",
50 50 :class => 'article-translations-menu simplemenu-trigger up'),
51 51 :class => 'article-translations')
52 52 end
... ...
app/helpers/profile_editor_helper.rb
... ... @@ -136,7 +136,7 @@ module ProfileEditorHelper
136 136 concat(
137 137 content_tag(
138 138 'div',
139   - capture(&block) + '<br style="clear:left;"/>&nbsp;',
  139 + capture(&block) + content_tag('br', '', :style => 'clear: left'),
140 140 :class => 'control-panel')
141 141 )
142 142 end
... ...
app/helpers/tags_helper.rb
... ... @@ -68,7 +68,7 @@ module TagsHelper
68 68 :title => n_( 'one item', '%d items', count ) % count
69 69 end
70 70  
71   - end.join("\n")
  71 + end.join("\n").html_safe
72 72 end
73 73  
74 74 end
... ...
app/models/article_block.rb
... ... @@ -16,7 +16,7 @@ class ArticleBlock &lt; Block
16 16 :gallery_view => false,
17 17 :inside_block => block, # For Blogs and folders
18 18 :format => block.visualization_format # For Articles and contents
19   - ) : _('Article not selected yet.'))
  19 + ).html_safe : _('Article not selected yet.'))
20 20 end
21 21 end
22 22  
... ...
app/models/feed_reader_block.rb
... ... @@ -47,11 +47,11 @@ class FeedReaderBlock &lt; Block
47 47  
48 48 def formatted_feed_content
49 49 if error_message.blank?
50   - "<ul>\n" +
51   - self.feed_items[0..(limit-1)].map{ |item| "<li><a href='#{item[:link]}'>#{item[:title]}</a></li>" }.join("\n") +
52   - "</ul>"
  50 + "<ul>\n".html_safe +
  51 + self.feed_items[0..(limit-1)].map{ |item| "<li><a href='#{item[:link]}'>#{item[:title]}</a></li>" }.join("\n").html_safe +
  52 + "</ul>".html_safe
53 53 else
54   - '<p>' + error_message + '</p>'
  54 + "<p>#{error_message}</p>".html_safe
55 55 end
56 56 end
57 57  
... ...
app/models/link_list_block.rb
... ... @@ -80,7 +80,7 @@ class LinkListBlock &lt; Block
80 80  
81 81 def icons_options
82 82 ICONS.map do |i|
83   - "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>"
  83 + "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe
84 84 end
85 85 end
86 86  
... ...
app/models/organization_mailing.rb
... ... @@ -5,7 +5,7 @@ class OrganizationMailing &lt; Mailing
5 5 end
6 6  
7 7 def recipients(offset=0, limit=100)
8   - source.members.all(:order => self.id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :conditions => { "m.person_id" => nil })
  8 + source.members.all(:order => :id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :conditions => { "m.person_id" => nil })
9 9 end
10 10  
11 11 def each_recipient
... ...
app/models/profile.rb
... ... @@ -68,7 +68,7 @@ class Profile &lt; ActiveRecord::Base
68 68 #FIXME: these will work only if the subclass is already loaded
69 69 named_scope :enterprises, lambda { {:conditions => (Enterprise.send(:subclasses).map(&:name) << 'Enterprise').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
70 70 named_scope :communities, lambda { {:conditions => (Community.send(:subclasses).map(&:name) << 'Community').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
71   - named_scope :templates, :conditions => {:is_template => true}
  71 + named_scope :templates, lambda { |environment| { :conditions => {:is_template => true, :environment_id => environment.id} } }
72 72  
73 73 def members
74 74 scopes = plugins.dispatch_scopes(:organization_members, self)
... ...
app/models/profile_list_block.rb
... ... @@ -49,13 +49,12 @@ class ProfileListBlock &lt; Block
49 49 send(:profile_image_link, item, :minor )
50 50 }.join("\n ")
51 51 if list.empty?
52   - list = '<div class="common-profile-list-block-none">'+ _('None') +'</div>'
  52 + list = content_tag 'div', _('None'), :class => 'common-profile-list-block-none'
53 53 else
54 54 list = content_tag 'ul', nl +' '+ list + nl
55 55 end
56 56 block_title(title) + nl +
57   - '<div class="common-profile-list-block">' +
58   - nl + list + nl + '<br style="clear:both" /></div>'
  57 + content_tag('div', nl + list + nl + content_tag('br', '', :style => 'clear:both'))
59 58 end
60 59 end
61 60  
... ...
app/models/tags_block.rb
... ... @@ -35,9 +35,9 @@ class TagsBlock &lt; Block
35 35 tagname_option = is_env ? :tag : :id
36 36  
37 37 block_title(title) +
38   - "\n<div class='tag_cloud'>\n"+
  38 + "\n<div class='tag_cloud'>\n".html_safe+
39 39 tag_cloud( tags, tagname_option, url, :max_size => 16, :min_size => 9 ) +
40   - "\n</div><!-- end class='tag_cloud' -->\n";
  40 + "\n</div><!-- end class='tag_cloud' -->\n".html_safe
41 41 end
42 42  
43 43 def footer
... ...
app/models/uploaded_file.rb
... ... @@ -113,7 +113,7 @@ class UploadedFile &lt; Article
113 113  
114 114 content_tag(
115 115 'div',
116   - link_to_previous + content_tag('span', _('image %d of %d'), :class => 'total-of-images') % [current_index + 1, total_of_images] + link_to_next,
  116 + link_to_previous + (content_tag('span', _('image %d of %d'), :class => 'total-of-images') % [current_index + 1, total_of_images]).html_safe + link_to_next,
117 117 :class => 'gallery-navigation'
118 118 )
119 119 end.to_s +
... ...
app/views/box_organizer/_highlights_block.rhtml
... ... @@ -5,7 +5,7 @@
5 5 <% for image in @block.images do %>
6 6 <tr>
7 7 <td>
8   - <%= select_tag 'block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(@block.folder_choices, :images, :name, :id, :name, image[:image_id].to_i), :style => "width: 100px" %></p>
  8 + <%= select_tag 'block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(@block.folder_choices, :images, :name, :id, :name, image[:image_id].to_i).html_safe, :style => "width: 100px" %></p>
9 9 </td>
10 10 <td><%= text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 10 %></td>
11 11 <td><%= text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 3 %></td>
... ... @@ -17,7 +17,7 @@
17 17  
18 18 <%= link_to_function(_('New highlight'), nil, :class => 'button icon-add with-text') do |page|
19 19 page.insert_html :bottom, 'highlights', content_tag('tr',
20   - content_tag('td', select_tag('block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(@block.folder_choices, :images, :name, :id, :name), :style => "width: 100px")) +
  20 + content_tag('td', select_tag('block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(@block.folder_choices, :images, :name, :id, :name).html_safe, :style => "width: 100px")) +
21 21 content_tag('td', text_field_tag('block[images][][address]', nil, :class => 'highlight-address', :size => 10)) +
22 22 content_tag('td', text_field_tag('block[images][][position]', nil, :class => 'highlight-position', :size => 3)) +
23 23 content_tag('td', text_field_tag('block[images][][title]', nil, :class => 'highlight-position', :size => 10))
... ...
app/views/favorite_enterprises/index.rhtml
... ... @@ -5,7 +5,7 @@
5 5 <ul class="profile-list">
6 6 <% @favorite_enterprises.each do |enterprise| %>
7 7 <li>
8   - <%= link_to_profile profile_image(enterprise) + '<br/>' + enterprise.name,
  8 + <%= link_to_profile profile_image(enterprise) + '<br/>'.html_safe + enterprise.name,
9 9 enterprise.identifier, :class => 'profile-link' %>
10 10 <%# profile_image_link enterprise, :portrait, 'div' %>
11 11 <div class="controll">
... ...
app/views/profile/_profile_wall.rhtml
1 1 <h3><%= _("%s's wall") % @profile.name %></h3>
2 2 <div id='leave_scrap'>
3 3 <%= flash[:error] %>
4   - <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :tab_action => 'wall' }, :update => 'profile_activities', :success => "$('leave_scrap_content').value=''" do %>
  4 + <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :tab_action => 'wall' }, :update => 'profile_activities', :success => "$('leave_scrap_content').value=''", :complete => "jQuery('#leave_scrap_form').removeClass('loading').find('*').attr('disabled', false)", :loading => "jQuery('#leave_scrap_form').addClass('loading').find('*').attr('disabled', true)", :html => {:id => 'leave_scrap_form' } do %>
5 5 <%= limited_text_area :scrap, :content, 420, 'leave_scrap_content', :cols => 50, :rows => 2 %>
6 6 <%= submit_button :new, _('Share') %>
7 7 <% end %>
... ...
app/views/profile_members/_manage_roles.html.erb
... ... @@ -13,11 +13,11 @@
13 13  
14 14 <% @roles.each do |role| %>
15 15 <% search_url = url_for(:action => 'search_user', :profile => profile.identifier, :role => role.id) %>
16   - <% @pre_population ||= profile.members_by_role_to_json(role) %>
  16 + <% pre_population = params[:action] == 'last_admin' ? [].to_json : profile.members_by_role_to_json(role) %>
17 17 <script type="text/javascript">
18 18 jQuery(<%= ('#search_' + role.key).to_json %>)
19 19 .tokenInput("<%= search_url %>", {
20   - prePopulate: <%= @pre_population %>,
  20 + prePopulate: <%= pre_population %>,
21 21 hintText: <%= _('Type in a search term for users').to_json %>,
22 22 noResultsText: <%= _('No results').to_json %>,
23 23 searchingText: <%= _('Searching...').to_json %>,
... ...
app/views/templates/index.html.erb
... ... @@ -2,9 +2,9 @@
2 2  
3 3 <%= _('Manage the templates used on creation of profiles') %>
4 4  
5   -<% list_of_templates = [[_('Person') , Person.templates , 'person' ],
6   - [_('Community') , Community.templates , 'community' ],
7   - [_('Enterprise'), Enterprise.templates, 'enterprise']] %>
  5 +<% list_of_templates = [[_('Person') , Person.templates(environment) , 'person' ],
  6 + [_('Community') , Community.templates(environment) , 'community' ],
  7 + [_('Enterprise'), Enterprise.templates(environment), 'enterprise']] %>
8 8  
9 9 <% list_of_templates.each do |title, templates, kind|%>
10 10 <div class='template-kind'>
... ...
app/views/themes/index.rhtml
... ... @@ -11,17 +11,17 @@
11 11 base_content = image_tag(
12 12 "/designs/templates/#{template.id}/thumbnail.png",
13 13 :alt => _('The "%s" template')) +
14   - '<div class="opt-info">' +
  14 + '<div class="opt-info">'.html_safe +
15 15 content_tag('strong', template.id, :class => 'name') +
16   - ' <br/> '
  16 + ' <br/> '.html_safe
17 17  
18 18 if @current_template == template.id # selected
19 19 content_tag( 'div',
20   - base_content + content_tag('big', _('(current)') ) +'</div>',
  20 + base_content + content_tag('big', _('(current)') ) +'</div>'.html_safe,
21 21 :class => 'template-opt list-opt selected')
22 22 else # Not selected
23 23 link_to(
24   - base_content +'</div>',
  24 + base_content +'</div>'.html_safe,
25 25 { :action => 'set_layout_template', :id => template.id },
26 26 :class => 'template-opt list-opt')
27 27 end
... ... @@ -48,17 +48,17 @@
48 48 base_content = image_tag(
49 49 "/designs/themes/#{theme.id}/preview.png",
50 50 :alt => (_('The "%s" theme.') % theme.name)) +
51   - '<div class="opt-info">' +
  51 + '<div class="opt-info">'.html_safe +
52 52 content_tag('strong', theme.name, :class => 'name') +
53   - ' <br/> '
  53 + ' <br/> '.html_safe
54 54  
55 55 if theme.id == @current_theme # selected
56 56 content_tag( 'div',
57   - base_content + content_tag('big', _('(current)') ) +'</div>',
  57 + base_content + content_tag('big', _('(current)') ) +'</div>'.html_safe,
58 58 :class => 'theme-opt list-opt selected')
59 59 else # Not selected
60 60 link_to(
61   - base_content + '</div>',
  61 + base_content + '</div>'.html_safe,
62 62 { :action => 'set', :id => theme.id },
63 63 :class => 'theme-opt list-opt')
64 64 end
... ...
app/views/users/_user_csv.rhtml
... ... @@ -1 +0,0 @@
1   -<%= user_csv.name %>;<%= user_csv.email %>
app/views/users/index_csv.rhtml
... ... @@ -1,2 +0,0 @@
1   -<%= _('name') %>;<%= _('email') %>
2   -<%= render :partial => 'user_csv', :collection => @users %>
debian/changelog
  1 +noosfero (0.41.2) unstable; urgency=low
  2 +
  3 + * Bugfixes release
  4 +
  5 + -- Rodrigo Souto <rodrigo@colivre.coop.br> Wed, 17 Apr 2013 16:22:53 -0300
  6 +
1 7 noosfero (0.41.1) unstable; urgency=low
2 8  
3 9 * Bugfixes release
... ...
lib/noosfero.rb
... ... @@ -3,7 +3,7 @@ require &#39;fast_gettext&#39;
3 3  
4 4 module Noosfero
5 5 PROJECT = 'noosfero'
6   - VERSION = '0.41.1'
  6 + VERSION = '0.41.2'
7 7  
8 8 def self.pattern_for_controllers_in_directory(dir)
9 9 disjunction = controllers_in_directory(dir).join('|')
... ...
plugins/shopping_cart/controllers/shopping_cart_plugin_controller.rb
... ... @@ -13,9 +13,15 @@ class ShoppingCartPluginController &lt; PublicController
13 13 def get
14 14 config =
15 15 if cart.nil?
16   - { 'enterprise_id' => nil, 'hasProducts' => false }
  16 + { :enterprise_id => nil,
  17 + :has_products => false,
  18 + :visible => false,
  19 + :products => []}
17 20 else
18   - { 'enterprise_id' => cart[:enterprise_id], 'hasProducts' => (cart[:items].keys.size > 0) }
  21 + { :enterprise_id => cart[:enterprise_id],
  22 + :has_products => (cart[:items].keys.size > 0),
  23 + :visible => visible?,
  24 + :products => products}
19 25 end
20 26 render :text => config.to_json
21 27 end
... ... @@ -56,16 +62,6 @@ class ShoppingCartPluginController &lt; PublicController
56 62  
57 63 def list
58 64 if validate_cart_presence
59   - products = self.cart[:items].collect do |id, quantity|
60   - product = Product.find(id)
61   - { :id => product.id,
62   - :name => product.name,
63   - :price => get_price(product, product.enterprise.environment),
64   - :description => product.description,
65   - :picture => product.default_image(:minor),
66   - :quantity => quantity
67   - }
68   - end
69 65 render :text => {
70 66 :ok => true,
71 67 :error => {:code => 0},
... ... @@ -128,7 +124,7 @@ class ShoppingCartPluginController &lt; PublicController
128 124 end
129 125  
130 126 def visibility
131   - render :text => self.cart.has_key?(:visibility) ? self.cart[:visibility].to_json : true.to_json
  127 + render :text => visible?.to_json
132 128 end
133 129  
134 130 def show
... ... @@ -317,4 +313,31 @@ class ShoppingCartPluginController &lt; PublicController
317 313 :_noosfero_plugin_shopping_cart
318 314 end
319 315  
  316 + def visible?
  317 + !self.cart.has_key?(:visibility) || self.cart[:visibility]
  318 + end
  319 +
  320 + def products
  321 + self.cart[:items].collect do |id, quantity|
  322 + product = Product.find_by_id(id)
  323 + if product
  324 + { :id => product.id,
  325 + :name => product.name,
  326 + :price => get_price(product, product.enterprise.environment),
  327 + :description => product.description,
  328 + :picture => product.default_image(:minor),
  329 + :quantity => quantity
  330 + }
  331 + else
  332 + { :id => id,
  333 + :name => _('Undefined product'),
  334 + :price => 0,
  335 + :description => _('Wrong product id'),
  336 + :picture => '',
  337 + :quantity => quantity
  338 + }
  339 + end
  340 + end
  341 + end
  342 +
320 343 end
... ...
plugins/shopping_cart/lib/shopping_cart_plugin.rb
... ... @@ -12,10 +12,6 @@ class ShoppingCartPlugin &lt; Noosfero::Plugin
12 12 _("A shopping basket feature for enterprises")
13 13 end
14 14  
15   - def enabled_default_setting
16   - true
17   - end
18   -
19 15 def delivery_default_setting
20 16 false
21 17 end
... ...
plugins/shopping_cart/public/cart.js
... ... @@ -6,50 +6,36 @@ function Cart(config) {
6 6 this.contentBox = $("#cart1 .cart-content");
7 7 this.itemsBox = $("#cart1 .cart-items");
8 8 this.items = {};
9   - this.empty = !config.hasProducts;
  9 + this.empty = !config.has_products;
10 10 this.visible = false;
11 11 $(".cart-buy", this.cartElem).button({ icons: { primary: 'ui-icon-cart'} });
12 12 if (!this.empty) {
13 13 $(this.cartElem).show();
14   - me = this;
15   - $.ajax({
16   - url: '/plugin/shopping_cart/visibility',
17   - dataType: 'json',
18   - success: function(data, status, ajax){
19   - me.visible = /^true$/i.test(data);
20   - me.listProducts();
21   - },
22   - cache: false,
23   - error: function(ajax, status, errorThrown) {
24   - alert('Visibility - HTTP '+status+': '+errorThrown);
25   - }
26   - });
27   - $(".cart-buy", this.cartElem).colorbox({ href: '/plugin/shopping_cart/buy' });
  14 + this.visible = config.visible;
  15 + this.addToList(config.products, true)
28 16 }
29 17 }
30 18  
31 19 (function($){
32 20  
33   - Cart.prototype.listProducts = function() {
  21 + // Forbidding the user to request more the one action on the cart
  22 + // simultaneously because the cart in the cookie doesn't supports it.
  23 + Cart.prototype.ajax = function(config){
34 24 var me = this;
35   - $.ajax({
36   - url: '/plugin/shopping_cart/list',
37   - dataType: 'json',
38   - success: function(data, ststus, ajax){
39   - if ( !data.ok ) alert(data.error.message);
40   - else me.addToList(data, true);
41   - },
42   - cache: false,
43   - error: function(ajax, status, errorThrown) {
44   - alert('List cart items - HTTP '+status+': '+errorThrown);
45   - }
46   - });
  25 + this.disabled = true;
  26 + var completeCallback = config.complete;
  27 + config.complete = function(){
  28 + me.disabled = false;
  29 + if (completeCallback) completeCallback();
  30 + };
  31 + $.ajax(config);
47 32 }
48 33  
49   - Cart.prototype.addToList = function(data, clear) {
  34 + Cart.prototype.addToList = function(products, clear) {
50 35 if( clear ) this.itemsBox.empty();
51 36 var me = this;
52   - for( var item,i=0; item=data.products[i]; i++ ) {
  37 + this.productsLength = products.length;
  38 + for( var item,i=0; item=products[i]; i++ ) {
53 39 this.items[item.id] = { price:item.price, quantity:item.quantity };
54 40 this.updateTotal();
55 41 var liId = "cart-item-"+item.id;
... ... @@ -75,9 +61,7 @@ function Cart(config) {
75 61 input.onchange = function() {
76 62 me.updateQuantity(this, this.productId, this.value);
77 63 };
78   -// document.location.href = "#"+liId;
79   -// document.location.href = "#"+this.cartElem.id;
80   -// history.go(-2);
  64 + // TODO: Scroll to newest item
81 65 var liBg = li.css("background-color");
82 66 li[0].style.backgroundColor = "#FF0";
83 67 li.animate({ backgroundColor: liBg }, 1000);
... ... @@ -86,24 +70,25 @@ function Cart(config) {
86 70 if (!clear && this.empty) $(this.cartElem).show();
87 71 if((!clear && this.empty) || (this.visible && clear)) {
88 72 this.contentBox.hide();
89   - this.show();
  73 + this.show(!clear);
90 74 }
91 75 this.empty = false;
92 76 }
93 77  
94 78 Cart.prototype.updateQuantity = function(input, itemId, quantity) {
  79 + if(this.disabled) return alert(shoppingCartPluginL10n.waitLastRequest);
95 80 quantity = parseInt(quantity);
96 81 input.disabled = true;
97 82 var originalBg = input.style.backgroundImage;
98 83 input.style.backgroundImage = "url(/images/loading-small.gif)";
99 84 var me = this;
100 85 if( quantity == NaN ) return input.value = input.lastValue;
101   - $.ajax({
  86 + this.ajax({
102 87 url: '/plugin/shopping_cart/update_quantity/'+ itemId +'?quantity='+ quantity,
103 88 dataType: 'json',
104 89 success: function(data, status, ajax){
105 90 if ( !data.ok ) {
106   - alert(data.error.message);
  91 + log.error(data.error);
107 92 input.value = input.lastValue;
108 93 }
109 94 else {
... ... @@ -114,7 +99,7 @@ function Cart(config) {
114 99 },
115 100 cache: false,
116 101 error: function(ajax, status, errorThrown) {
117   - alert('Add item - HTTP '+status+': '+errorThrown);
  102 + log.error('Add item - HTTP '+status, errorThrown);
118 103 input.value = input.lastValue;
119 104 },
120 105 complete: function(){
... ... @@ -132,89 +117,103 @@ function Cart(config) {
132 117 }
133 118  
134 119 Cart.addItem = function(itemId, link) {
  120 + if(this.instance.disabled) return alert(shoppingCartPluginL10n.waitLastRequest);
  121 + if ( this.productsLength > 100 ) {
  122 + // This limit protect the user from losing data on cookie limit.
  123 + // This is NOT limiting to 100 products, is limiting to 100 kinds of products.
  124 + alert(shoppingCartPluginL10n.maxNumberOfItens);
  125 + return false;
  126 + }
135 127 link.intervalId = setInterval(function() {
  128 + $(link).addClass('loading');
136 129 steps = ['w', 'n', 'e', 's'];
137 130 if( !link.step || link.step==3 ) link.step = 0;
138 131 link.step++;
139   - $(link).button({ icons: { primary: 'ui-icon-arrowrefresh-1-'+steps[link.step]}, disable: true })
  132 + $(link).button({ icons: { primary: 'ui-icon-arrowrefresh-1-'+steps[link.step]}})
140 133 }, 100);
141 134 var stopBtLoading = function() {
142 135 clearInterval(link.intervalId);
143   - $(link).button({ icons: { primary: 'ui-icon-cart'}, disable: false });
  136 + $(link).removeClass('loading');
  137 + $(link).button({ icons: { primary: 'ui-icon-cart'}});
144 138 };
145 139 this.instance.addItem(itemId, stopBtLoading);
146 140 }
147 141  
148 142 Cart.prototype.addItem = function(itemId, callback) {
149 143 var me = this;
150   - $.ajax({
  144 + this.ajax({
151 145 url: '/plugin/shopping_cart/add/'+ itemId,
152 146 dataType: 'json',
153 147 success: function(data, status, ajax){
154   - if ( !data.ok ) alert(data.error.message);
155   - else me.addToList(data);
  148 + if ( !data.ok ) log.error('Shopping cart data failure', data.error);
  149 + else me.addToList(data.products);
156 150 },
157 151 cache: false,
158 152 error: function(ajax, status, errorThrown) {
159   - alert('Add item - HTTP '+status+': '+errorThrown);
  153 + log.error('Add item - HTTP '+status, errorThrown);
160 154 },
161 155 complete: callback
162 156 });
163 157 }
164 158  
165 159 Cart.removeItem = function(itemId) {
166   - var message = this.instance.cartElem.getAttribute('data-l10nRemoveItem');
167   - if( confirm(message) ) this.instance.removeItem(itemId);
  160 + if(this.instance.disabled) return alert(shoppingCartPluginL10n.waitLastRequest);
  161 + if( confirm(shoppingCartPluginL10n.removeItem) ) this.instance.removeItem(itemId);
168 162 }
169 163  
170 164 Cart.prototype.removeItem = function(itemId) {
171 165 if ($("li", this.itemsBox).size() < 2) return this.clean();
172 166 var me = this;
173   - $.ajax({
  167 + this.ajax({
174 168 url: '/plugin/shopping_cart/remove/'+ itemId,
175 169 dataType: 'json',
176 170 success: function(data, status, ajax){
177   - if ( !data.ok ) alert(data.error.message);
  171 + if ( !data.ok ) log.error(data.error);
178 172 else me.removeFromList(data.product_id);
179 173 },
180 174 cache: false,
181 175 error: function(ajax, status, errorThrown) {
182   - alert('Remove item - HTTP '+status+': '+errorThrown);
  176 + log.error('Remove item - HTTP '+status, errorThrown);
183 177 }
184 178 });
185 179 }
186 180  
187 181 Cart.toggle = function(link) {
  182 + if(this.instance.disabled) return alert(shoppingCartPluginL10n.waitLastRequest);
188 183 link.parentNode.parentNode.cartObj.toggle();
189 184 }
190 185 Cart.prototype.toggle = function() {
191   - this.visible ? this.hide() : this.show();
  186 + this.visible ? this.hide(true) : this.show(true);
192 187 }
193 188  
194   - Cart.prototype.show = function() {
195   - $.ajax({
196   - url: '/plugin/shopping_cart/show',
197   - dataType: 'json',
198   - cache: false,
199   - error: function(ajax, status, errorThrown) {
200   - alert('Show - HTTP '+status+': '+errorThrown);
201   - }
202   - });
  189 + Cart.prototype.show = function(register) {
  190 + if(register) {
  191 + this.ajax({
  192 + url: '/plugin/shopping_cart/show',
  193 + dataType: 'json',
  194 + cache: false,
  195 + error: function(ajax, status, errorThrown) {
  196 + log.error('Show - HTTP '+status, errorThrown);
  197 + }
  198 + });
  199 + }
203 200 this.visible = true;
204 201 this.contentBox.slideDown(500);
205 202 $(".cart-toggle .str-show", this.cartElem).hide();
206 203 $(".cart-toggle .str-hide", this.cartElem).show();
207 204  
208 205 }
209   - Cart.prototype.hide = function() {
210   - $.ajax({
211   - url: '/plugin/shopping_cart/hide',
212   - dataType: 'json',
213   - cache: false,
214   - error: function(ajax, status, errorThrown) {
215   - alert('Hide - HTTP '+status+': '+errorThrown);
216   - }
217   - });
  206 + Cart.prototype.hide = function(register) {
  207 + if(register) {
  208 + this.ajax({
  209 + url: '/plugin/shopping_cart/hide',
  210 + dataType: 'json',
  211 + cache: false,
  212 + error: function(ajax, status, errorThrown) {
  213 + log.error('Hide - HTTP '+status, errorThrown);
  214 + }
  215 + });
  216 + }
218 217 this.visible = false;
219 218 this.contentBox.slideUp(500);
220 219 $(".cart-toggle .str-show", this.cartElem).show();
... ... @@ -238,17 +237,17 @@ function Cart(config) {
238 237 }
239 238  
240 239 Cart.clean = function(link) {
241   - var message = this.instance.cartElem.getAttribute('data-l10nCleanCart');
242   - if( confirm(message) ) link.parentNode.parentNode.parentNode.cartObj.clean();
  240 + if(this.instance.disabled) return alert(shoppingCartPluginL10n.waitLastRequest);
  241 + if( confirm(shoppingCartPluginL10n.cleanCart) ) link.parentNode.parentNode.parentNode.cartObj.clean();
243 242 }
244 243  
245 244 Cart.prototype.clean = function() {
246 245 var me = this;
247   - $.ajax({
  246 + this.ajax({
248 247 url: '/plugin/shopping_cart/clean',
249 248 dataType: 'json',
250 249 success: function(data, status, ajax){
251   - if ( !data.ok ) alert(data.error.message);
  250 + if ( !data.ok ) log.error(data.error);
252 251 else{
253 252 me.items = {};
254 253 $(me.cartElem).slideUp(500, function() {
... ... @@ -261,7 +260,7 @@ function Cart(config) {
261 260 },
262 261 cache: false,
263 262 error: function(ajax, status, errorThrown) {
264   - alert('Remove item - HTTP '+status+': '+errorThrown);
  263 + log.error('Remove item - HTTP '+status, errorThrown);
265 264 }
266 265 });
267 266 }
... ... @@ -274,7 +273,7 @@ function Cart(config) {
274 273  
275 274 Cart.prototype.send_request = function(params) {
276 275 var me = this;
277   - $.ajax({
  276 + this.ajax({
278 277 type: 'POST',
279 278 url: '/plugin/shopping_cart/send_request',
280 279 data: params,
... ... @@ -288,7 +287,7 @@ function Cart(config) {
288 287 },
289 288 cache: false,
290 289 error: function(ajax, status, errorThrown) {
291   - alert('Send request - HTTP '+status+': '+errorThrown);
  290 + log.error('Send request - HTTP '+status, errorThrown);
292 291 },
293 292 complete: function() {
294 293 $.colorbox.close();
... ... @@ -300,6 +299,11 @@ function Cart(config) {
300 299 $.colorbox.close();
301 300 }
302 301  
  302 + $(window).bind('beforeunload', function(){
  303 + log('Page unload.');
  304 + Cart.unloadingPage = true;
  305 + });
  306 +
303 307 $(function(){
304 308  
305 309 $.ajax({
... ... @@ -311,7 +315,18 @@ function Cart(config) {
311 315 },
312 316 cache: false,
313 317 error: function(ajax, status, errorThrown) {
314   - alert('Error getting shopping cart - HTTP '+status+': '+errorThrown);
  318 + // Give some time to register page unload.
  319 + setTimeout(function() {
  320 + // page unload is not our problem.
  321 + if (Cart.unloadingPage) {
  322 + log('Page unload before cart load.');
  323 + } else {
  324 + log.error('Error getting shopping cart - HTTP '+status, errorThrown);
  325 + if ( confirm(shoppingCartPluginL10n.getProblemConfirmReload) ) {
  326 + document.location.reload();
  327 + }
  328 + }
  329 + }, 100);
315 330 }
316 331 });
317 332 });
... ...
plugins/shopping_cart/test/unit/shopping_cart_plugin_test.rb
... ... @@ -26,4 +26,10 @@ class ShoppingCartPluginTest &lt; ActiveSupport::TestCase
26 26  
27 27 assert_nil shopping_cart.add_to_cart_button(product)
28 28 end
  29 +
  30 + should 'be disabled by default on the enterprise' do
  31 + enterprise = fast_create(Enterprise)
  32 + settings = Noosfero::Plugin::Settings.new(enterprise, ShoppingCartPlugin)
  33 + assert !settings.enabled
  34 + end
29 35 end
... ...
plugins/shopping_cart/views/cart.html.erb
1   -<div id="cart1" class="cart" style="display:none"
2   - data-l10nRemoveItem="<%=_('Are you sure you want to remove this item?')%>"
3   - data-l10nCleanCart="<%=_('Are you sure you want to clean your basket?')%>">
  1 +<div id="cart1" class="cart" style="display:none">
4 2 <div class="cart-inner">
5 3 <div class="cart-content">
6 4 <h3><%= _("Basket") %></h3>
7 5 <a href="cart:clean" onclick="Cart.clean(this); return false" class="cart-clean"><%=_('Clean basket')%></a>
8 6 <ul class="cart-items"></ul>
9 7 <div class="cart-total"><%=_('Total:')%> <b></b></div>
10   - <a href="/plugin/shopping_cart/buy" class="cart-buy"><%=_('Shopping checkout')%></a>
  8 + <a href="/plugin/shopping_cart/buy" class="cart-buy colorbox"><%=_('Shopping checkout')%></a>
11 9 </div>
12 10 <a href="#" onclick="Cart.toggle(this); return false" class="cart-toggle">
13 11 <span class="str-show"><%=_('Show basket')%></span>
... ... @@ -15,3 +13,18 @@
15 13 </a>
16 14 </div>
17 15 </div>
  16 +<script>
  17 + var shoppingCartPluginL10n = {
  18 + getProblemConfirmReload: <%= (
  19 + _('Ups... I had a problem to load the basket list.') +
  20 + "\n" +
  21 + _('Did you want to reload this page?')
  22 + ).to_json %>,
  23 + maxNumberOfItens: <%= (
  24 + _('Sorry, you can\'t have more then 100 kinds of items on this basket.')
  25 + ).to_json %>,
  26 + waitLastRequest: <%= _('Oops, you must wait your last request to finish first!').to_json %>,
  27 + removeItem: <%= _('Are you sure you want to remove this item?').to_json %>,
  28 + cleanCart: <%= _('Are you sure you want to clean your basket?').to_json %>
  29 + }
  30 +</script>
... ...
plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb
... ... @@ -8,7 +8,7 @@
8 8 <%= labelled_form_field('* ' + _("Contact phone"), f.text_field(:contact_phone, :class => 'required') ) %>
9 9 <%= labelled_form_field(_('Delivery option'), select_tag(:delivery_option, options_for_select(select_delivery_options(@settings.delivery_options, environment)), 'data-profile-identifier' => @enterprise.identifier)) unless !@settings.delivery || (@settings.free_delivery_price && get_total(@cart[:items]) >= @settings.free_delivery_price) %>
10 10 <%= labelled_form_field(_('Payment'), select_tag('customer[payment]', options_for_select([[_("Money"), :money],[_('Check'), :check]]))) %>
11   - <%= labelled_form_field(_('Change'), text_field_tag('customer[change]')) %>
  11 + <%= labelled_form_field(s_('shopping_cart|Change'), text_field_tag('customer[change]')) %>
12 12 </div>
13 13 <% if @settings.delivery %>
14 14 <fieldset><legend><%=_('Delivery Address')%></legend>
... ...
po/es/noosfero.po
... ... @@ -9345,11 +9345,9 @@ msgid &quot;&lt;span class=&#39;login&#39;&gt;%s&lt;/span&gt;&quot;
9345 9345 msgstr "<span class='welcome'>Bienvenido,</span> %s"
9346 9346  
9347 9347 #: app/views/layouts/application-ng.rhtml:68
9348   -#, fuzzy
9349 9348 msgid "<span class='or'>or</span> <span class='signup'>%s</span>"
9350 9349 msgstr ""
9351   -"<span class='login'>%s</span> <span class='or'>or</span> <span "
9352   -"class='signup'>%s</span>"
  9350 +"<span class='or'>o</span> <span class='signup'>%s</span>"
9353 9351  
9354 9352 #: app/views/layouts/application-ng.rhtml:68
9355 9353 msgid "Sign up"
... ...
po/pt/noosfero.po
... ... @@ -13,7 +13,7 @@ msgid &quot;&quot;
13 13 msgstr ""
14 14 "Project-Id-Version: noosfero 0.39.3\n"
15 15 "POT-Creation-Date: 2013-01-19 21:42-0000\n"
16   -"PO-Revision-Date: 2013-01-19 21:55+0000\n"
  16 +"PO-Revision-Date: 2013-03-13 17:47-0300\n"
17 17 "Last-Translator: Rodrigo Souto <rodrigo@colivre.coop.br>\n"
18 18 "Language-Team: LANGUAGE TEAM <E-MAIL@ADDRESS or HOME PAGE>\n"
19 19 "Language: \n"
... ... @@ -9205,7 +9205,7 @@ msgstr &quot;&lt;span class=&#39;login&#39;&gt;%s&lt;/span&gt;&quot;
9205 9205  
9206 9206 #: app/views/layouts/application-ng.rhtml:68
9207 9207 msgid "<span class='or'>or</span> <span class='signup'>%s</span>"
9208   -msgstr "<span class='or'>or</span> <span class='signup'>%s</span>"
  9208 +msgstr "<span class='or'>ou</span> <span class='signup'>%s</span>"
9209 9209  
9210 9210 #: app/views/layouts/application-ng.rhtml:68
9211 9211 msgid "Sign up"
... ... @@ -11086,6 +11086,10 @@ msgstr &quot;Tempo de tolerância para edição de comentários&quot;
11086 11086 msgid "Empty means unlimited and zero means right away."
11087 11087 msgstr "Vazio significa ilimitado e zero significa imediatamente."
11088 11088  
  11089 +#: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:11
  11090 +msgid "shopping_cart|Change"
  11091 +msgstr "Troco"
  11092 +
11089 11093 #: plugins/shopping_cart/views/cart.html.erb:2
11090 11094 msgid "Are you sure you want to remove this item?"
11091 11095 msgstr "Tem certeza de que quer excluir este ítem?"
... ... @@ -11163,7 +11167,6 @@ msgstr &quot;Pagamento&quot;
11163 11167 #: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/_orders_list.html.erb:35
11164 11168 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:22
11165 11169 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:20
11166   -#: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:11
11167 11170 #, fuzzy
11168 11171 msgid "Change"
11169 11172 msgstr "Mudar imagem"
... ...
public/javascripts/application.js
... ... @@ -129,9 +129,9 @@ function hideOthersIconSelector(current_div) {
129 129 }
130 130  
131 131 function loading(element_id, message) {
132   - $(element_id).addClassName('loading');
  132 + jQuery(element_id).addClass('loading');
133 133 if (message) {
134   - $(element_id).update(message);
  134 + jQuery(element_id).html(message);
135 135 }
136 136 }
137 137 function small_loading(element_id, message) {
... ... @@ -141,9 +141,9 @@ function small_loading(element_id, message) {
141 141 }
142 142 }
143 143 function loading_done(element_id) {
144   - $(element_id).removeClassName('loading');
145   - $(element_id).removeClassName('small-loading');
146   - $(element_id).removeClassName('small-loading-dark');
  144 + jQuery(element_id).removeClass('loading');
  145 + jQuery(element_id).removeClass('small-loading');
  146 + jQuery(element_id).removeClass('small-loading-dark');
147 147 }
148 148 function open_loading(message) {
149 149 jQuery('body').append("<div id='overlay_loading' class='ui-widget-overlay' style='display: none'/><div id='overlay_loading_modal' style='display: none'><p>"+message+"</p><img src='/images/loading-dark.gif'/></div>");
... ... @@ -937,13 +937,55 @@ function facet_options_toggle(id, url) {
937 937 });
938 938 }
939 939  
  940 +if ( !console ) console = {};
  941 +if ( !console.log ) console.log = function(){};
  942 +
  943 +// Two ways to call it:
  944 +// log(mixin1[, mixin2[, ...]]);
  945 +// log('<type>', mixin1[, mixin2[, ...]]);
  946 +// Where <type> may be: log, info warn, or error
  947 +window.log = function log() {
  948 + var type = arguments[0];
  949 + var argsClone = jQuery.merge([], arguments); // cloning the read-only arguments array.
  950 + if ( ['info', 'warn', 'error'].indexOf(type) == -1 ) {
  951 + type = 'log';
  952 + } else {
  953 + argsClone.shift();
  954 + }
  955 + var method = type;
  956 + if ( !console[method] ) method = 'log';
  957 + console[method].apply( console, jQuery.merge([(new Date).toISOString()], argsClone) );
  958 +}
  959 +
  960 +// Call log.info(mixin1[, mixin2[, ...]]);
  961 +log.info = function() {
  962 + window.log.apply(window, jQuery.merge(['info'], arguments));
  963 +}
  964 +
  965 +// Call log.warn(mixin1[, mixin2[, ...]]);
  966 +log.warn = function() {
  967 + window.log.apply(window, jQuery.merge(['warn'], arguments));
  968 +}
  969 +
  970 +// Call log.error(mixin1[, mixin2[, ...]]);
  971 +log.error = function() {
  972 + window.log.apply(window, jQuery.merge(['error'], arguments));
  973 +}
  974 +
940 975 jQuery(function($) {
941 976 $('.colorbox').live('click', function() {
942   - $.fn.colorbox({
943   - href:$(this).attr('href'),
944   - maxWidth: '600',
945   - maxHeight: '550',
946   - open:true
  977 + $.colorbox({
  978 + href: $(this).attr('href'),
  979 + maxWidth: $(window).width()-50,
  980 + height: $(window).height()-50,
  981 + open: true,
  982 + fixed: true,
  983 + close: 'Cancel',
  984 + onComplete: function(bt) {
  985 + var opt = {}, maxH = $(window).height()-50;
  986 + if ($('#cboxLoadedContent *:first').height() > maxH) opt.height = maxH;
  987 + $.colorbox.resize(opt);
  988 + }
947 989 });
948 990 return false;
949 991 });
... ...
public/stylesheets/application.css
... ... @@ -5222,6 +5222,9 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
5222 5222 #leave_scrap textarea {
5223 5223 overflow: hidden;
5224 5224 }
  5225 +#leave_scrap .loading textarea {
  5226 + background: url('/images/loading-small.gif') 50% 50% no-repeat;
  5227 +}
5225 5228 .profile-send-reply {
5226 5229 color: #aaa;
5227 5230 }
... ...
test/functional/account_controller_test.rb
... ... @@ -579,6 +579,21 @@ class AccountControllerTest &lt; ActionController::TestCase
579 579 assert_equal 1, assigns(:user).person.boxes[0].blocks.size
580 580 end
581 581  
  582 + should 'display only templates of the current environment' do
  583 + env2 = fast_create(Environment)
  584 +
  585 + template1 = fast_create(Person, :name => 'template1', :environment_id => Environment.default.id, :is_template => true)
  586 + template2 = fast_create(Person, :name => 'template2', :environment_id => Environment.default.id, :is_template => true)
  587 + template3 = fast_create(Person, :name => 'template3', :environment_id => env2.id, :is_template => true)
  588 +
  589 + get :signup
  590 + assert_select '#template-options' do |elements|
  591 + assert_match /template1/, elements[0].to_s
  592 + assert_match /template2/, elements[0].to_s
  593 + assert_no_match /template3/, elements[0].to_s
  594 + end
  595 + end
  596 +
582 597 should 'render person partial' do
583 598 Environment.any_instance.expects(:signup_person_fields).returns(['contact_phone']).at_least_once
584 599 get :signup
... ...
test/functional/content_viewer_controller_test.rb
... ... @@ -1082,7 +1082,7 @@ end
1082 1082 textile = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'textile', :language => 'en')
1083 1083 translation = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'translation', :language => 'es', :translation_of_id => textile)
1084 1084 xhr :get, :view_page, :profile => @profile.identifier, :page => textile.explode_path, :toolbar => true
1085   - assert_tag :a, :attributes => { :class => /article-translations-menu/, :onclick => /toggleSubmenu/ }
  1085 + assert_tag :a, :attributes => { :class => /article-translations-menu/, :onmouseover => /toggleSubmenu/ }
1086 1086 end
1087 1087  
1088 1088 should 'not be redirected if already in translation' do
... ...
test/functional/enterprise_registration_controller_test.rb
... ... @@ -203,4 +203,21 @@ class EnterpriseRegistrationControllerTest &lt; ActionController::TestCase
203 203 assert_tag :tag => 'input', :attributes => {:id => 'create_enterprise_plugin1', :type => 'hidden', :value => 'Plugin 1'}
204 204 assert_tag :tag => 'input', :attributes => {:id => 'create_enterprise_plugin2', :type => 'hidden', :value => 'Plugin 2'}
205 205 end
  206 +
  207 + should 'display only templates of the current environment' do
  208 + env2 = fast_create(Environment)
  209 +
  210 + template1 = fast_create(Enterprise, :name => 'template1', :environment_id => Environment.default.id, :is_template => true)
  211 + template2 = fast_create(Enterprise, :name => 'template2', :environment_id => Environment.default.id, :is_template => true)
  212 + template3 = fast_create(Enterprise, :name => 'template3', :environment_id => env2.id, :is_template => true)
  213 +
  214 + get :index
  215 +
  216 + assert_select '#template-options' do |elements|
  217 + assert_match /template1/, elements[0].to_s
  218 + assert_match /template2/, elements[0].to_s
  219 + assert_no_match /template3/, elements[0].to_s
  220 + end
  221 + end
  222 +
206 223 end
... ...
test/functional/memberships_controller_test.rb
... ... @@ -154,6 +154,22 @@ class MembershipsControllerTest &lt; ActionController::TestCase
154 154 assert_equal 1, assigns(:community).boxes[0].blocks.size
155 155 end
156 156  
  157 + should 'display only templates of the current environment' do
  158 + env2 = fast_create(Environment)
  159 +
  160 + template1 = fast_create(Community, :name => 'template1', :environment_id => Environment.default.id, :is_template => true)
  161 + template2 = fast_create(Community, :name => 'template2', :environment_id => Environment.default.id, :is_template => true)
  162 + template3 = fast_create(Community, :name => 'template3', :environment_id => env2.id, :is_template => true)
  163 +
  164 + get :new_community, :profile => profile.identifier
  165 +
  166 + assert_select '#template-options' do |elements|
  167 + assert_match /template1/, elements[0].to_s
  168 + assert_match /template2/, elements[0].to_s
  169 + assert_no_match /template3/, elements[0].to_s
  170 + end
  171 + end
  172 +
157 173 should 'display only required fields when register new community' do
158 174 env = Environment.default
159 175 env.custom_community_fields = {
... ...
test/functional/users_controller_test.rb
... ... @@ -42,6 +42,7 @@ class UsersControllerTest &lt; ActionController::TestCase
42 42  
43 43 get :index, :format => 'csv'
44 44 assert_equal 'text/csv', @response.content_type
  45 + assert_equal 'name;email', @response.body.split("\n")[0]
45 46 end
46 47  
47 48 end
... ...
test/unit/application_helper_test.rb
... ... @@ -243,6 +243,7 @@ class ApplicationHelperTest &lt; ActiveSupport::TestCase
243 243 end
244 244  
245 245 should 'not display templates options when there is no template' do
  246 + self.stubs(:environment).returns(Environment.default)
246 247 [Person, Community, Enterprise].each do |klass|
247 248 assert_equal '', template_options(klass, 'profile_data')
248 249 end
... ...
test/unit/block_helper_test.rb 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class BlogHelperTest < ActiveSupport::TestCase
  4 +
  5 + include BlockHelper
  6 + include ActionView::Helpers::TagHelper
  7 +
  8 + should 'escape title html' do
  9 + assert_no_match /<b>/, block_title('<b>test</b>')
  10 + assert_match /&lt;b&gt;test&lt;\/b&gt;/, block_title('<b>test</b>')
  11 + end
  12 +
  13 +end
... ...
test/unit/organization_mailing_test.rb
... ... @@ -66,6 +66,12 @@ class OrganizationMailingTest &lt; ActiveSupport::TestCase
66 66 assert_equal 2, ActionMailer::Base.deliveries.count
67 67 end
68 68  
  69 + should 'deliver mailing when there are many mailings created' do
  70 + 50.times { OrganizationMailing.create(:source => community, :subject => 'Hello', :body => 'We have some news', :person => person) }
  71 + process_delayed_job_queue
  72 + assert_equal 50*community.members_count, ActionMailer::Base.deliveries.count
  73 + end
  74 +
69 75 should 'create mailing sent to each recipient after delivering mailing' do
70 76 mailing = OrganizationMailing.create(:source => community, :subject => 'Hello', :body => 'We have some news', :person => person)
71 77 assert_difference MailingSent, :count, 2 do
... ...
test/unit/profile_test.rb
... ... @@ -1444,9 +1444,9 @@ class ProfileTest &lt; ActiveSupport::TestCase
1444 1444 t2 = fast_create(Profile, :is_template => true)
1445 1445 profile = fast_create(Profile)
1446 1446  
1447   - assert_includes Profile.templates, t1
1448   - assert_includes Profile.templates, t2
1449   - assert_not_includes Profile.templates, profile
  1447 + assert_includes Profile.templates(Environment.default), t1
  1448 + assert_includes Profile.templates(Environment.default), t2
  1449 + assert_not_includes Profile.templates(Environment.default), profile
1450 1450 end
1451 1451  
1452 1452 should 'provide URL to leave' do
... ...