Commit 4b48bec4b1b4be3a525c99a751b36303833a8708

Authored by Joenio Costa
Committed by Antonio Terceiro
1 parent 4182e506

Each community has its own agenda

 - New UI for calendar
 - New routes to /profile/:profile/events

(ActionItem1255)
app/controllers/public/events_controller.rb 0 → 100644
@@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
  1 +class EventsController < PublicController
  2 +
  3 + needs_profile
  4 + no_design_blocks
  5 +
  6 + def events
  7 + @selected_day = nil
  8 + @events_of_the_day = []
  9 + date = build_date(params[:year], params[:month], params[:day])
  10 +
  11 + if params[:day] || !params[:year] && !params[:month]
  12 + @selected_day = date
  13 + @events_of_the_day = profile.events.by_day(@selected_day)
  14 + end
  15 +
  16 + events = profile.events.by_range(Event.first_day_of_month(date - 1.month)..Event.last_day_of_month(date + 1.month))
  17 +
  18 + @calendar = populate_calendar(date, events)
  19 + @previous_calendar = populate_calendar(date - 1.month, events)
  20 + @next_calendar = populate_calendar(date + 1.month, events)
  21 + end
  22 +
  23 + def events_by_day
  24 + @selected_day = build_date(params[:year], params[:month], params[:day])
  25 + @events_of_the_day = profile.events.by_day(@selected_day)
  26 + render :partial => 'events_by_day'
  27 + end
  28 +
  29 + protected
  30 +
  31 + include EventsHelper
  32 +
  33 +end
app/controllers/public/search_controller.rb
@@ -43,30 +43,26 @@ class SearchController &lt; PublicController @@ -43,30 +43,26 @@ class SearchController &lt; PublicController
43 end 43 end
44 44
45 def events 45 def events
46 - @events = @results[:events]  
47 - @calendar = Event.date_range(params[:year], params[:month]).map do |date|  
48 - [  
49 - # the day itself  
50 - date,  
51 - # list of events of that day  
52 - @events.select do |event|  
53 - event.date_range.include?(date)  
54 - end,  
55 - # is this date in the current month?  
56 - true  
57 - ]  
58 - end  
59 -  
60 - # pad with days before  
61 - while @calendar.first.first.wday != 0  
62 - @calendar.unshift([@calendar.first.first - 1.day, [], false]) 46 + @category_id = @category ? @category.id : nil
  47 +
  48 + @selected_day = nil
  49 + @events_of_the_day = []
  50 + date = build_date(params[:year], params[:month], params[:day])
  51 +
  52 + if params[:day] || !params[:year] && !params[:month]
  53 + @selected_day = date
  54 + if @category_id and Category.exists?(@category_id)
  55 + @events_of_the_day = environment.events.by_day(@selected_day).in_category(Category.find(@category_id))
  56 + else
  57 + @events_of_the_day = environment.events.by_day(@selected_day)
  58 + end
63 end 59 end
64 60
65 - # pad with days after (until Saturday)  
66 - while @calendar.last.first.wday != 6  
67 - @calendar << [@calendar.last.first + 1.day, [], false]  
68 - end 61 + events = @results[:events]
69 62
  63 + @calendar = populate_calendar(date, events)
  64 + @previous_calendar = populate_calendar(date - 1.month, events)
  65 + @next_calendar = populate_calendar(date + 1.month, events)
70 end 66 end
71 67
72 def people 68 def people
@@ -105,7 +101,8 @@ class SearchController &lt; PublicController @@ -105,7 +101,8 @@ class SearchController &lt; PublicController
105 end 101 end
106 102
107 if month || year 103 if month || year
108 - result[:date_range] = Event.date_range(year, month) 104 + date = Date.new(year.to_i, month.to_i, 1)
  105 + result[:date_range] = (date - 1.month)..Event.last_day_of_month(date + 1.month)
109 end 106 end
110 107
111 result 108 result
@@ -240,4 +237,14 @@ class SearchController &lt; PublicController @@ -240,4 +237,14 @@ class SearchController &lt; PublicController
240 render :action => 'popup', :layout => false 237 render :action => 'popup', :layout => false
241 end 238 end
242 239
  240 + def events_by_day
  241 + @selected_day = build_date(params[:year], params[:month], params[:day])
  242 + if params[:category_id] and Category.exists?(params[:category_id])
  243 + @events_of_the_day = environment.events.by_day(@selected_day).in_category(Category.find(params[:category_id]))
  244 + else
  245 + @events_of_the_day = environment.events.by_day(@selected_day)
  246 + end
  247 + render :partial => 'events/events_by_day'
  248 + end
  249 +
243 end 250 end
app/helpers/application_helper.rb
@@ -908,4 +908,8 @@ module ApplicationHelper @@ -908,4 +908,8 @@ module ApplicationHelper
908 javascript_tag('var array = ' + email.split('@').to_json + '; document.write("<a href=\'mailto:" + array.join("@") + "\'>" + array.join("@") + "</a>")') 908 javascript_tag('var array = ' + email.split('@').to_json + '; document.write("<a href=\'mailto:" + array.join("@") + "\'>" + array.join("@") + "</a>")')
909 end 909 end
910 910
  911 + def stylesheet(*args)
  912 + content_for(:head) { stylesheet_link_tag(*args) }
  913 + end
  914 +
911 end 915 end
app/helpers/dates_helper.rb
@@ -2,6 +2,7 @@ module DatesHelper @@ -2,6 +2,7 @@ module DatesHelper
2 2
3 include GetText 3 include GetText
4 4
  5 + # FIXME Date#strftime should translate this for us !!!!
