Commit ee8fd9e4e3c8b50e569805fe27927c27294b868e

Authored by Braulio Bhavamitra
2 parents 4352c377 8dfded9f

Merge branch 'noosfero' into rails4

Showing 76 changed files with 2022 additions and 165 deletions   Show diff stats
AUTHORS.md
... ... @@ -90,15 +90,17 @@ Matheus Faria <matheus.sousa.faria@gmail.com>
90 90 Maurilio Atila <cabelotaina@gmail.com>
91 91 M for Momo <mo@rtnp.org>
92 92 Michal Čihař <michal@cihar.com>
93   -Michel Felipe <mfelipeof@gmail.com>
  93 +Michel Felipe de Oliveira Ferreira <michel.ferreira@serpro.gov.br>
94 94 Moises Machado <moises@colivre.coop.br>
95 95 Naíla Alves <naila@colivre.coop.br>
96 96 Nanda Lopes <nanda.listas+psl@gmail.com>
97 97 Niemand Jedermann <predatorix@web.de>
  98 +Omar Junior <omarroinuj@gmail.com>
98 99 Parley Martins <parleypachecomartins@gmail.com>
99 100 Paulo Meirelles <paulo@softwarelivre.org>
100 101 Pedro de Lyra <pedrodelyra@gmail.com>
101 102 Pedro Leal
  103 +Phillip Rohmberger <rohmberger@hotmail.de>
102 104 Rafael de Souza Queiroz <querafael@live.com>
103 105 Rafael Gomes <rafaelgomes@techfree.com.br>
104 106 Rafael Martins <rmmartins@gmail.com>
... ... @@ -112,6 +114,7 @@ Rodrigo Medeiros &lt;rodrigo.mss01@gmail.com&gt;
112 114 Rodrigo Souto <rodrigo@colivre.coop.br>
113 115 Ronny Kursawe <kursawe.ronny@googlemail.com>
114 116 Samuel R. C. Vale <srcvale@holoscopio.com>
  117 +Simiao Carvalho <simiaosimis@gmail.com>
115 118 Tallys Martins <tallysmartins@yahoo.com.br>
116 119 Thiago Casotti <thiago.casotti@uol.com.br>
117 120 Thiago Kairala <thiagor.kairala@gmail.com>
... ... @@ -123,6 +126,7 @@ Valessio Brito &lt;contato@valessiobrito.com.br&gt;
123 126 Victor Costa <vfcosta@gmail.com>
124 127 Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com>
125 128 Vinicius Cubas Brand <viniciuscb@gmail.com>
  129 +Vitor Barbosa <vitornga15@gmail.com>
126 130 Wilton Rodrigues <braynwilton@gmail.com>
127 131 Yann Lugrin <yann.lugrin@liquid-concept.ch>
128 132  
... ...
app/controllers/my_profile/cms_controller.rb
... ... @@ -111,10 +111,7 @@ class CmsController &lt; MyProfileController
111 111 end
112 112 end
113 113  
114   - unless @article.kind_of?(RssFeed)
115   - @escaped_body = CGI::escapeHTML(@article.body || '')
116   - @escaped_abstract = CGI::escapeHTML(@article.abstract || '')
117   - end
  114 + escape_fields @article
118 115 end
119 116  
120 117 def new
... ... @@ -185,6 +182,8 @@ class CmsController &lt; MyProfileController
185 182 end
186 183 end
187 184  
  185 + escape_fields @article
  186 +
188 187 render :action => 'edit'
189 188 end
190 189  
... ... @@ -534,4 +533,10 @@ class CmsController &lt; MyProfileController
534 533 end
535 534 end
536 535  
  536 + def escape_fields article
  537 + unless article.kind_of?(RssFeed)
  538 + @escaped_body = CGI::escapeHTML(article.body || '')
  539 + @escaped_abstract = CGI::escapeHTML(article.abstract || '')
  540 + end
  541 + end
537 542 end
... ...
app/controllers/public/content_viewer_controller.rb
... ... @@ -8,6 +8,7 @@ class ContentViewerController &lt; ApplicationController
8 8 helper TagsHelper
9 9  
10 10 def view_page
  11 +
11 12 path = get_path(params[:page], params[:format])
12 13  
13 14 @version = params[:version].to_i
... ... @@ -38,7 +39,7 @@ class ContentViewerController &lt; ApplicationController
38 39 end
39 40  
40 41 # At this point the page will be showed
41   - @page.hit unless user_is_a_bot?
  42 + @page.hit unless user_is_a_bot? || already_visited?(@page)
42 43  
43 44 @page = FilePresenter.for @page
44 45  
... ... @@ -272,4 +273,18 @@ class ContentViewerController &lt; ApplicationController
272 273 @comment_order = params[:comment_order].nil? ? 'oldest' : params[:comment_order]
273 274 end
274 275  
  276 + private
  277 +
  278 + def already_visited?(element)
  279 + user_id = if user.nil? then -1 else current_user.id end
  280 + user_id = "#{user_id}_#{element.id}_#{element.class}"
  281 +
  282 + if cookies.signed[:visited] == user_id
  283 + return true
  284 + else
  285 + cookies.permanent.signed[:visited] = user_id
  286 + return false
  287 + end
  288 + end
  289 +
275 290 end
... ...
app/controllers/public/profile_controller.rb
... ... @@ -66,7 +66,10 @@ class ProfileController &lt; PublicController
66 66  
67 67 def members
68 68 if is_cache_expired?(profile.members_cache_key(params))
69   - @members = profile.members_by_name.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage], :total_entries => profile.members.count)
  69 + sort = (params[:sort] == 'desc') ? params[:sort] : 'asc'
  70 + @profile_admins = profile.admins.includes(relations_to_include).order("name #{sort}").paginate(:per_page => members_per_page, :page => params[:npage])
  71 + @profile_members = profile.members.includes(relations_to_include).order("name #{sort}").paginate(:per_page => members_per_page, :page => params[:npage])
  72 + @profile_members_url = url_for(:controller => 'profile', :action => 'members')
70 73 end
71 74 end
72 75  
... ...
app/helpers/article_helper.rb
... ... @@ -88,7 +88,7 @@ module ArticleHelper
88 88 content_tag( 'small', _('Who will be able to create new topics on this forum?')) +
89 89 content_tag('div', '', slider_options) +
90 90 hidden_field_tag('article[topic_creation]', article.topic_creation) +
91   - javascript_include_tag('topic-creation-config')
  91 + javascript_include_tag("#{Noosfero.root}/assets/topic-creation-config.js")
92 92 end
93 93  
94 94 def privacity_exceptions(article, tokenized_children)
... ...
app/models/profile.rb
... ... @@ -920,7 +920,8 @@ private :generate_url, :url_options
920 920  
921 921 def members_cache_key(params = {})
922 922 page = params[:npage] || '1'
923   - cache_key + '-members-page-' + page
  923 + sort = (params[:sort] == 'desc') ? params[:sort] : 'asc'
  924 + cache_key + '-members-page-' + page + '-' + sort
924 925 end
925 926  
926 927 def more_recent_label
... ...
app/models/profile_activity.rb
... ... @@ -16,6 +16,7 @@ class ProfileActivity &lt; ActiveRecord::Base
16 16  
17 17 def self.update_activity activity
18 18 profile_activity = ProfileActivity.where(activity_id: activity.id, activity_type: activity.class.base_class.name).first
  19 + return unless profile_activity
19 20 profile_activity.send :copy_timestamps
20 21 profile_activity.save!
21 22 profile_activity
... ...
app/models/scrap.rb
... ... @@ -22,11 +22,11 @@ class Scrap &lt; ActiveRecord::Base
22 22  
23 23 scope :not_replies, ->{ where scrap_id: nil }
24 24  
25   - track_actions :leave_scrap, :after_create, :keep_params => ['sender.name', 'content', 'receiver.name', 'receiver.url'], :if => Proc.new{|s| s.sender != s.receiver && s.sender != s.top_root.receiver}, :custom_target => :action_tracker_target
  25 + track_actions :leave_scrap, :after_create, :keep_params => ['sender.name', 'content', 'receiver.name', 'receiver.url'], :if => Proc.new{|s| s.sender != s.receiver && s.sender != s.top_root.receiver}, :custom_target => :action_tracker_target, :custom_user => :sender
26 26  
27   - track_actions :leave_scrap_to_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender == s.receiver}
  27 + track_actions :leave_scrap_to_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender == s.receiver}, :custom_user => :sender
28 28  
29   - track_actions :reply_scrap_on_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender != s.receiver && s.sender == s.top_root.receiver}
  29 + track_actions :reply_scrap_on_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender != s.receiver && s.sender == s.top_root.receiver}, :custom_user => :sender
30 30  
31 31 after_create :send_notification
32 32  
... ...
app/views/cms/edit.html.erb
... ... @@ -5,8 +5,6 @@
5 5  
6 6 <%= hidden_field_tag("type", @type) if @type %>
7 7  
8   - <%= hidden_field_tag('parent_id', @parent_id) if @parent_id %>
9   -
10 8 <%= hidden_field_tag('back_to', @back_to) %>
11 9  
12 10 <%= hidden_field_tag('success_back_to', @success_back_to) %>
... ...
app/views/content_viewer/_article_toolbar.html.erb
... ... @@ -29,10 +29,10 @@
29 29 <%= expirable_button @page, :locale, content, url %>
30 30 <% end %>
31 31  
32   - <%= modal_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)))) unless remove_content_button(:new, @page) %>
  32 + <%= modal_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : @page.parent))) unless remove_content_button(:new, @page) %>
33 33  
34 34 <% content = content_tag('span', label_for_clone_article(@page)) %>
35   - <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'new', :id => @page.id, :clone => true, :type => @page.class }) %>
  35 + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'new', :id => @page.id, :clone => true, :parent_id => (@page.folder? ? @page : @page.parent), :type => @page.class}) %>
36 36 <%= expirable_button @page, :clone, content, url %>
37 37 <% end %>
38 38  
... ...
app/views/profile/_profile_members_list.html.erb 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +<div id="profile-members-sort-options">
  2 + <%= label_tag("sort-#{role}", _("Sort by:")) %>
  3 + <%= select_tag("sort-#{role}",
  4 + options_for_select([
  5 + [_("Name A-Z"), 'asc'],
  6 + [_("Name Z-A"), 'desc'],
  7 + ], :selected => params[:sort])
  8 + ) %>
  9 +</div>
  10 +<ul class="profile-list-<%= role %>" >
  11 + <% users.each do |u| %>
  12 + <%= profile_image_link(u) %>
  13 + <% end %>
  14 +</ul>
  15 +
  16 +<%= pagination_links users, :param_name => 'npage' %>
... ...
app/views/profile/members.html.erb
1 1 <div class="common-profile-list-block">
2 2  
3   -<h1><%= _("%s's members") % profile.name %></h1>
  3 +<h1><%= _("Members (%d)") % @profile_members.total_entries %></h1>
  4 +<h2 class="community-name"><%= profile.name %></h2>
4 5  
5 6 <% cache_timeout(profile.members_cache_key(params), 4.hours) do %>
6   - <ul class='profile-list'>
7   - <% @members.each do |member| %>
8   - <%= profile_image_link(member) %>
9   - <% end %>
10   - </ul>
  7 + <div class="profile-members-tabs-container">
  8 + <% tabs = [] %>
  9 +
  10 + <% div_members = content_tag :div, :class => "profile-members" do
  11 + render :partial => 'profile_members_list',
  12 + :locals => {
  13 + :users => @profile_members,
  14 + :role => "members"
  15 + }
  16 + end %>
  17 +
  18 + <% tabs << {:title => _("%d Members") % @profile_members.total_entries,
  19 + :id => "members-tab",
  20 + :content => div_members
  21 + } %>
11 22  
12   - <div id='pagination-profiles'>
13   - <%= pagination_links @members, :param_name => 'npage' %>
14   - </div>
  23 + <% div_admins = content_tag :div, :class => "profile-admins" do
  24 + render :partial => 'profile_members_list',
  25 + :locals => {
  26 + :users => @profile_admins,
  27 + :role => "admins"
  28 + }
  29 + end %>
  30 +
  31 + <% tabs << {:title => _("%d Administrators") % @profile_admins.total_entries,
  32 + :id => "admins-tab",
  33 + :content => div_admins
  34 + } %>
  35 +
  36 + <%= render_tabs(tabs) %>
  37 + </div><!-- end of class="profile-members-tabs-container" -->
15 38 <% end %>
16 39  
17 40 <% button_bar do %>
... ... @@ -26,4 +49,7 @@
26 49 <% end %>
27 50 <% end %>
28 51  
29   -</div><!-- fim class="common-profile-list-block" -->
  52 +<%= hidden_field_tag "profile_url", @profile_members_url %>
  53 +</div><!-- end of class="common-profile-list-block" -->
  54 +
  55 +<%= javascript_include_tag "members_page.js" %>
... ...
debian/changelog
  1 +noosfero (1.3~0.0) UNRELEASED; urgency=medium
  2 +
  3 + * Noosfero 1.3 ALPHA 0
  4 +
  5 + -- Antonio Terceiro <terceiro@debian.org> Wed, 09 Sep 2015 21:27:05 -0300
  6 +
1 7 noosfero (1.2) wheezy; urgency=low
2 8  
3 9 * Noosfero 1.2
... ...
lib/authenticated_system.rb
... ... @@ -2,12 +2,12 @@ module AuthenticatedSystem
2 2  
3 3 protected
4 4  
5   - # See impl. from http://stackoverflow.com/a/2513456/670229
6 5 def self.included base
7   - base.around_filter do
  6 + # See impl. from http://stackoverflow.com/a/2513456/670229
  7 + base.around_filter do |&block|
8 8 begin
9 9 User.current = current_user
10   - yield
  10 + block.call
11 11 ensure
12 12 # to address the thread variable leak issues in Puma/Thin webserver
13 13 User.current = nil
... ...
lib/noosfero/plugin.rb
... ... @@ -241,6 +241,16 @@ class Noosfero::Plugin
241 241 nil
242 242 end
243 243  
  244 + # -> Customize the way comments are counted for Profiles and Environment
  245 + # considering more than just articles comments
  246 + # Used on statistic block
  247 + # Ex: a plugin may want that Communities receive comments themselves
  248 + # as evaluations
  249 + # returns = the number of comments to be sum on the statistics
  250 + def more_comments_count owner
  251 + nil
  252 + end
  253 +
244 254 # -> Adds tabs to the profile
245 255 # returns = { :title => title, :id => id, :content => content, :start => start }
246 256 # title = name that will be displayed.
... ...
lib/noosfero/version.rb
1 1 module Noosfero
2 2 PROJECT = 'noosfero'
3   - VERSION = '1.2'
  3 + VERSION = '1.3~0.0'
4 4 end
5 5  
6 6 root = File.expand_path(File.dirname(__FILE__) + '/../..')
... ...
plugins/ldap/README.md
... ... @@ -13,6 +13,7 @@ Dependences
13 13 See the Noosfero install file. After install Noosfero, install LDAP dependences:
14 14  
15 15 $ gem install net-ldap -v 0.3.1
  16 +$ sudo apt-get install ruby-magic
16 17  
17 18 Enable Plugin
18 19 -------------
... ...
plugins/ldap/lib/ldap_authentication.rb
... ... @@ -19,6 +19,7 @@ require &#39;rubygems&#39;
19 19 require 'iconv'
20 20 require 'net/ldap'
21 21 require 'net/ldap/dn'
  22 +require 'magic'
22 23  
23 24 class LdapAuthentication
24 25  
... ... @@ -134,7 +135,18 @@ class LdapAuthentication
134 135  
135 136 def self.get_attr(entry, attr_name)
136 137 if !attr_name.blank?
137   - entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
  138 + val = entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
  139 + if val.nil?
  140 + Rails.logger.warn "LDAP entry #{entry.dn} has no attr #{attr_name}."
  141 + nil
  142 + elsif val == '' || val == ' '
  143 + Rails.logger.warn "LDAP entry #{entry.dn} has attr #{attr_name} empty."
  144 + ''
  145 + else
  146 + charset = Magic.guess_string_mime_encoding(val)
  147 + val.encode 'utf-8', charset, invalid: :replace, undef: :replace
  148 + end
138 149 end
139 150 end
  151 +
140 152 end
... ...
plugins/ldap/test/unit/ldap_authentication_test.rb
... ... @@ -2,141 +2,177 @@ require_relative &#39;../test_helper&#39;
2 2  
3 3 class LdapAuthenticationTest < ActiveSupport::TestCase
4 4  
  5 + def pseudoEntry(data)
  6 + entry = data.clone
  7 + def entry.dn; 'testDN'; end
  8 + entry
  9 + end
  10 +
5 11 def setup
6 12 @ldap_config = load_ldap_config
7 13 end
8 14  
9   - should "host be nil as default" do
  15 + should 'host be nil as default' do
10 16 ldap = LdapAuthentication.new
11 17 assert_nil ldap.host
12 18 end
13 19  
14   - should "create with host passed as parameter" do
  20 + should 'create with host passed as parameter' do
15 21 value = 'http://myhost.com'
16 22 ldap = LdapAuthentication.new('host' => value)
17 23 assert_equal value, ldap.host
18 24 end
19 25  
20   - should "port be 389 as default" do
  26 + should 'port be 389 as default' do
21 27 ldap = LdapAuthentication.new
22 28 assert_equal 389, ldap.port
23 29 end
24 30  
25   - should "create with port passed as parameter" do
  31 + should 'create with port passed as parameter' do
26 32 value = 555
27 33 ldap = LdapAuthentication.new('port' => value)
28 34 assert_equal value, ldap.port
29 35 end
30 36  
31   - should "account be nil as default" do
  37 + should 'account be nil as default' do
32 38 ldap = LdapAuthentication.new
33 39 assert_nil ldap.account
34 40 end
35 41  
36   - should "create with account passed as parameter" do
  42 + should 'create with account passed as parameter' do
37 43 value = 'uid=sector,ou=Service,ou=corp,dc=company,dc=com,dc=br'
38 44 ldap = LdapAuthentication.new('account' => value)
39 45 assert_equal value, ldap.account
40 46 end
41 47  
42   - should "account_password be nil as default" do
  48 + should 'account_password be nil as default' do
43 49 ldap = LdapAuthentication.new
44 50 assert_nil ldap.account_password
45 51 end
46 52  
47   - should "create with account_password passed as parameter" do
  53 + should 'create with account_password passed as parameter' do
48 54 value = 'password'
49 55 ldap = LdapAuthentication.new('account_password' => value)
50 56 assert_equal value, ldap.account_password
51 57 end
52 58  
53   - should "base_dn be nil as default" do
  59 + should 'base_dn be nil as default' do
54 60 ldap = LdapAuthentication.new
55 61 assert_nil ldap.base_dn
56 62 end
57 63  
58   - should "create with base_dn passed as parameter" do
  64 + should 'create with base_dn passed as parameter' do
59 65 value = 'dc=company,dc=com,dc=br'
60 66 ldap = LdapAuthentication.new('base_dn' => value)
61 67 assert_equal value, ldap.base_dn
62 68 end
63 69  
64   - should "attr_login be nil as default" do
  70 + should 'attr_login be nil as default' do
65 71 ldap = LdapAuthentication.new
66 72 assert_nil ldap.attr_login
67 73 end
68 74  
69   - should "create with attr_login passed as parameter" do
  75 + should 'create with attr_login passed as parameter' do
70 76 value = 'uid'
71 77 ldap = LdapAuthentication.new('attr_login' => value)
72 78 assert_equal value, ldap.attr_login
73 79 end
74 80  
75   - should "attr_fullname be nil as default" do
  81 + should 'attr_fullname be nil as default' do
76 82 ldap = LdapAuthentication.new
77 83 assert_nil ldap.attr_fullname
78 84 end
79 85  
80   - should "create with attr_fullname passed as parameter" do
  86 + should 'create with attr_fullname passed as parameter' do
81 87 value = 'Noosfero System'
82 88 ldap = LdapAuthentication.new('attr_fullname' => value)
83 89 assert_equal value, ldap.attr_fullname
84 90 end
85 91  
86   - should "attr_mail be nil as default" do
  92 + should 'attr_mail be nil as default' do
87 93 ldap = LdapAuthentication.new
88 94 assert_nil ldap.attr_mail
89 95 end
90 96  
91   - should "create with attr_mail passed as parameter" do
  97 + should 'create with attr_mail passed as parameter' do
92 98 value = 'test@noosfero.com'
93 99 ldap = LdapAuthentication.new('attr_mail' => value)
94 100 assert_equal value, ldap.attr_mail
95 101 end
96 102  
97   - should "onthefly_register be false as default" do
  103 + should 'onthefly_register be false as default' do
98 104 ldap = LdapAuthentication.new
99 105 refute ldap.onthefly_register
100 106 end
101 107  
102   - should "create with onthefly_register passed as parameter" do
  108 + should 'create with onthefly_register passed as parameter' do
103 109 value = true
104 110 ldap = LdapAuthentication.new('onthefly_register' => value)
105 111 assert_equal value, ldap.onthefly_register
106 112 end
107 113  
108   - should "filter be nil as default" do
  114 + should 'filter be nil as default' do
109 115 ldap = LdapAuthentication.new
110 116 assert_nil ldap.filter
111 117 end
112 118  
113   - should "create with filter passed as parameter" do
  119 + should 'create with filter passed as parameter' do
114 120 value = 'test'
115 121 ldap = LdapAuthentication.new('filter' => value)
116 122 assert_equal value, ldap.filter
117 123 end
118 124  
119   - should "tls be false as default" do
  125 + should 'tls be false as default' do
120 126 ldap = LdapAuthentication.new
121 127 refute ldap.tls
122 128 end
123 129  
124   - should "create with tls passed as parameter" do
  130 + should 'create with tls passed as parameter' do
125 131 value = true
126 132 ldap = LdapAuthentication.new('tls' => value)
127 133 assert_equal value, ldap.tls
128 134 end
129 135  
130   - should "onthefly_register? return true if onthefly_register is true" do
  136 + should 'onthefly_register? return true if onthefly_register is true' do
131 137 ldap = LdapAuthentication.new('onthefly_register' => true)
132 138 assert ldap.onthefly_register?
133 139 end
134 140  
135   - should "onthefly_register? return false if onthefly_register is false" do
  141 + should 'onthefly_register? return false if onthefly_register is false' do
136 142 ldap = LdapAuthentication.new('onthefly_register' => false)
137 143 refute ldap.onthefly_register?
138 144 end
139 145  
  146 + should 'detect and convert non utf-8 charset from ldap' do
  147 + entry = pseudoEntry('name' => "Jos\xE9 Jo\xE3o")
  148 + name = LdapAuthentication.get_attr entry, 'name'
  149 + assert_equal name, 'José João'
  150 + end
  151 +
  152 + should 'dont crash when entry key is empty string' do
  153 + entry = pseudoEntry('name' => "")
  154 + name = LdapAuthentication.get_attr entry, 'name'
  155 + assert_equal name, ''
  156 + end
  157 +
  158 + should 'dont crash when entry key has only a space char' do
  159 + entry = pseudoEntry('name' => " ")
  160 + name = LdapAuthentication.get_attr entry, 'name'
  161 + assert_equal name, ''
  162 + end
  163 +
  164 + should 'dont crash when entry key is nil' do
  165 + entry = pseudoEntry('name' => nil)
  166 + name = LdapAuthentication.get_attr entry, 'name'
  167 + assert_equal name, nil
  168 + end
  169 +
  170 + should 'dont crash when entry key does not exists' do
  171 + entry = pseudoEntry({})
  172 + name = LdapAuthentication.get_attr entry, 'name'
  173 + assert_equal name, nil
  174 + end
  175 +
140 176 if ldap_configured?
141 177 should 'return the user attributes' do
142 178 auth = LdapAuthentication.new(@ldap_config['server'])
... ...
plugins/organization_ratings/controllers/organization_ratings_plugin_admin_controller.rb 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +class OrganizationRatingsPluginAdminController < PluginAdminController
  2 +
  3 + include RatingsHelper
  4 + helper :ratings
  5 + append_view_path File.join(File.dirname(__FILE__) + '/../views')
  6 +
  7 + def index
  8 + end
  9 +
  10 + def update
  11 + if env_organization_ratings_config.update_attributes(params[:organization_ratings_config])
  12 + session[:notice] = _('Configuration updated successfully.')
  13 + else
  14 + session[:notice] = _('Configuration could not be saved.')
  15 + end
  16 + render :action => 'index'
  17 + end
  18 +
  19 +end
0 20 \ No newline at end of file
... ...
plugins/organization_ratings/controllers/organization_ratings_plugin_profile_controller.rb 0 → 100644
... ... @@ -0,0 +1,76 @@
  1 +class OrganizationRatingsPluginProfileController < ProfileController
  2 + include RatingsHelper
  3 + helper :ratings
  4 +
  5 + def new_rating
  6 + @rating_available = user_can_rate_now?
  7 + @users_ratings = get_ratings(profile.id).paginate(
  8 + :per_page => env_organization_ratings_config.per_page,
  9 + :page => params[:npage]
  10 + )
  11 + if request.post?
  12 + if @rating_available
  13 + create_new_rate
  14 + else
  15 + session[:notice] = _("You can not vote on this %s") % profile.class.name
  16 + end
  17 + end
  18 + end
  19 +
  20 + private
  21 +
  22 + def user_can_rate_now?
  23 + return false unless user
  24 + ratings = OrganizationRating.where(
  25 + :organization_id => profile.id,
  26 + :person_id => user.id
  27 + )
  28 +
  29 + return false if (!ratings.empty? && env_organization_ratings_config.vote_once)
  30 +
  31 + if ratings.empty?
  32 + true
  33 + else
  34 + elapsed_time_since_last_rating = Time.zone.now - ratings.last.created_at
  35 + elapsed_time_since_last_rating > env_organization_ratings_config.cooldown.hours
  36 + end
  37 + end
  38 +
  39 + def create_new_rate
  40 + rating = OrganizationRating.new(params[:organization_rating])
  41 + rating.person = current_user.person
  42 + rating.organization = profile
  43 + rating.value = params[:organization_rating_value] if params[:organization_rating_value]
  44 +
  45 + if rating.save
  46 + create_rating_comment(rating)
  47 + session[:notice] = _("%s successfully rated!") % profile.name
  48 + else
  49 + session[:notice] = _("Sorry, there were problems rating this profile.")
  50 + end
  51 +
  52 + redirect_to :controller => 'profile', :action => 'index'
  53 + end
  54 +
  55 + def create_rating_comment(rating)
  56 + if params[:comments]
  57 + comment_task = CreateOrganizationRatingComment.create!(
  58 + params[:comments].merge(
  59 + :requestor => rating.person,
  60 + :organization_rating_id => rating.id,
  61 + :target => rating.organization
  62 + )
  63 + )
  64 + comment_task.finish if can_perform?(params)
  65 + end
  66 + end
  67 +
  68 + def can_perform? (params)
  69 + (params[:comments][:body].blank? ||
  70 + !env_organization_ratings_config.are_moderated)
  71 + end
  72 +
  73 + def permission
  74 + :manage_memberships
  75 + end
  76 +end
... ...
plugins/organization_ratings/db/migrate/20150830225546_create_organization_ratings.rb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +class CreateOrganizationRatings < ActiveRecord::Migration
  2 + def change
  3 + create_table :organization_ratings do |t|
  4 + t.belongs_to :organization
  5 + t.belongs_to :person
  6 + t.belongs_to :comment
  7 + t.integer :value
  8 +
  9 + t.timestamps
  10 + end
  11 + end
  12 +end
... ...
plugins/organization_ratings/db/migrate/20150830225733_create_organization_ratings_config.rb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +class CreateOrganizationRatingsConfig < ActiveRecord::Migration
  2 +
  3 + def change
  4 + create_table :organization_ratings_configs do |t|
  5 + t.belongs_to :environment
  6 + t.integer :cooldown, :integer, :default => 24
  7 + t.integer :default_rating, :integer, :default => 1
  8 + t.string :order, :string, :default => "recent"
  9 + t.integer :per_page, :integer, :default => 10
  10 + t.boolean :vote_once, :boolean, :default => false
  11 + t.boolean :are_moderated, :boolean, :default => true
  12 + end
  13 + end
  14 +end
... ...
plugins/organization_ratings/db/migrate/20150830230047_add_comments_count_to_profile.rb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +class AddCommentsCountToProfile < ActiveRecord::Migration
  2 + def self.up
  3 + change_table :profiles do |t|
  4 + t.integer :comments_count
  5 + end
  6 + end
  7 +
  8 + def self.down
  9 + remove_column :profiles, :comments_count
  10 + end
  11 +end
0 12 \ No newline at end of file
... ...
plugins/organization_ratings/features/rate_community.feature 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +Feature: rate_community
  2 + As a user
  3 + I want to be able rate a community
  4 + So that users can see my feedback about that community
  5 +
  6 + Background:
  7 + Given plugin "OrganizationRatings" is enabled on environment
  8 + Given the following user
  9 + | login | name |
  10 + | joaosilva | Joao Silva |
  11 + And the following community
  12 + | identifier | name |
  13 + | mycommunity | My Community |
  14 + And the following blocks
  15 + | owner | type |
  16 + | mycommunity | AverageRatingBlock |
  17 + | mycommunity | OrganizationRatingsBlock |
  18 + And the environment domain is "localhost"
  19 + And I am logged in as "joaosilva"
  20 +
  21 + @selenium
  22 + Scenario: display rate button inside average block
  23 + Given I am on mycommunity's homepage
  24 + Then I should see "Rate this Community" within ".average-rating-block"
  25 + And I should see "Be the first to rate" within ".average-rating-block"
  26 +
  27 + @selenium
  28 + Scenario: display rate button inside communities ratings block
  29 + Given I am on mycommunity's homepage
  30 + Then I should see "Rate Community" within ".make-report-block"
... ...
plugins/organization_ratings/lib/average_rating_block.rb 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +class AverageRatingBlock < Block
  2 + include RatingsHelper
  3 +
  4 + def self.description
  5 + _('Organization Average Rating')
  6 + end
  7 +
  8 + def help
  9 + _('This block displays the organization average rating.')
  10 + end
  11 +
  12 + def content(args = {})
  13 + profile_identifier = self.owner.identifier
  14 + average_rating = OrganizationRating.average_rating self.owner.id
  15 +
  16 + proc do
  17 + render(
  18 + :file => 'blocks/display_organization_average_rating',
  19 + :locals => {
  20 + :profile_identifier => profile_identifier,
  21 + :average_rating => average_rating
  22 + }
  23 + )
  24 + end
  25 + end
  26 +
  27 + def cacheable?
  28 + false
  29 + end
  30 +end
... ...
plugins/organization_ratings/lib/create_organization_rating_comment.rb 0 → 100644
... ... @@ -0,0 +1,131 @@
  1 +class CreateOrganizationRatingComment < Task
  2 + include Rails.application.routes.url_helpers
  3 +
  4 + validates_presence_of :requestor_id, :organization_rating_id, :target_id
  5 +
  6 + settings_items :organization_rating_id, :type => Integer, :default => nil
  7 + settings_items :organization_rating_comment_id, :type => Integer, :default => nil
  8 +
  9 + attr_accessible :organization_rating_id, :body, :requestor
  10 + attr_accessible :reject_explanation, :target
  11 +
  12 + before_save :update_comment_body
  13 +
  14 + DATA_FIELDS = ['body']
  15 + DATA_FIELDS.each do |field|
  16 + settings_items field.to_sym
  17 + end
  18 +
  19 + def update_comment_body
  20 + if self.organization_rating_comment_id.nil?
  21 + create_comment
  22 + else
  23 + comment = Comment.find_by_id(self.organization_rating_comment_id)
  24 + comment.body = get_comment_message
  25 + comment.save
  26 + end
  27 + end
  28 +
  29 + def create_comment
  30 + if (self.body && !self.body.blank?)
  31 + comment_body = _("Comment waiting for approval")
  32 + comment = Comment.create!(:source => self.target, :body => comment_body, :author => self.requestor)
  33 +
  34 +
  35 + self.organization_rating_comment_id = comment.id
  36 + link_comment_with_its_rating(comment)
  37 + end
  38 + end
  39 +
  40 + def link_comment_with_its_rating(user_comment)
  41 + rating = OrganizationRating.find(self.organization_rating_id)
  42 + rating.comment = user_comment
  43 + rating.save
  44 + end
  45 +
  46 + def get_comment_message
  47 + if self.status == Status::CANCELLED
  48 + _("Comment rejected")
  49 + elsif self.status == Status::FINISHED
  50 + self.body
  51 + else
  52 + _("No comment")
  53 + end
  54 + end
  55 +
  56 + def accept_details
  57 + true
  58 + end
  59 +
  60 + def title
  61 + _("New Comment")
  62 + end
  63 +
  64 + def information
  65 + message = _("<a href=%{requestor_url}>%{requestor}</a> wants to create a comment in this %{target_class}") %
  66 + {:requestor_url => url_for(self.requestor.url), :requestor => self.requestor.name, :target_class => self.target.class.name.downcase}
  67 +
  68 + {:message => message}
  69 + end
  70 +
  71 + def reject_details
  72 + true
  73 + end
  74 +
  75 + def icon
  76 + {:type => :profile_image, :profile => requestor, :url => requestor.url}
  77 + end
  78 +
  79 + # tells if this request was rejected
  80 + def rejected?
  81 + self.status == Task::Status::CANCELLED
  82 + end
  83 +
  84 + # tells if this request was appoved
  85 + def approved?
  86 + self.status == Task::Status::FINISHED
  87 + end
  88 +
  89 + def target_notification_description
  90 + _("%{requestor} wants to create a comment in this \"%{target}\"") %
  91 + {:requestor => self.requestor.name, :target => self.target.class.name.downcase }
  92 + end
  93 +
  94 + def target_notification_message
  95 + _("User \"%{user}\" just requested to create a comment in the %{target_class}
  96 + \"%{target_name}\".
  97 + You have to approve or reject it through the \"Pending Validations\"
  98 + section in your control panel.\n") %
  99 + { :user => self.requestor.name, :target_class => self.target.class.name.downcase, :target_name => self.target.name }
  100 + end
  101 +
  102 + def task_created_message
  103 + _("Your request for commenting at %{target} was
  104 + just sent. Environment administrator will receive it and will approve or
  105 + reject your request according to his methods and criteria.
  106 + You will be notified as soon as environment administrator has a position
  107 + about your request.") %
  108 + { :target => self.target.name }
  109 + end
  110 +
  111 + def task_cancelled_message
  112 + _("Your request for commenting at %{target} was
  113 + not approved by the environment administrator. The following explanation
  114 + was given: \n\n%{explanation}") %
  115 + { :target => self.target.name,
  116 + :explanation => self.reject_explanation }
  117 + end
  118 +
  119 + def task_finished_message
  120 + _('Your request for commenting was approved.
  121 + You can access %{url} to see your comment.') %
  122 + { :url => ratings_url }
  123 + end
  124 +
  125 + private
  126 +
  127 + def ratings_url
  128 + url = url_for(self.target.public_profile_url) + "/plugin/organization_ratings/new_rating"
  129 + end
  130 +
  131 +end
... ...
plugins/organization_ratings/lib/ext/comments.rb 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +require_dependency "comment"
  2 +
  3 +Comment.class_eval do
  4 +
  5 + has_one :organization_rating
  6 +end
... ...
plugins/organization_ratings/lib/ext/environment.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +require_dependency "environment"
  2 +
  3 +class Environment
  4 + has_one :organization_ratings_config
  5 +end
... ...
plugins/organization_ratings/lib/ext/organization.rb 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +require_dependency 'organization'
  2 +
  3 +Organization.class_eval do
  4 + has_many :organization_ratings
  5 +
  6 + has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc'
  7 +end
... ...
plugins/organization_ratings/lib/ext/person.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +require_dependency 'person'
  2 +
  3 +Person.class_eval do
  4 + has_many :organization_ratings
  5 +end
... ...
plugins/organization_ratings/lib/organization_rating.rb 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +class OrganizationRating < ActiveRecord::Base
  2 + belongs_to :person
  3 + belongs_to :organization
  4 + belongs_to :comment
  5 +
  6 + attr_accessible :value, :person, :organization, :comment
  7 +
  8 + validates :value,
  9 + :presence => true, :inclusion => {
  10 + in: 1..5, message: _("must be between 1 and 5")
  11 + }
  12 +
  13 + validates :organization_id, :person_id,
  14 + :presence => true
  15 +
  16 +
  17 + def self.average_rating organization_id
  18 + average = OrganizationRating.where(organization_id: organization_id).average(:value)
  19 +
  20 + if average
  21 + (average - average.truncate) >= 0.5 ? average.ceil : average.floor
  22 + end
  23 + end
  24 +
  25 +end
... ...
plugins/organization_ratings/lib/organization_ratings_block.rb 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +class OrganizationRatingsBlock < Block
  2 + include RatingsHelper
  3 +
  4 + def self.description
  5 + _('Organization Ratings')
  6 + end
  7 +
  8 + def help
  9 + _('This block displays the community ratings.')
  10 + end
  11 +
  12 + def content(args = {})
  13 + block = self
  14 +
  15 + proc do
  16 + render(
  17 + :file => 'blocks/organization_ratings_block',
  18 + :locals => {:block => block}
  19 + )
  20 + end
  21 + end
  22 +
  23 + def limit_number_of_ratings
  24 + env_organization_ratings_config.per_page
  25 + end
  26 +
  27 + def cacheable?
  28 + false
  29 + end
  30 +end
... ...
plugins/organization_ratings/lib/organization_ratings_config.rb 0 → 100644
... ... @@ -0,0 +1,53 @@
  1 +class OrganizationRatingsConfig < ActiveRecord::Base
  2 +
  3 + belongs_to :environment
  4 +
  5 + attr_accessible :cooldown, :default_rating, :order, :per_page
  6 + attr_accessible :vote_once, :are_moderated, :environment_id
  7 +
  8 + ORDER_OPTIONS = {recent: _('More Recent'), best: _('Best Ratings')}
  9 +
  10 + MINIMUM_RATING = 1
  11 + MAX_COOLDOWN = 1000
  12 +
  13 + validates :default_rating,
  14 + :presence => true, :numericality => {
  15 + greater_than_or_equal_to: MINIMUM_RATING,
  16 + less_than_or_equal_to: 5
  17 + }
  18 +
  19 + validates :cooldown,
  20 + :presence => true, :numericality => {
  21 + greater_than_or_equal_to: 0,
  22 + less_than_or_equal_to: MAX_COOLDOWN
  23 + }
  24 +
  25 + validates :per_page,
  26 + :presence => true, :numericality => {
  27 + :greater_than_or_equal_to => 5,
  28 + :less_than_or_equal_to => 20
  29 + }
  30 +
  31 +
  32 + def order_options
  33 + ORDER_OPTIONS
  34 + end
  35 +
  36 + def minimum_ratings
  37 + MINIMUM_RATING
  38 + end
  39 +
  40 + def max_cooldown
  41 + MAX_COOLDOWN
  42 + end
  43 +
  44 + class << self
  45 + def instance
  46 + environment = Environment.default
  47 + environment.organization_ratings_config || create(environment_id: environment.id)
  48 + end
  49 +
  50 + private :new
  51 + end
  52 +
  53 +end
... ...
plugins/organization_ratings/lib/organization_ratings_plugin.rb 0 → 100644
... ... @@ -0,0 +1,73 @@
  1 +class OrganizationRatingsPlugin < Noosfero::Plugin
  2 + include Noosfero::Plugin::HotSpot
  3 +
  4 + def self.plugin_name
  5 + "Organization Ratings"
  6 + end
  7 +
  8 + def self.plugin_description
  9 + _("A plugin that allows you to rate a organization and comment about it.")
  10 + end
  11 +
  12 + module Hotspots
  13 + def organization_ratings_plugin_comments_extra_fields
  14 + nil
  15 + end
  16 +
  17 + def organization_ratings_title
  18 + nil
  19 + end
  20 +
  21 + def organization_ratings_plugin_star_message
  22 + nil
  23 + end
  24 +
  25 + def organization_ratings_plugin_extra_fields_show_data user_rating
  26 + nil
  27 + end
  28 + end
  29 +
  30 + # Plugin Hotspot to display the average rating
  31 + def display_organization_average_rating organization
  32 + unless organization.nil?
  33 + average_rating = OrganizationRating.average_rating organization.id
  34 +
  35 + Proc::new {
  36 + render :file => 'blocks/display_organization_average_rating',
  37 + :locals => {
  38 + :profile_identifier => organization.identifier,
  39 + :average_rating => average_rating
  40 + }
  41 + }
  42 + end
  43 + end
  44 +
  45 + def more_comments_count owner
  46 + if owner.kind_of?(Environment) then
  47 + owner.profiles.sum(:comments_count)
  48 + elsif owner.kind_of?(Profile) then
  49 + owner.comments_count
  50 + else
  51 + 0
  52 + end
  53 + end
  54 +
  55 + def self.extra_blocks
  56 + {
  57 + OrganizationRatingsBlock => {:type => [Enterprise, Community], :position => ['1']},
  58 + AverageRatingBlock => {:type => [Enterprise, Community]}
  59 + }
  60 + end
  61 +
  62 + def stylesheet?
  63 + true
  64 + end
  65 +
  66 + def js_files
  67 + %w(
  68 + public/rate.js
  69 + public/comunities_rating_management.js
  70 + )
  71 + end
  72 +
  73 +end
... ...
plugins/organization_ratings/lib/ratings_helper.rb 0 → 100644
... ... @@ -0,0 +1,15 @@
  1 +module RatingsHelper
  2 +
  3 + def env_organization_ratings_config
  4 + OrganizationRatingsConfig.instance
  5 + end
  6 +
  7 + def get_ratings (profile_id)
  8 + order_options = env_organization_ratings_config.order_options
  9 + if env_organization_ratings_config.order.downcase == order_options[:recent]
  10 + ratings = OrganizationRating.where(organization_id: profile_id).order("value DESC")
  11 + else
  12 + ratings = OrganizationRating.where(organization_id: profile_id).order("created_at DESC")
  13 + end
  14 + end
  15 +end
0 16 \ No newline at end of file
... ...
plugins/organization_ratings/public/images/small-star-negative.png 0 → 100644

529 Bytes

plugins/organization_ratings/public/images/small-star-positive.png 0 → 100644

509 Bytes

plugins/organization_ratings/public/images/star-negative-medium.png 0 → 100644

642 Bytes

plugins/organization_ratings/public/images/star-negative.png 0 → 100644

642 Bytes

plugins/organization_ratings/public/images/star-positive-medium.png 0 → 100644

637 Bytes

plugins/organization_ratings/public/images/star-positive.png 0 → 100644

637 Bytes

plugins/organization_ratings/public/images/user-not-logged.png 0 → 100644

2.48 KB

plugins/organization_ratings/public/organization_rating_management.js 0 → 100644
... ... @@ -0,0 +1,35 @@
  1 +(function($) {
  2 + "use strict";
  3 +
  4 + var VoteOnce = {
  5 + init: function() {
  6 + this.cacheDom();
  7 + this.setEvents();
  8 + },
  9 +
  10 +
  11 + cacheDom: function() {
  12 + this.$vote_once_checkbox = $("#environment_organization_ratings_vote_once");
  13 + this.$hours_timer_input = $("#environment_organization_ratings_cooldown");
  14 + },
  15 +
  16 +
  17 + setEvents: function() {
  18 + this.$vote_once_checkbox.on("click", this.verifyHoursTimerDisable.bind(this));
  19 + },
  20 +
  21 +
  22 + verifyHoursTimerDisable: function() {
  23 + if (this.$vote_once_checkbox.is(":checked")) {
  24 + this.$hours_timer_input.attr("disabled", "disabled");
  25 + } else {
  26 + this.$hours_timer_input.removeAttr("disabled");
  27 + }
  28 + }
  29 + }
  30 +
  31 +
  32 + $(document).ready(function() {
  33 + VoteOnce.init();
  34 + });
  35 +}) (jQuery);
... ...
plugins/organization_ratings/public/rate.js 0 → 100644
... ... @@ -0,0 +1,122 @@
  1 +;(function($, undefined) {
  2 + "use strict";
  3 +
  4 + /*
  5 + * All global data that are used in the stars feature.
  6 + */
  7 + var DATA = {
  8 + selected_rate: 0, // The actual selected star when the user click on a star
  9 + maximum_stars: 5, // (const) The maximum number of allowed stars
  10 + minimum_stars: 1, // (const) The minimum number of allowed stars
  11 + DATA_RATE_ATTRIBUTE: "data-star-rate", // (const) The data attribute with the star rate
  12 + NOT_SELECTED_VALUE: 0 // (const) The value when there is no selected rate
  13 + }
  14 +
  15 +
  16 + /*
  17 + * Prepare the global data that are variable.
  18 + * If the user already rated the organization, set the selected_rate as the rated value
  19 + */
  20 + function set_global_data() {
  21 + var selected_rate = parseInt($("#selected-star-rate").val());
  22 + var minimum_stars = parseInt($("#minimum_stars").val());
  23 + DATA.selected_rate = selected_rate;
  24 + DATA.minimum_stars = minimum_stars;
  25 + }
  26 +
  27 +
  28 + /*
  29 + * Given a start rate, an end rate and the elements, it makes a regex that filter
  30 + * the elements by the given range and returns it.
  31 + */
  32 + function star_filter(start, end, elements) {
  33 + var test_regex = undefined;
  34 +
  35 + // Verify if it is a valid range and makes its range regex: /[start-end]/
  36 + if (end >= start) {
  37 + test_regex = new RegExp("["+(start)+"-"+(end)+"]");
  38 + } else {
  39 + // If the range is invalid, make a regex that will return no element
  40 + test_regex = new RegExp("[]");
  41 + }
  42 +
  43 + // Filter the elements that are in the given range
  44 + var result = elements.filter(function(i, element) {
  45 + var rate = parseInt(element.getAttribute(DATA.DATA_RATE_ATTRIBUTE));
  46 +
  47 + return test_regex.test(rate);
  48 + });
  49 +
  50 + return result;
  51 + }
  52 +
  53 +
  54 + /*
  55 + * Show or hide the stars depending on the mouse position and the limit rate.
  56 + * Given the mouseover rate, the limit rate and the css classes to be swapped,
  57 + *
  58 + * It verify if the user already selected a star rate:
  59 + * If true:
  60 + * It swap the css classes from the selected star up to the given limit rate
  61 + * If false:
  62 + * It swap the css classes from the minimum rate up to the mouseover rate
  63 + */
  64 + function change_stars_class(rate_mouseover, limit_rate, remove_class, add_class) {
  65 + var previous_stars = undefined;
  66 +
  67 + // The default not selected rate value is 0 and minimum is 1.
  68 + if (DATA.selected_rate >= DATA.minimum_stars) {
  69 + previous_stars = star_filter(DATA.selected_rate+1, limit_rate, $("."+remove_class));
  70 + } else {
  71 + previous_stars = star_filter(DATA.minimum_stars, rate_mouseover, $("."+remove_class));
  72 + }
  73 +
  74 + previous_stars.switchClass(remove_class, add_class);
  75 + }
  76 +
  77 +
  78 + /*
  79 + * Sets the stars mouse events.
  80 + */
  81 + function set_star_hover_actions() {
  82 + $(".star-negative, .star-positive")
  83 + .on("mouseover", function() { // On mouse over, show the current rate star
  84 + var rate_mouseover = parseInt(this.getAttribute(DATA.DATA_RATE_ATTRIBUTE));
  85 +
  86 + change_stars_class(rate_mouseover, rate_mouseover, "star-negative", "star-positive");
  87 + })
  88 +
  89 + .on("mouseout", function() { // On mouse out, hide the stars
  90 + var rate_mouseover = parseInt(this.getAttribute(DATA.DATA_RATE_ATTRIBUTE));
  91 +
  92 + change_stars_class(rate_mouseover, DATA.maximum_stars, "star-positive", "star-negative");
  93 + })
  94 +
  95 + .on("click", function() { // On mouse click, set the selected star rate
  96 + var rate_mouseover = parseInt(this.getAttribute(DATA.DATA_RATE_ATTRIBUTE));
  97 +
  98 + // If the new rate is different from actual, update it
  99 + if (rate_mouseover !== DATA.selected_rate && rate_mouseover > DATA.minimum_stars) {
  100 + DATA.selected_rate = rate_mouseover;
  101 + } else { // or else, uncheck it
  102 + DATA.selected_rate = DATA.minimum_stars;
  103 + }
  104 +
  105 + // Mark the selected_rate
  106 + $("#selected-star-rate").val(DATA.selected_rate);
  107 +
  108 + var star_notice = $(".star-notice");
  109 + star_notice.find("span").html(DATA.selected_rate);
  110 + star_notice.removeClass("star-hide");
  111 + });
  112 + }
  113 +
  114 +
  115 + /*
  116 + * When the page DOM is ready, set all the stars events
  117 + */
  118 + $(document).ready(function() {
  119 + set_global_data();
  120 + set_star_hover_actions();
  121 + });
  122 +}) (jQuery);
... ...
plugins/organization_ratings/style.css 0 → 100644
... ... @@ -0,0 +1,200 @@
  1 +.star-container {
  2 + width: 100%;
  3 + height: 20px;
  4 +}
  5 +
  6 +.star-negative, .star-positive {
  7 + width: 20px;
  8 + height: 20px;
  9 + background-repeat: no-repeat;
  10 + margin-right: 2px;
  11 + position: relative;
  12 + float: left;
  13 + cursor: pointer;
  14 +}
  15 +
  16 +.star-negative {
  17 + background-image: url('public/images/star-negative.png');
  18 +}
  19 +
  20 +.star-positive {
  21 + background-image: url('public/images/star-positive.png');
  22 +}
  23 +
  24 +.small-star-negative, .small-star-positive {
  25 + background-repeat: no-repeat;
  26 + float: left;
  27 + height: 15px;
  28 + margin-right: 2px;
  29 + position: relative;
  30 + width: 15px;
  31 +}
  32 +
  33 +.small-star-negative {
  34 + background-image: url('public/images/small-star-negative.png');
  35 +}
  36 +
  37 +.small-star-positive {
  38 + background-image: url('public/images/small-star-positive.png');
  39 +}
  40 +
  41 +.medium-star-negative, .medium-star-positive {
  42 + background-repeat: no-repeat;
  43 + float: left;
  44 + height: 20px;
  45 + margin-right: 2px;
  46 + position: relative;
  47 + width: 20px;
  48 +}
  49 +
  50 +.medium-star-positive {
  51 + background-image: url('public/images/star-positive-medium.png');
  52 +}
  53 +
  54 +.medium-star-negative {
  55 + background-image: url('public/images/star-negative-medium.png');
  56 +}
  57 +
  58 +.star-hide {
  59 + display: none;
  60 +}
  61 +
  62 +.organization-average-rating-container {
  63 + border-top: 1px dotted #D3D6DE;
  64 + margin-top: 20px;
  65 + padding-top: 10px;
  66 +}
  67 +
  68 +.organization-average-rating-container .star-rate-text {
  69 + float: left;
  70 + margin-right: 10px;
  71 + padding-top: 5px;
  72 +}
  73 +
  74 +.organization-average-rating-container .rating-invitation {
  75 + font-size: 14px;
  76 + float: left;
  77 + margin-right: 10px;
  78 + padding-top: 3px;
  79 +}
  80 +
  81 +.organization-average-rating-container .star-container {
  82 + float: left;
  83 + width: 120px;
  84 +}
  85 +
  86 +.organization-average-rating-container .rate-this-organization {
  87 + border-left: 1px dotted #D3D6DE;
  88 + float: left;
  89 + padding: 4px 0px 2px 10px;
  90 +}
  91 +
  92 +.star-rate-data {
  93 + width: 100%;
  94 + padding-top: 20px;
  95 + position: relative;
  96 + overflow: auto;
  97 +}
  98 +
  99 +.star-profile-information, .star-rate-form {
  100 + display: table-cell;
  101 + vertical-align: top;
  102 + width: 362px;
  103 +}
  104 +
  105 +.star-profile-information {
  106 + width: 134px;
  107 +}
  108 +
  109 +.star-rate-form {
  110 + display: table-cell;
  111 + vertical-align: top;
  112 +}
  113 +
  114 +.star-profile-image, .star-profile-name {
  115 + text-align: center;
  116 +}
  117 +
  118 +.star-profile-name {
  119 + word-break: break-word;
  120 + margin: auto;
  121 + margin-top: 5px;
  122 + width: 66px;
  123 +}
  124 +
  125 +.star-rate-data .star-rate-form .star-comment-container .formfield textarea {
  126 + width: 361px;
  127 +}
  128 +
  129 +/************* Users ratings list ****************/
  130 +
  131 +.ratings-list .user-rating-block,
  132 +.ratings-list .make-report-block {
  133 + border-top: 1px solid #D3D6DE;
  134 + margin-top: 25px;
  135 + padding-top: 20px;
  136 +}
  137 +
  138 +.ratings-list .make-report-block {
  139 + padding-bottom: 25px;
  140 +}
  141 +
  142 +.ratings-list .see-more{
  143 + border-top: 1px solid #D3D6DE;
  144 +}
  145 +.ratings-list .user-rating-block .user-testimony-container {
  146 + display: table-cell;
  147 + padding-left: 20px;
  148 +}
  149 +
  150 +.ratings-list .make-report-block .make-report-container {
  151 + display: table-cell;
  152 +}
  153 +
  154 +.ratings-list .user-rating-block .user-testimony-container .star-container {
  155 + display: table-cell;
  156 +}
  157 +
  158 +.ratings-list .user-rating-block .user-testimony-container .testimony-rate-date {
  159 + display: table-cell;
  160 + max-width: 95px;
  161 + min-width: 95px;
  162 + padding-right: 160px;
  163 + white-space: nowrap;
  164 +}
  165 +
  166 +.ratings-list .user-rating-block .user-testimony-container .user-testimony {
  167 + margin-top: 10px;
  168 + word-break: break-word;
  169 +}
  170 +
  171 +.ratings-list .make-report-block .make-report-container .make-report-message {
  172 + font-size: 14px;
  173 + font-style: italic;
  174 + word-break: break-word;
  175 +}
  176 +
  177 +.ratings-list .make-report-block .make-report-container .button-bar {
  178 + overflow: auto;
  179 + padding-top: 15px;
  180 +}
  181 +
  182 +.ratings-list .user-rating-block .star-profile-information {
  183 + border-right: 1px dotted #D3D6DE;
  184 +}
  185 +
  186 +.ratings-list .icon-arrow-right-p {
  187 + background: url(/designs/themes/base/imgs/arrow-right-p.png) 100% 50% no-repeat;
  188 + display: block;
  189 + float: right;
  190 + margin-top: 20px;
  191 + padding-right: 15px;
  192 +}
  193 +
  194 +.task_information .comment {
  195 + padding-left: 60px;
  196 +}
  197 +
  198 +.average-rating-block {
  199 + height: 55px;
  200 +}
... ...
plugins/organization_ratings/test/functional/organization_ratings_plugin_admin_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,49 @@
  1 +require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper'
  2 +require File.expand_path(File.dirname(__FILE__)) + '/../../controllers/organization_ratings_plugin_admin_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class OrganizationRatingsPluginAdminController; def rescue_action(e) raise e end; end
  6 +
  7 +class OrganizationRatingsPluginAdminControllerTest < ActionController::TestCase
  8 +
  9 + def setup
  10 + @controller = OrganizationRatingsPluginAdminController.new
  11 + @request = ActionController::TestRequest.new
  12 + @response = ActionController::TestResponse.new
  13 +
  14 + @environment = Environment.default
  15 + @environment.enabled_plugins = ['OrganizationRatingsPlugin']
  16 + @environment.save
  17 +
  18 + @community = Community.create(:name => "TestCommunity")
  19 +
  20 + login_as(create_admin_user(@environment))
  21 + end
  22 +
  23 + test "should update organization rating plugin configuration" do
  24 + post :update, :organization_ratings_config => { :default_rating => 5,
  25 + :cooldown => 12,
  26 + :order => "recent",
  27 + :per_page => 10,
  28 + :vote_once => true }
  29 +
  30 + assert :success
  31 + @environment.reload
  32 + assert_equal 5, @environment.organization_ratings_config.default_rating
  33 + assert_equal "Configuration updated successfully.", session[:notice]
  34 + end
  35 +
  36 + test "should not update organization rating plugin configuration with negative cooldown time" do
  37 + post :update, :organization_ratings_config => { :default_rating => 5,
  38 + :cooldown => -50,
  39 + :order => "recent",
  40 + :per_page => 10,
  41 + :vote_once => true }
  42 +
  43 + assert :success
  44 + @environment.reload
  45 + assert_equal 24, @environment.organization_ratings_config.cooldown
  46 + assert_equal "Configuration could not be saved.", session[:notice]
  47 + end
  48 +end
  49 +
... ...
plugins/organization_ratings/test/functional/organization_ratings_plugin_profile_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,104 @@
  1 +require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper'
  2 +require File.expand_path(File.dirname(__FILE__)) + '/../../controllers/organization_ratings_plugin_profile_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class OrganizationRatingsPluginProfileController; def rescue_action(e) raise e end; end
  6 +
  7 +class OrganizationRatingsPluginProfileControllerTest < ActionController::TestCase
  8 +
  9 + def setup
  10 + @controller = OrganizationRatingsPluginProfileController.new
  11 + @request = ActionController::TestRequest.new
  12 + @response = ActionController::TestResponse.new
  13 +
  14 + @environment = Environment.default
  15 + @environment.enabled_plugins = ['OrganizationRatingsPlugin']
  16 + @environment.save
  17 +
  18 + @person = create_user('testuser').person
  19 + @community = Community.create(:name => "TestCommunity")
  20 + @enterprise = fast_create(Enterprise)
  21 + @config = OrganizationRatingsConfig.instance
  22 + login_as(@person.identifier)
  23 + @controller.stubs(:logged_in?).returns(true)
  24 + @controller.stubs(:current_user).returns(@person.user)
  25 + end
  26 +
  27 + test "should add new comment to community" do
  28 + post :new_rating, profile: @community.identifier, :comments => {:body => "This is a test"}, :organization_rating_value => 4
  29 + assert_equal "#{@community.name} successfully rated!", session[:notice]
  30 + end
  31 +
  32 + test "Create community_rating without comment body" do
  33 + post :new_rating, profile: @community.identifier, :comments => {:body => ""}, :organization_rating_value => 2
  34 +
  35 + assert_equal "#{@community.name} successfully rated!", session[:notice]
  36 + end
  37 +
  38 + test "Do not create community_rating without a rate value" do
  39 + post :new_rating, profile: @community.identifier, :comments => {:body => ""}, :organization_rating_value => nil
  40 +
  41 + assert_equal "Sorry, there were problems rating this profile.", session[:notice]
  42 + end
  43 +
  44 + test "do not create two ratings on Community when vote once config is true" do
  45 + post :new_rating, profile: @community.identifier, :comments => {:body => "This is a test"}, :organization_rating_value => 3
  46 +
  47 + assert_equal "#{@community.name} successfully rated!", session[:notice]
  48 +
  49 + @environment.organization_ratings_config.vote_once = true
  50 + @environment.save
  51 +
  52 + post :new_rating, profile: @community.identifier, :comments => {:body => "This is a test 2"}, :organization_rating_value => 3
  53 + assert_equal "You can not vote on this Community", session[:notice]
  54 + end
  55 +
  56 + test "do not create two ratings on Enterprise when vote once config is true" do
  57 + post :new_rating, profile: @enterprise.identifier, :comments => {:body => "This is a test"}, :organization_rating_value => 3
  58 +
  59 + assert_equal "#{@enterprise.name} successfully rated!", session[:notice]
  60 +
  61 + @environment.organization_ratings_config.vote_once = true
  62 + @environment.save
  63 +
  64 + post :new_rating, profile: @enterprise.identifier, :comments => {:body => "This is a test 2"}, :organization_rating_value => 3
  65 + assert_equal "You can not vote on this Enterprise", session[:notice]
  66 + end
  67 +
  68 + test "should count organization ratings on statistic block when block owner = Environment" do
  69 + block = StatisticsBlock.new
  70 + enterprise = fast_create(Enterprise)
  71 + post :new_rating, profile: enterprise.identifier, :comments => {:body => "body board"}, :organization_rating_value => 1
  72 + enterprise.reload
  73 + @environment.reload
  74 + block.expects(:owner).at_least_once.returns(@environment)
  75 + assert_equal 1, block.comments
  76 + end
  77 +
  78 +
  79 + test "should count organization ratings on statistic block when block owner = Profile" do
  80 + @config.cooldown = 0
  81 + @config.save
  82 +
  83 + block = StatisticsBlock.new
  84 +
  85 + post :new_rating, profile: @community.identifier, :comments => {:body => "body board"}, :organization_rating_value => 1
  86 + post :new_rating, profile: @community.identifier, :comments => {:body => "body surf"}, :organization_rating_value => 5
  87 +
  88 + block.expects(:owner).at_least_once.returns(@community)
  89 + @community.reload
  90 + assert_equal 2, block.comments
  91 + end
  92 +
  93 + test "Display unavailable rating message for users that must wait the rating cooldown time" do
  94 + post :new_rating, profile: @community.identifier, :comments => {:body => ""}, :organization_rating_value => 3
  95 + assert_not_match(/The administrators set the minimum time of/, @response.body)
  96 + valid_rating = OrganizationRating.last
  97 +
  98 + post :new_rating, profile: @community.identifier, :comments => {:body => ""}, :organization_rating_value => 3
  99 + assert_match(/The administrators set the minimum time of/, @response.body)
  100 + new_rating = OrganizationRating.last
  101 +
  102 + assert_equal valid_rating.id, new_rating.id
  103 + end
  104 +end
... ...
plugins/organization_ratings/test/unit/organization_rating_config_test.rb 0 → 100644
... ... @@ -0,0 +1,43 @@
  1 +require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper'
  2 +
  3 +class OrganizationRatingConfigTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @environment = Environment.default
  7 + @environment.enabled_plugins = ['OrganizationRatingsPlugin']
  8 + @environment.save
  9 + @organization_ratings_config = OrganizationRatingsConfig.instance
  10 + end
  11 +
  12 + test "Community ratings config default rating validation" do
  13 + @organization_ratings_config.default_rating = 0
  14 + @organization_ratings_config.save
  15 +
  16 + assert_equal false, @organization_ratings_config.valid?
  17 + assert_equal "must be greater than or equal to 1", @organization_ratings_config.errors[:default_rating].first
  18 +
  19 + @organization_ratings_config.default_rating = 6
  20 + assert_equal false, @organization_ratings_config.valid?
  21 +
  22 + assert_equal "must be less than or equal to 5", @organization_ratings_config.errors[:default_rating].first
  23 + end
  24 +
  25 + test "Communities ratings config cooldown validation" do
  26 + @organization_ratings_config.cooldown = -1
  27 + assert_equal false, @organization_ratings_config.valid?
  28 +
  29 + assert_equal "must be greater than or equal to 0", @organization_ratings_config.errors[:cooldown].first
  30 + end
  31 +
  32 + # test "communities ratings per page validation" do
  33 + # environment = Environment.new :communities_ratings_per_page => 4
  34 + # environment.valid?
  35 +
  36 + # assert_equal "must be greater than or equal to 5", environment.errors[:communities_ratings_per_page].first
  37 +
  38 + # environment.communities_ratings_per_page = 21
  39 + # environment.valid?
  40 +
  41 + # assert_equal "must be less than or equal to 20", environment.errors[:communities_ratings_per_page].first
  42 + # end
  43 +end
... ...
plugins/organization_ratings/test/unit/organization_rating_test.rb 0 → 100644
... ... @@ -0,0 +1,154 @@
  1 +require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper'
  2 +
  3 +class OrganizationRatingTest < ActiveSupport::TestCase
  4 + test "The value must be between 1 and 5" do
  5 + organization_rating1 = OrganizationRating.new :value => -1
  6 + organization_rating2 = OrganizationRating.new :value => 6
  7 +
  8 + assert_equal false, organization_rating1.valid?
  9 + assert_equal false, organization_rating2.valid?
  10 +
  11 + assert_equal true, organization_rating1.errors[:value].include?("must be between 1 and 5")
  12 + assert_equal true, organization_rating2.errors[:value].include?("must be between 1 and 5")
  13 +
  14 + organization_rating1.value = 1
  15 + organization_rating1.valid?
  16 +
  17 + organization_rating2.value = 5
  18 + organization_rating2.valid?
  19 +
  20 + assert_equal false, organization_rating1.errors[:value].include?("must be between 1 and 5")
  21 + assert_equal false, organization_rating2.errors[:value].include?("must be between 1 and 5")
  22 + end
  23 +
  24 + test "Create task for create a rating comment" do
  25 + person = create_user('molly').person
  26 + person.email = "person@email.com"
  27 + person.save!
  28 +
  29 + community = fast_create(Community)
  30 + community.add_admin(person)
  31 +
  32 + organization_rating = OrganizationRating.create!(
  33 + :value => 3,
  34 + :person => person,
  35 + :organization => community
  36 + )
  37 +
  38 + create_organization_rating_comment = CreateOrganizationRatingComment.create!(
  39 + :requestor => person,
  40 + :organization_rating_id => organization_rating.id,
  41 + :target => community
  42 + )
  43 +
  44 + assert community.tasks.include?(create_organization_rating_comment)
  45 + end
  46 +
  47 + test "Check comment message when Task status = ACTIVE" do
  48 + person = create_user('molly').person
  49 + person.email = "person@email.com"
  50 + person.save!
  51 +
  52 + community = fast_create(Community)
  53 + community.add_admin(person)
  54 +
  55 +
  56 + organization_rating = OrganizationRating.create!(
  57 + :value => 3,
  58 + :person => person,
  59 + :organization => community
  60 + )
  61 +
  62 + create_organization_rating_comment = CreateOrganizationRatingComment.create!(
  63 + :requestor => person,
  64 + :organization_rating_id => organization_rating.id,
  65 + :target => community,
  66 + :body => "sample comment"
  67 + )
  68 + assert_equal 1, create_organization_rating_comment.status
  69 + message = "Comment waiting for approval"
  70 + comment = Comment.find_by_id(create_organization_rating_comment.organization_rating_comment_id)
  71 + assert_equal message, comment.body
  72 + end
  73 +
  74 + test "Check comment message when Task status = CANCELLED" do
  75 + person = create_user('molly').person
  76 + person.email = "person@email.com"
  77 + person.save!
  78 +
  79 + community = fast_create(Community)
  80 + community.add_admin(person)
  81 +
  82 +
  83 + organization_rating = OrganizationRating.create!(
  84 + :value => 3,
  85 + :person => person,
  86 + :organization => community
  87 + )
  88 +
  89 + create_organization_rating_comment = CreateOrganizationRatingComment.create!(
  90 + :requestor => person,
  91 + :organization_rating_id => organization_rating.id,
  92 + :target => community,
  93 + :body => "sample comment"
  94 + )
  95 + create_organization_rating_comment.cancel
  96 + assert_equal 2, create_organization_rating_comment.status
  97 + message = "Comment rejected"
  98 + comment = Comment.find_by_id(create_organization_rating_comment.organization_rating_comment_id)
  99 + assert_equal message, comment.body
  100 + end
  101 +
  102 + test "Check comment message when Task status = FINISHED" do
  103 + person = create_user('molly').person
  104 + person.email = "person@email.com"
  105 + person.save!
  106 +
  107 + community = fast_create(Community)
  108 + community.add_admin(person)
  109 +
  110 + comment = Comment.create!(source: community,
  111 + body: "regular comment",
  112 + author: person)
  113 +
  114 + organization_rating = OrganizationRating.create!(
  115 + :value => 3,
  116 + :person => person,
  117 + :organization => community,
  118 + :comment => comment
  119 + )
  120 +
  121 + create_organization_rating_comment = CreateOrganizationRatingComment.create!(
  122 + :body => comment.body,
  123 + :requestor => organization_rating.person,
  124 + :organization_rating_id => organization_rating.id,
  125 + :target => organization_rating.organization,
  126 + :body => "sample comment"
  127 + )
  128 +
  129 + create_organization_rating_comment.finish
  130 + assert_equal 3, create_organization_rating_comment.status
  131 + message = "sample comment"
  132 + comment = Comment.find_by_id(create_organization_rating_comment.organization_rating_comment_id)
  133 + assert_equal message, comment.body
  134 + end
  135 +
  136 +
  137 + test "Should calculate community's rating average" do
  138 + community = fast_create Community
  139 + p1 = fast_create Person, :name=>"Person 1"
  140 + p2 = fast_create Person, :name=>"Person 2"
  141 + p3 = fast_create Person, :name=>"Person 3"
  142 +
  143 + OrganizationRating.create! :value => 2, :organization => community, :person => p1
  144 + OrganizationRating.create! :value => 3, :organization => community, :person => p2
  145 + OrganizationRating.create! :value => 5, :organization => community, :person => p3
  146 +
  147 + assert_equal 3, OrganizationRating.average_rating(community)
  148 +
  149 + p4 = fast_create Person, :name=>"Person 4"
  150 + OrganizationRating.create! :value => 4, :organization => community, :person => p4
  151 +
  152 + assert_equal 4, OrganizationRating.average_rating(community)
  153 + end
  154 +end
... ...
plugins/organization_ratings/test/unit/ratings_helper_test.rb 0 → 100644
... ... @@ -0,0 +1,63 @@
  1 +require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper'
  2 +require 'ratings_helper'
  3 +
  4 +class RatingsHelperTest < ActiveSupport::TestCase
  5 + include RatingsHelper
  6 +
  7 + def setup
  8 +
  9 + @environment = Environment.default
  10 + @environment.enabled_plugins = ['OrganizationRatingsPlugin']
  11 + @environment.save
  12 + @person = create_user('testuser').person
  13 + @community = Community.create(:name => "TestCommunity")
  14 + @organization_ratings_config = OrganizationRatingsConfig.instance
  15 + end
  16 +
  17 + should "get the ratings of a community ordered by most recent ratings" do
  18 + ratings_array = []
  19 +
  20 + first_rating = OrganizationRating.new
  21 + first_rating.organization = @community
  22 + first_rating.person = @person
  23 + first_rating.value = 3
  24 + first_rating.save
  25 +
  26 + most_recent_rating = OrganizationRating.new
  27 + most_recent_rating.organization = @community
  28 + most_recent_rating.person = @person
  29 + most_recent_rating.value = 5
  30 + sleep 2
  31 + most_recent_rating.save
  32 +
  33 + ratings_array << most_recent_rating
  34 + ratings_array << first_rating
  35 +
  36 + assert_equal @organization_ratings_config.order, "recent"
  37 + assert_equal ratings_array, get_ratings(@community.id)
  38 + end
  39 +
  40 + should "get the ratings of a community ordered by best ratings" do
  41 + ratings_array = []
  42 + @organization_ratings_config = "best"
  43 + @environment.save
  44 +
  45 + first_rating = OrganizationRating.new
  46 + first_rating.organization = @community
  47 + first_rating.person = @person
  48 + first_rating.value = 3
  49 + first_rating.save
  50 +
  51 + second_rating = OrganizationRating.new
  52 + second_rating.organization = @community
  53 + second_rating.person = @person
  54 + second_rating.value = 5
  55 + sleep 2
  56 + second_rating.save
  57 +
  58 + ratings_array << second_rating
  59 + ratings_array << first_rating
  60 +
  61 + assert_equal ratings_array, get_ratings(@community.id)
  62 + end
  63 +end
... ...
plugins/organization_ratings/views/blocks/display_organization_average_rating.html.erb 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +<div class="organization-average-rating-container">
  2 + <% if average_rating %>
  3 + <div class="star-rate-text">
  4 + <%= _("Rating: ") %>
  5 + </div>
  6 +
  7 + <div class="star-container">
  8 + <% (1..5).each do |star_number| %>
  9 + <% if star_number <= average_rating %>
  10 + <div class="medium-star-positive"></div>
  11 + <% else %>
  12 + <div class="medium-star-negative"></div>
  13 + <% end %>
  14 + <% end %>
  15 + </div>
  16 + <% else %>
  17 + <div class="rating-invitation">
  18 + <%= _("Be the first to rate!") %>
  19 + </div>
  20 + <% end %>
  21 +
  22 + <div class="rate-this-organization">
  23 + <%= link_to _("Rate this %s" % profile.class.name), url_for(:controller => "organization_ratings_plugin_profile", :action => "new_rating", :profile=>profile_identifier) %>
  24 + </div>
  25 +</div>
0 26 \ No newline at end of file
... ...
plugins/organization_ratings/views/blocks/organization_ratings_block.html.erb 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +<div class="ratings-title">
  2 + <%= block_title(block.title) %>
  3 + <% if block.get_ratings(block.owner.id).empty? %>
  4 + <div class="ratings-list">
  5 + <%= render :partial => 'shared/make_report_block' %>
  6 + </div>
  7 + <% else %>
  8 + <div class="ratings-list">
  9 + <% block.get_ratings(block.owner.id).each_with_index do |r, index| %>
  10 + <% break if index >= block.limit_number_of_ratings %>
  11 + <%= render :partial => "shared/user_rating_container", :locals => {:user_rate => r} %>
  12 + <% end %>
  13 +
  14 + <%= render :partial => 'shared/make_report_block' %>
  15 +
  16 + <div class="see-more">
  17 + <%= link_to _('See more'), url_for(:controller => 'organization_ratings_plugin_profile', :action => 'new_rating'), :class => 'icon-arrow-right-p' %>
  18 + </div>
  19 + </div>
  20 + <% end %>
  21 +</div>
... ...
plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb 0 → 100644
... ... @@ -0,0 +1,54 @@
  1 +<% config = env_organization_ratings_config %>
  2 +
  3 +<h1><%= _("Organization Rating Management") %> </h1>
  4 +
  5 +<%= labelled_form_for(:organization_ratings_config, :url => {:action => 'update'}) do |f| %>
  6 + <%= labelled_fields_for(:organization_ratings_config, config) do |c| %>
  7 + <table>
  8 + <tr>
  9 + <th><%= c_('Configuration') %></th>
  10 + <th><%= _('Value') %></th>
  11 + </tr>
  12 + <tr>
  13 + <td><%= _('Default amount of stars marked on evaluations') %></td>
  14 + <td><%= c.select :default_rating, (config.minimum_ratings)..5 %></td>
  15 + </tr>
  16 + <tr>
  17 + <td><%= _('Can rate an organization only once') %></td>
  18 + <td><%= c.check_box :vote_once %></td>
  19 + </tr>
  20 + <tr>
  21 + <td><%= _('The comments are moderated') %></td>
  22 + <td><%= c.check_box :are_moderated %></td>
  23 + </tr>
  24 + <tr>
  25 + <td>
  26 + <%= _('Time in hours between evaluations from the same user.') %>
  27 + <span class="hint" title=" <%= _('To disable cooldown use zero (0) value.') %> ">(?)</span>
  28 + </td>
  29 + <% hours_options = {size: 2} %>
  30 + <% hours_options[:disabled] = "disabled" if config.vote_once %>
  31 + <td><%= c.text_field :cooldown, hours_options %>
  32 + </td>
  33 + </tr>
  34 + <tr>
  35 + <td><%= _('Order ratings by') %></td>
  36 + <% order_options = [] %>
  37 + <% config.order_options.select{|k,v| order_options << v } %>
  38 + <td><%= c.select :order, order_options %></td>
  39 + </tr>
  40 + <tr>
  41 + <td><%= _('Ratings per page') %></td>
  42 + <td>
  43 + <%= c.select :per_page, 5..20 %>
  44 + </td>
  45 + </tr>
  46 + </table>
  47 + <div>
  48 + <% button_bar do %>
  49 + <%= submit_button('save', c_('Save changes')) %>
  50 + <%= button :back, _('Back'), :controller => 'plugins' %>
  51 + <% end %>
  52 + </div>
  53 + <% end %>
  54 +<% end %>
... ...
plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb 0 → 100644
... ... @@ -0,0 +1,80 @@
  1 +<% min_rate = env_organization_ratings_config.minimum_ratings %>
  2 +<% default_rating = env_organization_ratings_config.default_rating %>
  3 +
  4 +<div class="star-page-title">
  5 + <%= @plugins.dispatch(:organization_ratings_title).collect { |content| instance_exec(&content) }.join("") %>
  6 +</div>
  7 +
  8 +<div class="star-rate-data">
  9 +
  10 + <div class="star-profile-information">
  11 + <div class="star-profile-image">
  12 + <%= profile_image(current_user.person, :portrait) %>
  13 + </div>
  14 +
  15 + <div class="star-profile-name">
  16 + <%= current_user.name %>
  17 + </div>
  18 + </div>
  19 +
  20 + <% if @rating_available %>
  21 + <div class="star-rate-form">
  22 + <div data-rate-url=<%= url_for controller: "organization_ratings_plugin_profile", :action => "rate" %>>
  23 + <div class="star-rate-text">
  24 + <%= @plugins.dispatch(:organization_ratings_plugin_star_message).collect { |content| instance_exec(&content) }.join("") %>
  25 + </div>
  26 +
  27 + <div class="star-container" data-min-rate="<%= min_rate %>">
  28 +
  29 + <% (1..5).each do |rate_number| %>
  30 + <% if rate_number <= default_rating %>
  31 + <div class="star-positive" data-star-rate="<%= rate_number %>"></div>
  32 + <% else %>
  33 + <div class="star-negative" data-star-rate="<%= rate_number %>"></div>
  34 + <% end %>
  35 + <% end %>
  36 + </div>
  37 +
  38 + <div class="star-notice star-hide">
  39 + <%= _("Rated as") %> <span></span> <%= _("stars") %>
  40 + </div>
  41 + </div>
  42 +
  43 + <div class="star-comment-container">
  44 + <%= form_for :comments do |c| %>
  45 + <div class="formfieldline formfield type-text">
  46 + <%= c.label :body, _('Comment (Optional):'), :class => "formlabel" %>
  47 + <%= c.text_area :body %>
  48 + </div>
  49 +
  50 + <%= @plugins.dispatch(:organization_ratings_plugin_comments_extra_fields).collect { |content| instance_exec(&content) }.join("") %>
  51 +
  52 + <div class="button-bar">
  53 + <%= submit_button(:save, _('Save'), :cancel => {controller: 'profile', action: 'index'}) %>
  54 + </div>
  55 +
  56 + <input type="hidden" id="selected-star-rate" name="organization_rating_value" value="<%= @default_rate %>">
  57 + <input type="hidden" id="minimum_stars" name="organization_rating_min_value" value="<%= min_rate %>">
  58 + <% end %>
  59 + </div>
  60 +
  61 + <% elsif env_organization_ratings_config.vote_once %>
  62 + <div class="star-rate-form rating-vote-once">
  63 + <%= _("Hi, %s! The administrators set that you can vote") % current_user.name %>
  64 + <strong><%= _("only once") %></strong>
  65 + <%= _("for this %s.") % profile.class.name.downcase %>
  66 + <%= render :partial => 'shared/rating_button', :locals => { :disabled => true } %>
  67 + </div>
  68 + <% else %>
  69 + <div class="star-rate-form rating-cooldown">
  70 + <%= _("Hi, %s! The administrators set the minimum time of") % current_user.name %>
  71 + <strong><%= _("%s hour(s)" % env_organization_ratings_config.cooldown) %></strong>
  72 + <%= _("between each evaluation.") %>
  73 +
  74 + <%= render :partial => 'shared/rating_button', :locals => { :disabled => true } %>
  75 + </div>
  76 + <% end %>
  77 +
  78 +
  79 + </div>
  80 +</div>
0 81 \ No newline at end of file
... ...
plugins/organization_ratings/views/organization_ratings_plugin_profile/new_rating.html.erb 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +<% config = env_organization_ratings_config %>
  2 +<% if logged_in? %>
  3 + <%= render :partial => "new_rating_fields" %>
  4 +<% else %>
  5 + <div class="ratings-list">
  6 + <%= render :partial => "shared/make_report_block" %>
  7 + </div>
  8 +<% end %>
  9 +
  10 +<div class="ratings-list">
  11 + <% @users_ratings.each do |user_rate| %>
  12 + <%= render :partial => "shared/user_rating_container", :locals => {:user_rate => user_rate} %>
  13 + <% end %>
  14 +</div>
  15 +
  16 +<div id='pagination-profiles'>
  17 + <%= pagination_links @users_ratings, :param_name => 'npage' %>
  18 +</div>
0 19 \ No newline at end of file
... ...
plugins/organization_ratings/views/shared/_make_report_block.html.erb 0 → 100644
... ... @@ -0,0 +1,28 @@
  1 +<% logged_in_image = profile_image(current_user.person, :portrait) if current_user %>
  2 +<% logged_out_image = image_tag('plugins/organization_ratings/public/images/user-not-logged.png') %>
  3 +
  4 +<div class="make-report-block">
  5 + <div class="star-profile-information">
  6 + <div class="star-profile-image">
  7 + <%= logged_in? ? logged_in_image : logged_out_image %>
  8 + </div>
  9 +
  10 + <div class="star-profile-name">
  11 + <%= logged_in? ? current_user.person.name : _('User not logged *') %>
  12 + </div>
  13 + </div>
  14 +
  15 + <div class="make-report-container">
  16 + <div class="make-report-message">
  17 + <%= _('Report your experiences.') %>
  18 + </div>
  19 +
  20 + <%= render :partial => 'shared/rating_button', :locals => { :disabled => false } %>
  21 +
  22 + <% unless logged_in? %>
  23 + <div class="alert">
  24 + <%= _('* You must be logged in to submit a report.') %>
  25 + </div>
  26 + <% end %>
  27 + </div>
  28 +</div>
0 29 \ No newline at end of file
... ...
plugins/organization_ratings/views/shared/_rating_button.html.erb 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +<% button_bar do %>
  2 + <% if logged_in? %>
  3 + <%= button(:new,_("Rate %s ") % profile.class.name,
  4 + {:controller => "organization_ratings_plugin_profile",
  5 + :action => "new_rating"}) %>
  6 + <% else %>
  7 + <%= button(:login,_("Log in") , {:controller => 'account',
  8 + :action => 'login'}) %>
  9 + <% end %>
  10 +<% end %>
... ...
plugins/organization_ratings/views/shared/_user_rating_container.html.erb 0 → 100644
... ... @@ -0,0 +1,33 @@
  1 +<div class="user-rating-block">
  2 + <div class="star-profile-information">
  3 + <div class="star-profile-image">
  4 + <%= profile_image(user_rate.person, :portrait) %>
  5 + </div>
  6 +
  7 + <div class="star-profile-name">
  8 + <%= user_rate.person.name %>
  9 + </div>
  10 + </div>
  11 +
  12 + <div class="user-testimony-container">
  13 + <div class="testimony-rate-date">
  14 + <%= time_ago_in_words(user_rate.created_at) %>
  15 + </div>
  16 +
  17 + <div class="star-container">
  18 + <% (1..5).each do |rate_number| %>
  19 + <% if rate_number <= user_rate.value %>
  20 + <div class="small-star-positive"></div>
  21 + <% else %>
  22 + <div class="small-star-negative"></div>
  23 + <% end %>
  24 + <% end %>
  25 + </div>
  26 +
  27 + <div class="user-testimony">
  28 + <%= user_rate.comment.nil? ? _("No comment") : user_rate.comment.body %>
  29 + </div>
  30 +
  31 + <%= @plugins.dispatch(:organization_ratings_plugin_extra_fields_show_data, user_rate).collect { |content| instance_exec(&content) }.join("") %>
  32 + </div>
  33 +</div>
... ...
plugins/organization_ratings/views/tasks/_create_organization_rating_comment_accept_details.html.erb 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +<div class="organization-rating-comment-body">
  2 + <%= _("Comment:")%>
  3 + <%= "\"#{task.body}\""%>
  4 +</div>
... ...
plugins/people_block/controllers/people_block_plugin_profile_controller.rb
... ... @@ -1,20 +0,0 @@
1   -class PeopleBlockPluginProfileController < ProfileController
2   -
3   - append_view_path File.join(File.dirname(__FILE__) + '/../views')
4   -
5   - def members
6   - if is_cache_expired?(profile.members_cache_key(params))
7   - unless params[:role_key].blank?
8   - role = Role.find_by_key_and_environment_id(params[:role_key], profile.environment)
9   - @members = profile.members.with_role(role.id)
10   - @members_title = role.name
11   - else
12   - @members = profile.members
13   - @members_title = 'members'
14   - end
15   - @members = @members.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage], :total_entries => @members.count)
16   - end
17   - render "profile/members"
18   - end
19   -
20   -end
plugins/people_block/test/functional/people_block_plugin_profile_controller_test.rb
... ... @@ -1,72 +0,0 @@
1   -require_relative '../test_helper'
2   -require_relative '../../controllers/people_block_plugin_profile_controller'
3   -
4   -class PeopleBlockPluginProfileControllerTest < ActionController::TestCase
5   -
6   - def setup
7   - @controller = PeopleBlockPluginProfileController.new
8   - @request = ActionController::TestRequest.new
9   - @response = ActionController::TestResponse.new
10   -
11   - @profile = fast_create(Community)
12   -
13   - @environment = @profile.environment
14   - @environment.enabled_plugins = ['PeopleBlockPlugin']
15   - @environment.save!
16   -
17   - MembersBlock.delete_all
18   - @block = MembersBlock.new
19   - @block.box = @profile.boxes.first
20   - @block.save!
21   -
22   - @admin = create_user('adminprofile').person
23   - @member = create_user('memberprofile').person
24   - @moderator = create_user('moderatorprofile').person
25   - @profile.add_moderator(@moderator)
26   - @profile.add_member(@member)
27   - @profile.add_admin(@admin)
28   - end
29   -
30   - attr_accessor :profile, :block, :admin, :member, :moderator
31   -
32   - should 'list members without role_key' do
33   - get :members, :profile => profile.identifier, :role_key => ""
34   - assert_response :success
35   - assert_template 'members'
36   - assert_equivalent [@admin, @member, @moderator], assigns(:members)
37   - assert_match /adminprofile/, @response.body
38   - assert_match /memberprofile/, @response.body
39   - assert_match /moderatorprofile/, @response.body
40   - end
41   -
42   - should 'list members with role_key=nil' do
43   - get :members, :profile => profile.identifier, :role_key => nil
44   - assert_response :success
45   - assert_template 'members'
46   - assert_equivalent [@admin, @member, @moderator], assigns(:members)
47   - assert_match /adminprofile/, @response.body
48   - assert_match /memberprofile/, @response.body
49   - assert_match /moderatorprofile/, @response.body
50   - end
51   -
52   - should 'list members only' do
53   - get :members, :profile => profile.identifier, :role_key => Profile::Roles.member(profile.environment.id).key
54   - assert_response :success
55   - assert_template 'members'
56   - assert_equal [@member], assigns(:members)
57   - assert_no_match /adminprofile/, @response.body
58   - assert_match /memberprofile/, @response.body
59   - assert_no_match /moderatorprofile/, @response.body
60   - end
61   -
62   - should 'list moderators only' do
63   - get :members, :profile => profile.identifier, :role_key => Profile::Roles.moderator(profile.environment.id).key
64   - assert_response :success
65   - assert_template 'members'
66   - assert_equal [@moderator], assigns(:members)
67   - assert_no_match /adminprofile/, @response.body
68   - assert_no_match /memberprofile/, @response.body
69   - assert_match /moderatorprofile/, @response.body
70   - end
71   -
72   -end
plugins/people_block/test/unit/members_block_test.rb
... ... @@ -147,11 +147,11 @@ class MembersBlockTest &lt; ActionView::TestCase
147 147  
148 148 instance_eval(&block.footer)
149 149 assert_select 'a.view-all' do |elements|
150   - assert_select '[href=/profile/mytestuser/plugin/people_block/members]'
  150 + assert_select "[href=/profile/mytestuser/members#members-tab]"
151 151 end
152 152 end
153 153  
154   - should 'provide link to members page with a selected role' do
  154 + should 'provide link to members page when visible_role is profile_member' do
155 155 profile = create_user('mytestuser').person
156 156 block = MembersBlock.new
157 157 block.box = profile.boxes.first
... ... @@ -160,7 +160,33 @@ class MembersBlockTest &lt; ActionView::TestCase
160 160  
161 161 instance_eval(&block.footer)
162 162 assert_select 'a.view-all' do |elements|
163   - assert_select '[href=/profile/mytestuser/plugin/people_block/members?role_key=profile_member]'
  163 + assert_select '[href=/profile/mytestuser/members#members-tab]'
  164 + end
  165 + end
  166 +
  167 + should 'provide link to members page when visible_role is profile_moderator' do
  168 + profile = create_user('mytestuser').person
  169 + block = MembersBlock.new
  170 + block.box = profile.boxes.first
  171 + block.visible_role = 'profile_moderator'
  172 + block.save!
  173 +
  174 + instance_eval(&block.footer)
  175 + assert_select 'a.view-all' do |elements|
  176 + assert_select '[href=/profile/mytestuser/members#members-tab]'
  177 + end
  178 + end
  179 +
  180 + should 'provide link to admins page when visible_role is profile_admin' do
  181 + profile = create_user('mytestuser').person
  182 + block = MembersBlock.new
  183 + block.box = profile.boxes.first
  184 + block.visible_role = 'profile_admin'
  185 + block.save!
  186 +
  187 + instance_eval(&block.footer)
  188 + assert_select 'a.view-all' do |elements|
  189 + assert_select '[href=/profile/mytestuser/members#admins-tab]'
164 190 end
165 191 end
166 192  
... ...
plugins/people_block/views/blocks/members.html.erb
1   -<%= link_to c_('View all'), {:profile => profile.identifier, :controller => 'people_block_plugin_profile', :action => 'members', :role_key => role_key}, :class => 'view-all' %>
  1 +<% anchor = role_key == "profile_admin" ? "admins-tab" : "members-tab" %>
  2 +<%= link_to c_('View all'), {:profile => profile.identifier, :controller => 'profile', :action => 'members', :anchor =>anchor }, :class => 'view-all' %>
2 3  
3 4 <% if show_join_leave_button %>
4 5 <%= render :partial => 'blocks/profile_info_actions/join_leave_community' %>
... ...
plugins/statistics/lib/statistics_block.rb
... ... @@ -128,11 +128,12 @@ class StatisticsBlock &lt; Block
128 128 end
129 129 end
130 130  
  131 + include Noosfero::Plugin::HotSpot
131 132 def comments
132 133 if owner.kind_of?(Environment) then
133   - owner.profiles.joins(:articles).sum(:comments_count).to_i
  134 + owner.articles.sum(:comments_count).to_i + plugins.dispatch(:more_comments_count, owner).first.to_i
134 135 elsif owner.kind_of?(Profile) then
135   - owner.articles.sum(:comments_count)
  136 + owner.articles.sum(:comments_count) + plugins.dispatch(:more_comments_count, owner).first.to_i
136 137 else
137 138 0
138 139 end
... ...
public/designs/themes/base/style.scss
... ... @@ -231,6 +231,10 @@ body, th, td, input {
231 231 border-left: 0px;
232 232 }
233 233  
  234 +.menu-submenu-list>li{
  235 + width: 100%;
  236 +}
  237 +
234 238 #navigation .menu-submenu ul{
235 239 border: 1px solid #888a85;
236 240 border-top: 0px;
... ... @@ -1534,3 +1538,7 @@ table#recaptcha_table tr:hover td {
1534 1538 width: 494px;
1535 1539 padding-left: 2px;
1536 1540 }
  1541 +
  1542 +.profile-members-title-sort {
  1543 + clear: both;
  1544 +}
... ...
public/javascripts/members_page.js 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +(function($) {
  2 + "use strict";
  3 +
  4 + function set_members_sort() {
  5 + var profile_members_url = $("#profile_url").val();
  6 +
  7 + $("#sort-members, #sort-admins").on("change", function() {
  8 + var sort_value = this.value;
  9 + var role = this.id;
  10 + role = role.replace("sort-", '');
  11 + var actual_page_content = $(".profile-list-"+role);
  12 +
  13 + $.get(profile_members_url, {sort: sort_value}, function(response) {
  14 + var html_response = $(response);
  15 +
  16 + actual_page_content.html(html_response.find(".profile-list-"+role).html());
  17 + });
  18 + });
  19 + }
  20 +
  21 + $(document).ready(function() {
  22 + set_members_sort();
  23 + });
  24 +}) (jQuery);
... ...
public/stylesheets/application.css
... ... @@ -4775,6 +4775,11 @@ h1#agenda-title {
4775 4775 background-image: url(../images/control-panel/role-management.gif)
4776 4776 }
4777 4777 /* ==> public/stylesheets/controller_profile_members.css <== */
  4778 +
  4779 +.profile-members-tabs-container .ui-corner-all {
  4780 + overflow: auto;
  4781 +}
  4782 +
