Changeset - 96ed562709f9
[Not reviewed]
default
0 3 0
Thomas De Schampheleire - 11 years ago 2015-06-24 21:32:26
thomas.de.schampheleire@gmail.com
autocomplete: remove dead code

The three blocks of autocomplete code are clearly copy/pasted from one
another, with dead code remaining due to group-autocomplete not being
relevant for some cases.
3 files changed with 6 insertions and 36 deletions:
0 comments (0 inline, 0 general)
kallithea/public/js/base.js
Show inline comments
 
@@ -542,385 +542,385 @@ var _move_tooltip = function(e){
 
    e.stopImmediatePropagation();
 
    var $tipBox = $('#tip-box');
 
    $tipBox.css('top', (e.pageY + 15) + 'px');
 
    $tipBox.css('left', (e.pageX + 15) + 'px');
 
};
 

	
 
var _close_tooltip = function(e){
 
    e.stopImmediatePropagation();
 
    var $tipBox = $('#tip-box');
 
    $tipBox.hide();
 
    var el = e.currentTarget;
 
    $(el).attr('title', $(el).attr('tt_title'));
 
};
 

	
 
/**
 
 * Quick filter widget
 
 *
 
 * @param target: filter input target
 
 * @param nodes: list of nodes in html we want to filter.
 
 * @param display_element function that takes current node from nodes and
 
 *    does hide or show based on the node
 
 */
 
var q_filter = (function() {
 
    var _namespace = {};
 
    var namespace = function (target) {
 
        if (!(target in _namespace)) {
 
            _namespace[target] = {};
 
        }
 
        return _namespace[target];
 
    };
 
    return function (target, $nodes, display_element) {
 
        var $nodes = $nodes;
 
        var $q_filter_field = $('#' + target);
 
        var F = namespace(target);
 

	
 
        $q_filter_field.keyup(function (e) {
 
            clearTimeout(F.filterTimeout);
 
            F.filterTimeout = setTimeout(F.updateFilter, 600);
 
        });
 

	
 
        F.filterTimeout = null;
 

	
 
        F.updateFilter = function () {
 
            // Reset timeout
 
            F.filterTimeout = null;
 

	
 
            var obsolete = [];
 

	
 
            var req = $q_filter_field.val().toLowerCase();
 

	
 
            var showing = 0;
 
            $nodes.each(function () {
 
                var n = this;
 
                var target_element = display_element(n);
 
                if (req && n.innerHTML.toLowerCase().indexOf(req) == -1) {
 
                    $(target_element).hide();
 
                }
 
                else {
 
                    $(target_element).show();
 
                    showing += 1;
 
                }
 
            });
 

	
 
            $('#repo_count').html(showing);
 
            /* FIXME: don't hardcode */
 
        }
 
    }
 
})();
 

	
 
/* return jQuery expression with a tr with body in 3rd column and class cls and id named after the body */
 
var _table_tr = function(cls, body){
 
    // like: <div class="comment" id="comment-8" line="o92"><div class="comment-wrapp">...
 
    // except new inlines which are different ...
 
    var comment_id = ($(body).attr('id') || 'comment-new').split('comment-')[1];
 
    var tr_id = 'comment-tr-{0}'.format(comment_id);
 
    return $(('<tr id="{0}" class="{1}">'+
 
                  '<td class="lineno-inline new-inline"></td>'+
 
                  '<td class="lineno-inline old-inline"></td>'+
 
                  '<td>{2}</td>'+
 
                 '</tr>').format(tr_id, cls, body));
 
};
 

	
 
/** return jQuery expression with new inline form based on template **/
 
var _createInlineForm = function(parent_tr, f_path, line) {
 
    var $tmpl = $('#comment-inline-form-template').html().format(f_path, line);
 
    var $form = _table_tr('comment-form-inline', $tmpl)
 

	
 
    // create event for hide button
 
    $form.find('.hide-inline-form').click(function(e) {
 
        var newtr = e.currentTarget.parentNode.parentNode.parentNode.parentNode.parentNode;
 
        if($(newtr).next().hasClass('inline-comments-button')){
 
            $(newtr).next().show();
 
        }
 
        $(newtr).remove();
 
        $(parent_tr).removeClass('form-open');
 
        $(parent_tr).removeClass('hl-comment');
 
    });
 

	
 
    return $form
 
};
 

	
 
/**
 
 * Inject inline comment for an given TR. This tr should always be a .line .
 
 * The form will be inject after any comments.
 
 */
 
var injectInlineForm = function(tr){
 
    var $tr = $(tr);
 
    if(!$tr.hasClass('line')){
 
        return
 
    }
 
    var submit_url = AJAX_COMMENT_URL;
 
    var $td = $tr.find('.code');
 
    if($tr.hasClass('form-open') || $tr.hasClass('context') || $td.hasClass('no-comment')){
 
        return
 
    }
 
    $tr.addClass('form-open hl-comment');
 
    var $node = $tr.parent().parent().parent().find('.full_f_path');
 
    var f_path = $node.attr('path');
 
    var lineno = _getLineNo(tr);
 
    var $form = _createInlineForm(tr, f_path, lineno, submit_url);
 

	
 
    var $parent = $tr;
 
    while ($parent.next().hasClass('inline-comments')){
 
        var $parent = $parent.next();
 
    }
 
    $form.insertAfter($parent);
 
    var $overlay = $form.find('.submitting-overlay');
 
    var $inlineform = $form.find('.inline-form');
 

	
 
    $form.submit(function(e){
 
        e.preventDefault();
 

	
 
        if(lineno === undefined){
 
            alert('Error submitting, line ' + lineno + ' not found.');
 
            return;
 
        }
 
        if(f_path === undefined){
 
            alert('Error submitting, file path ' + f_path + ' not found.');
 
            return;
 
        }
 

	
 
        var text = $('#text_'+lineno).val();
 
        if(text == ""){
 
            return;
 
        }
 

	
 
        $overlay.show();
 

	
 
        var success = function(json_data){
 
            $tr.removeClass('form-open');
 
            $form.remove();
 
            _renderInlineComment(json_data);
 
            linkInlineComments($('.firstlink'), $('.comment'));
 
        };
 
        var postData = {
 
                'text': text,
 
                'f_path': f_path,
 
                'line': lineno
 
        };
 
        ajaxPOST(submit_url, postData, success);
 
    });
 

	
 
    $('#preview-btn_'+lineno).click(function(e){
 
        var text = $('#text_'+lineno).val();
 
        if(!text){
 
            return
 
        }
 
        $('#preview-box_'+lineno).addClass('unloaded');
 
        $('#preview-box_'+lineno).html(_TM['Loading ...']);
 
        $('#edit-container_'+lineno).hide();
 
        $('#edit-btn_'+lineno).show();
 
        $('#preview-container_'+lineno).show();
 
        $('#preview-btn_'+lineno).hide();
 

	
 
        var url = pyroutes.url('changeset_comment_preview', {'repo_name': REPO_NAME});
 
        var post_data = {'text': text};
 
        ajaxPOST(url, post_data, function(html){
 
            $('#preview-box_'+lineno).html(html);
 
            $('#preview-box_'+lineno).removeClass('unloaded');
 
        })
 
    })
 
    $('#edit-btn_'+lineno).click(function(e){
 
        $('#edit-container_'+lineno).show();
 
        $('#edit-btn_'+lineno).hide();
 
        $('#preview-container_'+lineno).hide();
 
        $('#preview-btn_'+lineno).show();
 
    })
 

	
 
    setTimeout(function(){
 
        // callbacks
 
        tooltip_activate();
 
        MentionsAutoComplete('text_'+lineno, 'mentions_container_'+lineno,
 
                             _USERS_AC_DATA, _GROUPS_AC_DATA);
 
                             _USERS_AC_DATA);
 
        $('#text_'+lineno).focus();
 
    },10)
 
};
 

	
 