5 MONTHS = [ 6 MONTHS = [
6 N_('January'), 7 N_('January'),
7 N_('February'), 8 N_('February'),
@@ -49,43 +50,66 @@ module DatesHelper @@ -49,43 +50,66 @@ module DatesHelper
49 end 50 end
50 end 51 end
51 52
52 - def show_day_of_week(date)  
53 - # FIXME Date#strftime should translate this for us !!!!  
54 - _([  
55 - N_('Sunday'),  
56 - N_('Monday'),  
57 - N_('Tuesday'),  
58 - N_('Wednesday'),  
59 - N_('Thursday'),  
60 - N_('Friday'),  
61 - N_('Saturday'),  
62 - ][date.wday]) 53 + def show_day_of_week(date, abbreviated = false)
  54 + # FIXME Date#strftime should translate this for us !!!!
  55 + N_('Sun'); N_('Mon'); N_('Tue'); N_('Wed'); N_('Thu'); N_('Fri'); N_('Sat');
  56 + if abbreviated
  57 + _(date.strftime("%a"))
  58 + else
  59 + # FIXME Date#strftime should translate this for us !!!!
  60 + _([
  61 + N_('Sunday'),
  62 + N_('Monday'),
  63 + N_('Tuesday'),
  64 + N_('Wednesday'),
  65 + N_('Thursday'),
  66 + N_('Friday'),
  67 + N_('Saturday'),
  68 + ][date.wday])
  69 + end
63 end 70 end
64 71
65 - def show_month(year, month)  
66 -  
67 - if year.blank?  
68 - year = Date.today.year  
69 - end  
70 - if month.blank?  
71 - month = Date.today.month 72 + def show_month(year, month, opts = {})
  73 + date = build_date(year, month)
  74 + if opts[:next]
  75 + date = date >> 1
  76 + elsif opts[:previous]
  77 + date = date << 1
72 end 78 end
  79 + _('%{month} %{year}') % { :year => date.year, :month => month_name(date.month.to_i) }
  80 + end
73 81
74 - _('%{month} %{year}') % { :year => year, :month => month_name(month.to_i) } 82 + def build_date(year, month, day = 1)
  83 + if year.blank? and month.blank? and day.blank?
  84 + Date.today
  85 + else
  86 + if year.blank?
  87 + year = Date.today.year
  88 + end
  89 + if month.blank?
  90 + month = Date.today.month
  91 + end
  92 + if day.blank?
  93 + day = 1
  94 + end
  95 + Date.new(year.to_i, month.to_i, day.to_i)
  96 + end
75 end 97 end
76 98
77 - def link_to_previous_month(year, month)  
78 - date = (year.blank? || month.blank?) ? Date.today : Date.new(year.to_i, month.to_i, 1) 99 + def link_to_previous_month(year, month, label = nil)
  100 + date = build_date(year, month)
79 previous_month_date = date - 1.month 101 previous_month_date = date - 1.month
80 102
81 - link_to '&larr; ' + show_month(previous_month_date.year, previous_month_date.month), :year => previous_month_date.year, :month => previous_month_date.month 103 + label ||= show_month(previous_month_date.year, previous_month_date.month)
  104 + link_to label, :year => previous_month_date.year, :month => previous_month_date.month
82 end 105 end
83 106
84 - def link_to_next_month(year, month)  
85 - date = (year.blank? || month.blank?) ? Date.today : Date.new(year.to_i, month.to_i, 1) 107 + def link_to_next_month(year, month, label = nil)
  108 + date = build_date(year, month)
86 next_month_date = date + 1.month 109 next_month_date = date + 1.month
87 110
88 - link_to show_month(next_month_date.year, next_month_date.month) + ' &rarr;', :year => next_month_date.year, :month => next_month_date.month 111 + label ||= show_month(next_month_date.year, next_month_date.month)
  112 + link_to label, :year => next_month_date.year, :month => next_month_date.month
89 end 113 end
90 114
91 def pick_date(object, method, options = {}, html_options = {}) 115 def pick_date(object, method, options = {}, html_options = {})
app/helpers/events_helper.rb 0 → 100644
@@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
  1 +module EventsHelper
  2 +
  3 + def list_events(date, events)
  4 + return content_tag('em', _("Select a day on the left to display it's events here"), :class => 'no-events') unless date
  5 + title = _('Events for %s') % show_date(date)
  6 + content_tag('h2', title) +
  7 + content_tag('div',
  8 + (events.any? ?
  9 + content_tag('table', events.select { |item| item.public? }.map {|item| display_event_in_listing(item)}.join('')) :
  10 + content_tag('em', _('No events for this date'))
  11 + ), :id => 'agenda-items'
  12 + )
  13 + end
  14 +
  15 + def display_event_in_listing(article)
  16 + content_tag(
  17 + 'tr',
  18 + content_tag('td', link_to(image_tag(icon_for_article(article)) + article.name, article.url)),
  19 + :class => 'agenda-item'
  20 + )
  21 + end
  22 +
  23 + def populate_calendar(selected_date, events)
  24 + calendar = Event.date_range(selected_date.year, selected_date.month).map do |date|
  25 + [
  26 + # the day itself
  27 + date,
  28 + # is there any events in this date?
  29 + events.any? do |event|
  30 + event.date_range.include?(date)
  31 + end,
  32 + # is this date in the current month?
  33 + true
  34 + ]
  35 + end
  36 + # pad with days before
  37 + while calendar.first.first.wday != 0
  38 + calendar.unshift([calendar.first.first - 1.day, false, false])
  39 + end
  40 +
  41 + # pad with days after (until Saturday)
  42 + while calendar.last.first.wday != 6
  43 + calendar << [calendar.last.first + 1.day, false, false]
  44 + end
  45 + calendar
  46 + end
  47 +
  48 +end
app/helpers/search_helper.rb
1 module SearchHelper 1 module SearchHelper
2 2
  3 + # FIXME remove it after search_controler refactored
  4 + include EventsHelper
  5 +
3 STOP_WORDS = { 6 STOP_WORDS = {
4 'pt_BR' => Ferret::Analysis::FULL_PORTUGUESE_STOP_WORDS, 7 'pt_BR' => Ferret::Analysis::FULL_PORTUGUESE_STOP_WORDS,
5 'en' => Ferret::Analysis::FULL_ENGLISH_STOP_WORDS, 8 'en' => Ferret::Analysis::FULL_ENGLISH_STOP_WORDS,
app/models/article.rb
@@ -28,6 +28,10 @@ class Article &lt; ActiveRecord::Base @@ -28,6 +28,10 @@ class Article &lt; ActiveRecord::Base
28 28
29 xss_terminate :only => [ :name ] 29 xss_terminate :only => [ :name ]
30 30
  31 + named_scope :in_category, lambda { |category|
  32 + {:include => 'categories', :conditions => { 'categories.id' => category.id }}
  33 + }
  34 +
31 def self.human_attribute_name(attrib) 35 def self.human_attribute_name(attrib)
32 case attrib.to_sym 36 case attrib.to_sym
33 when :name 37 when :name
app/models/category_finder.rb
@@ -104,7 +104,7 @@ class CategoryFinder @@ -104,7 +104,7 @@ class CategoryFinder
104 when 'Event' 104 when 'Event'
105 conditions = 105 conditions =
106 if date_range 106 if date_range
107 - ['articles_categories.category_id = (?) and start_date between ? and ?', category_id, date_range.first, date_range.last] 107 + ['articles_categories.category_id = (:category_id) and (start_date BETWEEN :start_day AND :end_day OR end_date BETWEEN :start_day AND :end_day)', {:category_id => category_id, :start_day => date_range.first, :end_day => date_range.last} ]
108 else 108 else
109 ['articles_categories.category_id = (?) ', category_id ] 109 ['articles_categories.category_id = (?) ', category_id ]
110 end 110 end
app/models/environment_finder.rb
@@ -32,7 +32,10 @@ class EnvironmentFinder @@ -32,7 +32,10 @@ class EnvironmentFinder
32 @environment.send(asset).send(finder_method, :all, options.merge( :order => 'profiles.name', :joins => 'inner join products on (products.enterprise_id = profiles.id) inner join product_categorizations on (product_categorizations.product_id = products.id)', :conditions => ['product_categorizations.category_id = (?)', product_category.id])) 32 @environment.send(asset).send(finder_method, :all, options.merge( :order => 'profiles.name', :joins => 'inner join products on (products.enterprise_id = profiles.id) inner join product_categorizations on (product_categorizations.product_id = products.id)', :conditions => ['product_categorizations.category_id = (?)', product_category.id]))
33 else 33 else
34 if (asset == :events) && date_range 34 if (asset == :events) && date_range
35 - @environment.send(asset).send(finder_method, :all, options.merge(:conditions => { :start_date => date_range})) 35 + @environment.send(asset).send(finder_method, :all, options.merge(:conditions => [
  36 + 'start_date BETWEEN :start_day AND :end_day OR end_date BETWEEN :start_day AND :end_day',
  37 + {:start_day => date_range.first, :end_day => date_range.last}
  38 + ]))
36 else 39 else
37 @environment.send(asset).send(finder_method, :all, options) 40 @environment.send(asset).send(finder_method, :all, options)
38 end 41 end
app/models/event.rb
@@ -16,6 +16,10 @@ class Event &lt; Article @@ -16,6 +16,10 @@ class Event &lt; Article
16 end 16 end
17 end 17 end
18 18
  19 + named_scope :by_day, lambda { |date|
  20 + {:conditions => ['start_date = :date AND end_date IS NULL OR (start_date <= :date AND end_date >= :date)', {:date => date}]}
  21 + }
  22 +
19 def self.description 23 def self.description
20 _('A calendar event') 24 _('A calendar event')
21 end 25 end
@@ -28,9 +32,12 @@ class Event &lt; Article @@ -28,9 +32,12 @@ class Event &lt; Article
28 'event' 32 'event'
29 end 33 end
30 34
31 - def self.by_month(year = nil, month = nil)  
32 - self.find(:all, :conditions => { :start_date => date_range(year, month) })  
33 - end 35 + named_scope :by_range, lambda { |range| {
  36 + :conditions => [
  37 + 'start_date BETWEEN :start_day AND :end_day OR end_date BETWEEN :start_day AND :end_day',
  38 + { :start_day => range.first, :end_day => range.last }
  39 + ]
  40 + }}
34 41
35 def self.date_range(year, month) 42 def self.date_range(year, month)
36 if year.nil? || month.nil? 43 if year.nil? || month.nil?
@@ -43,11 +50,22 @@ class Event &lt; Article @@ -43,11 +50,22 @@ class Event &lt; Article
43 end 50 end
44 51
45 first_day = Date.new(year, month, 1) 52 first_day = Date.new(year, month, 1)
46 - last_day = Date.new(year, month, 1) + 1.month - 1.day 53 + last_day = first_day + 1.month - 1.day
47 54
48 first_day..last_day 55 first_day..last_day
49 end 56 end
50 57
  58 + def self.first_day_of_month(date)
  59 + date ||= Date.today
  60 + Date.new(date.year, date.month, 1)
  61 + end
  62 +
  63 + def self.last_day_of_month(date)
  64 + date ||= Date.today
  65 + date >>= 1
  66 + Date.new(date.year, date.month, 1) - 1.day
  67 + end
  68 +
51 def date_range 69 def date_range
52 start_date..(end_date||start_date) 70 start_date..(end_date||start_date)
53 end 71 end
app/models/profile.rb
@@ -115,6 +115,8 @@ class Profile &lt; ActiveRecord::Base @@ -115,6 +115,8 @@ class Profile &lt; ActiveRecord::Base
115 115
116 has_many :tasks, :dependent => :destroy, :as => 'target' 116 has_many :tasks, :dependent => :destroy, :as => 'target'
117 117
  118 + has_many :events, :source => 'articles', :class_name => 'Event', :order => 'name'
  119 +
118 %w[ pending finished ].each do |status| 120 %w[ pending finished ].each do |status|
119 class_eval <<-CODE 121 class_eval <<-CODE
120 def all_#{status}_tasks 122 def all_#{status}_tasks
app/views/events/_agenda.rhtml 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +<div id='agenda'>
  2 + <div class='agenda-calendar'>
  3 + <table class='noborder current-month'>
  4 + <caption>
  5 + <h2><%= show_month(params[:year], params[:month]) %></h2>
  6 + <%= link_to_previous_month(params[:year], params[:month], '&larr; previous') %>
  7 + <%= link_to_next_month(params[:year], params[:month], 'next &rarr;') %>
  8 + </caption>
  9 + <%= render :partial => 'events/month', :locals => {:calendar => @calendar, :abbreviated => true} %>
  10 + </table>
  11 + <table class='noborder previous-month'>
  12 + <caption><h3><%= link_to_previous_month(params[:year], params[:month], show_month(params[:year], params[:month], :previous => true)) %></h3></caption>
  13 + <%= render :partial => 'events/month', :locals => {:calendar => @previous_calendar, :abbreviated => true} %>
  14 + </table>
  15 + <table class='noborder next-month'>
  16 + <caption><h3><%= link_to_next_month(params[:year], params[:month], show_month(params[:year], params[:month], :next => true)) %></h3></caption>
  17 + <%= render :partial => 'events/month', :locals => {:calendar => @next_calendar, :abbreviated => true} %>
  18 + </table>
  19 + <br clear='both'/>
  20 + </div>
  21 + <div id='events-of-the-day'>
  22 + <%= render :partial => 'events/events_by_day' %>
  23 + </div>
  24 +</div>
app/views/events/_events_by_day.rhtml 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= list_events(@selected_day, @events_of_the_day) %>
app/views/events/_month.rhtml 0 → 100644
@@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
  1 + <tr>
  2 + <% calendar.first(7).each do |day,event| %>
  3 + <th><%= show_day_of_week(day, abbreviated) %></th>
  4 + <% end %>
  5 + </tr>
  6 + <% calendar.in_groups_of(7).each do |week| %>
  7 + <tr>
  8 + <% week.each do |date, has_events, this_month| %>
  9 + <td class='calendar-day <%= this_month || "calendar-day-out" %> <%= date == Date.today && "selected" %>'>
  10 + <span>
  11 + <%= has_events ?
  12 + link_to_remote(
  13 + date.day,
  14 + :url => {:action => 'events_by_day', :year => date.year, :month => date.month, :day => date.day, :category_id => @category_id},
  15 + :update => 'events-of-the-day',
  16 + :loading => '$("events-of-the-day").addClassName("loading")',
  17 + :complete => '$("events-of-the-day").removeClassName("loading")'
  18 + ) :
  19 + date.day
  20 + %>
  21 + </span>
  22 + </td>
  23 + <% end %>
  24 + </tr>
  25 + <% end %>
app/views/events/events.rhtml 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +<%= button :back, _('Back to %s') % profile.name, profile.public_profile_url %>
  2 +
  3 +<h1><%= _("%s's events") % profile.name %></h1>
  4 +
  5 +<%= render :partial => 'agenda' %>
app/views/layouts/application-ng.rhtml
@@ -18,6 +18,8 @@ @@ -18,6 +18,8 @@
18 theme_stylesheet_path(), 18 theme_stylesheet_path(),
19 pngfix_stylesheet_path() 19 pngfix_stylesheet_path()
20 ) %> 20 ) %>
  21 + <%# Add custom tags/styles/etc via content_for %>
  22 + <%= yield :head %>
21 </head> 23 </head>
22 <body class="<%= 24 <body class="<%=
23 # Identify the current controller and action for the CSS: 25 # Identify the current controller and action for the CSS:
app/views/layouts/application.rhtml
@@ -28,11 +28,13 @@ @@ -28,11 +28,13 @@
28 import_controller_stylesheets + "\n" + 28 import_controller_stylesheets + "\n" +
29 import_controller_stylesheets(:themed_source => true) 29 import_controller_stylesheets(:themed_source => true)
30 %> 30 %>
31 -  
32 <%= template_stylesheet_tag %> 31 <%= template_stylesheet_tag %>
33 <%= icon_theme_stylesheet_tag %> 32 <%= icon_theme_stylesheet_tag %>
34 33
35 <%= pngfix_stylesheet %> 34 <%= pngfix_stylesheet %>
  35 +
  36 + <%# Add custom tags/styles/etc via content_for %>
  37 + <%= yield :head %>
36 </head> 38 </head>
37 39
38 <body class='noosfero category<%= category_color %><%= 40 <body class='noosfero category<%= category_color %><%=
app/views/profile/index.rhtml
@@ -24,6 +24,13 @@ @@ -24,6 +24,13 @@
24 </tr> 24 </tr>
25 <tr> 25 <tr>
26 <td> 26 <td>
  27 + </td>
  28 + <td>
  29 + <%= link_to _('Events'), :controller => 'events', :action => 'events' %>
  30 + </td>
  31 + </tr>
  32 + <tr>
  33 + <td>
27 <%= _('Tags:') %> 34 <%= _('Tags:') %>
28 </td> 35 </td>
29 <td> 36 <td>
app/views/search/events.rhtml
1 <h1> 1 <h1>
2 <% if @category %> 2 <% if @category %>
3 - <%= @category.name %>: 3 + <%= @category.name %>
4 <% end %> 4 <% end %>
5 - <%= show_month(params[:year], params[:month]) %>  
6 </h1> 5 </h1>
7 6
8 -<div style='text-align: center; margin: 1em;'>  
9 - <%= link_to_previous_month(params[:year], params[:month]) %>  
10 - &nbsp;  
11 - &nbsp;  
12 - &nbsp;  
13 - <%= link_to_next_month(params[:year], params[:month]) %>  
14 -</div> 7 +<% stylesheet 'controller_events' %>
15 8
16 -<table align='center' class='noborder'>  
17 - <tr>  
18 - <% @calendar.first(7).each do |day,event| %>  
19 - <th style='width: 10%;'><%= show_day_of_week(day) %></th>  
20 - <% end %>  
21 - </tr>  
22 - <% @calendar.in_groups_of(7).each do |week| %>  
23 - <tr style='height: 80px;'>  
24 - <% week.each do |date, events, this_month| %>  
25 - <td style='vertical-align: top; <%= ("background-color: gray;" unless this_month) %> <%= ("background-color: #ff9" if date == Date.today) %>'>  
26 - <div style='text-align: center;'>  
27 - <strong><%= date.day %></strong>  
28 - </div>  
29 -  
30 - <% events.each do |event| %>  
31 - <div style='border: 1px solid gray; margin: 0.25em;'>  
32 - <%= link_to event.name, event.url, :style => 'display: block;' %>  
33 - </div>  
34 - <% end %>  
35 -  
36 - </td>  
37 - <% end %>  
38 - </tr>  
39 - <% end %>  
40 -</table> 9 +<%= render :partial => 'events/agenda' %>
config/routes.rb
@@ -47,6 +47,11 @@ ActionController::Routing::Routes.draw do |map| @@ -47,6 +47,11 @@ ActionController::Routing::Routes.draw do |map|
47 # search 47 # search
48 map.connect 'search/:action/*category_path', :controller => 'search' 48 map.connect 'search/:action/*category_path', :controller => 'search'
49 49
  50 + # events
  51 + map.events 'profile/:profile/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format}/
  52 + map.events 'profile/:profile/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format}/
  53 + map.events 'profile/:profile/events/:year/:month', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :profile => /#{Noosfero.identifier_format}/
  54 + map.events 'profile/:profile/events', :controller => 'events', :action => 'events', :profile => /#{Noosfero.identifier_format}/
50 55
51 # public profile information 56 # public profile information
52 map.profile 'profile/:profile/:action/:id', :controller => 'profile', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format}/ 57 map.profile 'profile/:profile/:action/:id', :controller => 'profile', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format}/
features/events.feature 0 → 100644
@@ -0,0 +1,151 @@ @@ -0,0 +1,151 @@
  1 +Feature: events
  2 + As a noosfero visitor
  3 + I want to see some events
  4 +
  5 + Background:
  6 + Given the following users
  7 + | login |
  8 + | josesilva |
  9 + And the following events
  10 + | owner | name | start_date |
  11 + | josesilva | Another Conference | 2009-10-24 |
  12 +
  13 + Scenario: go to next month
  14 + Given I am on /profile/josesilva/events/2009/10
  15 + When I follow "next →"
  16 + Then I should see "November 2009" within ".current-month"
  17 +
  18 + Scenario: go to next month in global agenda
  19 + Given I am on /assets/events?year=2009&month=11
  20 + When I follow "next →"
  21 + Then I should see "December 2009" within ".current-month"
  22 +
  23 + Scenario: go to previous month
  24 + Given I am on /profile/josesilva/events/2009/10
  25 + When I follow "← previous"
  26 + Then I should see "September 2009" within ".current-month"
  27 +
  28 + Scenario: go to previous month in global agenda
  29 + Given I am on /assets/events?year=2009&month=11
  30 + When I follow "← previous"
  31 + Then I should see "October 2009" within ".current-month"
  32 +
  33 + Scenario: go to next month by clicking in month name
  34 + Given I am on /profile/josesilva/events/2009/10
  35 + When I follow "November 2009"
  36 + Then I should see "November 2009" within ".current-month"
  37 +
  38 + Scenario: go to previous month by clicking in month name
  39 + Given I am on /profile/josesilva/events/2009/10
  40 + When I follow "September 2009"
  41 + Then I should see "September 2009" within ".current-month"
  42 +
  43 + Scenario: go to specific day
  44 + Given I am on the homepage
  45 + When I am on /profile/josesilva/events/2009/01/20
  46 + Then I should see "Events for January 20, 2009"
  47 +
  48 + Scenario: go to specific day in global agenda
  49 + Given I am on the homepage
  50 + When I am on /assets/events?year=2009&month=11&day=12
  51 + Then I should see "Events for November 12, 2009"
  52 +
  53 + Scenario: list events for specific day
  54 + Given I am on /profile/josesilva/events/2009/10
  55 + And the following events
  56 + | owner | name | start_date |
  57 + | josesilva | WikiSym 2009 | 2009-10-25 |
  58 + When I am on /profile/josesilva/events/2009/10/25
  59 + Then I should see "WikiSym 2009"
  60 +
  61 + Scenario: dont list events for non-selected day
  62 + Given I am on /profile/josesilva/events/2009/10
  63 + And the following events
  64 + | owner | name | start_date |
  65 + | josesilva | WikiSym 2009 | 2009-10-25 |
  66 + When I am on /profile/josesilva/events/2009/10/20
  67 + Then I should not see "WikiSym 2009"
  68 +
  69 + Scenario: list event between a range
  70 + Given I am on /profile/josesilva/events/2009/10
  71 + And the following events
  72 + | owner | name | start_date | end_date |
  73 + | josesilva | WikiSym 2009 | 2009-10-25 | 2009-10-27 |
  74 + When I am on /profile/josesilva/events/2009/10/26
  75 + Then I should see "WikiSym 2009"
  76 +
  77 + Scenario: dont list events from other profiles
  78 + Given the following users
  79 + | login |
  80 + | josemanuel |
  81 + And the following events
  82 + | owner | name | start_date |
  83 + | josemanuel | Manuel Birthday | 2009-10-24 |
  84 + When I am on /profile/josesilva/events/2009/10/24
  85 + Then I should see "Another Conference"
  86 + And I should not see "Manuel Birthday"
  87 +
  88 + Scenario: list all events in global agenda
  89 + Given the following users
  90 + | login |
  91 + | josemanuel |
  92 + And the following events
  93 + | owner | name | start_date |
  94 + | josemanuel | Manuel Birthday | 2009-10-24 |
  95 + When I am on /assets/events?year=2009&month=10&day=24
  96 + Then I should see "Another Conference"
  97 + And I should see "Manuel Birthday"
  98 +
  99 + Scenario: ask for a day when no inform complete date
  100 + When I am on /profile/josesilva/events/2009/5
  101 + Then I should see "Select a day on the left to display it's events here"
  102 +
  103 + Scenario: ask for a day when no inform complete date in global agenda
  104 + When I am on /assets/events?year=2009&month=5
  105 + Then I should see "Select a day on the left to display it's events here"
  106 +
  107 + Scenario: provide links to days with events
  108 + Given I am on /profile/josesilva/events/2009/10
  109 + Then I should see "24" link
  110 + When I follow "next →"
  111 + Then I should see "24" link
  112 + When I follow "next →"
  113 + Then I should not see "24" link
  114 +
  115 + Scenario: provide links to all days between start and end date
  116 + Given the following users
  117 + | login |
  118 + | fudencio |
  119 + And the following events
  120 + | owner | name | start_date | end_date |
  121 + | fudencio | YAPC::Brasil 2009 | 2010-10-30 | 2010-11-01 |
  122 + And I am on /profile/fudencio/events/2010/10
  123 + Then I should not see "29" link
  124 + And I should see "30" link
  125 + And I should see "31" link
  126 + And I should see "1" link
  127 +
  128 + @selenium
  129 + Scenario: show events when i follow a specific day
  130 + Given I am on /profile/josesilva/events/2009/10
  131 + And I should not see "Another Conference"
  132 + When I follow "24"
  133 + Then I should see "Another Conference"
  134 +
  135 + @selenium
  136 + Scenario: show events in a range when i follow a specific day
  137 + Given the following events
  138 + | owner | name | start_date | end_date |
  139 + | josesilva | YAPC::Brasil 2010 | 2010-10-30 | 2010-11-01 |
  140 + And I am on /profile/josesilva/events/2010/10
  141 + And I should not see "YAPC::Brasil 2010"
  142 + When I follow "31"
  143 + Then I should see "YAPC::Brasil 2010"
  144 +
  145 + Scenario: provide button to back from profile
  146 + When I am on /profile/josesilva/events
  147 + Then I should see "Back to josesilva" link
  148 +
  149 + Scenario: warn when there is no events
  150 + When I am on /profile/josesilva/events/2020/12/1
  151 + Then I should see "No events for this date"
features/step_definitions/webrat_steps.rb
@@ -188,6 +188,10 @@ Then /^show me the page$/ do @@ -188,6 +188,10 @@ Then /^show me the page$/ do
188 save_and_open_page 188 save_and_open_page
189 end 189 end
190 190
191 -Then /^the source should contain tag ([^\"]+)$/ do |tag|  
192 - response_body.should have_tag(tag, {id => 10}) 191 +When /^I should see "([^\"]+)" link$/ do |link|
  192 + response.should have_selector("a", :content => link)
  193 +end
  194 +
  195 +When /^I should not see "([^\"]+)" link$/ do |link|
  196 + response.should_not have_selector("a", :content => link)
193 end 197 end
public/stylesheets/common.css
@@ -327,17 +327,22 @@ div.pending-tasks { @@ -327,17 +327,22 @@ div.pending-tasks {
327 margin-bottom: 20px; 327 margin-bottom: 20px;
328 } 328 }
329 329
330 -/* sitemap */ 330 +/* sitemap and agenda */
  331 +
331 .sitemap-item a:link, 332 .sitemap-item a:link,
332 -.sitemap-item a:visited { 333 +.agenda-item a:link,
  334 +.sitemap-item a:visited,
  335 +.agenda-item a:visited {
333 display: block; 336 display: block;
334 border: none; 337 border: none;
335 text-decoration: none; 338 text-decoration: none;
336 } 339 }
337 -.sitemap-item img { 340 +.sitemap-item img,
  341 +.agenda-item img {
338 border: none; 342 border: none;
339 } 343 }
340 -.sitemap-item a:hover { 344 +.sitemap-item a:hover,
  345 +.agenda-item a:hover {
341 background: #e0e0e0; 346 background: #e0e0e0;
342 color: red; 347 color: red;
343 text-decoration: underline; 348 text-decoration: underline;
@@ -346,7 +351,6 @@ div.pending-tasks { @@ -346,7 +351,6 @@ div.pending-tasks {
346 font-size: small; 351 font-size: small;
347 } 352 }
348 353
349 -  
350 /* * * icons for product category on profile * * */ 354 /* * * icons for product category on profile * * */
351 355
352 #content .product-category-icons { 356 #content .product-category-icons {
@@ -593,3 +597,10 @@ div.pending-tasks { @@ -593,3 +597,10 @@ div.pending-tasks {
593 code input { 597 code input {
594 font-family: monospace; 598 font-family: monospace;
595 } 599 }
  600 +
  601 +/** LOADING... **/
  602 +
  603 +.loading {
  604 + cursor: progress;
  605 + background: transparent url(../images/loading.gif) no-repeat scroll center 50px;
  606 +}
public/stylesheets/controller_events.css 0 → 100644
@@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
  1 +#agenda {
  2 + position: relative;
  3 + width: 100%;
  4 +}
  5 +
  6 +#agenda .agenda-calendar {
  7 + width: 50%;
  8 +}
  9 +
  10 +#agenda td, #agenda th {
  11 + padding: 0px;
  12 +}
  13 +
  14 +#agenda .agenda-calendar .previous-month td,
  15 +#agenda .agenda-calendar .previous-month th,
  16 +#agenda .agenda-calendar .next-month td,
  17 +#agenda .agenda-calendar .next-month th {
  18 + font-size: 10px;
  19 + color: gray;
  20 +}
  21 +#agenda .agenda-calendar .current-month td {
  22 +}
  23 +#agenda .agenda-calendar .calendar-day {
  24 +}
  25 +#agenda .agenda-calendar .calendar-day-out {
  26 + color: gray;
  27 +}
  28 +#agenda .agenda-calendar .calendar-day-out span {
  29 + display: none;
  30 +}
  31 +#agenda .agenda-calendar td {
  32 + text-align: center;
  33 + padding: 0px;
  34 +}
  35 +#agenda .agenda-calendar h3 {
  36 + font-size: 12px;
  37 +}
  38 +#agenda .agenda-calendar .current-month {
  39 + height: 250px;
  40 + border-bottom: 1px solid #BFC2BC;
  41 +}
  42 +#agenda .agenda-calendar .previous-month,
  43 +#agenda .agenda-calendar .next-month {
  44 + float: left;
  45 + width: 50%;
  46 +}
  47 +#agenda .agenda-calendar .previous-month {
  48 +}
  49 +#agenda .agenda-calendar .next-month {
  50 + border-left: 1px solid #BFC2BC;
  51 +}
  52 +#agenda .selected {
  53 + background: #ff9;
  54 + font-style: normal;
  55 +}
  56 +#agenda td {
  57 + vertical-align: middle;
  58 +}
  59 +
  60 +#agenda .agenda-calendar .current-month caption {
  61 + margin-bottom: 10px;
  62 +}
  63 +
  64 +#agenda #events-of-the-day {
  65 + position: absolute;
  66 + left: 50%;
  67 + width: 45%;
  68 + top: 0px;
  69 + height: 100%;
  70 + border-left: 1px solid #BFC2BC;
  71 + padding-left: 20px;
  72 +}
  73 +
  74 +#agenda #events-of-the-day #agenda-items {
  75 + display: block;
  76 + overflow: auto;
  77 +}
  78 +
  79 +body.noosfero #content .no-boxes a.button.icon-back {
  80 + float: left;
  81 + position: absolute;
  82 + border: none;
  83 + opacity: 0.5;
  84 +}
