チケット一覧のコンテキストメニューに項目を追加して、その項目をクリックしたらサーバ側に選択しているチケットの番号を送って、サーバ側で処理させることができないかという質問をいただいたので、View customize pluginで試行錯誤してみました。
チケット一覧でのコンテキストメニュー生成の仕組み
チケット一覧のコンテキストメニューは、チケット一覧上での右クリックのタイミングで、選択されている行の情報などをサーバ側に送り、コンテキストメニューの情報(HTMLの断片)を受け取って、それをdiv#context-menu
に設定しています。
具体的には、context_menu.js
内の、contextMenuShow
関数で行っています。$.ajax
で通信し、そのコールバックでコンテキストメニューを作ってしまっているので、Redmine側のコード上だとフックするポイントがありません。。
function contextMenuShow(event) {
var mouse_x = event.pageX;
var mouse_y = event.pageY;
var mouse_y_c = event.clientY;
var render_x = mouse_x;
var render_y = mouse_y;
var dims;
var menu_width;
var menu_height;
var window_width;
var window_height;
var max_width;
var max_height;
$('#context-menu').css('left', (render_x + 'px'));
$('#context-menu').css('top', (render_y + 'px'));
$('#context-menu').html('');
$.ajax({
url: contextMenuUrl,
data: $(event.target).parents('form').first().serialize(),
success: function(data, textStatus, jqXHR) {
$('#context-menu').html(data);
menu_width = $('#context-menu').width();
menu_height = $('#context-menu').height();
max_width = mouse_x + 2*menu_width;
max_height = mouse_y_c + menu_height;
var ws = window_size();
window_width = ws.width;
window_height = ws.height;
if (max_width > window_width) {
render_x -= menu_width;
$('#context-menu').addClass('reverse-x');
} else {
$('#context-menu').removeClass('reverse-x');
}
if (max_height > window_height) {
render_y -= menu_height;
$('#context-menu').addClass('reverse-y');
if (mouse_y_c < 325) {
$('#context-menu .folder').addClass('down');
}
} else {
if (window_height - mouse_y_c < 345) {
$('#context-menu .folder').addClass('up');
}
$('#context-menu').removeClass('reverse-y');
}
if (render_x <= 0) render_x = 1;
if (render_y <= 0) render_y = 1;
$('#context-menu').css('left', (render_x + 'px'));
$('#context-menu').css('top', (render_y + 'px'));
$('#context-menu').show();
}
});
}
jQueryの関数でフックする
しょうがないので、今回は、jQueryのshow関数でフックするような対応を取りました。
#context-menu
に対してのshowの場合に、メニューを追加する処理を行うイメージです。
View customize の設定内容
Path pattern
チケット一覧を対象とします。
/issues$
Code
Type:JavaScriptとして下記を設定します。
送り先のURLなどは適宜変更してください。
$(function() {
var commandUrl = '/test';
var commandTitle = 'コマンド実行';
jQuery.fn._show = jQuery.fn.show;
jQuery.fn.show = function() {
if (this.attr('id') == 'context-menu') {
var menu = $('<a>').text(commandTitle).click(function() {
execute();
return false;
})
this.children('ul').append($('<li>').append(menu));
}
return jQuery.fn._show.apply(this, arguments);
};
var execute = function() {
var issues = $('input[name="ids[]"]:checked').map(function() { return $(this).val();}).get().join(',');
$.ajax({
type: 'GET',
url: commandUrl,
data: 'issues=' + issues
}).done(function(data, textStatus, jqXHR){
alert('成功しました。');
}).fail(function(jqXHR, textStatus, errorThrown){
alert('失敗しました。 status:' + jqXHR.status);
});
contextMenuHide();
};
});
設定後のイメージ
コンテキストメニューに項目が追加され、これをクリックすると、対象のURLに対してチケット番号を送るようになります。