プラグイン紹介 redmine_absolute_dates

使っているプラグインを紹介します。redmine_absolute_dates です。

チケットを表示しているとき作成日や更新日が
「3ヶ月前に追加. 10日前に更新.」
のように相対時間形式で表示されます。
マウスカーソルを「3ヶ月前」のところにしばらく置いておくと
「2012/09/20 16:54」
と絶対時間形式でポップアップ表示されますがいちいち面倒なのでデフォルトで
「2012/09/20に追加. 2012/11/27に更新. 」
と絶対時間形式で表示してくれるプラグインです。

このプラグインはポップアップで表示する形式も変わらず絶対時間形式ですが
「3ヶ月 ago (2012/09/20 16:54)」
のように相対時間形式+絶対時間(時刻込み)を表示するように手を入れました。
それと日本語メッセージで時間の前後にスペースがなくつまり気味に感じたので空白を入れました。

以下がそのパッチです。

--- ./config/locales/ja.yml.org
+++ ./config/locales/ja.yml
@@ -1,4 +1,4 @@
 ja:
-  label_added_absolute_time_by: "%{author} が%{age}に追加"
-  label_updated_time: "%{value}に更新"
-  label_updated_time_by: "%{author} が%{age}に更新"
+  label_added_absolute_time_by: "%{author} が %{age} に追加"
+  label_updated_time: "%{value} に更新"
+  label_updated_time_by: "%{author} が %{age} に更新"
--- lib/absolute_date_helper_patch.rb.org
+++ lib/absolute_date_helper_patch.rb
@@ -17,5 +17,5 @@
     def time_tag_with_absolute_date(time)
       text = format_date(time)
-      tip_text = format_time(time)
+      tip_text = distance_of_time_in_words(Time.now, time) + ' ago (' + format_time(time) + ')'
       if @project
         link_to(text, {:controller => 'activities', :action => 'index', :id => @project, :from => time.to_date}, :title => tip_text).html_safe

Redmine の Wiki の履歴とアノテート

チケットの表示画面には履歴も一緒に表示され変更箇所も「〜を更新(diff)」の「diff」のリンクをたどれば詳しくみることができます。
Wikiの画面には履歴の内容は表示されませんが、画面右上の方の「履歴」というリンクをたどると Wiki の履歴画面にとぶことができます。各行は左から

  • バージョン番号
  • 「差分を見る」ときに使うラジオボタン
  • 更新日
  • 作成者
  • コメント
  • 「アノテート」リンク

と並んでいます。
バージョン番号のリンクをたどるとそのバージョンの内容が表示されます。
ラジオボタンで比較したい2つのバージョンをチェックして下にある「差分を見る」ボタンを押すと差分が表示されます。
「アノテート」リンクをたどるとそのバージョンの内容に付加情報がついて表示されます。各行は左から、

  • 行番号
  • その行が書かれたバージョン
  • その行を書いたユーザ
  • 行の内容

と並んでいます。
Git の blame表示と同様です。

プラグインから require するときの注意2

preview_attach_columnプラグインと smart_issues_sortプラグインの両方を入れたとき preview_attach_column の機能が効かなくなってしまうということがありました。
原因は、
redmine_preview_attach_column/lib/pac_patches.rb で

require_dependency 'query'

と読み込んだ Queryクラスをいじってメソッドの動きを変更した後に、
redmine_smart_issues_sort/init.rb で

require 'query'

と読み込んで Queryクラスのメソッドを元に戻してしまったためでした。

require_dependency も内部の処理で最終的に require に任せているし、require は同じファイルを二度は読み込まないはすなのになぜ query.rb が二度読み込まれたのでしょう。
require はすでに読み込まれたかどうかを判定するためにファイル名の拡張子を外した部分(feature)を記録して管理しています。
require_dependency はというとファイル名を絶対パスにしてから require に渡します。
そのため require_dependency を使っていた redmine_preview_attach_column側からは

require '<RedmineのROOTディレクトリ>/app/models/query'

として呼ばれ、redmine_smart_issues_sort側からは

require 'query'

として呼ばれ、両者の feature は異なるので二度目の require のときも読み込まれたのです。

同じライブラリを require と require_dependency の両方で読み込んでいないか注意しましょう。

プラグインから require するときの注意1

ezfaq_plugin と redmine_xapian plugin の両方を入れたときに Redmine起動時にエラーになることがありました。
原因は両方のプラグインに lib/attachment_patch.rb という同名のファイルがあり
ezfaq_plugin の init.rb での

require 'attachment_patch'

のところで ezfaq_plugin側ではなく redmine_xapian側の attachment_patch.rb が読み込まれてしまったためでした。*1