4778 4783 .controller-profile_members .no-boxes {
4779 4784 margin: 30px
4780 4785 }
... ... @@ -5430,6 +5435,7 @@ h1#agenda-title {
5430 5435 margin: 0;
5431 5436 padding: 0;
5432 5437 width: 100%;
  5438 + height: 92px;
5433 5439 }
5434 5440 #content .menu-submenu-content ul {
5435 5441 margin: 0;
... ...
script/authors.sed
... ... @@ -161,6 +161,10 @@ s/Marcos da Silva Ramos &lt;ms.ramos@outlook.com&gt;/Marcos Ramos &lt;ms.ramos@outlook.co
161 161 s/Marcos Ramos <ms.ramos@outlook.com$/Marcos Ramos <ms.ramos@outlook.com>/
162 162 s/Marcos <marcos.rpj2@gmail.com>/Marcos Ronaldo <marcos.rpj2@gmail.com>/
163 163  
  164 +s/Michel Felipe <mfelipeof@gmail.com>/Michel Felipe de Oliveira Ferreira <michel.ferreira@serpro.gov.br>/
  165 +
  166 +s/Omar Júnior/Omar Junior/
  167 +
164 168 s/Parley Martins <parley@outlook.com>/Parley Martins <parleypachecomartins@gmail.com>/
165 169  
166 170 s/Paulo Meirelles$/Paulo Meirelles <paulo@softwarelivre.org>/
... ... @@ -180,6 +184,8 @@ s/Pedro Leal &lt;carlos88morais@gmail.com&gt;/Pedro Leal/
180 184 s/Pedro Leal <diegoamc90@gmail.com>/Pedro Leal/
181 185 s/Pedro Leal <jaodsilv@linux.ime.usp.br>/Pedro Leal/
182 186  
  187 +s/^pedrodelyra/Pedro de Lyra/
  188 +
