Redmineカスタムフィールド
表示改善方法
2016/5/14
redmine.tokyo 第10回勉強会
@y503unavailable
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 1
自己紹介
• 名前:奈良 裕記 ( y503unavailable <- httpエラーコード503)
• 製造業で製品開発部門のadminやってます。
• 部門サーバ、LAN、PC、全般の構築/運用/子守
(全社単位の情報システムとは別、部門所属)
• Redmine歴
• 2009年から利用
• 部内SaaSの積りで各種運用中。
• Redmine.Tokyoには第4回から参加
• 第7回勉強会にてRedmineサーバ統合事例を発表
http://www.slideshare.net/y503unavailable/redmine-42182169
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 2
お断り
• 発表内容は、自分が管理する環境における実施事例
です。
•あくまで参考程度にお願いします。
• 使用していない機能は検証していません。
• 各自環境への適合性は勿論保証できません。
• データ破損が後日発見されるかもしれません。
• 異常処理は何も行っていません.
• より効率的な方法もあるでしょう。
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 3
カスタムフィールド表示改善
Redmineで多数のカスタムフィールドを使用すると、
チケット編集/表示画面が見難くなります。
(固定2列表示・項目区切り無。サイズ調整不可)
しかし、Redmineソースを数個修正するだけで、
編集/表示画面を大幅に改善できます。
サンプルデータ(次頁以降)
• 管理項目:チケット駆動開発本のP39(Redmine)とP70(Mantis)
• Redmine3.2.1ベースで改造
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 4
Redmineデフォルトの編集画面
(カスタムフィールド-14個)
・項目の区切り不明
・長文編集困難(猫の額)
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 5
改造後のRedmine入力画面
• セクション区切り
• 見出し表示
• 行項目数調整
• 編集枠サイズ調整
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 6
改造後の表示画面
• セクション区切り
• 見出し表示
• 行項目数調整
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 7
改造作業手順
1. CFを実際の表示順に並べる(Redmine標準機能)
2. CFの配置/改行位置、入力枠の幅・高さを検討
3. 各項目のCFIDを確認(Redmine標準機能)
4. 区切線/見出しを付ける場合は、直後のCFIDを確認
5. ソース調整/CSS調整
(ソース変更時はRedmine再起動要,CSSは再起動不要)
注意事項
・Redmineコアのソースファイルを編集します。
VUP毎に実施必要(大半はコピペ)
・ファイルはUTF-8で保存必要
・(以下、カスタムフィールド=CFと略記)
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 8
ソース変更内容
対象ソースファイ
ル
(機能)変更内容 VUP時作業 項目変更
時対応
/app/views/issues/sh
ow.html.erb
(表示)render_custom_fields_rows呼
び出し箇所を別名に変更
Patch/コピペ 不要
/app/helpers/issues_
helper.rb
(表示)render_custom_fields_rowsを
別名で保存し変更
・CFを一列表示化
・指定CF直前に見出表示
・CF種別毎タグ調整(改行有無の対
応など)
Patch/コピペ 変更有
/app/views/issues/_f
orm_custom_fields.h
tml.erb
(編集) 表示一列化
CFID毎に処理変更(見出し、改行、、)
Patch/コピペ+
α
変更有
/app/helpers/custom
_fields_helper.rb
(編集)CF表示制御処理を追加
(label,preタグ有無、定型処理)
Patch/コピペ 不要
/public/themes/名
前/application.css
各CFの編集幅/高さ指定 ファイルコ
ピー
変更有
単純にチケット表示/編集のHTML出力部分
を変更しているだけです。。。
CF:カスタムフィールド、UTF-8でファイル保存
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 9
HTMLタグ変更内容
• 行単位出力化
• <p> </p>行頭/行末のみ出力
• <tr><th>1行単位</th></tr>、<td>項目単位</td>
• 項目名の太字化は<th>の代わりに<b>利用
• ThのCSSは無視、tdのCSSは出力
• 区切り線と見出しは、単に<hr><h2>見出しを出
力
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 10
実施効果
• Redmineの利用可能分野拡大
(カスタムフィールドの管理項目多用、既存帳票移行)
• 利用者の作業効率向上
• →Redmine管理者の株価上昇
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 11
禁断のソース変更
• ソース変更はVUPの妨げとなる為、一般に非推奨です。
• 今回の変更は単純で見通し良いので、自分はコピペ
程度の作業で3年間更新し続けました。
• 変更はViewのみでDB差異無し→戻せばOKの安心感
• テキストファイルのため、再コンパイル等は無用。
Redmine自身の再起動のみ。(愛しのInternalError500 (嘘))
• Gem,RAILS,Ruby,,依存関係/Ver非互換でハマるより楽。
• 自分はソース変更でペイしたと考えています。
しかし、、、→次頁
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 12
パッチの関係、3年でついに破局
• Redmine3.2で、改造部分の処理が大幅に変更された。
(rev14846 helpers/issues_helper.rb)
• http://www.redmine.org/projects/redmine/repository/revisions/14846
• Use #issue_fields_rows to render custom fields values.
• 3.2上の従来改造コードでも、現時点では正常に動作
しているが、今後の動作は不明。
• Rev14846は、関連チケット番号が記入されず、
本家ロードマップにも無く、redmine.jpにも記載無し。
SVNから追掛け必要?。。チケット駆動..
• 本稿作成過程で判明。
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 13
今後の対応(他力本願)
• 本手法は、Redmineソース変更以外に、
プラグイン/標準取込により実装可能です。
• 1行表示の選択切替(トラッカー、プロジェクト選択)
• 各カスタムフィールド前後のHTMLタグ出力をWeb上で設定
可能にする。
(CF前後の改行有無、見出し、入力幅/高さ)
• カスタムフィールドの表示幅-CSSファイルの書換
• メリット
• ソース変更不可の環境でも利用可能になる。
• 追加/変更時のRedmine再起動不要
• ということで、どなたか、、 #本家チケット要?アカウント作成しましたが
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 14
結論
• ソース修正で対応できるのはOSSの特権
• Plugin/運用対応より、楽に見通し良く解決できる場合もある。
• 過度に恐れず、適材適所で利用。
できるだけ単純に見通し良く。
・より多くの環境で有効利用できれば良い
• 標準取込/プラグイン対応も選択肢(役に立つなら)
• パッチの賞味期限→標準取込最強。
• みんなでRedmineを(もっと)良くしよう
自分ができることから。
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 15
ソース変更内容詳細
• お断り
• 実際のカスタムフィールドIDに合わせて設定必要です。
間違うと画面が福笑いになります。
• 処理不十分な箇所もあります。参考程度にお願いしま
す。
• 最新(3.2以降)の処理には追随できていません。
(3.2で一応動いてはいますが)
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 16
_form_custom_fields.html.erb
(編集画面のHTML出力)
<% custom_field_values =
@issue.editable_custom_field_values %>
<% if custom_field_values.present? %>
<div class="splitcontent">
<% split_on = custom_field_values.size %>
<% custom_field_values.each do |value| %>
<% case value.custom_field_id
when 4 %>
<hr><h2>障害現象</h2>
<% when 3 %>
<hr><h2>原因</h2>
<% when 10 %>
<hr><h2>処置</h2>
<% end %>
<% case (0+value.custom_field_id)
when 4,6,3 %>
<p>
<%= custom_field_tag_with_label_nopre :issue,
value , :required =>
@issue.required_attribute?(value.custom_field_id) %>
<% when 5,1,7 %>
<%= custom_field_tag_without_label_nopre :issue,
value , :required =>
@issue.required_attribute?(value.custom_field_id) %>
<% when 13,2,8 %>
<%= custom_field_tag_without_label_nopre :issue,
value , :required =>
@issue.required_attribute?(value.custom_field_id) %>
</p>
<% else %>
<p><%= custom_field_tag_with_label :issue,
value, :required =>
@issue.required_attribute?(value.custom_field_id) %></p
>
<% end %>
<% end %>
</div>
<% end %>
セクション
最初のフィールド
区切り線+見出し
行頭
行末
行途中
1項目1行
CFID場合分け
CFID場合分け
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 17
custom_fields_helper.rb 追加分
(編集画面の共通処理追加)
# modified from custom_field_label_tag
# remove label tag , field name BOLD tag
def custom_field_nolabel_tag(name, custom_value,
options={})
required = options[:required] ||
custom_value.custom_field.is_required?
title = custom_value.custom_field.description.presence
content = content_tag 'span',
custom_value.custom_field.name, :title => title
content_required= (required ? " <span
class="required">*</span>".html_safe : "")
"<B>"+content + "</B>" + content_required
end
# Return custom field tag with its label, p tag exclude
# Top <p><label -> <label
# Buttom </p> -> None
def custom_field_tag_with_label_nopre(name,
custom_value, options={})
tag_org=(custom_field_label_tag(name, custom_value,
options) + custom_field_tag(name, custom_value)).strip
tag_org.sub(/A<p>/,'').sub(/</p>Z/,'').html_safe
end
# Return custom field tag with its label, p tag exclude
# Top <p><label -> None
# Buttom </p> -> None
# label tag -> None
def custom_field_tag_without_label_nopre(name,
custom_value, options={})
tag_org=(custom_field_nolabel_tag(name, custom_value,
options) + custom_field_tag(name, custom_value)).strip
tag_org.sub(/A<p>/,'').sub(/</p>Z/,'').html_safe
• end
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 18
issues_helper.rb 追加分(1)
(表示画面のHTML出力)
# modified from render_custom_fields_rows
def render_custom_fields_rows_example(issue)
return if issue.custom_field_values.empty?
# HTML出力文字列の生成(1列化)
s = ""
issue.custom_field_values.compact.each do |value|
css = "cf_#{value.custom_field.id}"
case value.custom_field_id
when 4
s << "n<hr>n"
s << "<tr>nt<th><h2>障害現象
</h2></th><td></td>n</tr>n"
when 3
s << "n<hr>n"
s << "<tr>nt<th><h2>原因
</h2></th><td></td>n</tr>n"
when 10
s << "n<hr>n"
s << "<tr>nt<th><h2>処置
</h2></th><td></td>n</tr>n"
end
case value.custom_field_id
when 4,6,3
# 編集では <p><%=
custom_field_tag_with_label_nopre :issue, value %>
# 1列目(2列目あり)
# 表の行を終わらせない
s <<
"<tr>nt<th><b>#{ h(value.custom_field.name) }</b>:
"
s << "</th>"
s <<
"<td>#{ simple_format_without_paragraph(h(show_value(
value))) } "
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 19
issues_helper.rb 追加分(2)
(表示画面のHTML出力)
when 13,2,8
# 編集では <%=
custom_field_tag_without_label_nopre :issue,
value %></p>
# 最終列(2列目以降で)
# <td>後の途中から始まるth,tdはSP2つで代替
# 最終列なので</td>以降は変化無し
s << "、<b>#{ h(value.custom_field.name) }</b>:"
s << " "
s <<
"#{ simple_format_without_paragraph(h(show_value(value
))) }</td>n</tr><br>"
when 5,1,7
# 編集では <%=
custom_field_tag_without_label_nopre :issue, value %>
# 3列以上の途中
# <td>後の途中から始まるth,tdはSP2つで代替
# 最終列ではないので</td>以降も省略する。
s << "、<b>#{ h(value.custom_field.name) }</b>:"
s << " "
s <<
"#{ simple_format_without_paragraph(h(show_value(value
))) } "
else
# 編集では <p> <%=
custom_field_tag_with_label :issue, value %> </p>
# 1列のみ項目-オリジナルを基にした。(CSS対応含む)
s << "<tr>n"
s << "t<th
class="#{css}"><b>#{ h(value.custom_field.name) }</
b>:</th><td
class="#{css}">#{ h(show_value(value)) }</td><br>"
end
end
s.html_safe
end
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 20
application.css show.html.erb変更分
Application.css 末尾追加分
textarea#issue_custom_field_values_14 { width: 95%;
max-height: 150px; height: 70px; }
select#issue_custom_field_values_4 { width: 5em; }
select#issue_custom_field_values_5 { width: 5em; }
select#issue_custom_field_values_13 { width: 15em; }
select#issue_custom_field_values_6 { width: 7em; }
select#issue_custom_field_values_1 { width: 12em; }
select#issue_custom_field_values_2 { width: 12em; }
select#issue_custom_field_values_11 { width: 7em; }
textarea#issue_custom_field_values_9 { width: 95%;
max-height: 150px; height: 50px; }
select#issue_custom_field_values_3 { width: 12em; }
select#issue_custom_field_values_7 { width: 8em; }
select#issue_custom_field_values_8 { width: 8em; }
textarea#issue_custom_field_values_10 { width: 95%;
max-height: 150px; height: 50px; }
Show.html.erb
(表示)render_custom_fields_rows呼び出し箇所を別名に変更
2016/5/15 第10回redmine.tokyo 勉強会 Redminekカスタムフィールド表示改善 @y503unavailable 21
CSSの設定/確認については、onozaty
さんの下記資料など参照
application.cssを変更しなくとも、View
customize上で対応可能と思います。
View customize plugin を使いこなす!
http://www.slideshare.net/onozaty/vie
w-customizeplugin-62005780
Redmineの画面で振られているclass属
性について
http://blog.enjoyxstudy.com/entry/201
4/10/11/000000

Redmineカスタムフィールド表示改善