プラグインの下のファイルを読み込みたいときは

require File.dirname(__FILE__) + '/lib/attachment_patch'

のように「File.dirname(__FILE__) + 相対パス」を使うと確実です。

*1:プラグインはアルファベット順に読み込まれるのになぜ順番が後の redmine_xapian側から読み込まれるのかというとライブラリの検索パスはスタック状に積まれるから(だったと思います)。

Redmine のガントチャートでチケットを開始日順に表示する

ガントチャートでは親子関係をインデントによる階層表示した上で後はチケット番号順に表示しています。
開始日順に表示させる変更は redmine_better_gantt_chartプラグインやその他の試みがありますが私がググって見つけたものを試した限りでは複雑なチケット順、親子関係、開始日順になっている状況では階層表示が親子関係を正しく反映していませんでした。

以下が root までさかのぼって開始日順にソートするパッチです。だたし rootチケットだけは開始日ではなくチケット番号をソート対象にしています。
比較ごとに root までたどる array が作られるので多くのチケットを並べる状況だと重くなるかもしれません。

redmine-1.3.2 で確認しましたがコードを見る限り redmine-2系にも対応していると思います。

--- lib/redmine/helpers/gantt.rb.org
+++ lib/redmine/helpers/gantt.rb
@@ -674,11 +674,17 @@
       end
 
-      # TODO: top level issues should be sorted by start date
-      def gantt_issue_compare(x, y, issues)
-        if x.root_id == y.root_id
-          x.lft <=> y.lft
-        else
-          x.root_id <=> y.root_id
+      def gantt_issue_compare(x, y, issues = nil)
+        get_compare_params(x) <=> get_compare_params(y)
+      end
+
+      def get_compare_params(issue)
+        julian_date = Date.new()
+        ancesters_start_date = []
+        while (parent = issue.parent)
+          ancesters_start_date.unshift(issue.start_date || julian_date)
+          issue = parent
         end
+        ancesters_start_date.unshift(issue.id)
+        ancesters_start_date
       end
 

Redmine カレンダーで前月の月末週、来月の月初週も見たい

カレンダーは月毎に表示されますが月初が日曜日だとその前の週は先月なのでカレンダーにまったく表示されません。
そのため月初めに先週のイベントを確認したいときは先月のカレンダーを改めて表示させる必要があります。
同様に月末が土曜日だと次週のイベントを確認したいときは翌月のカレンダーを改めて表示させる必要があります。

この煩わしさをなくすため、当日が月最初の週のときは必ず前の週から表示するように、月最後の週のときは必ず次の週まで表示するパッチです。

redmine-1.3.2 で確認しましたがコードを見る限り redmine-2系にも対応していると思います。

--- app/controllers/calendars_controller.rb.org
+++ app/controllers/calendars_controller.rb
@@ -39,6 +39,8 @@
     @month ||= Date.today.month
 
     @calendar = Redmine::Helpers::Calendar.new(Date.civil(@year, @month, 
1), current_language, :month)
+    @calendar.startdt -= 1.week if Date.today < @calendar.startdt + 1.week
+    @calendar.enddt += 1.week if Date.today > @calendar.enddt - 1.week
     retrieve_query
     @query.group_by = nil
     if @query.valid?
--- lib/redmine/helpers/calendar.rb.org
+++ lib/redmine/helpers/calendar.rb
@@ -21,7 +21,7 @@
     # Simple class to compute the start and end dates of a calendar
     class Calendar
       include Redmine::I18n
-      attr_reader :startdt, :enddt
+      attr_accessor :startdt, :enddt
 
       def initialize(date, lang = current_language, period = :month)
         @date = date

ひとり Redmine Advent Calendar 2012 目次

明日から「ひとり Redmine Advent Calendar 2012」を始めよう。

1日目 Redmine カレンダーで前月の月末週、来月の月初週も見たい
2日目 Redmine のガントチャートでチケットを開始日順に表示する
3日目 プラグインから require するときの注意1
4日目 プラグインから require するときの注意2
5日目 Redmine の Wiki の履歴とアノテート
6日目 プラグイン紹介 redmine_absolute_dates
7日目 Redmine の数値カスタムフィールドを3桁区切りで表示する
8日目 プラグイン紹介 redmine draft
9日目 プラグイン紹介 redmine_default_columns
10日目 *この日は他の Advent Calendar を書くので欠番にします
11日目 プラグイン紹介 redmine_comment_only
12日目 プラグイン紹介 redmine_better_gantt_chart
13日目 Redmine の検索の対象や出力をカスタマイズ