public/stylesheets/controller_profile_members.css
@@ -44,11 +44,6 @@ @@ -44,11 +44,6 @@
44 position: relative; 44 position: relative;
45 } 45 }
46 46
47 -.loading {  
48 - cursor: progress;  
49 - background: transparent url(../images/loading.gif) no-repeat scroll center 50px;  
50 -}  
51 -  
52 table { 47 table {
53 text-align: left; 48 text-align: left;
54 } 49 }
test/functional/events_controller_test.rb 0 → 100644
@@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class EventsControllerTest < ActionController::TestCase
  4 +
  5 + def setup
  6 + @profile = create_user('testuser').person
  7 + end
  8 + attr_reader :profile
  9 +
  10 + should 'hide sideboxes when show calendar' do
  11 + get :events, :profile => profile.identifier
  12 + assert_no_tag :tag => 'div', :attributes => {:id => 'boxes'}
  13 + end
  14 +
  15 + should 'list today events by default' do
  16 + profile.events << Event.new(:name => 'Joao Birthday', :start_date => Date.today)
  17 + profile.events << Event.new(:name => 'Maria Birthday', :start_date => Date.today)
  18 +
  19 + get :events, :profile => profile.identifier
  20 +
  21 + today = Date.today.strftime("%B %d, %Y")
  22 + assert_tag :tag => 'div', :attributes => {:id => "agenda-items"},
  23 + :descendant => {:tag => 'h3', :content => "Events for #{today}"},
  24 + :descendant => {:tag => 'tr', :content => "Joao Birthday"},
  25 + :descendant => {:tag => 'tr', :content => "Maria Birthday"}
  26 + end
  27 +
  28 + should 'display calendar of current month' do
  29 + get :events, :profile => profile.identifier
  30 +
  31 + month = Date.today.strftime("%B %Y")
  32 + assert_tag :tag => 'table', :attributes => {:class => /current-month/}, :descendant => {:tag => 'caption', :content => /#{month}/}
  33 + end
  34 +
  35 + should 'display calendar of previous month' do
  36 + get :events, :profile => profile.identifier
  37 +
  38 + month = (Date.today << 1).strftime("%B %Y")
  39 + assert_tag :tag => 'table', :attributes => {:class => /previous-month/}, :descendant => {:tag => 'caption', :content => /#{month}/}
  40 + end
  41 +
  42 + should 'display calendar of next month' do
  43 + get :events, :profile => profile.identifier
  44 +
  45 + month = (Date.today >> 1).strftime("%B %Y")
  46 + assert_tag :tag => 'table', :attributes => {:class => /next-month/}, :descendant => {:tag => 'caption', :content => /#{month}/}
  47 + end
  48 +
  49 + should 'display links to previous and next month' do
  50 + get :events, :profile => profile.identifier
  51 +
  52 + prev_month = Date.today << 1
  53 + next_month = Date.today >> 1
  54 + assert_tag :tag =>'a', :attributes => {:href => "/profile/#{profile.identifier}/events/#{next_month.year}/#{next_month.month}"}, :content => /next/
  55 + assert_tag :tag =>'a', :attributes => {:href => "/profile/#{profile.identifier}/events/#{prev_month.year}/#{prev_month.month}"}, :content => /previous/
  56 + end
  57 +
  58 +end
test/functional/profile_controller_test.rb
@@ -657,4 +657,9 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -657,4 +657,9 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
657 assert_nil @request.session[:before_join] 657 assert_nil @request.session[:before_join]
658 end 658 end
659 659
  660 + should 'show link to events in index' do
  661 + get :index, :profile => profile.identifier
  662 + assert_tag :tag => 'a', :attributes => { :href => "/profile/#{profile.identifier}/events" }
  663 + end
  664 +
660 end 665 end
test/functional/search_controller_test.rb
@@ -682,7 +682,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase @@ -682,7 +682,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase
682 person = create_user('testuser').person 682 person = create_user('testuser').person
683 683
684 create_event(person, :name => 'upcoming event 1', :category_ids => [@category.id], :start_date => Date.new(2008, 1, 25)) 684 create_event(person, :name => 'upcoming event 1', :category_ids => [@category.id], :start_date => Date.new(2008, 1, 25))
685 - create_event(person, :name => 'upcoming event 2', :category_ids => [@category.id], :start_date => Date.new(2008, 2, 27)) 685 + create_event(person, :name => 'upcoming event 2', :category_ids => [@category.id], :start_date => Date.new(2008, 4, 27))
686 686
687 get :assets, :asset => 'events', :year => '2008', :month => '1' 687 get :assets, :asset => 'events', :year => '2008', :month => '1'
688 688
@@ -693,7 +693,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase @@ -693,7 +693,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase
693 person = create_user('testuser').person 693 person = create_user('testuser').person
694 694
695 create_event(person, :name => 'upcoming event 1', :category_ids => [@category.id], :start_date => Date.new(2008, 1, 25)) 695 create_event(person, :name => 'upcoming event 1', :category_ids => [@category.id], :start_date => Date.new(2008, 1, 25))
696 - create_event(person, :name => 'upcoming event 2', :category_ids => [@category.id], :start_date => Date.new(2008, 2, 27)) 696 + create_event(person, :name => 'upcoming event 2', :category_ids => [@category.id], :start_date => Date.new(2008, 4, 27))
697 697
698 get :assets, :asset => 'events', :category_path => [ 'my-category' ], :year => '2008', :month => '1' 698 get :assets, :asset => 'events', :category_path => [ 'my-category' ], :year => '2008', :month => '1'
699 699
@@ -875,11 +875,11 @@ class SearchControllerTest &lt; Test::Unit::TestCase @@ -875,11 +875,11 @@ class SearchControllerTest &lt; Test::Unit::TestCase
875 assert_equal 0, assigns(:calendar).size % 7 875 assert_equal 0, assigns(:calendar).size % 7
876 end 876 end
877 877
878 - should 'display current year/month by default' do 878 + should 'display current year/month by default as caption of current month' do
879 Date.expects(:today).returns(Date.new(2008, 8, 1)).at_least_once 879 Date.expects(:today).returns(Date.new(2008, 8, 1)).at_least_once
880 880
881 get :assets, :asset => 'events' 881 get :assets, :asset => 'events'
882 - assert_tag :tag => 'h1', :content => /^\s*August 2008\s*$/ 882 + assert_tag :tag => 'table', :attributes => {:class => /current-month/}, :descendant => {:tag => 'caption', :content => /August 2008/}
883 end 883 end
884 884
885 should 'submit search form to /search when viewing asset' do 885 should 'submit search form to /search when viewing asset' do
@@ -1001,6 +1001,55 @@ class SearchControllerTest &lt; Test::Unit::TestCase @@ -1001,6 +1001,55 @@ class SearchControllerTest &lt; Test::Unit::TestCase
1001 assert_includes assigns(:results)[:products], prod 1001 assert_includes assigns(:results)[:products], prod
1002 end 1002 end
1003 1003
  1004 + should 'show events of specific day' do
  1005 + person = create_user('anotheruser').person
  1006 + event = create_event(person, :name => 'Joao Birthday', :start_date => Date.new(2009, 10, 28))
  1007 +
  1008 + get :events_by_day, :year => 2009, :month => 10, :day => 28
  1009 +
  1010 + assert_tag :tag => 'a', :content => /Joao Birthday/
  1011 + end
  1012 +
  1013 + should 'filter events by category' do
  1014 + person = create_user('anotheruser').person
  1015 +
  1016 + searched_category = Category.create!(:name => 'Category with events', :environment => Environment.default)
  1017 +
  1018 + event_in_searched_category = create_event(person, :name => 'Maria Birthday', :start_date => Date.today, :category_ids => [searched_category.id])
  1019 + event_in_non_searched_category = create_event(person, :name => 'Joao Birthday', :start_date => Date.today, :category_ids => [@category.id])
  1020 +
  1021 + get :assets, :asset => 'events', :category_path => ['category-with-events']
  1022 +
  1023 + assert_includes assigns(:events_of_the_day), event_in_searched_category
  1024 + assert_not_includes assigns(:events_of_the_day), event_in_non_searched_category
  1025 + end
  1026 +
  1027 + should 'filter events by category of specific day' do
  1028 + person = create_user('anotheruser').person
  1029 +
  1030 + searched_category = Category.create!(:name => 'Category with events', :environment => Environment.default)
  1031 +
  1032 + event_in_searched_category = create_event(person, :name => 'Maria Birthday', :start_date => Date.new(2009, 10, 28), :category_ids => [searched_category.id])
  1033 + event_in_non_searched_category = create_event(person, :name => 'Joao Birthday', :start_date => Date.new(2009, 10, 28), :category_ids => [@category.id])
  1034 +
  1035 + get :events_by_day, :year => 2009, :month => 10, :day => 28, :category_id => searched_category.id
  1036 +
  1037 + assert_tag :tag => 'a', :content => /Maria Birthday/
  1038 + assert_no_tag :tag => 'a', :content => /Joao Birthday/
  1039 + end
  1040 +
  1041 + should 'ignore filter of events if category not exists' do
  1042 + person = create_user('anotheruser').person
  1043 + create_event(person, :name => 'Joao Birthday', :start_date => Date.new(2009, 10, 28), :category_ids => [@category.id])
  1044 + create_event(person, :name => 'Maria Birthday', :start_date => Date.new(2009, 10, 28))
  1045 +
  1046 + id_of_unexistent_category = Category.last.id + 10
  1047 +
  1048 + get :events_by_day, :year => 2009, :month => 10, :day => 28, :category_id => id_of_unexistent_category
  1049 +
  1050 + assert_tag :tag => 'a', :content => /Joao Birthday/
  1051 + assert_tag :tag => 'a', :content => /Maria Birthday/
  1052 + end
1004 1053
1005 ################################################################## 1054 ##################################################################
1006 ################################################################## 1055 ##################################################################
@@ -1011,4 +1060,5 @@ class SearchControllerTest &lt; Test::Unit::TestCase @@ -1011,4 +1060,5 @@ class SearchControllerTest &lt; Test::Unit::TestCase
1011 ev.save! 1060 ev.save!
1012 ev 1061 ev
1013 end 1062 end
  1063 +
1014 end 1064 end
test/unit/article_test.rb
@@ -801,4 +801,17 @@ class ArticleTest &lt; Test::Unit::TestCase @@ -801,4 +801,17 @@ class ArticleTest &lt; Test::Unit::TestCase
801 assert_equal 'changed-name', article.slug 801 assert_equal 'changed-name', article.slug
802 end 802 end
803 803
  804 + should 'find articles in a specific category' do
  805 + env = Environment.default
  806 + category_with_articles = env.categories.create!(:name => "Category with articles")
  807 + category_without_articles = env.categories.create!(:name => "Category without articles")
  808 +
  809 + article_in_category = profile.articles.create!(:name => 'Article in category')
  810 +
  811 + article_in_category.add_category(category_with_articles)
  812 +
  813 + assert_includes profile.articles.in_category(category_with_articles), article_in_category
  814 + assert_not_includes profile.articles.in_category(category_without_articles), article_in_category
  815 + end
  816 +
804 end 817 end
test/unit/category_finder_test.rb
@@ -464,4 +464,18 @@ class CategoryFinderTest &lt; ActiveSupport::TestCase @@ -464,4 +464,18 @@ class CategoryFinderTest &lt; ActiveSupport::TestCase
464 assert_not_includes list, art2 464 assert_not_includes list, art2
465 end 465 end
466 466
  467 + should 'find events in a date range' do
  468 + person = create_user('testuser').person
  469 +
  470 + date_range = Date.new(2009, 11, 28)..Date.new(2009, 12, 3)
  471 +
  472 + event_in_range = Event.create!(:name => 'Event in range', :profile => person, :start_date => Date.new(2009, 11, 27), :end_date => date_range.last, :category_ids => [@category.id])
  473 + event_out_of_range = Event.create!(:name => 'Event out of range', :profile => person, :start_date => Date.new(2009, 12, 4), :category_ids => [@category.id])
  474 +
  475 + events_found = @finder.find(:events, '', :date_range => date_range)
  476 +
  477 + assert_includes events_found, event_in_range
  478 + assert_not_includes events_found, event_out_of_range
  479 + end
  480 +
467 end 481 end
test/unit/dates_helper_test.rb
@@ -43,6 +43,12 @@ class DatesHelperTest &lt; Test::Unit::TestCase @@ -43,6 +43,12 @@ class DatesHelperTest &lt; Test::Unit::TestCase
43 assert_equal "Domingo", show_day_of_week(date) 43 assert_equal "Domingo", show_day_of_week(date)
44 end 44 end
45 45
  46 + should 'show abbreviated day of week' do
  47 + expects(:_).with("Sun").returns("Dom")
  48 + date = Date.new(2009, 10, 25)
  49 + assert_equal "Dom", show_day_of_week(date, true)
  50 + end
  51 +
46 should 'show month' do 52 should 'show month' do
47 expects(:_).with('January').returns('January') 53 expects(:_).with('January').returns('January')
48 expects(:_).with('%{month} %{year}').returns('%{month} %{year}') 54 expects(:_).with('%{month} %{year}').returns('%{month} %{year}')
@@ -58,35 +64,47 @@ class DatesHelperTest &lt; Test::Unit::TestCase @@ -58,35 +64,47 @@ class DatesHelperTest &lt; Test::Unit::TestCase
58 assert_equal 'November 2008', show_month('', '') 64 assert_equal 'November 2008', show_month('', '')
59 end 65 end
60 66
  67 + should 'show next month' do
  68 + expects(:_).with('November').returns('November').at_least_once
  69 + expects(:_).with('%{month} %{year}').returns('%{month} %{year}').at_least_once
  70 + assert_equal 'November 2009', show_month(2009, 10, :next => true)
  71 + end
  72 +
  73 + should 'show previous month' do
  74 + expects(:_).with('September').returns('September').at_least_once
  75 + expects(:_).with('%{month} %{year}').returns('%{month} %{year}').at_least_once
  76 + assert_equal 'September 2009', show_month(2009, 10, :previous => true)
  77 + end
  78 +
61 should 'provide link to previous month' do 79 should 'provide link to previous month' do
62 - expects(:link_to).with('&larr; January 2008', { :year => 2008, :month => 1}) 80 + expects(:link_to).with('January 2008', { :year => 2008, :month => 1})
63 link_to_previous_month('2008', '2') 81 link_to_previous_month('2008', '2')
64 end 82 end
65 83
66 should 'support last year in link to previous month' do 84 should 'support last year in link to previous month' do
67 - expects(:link_to).with('&larr; December 2007', { :year => 2007, :month => 12}) 85 + expects(:link_to).with('December 2007', { :year => 2007, :month => 12})
68 link_to_previous_month('2008', '1') 86 link_to_previous_month('2008', '1')
69 end 87 end
70 88
71 should 'provide link to next month' do 89 should 'provide link to next month' do
72 - expects(:link_to).with('March 2008 &rarr;', { :year => 2008, :month => 3}) 90 + expects(:link_to).with('March 2008', { :year => 2008, :month => 3})
73 link_to_next_month('2008', '2') 91 link_to_next_month('2008', '2')
74 end 92 end
75 93
76 should 'support next year in link to next month' do 94 should 'support next year in link to next month' do
77 - expects(:link_to).with('January 2009 &rarr;', { :year => 2009, :month => 1}) 95 + expects(:link_to).with('January 2009', { :year => 2009, :month => 1})
78 link_to_next_month('2008', '12') 96 link_to_next_month('2008', '12')
79 end 97 end
80 98
81 should 'get current date when year and month are not informed for next month' do 99 should 'get current date when year and month are not informed for next month' do
82 - Date.expects(:today).returns(Date.new(2008,1,1))  
83 - expects(:link_to).with('February 2008 &rarr;', { :year => 2008, :month => 2}) 100 + Date.stubs(:today).returns(Date.new(2008,1,1))
  101 + expects(:link_to).with('February 2008', { :year => 2008, :month => 2})
84 link_to_next_month(nil, nil) 102 link_to_next_month(nil, nil)
85 end 103 end
86 104
87 should 'get current date when year and month are not informed for previous month' do 105 should 'get current date when year and month are not informed for previous month' do
88 - Date.expects(:today).returns(Date.new(2008,1,1))  
89 - expects(:link_to).with('&larr; December 2007', { :year => 2007, :month => 12}) 106 + Date.stubs(:today).returns(Date.new(2008,1,1))
  107 + expects(:link_to).with('December 2007', { :year => 2007, :month => 12})
90 link_to_previous_month(nil, nil) 108 link_to_previous_month(nil, nil)
91 end 109 end
92 110
@@ -141,4 +159,16 @@ class DatesHelperTest &lt; Test::Unit::TestCase @@ -141,4 +159,16 @@ class DatesHelperTest &lt; Test::Unit::TestCase
141 assert_equal '', show_time(nil) 159 assert_equal '', show_time(nil)
142 end 160 end
143 161
  162 + should 'build date' do
  163 + assert_equal Date.new(2009, 10, 24), build_date(2009, 10, 24)
  164 + end
  165 +
  166 + should 'build date to day 1 by default' do
  167 + assert_equal Date.new(2009, 10, 1), build_date(2009, 10)
  168 + end
  169 +
  170 + should 'build today date when year and month are blank' do
  171 + assert_equal Date.new(Date.today.year, Date.today.month, 1), build_date('', '')
  172 + end
  173 +
144 end 174 end
test/unit/environment_finder_test.rb
@@ -323,4 +323,19 @@ class EnvironmentFinderTest &lt; ActiveSupport::TestCase @@ -323,4 +323,19 @@ class EnvironmentFinderTest &lt; ActiveSupport::TestCase
323 assert_equal 20, finder.find(:enterprises, 'test').total_entries 323 assert_equal 20, finder.find(:enterprises, 'test').total_entries
324 end 324 end
325 325
  326 + should 'find events in a date range' do
  327 + finder = EnvironmentFinder.new(Environment.default)
  328 + person = create_user('testuser').person
  329 +
  330 + date_range = Date.new(2009, 11, 28)..Date.new(2009, 12, 3)
  331 +
  332 + event_in_range = Event.create!(:name => 'Event in range', :profile => person, :start_date => Date.new(2009, 11, 27), :end_date => date_range.last)
  333 + event_out_of_range = Event.create!(:name => 'Event out of range', :profile => person, :start_date => Date.new(2009, 12, 4))
  334 +
  335 + events_found = finder.find(:events, '', :date_range => date_range)
  336 +
  337 + assert_includes events_found, event_in_range
  338 + assert_not_includes events_found, event_out_of_range
  339 + end
  340 +
326 end 341 end
test/unit/event_test.rb
@@ -76,35 +76,22 @@ class EventTest &lt; ActiveSupport::TestCase @@ -76,35 +76,22 @@ class EventTest &lt; ActiveSupport::TestCase
76 assert !e.errors.invalid?(:start_date) 76 assert !e.errors.invalid?(:start_date)
77 end 77 end
78 78
79 - should 'find by year and month' do 79 + should 'find by range of dates' do
80 profile = create_user('testuser').person 80 profile = create_user('testuser').person
81 e1 = Event.create!(:name => 'e1', :start_date => Date.new(2008,1,1), :profile => profile) 81 e1 = Event.create!(:name => 'e1', :start_date => Date.new(2008,1,1), :profile => profile)
82 e2 = Event.create!(:name => 'e2', :start_date => Date.new(2008,2,1), :profile => profile) 82 e2 = Event.create!(:name => 'e2', :start_date => Date.new(2008,2,1), :profile => profile)
83 e3 = Event.create!(:name => 'e3', :start_date => Date.new(2008,3,1), :profile => profile) 83 e3 = Event.create!(:name => 'e3', :start_date => Date.new(2008,3,1), :profile => profile)
84 84
85 - found = Event.by_month(2008, 2) 85 + found = Event.by_range(Date.new(2008, 1, 1)..Date.new(2008, 2, 28))
  86 + assert_includes found, e1
86 assert_includes found, e2 87 assert_includes found, e2
87 - assert_not_includes found, e1  
88 assert_not_includes found, e3 88 assert_not_includes found, e3
89 end 89 end
90 90
91 - should 'find when in first day of month' do 91 + should 'filter events by range' do
92 profile = create_user('testuser').person 92 profile = create_user('testuser').person
93 - e1 = Event.create!(:name => 'e1', :start_date => Date.new(2008,1,1), :profile => profile)  
94 - assert_includes Event.by_month(2008, 1), e1  
95 - end  
96 -  
97 - should 'find when in last day of month' do  
98 - profile = create_user('testuser').person  
99 - e1 = Event.create!(:name => 'e1', :start_date => Date.new(2008,1,31), :profile => profile)  
100 - assert_includes Event.by_month(2008, 1), e1  
101 - end  
102 -  
103 - should 'use current month by default' do  
104 - profile = create_user('testuser').person  
105 - e1 = Event.create!(:name => 'e1', :start_date => Date.new(2008,1,31), :profile => profile)  
106 - Date.expects(:today).returns(Date.new(2008, 1, 15))  
107 - assert_includes Event.by_month, e1 93 + e1 = Event.create!(:name => 'e1', :start_date => Date.new(2008,1,15), :profile => profile)
  94 + assert_includes profile.events.by_range(Date.new(2008, 1, 10)..Date.new(2008, 1, 20)), e1
108 end 95 end
109 96
110 should 'provide period for searching in month' do 97 should 'provide period for searching in month' do
@@ -184,4 +171,55 @@ class EventTest &lt; ActiveSupport::TestCase @@ -184,4 +171,55 @@ class EventTest &lt; ActiveSupport::TestCase
184 end 171 end
185 end 172 end
186 173
  174 + should 'list all events' do
  175 + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile')
  176 + event1 = Event.new(:name => 'Ze Birthday', :start_date => Date.today)
  177 + event2 = Event.new(:name => 'Mane Birthday', :start_date => Date.today >> 1)
  178 + profile.events << [event1, event2]
  179 + assert_includes profile.events, event1
  180 + assert_includes profile.events, event2
  181 + end
  182 +
  183 + should 'list events by day' do
  184 + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile')
  185 +
  186 + today = Date.today
  187 + yesterday_event = Event.new(:name => 'Joao Birthday', :start_date => today - 1.day)
  188 + today_event = Event.new(:name => 'Ze Birthday', :start_date => today)
  189 + tomorrow_event = Event.new(:name => 'Mane Birthday', :start_date => today + 1.day)
  190 +
  191 + profile.events << [yesterday_event, today_event, tomorrow_event]
  192 +
  193 + assert_equal [today_event], profile.events.by_day(today)
  194 + end
  195 +
  196 + should 'list events in a range' do
  197 + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile')
  198 +
  199 + today = Date.today
  200 + event_in_range = Event.new(:name => 'Noosfero Conference', :start_date => today - 2.day, :end_date => today + 2.day)
  201 + event_in_day = Event.new(:name => 'Ze Birthday', :start_date => today)
  202 +
  203 + profile.events << [event_in_range, event_in_day]
  204 +
  205 + assert_equal [event_in_range], profile.events.by_day(today - 1.day)
  206 + assert_equal [event_in_range], profile.events.by_day(today + 1.day)
  207 + assert_equal [event_in_range, event_in_day], profile.events.by_day(today)
  208 + end
  209 +
  210 + should 'not list events out of range' do
  211 + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile')
  212 +
  213 + today = Date.today
  214 + event_in_range1 = Event.new(:name => 'Foswiki Conference', :start_date => today - 2.day, :end_date => today + 2.day)
  215 + event_in_range2 = Event.new(:name => 'Debian Conference', :start_date => today - 2.day, :end_date => today + 3.day)
  216 + event_out_of_range = Event.new(:name => 'Ze Birthday', :start_date => today - 5.day, :end_date => today - 3.day)
  217 +
  218 + profile.events << [event_in_range1, event_in_range2, event_out_of_range]
  219 +
  220 + assert_includes profile.events.by_day(today), event_in_range1
  221 + assert_includes profile.events.by_day(today), event_in_range2
  222 + assert_not_includes profile.events.by_day(today), event_out_of_range
  223 + end
  224 +
187 end 225 end
test/unit/events_helper_test.rb 0 → 100644
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class EventsHelperTest < Test::Unit::TestCase
  4 +
  5 + include EventsHelper
  6 +
  7 + should 'list events' do
  8 + expects(:show_date).returns('')
  9 + expects(:_).with('Events for %s').returns('')
  10 + event1 = mock; event1.expects(:public?).returns(true); event1.expects(:name).returns('Event 1'); event1.expects(:url).returns({})
  11 + event2 = mock; event2.expects(:public?).returns(true); event2.expects(:name).returns('Event 2'); event2.expects(:url).returns({})
  12 + result = list_events('', [event1, event2])
  13 + assert_match /Event 1/, result
  14 + assert_match /Event 2/, result
  15 + end
  16 +
  17 + protected
  18 +
  19 + def content_tag(tag, text, options = {})
  20 + "<#{tag}>#{text}</#{tag}>"
  21 + end
  22 + def icon_for_article(article)
  23 + ''
  24 + end
  25 + def image_tag(arg)
  26 + arg
  27 + end
  28 + def link_to(text, url, options = {})
  29 + "<a href='#{url.to_s}'>#{text}</a>"
  30 + end
  31 +
  32 +end
test/unit/profile_test.rb
@@ -1402,6 +1402,66 @@ class ProfileTest &lt; Test::Unit::TestCase @@ -1402,6 +1402,66 @@ class ProfileTest &lt; Test::Unit::TestCase
1402 assert_equal 3, p.blogs.count 1402 assert_equal 3, p.blogs.count
1403 end 1403 end
1404 1404
  1405 + should 'list all events' do
  1406 + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile')
  1407 + event1 = Event.new(:name => 'Ze Birthday', :start_date => Date.today)
  1408 + event2 = Event.new(:name => 'Mane Birthday', :start_date => Date.today >> 1)
  1409 + profile.events << [event1, event2]
  1410 + assert_includes profile.events, event1
  1411 + assert_includes profile.events, event2
  1412 + end
  1413 +
  1414 + should 'list events by day' do
  1415 + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile')
  1416 +
  1417 + today = Date.today
  1418 + yesterday_event = Event.new(:name => 'Joao Birthday', :start_date => today - 1.day)
  1419 + today_event = Event.new(:name => 'Ze Birthday', :start_date => today)
  1420 + tomorrow_event = Event.new(:name => 'Mane Birthday', :start_date => today + 1.day)
  1421 +
  1422 + profile.events << [yesterday_event, today_event, tomorrow_event]
  1423 +
  1424 + assert_equal [today_event], profile.events.by_day(today)
  1425 + end
  1426 +
  1427 + should 'list events in a range' do
  1428 + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile')
  1429 +
  1430 + today = Date.today
  1431 + event_in_range = Event.new(:name => 'Noosfero Conference', :start_date => today - 2.day, :end_date => today + 2.day)
  1432 + event_in_day = Event.new(:name => 'Ze Birthday', :start_date => today)
  1433 +
  1434 + profile.events << [event_in_range, event_in_day]
  1435 +
  1436 + assert_equal [event_in_range], profile.events.by_day(today - 1.day)
  1437 + assert_equal [event_in_range], profile.events.by_day(today + 1.day)
  1438 + assert_equal [event_in_range, event_in_day], profile.events.by_day(today)
  1439 + end
  1440 +
  1441 + should 'not list events out of range' do
  1442 + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile')
  1443 +
  1444 + today = Date.today
  1445 + event_in_range1 = Event.new(:name => 'Foswiki Conference', :start_date => today - 2.day, :end_date => today + 2.day)
  1446 + event_in_range2 = Event.new(:name => 'Debian Conference', :start_date => today - 2.day, :end_date => today + 3.day)
  1447 + event_out_of_range = Event.new(:name => 'Ze Birthday', :start_date => today - 5.day, :end_date => today - 3.day)
  1448 +
  1449 + profile.events << [event_in_range1, event_in_range2, event_out_of_range]
  1450 +
  1451 + assert_includes profile.events.by_day(today), event_in_range1
  1452 + assert_includes profile.events.by_day(today), event_in_range2
  1453 + assert_not_includes profile.events.by_day(today), event_out_of_range
  1454 + end
  1455 +
  1456 + should 'sort events by name' do
  1457 + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile')
  1458 + event1 = Event.new(:name => 'Noosfero Hackaton', :start_date => Date.today)
  1459 + event2 = Event.new(:name => 'Debian Day', :start_date => Date.today)
  1460 + event3 = Event.new(:name => 'Fisl 10', :start_date => Date.today)
  1461 + profile.events << [event1, event2, event3]
  1462 + assert_equal [event2, event3, event1], profile.events
  1463 + end
  1464 +
1405 private 1465 private
1406 1466
1407 def assert_invalid_identifier(id) 1467 def assert_invalid_identifier(id)