2011年04月13日

Redmineガントチャートの日付表示再び

■今回行ったこと.
・ガントチャートの日付表示
・ガントチャートの曜日に色付け
・さらに上記の2つをPDF出力でも対応

<2011.05.26に上記の文章追記.>


Redmineのガントチャート,上司に作業を方向したりするには便利なのだけど日付がでないのがいつも不便だと思ってました.最新版でも出ません.どうやら,海外の人は日付よりも週単位の表示に慣れているらしいのですが本当のところは分かりません.


だいぶ前に対応したことがあったのだけど,それからRedmineのバージョンが上がり,ソースコードが大きく変更されたりで毎回修正するのも面倒になって対応していませんでした.

以前に対応したときのメモ:
この時は今とサーバーが違ったので添付ファイルが見られないかもしれません.

Redmine ガントチャートに日付を表示してみた




Redmine とガントチャートPDF 出力と整形


今回,ちょっと頑張ろうと思って色々試行錯誤した結果,綺麗に出力されるようになったので報告します.




修正箇所を以下に記します.パッチは多分役立たないので貼り付けません.

理由: 今回の自分の環境のRedmineは4月9日付の最新版Trunkから引っ張ってきた環境であり,リリースされたものではありません.そのため,リリース版とは当然ファイルのコードに差分がありますし,現在も開発が進んでいるため差が生じる可能性があるため,参考程度にしかならないと思うため.


そのかわり,修正したファイルは貼り付けます.
こちらからどうぞ.
show.html.erb

gantts_controller.rb

gantt.rb


参考にしたサイト: Special Thanks!
"redmineのガントチャートに日付を追加 - 雑多な日々"


以下,修正した箇所を記述していきます.当該ファイルを開いてそれぞれの場所を直していきます.

■修正ファイル

- /app/controllers/gantts_controller.rb

# add date for output.
# これはプロジェクトの名前を出力するだけです.

#basename = (@project ? "#{@project.identifier}-" : '') + 'gantt'
basename = Time.now.strftime("%Y%m%d-") + (@project ? "#{@project.identifier}-" : '') + 'gantt'





- /app/views/gantts/show.html.erb

# ガントチャートの表示領域によって判定する日付用フラグを追加します.
show_weeks = false
show_days = false
# add show day
show_day_num = false # <= ここ




#----------------------
# 日付を表示する条件を追記します.

# if @gantt.zoom >1
show_weeks = true
headers_height = 2*header_heigth
if @gantt.zoom > 2
show_days = true
headers_height = 3*header_heigth
end
if @gantt.zoom > 3 # <= ここの条件を丸々追加
show_day_num = true
headers_height = 4*header_heigth
end
end


#----------------------





#----------------------
# 日付を表示するメイン処理を追加 Days headers の直前あたりに挿入.

<%
#add show day
#
# Days headers Num
#
if show_day_num
left = 0
height = g_height + header_heigth*2 - 1
wday = @gantt.date_from.cwday
day_num = @gantt.date_from
(@gantt.date_to - @gantt.date_from + 1).to_i.times do
width = zoom - 1
%>
5 %><%= "color:blue;" if wday == 6 %><%= "color:red;" if wday == 7 %>" class="gantt_hdr">
<%= day_num.day %>

<%
left = left + width+1
day_num = day_num + 1
wday = wday + 1
wday = 1 if wday > 7
end
end %>


#----------------------
#----------------------
# 曜日表示の変更も日付表示ありとなしで高さを変える.
<%
#
# Days headers
#
if show_days
left = 0
height = g_height + header_heigth - 1
top = (show_day_num ? 55 : 37) # <= ここ
wday = @gantt.date_from.cwday
(@gantt.date_to - @gantt.date_from + 1).to_i.times do
width = zoom - 1
%>
5 %><%= "color:blue;" if wday == 6 %><%= "color:red;" if wday == 7 %>" class="gantt_hdr"> # <= ここ
<%= day_name(wday).first %>


#----------------------



- lib/redmine/export/pdf.rb

ここは修正不要だった(というか,ファイルがリンク先の情報と異なってて分からなかった).ここをしないでガントチャートの処理は全て以下のファイルで行うようになったらしい.


