##// END OF EJS Templates
Added option to close pull requests, in future that will be close & merge
marcink -
r2608:58c52933 beta
parent child Browse files
Show More
@@ -169,7 +169,7 b' class PullrequestsController(BaseRepoCon'
169 return redirect(url('pullrequest_show', repo_name=other_repo,
169 return redirect(url('pullrequest_show', repo_name=other_repo,
170 pull_request_id=pull_request.pull_request_id))
170 pull_request_id=pull_request.pull_request_id))
171
171
172 def _load_compare_data(self, pull_request):
172 def _load_compare_data(self, pull_request, enable_comments=True):
173 """
173 """
174 Load context data needed for generating compare diff
174 Load context data needed for generating compare diff
175
175
@@ -211,7 +211,7 b' class PullrequestsController(BaseRepoCon'
211 for f in _parsed:
211 for f in _parsed:
212 fid = h.FID('', f['filename'])
212 fid = h.FID('', f['filename'])
213 c.files.append([fid, f['operation'], f['filename'], f['stats']])
213 c.files.append([fid, f['operation'], f['filename'], f['stats']])
214 diff = diff_processor.as_html(enable_comments=True,
214 diff = diff_processor.as_html(enable_comments=enable_comments,
215 diff_lines=[f])
215 diff_lines=[f])
216 c.changes[fid] = [f['operation'], f['filename'], diff]
216 c.changes[fid] = [f['operation'], f['filename'], diff]
217
217
@@ -246,7 +246,8 b' class PullrequestsController(BaseRepoCon'
246 raise HTTPNotFound
246 raise HTTPNotFound
247
247
248 # load compare data into template context
248 # load compare data into template context
249 self._load_compare_data(c.pull_request)
249 enable_comments = not c.pull_request.is_closed()
250 self._load_compare_data(c.pull_request, enable_comments=enable_comments)
250
251
251 # inline comments
252 # inline comments
252 c.inline_cnt = 0
253 c.inline_cnt = 0
@@ -271,6 +272,9 b' class PullrequestsController(BaseRepoCon'
271
272
272 @jsonify
273 @jsonify
273 def comment(self, repo_name, pull_request_id):
274 def comment(self, repo_name, pull_request_id):
275 pull_request = PullRequest.get_or_404(pull_request_id)
276 if pull_request.is_closed():
277 raise HTTPForbidden()
274
278
275 status = request.POST.get('changeset_status')
279 status = request.POST.get('changeset_status')
276 change_status = request.POST.get('change_changeset_status')
280 change_status = request.POST.get('change_changeset_status')
@@ -299,6 +303,12 b' class PullrequestsController(BaseRepoCon'
299 'user_commented_pull_request:%s' % pull_request_id,
303 'user_commented_pull_request:%s' % pull_request_id,
300 c.rhodecode_db_repo, self.ip_addr, self.sa)
304 c.rhodecode_db_repo, self.ip_addr, self.sa)
301
305
306 if request.POST.get('save_close'):
307 PullRequestModel().close_pull_request(pull_request_id)
308 action_logger(self.rhodecode_user,
309 'user_closed_pull_request:%s' % pull_request_id,
310 c.rhodecode_db_repo, self.ip_addr, self.sa)
311
302 Session().commit()
312 Session().commit()
303
313
304 if not request.environ.get('HTTP_X_PARTIAL_XHR'):
314 if not request.environ.get('HTTP_X_PARTIAL_XHR'):
@@ -319,6 +329,10 b' class PullrequestsController(BaseRepoCon'
319 @jsonify
329 @jsonify
320 def delete_comment(self, repo_name, comment_id):
330 def delete_comment(self, repo_name, comment_id):
321 co = ChangesetComment.get(comment_id)
331 co = ChangesetComment.get(comment_id)
332 if co.pull_request.is_closed():
333 #don't allow deleting comments on closed pull request
334 raise HTTPForbidden()
335
322 owner = lambda: co.author.user_id == c.rhodecode_user.user_id
336 owner = lambda: co.author.user_id == c.rhodecode_user.user_id
323 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
337 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
324 ChangesetCommentsModel().delete(comment=co)
338 ChangesetCommentsModel().delete(comment=co)
@@ -1519,6 +1519,7 b' class PullRequest(Base, BaseModel):'
1519 description = Column('description', UnicodeText(10240), nullable=True)
1519 description = Column('description', UnicodeText(10240), nullable=True)
1520 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1520 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1521 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1521 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1522 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1522 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1523 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1523 _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max
1524 _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max
1524 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1525 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
@@ -1526,6 +1527,8 b' class PullRequest(Base, BaseModel):'
1526 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1527 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1527 other_ref = Column('other_ref', Unicode(256), nullable=False)
1528 other_ref = Column('other_ref', Unicode(256), nullable=False)
1528
1529
1530 statuses = relationship('ChangesetStatus')
1531
1529 @hybrid_property
1532 @hybrid_property
1530 def revisions(self):
1533 def revisions(self):
1531 return self._revisions.split(':')
1534 return self._revisions.split(':')
@@ -1539,6 +1542,9 b' class PullRequest(Base, BaseModel):'
1539 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1542 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1540 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1543 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1541
1544
1545 def is_closed(self):
1546 return self.status == self.STATUS_CLOSED
1547
1542 def __json__(self):
1548 def __json__(self):
1543 return dict(
1549 return dict(
1544 revisions=self.revisions
1550 revisions=self.revisions
@@ -1,7 +1,7 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.pull_reuquest
3 rhodecode.model.pull_request
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 pull request model for RhodeCode
6 pull request model for RhodeCode
7
7
@@ -25,6 +25,7 b''
25
25
26 import logging
26 import logging
27 import binascii
27 import binascii
28 import datetime
28
29
29 from pylons.i18n.translation import _
30 from pylons.i18n.translation import _
30
31
@@ -44,6 +45,9 b' class PullRequestModel(BaseModel):'
44
45
45 cls = PullRequest
46 cls = PullRequest
46
47
48 def __get_pull_request(self, pull_request):
49 return self._get_instance(PullRequest, pull_request)
50
47 def get_all(self, repo):
51 def get_all(self, repo):
48 repo = self._get_repo(repo)
52 repo = self._get_repo(repo)
49 return PullRequest.query().filter(PullRequest.other_repo == repo).all()
53 return PullRequest.query().filter(PullRequest.other_repo == repo).all()
@@ -93,6 +97,12 b' class PullRequestModel(BaseModel):'
93
97
94 return new
98 return new
95
99
100 def close_pull_request(self, pull_request):
101 pull_request = self.__get_pull_request(pull_request)
102 pull_request.status = PullRequest.STATUS_CLOSED
103 pull_request.updated_on = datetime.datetime.now()
104 self.sa.add(pull_request)
105
96 def _get_changesets(self, org_repo, org_ref, other_repo, other_ref,
106 def _get_changesets(self, org_repo, org_ref, other_repo, other_ref,
97 discovery_data):
107 discovery_data):
98 """
108 """
@@ -396,7 +396,8 b' var injectInlineForm = function(tr){'
396 return
396 return
397 }
397 }
398 var submit_url = AJAX_COMMENT_URL;
398 var submit_url = AJAX_COMMENT_URL;
399 if(YUD.hasClass(tr,'form-open') || YUD.hasClass(tr,'context') || YUD.hasClass(tr,'no-comment')){
399 var _td = tr.getElementsByClassName('code')[0];
400 if(YUD.hasClass(tr,'form-open') || YUD.hasClass(tr,'context') || YUD.hasClass(_td,'no-comment')){
400 return
401 return
401 }
402 }
402 YUD.addClass(tr,'form-open');
403 YUD.addClass(tr,'form-open');
@@ -136,7 +136,10 b''
136 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
136 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
137 ${comment.comment_inline_form()}
137 ${comment.comment_inline_form()}
138
138
139 ## render comments main comments form and it status
139 ## render comments and inlines
140 ${comment.generate_comments()}
141
142 ## main comment form and it status
140 ${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision=c.changeset.raw_id),
143 ${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision=c.changeset.raw_id),
141 h.changeset_status(c.rhodecode_db_repo, c.changeset.raw_id))}
144 h.changeset_status(c.rhodecode_db_repo, c.changeset.raw_id))}
142
145
@@ -92,9 +92,8 b''
92
92
93 </%def>
93 </%def>
94
94
95 ## MAIN COMMENT FORM
95 ## generate inline comments and the main ones
96 <%def name="comments(post_url, cur_status)">
96 <%def name="generate_comments()">
97
98 <div class="comments">
97 <div class="comments">
99 <div id="inline-comments-container">
98 <div id="inline-comments-container">
100 ## generate inlines for this changeset
99 ## generate inlines for this changeset
@@ -106,6 +105,13 b''
106 ${comment_block(co)}
105 ${comment_block(co)}
107 </div>
106 </div>
108 %endfor
107 %endfor
108 </div>
109 </%def>
110
111 ## MAIN COMMENT FORM
112 <%def name="comments(post_url, cur_status, close_btn=False)">
113
114 <div class="comments">
109 %if c.rhodecode_user.username != 'default':
115 %if c.rhodecode_user.username != 'default':
110 <div class="comment-form ac">
116 <div class="comment-form ac">
111 ${h.form(post_url)}
117 ${h.form(post_url)}
@@ -129,7 +135,10 b''
129 ${h.textarea('text')}
135 ${h.textarea('text')}
130 </div>
136 </div>
131 <div class="comment-button">
137 <div class="comment-button">
132 ${h.submit('save', _('Comment'), class_='ui-button')}
138 ${h.submit('save', _('Comment'), class_="ui-btn large")}
139 %if close_btn:
140 ${h.submit('save_close', _('Comment and close'), class_='ui-btn blue large')}
141 %endif
133 </div>
142 </div>
134 ${h.end_form()}
143 ${h.end_form()}
135 </div>
144 </div>
@@ -19,12 +19,14 b''
19 <div class="title">
19 <div class="title">
20 ${self.breadcrumbs()}
20 ${self.breadcrumbs()}
21 </div>
21 </div>
22
22 %if c.pull_request.is_closed():
23 <div style="padding:10px; font-size:22px;width:100%;text-align: center; color:#88D882">${_('Closed %s') % (h.age(c.pull_request.updated_on))}</div>
24 %endif
23 <h3>${_('Title')}: ${c.pull_request.title}
25 <h3>${_('Title')}: ${c.pull_request.title}
24 <div class="changeset-status-container" style="float:none">
26 <div class="changeset-status-container" style="float:none">
25 %if c.current_changeset_status:
27 %if c.current_changeset_status:
26 <div title="${_('Pull request status')}" class="changeset-status-lbl">[${h.changeset_status_lbl(c.current_changeset_status)}]</div>
28 <div title="${_('Pull request status')}" class="changeset-status-lbl">[${h.changeset_status_lbl(c.current_changeset_status)}]</div>
27 <div class="changeset-status-ico" style="padding:4px"><img src="${h.url('/images/icons/flag_status_%s.png' % c.current_changeset_status)}" /></div>
29 <div class="changeset-status-ico" style="padding:4px"><img src="${h.url('/images/icons/flag_status_%s.png' % c.current_changeset_status)}" /></div>
28 %endif
30 %endif
29 </div>
31 </div>
30 </h3>
32 </h3>
@@ -96,11 +98,17 b''
96 ## template for inline comment form
98 ## template for inline comment form
97 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
99 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
98 ${comment.comment_inline_form()}
100 ${comment.comment_inline_form()}
99
101
100 ## render comments main comments form and it status
102 ## render comments and inlines
101 ${comment.comments(h.url('pullrequest_comment', repo_name=c.repo_name, pull_request_id=c.pull_request.pull_request_id),
103 ${comment.generate_comments()}
102 c.current_changeset_status)}
104
103
105 % if not c.pull_request.is_closed():
106 ## main comment form and it status
107 ${comment.comments(h.url('pullrequest_comment', repo_name=c.repo_name,
108 pull_request_id=c.pull_request.pull_request_id),
109 c.current_changeset_status,
110 close_btn=True)}
111 %endif
104
112
105 <script type="text/javascript">
113 <script type="text/javascript">
106 YUE.onDOMReady(function(){
114 YUE.onDOMReady(function(){
@@ -131,10 +139,8 b''
131 var file_comments = YUQ('.inline-comment-placeholder');
139 var file_comments = YUQ('.inline-comment-placeholder');
132 renderInlineComments(file_comments);
140 renderInlineComments(file_comments);
133 })
141 })
134
135 </script>
142 </script>
136
143
137
138 </div>
144 </div>
139
145
140 </%def>
146 </%def>
@@ -1,7 +1,7 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} ${_('All pull requests')}
4 ${c.repo_name} ${_('all pull requests')}
5 </%def>
5 </%def>
6
6
7 <%def name="breadcrumbs_links()">
7 <%def name="breadcrumbs_links()">
@@ -22,7 +22,11 b''
22
22
23 %for pr in c.pull_requests:
23 %for pr in c.pull_requests:
24 <div>
24 <div>
25 <h4><a href="${h.url('pullrequest_show',repo_name=c.repo_name,pull_request_id=pr.pull_request_id)}">
25 <h4>
26 %if pr.is_closed():
27 <img src="${h.url('/images/icons/tick.png')}" alt="${_('Closed')}" />
28 %endif
29 <a href="${h.url('pullrequest_show',repo_name=c.repo_name,pull_request_id=pr.pull_request_id)}">
26 ${_('Pull request #%s opened by %s on %s') % (pr.pull_request_id, pr.author.full_name, h.fmt_date(pr.created_on))}
30 ${_('Pull request #%s opened by %s on %s') % (pr.pull_request_id, pr.author.full_name, h.fmt_date(pr.created_on))}
27 </a>
31 </a>
28 </h4>
32 </h4>
General Comments 0
You need to be logged in to leave comments. Login now