var deleteComment = function(comment_id){
 
    var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__',comment_id);
 
    var postData = {'_method':'delete'};
 
    var success = function(o){
 
        var $deleted = $('#comment-tr-'+comment_id);
 
        var $prev = $deleted.prev('tr');
 
        while ($prev.hasClass('inline-comments')){
 
            $prev = $prev.prev('tr');
 
        }
 
        $deleted.remove();
 
        _placeAddButton($prev);
 
    }
 
    ajaxPOST(url,postData,success);
 
}
 

	
 
var _getLineNo = function(tr) {
 
    var line;
 
    var o = $(tr).children()[0].id.split('_');
 
    var n = $(tr).children()[1].id.split('_');
 

	
 
    if (n.length >= 2) {
 
        line = n[n.length-1];
 
    } else if (o.length >= 2) {
 
        line = o[o.length-1];
 
    }
 

	
 
    return line
 
};
 

	
 
var _placeAddButton = function($line_tr){
 
    var $tr = $line_tr;
 
    while ($tr.next().hasClass('inline-comments')){
 
        $tr.find('.add-comment').remove();
 
        $tr = $tr.next();
 
    }
 
    $tr.find('.add-comment').remove();
 
    var label = TRANSLATION_MAP['Add Another Comment'];
 
    var $html_el = $('<div class="add-comment"><span class="btn btn-mini">{0}</span></div>'.format(label));
 
    $html_el.click(function(e) {
 
        injectInlineForm($line_tr);
 
    });
 
    $tr.find('.comment').after($html_el);
 
};
 

	
 
/**
 
 * Places the inline comment into the changeset block in proper line position
 
 */
 
var _placeInline = function(target_id, lineno, html){
 
    var $td = $("#{0}_{1}".format(target_id, lineno));
 
    if (!$td.length){
 
        return false;
 
    }
 

	
 
    // check if there are comments already !
 
    var $line_tr = $td.parent(); // the tr
 
    var $after_tr = $line_tr;
 
    while ($after_tr.next().hasClass('inline-comments')){
 
        $after_tr = $after_tr.next();
 
    }
 
    // put in the comment at the bottom
 
    var $tr = _table_tr('inline-comments', html)
 
    $tr.find('div.comment').addClass('inline-comment');
 
    $after_tr.after($tr);
 

	
 
    // scan nodes, and attach add button to last one
 
    _placeAddButton($line_tr);
 
    return true;
 
}
 

	
 
/**
 
 * make a single inline comment and place it inside
 
 */
 
var _renderInlineComment = function(json_data){
 
    var html =  json_data['rendered_text'];
 
    var lineno = json_data['line_no'];
 
    var target_id = json_data['target_id'];
 
    return _placeInline(target_id, lineno, html);
 
}
 

	
 
/**
 
 * Iterates over all the inlines, and places them inside proper blocks of data
 
 */
 
var renderInlineComments = function(file_comments){
 
    for (var f in file_comments){
 
        // holding all comments for a FILE
 
        var box = file_comments[f];
 

	
 
        var target_id = $(box).attr('target_id');
 
        // actual comments with line numbers
 
        var comments = box.children;
 
        var obsolete_comments = [];
 
        for(var i=0; i<comments.length; i++){
 
            var data = {
 
                'rendered_text': comments[i].outerHTML,
 
                'line_no': $(comments[i]).attr('line'),
 
                'target_id': target_id
 
            }
 
            if (_renderInlineComment(data)) {
 
                obsolete_comments.push(comments[i]);
 
                $(comments[i]).hide();
 
            }else{
 
                var txt = document.createTextNode(
 
                        "Comment to " + YUD.getAttribute(comments[i].parentNode,'path') +
 
                        " line " + data.line_no +
 
                        " which is outside the diff context:");
 
                comments[i].insertBefore(txt, comments[i].firstChild);
 
            }
 
        }
 
        // now remove all the obsolete comments that have been copied to their
 
        // respective locations.
 
        for (var i=0; i < obsolete_comments.length; i++) {
 
            obsolete_comments[i].parentNode.removeChild(obsolete_comments[i]);
 
        }
 

	
 
        $(box).show();
 
    }
 
}
 

	
 
/**
 
 * Double link comments
 
 */
 
var linkInlineComments = function($firstlinks, $comments){
 
    if ($comments.length > 0) {
 
        $firstlinks.html('<a href="#{0}">First comment</a>'.format($comments.attr('id')));
 
    }
 
    if ($comments.length <= 1) {
 
        return;
 
    }
 

	
 
    $comments.each(function(i, e){
 
            var prev = '';
 
            if (i > 0){
 
                var prev_anchor = $($comments.get(i-1)).attr('id');
 
                prev = '<a href="#{0}">Previous comment</a>'.format(prev_anchor);
 
            }
 
            var next = '';
 
            if (i+1 < $comments.length){
 
                var next_anchor = $($comments.get(i+1)).attr('id');
 
                next = '<a href="#{0}">Next comment</a>'.format(next_anchor);
 
            }
 
            $(this).find('.comment-prev-next-links').html(
 
                '<div class="prev-comment">{0}</div>'.format(prev) +
 
                '<div class="next-comment">{0}</div>'.format(next));
 
        });
 
}
 

	
 
/* activate files.html stuff */
 