以下は,独自で改造してうまく言った日付付きPDF出力.

=========================
PDF出力で表示する場合は,lib/redmine/helpers/gantt.rb を修正する.ここでImageファイルも色々できるけどしない.

Line533 付近

show_weeks = false
show_days = false
show_day_num = false # <= 追加



#--------------------------------
# PDF出力が3ヶ月未満の場合は日付も出す(曜日と同じでよいと思う)

if self.months < 3
show_days = true
show_day_num = true # <= 追加
headers_heigth = 4*header_heigth # <= 追加
end


#--------------------------------
# Line607 付近
# Days headers の処理の後に以下を全て追加

# Day num headers
if show_days # num
left = subject_width
height = header_heigth
wday = self.date_from.cwday
day_num = self.date_from
pdf.SetFontStyle('B',7)
(self.date_to - self.date_from + 1).to_i.times do
width = zoom
pdf.SetY(y_start + 3 * header_heigth)
pdf.SetX(left)
# pdf.rbでは文字列で渡ってくることを期待している.
pdf.RDMCell(width, height, day_num.day.to_s, "LTR", 0, "C")
left = left + width
day_num = day_num + 1
wday = wday + 1
wday = 1 if wday > 7
end
end




これでいけるはず.day_num.day をstring に変換して渡してあげるところで苦戦してました…情けない.



=========================
■ もう一つ別の改造。
以下はガントチャートのチケットの並びが発行した順番になってて見づらいので,それをチケットの開始日時で並び替える改造です.


参考にしたサイト: Special Thanks!
"【Redmine 1.1.2】ガントチャートを開始日順にソートする|渋谷ではたらくイタズラ者、マー君のブログ。"



- lib/redmine/helpers/gantt.rb

# TODO: top level issues should be sorted by start date
#-----

def gantt_issue_compare(x, y, issues)
#if x.root_id == y.root_id
if x.start_date == y.start_date
x.lft <=> y.lft
else
#x.root_id <=> y.root_id
x.start_date <=> y.start_date
end


-----
以上の変更で,ガントチャートが開始日毎に並び替えられる.


...と書かれていますが,私の環境では,"<=>"がundefineだよって怒られてしまいました.

このif文の箇所をまるごとコメントアウトして,以下のコードに置き換えることで現状うまくいっています.

多重配列の比較・並び替え使ってます.


# TODO: top level issues should be sorted by start date
def gantt_issue_compare(x, y, issues)
[(x.root.start_date or x.start_date or Date.new()), x.root_id, (x.start_date or Date.new()), x.lft] <=> [(y.root.start_date or y.start_date or Date.new()), y.root_id, (y.start_date or Date.new()), y.lft]

ふぅ,満足.
posted by maplewine at 20:54| Comment(7) | TrackBack(0) | ruby | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
「ガントチャートを開始日順にソートする」ですが、チケットの階層構造が崩れてしまうようです。
力ずくですが最下層チケットのみを開始日順でソートするようにしてみました。(for 1.2.1)
それより上はどうしてもできませんでした。。。
sort_issues()から変えた方がやりやすいのかもしれません。

# TODO: top level issues should be sorted by start date
def gantt_issue_compare(x, y, issues)
x_rank=calc_rank_top(x, issues)
y_rank=calc_rank_top(y, issues)
x_rank <=> y_rank
end
def calc_rank_top(x, issues)
if x.parent.nil?
[x.root_id]
else
if isLeaf(x, issues)
calc_rank(x).push(x.parent.lft+1).push(x.start_date)
else
calc_rank(x).push(x.lft)
end
end
end
def calc_rank(x)
if x.parent.nil?
[x.root_id]
else
calc_rank(x.parent).push(x.parent.lft)
end
end
def isLeaf(x, issues)
issues.select{|issue| issue.parent_id==x.id}.count >0 ? false : true
end
Posted by ダビ at 2011年11月30日 03:10
ダビさん.
単純にソートしてるだけだったので確かに階層構造崩れてしまいますね…
1.2.0に上げたあと,この並び替えの修正は入れていなかったので気づいていませんでした.
教えて頂いたコード試してみます!ありがとうございます.
Posted by 管理人 at 2011年11月30日 09:39
すみませんバグがあったので修正しました。

