##// END OF EJS Templates
pull-requests: fixed title/description generation for single commits which are numbers....
dan -
r4163:a80d50b2 default
parent child Browse files
Show More
@@ -1,623 +1,624 b''
1 // # Copyright (C) 2010-2019 RhodeCode GmbH
1 // # Copyright (C) 2010-2019 RhodeCode GmbH
2 // #
2 // #
3 // # This program is free software: you can redistribute it and/or modify
3 // # This program is free software: you can redistribute it and/or modify
4 // # it under the terms of the GNU Affero General Public License, version 3
4 // # it under the terms of the GNU Affero General Public License, version 3
5 // # (only), as published by the Free Software Foundation.
5 // # (only), as published by the Free Software Foundation.
6 // #
6 // #
7 // # This program is distributed in the hope that it will be useful,
7 // # This program is distributed in the hope that it will be useful,
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // # GNU General Public License for more details.
10 // # GNU General Public License for more details.
11 // #
11 // #
12 // # You should have received a copy of the GNU Affero General Public License
12 // # You should have received a copy of the GNU Affero General Public License
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 // #
14 // #
15 // # This program is dual-licensed. If you wish to learn more about the
15 // # This program is dual-licensed. If you wish to learn more about the
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19
19
20 var prButtonLockChecks = {
20 var prButtonLockChecks = {
21 'compare': false,
21 'compare': false,
22 'reviewers': false
22 'reviewers': false
23 };
23 };
24
24
25 /**
25 /**
26 * lock button until all checks and loads are made. E.g reviewer calculation
26 * lock button until all checks and loads are made. E.g reviewer calculation
27 * should prevent from submitting a PR
27 * should prevent from submitting a PR
28 * @param lockEnabled
28 * @param lockEnabled
29 * @param msg
29 * @param msg
30 * @param scope
30 * @param scope
31 */
31 */
32 var prButtonLock = function(lockEnabled, msg, scope) {
32 var prButtonLock = function(lockEnabled, msg, scope) {
33 scope = scope || 'all';
33 scope = scope || 'all';
34 if (scope == 'all'){
34 if (scope == 'all'){
35 prButtonLockChecks['compare'] = !lockEnabled;
35 prButtonLockChecks['compare'] = !lockEnabled;
36 prButtonLockChecks['reviewers'] = !lockEnabled;
36 prButtonLockChecks['reviewers'] = !lockEnabled;
37 } else if (scope == 'compare') {
37 } else if (scope == 'compare') {
38 prButtonLockChecks['compare'] = !lockEnabled;
38 prButtonLockChecks['compare'] = !lockEnabled;
39 } else if (scope == 'reviewers'){
39 } else if (scope == 'reviewers'){
40 prButtonLockChecks['reviewers'] = !lockEnabled;
40 prButtonLockChecks['reviewers'] = !lockEnabled;
41 }
41 }
42 var checksMeet = prButtonLockChecks.compare && prButtonLockChecks.reviewers;
42 var checksMeet = prButtonLockChecks.compare && prButtonLockChecks.reviewers;
43 if (lockEnabled) {
43 if (lockEnabled) {
44 $('#pr_submit').attr('disabled', 'disabled');
44 $('#pr_submit').attr('disabled', 'disabled');
45 }
45 }
46 else if (checksMeet) {
46 else if (checksMeet) {
47 $('#pr_submit').removeAttr('disabled');
47 $('#pr_submit').removeAttr('disabled');
48 }
48 }
49
49
50 if (msg) {
50 if (msg) {
51 $('#pr_open_message').html(msg);
51 $('#pr_open_message').html(msg);
52 }
52 }
53 };
53 };
54
54
55
55
56 /**
56 /**
57 Generate Title and Description for a PullRequest.
57 Generate Title and Description for a PullRequest.
58 In case of 1 commits, the title and description is that one commit
58 In case of 1 commits, the title and description is that one commit
59 in case of multiple commits, we iterate on them with max N number of commits,
59 in case of multiple commits, we iterate on them with max N number of commits,
60 and build description in a form
60 and build description in a form
61 - commitN
61 - commitN
62 - commitN+1
62 - commitN+1
63 ...
63 ...
64
64
65 Title is then constructed from branch names, or other references,
65 Title is then constructed from branch names, or other references,
66 replacing '-' and '_' into spaces
66 replacing '-' and '_' into spaces
67
67
68 * @param sourceRef
68 * @param sourceRef
69 * @param elements
69 * @param elements
70 * @param limit
70 * @param limit
71 * @returns {*[]}
71 * @returns {*[]}
72 */
72 */
73 var getTitleAndDescription = function(sourceRef, elements, limit) {
73 var getTitleAndDescription = function(sourceRef, elements, limit) {
74 var title = '';
74 var title = '';
75 var desc = '';
75 var desc = '';
76
76
77 $.each($(elements).get().reverse().slice(0, limit), function(idx, value) {
77 $.each($(elements).get().reverse().slice(0, limit), function(idx, value) {
78 var rawMessage = $(value).find('td.td-description .message').data('messageRaw');
78 var rawMessage = $(value).find('td.td-description .message').data('messageRaw').toString();
79 desc += '- ' + rawMessage.split('\n')[0].replace(/\n+$/, "") + '\n';
79 desc += '- ' + rawMessage.split('\n')[0].replace(/\n+$/, "") + '\n';
80 });
80 });
81 // only 1 commit, use commit message as title
81 // only 1 commit, use commit message as title
82 if (elements.length === 1) {
82 if (elements.length === 1) {
83 title = $(elements[0]).find('td.td-description .message').data('messageRaw').split('\n')[0];
83 var rawMessage = $(elements[0]).find('td.td-description .message').data('messageRaw').toString();
84 title = rawMessage.split('\n')[0];
84 }
85 }
85 else {
86 else {
86 // use reference name
87 // use reference name
87 title = sourceRef.replace(/-/g, ' ').replace(/_/g, ' ').capitalizeFirstLetter();
88 title = sourceRef.replace(/-/g, ' ').replace(/_/g, ' ').capitalizeFirstLetter();
88 }
89 }
89
90
90 return [title, desc]
91 return [title, desc]
91 };
92 };
92
93
93
94
94
95
95 ReviewersController = function () {
96 ReviewersController = function () {
96 var self = this;
97 var self = this;
97 this.$reviewRulesContainer = $('#review_rules');
98 this.$reviewRulesContainer = $('#review_rules');
98 this.$rulesList = this.$reviewRulesContainer.find('.pr-reviewer-rules');
99 this.$rulesList = this.$reviewRulesContainer.find('.pr-reviewer-rules');
99 this.forbidReviewUsers = undefined;
100 this.forbidReviewUsers = undefined;
100 this.$reviewMembers = $('#review_members');
101 this.$reviewMembers = $('#review_members');
101 this.currentRequest = null;
102 this.currentRequest = null;
102
103
103 this.defaultForbidReviewUsers = function() {
104 this.defaultForbidReviewUsers = function() {
104 return [
105 return [
105 {'username': 'default',
106 {'username': 'default',
106 'user_id': templateContext.default_user.user_id}
107 'user_id': templateContext.default_user.user_id}
107 ];
108 ];
108 };
109 };
109
110
110 this.hideReviewRules = function() {
111 this.hideReviewRules = function() {
111 self.$reviewRulesContainer.hide();
112 self.$reviewRulesContainer.hide();
112 };
113 };
113
114
114 this.showReviewRules = function() {
115 this.showReviewRules = function() {
115 self.$reviewRulesContainer.show();
116 self.$reviewRulesContainer.show();
116 };
117 };
117
118
118 this.addRule = function(ruleText) {
119 this.addRule = function(ruleText) {
119 self.showReviewRules();
120 self.showReviewRules();
120 return '<div>- {0}</div>'.format(ruleText)
121 return '<div>- {0}</div>'.format(ruleText)
121 };
122 };
122
123
123 this.loadReviewRules = function(data) {
124 this.loadReviewRules = function(data) {
124 // reset forbidden Users
125 // reset forbidden Users
125 this.forbidReviewUsers = self.defaultForbidReviewUsers();
126 this.forbidReviewUsers = self.defaultForbidReviewUsers();
126
127
127 // reset state of review rules
128 // reset state of review rules
128 self.$rulesList.html('');
129 self.$rulesList.html('');
129
130
130 if (!data || data.rules === undefined || $.isEmptyObject(data.rules)) {
131 if (!data || data.rules === undefined || $.isEmptyObject(data.rules)) {
131 // default rule, case for older repo that don't have any rules stored
132 // default rule, case for older repo that don't have any rules stored
132 self.$rulesList.append(
133 self.$rulesList.append(
133 self.addRule(
134 self.addRule(
134 _gettext('All reviewers must vote.'))
135 _gettext('All reviewers must vote.'))
135 );
136 );
136 return self.forbidReviewUsers
137 return self.forbidReviewUsers
137 }
138 }
138
139
139 if (data.rules.voting !== undefined) {
140 if (data.rules.voting !== undefined) {
140 if (data.rules.voting < 0) {
141 if (data.rules.voting < 0) {
141 self.$rulesList.append(
142 self.$rulesList.append(
142 self.addRule(
143 self.addRule(
143 _gettext('All individual reviewers must vote.'))
144 _gettext('All individual reviewers must vote.'))
144 )
145 )
145 } else if (data.rules.voting === 1) {
146 } else if (data.rules.voting === 1) {
146 self.$rulesList.append(
147 self.$rulesList.append(
147 self.addRule(
148 self.addRule(
148 _gettext('At least {0} reviewer must vote.').format(data.rules.voting))
149 _gettext('At least {0} reviewer must vote.').format(data.rules.voting))
149 )
150 )
150
151
151 } else {
152 } else {
152 self.$rulesList.append(
153 self.$rulesList.append(
153 self.addRule(
154 self.addRule(
154 _gettext('At least {0} reviewers must vote.').format(data.rules.voting))
155 _gettext('At least {0} reviewers must vote.').format(data.rules.voting))
155 )
156 )
156 }
157 }
157 }
158 }
158
159
159 if (data.rules.voting_groups !== undefined) {
160 if (data.rules.voting_groups !== undefined) {
160 $.each(data.rules.voting_groups, function(index, rule_data) {
161 $.each(data.rules.voting_groups, function(index, rule_data) {
161 self.$rulesList.append(
162 self.$rulesList.append(
162 self.addRule(rule_data.text)
163 self.addRule(rule_data.text)
163 )
164 )
164 });
165 });
165 }
166 }
166
167
167 if (data.rules.use_code_authors_for_review) {
168 if (data.rules.use_code_authors_for_review) {
168 self.$rulesList.append(
169 self.$rulesList.append(
169 self.addRule(
170 self.addRule(
170 _gettext('Reviewers picked from source code changes.'))
171 _gettext('Reviewers picked from source code changes.'))
171 )
172 )
172 }
173 }
173 if (data.rules.forbid_adding_reviewers) {
174 if (data.rules.forbid_adding_reviewers) {
174 $('#add_reviewer_input').remove();
175 $('#add_reviewer_input').remove();
175 self.$rulesList.append(
176 self.$rulesList.append(
176 self.addRule(
177 self.addRule(
177 _gettext('Adding new reviewers is forbidden.'))
178 _gettext('Adding new reviewers is forbidden.'))
178 )
179 )
179 }
180 }
180 if (data.rules.forbid_author_to_review) {
181 if (data.rules.forbid_author_to_review) {
181 self.forbidReviewUsers.push(data.rules_data.pr_author);
182 self.forbidReviewUsers.push(data.rules_data.pr_author);
182 self.$rulesList.append(
183 self.$rulesList.append(
183 self.addRule(
184 self.addRule(
184 _gettext('Author is not allowed to be a reviewer.'))
185 _gettext('Author is not allowed to be a reviewer.'))
185 )
186 )
186 }
187 }
187 if (data.rules.forbid_commit_author_to_review) {
188 if (data.rules.forbid_commit_author_to_review) {
188
189
189 if (data.rules_data.forbidden_users) {
190 if (data.rules_data.forbidden_users) {
190 $.each(data.rules_data.forbidden_users, function(index, member_data) {
191 $.each(data.rules_data.forbidden_users, function(index, member_data) {
191 self.forbidReviewUsers.push(member_data)
192 self.forbidReviewUsers.push(member_data)
192 });
193 });
193
194
194 }
195 }
195
196
196 self.$rulesList.append(
197 self.$rulesList.append(
197 self.addRule(
198 self.addRule(
198 _gettext('Commit Authors are not allowed to be a reviewer.'))
199 _gettext('Commit Authors are not allowed to be a reviewer.'))
199 )
200 )
200 }
201 }
201
202
202 return self.forbidReviewUsers
203 return self.forbidReviewUsers
203 };
204 };
204
205
205 this.loadDefaultReviewers = function(sourceRepo, sourceRef, targetRepo, targetRef) {
206 this.loadDefaultReviewers = function(sourceRepo, sourceRef, targetRepo, targetRef) {
206
207
207 if (self.currentRequest) {
208 if (self.currentRequest) {
208 // make sure we cleanup old running requests before triggering this
209 // make sure we cleanup old running requests before triggering this
209 // again
210 // again
210 self.currentRequest.abort();
211 self.currentRequest.abort();
211 }
212 }
212
213
213 $('.calculate-reviewers').show();
214 $('.calculate-reviewers').show();
214 // reset reviewer members
215 // reset reviewer members
215 self.$reviewMembers.empty();
216 self.$reviewMembers.empty();
216
217
217 prButtonLock(true, null, 'reviewers');
218 prButtonLock(true, null, 'reviewers');
218 $('#user').hide(); // hide user autocomplete before load
219 $('#user').hide(); // hide user autocomplete before load
219
220
220 if (sourceRef.length !== 3 || targetRef.length !== 3) {
221 if (sourceRef.length !== 3 || targetRef.length !== 3) {
221 // don't load defaults in case we're missing some refs...
222 // don't load defaults in case we're missing some refs...
222 $('.calculate-reviewers').hide();
223 $('.calculate-reviewers').hide();
223 return
224 return
224 }
225 }
225
226
226 var url = pyroutes.url('repo_default_reviewers_data',
227 var url = pyroutes.url('repo_default_reviewers_data',
227 {
228 {
228 'repo_name': templateContext.repo_name,
229 'repo_name': templateContext.repo_name,
229 'source_repo': sourceRepo,
230 'source_repo': sourceRepo,
230 'source_ref': sourceRef[2],
231 'source_ref': sourceRef[2],
231 'target_repo': targetRepo,
232 'target_repo': targetRepo,
232 'target_ref': targetRef[2]
233 'target_ref': targetRef[2]
233 });
234 });
234
235
235 self.currentRequest = $.get(url)
236 self.currentRequest = $.get(url)
236 .done(function(data) {
237 .done(function(data) {
237 self.currentRequest = null;
238 self.currentRequest = null;
238
239
239 // review rules
240 // review rules
240 self.loadReviewRules(data);
241 self.loadReviewRules(data);
241
242
242 for (var i = 0; i < data.reviewers.length; i++) {
243 for (var i = 0; i < data.reviewers.length; i++) {
243 var reviewer = data.reviewers[i];
244 var reviewer = data.reviewers[i];
244 self.addReviewMember(
245 self.addReviewMember(
245 reviewer, reviewer.reasons, reviewer.mandatory);
246 reviewer, reviewer.reasons, reviewer.mandatory);
246 }
247 }
247 $('.calculate-reviewers').hide();
248 $('.calculate-reviewers').hide();
248 prButtonLock(false, null, 'reviewers');
249 prButtonLock(false, null, 'reviewers');
249 $('#user').show(); // show user autocomplete after load
250 $('#user').show(); // show user autocomplete after load
250 });
251 });
251 };
252 };
252
253
253 // check those, refactor
254 // check those, refactor
254 this.removeReviewMember = function(reviewer_id, mark_delete) {
255 this.removeReviewMember = function(reviewer_id, mark_delete) {
255 var reviewer = $('#reviewer_{0}'.format(reviewer_id));
256 var reviewer = $('#reviewer_{0}'.format(reviewer_id));
256
257
257 if(typeof(mark_delete) === undefined){
258 if(typeof(mark_delete) === undefined){
258 mark_delete = false;
259 mark_delete = false;
259 }
260 }
260
261
261 if(mark_delete === true){
262 if(mark_delete === true){
262 if (reviewer){
263 if (reviewer){
263 // now delete the input
264 // now delete the input
264 $('#reviewer_{0} input'.format(reviewer_id)).remove();
265 $('#reviewer_{0} input'.format(reviewer_id)).remove();
265 // mark as to-delete
266 // mark as to-delete
266 var obj = $('#reviewer_{0}_name'.format(reviewer_id));
267 var obj = $('#reviewer_{0}_name'.format(reviewer_id));
267 obj.addClass('to-delete');
268 obj.addClass('to-delete');
268 obj.css({"text-decoration":"line-through", "opacity": 0.5});
269 obj.css({"text-decoration":"line-through", "opacity": 0.5});
269 }
270 }
270 }
271 }
271 else{
272 else{
272 $('#reviewer_{0}'.format(reviewer_id)).remove();
273 $('#reviewer_{0}'.format(reviewer_id)).remove();
273 }
274 }
274 };
275 };
275 this.reviewMemberEntry = function() {
276 this.reviewMemberEntry = function() {
276
277
277 };
278 };
278 this.addReviewMember = function(reviewer_obj, reasons, mandatory) {
279 this.addReviewMember = function(reviewer_obj, reasons, mandatory) {
279 var members = self.$reviewMembers.get(0);
280 var members = self.$reviewMembers.get(0);
280 var id = reviewer_obj.user_id;
281 var id = reviewer_obj.user_id;
281 var username = reviewer_obj.username;
282 var username = reviewer_obj.username;
282
283
283 var reasons = reasons || [];
284 var reasons = reasons || [];
284 var mandatory = mandatory || false;
285 var mandatory = mandatory || false;
285
286
286 // register IDS to check if we don't have this ID already in
287 // register IDS to check if we don't have this ID already in
287 var currentIds = [];
288 var currentIds = [];
288 var _els = self.$reviewMembers.find('li').toArray();
289 var _els = self.$reviewMembers.find('li').toArray();
289 for (el in _els){
290 for (el in _els){
290 currentIds.push(_els[el].id)
291 currentIds.push(_els[el].id)
291 }
292 }
292
293
293 var userAllowedReview = function(userId) {
294 var userAllowedReview = function(userId) {
294 var allowed = true;
295 var allowed = true;
295 $.each(self.forbidReviewUsers, function(index, member_data) {
296 $.each(self.forbidReviewUsers, function(index, member_data) {
296 if (parseInt(userId) === member_data['user_id']) {
297 if (parseInt(userId) === member_data['user_id']) {
297 allowed = false;
298 allowed = false;
298 return false // breaks the loop
299 return false // breaks the loop
299 }
300 }
300 });
301 });
301 return allowed
302 return allowed
302 };
303 };
303
304
304 var userAllowed = userAllowedReview(id);
305 var userAllowed = userAllowedReview(id);
305 if (!userAllowed){
306 if (!userAllowed){
306 alert(_gettext('User `{0}` not allowed to be a reviewer').format(username));
307 alert(_gettext('User `{0}` not allowed to be a reviewer').format(username));
307 } else {
308 } else {
308 // only add if it's not there
309 // only add if it's not there
309 var alreadyReviewer = currentIds.indexOf('reviewer_'+id) != -1;
310 var alreadyReviewer = currentIds.indexOf('reviewer_'+id) != -1;
310
311
311 if (alreadyReviewer) {
312 if (alreadyReviewer) {
312 alert(_gettext('User `{0}` already in reviewers').format(username));
313 alert(_gettext('User `{0}` already in reviewers').format(username));
313 } else {
314 } else {
314 members.innerHTML += renderTemplate('reviewMemberEntry', {
315 members.innerHTML += renderTemplate('reviewMemberEntry', {
315 'member': reviewer_obj,
316 'member': reviewer_obj,
316 'mandatory': mandatory,
317 'mandatory': mandatory,
317 'allowed_to_update': true,
318 'allowed_to_update': true,
318 'review_status': 'not_reviewed',
319 'review_status': 'not_reviewed',
319 'review_status_label': _gettext('Not Reviewed'),
320 'review_status_label': _gettext('Not Reviewed'),
320 'reasons': reasons,
321 'reasons': reasons,
321 'create': true
322 'create': true
322 });
323 });
323 tooltipActivate();
324 tooltipActivate();
324 }
325 }
325 }
326 }
326
327
327 };
328 };
328
329
329 this.updateReviewers = function(repo_name, pull_request_id){
330 this.updateReviewers = function(repo_name, pull_request_id){
330 var postData = $('#reviewers input').serialize();
331 var postData = $('#reviewers input').serialize();
331 _updatePullRequest(repo_name, pull_request_id, postData);
332 _updatePullRequest(repo_name, pull_request_id, postData);
332 };
333 };
333
334
334 };
335 };
335
336
336
337
337 var _updatePullRequest = function(repo_name, pull_request_id, postData) {
338 var _updatePullRequest = function(repo_name, pull_request_id, postData) {
338 var url = pyroutes.url(
339 var url = pyroutes.url(
339 'pullrequest_update',
340 'pullrequest_update',
340 {"repo_name": repo_name, "pull_request_id": pull_request_id});
341 {"repo_name": repo_name, "pull_request_id": pull_request_id});
341 if (typeof postData === 'string' ) {
342 if (typeof postData === 'string' ) {
342 postData += '&csrf_token=' + CSRF_TOKEN;
343 postData += '&csrf_token=' + CSRF_TOKEN;
343 } else {
344 } else {
344 postData.csrf_token = CSRF_TOKEN;
345 postData.csrf_token = CSRF_TOKEN;
345 }
346 }
346
347
347 var success = function(o) {
348 var success = function(o) {
348 var redirectUrl = o['redirect_url'];
349 var redirectUrl = o['redirect_url'];
349 if (redirectUrl !== undefined && redirectUrl !== null && redirectUrl !== '') {
350 if (redirectUrl !== undefined && redirectUrl !== null && redirectUrl !== '') {
350 window.location = redirectUrl;
351 window.location = redirectUrl;
351 } else {
352 } else {
352 window.location.reload();
353 window.location.reload();
353 }
354 }
354 };
355 };
355
356
356 ajaxPOST(url, postData, success);
357 ajaxPOST(url, postData, success);
357 };
358 };
358
359
359 /**
360 /**
360 * PULL REQUEST update commits
361 * PULL REQUEST update commits
361 */
362 */
362 var updateCommits = function(repo_name, pull_request_id, force) {
363 var updateCommits = function(repo_name, pull_request_id, force) {
363 var postData = {
364 var postData = {
364 'update_commits': true
365 'update_commits': true
365 };
366 };
366 if (force !== undefined && force === true) {
367 if (force !== undefined && force === true) {
367 postData['force_refresh'] = true
368 postData['force_refresh'] = true
368 }
369 }
369 _updatePullRequest(repo_name, pull_request_id, postData);
370 _updatePullRequest(repo_name, pull_request_id, postData);
370 };
371 };
371
372
372
373
373 /**
374 /**
374 * PULL REQUEST edit info
375 * PULL REQUEST edit info
375 */
376 */
376 var editPullRequest = function(repo_name, pull_request_id, title, description, renderer) {
377 var editPullRequest = function(repo_name, pull_request_id, title, description, renderer) {
377 var url = pyroutes.url(
378 var url = pyroutes.url(
378 'pullrequest_update',
379 'pullrequest_update',
379 {"repo_name": repo_name, "pull_request_id": pull_request_id});
380 {"repo_name": repo_name, "pull_request_id": pull_request_id});
380
381
381 var postData = {
382 var postData = {
382 'title': title,
383 'title': title,
383 'description': description,
384 'description': description,
384 'description_renderer': renderer,
385 'description_renderer': renderer,
385 'edit_pull_request': true,
386 'edit_pull_request': true,
386 'csrf_token': CSRF_TOKEN
387 'csrf_token': CSRF_TOKEN
387 };
388 };
388 var success = function(o) {
389 var success = function(o) {
389 window.location.reload();
390 window.location.reload();
390 };
391 };
391 ajaxPOST(url, postData, success);
392 ajaxPOST(url, postData, success);
392 };
393 };
393
394
394
395
395 /**
396 /**
396 * Reviewer autocomplete
397 * Reviewer autocomplete
397 */
398 */
398 var ReviewerAutoComplete = function(inputId) {
399 var ReviewerAutoComplete = function(inputId) {
399 $(inputId).autocomplete({
400 $(inputId).autocomplete({
400 serviceUrl: pyroutes.url('user_autocomplete_data'),
401 serviceUrl: pyroutes.url('user_autocomplete_data'),
401 minChars:2,
402 minChars:2,
402 maxHeight:400,
403 maxHeight:400,
403 deferRequestBy: 300, //miliseconds
404 deferRequestBy: 300, //miliseconds
404 showNoSuggestionNotice: true,
405 showNoSuggestionNotice: true,
405 tabDisabled: true,
406 tabDisabled: true,
406 autoSelectFirst: true,
407 autoSelectFirst: true,
407 params: { user_id: templateContext.rhodecode_user.user_id, user_groups:true, user_groups_expand:true, skip_default_user:true },
408 params: { user_id: templateContext.rhodecode_user.user_id, user_groups:true, user_groups_expand:true, skip_default_user:true },
408 formatResult: autocompleteFormatResult,
409 formatResult: autocompleteFormatResult,
409 lookupFilter: autocompleteFilterResult,
410 lookupFilter: autocompleteFilterResult,
410 onSelect: function(element, data) {
411 onSelect: function(element, data) {
411 var mandatory = false;
412 var mandatory = false;
412 var reasons = [_gettext('added manually by "{0}"').format(templateContext.rhodecode_user.username)];
413 var reasons = [_gettext('added manually by "{0}"').format(templateContext.rhodecode_user.username)];
413
414
414 // add whole user groups
415 // add whole user groups
415 if (data.value_type == 'user_group') {
416 if (data.value_type == 'user_group') {
416 reasons.push(_gettext('member of "{0}"').format(data.value_display));
417 reasons.push(_gettext('member of "{0}"').format(data.value_display));
417
418
418 $.each(data.members, function(index, member_data) {
419 $.each(data.members, function(index, member_data) {
419 var reviewer = member_data;
420 var reviewer = member_data;
420 reviewer['user_id'] = member_data['id'];
421 reviewer['user_id'] = member_data['id'];
421 reviewer['gravatar_link'] = member_data['icon_link'];
422 reviewer['gravatar_link'] = member_data['icon_link'];
422 reviewer['user_link'] = member_data['profile_link'];
423 reviewer['user_link'] = member_data['profile_link'];
423 reviewer['rules'] = [];
424 reviewer['rules'] = [];
424 reviewersController.addReviewMember(reviewer, reasons, mandatory);
425 reviewersController.addReviewMember(reviewer, reasons, mandatory);
425 })
426 })
426 }
427 }
427 // add single user
428 // add single user
428 else {
429 else {
429 var reviewer = data;
430 var reviewer = data;
430 reviewer['user_id'] = data['id'];
431 reviewer['user_id'] = data['id'];
431 reviewer['gravatar_link'] = data['icon_link'];
432 reviewer['gravatar_link'] = data['icon_link'];
432 reviewer['user_link'] = data['profile_link'];
433 reviewer['user_link'] = data['profile_link'];
433 reviewer['rules'] = [];
434 reviewer['rules'] = [];
434 reviewersController.addReviewMember(reviewer, reasons, mandatory);
435 reviewersController.addReviewMember(reviewer, reasons, mandatory);
435 }
436 }
436
437
437 $(inputId).val('');
438 $(inputId).val('');
438 }
439 }
439 });
440 });
440 };
441 };
441
442
442
443
443 VersionController = function () {
444 VersionController = function () {
444 var self = this;
445 var self = this;
445 this.$verSource = $('input[name=ver_source]');
446 this.$verSource = $('input[name=ver_source]');
446 this.$verTarget = $('input[name=ver_target]');
447 this.$verTarget = $('input[name=ver_target]');
447 this.$showVersionDiff = $('#show-version-diff');
448 this.$showVersionDiff = $('#show-version-diff');
448
449
449 this.adjustRadioSelectors = function (curNode) {
450 this.adjustRadioSelectors = function (curNode) {
450 var getVal = function (item) {
451 var getVal = function (item) {
451 if (item == 'latest') {
452 if (item == 'latest') {
452 return Number.MAX_SAFE_INTEGER
453 return Number.MAX_SAFE_INTEGER
453 }
454 }
454 else {
455 else {
455 return parseInt(item)
456 return parseInt(item)
456 }
457 }
457 };
458 };
458
459
459 var curVal = getVal($(curNode).val());
460 var curVal = getVal($(curNode).val());
460 var cleared = false;
461 var cleared = false;
461
462
462 $.each(self.$verSource, function (index, value) {
463 $.each(self.$verSource, function (index, value) {
463 var elVal = getVal($(value).val());
464 var elVal = getVal($(value).val());
464
465
465 if (elVal > curVal) {
466 if (elVal > curVal) {
466 if ($(value).is(':checked')) {
467 if ($(value).is(':checked')) {
467 cleared = true;
468 cleared = true;
468 }
469 }
469 $(value).attr('disabled', 'disabled');
470 $(value).attr('disabled', 'disabled');
470 $(value).removeAttr('checked');
471 $(value).removeAttr('checked');
471 $(value).css({'opacity': 0.1});
472 $(value).css({'opacity': 0.1});
472 }
473 }
473 else {
474 else {
474 $(value).css({'opacity': 1});
475 $(value).css({'opacity': 1});
475 $(value).removeAttr('disabled');
476 $(value).removeAttr('disabled');
476 }
477 }
477 });
478 });
478
479
479 if (cleared) {
480 if (cleared) {
480 // if we unchecked an active, set the next one to same loc.
481 // if we unchecked an active, set the next one to same loc.
481 $(this.$verSource).filter('[value={0}]'.format(
482 $(this.$verSource).filter('[value={0}]'.format(
482 curVal)).attr('checked', 'checked');
483 curVal)).attr('checked', 'checked');
483 }
484 }
484
485
485 self.setLockAction(false,
486 self.setLockAction(false,
486 $(curNode).data('verPos'),
487 $(curNode).data('verPos'),
487 $(this.$verSource).filter(':checked').data('verPos')
488 $(this.$verSource).filter(':checked').data('verPos')
488 );
489 );
489 };
490 };
490
491
491
492
492 this.attachVersionListener = function () {
493 this.attachVersionListener = function () {
493 self.$verTarget.change(function (e) {
494 self.$verTarget.change(function (e) {
494 self.adjustRadioSelectors(this)
495 self.adjustRadioSelectors(this)
495 });
496 });
496 self.$verSource.change(function (e) {
497 self.$verSource.change(function (e) {
497 self.adjustRadioSelectors(self.$verTarget.filter(':checked'))
498 self.adjustRadioSelectors(self.$verTarget.filter(':checked'))
498 });
499 });
499 };
500 };
500
501
501 this.init = function () {
502 this.init = function () {
502
503
503 var curNode = self.$verTarget.filter(':checked');
504 var curNode = self.$verTarget.filter(':checked');
504 self.adjustRadioSelectors(curNode);
505 self.adjustRadioSelectors(curNode);
505 self.setLockAction(true);
506 self.setLockAction(true);
506 self.attachVersionListener();
507 self.attachVersionListener();
507
508
508 };
509 };
509
510
510 this.setLockAction = function (state, selectedVersion, otherVersion) {
511 this.setLockAction = function (state, selectedVersion, otherVersion) {
511 var $showVersionDiff = this.$showVersionDiff;
512 var $showVersionDiff = this.$showVersionDiff;
512
513
513 if (state) {
514 if (state) {
514 $showVersionDiff.attr('disabled', 'disabled');
515 $showVersionDiff.attr('disabled', 'disabled');
515 $showVersionDiff.addClass('disabled');
516 $showVersionDiff.addClass('disabled');
516 $showVersionDiff.html($showVersionDiff.data('labelTextLocked'));
517 $showVersionDiff.html($showVersionDiff.data('labelTextLocked'));
517 }
518 }
518 else {
519 else {
519 $showVersionDiff.removeAttr('disabled');
520 $showVersionDiff.removeAttr('disabled');
520 $showVersionDiff.removeClass('disabled');
521 $showVersionDiff.removeClass('disabled');
521
522
522 if (selectedVersion == otherVersion) {
523 if (selectedVersion == otherVersion) {
523 $showVersionDiff.html($showVersionDiff.data('labelTextShow'));
524 $showVersionDiff.html($showVersionDiff.data('labelTextShow'));
524 } else {
525 } else {
525 $showVersionDiff.html($showVersionDiff.data('labelTextDiff'));
526 $showVersionDiff.html($showVersionDiff.data('labelTextDiff'));
526 }
527 }
527 }
528 }
528
529
529 };
530 };
530
531
531 this.showVersionDiff = function () {
532 this.showVersionDiff = function () {
532 var target = self.$verTarget.filter(':checked');
533 var target = self.$verTarget.filter(':checked');
533 var source = self.$verSource.filter(':checked');
534 var source = self.$verSource.filter(':checked');
534
535
535 if (target.val() && source.val()) {
536 if (target.val() && source.val()) {
536 var params = {
537 var params = {
537 'pull_request_id': templateContext.pull_request_data.pull_request_id,
538 'pull_request_id': templateContext.pull_request_data.pull_request_id,
538 'repo_name': templateContext.repo_name,
539 'repo_name': templateContext.repo_name,
539 'version': target.val(),
540 'version': target.val(),
540 'from_version': source.val()
541 'from_version': source.val()
541 };
542 };
542 window.location = pyroutes.url('pullrequest_show', params)
543 window.location = pyroutes.url('pullrequest_show', params)
543 }
544 }
544
545
545 return false;
546 return false;
546 };
547 };
547
548
548 this.toggleVersionView = function (elem) {
549 this.toggleVersionView = function (elem) {
549
550
550 if (this.$showVersionDiff.is(':visible')) {
551 if (this.$showVersionDiff.is(':visible')) {
551 $('.version-pr').hide();
552 $('.version-pr').hide();
552 this.$showVersionDiff.hide();
553 this.$showVersionDiff.hide();
553 $(elem).html($(elem).data('toggleOn'))
554 $(elem).html($(elem).data('toggleOn'))
554 } else {
555 } else {
555 $('.version-pr').show();
556 $('.version-pr').show();
556 this.$showVersionDiff.show();
557 this.$showVersionDiff.show();
557 $(elem).html($(elem).data('toggleOff'))
558 $(elem).html($(elem).data('toggleOff'))
558 }
559 }
559
560
560 return false
561 return false
561 };
562 };
562
563
563 this.toggleElement = function (elem, target) {
564 this.toggleElement = function (elem, target) {
564 var $elem = $(elem);
565 var $elem = $(elem);
565 var $target = $(target);
566 var $target = $(target);
566
567
567 if ($target.is(':visible')) {
568 if ($target.is(':visible')) {
568 $target.hide();
569 $target.hide();
569 $elem.html($elem.data('toggleOn'))
570 $elem.html($elem.data('toggleOn'))
570 } else {
571 } else {
571 $target.show();
572 $target.show();
572 $elem.html($elem.data('toggleOff'))
573 $elem.html($elem.data('toggleOff'))
573 }
574 }
574
575
575 return false
576 return false
576 }
577 }
577
578
578 };
579 };
579
580
580
581
581 UpdatePrController = function () {
582 UpdatePrController = function () {
582 var self = this;
583 var self = this;
583 this.$updateCommits = $('#update_commits');
584 this.$updateCommits = $('#update_commits');
584 this.$updateCommitsSwitcher = $('#update_commits_switcher');
585 this.$updateCommitsSwitcher = $('#update_commits_switcher');
585
586
586 this.lockUpdateButton = function (label) {
587 this.lockUpdateButton = function (label) {
587 self.$updateCommits.attr('disabled', 'disabled');
588 self.$updateCommits.attr('disabled', 'disabled');
588 self.$updateCommitsSwitcher.attr('disabled', 'disabled');
589 self.$updateCommitsSwitcher.attr('disabled', 'disabled');
589
590
590 self.$updateCommits.addClass('disabled');
591 self.$updateCommits.addClass('disabled');
591 self.$updateCommitsSwitcher.addClass('disabled');
592 self.$updateCommitsSwitcher.addClass('disabled');
592
593
593 self.$updateCommits.removeClass('btn-primary');
594 self.$updateCommits.removeClass('btn-primary');
594 self.$updateCommitsSwitcher.removeClass('btn-primary');
595 self.$updateCommitsSwitcher.removeClass('btn-primary');
595
596
596 self.$updateCommits.text(_gettext(label));
597 self.$updateCommits.text(_gettext(label));
597 };
598 };
598
599
599 this.isUpdateLocked = function () {
600 this.isUpdateLocked = function () {
600 return self.$updateCommits.attr('disabled') !== undefined;
601 return self.$updateCommits.attr('disabled') !== undefined;
601 };
602 };
602
603
603 this.updateCommits = function (curNode) {
604 this.updateCommits = function (curNode) {
604 if (self.isUpdateLocked()) {
605 if (self.isUpdateLocked()) {
605 return
606 return
606 }
607 }
607 self.lockUpdateButton(_gettext('Updating...'));
608 self.lockUpdateButton(_gettext('Updating...'));
608 updateCommits(
609 updateCommits(
609 templateContext.repo_name,
610 templateContext.repo_name,
610 templateContext.pull_request_data.pull_request_id);
611 templateContext.pull_request_data.pull_request_id);
611 };
612 };
612
613
613 this.forceUpdateCommits = function () {
614 this.forceUpdateCommits = function () {
614 if (self.isUpdateLocked()) {
615 if (self.isUpdateLocked()) {
615 return
616 return
616 }
617 }
617 self.lockUpdateButton(_gettext('Force updating...'));
618 self.lockUpdateButton(_gettext('Force updating...'));
618 var force = true;
619 var force = true;
619 updateCommits(
620 updateCommits(
620 templateContext.repo_name,
621 templateContext.repo_name,
621 templateContext.pull_request_data.pull_request_id, force);
622 templateContext.pull_request_data.pull_request_id, force);
622 };
623 };
623 }; No newline at end of file
624 };
General Comments 0
You need to be logged in to leave comments. Login now