var fileBrowserListeners = function(current_url, node_list_url, url_base){
 
    var current_url_branch = "?branch=__BRANCH__";
 

	
 
    $('#stay_at_branch').on('click',function(e){
 
        if(e.currentTarget.checked){
 
            var uri = current_url_branch;
 
            uri = uri.replace('__BRANCH__',e.currentTarget.value);
 
            window.location = uri;
 
        }
 
        else{
 
            window.location = current_url;
 
        }
 
    })
 

	
 
    var $node_filter = $('#node_filter');
 

	
 
    var filterTimeout = null;
 
    var nodes = null;
 

	
 
    var initFilter = function(){
 
        $('#node_filter_box_loading').show();
 
        $('#search_activate_id').hide();
 
        $('#add_node_id').hide();
 
        $.ajax({url: node_list_url, headers: {'X-PARTIAL-XHR': '1'}, cache: false})
 
            .done(function(json) {
 
                    nodes = json.nodes;
 
                    $('#node_filter_box_loading').hide();
 
                    $('#node_filter_box').show();
 
                    $node_filter.focus();
 
                    if($node_filter.hasClass('init')){
 
                        $node_filter.val('');
 
                        $node_filter.removeClass('init');
 
                    }
 
                })
 
            .fail(function() {
 
                    console.log('fileBrowserListeners initFilter failed to load');
 
                })
 
        ;
 
    }
 

	
 
    var updateFilter = function(e) {
 
@@ -1100,658 +1100,628 @@ var readNotification = function(url, not
 
            _run_callbacks(callbacks);
 
        };
 
    var failure = function(o){
 
            alert("readNotification failure");
 
        };
 
    var postData = {'_method': 'put'};
 
    var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
 
    ajaxPOST(sUrl, postData, success, failure);
 
};
 

	
 
/** MEMBERS AUTOCOMPLETE WIDGET **/
 

	
 
var _MembersAutoComplete = function (divid, cont, users_list, groups_list) {
 
    var myUsers = users_list;
 
    var myGroups = groups_list;
 

	
 
    // Define a custom search function for the DataSource of users
 
    var matchUsers = function (sQuery) {
 
            // Case insensitive matching
 
            var query = sQuery.toLowerCase();
 
            var i = 0;
 
            var l = myUsers.length;
 
            var matches = [];
 

	
 
            // Match against each name of each contact
 
            for (; i < l; i++) {
 
                var contact = myUsers[i];
 
                if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
 
                     ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
 
                     ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
 
                    matches[matches.length] = contact;
 
                }
 
            }
 
            return matches;
 
        };
 

	
 
    // Define a custom search function for the DataSource of userGroups
 
    var matchGroups = function (sQuery) {
 
            // Case insensitive matching
 
            var query = sQuery.toLowerCase();
 
            var i = 0;
 
            var l = myGroups.length;
 
            var matches = [];
 

	
 
            // Match against each name of each contact
 
            for (; i < l; i++) {
 
                var matched_group = myGroups[i];
 
                if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
 
                    matches[matches.length] = matched_group;
 
                }
 
            }
 
            return matches;
 
        };
 

	
 
    //match all
 
    var matchAll = function (sQuery) {
 
            var u = matchUsers(sQuery);
 
            var g = matchGroups(sQuery);
 
            return u.concat(g);
 
        };
 

	
 
    // DataScheme for members
 
    var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
 
    memberDS.responseSchema = {
 
        fields: ["id", "fname", "lname", "nname", "grname", "grmembers", "gravatar_lnk", "gravatar_size"]
 
    };
 

	
 
    // DataScheme for owner
 
    var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
 
    ownerDS.responseSchema = {
 
        fields: ["id", "fname", "lname", "nname", "gravatar_lnk", "gravatar_size"]
 
    };
 

	
 
    // Instantiate AutoComplete for perms
 
    var membersAC = new YAHOO.widget.AutoComplete(divid, cont, memberDS);
 
    membersAC.useShadow = false;
 
    membersAC.resultTypeList = false;
 
    membersAC.animVert = false;
 
    membersAC.animHoriz = false;
 
    membersAC.animSpeed = 0.1;
 

	
 
    // Instantiate AutoComplete for owner
 
    var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
 
    ownerAC.useShadow = false;
 
    ownerAC.resultTypeList = false;
 
    ownerAC.animVert = false;
 
    ownerAC.animHoriz = false;
 
    ownerAC.animSpeed = 0.1;
 

	
 
    // Helper highlight function for the formatter
 
    var highlightMatch = function (full, snippet, matchindex) {
 
            return full.substring(0, matchindex)
 
            + "<span class='match'>"
 
            + full.substr(matchindex, snippet.length)
 
            + "</span>" + full.substring(matchindex + snippet.length);
 
        };
 

	
 
    // Custom formatter to highlight the matching letters
 
    var custom_formatter = function (oResultData, sQuery, sResultMatch) {
 
            var query = sQuery.toLowerCase();
 
            var _gravatar = function(res, em, size, group){
 
                var elem = '<img alt="gravatar" class="perm-gravatar-ac" style="width: {0}px; height: {0}px" src="{1}"/>'.format(size, em);
 
                if (!em) {
 
                    elem = '<i class="icon-user perm-gravatar-ac" style="font-size: {0}px;"></i>'.format(size);
 
                }
 
                if (group !== undefined){
 
                    elem = '<i class="perm-gravatar-ac icon-users"></i>'
 
                }
 
                var tmpl = '<div class="ac-container-wrap">{0}{1}</div>'
 
                return tmpl.format(elem,res)
 
            }
 
            // group
 
            if (oResultData.grname != undefined) {
 
                var grname = oResultData.grname;
 
                var grmembers = oResultData.grmembers;
 
                var grnameMatchIndex = grname.toLowerCase().indexOf(query);
 
                var grprefix = "{0}: ".format(_TM['Group']);
 
                var grsuffix = " (" + grmembers + "  )";
 
                var grsuffix = " ({0}  {1})".format(grmembers, _TM['members']);
 

	
 
                if (grnameMatchIndex > -1) {
 
                    return _gravatar(grprefix + highlightMatch(grname, query, grnameMatchIndex) + grsuffix,null,null,true);
 
                }
 
                return _gravatar(grprefix + oResultData.grname + grsuffix, null, null, true);
 
            // Users
 
            } else if (oResultData.nname != undefined) {
 
                var fname = oResultData.fname || "";
 
                var lname = oResultData.lname || "";
 
                var nname = oResultData.nname;
 

	
 
                // Guard against null value
 
                var fnameMatchIndex = fname.toLowerCase().indexOf(query),
 
                    lnameMatchIndex = lname.toLowerCase().indexOf(query),
 
                    nnameMatchIndex = nname.toLowerCase().indexOf(query),
 
                    displayfname, displaylname, displaynname;
 

	
 
                if (fnameMatchIndex > -1) {
 
                    displayfname = highlightMatch(fname, query, fnameMatchIndex);
 
                } else {
 
                    displayfname = fname;
 
                }
 

	
 
                if (lnameMatchIndex > -1) {
 
                    displaylname = highlightMatch(lname, query, lnameMatchIndex);
 
                } else {
 
                    displaylname = lname;
 
                }
 

	
 
                if (nnameMatchIndex > -1) {
 
                    displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
 
                } else {
 
                    displaynname = nname ? "(" + nname + ")" : "";
 
                }
 

	
 
                return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk, oResultData.gravatar_size);
 
            } else {
 
                return '';
 
            }
 
        };
 
    membersAC.formatResult = custom_formatter;
 
    ownerAC.formatResult = custom_formatter;
 

	
 
    var myHandler = function (sType, aArgs) {
 
            var nextId = divid.split('perm_new_member_name_')[1];
 
            var myAC = aArgs[0]; // reference back to the AC instance
 
            var elLI = aArgs[1]; // reference to the selected LI element
 
            var oData = aArgs[2]; // object literal of selected item's result data
 
            //fill the autocomplete with value
 
            if (oData.nname != undefined) {
 
                //users
 
                myAC.getInputEl().value = oData.nname;
 
                $('#perm_new_member_type_'+nextId).val('user');
 
            } else {
 
                //groups
 
                myAC.getInputEl().value = oData.grname;
 
                $('#perm_new_member_type_'+nextId).val('users_group');
 
            }
 
        };
 

	
 
    membersAC.itemSelectEvent.subscribe(myHandler);
 
    if(ownerAC.itemSelectEvent){
 
        ownerAC.itemSelectEvent.subscribe(myHandler);
 
    }
 

	
 
    return {
 
        memberDS: memberDS,
 
        ownerDS: ownerDS,
 
        membersAC: membersAC,
 
        ownerAC: ownerAC
 
    };
 
}
 

	
 
