##// END OF EJS Templates
pull-requests: wait for all dynamic checks before enabling opening a PR.
marcink -
r1276:7a9c1981 default
parent child Browse files
Show More
@@ -1,569 +1,593 b''
1 <%inherit file="/base/base.html"/>
1 <%inherit file="/base/base.html"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ${c.repo_name} ${_('New pull request')}
4 ${c.repo_name} ${_('New pull request')}
5 </%def>
5 </%def>
6
6
7 <%def name="breadcrumbs_links()">
7 <%def name="breadcrumbs_links()">
8 ${_('New pull request')}
8 ${_('New pull request')}
9 </%def>
9 </%def>
10
10
11 <%def name="menu_bar_nav()">
11 <%def name="menu_bar_nav()">
12 ${self.menu_items(active='repositories')}
12 ${self.menu_items(active='repositories')}
13 </%def>
13 </%def>
14
14
15 <%def name="menu_bar_subnav()">
15 <%def name="menu_bar_subnav()">
16 ${self.repo_menu(active='showpullrequest')}
16 ${self.repo_menu(active='showpullrequest')}
17 </%def>
17 </%def>
18
18
19 <%def name="main()">
19 <%def name="main()">
20 <div class="box">
20 <div class="box">
21 <div class="title">
21 <div class="title">
22 ${self.repo_page_title(c.rhodecode_db_repo)}
22 ${self.repo_page_title(c.rhodecode_db_repo)}
23 ${self.breadcrumbs()}
23 ${self.breadcrumbs()}
24 </div>
24 </div>
25
25
26 ${h.secure_form(url('pullrequest', repo_name=c.repo_name), method='post', id='pull_request_form')}
26 ${h.secure_form(url('pullrequest', repo_name=c.repo_name), method='post', id='pull_request_form')}
27 <div class="box pr-summary">
27 <div class="box pr-summary">
28
28
29 <div class="summary-details block-left">
29 <div class="summary-details block-left">
30
30
31 <div class="form">
31 <div class="form">
32 <!-- fields -->
32 <!-- fields -->
33
33
34 <div class="fields" >
34 <div class="fields" >
35
35
36 <div class="field">
36 <div class="field">
37 <div class="label">
37 <div class="label">
38 <label for="pullrequest_title">${_('Title')}:</label>
38 <label for="pullrequest_title">${_('Title')}:</label>
39 </div>
39 </div>
40 <div class="input">
40 <div class="input">
41 ${h.text('pullrequest_title', c.default_title, class_="medium autogenerated-title")}
41 ${h.text('pullrequest_title', c.default_title, class_="medium autogenerated-title")}
42 </div>
42 </div>
43 </div>
43 </div>
44
44
45 <div class="field">
45 <div class="field">
46 <div class="label label-textarea">
46 <div class="label label-textarea">
47 <label for="pullrequest_desc">${_('Description')}:</label>
47 <label for="pullrequest_desc">${_('Description')}:</label>
48 </div>
48 </div>
49 <div class="textarea text-area editor">
49 <div class="textarea text-area editor">
50 ${h.textarea('pullrequest_desc',size=30, )}
50 ${h.textarea('pullrequest_desc',size=30, )}
51 <span class="help-block">
51 <span class="help-block">
52 ${_('Write a short description on this pull request')}
52 ${_('Write a short description on this pull request')}
53 </span>
53 </span>
54 </div>
54 </div>
55 </div>
55 </div>
56
56
57 <div class="field">
57 <div class="field">
58 <div class="label label-textarea">
58 <div class="label label-textarea">
59 <label for="pullrequest_desc">${_('Commit flow')}:</label>
59 <label for="pullrequest_desc">${_('Commit flow')}:</label>
60 </div>
60 </div>
61
61
62 ## TODO: johbo: Abusing the "content" class here to get the
62 ## TODO: johbo: Abusing the "content" class here to get the
63 ## desired effect. Should be replaced by a proper solution.
63 ## desired effect. Should be replaced by a proper solution.
64
64
65 ##ORG
65 ##ORG
66 <div class="content">
66 <div class="content">
67 <strong>${_('Origin repository')}:</strong>
67 <strong>${_('Origin repository')}:</strong>
68 ${c.rhodecode_db_repo.description}
68 ${c.rhodecode_db_repo.description}
69 </div>
69 </div>
70 <div class="content">
70 <div class="content">
71 ${h.hidden('source_repo')}
71 ${h.hidden('source_repo')}
72 ${h.hidden('source_ref')}
72 ${h.hidden('source_ref')}
73 </div>
73 </div>
74
74
75 ##OTHER, most Probably the PARENT OF THIS FORK
75 ##OTHER, most Probably the PARENT OF THIS FORK
76 <div class="content">
76 <div class="content">
77 ## filled with JS
77 ## filled with JS
78 <div id="target_repo_desc"></div>
78 <div id="target_repo_desc"></div>
79 </div>
79 </div>
80
80
81 <div class="content">
81 <div class="content">
82 ${h.hidden('target_repo')}
82 ${h.hidden('target_repo')}
83 ${h.hidden('target_ref')}
83 ${h.hidden('target_ref')}
84 <span id="target_ref_loading" style="display: none">
84 <span id="target_ref_loading" style="display: none">
85 ${_('Loading refs...')}
85 ${_('Loading refs...')}
86 </span>
86 </span>
87 </div>
87 </div>
88 </div>
88 </div>
89
89
90 <div class="field">
90 <div class="field">
91 <div class="label label-textarea">
91 <div class="label label-textarea">
92 <label for="pullrequest_submit"></label>
92 <label for="pullrequest_submit"></label>
93 </div>
93 </div>
94 <div class="input">
94 <div class="input">
95 <div class="pr-submit-button">
95 <div class="pr-submit-button">
96 ${h.submit('save',_('Submit Pull Request'),class_="btn")}
96 ${h.submit('save',_('Submit Pull Request'),class_="btn")}
97 </div>
97 </div>
98 <div id="pr_open_message"></div>
98 <div id="pr_open_message"></div>
99 </div>
99 </div>
100 </div>
100 </div>
101
101
102 <div class="pr-spacing-container"></div>
102 <div class="pr-spacing-container"></div>
103 </div>
103 </div>
104 </div>
104 </div>
105 </div>
105 </div>
106 <div>
106 <div>
107 <div class="reviewers-title block-right">
107 <div class="reviewers-title block-right">
108 <div class="pr-details-title">
108 <div class="pr-details-title">
109 ${_('Pull request reviewers')}
109 ${_('Pull request reviewers')}
110 <span class="calculate-reviewers"> - ${_('loading...')}</span>
110 </div>
111 </div>
111 </div>
112 </div>
112 <div id="reviewers" class="block-right pr-details-content reviewers">
113 <div id="reviewers" class="block-right pr-details-content reviewers">
113 ## members goes here, filled via JS based on initial selection !
114 ## members goes here, filled via JS based on initial selection !
114 <input type="hidden" name="__start__" value="review_members:sequence">
115 <input type="hidden" name="__start__" value="review_members:sequence">
115 <ul id="review_members" class="group_members"></ul>
116 <ul id="review_members" class="group_members"></ul>
116 <input type="hidden" name="__end__" value="review_members:sequence">
117 <input type="hidden" name="__end__" value="review_members:sequence">
117 <div id="add_reviewer_input" class='ac'>
118 <div id="add_reviewer_input" class='ac'>
118 <div class="reviewer_ac">
119 <div class="reviewer_ac">
119 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer'))}
120 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer'))}
120 <div id="reviewers_container"></div>
121 <div id="reviewers_container"></div>
121 </div>
122 </div>
122 </div>
123 </div>
123 </div>
124 </div>
124 </div>
125 </div>
125 </div>
126 </div>
126 <div class="box">
127 <div class="box">
127 <div>
128 <div>
128 ## overview pulled by ajax
129 ## overview pulled by ajax
129 <div id="pull_request_overview"></div>
130 <div id="pull_request_overview"></div>
130 </div>
131 </div>
131 </div>
132 </div>
132 ${h.end_form()}
133 ${h.end_form()}
133 </div>
134 </div>
134
135
135 <script type="text/javascript">
136 <script type="text/javascript">
136 $(function(){
137 $(function(){
137 var defaultSourceRepo = '${c.default_repo_data['source_repo_name']}';
138 var defaultSourceRepo = '${c.default_repo_data['source_repo_name']}';
138 var defaultSourceRepoData = ${c.default_repo_data['source_refs_json']|n};
139 var defaultSourceRepoData = ${c.default_repo_data['source_refs_json']|n};
139 var defaultTargetRepo = '${c.default_repo_data['target_repo_name']}';
140 var defaultTargetRepo = '${c.default_repo_data['target_repo_name']}';
140 var defaultTargetRepoData = ${c.default_repo_data['target_refs_json']|n};
141 var defaultTargetRepoData = ${c.default_repo_data['target_refs_json']|n};
141 var targetRepoName = '${c.repo_name}';
142 var targetRepoName = '${c.repo_name}';
142
143
143 var $pullRequestForm = $('#pull_request_form');
144 var $pullRequestForm = $('#pull_request_form');
144 var $sourceRepo = $('#source_repo', $pullRequestForm);
145 var $sourceRepo = $('#source_repo', $pullRequestForm);
145 var $targetRepo = $('#target_repo', $pullRequestForm);
146 var $targetRepo = $('#target_repo', $pullRequestForm);
146 var $sourceRef = $('#source_ref', $pullRequestForm);
147 var $sourceRef = $('#source_ref', $pullRequestForm);
147 var $targetRef = $('#target_ref', $pullRequestForm);
148 var $targetRef = $('#target_ref', $pullRequestForm);
148
149
149 var calculateContainerWidth = function() {
150 var calculateContainerWidth = function() {
150 var maxWidth = 0;
151 var maxWidth = 0;
151 var repoSelect2Containers = ['#source_repo', '#target_repo'];
152 var repoSelect2Containers = ['#source_repo', '#target_repo'];
152 $.each(repoSelect2Containers, function(idx, value) {
153 $.each(repoSelect2Containers, function(idx, value) {
153 $(value).select2('container').width('auto');
154 $(value).select2('container').width('auto');
154 var curWidth = $(value).select2('container').width();
155 var curWidth = $(value).select2('container').width();
155 if (maxWidth <= curWidth) {
156 if (maxWidth <= curWidth) {
156 maxWidth = curWidth;
157 maxWidth = curWidth;
157 }
158 }
158 $.each(repoSelect2Containers, function(idx, value) {
159 $.each(repoSelect2Containers, function(idx, value) {
159 $(value).select2('container').width(maxWidth + 10);
160 $(value).select2('container').width(maxWidth + 10);
160 });
161 });
161 });
162 });
162 };
163 };
163
164
164 var initRefSelection = function(selectedRef) {
165 var initRefSelection = function(selectedRef) {
165 return function(element, callback) {
166 return function(element, callback) {
166 // translate our select2 id into a text, it's a mapping to show
167 // translate our select2 id into a text, it's a mapping to show
167 // simple label when selecting by internal ID.
168 // simple label when selecting by internal ID.
168 var id, refData;
169 var id, refData;
169 if (selectedRef === undefined) {
170 if (selectedRef === undefined) {
170 id = element.val();
171 id = element.val();
171 refData = element.val().split(':');
172 refData = element.val().split(':');
172 } else {
173 } else {
173 id = selectedRef;
174 id = selectedRef;
174 refData = selectedRef.split(':');
175 refData = selectedRef.split(':');
175 }
176 }
176
177
177 var text = refData[1];
178 var text = refData[1];
178 if (refData[0] === 'rev') {
179 if (refData[0] === 'rev') {
179 text = text.substring(0, 12);
180 text = text.substring(0, 12);
180 }
181 }
181
182
182 var data = {id: id, text: text};
183 var data = {id: id, text: text};
183
184
184 callback(data);
185 callback(data);
185 };
186 };
186 };
187 };
187
188
188 var formatRefSelection = function(item) {
189 var formatRefSelection = function(item) {
189 var prefix = '';
190 var prefix = '';
190 var refData = item.id.split(':');
191 var refData = item.id.split(':');
191 if (refData[0] === 'branch') {
192 if (refData[0] === 'branch') {
192 prefix = '<i class="icon-branch"></i>';
193 prefix = '<i class="icon-branch"></i>';
193 }
194 }
194 else if (refData[0] === 'book') {
195 else if (refData[0] === 'book') {
195 prefix = '<i class="icon-bookmark"></i>';
196 prefix = '<i class="icon-bookmark"></i>';
196 }
197 }
197 else if (refData[0] === 'tag') {
198 else if (refData[0] === 'tag') {
198 prefix = '<i class="icon-tag"></i>';
199 prefix = '<i class="icon-tag"></i>';
199 }
200 }
200
201
201 var originalOption = item.element;
202 var originalOption = item.element;
202 return prefix + item.text;
203 return prefix + item.text;
203 };
204 };
204
205
205 // custom code mirror
206 // custom code mirror
206 var codeMirrorInstance = initPullRequestsCodeMirror('#pullrequest_desc');
207 var codeMirrorInstance = initPullRequestsCodeMirror('#pullrequest_desc');
207
208
208 var queryTargetRepo = function(self, query) {
209 var queryTargetRepo = function(self, query) {
209 // cache ALL results if query is empty
210 // cache ALL results if query is empty
210 var cacheKey = query.term || '__';
211 var cacheKey = query.term || '__';
211 var cachedData = self.cachedDataSource[cacheKey];
212 var cachedData = self.cachedDataSource[cacheKey];
212
213
213 if (cachedData) {
214 if (cachedData) {
214 query.callback({results: cachedData.results});
215 query.callback({results: cachedData.results});
215 } else {
216 } else {
216 $.ajax({
217 $.ajax({
217 url: pyroutes.url('pullrequest_repo_destinations', {'repo_name': targetRepoName}),
218 url: pyroutes.url('pullrequest_repo_destinations', {'repo_name': targetRepoName}),
218 data: {query: query.term},
219 data: {query: query.term},
219 dataType: 'json',
220 dataType: 'json',
220 type: 'GET',
221 type: 'GET',
221 success: function(data) {
222 success: function(data) {
222 self.cachedDataSource[cacheKey] = data;
223 self.cachedDataSource[cacheKey] = data;
223 query.callback({results: data.results});
224 query.callback({results: data.results});
224 },
225 },
225 error: function(data, textStatus, errorThrown) {
226 error: function(data, textStatus, errorThrown) {
226 alert(
227 alert(
227 "Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
228 "Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
228 }
229 }
229 });
230 });
230 }
231 }
231 };
232 };
232
233
233 var queryTargetRefs = function(initialData, query) {
234 var queryTargetRefs = function(initialData, query) {
234 var data = {results: []};
235 var data = {results: []};
235 // filter initialData
236 // filter initialData
236 $.each(initialData, function() {
237 $.each(initialData, function() {
237 var section = this.text;
238 var section = this.text;
238 var children = [];
239 var children = [];
239 $.each(this.children, function() {
240 $.each(this.children, function() {
240 if (query.term.length === 0 ||
241 if (query.term.length === 0 ||
241 this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ) {
242 this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ) {
242 children.push({'id': this.id, 'text': this.text})
243 children.push({'id': this.id, 'text': this.text})
243 }
244 }
244 });
245 });
245 data.results.push({'text': section, 'children': children})
246 data.results.push({'text': section, 'children': children})
246 });
247 });
247 query.callback({results: data.results});
248 query.callback({results: data.results});
248 };
249 };
249
250
250 var prButtonLock = function(lockEnabled, msg) {
251
252 var prButtonLockChecks = {
253 'compare': false,
254 'reviewers': false
255 };
256
257 var prButtonLock = function(lockEnabled, msg, scope) {
258 scope = scope || 'all';
259 if (scope == 'all'){
260 prButtonLockChecks['compare'] = !lockEnabled;
261 prButtonLockChecks['reviewers'] = !lockEnabled;
262 } else if (scope == 'compare') {
263 prButtonLockChecks['compare'] = !lockEnabled;
264 } else if (scope == 'reviewers'){
265 prButtonLockChecks['reviewers'] = !lockEnabled;
266 }
267 var checksMeet = prButtonLockChecks.compare && prButtonLockChecks.reviewers;
251 if (lockEnabled) {
268 if (lockEnabled) {
252 $('#save').attr('disabled', 'disabled');
269 $('#save').attr('disabled', 'disabled');
253 }
270 }
254 else {
271 else if (checksMeet) {
255 $('#save').removeAttr('disabled');
272 $('#save').removeAttr('disabled');
256 }
273 }
257
274
275 if (msg) {
258 $('#pr_open_message').html(msg);
276 $('#pr_open_message').html(msg);
259
277 }
260 };
278 };
261
279
262 var loadRepoRefDiffPreview = function() {
280 var loadRepoRefDiffPreview = function() {
263 var sourceRepo = $sourceRepo.eq(0).val();
281 var sourceRepo = $sourceRepo.eq(0).val();
264 var sourceRef = $sourceRef.eq(0).val().split(':');
282 var sourceRef = $sourceRef.eq(0).val().split(':');
265
283
266 var targetRepo = $targetRepo.eq(0).val();
284 var targetRepo = $targetRepo.eq(0).val();
267 var targetRef = $targetRef.eq(0).val().split(':');
285 var targetRef = $targetRef.eq(0).val().split(':');
268
286
269 var url_data = {
287 var url_data = {
270 'repo_name': targetRepo,
288 'repo_name': targetRepo,
271 'target_repo': sourceRepo,
289 'target_repo': sourceRepo,
272 'source_ref': targetRef[2],
290 'source_ref': targetRef[2],
273 'source_ref_type': 'rev',
291 'source_ref_type': 'rev',
274 'target_ref': sourceRef[2],
292 'target_ref': sourceRef[2],
275 'target_ref_type': 'rev',
293 'target_ref_type': 'rev',
276 'merge': true,
294 'merge': true,
277 '_': Date.now() // bypass browser caching
295 '_': Date.now() // bypass browser caching
278 }; // gather the source/target ref and repo here
296 }; // gather the source/target ref and repo here
279
297
280 if (sourceRef.length !== 3 || targetRef.length !== 3) {
298 if (sourceRef.length !== 3 || targetRef.length !== 3) {
281 prButtonLock(true, "${_('Please select origin and destination')}");
299 prButtonLock(true, "${_('Please select origin and destination')}");
282 return;
300 return;
283 }
301 }
284 var url = pyroutes.url('compare_url', url_data);
302 var url = pyroutes.url('compare_url', url_data);
285
303
286 // lock PR button, so we cannot send PR before it's calculated
304 // lock PR button, so we cannot send PR before it's calculated
287 prButtonLock(true, "${_('Loading compare ...')}");
305 prButtonLock(true, "${_('Loading compare ...')}", 'compare');
288
306
289 if (loadRepoRefDiffPreview._currentRequest) {
307 if (loadRepoRefDiffPreview._currentRequest) {
290 loadRepoRefDiffPreview._currentRequest.abort();
308 loadRepoRefDiffPreview._currentRequest.abort();
291 }
309 }
292
310
293 loadRepoRefDiffPreview._currentRequest = $.get(url)
311 loadRepoRefDiffPreview._currentRequest = $.get(url)
294 .error(function(data, textStatus, errorThrown) {
312 .error(function(data, textStatus, errorThrown) {
295 alert(
313 alert(
296 "Error while processing request.\nError code {0} ({1}).".format(
314 "Error while processing request.\nError code {0} ({1}).".format(
297 data.status, data.statusText));
315 data.status, data.statusText));
298 })
316 })
299 .done(function(data) {
317 .done(function(data) {
300 loadRepoRefDiffPreview._currentRequest = null;
318 loadRepoRefDiffPreview._currentRequest = null;
301 $('#pull_request_overview').html(data);
319 $('#pull_request_overview').html(data);
302 var commitElements = $(data).find('tr[commit_id]');
320 var commitElements = $(data).find('tr[commit_id]');
303
321
304 var prTitleAndDesc = getTitleAndDescription(sourceRef[1],
322 var prTitleAndDesc = getTitleAndDescription(sourceRef[1],
305 commitElements, 5);
323 commitElements, 5);
306
324
307 var title = prTitleAndDesc[0];
325 var title = prTitleAndDesc[0];
308 var proposedDescription = prTitleAndDesc[1];
326 var proposedDescription = prTitleAndDesc[1];
309
327
310 var useGeneratedTitle = (
328 var useGeneratedTitle = (
311 $('#pullrequest_title').hasClass('autogenerated-title') ||
329 $('#pullrequest_title').hasClass('autogenerated-title') ||
312 $('#pullrequest_title').val() === "");
330 $('#pullrequest_title').val() === "");
313
331
314 if (title && useGeneratedTitle) {
332 if (title && useGeneratedTitle) {
315 // use generated title if we haven't specified our own
333 // use generated title if we haven't specified our own
316 $('#pullrequest_title').val(title);
334 $('#pullrequest_title').val(title);
317 $('#pullrequest_title').addClass('autogenerated-title');
335 $('#pullrequest_title').addClass('autogenerated-title');
318
336
319 }
337 }
320
338
321 var useGeneratedDescription = (
339 var useGeneratedDescription = (
322 !codeMirrorInstance._userDefinedDesc ||
340 !codeMirrorInstance._userDefinedDesc ||
323 codeMirrorInstance.getValue() === "");
341 codeMirrorInstance.getValue() === "");
324
342
325 if (proposedDescription && useGeneratedDescription) {
343 if (proposedDescription && useGeneratedDescription) {
326 // set proposed content, if we haven't defined our own,
344 // set proposed content, if we haven't defined our own,
327 // or we don't have description written
345 // or we don't have description written
328 codeMirrorInstance._userDefinedDesc = false; // reset state
346 codeMirrorInstance._userDefinedDesc = false; // reset state
329 codeMirrorInstance.setValue(proposedDescription);
347 codeMirrorInstance.setValue(proposedDescription);
330 }
348 }
331
349
332 var msg = '';
350 var msg = '';
333 if (commitElements.length === 1) {
351 if (commitElements.length === 1) {
334 msg = "${ungettext('This pull request will consist of __COMMITS__ commit.', 'This pull request will consist of __COMMITS__ commits.', 1)}";
352 msg = "${ungettext('This pull request will consist of __COMMITS__ commit.', 'This pull request will consist of __COMMITS__ commits.', 1)}";
335 } else {
353 } else {
336 msg = "${ungettext('This pull request will consist of __COMMITS__ commit.', 'This pull request will consist of __COMMITS__ commits.', 2)}";
354 msg = "${ungettext('This pull request will consist of __COMMITS__ commit.', 'This pull request will consist of __COMMITS__ commits.', 2)}";
337 }
355 }
338
356
339 msg += ' <a id="pull_request_overview_url" href="{0}" target="_blank">${_('Show detailed compare.')}</a>'.format(url);
357 msg += ' <a id="pull_request_overview_url" href="{0}" target="_blank">${_('Show detailed compare.')}</a>'.format(url);
340
358
341 if (commitElements.length) {
359 if (commitElements.length) {
342 var commitsLink = '<a href="#pull_request_overview"><strong>{0}</strong></a>'.format(commitElements.length);
360 var commitsLink = '<a href="#pull_request_overview"><strong>{0}</strong></a>'.format(commitElements.length);
343 prButtonLock(false, msg.replace('__COMMITS__', commitsLink));
361 prButtonLock(false, msg.replace('__COMMITS__', commitsLink), 'compare');
344 }
362 }
345 else {
363 else {
346 prButtonLock(true, "${_('There are no commits to merge.')}");
364 prButtonLock(true, "${_('There are no commits to merge.')}", 'compare');
347 }
365 }
348
366
349
367
350 });
368 });
351 };
369 };
352
370
353 /**
371 /**
354 Generate Title and Description for a PullRequest.
372 Generate Title and Description for a PullRequest.
355 In case of 1 commits, the title and description is that one commit
373 In case of 1 commits, the title and description is that one commit
356 in case of multiple commits, we iterate on them with max N number of commits,
374 in case of multiple commits, we iterate on them with max N number of commits,
357 and build description in a form
375 and build description in a form
358 - commitN
376 - commitN
359 - commitN+1
377 - commitN+1
360 ...
378 ...
361
379
362 Title is then constructed from branch names, or other references,
380 Title is then constructed from branch names, or other references,
363 replacing '-' and '_' into spaces
381 replacing '-' and '_' into spaces
364
382
365 * @param sourceRef
383 * @param sourceRef
366 * @param elements
384 * @param elements
367 * @param limit
385 * @param limit
368 * @returns {*[]}
386 * @returns {*[]}
369 */
387 */
370 var getTitleAndDescription = function(sourceRef, elements, limit) {
388 var getTitleAndDescription = function(sourceRef, elements, limit) {
371 var title = '';
389 var title = '';
372 var desc = '';
390 var desc = '';
373
391
374 $.each($(elements).get().reverse().slice(0, limit), function(idx, value) {
392 $.each($(elements).get().reverse().slice(0, limit), function(idx, value) {
375 var rawMessage = $(value).find('td.td-description .message').data('messageRaw');
393 var rawMessage = $(value).find('td.td-description .message').data('messageRaw');
376 desc += '- ' + rawMessage.split('\n')[0].replace(/\n+$/, "") + '\n';
394 desc += '- ' + rawMessage.split('\n')[0].replace(/\n+$/, "") + '\n';
377 });
395 });
378 // only 1 commit, use commit message as title
396 // only 1 commit, use commit message as title
379 if (elements.length == 1) {
397 if (elements.length == 1) {
380 title = $(elements[0]).find('td.td-description .message').data('messageRaw').split('\n')[0];
398 title = $(elements[0]).find('td.td-description .message').data('messageRaw').split('\n')[0];
381 }
399 }
382 else {
400 else {
383 // use reference name
401 // use reference name
384 title = sourceRef.replace(/-/g, ' ').replace(/_/g, ' ').capitalizeFirstLetter();
402 title = sourceRef.replace(/-/g, ' ').replace(/_/g, ' ').capitalizeFirstLetter();
385 }
403 }
386
404
387 return [title, desc]
405 return [title, desc]
388 };
406 };
389
407
390 var Select2Box = function(element, overrides) {
408 var Select2Box = function(element, overrides) {
391 var globalDefaults = {
409 var globalDefaults = {
392 dropdownAutoWidth: true,
410 dropdownAutoWidth: true,
393 containerCssClass: "drop-menu",
411 containerCssClass: "drop-menu",
394 dropdownCssClass: "drop-menu-dropdown",
412 dropdownCssClass: "drop-menu-dropdown"
395 };
413 };
396
414
397 var initSelect2 = function(defaultOptions) {
415 var initSelect2 = function(defaultOptions) {
398 var options = jQuery.extend(globalDefaults, defaultOptions, overrides);
416 var options = jQuery.extend(globalDefaults, defaultOptions, overrides);
399 element.select2(options);
417 element.select2(options);
400 };
418 };
401
419
402 return {
420 return {
403 initRef: function() {
421 initRef: function() {
404 var defaultOptions = {
422 var defaultOptions = {
405 minimumResultsForSearch: 5,
423 minimumResultsForSearch: 5,
406 formatSelection: formatRefSelection
424 formatSelection: formatRefSelection
407 };
425 };
408
426
409 initSelect2(defaultOptions);
427 initSelect2(defaultOptions);
410 },
428 },
411
429
412 initRepo: function(defaultValue, readOnly) {
430 initRepo: function(defaultValue, readOnly) {
413 var defaultOptions = {
431 var defaultOptions = {
414 initSelection : function (element, callback) {
432 initSelection : function (element, callback) {
415 var data = {id: defaultValue, text: defaultValue};
433 var data = {id: defaultValue, text: defaultValue};
416 callback(data);
434 callback(data);
417 }
435 }
418 };
436 };
419
437
420 initSelect2(defaultOptions);
438 initSelect2(defaultOptions);
421
439
422 element.select2('val', defaultSourceRepo);
440 element.select2('val', defaultSourceRepo);
423 if (readOnly === true) {
441 if (readOnly === true) {
424 element.select2('readonly', true);
442 element.select2('readonly', true);
425 };
443 }
426 }
444 }
427 };
445 };
428 };
446 };
429
447
430 var initTargetRefs = function(refsData, selectedRef){
448 var initTargetRefs = function(refsData, selectedRef){
431 Select2Box($targetRef, {
449 Select2Box($targetRef, {
432 query: function(query) {
450 query: function(query) {
433 queryTargetRefs(refsData, query);
451 queryTargetRefs(refsData, query);
434 },
452 },
435 initSelection : initRefSelection(selectedRef)
453 initSelection : initRefSelection(selectedRef)
436 }).initRef();
454 }).initRef();
437
455
438 if (!(selectedRef === undefined)) {
456 if (!(selectedRef === undefined)) {
439 $targetRef.select2('val', selectedRef);
457 $targetRef.select2('val', selectedRef);
440 }
458 }
441 };
459 };
442
460
443 var targetRepoChanged = function(repoData) {
461 var targetRepoChanged = function(repoData) {
444 // generate new DESC of target repo displayed next to select
462 // generate new DESC of target repo displayed next to select
445 $('#target_repo_desc').html(
463 $('#target_repo_desc').html(
446 "<strong>${_('Destination repository')}</strong>: {0}".format(repoData['description'])
464 "<strong>${_('Destination repository')}</strong>: {0}".format(repoData['description'])
447 );
465 );
448
466
449 // generate dynamic select2 for refs.
467 // generate dynamic select2 for refs.
450 initTargetRefs(repoData['refs']['select2_refs'],
468 initTargetRefs(repoData['refs']['select2_refs'],
451 repoData['refs']['selected_ref']);
469 repoData['refs']['selected_ref']);
452
470
453 };
471 };
454
472
455 var sourceRefSelect2 = Select2Box(
473 var sourceRefSelect2 = Select2Box(
456 $sourceRef, {
474 $sourceRef, {
457 placeholder: "${_('Select commit reference')}",
475 placeholder: "${_('Select commit reference')}",
458 query: function(query) {
476 query: function(query) {
459 var initialData = defaultSourceRepoData['refs']['select2_refs'];
477 var initialData = defaultSourceRepoData['refs']['select2_refs'];
460 queryTargetRefs(initialData, query)
478 queryTargetRefs(initialData, query)
461 },
479 },
462 initSelection: initRefSelection()
480 initSelection: initRefSelection()
463 }
481 }
464 );
482 );
465
483
466 var sourceRepoSelect2 = Select2Box($sourceRepo, {
484 var sourceRepoSelect2 = Select2Box($sourceRepo, {
467 query: function(query) {}
485 query: function(query) {}
468 });
486 });
469
487
470 var targetRepoSelect2 = Select2Box($targetRepo, {
488 var targetRepoSelect2 = Select2Box($targetRepo, {
471 cachedDataSource: {},
489 cachedDataSource: {},
472 query: $.debounce(250, function(query) {
490 query: $.debounce(250, function(query) {
473 queryTargetRepo(this, query);
491 queryTargetRepo(this, query);
474 }),
492 }),
475 formatResult: formatResult
493 formatResult: formatResult
476 });
494 });
477
495
478 sourceRefSelect2.initRef();
496 sourceRefSelect2.initRef();
479
497
480 sourceRepoSelect2.initRepo(defaultSourceRepo, true);
498 sourceRepoSelect2.initRepo(defaultSourceRepo, true);
481
499
482 targetRepoSelect2.initRepo(defaultTargetRepo, false);
500 targetRepoSelect2.initRepo(defaultTargetRepo, false);
483
501
484 $sourceRef.on('change', function(e){
502 $sourceRef.on('change', function(e){
485 loadRepoRefDiffPreview();
503 loadRepoRefDiffPreview();
486 loadDefaultReviewers();
504 loadDefaultReviewers();
487 });
505 });
488
506
489 $targetRef.on('change', function(e){
507 $targetRef.on('change', function(e){
490 loadRepoRefDiffPreview();
508 loadRepoRefDiffPreview();
491 loadDefaultReviewers();
509 loadDefaultReviewers();
492 });
510 });
493
511
494 $targetRepo.on('change', function(e){
512 $targetRepo.on('change', function(e){
495 var repoName = $(this).val();
513 var repoName = $(this).val();
496 calculateContainerWidth();
514 calculateContainerWidth();
497 $targetRef.select2('destroy');
515 $targetRef.select2('destroy');
498 $('#target_ref_loading').show();
516 $('#target_ref_loading').show();
499
517
500 $.ajax({
518 $.ajax({
501 url: pyroutes.url('pullrequest_repo_refs',
519 url: pyroutes.url('pullrequest_repo_refs',
502 {'repo_name': targetRepoName, 'target_repo_name':repoName}),
520 {'repo_name': targetRepoName, 'target_repo_name':repoName}),
503 data: {},
521 data: {},
504 dataType: 'json',
522 dataType: 'json',
505 type: 'GET',
523 type: 'GET',
506 success: function(data) {
524 success: function(data) {
507 $('#target_ref_loading').hide();
525 $('#target_ref_loading').hide();
508 targetRepoChanged(data);
526 targetRepoChanged(data);
509 loadRepoRefDiffPreview();
527 loadRepoRefDiffPreview();
510 },
528 },
511 error: function(data, textStatus, errorThrown) {
529 error: function(data, textStatus, errorThrown) {
512 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
530 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
513 }
531 }
514 })
532 })
515
533
516 });
534 });
517
535
518 var loadDefaultReviewers = function() {
536 var loadDefaultReviewers = function() {
519 if (loadDefaultReviewers._currentRequest) {
537 if (loadDefaultReviewers._currentRequest) {
520 loadDefaultReviewers._currentRequest.abort();
538 loadDefaultReviewers._currentRequest.abort();
521 }
539 }
540 $('.calculate-reviewers').show();
541 prButtonLock(true, null, 'reviewers');
542
522 var url = pyroutes.url('repo_default_reviewers_data', {'repo_name': targetRepoName});
543 var url = pyroutes.url('repo_default_reviewers_data', {'repo_name': targetRepoName});
523
544
524 var sourceRepo = $sourceRepo.eq(0).val();
545 var sourceRepo = $sourceRepo.eq(0).val();
525 var sourceRef = $sourceRef.eq(0).val().split(':');
546 var sourceRef = $sourceRef.eq(0).val().split(':');
526 var targetRepo = $targetRepo.eq(0).val();
547 var targetRepo = $targetRepo.eq(0).val();
527 var targetRef = $targetRef.eq(0).val().split(':');
548 var targetRef = $targetRef.eq(0).val().split(':');
528 url += '?source_repo=' + sourceRepo;
549 url += '?source_repo=' + sourceRepo;
529 url += '&source_ref=' + sourceRef[2];
550 url += '&source_ref=' + sourceRef[2];
530 url += '&target_repo=' + targetRepo;
551 url += '&target_repo=' + targetRepo;
531 url += '&target_ref=' + targetRef[2];
552 url += '&target_ref=' + targetRef[2];
532
553
533 loadDefaultReviewers._currentRequest = $.get(url)
554 loadDefaultReviewers._currentRequest = $.get(url)
534 .done(function(data) {
555 .done(function(data) {
535 loadDefaultReviewers._currentRequest = null;
556 loadDefaultReviewers._currentRequest = null;
536
557
537 // reset && add the reviewer based on selected repo
558 // reset && add the reviewer based on selected repo
538 $('#review_members').html('');
559 $('#review_members').html('');
539 for (var i = 0; i < data.reviewers.length; i++) {
560 for (var i = 0; i < data.reviewers.length; i++) {
540 var reviewer = data.reviewers[i];
561 var reviewer = data.reviewers[i];
541 addReviewMember(
562 addReviewMember(
542 reviewer.user_id, reviewer.firstname,
563 reviewer.user_id, reviewer.firstname,
543 reviewer.lastname, reviewer.username,
564 reviewer.lastname, reviewer.username,
544 reviewer.gravatar_link, reviewer.reasons);
565 reviewer.gravatar_link, reviewer.reasons);
545 }
566 }
567 $('.calculate-reviewers').hide();
568 prButtonLock(false, null, 'reviewers');
546 });
569 });
547 };
570 };
548 prButtonLock(true, "${_('Please select origin and destination')}");
571
572 prButtonLock(true, "${_('Please select origin and destination')}", 'all');
549
573
550 // auto-load on init, the target refs select2
574 // auto-load on init, the target refs select2
551 calculateContainerWidth();
575 calculateContainerWidth();
552 targetRepoChanged(defaultTargetRepoData);
576 targetRepoChanged(defaultTargetRepoData);
553
577
554 $('#pullrequest_title').on('keyup', function(e){
578 $('#pullrequest_title').on('keyup', function(e){
555 $(this).removeClass('autogenerated-title');
579 $(this).removeClass('autogenerated-title');
556 });
580 });
557
581
558 %if c.default_source_ref:
582 % if c.default_source_ref:
559 // in case we have a pre-selected value, use it now
583 // in case we have a pre-selected value, use it now
560 $sourceRef.select2('val', '${c.default_source_ref}');
584 $sourceRef.select2('val', '${c.default_source_ref}');
561 loadRepoRefDiffPreview();
585 loadRepoRefDiffPreview();
562 loadDefaultReviewers();
586 loadDefaultReviewers();
563 %endif
587 % endif
564
588
565 ReviewerAutoComplete('user');
589 ReviewerAutoComplete('user');
566 });
590 });
567 </script>
591 </script>
568
592
569 </%def>
593 </%def>
General Comments 0
You need to be logged in to leave comments. Login now