diff --git a/app/controllers/public/events_controller.rb b/app/controllers/public/events_controller.rb new file mode 100644 index 0000000..9cadf1c --- /dev/null +++ b/app/controllers/public/events_controller.rb @@ -0,0 +1,33 @@ +class EventsController < PublicController + + needs_profile + no_design_blocks + + def events + @selected_day = nil + @events_of_the_day = [] + date = build_date(params[:year], params[:month], params[:day]) + + if params[:day] || !params[:year] && !params[:month] + @selected_day = date + @events_of_the_day = profile.events.by_day(@selected_day) + end + + events = profile.events.by_range(Event.first_day_of_month(date - 1.month)..Event.last_day_of_month(date + 1.month)) + + @calendar = populate_calendar(date, events) + @previous_calendar = populate_calendar(date - 1.month, events) + @next_calendar = populate_calendar(date + 1.month, events) + end + + def events_by_day + @selected_day = build_date(params[:year], params[:month], params[:day]) + @events_of_the_day = profile.events.by_day(@selected_day) + render :partial => 'events_by_day' + end + + protected + + include EventsHelper + +end diff --git a/app/controllers/public/search_controller.rb b/app/controllers/public/search_controller.rb index c7c5e02..40034c0 100644 --- a/app/controllers/public/search_controller.rb +++ b/app/controllers/public/search_controller.rb @@ -43,30 +43,26 @@ class SearchController < PublicController end def events - @events = @results[:events] - @calendar = Event.date_range(params[:year], params[:month]).map do |date| - [ - # the day itself - date, - # list of events of that day - @events.select do |event| - event.date_range.include?(date) - end, - # is this date in the current month? - true - ] - end - - # pad with days before - while @calendar.first.first.wday != 0 - @calendar.unshift([@calendar.first.first - 1.day, [], false]) + @category_id = @category ? @category.id : nil + + @selected_day = nil + @events_of_the_day = [] + date = build_date(params[:year], params[:month], params[:day]) + + if params[:day] || !params[:year] && !params[:month] + @selected_day = date + if @category_id and Category.exists?(@category_id) + @events_of_the_day = environment.events.by_day(@selected_day).in_category(Category.find(@category_id)) + else + @events_of_the_day = environment.events.by_day(@selected_day) + end end - # pad with days after (until Saturday) - while @calendar.last.first.wday != 6 - @calendar << [@calendar.last.first + 1.day, [], false] - end + events = @results[:events] + @calendar = populate_calendar(date, events) + @previous_calendar = populate_calendar(date - 1.month, events) + @next_calendar = populate_calendar(date + 1.month, events) end def people @@ -105,7 +101,8 @@ class SearchController < PublicController end if month || year - result[:date_range] = Event.date_range(year, month) + date = Date.new(year.to_i, month.to_i, 1) + result[:date_range] = (date - 1.month)..Event.last_day_of_month(date + 1.month) end result @@ -240,4 +237,14 @@ class SearchController < PublicController render :action => 'popup', :layout => false end + def events_by_day + @selected_day = build_date(params[:year], params[:month], params[:day]) + if params[:category_id] and Category.exists?(params[:category_id]) + @events_of_the_day = environment.events.by_day(@selected_day).in_category(Category.find(params[:category_id])) + else + @events_of_the_day = environment.events.by_day(@selected_day) + end + render :partial => 'events/events_by_day' + end + end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e0786c7..df9c88e 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -908,4 +908,8 @@ module ApplicationHelper javascript_tag('var array = ' + email.split('@').to_json + '; document.write("" + array.join("@") + "")') end + def stylesheet(*args) + content_for(:head) { stylesheet_link_tag(*args) } + end + end diff --git a/app/helpers/dates_helper.rb b/app/helpers/dates_helper.rb index 3771905..fb47d98 100644 --- a/app/helpers/dates_helper.rb +++ b/app/helpers/dates_helper.rb @@ -2,6 +2,7 @@ module DatesHelper include GetText + # FIXME Date#strftime should translate this for us !!!! MONTHS = [ N_('January'), N_('February'), @@ -49,43 +50,66 @@ module DatesHelper end end - def show_day_of_week(date) - # FIXME Date#strftime should translate this for us !!!! - _([ - N_('Sunday'), - N_('Monday'), - N_('Tuesday'), - N_('Wednesday'), - N_('Thursday'), - N_('Friday'), - N_('Saturday'), - ][date.wday]) + def show_day_of_week(date, abbreviated = false) + # FIXME Date#strftime should translate this for us !!!! + N_('Sun'); N_('Mon'); N_('Tue'); N_('Wed'); N_('Thu'); N_('Fri'); N_('Sat'); + if abbreviated + _(date.strftime("%a")) + else + # FIXME Date#strftime should translate this for us !!!! + _([ + N_('Sunday'), + N_('Monday'), + N_('Tuesday'), + N_('Wednesday'), + N_('Thursday'), + N_('Friday'), + N_('Saturday'), + ][date.wday]) + end end - def show_month(year, month) - - if year.blank? - year = Date.today.year - end - if month.blank? - month = Date.today.month + def show_month(year, month, opts = {}) + date = build_date(year, month) + if opts[:next] + date = date >> 1 + elsif opts[:previous] + date = date << 1 end + _('%{month} %{year}') % { :year => date.year, :month => month_name(date.month.to_i) } + end - _('%{month} %{year}') % { :year => year, :month => month_name(month.to_i) } + def build_date(year, month, day = 1) + if year.blank? and month.blank? and day.blank? + Date.today + else + if year.blank? + year = Date.today.year + end + if month.blank? + month = Date.today.month + end + if day.blank? + day = 1 + end + Date.new(year.to_i, month.to_i, day.to_i) + end end - def link_to_previous_month(year, month) - date = (year.blank? || month.blank?) ? Date.today : Date.new(year.to_i, month.to_i, 1) + def link_to_previous_month(year, month, label = nil) + date = build_date(year, month) previous_month_date = date - 1.month - link_to '← ' + show_month(previous_month_date.year, previous_month_date.month), :year => previous_month_date.year, :month => previous_month_date.month + label ||= show_month(previous_month_date.year, previous_month_date.month) + link_to label, :year => previous_month_date.year, :month => previous_month_date.month end - def link_to_next_month(year, month) - date = (year.blank? || month.blank?) ? Date.today : Date.new(year.to_i, month.to_i, 1) + def link_to_next_month(year, month, label = nil) + date = build_date(year, month) next_month_date = date + 1.month - link_to show_month(next_month_date.year, next_month_date.month) + ' →', :year => next_month_date.year, :month => next_month_date.month + label ||= show_month(next_month_date.year, next_month_date.month) + link_to label, :year => next_month_date.year, :month => next_month_date.month end def pick_date(object, method, options = {}, html_options = {}) diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb new file mode 100644 index 0000000..b5d209f --- /dev/null +++ b/app/helpers/events_helper.rb @@ -0,0 +1,48 @@ +module EventsHelper + + def list_events(date, events) + return content_tag('em', _("Select a day on the left to display it's events here"), :class => 'no-events') unless date + title = _('Events for %s') % show_date(date) + content_tag('h2', title) + + content_tag('div', + (events.any? ? + content_tag('table', events.select { |item| item.public? }.map {|item| display_event_in_listing(item)}.join('')) : + content_tag('em', _('No events for this date')) + ), :id => 'agenda-items' + ) + end + + def display_event_in_listing(article) + content_tag( + 'tr', + content_tag('td', link_to(image_tag(icon_for_article(article)) + article.name, article.url)), + :class => 'agenda-item' + ) + end + + def populate_calendar(selected_date, events) + calendar = Event.date_range(selected_date.year, selected_date.month).map do |date| + [ + # the day itself + date, + # is there any events in this date? + events.any? do |event| + event.date_range.include?(date) + end, + # is this date in the current month? + true + ] + end + # pad with days before + while calendar.first.first.wday != 0 + calendar.unshift([calendar.first.first - 1.day, false, false]) + end + + # pad with days after (until Saturday) + while calendar.last.first.wday != 6 + calendar << [calendar.last.first + 1.day, false, false] + end + calendar + end + +end diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 728742e..29f4648 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -1,5 +1,8 @@ module SearchHelper + # FIXME remove it after search_controler refactored + include EventsHelper + STOP_WORDS = { 'pt_BR' => Ferret::Analysis::FULL_PORTUGUESE_STOP_WORDS, 'en' => Ferret::Analysis::FULL_ENGLISH_STOP_WORDS, diff --git a/app/models/article.rb b/app/models/article.rb index 9e05f17..34f95c6 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -28,6 +28,10 @@ class Article < ActiveRecord::Base xss_terminate :only => [ :name ] + named_scope :in_category, lambda { |category| + {:include => 'categories', :conditions => { 'categories.id' => category.id }} + } + def self.human_attribute_name(attrib) case attrib.to_sym when :name diff --git a/app/models/category_finder.rb b/app/models/category_finder.rb index 539b61c..0879bad 100644 --- a/app/models/category_finder.rb +++ b/app/models/category_finder.rb @@ -104,7 +104,7 @@ class CategoryFinder when 'Event' conditions = if date_range - ['articles_categories.category_id = (?) and start_date between ? and ?', category_id, date_range.first, date_range.last] + ['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} ] else ['articles_categories.category_id = (?) ', category_id ] end diff --git a/app/models/environment_finder.rb b/app/models/environment_finder.rb index bbb1724..809d1d2 100644 --- a/app/models/environment_finder.rb +++ b/app/models/environment_finder.rb @@ -32,7 +32,10 @@ class EnvironmentFinder @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])) else if (asset == :events) && date_range - @environment.send(asset).send(finder_method, :all, options.merge(:conditions => { :start_date => date_range})) + @environment.send(asset).send(finder_method, :all, options.merge(:conditions => [ + 'start_date BETWEEN :start_day AND :end_day OR end_date BETWEEN :start_day AND :end_day', + {:start_day => date_range.first, :end_day => date_range.last} + ])) else @environment.send(asset).send(finder_method, :all, options) end diff --git a/app/models/event.rb b/app/models/event.rb index ce44583..c304881 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -16,6 +16,10 @@ class Event < Article end end + named_scope :by_day, lambda { |date| + {:conditions => ['start_date = :date AND end_date IS NULL OR (start_date <= :date AND end_date >= :date)', {:date => date}]} + } + def self.description _('A calendar event') end @@ -28,9 +32,12 @@ class Event < Article 'event' end - def self.by_month(year = nil, month = nil) - self.find(:all, :conditions => { :start_date => date_range(year, month) }) - end + named_scope :by_range, lambda { |range| { + :conditions => [ + 'start_date BETWEEN :start_day AND :end_day OR end_date BETWEEN :start_day AND :end_day', + { :start_day => range.first, :end_day => range.last } + ] + }} def self.date_range(year, month) if year.nil? || month.nil? @@ -43,11 +50,22 @@ class Event < Article end first_day = Date.new(year, month, 1) - last_day = Date.new(year, month, 1) + 1.month - 1.day + last_day = first_day + 1.month - 1.day first_day..last_day end + def self.first_day_of_month(date) + date ||= Date.today + Date.new(date.year, date.month, 1) + end + + def self.last_day_of_month(date) + date ||= Date.today + date >>= 1 + Date.new(date.year, date.month, 1) - 1.day + end + def date_range start_date..(end_date||start_date) end diff --git a/app/models/profile.rb b/app/models/profile.rb index 04aa0be..d094b05 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -115,6 +115,8 @@ class Profile < ActiveRecord::Base has_many :tasks, :dependent => :destroy, :as => 'target' + has_many :events, :source => 'articles', :class_name => 'Event', :order => 'name' + %w[ pending finished ].each do |status| class_eval <<-CODE def all_#{status}_tasks diff --git a/app/views/events/_agenda.rhtml b/app/views/events/_agenda.rhtml new file mode 100644 index 0000000..582bb04 --- /dev/null +++ b/app/views/events/_agenda.rhtml @@ -0,0 +1,24 @@ +
+
+ + + <%= render :partial => 'events/month', :locals => {:calendar => @calendar, :abbreviated => true} %> +
+

<%= show_month(params[:year], params[:month]) %>

+ <%= link_to_previous_month(params[:year], params[:month], '← previous') %> + <%= link_to_next_month(params[:year], params[:month], 'next →') %> +
+ + + <%= render :partial => 'events/month', :locals => {:calendar => @previous_calendar, :abbreviated => true} %> +

<%= link_to_previous_month(params[:year], params[:month], show_month(params[:year], params[:month], :previous => true)) %>

+ + + <%= render :partial => 'events/month', :locals => {:calendar => @next_calendar, :abbreviated => true} %> +

<%= link_to_next_month(params[:year], params[:month], show_month(params[:year], params[:month], :next => true)) %>

+
+
+
+ <%= render :partial => 'events/events_by_day' %> +
+
diff --git a/app/views/events/_events_by_day.rhtml b/app/views/events/_events_by_day.rhtml new file mode 100644 index 0000000..e8b37c6 --- /dev/null +++ b/app/views/events/_events_by_day.rhtml @@ -0,0 +1 @@ +<%= list_events(@selected_day, @events_of_the_day) %> diff --git a/app/views/events/_month.rhtml b/app/views/events/_month.rhtml new file mode 100644 index 0000000..a1aa702 --- /dev/null +++ b/app/views/events/_month.rhtml @@ -0,0 +1,25 @@ + + <% calendar.first(7).each do |day,event| %> + <%= show_day_of_week(day, abbreviated) %> + <% end %> + + <% calendar.in_groups_of(7).each do |week| %> + + <% week.each do |date, has_events, this_month| %> + + + <%= has_events ? + link_to_remote( + date.day, + :url => {:action => 'events_by_day', :year => date.year, :month => date.month, :day => date.day, :category_id => @category_id}, + :update => 'events-of-the-day', + :loading => '$("events-of-the-day").addClassName("loading")', + :complete => '$("events-of-the-day").removeClassName("loading")' + ) : + date.day + %> + + + <% end %> + + <% end %> diff --git a/app/views/events/events.rhtml b/app/views/events/events.rhtml new file mode 100644 index 0000000..a169bd1 --- /dev/null +++ b/app/views/events/events.rhtml @@ -0,0 +1,5 @@ +<%= button :back, _('Back to %s') % profile.name, profile.public_profile_url %> + +

<%= _("%s's events") % profile.name %>

+ +<%= render :partial => 'agenda' %> diff --git a/app/views/layouts/application-ng.rhtml b/app/views/layouts/application-ng.rhtml index 7e0c3c5..e998933 100644 --- a/app/views/layouts/application-ng.rhtml +++ b/app/views/layouts/application-ng.rhtml @@ -18,6 +18,8 @@ theme_stylesheet_path(), pngfix_stylesheet_path() ) %> + <%# Add custom tags/styles/etc via content_for %> + <%= yield :head %> true) %> - <%= template_stylesheet_tag %> <%= icon_theme_stylesheet_tag %> <%= pngfix_stylesheet %> + + <%# Add custom tags/styles/etc via content_for %> + <%= yield :head %> 'events', :action => 'events' %> + + + + <%= _('Tags:') %> diff --git a/app/views/search/events.rhtml b/app/views/search/events.rhtml index e262c9c..a7584d0 100644 --- a/app/views/search/events.rhtml +++ b/app/views/search/events.rhtml @@ -1,40 +1,9 @@

