torutkのブログ

ソフトウェア・エンジニアのブログ

RedmineでWikiページにカスタムクエリへのリンクを記述する

きっかけ

Redmineのチケット機能を使って、バグ管理、課題管理、Q&A管理、備品管理、タスク管理など様々な作業の管理が行えます。一つのプロジェクトで多数の種類のチケット管理をするようになると、それぞれの種類ごとに一覧表を見られるようにしたくなります。例えば、バグ一覧、課題未着手一覧、備品貸し出し中一覧、Q&A問い合わせ中一覧などです。

Redmineの標準機能であるカスタムクエリを使うと、検索条件を名前を付けて保存することでチケット画面の右側パネルにクエリの名前が表示されて簡単に目的の一覧が見られます。

しかし、いったんチケットに切り替える必要があり、またカスタムクエリの種類が増えるとちょっと選択が手間になってきます。

そこで、Wikiページにカスタムクエリへのリンクを系統立てて記載することができると便利です。Wikiページをプロジェクトのポータルとして位置付けることになります。

ところが、Redmineの標準機能ではカスタムクエリへのリンクがWiki記法には用意されていないので、HTTPのURLをコピー&ペーストすることになります。

h2. 課題管理

* "課題管理一覧(全表示)":/projects/myproject/issues?query_id=12
* "課題管理一覧(未着手)":/projects/myproject/issues?query_id=15
* "課題管理一覧(処置中)":/projects/myproject/issues?query_id=16

とこんな感じです。

ポータルページは、テンプレートとするプロジェクトに作り込んでおき、利用するプロジェクトはこのテンプレートとするプロジェクトからコピーして作成することで、プロジェクトの初期設定を楽にしたいのです。
しかし、URLにプロジェクト識別子が含まれてしまうと、プロジェクトごとに修正しなくてはならず、甚だ厄介です。

URLのリンクからプロジェクト部分を取り除くと、

* "課題管理一覧(全表示)":/issues?query_id=12

他のプロジェクトのチケットも含めて検索して一覧表示します。

ということで、Wikiページにカスタムクエリへのリンクを、プロジェクト識別子(名)を含めることなくWikiページのプロジェクトのチケットを検索範囲とするように設けたいな、という動機です。

プラグインとかで実現していないのかを調査

まず、Redmineの開発管理チケットで、"Link to custom query from wiki"というズバリなチケットが見つかりました。
http://www.redmine.org/issues/3258

7年前に作成され、ステータスは"New"のまま、進展はまったくなさそうです。

次は、Wiki Extensionsプラグインの開発管理チケットで、"Link to queries"というこれもズバリなチケットが見つかりました。
http://www.r-labs.org/issues/828

5年前に作成され、マクロ仕様について議論が少しありますが、進展はなさそうです。

Wiki Listsプラグインは、Wikiページにカスタムクエリ結果を表示するという機能があります。あくまでWikiページ内に表としてチケット一覧を表示するので、今回の用途とはちょっと違いました。
http://www.r-labs.org/projects/wiki_lists/wiki/Wiki_Lists

ということで、現状では実現されていないと判断し、自分で作る方法を模索することとします。

View Customizeプラグインでできるか?

HTML中のURLの一部(プロジェクト識別子)を、動的にプロジェクト識別子を拾って置換することができれば、といじり始めました。が、非Web系プログラマーとしてはHTML・JavaScriptを屠ることができず挫折。

プラグインを書くか?

Wiki上の表記をいじるのはちょっと筋が違うような・・・

マクロで書くか?

torutk.hatenablog.jp
で、Wiki Listsプラグインを利用した際に、マクロのパラメータ指定方法を調べるのにソースを少し追ってみました。そのときに、現在のプロジェクトを取得するなどしており、これならマクロで実現できそうだと思いました。

そこで、まずチケット一覧ページの右パネルにあるカスタムクエリへのリンクをどう実装しているか、Redmineソースコードを追ってみたところ、次のようになっていました(コードは分かりやすいように置き換え)。

  • チケット一覧表示は、app/views/issues/index.html.erb
  • 右側パネル(sidebar)は、app/views/issues/_sidebar.html.erb に委譲(render :partial)
  • クエリへのリンク生成は、app/helpers/issues_helper.rb

クエリ生成の中では、lint_to を使って次のように指定しています。

link_to("バグ確認待ち", 
        {:controller => 'issues', :action => 'index',
         :project_id => @project, :query_id => query, :class= 'query'})

リンク文字列とカスタムクエリIDを指定すれば、プロジェクトはWikiページの続するプロジェクトを自動で指定した、任意のリンクが生成できそうです。

マクロの作成

見よう見真似でマクロを作成してみます。マクロもプラグインとして作成します。プラグイン名は"query_links"としました。

redmine-3.3.0$ cd plugins
plugins$ mkdir query_links
plugins$ cd query_links
query_links$

plugins/query_links/init.rb を作成します。

Redmine::Plugin.register :query_links do
  name 'Query Links plugin'
  author 'Toru Takahashi'
  description 'create macro which links to custom query.'
  version '0.0.1'
  url 'http://d.hatena.ne.jp/torutk/20161007'
  author_url 'http://d.hatena.ne.jp/torutk/about'
end

Redmine::WikiFormatting::Macros.register do
  desc "create macro which links to custom query."
  macro :query_link do |obj, args|
    text, query_id = args.first(2)
    link_to(text, {:controller => 'issues', :action => 'index',
        :project_id => @project, :query_id => query_id},
        :class => 'query')
  end
end

前半の、Redmine::Plugin.register は、プラグインの情報を提供する部分でプラグインのお決まりの定義です。
後半の、Redmine::WikiFormatting:Macros.register は、Wikiマクロを定義する部分です。descでWikiマクロの説明を記述、macroでマクロ定義を記述します。

Wikiマクロ名が :query_link で、これはWiki中にマクロ {{query_link(...)}}と記述する際の名前となります。

マクロで引数を指定すると、上述コードのargs配列に入ります。
ここでは、1つ目の引数をリンク文字列、2つ目の引数をカスタムクエリIDと決め打ちして取得しています。

Wikiページが属するプロジェクトは、@projectにあらかじめ設定されていました*1

link_to には次を渡します。

  1. 第一引数にWiki上でリンク箇所となる文字列
  2. 第二引数にRailsのパス(コントローラ、アクション、および付加情報としてプロジェクト、クエリID)を指定
  3. 第三引数はHTMLオプションとしてclass属性を指定

Railsサーバーを再起動し、query_linksがプラグインとして認識されていることを確認します。

カスタムクエリをいくつか生成し、そのIDを確認し(チケット一覧で右側パネルのカスタムクエリのリンクURLを見るとIDが分かります)、Wikiページを編集します。

h3. Query Linksマクロの実験

* {{query_link(課題管理一覧(全表示), 12)}}
* {{query_link(課題管理一覧(未着手), 15)}}
* {{query_link(課題管理一覧(処置中), 16)}}

Wiki上では、「未着手のタスク」がリンク文字列となり、クリックするとカスタムクエリの結果画面(チケット一覧)となればOKです。

解決

Wiki記述上にはプロジェクトを特定するコードがないので、query_linkを含むWikiページを別のプロジェクトに移動した場合や、プロジェクトをコピーして新たなプロジェクトを作成した場合でも、リンクの記述を修正することなく移動/コピー先のプロジェクトのチケットを対象にカスタムクエリを呼び出すことができるようになります。

*1:Wikiマクロは、おそらくWikiコントローラのコンテキストで動作しており、Wikiコントローラが@projectに現在のプロジェクトを設定していると推測ます。