var MentionsAutoComplete = function (divid, cont, users_list, groups_list) {
 
var MentionsAutoComplete = function (divid, cont, users_list) {
 
    var myUsers = users_list;
 
    var myGroups = groups_list;
 

	
 
    // Define a custom search function for the DataSource of users
 
    var matchUsers = function (sQuery) {
 
            var org_sQuery = sQuery;
 
            if(this.mentionQuery == null){
 
                return []
 
            }
 
            sQuery = this.mentionQuery;
 
            // Case insensitive matching
 
            var query = sQuery.toLowerCase();
 
            var i = 0;
 
            var l = myUsers.length;
 
            var matches = [];
 

	
 
            // Match against each name of each contact
 
            for (; i < l; i++) {
 
                var contact = myUsers[i];
 
                if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
 
                     ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
 
                     ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
 
                    matches[matches.length] = contact;
 
                }
 
            }
 
            return matches
 
        };
 

	
 
    //match all
 
    var matchAll = function (sQuery) {
 
            return matchUsers(sQuery);
 
        };
 

	
 
    // DataScheme for owner
 
    var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
 

	
 
    ownerDS.responseSchema = {
 
        fields: ["id", "fname", "lname", "nname", "gravatar_lnk", "gravatar_size"]
 
    };
 

	
 
    // Instantiate AutoComplete for mentions
 
    var ownerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
 
    ownerAC.useShadow = false;
 
    ownerAC.resultTypeList = false;
 
    ownerAC.suppressInputUpdate = true;
 
    ownerAC.animVert = false;
 
    ownerAC.animHoriz = false;
 
    ownerAC.animSpeed = 0.1;
 

	
 
    // Helper highlight function for the formatter
 
    var highlightMatch = function (full, snippet, matchindex) {
 
            return full.substring(0, matchindex)
 
                + "<span class='match'>"
 
                + full.substr(matchindex, snippet.length)
 
                + "</span>" + full.substring(matchindex + snippet.length);
 
        };
 

	
 
    // Custom formatter to highlight the matching letters
 
    ownerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
 
            var org_sQuery = sQuery;
 
            if(this.dataSource.mentionQuery != null){
 
                sQuery = this.dataSource.mentionQuery;
 
            }
 

	
 
            var query = sQuery.toLowerCase();
 
            var _gravatar = function(res, em, size, group){
 
                var elem = '<img alt="gravatar" class="perm-gravatar-ac" style="width: {0}px; height: {0}px" src="{1}"/>'.format(size, em);
 
                if (!em) {
 
                    elem = '<i class="icon-user perm-gravatar-ac" style="font-size: {0}px;"></i>'.format(size);
 
                }
 
                if (group !== undefined){
 
                    elem = '<i class="perm-gravatar-ac icon-users"></i>'
 
                }
 
                var tmpl = '<div class="ac-container-wrap">{0}{1}</div>'
 
                return tmpl.format(elem,res)
 
            }
 
            if (oResultData.nname != undefined) {
 
                var fname = oResultData.fname || "";
 
                var lname = oResultData.lname || "";
 
                var nname = oResultData.nname;
 

	
 
                // Guard against null value
 
                var fnameMatchIndex = fname.toLowerCase().indexOf(query),
 
                    lnameMatchIndex = lname.toLowerCase().indexOf(query),
 
                    nnameMatchIndex = nname.toLowerCase().indexOf(query),
 
                    displayfname, displaylname, displaynname;
 

	
 
                if (fnameMatchIndex > -1) {
 
                    displayfname = highlightMatch(fname, query, fnameMatchIndex);
 
                } else {
 
                    displayfname = fname;
 
                }
 

	
 
                if (lnameMatchIndex > -1) {
 
                    displaylname = highlightMatch(lname, query, lnameMatchIndex);
 
                } else {
 
                    displaylname = lname;
 
                }
 

	
 
                if (nnameMatchIndex > -1) {
 
                    displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
 
                } else {
 
                    displaynname = nname ? "(" + nname + ")" : "";
 
                }
 

	
 
                return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk, oResultData.gravatar_size);
 
            } else {
 
                return '';
 
            }
 
        };
 

	
 
    if(ownerAC.itemSelectEvent){
 
        ownerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
 
            var myAC = aArgs[0]; // reference back to the AC instance
 
            var elLI = aArgs[1]; // reference to the selected LI element
 
            var oData = aArgs[2]; // object literal of selected item's result data
 
            //fill the autocomplete with value
 
            if (oData.nname != undefined) {
 
                //users
 
                //Replace the mention name with replaced
 
                var re = new RegExp();
 
                var org = myAC.getInputEl().value;
 
                var chunks = myAC.dataSource.chunks
 
                // replace middle chunk(the search term) with actuall  match
 
                chunks[1] = chunks[1].replace('@'+myAC.dataSource.mentionQuery,
 
                                              '@'+oData.nname+' ');
 
                myAC.getInputEl().value = chunks.join('')
 
                myAC.getInputEl().focus(); // Y U NO WORK !?
 
            } else {
 
                //groups
 
                myAC.getInputEl().value = oData.grname;
 
                $('#perm_new_member_type').val('users_group');
 
            }
 
        });
 
    }
 

	
 
    // in this keybuffer we will gather current value of search !
 
    // since we need to get this just when someone does `@` then we do the
 
    // search
 
    ownerAC.dataSource.chunks = [];
 
    ownerAC.dataSource.mentionQuery = null;
 

	
 
    ownerAC.get_mention = function(msg, max_pos) {
 
        var org = msg;
 
        // Must match utils2.py MENTIONS_REGEX.
 
        // Only matching on string up to cursor, so it must end with $
 
        var re = new RegExp('(?:^|[^a-zA-Z0-9])@([a-zA-Z0-9][-_.a-zA-Z0-9]*[a-zA-Z0-9])$')
 
        var chunks  = [];
 

	
 
        // cut first chunk until current pos
 
        var to_max = msg.substr(0, max_pos);
 
        var at_pos = Math.max(0,to_max.lastIndexOf('@')-1);
 
        var msg2 = to_max.substr(at_pos);
 

	
 
        chunks.push(org.substr(0,at_pos))// prefix chunk
 
        chunks.push(msg2)                // search chunk
 
        chunks.push(org.substr(max_pos)) // postfix chunk
 

	
 
        // clean up msg2 for filtering and regex match
 
        var msg2 = msg2.lstrip(' ').lstrip('\n');
 

	
 
        if(re.test(msg2)){
 
            var unam = re.exec(msg2)[1];
 
            return [unam, chunks];
 
        }
 
        return [null, null];
 
    };
 

	
 
    var $divid = $('#'+divid);
 
    $divid.keyup(function(e){
 
            var currentMessage = $divid.val();
 
            var currentCaretPosition = $divid[0].selectionStart;
 

	
 
            var unam = ownerAC.get_mention(currentMessage, currentCaretPosition);
 
            var curr_search = null;
 
            if(unam[0]){
 
                curr_search = unam[0];
 
            }
 

	
 
            ownerAC.dataSource.chunks = unam[1];
 
            ownerAC.dataSource.mentionQuery = curr_search;
 
        });
 
}
 

	
 
var addReviewMember = function(id,fname,lname,nname,gravatar_link,gravatar_size){
 
    var displayname = "{0} {1}".format(fname, lname);
 
    var gravatarelm = '<img alt="gravatar" style="width: {0}px; height: {0}px" src="{1}"/>'.format(gravatar_size, gravatar_link);
 
    if (!gravatar_link)
 
        gravatarelm = '<i class="icon-user" style="font-size: {0}px;"></i>'.format(gravatar_size);
 
    // WARNING: the HTML below is duplicate with
 
    // kallithea/templates/pullrequests/pullrequest_show.html
 
    // If you change something here it should be reflected in the template too.
 
    var element = (
 
        '     <li id="reviewer_{2}">\n'+
 
        '       <div class="reviewers_member">\n'+
 
        '           <div class="reviewer_status tooltip" title="not_reviewed">\n'+
 
        '             <i class="icon-circle changeset-status-not_reviewed"></i>\n'+
 
        '           </div>\n'+
 
        '         <div class="reviewer_gravatar gravatar">{0}</div>\n'+
 
        '         <div style="float:left;">{1}</div>\n'+
 
        '         <input type="hidden" value="{2}" name="review_members" />\n'+
 
        '         <div class="reviewer_member_remove action_button" onclick="removeReviewMember({2})">\n'+
 
        '             <i class="icon-minus-circled"></i>\n'+
 
        '         </div> (add not saved)\n'+
 
        '       </div>\n'+
 
        '     </li>\n'
 
        ).format(gravatarelm, displayname, id);
 
    // check if we don't have this ID already in
 
    var ids = [];
 
    $('#review_members').find('li').each(function() {
 
            ids.push(this.id);
 
        });
 
    if(ids.indexOf('reviewer_'+id) == -1){
 
        //only add if it's not there
 
        $('#review_members').append(element);
 
    }
 
}
 

	
 