183 189 s/Rafael Manzo$/Rafael Reggiani Manzo <rr.manzo@gmail.com>/
184 190 s/Rafael Manzo <alessandro.palmeira@gmail.com>/Rafael Reggiani Manzo <rr.manzo@gmail.com>/
185 191 s/Rafael Manzo <caio.csalgado@gmail.com>/Rafael Reggiani Manzo <rr.manzo@gmail.com>/
... ... @@ -214,6 +220,10 @@ s/Valéssio Brito &lt;contato@valessiobrito.com.br&gt;/Valessio Brito &lt;contato@valessi
214 220 s/Valessio Brito <contato@valessiobrito.info>/Valessio Brito <contato@valessiobrito.com.br>/
215 221 s/Valessio Brito <valessio@gmail.com>/Valessio Brito <contato@valessiobrito.com.br>/
216 222 /Visita <visita@debian.(none)>/d
  223 +
  224 +s/Vítor Barbosa/Vitor Barbosa/
  225 +s/vitormga15@gmail.com/vitornga15@gmail.com/
  226 +
217 227 s/vfcosta <vfcosta@gmail.com>/Victor Costa <vfcosta@gmail.com>/
218 228 s/Victor Carvalho <victorhugodf.ac@gmail.com>/Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com>/
219 229  
... ...
script/install-dependencies/debian-wheezy.sh
1   -binary_packages='deb http://download.noosfero.org/debian/wheezy-1.2 ./'
  1 +binary_packages='deb http://download.noosfero.org/debian/wheezy-1.3 ./'
