##// END OF EJS Templates
drafts: support draft in commits view...
milka -
r4555:57bb7bdc default
parent child Browse files
Show More
@@ -380,49 +380,36 b' class RepoCommitsView(RepoAppView):'
380 commit_id = self.request.matchdict['commit_id']
380 commit_id = self.request.matchdict['commit_id']
381 return self._commit(commit_id, method='download')
381 return self._commit(commit_id, method='download')
382
382
383 @LoginRequired()
383 def _commit_comments_create(self, commit_id, comments):
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):
392 _ = self.request.translate
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()
391 all_drafts = len([x for x in comments if str2bool(x['is_draft'])]) == len(comments)
396 status = self.request.POST.get('changeset_status', None)
392 for entry in comments:
397 is_draft = str2bool(self.request.POST.get('draft'))
393 c = self.load_default_context()
398 text = self.request.POST.get('text')
394 comment_type = entry['comment_type']
399 comment_type = self.request.POST.get('comment_type')
395 text = entry['text']
400 resolves_comment_id = self.request.POST.get('resolves_comment_id', None)
396 status = entry['status']
401 f_path = self.request.POST.get('f_path')
397 is_draft = str2bool(entry['is_draft'])
402 line_no = self.request.POST.get('line')
398 resolves_comment_id = entry['resolves_comment_id']
403 target_elem_id = 'file-{}'.format(h.safeid(h.safe_unicode(f_path)))
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:
403 if status:
406 text = text or (_('Status change %(transition_icon)s %(status)s')
404 text = text or (_('Status change %(transition_icon)s %(status)s')
407 % {'transition_icon': '>',
405 % {'transition_icon': '>',
408 'status': ChangesetStatus.get_status_lbl(status)})
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 comment = CommentsModel().create(
408 comment = CommentsModel().create(
422 text=text,
409 text=text,
423 repo=self.db_repo.repo_id,
410 repo=self.db_repo.repo_id,
424 user=self._rhodecode_db_user.user_id,
411 user=self._rhodecode_db_user.user_id,
425 commit_id=current_id,
412 commit_id=commit_id,
426 f_path=f_path,
413 f_path=f_path,
427 line_no=line_no,
414 line_no=line_no,
428 status_change=(ChangesetStatus.get_status_lbl(status)
415 status_change=(ChangesetStatus.get_status_lbl(status)
@@ -438,9 +425,9 b' class RepoCommitsView(RepoAppView):'
438
425
439 # get status if set !
426 # get status if set !
440 if status:
427 if status:
428 # `dont_allow_on_closed_pull_request = True` means
441 # if latest status was from pull request and it's closed
429 # if latest status was from pull request and it's closed
442 # disallow changing status !
430 # disallow changing status !
443 # dont_allow_on_closed_pull_request = True !
444
431
445 try:
432 try:
446 ChangesetStatusModel().set_status(
433 ChangesetStatusModel().set_status(
@@ -448,7 +435,7 b' class RepoCommitsView(RepoAppView):'
448 status,
435 status,
449 self._rhodecode_db_user.user_id,
436 self._rhodecode_db_user.user_id,
450 comment,
437 comment,
451 revision=current_id,
438 revision=commit_id,
452 dont_allow_on_closed_pull_request=True
439 dont_allow_on_closed_pull_request=True
453 )
440 )
454 except StatusChangeOnClosedPullRequestError:
441 except StatusChangeOnClosedPullRequestError:
@@ -458,11 +445,15 b' class RepoCommitsView(RepoAppView):'
458 h.flash(msg, category='warning')
445 h.flash(msg, category='warning')
459 raise HTTPFound(h.route_path(
446 raise HTTPFound(h.route_path(
460 'repo_commit', repo_name=self.db_repo_name,
447 'repo_commit', repo_name=self.db_repo_name,
461 commit_id=current_id))
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 # skip notifications for drafts
455 # skip notifications for drafts
464 if not is_draft:
456 if not is_draft:
465 commit = self.db_repo.get_commit(current_id)
466 CommentsModel().trigger_commit_comment_hook(
457 CommentsModel().trigger_commit_comment_hook(
467 self.db_repo, self._rhodecode_user, 'create',
458 self.db_repo, self._rhodecode_user, 'create',
468 data={'comment': comment, 'commit': commit})
459 data={'comment': comment, 'commit': commit})
@@ -471,6 +462,8 b' class RepoCommitsView(RepoAppView):'
471 data[comment_id] = {
462 data[comment_id] = {
472 'target_id': target_elem_id
463 'target_id': target_elem_id
473 }
464 }
465 Session().flush()
466
474 c.co = comment
467 c.co = comment
475 c.at_version_num = 0
468 c.at_version_num = 0
476 c.is_new = True
469 c.is_new = True
@@ -481,21 +474,25 b' class RepoCommitsView(RepoAppView):'
481 data[comment_id].update(comment.get_dict())
474 data[comment_id].update(comment.get_dict())
482 data[comment_id].update({'rendered_text': rendered_comment})
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 # finalize, commit and redirect
477 # finalize, commit and redirect
497 Session().commit()
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 return data
496 return data
500
497
501 @LoginRequired()
498 @LoginRequired()
@@ -504,6 +501,44 b' class RepoCommitsView(RepoAppView):'
504 'repository.read', 'repository.write', 'repository.admin')
501 'repository.read', 'repository.write', 'repository.admin')
505 @CSRFRequired()
502 @CSRFRequired()
506 @view_config(
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 route_name='repo_commit_comment_preview', request_method='POST',
542 route_name='repo_commit_comment_preview', request_method='POST',
508 renderer='string', xhr=True)
543 renderer='string', xhr=True)
509 def repo_commit_comment_preview(self):
544 def repo_commit_comment_preview(self):
@@ -690,6 +725,7 b' class RepoCommitsView(RepoAppView):'
690 def repo_commit_comment_edit(self):
725 def repo_commit_comment_edit(self):
691 self.load_default_context()
726 self.load_default_context()
692
727
728 commit_id = self.request.matchdict['commit_id']
693 comment_id = self.request.matchdict['comment_id']
729 comment_id = self.request.matchdict['comment_id']
694 comment = ChangesetComment.get_or_404(comment_id)
730 comment = ChangesetComment.get_or_404(comment_id)
695
731
@@ -742,11 +778,11 b' class RepoCommitsView(RepoAppView):'
742 if not comment_history:
778 if not comment_history:
743 raise HTTPNotFound()
779 raise HTTPNotFound()
744
780
745 commit_id = self.request.matchdict['commit_id']
781 if not comment.draft:
746 commit = self.db_repo.get_commit(commit_id)
782 commit = self.db_repo.get_commit(commit_id)
747 CommentsModel().trigger_commit_comment_hook(
783 CommentsModel().trigger_commit_comment_hook(
748 self.db_repo, self._rhodecode_user, 'edit',
784 self.db_repo, self._rhodecode_user, 'edit',
749 data={'comment': comment, 'commit': commit})
785 data={'comment': comment, 'commit': commit})
750
786
751 Session().commit()
787 Session().commit()
752 return {
788 return {
@@ -1523,9 +1523,9 b' class RepoPullRequestsView(RepoAppView, '
1523 def _pull_request_comments_create(self, pull_request, comments):
1523 def _pull_request_comments_create(self, pull_request, comments):
1524 _ = self.request.translate
1524 _ = self.request.translate
1525 data = {}
1525 data = {}
1526 pull_request_id = pull_request.pull_request_id
1527 if not comments:
1526 if not comments:
1528 return
1527 return
1528 pull_request_id = pull_request.pull_request_id
1529
1529
1530 all_drafts = len([x for x in comments if str2bool(x['is_draft'])]) == len(comments)
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 # loaded on comment
1616 # loaded on comment
1617 Session().refresh(comment)
1617 Session().refresh(comment)
1618
1618
1619 PullRequestModel().trigger_pull_request_hook(
1619 # skip notifications for drafts
1620 pull_request, self._rhodecode_user, 'comment',
1620 if not is_draft:
1621 data={'comment': comment})
1621 PullRequestModel().trigger_pull_request_hook(
1622 pull_request, self._rhodecode_user, 'comment',
1623 data={'comment': comment})
1622
1624
1623 # we now calculate the status of pull request, and based on that
1625 # we now calculate the status of pull request, and based on that
1624 # calculation we set the commits status
1626 # calculation we set the commits status
@@ -1647,16 +1649,16 b' class RepoPullRequestsView(RepoAppView, '
1647 Session().commit()
1649 Session().commit()
1648
1650
1649 # skip channelstream for draft comments
1651 # skip channelstream for draft comments
1650 if all_drafts:
1652 if not all_drafts:
1651 comment_broadcast_channel = channelstream.comment_channel(
1653 comment_broadcast_channel = channelstream.comment_channel(
1652 self.db_repo_name, pull_request_obj=pull_request)
1654 self.db_repo_name, pull_request_obj=pull_request)
1653
1655
1654 comment_data = data
1656 comment_data = data
1655 comment_type = 'inline' if is_inline else 'general'
1657 posted_comment_type = 'inline' if is_inline else 'general'
1656 if len(data) == 1:
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 else:
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 channelstream.comment_channelstream_push(
1663 channelstream.comment_channelstream_push(
1662 self.request, comment_broadcast_channel, self._rhodecode_user, msg,
1664 self.request, comment_broadcast_channel, self._rhodecode_user, msg,
@@ -1782,11 +1784,6 b' class RepoPullRequestsView(RepoAppView, '
1782 log.debug('comment: forbidden because pull request is closed')
1784 log.debug('comment: forbidden because pull request is closed')
1783 raise HTTPForbidden()
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 if comment.pull_request.is_closed():
1787 if comment.pull_request.is_closed():
1791 # don't allow deleting comments on closed pull request
1788 # don't allow deleting comments on closed pull request
1792 raise HTTPForbidden()
1789 raise HTTPForbidden()
@@ -1837,10 +1834,10 b' class RepoPullRequestsView(RepoAppView, '
1837 raise HTTPNotFound()
1834 raise HTTPNotFound()
1838
1835
1839 Session().commit()
1836 Session().commit()
1840
1837 if not comment.draft:
1841 PullRequestModel().trigger_pull_request_hook(
1838 PullRequestModel().trigger_pull_request_hook(
1842 pull_request, self._rhodecode_user, 'comment_edit',
1839 pull_request, self._rhodecode_user, 'comment_edit',
1843 data={'comment': comment})
1840 data={'comment': comment})
1844
1841
1845 return {
1842 return {
1846 'comment_history_id': comment_history.comment_history_id,
1843 'comment_history_id': comment_history.comment_history_id,
@@ -509,9 +509,9 b' form.comment-form {'
509 }
509 }
510
510
511 .toolbar-text {
511 .toolbar-text {
512 height: 42px;
512 height: 28px;
513 display: table-cell;
513 display: table-cell;
514 vertical-align: bottom;
514 vertical-align: baseline;
515 font-size: 11px;
515 font-size: 11px;
516 color: @grey4;
516 color: @grey4;
517 text-align: right;
517 text-align: right;
@@ -387,6 +387,7 b' function registerRCRoutes() {'
387 pyroutes.register('my_account_external_identity', '/_admin/my_account/external-identity', []);
387 pyroutes.register('my_account_external_identity', '/_admin/my_account/external-identity', []);
388 pyroutes.register('my_account_external_identity_delete', '/_admin/my_account/external-identity/delete', []);
388 pyroutes.register('my_account_external_identity_delete', '/_admin/my_account/external-identity/delete', []);
389 pyroutes.register('pullrequest_draft_comments_submit', '/%(repo_name)s/pull-request/%(pull_request_id)s/draft_comments_submit', ['repo_name', 'pull_request_id']);
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 pyroutes.register('repo_artifacts_list', '/%(repo_name)s/artifacts', ['repo_name']);
391 pyroutes.register('repo_artifacts_list', '/%(repo_name)s/artifacts', ['repo_name']);
391 pyroutes.register('repo_artifacts_data', '/%(repo_name)s/artifacts_data', ['repo_name']);
392 pyroutes.register('repo_artifacts_data', '/%(repo_name)s/artifacts_data', ['repo_name']);
392 pyroutes.register('repo_artifacts_new', '/%(repo_name)s/artifacts/new', ['repo_name']);
393 pyroutes.register('repo_artifacts_new', '/%(repo_name)s/artifacts/new', ['repo_name']);
@@ -700,7 +700,16 b' var CommentsController = function() {'
700 var $comment = $node.closest('.comment');
700 var $comment = $node.closest('.comment');
701 var comment_id = $($comment).data('commentId');
701 var comment_id = $($comment).data('commentId');
702 var isDraft = $($comment).data('commentDraft');
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 var postData = {
713 var postData = {
705 'csrf_token': CSRF_TOKEN
714 'csrf_token': CSRF_TOKEN
706 };
715 };
@@ -756,16 +765,20 b' var CommentsController = function() {'
756
765
757 this._finalizeDrafts = function(commentIds) {
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 $.each(commentIds, function(idx, val){
778 $.each(commentIds, function(idx, val){
761 $('#comment-{0}'.format(val)).remove();
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 var postData = {'comments': commentIds, 'csrf_token': CSRF_TOKEN};
782 var postData = {'comments': commentIds, 'csrf_token': CSRF_TOKEN};
770
783
771 var submitSuccessCallback = function(json_data) {
784 var submitSuccessCallback = function(json_data) {
@@ -24,8 +24,6 b''
24
24
25 <%def name="main()">
25 <%def name="main()">
26 <script type="text/javascript">
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 templateContext.commit_data.commit_id = "${c.commit.raw_id}";
27 templateContext.commit_data.commit_id = "${c.commit.raw_id}";
30 </script>
28 </script>
31
29
@@ -542,7 +542,7 b''
542
542
543 <div class="toolbar-text">
543 <div class="toolbar-text">
544 <% renderer_url = '<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper()) %>
544 <% renderer_url = '<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper()) %>
545 <span>${_('Styling with {} is supported.').format(renderer_url)|n}
545 <span>${_('{} is supported.').format(renderer_url)|n}
546
546
547 <i class="icon-info-circled tooltip-hovercard"
547 <i class="icon-info-circled tooltip-hovercard"
548 data-hovercard-alt="ALT"
548 data-hovercard-alt="ALT"
@@ -32,8 +32,6 b''
32 %>
32 %>
33
33
34 <script type="text/javascript">
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 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
35 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
38 templateContext.pull_request_data.pull_request_version = '${request.GET.get('version', '')}';
36 templateContext.pull_request_data.pull_request_version = '${request.GET.get('version', '')}';
39 </script>
37 </script>
General Comments 0
You need to be logged in to leave comments. Login now