var removeReviewMember = function(reviewer_id, repo_name, pull_request_id){
 
    var $li = $('#reviewer_{0}'.format(reviewer_id));
 
    $li.find('div div').css("text-decoration", "line-through");
 
    $li.find('input').attr('name', 'review_members_removed');
 
    $li.find('.reviewer_member_remove').replaceWith('&nbsp;(remove not saved)');
 
}
 

	
 
/* activate auto completion of users and groups ... but only used for users as PR reviewers */
 
var PullRequestAutoComplete = function (divid, cont, users_list, groups_list) {
 
/* activate auto completion of users as PR reviewers */
 
var PullRequestAutoComplete = function (divid, cont, users_list) {
 
    var myUsers = users_list;
 
    var myGroups = groups_list;
 

	
 
    // Define a custom search function for the DataSource of users
 
    var matchUsers = function (sQuery) {
 
            // Case insensitive matching
 
            var query = sQuery.toLowerCase();
 
            var i = 0;
 
            var l = myUsers.length;
 
            var matches = [];
 

	
 
            // Match against each name of each contact
 
            for (; i < l; i++) {
 
                var contact = myUsers[i];
 
                if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
 
                     ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
 
                     ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
 
                    matches[matches.length] = contact;
 
                }
 
            }
 
            return matches;
 
        };
 

	
 
    // Define a custom search function for the DataSource of userGroups
 
    var matchGroups = function (sQuery) {
 
            // Case insensitive matching
 
            var query = sQuery.toLowerCase();
 
            var i = 0;
 
            var l = myGroups.length;
 
            var matches = [];
 

	
 
            // Match against each name of each contact
 
            for (; i < l; i++) {
 
                matched_group = myGroups[i];
 
                if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
 
                    matches[matches.length] = matched_group;
 
                }
 
            }
 
            return matches;
 
        };
 

	
 
    //match all
 
    var matchAll = function (sQuery) {
 
            return matchUsers(sQuery);
 
        };
 

	
 
    // DataScheme for owner
 
    var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
 

	
 
    ownerDS.responseSchema = {
 
        fields: ["id", "fname", "lname", "nname", "gravatar_lnk", "gravatar_size"]
 
    };
 

	
 
    // Instantiate AutoComplete for mentions
 
    var reviewerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
 
    reviewerAC.useShadow = false;
 
    reviewerAC.resultTypeList = false;
 
    reviewerAC.suppressInputUpdate = true;
 
    reviewerAC.animVert = false;
 
    reviewerAC.animHoriz = false;
 
    reviewerAC.animSpeed = 0.1;
 

	
 
    // Helper highlight function for the formatter
 
    var highlightMatch = function (full, snippet, matchindex) {
 
            return full.substring(0, matchindex)
 
                + "<span class='match'>"
 
                + full.substr(matchindex, snippet.length)
 
                + "</span>" + full.substring(matchindex + snippet.length);
 
        };
 

	
 
    // Custom formatter to highlight the matching letters
 
    reviewerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
 
            var org_sQuery = sQuery;
 
            if(this.dataSource.mentionQuery != null){
 
                sQuery = this.dataSource.mentionQuery;
 
            }
 

	
 
            var query = sQuery.toLowerCase();
 
            var _gravatar = function(res, em, size, group){
 
                var elem = '<img alt="gravatar" class="perm-gravatar-ac" style="width: {0}px; height: {0}px" src="{1}"/>'.format(size, em);
 
                if (!em) {
 
                    elem = '<i class="icon-user perm-gravatar-ac" style="font-size: {0}px;"></i>'.format(size);
 
                }
 
                if (group !== undefined){
 
                    elem = '<i class="perm-gravatar-ac icon-users"></i>'
 
                }
 
                var tmpl = '<div class="ac-container-wrap">{0}{1}</div>'
 
                return tmpl.format(elem,res)
 
            }
 
            if (oResultData.nname != undefined) {
 
                var fname = oResultData.fname || "";
 
                var lname = oResultData.lname || "";
 
                var nname = oResultData.nname;
 

	
 
                // Guard against null value
 
                var fnameMatchIndex = fname.toLowerCase().indexOf(query),
 
                    lnameMatchIndex = lname.toLowerCase().indexOf(query),
 
                    nnameMatchIndex = nname.toLowerCase().indexOf(query),
 
                    displayfname, displaylname, displaynname;
 

	
 
                if (fnameMatchIndex > -1) {
 
                    displayfname = highlightMatch(fname, query, fnameMatchIndex);
 
                } else {
 
                    displayfname = fname;
 
                }
 

	
 
                if (lnameMatchIndex > -1) {
 
                    displaylname = highlightMatch(lname, query, lnameMatchIndex);
 
                } else {
 
                    displaylname = lname;
 
                }
 

	
 
                if (nnameMatchIndex > -1) {
 
                    displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
 
                } else {
 
                    displaynname = nname ? "(" + nname + ")" : "";
 
                }
 

	
 
                return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk, oResultData.gravatar_size);
 
            } else {
 
                return '';
 
            }
 
        };
 

	
 
    //members cache to catch duplicates
 
    reviewerAC.dataSource.cache = [];
 
    // hack into select event
 
    if(reviewerAC.itemSelectEvent){
 
        reviewerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
 

	
 
            var myAC = aArgs[0]; // reference back to the AC instance
 
            var elLI = aArgs[1]; // reference to the selected LI element
 
            var oData = aArgs[2]; // object literal of selected item's result data
 

	
 
            //fill the autocomplete with value
 
            if (oData.nname != undefined) {
 
                addReviewMember(oData.id, oData.fname, oData.lname, oData.nname,
 
                                oData.gravatar_lnk, oData.gravatar_size);
 
                myAC.dataSource.cache.push(oData.id);
 
                $('#user').val('');
 
            }
 
        });
 
    }
 
}
 

	
 
/**
 
 * Activate .quick_repo_menu
 
 */
 
var quick_repo_menu = function(){
 
    $(".quick_repo_menu").mouseenter(function(e) {
 
            var $menu = $(e.currentTarget).children().first().children().first();
 
            if($menu.hasClass('hidden')){
 
                $menu.removeClass('hidden').addClass('active');
 
                $(e.currentTarget).removeClass('hidden').addClass('active');
 
            }
 
        })
 
    $(".quick_repo_menu").mouseleave(function(e) {
 
            var $menu = $(e.currentTarget).children().first().children().first();
 
            if($menu.hasClass('active')){
 
                $menu.removeClass('active').addClass('hidden');
 
                $(e.currentTarget).removeClass('active').addClass('hidden');
 
            }
 
        })
 
};
 

	
 

	
 
/**
 
 * TABLE SORTING
 
 */
 

	
 
var revisionSort = function(a, b, desc, field) {
 
    var a_ = parseInt(a.getData('last_rev_raw') || 0);
 
    var b_ = parseInt(b.getData('last_rev_raw') || 0);
 

	
 
    return YAHOO.util.Sort.compare(a_, b_, desc);
 
};
 

	
 
