diff --git a/app/controllers/public/browse_controller.rb b/app/controllers/public/browse_controller.rb
new file mode 100644
index 0000000..243b963
--- /dev/null
+++ b/app/controllers/public/browse_controller.rb
@@ -0,0 +1,58 @@
+class BrowseController < PublicController
+
+ no_design_blocks
+
+ FILTERS = %w(
+ more_recent
+ more_active
+ more_popular
+ )
+
+ def people
+ @filter = filter
+ @title = self.filter_description(params[:action] + '_' + @filter )
+
+ @results = @environment.people.send(@filter)
+
+ if params[:query].blank?
+ @results = @results.paginate(:per_page => 27, :page => params[:page])
+ else
+ @results = @results.find_by_contents(params[:query]).paginate(:per_page => 27, :page => params[:page])
+ end
+ end
+
+ def communities
+ @filter = filter
+ @title = self.filter_description(params[:action] + '_' + @filter )
+
+ @results = @environment.communities.send(@filter)
+
+ if params[:query].blank?
+ @results = @results.paginate(:per_page => 27, :page => params[:page])
+ else
+ @results = @results.find_by_contents(params[:query]).paginate(:per_page => 27, :page => params[:page])
+ end
+ end
+
+ protected
+
+ def filter
+ if FILTERS.include?(params[:filter])
+ params[:filter]
+ else
+ 'more_recent'
+ end
+ end
+
+ def filter_description(str)
+ {
+ 'people_more_recent' => _('People more recent'),
+ 'people_more_active' => _('People more active'),
+ 'people_more_popular' => _('People more popular'),
+ 'communities_more_recent' => _('Communities more recent'),
+ 'communities_more_active' => _('Communities more active'),
+ 'communities_more_popular' => _('Communities more popular'),
+ }[str] || str
+ end
+
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 178d598..c3d2749 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -479,9 +479,38 @@ module ApplicationHelper
:class => the_class
end
+ def links_for_balloon(profile)
+ if environment.enabled?(:show_balloon_with_profile_links_when_clicked)
+ if profile.kind_of?(Person)
+ [
+ {_('Home Page') => url_for(profile.url)},
+ {_('Profile') => url_for(profile.public_profile_url)},
+ {_('Friends') => url_for(:controller => :profile, :action => :friends, :profile => profile.identifier)},
+ {_('Communities') => url_for(:controller => :profile, :action => :communities, :profile => profile.identifier)}
+ ]
+ elsif profile.kind_of?(Community)
+ [
+ {_('Home Page') => url_for(profile.url)},
+ {_('Profile') => url_for(profile.public_profile_url)},
+ {_('Members') => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)},
+ {_('Agenda') => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)}
+ ]
+ elsif profile.kind_of?(Enterprise)
+ [
+ {_('Home Page') => url_for(profile.url)},
+ {_('Products') => catalog_path(profile.identifier)},
+ {_('Members') => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)},
+ {_('Agenda') => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)}
+ ]
+ else
+ []
+ end
+ end
+ end
+
# displays a link to the profile homepage with its image (as generated by
# #profile_image) and its name below it.
- def profile_image_link( profile, size=:portrait, tag='li' )
+ def profile_image_link( profile, size=:portrait, tag='li', extra_info = nil )
if profile.class == Person
name = profile.short_name
city = content_tag 'span', content_tag( 'span', profile.city, :class => 'locality' ), :class => 'adr'
@@ -489,11 +518,14 @@ module ApplicationHelper
name = profile.short_name
city = ''
end
+ extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' )
+ links = links_for_balloon(profile)
content_tag tag,
+ (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => 'menu-submenu-trigger' ) : "") +
link_to(
content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) +
content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) +
- city + profile_sex_icon( profile ) + profile_cat_icons( profile ),
+ city + extra_info + profile_sex_icon( profile ) + profile_cat_icons( profile ),
profile.url,
:onclick => 'document.location.href = this.href', # work-arround for ie.
:class => 'profile_link url',
@@ -1019,4 +1051,34 @@ module ApplicationHelper
") : '')
end
+ def browse_people_menu
+ links = [
+ {_('More Recent') => url_for({:controller => 'browse', :action => 'people', :filter => 'more_recent'})},
+ {_('More Active') => url_for({:controller => 'browse', :action => 'people', :filter => 'more_active'})},
+ {_('More Popular') => url_for({:controller => 'browse', :action => 'people', :filter => 'more_popular'})}
+ ]
+ if logged_in?
+ links.push(_('My friends') => url_for({:profile => current_user.login, :controller => 'friends'}))
+ links.push(_('Invite friends') => url_for({:profile => current_user.login, :controller => 'invite', :action => 'friends'}))
+ end
+
+ link_to(content_tag(:span, _('People'), :class => 'icon-menu-people'), {:controller => "browse", :action => 'people'}, :id => 'submenu-people') +
+ link_to(content_tag(:span, _('People Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json})", :class => 'menu-submenu-trigger up', :id => 'submenu-people-trigger')
+ end
+
+ def browse_communities_menu
+ links = [
+ {_('More Recent') => url_for({:controller => 'browse', :action => 'communities', :filter => 'more_recent'})},
+ {_('More Active') => url_for({:controller => 'browse', :action => 'communities', :filter => 'more_active'})},
+ {_('More Popular') => url_for({:controller => 'browse', :action => 'communities', :filter => 'more_popular'})}
+ ]
+ if logged_in?
+ links.push(_('My communities') => url_for({:profile => current_user.login, :controller => 'memberships'}))
+ links.push(_('New community') => url_for({:profile => current_user.login, :controller => 'memberships', :action => 'new_community'}))
+ end
+
+ link_to(content_tag(:span, _('Communities'), :class => 'icon-menu-community'), {:controller => "browse", :action => 'communities'}, :id => 'submenu-communities') +
+ link_to(content_tag(:span, _('Communities Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json})", :class => 'menu-submenu-trigger up', :id => 'submenu-communities-trigger')
+ end
+
end
diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb
index 1d01020..60dcef7 100644
--- a/app/models/enterprise.rb
+++ b/app/models/enterprise.rb
@@ -4,7 +4,7 @@ class Enterprise < Organization
N_('Enterprise')
- has_many :products, :dependent => :destroy
+ has_many :products, :dependent => :destroy, :order => 'name ASC'
extra_data_for_index :product_categories
diff --git a/app/models/environment.rb b/app/models/environment.rb
index f3e7470..27ef603 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -108,6 +108,7 @@ class Environment < ActiveRecord::Base
'enable_organization_url_change' => _("Allow organizations to change their URL"),
'admin_must_approve_new_communities' => _("Admin must approve creation of communities"),
'enterprises_are_disabled_when_created' => __('Enterprises are disabled when created'),
+ 'show_balloon_with_profile_links_when_clicked' => _('Show a balloon with profile links when a profile image is clicked'),
}
end
diff --git a/app/models/person.rb b/app/models/person.rb
index 6393f19..b6b487d 100644
--- a/app/models/person.rb
+++ b/app/models/person.rb
@@ -8,6 +8,12 @@ class Person < Profile
has_many :requested_tasks, :class_name => 'Task', :foreign_key => :requestor_id, :dependent => :destroy
+ named_scope :more_popular,
+ :select => "#{Profile.qualified_column_names}, count(friend_id) as total",
+ :group => Profile.qualified_column_names,
+ :joins => :friendships,
+ :order => "total DESC"
+
after_destroy do |person|
Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy }
end
@@ -286,4 +292,13 @@ class Person < Profile
def relationships_cache_key
cache_key + '-profile-relationships'
end
+
+ def more_popular_label
+ amount = self.friends.count
+ {
+ 0 => _('none'),
+ 1 => _('one friend')
+ }[amount] || _("%s friends") % amount
+ end
+
end
diff --git a/app/models/profile.rb b/app/models/profile.rb
index b7b39b7..dca5508 100644
--- a/app/models/profile.rb
+++ b/app/models/profile.rb
@@ -57,7 +57,23 @@ class Profile < ActiveRecord::Base
acts_as_taggable
+ def self.qualified_column_names
+ Profile.column_names.map{|n| [Profile.table_name, n].join('.')}.join(',')
+ end
+
named_scope :visible, :conditions => { :visible => true }
+ named_scope :more_recent, :order => "created_at DESC"
+ named_scope :more_popular,
+ :select => "#{Profile.qualified_column_names}, count(resource_id) as total",
+ :group => Profile.qualified_column_names,
+ :joins => :role_assignments,
+ :order => "total DESC"
+ named_scope :more_active,
+ :select => "#{Profile.qualified_column_names}, count(articles.id) as total, sum(articles.comments_count) as total_comments",
+ :joins => :articles,
+ :group => Profile.qualified_column_names,
+ :order => "total DESC, total_comments DESC",
+ :conditions => ["articles.created_at BETWEEN ? AND ?", 7.days.ago, DateTime.now]
# FIXME ugly workaround
def self.human_attribute_name(attrib)
@@ -675,6 +691,26 @@ private :generate_url, :url_options
cache_key + '-members-page-' + page
end
+ def more_recent_label
+ _("Since: ")
+ end
+
+ def more_active_label
+ amount = self.articles.count
+ {
+ 0 => _('none'),
+ 1 => _('one article')
+ }[amount] || _("%s articles") % amount
+ end
+
+ def more_popular_label
+ amount = self.members.count
+ {
+ 0 => _('none'),
+ 1 => _('one member')
+ }[amount] || _("%s members") % amount
+ end
+
protected
def display_private_info_to?(user)
@@ -684,4 +720,5 @@ private :generate_url, :url_options
(user == self) || (user.is_admin?(self.environment)) || user.is_admin?(self) || user.memberships.include?(self)
end
end
+
end
diff --git a/app/views/browse/_display_results.rhtml b/app/views/browse/_display_results.rhtml
new file mode 100644
index 0000000..8185bb6
--- /dev/null
+++ b/app/views/browse/_display_results.rhtml
@@ -0,0 +1,19 @@
+
+
+
+ <% if @results.empty? %>
+
+ <% end %>
+
+ <% @results.each do |result| %>
+ <%= render :partial => partial_for_class(result.class), :locals => {:profile => result} %>
+ <% end %>
+
+
+
+
+
+
+
diff --git a/app/views/browse/_profile.rhtml b/app/views/browse/_profile.rhtml
new file mode 100644
index 0000000..10da93c
--- /dev/null
+++ b/app/views/browse/_profile.rhtml
@@ -0,0 +1 @@
+<%= profile_image_link profile, :portrait, 'li', @filter == 'more_recent' ? profile.send(@filter + '_label') + show_date(profile.created_at) : profile.send(@filter + '_label') %>
diff --git a/app/views/browse/_search_form.rhtml b/app/views/browse/_search_form.rhtml
new file mode 100644
index 0000000..841f1ff
--- /dev/null
+++ b/app/views/browse/_search_form.rhtml
@@ -0,0 +1,10 @@
+<% form_tag( { :controller => 'browse', :action => action}, :method => 'get', :class => 'search_form' ) do %>
+
+
+
+ <%= text_field_tag 'query', @query, :size => 50 %>
+
+ <%= submit_button(:search, _('Search')) %>
+
+
+<% end %>
diff --git a/app/views/browse/communities.rhtml b/app/views/browse/communities.rhtml
new file mode 100644
index 0000000..411774d
--- /dev/null
+++ b/app/views/browse/communities.rhtml
@@ -0,0 +1,9 @@
+<%= search_page_title( @title, { :query => @query} ) %>
+
+<%= render :partial => 'search_form', :locals => {:action => 'communities'} %>
+
+<%= render :partial => 'display_results' %>
+
+<%= will_paginate @results %>
+
+
diff --git a/app/views/browse/people.rhtml b/app/views/browse/people.rhtml
new file mode 100644
index 0000000..8610c0d
--- /dev/null
+++ b/app/views/browse/people.rhtml
@@ -0,0 +1,9 @@
+<%= search_page_title( @title, { :query => @query} ) %>
+
+<%= render :partial => 'search_form', :locals => {:action => 'people'} %>
+
+<%= render :partial => 'display_results' %>
+
+<%= will_paginate @results %>
+
+
diff --git a/config/routes.rb b/config/routes.rb
index 52f404f..dc62086 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -51,6 +51,10 @@ ActionController::Routing::Routes.draw do |map|
# search
map.connect 'search/:action/*category_path', :controller => 'search'
+ # Browse
+ map.connect 'browse/:action/:filter', :controller => 'browse'
+ map.connect 'browse/:action', :controller => 'browse'
+
# events
map.events 'profile/:profile/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format}/
map.events 'profile/:profile/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format}/
diff --git a/features/balloon.feature b/features/balloon.feature
new file mode 100644
index 0000000..35f2158
--- /dev/null
+++ b/features/balloon.feature
@@ -0,0 +1,62 @@
+Feature: balloon
+ I want to view a balloon when mouse clicks on profile trigger
+
+ Background:
+ Given I am on the homepage
+ Given the following users
+ | login | name |
+ | joaosilva | Joao Silva |
+ And the following communities
+ | identifier | name |
+ | sample | Sample |
+
+ @selenium
+ Scenario: I should not see trigger if not enabled
+ Given the following blocks
+ | owner | type |
+ | environment | PeopleBlock |
+ And feature "show_balloon_with_profile_links_when_clicked" is disabled on environment
+ And I go to the homepage
+ Then I should not see "Friends"
+
+ @selenium
+ Scenario: I should not see trigger by default
+ Given the following blocks
+ | owner | type |
+ | environment | PeopleBlock |
+ And feature "show_balloon_with_profile_links_when_clicked" is enabled on environment
+ And I go to the homepage
+ Then I should not see "Friends"
+
+ @selenium
+ Scenario: I should see balloon when clicked on block trigger
+ Given the following blocks
+ | owner | type |
+ | environment | PeopleBlock |
+ And feature "show_balloon_with_profile_links_when_clicked" is enabled on environment
+ And I go to the homepage
+ When I click ".menu-submenu-trigger"
+ Then I should see "Profile"
+ And I should see "Friends"
+ And I should see "Home Page"
+
+ @selenium
+ Scenario: I should not see trigger if not enabled on page
+ Given feature "show_balloon_with_profile_links_when_clicked" is disabled on environment
+ And I go to /assets/communities
+ Then I should not see "Members"
+
+ @selenium
+ Scenario: I should not see trigger by default on page
+ Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment
+ And I go to /assets/communities
+ Then I should not see "Members"
+
+ @selenium
+ Scenario: I should see balloon when clicked on page trigger
+ Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment
+ And I go to /assets/communities
+ When I click ".menu-submenu-trigger"
+ Then I should see "Members"
+ And I should see "Agenda"
+ And I should see "Home Page"
diff --git a/features/browse.feature b/features/browse.feature
new file mode 100644
index 0000000..672f324
--- /dev/null
+++ b/features/browse.feature
@@ -0,0 +1,89 @@
+Feature: browse
+ As a noosfero visitor
+ I want to browse people and communities
+
+ Background:
+ Given I am on the homepage
+ And the following users
+ | login | name |
+ | joaosilva | Joao Silva |
+ | pedrosilva | Pedro Silva |
+ | pauloneto | Paulo Neto |
+ And the following communities
+ | identifier | name |
+ | comunity-silva | Community Silva |
+ | comunity-neto | Community Neto |
+
+ @selenium
+ Scenario: Show people browse menu
+ Given I should not see "More Recent"
+ And I should not see "More Active"
+ And I should not see "More Popular"
+ When I click "#submenu-people-trigger"
+ Then I should see "More Recent"
+ And I should see "More Active"
+ And I should see "More Popular"
+
+ @selenium
+ Scenario: People browse menu should add logged information
+ Given I am logged in as "joaosilva"
+ And I should not see "More Recent"
+ And I should not see "More Active"
+ And I should not see "More Popular"
+ And I should not see "Invite friends"
+ And I should not see "My friends"
+ When I click "#submenu-people-trigger"
+ Then I should see "More Recent"
+ And I should see "More Active"
+ And I should see "More Popular"
+ And I should see "Invite friends"
+ And I should see "My friends"
+
+ @selenium
+ Scenario: Browse people by query
+ Given I go to /browse/people
+ When I fill in "query" with "Silva"
+ And I press "Search"
+ Then I should see "Joao Silva"
+ And I should see "Pedro Silva"
+ And I should not see "Paulo Neto"
+ And I should not see "Community Silva"
+ And I should not see "Community Neto"
+
+ @selenium
+ Scenario: Communities browse menu should add logged information
+ Given I am logged in as "joaosilva"
+ And I am on the homepage
+ And I should not see "More Recent"
+ And I should not see "More Active"
+ And I should not see "More Popular"
+ And I should not see "My communities"
+ And I should not see "New community"
+ When I click "#submenu-communities-trigger"
+ Then I should see "More Recent"
+ And I should see "More Active"
+ And I should see "More Popular"
+ And I should see "My communities"
+ And I should see "New community"
+
+ @selenium
+ Scenario: Show communities browse menu
+ Given I should not see "More Recent"
+ And I should not see "More Active"
+ And I should not see "More Popular"
+ When I click "#submenu-communities-trigger"
+ Then I should see "More Recent"
+ And I should see "More Active"
+ And I should see "More Popular"
+
+ @selenium
+ Scenario: Browse communities by query
+ Given I go to /browse/communities
+ When I fill in "query" with "Silva"
+ And I press "Search"
+ Then I should see "Community Silva"
+ And I should not see "Joao Silva"
+ And I should not see "Pedro Silva"
+ And I should not see "Paulo Neto"
+ And I should not see "Community Neto"
+
diff --git a/features/manage_products.feature b/features/manage_products.feature
index e99173b..a0b61a4 100644
--- a/features/manage_products.feature
+++ b/features/manage_products.feature
@@ -17,31 +17,31 @@ Feature: manage products
| Bicycle |
And the following products
| owner | category | name | description |
- | redemoinho | bicycle | Bike 1 | bicycle 1 |
- | redemoinho | bicycle | Bike 2 | bicycle 2 |
- | redemoinho | bicycle | Bike 3 | bicycle 3 |
- | redemoinho | bicycle | Bike 4 | bicycle 4 |
- | redemoinho | bicycle | Bike 5 | bicycle 5 |
- | redemoinho | bicycle | Bike 6 | bicycle 6 |
- | redemoinho | bicycle | Bike 7 | bicycle 7 |
- | redemoinho | bicycle | Bike 8 | bicycle 8 |
- | redemoinho | bicycle | Bike 9 | bicycle 9 |
- | redemoinho | bicycle | Bike 10| bicycle 10 |
- | redemoinho | bicycle | Bike 11| bicycle 11 |
+ | redemoinho | bicycle | Bike A | bicycle 1 |
+ | redemoinho | bicycle | Bike B | bicycle 2 |
+ | redemoinho | bicycle | Bike C | bicycle 3 |
+ | redemoinho | bicycle | Bike D | bicycle 4 |
+ | redemoinho | bicycle | Bike E | bicycle 5 |
+ | redemoinho | bicycle | Bike F | bicycle 6 |
+ | redemoinho | bicycle | Bike G | bicycle 7 |
+ | redemoinho | bicycle | Bike H | bicycle 8 |
+ | redemoinho | bicycle | Bike I | bicycle 9 |
+ | redemoinho | bicycle | Bike J | bicycle 10 |
+ | redemoinho | bicycle | Bike K | bicycle 11 |
When I go to /catalog/redemoinho
- Then I should see "Bike 1"
- And I should see "Bike 2"
- And I should see "Bike 3"
- And I should see "Bike 4"
- And I should see "Bike 5"
- And I should see "Bike 6"
- And I should see "Bike 7"
- And I should see "Bike 8"
- And I should see "Bike 9"
- And I should see "Bike 10"
- And I should not see "Bike 11"
+ Then I should see "Bike A" within "#product_list"
+ And I should see "Bike B" within "#product_list"
+ And I should see "Bike C" within "#product_list"
+ And I should see "Bike D" within "#product_list"
+ And I should see "Bike E" within "#product_list"
+ And I should see "Bike F" within "#product_list"
+ And I should see "Bike G" within "#product_list"
+ And I should see "Bike H" within "#product_list"
+ And I should see "Bike I" within "#product_list"
+ And I should see "Bike J" within "#product_list"
+ And I should not see "Bike K" within "#product_list"
When I follow "Next"
- Then I should see "Bike 11"
+ Then I should see "Bike K" within "#product_list"
Scenario: listing products and services
Given I am logged in as "joaosilva"
diff --git a/public/designs/themes/base/navigation.rhtml b/public/designs/themes/base/navigation.rhtml
index 5946359..1dd46c6 100644
--- a/public/designs/themes/base/navigation.rhtml
+++ b/public/designs/themes/base/navigation.rhtml
@@ -1,5 +1,7 @@
-
-
-
-
+
+ <%= browse_people_menu %>
+
+
+ <%= browse_communities_menu %>
+
diff --git a/public/designs/themes/base/style.css b/public/designs/themes/base/style.css
index 83da3c3..589e689 100644
--- a/public/designs/themes/base/style.css
+++ b/public/designs/themes/base/style.css
@@ -201,18 +201,20 @@ body, th, td, input {
margin: 0px;
padding: 0px 10px 0px 0px;
float: right;
- overflow: hidden;
}
#navigation li {
list-style: none;
display: block;
- height: 54px;
+ height: auto;
+ width: 125px;
float: left;
- border-left: 1px solid #888a85;
+ text-align: center;
+ position: relative;
}
#navigation a {
+ border-left: 1px solid #888a85;
display: block;
font-size: 15px;
line-height: 42px;
@@ -225,11 +227,71 @@ body, th, td, input {
}
#navigation span {
- padding: 0px 10px 0px 35px;
- background-position: 15px 50%;
+ padding: 0px 0px 0px 30px;
+ background-position: 5px 50%;
background-repeat: no-repeat;
}
+#navigation .menu-submenu ul, #navigation .menu-submenu li{
+ float: none;
+ text-align: right;
+ border-left: 0px;
+}
+
+#navigation .menu-submenu ul{
+ border: 1px solid #888a85;
+ border-top: 0px;
+ border-left: 0px;
+ background-color: #ccc;
+ padding-right: 2px;
+ height: auto;
+ display: block;
+}
+
+#navigation .menu-submenu{
+ bottom: -75px;
+ width: 126px;
+ top: 0px;
+ right: 0px;
+ position: relative;
+}
+
+#navigation .menu-submenu a{
+ padding: 4px 5px;
+ font-size: 12px;
+ line-height: normal;
+}
+
+#navigation .menu-submenu-trigger {
+ background: #eee url(/images/down-arrow.png) center center no-repeat;
+ border: 0px;
+ height: 8px;
+ width: 124px;
+}
+#navigation li:hover .menu-submenu-trigger:hover {
+ background: #eee url(/images/down-arrow.png) center center no-repeat;
+}
+
+#navigation li:hover .menu-submenu-trigger{
+ display: block;
+}
+
+#navigation li .menu-submenu-trigger{
+ display: none;
+}
+
+#navigation .menu-submenu-header, #navigation .menu-submenu-footer, #navigation .menu-submenu h4{
+ display: none;
+}
+
+#navigation .common-profile-list-block .vcard .menu-submenu-trigger,
+.menu-submenu-trigger {
+ left: 1px;
+ top: 33px;
+ -moz-border-radius: 0px;
+ -webkit-border-radius: 0px;
+}
+
/***************************** boxes ********************************/
.template-default .box-1 { /* Center */
@@ -1119,12 +1181,12 @@ hr.pre-posts, hr.sep-posts {
/******** controller-friends action-friends-index ********/
.action-friends-index .profile-list li,
-.common-profile-list-block .vcard a {
+.common-profile-list-block .vcard {
border: 1px solid transparent;
}
.action-friends-index .profile-list li:hover,
-.common-profile-list-block .vcard a:hover {
+.common-profile-list-block .vcard:hover {
border: 1px solid #CCC;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
@@ -1132,6 +1194,11 @@ hr.pre-posts, hr.sep-posts {
text-decoration: none;
}
+.common-profile-list-block .vcard a,
+.common-profile-list-block .vcard a:hover {
+ background: transparent;
+ border: 0;
+}
/******** controller-profile action-profile-index ********/
@@ -1205,4 +1272,56 @@ table.profile th {
border-bottom: 2px solid black;
}
+/**************************** Browse *******************************/
+.controller-browse #content .search_form {
+ background: #DDD;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ padding: 12px 15px 13px 15px;
+ position: relative;
+ text-align: left;
+}
+
+.controller-browse a {
+ color: #555753;
+}
+
+.browse-results-innerbox {
+ margin-top: 10px;
+ border-bottom: none;
+ border: 1px solid #CCC;
+ background: url(imgs/comment-bg-S.png) 0% 100% repeat-x;
+ padding-bottom: 10px;
+
+}
+.browse-results-innerbox ul{
+ padding: 0px;
+}
+
+.browse-results-innerbox .browse-results-type-empty div {
+ text-align: center;
+ color: #DDD;
+ font-weight: bold;
+ font-size: 30px;
+ padding: 70px 10px 0px 0px;
+ border: none;
+
+}
+
+.search-results-type-article.search-results-innerbox {
+ padding: 5px 0px 5px 10px;
+ max-height: 215px;
+ height: 225px;
+}
+
+#content .search-results-type-article li {
+ padding: 5px 0px;
+}
+
+.search-results-type-article a {
+ text-decoration: none;
+}
+.search-results-type-article a:hover {
+ text-decoration: underline;
+}
diff --git a/public/images/balloon-footer.png b/public/images/balloon-footer.png
new file mode 100644
index 0000000..3c1a606
Binary files /dev/null and b/public/images/balloon-footer.png differ
diff --git a/public/images/balloon-header.png b/public/images/balloon-header.png
new file mode 100644
index 0000000..054e5d3
Binary files /dev/null and b/public/images/balloon-header.png differ
diff --git a/public/images/balloon-middle.png b/public/images/balloon-middle.png
new file mode 100644
index 0000000..83cee0e
Binary files /dev/null and b/public/images/balloon-middle.png differ
diff --git a/public/images/down-arrow.png b/public/images/down-arrow.png
new file mode 100644
index 0000000..9e6b5dc
Binary files /dev/null and b/public/images/down-arrow.png differ
diff --git a/public/images/top-arrow.png b/public/images/top-arrow.png
new file mode 100644
index 0000000..9b2b158
Binary files /dev/null and b/public/images/top-arrow.png differ
diff --git a/public/javascripts/application.js b/public/javascripts/application.js
index afb769c..3c5b4a2 100644
--- a/public/javascripts/application.js
+++ b/public/javascripts/application.js
@@ -214,3 +214,52 @@ function expandCategory(block, id) {
}
}
}
+
+function toggleSubmenu(trigger, title, link_list) {
+ trigger.onclick = function() {
+ var submenu = jQuery(trigger).siblings('.menu-submenu');
+ var hide = false;
+ if (submenu.length > 0 && submenu.is(':visible')) hide = true;
+ hideAllSubmenus();
+ // Hide or show this submenu if it already exists
+ if (submenu.length > 0) {
+ if (!hide) {
+ var direction = 'down';
+ if (submenu.hasClass('up')) direction = 'up';
+ submenu.show('slide', { 'direction' : direction }, 'slow');
+ }
+ }
+ return false;
+ }
+
+ hideAllSubmenus();
+ // Build and show this submenu if it doesn't exist yet
+ var direction = 'down';
+ if (jQuery(trigger).hasClass('up')) direction = 'up';
+ var submenu = jQuery('').attr('class', 'menu-submenu ' + direction).attr('style', 'display: none');
+ var header = jQuery('').attr('class', 'menu-submenu-header');
+ var content = jQuery('').attr('class', 'menu-submenu-content');
+ var list = jQuery('').attr('class', 'menu-submenu-list');
+ var footer = jQuery('').attr('class', 'menu-submenu-footer');
+ content.append('' + title + '
');
+ jQuery.each(link_list, function(index, link_hash) {
+ for (label in link_hash) {
+ list.append('' + label + '');
+ }
+ });
+ content.append(list);
+ submenu.append(header).append(content).append(footer);
+ jQuery(trigger).before(submenu);
+ submenu.show('slide', { 'direction' : direction }, 'slow');
+}
+
+function hideAllSubmenus() {
+ jQuery('.menu-submenu.up:visible').hide('slide', { 'direction' : 'up' }, 'slow');
+ jQuery('.menu-submenu.down:visible').hide('slide', { 'direction' : 'down' }, 'slow');
+}
+
+// Hide visible ballons when clicked outside them
+jQuery(document).ready(function() {
+ jQuery('body').click(function() { hideAllSubmenus(); });
+ jQuery('.menu-submenu-trigger').click(function(e) { e.stopPropagation(); });
+});
diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css
index 6f128e8..fc2db10 100644
--- a/public/stylesheets/application.css
+++ b/public/stylesheets/application.css
@@ -1644,13 +1644,13 @@ input.disabled {
margin: 0px;
padding: 0px;
list-style: none;
- display: inline;
+ position: relative;
}
.common-profile-list-block .vcard a {
display: block;
- height: 95px;
- max-height: 92px;
+ height: 112px;
+ max-height: 112px;
padding-top: 3px;
margin: 0px 2px;
float: left;
@@ -1738,6 +1738,12 @@ input.disabled {
display: none;
}
+.common-profile-list-block .extra_info {
+ font-size: 9px;
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+}
+
/* ==> blocks/recent-documents-block.css <<= */
@@ -3603,7 +3609,6 @@ h1#agenda-title {
border: 1px solid #2A5896;
padding: 10px 0px 10px 10px;
height: 205px;
- overflow: auto;
position: relative; /* work-arround-bug fo MSIE */
}
@@ -3630,6 +3635,7 @@ h1#agenda-title {
.controller-search .only-one-result-box .search-results-innerbox,
.controller-search .only-one-result-box .search-results-innerbox.common-profile-list-block {
height: auto;
+ float: left;
padding: 10px 4px 10px 10px;
}
@@ -4088,3 +4094,100 @@ h1#agenda-title {
.categories-block .ui-icon {
margin-top: 2px;
}
+
+/* Profile balloon */
+
+.common-profile-list-block .vcard {
+ position: relative !important;
+ float: left;
+}
+
+.common-profile-list-block .vcard .menu-submenu-trigger,
+.menu-submenu-trigger {
+ display: none;
+ width: 16px;
+ height: 16px;
+ position: absolute;
+ top: -1px;
+ left: -3px;
+ overflow: hidden;
+ background: #efefef url(/images/top-arrow.png) center center no-repeat;
+ border: 1px solid #ccc;
+ z-index: 2;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+}
+
+.common-profile-list-block .vcard .menu-submenu-trigger:hover,
+.menu-submenu-trigger:hover {
+ background: #fff url(/images/top-arrow.png) center center no-repeat;
+ border: 1px solid #ccc;
+}
+
+.menu-submenu-trigger span {
+ display: none;
+}
+
+.common-profile-list-block .vcard:hover .menu-submenu-trigger {
+ display: block;
+}
+
+.menu-submenu {
+ position: absolute;
+ bottom: 115px;
+ right: -27px;
+ z-index: 11;
+ width: 150px;
+ padding: 0;
+ text-align: left;
+}
+
+.menu-submenu-footer {
+ background: transparent url(/images/balloon-footer.png) center center no-repeat;
+ height: 29px;
+ margin: 0;
+}
+
+.menu-submenu-header {
+ background: transparent url(/images/balloon-header.png) center center no-repeat;
+ height: 17px;
+ margin: 0;
+}
+
+.menu-submenu-content {
+ background: transparent url(/images/balloon-middle.png) top left repeat-y;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+}
+
+#content .menu-submenu-content ul {
+ margin: 0;
+ padding: 0;
+ width: 100% !important;
+ min-width: 100% !important;
+}
+
+#content .menu-submenu-content ul a {
+ text-align: left;
+ padding-left: 12px;
+}
+
+.common-profile-list-block .vcard .menu-submenu a {
+ float: none;
+ display: block;
+ height: auto;
+ font-size: 12px;
+}
+
+#content .menu-submenu h4 {
+ margin: 0;
+ font-size: 12px;
+ font-weight: bold;
+ text-align: left;
+ margin: 0 auto;
+ padding-bottom: 3px;
+ margin-bottom: 3px;
+ border-bottom: 1px solid #000;
+ width: 90%;
+}
diff --git a/test/functional/browse_controller_test.rb b/test/functional/browse_controller_test.rb
new file mode 100644
index 0000000..969faec
--- /dev/null
+++ b/test/functional/browse_controller_test.rb
@@ -0,0 +1,221 @@
+require File.dirname(__FILE__) + '/../test_helper'
+require 'browse_controller'
+
+# Re-raise errors caught by the controller.
+class BrowseController; def rescue_action(e) raise e end; end
+
+class BrowseControllerTest < Test::Unit::TestCase
+
+ def setup
+ @controller = BrowseController.new
+ @request = ActionController::TestRequest.new
+ @request.stubs(:ssl?).returns(false)
+ @response = ActionController::TestResponse.new
+
+ # By pass user validation on person creation
+ user = mock()
+ user.stubs(:id).returns(1)
+ user.stubs(:valid?).returns(true)
+ user.stubs(:email).returns('some@test.com')
+ user.stubs(:save!).returns(true)
+ Person.any_instance.stubs(:user).returns(user)
+ end
+
+ should 'search for people' do
+ Person.delete_all
+ small = create(Person, :name => 'A small person for testing', :user_id => 1)
+ create(Person, :name => 'A big person for testing', :user_id => 2)
+
+ get :people, :query => 'small'
+ assert_equal [small], assigns(:results)
+ end
+
+ should 'list all people order by more recent one by default' do
+ Person.delete_all
+ p1 = create(Person, :name => 'Testing person 1', :user_id => 1, :created_at => DateTime.now - 2)
+ p2 = create(Person, :name => 'Testing person 2', :user_id => 2, :created_at => DateTime.now - 1)
+ p3 = create(Person, :name => 'Testing person 3', :user_id => 3)
+
+ get :people
+ assert_equal [p3,p2,p1] , assigns(:results)
+ end
+
+ should 'paginate search of people in groups of 27' do
+ Person.delete_all
+
+ 1.upto(30).map do |n|
+ create(Person, :name => 'Testing person', :user_id => n)
+ end
+
+ get :people
+ assert_equal 30 , Person.count
+ assert_equal 27 , assigns(:results).count
+ assert_tag :a, '', :attributes => {:class => 'next_page'}
+ end
+
+ should 'paginate ferret search of people in groups of 27' do
+ Person.delete_all
+
+ 1.upto(30).map do |n|
+ create(Person, :name => 'Testing person', :user_id => n)
+ end
+
+ get :people, :query => 'Testing'
+ assert_equal 27 , assigns(:results).count
+ assert_tag :a, '', :attributes => {:class => 'next_page'}
+ end
+
+ should 'list all people filter by more active' do
+ Person.delete_all
+ p1 = create(Person, :name => 'Testing person 1', :user_id => 1)
+ p2 = create(Person, :name => 'Testing person 2', :user_id => 2)
+ p3 = create(Person, :name => 'Testing person 3', :user_id => 3)
+ Article.delete_all
+ fast_create(Article, :profile_id => p1, :created_at => 1.day.ago)
+ fast_create(Article, :profile_id => p2, :created_at => DateTime.now.beginning_of_day)
+ get :people, :filter => 'more_active'
+ assert_equal [p1,p2] , assigns(:results)
+ end
+
+ should 'filter more popular people' do
+ Person.delete_all
+ p1 = create(Person, :name => 'Testing person 1', :user_id => 1)
+ p2 = create(Person, :name => 'Testing person 2', :user_id => 2)
+ p3 = create(Person, :name => 'Testing person 3', :user_id => 3)
+
+ p1.add_friend(p2)
+ p2.add_friend(p1)
+ p2.add_friend(p3)
+ get :people, :filter => 'more_popular'
+ assert_equal [p2,p1] , assigns(:results)
+ end
+
+ should 'the people filter be only the hardcoded one' do
+ get :people, :filter => 'more_recent'
+ assert_equal 'more_recent' , assigns(:filter)
+
+ get :people, :filter => 'more_active'
+ assert_equal 'more_active' , assigns(:filter)
+
+ get :people, :filter => 'more_popular'
+ assert_equal 'more_popular' , assigns(:filter)
+
+ get :people, :filter => 'more_anything'
+ assert_equal 'more_recent' , assigns(:filter)
+ end
+
+ should 'the people filter define the title' do
+ get :people, :filter => 'more_recent'
+ assert_equal 'People more recent' , assigns(:title)
+ assert_tag :h1, :content => 'People more recent'
+
+ get :people, :filter => 'more_active'
+ assert_equal 'People more active' , assigns(:title)
+ assert_tag :h1, :content => 'People more active'
+
+ get :people, :filter => 'more_popular'
+ assert_equal 'People more popular' , assigns(:title)
+ assert_tag :h1, :content => 'People more popular'
+
+ get :people, :filter => 'more_anything'
+ assert_equal 'People more recent' , assigns(:title)
+ assert_tag :h1, :content => 'People more recent'
+ end
+
+ should 'search for community' do
+ small = create(Community, :name => 'A small community for testing')
+ create(Community, :name => 'A big community for testing')
+
+ get :communities, :query => 'small'
+ assert_equal [small], assigns(:results)
+ end
+
+ should 'list all community order by more recent one by default' do
+ c1 = create(Community, :name => 'Testing community 1', :created_at => DateTime.now - 2)
+ c2 = create(Community, :name => 'Testing community 2', :created_at => DateTime.now - 1)
+ c3 = create(Community, :name => 'Testing community 3')
+
+ get :communities
+ assert_equal [c3,c2,c1] , assigns(:results)
+ end
+
+ should 'paginate search of communities in groups of 27' do
+ 1.upto(30).map do |n|
+ create(Community, :name => 'Testing community')
+ end
+
+ get :communities
+ assert_equal 30 , Community.count
+ assert_equal 27 , assigns(:results).count
+ assert_tag :a, '', :attributes => {:class => 'next_page'}
+ end
+
+ should 'paginate ferret search of communities in groups of 27' do
+ 1.upto(30).map do |n|
+ create(Community, :name => 'Testing community')
+ end
+
+ get :communities, :query => 'Testing'
+ assert_equal 27 , assigns(:results).count
+ assert_tag :a, '', :attributes => {:class => 'next_page'}
+ end
+
+ should 'list all communities filter by more active' do
+ c1 = create(Community, :name => 'Testing community 1')
+ c2 = create(Community, :name => 'Testing community 2')
+ c3 = create(Community, :name => 'Testing community 3')
+ Article.delete_all
+ fast_create(Article, :profile_id => c1, :created_at => 1.day.ago)
+ fast_create(Article, :profile_id => c2, :created_at => DateTime.now.beginning_of_day)
+ get :communities, :filter => 'more_active'
+ assert_equal [c1,c2] , assigns(:results)
+ end
+
+ should 'filter more popular communities' do
+ Person.delete_all
+ c1 = create(Community, :name => 'Testing community 1')
+ c2 = create(Community, :name => 'Testing community 2')
+ create(Community, :name => 'Testing community 3')
+
+ p1 = create(Person, :name => 'Testing person 1', :user_id => 1)
+ p2 = create(Person, :name => 'Testing person 2', :user_id => 2)
+ c1.add_member(p1)
+ c2.add_member(p1)
+ c2.add_member(p2)
+ get :communities, :filter => 'more_popular'
+ assert_equal [c2,c1] , assigns(:results)
+ end
+
+ should 'the communities filter be only the hardcoded one' do
+ get :communities, :filter => 'more_recent'
+ assert_equal 'more_recent' , assigns(:filter)
+
+ get :communities, :filter => 'more_active'
+ assert_equal 'more_active' , assigns(:filter)
+
+ get :communities, :filter => 'more_popular'
+ assert_equal 'more_popular' , assigns(:filter)
+
+ get :communities, :filter => 'more_anything'
+ assert_equal 'more_recent' , assigns(:filter)
+ end
+
+ should 'the communities filter define the title' do
+ get :communities, :filter => 'more_recent'
+ assert_equal 'Communities more recent' , assigns(:title)
+ assert_tag :h1, :content => 'Communities more recent'
+
+ get :communities, :filter => 'more_active'
+ assert_equal 'Communities more active' , assigns(:title)
+ assert_tag :h1, :content => 'Communities more active'
+
+ get :communities, :filter => 'more_popular'
+ assert_equal 'Communities more popular' , assigns(:title)
+ assert_tag :h1, :content => 'Communities more popular'
+
+ get :communities, :filter => 'more_anything'
+ assert_equal 'Communities more recent' , assigns(:title)
+ assert_tag :h1, :content => 'Communities more recent'
+ end
+
+end
diff --git a/test/integration/routing_test.rb b/test/integration/routing_test.rb
index 3b28a71..e0538ee 100644
--- a/test/integration/routing_test.rb
+++ b/test/integration/routing_test.rb
@@ -216,4 +216,11 @@ class RoutingTest < ActionController::IntegrationTest
assert_routing('/doc', :controller => 'doc', :action => 'index')
end
+ # browse controller
+ def test_browse_routing
+ assert_routing('/browse/people', :controller => 'browse', :action => 'people')
+ assert_routing('/browse/people/more_popular', :controller => 'browse', :action => 'people', :filter => 'more_popular')
+ assert_routing('/browse/communities', :controller => 'browse', :action => 'communities')
+ assert_routing('/browse/communities/more_active', :controller => 'browse', :action => 'communities', :filter => 'more_active')
+ end
end
diff --git a/test/unit/application_helper_test.rb b/test/unit/application_helper_test.rb
index 186b605..fbc4f80 100644
--- a/test/unit/application_helper_test.rb
+++ b/test/unit/application_helper_test.rb
@@ -567,6 +567,60 @@ class ApplicationHelperTest < Test::Unit::TestCase
assert_equal environment.theme, current_theme
end
+ should 'trunc to 15 chars the big filename' do
+ assert_equal 'AGENDA(...).mp3', short_filename('AGENDA_CULTURA_-_FESTA_DE_VAQUEIROS_PONTO_DE_SERRA_PRETA_BAIXA.mp3',15)
+ end
+
+ should 'trunc to default limit the big filename' do
+ assert_equal 'AGENDA_CULTURA_-_FESTA_DE_VAQUEIRO(...).mp3', short_filename('AGENDA_CULTURA_-_FESTA_DE_VAQUEIROS_PONTO_DE_SERRA_PRETA_BAIXA.mp3')
+ end
+
+ should 'does not trunc short filename' do
+ assert_equal 'filename.mp3', short_filename('filename.mp3')
+ end
+
+ should 'return nil when :show_balloon_with_profile_links_when_clicked is not enabled in environment' do
+ env = Environment.default
+ env.stubs(:enabled?).with(:show_balloon_with_profile_links_when_clicked).returns(false)
+ stubs(:environment).returns(env)
+ profile = Profile.new
+ assert_nil links_for_balloon(profile)
+ end
+
+ should 'return ordered list of links to balloon to Person' do
+ env = Environment.default
+ env.stubs(:enabled?).with(:show_balloon_with_profile_links_when_clicked).returns(true)
+ stubs(:environment).returns(env)
+ person = Person.new
+ person.stubs(:url).returns('url for person')
+ person.stubs(:public_profile_url).returns('url for person')
+ links = links_for_balloon(person)
+ assert_equal ['Home Page', 'Profile', 'Friends', 'Communities'], links.map{|i| i.keys.first}
+ end
+
+ should 'return ordered list of links to balloon to Community' do
+ env = Environment.default
+ env.stubs(:enabled?).with(:show_balloon_with_profile_links_when_clicked).returns(true)
+ stubs(:environment).returns(env)
+ community = Community.new
+ community.stubs(:url).returns('url for community')
+ community.stubs(:public_profile_url).returns('url for community')
+ links = links_for_balloon(community)
+ assert_equal ['Home Page', 'Profile', 'Members', 'Agenda'], links.map{|i| i.keys.first}
+ end
+
+ should 'return ordered list of links to balloon to Enterprise' do
+ env = Environment.default
+ env.stubs(:enabled?).with(:show_balloon_with_profile_links_when_clicked).returns(true)
+ stubs(:environment).returns(env)
+ enterprise = Enterprise.new
+ enterprise.stubs(:url).returns('url for enterprise')
+ enterprise.stubs(:public_profile_url).returns('url for enterprise')
+ stubs(:catalog_path)
+ links = links_for_balloon(enterprise)
+ assert_equal ['Home Page', 'Products', 'Members', 'Agenda'], links.map{|i| i.keys.first}
+ end
+
protected
def url_for(args = {})
diff --git a/test/unit/person_test.rb b/test/unit/person_test.rb
index 7aebcf3..ffe29c2 100644
--- a/test/unit/person_test.rb
+++ b/test/unit/person_test.rb
@@ -588,4 +588,51 @@ class PersonTest < Test::Unit::TestCase
end
end
+ should "return none on label if the person hasn't friends" do
+ p = fast_create(Person)
+ assert_equal 0, p.friends.count
+ assert_equal "none", p.more_popular_label
+ end
+
+ should "return one friend on label if the profile has one member" do
+ p1 = fast_create(Person)
+ p2 = fast_create(Person)
+ p1.add_friend(p2)
+ assert_equal 1, p1.friends.count
+ assert_equal "one friend", p1.more_popular_label
+ end
+
+ should "return the number of friends on label if the person has more than one friend" do
+ p1 = fast_create(Person)
+ p2 = fast_create(Person)
+ p3 = fast_create(Person)
+ p1.add_friend(p2)
+ p1.add_friend(p3)
+ assert_equal 2, p1.friends.count
+ assert_equal "2 friends", p1.more_popular_label
+
+ p4 = fast_create(Person)
+ p1.add_friend(p4)
+ assert_equal 3, p1.friends.count
+ assert_equal "3 friends", p1.more_popular_label
+ end
+
+ should 'find more popular people' do
+ Person.delete_all
+ env = fast_create(Environment)
+ p1 = fast_create(Person)
+ p2 = fast_create(Person)
+ p3 = fast_create(Person)
+
+ p1.add_friend(p2)
+ assert_equal [p1], Person.more_popular
+
+ p2.add_friend(p1)
+ p2.add_friend(p3)
+ assert_equal [p2,p1] , Person.more_popular
+
+ p2.remove_friend(p3)
+ assert_equal [p1,p2] , Person.more_popular
+ end
+
end
diff --git a/test/unit/profile_test.rb b/test/unit/profile_test.rb
index 30898f2..5ec2e9f 100644
--- a/test/unit/profile_test.rb
+++ b/test/unit/profile_test.rb
@@ -1563,6 +1563,212 @@ class ProfileTest < Test::Unit::TestCase
assert_match / Wellformed html code <\/h1>/, profile.custom_footer
end
+ should 'find more recent people' do
+ Person.delete_all
+ p1 = fast_create(Person,:created_at => 4.days.ago)
+ p2 = fast_create(Person, :created_at => DateTime.now)
+ p3 = fast_create(Person, :created_at => 2.days.ago)
+
+ assert_equal [p2,p3,p1] , Person.more_recent
+
+ p4 = fast_create(Person, :created_at => 3.days.ago)
+ assert_equal [p2,p3,p4,p1] , Person.more_recent
+ end
+
+ should 'find more active people' do
+ Person.delete_all
+ p1 = fast_create(Person)
+ p2 = fast_create(Person)
+ p3 = fast_create(Person)
+ Article.delete_all
+ fast_create(Article, :profile_id => p1, :created_at => 7.days.ago)
+ fast_create(Article, :profile_id => p1, :created_at => DateTime.now.beginning_of_day)
+ fast_create(Article, :profile_id => p2, :created_at => DateTime.now.beginning_of_day)
+ assert_equal [p1,p2] , Person.more_active
+
+ fast_create(Article, :profile_id => p2, :created_at => 1.day.ago)
+ fast_create(Article, :profile_id => p2, :created_at => 5.days.ago)
+ fast_create(Article, :profile_id => p3, :created_at => 2.days.ago)
+ assert_equal [p2,p1,p3] , Person.more_active
+ end
+
+ should 'the ties on more active people be solved by the number of comments' do
+ Person.delete_all
+ p1 = fast_create(Person)
+ p2 = fast_create(Person)
+ Article.delete_all
+ a1 = fast_create(Article, :profile_id => p1, :created_at => DateTime.now.beginning_of_day)
+ a2 = fast_create(Article, :profile_id => p2, :created_at => DateTime.now.beginning_of_day)
+ assert_equal [], [p1,p2] - Person.more_active
+ assert_equal [], Person.more_active - [p1, p2]
+
+ a2.comments.build(:title => 'test comment', :body => 'anything', :author => p1).save!
+ assert_equal [p2,p1] , Person.more_active
+
+ a1.comments.build(:title => 'test comment', :body => 'anything', :author => p2).save!
+ a1.comments.build(:title => 'test comment', :body => 'anything', :author => p2).save!
+ assert_equal [p1,p2] , Person.more_active
+ end
+
+ should 'more active people take in consideration only articles created current the last week' do
+ Person.delete_all
+ env = fast_create(Environment)
+ p1 = fast_create(Person)
+ p2 = fast_create(Person)
+ p3 = fast_create(Person)
+ Article.delete_all
+ fast_create(Article, :profile_id => p1, :created_at => DateTime.now.beginning_of_day)
+ fast_create(Article, :profile_id => p2, :created_at => 10.days.ago)
+ assert_equal [p1] , Person.more_active
+
+ fast_create(Article, :profile_id => p2, :created_at => DateTime.now.beginning_of_day)
+ fast_create(Article, :profile_id => p2, :created_at => 7.days.ago)
+ fast_create(Article, :profile_id => p3, :created_at => 8.days.ago)
+ assert_equal [p2,p1] , Person.more_active
+ end
+
+ should 'find more recent community' do
+ c1 = fast_create(Community, :created_at => 3.days.ago)
+ c2 = fast_create(Community, :created_at => 1.day.ago)
+ c3 = fast_create(Community, :created_at => DateTime.now)
+
+ assert_equal [c3,c2,c1] , Community.more_recent
+
+ c4 = fast_create(Community, :created_at => 2.days.ago)
+ assert_equal [c3,c2,c4,c1] , Community.more_recent
+ end
+
+ should 'find more active community' do
+ c1 = fast_create(Community)
+ c2 = fast_create(Community)
+ c3 = fast_create(Community)
+
+ Article.delete_all
+ fast_create(Article, :profile_id => c1, :created_at => 1.day.ago)
+ fast_create(Article, :profile_id => c1, :created_at => DateTime.now.beginning_of_day)
+ fast_create(Article, :profile_id => c2, :created_at => DateTime.now.beginning_of_day)
+ assert_equal [c1,c2], Community.more_active
+
+ fast_create(Article, :profile_id => c2, :created_at => 2.days.ago)
+ fast_create(Article, :profile_id => c2, :created_at => 7.days.ago)
+ fast_create(Article, :profile_id => c3, :created_at => 1.day.ago)
+ assert_equal [c2,c1,c3] , Community.more_active
+ end
+
+ should 'the ties on more active communities be solved by the number of comments' do
+ env = create(Environment)
+ Community.delete_all
+ c1 = fast_create(Community)
+ c2 = fast_create(Community)
+ Article.delete_all
+ a1 = fast_create(Article, :profile_id => c1, :created_at => DateTime.now.beginning_of_day)
+ a2 = fast_create(Article, :profile_id => c2, :created_at => DateTime.now.beginning_of_day)
+ assert_equal [c1,c2] , Community.more_active
+
+ p1 = fast_create(Person)
+ a2.comments.build(:title => 'test comment', :body => 'anything', :author => p1).save!
+ assert_equal [c2,c1] , Community.more_active
+
+ a1.comments.build(:title => 'test comment', :body => 'anything', :author => p1).save!
+ a1.comments.build(:title => 'test comment', :body => 'anything', :author => p1).save!
+ assert_equal [c1,c2] , Community.more_active
+ end
+
+ should 'more active communities take in consideration only articles created current the last week' do
+ c1 = fast_create(Community)
+ c2 = fast_create(Community)
+ c3 = fast_create(Community)
+ Article.delete_all
+ fast_create(Article, :profile_id => c1, :created_at => DateTime.now.beginning_of_day)
+ fast_create(Article, :profile_id => c2, :created_at => 10.days.ago)
+ assert_equal [c1] , Community.more_active
+
+ fast_create(Article, :profile_id => c2, :created_at => DateTime.now.beginning_of_day)
+ fast_create(Article, :profile_id => c2, :created_at => 7.days.ago)
+ fast_create(Article, :profile_id => c3, :created_at => 8.days.ago)
+ assert_equal [c2,c1] , Community.more_active
+ end
+
+ should 'find more popular communities' do
+ Community.delete_all
+
+ c1 = fast_create(Community)
+ c2 = fast_create(Community)
+ fast_create(Community)
+
+ p1 = fast_create(Person)
+ p2 = fast_create(Person)
+ c1.add_member(p1)
+ assert_equal [c1] , Community.more_popular
+
+ c2.add_member(p1)
+ c2.add_member(p2)
+ assert_equal [c2,c1] , Community.more_popular
+
+ c2.remove_member(p2)
+ c2.remove_member(p1)
+ assert_equal [c1] , Community.more_popular
+ end
+
+ should "return the more recent label" do
+ p = fast_create(Profile)
+ assert_equal "Since: ", p.more_recent_label
+ end
+
+ should "return none on label if the profile hasn't articles" do
+ p = fast_create(Profile)
+ assert_equal 0, p.articles.count
+ assert_equal "none", p.more_active_label
+ end
+
+ should "return one article on label if the profile has one article" do
+ p = fast_create(Profile)
+ fast_create(Article, :profile_id => p.id)
+ assert_equal 1, p.articles.count
+ assert_equal "one article", p.more_active_label
+ end
+
+ should "return number of artciles on label if the profile has more than one article" do
+ p = fast_create(Profile)
+ fast_create(Article, :profile_id => p.id)
+ fast_create(Article, :profile_id => p.id)
+ assert_equal 2, p.articles.count
+ assert_equal "2 articles", p.more_active_label
+
+ fast_create(Article, :profile_id => p.id)
+ assert_equal 3, p.articles.count
+ assert_equal "3 articles", p.more_active_label
+ end
+
+ should "return none on label if the profile hasn't members" do
+ p = fast_create(Profile)
+ assert_equal 0, p.members.count
+ assert_equal "none", p.more_popular_label
+ end
+
+ should "return one member on label if the profile has one member" do
+ p = fast_create(Person)
+ c = fast_create(Community)
+ c.add_member(p)
+ assert_equal 1, c.members.count
+ assert_equal "one member", c.more_popular_label
+ end
+
+ should "return the number of members on label if the profile has more than one member" do
+ p1 = fast_create(Profile)
+ p2 = fast_create(Person)
+ c = fast_create(Community)
+ c.add_member(p1)
+ c.add_member(p2)
+ assert_equal 2, c.members.count
+ assert_equal "2 members", c.more_popular_label
+
+ p3 = fast_create(Person)
+ c.add_member(p3)
+ assert_equal 3, c.members.count
+ assert_equal "3 members", c.more_popular_label
+ end
+
private
def assert_invalid_identifier(id)
--
libgit2 0.21.2