<% if @category %> - <%= @category.name %>: + <%= @category.name %> <% end %> - <%= show_month(params[:year], params[:month]) %>

-
- <%= link_to_previous_month(params[:year], params[:month]) %> -   -   -   - <%= link_to_next_month(params[:year], params[:month]) %> -
+<% stylesheet 'controller_events' %> - - - <% @calendar.first(7).each do |day,event| %> - - <% end %> - - <% @calendar.in_groups_of(7).each do |week| %> - - <% week.each do |date, events, this_month| %> - - <% end %> - - <% end %> -
<%= show_day_of_week(day) %>
-
- <%= date.day %> -
- - <% events.each do |event| %> -
- <%= link_to event.name, event.url, :style => 'display: block;' %> -
- <% end %> - -
+<%= render :partial => 'events/agenda' %> diff --git a/config/routes.rb b/config/routes.rb index 769dcd8..d99781f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -47,6 +47,11 @@ ActionController::Routing::Routes.draw do |map| # search map.connect 'search/:action/*category_path', :controller => 'search' + # 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}/ + map.events 'profile/:profile/events/:year/:month', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :profile => /#{Noosfero.identifier_format}/ + map.events 'profile/:profile/events', :controller => 'events', :action => 'events', :profile => /#{Noosfero.identifier_format}/ # public profile information map.profile 'profile/:profile/:action/:id', :controller => 'profile', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format}/ diff --git a/features/events.feature b/features/events.feature new file mode 100644 index 0000000..8c42267 --- /dev/null +++ b/features/events.feature @@ -0,0 +1,151 @@ +Feature: events + As a noosfero visitor + I want to see some events + + Background: + Given the following users + | login | + | josesilva | + And the following events + | owner | name | start_date | + | josesilva | Another Conference | 2009-10-24 | + + Scenario: go to next month + Given I am on /profile/josesilva/events/2009/10 + When I follow "next →" + Then I should see "November 2009" within ".current-month" + + Scenario: go to next month in global agenda + Given I am on /assets/events?year=2009&month=11 + When I follow "next →" + Then I should see "December 2009" within ".current-month" + + Scenario: go to previous month + Given I am on /profile/josesilva/events/2009/10 + When I follow "← previous" + Then I should see "September 2009" within ".current-month" + + Scenario: go to previous month in global agenda + Given I am on /assets/events?year=2009&month=11 + When I follow "← previous" + Then I should see "October 2009" within ".current-month" + + Scenario: go to next month by clicking in month name + Given I am on /profile/josesilva/events/2009/10 + When I follow "November 2009" + Then I should see "November 2009" within ".current-month" + + Scenario: go to previous month by clicking in month name + Given I am on /profile/josesilva/events/2009/10 + When I follow "September 2009" + Then I should see "September 2009" within ".current-month" + + Scenario: go to specific day + Given I am on the homepage + When I am on /profile/josesilva/events/2009/01/20 + Then I should see "Events for January 20, 2009" + + Scenario: go to specific day in global agenda + Given I am on the homepage + When I am on /assets/events?year=2009&month=11&day=12 + Then I should see "Events for November 12, 2009" + + Scenario: list events for specific day + Given I am on /profile/josesilva/events/2009/10 + And the following events + | owner | name | start_date | + | josesilva | WikiSym 2009 | 2009-10-25 | + When I am on /profile/josesilva/events/2009/10/25 + Then I should see "WikiSym 2009" + + Scenario: dont list events for non-selected day + Given I am on /profile/josesilva/events/2009/10 + And the following events + | owner | name | start_date | + | josesilva | WikiSym 2009 | 2009-10-25 | + When I am on /profile/josesilva/events/2009/10/20 + Then I should not see "WikiSym 2009" + + Scenario: list event between a range + Given I am on /profile/josesilva/events/2009/10 + And the following events + | owner | name | start_date | end_date | + | josesilva | WikiSym 2009 | 2009-10-25 | 2009-10-27 | + When I am on /profile/josesilva/events/2009/10/26 + Then I should see "WikiSym 2009" + + Scenario: dont list events from other profiles + Given the following users + | login | + | josemanuel | + And the following events + | owner | name | start_date | + | josemanuel | Manuel Birthday | 2009-10-24 | + When I am on /profile/josesilva/events/2009/10/24 + Then I should see "Another Conference" + And I should not see "Manuel Birthday" + + Scenario: list all events in global agenda + Given the following users + | login | + | josemanuel | + And the following events + | owner | name | start_date | + | josemanuel | Manuel Birthday | 2009-10-24 | + When I am on /assets/events?year=2009&month=10&day=24 + Then I should see "Another Conference" + And I should see "Manuel Birthday" + + Scenario: ask for a day when no inform complete date + When I am on /profile/josesilva/events/2009/5 + Then I should see "Select a day on the left to display it's events here" + + Scenario: ask for a day when no inform complete date in global agenda + When I am on /assets/events?year=2009&month=5 + Then I should see "Select a day on the left to display it's events here" + + Scenario: provide links to days with events + Given I am on /profile/josesilva/events/2009/10 + Then I should see "24" link + When I follow "next →" + Then I should see "24" link + When I follow "next →" + Then I should not see "24" link + + Scenario: provide links to all days between start and end date + Given the following users + | login | + | fudencio | + And the following events + | owner | name | start_date | end_date | + | fudencio | YAPC::Brasil 2009 | 2010-10-30 | 2010-11-01 | + And I am on /profile/fudencio/events/2010/10 + Then I should not see "29" link + And I should see "30" link + And I should see "31" link + And I should see "1" link + + @selenium + Scenario: show events when i follow a specific day + Given I am on /profile/josesilva/events/2009/10 + And I should not see "Another Conference" + When I follow "24" + Then I should see "Another Conference" + + @selenium + Scenario: show events in a range when i follow a specific day + Given the following events + | owner | name | start_date | end_date | + | josesilva | YAPC::Brasil 2010 | 2010-10-30 | 2010-11-01 | + And I am on /profile/josesilva/events/2010/10 + And I should not see "YAPC::Brasil 2010" + When I follow "31" + Then I should see "YAPC::Brasil 2010" + + Scenario: provide button to back from profile + When I am on /profile/josesilva/events + Then I should see "Back to josesilva" link + + Scenario: warn when there is no events + When I am on /profile/josesilva/events/2020/12/1 + Then I should see "No events for this date" diff --git a/features/step_definitions/webrat_steps.rb b/features/step_definitions/webrat_steps.rb index 2cd3cc2..7f5c575 100644 --- a/features/step_definitions/webrat_steps.rb +++ b/features/step_definitions/webrat_steps.rb @@ -188,6 +188,10 @@ Then /^show me the page$/ do save_and_open_page end -Then /^the source should contain tag ([^\"]+)$/ do |tag| - response_body.should have_tag(tag, {id => 10}) +When /^I should see "([^\"]+)" link$/ do |link| + response.should have_selector("a", :content => link) +end + +When /^I should not see "([^\"]+)" link$/ do |link| + response.should_not have_selector("a", :content => link) end diff --git a/public/stylesheets/common.css b/public/stylesheets/common.css index 8d36ad2..ec97a3f 100644 --- a/public/stylesheets/common.css +++ b/public/stylesheets/common.css @@ -327,17 +327,22 @@ div.pending-tasks { margin-bottom: 20px; } -/* sitemap */ +/* sitemap and agenda */ + .sitemap-item a:link, -.sitemap-item a:visited { +.agenda-item a:link, +.sitemap-item a:visited, +.agenda-item a:visited { display: block; border: none; text-decoration: none; } -.sitemap-item img { +.sitemap-item img, +.agenda-item img { border: none; } -.sitemap-item a:hover { +.sitemap-item a:hover, +.agenda-item a:hover { background: #e0e0e0; color: red; text-decoration: underline; @@ -346,7 +351,6 @@ div.pending-tasks { font-size: small; } - /* * * icons for product category on profile * * */ #content .product-category-icons { @@ -593,3 +597,10 @@ div.pending-tasks { code input { font-family: monospace; } + +/** LOADING... **/ + +.loading { + cursor: progress; + background: transparent url(../images/loading.gif) no-repeat scroll center 50px; +} diff --git a/public/stylesheets/controller_events.css b/public/stylesheets/controller_events.css new file mode 100644 index 0000000..00b978c --- /dev/null +++ b/public/stylesheets/controller_events.css @@ -0,0 +1,84 @@ +#agenda { + position: relative; + width: 100%; +} + +#agenda .agenda-calendar { + width: 50%; +} + +#agenda td, #agenda th { + padding: 0px; +} + +#agenda .agenda-calendar .previous-month td, +#agenda .agenda-calendar .previous-month th, +#agenda .agenda-calendar .next-month td, +#agenda .agenda-calendar .next-month th { + font-size: 10px; + color: gray; +} +#agenda .agenda-calendar .current-month td { +} +#agenda .agenda-calendar .calendar-day { +} +#agenda .agenda-calendar .calendar-day-out { + color: gray; +} +#agenda .agenda-calendar .calendar-day-out span { + display: none; +} +#agenda .agenda-calendar td { + text-align: center; + padding: 0px; +} +#agenda .agenda-calendar h3 { + font-size: 12px; +} +#agenda .agenda-calendar .current-month { + height: 250px; + border-bottom: 1px solid #BFC2BC; +} +#agenda .agenda-calendar .previous-month, +#agenda .agenda-calendar .next-month { + float: left; + width: 50%; +} +#agenda .agenda-calendar .previous-month { +} +#agenda .agenda-calendar .next-month { + border-left: 1px solid #BFC2BC; +} +#agenda .selected { + background: #ff9; + font-style: normal; +} +#agenda td { + vertical-align: middle; +} + +#agenda .agenda-calendar .current-month caption { + margin-bottom: 10px; +} + +#agenda #events-of-the-day { + position: absolute; + left: 50%; + width: 45%; + top: 0px; + height: 100%; + border-left: 1px solid #BFC2BC; + padding-left: 20px; +} + +#agenda #events-of-the-day #agenda-items { + display: block; + overflow: auto; +} + +body.noosfero #content .no-boxes a.button.icon-back { + float: left; + position: absolute; + border: none; + opacity: 0.5; +} diff --git a/public/stylesheets/controller_profile_members.css b/public/stylesheets/controller_profile_members.css index fd795df..601c03f 100644 --- a/public/stylesheets/controller_profile_members.css +++ b/public/stylesheets/controller_profile_members.css @@ -44,11 +44,6 @@ position: relative; } -.loading { - cursor: progress; - background: transparent url(../images/loading.gif) no-repeat scroll center 50px; -} - table { text-align: left; } diff --git a/test/functional/events_controller_test.rb b/test/functional/events_controller_test.rb new file mode 100644 index 0000000..c503a35 --- /dev/null +++ b/test/functional/events_controller_test.rb @@ -0,0 +1,58 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class EventsControllerTest < ActionController::TestCase + + def setup + @profile = create_user('testuser').person + end + attr_reader :profile + + should 'hide sideboxes when show calendar' do + get :events, :profile => profile.identifier + assert_no_tag :tag => 'div', :attributes => {:id => 'boxes'} + end + + should 'list today events by default' do + profile.events << Event.new(:name => 'Joao Birthday', :start_date => Date.today) + profile.events << Event.new(:name => 'Maria Birthday', :start_date => Date.today) + + get :events, :profile => profile.identifier + + today = Date.today.strftime("%B %d, %Y") + assert_tag :tag => 'div', :attributes => {:id => "agenda-items"}, + :descendant => {:tag => 'h3', :content => "Events for #{today}"}, + :descendant => {:tag => 'tr', :content => "Joao Birthday"}, + :descendant => {:tag => 'tr', :content => "Maria Birthday"} + end + + should 'display calendar of current month' do + get :events, :profile => profile.identifier + + month = Date.today.strftime("%B %Y") + assert_tag :tag => 'table', :attributes => {:class => /current-month/}, :descendant => {:tag => 'caption', :content => /#{month}/} + end + + should 'display calendar of previous month' do + get :events, :profile => profile.identifier + + month = (Date.today << 1).strftime("%B %Y") + assert_tag :tag => 'table', :attributes => {:class => /previous-month/}, :descendant => {:tag => 'caption', :content => /#{month}/} + end + + should 'display calendar of next month' do + get :events, :profile => profile.identifier + + month = (Date.today >> 1).strftime("%B %Y") + assert_tag :tag => 'table', :attributes => {:class => /next-month/}, :descendant => {:tag => 'caption', :content => /#{month}/} + end + + should 'display links to previous and next month' do + get :events, :profile => profile.identifier + + prev_month = Date.today << 1 + next_month = Date.today >> 1 + assert_tag :tag =>'a', :attributes => {:href => "/profile/#{profile.identifier}/events/#{next_month.year}/#{next_month.month}"}, :content => /next/ + assert_tag :tag =>'a', :attributes => {:href => "/profile/#{profile.identifier}/events/#{prev_month.year}/#{prev_month.month}"}, :content => /previous/ + end + +end diff --git a/test/functional/profile_controller_test.rb b/test/functional/profile_controller_test.rb index a7873c4..9265ad4 100644 --- a/test/functional/profile_controller_test.rb +++ b/test/functional/profile_controller_test.rb @@ -657,4 +657,9 @@ class ProfileControllerTest < Test::Unit::TestCase assert_nil @request.session[:before_join] end + should 'show link to events in index' do + get :index, :profile => profile.identifier + assert_tag :tag => 'a', :attributes => { :href => "/profile/#{profile.identifier}/events" } + end + end diff --git a/test/functional/search_controller_test.rb b/test/functional/search_controller_test.rb index 2a0163f..f77ee37 100644 --- a/test/functional/search_controller_test.rb +++ b/test/functional/search_controller_test.rb @@ -682,7 +682,7 @@ class SearchControllerTest < Test::Unit::TestCase person = create_user('testuser').person create_event(person, :name => 'upcoming event 1', :category_ids => [@category.id], :start_date => Date.new(2008, 1, 25)) - create_event(person, :name => 'upcoming event 2', :category_ids => [@category.id], :start_date => Date.new(2008, 2, 27)) + create_event(person, :name => 'upcoming event 2', :category_ids => [@category.id], :start_date => Date.new(2008, 4, 27)) get :assets, :asset => 'events', :year => '2008', :month => '1' @@ -693,7 +693,7 @@ class SearchControllerTest < Test::Unit::TestCase person = create_user('testuser').person create_event(person, :name => 'upcoming event 1', :category_ids => [@category.id], :start_date => Date.new(2008, 1, 25)) - create_event(person, :name => 'upcoming event 2', :category_ids => [@category.id], :start_date => Date.new(2008, 2, 27)) + create_event(person, :name => 'upcoming event 2', :category_ids => [@category.id], :start_date => Date.new(2008, 4, 27)) get :assets, :asset => 'events', :category_path => [ 'my-category' ], :year => '2008', :month => '1' @@ -875,11 +875,11 @@ class SearchControllerTest < Test::Unit::TestCase assert_equal 0, assigns(:calendar).size % 7 end - should 'display current year/month by default' do + should 'display current year/month by default as caption of current month' do Date.expects(:today).returns(Date.new(2008, 8, 1)).at_least_once get :assets, :asset => 'events' - assert_tag :tag => 'h1', :content => /^\s*August 2008\s*$/ + assert_tag :tag => 'table', :attributes => {:class => /current-month/}, :descendant => {:tag => 'caption', :content => /August 2008/} end should 'submit search form to /search when viewing asset' do @@ -1001,6 +1001,55 @@ class SearchControllerTest < Test::Unit::TestCase assert_includes assigns(:results)[:products], prod end + should 'show events of specific day' do + person = create_user('anotheruser').person + event = create_event(person, :name => 'Joao Birthday', :start_date => Date.new(2009, 10, 28)) + + get :events_by_day, :year => 2009, :month => 10, :day => 28 + + assert_tag :tag => 'a', :content => /Joao Birthday/ + end + + should 'filter events by category' do + person = create_user('anotheruser').person + + searched_category = Category.create!(:name => 'Category with events', :environment => Environment.default) + + event_in_searched_category = create_event(person, :name => 'Maria Birthday', :start_date => Date.today, :category_ids => [searched_category.id]) + event_in_non_searched_category = create_event(person, :name => 'Joao Birthday', :start_date => Date.today, :category_ids => [@category.id]) + + get :assets, :asset => 'events', :category_path => ['category-with-events'] + + assert_includes assigns(:events_of_the_day), event_in_searched_category + assert_not_includes assigns(:events_of_the_day), event_in_non_searched_category + end + + should 'filter events by category of specific day' do + person = create_user('anotheruser').person + + searched_category = Category.create!(:name => 'Category with events', :environment => Environment.default) + + event_in_searched_category = create_event(person, :name => 'Maria Birthday', :start_date => Date.new(2009, 10, 28), :category_ids => [searched_category.id]) + event_in_non_searched_category = create_event(person, :name => 'Joao Birthday', :start_date => Date.new(2009, 10, 28), :category_ids => [@category.id]) + + get :events_by_day, :year => 2009, :month => 10, :day => 28, :category_id => searched_category.id + + assert_tag :tag => 'a', :content => /Maria Birthday/ + assert_no_tag :tag => 'a', :content => /Joao Birthday/ + end + + should 'ignore filter of events if category not exists' do + person = create_user('anotheruser').person + create_event(person, :name => 'Joao Birthday', :start_date => Date.new(2009, 10, 28), :category_ids => [@category.id]) + create_event(person, :name => 'Maria Birthday', :start_date => Date.new(2009, 10, 28)) + + id_of_unexistent_category = Category.last.id + 10 + + get :events_by_day, :year => 2009, :month => 10, :day => 28, :category_id => id_of_unexistent_category + + assert_tag :tag => 'a', :content => /Joao Birthday/ + assert_tag :tag => 'a', :content => /Maria Birthday/ + end ################################################################## ################################################################## @@ -1011,4 +1060,5 @@ class SearchControllerTest < Test::Unit::TestCase ev.save! ev end + end diff --git a/test/unit/article_test.rb b/test/unit/article_test.rb index db98290..d0fa383 100644 --- a/test/unit/article_test.rb +++ b/test/unit/article_test.rb @@ -801,4 +801,17 @@ class ArticleTest < Test::Unit::TestCase assert_equal 'changed-name', article.slug end + should 'find articles in a specific category' do + env = Environment.default + category_with_articles = env.categories.create!(:name => "Category with articles") + category_without_articles = env.categories.create!(:name => "Category without articles") + + article_in_category = profile.articles.create!(:name => 'Article in category') + + article_in_category.add_category(category_with_articles) + + assert_includes profile.articles.in_category(category_with_articles), article_in_category + assert_not_includes profile.articles.in_category(category_without_articles), article_in_category + end + end diff --git a/test/unit/category_finder_test.rb b/test/unit/category_finder_test.rb index 7e09ab6..264bf73 100644 --- a/test/unit/category_finder_test.rb +++ b/test/unit/category_finder_test.rb @@ -464,4 +464,18 @@ class CategoryFinderTest < ActiveSupport::TestCase assert_not_includes list, art2 end + should 'find events in a date range' do + person = create_user('testuser').person + + date_range = Date.new(2009, 11, 28)..Date.new(2009, 12, 3) + + 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]) + event_out_of_range = Event.create!(:name => 'Event out of range', :profile => person, :start_date => Date.new(2009, 12, 4), :category_ids => [@category.id]) + + events_found = @finder.find(:events, '', :date_range => date_range) + + assert_includes events_found, event_in_range + assert_not_includes events_found, event_out_of_range + end + end diff --git a/test/unit/dates_helper_test.rb b/test/unit/dates_helper_test.rb index fe3894e..2644241 100644 --- a/test/unit/dates_helper_test.rb +++ b/test/unit/dates_helper_test.rb @@ -43,6 +43,12 @@ class DatesHelperTest < Test::Unit::TestCase assert_equal "Domingo", show_day_of_week(date) end + should 'show abbreviated day of week' do + expects(:_).with("Sun").returns("Dom") + date = Date.new(2009, 10, 25) + assert_equal "Dom", show_day_of_week(date, true) + end + should 'show month' do expects(:_).with('January').returns('January') expects(:_).with('%{month} %{year}').returns('%{month} %{year}') @@ -58,35 +64,47 @@ class DatesHelperTest < Test::Unit::TestCase assert_equal 'November 2008', show_month('', '') end + should 'show next month' do + expects(:_).with('November').returns('November').at_least_once + expects(:_).with('%{month} %{year}').returns('%{month} %{year}').at_least_once + assert_equal 'November 2009', show_month(2009, 10, :next => true) + end + + should 'show previous month' do + expects(:_).with('September').returns('September').at_least_once + expects(:_).with('%{month} %{year}').returns('%{month} %{year}').at_least_once + assert_equal 'September 2009', show_month(2009, 10, :previous => true) + end + should 'provide link to previous month' do - expects(:link_to).with('← January 2008', { :year => 2008, :month => 1}) + expects(:link_to).with('January 2008', { :year => 2008, :month => 1}) link_to_previous_month('2008', '2') end should 'support last year in link to previous month' do - expects(:link_to).with('← December 2007', { :year => 2007, :month => 12}) + expects(:link_to).with('December 2007', { :year => 2007, :month => 12}) link_to_previous_month('2008', '1') end should 'provide link to next month' do - expects(:link_to).with('March 2008 →', { :year => 2008, :month => 3}) + expects(:link_to).with('March 2008', { :year => 2008, :month => 3}) link_to_next_month('2008', '2') end should 'support next year in link to next month' do - expects(:link_to).with('January 2009 →', { :year => 2009, :month => 1}) + expects(:link_to).with('January 2009', { :year => 2009, :month => 1}) link_to_next_month('2008', '12') end should 'get current date when year and month are not informed for next month' do - Date.expects(:today).returns(Date.new(2008,1,1)) - expects(:link_to).with('February 2008 →', { :year => 2008, :month => 2}) + Date.stubs(:today).returns(Date.new(2008,1,1)) + expects(:link_to).with('February 2008', { :year => 2008, :month => 2}) link_to_next_month(nil, nil) end should 'get current date when year and month are not informed for previous month' do - Date.expects(:today).returns(Date.new(2008,1,1)) - expects(:link_to).with('← December 2007', { :year => 2007, :month => 12}) + Date.stubs(:today).returns(Date.new(2008,1,1)) + expects(:link_to).with('December 2007', { :year => 2007, :month => 12}) link_to_previous_month(nil, nil) end @@ -141,4 +159,16 @@ class DatesHelperTest < Test::Unit::TestCase assert_equal '', show_time(nil) end + should 'build date' do + assert_equal Date.new(2009, 10, 24), build_date(2009, 10, 24) + end + + should 'build date to day 1 by default' do + assert_equal Date.new(2009, 10, 1), build_date(2009, 10) + end + + should 'build today date when year and month are blank' do + assert_equal Date.new(Date.today.year, Date.today.month, 1), build_date('', '') + end + end diff --git a/test/unit/environment_finder_test.rb b/test/unit/environment_finder_test.rb index 6b81fb2..24cd435 100644 --- a/test/unit/environment_finder_test.rb +++ b/test/unit/environment_finder_test.rb @@ -323,4 +323,19 @@ class EnvironmentFinderTest < ActiveSupport::TestCase assert_equal 20, finder.find(:enterprises, 'test').total_entries end + should 'find events in a date range' do + finder = EnvironmentFinder.new(Environment.default) + person = create_user('testuser').person + + date_range = Date.new(2009, 11, 28)..Date.new(2009, 12, 3) + + event_in_range = Event.create!(:name => 'Event in range', :profile => person, :start_date => Date.new(2009, 11, 27), :end_date => date_range.last) + event_out_of_range = Event.create!(:name => 'Event out of range', :profile => person, :start_date => Date.new(2009, 12, 4)) + + events_found = finder.find(:events, '', :date_range => date_range) + + assert_includes events_found, event_in_range + assert_not_includes events_found, event_out_of_range + end + end diff --git a/test/unit/event_test.rb b/test/unit/event_test.rb index 45c2496..6357730 100644 --- a/test/unit/event_test.rb +++ b/test/unit/event_test.rb @@ -76,35 +76,22 @@ class EventTest < ActiveSupport::TestCase assert !e.errors.invalid?(:start_date) end - should 'find by year and month' do + should 'find by range of dates' do profile = create_user('testuser').person e1 = Event.create!(:name => 'e1', :start_date => Date.new(2008,1,1), :profile => profile) e2 = Event.create!(:name => 'e2', :start_date => Date.new(2008,2,1), :profile => profile) e3 = Event.create!(:name => 'e3', :start_date => Date.new(2008,3,1), :profile => profile) - found = Event.by_month(2008, 2) + found = Event.by_range(Date.new(2008, 1, 1)..Date.new(2008, 2, 28)) + assert_includes found, e1 assert_includes found, e2 - assert_not_includes found, e1 assert_not_includes found, e3 end - should 'find when in first day of month' do + should 'filter events by range' do profile = create_user('testuser').person - e1 = Event.create!(:name => 'e1', :start_date => Date.new(2008,1,1), :profile => profile) - assert_includes Event.by_month(2008, 1), e1 - end - - should 'find when in last day of month' do - profile = create_user('testuser').person - e1 = Event.create!(:name => 'e1', :start_date => Date.new(2008,1,31), :profile => profile) - assert_includes Event.by_month(2008, 1), e1 - end - - should 'use current month by default' do - profile = create_user('testuser').person - e1 = Event.create!(:name => 'e1', :start_date => Date.new(2008,1,31), :profile => profile) - Date.expects(:today).returns(Date.new(2008, 1, 15)) - assert_includes Event.by_month, e1 + e1 = Event.create!(:name => 'e1', :start_date => Date.new(2008,1,15), :profile => profile) + assert_includes profile.events.by_range(Date.new(2008, 1, 10)..Date.new(2008, 1, 20)), e1 end should 'provide period for searching in month' do @@ -184,4 +171,55 @@ class EventTest < ActiveSupport::TestCase end end + should 'list all events' do + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile') + event1 = Event.new(:name => 'Ze Birthday', :start_date => Date.today) + event2 = Event.new(:name => 'Mane Birthday', :start_date => Date.today >> 1) + profile.events << [event1, event2] + assert_includes profile.events, event1 + assert_includes profile.events, event2 + end + + should 'list events by day' do + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile') + + today = Date.today + yesterday_event = Event.new(:name => 'Joao Birthday', :start_date => today - 1.day) + today_event = Event.new(:name => 'Ze Birthday', :start_date => today) + tomorrow_event = Event.new(:name => 'Mane Birthday', :start_date => today + 1.day) + + profile.events << [yesterday_event, today_event, tomorrow_event] + + assert_equal [today_event], profile.events.by_day(today) + end + + should 'list events in a range' do + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile') + + today = Date.today + event_in_range = Event.new(:name => 'Noosfero Conference', :start_date => today - 2.day, :end_date => today + 2.day) + event_in_day = Event.new(:name => 'Ze Birthday', :start_date => today) + + profile.events << [event_in_range, event_in_day] + + assert_equal [event_in_range], profile.events.by_day(today - 1.day) + assert_equal [event_in_range], profile.events.by_day(today + 1.day) + assert_equal [event_in_range, event_in_day], profile.events.by_day(today) + end + + should 'not list events out of range' do + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile') + + today = Date.today + event_in_range1 = Event.new(:name => 'Foswiki Conference', :start_date => today - 2.day, :end_date => today + 2.day) + event_in_range2 = Event.new(:name => 'Debian Conference', :start_date => today - 2.day, :end_date => today + 3.day) + event_out_of_range = Event.new(:name => 'Ze Birthday', :start_date => today - 5.day, :end_date => today - 3.day) + + profile.events << [event_in_range1, event_in_range2, event_out_of_range] + + assert_includes profile.events.by_day(today), event_in_range1 + assert_includes profile.events.by_day(today), event_in_range2 + assert_not_includes profile.events.by_day(today), event_out_of_range + end + end diff --git a/test/unit/events_helper_test.rb b/test/unit/events_helper_test.rb new file mode 100644 index 0000000..e9f06b0 --- /dev/null +++ b/test/unit/events_helper_test.rb @@ -0,0 +1,32 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class EventsHelperTest < Test::Unit::TestCase + + include EventsHelper + + should 'list events' do + expects(:show_date).returns('') + expects(:_).with('Events for %s').returns('') + event1 = mock; event1.expects(:public?).returns(true); event1.expects(:name).returns('Event 1'); event1.expects(:url).returns({}) + event2 = mock; event2.expects(:public?).returns(true); event2.expects(:name).returns('Event 2'); event2.expects(:url).returns({}) + result = list_events('', [event1, event2]) + assert_match /Event 1/, result + assert_match /Event 2/, result + end + + protected + + def content_tag(tag, text, options = {}) + "<#{tag}>#{text}" + end + def icon_for_article(article) + '' + end + def image_tag(arg) + arg + end + def link_to(text, url, options = {}) + "#{text}" + end + +end diff --git a/test/unit/profile_test.rb b/test/unit/profile_test.rb index cbe0385..5f82d00 100644 --- a/test/unit/profile_test.rb +++ b/test/unit/profile_test.rb @@ -1402,6 +1402,66 @@ class ProfileTest < Test::Unit::TestCase assert_equal 3, p.blogs.count end + should 'list all events' do + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile') + event1 = Event.new(:name => 'Ze Birthday', :start_date => Date.today) + event2 = Event.new(:name => 'Mane Birthday', :start_date => Date.today >> 1) + profile.events << [event1, event2] + assert_includes profile.events, event1 + assert_includes profile.events, event2 + end + + should 'list events by day' do + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile') + + today = Date.today + yesterday_event = Event.new(:name => 'Joao Birthday', :start_date => today - 1.day) + today_event = Event.new(:name => 'Ze Birthday', :start_date => today) + tomorrow_event = Event.new(:name => 'Mane Birthday', :start_date => today + 1.day) + + profile.events << [yesterday_event, today_event, tomorrow_event] + + assert_equal [today_event], profile.events.by_day(today) + end + + should 'list events in a range' do + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile') + + today = Date.today + event_in_range = Event.new(:name => 'Noosfero Conference', :start_date => today - 2.day, :end_date => today + 2.day) + event_in_day = Event.new(:name => 'Ze Birthday', :start_date => today) + + profile.events << [event_in_range, event_in_day] + + assert_equal [event_in_range], profile.events.by_day(today - 1.day) + assert_equal [event_in_range], profile.events.by_day(today + 1.day) + assert_equal [event_in_range, event_in_day], profile.events.by_day(today) + end + + should 'not list events out of range' do + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile') + + today = Date.today + event_in_range1 = Event.new(:name => 'Foswiki Conference', :start_date => today - 2.day, :end_date => today + 2.day) + event_in_range2 = Event.new(:name => 'Debian Conference', :start_date => today - 2.day, :end_date => today + 3.day) + event_out_of_range = Event.new(:name => 'Ze Birthday', :start_date => today - 5.day, :end_date => today - 3.day) + + profile.events << [event_in_range1, event_in_range2, event_out_of_range] + + assert_includes profile.events.by_day(today), event_in_range1 + assert_includes profile.events.by_day(today), event_in_range2 + assert_not_includes profile.events.by_day(today), event_out_of_range + end + + should 'sort events by name' do + profile = Profile.create!(:name => "Test Profile", :identifier => 'testprofile') + event1 = Event.new(:name => 'Noosfero Hackaton', :start_date => Date.today) + event2 = Event.new(:name => 'Debian Day', :start_date => Date.today) + event3 = Event.new(:name => 'Fisl 10', :start_date => Date.today) + profile.events << [event1, event2, event3] + assert_equal [event2, event3, event1], profile.events + end + private def assert_invalid_identifier(id) -- libgit2 0.21.2