Redmineのカレンダー流用まとめの修正

月末が日曜日だと表示されない問題がやっとわかった。しかもRedmineのカレンダー流用まとめがマトメになっていない。

ちょいと書きなおしてみる。

redmine203の導入

redmineからDLして展開

i18n.rb

redmine203/lib/redmine/i18n.rb を app/lib/redmine/i18n.rb へ丸々コピー

application_helper.rb

redmin203/app/helpers/calendars_helper.rb から一部抜粋して app/helpers/application_helper.rb に追記

  # layouts/_calendar.html.erbで使う
  # name: controllerの名前
  def calendar_link(m, name)
    case name
    when "mikus"
      calendar_link_miku(m)
    end
  end



#
# カレンダー用 redMineからパクリ
#
  def link_to_previous_month(year, month, options={})
    target_year, target_month = if month == 1
                                  [year - 1, 12]
                                else
                                  [year, month - 1]
                                end
    name = if target_month == 12
             "#{month_name(target_month)} #{target_year}"
           else
             "#{month_name(target_month)}"
           end

    # \xc2\xab(utf-8) = «
    link_to_month(("\xc2\xab " + name), target_year, target_month, options)
  end
  def link_to_next_month(year, month, options={})
    target_year, target_month = if month == 12
                                  [year + 1, 1]
                                else
                                  [year, month + 1]
                                end

    name = if target_month == 1
             "#{month_name(target_month)} #{target_year}"
           else
             "#{month_name(target_month)}"
           end

    # \xc2\xbb(utf-8) = »
    link_to_month((name + " \xc2\xbb"), target_year, target_month, options)
  end
  def link_to_month(link_name, year, month, options={})
    link_to_content_update(h(link_name), params.merge(:year => year, :month => month))
  end

redmineのヘルパー

redmine203/lib/redmine/helpers/calendar.rb を app/lib/redmine/helpers/calendar.rbにコピー

モデル毎のeventsを作成しておく。
最終日指定を日付型で行うと23:59までのデータを含めてくれないので1日を追加する。

module Redmine
  module Helpers

    # Simple class to compute the start and end dates of a calendar
    class Calendar
      include Redmine::I18n
      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_if_valid 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
          @enddt = @enddt + (last_wday - @enddt.cwday)%7 + 1.day
        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
      
      # custom events 
      # 範囲を設定する
      # miku
      def events_miku=(events)
        @events = events
        @ending_events_by_days = events.group_by {|event| event.dtend.to_s(:date)}
        @starting_events_by_days = events.group_by {|event| event.dtstart.to_s(: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 ||= (1 - 1)%7 + 1
      end

      def last_wday
        @last_dow ||= (first_wday + 5)%7 + 1
      end
    end
  end
end

application_controller.rb

カレンダー表示用のパラメータを作成する

  def calendar_param
    if params[:year] and params[:year].to_i > 1900
      @year = params[:year].to_i
      if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
        @month = params[:month].to_i
      end
    end
    @year ||= Date.today.year
    @month ||= Date.today.month
  end

コントローラでの召喚

miku_controller.rb

  # カレンダー
  def calendar
    calendar_param
    @calendar = Redmine::Helpers::Calendar.new(Date.civil(@year, @month, 1), "ja", :month)
    events = Miku.where("dtstart between ? AND ?",@calendar.startdt, @calendar.enddt).where("campus = ?", @current_campus)
    @calendar.events_miku = events
  end

あっちこっちで使う部分

views/layouts/_calendar.html.erb

<table class="cal">
<thead>
<tr><th scope="col" title="<%= l(:label_week) %>" class="week-number"></th><% 7.times do |i| %><th scope="col"><%= day_name( (calendar.first_wday+i)%7 ) %></th><% end %></tr>
</thead>
<tbody>
<tr>
<% day = calendar.startdt
while day < calendar.enddt %>
<%= ("<td class='week-number' title='#{ l(:label_week) }'>#{(day+(11-day.cwday)%7).cweek}</td>".html_safe) if day.cwday == calendar.first_wday %>
<td class="<%= day.month==calendar.month ? 'even' : 'odd' %>
	<%= week_name(day) %>
	<%= ' today' if Date.today == day %>">
<p class="day-num"><%= day.day %></p>
<% calendar.events_on(day.to_s).each do |i| %>

<%== calendar_link(i, controller.controller_name, day) %>
  
<% end %>
</td>
<%= '</tr><tr>'.html_safe if day.cwday==calendar.last_wday and day!=calendar.enddt %>
<% day = day + 1
end %>
</tr>
</tbody>
</table>

コントローラ毎のヘルパー

HTMLをテキトーにつくる

module MikusHelper
  
  def calendar_link_miku(m)
    text = link_to m.machine, :action=>:show, :id=>m.id
    tip = link_to(m.machine, :action=>:show, :id=>m.id) +
      with_br(m.dtstart.to_s(:jp_time)+"から"+m.dtend.to_s(:jp_time))
    tooltip_s(text, raw(tip))
  end

びゅー

コントローラ毎につくる

<%= form_tag :action => "calendar" do %>

<div class="calendar">
<div class="navi">
	<%= link_to_previous_month(@year, @month) %> 
	<%= select_year(@year, {:prefix => "year", :discard_type => true}, {:onchange => 'this.form.submit()'}) %>
	<%= select_month(@month, {:prefix => "month", :discard_type => true}, {:onchange => "this.form.submit()"})%>
	<%= link_to_next_month(@year, @month) %>
</div>

<% unless @calendar.nil? %>
<%= render :partial => '/layouts/calendar', :locals => {:calendar => @calendar} %>
<% end %>
</div>
<% end %>

どよ?