Show More
@@ -380,49 +380,36 b' class RepoCommitsView(RepoAppView):' | |||
|
380 | 380 | commit_id = self.request.matchdict['commit_id'] |
|
381 | 381 | return self._commit(commit_id, method='download') |
|
382 | 382 | |
|
383 | @LoginRequired() | |
|
384 | @NotAnonymous() | |
|
385 | @HasRepoPermissionAnyDecorator( | |
|
386 | 'repository.read', 'repository.write', 'repository.admin') | |
|
387 | @CSRFRequired() | |
|
388 | @view_config( | |
|
389 | route_name='repo_commit_comment_create', request_method='POST', | |
|
390 | renderer='json_ext') | |
|
391 | def repo_commit_comment_create(self): | |
|
383 | def _commit_comments_create(self, commit_id, comments): | |
|
392 | 384 | _ = self.request.translate |
|
393 | commit_id = self.request.matchdict['commit_id'] | |
|
385 | data = {} | |
|
386 | if not comments: | |
|
387 | return | |
|
388 | ||
|
389 | commit = self.db_repo.get_commit(commit_id) | |
|
394 | 390 | |
|
395 | c = self.load_default_context() | |
|
396 | status = self.request.POST.get('changeset_status', None) | |
|
397 | is_draft = str2bool(self.request.POST.get('draft')) | |
|
398 | text = self.request.POST.get('text') | |
|
399 | comment_type = self.request.POST.get('comment_type') | |
|
400 | resolves_comment_id = self.request.POST.get('resolves_comment_id', None) | |
|
401 | f_path = self.request.POST.get('f_path') | |
|
402 | line_no = self.request.POST.get('line') | |
|
403 | target_elem_id = 'file-{}'.format(h.safeid(h.safe_unicode(f_path))) | |
|
391 | all_drafts = len([x for x in comments if str2bool(x['is_draft'])]) == len(comments) | |
|
392 | for entry in comments: | |
|
393 | c = self.load_default_context() | |
|
394 | comment_type = entry['comment_type'] | |
|
395 | text = entry['text'] | |
|
396 | status = entry['status'] | |
|
397 | is_draft = str2bool(entry['is_draft']) | |
|
398 | resolves_comment_id = entry['resolves_comment_id'] | |
|
399 | f_path = entry['f_path'] | |
|
400 | line_no = entry['line'] | |
|
401 | target_elem_id = 'file-{}'.format(h.safeid(h.safe_unicode(f_path))) | |
|
404 | 402 | |
|
405 | if status: | |
|
406 | text = text or (_('Status change %(transition_icon)s %(status)s') | |
|
407 | % {'transition_icon': '>', | |
|
408 | 'status': ChangesetStatus.get_status_lbl(status)}) | |
|
403 | if status: | |
|
404 | text = text or (_('Status change %(transition_icon)s %(status)s') | |
|
405 | % {'transition_icon': '>', | |
|
406 | 'status': ChangesetStatus.get_status_lbl(status)}) | |
|
409 | 407 | |
|
410 | multi_commit_ids = [] | |
|
411 | for _commit_id in self.request.POST.get('commit_ids', '').split(','): | |
|
412 | if _commit_id not in ['', None, EmptyCommit.raw_id]: | |
|
413 | if _commit_id not in multi_commit_ids: | |
|
414 | multi_commit_ids.append(_commit_id) | |
|
415 | ||
|
416 | commit_ids = multi_commit_ids or [commit_id] | |
|
417 | ||
|
418 | data = {} | |
|
419 | # Multiple comments for each passed commit id | |
|
420 | for current_id in filter(None, commit_ids): | |
|
421 | 408 | comment = CommentsModel().create( |
|
422 | 409 | text=text, |
|
423 | 410 | repo=self.db_repo.repo_id, |
|
424 | 411 | user=self._rhodecode_db_user.user_id, |
|
425 |
commit_id=c |
|
|
412 | commit_id=commit_id, | |
|
426 | 413 | f_path=f_path, |
|
427 | 414 | line_no=line_no, |
|
428 | 415 | status_change=(ChangesetStatus.get_status_lbl(status) |
@@ -438,9 +425,9 b' class RepoCommitsView(RepoAppView):' | |||
|
438 | 425 | |
|
439 | 426 | # get status if set ! |
|
440 | 427 | if status: |
|
428 | # `dont_allow_on_closed_pull_request = True` means | |
|
441 | 429 | # if latest status was from pull request and it's closed |
|
442 | 430 | # disallow changing status ! |
|
443 | # dont_allow_on_closed_pull_request = True ! | |
|
444 | 431 | |
|
445 | 432 | try: |
|
446 | 433 | ChangesetStatusModel().set_status( |
@@ -448,7 +435,7 b' class RepoCommitsView(RepoAppView):' | |||
|
448 | 435 | status, |
|
449 | 436 | self._rhodecode_db_user.user_id, |
|
450 | 437 | comment, |
|
451 |
revision=c |
|
|
438 | revision=commit_id, | |
|
452 | 439 | dont_allow_on_closed_pull_request=True |
|
453 | 440 | ) |
|
454 | 441 | except StatusChangeOnClosedPullRequestError: |
@@ -458,11 +445,15 b' class RepoCommitsView(RepoAppView):' | |||
|
458 | 445 | h.flash(msg, category='warning') |
|
459 | 446 | raise HTTPFound(h.route_path( |
|
460 | 447 | 'repo_commit', repo_name=self.db_repo_name, |
|
461 |
commit_id=c |
|
|
448 | commit_id=commit_id)) | |
|
449 | ||
|
450 | Session().flush() | |
|
451 | # this is somehow required to get access to some relationship | |
|
452 | # loaded on comment | |
|
453 | Session().refresh(comment) | |
|
462 | 454 | |
|
463 | 455 | # skip notifications for drafts |
|
464 | 456 | if not is_draft: |
|
465 | commit = self.db_repo.get_commit(current_id) | |
|
466 | 457 | CommentsModel().trigger_commit_comment_hook( |
|
467 | 458 | self.db_repo, self._rhodecode_user, 'create', |
|
468 | 459 | data={'comment': comment, 'commit': commit}) |
@@ -471,6 +462,8 b' class RepoCommitsView(RepoAppView):' | |||
|
471 | 462 | data[comment_id] = { |
|
472 | 463 | 'target_id': target_elem_id |
|
473 | 464 | } |
|
465 | Session().flush() | |
|
466 | ||
|
474 | 467 | c.co = comment |
|
475 | 468 | c.at_version_num = 0 |
|
476 | 469 | c.is_new = True |
@@ -481,21 +474,25 b' class RepoCommitsView(RepoAppView):' | |||
|
481 | 474 | data[comment_id].update(comment.get_dict()) |
|
482 | 475 | data[comment_id].update({'rendered_text': rendered_comment}) |
|
483 | 476 | |
|
484 | # skip channelstream for draft comments | |
|
485 | if not is_draft: | |
|
486 | comment_broadcast_channel = channelstream.comment_channel( | |
|
487 | self.db_repo_name, commit_obj=commit) | |
|
488 | ||
|
489 | comment_data = data | |
|
490 | posted_comment_type = 'inline' if is_inline else 'general' | |
|
491 | channelstream.comment_channelstream_push( | |
|
492 | self.request, comment_broadcast_channel, self._rhodecode_user, | |
|
493 | _('posted a new {} comment').format(posted_comment_type), | |
|
494 | comment_data=comment_data) | |
|
495 | ||
|
496 | 477 | # finalize, commit and redirect |
|
497 | 478 | Session().commit() |
|
498 | 479 | |
|
480 | # skip channelstream for draft comments | |
|
481 | if not all_drafts: | |
|
482 | comment_broadcast_channel = channelstream.comment_channel( | |
|
483 | self.db_repo_name, commit_obj=commit) | |
|
484 | ||
|
485 | comment_data = data | |
|
486 | posted_comment_type = 'inline' if is_inline else 'general' | |
|
487 | if len(data) == 1: | |
|
488 | msg = _('posted {} new {} comment').format(len(data), posted_comment_type) | |
|
489 | else: | |
|
490 | msg = _('posted {} new {} comments').format(len(data), posted_comment_type) | |
|
491 | ||
|
492 | channelstream.comment_channelstream_push( | |
|
493 | self.request, comment_broadcast_channel, self._rhodecode_user, msg, | |
|
494 | comment_data=comment_data) | |
|
495 | ||
|
499 | 496 | return data |
|
500 | 497 | |
|
501 | 498 | @LoginRequired() |
@@ -504,6 +501,44 b' class RepoCommitsView(RepoAppView):' | |||
|
504 | 501 | 'repository.read', 'repository.write', 'repository.admin') |
|
505 | 502 | @CSRFRequired() |
|
506 | 503 | @view_config( |
|
504 | route_name='repo_commit_comment_create', request_method='POST', | |
|
505 | renderer='json_ext') | |
|
506 | def repo_commit_comment_create(self): | |
|
507 | _ = self.request.translate | |
|
508 | commit_id = self.request.matchdict['commit_id'] | |
|
509 | ||
|
510 | multi_commit_ids = [] | |
|
511 | for _commit_id in self.request.POST.get('commit_ids', '').split(','): | |
|
512 | if _commit_id not in ['', None, EmptyCommit.raw_id]: | |
|
513 | if _commit_id not in multi_commit_ids: | |
|
514 | multi_commit_ids.append(_commit_id) | |
|
515 | ||
|
516 | commit_ids = multi_commit_ids or [commit_id] | |
|
517 | ||
|
518 | data = [] | |
|
519 | # Multiple comments for each passed commit id | |
|
520 | for current_id in filter(None, commit_ids): | |
|
521 | comment_data = { | |
|
522 | 'comment_type': self.request.POST.get('comment_type'), | |
|
523 | 'text': self.request.POST.get('text'), | |
|
524 | 'status': self.request.POST.get('changeset_status', None), | |
|
525 | 'is_draft': self.request.POST.get('draft'), | |
|
526 | 'resolves_comment_id': self.request.POST.get('resolves_comment_id', None), | |
|
527 | 'close_pull_request': self.request.POST.get('close_pull_request'), | |
|
528 | 'f_path': self.request.POST.get('f_path'), | |
|
529 | 'line': self.request.POST.get('line'), | |
|
530 | } | |
|
531 | comment = self._commit_comments_create(commit_id=current_id, comments=[comment_data]) | |
|
532 | data.append(comment) | |
|
533 | ||
|
534 | return data if len(data) > 1 else data[0] | |
|
535 | ||
|
536 | @LoginRequired() | |
|
537 | @NotAnonymous() | |
|
538 | @HasRepoPermissionAnyDecorator( | |
|
539 | 'repository.read', 'repository.write', 'repository.admin') | |
|
540 | @CSRFRequired() | |
|
541 | @view_config( | |
|
507 | 542 | route_name='repo_commit_comment_preview', request_method='POST', |
|
508 | 543 | renderer='string', xhr=True) |
|
509 | 544 | def repo_commit_comment_preview(self): |
@@ -690,6 +725,7 b' class RepoCommitsView(RepoAppView):' | |||
|
690 | 725 | def repo_commit_comment_edit(self): |
|
691 | 726 | self.load_default_context() |
|
692 | 727 | |
|
728 | commit_id = self.request.matchdict['commit_id'] | |
|
693 | 729 | comment_id = self.request.matchdict['comment_id'] |
|
694 | 730 | comment = ChangesetComment.get_or_404(comment_id) |
|
695 | 731 | |
@@ -742,11 +778,11 b' class RepoCommitsView(RepoAppView):' | |||
|
742 | 778 | if not comment_history: |
|
743 | 779 | raise HTTPNotFound() |
|
744 | 780 | |
|
745 | commit_id = self.request.matchdict['commit_id'] | |
|
746 | commit = self.db_repo.get_commit(commit_id) | |
|
747 | CommentsModel().trigger_commit_comment_hook( | |
|
748 | self.db_repo, self._rhodecode_user, 'edit', | |
|
749 | data={'comment': comment, 'commit': commit}) | |
|
781 | if not comment.draft: | |
|
782 | commit = self.db_repo.get_commit(commit_id) | |
|
783 | CommentsModel().trigger_commit_comment_hook( | |
|
784 | self.db_repo, self._rhodecode_user, 'edit', | |
|
785 | data={'comment': comment, 'commit': commit}) | |
|
750 | 786 | |
|
751 | 787 | Session().commit() |
|
752 | 788 | return { |
@@ -1523,9 +1523,9 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1523 | 1523 | def _pull_request_comments_create(self, pull_request, comments): |
|
1524 | 1524 | _ = self.request.translate |
|
1525 | 1525 | data = {} |
|
1526 | pull_request_id = pull_request.pull_request_id | |
|
1527 | 1526 | if not comments: |
|
1528 | 1527 | return |
|
1528 | pull_request_id = pull_request.pull_request_id | |
|
1529 | 1529 | |
|
1530 | 1530 | all_drafts = len([x for x in comments if str2bool(x['is_draft'])]) == len(comments) |
|
1531 | 1531 | |
@@ -1616,9 +1616,11 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1616 | 1616 | # loaded on comment |
|
1617 | 1617 | Session().refresh(comment) |
|
1618 | 1618 | |
|
1619 | PullRequestModel().trigger_pull_request_hook( | |
|
1620 | pull_request, self._rhodecode_user, 'comment', | |
|
1621 | data={'comment': comment}) | |
|
1619 | # skip notifications for drafts | |
|
1620 | if not is_draft: | |
|
1621 | PullRequestModel().trigger_pull_request_hook( | |
|
1622 | pull_request, self._rhodecode_user, 'comment', | |
|
1623 | data={'comment': comment}) | |
|
1622 | 1624 | |
|
1623 | 1625 | # we now calculate the status of pull request, and based on that |
|
1624 | 1626 | # calculation we set the commits status |
@@ -1647,16 +1649,16 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1647 | 1649 | Session().commit() |
|
1648 | 1650 | |
|
1649 | 1651 | # skip channelstream for draft comments |
|
1650 | if all_drafts: | |
|
1652 | if not all_drafts: | |
|
1651 | 1653 | comment_broadcast_channel = channelstream.comment_channel( |
|
1652 | 1654 | self.db_repo_name, pull_request_obj=pull_request) |
|
1653 | 1655 | |
|
1654 | 1656 | comment_data = data |
|
1655 | comment_type = 'inline' if is_inline else 'general' | |
|
1657 | posted_comment_type = 'inline' if is_inline else 'general' | |
|
1656 | 1658 | if len(data) == 1: |
|
1657 | msg = _('posted {} new {} comment').format(len(data), comment_type) | |
|
1659 | msg = _('posted {} new {} comment').format(len(data), posted_comment_type) | |
|
1658 | 1660 | else: |
|
1659 | msg = _('posted {} new {} comments').format(len(data), comment_type) | |
|
1661 | msg = _('posted {} new {} comments').format(len(data), posted_comment_type) | |
|
1660 | 1662 | |
|
1661 | 1663 | channelstream.comment_channelstream_push( |
|
1662 | 1664 | self.request, comment_broadcast_channel, self._rhodecode_user, msg, |
@@ -1782,11 +1784,6 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1782 | 1784 | log.debug('comment: forbidden because pull request is closed') |
|
1783 | 1785 | raise HTTPForbidden() |
|
1784 | 1786 | |
|
1785 | if not comment: | |
|
1786 | log.debug('Comment with id:%s not found, skipping', comment_id) | |
|
1787 | # comment already deleted in another call probably | |
|
1788 | return True | |
|
1789 | ||
|
1790 | 1787 | if comment.pull_request.is_closed(): |
|
1791 | 1788 | # don't allow deleting comments on closed pull request |
|
1792 | 1789 | raise HTTPForbidden() |
@@ -1837,10 +1834,10 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1837 | 1834 | raise HTTPNotFound() |
|
1838 | 1835 | |
|
1839 | 1836 | Session().commit() |
|
1840 | ||
|
1841 | PullRequestModel().trigger_pull_request_hook( | |
|
1842 | pull_request, self._rhodecode_user, 'comment_edit', | |
|
1843 | data={'comment': comment}) | |
|
1837 | if not comment.draft: | |
|
1838 | PullRequestModel().trigger_pull_request_hook( | |
|
1839 | pull_request, self._rhodecode_user, 'comment_edit', | |
|
1840 | data={'comment': comment}) | |
|
1844 | 1841 | |
|
1845 | 1842 | return { |
|
1846 | 1843 | 'comment_history_id': comment_history.comment_history_id, |
@@ -509,9 +509,9 b' form.comment-form {' | |||
|
509 | 509 | } |
|
510 | 510 | |
|
511 | 511 | .toolbar-text { |
|
512 |
height: |
|
|
512 | height: 28px; | |
|
513 | 513 | display: table-cell; |
|
514 |
vertical-align: b |
|
|
514 | vertical-align: baseline; | |
|
515 | 515 | font-size: 11px; |
|
516 | 516 | color: @grey4; |
|
517 | 517 | text-align: right; |
@@ -387,6 +387,7 b' function registerRCRoutes() {' | |||
|
387 | 387 | pyroutes.register('my_account_external_identity', '/_admin/my_account/external-identity', []); |
|
388 | 388 | pyroutes.register('my_account_external_identity_delete', '/_admin/my_account/external-identity/delete', []); |
|
389 | 389 | pyroutes.register('pullrequest_draft_comments_submit', '/%(repo_name)s/pull-request/%(pull_request_id)s/draft_comments_submit', ['repo_name', 'pull_request_id']); |
|
390 | pyroutes.register('commit_draft_comments_submit', '/%(repo_name)s/changeset/%(commit_id)s/draft_comments_submit', ['repo_name', 'commit_id']); | |
|
390 | 391 | pyroutes.register('repo_artifacts_list', '/%(repo_name)s/artifacts', ['repo_name']); |
|
391 | 392 | pyroutes.register('repo_artifacts_data', '/%(repo_name)s/artifacts_data', ['repo_name']); |
|
392 | 393 | pyroutes.register('repo_artifacts_new', '/%(repo_name)s/artifacts/new', ['repo_name']); |
@@ -700,7 +700,16 b' var CommentsController = function() {' | |||
|
700 | 700 | var $comment = $node.closest('.comment'); |
|
701 | 701 | var comment_id = $($comment).data('commentId'); |
|
702 | 702 | var isDraft = $($comment).data('commentDraft'); |
|
703 | var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id); | |
|
703 | ||
|
704 | var pullRequestId = templateContext.pull_request_data.pull_request_id; | |
|
705 | var commitId = templateContext.commit_data.commit_id; | |
|
706 | ||
|
707 | if (pullRequestId) { | |
|
708 | var url = pyroutes.url('pullrequest_comment_delete', {"comment_id": comment_id, "repo_name": templateContext.repo_name, "pull_request_id": pullRequestId}) | |
|
709 | } else if (commitId) { | |
|
710 | var url = pyroutes.url('repo_commit_comment_delete', {"comment_id": comment_id, "repo_name": templateContext.repo_name, "commit_id": commitId}) | |
|
711 | } | |
|
712 | ||
|
704 | 713 | var postData = { |
|
705 | 714 | 'csrf_token': CSRF_TOKEN |
|
706 | 715 | }; |
@@ -756,16 +765,20 b' var CommentsController = function() {' | |||
|
756 | 765 | |
|
757 | 766 | this._finalizeDrafts = function(commentIds) { |
|
758 | 767 | |
|
759 | // remove the drafts so we can lock them before submit. | |
|
768 | var pullRequestId = templateContext.pull_request_data.pull_request_id; | |
|
769 | var commitId = templateContext.commit_data.commit_id; | |
|
770 | ||
|
771 | if (pullRequestId) { | |
|
772 | var url = pyroutes.url('pullrequest_draft_comments_submit', {"repo_name": templateContext.repo_name, "pull_request_id": pullRequestId}) | |
|
773 | } else if (commitId) { | |
|
774 | var url = pyroutes.url('commit_draft_comments_submit', {"repo_name": templateContext.repo_name, "commit_id": commitId}) | |
|
775 | } | |
|
776 | ||
|
777 | // remove the drafts so we can lock them before submit. | |
|
760 | 778 | $.each(commentIds, function(idx, val){ |
|
761 | 779 | $('#comment-{0}'.format(val)).remove(); |
|
762 | 780 | }) |
|
763 | 781 | |
|
764 | var params = { | |
|
765 | 'pull_request_id': templateContext.pull_request_data.pull_request_id, | |
|
766 | 'repo_name': templateContext.repo_name, | |
|
767 | }; | |
|
768 | var url = pyroutes.url('pullrequest_draft_comments_submit', params) | |
|
769 | 782 | var postData = {'comments': commentIds, 'csrf_token': CSRF_TOKEN}; |
|
770 | 783 | |
|
771 | 784 | var submitSuccessCallback = function(json_data) { |
@@ -24,8 +24,6 b'' | |||
|
24 | 24 | |
|
25 | 25 | <%def name="main()"> |
|
26 | 26 | <script type="text/javascript"> |
|
27 | // TODO: marcink switch this to pyroutes | |
|
28 | AJAX_COMMENT_DELETE_URL = "${h.route_path('repo_commit_comment_delete',repo_name=c.repo_name,commit_id=c.commit.raw_id,comment_id='__COMMENT_ID__')}"; | |
|
29 | 27 | templateContext.commit_data.commit_id = "${c.commit.raw_id}"; |
|
30 | 28 | </script> |
|
31 | 29 |
@@ -542,7 +542,7 b'' | |||
|
542 | 542 | |
|
543 | 543 | <div class="toolbar-text"> |
|
544 | 544 | <% renderer_url = '<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper()) %> |
|
545 |
<span>${_(' |
|
|
545 | <span>${_('{} is supported.').format(renderer_url)|n} | |
|
546 | 546 | |
|
547 | 547 | <i class="icon-info-circled tooltip-hovercard" |
|
548 | 548 | data-hovercard-alt="ALT" |
@@ -32,8 +32,6 b'' | |||
|
32 | 32 | %> |
|
33 | 33 | |
|
34 | 34 | <script type="text/javascript"> |
|
35 | // TODO: marcink switch this to pyroutes | |
|
36 | AJAX_COMMENT_DELETE_URL = "${h.route_path('pullrequest_comment_delete',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id,comment_id='__COMMENT_ID__')}"; | |
|
37 | 35 | templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id}; |
|
38 | 36 | templateContext.pull_request_data.pull_request_version = '${request.GET.get('version', '')}'; |
|
39 | 37 | </script> |
General Comments 0
You need to be logged in to leave comments.
Login now