var ageSort = function(a, b, desc, field) {
 
    // data is like: <span class="tooltip" date="2014-06-04 18:18:55.325474" title="Wed, 04 Jun 2014 18:18:55">1 day and 23 hours ago</span>
 
    var a_ = $(a.getData(field)).attr('date');
 
    var b_ = $(b.getData(field)).attr('date');
 

	
 
    return YAHOO.util.Sort.compare(a_, b_, desc);
 
};
 

	
 
var lastLoginSort = function(a, b, desc, field) {
 
    var a_ = parseFloat(a.getData('last_login_raw') || 0);
 
    var b_ = parseFloat(b.getData('last_login_raw') || 0);
 

	
 
    return YAHOO.util.Sort.compare(a_, b_, desc);
 
};
 

	
 
var nameSort = function(a, b, desc, field) {
 
    var a_ = a.getData('raw_name') || 0;
 
    var b_ = b.getData('raw_name') || 0;
 

	
 
    return YAHOO.util.Sort.compare(a_, b_, desc);
 
};
 

	
 
var dateSort = function(a, b, desc, field) {
 
    var a_ = parseFloat(a.getData('raw_date') || 0);
 
    var b_ = parseFloat(b.getData('raw_date') || 0);
 

	
 
    return YAHOO.util.Sort.compare(a_, b_, desc);
 
};
 

	
 
var addPermAction = function(_html, users_list, groups_list){
 
    var $last_node = $('.last_new_member').last(); // empty tr between last and add
 
    var next_id = $('.new_members').length;
 
    $last_node.before($('<tr class="new_members">').append(_html.format(next_id)));
 
    _MembersAutoComplete("perm_new_member_name_"+next_id,
 
            "perm_container_"+next_id, users_list, groups_list);
 
}
 

	
 
function ajaxActionRevokePermission(url, obj_id, obj_type, field_id, extra_data) {
 
    var success = function (o) {
 
            $('#' + field_id).remove();
 
        };
 
    var failure = function (o) {
 
            alert(_TM['Failed to revoke permission'] + ": " + o.status);
 
        };
 
    var query_params = {
 
        '_method': 'delete'
 
    }
 
    // put extra data into POST
 
    if (extra_data !== undefined && (typeof extra_data === 'object')){
 
        for(var k in extra_data){
 
            query_params[k] = extra_data[k];
 
        }
 
    }
 

	
 
    if (obj_type=='user'){
 
        query_params['user_id'] = obj_id;
 
        query_params['obj_type'] = 'user';
 
    }
 
    else if (obj_type=='user_group'){
 
        query_params['user_group_id'] = obj_id;
 
        query_params['obj_type'] = 'user_group';
kallithea/templates/pullrequests/pullrequest.html
Show inline comments
 
<%inherit file="/base/base.html"/>
 

	
 
<%block name="title">
 
    ${c.repo_name} ${_('New Pull Request')}
 
</%block>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${_('New Pull Request')}
 
</%def>
 

	
 
<%block name="header_menu">
 
    ${self.menu('repositories')}
 
</%block>
 

	
 
<%def name="main()">
 
${self.repo_context_bar('showpullrequest')}
 
<div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
    </div>
 

	
 
    ${h.form(url('pullrequest', repo_name=c.repo_name), method='post', id='pull_request_form')}
 
    <div class="form">
 
        <!-- fields -->
 

	
 
        <div class="fields" style="float:left;width:50%;padding-right:30px;">
 

	
 
             <div class="field">
 
                <div class="label">
 
                    <label for="pullrequest_title">${_('Title')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.text('pullrequest_title',class_="large",placeholder=_('Summarize the changes - or leave empty'))}
 
                </div>
 
             </div>
 

	
 
            <div class="field">
 
                <div class="label label-textarea">
 
                    <label for="pullrequest_desc">${_('Description')}:</label>
 
                </div>
 
                <div class="textarea text-area editor">
 
                    ${h.textarea('pullrequest_desc',size=30,placeholder=_('Write a short description on this pull request'))}
 
                </div>
 
            </div>
 

	
 
            <div class="field">
 
                <div class="label label-textarea">
 
                    <label for="pullrequest_desc">${_('Changeset flow')}:</label>
 
                </div>
 
                <div class="input">
 
                    ##ORG
 
                    <div>
 
                        <div>
 
                            <div style="padding:5px 3px 3px 3px;">
 
                            <b>${_('Origin repository')}:</b> <span id="org_repo_desc">${c.db_repo.description.split('\n')[0]}</span>
 
                            </div>
 
                            <div>
 
                            ${h.select('org_repo','',c.cs_repos,class_='refs')}:${h.select('org_ref',c.default_cs_ref,c.cs_refs,class_='refs')}
 
                            </div>
 
                            <div style="padding:5px 3px 3px 3px;">
 
                            <b>${_('Revision')}:</b> <span id="org_rev_span">-</span>
 
                            </div>
 
                        </div>
 
                    </div>
 

	
 
                    ##OTHER, most Probably the PARENT OF THIS FORK
 
                    <div style="border-top: 1px solid #EEE; margin: 5px 0px 0px 0px">
 
                        <div>
 
                            ## filled with JS
 
                            <div style="padding:5px 3px 3px 3px;">
 
                            <b>${_('Destination repository')}:</b> <span id="other_repo_desc">${c.a_repo.description.split('\n')[0]}</span>
 
                            </div>
 
                            <div>
 
                            ${h.select('other_repo',c.a_repo.repo_name,c.a_repos,class_='refs')}:${h.select('other_ref',c.default_a_ref,c.a_refs,class_='refs')}
 
                            </div>
 
                            <div style="padding:5px 3px 3px 3px;">
 
                            <b>${_('Revision')}:</b> <span id="other_rev_span">-</span>
 
                            </div>
 
                        </div>
 
                    </div>
 
                    <div style="clear:both"></div>
 
                </div>
 
            </div>
 

	
 
            <div class="field">
 
                <div class="buttons">
 
                    ${h.submit('save',_('Create Pull Request'),class_="btn")}
 
                    ${h.reset('reset',_('Reset'),class_="btn")}
 
               </div>
 
            </div>
 

	
 
        </div>
 

	
 
        ## Reviewers
 
        <div style="float:left; border-left:1px dashed #eee">
 
            <div class="pr-details-title">${_('Pull Request Reviewers')}</div>
 
            <div id="reviewers" style="padding:0px 0px 0px 15px">
 
              ## members goes here !
 
              <div>
 
                <ul id="review_members" class="group_members">
 
                </ul>
 
              </div>
 

	
 
              <div class='ac'>
 
                <div class="reviewer_ac">
 
                   ${h.text('user', class_='yui-ac-input',placeholder=_('Type name of reviewer to add'))}
 
                   <div id="reviewers_container"></div>
 
                </div>
 
              </div>
 
            </div>
 
        </div>
 

	
 
        <div style="clear:both;padding: 0 0 30px 0;"></div>
 

	
 
        <h4>${_('Changesets')}</h4>
 
        <div style="float:left;padding:0px 30px 30px 30px">
 
           ## overview pulled by ajax
 
           <div style="float:left" id="pull_request_overview"></div>
 
        </div>
 
        <div style="clear:both;"></div>
 

	
 
    </div>
 

	
 
    ${h.end_form()}
 

	
 
</div>
 

	
 
<script type="text/javascript" src="${h.url('/js/graph.js', ver=c.kallithea_version)}"></script>
 
<script type="text/javascript">
 
  var _USERS_AC_DATA = ${c.users_array|n};
 
  var _GROUPS_AC_DATA = ${c.user_groups_array|n};
 
  PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
 
  PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA);
 

	
 
  pyroutes.register('pullrequest_repo_info', "${url('pullrequest_repo_info',repo_name='%(repo_name)s')}", ['repo_name']);
 

	
 
  var pendingajax = undefined;
 
  var otherrepoChanged = function(){
 
      var $other_ref = $('#other_ref');
 
      $other_ref.prop('disabled', true);
 
      var repo_name = $('#other_repo').val();
 
      if (pendingajax) {
 
          pendingajax.abort();
 
          pendingajax = undefined;
 
      }
 
      pendingajax = ajaxGET(pyroutes.url('pullrequest_repo_info', {"repo_name": repo_name}),
 
          function(data){
 
              pendingajax = undefined;
 
              $('#other_repo_desc').html(data.description);
 

	
 
              // replace options of other_ref with the ones for the current other_repo
 
              $other_ref.empty();
 
              for(var i = 0; i < data.refs.length; i++)
 
              {
 
                var $optgroup = $('<optgroup/>').attr('label', data.refs[i][1]);
 
                var options = data.refs[i][0];
 
                var length = options.length;
 
                for(var j = 0; j < length; j++)
 
                {
 
                  $optgroup.append($('<option/>').text(options[j][1]).val(options[j][0]));
 
                }
 
                $other_ref.append($optgroup);
 
              }
 
              $other_ref.val(data.selected_ref);
 

	
 
              // re-populate the select2 thingie
 
              $("#other_ref").select2({
 
                  dropdownAutoWidth: true
 
              });
 

	
 
              $other_ref.prop('disabled', false);
 
              loadPreview();
 
          });
 
  };
 

	
 
  var loadPreview = function(){
 
      //url template
 
      var url = "${h.url('compare_url',
 
                         repo_name='__other_repo__',
 
                         org_ref_type='rev',
 
                         org_ref_name='__other_ref_name__',
 
                         other_repo='__org_repo__',
 
                         other_ref_type='rev',
 
                         other_ref_name='__org_ref_name__',
 
                         as_form=True,
 
                         merge=True,
 
                         )}";
 
      var org_repo = $('#pull_request_form #org_repo').val();
 
      var org_ref = $('#pull_request_form #org_ref').val().split(':');
 
      ## TODO: make nice link like link_to_ref() do
 
      $('#org_rev_span').html(org_ref[2].substr(0,12));
 

	
 
      var other_repo = $('#pull_request_form #other_repo').val();
 
      var other_ref = $('#pull_request_form #other_ref').val().split(':');
 
      $('#other_rev_span').html(other_ref[2].substr(0,12));
 

	
 
      var rev_data = {
 
          '__org_repo__': org_repo,
 
          '__org_ref_name__': org_ref[2],
 
          '__other_repo__': other_repo,
 
          '__other_ref_name__': other_ref[2]
 
      }; // gather the org/other ref and repo here
 

	
 
      for (k in rev_data){
 
          url = url.replace(k,rev_data[k]);
 
      }
 

	
 
      if (pendingajax) {
 
          pendingajax.abort();
 
          pendingajax = undefined;
 
      }
 
      pendingajax = asynchtml(url, $('#pull_request_overview'), function(o){
 
          pendingajax = undefined;
 
          var jsdata = eval('('+YUD.get('jsdata').innerHTML+')'); // TODO: just get json
 
          var r = new BranchRenderer('graph_canvas', 'graph_content_pr', 'chg_');
 
          r.render(jsdata,100);
 
      });
 
  }
 

	
 
  $(document).ready(function(){
 
      $("#org_repo").select2({
 
          dropdownAutoWidth: true
 
      });
 
      ## (org_repo can't change)
 

	
 
      $("#org_ref").select2({
 
          dropdownAutoWidth: true,
 
          sortResults: branchSort
 
      });
 
      $("#org_ref").on("change", function(e){
 
          loadPreview();
 
      });
 

	
 
      $("#other_repo").select2({
 
          dropdownAutoWidth: true
 
      });
 
      $("#other_repo").on("change", function(e){
 
          otherrepoChanged();
 
      });
 

	
 
      $("#other_ref").select2({
 
          dropdownAutoWidth: true,
 
          sortResults: branchSort
 
      });
 
      $("#other_ref").on("change", function(e){
 
          loadPreview();
 
      });
 

	
 
      //lazy load overview after 0.5s
 
      setTimeout(loadPreview, 500);
 
  });
 

	
 
