# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class MyController < ApplicationController
+ helper :issues
+
layout 'base'
before_filter :require_login
end
end
@year ||= Date.today.year
- @month ||= Date.today.month
-
- @date_from = Date.civil(@year, @month, 1)
- @date_to = (@date_from >> 1)-1
- # start on monday
- @date_from = @date_from - (@date_from.cwday-1)
- # finish on sunday
- @date_to = @date_to + (7-@date_to.cwday)
+ @month ||= Date.today.month
+ @calendar = Redmine::Helpers::Calendar.new(Date.civil(@year, @month, 1), current_language, :month)
- @events = []
+ events = []
@project.issues_with_subprojects(params[:with_subprojects]) do
- @events += Issue.find(:all,
+ events += Issue.find(:all,
:include => [:tracker, :status, :assigned_to, :priority, :project],
- :conditions => ["((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?)) and #{Issue.table_name}.tracker_id in (#{@selected_tracker_ids.join(',')})", @date_from, @date_to, @date_from, @date_to]
+ :conditions => ["((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?)) AND #{Issue.table_name}.tracker_id IN (#{@selected_tracker_ids.join(',')})", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt]
) unless @selected_tracker_ids.empty?
end
- @events += @project.versions.find(:all, :conditions => ["effective_date BETWEEN ? AND ?", @date_from, @date_to])
-
- @ending_events_by_days = @events.group_by {|event| event.due_date}
- @starting_events_by_days = @events.group_by {|event| event.start_date}
+ events += @project.versions.find(:all, :conditions => ["effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
+ @calendar.events = events
render :layout => false if request.xhr?
end
--- /dev/null
+<table class="cal">
+<thead>
+<tr><td></td><% 7.times do |i| %><th><%= day_name( (calendar.first_wday+i)%7 ) %></th><% end %></tr>
+</thead>
+<tbody>
+<tr>
+<% day = calendar.startdt
+while day <= calendar.enddt %>
+<%= "<th>#{day.cweek}</th>" if day.cwday == calendar.first_wday %>
+<td class="<%= day.month==calendar.month ? 'even' : 'odd' %><%= ' today' if Date.today == day %>">
+<p class="day-num"><%= day.day %></p>
+<% calendar.events_on(day).each do |i| %>
+ <% if i.is_a? Issue %>
+ <div class="tooltip">
+ <%= if day == i.start_date && day == i.due_date
+ image_tag('arrow_bw.png')
+ elsif day == i.start_date
+ image_tag('arrow_from.png')
+ elsif day == i.due_date
+ image_tag('arrow_to.png')
+ end %>
+ <%= h("#{i.project.name} -") unless @project && @project == i.project %>
+ <%= link_to_issue i %>: <%= h(truncate(i.subject, 30)) %>
+ <span class="tip"><%= render_issue_tooltip i %></span>
+ </div>
+ <% else %>
+ <%= link_to_version i, :class => "icon icon-package" %>
+ <% end %>
+<% end %>
+</td>
+<%= '</tr><tr>' if day.cwday==calendar.last_wday and day!=calendar.enddt %>
+<% day = day + 1
+end %>
+</tr>
+</tbody>
+</table>
<h3><%= l(:label_calendar) %></h3>
-<%
-@date_from = Date.today - (Date.today.cwday-1)
-@date_to = Date.today + (7-Date.today.cwday)
-@issues = Issue.find :all,
- :conditions => ["#{Issue.table_name}.project_id in (#{@user.projects.collect{|m| m.id}.join(',')}) AND ((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?))", @date_from, @date_to, @date_from, @date_to],
- :include => [:project, :tracker] unless @user.projects.empty?
-@issues ||= []
-%>
+<% calendar = Redmine::Helpers::Calendar.new(Date.today, current_language, :week)
+ calendar.events = Issue.find :all,
+ :conditions => ["#{Issue.table_name}.project_id in (#{@user.projects.collect{|m| m.id}.join(',')}) AND ((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?))", calendar.startdt, calendar.enddt, calendar.startdt, calendar.enddt],
+ :include => [:project, :tracker, :priority, :assigned_to] unless @user.projects.empty? %>
-<table class="cal">
-<thead><tr>
-<td></td>
-<% 1.upto(7) do |d| %>
- <th align="center" width="14%"><%= day_name(d) %></th>
-<% end %>
-</tr></thead>
-<tbdoy>
-<tr height="100">
-<% day = @date_from
-while day <= @date_to
- if day.cwday == 1 %>
- <th valign="middle"><%= day.cweek %></th>
- <% end %>
- <td valign="top" width="14%" class="<%= day.month==@month ? "even" : "odd" %>">
- <p align="right"><%= day==Date.today ? "<b>#{day.day}</b>" : day.day %></p>
- <% day_issues = []
- @issues.each { |i| day_issues << i if i.start_date == day or i.due_date == day }
- day_issues.each do |i| %>
- <%= if day == i.start_date and day == i.due_date
- image_tag('arrow_bw.png')
- elsif day == i.start_date
- image_tag('arrow_from.png')
- elsif day == i.due_date
- image_tag('arrow_to.png')
- end %>
- <small><%= link_to_issue i %>: <%=h i.subject.sub(/^(.{30}[^\s]*\s).*$/, '\1 (...)') %></small><br />
- <% end %>
- </td>
- <%= '</tr><tr height="100">' if day.cwday >= 7 and day!=@date_to %>
- <%
- day = day + 1
-end %>
-</tr>
-</tbody>
-</table>
\ No newline at end of file
+<%= render :partial => 'common/calendar', :locals => {:calendar => calendar } %>
</td></tr>
</table>
-<table class="cal">
-<thead>
-<tr>
-<td></td>
-<% 1.upto(7) do |d| %>
- <th style="width:14%"><%= day_name(d) %></th>
-<% end %>
-</tr>
-</thead>
-<tbody>
-<tr style="height:100px">
-<% day = @date_from
-while day <= @date_to
- if day.cwday == 1 %>
- <th><%= day.cweek %></th>
- <% end %>
- <td valign="top" class="<%= day.month==@month ? "even" : "odd" %> <%= Date.today == day ? 'today' : '' %>" style="width:14%;">
- <p class="textright"><%= day==Date.today ? "<b>#{day.day}</b>" : day.day %></p>
- <% ((@ending_events_by_days[day] || []) + (@starting_events_by_days[day] || [])).uniq.each do |i| %>
- <% if i.is_a? Issue %>
- <div class="tooltip">
- <%= if day == i.start_date and day == i.due_date
- image_tag('arrow_bw.png')
- elsif day == i.start_date
- image_tag('arrow_from.png')
- elsif day == i.due_date
- image_tag('arrow_to.png')
- end %>
- <small>
- <%= h("#{i.project.name} -") unless @project && @project == i.project %>
- <%= link_to_issue i %>:
- <%= h(truncate(i.subject, 30)) %>
- </small>
- <span class="tip">
- <%= render_issue_tooltip i %>
- </span>
- </div>
- <% else %>
- <small><%= link_to_version i, :class => "icon icon-package" %></small>
- <% end %>
- <% end %>
- </td>
- <%= '</tr><tr style="height:100px">' if day.cwday >= 7 and day!=@date_to %>
- <%
- day = day + 1
-end %>
-</tr>
-</tbody>
-</table>
+<%= render :partial => 'common/calendar', :locals => {:calendar => @calendar} %>
<%= image_tag 'arrow_from.png' %> <%= l(:text_tip_task_begin_day) %><br />
<%= image_tag 'arrow_to.png' %> <%= l(:text_tip_task_end_day) %><br />
general_csv_encoding: ISO-8859-1
general_pdf_encoding: ISO-8859-1
general_day_names: Понеделник,Вторник,Сряда,Четвъртък,Петък,Събота,Неделя
+general_first_day_of_week: '1'
notice_account_updated: Профилът е обновен успешно.
notice_account_invalid_creditentials: Невалиден потребител или парола.
general_csv_encoding: UTF-8
general_pdf_encoding: UTF-8
general_day_names: Pondělí,Úterý,Středa,Čtvrtek,Pátek,Sobota,Neděle
+general_first_day_of_week: '1'
notice_account_updated: Účet byl úspěšně změněn.
notice_account_invalid_creditentials: Chybné jméno nebo heslo
general_csv_encoding: ISO-8859-1
general_pdf_encoding: ISO-8859-1
general_day_names: Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag,Sonntag
+general_first_day_of_week: '1'
notice_account_updated: Konto wurde erfolgreich aktualisiert.
notice_account_invalid_creditentials: Benutzer oder Kennwort unzulässig
general_csv_encoding: ISO-8859-1
general_pdf_encoding: ISO-8859-1
general_day_names: Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
+general_first_day_of_week: '7'
notice_account_updated: Account was successfully updated.
notice_account_invalid_creditentials: Invalid user or password
general_csv_encoding: ISO-8859-15
general_pdf_encoding: ISO-8859-15
general_day_names: Lunes,Martes,Miércoles,Jueves,Viernes,Sábado,Domingo
+general_first_day_of_week: '1'
notice_account_updated: Cuenta creada correctamente.
notice_account_invalid_creditentials: Inválido usuario o contraseña
general_csv_encoding: ISO-8859-1
general_pdf_encoding: ISO-8859-1
general_day_names: Lundi,Mardi,Mercredi,Jeudi,Vendredi,Samedi,Dimanche
+general_first_day_of_week: '1'
notice_account_updated: Le compte a été mis à jour avec succès.
notice_account_invalid_creditentials: Identifiant ou mot de passe invalide.
general_csv_encoding: ISO-8859-1
general_pdf_encoding: ISO-8859-1
general_day_names: Lunedì,Martedì,Mercoledì,Giovedì,Venerdì,Sabato,Domenica
+general_first_day_of_week: '1'
notice_account_updated: L'utenza è stata aggiornata.
notice_account_invalid_creditentials: Nome utente o password non validi.
general_csv_encoding: SJIS
general_pdf_encoding: SJIS
general_day_names: 月曜日,火曜日,水曜日,木曜日,金曜日,土曜日,日曜日
+general_first_day_of_week: '7'
notice_account_updated: アカウントが更新されました。
notice_account_invalid_creditentials: ユーザ名もしくはパスワードが無効
general_csv_encoding: ISO-8859-1
general_pdf_encoding: ISO-8859-1
general_day_names: Maandag, Dinsdag, Woensdag, Donderdag, Vrijdag, Zaterdag, Zondag
+general_first_day_of_week: '7'
notice_account_updated: Account is met succes gewijzigd
notice_account_invalid_creditentials: Incorrecte gebruikersnaam of wachtwoord
general_csv_encoding: ISO-8859-2
general_pdf_encoding: ISO-8859-2
general_day_names: Poniedziałek,Wtorek,Środa,Czwartek,Piątek,Sobota,Niedziela
+general_first_day_of_week: '1'
notice_account_updated: Konto prawidłowo zaktualizowane.
notice_account_invalid_creditentials: Zły użytkownik lub hasło
general_csv_encoding: ISO-8859-1\r
general_pdf_encoding: ISO-8859-1\r
general_day_names: Segunda,Terca,Quarta,Quinta,Sexta,Sabado,Domingo\r
+general_first_day_of_week: '1'\r
\r
notice_account_updated: Conta foi alterada com sucesso.\r
notice_account_invalid_creditentials: Usuario ou senha invalido.\r
general_csv_encoding: ISO-8859-1
general_pdf_encoding: ISO-8859-1
general_day_names: Segunda,Terça,Quarta,Quinta,Sexta,Sábado,Domingo
+general_first_day_of_week: '1'
notice_account_updated: Conta foi atualizada com sucesso.
notice_account_invalid_creditentials: Usuário ou senha inválidos.
general_csv_encoding: ISO-8859-1
general_pdf_encoding: ISO-8859-1
general_day_names: Luni,Marti,Miercuri,Joi,Vineri,Sambata,Duminica
+general_first_day_of_week: '7'
notice_account_updated: Contul a fost creat cu succes.
notice_account_invalid_creditentials: Numele utilizator sau parola este invalida.
general_csv_encoding: ISO-8859-1
general_pdf_encoding: ISO-8859-1
general_day_names: Måndag,Tisdag,Onsdag,Torsdag,Fredag,Lördag,Söndag
+general_first_day_of_week: '7'
notice_account_updated: Kontot har uppdaterats
notice_account_invalid_creditentials: Fel användarnamn eller lösenord
general_csv_encoding: gb2312
general_pdf_encoding: Big5
general_day_names: 一,二,三,四,五,六,日
+general_first_day_of_week: '7'
notice_account_updated: 帐户更新成功。
notice_account_invalid_creditentials: 用户名或密码不正确
--- /dev/null
+# redMine - project management software
+# Copyright (C) 2006-2007 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+module Redmine
+ module Helpers
+
+ # Simple class to compute the start and end dates of a calendar
+ class Calendar
+ include GLoc
+ attr_reader :startdt, :enddt
+
+ def initialize(date, lang = current_language, period = :month)
+ @date = date
+ @events = []
+ @ending_events_by_days = {}
+ @starting_events_by_days = {}
+ set_language lang
+ case period
+ when :month
+ @startdt = Date.civil(date.year, date.month, 1)
+ @enddt = (@startdt >> 1)-1
+ # starts from the first day of the week
+ @startdt = @startdt - (@startdt.cwday - first_wday)%7
+ # ends on the last day of the week
+ @enddt = @enddt + (last_wday - @enddt.cwday)%7
+ when :week
+ @startdt = date - (date.cwday - first_wday)%7
+ @enddt = date + (last_wday - date.cwday)%7
+ else
+ raise 'Invalid period'
+ end
+ end
+
+ # Sets calendar events
+ def events=(events)
+ @events = events
+ @ending_events_by_days = @events.group_by {|event| event.due_date}
+ @starting_events_by_days = @events.group_by {|event| event.start_date}
+ end
+
+ # Returns events for the given day
+ def events_on(day)
+ ((@ending_events_by_days[day] || []) + (@starting_events_by_days[day] || [])).uniq
+ end
+
+ # Calendar current month
+ def month
+ @date.month
+ end
+
+ # Return the first day of week
+ # 1 = Monday ... 7 = Sunday
+ def first_wday
+ @first_dow ||= (l(:general_first_day_of_week).to_i - 1)%7 + 1
+ end
+
+ def last_wday
+ @last_dow ||= (first_wday + 5)%7 + 1
+ end
+ end
+ end
+end
/***** Calendar *****/
table.cal {border-collapse: collapse; width: 100%; margin: 8px 0 6px 0;border: 1px solid #d7d7d7;}
+table.cal thead th {width: 14%;}
+table.cal tbody tr {height: 100px;}
table.cal th { background-color:#EEEEEE; padding: 4px; }
-table.cal td {border: 1px solid #d7d7d7;}
+table.cal td {border: 1px solid #d7d7d7; vertical-align: top; font-size: 0.9em;}
+table.cal td p.day-num {font-size: 1.1em; text-align:right;}
+table.cal td.odd p.day-num {color: #bbb;}
table.cal td.today {background:#ffffdd;}
+table.cal td.today p.day-num {font-weight: bold;}
/***** Tooltips ******/
.tooltip{position:relative;z-index:24;}
--- /dev/null
+# redMine - project management software
+# Copyright (C) 2006-2007 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+class CalendarTest < Test::Unit::TestCase
+
+ def test_monthly
+ c = Redmine::Helpers::Calendar.new(Date.today, :fr, :month)
+ assert_equal [1, 7], [c.startdt.cwday, c.enddt.cwday]
+
+ c = Redmine::Helpers::Calendar.new('2007-07-14'.to_date, :fr, :month)
+ assert_equal ['2007-06-25'.to_date, '2007-08-05'.to_date], [c.startdt, c.enddt]
+
+ c = Redmine::Helpers::Calendar.new(Date.today, :en, :month)
+ assert_equal [7, 6], [c.startdt.cwday, c.enddt.cwday]
+ end
+
+ def test_weekly
+ c = Redmine::Helpers::Calendar.new(Date.today, :fr, :week)
+ assert_equal [1, 7], [c.startdt.cwday, c.enddt.cwday]
+
+ c = Redmine::Helpers::Calendar.new('2007-07-14'.to_date, :fr, :week)
+ assert_equal ['2007-07-09'.to_date, '2007-07-15'.to_date], [c.startdt, c.enddt]
+
+ c = Redmine::Helpers::Calendar.new(Date.today, :en, :week)
+ assert_equal [7, 6], [c.startdt.cwday, c.enddt.cwday]
+ end
+end