Redmineの画面を
あなた好みにカスタマイズ
- View customize pluginの紹介 -
2020-09-18 Redmine Japan 2020 [B07]
@onozaty
自己紹介
• Hirokazu Onozato
• 株式会社ユニスティ所属
• ソフトウエア開発者
• プログラムを書くのが好き
• 個人でChrome/Firefoxの拡張機能や、ちょっとしたツールなど
作って公開
@onozaty
https://github.com/onozaty
Redmineとの関わり
• Redmine歴は11年くらい
• 主にアプリケーション開発のタスク管理に利用
• Redmineに関連して作ったもの (今もメンテナンスしているもの)
• View customize plugin https://github.com/onozaty/redmine-view-customize
• 本日詳しく紹介
• Redmine issue loader https://github.com/onozaty/redmine-issue-loader
• CSVを読み込んでRedmineにチケットとして取り込む(新規、更新)するため
のツール
View customize plugin
View customize plugin
• Redmineの画面をカスタマイズするためのPlugin
• 特定の画面に対して、JavaScript、CSSを埋め込む機能を提供
• ブラウザのUserScriptを、クライアントではなくサーバ側で設定し
て、Redmineを使用する全ユーザに適用するイメージ
• 再起動不要で、手軽にRedmineをカスタマイズできる
できること
• JavaScriptとCSSを埋め込んで実行できるので、画面上に存在する情
報で完結することはたいていできる
• 画面上に存在しない情報(ユーザのカスタムフィールドやAPIキーな
ど)にアクセスする方法もプラグインとして提供しているので、それ
らを組み合わせると、出来ることの幅はさらに広がる
例
例:バナーを表示
例:プロジェクトによってヘッダの色を切り替え
例:チケット一覧を装飾
適用前
適用後
例:カスタムフィールドを連動
適用前
適用後
例:子チケット作成時に親チケットの情報を引き継ぐ
例:担当者の選択でインクリメンタルサーチ
適用前 適用後
例:複数の子チケットをまとめて作成
使い方
インストール方法
• Redmineのpluginsディレクトリにファイルを配置して、bundle
installとmigrateを実施して、Redmineを再起動
• ディレクトリ名は view_customize としてください
cd {RAILS_ROOT}/plugins
git clone https://github.com/onozaty/redmine-view-customize.git view_customize
cd ../ bundle install --without development test
bundle exec rake redmine:plugins:migrate RAILS_ENV=production
インストールがうまくいかなかったという問い合わせの
大半はこれが原因
設定方法
管理 > 表示のカスタマイズ > 新しい表示のカスタマイズ で新規設定へ
設定方法
実行対象の指定
実行するコード
その他
設定画面
設定画面:実行対象の指定
• パス(URL)とプロジェクト(識別子)を正規表現で入力することで、実
行対象とする画面を絞る ※プロジェクトは v2.7.0 から
• コードの挿入位置を下記から選択
• 全ページのヘッダ
• チケット入力欄の下
• チケット詳細の下
設定画面:実行するコード
• 種別は下記から選択 (種別によってコードの埋め込まれ方が変わる)
• JavaScript (scriptタグで埋め込まれる)
• CSS (styleタグで埋め込まれる)
• HTML (そのままの状態で埋め込まれる) ※v2.1.0から
設定画面:その他
• コメントは一覧上で表示される
• 設定内容を表すものを入れておくことで、識別しやすくなる
• 有効のチェックを外すと、設定を無効にできる
• プライベートにチェックすると、作成者のみに適用できる
実行
実行対象にコードが
埋め込まれて実行
設定内容と実行結果の例 (JavaScript)
チケット入力欄でステータスとして却下を
選んだ時に、期日が未入力ならば現在日を
期日として入れるように設定
設定内容と実行結果の例 (CSS)
プロジェクトaの場合に、ヘッダとトップ
メニューの色が緑になるように設定
設定に関するノウハウ
実行対象の絞り込み方
実行対象の絞り込み方:挿入位置
まずは挿入位置で対象を絞り込めるか考える
• 全ページのヘッダ
• すべての画面が対象になる
• チケット入力欄の下
• チケット新規作成画面、チケット表示・編集画面が対象になる
• チケット入力欄は、トラッカーやステータスを変えた際に再構築されるが、
再構築の際にも再度挿入される
• チケット詳細の下
• チケット表示・編集画面が対象になる
実行対象の絞り込み方:パスパターン
挿入位置だけで絞り込めない場合、パスを正規表現で指定することで、
さらに絞り込みを行う
• URLでアプリケーション配下かつクエリパラメータを含まない部分
がパス
• http://192.168.33.41/redmine/projects/a/issues?xxx=xx -> /projects/a/issues
• View customizeでHTMLにパスをコメントとして埋め込んでいるの
で、ブラウザのソース表示でみれば、その画面のパスが確認できる
実行対象の絞り込み方:パスパターンの指定例
パスパターン 一致する画面
/issues$ チケット一覧
/issues/new$ チケットの新規作成画面
/issues/[0-9]+/copy$ チケットのコピーによる作成画面
/issues/gantt ガントチャート
/projects$ プロジェクト一覧
/projects/.+/wiki Wiki
v2.7.0 からパスパターンは任意となったため、パスパターンで絞り
込みたくない場合に .* を入れる必要が無くなった
.*[]+$ といった文字は、正規表現におけるメタ文字(特殊な意味をもった文字)
実行対象の絞り込み方:プロジェクトパターン
特定のプロジェクトのみで適用したい場合に、プロジェクト識別子を
正規表現で指定する ※v2.7.0 にて追加
• チケット表示画面だと、パスにプロジェクトの情報が入らないので、
v2.7.0より前だとJavaScriptのコードとして判断する必要があった
• プロジェクト識別子は、プロジェクト配下の画面にアクセスすると、
URLからわかる
URLが /projects/a なので、
プロジェクト識別子は a
CSSセレクタ
CSSセレクタ
• CSSセレクタとは、CSSでスタイルを適用する対象を示すもの
• CSSを書く場合だけでなく、JavaScriptで対象要素を操作するのにも、
CSSセレクタが重要
セレクタ名 書式 対象
型セレクタ E E要素
idセレクタ E#myid id属性がmyidのE要素
classセレクタ E.warning class属性がwarinigのE要素
子孫セレクタ E F E要素の子孫にあたるF要素
子セレクタ E > F E要素の子にあたるF要素
(子孫セレクタは、E要素の配下ならば、どこにあって
も良いが、子セレクタは、1階層下のみが対象)
【良く使うセレクタ】
※セレクタは他にもいろいろあるので、詳しく知りたい方は「CSSセレクタ」で検索を
RedmineとCSSセレクタ
• Redmineでは、必要となるような要素へのid、class属性が適切に振
られている
• 入力項目となるような要素へはid属性
• body要素やチケット一覧には、内容を表すようなclass属性も付与
class属性
• body要素
• チケット一覧の各行
• project-{プロジェクト識別子}
• controller-{コントローラ名}
• action-{アクション名}
• tracker-{トラッカーID}
• status-{ステータスID}
• priority-{優先度ID}
• created-by-me
• assigned-to-me
参考:Redmineの画面で振られているclass属性について
https://blog.enjoyxstudy.com/entry/2014/10/11/000000
ViewCustomize.context
ViewCustomize.context
ユーザやプロジェクトの情報にJavaScriptで簡単にアクセスできるよう
に、ViewCustomize.context というオブジェクトが用意されている
分類 項目
ユーザ ユーザID、ログインID、管理者かどうか、姓名、最終ログイン日時、グループ、
APIキー、カスタムフィールド
プロジェクト 識別子、名前、ロール、カスタムフィールド
チケット チケットID
ViewCustomize.context
ViewCustomize = {
"context": {
"user": {
"id": 1,
"login": "admin",
"admin": true,
"firstname": "Redmine",
"lastname": "Admin",
"lastLoginOn": "2019-09-22T14:44:53Z",
"groups": [{"id": 5, "name": "Group1"}],
"apiKey": "3dd35b5ad8456d90d21ef882f7aea651d367a9d8",
"customFields": [{"id": 1, "name": "[Custom field] Text", "value": "text"}]
},
"project": {
"identifier": "project-a",
"name": "Project A",
"roles": [{"id": 6, "name": "RoleX"}],
"customFields": [{"id": 4, "name": "[Project Custom field] Text", "value": "text"}]
},
"issue": {
"id": 1
}
}
}
例:カスタムフィールドを使った制御
• ユーザのカスタムフィールド(真偽値)によって、スクリプトの適用
可否を判断
• 管理者ではなく、ユーザ側に選択権を持たせることができる
例:カスタムフィールドを使った制御
$(function() {
const isEnabled = ViewCustomize.context.user.customFields
.some(function(customField) {
// チェックしたいカスタムフィールドのIDと値でチェック ("1"がtrue)
return customField.id == 1 && customField.value == '1';
});
if (!isEnabled) {
// 無効の場合は処理終了
return;
}
// 以降実際に実行したいスクリプト
console.log('execute script.');
});
例: APIキーを使ってREST APIを呼び出し
• ユーザのAPIキーを利用することで、Redmineの様々なREST APIを呼
び出し可能に
• REST APIを使うと、各種情報の登録、更新なども行えるようになり、
自由度が高まる
その分コードが複雑になっていくので、
ある程度覚悟を持ってやる必要あり
例: APIキーを使ってREST APIを呼び出し
$.ajax({
type: 'PUT',
url: '/issues/' + issueId + '.json',
headers: {
'X-Redmine-API-Key': ViewCustomize.context.user.apiKey // APIキー取得
},
// 更新時はレスポンスのコンテンツが無く、jsonだとエラーとなるのでtextにしておく
dataType: 'text',
contentType: 'application/json',
data: JSON.stringify({
'issue': {
'parent_issue_id': '' // 親チケットIDをクリア
}
})
})
.done(function(data) {
// 成功したらリロード
location.reload();
})
.fail(function(data) {
alert('失敗しました');
});
REST APIを使って親チケットをクリアする部分の例
APIキーに関する注意事項
• 設定画面より「RESTによるWebサービスを
有効にする」にチェック
• これをしないと、REST API自体が使えない
• 各自で個人設定からAPIアクセスキーを1度
表示しておく
• RedmineでのAPIキー払い出しが、最初に
表示したタイミングになっているため
• これが面倒な場合は、プラグインの設定で「APIアクセスキーを自動的に作
成する」をチェックしておくと、自動的に作られるようになる
外部JavaScriptの読み込み
外部JavaScriptの読み込み
• 種別としてHTMLを指定すると、HTMLをそのままで埋め込めるので、
外部JavaScriptの読み込みも簡単に指定できる
• scriptタグのsrc属性で読み込むだけ
• JavaScriptライブラリをCDNなどから読み込めば、やれることの幅
が広がる
• JavaScriptライブラリを読み込んで、テキストエリアでの入力補完を実装し
た例 https://blog.enjoyxstudy.com/entry/2019/03/22/000000
外部JavaScriptの読み込み
Redmine自体で既に使われているJavaScriptライブラリは、View
customize側で読み込みをしなくても使える
• jQuery
• jQuery UI
• Tribute.js ※4.1.0で追加された
ブラウザのDeveloper Toolの活用
ブラウザのDeveloper Toolの活用
いきなりView customizeでコードを書き始めるのではなく、ブラウザ
のDeveloper Toolを使いながら、作成、確認をしていくと良い
• 「DOMインスペクタ」を使って、変更したい箇所のHTML構造など
を確認する
• 「コンソール」上でコードを実行し、どういった結果になるか確認
• うまくいったら、View customizeとして設定する
DOMインスペクタ
選択した要素がHTML上でどういった構造になっているか確認できる
ブラウザ上での選択箇所と
Elementsパネルでの選択箇所が
連動することでHTMLの内容が
簡単に確認できる
コンソール
表示している画面でコードを実行し、動作を確認できる
コードを入力し実行すると、
ブラウザ上にリアルタイムに
反映される
うまく動かないときの確認ポイント
対象画面の指定があっているか
• ブラウザ上でソース表示して、View customizeで指定したコードが
埋め込まれているか確認
• 埋め込まれていない場合には、挿入位置、パス、プロジェクトパ
ターンのいずれかが間違えている
JavaScriptでエラーが発生していないか
• Developer Toolでエラーメッセージが出力されていないか確認
• エラーメッセージが出力されていれば、エラー内容を元に修正
スタイルが上書きされていないか
• 複数のスタイルが一致する場合、その要素に対してどのスタイルが
適用されるかは、優先度によって決まる
• より詳細に指定している方が優先
• 型セレクタよりidセレクタの方が優先など
• セレクタのレベルが同じならば、後から書かれたものが優先
スタイルが上書きされていないか
• Developer Toolで見ると、どういった優先度で適用されているかわ
かる
取り消し線がついているもの
は、優先度の高いスタイルに
よって上書きされたもの
Redmineでの試し方
運用中のRedmine環境
• 運用中の環境で試す場合、いきなり全体に適用してしまうと想定通
りの動きをしなかった場合に影響が大きいので、まずは作成者のみ
に適用されるように「プライベート」にチェックを付けて確認する
別途Redmine環境を用意
• Redmineを試すにあたって様々な構築方法が用意されているので、
それを利用して動作環境を作る
• Ansible
• https://github.com/farend/redmine-centos-ansible
• Docker
• https://hub.docker.com/_/redmine
• Vagrant
• https://app.vagrantup.com/onozaty/boxes/redmine-4.1
例:Vagrant
Vagrantがインストールされている状態で、コマンド2つでRedmineの
環境を立ち上げられる
View customizeがインストール済みのboxもあるので、View customize
を試すときは、それを使うとプラグインのインストールも不要
※Vagrantfileでネットワークの設定は適宜
vagrant init onozaty/redmine-4.1
vagrant up
vagrant init onozaty/redmine-viewcustomize
vagrant up
コードを書くのが大変?
コードを書くのが大変?
• サンプルコードも公開されているので、それを参考にすれば大丈夫
• onozaty/redmine-view-customize-scripts
https://github.com/onozaty/redmine-view-customize-scripts
• farend/redmine-view-customize-examples: Redmineのプラグイン「View
customize」を利用したRedmineカスタマイズ集
https://github.com/farend/redmine-view-customize-examples
• 「redmine view customize」の検索結果 - Qiita
https://qiita.com/search?sort=&q=redmine+view+customize
• エンジニアではない人でも、サンプルコードを参考にながらカスタ
マイズしている
おわりに
• 困ったことや、わからないことがあれば、お気軽に @onozaty まで
• Twitterでは新しいカスタマイズ例などのつぶやきも
• こういったことできますか?といったような質問は、GitHubのIssue
でもOK
• https://github.com/onozaty/redmine-view-customize-scripts

Redmineの画面をあなた好みにカスタマイズ - View customize pluginの紹介 - Redmine Japan 2020