Show More
@@ -0,0 +1,37 b'' | |||||
|
1 | ||||
|
2 | <div class="pull-request-wrap"> | |||
|
3 | ||||
|
4 | <ul> | |||
|
5 | % for pr_check_type, pr_check_msg in c.pr_merge_checks: | |||
|
6 | <li> | |||
|
7 | <span class="merge-message ${pr_check_type}" data-role="merge-message"> | |||
|
8 | % if pr_check_type in ['success']: | |||
|
9 | <i class="icon-true"></i> | |||
|
10 | % else: | |||
|
11 | <i class="icon-false"></i> | |||
|
12 | % endif | |||
|
13 | ${pr_check_msg} | |||
|
14 | </span> | |||
|
15 | </li> | |||
|
16 | % endfor | |||
|
17 | </ul> | |||
|
18 | ||||
|
19 | <div class="pull-request-merge-actions"> | |||
|
20 | % if c.allowed_to_merge: | |||
|
21 | <div class="pull-right"> | |||
|
22 | ${h.secure_form(url('pullrequest_merge', repo_name=c.repo_name, pull_request_id=c.pull_request.pull_request_id), id='merge_pull_request_form')} | |||
|
23 | <% merge_disabled = ' disabled' if c.pr_merge_status is False else '' %> | |||
|
24 | <a class="btn" href="#" onclick="refreshMergeChecks(); return false;">${_('refresh checks')}</a> | |||
|
25 | <input type="submit" id="merge_pull_request" value="${_('Merge Pull Request')}" class="btn${merge_disabled}"${merge_disabled}> | |||
|
26 | ${h.end_form()} | |||
|
27 | </div> | |||
|
28 | % elif c.rhodecode_user.username != h.DEFAULT_USER: | |||
|
29 | <a class="btn" href="#" onclick="refreshMergeChecks(); return false;">${_('refresh checks')}</a> | |||
|
30 | <input type="submit" value="${_('Merge Pull Request')}" class="btn disabled" disabled="disabled" title="${_('You are not allowed to merge this pull request.')}"> | |||
|
31 | % else: | |||
|
32 | <input type="submit" value="${_('Login to Merge this Pull Request')}" class="btn disabled" disabled="disabled"> | |||
|
33 | % endif | |||
|
34 | </div> | |||
|
35 | ||||
|
36 | </div> | |||
|
37 |
@@ -633,6 +633,18 b' class PullrequestsController(BaseRepoCon' | |||||
633 | msg = _('Pull request reviewer approval is pending.') |
|
633 | msg = _('Pull request reviewer approval is pending.') | |
634 | h.flash(msg, category='error') |
|
634 | h.flash(msg, category='error') | |
635 | return False |
|
635 | return False | |
|
636 | ||||
|
637 | todos = CommentsModel().get_unresolved_todos(pull_request) | |||
|
638 | if todos: | |||
|
639 | log.debug("Cannot merge, unresolved todos left.") | |||
|
640 | if len(todos) == 1: | |||
|
641 | msg = _('Cannot merge, {} todo still not resolved.').format( | |||
|
642 | len(todos)) | |||
|
643 | else: | |||
|
644 | msg = _('Cannot merge, {} todos still not resolved.').format( | |||
|
645 | len(todos)) | |||
|
646 | h.flash(msg, category='error') | |||
|
647 | return False | |||
636 | return True |
|
648 | return True | |
637 |
|
649 | |||
638 | def _merge_pull_request(self, pull_request, user, extras): |
|
650 | def _merge_pull_request(self, pull_request, user, extras): | |
@@ -761,6 +773,7 b' class PullrequestsController(BaseRepoCon' | |||||
761 | def show(self, repo_name, pull_request_id): |
|
773 | def show(self, repo_name, pull_request_id): | |
762 | pull_request_id = safe_int(pull_request_id) |
|
774 | pull_request_id = safe_int(pull_request_id) | |
763 | version = request.GET.get('version') |
|
775 | version = request.GET.get('version') | |
|
776 | merge_checks = request.GET.get('merge_checks') | |||
764 |
|
777 | |||
765 | (pull_request_latest, |
|
778 | (pull_request_latest, | |
766 | pull_request_at_ver, |
|
779 | pull_request_at_ver, | |
@@ -778,6 +791,10 b' class PullrequestsController(BaseRepoCon' | |||||
778 | c.shadow_clone_url = PullRequestModel().get_shadow_clone_url( |
|
791 | c.shadow_clone_url = PullRequestModel().get_shadow_clone_url( | |
779 | pull_request_at_ver) |
|
792 | pull_request_at_ver) | |
780 |
|
793 | |||
|
794 | c.ancestor = None # TODO: add ancestor here | |||
|
795 | c.pull_request = pull_request_display_obj | |||
|
796 | c.pull_request_latest = pull_request_latest | |||
|
797 | ||||
781 | pr_closed = pull_request_latest.is_closed() |
|
798 | pr_closed = pull_request_latest.is_closed() | |
782 | if at_version and not at_version == 'latest': |
|
799 | if at_version and not at_version == 'latest': | |
783 | c.allowed_to_change_status = False |
|
800 | c.allowed_to_change_status = False | |
@@ -800,12 +817,6 b' class PullrequestsController(BaseRepoCon' | |||||
800 |
|
817 | |||
801 | c.pull_request_reviewers = pull_request_at_ver.reviewers_statuses() |
|
818 | c.pull_request_reviewers = pull_request_at_ver.reviewers_statuses() | |
802 | c.pull_request_review_status = pull_request_at_ver.calculated_review_status() |
|
819 | c.pull_request_review_status = pull_request_at_ver.calculated_review_status() | |
803 | c.pr_merge_status, c.pr_merge_msg = PullRequestModel().merge_status( |
|
|||
804 | pull_request_at_ver) |
|
|||
805 | c.approval_msg = None |
|
|||
806 | if c.pull_request_review_status != ChangesetStatus.STATUS_APPROVED: |
|
|||
807 | c.approval_msg = _('Reviewer approval is pending.') |
|
|||
808 | c.pr_merge_status = False |
|
|||
809 |
|
820 | |||
810 | c.versions = pull_request_display_obj.versions() |
|
821 | c.versions = pull_request_display_obj.versions() | |
811 | c.at_version = at_version |
|
822 | c.at_version = at_version | |
@@ -830,7 +841,7 b' class PullrequestsController(BaseRepoCon' | |||||
830 |
|
841 | |||
831 | # if we use version, then do not show later comments |
|
842 | # if we use version, then do not show later comments | |
832 | # than current version |
|
843 | # than current version | |
833 |
pat |
|
844 | display_inline_comments = collections.defaultdict(lambda: collections.defaultdict(list)) | |
834 | for co in inline_comments: |
|
845 | for co in inline_comments: | |
835 | if c.at_version_num: |
|
846 | if c.at_version_num: | |
836 | # pick comments that are at least UPTO given version, so we |
|
847 | # pick comments that are at least UPTO given version, so we | |
@@ -842,11 +853,32 b' class PullrequestsController(BaseRepoCon' | |||||
842 | should_render = True |
|
853 | should_render = True | |
843 |
|
854 | |||
844 | if should_render: |
|
855 | if should_render: | |
845 |
pat |
|
856 | display_inline_comments[co.f_path][co.line_no].append(co) | |
846 | inline_comments = paths |
|
857 | ||
|
858 | c.pr_merge_checks = [] | |||
|
859 | c.pr_merge_status, c.pr_merge_msg = PullRequestModel().merge_status( | |||
|
860 | pull_request_at_ver) | |||
|
861 | c.pr_merge_checks.append(['warning' if not c.pr_merge_status else 'success', c.pr_merge_msg]) | |||
|
862 | ||||
|
863 | if c.pull_request_review_status != ChangesetStatus.STATUS_APPROVED: | |||
|
864 | approval_msg = _('Reviewer approval is pending.') | |||
|
865 | c.pr_merge_status = False | |||
|
866 | c.pr_merge_checks.append(['warning', approval_msg]) | |||
|
867 | ||||
|
868 | todos = cc_model.get_unresolved_todos(pull_request_latest) | |||
|
869 | if todos: | |||
|
870 | c.pr_merge_status = False | |||
|
871 | if len(todos) == 1: | |||
|
872 | msg = _('{} todo still not resolved.').format(len(todos)) | |||
|
873 | else: | |||
|
874 | msg = _('{} todos still not resolved.').format(len(todos)) | |||
|
875 | c.pr_merge_checks.append(['warning', msg]) | |||
|
876 | ||||
|
877 | if merge_checks: | |||
|
878 | return render('/pullrequests/pullrequest_merge_checks.mako') | |||
847 |
|
879 | |||
848 | # load compare data into template context |
|
880 | # load compare data into template context | |
849 | self._load_compare_data(pull_request_at_ver, inline_comments) |
|
881 | self._load_compare_data(pull_request_at_ver, display_inline_comments) | |
850 |
|
882 | |||
851 | # this is a hack to properly display links, when creating PR, the |
|
883 | # this is a hack to properly display links, when creating PR, the | |
852 | # compare view and others uses different notation, and |
|
884 | # compare view and others uses different notation, and | |
@@ -861,10 +893,6 b' class PullrequestsController(BaseRepoCon' | |||||
861 | statuses = ChangesetStatus.STATUSES |
|
893 | statuses = ChangesetStatus.STATUSES | |
862 | c.commit_statuses = statuses |
|
894 | c.commit_statuses = statuses | |
863 |
|
895 | |||
864 | c.ancestor = None # TODO: add ancestor here |
|
|||
865 | c.pull_request = pull_request_display_obj |
|
|||
866 | c.pull_request_latest = pull_request_latest |
|
|||
867 |
|
||||
868 | c.changes = None |
|
896 | c.changes = None | |
869 | c.file_changes = None |
|
897 | c.file_changes = None | |
870 |
|
898 |
@@ -129,6 +129,18 b' class CommentsModel(BaseModel):' | |||||
129 |
|
129 | |||
130 | return comment_versions |
|
130 | return comment_versions | |
131 |
|
131 | |||
|
132 | def get_unresolved_todos(self, pull_request): | |||
|
133 | ||||
|
134 | todos = Session().query(ChangesetComment) \ | |||
|
135 | .filter(ChangesetComment.pull_request == pull_request) \ | |||
|
136 | .filter(ChangesetComment.resolved_by == None) \ | |||
|
137 | .filter(ChangesetComment.comment_type | |||
|
138 | == ChangesetComment.COMMENT_TYPE_TODO) \ | |||
|
139 | .filter(coalesce(ChangesetComment.display_state, '') != | |||
|
140 | ChangesetComment.COMMENT_OUTDATED).all() | |||
|
141 | ||||
|
142 | return todos | |||
|
143 | ||||
132 | def create(self, text, repo, user, commit_id=None, pull_request=None, |
|
144 | def create(self, text, repo, user, commit_id=None, pull_request=None, | |
133 | f_path=None, line_no=None, status_change=None, |
|
145 | f_path=None, line_no=None, status_change=None, | |
134 | status_change_type=None, comment_type=None, |
|
146 | status_change_type=None, comment_type=None, |
@@ -2972,6 +2972,10 b' class ChangesetComment(Base, BaseModel):' | |||||
2972 | def resolved(self): |
|
2972 | def resolved(self): | |
2973 | return self.resolved_by[0] if self.resolved_by else None |
|
2973 | return self.resolved_by[0] if self.resolved_by else None | |
2974 |
|
2974 | |||
|
2975 | @property | |||
|
2976 | def is_todo(self): | |||
|
2977 | return self.comment_type == self.COMMENT_TYPE_TODO | |||
|
2978 | ||||
2975 | def get_index_version(self, versions): |
|
2979 | def get_index_version(self, versions): | |
2976 | return self.get_index_from_version( |
|
2980 | return self.get_index_from_version( | |
2977 | self.pull_request_version_id, versions) |
|
2981 | self.pull_request_version_id, versions) |
@@ -1610,19 +1610,53 b' BIN_FILENODE = 7' | |||||
1610 | } |
|
1610 | } | |
1611 |
|
1611 | |||
1612 | .pull-request-merge { |
|
1612 | .pull-request-merge { | |
1613 | padding: 10px 0; |
|
1613 | border: 1px solid @grey5; | |
|
1614 | padding: 10px 0px 20px; | |||
1614 | margin-top: 10px; |
|
1615 | margin-top: 10px; | |
1615 | margin-bottom: 20px; |
|
1616 | margin-bottom: 20px; | |
1616 | } |
|
1617 | } | |
1617 |
|
1618 | |||
|
1619 | .pull-request-merge ul { | |||
|
1620 | padding: 0px 0px; | |||
|
1621 | } | |||
|
1622 | ||||
|
1623 | .pull-request-merge li:before{ | |||
|
1624 | content:none; | |||
|
1625 | } | |||
|
1626 | ||||
1618 | .pull-request-merge .pull-request-wrap { |
|
1627 | .pull-request-merge .pull-request-wrap { | |
1619 |
height: |
|
1628 | height: auto; | |
1620 |
padding: |
|
1629 | padding: 0px 0px; | |
|
1630 | text-align: right; | |||
1621 | } |
|
1631 | } | |
1622 |
|
1632 | |||
1623 | .pull-request-merge span { |
|
1633 | .pull-request-merge span { | |
1624 |
margin-right: |
|
1634 | margin-right: 5px; | |
1625 | } |
|
1635 | } | |
|
1636 | ||||
|
1637 | .pull-request-merge-actions { | |||
|
1638 | height: 30px; | |||
|
1639 | padding: 0px 0px; | |||
|
1640 | } | |||
|
1641 | ||||
|
1642 | .merge-message { | |||
|
1643 | font-size: 1.2em | |||
|
1644 | } | |||
|
1645 | .merge-message li{ | |||
|
1646 | text-decoration: none; | |||
|
1647 | } | |||
|
1648 | ||||
|
1649 | .merge-message.success i { | |||
|
1650 | color:@alert1; | |||
|
1651 | } | |||
|
1652 | .merge-message.warning i { | |||
|
1653 | color: @alert3; | |||
|
1654 | } | |||
|
1655 | .merge-message.error i { | |||
|
1656 | color:@alert2; | |||
|
1657 | } | |||
|
1658 | ||||
|
1659 | ||||
1626 |
|
1660 | |||
1627 | .pr-versions { |
|
1661 | .pr-versions { | |
1628 | position: relative; |
|
1662 | position: relative; |
@@ -240,7 +240,12 b' var bindToggleButtons = function() {' | |||||
240 | $(this.statusChange).select2('readonly', false); |
|
240 | $(this.statusChange).select2('readonly', false); | |
241 | }; |
|
241 | }; | |
242 |
|
242 | |||
243 |
this.globalSubmitSuccessCallback = function(){ |
|
243 | this.globalSubmitSuccessCallback = function(){ | |
|
244 | // default behaviour is to call GLOBAL hook, if it's registered. | |||
|
245 | if (window.commentFormGlobalSubmitSuccessCallback !== undefined){ | |||
|
246 | commentFormGlobalSubmitSuccessCallback() | |||
|
247 | } | |||
|
248 | }; | |||
244 |
|
249 | |||
245 | this.submitAjaxPOST = function(url, postData, successHandler, failHandler) { |
|
250 | this.submitAjaxPOST = function(url, postData, successHandler, failHandler) { | |
246 | failHandler = failHandler || function() {}; |
|
251 | failHandler = failHandler || function() {}; | |
@@ -300,7 +305,8 b' var bindToggleButtons = function() {' | |||||
300 | } |
|
305 | } | |
301 |
|
306 | |||
302 | var submitSuccessCallback = function(o) { |
|
307 | var submitSuccessCallback = function(o) { | |
303 | if (status) { |
|
308 | // reload page if we change status for single commit. | |
|
309 | if (status && self.commitId) { | |||
304 | location.reload(true); |
|
310 | location.reload(true); | |
305 | } else { |
|
311 | } else { | |
306 | $('#injected_page_comments').append(o.rendered_text); |
|
312 | $('#injected_page_comments').append(o.rendered_text); |
@@ -170,29 +170,6 b'' | |||||
170 |
|
170 | |||
171 | <%def name="comments(post_url, cur_status, is_pull_request=False, is_compare=False, change_status=True, form_extras=None)"> |
|
171 | <%def name="comments(post_url, cur_status, is_pull_request=False, is_compare=False, change_status=True, form_extras=None)"> | |
172 |
|
172 | |||
173 | ## merge status, and merge action |
|
|||
174 | %if is_pull_request: |
|
|||
175 | <div class="pull-request-merge"> |
|
|||
176 | %if c.allowed_to_merge: |
|
|||
177 | <div class="pull-request-wrap"> |
|
|||
178 | <div class="pull-right"> |
|
|||
179 | ${h.secure_form(url('pullrequest_merge', repo_name=c.repo_name, pull_request_id=c.pull_request.pull_request_id), id='merge_pull_request_form')} |
|
|||
180 | <span data-role="merge-message">${c.pr_merge_msg} ${c.approval_msg if c.approval_msg else ''}</span> |
|
|||
181 | <% merge_disabled = ' disabled' if c.pr_merge_status is False else '' %> |
|
|||
182 | <input type="submit" id="merge_pull_request" value="${_('Merge Pull Request')}" class="btn${merge_disabled}"${merge_disabled}> |
|
|||
183 | ${h.end_form()} |
|
|||
184 | </div> |
|
|||
185 | </div> |
|
|||
186 | %else: |
|
|||
187 | <div class="pull-request-wrap"> |
|
|||
188 | <div class="pull-right"> |
|
|||
189 | <span>${c.pr_merge_msg} ${c.approval_msg if c.approval_msg else ''}</span> |
|
|||
190 | </div> |
|
|||
191 | </div> |
|
|||
192 | %endif |
|
|||
193 | </div> |
|
|||
194 | %endif |
|
|||
195 |
|
||||
196 | <div class="comments"> |
|
173 | <div class="comments"> | |
197 | <% |
|
174 | <% | |
198 | if is_pull_request: |
|
175 | if is_pull_request: |
@@ -482,8 +482,8 b' Changed files:' | |||||
482 |
|
482 | |||
483 | <div id="comment-tr-show"> |
|
483 | <div id="comment-tr-show"> | |
484 | <div class="comment"> |
|
484 | <div class="comment"> | |
|
485 | % if general_outdated_comm_count_ver: | |||
485 | <div class="meta"> |
|
486 | <div class="meta"> | |
486 | % if general_outdated_comm_count_ver: |
|
|||
487 |
|
|
487 | % if general_outdated_comm_count_ver == 1: | |
488 |
|
|
488 | ${_('there is {num} general comment from older versions').format(num=general_outdated_comm_count_ver)}, | |
489 |
|
|
489 | <a href="#" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show it')}</a> | |
@@ -491,14 +491,19 b' Changed files:' | |||||
491 |
|
|
491 | ${_('there are {num} general comments from older versions').format(num=general_outdated_comm_count_ver)}, | |
492 |
|
|
492 | <a href="#" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show them')}</a> | |
493 |
|
|
493 | % endif | |
|
494 | </div> | |||
494 |
|
|
495 | % endif | |
495 |
|
|
496 | </div> | |
496 |
|
|
497 | </div> | |
497 | </div> |
|
|||
498 |
|
498 | |||
499 | ${comment.generate_comments(c.comments, include_pull_request=True, is_pull_request=True)} |
|
499 | ${comment.generate_comments(c.comments, include_pull_request=True, is_pull_request=True)} | |
500 |
|
500 | |||
501 | % if not c.pull_request.is_closed(): |
|
501 | % if not c.pull_request.is_closed(): | |
|
502 | ## merge status, and merge action | |||
|
503 | <div class="pull-request-merge"> | |||
|
504 | <%include file="/pullrequests/pullrequest_merge_checks.mako"/> | |||
|
505 | </div> | |||
|
506 | ||||
502 | ## main comment form and it status |
|
507 | ## main comment form and it status | |
503 |
|
|
508 | ${comment.comments(h.url('pullrequest_comment', repo_name=c.repo_name, | |
504 | pull_request_id=c.pull_request.pull_request_id), |
|
509 | pull_request_id=c.pull_request.pull_request_id), | |
@@ -603,6 +608,16 b' Changed files:' | |||||
603 | $('.showOutdatedComments').show(); |
|
608 | $('.showOutdatedComments').show(); | |
604 | }; |
|
609 | }; | |
605 |
|
610 | |||
|
611 | refreshMergeChecks = function(){ | |||
|
612 | var loadUrl = "${h.url.current(merge_checks=1)}"; | |||
|
613 | $('.pull-request-merge').css('opacity', 0.3); | |||
|
614 | $('.pull-request-merge').load( | |||
|
615 | loadUrl,function() { | |||
|
616 | $('.pull-request-merge').css('opacity', 1); | |||
|
617 | } | |||
|
618 | ); | |||
|
619 | }; | |||
|
620 | ||||
606 | $('#show-outdated-comments').on('click', function(e){ |
|
621 | $('#show-outdated-comments').on('click', function(e){ | |
607 | var button = $(this); |
|
622 | var button = $(this); | |
608 | var outdated = $('.comment-outdated'); |
|
623 | var outdated = $('.comment-outdated'); | |
@@ -683,6 +698,12 b' Changed files:' | |||||
683 | button.addClass("comments-visible"); |
|
698 | button.addClass("comments-visible"); | |
684 | } |
|
699 | } | |
685 | }); |
|
700 | }); | |
|
701 | ||||
|
702 | // register submit callback on commentForm form to track TODOs | |||
|
703 | window.commentFormGlobalSubmitSuccessCallback = function(){ | |||
|
704 | refreshMergeChecks(); | |||
|
705 | }; | |||
|
706 | ||||
686 | }) |
|
707 | }) | |
687 | </script> |
|
708 | </script> | |
688 |
|
709 |
General Comments 0
You need to be logged in to leave comments.
Login now