JavaScript
Redmine
ViewCustomizePlugin
RedmineDay 12

RedmineのJavaScriptから各種データを取得する方法

RedmineのJavaScriptからRedmineの内部データを取得する方法の中で、authenticity_tokenを使う方法と、REST APIを使う方法を紹介する。


authenticity_tokenを使ったデータの取得

Redmine自身のフロントエンドが呼び出している機能を利用する。

各ページに埋め込まれているauthenticity_tokenが必要。


authenticity_tokenの取得

authenticity_tokenはRedmineの全てのページには埋め込まれているわけではない。

何かしらのデータ作成や更新の機能があるページに埋め込まれている模様。

$(':input[name="authenticity_token"]:first').val()

下記ページには埋め込まれているのを確認した。他にもあると思う。


  • グローバルメニュー


    • 「マイページ」

    • 「プロジェクト」 > 新しいプロジェクト

    • 「個人設定」



  • プロジェクトメニュー


    • 「概要」 > 新しいサブプロジェクト

    • 「ロードマップ」

    • 「リリース」 > 新しいリリース

    • 「チケット」

    • 「新しいチケット」

    • 「Wiki」

    • 「文書」

    • 「ニュース」

    • 「ファイル」 > 新しいファイル

    • 「設定」

    • 既存のチケット詳細

    • 作業時間の記録




チケットに入力可能な値の一覧の取得

Redmine自身がチケット入力フォームを部分更新する際に使用しているupdate_form.jsを利用して、チケット入力フォームのHTMLと、HTMLをパースすることでチケットに入力可能なステータスなどの値を取得する。

ここで取得したhtmlIssueFormをjQueryセレクターの第2引数に渡すことで、<input><select>に入力されているパラメータを抽出することもこのHTMLをそのまま利用して自前のチケット情報入力フォームのパーツに流用することもできる

var project_identifier = "redmine-test";

var issue_id = '7'; // if create new issue, set blank.
$.post(
'/projects/' + project_identifier + '/issues/update_form.js' + (issue_id ? 'id=' + issue_id : ''),
{utf8:"✓", authenticity_token:$(':input[name="authenticity_token"]:first').val()}
).done(function(data){
eval(data.split("\n")[0].replace(/^replaceIssueFormWith\(/, 'var htmlIssueForm=').replace(/\);$/, ';'));
// デバッグ表示:HTMLフォーム
console.log(htmlIssueForm);
// デバッグ表示:入力項目の抽出
console.log($(":input", $(htmlIssueForm)));
});

解説すると少しトリッキーなことをしている。(Redmineのバージョンアップで死ぬ可能性がままある)

このレスポンス(data)にはチケット編集のHTMLフォームを置き換えるJavaScriptコードが含まれる。

このJavaScriptの本来の使われ方は、例えばトラッカーが変化するとトラッカーごとに入力フォームの入力項目が変わったり、ユーザーのロールによって選択可能なステータスが変わるなどのリアルタイムなHTMLフォームの変化に用いられている。

上記の処理はそのHTMLフォームの置き換えコードを正規表現で無理矢理に変数htmlIssueFormへの代入に変更してeval()実行している。

これにより置き換えに使われるはずだったHTMLがアクセス可能な変数htmlIssueFormに代入される。


REST APIを使ったデータの取得

Rest api - Redmine

JavaScriptからREST APIでよく取得したくなるデータを抜粋した。

ここでは取得方法のみを軽く書いたが、APIによっては新規作成も更新もできる。

詳細はリンクしているREST APIドキュメントを参照して欲しい。

またJavaScriptからREST APIを呼び出す記事は別途作成した。

RedmineのJavaScriptからREST APIを使用する


ログインユーザーのapikeyの取得

apikeyを取得するような関数は存在しないためログインユーザーの「個人設定」をスクレイピングして取得する。

(下記コードは、当然ながらRedmineのバージョンアップなどで動かなくなる可能性はある)

// Redmineの全バージョンに対応。

// REST APIがONになっていなければapikeyには空文字が入る。
let apikey = "";
$.get('/my/account').done(function(data){
apikey = $("#api-access-key", $(data)).first().text();
});

// Redmine 3.1以上の低負荷版。専用ページなので読み込み負荷は若干低くなるはず。
// REST APIのON/OFFに関わらずapikeyにはAPIキーの文字列が入る。
let apikey = "";
$.get('/my/api_key').done(function(data){
apikey = $('#content > div.box > pre', $(data)).first().text();
});


プロジェクトデータの取得


プロジェクト

Projects - Redmine

var apikey = '****************************************';

// プロジェクト一覧
$.ajax({
type: 'get',
url: '/projects.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));

// プロジェクト詳細
var project_identifier = "redmine-test";

$.ajax({
type: 'get',
url: '/projects/' + project_identifier + '.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));


カテゴリー

Issue Categories - Redmine

var apikey = '****************************************';

var project_identifier = "redmine-test";

$.ajax({
type: 'get',
url: '/projects/' + project_identifier + '/issue_categories.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));


バージョン

Versions - Redmine

var apikey = '****************************************';

var project_identifier = "redmine-test";

$.ajax({
type: 'get',
url: '/projects/' + project_identifier + '/versions.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));


Wiki

Wiki Pages - Redmine

var apikey = '****************************************';

var project_identifier = "redmine-test";

// ページ一覧
$.ajax({
type: 'get',
url: '/projects/' + project_identifier + '/wiki/index.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));

// ページ詳細
var page_name = 'Wiki';

$.ajax({
type: 'get',
url: '/projects/' + project_identifier + '/wiki/' + page_name + '.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));


チケットデータの取得


チケット

Issues - Redmine

var apikey = '****************************************';

// チケット
$.ajax({
type: 'get',
url: '/issues.json',
headers: {'X-Redmine-API-Key': apikey},
data: {project_id:1, limit:100, include:'relations'},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));

// ページ詳細
var issue_id = '15781';

$.ajax({
type: 'get',
url: '/issues/' + issue_id + '.json',
headers: {'X-Redmine-API-Key': apikey},
data: {include:'children,attachments,relations,changesets,journals,watchers'},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));


関連するチケット

Issue Relations - Redmine

var apikey = '****************************************';

var issue_id = '16894';

$.ajax({
type: 'get',
url: '/issues/' + issue_id + '/relations.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));


システム定義データの取得


トラッカー

Trackers - Redmine

var apikey = '****************************************';

$.ajax({
type: 'get',
url: '/trackers.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));


チケットステータス

Issue Statuses - Redmine

var apikey = '****************************************';

$.ajax({
type: 'get',
url: '/issue_statuses.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));


列挙項目

Enumerations - Redmine

var apikey = '****************************************';

$.ajax({
type: 'get',
url: '/enumerations/issue_priorities.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));


カスタムフィールド

Custom Fields - Redmine

※システム管理者のapikeyが必要

var apikey = '****************************************';

$.ajax({
type: 'get',
url: '/custom_fields.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));