2 2  
3 3 source_packages=$(echo "$binary_packages" | sed -e 's/^deb/deb-src/')
4 4  
... ...
test/functional/application_controller_test.rb
... ... @@ -188,6 +188,16 @@ class ApplicationControllerTest &lt; ActionController::TestCase
188 188 assert_tag :tag => 'option', :attributes => { :value => 'it' }, :content => 'Italiano'
189 189 end
190 190  
  191 + should 'set and unset the current user' do
  192 + testuser = create_user 'testuser'
  193 + login_as 'testuser'
  194 + User.expects(:current=).with do |user|
  195 + user == testuser
  196 + end.at_least_once
  197 + User.expects(:current=).with(nil).at_least_once
  198 + get :index
  199 + end
  200 +
191 201 should 'display link to webmail if enabled for system' do
192 202 @controller.stubs(:get_layout).returns('application')
193 203 login_as('ze')
... ...
test/functional/cms_controller_test.rb
... ... @@ -557,8 +557,17 @@ class CmsControllerTest &lt; ActionController::TestCase
557 557 end
558 558  
559 559 should 'keep informed parent_id' do
  560 + fast_create(:blog, :name=>"Sample blog", :profile_id=>@profile.id)
  561 +
  562 + profile.home_page = profile.blogs.find_by_name "Sample blog"
  563 + profile.save!
  564 +
