ガントチャートとかカレンダー
Ruby on Railsのプラグインを探す。カレンダープラグインは以前につかったものしか見つからない。使った瞬間は感動するんだけど、複数日を跨ぐ表示には向いていないというか出来そうに無い。
そしてガントチャートを探すが、見つかるのはredMineの記事ばかり。
オイラがクレクレといっているのはプラグインなのだ。
仕方ないので以前に入れてみたredMineのコードを眺める。
app/controllers/projects_controller.rb app/views/projects/calender.rhtml app/views/projects/gantt.rhtml
modesとhelpersにもイロイロ入っているけど、大まかなところはOK
今欲しい機能は、redMineのプロジェクトのカレンダーだけで十分な気がしてきた。なので解読と改造を始める!(出来るのか?
やりたいこと
Rentalというテーブルに「品目」「ユーザー名」「貸出日時」「返却日時」とか入っている。
日付を元にした縦長の表があるけど、状況を確認しずらいのでカレンダーっぽく表示させたい。
コードの確認
必要なのか不必要なのか考えてみる
app/controllers/projects_controller.rb#calendar
ここね。
@trackers = Tracker.find(:all, :order => 'position') retrieve_selected_tracker_ids(@trackers)
positionを元に
def retrieve_selected_tracker_ids(selectable_trackers) if ids = params[:tracker_ids] @selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s } else @selected_tracker_ids = selectable_trackers.collect {|t| t.id.to_s } end end
たぶん要らない。
次の年月の作成のところ
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
1900年とか凄い確認をしている。このまま引用!
@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)
civilって何?http://www.ruby-lang.org/ja/man/html/Date.htmlを見る。
civil([year[, mon[, mday[, start]]]])
暦日付に相当する日付オブジェクトを生成します。このクラスでは、紀元前の年を天文学の流儀で勘定します。 1年の前は零年、零年の前は-1年、のようにします。月、および月の日は負、または正の数でなければなりません (負のときは最後からの序数)。零であってはなりません。
最後の引数は、グレゴリオ暦をつかい始めた日をあらわすユリウス日です。グレゴリオ暦の指定として真、ユリウス暦の指定として偽を与えることもできます。省略した場合は、Date::ITALY (1582年10月15日) になります。
うむ。
cwday
暦週の日 (曜日) を返します (1-7、月曜は1)。
うむ。
@events = [] @project.issues_with_subprojects(params[:with_subprojects]) do @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] ) unless @selected_tracker_ids.empty? end
まずは「issues_with_subprojects」って何?
app/models/project.rb
def issues_with_subprojects(include_subprojects=false) conditions = nil if include_subprojects && !active_children.empty? ids = [id] + active_children.collect {|c| c.id} conditions = ["#{Issue.table_name}.project_id IN (#{ids.join(',')})"] end conditions ||= ["#{Issue.table_name}.project_id = ?", id] Issue.with_scope :find => { :conditions => conditions } do yield end end
検索するプロジェクトを調べているっぽい。単純な構成を想定しているので、ここは要らない。
普通のfindを使うことにしよう。
conditionsの中
#{Issue.table_name}.tracker_id in (#{@selected_tracker_ids.join(',')})", と unless @selected_tracker_ids.empty?
この条件もイラネ、unlessは無くても大丈夫・・・だと思う。
views/projects/calendar.rhtmlも使いまわししたいので、変数とかはなるべく変更しないことにしよう!
コントローラ側
作ってみた。
def rentalcalendar @page_title = "貸出の月間表示" 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 @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) @events = [] @events += Rental.find(:all, :conditions =>["lending>=? and rtning<=?", @date_from, @date_to], :order=>"lending, rtning") @ending_events_by_days = @events.group_by {|event| event.rtning} @starting_events_by_days = @events.group_by {|event| event.lending} render :layout => false if request.xhr? end
ポイントは
- 予定の開始日:start_dateからlending
- 予定の終了日:due_dateからrtning
findとconditionsのところがカスタマイズするところかな?(まだViewを作っていないので動くのか?)
ビュー側
イロイロ不要なものがある
たいへんだ・・・
要らない部分はどんどん削除!!
<h2><%= @page_title %> <%= @year %>年<%= @month %>月</h2> <% form_tag do %> <table width="100%"> <tr> <th align="left" style="width:15%"> <%= link_to ('« ' + (@month==1 ? "#{month_name(12)} #{@year-1}" : "#{month_name(@month-1)}")), :action=>'rentalcalendar', :year=>(@month==1 ? @year-1 : @year), :month=>(@month==1 ? 12 : @month-1) %> </th> <th align="center" style="width:55%"> <%= select_month(@month, :prefix => "month", :discard_type => true) %> <%= select_year(@year, :prefix => "year", :discard_type => true) %> <%= submit_tag ("変更"), :class => "button-small" %> </th> <th align="right" style="width:15%"> <%= link_to ((@month==12 ? "#{month_name(1)} #{@year+1}" : "#{month_name(@month+1)}") + ' »'), :action=>'rentalcalendar', :year=>(@month==12 ? @year+1 : @year), :month=>(@month==12 ? 1 : @month+1) %> </th> </tr> </table> <% end %> <table class="list with-cells"> <thead> <tr class='dayName'> <th> </th> <% 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" %>" style="width:14%; <%= Date.today == day ? 'background:#FDFED0;' : '' %>"> <p class="textright"> <%= link_to((day==Date.today ? "<b>#{day.day}</b>" : day.day), :controller => 'support/rental', :action=>'search', :rtning_from=>day, :rtning_to=>day ) %> </p> <% ((@ending_events_by_days[day] || []) + (@starting_events_by_days[day] || [])).uniq.each do |i| %> <div class="tooltip"> <%= if day == i.lending.to_date and day == i.rtning.to_date image_tag('patrols/arrow_bw.png') elsif day == i.lending.to_date image_tag('patrols/arrow_from.png') elsif day == i.rtning.to_date image_tag('patrols/arrow_to.png') end %> <small><%= link_to h(i.title), :controller => 'support/rental', :action=>'edit', :id=>i %> <%=h i.member_name.sub(/^(.{30}[^\s]*\s).*$/, '\1 (...)') %></small> </div> <% end %> </td> <%= '</tr><tr style="height:100px">' if day.cwday >= 7 and day!=@date_to %> <% day = day + 1 end %> </tr> </tbody> </table> <%= image_tag 'patrols/arrow_from.png' %> この日からの貸出<br /> <%= image_tag 'patrols/arrow_to.png' %> この日に返却<br /> <%= image_tag 'patrols/arrow_bw.png' %> 当日に貸出と返却<br />
- Calendar Helperを使っているのでスタイルは使いまわし
- link_to_remoteはIE7でよい結果にならなかったのでlink_toに変更
- 言語系は直接仕込む
- 画像はインスパイア
- ヘルパーを追加作成
#redMineからのインスパイア(パクリ def month_name(month) month_arrays=["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"] month_arrays[month-1] end def day_name(day) day_arrays=["月曜日","火曜日","水曜日","木曜日","金曜日","土曜日","日曜日"] day_arrays[day-1] end
ひとまず動いているからOKとしよう。
完成してからの感想:僕が欲しいビューはこんなんじゃない!