2016年2月25日木曜日

Redmineでクリックすると値が加算されるフィールドを作る

Redmineのカスタムフィールドを使用して、値をクリックすると+1されるフィールドなんてものを作ってみました。早い話が「いいね!」ボタンです。

Wiki Extensionにはvoteがあるのでいいね!が使えますが、チケットにはありません。
 チケットでもやりたくなりいろいろ考えたところ、カスタムフィールドのURLリンク機能を使い、そこにJavascriptを直接記述する、という方法を見つけました。
我ながらなかなかイカス方法と思います。

・環境
Redmine 2.6.5(bitnami)

・設定

(Redmine管理者)
REST APIを有効に。
カスタムフィールドを作成し、整数、初期値0とする。ここでは「いいね!」という名前にしておく。
(プロジェクト担当者)
使うプロジェクトでこのカスタムフィールドを使うように設定。

・jsでのプログラム

下記プログラムを作成。
なお、cfid="1"とありますが、これはカスタムフィールドのIDです。作成したカスタムフィールドのIDに置き換えてください。
あとパスも環境に合わせて直してください。


javascript:
cfid="1";
var keyreq=new XMLHttpRequest();
keyreq.open("GET", "/redmine/my/account", true);
keyreq.onreadystatechange=function(){
        if(keyreq.readyState == 4 && keyreq.status == 200) {
                keyres = keyreq.responseText;
                var key = "";
                result = keyres.match(/\<pre id\=\'api-access-key\'.*\>([0-9a-zA-Z]*)\<\/pre\>/);
                if(result != null){
                        key = result[1];
                }else{
                        alert("ng");
                        return;
                }

                var rreq=new XMLHttpRequest();

                rreq.open("GET", "/redmine/issues/%id%.xml?format=xml&key=" + key, true);
                rreq.onreadystatechange=function(){
                        if(rreq.readyState == 4 && rreq.status == 200){
                                var xml = rreq.responseXML;
                                var value = %value%;
                                cfs = xml.getElementsByTagName("custom_field");
                                for (i = 0; i < cfs.length; i ++) {
if (cfs[i].getAttribute("id") == cfid) {
value = parseInt(cfs[i].getElementsByTagName("value")[0].textContent, 10);
}
                                }

                                var req=new XMLHttpRequest();
                                req.onreadystatechange=function(){
if (req.readyState == 4) {
location.reload()
}
                                };
                                req.open('PUT',"/redmine/issues/" + %id% + ".xml?format=xml&key=" + key);
                                req.setRequestHeader("content-type","application/xml");
                                req.send('<?xml version="1.0" encoding="UTF-8" ?>\n<issue><custom_fields type="array"><custom_field id="' + cfid + '"><value>' + (value + 1).toString(10) + '</value></custom_field></custom_fields></issue>');
                        }
                };
                rreq.send("");

        }
};
keyreq.send("");




これを、一行に直し、カスタムフィールドのリンクURLに設定する。

・動作原理
カスタムフィールドにはリンクを設定できるが、そこにjavascriptのコードが直接書けるようだ。
そこで、カスタムフィールドの更新のコードを入れることでクリックすると更新することが可能になる。

下記3回のアクセスを行っている。
1. keyを取得するために個人設定のページにアクセス
2. 元の値を取るためにGETアクセス(これをしないとチケットを開いてからしばらくたってクリックすると古い値+1で更新してしまう可能性がある)
3. カスタムフィールドの値を更新するためにPUTアクセス

URLリンク欄って結構長いコードも書けるようで驚き。
・免責
最近のRedmineでどうなっているかは不明。
また、プラグインを入れればいいじゃん、というご意見もごもっとも。

※コードはこちらを利用して変換して貼り付け。