560 565 get :new, :profile => @profile.identifier, :parent_id => profile.home_page.id, :type => 'TextileArticle'
561   - assert_tag :tag => 'input', :attributes => { :name => 'parent_id', :value => profile.home_page.id }
  566 + assert_tag :tag => 'select',
  567 + :attributes => { :id => 'article_parent_id' },
  568 + :child => {
  569 + :tag => "option", :attributes => {:value => profile.home_page.id, :selected => "selected"}
  570 + }
562 571 end
563 572  
564 573 should 'list folders before others' do
... ... @@ -1836,14 +1845,6 @@ class CmsControllerTest &lt; ActionController::TestCase
1836 1845 assert_equal 'first version', assigns(:article).name
1837 1846 end
1838 1847  
1839   - should 'clone article with its content' do
1840   - article = profile.articles.create(:name => 'first version')
1841   -
1842   - get :new, :profile => profile.identifier, :id => article.id, :clone => true, :type => 'TinyMceArticle'
1843   -
1844   - assert_match article.name, @response.body
1845   - end
1846   -
1847 1848 should 'save article with content from older version' do
1848 1849 article = profile.articles.create(:name => 'first version')
1849 1850 article.name = 'second version'; article.save
... ... @@ -1894,6 +1895,33 @@ class CmsControllerTest &lt; ActionController::TestCase
1894 1895 assert_equal '[{"label":"linux","value":"linux"}]', @response.body
1895 1896 end
1896 1897  
  1898 + should 'clone an article with its parent' do
  1899 + login_as(profile.identifier)
  1900 +
  1901 + f = Folder.new(:name => 'f')
  1902 + profile.articles << f
  1903 + f.save!
  1904 +
  1905 + post :new, :type => 'TinyMceArticle', :profile => profile.identifier, :parent_id => f.id,
  1906 + :article => { :name => 'Main Article', :body => 'some content' }
  1907 +
  1908 + main_article = profile.articles.find_by_name('Main Article')
  1909 + assert_not_nil main_article
  1910 +
  1911 + post :new, :type => 'TinyMceArticle', :profile => profile.identifier, :parent_id => f.id,
  1912 + :id => main_article.id, :clone => true
  1913 +
  1914 + cloned_main_article = profile.articles.find_by_name('Main Article')
  1915 + assert_not_nil cloned_main_article
  1916 +
  1917 + assert_equal main_article.parent_id, cloned_main_article.parent_id
  1918 +
  1919 + get :new, :profile => profile.identifier, :id => cloned_main_article.id,
  1920 + :clone => true, :type => 'TinyMceArticle'
  1921 +
  1922 + assert_match main_article.body, @response.body
  1923 + end
  1924 +
1897 1925 protected
1898 1926  
1899 1927 # FIXME this is to avoid adding an extra dependency for a proper JSON parser.
... ...
test/functional/content_viewer_controller_test.rb
... ... @@ -1584,4 +1584,33 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1584 1584 assert_tag :tag => 'div', :attributes => { :class => 'article-compact-image' }
1585 1585 assert_tag :tag => 'div', :attributes => { :class => 'article-compact-abstract-with-image' }
1586 1586 end
  1587 +
  1588 + should 'not count a visit twice for the same user' do
  1589 + profile = create_user('someone').person
  1590 + login_as(@profile.identifier)
  1591 + page = profile.articles.build(:name => 'myarticle', :body => 'the body of the text')
  1592 + page.save!
  1593 +
  1594 + get :view_page, :profile => profile.identifier, :page => 'myarticle'
  1595 + page.reload
  1596 + assert_equal 1, page.hits
  1597 +
  1598 + get :view_page, :profile => profile.identifier, :page => 'myarticle'
  1599 + page.reload
  1600 + assert_equal 1, page.hits
  1601 + end
  1602 +
  1603 + should 'not count a visit twice for unlogged users' do
  1604 + profile = create_user('someone').person
  1605 + page = profile.articles.build(:name => 'myarticle', :body => 'the body of the text')
  1606 + page.save!
  1607 +
  1608 + get :view_page, :profile => profile.identifier, :page => 'myarticle'
  1609 + page.reload
  1610 + assert_equal 1, page.hits
  1611 +
  1612 + get :view_page, :profile => profile.identifier, :page => 'myarticle'
  1613 + page.reload
  1614 + assert_equal 1, page.hits
  1615 + end
1587 1616 end
... ...
test/functional/profile_controller_test.rb
... ... @@ -52,7 +52,8 @@ class ProfileControllerTest &lt; ActionController::TestCase
52 52  
53 53 assert_response :success
54 54 assert_template 'members'
55   - assert assigns(:members)
  55 + assert assigns(:profile_members)
  56 + assert assigns(:profile_admins)
56 57 end
57 58  
58 59 should 'list favorite enterprises' do
... ... @@ -940,7 +941,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
940 941 @controller.stubs(:current_user).returns(user)
941 942 Person.any_instance.stubs(:follows?).returns(true)
942 943 get :index, :profile => p1.identifier
943   - assert_equal [s3,s2], assigns(:activities).map(&:activity)
  944 + assert_equal [s3,s2], assigns(:activities).map(&:activity).select {|a| a.kind_of?(Scrap)}
944 945 end
945 946  
946 947 should 'the activities be the received scraps in community profile' do
... ... @@ -1746,4 +1747,68 @@ class ProfileControllerTest &lt; ActionController::TestCase
1746 1747 assert_no_tag :tag => 'td', :descendant => { :tag => 'a', :content => /#{person.enterprises.count}/, :attributes => { :href => /profile\/#{person.identifier}\/enterprises$/ }}
1747 1748 end
1748 1749  
  1750 + should 'admins from a community be present in admin users div and members div' do
  1751 + community = fast_create(Community)
  1752 + another_user = create_user('another_user').person
  1753 +
  1754 + login_as(@profile.identifier)
  1755 +
  1756 + community.add_admin(@profile)
  1757 +
  1758 + assert community.admins.include? @profile
  1759 + get :members, :profile => community.identifier
  1760 +
  1761 + assert_tag :tag => 'ul', :attributes => { :class => /profile-list-admins/},
  1762 + :descendant => { :tag => 'a', :attributes => { :title => "testuser" } }
  1763 +
  1764 + assert_tag :tag => 'ul', :attributes => { :class => /profile-list-members/},
  1765 + :descendant => { :tag => 'a', :attributes => { :title => "testuser" } }
  1766 + end
  1767 +
  1768 + should 'all members, except admins, be present in members div' do
  1769 + community = fast_create(Community)
  1770 + community.add_member(@profile)
  1771 +
  1772 + another_user = create_user('another_user').person
  1773 + community.add_member(another_user)
  1774 +
  1775 + assert_equal false, community.admins.include?(another_user)
  1776 +
  1777 + get :members, :profile => community.identifier
  1778 +
  1779 + assert_tag :tag => 'ul', :attributes => { :class => /profile-list-members/},
  1780 + :descendant => { :tag => 'a', :attributes => { :title => "another_user" } }
  1781 +
  1782 + assert_no_tag :tag => 'ul', :attributes => { :class => /profile-list-admins/},
  1783 + :descendant => { :tag => 'a', :attributes => { :title => "another_user" } }
  1784 + end
  1785 +
  1786 + should 'members be sorted by name in ascendant order' do
  1787 + community = fast_create(Community)
  1788 + another_user = create_user('another_user').person
  1789 + different_user = create_user('different_user').person
  1790 +
  1791 + community.add_member(@profile)
  1792 + community.add_member(another_user)
  1793 + community.add_member(different_user)
  1794 +
  1795 + get :members, :profile => community.identifier, :sort => "asc"
  1796 +
  1797 + assert @response.body.index("another_user") < @response.body.index("different_user")
  1798 + end
  1799 +
  1800 + should 'members be sorted by name in descendant order' do
  1801 + community = fast_create(Community)
  1802 + another_user = create_user('another_user').person
  1803 + different_user = create_user('different_user').person
  1804 +
  1805 + community.add_member(@profile)
  1806 + community.add_member(another_user)
  1807 + community.add_member(different_user)
  1808 +
  1809 + get :members, :profile => community.identifier, :sort => "desc"
  1810 +
  1811 + assert @response.body.index("another_user") > @response.body.index("different_user")
  1812 + end
  1813 +
1749 1814 end
... ...
test/unit/clone_article_test.rb 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +require_relative "../test_helper"
  2 +
  3 +class CloneArticleTest < ActiveSupport::TestCase
  4 +
  5 + should 'cloned article have its source attributes' do
  6 + community = fast_create(Community)
  7 + folder = fast_create(Folder, :profile_id => community.id)
  8 + article = fast_create(TinyMceArticle, :profile_id => community.id)
  9 + article.parent_id = folder.id
  10 + article.save!
  11 +
  12 + article.reload
  13 + cloned_article = article.copy_without_save({:parent_id => article.parent_id})
  14 +
  15 + assert_equal folder.id, cloned_article.parent_id
  16 + assert_equal article.body , cloned_article.body
  17 + assert_equal article.name, cloned_article.name
  18 + assert_equal article.setting, cloned_article.setting
  19 + end
  20 +
  21 +end
0 22 \ No newline at end of file
... ...
test/unit/scrap_test.rb
... ... @@ -6,6 +6,7 @@ class ScrapTest &lt; ActiveSupport::TestCase
6 6 Person.destroy_all
7 7 Scrap.destroy_all
8 8 ActionTracker::Record.destroy_all
  9 + Delayed::Job.destroy_all
9 10 end
10 11  
11 12 should "have the content" do
... ...