Show More
@@ -252,7 +252,7 b' But please check this code' | |||||
252 | var comment = $('#comment-'+commentId); |
|
252 | var comment = $('#comment-'+commentId); | |
253 | var commentData = comment.data(); |
|
253 | var commentData = comment.data(); | |
254 | if (commentData.commentInline) { |
|
254 | if (commentData.commentInline) { | |
255 | this.createComment(comment, commentId) |
|
255 | this.createComment(comment, f_path, line_no, commentId) | |
256 | } else { |
|
256 | } else { | |
257 | Rhodecode.comments.createGeneralComment('general', "$placeholder", commentId) |
|
257 | Rhodecode.comments.createGeneralComment('general', "$placeholder", commentId) | |
258 | } |
|
258 | } |
@@ -383,6 +383,9 b' class RepoCommitsView(RepoAppView):' | |||||
383 | text = self.request.POST.get('text') |
|
383 | text = self.request.POST.get('text') | |
384 | comment_type = self.request.POST.get('comment_type') |
|
384 | comment_type = self.request.POST.get('comment_type') | |
385 | resolves_comment_id = self.request.POST.get('resolves_comment_id', None) |
|
385 | resolves_comment_id = self.request.POST.get('resolves_comment_id', None) | |
|
386 | f_path = self.request.POST.get('f_path') | |||
|
387 | line_no = self.request.POST.get('line') | |||
|
388 | target_elem_id = 'file-{}'.format(h.safeid(h.safe_unicode(f_path))) | |||
386 |
|
389 | |||
387 | if status: |
|
390 | if status: | |
388 | text = text or (_('Status change %(transition_icon)s %(status)s') |
|
391 | text = text or (_('Status change %(transition_icon)s %(status)s') | |
@@ -404,8 +407,8 b' class RepoCommitsView(RepoAppView):' | |||||
404 | repo=self.db_repo.repo_id, |
|
407 | repo=self.db_repo.repo_id, | |
405 | user=self._rhodecode_db_user.user_id, |
|
408 | user=self._rhodecode_db_user.user_id, | |
406 | commit_id=current_id, |
|
409 | commit_id=current_id, | |
407 |
f_path= |
|
410 | f_path=f_path, | |
408 |
line_no= |
|
411 | line_no=line_no, | |
409 | status_change=(ChangesetStatus.get_status_lbl(status) |
|
412 | status_change=(ChangesetStatus.get_status_lbl(status) | |
410 | if status else None), |
|
413 | if status else None), | |
411 | status_change_type=status, |
|
414 | status_change_type=status, | |
@@ -447,19 +450,20 b' class RepoCommitsView(RepoAppView):' | |||||
447 | # finalize, commit and redirect |
|
450 | # finalize, commit and redirect | |
448 | Session().commit() |
|
451 | Session().commit() | |
449 |
|
452 | |||
450 | data = { |
|
453 | data = {} | |
451 | 'target_id': h.safeid(h.safe_unicode( |
|
|||
452 | self.request.POST.get('f_path'))), |
|
|||
453 | } |
|
|||
454 | if comment: |
|
454 | if comment: | |
|
455 | comment_id = comment.comment_id | |||
|
456 | data[comment_id] = { | |||
|
457 | 'target_id': target_elem_id | |||
|
458 | } | |||
455 | c.co = comment |
|
459 | c.co = comment | |
456 | c.at_version_num = 0 |
|
460 | c.at_version_num = 0 | |
457 | rendered_comment = render( |
|
461 | rendered_comment = render( | |
458 | 'rhodecode:templates/changeset/changeset_comment_block.mako', |
|
462 | 'rhodecode:templates/changeset/changeset_comment_block.mako', | |
459 | self._get_template_context(c), self.request) |
|
463 | self._get_template_context(c), self.request) | |
460 |
|
464 | |||
461 | data.update(comment.get_dict()) |
|
465 | data[comment_id].update(comment.get_dict()) | |
462 | data.update({'rendered_text': rendered_comment}) |
|
466 | data[comment_id].update({'rendered_text': rendered_comment}) | |
463 |
|
467 | |||
464 | comment_broadcast_channel = channelstream.comment_channel( |
|
468 | comment_broadcast_channel = channelstream.comment_channel( | |
465 | self.db_repo_name, commit_obj=commit) |
|
469 | self.db_repo_name, commit_obj=commit) |
@@ -983,8 +983,9 b' class RepoPullRequestsView(RepoAppView, ' | |||||
983 | } |
|
983 | } | |
984 | return data |
|
984 | return data | |
985 |
|
985 | |||
986 | def _get_existing_ids(self, post_data): |
|
986 | @classmethod | |
987 | return filter(lambda e: e, map(safe_int, aslist(post_data.get('comments'), ','))) |
|
987 | def get_comment_ids(cls, post_data): | |
|
988 | return filter(lambda e: e > 0, map(safe_int, aslist(post_data.get('comments'), ','))) | |||
988 |
|
989 | |||
989 | @LoginRequired() |
|
990 | @LoginRequired() | |
990 | @NotAnonymous() |
|
991 | @NotAnonymous() | |
@@ -1022,7 +1023,7 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1022 | self.register_comments_vars(c, pull_request_latest, versions, include_drafts=False) |
|
1023 | self.register_comments_vars(c, pull_request_latest, versions, include_drafts=False) | |
1023 | all_comments = c.inline_comments_flat + c.comments |
|
1024 | all_comments = c.inline_comments_flat + c.comments | |
1024 |
|
1025 | |||
1025 |
existing_ids = self. |
|
1026 | existing_ids = self.get_comment_ids(self.request.POST) | |
1026 | return _render('comments_table', all_comments, len(all_comments), |
|
1027 | return _render('comments_table', all_comments, len(all_comments), | |
1027 | existing_ids=existing_ids) |
|
1028 | existing_ids=existing_ids) | |
1028 |
|
1029 | |||
@@ -1064,7 +1065,7 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1064 | .get_pull_request_resolved_todos(pull_request, include_drafts=False) |
|
1065 | .get_pull_request_resolved_todos(pull_request, include_drafts=False) | |
1065 |
|
1066 | |||
1066 | all_comments = c.unresolved_comments + c.resolved_comments |
|
1067 | all_comments = c.unresolved_comments + c.resolved_comments | |
1067 |
existing_ids = self. |
|
1068 | existing_ids = self.get_comment_ids(self.request.POST) | |
1068 | return _render('comments_table', all_comments, len(c.unresolved_comments), |
|
1069 | return _render('comments_table', all_comments, len(c.unresolved_comments), | |
1069 | todo_comments=True, existing_ids=existing_ids) |
|
1070 | todo_comments=True, existing_ids=existing_ids) | |
1070 |
|
1071 | |||
@@ -1518,6 +1519,150 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1518 | self._rhodecode_user) |
|
1519 | self._rhodecode_user) | |
1519 | raise HTTPNotFound() |
|
1520 | raise HTTPNotFound() | |
1520 |
|
1521 | |||
|
1522 | def _pull_request_comments_create(self, pull_request, comments): | |||
|
1523 | _ = self.request.translate | |||
|
1524 | data = {} | |||
|
1525 | pull_request_id = pull_request.pull_request_id | |||
|
1526 | if not comments: | |||
|
1527 | return | |||
|
1528 | ||||
|
1529 | all_drafts = len([x for x in comments if str2bool(x['is_draft'])]) == len(comments) | |||
|
1530 | ||||
|
1531 | for entry in comments: | |||
|
1532 | c = self.load_default_context() | |||
|
1533 | comment_type = entry['comment_type'] | |||
|
1534 | text = entry['text'] | |||
|
1535 | status = entry['status'] | |||
|
1536 | is_draft = str2bool(entry['is_draft']) | |||
|
1537 | resolves_comment_id = entry['resolves_comment_id'] | |||
|
1538 | close_pull_request = entry['close_pull_request'] | |||
|
1539 | f_path = entry['f_path'] | |||
|
1540 | line_no = entry['line'] | |||
|
1541 | target_elem_id = 'file-{}'.format(h.safeid(h.safe_unicode(f_path))) | |||
|
1542 | ||||
|
1543 | # the logic here should work like following, if we submit close | |||
|
1544 | # pr comment, use `close_pull_request_with_comment` function | |||
|
1545 | # else handle regular comment logic | |||
|
1546 | ||||
|
1547 | if close_pull_request: | |||
|
1548 | # only owner or admin or person with write permissions | |||
|
1549 | allowed_to_close = PullRequestModel().check_user_update( | |||
|
1550 | pull_request, self._rhodecode_user) | |||
|
1551 | if not allowed_to_close: | |||
|
1552 | log.debug('comment: forbidden because not allowed to close ' | |||
|
1553 | 'pull request %s', pull_request_id) | |||
|
1554 | raise HTTPForbidden() | |||
|
1555 | ||||
|
1556 | # This also triggers `review_status_change` | |||
|
1557 | comment, status = PullRequestModel().close_pull_request_with_comment( | |||
|
1558 | pull_request, self._rhodecode_user, self.db_repo, message=text, | |||
|
1559 | auth_user=self._rhodecode_user) | |||
|
1560 | Session().flush() | |||
|
1561 | is_inline = comment.is_inline | |||
|
1562 | ||||
|
1563 | PullRequestModel().trigger_pull_request_hook( | |||
|
1564 | pull_request, self._rhodecode_user, 'comment', | |||
|
1565 | data={'comment': comment}) | |||
|
1566 | ||||
|
1567 | else: | |||
|
1568 | # regular comment case, could be inline, or one with status. | |||
|
1569 | # for that one we check also permissions | |||
|
1570 | # Additionally ENSURE if somehow draft is sent we're then unable to change status | |||
|
1571 | allowed_to_change_status = PullRequestModel().check_user_change_status( | |||
|
1572 | pull_request, self._rhodecode_user) and not is_draft | |||
|
1573 | ||||
|
1574 | if status and allowed_to_change_status: | |||
|
1575 | message = (_('Status change %(transition_icon)s %(status)s') | |||
|
1576 | % {'transition_icon': '>', | |||
|
1577 | 'status': ChangesetStatus.get_status_lbl(status)}) | |||
|
1578 | text = text or message | |||
|
1579 | ||||
|
1580 | comment = CommentsModel().create( | |||
|
1581 | text=text, | |||
|
1582 | repo=self.db_repo.repo_id, | |||
|
1583 | user=self._rhodecode_user.user_id, | |||
|
1584 | pull_request=pull_request, | |||
|
1585 | f_path=f_path, | |||
|
1586 | line_no=line_no, | |||
|
1587 | status_change=(ChangesetStatus.get_status_lbl(status) | |||
|
1588 | if status and allowed_to_change_status else None), | |||
|
1589 | status_change_type=(status | |||
|
1590 | if status and allowed_to_change_status else None), | |||
|
1591 | comment_type=comment_type, | |||
|
1592 | is_draft=is_draft, | |||
|
1593 | resolves_comment_id=resolves_comment_id, | |||
|
1594 | auth_user=self._rhodecode_user, | |||
|
1595 | send_email=not is_draft, # skip notification for draft comments | |||
|
1596 | ) | |||
|
1597 | is_inline = comment.is_inline | |||
|
1598 | ||||
|
1599 | if allowed_to_change_status: | |||
|
1600 | # calculate old status before we change it | |||
|
1601 | old_calculated_status = pull_request.calculated_review_status() | |||
|
1602 | ||||
|
1603 | # get status if set ! | |||
|
1604 | if status: | |||
|
1605 | ChangesetStatusModel().set_status( | |||
|
1606 | self.db_repo.repo_id, | |||
|
1607 | status, | |||
|
1608 | self._rhodecode_user.user_id, | |||
|
1609 | comment, | |||
|
1610 | pull_request=pull_request | |||
|
1611 | ) | |||
|
1612 | ||||
|
1613 | Session().flush() | |||
|
1614 | # this is somehow required to get access to some relationship | |||
|
1615 | # loaded on comment | |||
|
1616 | Session().refresh(comment) | |||
|
1617 | ||||
|
1618 | PullRequestModel().trigger_pull_request_hook( | |||
|
1619 | pull_request, self._rhodecode_user, 'comment', | |||
|
1620 | data={'comment': comment}) | |||
|
1621 | ||||
|
1622 | # we now calculate the status of pull request, and based on that | |||
|
1623 | # calculation we set the commits status | |||
|
1624 | calculated_status = pull_request.calculated_review_status() | |||
|
1625 | if old_calculated_status != calculated_status: | |||
|
1626 | PullRequestModel().trigger_pull_request_hook( | |||
|
1627 | pull_request, self._rhodecode_user, 'review_status_change', | |||
|
1628 | data={'status': calculated_status}) | |||
|
1629 | ||||
|
1630 | comment_id = comment.comment_id | |||
|
1631 | data[comment_id] = { | |||
|
1632 | 'target_id': target_elem_id | |||
|
1633 | } | |||
|
1634 | Session().flush() | |||
|
1635 | ||||
|
1636 | c.co = comment | |||
|
1637 | c.at_version_num = None | |||
|
1638 | c.is_new = True | |||
|
1639 | rendered_comment = render( | |||
|
1640 | 'rhodecode:templates/changeset/changeset_comment_block.mako', | |||
|
1641 | self._get_template_context(c), self.request) | |||
|
1642 | ||||
|
1643 | data[comment_id].update(comment.get_dict()) | |||
|
1644 | data[comment_id].update({'rendered_text': rendered_comment}) | |||
|
1645 | ||||
|
1646 | Session().commit() | |||
|
1647 | ||||
|
1648 | # skip channelstream for draft comments | |||
|
1649 | if all_drafts: | |||
|
1650 | comment_broadcast_channel = channelstream.comment_channel( | |||
|
1651 | self.db_repo_name, pull_request_obj=pull_request) | |||
|
1652 | ||||
|
1653 | comment_data = data | |||
|
1654 | comment_type = 'inline' if is_inline else 'general' | |||
|
1655 | if len(data) == 1: | |||
|
1656 | msg = _('posted {} new {} comment').format(len(data), comment_type) | |||
|
1657 | else: | |||
|
1658 | msg = _('posted {} new {} comments').format(len(data), comment_type) | |||
|
1659 | ||||
|
1660 | channelstream.comment_channelstream_push( | |||
|
1661 | self.request, comment_broadcast_channel, self._rhodecode_user, msg, | |||
|
1662 | comment_data=comment_data) | |||
|
1663 | ||||
|
1664 | return data | |||
|
1665 | ||||
1521 | @LoginRequired() |
|
1666 | @LoginRequired() | |
1522 | @NotAnonymous() |
|
1667 | @NotAnonymous() | |
1523 | @HasRepoPermissionAnyDecorator( |
|
1668 | @HasRepoPermissionAnyDecorator( | |
@@ -1529,9 +1674,7 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1529 | def pull_request_comment_create(self): |
|
1674 | def pull_request_comment_create(self): | |
1530 | _ = self.request.translate |
|
1675 | _ = self.request.translate | |
1531 |
|
1676 | |||
1532 | pull_request = PullRequest.get_or_404( |
|
1677 | pull_request = PullRequest.get_or_404(self.request.matchdict['pull_request_id']) | |
1533 | self.request.matchdict['pull_request_id']) |
|
|||
1534 | pull_request_id = pull_request.pull_request_id |
|
|||
1535 |
|
1678 | |||
1536 | if pull_request.is_closed(): |
|
1679 | if pull_request.is_closed(): | |
1537 | log.debug('comment: forbidden because pull request is closed') |
|
1680 | log.debug('comment: forbidden because pull request is closed') | |
@@ -1543,130 +1686,17 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1543 | log.debug('comment: forbidden because pull request is from forbidden repo') |
|
1686 | log.debug('comment: forbidden because pull request is from forbidden repo') | |
1544 | raise HTTPForbidden() |
|
1687 | raise HTTPForbidden() | |
1545 |
|
1688 | |||
1546 | c = self.load_default_context() |
|
1689 | comment_data = { | |
1547 |
|
1690 | 'comment_type': self.request.POST.get('comment_type'), | ||
1548 |
|
|
1691 | 'text': self.request.POST.get('text'), | |
1549 |
|
|
1692 | 'status': self.request.POST.get('changeset_status', None), | |
1550 |
|
|
1693 | 'is_draft': self.request.POST.get('draft'), | |
1551 | is_draft = str2bool(self.request.POST.get('draft')) |
|
1694 | 'resolves_comment_id': self.request.POST.get('resolves_comment_id', None), | |
1552 | resolves_comment_id = self.request.POST.get('resolves_comment_id', None) |
|
1695 | 'close_pull_request': self.request.POST.get('close_pull_request'), | |
1553 |
|
|
1696 | 'f_path': self.request.POST.get('f_path'), | |
1554 |
|
1697 | 'line': self.request.POST.get('line'), | ||
1555 | # the logic here should work like following, if we submit close |
|
|||
1556 | # pr comment, use `close_pull_request_with_comment` function |
|
|||
1557 | # else handle regular comment logic |
|
|||
1558 |
|
||||
1559 | if close_pull_request: |
|
|||
1560 | # only owner or admin or person with write permissions |
|
|||
1561 | allowed_to_close = PullRequestModel().check_user_update( |
|
|||
1562 | pull_request, self._rhodecode_user) |
|
|||
1563 | if not allowed_to_close: |
|
|||
1564 | log.debug('comment: forbidden because not allowed to close ' |
|
|||
1565 | 'pull request %s', pull_request_id) |
|
|||
1566 | raise HTTPForbidden() |
|
|||
1567 |
|
||||
1568 | # This also triggers `review_status_change` |
|
|||
1569 | comment, status = PullRequestModel().close_pull_request_with_comment( |
|
|||
1570 | pull_request, self._rhodecode_user, self.db_repo, message=text, |
|
|||
1571 | auth_user=self._rhodecode_user) |
|
|||
1572 | Session().flush() |
|
|||
1573 | is_inline = comment.is_inline |
|
|||
1574 |
|
||||
1575 | PullRequestModel().trigger_pull_request_hook( |
|
|||
1576 | pull_request, self._rhodecode_user, 'comment', |
|
|||
1577 | data={'comment': comment}) |
|
|||
1578 |
|
||||
1579 | else: |
|
|||
1580 | # regular comment case, could be inline, or one with status. |
|
|||
1581 | # for that one we check also permissions |
|
|||
1582 | # Additionally ENSURE if somehow draft is sent we're then unable to change status |
|
|||
1583 | allowed_to_change_status = PullRequestModel().check_user_change_status( |
|
|||
1584 | pull_request, self._rhodecode_user) and not is_draft |
|
|||
1585 |
|
||||
1586 | if status and allowed_to_change_status: |
|
|||
1587 | message = (_('Status change %(transition_icon)s %(status)s') |
|
|||
1588 | % {'transition_icon': '>', |
|
|||
1589 | 'status': ChangesetStatus.get_status_lbl(status)}) |
|
|||
1590 | text = text or message |
|
|||
1591 |
|
||||
1592 | comment = CommentsModel().create( |
|
|||
1593 | text=text, |
|
|||
1594 | repo=self.db_repo.repo_id, |
|
|||
1595 | user=self._rhodecode_user.user_id, |
|
|||
1596 | pull_request=pull_request, |
|
|||
1597 | f_path=self.request.POST.get('f_path'), |
|
|||
1598 | line_no=self.request.POST.get('line'), |
|
|||
1599 | status_change=(ChangesetStatus.get_status_lbl(status) |
|
|||
1600 | if status and allowed_to_change_status else None), |
|
|||
1601 | status_change_type=(status |
|
|||
1602 | if status and allowed_to_change_status else None), |
|
|||
1603 | comment_type=comment_type, |
|
|||
1604 | is_draft=is_draft, |
|
|||
1605 | resolves_comment_id=resolves_comment_id, |
|
|||
1606 | auth_user=self._rhodecode_user, |
|
|||
1607 | send_email=not is_draft, # skip notification for draft comments |
|
|||
1608 | ) |
|
|||
1609 | is_inline = comment.is_inline |
|
|||
1610 |
|
||||
1611 | if allowed_to_change_status: |
|
|||
1612 | # calculate old status before we change it |
|
|||
1613 | old_calculated_status = pull_request.calculated_review_status() |
|
|||
1614 |
|
||||
1615 | # get status if set ! |
|
|||
1616 | if status: |
|
|||
1617 | ChangesetStatusModel().set_status( |
|
|||
1618 | self.db_repo.repo_id, |
|
|||
1619 | status, |
|
|||
1620 | self._rhodecode_user.user_id, |
|
|||
1621 | comment, |
|
|||
1622 | pull_request=pull_request |
|
|||
1623 | ) |
|
|||
1624 |
|
||||
1625 | Session().flush() |
|
|||
1626 | # this is somehow required to get access to some relationship |
|
|||
1627 | # loaded on comment |
|
|||
1628 | Session().refresh(comment) |
|
|||
1629 |
|
||||
1630 | PullRequestModel().trigger_pull_request_hook( |
|
|||
1631 | pull_request, self._rhodecode_user, 'comment', |
|
|||
1632 | data={'comment': comment}) |
|
|||
1633 |
|
||||
1634 | # we now calculate the status of pull request, and based on that |
|
|||
1635 | # calculation we set the commits status |
|
|||
1636 | calculated_status = pull_request.calculated_review_status() |
|
|||
1637 | if old_calculated_status != calculated_status: |
|
|||
1638 | PullRequestModel().trigger_pull_request_hook( |
|
|||
1639 | pull_request, self._rhodecode_user, 'review_status_change', |
|
|||
1640 | data={'status': calculated_status}) |
|
|||
1641 |
|
||||
1642 | Session().commit() |
|
|||
1643 |
|
||||
1644 | data = { |
|
|||
1645 | 'target_id': h.safeid(h.safe_unicode( |
|
|||
1646 | self.request.POST.get('f_path'))), |
|
|||
1647 | } |
|
1698 | } | |
1648 |
|
1699 | data = self._pull_request_comments_create(pull_request, [comment_data]) | ||
1649 | if comment: |
|
|||
1650 | c.co = comment |
|
|||
1651 | c.at_version_num = None |
|
|||
1652 | rendered_comment = render( |
|
|||
1653 | 'rhodecode:templates/changeset/changeset_comment_block.mako', |
|
|||
1654 | self._get_template_context(c), self.request) |
|
|||
1655 |
|
||||
1656 | data.update(comment.get_dict()) |
|
|||
1657 | data.update({'rendered_text': rendered_comment}) |
|
|||
1658 |
|
||||
1659 | # skip channelstream for draft comments |
|
|||
1660 | if not is_draft: |
|
|||
1661 | comment_broadcast_channel = channelstream.comment_channel( |
|
|||
1662 | self.db_repo_name, pull_request_obj=pull_request) |
|
|||
1663 |
|
||||
1664 | comment_data = data |
|
|||
1665 | comment_type = 'inline' if is_inline else 'general' |
|
|||
1666 | channelstream.comment_channelstream_push( |
|
|||
1667 | self.request, comment_broadcast_channel, self._rhodecode_user, |
|
|||
1668 | _('posted a new {} comment').format(comment_type), |
|
|||
1669 | comment_data=comment_data) |
|
|||
1670 |
|
1700 | |||
1671 | return data |
|
1701 | return data | |
1672 |
|
1702 |
@@ -339,13 +339,12 b' def comment_channelstream_push(request, ' | |||||
339 |
|
339 | |||
340 | comment_data = kwargs.pop('comment_data', {}) |
|
340 | comment_data = kwargs.pop('comment_data', {}) | |
341 | user_data = kwargs.pop('user_data', {}) |
|
341 | user_data = kwargs.pop('user_data', {}) | |
342 |
comment_id = comment_data. |
|
342 | comment_id = comment_data.keys()[0] if comment_data else '' | |
343 |
|
343 | |||
344 |
message = '<strong>{}</strong> {} #{} |
|
344 | message = '<strong>{}</strong> {} #{}'.format( | |
345 | user.username, |
|
345 | user.username, | |
346 | msg, |
|
346 | msg, | |
347 | comment_id, |
|
347 | comment_id, | |
348 | _reload_link(_('Reload page to see new comments')), |
|
|||
349 | ) |
|
348 | ) | |
350 |
|
349 | |||
351 | message_obj = { |
|
350 | message_obj = { |
@@ -1148,7 +1148,7 b' class DiffLimitExceeded(Exception):' | |||||
1148 |
|
1148 | |||
1149 | # NOTE(marcink): if diffs.mako change, probably this |
|
1149 | # NOTE(marcink): if diffs.mako change, probably this | |
1150 | # needs a bump to next version |
|
1150 | # needs a bump to next version | |
1151 |
CURRENT_DIFF_VERSION = 'v |
|
1151 | CURRENT_DIFF_VERSION = 'v5' | |
1152 |
|
1152 | |||
1153 |
|
1153 | |||
1154 | def _cleanup_cache_file(cached_diff_file): |
|
1154 | def _cleanup_cache_file(cached_diff_file): |
@@ -370,7 +370,7 b' input[type="button"] {' | |||||
370 | color: @alert2; |
|
370 | color: @alert2; | |
371 |
|
371 | |||
372 | &:hover { |
|
372 | &:hover { | |
373 | color: darken(@alert2,30%); |
|
373 | color: darken(@alert2, 30%); | |
374 | } |
|
374 | } | |
375 |
|
375 | |||
376 | &:disabled { |
|
376 | &:disabled { |
@@ -1002,7 +1002,7 b' input.filediff-collapse-state {' | |||||
1002 | .nav-chunk { |
|
1002 | .nav-chunk { | |
1003 | position: absolute; |
|
1003 | position: absolute; | |
1004 | right: 20px; |
|
1004 | right: 20px; | |
1005 |
margin-top: -1 |
|
1005 | margin-top: -15px; | |
1006 | } |
|
1006 | } | |
1007 |
|
1007 | |||
1008 | .nav-chunk.selected { |
|
1008 | .nav-chunk.selected { |
@@ -4,7 +4,7 b'' | |||||
4 |
|
4 | |||
5 |
|
5 | |||
6 | // Comments |
|
6 | // Comments | |
7 |
@comment-outdated-opacity: 0 |
|
7 | @comment-outdated-opacity: 1.0; | |
8 |
|
8 | |||
9 | .comments { |
|
9 | .comments { | |
10 | width: 100%; |
|
10 | width: 100%; | |
@@ -64,32 +64,34 b' tr.inline-comments div {' | |||||
64 | .comment-draft { |
|
64 | .comment-draft { | |
65 | float: left; |
|
65 | float: left; | |
66 | margin-right: 10px; |
|
66 | margin-right: 10px; | |
67 |
font-weight: |
|
67 | font-weight: 400; | |
68 |
color: @ |
|
68 | color: @color-draft; | |
|
69 | } | |||
|
70 | ||||
|
71 | .comment-new { | |||
|
72 | float: left; | |||
|
73 | margin-right: 10px; | |||
|
74 | font-weight: 400; | |||
|
75 | color: @color-new; | |||
69 | } |
|
76 | } | |
70 |
|
77 | |||
71 | .comment-label { |
|
78 | .comment-label { | |
72 | float: left; |
|
79 | float: left; | |
73 |
|
80 | |||
74 |
padding: 0 |
|
81 | padding: 0 8px 0 0; | |
75 | margin: 2px 4px 0px 0px; |
|
|||
76 | display: inline-block; |
|
|||
77 | min-height: 0; |
|
82 | min-height: 0; | |
78 |
|
83 | |||
79 | text-align: center; |
|
84 | text-align: center; | |
80 | font-size: 10px; |
|
85 | font-size: 10px; | |
81 | line-height: .8em; |
|
|||
82 |
|
86 | |||
83 | font-family: @text-italic; |
|
87 | font-family: @text-italic; | |
84 | font-style: italic; |
|
88 | font-style: italic; | |
85 | background: #fff none; |
|
89 | background: #fff none; | |
86 | color: @grey3; |
|
90 | color: @grey3; | |
87 | border: 1px solid @grey4; |
|
|||
88 | white-space: nowrap; |
|
91 | white-space: nowrap; | |
89 |
|
92 | |||
90 | text-transform: uppercase; |
|
93 | text-transform: uppercase; | |
91 | min-width: 50px; |
|
94 | min-width: 50px; | |
92 | border-radius: 4px; |
|
|||
93 |
|
95 | |||
94 | &.todo { |
|
96 | &.todo { | |
95 | color: @color5; |
|
97 | color: @color5; | |
@@ -277,64 +279,165 b' tr.inline-comments div {' | |||||
277 | .comment-outdated { |
|
279 | .comment-outdated { | |
278 | opacity: @comment-outdated-opacity; |
|
280 | opacity: @comment-outdated-opacity; | |
279 | } |
|
281 | } | |
|
282 | ||||
|
283 | .comment-outdated-label { | |||
|
284 | color: @grey3; | |||
|
285 | padding-right: 4px; | |||
|
286 | } | |||
280 | } |
|
287 | } | |
281 |
|
288 | |||
282 | .inline-comments { |
|
289 | .inline-comments { | |
283 | border-radius: @border-radius; |
|
290 | ||
284 | .comment { |
|
291 | .comment { | |
285 | margin: 0; |
|
292 | margin: 0; | |
286 | border-radius: @border-radius; |
|
|||
287 | } |
|
293 | } | |
|
294 | ||||
288 | .comment-outdated { |
|
295 | .comment-outdated { | |
289 | opacity: @comment-outdated-opacity; |
|
296 | opacity: @comment-outdated-opacity; | |
290 | } |
|
297 | } | |
291 |
|
298 | |||
|
299 | .comment-outdated-label { | |||
|
300 | color: @grey3; | |||
|
301 | padding-right: 4px; | |||
|
302 | } | |||
|
303 | ||||
292 | .comment-inline { |
|
304 | .comment-inline { | |
|
305 | ||||
|
306 | &:first-child { | |||
|
307 | margin: 4px 4px 0 4px; | |||
|
308 | border-top: 1px solid @grey5; | |||
|
309 | border-bottom: 0 solid @grey5; | |||
|
310 | border-left: 1px solid @grey5; | |||
|
311 | border-right: 1px solid @grey5; | |||
|
312 | .border-radius-top(4px); | |||
|
313 | } | |||
|
314 | ||||
|
315 | &:only-child { | |||
|
316 | margin: 4px 4px 0 4px; | |||
|
317 | border-top: 1px solid @grey5; | |||
|
318 | border-bottom: 0 solid @grey5; | |||
|
319 | border-left: 1px solid @grey5; | |||
|
320 | border-right: 1px solid @grey5; | |||
|
321 | .border-radius-top(4px); | |||
|
322 | } | |||
|
323 | ||||
293 | background: white; |
|
324 | background: white; | |
294 | padding: @comment-padding @comment-padding; |
|
325 | padding: @comment-padding @comment-padding; | |
295 | border: @comment-padding solid @grey6; |
|
326 | margin: 0 4px 0 4px; | |
|
327 | border-top: 0 solid @grey5; | |||
|
328 | border-bottom: 0 solid @grey5; | |||
|
329 | border-left: 1px solid @grey5; | |||
|
330 | border-right: 1px solid @grey5; | |||
296 |
|
331 | |||
297 | .text { |
|
332 | .text { | |
298 | border: none; |
|
333 | border: none; | |
299 | } |
|
334 | } | |
|
335 | ||||
300 | .meta { |
|
336 | .meta { | |
301 | border-bottom: 1px solid @grey6; |
|
337 | border-bottom: 1px solid @grey6; | |
302 | margin: -5px 0px; |
|
338 | margin: -5px 0px; | |
303 | line-height: 24px; |
|
339 | line-height: 24px; | |
304 | } |
|
340 | } | |
|
341 | ||||
305 | } |
|
342 | } | |
306 | .comment-selected { |
|
343 | .comment-selected { | |
307 | border-left: 6px solid @comment-highlight-color; |
|
344 | border-left: 6px solid @comment-highlight-color; | |
308 | } |
|
345 | } | |
|
346 | ||||
|
347 | .comment-inline-form-open { | |||
|
348 | display: block !important; | |||
|
349 | } | |||
|
350 | ||||
309 | .comment-inline-form { |
|
351 | .comment-inline-form { | |
310 | padding: @comment-padding; |
|
|||
311 | display: none; |
|
352 | display: none; | |
312 | } |
|
353 | } | |
313 | .cb-comment-add-button { |
|
354 | ||
314 | margin: @comment-padding; |
|
355 | .comment-inline-form-edit { | |
|
356 | padding: 0; | |||
|
357 | margin: 0px 4px 2px 4px; | |||
|
358 | } | |||
|
359 | ||||
|
360 | .reply-thread-container { | |||
|
361 | display: table; | |||
|
362 | width: 100%; | |||
|
363 | padding: 0px 4px 4px 4px; | |||
|
364 | } | |||
|
365 | ||||
|
366 | .reply-thread-container-wrapper { | |||
|
367 | margin: 0 4px 4px 4px; | |||
|
368 | border-top: 0 solid @grey5; | |||
|
369 | border-bottom: 1px solid @grey5; | |||
|
370 | border-left: 1px solid @grey5; | |||
|
371 | border-right: 1px solid @grey5; | |||
|
372 | .border-radius-bottom(4px); | |||
|
373 | } | |||
|
374 | ||||
|
375 | .reply-thread-gravatar { | |||
|
376 | display: table-cell; | |||
|
377 | width: 24px; | |||
|
378 | height: 24px; | |||
|
379 | padding-top: 10px; | |||
|
380 | padding-left: 10px; | |||
|
381 | background-color: #eeeeee; | |||
|
382 | vertical-align: top; | |||
315 | } |
|
383 | } | |
316 | /* hide add comment button when form is open */ |
|
384 | ||
|
385 | .reply-thread-reply-button { | |||
|
386 | display: table-cell; | |||
|
387 | width: 100%; | |||
|
388 | height: 33px; | |||
|
389 | padding: 3px 8px; | |||
|
390 | margin-left: 8px; | |||
|
391 | background-color: #eeeeee; | |||
|
392 | } | |||
|
393 | ||||
|
394 | .reply-thread-reply-button .cb-comment-add-button { | |||
|
395 | border-radius: 4px; | |||
|
396 | width: 100%; | |||
|
397 | padding: 6px 2px; | |||
|
398 | text-align: left; | |||
|
399 | cursor: text; | |||
|
400 | color: @grey3; | |||
|
401 | } | |||
|
402 | .reply-thread-reply-button .cb-comment-add-button:hover { | |||
|
403 | background-color: white; | |||
|
404 | color: @grey2; | |||
|
405 | } | |||
|
406 | ||||
|
407 | .reply-thread-last { | |||
|
408 | display: table-cell; | |||
|
409 | width: 10px; | |||
|
410 | } | |||
|
411 | ||||
|
412 | /* Hide reply box when it's a first element, | |||
|
413 | can happen when drafts are saved but not shown to specific user, | |||
|
414 | or there are outdated comments hidden | |||
|
415 | */ | |||
|
416 | .reply-thread-container-wrapper:first-child:not(.comment-form-active) { | |||
|
417 | display: none; | |||
|
418 | } | |||
|
419 | ||||
|
420 | .reply-thread-container-wrapper.comment-outdated { | |||
|
421 | display: none | |||
|
422 | } | |||
|
423 | ||||
|
424 | /* hide add comment button when form is open */ | |||
317 | .comment-inline-form-open ~ .cb-comment-add-button { |
|
425 | .comment-inline-form-open ~ .cb-comment-add-button { | |
318 | display: none; |
|
426 | display: none; | |
319 | } |
|
427 | } | |
320 | .comment-inline-form-open { |
|
428 | ||
321 | display: block; |
|
|||
322 | } |
|
|||
323 | /* hide add comment button when form but no comments */ |
|
|||
324 | .comment-inline-form:first-child + .cb-comment-add-button { |
|
|||
325 | display: none; |
|
|||
326 | } |
|
|||
327 | /* hide add comment button when no comments or form */ |
|
|||
328 | .cb-comment-add-button:first-child { |
|
|||
329 | display: none; |
|
|||
330 | } |
|
|||
331 | /* hide add comment button when only comment is being deleted */ |
|
429 | /* hide add comment button when only comment is being deleted */ | |
332 | .comment-deleting:first-child + .cb-comment-add-button { |
|
430 | .comment-deleting:first-child + .cb-comment-add-button { | |
333 | display: none; |
|
431 | display: none; | |
334 | } |
|
432 | } | |
|
433 | ||||
|
434 | /* hide add comment button when form but no comments */ | |||
|
435 | .comment-inline-form:first-child + .cb-comment-add-button { | |||
|
436 | display: none; | |||
|
437 | } | |||
|
438 | ||||
335 | } |
|
439 | } | |
336 |
|
440 | |||
337 |
|
||||
338 | .show-outdated-comments { |
|
441 | .show-outdated-comments { | |
339 | display: inline; |
|
442 | display: inline; | |
340 | color: @rcblue; |
|
443 | color: @rcblue; | |
@@ -387,23 +490,40 b' form.comment-form {' | |||||
387 | } |
|
490 | } | |
388 |
|
491 | |||
389 | .comment-footer { |
|
492 | .comment-footer { | |
390 | position: relative; |
|
493 | display: table; | |
391 | width: 100%; |
|
494 | width: 100%; | |
392 |
|
|
495 | height: 42px; | |
393 |
|
496 | |||
394 |
.status |
|
497 | .comment-status-box, | |
395 | .cancel-button { |
|
498 | .cancel-button { | |
396 | float: left; |
|
|||
397 | display: inline-block; |
|
499 | display: inline-block; | |
398 | } |
|
500 | } | |
399 |
|
501 | |||
400 |
.status |
|
502 | .comment-status-box { | |
401 | margin-left: 10px; |
|
503 | margin-left: 10px; | |
402 | } |
|
504 | } | |
403 |
|
505 | |||
404 | .action-buttons { |
|
506 | .action-buttons { | |
405 |
|
|
507 | display: table-cell; | |
406 | display: inline-block; |
|
508 | padding: 5px 0 5px 2px; | |
|
509 | } | |||
|
510 | ||||
|
511 | .toolbar-text { | |||
|
512 | height: 42px; | |||
|
513 | display: table-cell; | |||
|
514 | vertical-align: bottom; | |||
|
515 | font-size: 11px; | |||
|
516 | color: @grey4; | |||
|
517 | text-align: right; | |||
|
518 | ||||
|
519 | a { | |||
|
520 | color: @grey4; | |||
|
521 | } | |||
|
522 | ||||
|
523 | p { | |||
|
524 | padding: 0; | |||
|
525 | margin: 0; | |||
|
526 | } | |||
407 | } |
|
527 | } | |
408 |
|
528 | |||
409 | .action-buttons-extra { |
|
529 | .action-buttons-extra { | |
@@ -434,10 +554,6 b' form.comment-form {' | |||||
434 | margin-right: 0; |
|
554 | margin-right: 0; | |
435 | } |
|
555 | } | |
436 |
|
556 | |||
437 | .comment-footer { |
|
|||
438 | margin-bottom: 50px; |
|
|||
439 | margin-top: 10px; |
|
|||
440 | } |
|
|||
441 | } |
|
557 | } | |
442 |
|
558 | |||
443 |
|
559 | |||
@@ -489,8 +605,8 b' form.comment-form {' | |||||
489 | .injected_diff .comment-inline-form, |
|
605 | .injected_diff .comment-inline-form, | |
490 | .comment-inline-form { |
|
606 | .comment-inline-form { | |
491 | background-color: white; |
|
607 | background-color: white; | |
492 |
margin-top: |
|
608 | margin-top: 4px; | |
493 |
margin-bottom: |
|
609 | margin-bottom: 10px; | |
494 | } |
|
610 | } | |
495 |
|
611 | |||
496 | .inline-form { |
|
612 | .inline-form { | |
@@ -526,9 +642,6 b' form.comment-form {' | |||||
526 | margin: 0px; |
|
642 | margin: 0px; | |
527 | } |
|
643 | } | |
528 |
|
644 | |||
529 | .comment-inline-form .comment-footer { |
|
|||
530 | margin: 10px 0px 0px 0px; |
|
|||
531 | } |
|
|||
532 |
|
645 | |||
533 | .hide-inline-form-button { |
|
646 | .hide-inline-form-button { | |
534 | margin-left: 5px; |
|
647 | margin-left: 5px; | |
@@ -554,6 +667,7 b' comment-area-text {' | |||||
554 |
|
667 | |||
555 | .comment-area-header { |
|
668 | .comment-area-header { | |
556 | height: 35px; |
|
669 | height: 35px; | |
|
670 | border-bottom: 1px solid @grey5; | |||
557 | } |
|
671 | } | |
558 |
|
672 | |||
559 | .comment-area-header .nav-links { |
|
673 | .comment-area-header .nav-links { | |
@@ -561,6 +675,7 b' comment-area-text {' | |||||
561 | flex-flow: row wrap; |
|
675 | flex-flow: row wrap; | |
562 | -webkit-flex-flow: row wrap; |
|
676 | -webkit-flex-flow: row wrap; | |
563 | width: 100%; |
|
677 | width: 100%; | |
|
678 | border: none; | |||
564 | } |
|
679 | } | |
565 |
|
680 | |||
566 | .comment-area-footer { |
|
681 | .comment-area-footer { | |
@@ -629,14 +744,3 b' comment-area-text {' | |||||
629 | border-bottom: 2px solid transparent; |
|
744 | border-bottom: 2px solid transparent; | |
630 | } |
|
745 | } | |
631 |
|
746 | |||
632 | .toolbar-text { |
|
|||
633 | float: right; |
|
|||
634 | font-size: 11px; |
|
|||
635 | color: @grey4; |
|
|||
636 | text-align: right; |
|
|||
637 |
|
||||
638 | a { |
|
|||
639 | color: @grey4; |
|
|||
640 | } |
|
|||
641 | } |
|
|||
642 |
|
@@ -3212,7 +3212,12 b' details:not([open]) > :not(summary) {' | |||||
3212 |
|
3212 | |||
3213 | .sidebar-element { |
|
3213 | .sidebar-element { | |
3214 | margin-top: 20px; |
|
3214 | margin-top: 20px; | |
3215 | } |
|
3215 | ||
|
3216 | .icon-draft { | |||
|
3217 | color: @color-draft | |||
|
3218 | } | |||
|
3219 | } | |||
|
3220 | ||||
3216 |
|
3221 | |||
3217 | .right-sidebar-collapsed-state { |
|
3222 | .right-sidebar-collapsed-state { | |
3218 | display: flex; |
|
3223 | display: flex; | |
@@ -3235,5 +3240,4 b' details:not([open]) > :not(summary) {' | |||||
3235 |
|
3240 | |||
3236 | .old-comments-marker td { |
|
3241 | .old-comments-marker td { | |
3237 | padding-top: 15px; |
|
3242 | padding-top: 15px; | |
3238 | border-bottom: 1px solid @grey5; |
|
3243 | } | |
3239 | } |
|
@@ -47,6 +47,8 b'' | |||||
47 |
|
47 | |||
48 | // Highlight color for lines and colors |
|
48 | // Highlight color for lines and colors | |
49 | @comment-highlight-color: #ffd887; |
|
49 | @comment-highlight-color: #ffd887; | |
|
50 | @color-draft: darken(@alert3, 30%); | |||
|
51 | @color-new: darken(@alert1, 5%); | |||
50 |
|
52 | |||
51 | // FONTS |
|
53 | // FONTS | |
52 | @basefontsize: 13px; |
|
54 | @basefontsize: 13px; |
@@ -71,14 +71,20 b' export class RhodecodeApp extends Polyme' | |||||
71 | if (elem) { |
|
71 | if (elem) { | |
72 | elem.handleNotification(data); |
|
72 | elem.handleNotification(data); | |
73 | } |
|
73 | } | |
74 |
|
||||
75 | } |
|
74 | } | |
76 |
|
75 | |||
77 | handleComment(data) { |
|
76 | handleComment(data) { | |
78 | if (data.message.comment_id) { |
|
77 | ||
|
78 | if (data.message.comment_data.length !== 0) { | |||
79 | if (window.refreshAllComments !== undefined) { |
|
79 | if (window.refreshAllComments !== undefined) { | |
80 | refreshAllComments() |
|
80 | refreshAllComments() | |
81 | } |
|
81 | } | |
|
82 | var json_data = data.message.comment_data; | |||
|
83 | ||||
|
84 | if (window.commentsController !== undefined) { | |||
|
85 | ||||
|
86 | window.commentsController.attachComment(json_data) | |||
|
87 | } | |||
82 | } |
|
88 | } | |
83 | } |
|
89 | } | |
84 |
|
90 |
@@ -364,12 +364,15 b' var _submitAjaxPOST = function(url, post' | |||||
364 | postData['close_pull_request'] = true; |
|
364 | postData['close_pull_request'] = true; | |
365 | } |
|
365 | } | |
366 |
|
366 | |||
367 |
|
|
367 | // submitSuccess for general comments | |
|
368 | var submitSuccessCallback = function(json_data) { | |||
368 | // reload page if we change status for single commit. |
|
369 | // reload page if we change status for single commit. | |
369 | if (status && self.commitId) { |
|
370 | if (status && self.commitId) { | |
370 | location.reload(true); |
|
371 | location.reload(true); | |
371 | } else { |
|
372 | } else { | |
372 | $('#injected_page_comments').append(o.rendered_text); |
|
373 | // inject newly created comments, json_data is {<comment_id>: {}} | |
|
374 | self.attachGeneralComment(json_data) | |||
|
375 | ||||
373 | self.resetCommentFormState(); |
|
376 | self.resetCommentFormState(); | |
374 | timeagoActivate(); |
|
377 | timeagoActivate(); | |
375 | tooltipActivate(); |
|
378 | tooltipActivate(); | |
@@ -565,26 +568,6 b' var CommentsController = function() {' | |||||
565 | var mainComment = '#text'; |
|
568 | var mainComment = '#text'; | |
566 | var self = this; |
|
569 | var self = this; | |
567 |
|
570 | |||
568 | this.cancelComment = function (node) { |
|
|||
569 | var $node = $(node); |
|
|||
570 | var edit = $(this).attr('edit'); |
|
|||
571 | if (edit) { |
|
|||
572 | var $general_comments = null; |
|
|||
573 | var $inline_comments = $node.closest('div.inline-comments'); |
|
|||
574 | if (!$inline_comments.length) { |
|
|||
575 | $general_comments = $('#comments'); |
|
|||
576 | var $comment = $general_comments.parent().find('div.comment:hidden'); |
|
|||
577 | // show hidden general comment form |
|
|||
578 | $('#cb-comment-general-form-placeholder').show(); |
|
|||
579 | } else { |
|
|||
580 | var $comment = $inline_comments.find('div.comment:hidden'); |
|
|||
581 | } |
|
|||
582 | $comment.show(); |
|
|||
583 | } |
|
|||
584 | $node.closest('.comment-inline-form').remove(); |
|
|||
585 | return false; |
|
|||
586 | }; |
|
|||
587 |
|
||||
588 | this.showVersion = function (comment_id, comment_history_id) { |
|
571 | this.showVersion = function (comment_id, comment_history_id) { | |
589 |
|
572 | |||
590 | var historyViewUrl = pyroutes.url( |
|
573 | var historyViewUrl = pyroutes.url( | |
@@ -682,6 +665,35 b' var CommentsController = function() {' | |||||
682 | return self.scrollToComment(node, -1, true); |
|
665 | return self.scrollToComment(node, -1, true); | |
683 | }; |
|
666 | }; | |
684 |
|
667 | |||
|
668 | this.cancelComment = function (node) { | |||
|
669 | var $node = $(node); | |||
|
670 | var edit = $(this).attr('edit'); | |||
|
671 | var $inlineComments = $node.closest('div.inline-comments'); | |||
|
672 | ||||
|
673 | if (edit) { | |||
|
674 | var $general_comments = null; | |||
|
675 | if (!$inlineComments.length) { | |||
|
676 | $general_comments = $('#comments'); | |||
|
677 | var $comment = $general_comments.parent().find('div.comment:hidden'); | |||
|
678 | // show hidden general comment form | |||
|
679 | $('#cb-comment-general-form-placeholder').show(); | |||
|
680 | } else { | |||
|
681 | var $comment = $inlineComments.find('div.comment:hidden'); | |||
|
682 | } | |||
|
683 | $comment.show(); | |||
|
684 | } | |||
|
685 | var $replyWrapper = $node.closest('.comment-inline-form').closest('.reply-thread-container-wrapper') | |||
|
686 | $replyWrapper.removeClass('comment-form-active'); | |||
|
687 | ||||
|
688 | var lastComment = $inlineComments.find('.comment-inline').last(); | |||
|
689 | if ($(lastComment).hasClass('comment-outdated')) { | |||
|
690 | $replyWrapper.hide(); | |||
|
691 | } | |||
|
692 | ||||
|
693 | $node.closest('.comment-inline-form').remove(); | |||
|
694 | return false; | |||
|
695 | }; | |||
|
696 | ||||
685 | this._deleteComment = function(node) { |
|
697 | this._deleteComment = function(node) { | |
686 | var $node = $(node); |
|
698 | var $node = $(node); | |
687 | var $td = $node.closest('td'); |
|
699 | var $td = $node.closest('td'); | |
@@ -751,7 +763,7 b' var CommentsController = function() {' | |||||
751 | this.finalizeDrafts = function(commentIds) { |
|
763 | this.finalizeDrafts = function(commentIds) { | |
752 |
|
764 | |||
753 | SwalNoAnimation.fire({ |
|
765 | SwalNoAnimation.fire({ | |
754 | title: _ngettext('Submit {0} draft comment', 'Submit {0} draft comments', commentIds.length).format(commentIds.length), |
|
766 | title: _ngettext('Submit {0} draft comment.', 'Submit {0} draft comments.', commentIds.length).format(commentIds.length), | |
755 | icon: 'warning', |
|
767 | icon: 'warning', | |
756 | showCancelButton: true, |
|
768 | showCancelButton: true, | |
757 | confirmButtonText: _gettext('Yes, finalize drafts'), |
|
769 | confirmButtonText: _gettext('Yes, finalize drafts'), | |
@@ -764,6 +776,7 b' var CommentsController = function() {' | |||||
764 | }; |
|
776 | }; | |
765 |
|
777 | |||
766 | this.toggleWideMode = function (node) { |
|
778 | this.toggleWideMode = function (node) { | |
|
779 | ||||
767 | if ($('#content').hasClass('wrapper')) { |
|
780 | if ($('#content').hasClass('wrapper')) { | |
768 | $('#content').removeClass("wrapper"); |
|
781 | $('#content').removeClass("wrapper"); | |
769 | $('#content').addClass("wide-mode-wrapper"); |
|
782 | $('#content').addClass("wide-mode-wrapper"); | |
@@ -778,16 +791,49 b' var CommentsController = function() {' | |||||
778 |
|
791 | |||
779 | }; |
|
792 | }; | |
780 |
|
793 | |||
781 | this.toggleComments = function(node, show) { |
|
794 | /** | |
|
795 | * Turn off/on all comments in file diff | |||
|
796 | */ | |||
|
797 | this.toggleDiffComments = function(node) { | |||
|
798 | // Find closes filediff container | |||
782 | var $filediff = $(node).closest('.filediff'); |
|
799 | var $filediff = $(node).closest('.filediff'); | |
|
800 | if ($(node).hasClass('toggle-on')) { | |||
|
801 | var show = false; | |||
|
802 | } else if ($(node).hasClass('toggle-off')) { | |||
|
803 | var show = true; | |||
|
804 | } | |||
|
805 | ||||
|
806 | // Toggle each individual comment block, so we can un-toggle single ones | |||
|
807 | $.each($filediff.find('.toggle-comment-action'), function(idx, val) { | |||
|
808 | self.toggleLineComments($(val), show) | |||
|
809 | }) | |||
|
810 | ||||
|
811 | // since we change the height of the diff container that has anchor points for upper | |||
|
812 | // sticky header, we need to tell it to re-calculate those | |||
|
813 | if (window.updateSticky !== undefined) { | |||
|
814 | // potentially our comments change the active window size, so we | |||
|
815 | // notify sticky elements | |||
|
816 | updateSticky() | |||
|
817 | } | |||
|
818 | ||||
|
819 | return false; | |||
|
820 | } | |||
|
821 | ||||
|
822 | this.toggleLineComments = function(node, show) { | |||
|
823 | ||||
|
824 | var trElem = $(node).closest('tr') | |||
|
825 | ||||
783 | if (show === true) { |
|
826 | if (show === true) { | |
784 | $filediff.removeClass('hide-comments'); |
|
827 | // mark outdated comments as visible before the toggle; | |
|
828 | $(trElem).find('.comment-outdated').show(); | |||
|
829 | $(trElem).removeClass('hide-line-comments'); | |||
785 | } else if (show === false) { |
|
830 | } else if (show === false) { | |
786 | $filediff.find('.hide-line-comments').removeClass('hide-line-comments'); |
|
831 | $(trElem).find('.comment-outdated').hide(); | |
787 |
|
|
832 | $(trElem).addClass('hide-line-comments'); | |
788 | } else { |
|
833 | } else { | |
789 | $filediff.find('.hide-line-comments').removeClass('hide-line-comments'); |
|
834 | // mark outdated comments as visible before the toggle; | |
790 | $filediff.toggleClass('hide-comments'); |
|
835 | $(trElem).find('.comment-outdated').show(); | |
|
836 | $(trElem).toggleClass('hide-line-comments'); | |||
791 | } |
|
837 | } | |
792 |
|
838 | |||
793 | // since we change the height of the diff container that has anchor points for upper |
|
839 | // since we change the height of the diff container that has anchor points for upper | |
@@ -798,15 +844,6 b' var CommentsController = function() {' | |||||
798 | updateSticky() |
|
844 | updateSticky() | |
799 | } |
|
845 | } | |
800 |
|
846 | |||
801 | return false; |
|
|||
802 | }; |
|
|||
803 |
|
||||
804 | this.toggleLineComments = function(node) { |
|
|||
805 | self.toggleComments(node, true); |
|
|||
806 | var $node = $(node); |
|
|||
807 | // mark outdated comments as visible before the toggle; |
|
|||
808 | $(node.closest('tr')).find('.comment-outdated').show(); |
|
|||
809 | $node.closest('tr').toggleClass('hide-line-comments'); |
|
|||
810 | }; |
|
847 | }; | |
811 |
|
848 | |||
812 | this.createCommentForm = function(formElement, lineno, placeholderText, initAutocompleteActions, resolvesCommentId, edit, comment_id){ |
|
849 | this.createCommentForm = function(formElement, lineno, placeholderText, initAutocompleteActions, resolvesCommentId, edit, comment_id){ | |
@@ -960,64 +997,58 b' var CommentsController = function() {' | |||||
960 | return commentForm; |
|
997 | return commentForm; | |
961 | }; |
|
998 | }; | |
962 |
|
999 | |||
963 | this.editComment = function(node) { |
|
1000 | this.editComment = function(node, line_no, f_path) { | |
|
1001 | self.edit = true; | |||
964 | var $node = $(node); |
|
1002 | var $node = $(node); | |
|
1003 | var $td = $node.closest('td'); | |||
|
1004 | ||||
965 | var $comment = $(node).closest('.comment'); |
|
1005 | var $comment = $(node).closest('.comment'); | |
966 | var comment_id = $($comment).data('commentId'); |
|
1006 | var comment_id = $($comment).data('commentId'); | |
967 | var isDraft = $($comment).data('commentDraft'); |
|
1007 | var isDraft = $($comment).data('commentDraft'); | |
968 |
var $ |
|
1008 | var $editForm = null | |
969 |
|
1009 | |||
970 | var $comments = $node.closest('div.inline-comments'); |
|
1010 | var $comments = $node.closest('div.inline-comments'); | |
971 | var $general_comments = null; |
|
1011 | var $general_comments = null; | |
972 | var lineno = null; |
|
|||
973 |
|
1012 | |||
974 | if($comments.length){ |
|
1013 | if($comments.length){ | |
975 | // inline comments setup |
|
1014 | // inline comments setup | |
976 |
$ |
|
1015 | $editForm = $comments.find('.comment-inline-form'); | |
977 | lineno = self.getLineNumber(node) |
|
1016 | line_no = self.getLineNumber(node) | |
978 | } |
|
1017 | } | |
979 | else{ |
|
1018 | else{ | |
980 | // general comments setup |
|
1019 | // general comments setup | |
981 | $comments = $('#comments'); |
|
1020 | $comments = $('#comments'); | |
982 |
$ |
|
1021 | $editForm = $comments.find('.comment-inline-form'); | |
983 | lineno = $comment[0].id |
|
1022 | line_no = $comment[0].id | |
984 | $('#cb-comment-general-form-placeholder').hide(); |
|
1023 | $('#cb-comment-general-form-placeholder').hide(); | |
985 | } |
|
1024 | } | |
986 |
|
1025 | |||
987 | this.edit = true; |
|
1026 | if ($editForm.length === 0) { | |
988 |
|
1027 | |||
989 | if (!$form.length) { |
|
1028 | // unhide all comments if they are hidden for a proper REPLY mode | |
990 |
|
||||
991 | var $filediff = $node.closest('.filediff'); |
|
1029 | var $filediff = $node.closest('.filediff'); | |
992 | $filediff.removeClass('hide-comments'); |
|
1030 | $filediff.removeClass('hide-comments'); | |
993 | var f_path = $filediff.attr('data-f-path'); |
|
|||
994 |
|
||||
995 | // create a new HTML from template |
|
|||
996 |
|
1031 | |||
997 | var tmpl = $('#cb-comment-inline-form-template').html(); |
|
1032 | $editForm = self.createNewFormWrapper(f_path, line_no); | |
998 | tmpl = tmpl.format(escapeHtml(f_path), lineno); |
|
1033 | if(f_path && line_no) { | |
999 | $form = $(tmpl); |
|
1034 | $editForm.addClass('comment-inline-form-edit') | |
1000 | $comment.after($form) |
|
1035 | } | |
1001 |
|
1036 | |||
1002 | var _form = $($form[0]).find('form'); |
|
1037 | $comment.after($editForm) | |
|
1038 | ||||
|
1039 | var _form = $($editForm[0]).find('form'); | |||
1003 | var autocompleteActions = ['as_note',]; |
|
1040 | var autocompleteActions = ['as_note',]; | |
1004 | var commentForm = this.createCommentForm( |
|
1041 | var commentForm = this.createCommentForm( | |
1005 | _form, lineno, '', autocompleteActions, resolvesCommentId, |
|
1042 | _form, line_no, '', autocompleteActions, resolvesCommentId, | |
1006 | this.edit, comment_id); |
|
1043 | this.edit, comment_id); | |
1007 | var old_comment_text_binary = $comment.attr('data-comment-text'); |
|
1044 | var old_comment_text_binary = $comment.attr('data-comment-text'); | |
1008 | var old_comment_text = b64DecodeUnicode(old_comment_text_binary); |
|
1045 | var old_comment_text = b64DecodeUnicode(old_comment_text_binary); | |
1009 | commentForm.cm.setValue(old_comment_text); |
|
1046 | commentForm.cm.setValue(old_comment_text); | |
1010 | $comment.hide(); |
|
1047 | $comment.hide(); | |
|
1048 | tooltipActivate(); | |||
1011 |
|
1049 | |||
1012 | $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({ |
|
1050 | // set a CUSTOM submit handler for inline comment edit action. | |
1013 | form: _form, |
|
1051 | commentForm.setHandleFormSubmit(function(o) { | |
1014 | parent: $comments, |
|
|||
1015 | lineno: lineno, |
|
|||
1016 | f_path: f_path} |
|
|||
1017 | ); |
|
|||
1018 |
|
||||
1019 | // set a CUSTOM submit handler for inline comments. |
|
|||
1020 | commentForm.setHandleFormSubmit(function(o) { |
|
|||
1021 | var text = commentForm.cm.getValue(); |
|
1052 | var text = commentForm.cm.getValue(); | |
1022 | var commentType = commentForm.getCommentType(); |
|
1053 | var commentType = commentForm.getCommentType(); | |
1023 |
|
1054 | |||
@@ -1048,7 +1079,7 b' var CommentsController = function() {' | |||||
1048 | var postData = { |
|
1079 | var postData = { | |
1049 | 'text': text, |
|
1080 | 'text': text, | |
1050 | 'f_path': f_path, |
|
1081 | 'f_path': f_path, | |
1051 | 'line': lineno, |
|
1082 | 'line': line_no, | |
1052 | 'comment_type': commentType, |
|
1083 | 'comment_type': commentType, | |
1053 | 'draft': isDraft, |
|
1084 | 'draft': isDraft, | |
1054 | 'version': version, |
|
1085 | 'version': version, | |
@@ -1056,7 +1087,7 b' var CommentsController = function() {' | |||||
1056 | }; |
|
1087 | }; | |
1057 |
|
1088 | |||
1058 | var submitSuccessCallback = function(json_data) { |
|
1089 | var submitSuccessCallback = function(json_data) { | |
1059 |
$ |
|
1090 | $editForm.remove(); | |
1060 | $comment.show(); |
|
1091 | $comment.show(); | |
1061 | var postData = { |
|
1092 | var postData = { | |
1062 | 'text': text, |
|
1093 | 'text': text, | |
@@ -1121,8 +1152,7 b' var CommentsController = function() {' | |||||
1121 | 'commit_id': templateContext.commit_data.commit_id}); |
|
1152 | 'commit_id': templateContext.commit_data.commit_id}); | |
1122 |
|
1153 | |||
1123 | _submitAjaxPOST( |
|
1154 | _submitAjaxPOST( | |
1124 | previewUrl, postData, successRenderCommit, |
|
1155 | previewUrl, postData, successRenderCommit, failRenderCommit | |
1125 | failRenderCommit |
|
|||
1126 | ); |
|
1156 | ); | |
1127 |
|
1157 | |||
1128 | try { |
|
1158 | try { | |
@@ -1178,49 +1208,103 b' var CommentsController = function() {' | |||||
1178 | }); |
|
1208 | }); | |
1179 | } |
|
1209 | } | |
1180 |
|
1210 | |||
1181 |
$ |
|
1211 | $editForm.addClass('comment-inline-form-open'); | |
1182 | }; |
|
1212 | }; | |
1183 |
|
1213 | |||
1184 |
this. |
|
1214 | this.attachComment = function(json_data) { | |
1185 | var resolvesCommentId = resolutionComment || null; |
|
1215 | var self = this; | |
|
1216 | $.each(json_data, function(idx, val) { | |||
|
1217 | var json_data_elem = [val] | |||
|
1218 | var isInline = val.comment_f_path && val.comment_lineno | |||
|
1219 | ||||
|
1220 | if (isInline) { | |||
|
1221 | self.attachInlineComment(json_data_elem) | |||
|
1222 | } else { | |||
|
1223 | self.attachGeneralComment(json_data_elem) | |||
|
1224 | } | |||
|
1225 | }) | |||
|
1226 | ||||
|
1227 | } | |||
|
1228 | ||||
|
1229 | this.attachGeneralComment = function(json_data) { | |||
|
1230 | $.each(json_data, function(idx, val) { | |||
|
1231 | $('#injected_page_comments').append(val.rendered_text); | |||
|
1232 | }) | |||
|
1233 | } | |||
|
1234 | ||||
|
1235 | this.attachInlineComment = function(json_data) { | |||
|
1236 | ||||
|
1237 | $.each(json_data, function (idx, val) { | |||
|
1238 | var line_qry = '*[data-line-no="{0}"]'.format(val.line_no); | |||
|
1239 | var html = val.rendered_text; | |||
|
1240 | var $inlineComments = $('#' + val.target_id) | |||
|
1241 | .find(line_qry) | |||
|
1242 | .find('.inline-comments'); | |||
|
1243 | ||||
|
1244 | var lastComment = $inlineComments.find('.comment-inline').last(); | |||
|
1245 | ||||
|
1246 | if (lastComment.length === 0) { | |||
|
1247 | // first comment, we append simply | |||
|
1248 | $inlineComments.find('.reply-thread-container-wrapper').before(html); | |||
|
1249 | } else { | |||
|
1250 | $(lastComment).after(html) | |||
|
1251 | } | |||
|
1252 | ||||
|
1253 | }) | |||
|
1254 | ||||
|
1255 | }; | |||
|
1256 | ||||
|
1257 | this.createNewFormWrapper = function(f_path, line_no) { | |||
|
1258 | // create a new reply HTML form from template | |||
|
1259 | var tmpl = $('#cb-comment-inline-form-template').html(); | |||
|
1260 | tmpl = tmpl.format(escapeHtml(f_path), line_no); | |||
|
1261 | return $(tmpl); | |||
|
1262 | } | |||
|
1263 | ||||
|
1264 | this.createComment = function(node, f_path, line_no, resolutionComment) { | |||
|
1265 | self.edit = false; | |||
1186 | var $node = $(node); |
|
1266 | var $node = $(node); | |
1187 | var $td = $node.closest('td'); |
|
1267 | var $td = $node.closest('td'); | |
1188 | var $form = $td.find('.comment-inline-form'); |
|
1268 | var resolvesCommentId = resolutionComment || null; | |
1189 | this.edit = false; |
|
|||
1190 |
|
1269 | |||
1191 | if (!$form.length) { |
|
1270 | var $replyForm = $td.find('.comment-inline-form'); | |
1192 |
|
1271 | |||
1193 | var $filediff = $node.closest('.filediff'); |
|
1272 | // if form isn't existing, we're generating a new one and injecting it. | |
1194 | $filediff.removeClass('hide-comments'); |
|
1273 | if ($replyForm.length === 0) { | |
1195 | var f_path = $filediff.attr('data-f-path'); |
|
1274 | ||
1196 | var lineno = self.getLineNumber(node); |
|
1275 | // unhide/expand all comments if they are hidden for a proper REPLY mode | |
1197 | // create a new HTML from template |
|
1276 | self.toggleLineComments($node, true); | |
1198 | var tmpl = $('#cb-comment-inline-form-template').html(); |
|
1277 | ||
1199 |
|
|
1278 | $replyForm = self.createNewFormWrapper(f_path, line_no); | |
1200 | $form = $(tmpl); |
|
|||
1201 |
|
1279 | |||
1202 | var $comments = $td.find('.inline-comments'); |
|
1280 | var $comments = $td.find('.inline-comments'); | |
1203 | if (!$comments.length) { |
|
1281 | ||
1204 | $comments = $( |
|
1282 | // There aren't any comments, we init the `.inline-comments` with `reply-thread-container` first | |
1205 | $('#cb-comments-inline-container-template').html()); |
|
1283 | if ($comments.length===0) { | |
1206 | $td.append($comments); |
|
1284 | var replBtn = '<button class="cb-comment-add-button" onclick="return Rhodecode.comments.createComment(this, \'{0}\', \'{1}\', null)">Reply...</button>'.format(f_path, line_no) | |
|
1285 | var $reply_container = $('#cb-comments-inline-container-template') | |||
|
1286 | $reply_container.find('button.cb-comment-add-button').replaceWith(replBtn); | |||
|
1287 | $td.append($($reply_container).html()); | |||
1207 | } |
|
1288 | } | |
1208 |
|
1289 | |||
1209 | $td.find('.cb-comment-add-button').before($form); |
|
1290 | // default comment button exists, so we prepend the form for leaving initial comment | |
|
1291 | $td.find('.cb-comment-add-button').before($replyForm); | |||
|
1292 | // set marker, that we have a open form | |||
|
1293 | var $replyWrapper = $td.find('.reply-thread-container-wrapper') | |||
|
1294 | $replyWrapper.addClass('comment-form-active'); | |||
1210 |
|
1295 | |||
1211 | var placeholderText = _gettext('Leave a comment on line {0}.').format(lineno); |
|
1296 | var lastComment = $comments.find('.comment-inline').last(); | |
1212 | var _form = $($form[0]).find('form'); |
|
1297 | if ($(lastComment).hasClass('comment-outdated')) { | |
|
1298 | $replyWrapper.show(); | |||
|
1299 | } | |||
|
1300 | ||||
|
1301 | var _form = $($replyForm[0]).find('form'); | |||
1213 | var autocompleteActions = ['as_note', 'as_todo']; |
|
1302 | var autocompleteActions = ['as_note', 'as_todo']; | |
1214 | var comment_id=null; |
|
1303 | var comment_id=null; | |
1215 | var commentForm = this.createCommentForm( |
|
1304 | var placeholderText = _gettext('Leave a comment on file {0} line {1}.').format(f_path, line_no); | |
1216 | _form, lineno, placeholderText, autocompleteActions, resolvesCommentId, this.edit, comment_id); |
|
1305 | var commentForm = self.createCommentForm( | |
1217 |
|
1306 | _form, line_no, placeholderText, autocompleteActions, resolvesCommentId, | ||
1218 | $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({ |
|
1307 | self.edit, comment_id); | |
1219 | form: _form, |
|
|||
1220 | parent: $td[0], |
|
|||
1221 | lineno: lineno, |
|
|||
1222 | f_path: f_path} |
|
|||
1223 | ); |
|
|||
1224 |
|
1308 | |||
1225 | // set a CUSTOM submit handler for inline comments. |
|
1309 | // set a CUSTOM submit handler for inline comments. | |
1226 | commentForm.setHandleFormSubmit(function(o) { |
|
1310 | commentForm.setHandleFormSubmit(function(o) { | |
@@ -1233,12 +1317,13 b' var CommentsController = function() {' | |||||
1233 | return; |
|
1317 | return; | |
1234 | } |
|
1318 | } | |
1235 |
|
1319 | |||
1236 | if (lineno === undefined) { |
|
1320 | if (line_no === undefined) { | |
1237 | alert('missing line !'); |
|
1321 | alert('Error: unable to fetch line number for this inline comment !'); | |
1238 | return; |
|
1322 | return; | |
1239 | } |
|
1323 | } | |
|
1324 | ||||
1240 | if (f_path === undefined) { |
|
1325 | if (f_path === undefined) { | |
1241 | alert('missing file path !'); |
|
1326 | alert('Error: unable to fetch file path for this inline comment !'); | |
1242 | return; |
|
1327 | return; | |
1243 | } |
|
1328 | } | |
1244 |
|
1329 | |||
@@ -1249,7 +1334,7 b' var CommentsController = function() {' | |||||
1249 | var postData = { |
|
1334 | var postData = { | |
1250 | 'text': text, |
|
1335 | 'text': text, | |
1251 | 'f_path': f_path, |
|
1336 | 'f_path': f_path, | |
1252 | 'line': lineno, |
|
1337 | 'line': line_no, | |
1253 | 'comment_type': commentType, |
|
1338 | 'comment_type': commentType, | |
1254 | 'draft': isDraft, |
|
1339 | 'draft': isDraft, | |
1255 | 'csrf_token': CSRF_TOKEN |
|
1340 | 'csrf_token': CSRF_TOKEN | |
@@ -1258,32 +1343,32 b' var CommentsController = function() {' | |||||
1258 | postData['resolves_comment_id'] = resolvesCommentId; |
|
1343 | postData['resolves_comment_id'] = resolvesCommentId; | |
1259 | } |
|
1344 | } | |
1260 |
|
1345 | |||
|
1346 | // submitSuccess for inline commits | |||
1261 | var submitSuccessCallback = function(json_data) { |
|
1347 | var submitSuccessCallback = function(json_data) { | |
1262 | $form.remove(); |
|
1348 | ||
1263 | try { |
|
1349 | $replyForm.remove(); | |
1264 | var html = json_data.rendered_text; |
|
1350 | $td.find('.reply-thread-container-wrapper').removeClass('comment-form-active'); | |
1265 | var lineno = json_data.line_no; |
|
1351 | ||
1266 | var target_id = json_data.target_id; |
|
1352 | try { | |
|
1353 | ||||
|
1354 | // inject newly created comments, json_data is {<comment_id>: {}} | |||
|
1355 | self.attachInlineComment(json_data) | |||
1267 |
|
1356 | |||
1268 | $comments.find('.cb-comment-add-button').before(html); |
|
1357 | //mark visually which comment was resolved | |
|
1358 | if (resolvesCommentId) { | |||
|
1359 | commentForm.markCommentResolved(resolvesCommentId); | |||
|
1360 | } | |||
1269 |
|
1361 | |||
1270 | //mark visually which comment was resolved |
|
1362 | // run global callback on submit | |
1271 | if (resolvesCommentId) { |
|
1363 | commentForm.globalSubmitSuccessCallback({ | |
1272 | commentForm.markCommentResolved(resolvesCommentId); |
|
1364 | draft: isDraft, | |
|
1365 | comment_id: comment_id | |||
|
1366 | }); | |||
|
1367 | ||||
|
1368 | } catch (e) { | |||
|
1369 | console.error(e); | |||
1273 | } |
|
1370 | } | |
1274 |
|
1371 | |||
1275 | // run global callback on submit |
|
|||
1276 | commentForm.globalSubmitSuccessCallback({draft: isDraft, comment_id: comment_id}); |
|
|||
1277 |
|
||||
1278 | } catch (e) { |
|
|||
1279 | console.error(e); |
|
|||
1280 | } |
|
|||
1281 |
|
||||
1282 | // re trigger the linkification of next/prev navigation |
|
|||
1283 | linkifyComments($('.inline-comment-injected')); |
|
|||
1284 | timeagoActivate(); |
|
|||
1285 | tooltipActivate(); |
|
|||
1286 |
|
||||
1287 | if (window.updateSticky !== undefined) { |
|
1372 | if (window.updateSticky !== undefined) { | |
1288 | // potentially our comments change the active window size, so we |
|
1373 | // potentially our comments change the active window size, so we | |
1289 | // notify sticky elements |
|
1374 | // notify sticky elements | |
@@ -1297,19 +1382,27 b' var CommentsController = function() {' | |||||
1297 |
|
1382 | |||
1298 | commentForm.setActionButtonsDisabled(false); |
|
1383 | commentForm.setActionButtonsDisabled(false); | |
1299 |
|
1384 | |||
|
1385 | // re trigger the linkification of next/prev navigation | |||
|
1386 | linkifyComments($('.inline-comment-injected')); | |||
|
1387 | timeagoActivate(); | |||
|
1388 | tooltipActivate(); | |||
1300 | }; |
|
1389 | }; | |
|
1390 | ||||
1301 | var submitFailCallback = function(jqXHR, textStatus, errorThrown) { |
|
1391 | var submitFailCallback = function(jqXHR, textStatus, errorThrown) { | |
1302 | var prefix = "Error while submitting comment.\n" |
|
1392 | var prefix = "Error while submitting comment.\n" | |
1303 | var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix); |
|
1393 | var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix); | |
1304 | ajaxErrorSwal(message); |
|
1394 | ajaxErrorSwal(message); | |
1305 | commentForm.resetCommentFormState(text) |
|
1395 | commentForm.resetCommentFormState(text) | |
1306 | }; |
|
1396 | }; | |
|
1397 | ||||
1307 | commentForm.submitAjaxPOST( |
|
1398 | commentForm.submitAjaxPOST( | |
1308 | commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback); |
|
1399 | commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback); | |
1309 | }); |
|
1400 | }); | |
1310 | } |
|
1401 | } | |
1311 |
|
1402 | |||
1312 | $form.addClass('comment-inline-form-open'); |
|
1403 | // Finally "open" our reply form, since we know there are comments and we have the "attached" old form | |
|
1404 | $replyForm.addClass('comment-inline-form-open'); | |||
|
1405 | tooltipActivate(); | |||
1313 | }; |
|
1406 | }; | |
1314 |
|
1407 | |||
1315 | this.createResolutionComment = function(commentId){ |
|
1408 | this.createResolutionComment = function(commentId){ | |
@@ -1319,9 +1412,12 b' var CommentsController = function() {' | |||||
1319 | var comment = $('#comment-'+commentId); |
|
1412 | var comment = $('#comment-'+commentId); | |
1320 | var commentData = comment.data(); |
|
1413 | var commentData = comment.data(); | |
1321 | if (commentData.commentInline) { |
|
1414 | if (commentData.commentInline) { | |
1322 | this.createComment(comment, commentId) |
|
1415 | var f_path = commentData.fPath; | |
|
1416 | var line_no = commentData.lineNo; | |||
|
1417 | //TODO check this if we need to give f_path/line_no | |||
|
1418 | this.createComment(comment, f_path, line_no, commentId) | |||
1323 | } else { |
|
1419 | } else { | |
1324 |
|
|
1420 | this.createGeneralComment('general', "$placeholder", commentId) | |
1325 | } |
|
1421 | } | |
1326 |
|
1422 | |||
1327 | return false; |
|
1423 | return false; | |
@@ -1347,3 +1443,8 b' var CommentsController = function() {' | |||||
1347 | }; |
|
1443 | }; | |
1348 |
|
1444 | |||
1349 | }; |
|
1445 | }; | |
|
1446 | ||||
|
1447 | window.commentHelp = function(renderer) { | |||
|
1448 | var funcData = {'renderer': renderer} | |||
|
1449 | return renderTemplate('commentHelpHovercard', funcData) | |||
|
1450 | } No newline at end of file |
@@ -42,12 +42,22 b' window.toggleElement = function (elem, t' | |||||
42 | var $elem = $(elem); |
|
42 | var $elem = $(elem); | |
43 | var $target = $(target); |
|
43 | var $target = $(target); | |
44 |
|
44 | |||
45 | if ($target.is(':visible') || $target.length === 0) { |
|
45 | if (target !== undefined) { | |
|
46 | var show = $target.is(':visible') || $target.length === 0; | |||
|
47 | } else { | |||
|
48 | var show = $elem.hasClass('toggle-off') | |||
|
49 | } | |||
|
50 | ||||
|
51 | if (show) { | |||
46 | $target.hide(); |
|
52 | $target.hide(); | |
47 | $elem.html($elem.data('toggleOn')) |
|
53 | $elem.html($elem.data('toggleOn')) | |
|
54 | $elem.addClass('toggle-on') | |||
|
55 | $elem.removeClass('toggle-off') | |||
48 | } else { |
|
56 | } else { | |
49 | $target.show(); |
|
57 | $target.show(); | |
50 | $elem.html($elem.data('toggleOff')) |
|
58 | $elem.html($elem.data('toggleOff')) | |
|
59 | $elem.addClass('toggle-off') | |||
|
60 | $elem.removeClass('toggle-on') | |||
51 | } |
|
61 | } | |
52 |
|
62 | |||
53 | return false |
|
63 | return false |
@@ -1,7 +1,5 b'' | |||||
1 | /__MAIN_APP__ - launched when rhodecode-app element is attached to DOM |
|
1 | /__MAIN_APP__ - launched when rhodecode-app element is attached to DOM | |
2 | /plugins/__REGISTER__ - launched after the onDomReady() code from rhodecode.js is executed |
|
2 | /plugins/__REGISTER__ - launched after the onDomReady() code from rhodecode.js is executed | |
3 | /ui/plugins/code/anchor_focus - launched when rc starts to scroll on load to anchor on PR/Codeview |
|
|||
4 | /ui/plugins/code/comment_form_built - launched when injectInlineForm() is executed and the form object is created |
|
|||
5 | /notifications - shows new event notifications |
|
3 | /notifications - shows new event notifications | |
6 | /connection_controller/subscribe - subscribes user to new channels |
|
4 | /connection_controller/subscribe - subscribes user to new channels | |
7 | /connection_controller/presence - receives presence change messages |
|
5 | /connection_controller/presence - receives presence change messages |
@@ -1,4 +1,4 b'' | |||||
1 | ## this is a dummy html file for partial rendering on server and sending |
|
1 | ## this is a dummy html file for partial rendering on server and sending | |
2 | ## generated output via ajax after comment submit |
|
2 | ## generated output via ajax after comment submit | |
3 | <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/> |
|
3 | <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/> | |
4 | ${comment.comment_block(c.co, inline=c.co.is_inline)} |
|
4 | ${comment.comment_block(c.co, inline=c.co.is_inline, is_new=c.is_new)} |
@@ -10,7 +10,7 b'' | |||||
10 | %> |
|
10 | %> | |
11 |
|
11 | |||
12 |
|
12 | |||
13 | <%def name="comment_block(comment, inline=False, active_pattern_entries=None)"> |
|
13 | <%def name="comment_block(comment, inline=False, active_pattern_entries=None, is_new=False)"> | |
14 |
|
14 | |||
15 | <% |
|
15 | <% | |
16 | from rhodecode.model.comment import CommentsModel |
|
16 | from rhodecode.model.comment import CommentsModel | |
@@ -40,6 +40,7 b'' | |||||
40 | data-comment-draft=${h.json.dumps(comment.draft)} |
|
40 | data-comment-draft=${h.json.dumps(comment.draft)} | |
41 | data-comment-renderer="${comment.renderer}" |
|
41 | data-comment-renderer="${comment.renderer}" | |
42 | data-comment-text="${comment.text | html_filters.base64,n}" |
|
42 | data-comment-text="${comment.text | html_filters.base64,n}" | |
|
43 | data-comment-f-path="${comment.f_path}" | |||
43 | data-comment-line-no="${comment.line_no}" |
|
44 | data-comment-line-no="${comment.line_no}" | |
44 | data-comment-inline=${h.json.dumps(inline)} |
|
45 | data-comment-inline=${h.json.dumps(inline)} | |
45 | style="${'display: none;' if outdated_at_ver else ''}"> |
|
46 | style="${'display: none;' if outdated_at_ver else ''}"> | |
@@ -47,8 +48,17 b'' | |||||
47 | <div class="meta"> |
|
48 | <div class="meta"> | |
48 | <div class="comment-type-label"> |
|
49 | <div class="comment-type-label"> | |
49 | % if comment.draft: |
|
50 | % if comment.draft: | |
50 |
|
|
51 | <div class="tooltip comment-draft" title="${_('Draft comments are only visible to the author until submitted')}."> | |
|
52 | DRAFT | |||
|
53 | </div> | |||
51 | % endif |
|
54 | % endif | |
|
55 | ||||
|
56 | % if is_new: | |||
|
57 | <div class="tooltip comment-new" title="${_('This comment was added while you browsed this page')}."> | |||
|
58 | NEW | |||
|
59 | </div> | |||
|
60 | % endif | |||
|
61 | ||||
52 | <div class="comment-label ${comment.comment_type or 'note'}" id="comment-label-${comment.comment_id}"> |
|
62 | <div class="comment-label ${comment.comment_type or 'note'}" id="comment-label-${comment.comment_id}"> | |
53 |
|
63 | |||
54 | ## TODO COMMENT |
|
64 | ## TODO COMMENT | |
@@ -176,7 +186,7 b'' | |||||
176 | % if inline: |
|
186 | % if inline: | |
177 | <a class="pr-version-inline" href="${request.current_route_path(_query=dict(version=comment.pull_request_version_id), _anchor='comment-{}'.format(comment.comment_id))}"> |
|
187 | <a class="pr-version-inline" href="${request.current_route_path(_query=dict(version=comment.pull_request_version_id), _anchor='comment-{}'.format(comment.comment_id))}"> | |
178 | % if outdated_at_ver: |
|
188 | % if outdated_at_ver: | |
179 |
<code class="tooltip pr-version-num" title="${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}"> |
|
189 | <strong class="comment-outdated-label">outdated</strong> <code class="tooltip pr-version-num" title="${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}">${'v{}'.format(comment_ver)}</code> | |
180 | <code class="action-divider">|</code> |
|
190 | <code class="action-divider">|</code> | |
181 | % elif comment_ver: |
|
191 | % elif comment_ver: | |
182 | <code class="tooltip pr-version-num" title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}">${'v{}'.format(comment_ver)}</code> |
|
192 | <code class="tooltip pr-version-num" title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}">${'v{}'.format(comment_ver)}</code> | |
@@ -222,12 +232,13 b'' | |||||
222 | %if comment.immutable is False and (c.is_super_admin or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or comment.author.user_id == c.rhodecode_user.user_id): |
|
232 | %if comment.immutable is False and (c.is_super_admin or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or comment.author.user_id == c.rhodecode_user.user_id): | |
223 | <div class="dropdown-divider"></div> |
|
233 | <div class="dropdown-divider"></div> | |
224 | <div class="dropdown-item"> |
|
234 | <div class="dropdown-item"> | |
225 | <a onclick="return Rhodecode.comments.editComment(this);" class="btn btn-link btn-sm edit-comment">${_('Edit')}</a> |
|
235 | <a onclick="return Rhodecode.comments.editComment(this, '${comment.line_no}', '${comment.f_path}');" class="btn btn-link btn-sm edit-comment">${_('Edit')}</a> | |
226 | </div> |
|
236 | </div> | |
227 | <div class="dropdown-item"> |
|
237 | <div class="dropdown-item"> | |
228 | <a onclick="return Rhodecode.comments.deleteComment(this);" class="btn btn-link btn-sm btn-danger delete-comment">${_('Delete')}</a> |
|
238 | <a onclick="return Rhodecode.comments.deleteComment(this);" class="btn btn-link btn-sm btn-danger delete-comment">${_('Delete')}</a> | |
229 | </div> |
|
239 | </div> | |
230 | % if comment.draft: |
|
240 | ## Only available in EE edition | |
|
241 | % if comment.draft and c.rhodecode_edition_id == 'EE': | |||
231 | <div class="dropdown-item"> |
|
242 | <div class="dropdown-item"> | |
232 | <a onclick="return Rhodecode.comments.finalizeDrafts([${comment.comment_id}]);" class="btn btn-link btn-sm finalize-draft-comment">${_('Submit draft')}</a> |
|
243 | <a onclick="return Rhodecode.comments.finalizeDrafts([${comment.comment_id}]);" class="btn btn-link btn-sm finalize-draft-comment">${_('Submit draft')}</a> | |
233 | </div> |
|
244 | </div> | |
@@ -391,7 +402,7 b'' | |||||
391 |
|
402 | |||
392 | <div class="comment-area-write" style="display: block;"> |
|
403 | <div class="comment-area-write" style="display: block;"> | |
393 | <div id="edit-container"> |
|
404 | <div id="edit-container"> | |
394 |
<div style="padding: |
|
405 | <div style="padding: 20px 0px 0px 0;"> | |
395 | ${_('You need to be logged in to leave comments.')} |
|
406 | ${_('You need to be logged in to leave comments.')} | |
396 | <a href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">${_('Login now')}</a> |
|
407 | <a href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">${_('Login now')}</a> | |
397 | </div> |
|
408 | </div> | |
@@ -450,7 +461,7 b'' | |||||
450 | </div> |
|
461 | </div> | |
451 |
|
462 | |||
452 | <div class="comment-area-write" style="display: block;"> |
|
463 | <div class="comment-area-write" style="display: block;"> | |
453 | <div id="edit-container_${lineno_id}"> |
|
464 | <div id="edit-container_${lineno_id}" style="margin-top: -1px"> | |
454 | <textarea id="text_${lineno_id}" name="text" class="comment-block-ta ac-input"></textarea> |
|
465 | <textarea id="text_${lineno_id}" name="text" class="comment-block-ta ac-input"></textarea> | |
455 | </div> |
|
466 | </div> | |
456 | <div id="preview-container_${lineno_id}" class="clearfix" style="display: none;"> |
|
467 | <div id="preview-container_${lineno_id}" class="clearfix" style="display: none;"> | |
@@ -500,40 +511,47 b'' | |||||
500 | <input class="btn btn-success comment-button-input submit-comment-action" id="save_${lineno_id}" name="save" type="submit" value="${_('Add comment')}" data-is-draft=false onclick="$(this).addClass('submitter')"> |
|
511 | <input class="btn btn-success comment-button-input submit-comment-action" id="save_${lineno_id}" name="save" type="submit" value="${_('Add comment')}" data-is-draft=false onclick="$(this).addClass('submitter')"> | |
501 |
|
512 | |||
502 | % if form_type == 'inline': |
|
513 | % if form_type == 'inline': | |
503 | <input class="btn btn-warning comment-button-input submit-draft-action" id="save_draft_${lineno_id}" name="save_draft" type="submit" value="${_('Add draft')}" data-is-draft=true onclick="$(this).addClass('submitter')"> |
|
514 | % if c.rhodecode_edition_id == 'EE': | |
|
515 | ## Disable the button for CE, the "real" validation is in the backend code anyway | |||
|
516 | <input class="btn btn-warning comment-button-input submit-draft-action" id="save_draft_${lineno_id}" name="save_draft" type="submit" value="${_('Add draft')}" data-is-draft=true onclick="$(this).addClass('submitter')"> | |||
|
517 | % else: | |||
|
518 | <input class="tooltip btn btn-warning comment-button-input submit-draft-action disabled" type="submit" disabled="disabled" value="${_('Add draft')}" onclick="return false;" title="Draft comments only available in EE edition of RhodeCode"> | |||
|
519 | % endif | |||
|
520 | % endif | |||
|
521 | ||||
|
522 | % if review_statuses: | |||
|
523 | <div class="comment-status-box"> | |||
|
524 | <select id="change_status_${lineno_id}" name="changeset_status"> | |||
|
525 | <option></option> ## Placeholder | |||
|
526 | % for status, lbl in review_statuses: | |||
|
527 | <option value="${status}" data-status="${status}">${lbl}</option> | |||
|
528 | %if is_pull_request and change_status and status in ('approved', 'rejected'): | |||
|
529 | <option value="${status}_closed" data-status="${status}">${lbl} & ${_('Closed')}</option> | |||
|
530 | %endif | |||
|
531 | % endfor | |||
|
532 | </select> | |||
|
533 | </div> | |||
504 | % endif |
|
534 | % endif | |
505 |
|
535 | |||
506 | ## inline for has a file, and line-number together with cancel hide button. |
|
536 | ## inline for has a file, and line-number together with cancel hide button. | |
507 | % if form_type == 'inline': |
|
537 | % if form_type == 'inline': | |
508 | <input type="hidden" name="f_path" value="{0}"> |
|
538 | <input type="hidden" name="f_path" value="{0}"> | |
509 | <input type="hidden" name="line" value="${lineno_id}"> |
|
539 | <input type="hidden" name="line" value="${lineno_id}"> | |
510 |
<button type="button" class=" |
|
540 | <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);"> | |
511 | <i class="icon-cancel-circled2"></i> |
|
541 | <i class="icon-cancel-circled2"></i> | |
512 | </button> |
|
542 | </button> | |
513 | % endif |
|
543 | % endif | |
514 | </div> |
|
544 | </div> | |
515 |
|
|
545 | ||
516 | % if review_statuses: |
|
|||
517 | <div class="status_box"> |
|
|||
518 | <select id="change_status_${lineno_id}" name="changeset_status"> |
|
|||
519 | <option></option> ## Placeholder |
|
|||
520 | % for status, lbl in review_statuses: |
|
|||
521 | <option value="${status}" data-status="${status}">${lbl}</option> |
|
|||
522 | %if is_pull_request and change_status and status in ('approved', 'rejected'): |
|
|||
523 | <option value="${status}_closed" data-status="${status}">${lbl} & ${_('Closed')}</option> |
|
|||
524 | %endif |
|
|||
525 | % endfor |
|
|||
526 | </select> |
|
|||
527 | </div> |
|
|||
528 | % endif |
|
|||
529 |
|
||||
530 | <div class="toolbar-text"> |
|
546 | <div class="toolbar-text"> | |
531 | <% renderer_url = '<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper()) %> |
|
547 | <% renderer_url = '<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper()) %> | |
532 |
${_(' |
|
548 | <p>${_('Styling with {} is supported.').format(renderer_url)|n} | |
533 | <span class="tooltip" title="${_('Use @username inside this text to send notification to this RhodeCode user')}">@mention</span> |
|
549 | ||
534 | ${_('and')} |
|
550 | <i class="icon-info-circled tooltip-hovercard" | |
535 | <span class="tooltip" title="${_('Start typing with / for certain actions to be triggered via text box.')}">`/` autocomplete</span> |
|
551 | data-hovercard-alt="ALT" | |
536 | ${_('actions supported.')} |
|
552 | data-hovercard-url="javascript:commentHelp('${c.visual.default_renderer.upper()}')" | |
|
553 | data-comment-json-b64='${h.b64(h.json.dumps({}))}'></i> | |||
|
554 | </p> | |||
537 | </div> |
|
555 | </div> | |
538 | </div> |
|
556 | </div> | |
539 |
|
557 |
@@ -1,3 +1,4 b'' | |||||
|
1 | <%namespace name="base" file="/base/base.mako"/> | |||
1 | <%namespace name="commentblock" file="/changeset/changeset_file_comment.mako"/> |
|
2 | <%namespace name="commentblock" file="/changeset/changeset_file_comment.mako"/> | |
2 |
|
3 | |||
3 | <%def name="diff_line_anchor(commit, filename, line, type)"><% |
|
4 | <%def name="diff_line_anchor(commit, filename, line, type)"><% | |
@@ -74,24 +75,9 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
74 |
|
75 | |||
75 | <div class="js-template" id="cb-comment-inline-form-template"> |
|
76 | <div class="js-template" id="cb-comment-inline-form-template"> | |
76 | <div class="comment-inline-form ac"> |
|
77 | <div class="comment-inline-form ac"> | |
77 |
|
78 | %if not c.rhodecode_user.is_default: | ||
78 | %if c.rhodecode_user.username != h.DEFAULT_USER: |
|
|||
79 | ## render template for inline comments |
|
79 | ## render template for inline comments | |
80 | ${commentblock.comment_form(form_type='inline')} |
|
80 | ${commentblock.comment_form(form_type='inline')} | |
81 | %else: |
|
|||
82 | ${h.form('', class_='inline-form comment-form-login', method='get')} |
|
|||
83 | <div class="pull-left"> |
|
|||
84 | <div class="comment-help pull-right"> |
|
|||
85 | ${_('You need to be logged in to leave comments.')} <a href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">${_('Login now')}</a> |
|
|||
86 | </div> |
|
|||
87 | </div> |
|
|||
88 | <div class="comment-button pull-right"> |
|
|||
89 | <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);"> |
|
|||
90 | ${_('Cancel')} |
|
|||
91 | </button> |
|
|||
92 | </div> |
|
|||
93 | <div class="clearfix"></div> |
|
|||
94 | ${h.end_form()} |
|
|||
95 | %endif |
|
81 | %endif | |
96 | </div> |
|
82 | </div> | |
97 | </div> |
|
83 | </div> | |
@@ -327,7 +313,7 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
327 | </label> |
|
313 | </label> | |
328 |
|
314 | |||
329 | ${diff_menu(filediff, use_comments=use_comments)} |
|
315 | ${diff_menu(filediff, use_comments=use_comments)} | |
330 | <table data-f-path="${filediff.patch['filename']}" data-anchor-id="${h.FID(filediff.raw_id, filediff.patch['filename'])}" class="code-visible-block cb cb-diff-${c.user_session_attrs["diffmode"]} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}"> |
|
316 | <table id="file-${h.safeid(h.safe_unicode(filediff.patch['filename']))}" data-f-path="${filediff.patch['filename']}" data-anchor-id="${h.FID(filediff.raw_id, filediff.patch['filename'])}" class="code-visible-block cb cb-diff-${c.user_session_attrs["diffmode"]} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}"> | |
331 |
|
317 | |||
332 | ## new/deleted/empty content case |
|
318 | ## new/deleted/empty content case | |
333 | % if not filediff.hunks: |
|
319 | % if not filediff.hunks: | |
@@ -626,8 +612,10 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
626 |
|
612 | |||
627 | % if use_comments: |
|
613 | % if use_comments: | |
628 | | |
|
614 | | | |
629 |
<a href="#" onclick=" |
|
615 | <a href="#" onclick="Rhodecode.comments.toggleDiffComments(this);return toggleElement(this)" | |
630 | <span class="show-comment-button">${_('Show comments')}</span><span class="hide-comment-button">${_('Hide comments')}</span> |
|
616 | data-toggle-on="${_('Hide comments')}" | |
|
617 | data-toggle-off="${_('Show comments')}"> | |||
|
618 | <span class="hide-comment-button">${_('Hide comments')}</span> | |||
631 | </a> |
|
619 | </a> | |
632 | % endif |
|
620 | % endif | |
633 |
|
621 | |||
@@ -637,23 +625,36 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
637 | </%def> |
|
625 | </%def> | |
638 |
|
626 | |||
639 |
|
627 | |||
640 | <%def name="inline_comments_container(comments, active_pattern_entries=None)"> |
|
628 | <%def name="inline_comments_container(comments, active_pattern_entries=None, line_no='', f_path='')"> | |
641 |
|
629 | |||
642 | <div class="inline-comments"> |
|
630 | <div class="inline-comments"> | |
643 | %for comment in comments: |
|
631 | %for comment in comments: | |
644 | ${commentblock.comment_block(comment, inline=True, active_pattern_entries=active_pattern_entries)} |
|
632 | ${commentblock.comment_block(comment, inline=True, active_pattern_entries=active_pattern_entries)} | |
645 | %endfor |
|
633 | %endfor | |
646 | % if comments and comments[-1].outdated: |
|
634 | ||
647 | <span class="btn btn-secondary cb-comment-add-button comment-outdated}" style="display: none;}"> |
|
635 | <% | |
648 | ${_('Add another comment')} |
|
636 | extra_class = '' | |
649 | </span> |
|
637 | extra_style = '' | |
650 | % else: |
|
638 | ||
651 | <span onclick="return Rhodecode.comments.createComment(this)" class="btn btn-secondary cb-comment-add-button"> |
|
639 | if comments and comments[-1].outdated: | |
652 | ${_('Add another comment')} |
|
640 | extra_class = ' comment-outdated' | |
653 | </span> |
|
641 | extra_style = 'display: none;' | |
654 | % endif |
|
|||
655 |
|
642 | |||
|
643 | %> | |||
|
644 | <div class="reply-thread-container-wrapper${extra_class}" style="${extra_style}"> | |||
|
645 | <div class="reply-thread-container${extra_class}"> | |||
|
646 | <div class="reply-thread-gravatar"> | |||
|
647 | ${base.gravatar(c.rhodecode_user.email, 20, tooltip=True, user=c.rhodecode_user)} | |||
|
648 | </div> | |||
|
649 | <div class="reply-thread-reply-button"> | |||
|
650 | ## initial reply button, some JS logic can append here a FORM to leave a first comment. | |||
|
651 | <button class="cb-comment-add-button" onclick="return Rhodecode.comments.createComment(this, '${f_path}', '${line_no}', null)">Reply...</button> | |||
|
652 | </div> | |||
|
653 | <div class="reply-thread-last"></div> | |||
|
654 | </div> | |||
|
655 | </div> | |||
656 | </div> |
|
656 | </div> | |
|
657 | ||||
657 | </%def> |
|
658 | </%def> | |
658 |
|
659 | |||
659 | <%! |
|
660 | <%! | |
@@ -721,9 +722,9 b' def get_comments_for(diff_type, comments' | |||||
721 | %endif |
|
722 | %endif | |
722 | %if line_old_comments_no_drafts: |
|
723 | %if line_old_comments_no_drafts: | |
723 | % if has_outdated: |
|
724 | % if has_outdated: | |
724 |
<i class="tooltip icon-comment-toggle" title="${_(' |
|
725 | <i class="tooltip toggle-comment-action icon-comment-toggle" title="${_('Comments including outdated: {}. Click here to toggle them.').format(len(line_old_comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i> | |
725 | % else: |
|
726 | % else: | |
726 |
<i class="tooltip icon-comment" title="${_(' |
|
727 | <i class="tooltip toggle-comment-action icon-comment" title="${_('Comments: {}. Click to toggle them.').format(len(line_old_comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i> | |
727 | % endif |
|
728 | % endif | |
728 | %endif |
|
729 | %endif | |
729 | </td> |
|
730 | </td> | |
@@ -737,16 +738,18 b' def get_comments_for(diff_type, comments' | |||||
737 | <a name="${old_line_anchor}" href="#${old_line_anchor}">${line.original.lineno}</a> |
|
738 | <a name="${old_line_anchor}" href="#${old_line_anchor}">${line.original.lineno}</a> | |
738 | %endif |
|
739 | %endif | |
739 | </td> |
|
740 | </td> | |
|
741 | ||||
|
742 | <% line_no = 'o{}'.format(line.original.lineno) %> | |||
740 | <td class="cb-content ${action_class(line.original.action)}" |
|
743 | <td class="cb-content ${action_class(line.original.action)}" | |
741 |
data-line-no=" |
|
744 | data-line-no="${line_no}" | |
742 | > |
|
745 | > | |
743 | %if use_comments and line.original.lineno: |
|
746 | %if use_comments and line.original.lineno: | |
744 | ${render_add_comment_button()} |
|
747 | ${render_add_comment_button(line_no=line_no, f_path=filediff.patch['filename'])} | |
745 | %endif |
|
748 | %endif | |
746 | <span class="cb-code"><span class="cb-action ${action_class(line.original.action)}"></span>${line.original.content or '' | n}</span> |
|
749 | <span class="cb-code"><span class="cb-action ${action_class(line.original.action)}"></span>${line.original.content or '' | n}</span> | |
747 |
|
750 | |||
748 | %if use_comments and line.original.lineno and line_old_comments: |
|
751 | %if use_comments and line.original.lineno and line_old_comments: | |
749 | ${inline_comments_container(line_old_comments, active_pattern_entries=active_pattern_entries)} |
|
752 | ${inline_comments_container(line_old_comments, active_pattern_entries=active_pattern_entries, line_no=line_no, f_path=filediff.patch['filename'])} | |
750 | %endif |
|
753 | %endif | |
751 |
|
754 | |||
752 | </td> |
|
755 | </td> | |
@@ -766,9 +769,9 b' def get_comments_for(diff_type, comments' | |||||
766 |
|
769 | |||
767 | %if line_new_comments_no_drafts: |
|
770 | %if line_new_comments_no_drafts: | |
768 | % if has_outdated: |
|
771 | % if has_outdated: | |
769 |
<i class="tooltip icon-comment-toggle" title="${_(' |
|
772 | <i class="tooltip toggle-comment-action icon-comment-toggle" title="${_('Comments including outdated: {}. Click here to toggle them.').format(len(line_new_comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i> | |
770 | % else: |
|
773 | % else: | |
771 |
<i class="tooltip icon-comment" title="${_(' |
|
774 | <i class="tooltip toggle-comment-action icon-comment" title="${_('Comments: {}. Click to toggle them.').format(len(line_new_comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i> | |
772 | % endif |
|
775 | % endif | |
773 | %endif |
|
776 | %endif | |
774 | </div> |
|
777 | </div> | |
@@ -783,22 +786,25 b' def get_comments_for(diff_type, comments' | |||||
783 | <a name="${new_line_anchor}" href="#${new_line_anchor}">${line.modified.lineno}</a> |
|
786 | <a name="${new_line_anchor}" href="#${new_line_anchor}">${line.modified.lineno}</a> | |
784 | %endif |
|
787 | %endif | |
785 | </td> |
|
788 | </td> | |
|
789 | ||||
|
790 | <% line_no = 'n{}'.format(line.modified.lineno) %> | |||
786 | <td class="cb-content ${action_class(line.modified.action)}" |
|
791 | <td class="cb-content ${action_class(line.modified.action)}" | |
787 |
data-line-no=" |
|
792 | data-line-no="${line_no}" | |
788 | > |
|
793 | > | |
789 | %if use_comments and line.modified.lineno: |
|
794 | %if use_comments and line.modified.lineno: | |
790 | ${render_add_comment_button()} |
|
795 | ${render_add_comment_button(line_no=line_no, f_path=filediff.patch['filename'])} | |
791 | %endif |
|
796 | %endif | |
792 | <span class="cb-code"><span class="cb-action ${action_class(line.modified.action)}"></span>${line.modified.content or '' | n}</span> |
|
797 | <span class="cb-code"><span class="cb-action ${action_class(line.modified.action)}"></span>${line.modified.content or '' | n}</span> | |
793 | %if use_comments and line.modified.lineno and line_new_comments: |
|
|||
794 | ${inline_comments_container(line_new_comments, active_pattern_entries=active_pattern_entries)} |
|
|||
795 | %endif |
|
|||
796 | % if line_action in ['+', '-'] and prev_line_action not in ['+', '-']: |
|
798 | % if line_action in ['+', '-'] and prev_line_action not in ['+', '-']: | |
797 | <div class="nav-chunk" style="visibility: hidden"> |
|
799 | <div class="nav-chunk" style="visibility: hidden"> | |
798 | <i class="icon-eye" title="viewing diff hunk-${hunk.index}-${chunk_count}"></i> |
|
800 | <i class="icon-eye" title="viewing diff hunk-${hunk.index}-${chunk_count}"></i> | |
799 | </div> |
|
801 | </div> | |
800 | <% chunk_count +=1 %> |
|
802 | <% chunk_count +=1 %> | |
801 | % endif |
|
803 | % endif | |
|
804 | %if use_comments and line.modified.lineno and line_new_comments: | |||
|
805 | ${inline_comments_container(line_new_comments, active_pattern_entries=active_pattern_entries, line_no=line_no, f_path=filediff.patch['filename'])} | |||
|
806 | %endif | |||
|
807 | ||||
802 | </td> |
|
808 | </td> | |
803 | </tr> |
|
809 | </tr> | |
804 | %endfor |
|
810 | %endfor | |
@@ -830,9 +836,9 b' def get_comments_for(diff_type, comments' | |||||
830 |
|
836 | |||
831 | % if comments_no_drafts: |
|
837 | % if comments_no_drafts: | |
832 | % if has_outdated: |
|
838 | % if has_outdated: | |
833 |
<i class="tooltip icon-comment-toggle" title="${_(' |
|
839 | <i class="tooltip toggle-comment-action icon-comment-toggle" title="${_('Comments including outdated: {}. Click here to toggle them.').format(len(comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i> | |
834 | % else: |
|
840 | % else: | |
835 |
<i class="tooltip icon-comment" title="${_(' |
|
841 | <i class="tooltip toggle-comment-action icon-comment" title="${_('Comments: {}. Click to toggle them.').format(len(comments_no_drafts))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i> | |
836 | % endif |
|
842 | % endif | |
837 | % endif |
|
843 | % endif | |
838 | </div> |
|
844 | </div> | |
@@ -857,15 +863,16 b' def get_comments_for(diff_type, comments' | |||||
857 | <a name="${new_line_anchor}" href="#${new_line_anchor}">${new_line_no}</a> |
|
863 | <a name="${new_line_anchor}" href="#${new_line_anchor}">${new_line_no}</a> | |
858 | %endif |
|
864 | %endif | |
859 | </td> |
|
865 | </td> | |
|
866 | <% line_no = '{}{}'.format(new_line_no and 'n' or 'o', new_line_no or old_line_no) %> | |||
860 | <td class="cb-content ${action_class(action)}" |
|
867 | <td class="cb-content ${action_class(action)}" | |
861 | data-line-no="${(new_line_no and 'n' or 'o')}${(new_line_no or old_line_no)}" |
|
868 | data-line-no="${line_no}" | |
862 | > |
|
869 | > | |
863 | %if use_comments: |
|
870 | %if use_comments: | |
864 | ${render_add_comment_button()} |
|
871 | ${render_add_comment_button(line_no=line_no, f_path=filediff.patch['filename'])} | |
865 | %endif |
|
872 | %endif | |
866 | <span class="cb-code"><span class="cb-action ${action_class(action)}"></span> ${content or '' | n}</span> |
|
873 | <span class="cb-code"><span class="cb-action ${action_class(action)}"></span> ${content or '' | n}</span> | |
867 | %if use_comments and comments: |
|
874 | %if use_comments and comments: | |
868 | ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)} |
|
875 | ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries, line_no=line_no, f_path=filediff.patch['filename'])} | |
869 | %endif |
|
876 | %endif | |
870 | </td> |
|
877 | </td> | |
871 | </tr> |
|
878 | </tr> | |
@@ -886,10 +893,12 b' def get_comments_for(diff_type, comments' | |||||
886 | </%def>file changes |
|
893 | </%def>file changes | |
887 |
|
894 | |||
888 |
|
895 | |||
889 | <%def name="render_add_comment_button()"> |
|
896 | <%def name="render_add_comment_button(line_no='', f_path='')"> | |
890 | <button class="btn btn-small btn-primary cb-comment-box-opener" onclick="return Rhodecode.comments.createComment(this)"> |
|
897 | % if not c.rhodecode_user.is_default: | |
|
898 | <button class="btn btn-small btn-primary cb-comment-box-opener" onclick="return Rhodecode.comments.createComment(this, '${f_path}', '${line_no}', null)"> | |||
891 | <span><i class="icon-comment"></i></span> |
|
899 | <span><i class="icon-comment"></i></span> | |
892 | </button> |
|
900 | </button> | |
|
901 | % endif | |||
893 | </%def> |
|
902 | </%def> | |
894 |
|
903 | |||
895 | <%def name="render_diffset_menu(diffset, range_diff_on=None, commit=None, pull_request_menu=None)"> |
|
904 | <%def name="render_diffset_menu(diffset, range_diff_on=None, commit=None, pull_request_menu=None)"> |
@@ -456,7 +456,7 b'' | |||||
456 | </div> |
|
456 | </div> | |
457 |
|
457 | |||
458 | <div class="markup-form-area-write" style="display: block;"> |
|
458 | <div class="markup-form-area-write" style="display: block;"> | |
459 | <div id="edit-container_${form_id}"> |
|
459 | <div id="edit-container_${form_id}" style="margin-top: -1px"> | |
460 | <textarea id="${form_id}" name="${form_id}" class="comment-block-ta ac-input">${form_text if form_text else ''}</textarea> |
|
460 | <textarea id="${form_id}" name="${form_id}" class="comment-block-ta ac-input">${form_text if form_text else ''}</textarea> | |
461 | </div> |
|
461 | </div> | |
462 | <div id="preview-container_${form_id}" class="clearfix" style="display: none;"> |
|
462 | <div id="preview-container_${form_id}" class="clearfix" style="display: none;"> |
@@ -237,6 +237,24 b' if (show_disabled) {' | |||||
237 |
|
237 | |||
238 | </script> |
|
238 | </script> | |
239 |
|
239 | |||
|
240 | <script id="ejs_commentHelpHovercard" type="text/template" class="ejsTemplate"> | |||
|
241 | ||||
|
242 | <div> | |||
|
243 | Use <strong>@username</strong> mention syntax to send direct notification to this RhodeCode user.<br/> | |||
|
244 | Typing / starts autocomplete for certain action, e.g set review status, or comment type. <br/> | |||
|
245 | <br/> | |||
|
246 | Use <strong>Cmd/ctrl+enter</strong> to submit comment, or <strong>Shift+Cmd/ctrl+enter</strong> to submit a draft.<br/> | |||
|
247 | <br/> | |||
|
248 | <strong>Draft comments</strong> are private to the author, and trigger no notification to others.<br/> | |||
|
249 | They are permanent until deleted, or converted to regular comments.<br/> | |||
|
250 | <br/> | |||
|
251 | <br/> | |||
|
252 | </div> | |||
|
253 | ||||
|
254 | </script> | |||
|
255 | ||||
|
256 | ||||
|
257 | ||||
240 | ##// END OF EJS Templates |
|
258 | ##// END OF EJS Templates | |
241 | </div> |
|
259 | </div> | |
242 |
|
260 |
@@ -846,6 +846,7 b' versionController.init();' | |||||
846 |
|
846 | |||
847 | reviewersController = new ReviewersController(); |
|
847 | reviewersController = new ReviewersController(); | |
848 | commitsController = new CommitsController(); |
|
848 | commitsController = new CommitsController(); | |
|
849 | commentsController = new CommentsController(); | |||
849 |
|
850 | |||
850 | updateController = new UpdatePrController(); |
|
851 | updateController = new UpdatePrController(); | |
851 |
|
852 | |||
@@ -1002,6 +1003,8 b' window.setObserversData = ${c.pull_reque' | |||||
1002 | alert('okok !' + commentIds) |
|
1003 | alert('okok !' + commentIds) | |
1003 |
|
1004 | |||
1004 | } |
|
1005 | } | |
|
1006 | // register globally so inject comment logic can re-use it. | |||
|
1007 | window.commentsController = commentsController; | |||
1005 |
|
1008 | |||
1006 | }) |
|
1009 | }) | |
1007 | </script> |
|
1010 | </script> |
General Comments 0
You need to be logged in to leave comments.
Login now