</script>
 

	
 
</%def>
kallithea/templates/pullrequests/pullrequest_show.html
Show inline comments
 
@@ -180,238 +180,238 @@ ${self.repo_context_bar('showpullrequest
 
                    <tr id="chg_available_${cnt+1}">
 
                      %if cs.revision == c.cs_ranges[-1].revision:
 
                        <td>
 
                          %if editable:
 
                            ${h.radio(name='updaterev', value='')}
 
                          %endif
 
                        </td>
 
                        <td colspan="2">${_("Current revision - no change")}</td>
 
                      %else:
 
                        <td>
 
                          %if editable and cs.revision in c.avail_revs:
 
                            ${h.radio(name='updaterev', value=cs.raw_id)}
 
                          %endif
 
                        </td>
 
                        <td>${h.link_to(h.show_id(cs),h.url('changeset_home',repo_name=c.cs_repo.repo_name,revision=cs.raw_id))}</td>
 
                        <td><div class="message" style="white-space:normal; height:1.1em; max-width: 500px; padding:0">${h.urlify_commit(cs.message, c.repo_name)}</div></td>
 
                      %endif
 
                    </tr>
 
                  %endfor
 
                </table>
 
              </div>
 
              %endif
 
              <div class="msg-div">${c.update_msg_other}</div>
 
            </div>
 
        </div>
 
      </div>
 
    </div>
 
    ## REVIEWERS
 
    <div style="float:left; border-left:1px dashed #eee">
 
        <div class="pr-details-title">${_('Pull Request Reviewers')}</div>
 
        <div id="reviewers" style="padding:0px 0px 5px 10px">
 
          ## members goes here !
 
          <div>
 
            <ul id="review_members" class="group_members">
 
            %for member,status in c.pull_request_reviewers:
 
              ## WARNING: the HTML below is duplicate with
 
              ## kallithea/public/js/base.js
 
              ## If you change something here it should be reflected in the template too.
 
              <li id="reviewer_${member.user_id}">
 
                <div class="reviewers_member">
 
                    <div class="reviewer_status tooltip" title="${h.tooltip(h.changeset_status_lbl(status.status if status else 'not_reviewed'))}">
 
                      <i class="icon-circle changeset-status-${status.status if status else 'not_reviewed'}"></i>
 
                    </div>
 
                  <div class="reviewer_gravatar gravatar">
 
                    ${h.gravatar(member.email, size=14)}
 
                  </div>
 
                  <div style="float:left;">${member.full_name} (${_('Owner') if c.pull_request.user_id == member.user_id else _('Reviewer')})</div>
 
                  <input type="hidden" value="${member.user_id}" name="review_members" />
 
                  %if editable:
 
                  <div class="reviewer_member_remove action_button" onclick="removeReviewMember(${member.user_id})" title="${_('Remove reviewer')}">
 
                      <i class="icon-minus-circled"></i>
 
                  </div>
 
                  %endif
 
                </div>
 
              </li>
 
            %endfor
 
            </ul>
 
          </div>
 
          %if editable:
 
          <div class='ac'>
 
            <div class="reviewer_ac">
 
               ${h.text('user', class_='yui-ac-input',placeholder=_('Type name of reviewer to add'))}
 
               <div id="reviewers_container"></div>
 
            </div>
 
          </div>
 
          %endif
 
        </div>
 

	
 
        %if not c.pull_request_reviewers:
 
        <div class="pr-details-title">${_('Potential Reviewers')}</div>
 
        <div style="margin: 10px 0 10px 10px; max-width: 250px">
 
          <div>
 
            ${_('Click to add the repository owner as reviewer:')}
 
          </div>
 
          <ul style="margin-top: 10px">
 
            %for u in [c.pull_request.other_repo.user]:
 
              <li>
 
                <a class="missing_reviewer missing_reviewer_${u.user_id}"
 
                  user_id="${u.user_id}"
 
                  fname="${u.name}"
 
                  lname="${u.lastname}"
 
                  nname="${u.username}"
 
                  gravatar_lnk="${h.gravatar_url(u.email, size=28)}"
 
                  gravatar_size="14"
 
                  title="Click to add reviewer to the list, then Save Changes.">${u.full_name}</a>
 
              </li>
 
            %endfor
 
          </ul>
 
        </div>
 
        %endif
 
    </div>
 
    <div class="form" style="clear:both">
 
      <div class="fields">
 
        %if editable:
 
          <div class="buttons">
 
            ${h.submit('pr-form-save',_('Save Changes'),class_="btn btn-small")}
 
            ${h.submit('pr-form-clone',_('Save as New Pull Request'),class_="btn btn-small",disabled='disabled')}
 
            ${h.reset('pr-form-reset',_('Cancel Changes'),class_="btn btn-small")}
 
          </div>
 
        %endif
 
      </div>
 
    </div>
 
  ${h.end_form()}
 
</div>
 

	
 
<div class="box">
 
    <div class="title">
 
      <div class="breadcrumbs">${_('Pull Request Content')}</div>
 
    </div>
 
    <div class="table">
 
          <div id="changeset_compare_view_content">
 
              <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
 
                  ${comment.comment_count(c.inline_cnt, len(c.comments))}
 
              </div>
 
              ##CS
 
              <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
 
                ${ungettext('Showing %s commit','Showing %s commits', len(c.cs_ranges)) % len(c.cs_ranges)}
 
              </div>
 
              <%include file="/compare/compare_cs.html" />
 

	
 
              <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
 
              ${_('Common ancestor')}:
 
              ${h.link_to(h.short_id(c.a_rev),h.url('changeset_home',repo_name=c.a_repo.repo_name,revision=c.a_rev))}
 
              </div>
 

	
 
              ## FILES
 
              <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
 

	
 
              % if c.limited_diff:
 
                  ${ungettext('%s file changed', '%s files changed', len(c.files)) % len(c.files)}
 
              % else:
 
                  ${ungettext('%s file changed with %s insertions and %s deletions','%s files changed with %s insertions and %s deletions', len(c.files)) % (len(c.files),c.lines_added,c.lines_deleted)}:
 
              %endif
 

	
 
              </div>
 
              <div class="cs_files">
 
                %if not c.files:
 
                   <span class="empty_data">${_('No files')}</span>
 
                %endif
 
                %for fid, change, f, stat in c.files:
 
                    <div class="cs_${change}">
 
                      <div class="node">
 
                          <i class="icon-diff-${change}"></i>
 
                          ${h.link_to(h.safe_unicode(f),'#' + fid)}
 
                      </div>
 
                      <div class="changes">${h.fancy_file_stats(stat)}</div>
 
                    </div>
 
                %endfor
 
              </div>
 
              % if c.limited_diff:
 
                <h5>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff anyway')}</a></h5>
 
              % endif
 
          </div>
 
    </div>
 
    <script>
 
    var _USERS_AC_DATA = ${c.users_array|n};
 
    var _GROUPS_AC_DATA = ${c.user_groups_array|n};
 
    // TODO: switch this to pyroutes
 
    AJAX_COMMENT_URL = "${url('pullrequest_comment',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id)}";
 
    AJAX_COMMENT_DELETE_URL = "${url('pullrequest_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
 

	
 
    pyroutes.register('pullrequest_comment', "${url('pullrequest_comment',repo_name='%(repo_name)s',pull_request_id='%(pull_request_id)s')}", ['repo_name', 'pull_request_id']);
 
    pyroutes.register('pullrequest_comment_delete', "${url('pullrequest_comment_delete',repo_name='%(repo_name)s',comment_id='%(comment_id)s')}", ['repo_name', 'comment_id']);
 

	
 
    </script>
 

	
 
    ## diff block
 
    <div class="commentable-diff">
 
    <%namespace name="diff_block" file="/changeset/diff_block.html"/>
 
    ${diff_block.diff_block_js()}
 
    %for fid, change, f, stat in c.files:
 
      ${diff_block.diff_block_simple([c.changes[fid]])}
 
    %endfor
 
    % if c.limited_diff:
 
      <h4>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff anyway')}</a></h4>
 
    % endif
 
    </div>
 

	
 
    ## template for inline comment form
 
    ${comment.comment_inline_form()}
 

	
 
    ## render comments and inlines
 
    ${comment.generate_comments()}
 

	
 
    ## main comment form and it status
 
    ${comment.comments(h.url('pullrequest_comment', repo_name=c.repo_name,
 
                              pull_request_id=c.pull_request.pull_request_id),
 
                       c.current_voting_result,
 
                       is_pr=True, change_status=c.allowed_to_change_status)}
 

	
 
    <script type="text/javascript">
 
      $(document).ready(function(){
 
          PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
 
          PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA);
 

	
 
          $('.add-bubble').click(function(e){
 
              var tr = e.currentTarget;
 
              injectInlineForm(tr.parentNode.parentNode);
 
          });
 

	
 
          var avail_jsdata = ${c.avail_jsdata|n};
 
          var avail_r = new BranchRenderer('avail_graph_canvas', 'updaterevs-table', 'chg_available_');
 
          avail_r.render(avail_jsdata,40);
 

	
 
          // inject comments into they proper positions
 
          var file_comments = $('.inline-comment-placeholder').toArray();
 
          renderInlineComments(file_comments);
 

	
 
          linkInlineComments($('.firstlink'), $('.comment'));
 

	
 
          $('#updaterevs input').change(function(e){
 
              var update = !!e.target.value;
 
              $('#pr-form-save').prop('disabled',update);
 
              $('#pr-form-clone').prop('disabled',!update);
 
          });
 
          var $org_review_members = $('#review_members').clone();
 
          $('#pr-form-reset').click(function(e){
 
              $('#pr-edit-form').hide();
 
              $('.pr-not-edit').show();
 
              $('#pr-form-save').prop('disabled',false);
 
              $('#pr-form-clone').prop('disabled',true);
 
              $('#review_members').html($org_review_members);
 
          });
 

	
 
          // hack: re-navigate to target after JS is done ... if a target is set and setting href thus won't reload
 
          if (window.location.hash != "") {
 
              window.location.href = window.location.href;
 
          }
 

	
 
          $('.missing_reviewer').click(function(){
 
            var $this = $(this);
 
            addReviewMember($this.attr('user_id'), $this.attr('fname'), $this.attr('lname'), $this.attr('nname'), $this.attr('gravatar_lnk'), $this.attr('gravatar_size'));
 
          });
 
      });
 
    </script>
 

	
 
</div>
 

	
 
</%def>
0 comments (0 inline, 0 general)