##// END OF EJS Templates
review members are dynamically changed based on selected other_repo owner...
marcink -
r3388:cb40b3f6 beta
parent child Browse files
Show More
@@ -0,0 +1,11
1 //Format is key == name
2 // "mark_error_fixed": [ # key
3 // "/mark_error_fixed/%(error_id)s", #url template
4 // [
5 // "error_id" # list of args
6 // ]
7 // ],
8 //
9 var PROUTES_MAP = {
10
11 } No newline at end of file
@@ -129,16 +129,25 class PullrequestsController(BaseRepoCon
129 c.other_repos.extend(c.org_repos)
129 c.other_repos.extend(c.org_repos)
130 c.default_other_repo = org_repo.repo_name
130 c.default_other_repo = org_repo.repo_name
131 c.default_other_refs, c.default_other_ref = self._get_repo_refs(org_repo.scm_instance)
131 c.default_other_refs, c.default_other_ref = self._get_repo_refs(org_repo.scm_instance)
132 usr_data = lambda usr: dict(user_id=usr.user_id,
133 username=usr.username,
134 firstname=usr.firstname,
135 lastname=usr.lastname,
136 gravatar_link=h.gravatar_url(usr.email, 14))
132 other_repos_info[org_repo.repo_name] = {
137 other_repos_info[org_repo.repo_name] = {
138 'user': usr_data(org_repo.user),
133 'description': org_repo.description,
139 'description': org_repo.description,
134 'revs': h.select('other_ref', c.default_other_ref, c.default_other_refs, class_='refs')
140 'revs': h.select('other_ref', c.default_other_ref,
141 c.default_other_refs, class_='refs')
135 }
142 }
136
143
137 # gather forks and add to this list ... even though it is rare to request forks to pull their parent
144 # gather forks and add to this list ... even though it is rare to
145 # request forks to pull their parent
138 for fork in org_repo.forks:
146 for fork in org_repo.forks:
139 c.other_repos.append((fork.repo_name, fork.repo_name))
147 c.other_repos.append((fork.repo_name, fork.repo_name))
140 refs, default_ref = self._get_repo_refs(fork.scm_instance)
148 refs, default_ref = self._get_repo_refs(fork.scm_instance)
141 other_repos_info[fork.repo_name] = {
149 other_repos_info[fork.repo_name] = {
150 'user': usr_data(fork.user),
142 'description': fork.description,
151 'description': fork.description,
143 'revs': h.select('other_ref', default_ref, refs, class_='refs')
152 'revs': h.select('other_ref', default_ref, refs, class_='refs')
144 }
153 }
@@ -149,12 +158,15 class PullrequestsController(BaseRepoCon
149 c.default_other_refs, c.default_other_ref = self._get_repo_refs(org_repo.parent.scm_instance)
158 c.default_other_refs, c.default_other_ref = self._get_repo_refs(org_repo.parent.scm_instance)
150 c.other_repos.append((org_repo.parent.repo_name, org_repo.parent.repo_name))
159 c.other_repos.append((org_repo.parent.repo_name, org_repo.parent.repo_name))
151 other_repos_info[org_repo.parent.repo_name] = {
160 other_repos_info[org_repo.parent.repo_name] = {
161 'user': usr_data(org_repo.parent.user),
152 'description': org_repo.parent.description,
162 'description': org_repo.parent.description,
153 'revs': h.select('other_ref', c.default_other_ref, c.default_other_refs, class_='refs')
163 'revs': h.select('other_ref', c.default_other_ref,
164 c.default_other_refs, class_='refs')
154 }
165 }
155
166
156 c.other_repos_info = json.dumps(other_repos_info)
167 c.other_repos_info = json.dumps(other_repos_info)
157 c.review_members = [org_repo.user]
168 # other repo owner
169 c.review_members = []
158 return render('/pullrequests/pullrequest.html')
170 return render('/pullrequests/pullrequest.html')
159
171
160 @NotAnonymous()
172 @NotAnonymous()
@@ -163,7 +163,175 ColorGenerator.prototype = {
163 }
163 }
164 }
164 }
165
165
166 /**
167 * PyRoutesJS
168 *
169 * Usage pyroutes.url('mark_error_fixed',{"error_id":error_id}) // /mark_error_fixed/<error_id>
170 */
171 var pyroutes = (function() {
172 // access global map defined in special file pyroutes
173 var matchlist = PROUTES_MAP;
174 var sprintf = (function() {
175 function get_type(variable) {
176 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
177 }
178 function str_repeat(input, multiplier) {
179 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
180 return output.join('');
181 }
166
182
183 var str_format = function() {
184 if (!str_format.cache.hasOwnProperty(arguments[0])) {
185 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
186 }
187 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
188 };
189
190 str_format.format = function(parse_tree, argv) {
191 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
192 for (i = 0; i < tree_length; i++) {
193 node_type = get_type(parse_tree[i]);
194 if (node_type === 'string') {
195 output.push(parse_tree[i]);
196 }
197 else if (node_type === 'array') {
198 match = parse_tree[i]; // convenience purposes only
199 if (match[2]) { // keyword argument
200 arg = argv[cursor];
201 for (k = 0; k < match[2].length; k++) {
202 if (!arg.hasOwnProperty(match[2][k])) {
203 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
204 }
205 arg = arg[match[2][k]];
206 }
207 }
208 else if (match[1]) { // positional argument (explicit)
209 arg = argv[match[1]];
210 }
211 else { // positional argument (implicit)
212 arg = argv[cursor++];
213 }
214
215 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
216 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
217 }
218 switch (match[8]) {
219 case 'b': arg = arg.toString(2); break;
220 case 'c': arg = String.fromCharCode(arg); break;
221 case 'd': arg = parseInt(arg, 10); break;
222 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
223 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
224 case 'o': arg = arg.toString(8); break;
225 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
226 case 'u': arg = Math.abs(arg); break;
227 case 'x': arg = arg.toString(16); break;
228 case 'X': arg = arg.toString(16).toUpperCase(); break;
229 }
230 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
231 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
232 pad_length = match[6] - String(arg).length;
233 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
234 output.push(match[5] ? arg + pad : pad + arg);
235 }
236 }
237 return output.join('');
238 };
239
240 str_format.cache = {};
241
242 str_format.parse = function(fmt) {
243 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
244 while (_fmt) {
245 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
246 parse_tree.push(match[0]);
247 }
248 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
249 parse_tree.push('%');
250 }
251 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
252 if (match[2]) {
253 arg_names |= 1;
254 var field_list = [], replacement_field = match[2], field_match = [];
255 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
256 field_list.push(field_match[1]);
257 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
258 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
259 field_list.push(field_match[1]);
260 }
261 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
262 field_list.push(field_match[1]);
263 }
264 else {
265 throw('[sprintf] huh?');
266 }
267 }
268 }
269 else {
270 throw('[sprintf] huh?');
271 }
272 match[2] = field_list;
273 }
274 else {
275 arg_names |= 2;
276 }
277 if (arg_names === 3) {
278 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
279 }
280 parse_tree.push(match);
281 }
282 else {
283 throw('[sprintf] huh?');
284 }
285 _fmt = _fmt.substring(match[0].length);
286 }
287 return parse_tree;
288 };
289
290 return str_format;
291 })();
292
293 var vsprintf = function(fmt, argv) {
294 argv.unshift(fmt);
295 return sprintf.apply(null, argv);
296 };
297 return {
298 'url': function(route_name, params) {
299 var result = route_name;
300 if (typeof(params) != 'object'){
301 params = {};
302 }
303 if (matchlist.hasOwnProperty(route_name)) {
304 var route = matchlist[route_name];
305 for(var i=0; i < route[1].length; i++) {
306
307 if (!params.hasOwnProperty(route[1][i]))
308 throw new Error(route[1][i] + ' missing in "' + route_name + '" route generation');
309 }
310 result = sprintf(route[0], params);
311 }
312
313 return result;
314 },
315 'register': function(route_name, route_tmpl, req_params) {
316 if (typeof(req_params) != 'object') {
317 req_params = [];
318 }
319 //fix escape
320 route_tmpl = unescape(route_tmpl);
321 keys = [];
322 for (o in req_params){
323 keys.push(req_params[o])
324 }
325 matchlist[route_name] = [
326 route_tmpl,
327 keys
328 ]
329 },
330 '_routes': function(){
331 return matchlist;
332 }
333 }
334 })();
167
335
168
336
169
337
@@ -333,8 +501,9 var show_changeset_tooltip = function(){
333 YUD.setAttribute(target,'id',ttid);
501 YUD.setAttribute(target,'id',ttid);
334 YUD.setAttribute(target, 'title',_TM['loading...']);
502 YUD.setAttribute(target, 'title',_TM['loading...']);
335 YAHOO.yuitip.main.set_listeners(target);
503 YAHOO.yuitip.main.set_listeners(target);
336 YAHOO.yuitip.main.show_yuitip(e, target);
504 YAHOO.yuitip.main.show_yuitip(e, target);
337 ajaxGET(LAZY_CS_URL.replace('__NAME__',repo_name).replace('__REV__', rid), success)
505 var url = pyroutes.url('changeset_info', {"repo_name":repo_name, "revision": rid});
506 ajaxGET(url, success)
338 }
507 }
339 });
508 });
340 };
509 };
@@ -396,7 +565,7 var showRepoSize = function(target, repo
396
565
397 if(!YUD.hasClass(target, 'loaded')){
566 if(!YUD.hasClass(target, 'loaded')){
398 YUD.get(target).innerHTML = _TM['loading...'];
567 YUD.get(target).innerHTML = _TM['loading...'];
399 var url = REPO_SIZE_URL.replace('__NAME__', repo_name);
568 var url = pyroutes.url('repo_size', {"repo_name":repo_name});
400 YUC.asyncRequest('POST',url,{
569 YUC.asyncRequest('POST',url,{
401 success:function(o){
570 success:function(o){
402 YUD.get(target).innerHTML = JSON.parse(o.responseText);
571 YUD.get(target).innerHTML = JSON.parse(o.responseText);
@@ -725,24 +894,6 var deleteComment = function(comment_id)
725 ajaxPOST(url,postData,success);
894 ajaxPOST(url,postData,success);
726 }
895 }
727
896
728 var updateReviewers = function(reviewers_ids){
729 if (reviewers_ids === undefined){
730 var reviewers_ids = [];
731 var ids = YUQ('#review_members input');
732 for(var i=0; i<ids.length;i++){
733 var id = ids[i].value
734 reviewers_ids.push(id);
735 }
736 }
737 var url = AJAX_UPDATE_PULLREQUEST;
738 var postData = {'_method':'put',
739 'reviewers_ids': reviewers_ids};
740 var success = function(o){
741 window.location.reload();
742 }
743 ajaxPOST(url,postData,success);
744 }
745
746 var createInlineAddButton = function(tr){
897 var createInlineAddButton = function(tr){
747
898
748 var label = TRANSLATION_MAP['add another comment'];
899 var label = TRANSLATION_MAP['add another comment'];
@@ -869,14 +1020,6 var renderInlineComments = function(file
869 }
1020 }
870 }
1021 }
871
1022
872 var removeReviewer = function(reviewer_id){
873 var el = YUD.get('reviewer_{0}'.format(reviewer_id));
874 if (el.parentNode !== undefined){
875 el.parentNode.removeChild(el);
876 }
877 updateReviewers();
878 }
879
880 var fileBrowserListeners = function(current_url, node_list_url, url_base){
1023 var fileBrowserListeners = function(current_url, node_list_url, url_base){
881 var current_url_branch = +"?branch=__BRANCH__";
1024 var current_url_branch = +"?branch=__BRANCH__";
882
1025
@@ -1488,6 +1631,56 var MentionsAutoComplete = function (div
1488 };
1631 };
1489 }
1632 }
1490
1633
1634 var addReviewMember = function(id,fname,lname,nname,gravatar_link){
1635 var members = YUD.get('review_members');
1636 var tmpl = '<li id="reviewer_{2}">'+
1637 '<div class="reviewers_member">'+
1638 '<div class="gravatar"><img alt="gravatar" src="{0}"/> </div>'+
1639 '<div style="float:left">{1}</div>'+
1640 '<input type="hidden" value="{2}" name="review_members" />'+
1641 '<span class="delete_icon action_button" onclick="removeReviewMember({2})"></span>'+
1642 '</div>'+
1643 '</li>' ;
1644 var displayname = "{0} {1} ({2})".format(fname,lname,nname);
1645 var element = tmpl.format(gravatar_link,displayname,id);
1646 // check if we don't have this ID already in
1647 var ids = [];
1648 var _els = YUQ('#review_members li');
1649 for (el in _els){
1650 ids.push(_els[el].id)
1651 }
1652 if(ids.indexOf('reviewer_'+id) == -1){
1653 //only add if it's not there
1654 members.innerHTML += element;
1655 }
1656
1657 }
1658
1659 var removeReviewMember = function(reviewer_id, repo_name, pull_request_id){
1660 var el = YUD.get('reviewer_{0}'.format(reviewer_id));
1661 if (el.parentNode !== undefined){
1662 el.parentNode.removeChild(el);
1663 }
1664 }
1665
1666 var updateReviewers = function(reviewers_ids, repo_name, pull_request_id){
1667 if (reviewers_ids === undefined){
1668 var reviewers_ids = [];
1669 var ids = YUQ('#review_members input');
1670 for(var i=0; i<ids.length;i++){
1671 var id = ids[i].value
1672 reviewers_ids.push(id);
1673 }
1674 }
1675 var url = pyroutes.url('pullrequest_update', {"repo_name":repo_name,
1676 "pull_request_id": pull_request_id});
1677 var postData = {'_method':'put',
1678 'reviewers_ids': reviewers_ids};
1679 var success = function(o){
1680 window.location.reload();
1681 }
1682 ajaxPOST(url,postData,success);
1683 }
1491
1684
1492 var PullRequestAutoComplete = function (divid, cont, users_list, groups_list) {
1685 var PullRequestAutoComplete = function (divid, cont, users_list, groups_list) {
1493 var myUsers = users_list;
1686 var myUsers = users_list;
@@ -1620,26 +1813,12 var PullRequestAutoComplete = function (
1620 var myAC = aArgs[0]; // reference back to the AC instance
1813 var myAC = aArgs[0]; // reference back to the AC instance
1621 var elLI = aArgs[1]; // reference to the selected LI element
1814 var elLI = aArgs[1]; // reference to the selected LI element
1622 var oData = aArgs[2]; // object literal of selected item's result data
1815 var oData = aArgs[2]; // object literal of selected item's result data
1623 var members = YUD.get('review_members');
1816
1624 //fill the autocomplete with value
1817 //fill the autocomplete with value
1625
1818
1626 if (oData.nname != undefined) {
1819 if (oData.nname != undefined) {
1627 if (myAC.dataSource.cache.indexOf(oData.id) != -1){
1820 addReviewMember(oData.id, oData.fname, oData.lname, oData.nname,
1628 return
1821 oData.gravatar_lnk);
1629 }
1630
1631 var tmpl = '<li id="reviewer_{2}">'+
1632 '<div class="reviewers_member">'+
1633 '<div class="gravatar"><img alt="gravatar" src="{0}"/> </div>'+
1634 '<div style="float:left">{1}</div>'+
1635 '<input type="hidden" value="{2}" name="review_members" />'+
1636 '<span class="delete_icon action_button" onclick="removeReviewer({2})"></span>'+
1637 '</div>'+
1638 '</li>'
1639
1640 var displayname = "{0} {1} ({2})".format(oData.fname,oData.lname,oData.nname);
1641 var element = tmpl.format(oData.gravatar_lnk,displayname,oData.id);
1642 members.innerHTML += element;
1643 myAC.dataSource.cache.push(oData.id);
1822 myAC.dataSource.cache.push(oData.id);
1644 YUD.get('user').value = ''
1823 YUD.get('user').value = ''
1645 }
1824 }
@@ -1651,7 +1830,6 var PullRequestAutoComplete = function (
1651 };
1830 };
1652 }
1831 }
1653
1832
1654
1655 /**
1833 /**
1656 * QUICK REPO MENU
1834 * QUICK REPO MENU
1657 */
1835 */
@@ -53,9 +53,8
53 'Selection link': "${_('Selection link')}",
53 'Selection link': "${_('Selection link')}",
54 };
54 };
55 var _TM = TRANSLATION_MAP;
55 var _TM = TRANSLATION_MAP;
56
56 var TOGGLE_FOLLOW_URL = "${h.url('toggle_following')}";
57 var TOGGLE_FOLLOW_URL = "${h.url('toggle_following')}";
57 var LAZY_CS_URL = "${h.url('changeset_info', repo_name='__NAME__', revision='__REV__')}";
58 var REPO_SIZE_URL = "${h.url('repo_size', repo_name='__NAME__')}";
59
58
60 </script>
59 </script>
61 <script type="text/javascript" src="${h.url('/js/yui.2.9.js', ver=c.rhodecode_version)}"></script>
60 <script type="text/javascript" src="${h.url('/js/yui.2.9.js', ver=c.rhodecode_version)}"></script>
@@ -64,6 +63,7
64 <![endif]-->
63 <![endif]-->
65 <script type="text/javascript" src="${h.url('/js/yui.flot.js', ver=c.rhodecode_version)}"></script>
64 <script type="text/javascript" src="${h.url('/js/yui.flot.js', ver=c.rhodecode_version)}"></script>
66 <script type="text/javascript" src="${h.url('/js/native.history.js', ver=c.rhodecode_version)}"></script>
65 <script type="text/javascript" src="${h.url('/js/native.history.js', ver=c.rhodecode_version)}"></script>
66 <script type="text/javascript" src="${h.url('/js/pyroutes_map.js', ver=c.rhodecode_version)}"></script>
67 <script type="text/javascript" src="${h.url('/js/rhodecode.js', ver=c.rhodecode_version)}"></script>
67 <script type="text/javascript" src="${h.url('/js/rhodecode.js', ver=c.rhodecode_version)}"></script>
68 ## EXTRA FOR JS
68 ## EXTRA FOR JS
69 ${self.js_extra()}
69 ${self.js_extra()}
@@ -82,6 +82,10
82 tooltip_activate();
82 tooltip_activate();
83 show_more_event();
83 show_more_event();
84 show_changeset_tooltip();
84 show_changeset_tooltip();
85 // routes registration
86 pyroutes.register('toggle_following', "${h.url('toggle_following')}");
87 pyroutes.register('changeset_info', "${h.url('changeset_info', repo_name='%(repo_name)s', revision='%(revision)s')}", ['repo_name', 'revision']);
88 pyroutes.register('repo_size', "${h.url('repo_size', repo_name='%(repo_name)s')}", ['repo_name']);
85 })
89 })
86 </script>
90 </script>
87 </%def>
91 </%def>
@@ -67,7 +67,7
67 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(member.email,14)}"/> </div>
67 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(member.email,14)}"/> </div>
68 <div style="float:left">${member.full_name} (${_('owner')})</div>
68 <div style="float:left">${member.full_name} (${_('owner')})</div>
69 <input type="hidden" value="${member.user_id}" name="review_members" />
69 <input type="hidden" value="${member.user_id}" name="review_members" />
70 <span class="delete_icon action_button" onclick="removeReviewer(${member.user_id})"></span>
70 <span class="delete_icon action_button" onclick="removeReviewMember(${member.user_id})"></span>
71 </div>
71 </div>
72 </li>
72 </li>
73 %endfor
73 %endfor
@@ -161,12 +161,18
161 ypjax(url,'pull_request_overview', function(data){
161 ypjax(url,'pull_request_overview', function(data){
162 var sel_box = YUQ('#pull_request_form #other_repo')[0];
162 var sel_box = YUQ('#pull_request_form #other_repo')[0];
163 var repo_name = sel_box.options[sel_box.selectedIndex].value;
163 var repo_name = sel_box.options[sel_box.selectedIndex].value;
164 var _data = other_repos_info[repo_name];
164 YUD.get('pull_request_overview_url').href = url;
165 YUD.get('pull_request_overview_url').href = url;
165 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','');
166 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','');
166 YUD.get('other_repo_desc').innerHTML = other_repos_info[repo_name]['description'];
167 YUD.get('other_repo_desc').innerHTML = other_repos_info[repo_name]['description'];
167 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
168 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
168 // select back the revision that was just compared
169 // select back the revision that was just compared
169 setSelectValue(YUD.get('other_ref'), rev_data['other_ref']);
170 setSelectValue(YUD.get('other_ref'), rev_data['other_ref']);
171 // reset && add the reviewer based on selected repo
172 YUD.get('review_members').innerHTML = '';
173 addReviewMember(_data.user.user_id, _data.user.firstname,
174 _data.user.lastname, _data.user.username,
175 _data.user.gravatar_link);
170 })
176 })
171 }
177 }
172
178
@@ -28,7 +28,7
28 <div id="summary" class="fields">
28 <div id="summary" class="fields">
29 <div class="field">
29 <div class="field">
30 <div class="label-summary">
30 <div class="label-summary">
31 <label>${_('Status')}:</label>
31 <label>${_('Review status')}:</label>
32 </div>
32 </div>
33 <div class="input">
33 <div class="input">
34 <div class="changeset-status-container" style="float:none;clear:both">
34 <div class="changeset-status-container" style="float:none;clear:both">
@@ -140,7 +140,7
140 <div style="float:left">${member.full_name} (${_('owner') if c.pull_request.user_id == member.user_id else _('reviewer')})</div>
140 <div style="float:left">${member.full_name} (${_('owner') if c.pull_request.user_id == member.user_id else _('reviewer')})</div>
141 <input type="hidden" value="${member.user_id}" name="review_members" />
141 <input type="hidden" value="${member.user_id}" name="review_members" />
142 %if not c.pull_request.is_closed() and (h.HasPermissionAny('hg.admin', 'repository.admin')() or c.pull_request.user_id == c.rhodecode_user.user_id):
142 %if not c.pull_request.is_closed() and (h.HasPermissionAny('hg.admin', 'repository.admin')() or c.pull_request.user_id == c.rhodecode_user.user_id):
143 <span class="delete_icon action_button" onclick="removeReviewer(${member.user_id})"></span>
143 <span class="delete_icon action_button" onclick="removeReviewMember(${member.user_id})"></span>
144 %endif
144 %endif
145 </div>
145 </div>
146 </li>
146 </li>
@@ -152,11 +152,11
152 %if h.HasPermissionAny('hg.admin', 'repository.admin')() or c.pull_request.author.user_id == c.rhodecode_user.user_id:
152 %if h.HasPermissionAny('hg.admin', 'repository.admin')() or c.pull_request.author.user_id == c.rhodecode_user.user_id:
153 <div class="reviewer_ac">
153 <div class="reviewer_ac">
154 ${h.text('user', class_='yui-ac-input')}
154 ${h.text('user', class_='yui-ac-input')}
155 <span class="help-block">${_('Add reviewer to this pull request.')}</span>
155 <span class="help-block">${_('Add or remove reviewer to this pull request.')}</span>
156 <div id="reviewers_container"></div>
156 <div id="reviewers_container"></div>
157 </div>
157 </div>
158 <div style="padding:0px 10px">
158 <div style="padding:0px 10px">
159 <span id="update_pull_request" class="ui-btn xsmall">${_('save')}</span>
159 <span id="update_pull_request" class="ui-btn xsmall">${_('save changes')}</span>
160 </div>
160 </div>
161 %endif
161 %endif
162 </div>
162 </div>
@@ -167,9 +167,14
167 <script>
167 <script>
168 var _USERS_AC_DATA = ${c.users_array|n};
168 var _USERS_AC_DATA = ${c.users_array|n};
169 var _GROUPS_AC_DATA = ${c.users_groups_array|n};
169 var _GROUPS_AC_DATA = ${c.users_groups_array|n};
170 // TODO: switch this to pyroutes
170 AJAX_COMMENT_URL = "${url('pullrequest_comment',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id)}";
171 AJAX_COMMENT_URL = "${url('pullrequest_comment',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id)}";
171 AJAX_COMMENT_DELETE_URL = "${url('pullrequest_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
172 AJAX_COMMENT_DELETE_URL = "${url('pullrequest_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
172 AJAX_UPDATE_PULLREQUEST = "${url('pullrequest_update',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id)}"
173
174 pyroutes.register('pullrequest_comment', "${url('pullrequest_comment',repo_name='%(repo_name)s',pull_request_id='%(pull_request_id)s')}", ['repo_name', 'pull_request_id']);
175 pyroutes.register('pullrequest_comment_delete', "${url('pullrequest_comment_delete',repo_name='%(repo_name)s',comment_id='%(comment_id)s')}", ['repo_name', 'comment_id']);
176 pyroutes.register('pullrequest_update', "${url('pullrequest_update',repo_name='%(repo_name)s',pull_request_id='%(pull_request_id)s')}", ['repo_name', 'pull_request_id']);
177
173 </script>
178 </script>
174
179
175 ## diff block
180 ## diff block
@@ -228,7 +233,7
228 renderInlineComments(file_comments);
233 renderInlineComments(file_comments);
229
234
230 YUE.on(YUD.get('update_pull_request'),'click',function(e){
235 YUE.on(YUD.get('update_pull_request'),'click',function(e){
231 updateReviewers();
236 updateReviewers(undefined, "${c.repo_name}", "${c.pull_request.pull_request_id}");
232 })
237 })
233 })
238 })
234 </script>
239 </script>
General Comments 0
You need to be logged in to leave comments. Login now