def gantt_issue_compare(x, y, issues)
x_rank=calc_rank_top(x, issues)
y_rank=calc_rank_top(y, issues)
comp = x_rank <=> y_rank
comp = x.start_date <=> y.start_date if comp==0
return comp
end
def calc_rank_top(x, issues)
if x.parent.nil?
[x.root_id]
else
if isLeaf(x, issues)
calc_rank(x).push(1)
else
calc_rank(x).push(x.lft)
end
end
end
def calc_rank(x)
if x.parent.nil?
[x.root_id]
else
calc_rank(x.parent).push(x.parent.lft)
end
end
def isLeaf(x, issues)
issues.select{|issue| issue.parent_id==x.id}.count >0 ? false : true
end
Posted by ダビ at 2011年11月30日 17:53
> ダビさん
修正コードありがとうございます。とりあえず、内のRedmine1.3.1でも教えて頂いたコードで動いております。

ただ、運用上使わないとは思いますが、開始日を空にした場合エラーになるので、そこだけ回避するコードを足した方が良いかと思われます。
Posted by みちばな at 2012年02月27日 22:46
とても参考になりました。
ありがとうございます。

ところで「header_heigth」となっているところは「header_height」ではないでしょうか?
確認してもらえると嬉しいです。
Posted by ひろし at 2012年11月13日 20:29
ダビさん
修正コードありがとうございました。
私は、最近Redmineは使っていますがいじったりなど遊べておらず、滞り気味です。。


ひろしさん
ご指摘ありがとうございます。
おっしゃるとおりだと思います。助かります。
Posted by 管理人 at 2012年11月15日 16:39
印鑑を輸送

代理人を通して印鑑登録廃止<a href="http://www.superhanko.com/">角印</a>登録を行うこともできます。ただし、本人からの申請であるかどうかを確認する必要があるため、登録者本人が来庁するのに比べ、手続きが多く期間も要します(代理人申請では、一度の来庁では印鑑登録は完了せず、証明書を交付することはできません)。個人ではなく法人(団体)の請求書、領収書、契約書などに、社名や<a href="http://www.superhanko.com/">社印</a>住所に付して確認のための印として用いられる角型の印鑑。右縦書きで篆書体で「○○株式会社之印」のように彫られていることが多い住民票のある役場でその印鑑登録を抹消する手続きをすれば会社で持っているカードはその時点で無効になります。印鑑登録が必要なら、再度登録すれば新しいカードが交付されますし新旧2枚のカードで別々に取った<a href="http://www.superhanko.com/">印鑑</a>証明書がある場合には「あたらしい日付のものが有効」です。印鑑カードの発行のみ、登記をした法務局でしか取得できません。印鑑カードを持っていなければ、管轄の法務局に行かないといけません。印鑑カードを取得しており、印鑑証明書の発行のみであれば、管轄外の法務局でもできます。あなたがお持ちの<a href="http://www.superhanko.com/">印鑑通販</a>「印鑑判子」を実印に使っていたり、銀行に使っていたりすればいくら安い物でもそれはとても大事な「<a href="http://www.superhanko.com/kojin-set2.html">実印販売</a>」になります。反対にいくら高い「印鑑判子」でも役所や銀行に届けを出していないものは、只の字の彫られた棒きれです。スポンジが薄くなり、カスが出たり、汚れたり、ぼろぼろなっている様でしたら、スポンジごと交換いたしましょう。印鑑ケースに愛着があるようでしたら、やはり朱肉部分の交換<a href="http://www.superhanko.com/yzkojin-zituin.html">印鑑激安</a>です。シャチハ○等で補充インキカートリッジが市販されてます。そっくり交換が簡単のようです。 2個入りです。250〜300円で量販店などで売られております。後々の使い勝手が大変良いのが、実感なのです。申請後、本人の意思確認のため、照会書を本人の住所地宛に送付されますので、照会書が届いてから所定の期日内に、必要事項を記載して再度持参してください。
Posted by 印鑑を輸送 at 2012年11月17日 19:21
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック