チケット一覧のコンテキストメニューに項目を追加して、その項目をクリックしたらサーバ側に選択しているチケットの番号を送って、サーバ側で処理させることができないかという質問をいただいたので、View customize pluginで試行錯誤してみました。
- onozaty/redmine-view-customize - GitHub
- 画面をJavaScript/CSSで簡単にカスタマイズできるRedmineプラグインを作成しました (Redmine view customize plugin) - Enjoy*Study
チケット一覧でのコンテキストメニュー生成の仕組み
チケット一覧のコンテキストメニューは、チケット一覧上での右クリックのタイミングで、選択されている行の情報などをサーバ側に送り、コンテキストメニューの情報(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; /* display the menu above and/or to the left of the click if needed */ 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'); // adding class for submenu if (mouse_y_c < 325) { $('#context-menu .folder').addClass('down'); } } else { // adding class for submenu 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(); //if (window.parseStylesheets) { window.parseStylesheets(); } // IE } }); }
jQueryの関数でフックする
しょうがないので、今回は、jQueryのshow関数でフックするような対応を取りました。
#context-menu
に対してのshowの場合に、メニューを追加する処理を行うイメージです。
View customize の設定内容
Path pattern
チケット一覧を対象とします。
/issues$
Code
Type:JavaScriptとして下記を設定します。
送り先のURLなどは適宜変更してください。
$(function() { // 対象のURL(同一ドメイン) var commandUrl = '/test'; var commandTitle = 'コマンド実行'; // コンテキストメニューを表示したタイミングでフックするために // jQueryのshow関数を差し替え 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(','); // 対象のURIにチケット番号をパラメータとして送信 $.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に対してチケット番号を送るようになります。