diff --git a/pillar/web/nodes/custom/comments.py b/pillar/web/nodes/custom/comments.py index 14cc036f..6693a8ac 100644 --- a/pillar/web/nodes/custom/comments.py +++ b/pillar/web/nodes/custom/comments.py @@ -126,7 +126,10 @@ def format_comment(comment, is_reply=False, is_team=False, replies=None): @blueprint.route('//comments') def comments_for_node(node_id): - """Shows the comments attached to the given node.""" + """Shows the comments attached to the given node. + + The URL can be overridden in order to define can_post_comments in a different way + """ api = system_util.pillar_api() @@ -134,7 +137,14 @@ def comments_for_node(node_id): project = Project({'_id': node.project}) can_post_comments = project.node_type_has_method('comment', 'POST', api=api) can_comment_override = request.args.get('can_comment', 'True') == 'True' - can_post_comments = can_post_comments and can_comment_override and current_user.has_cap('subscriber') + can_post_comments = can_post_comments and can_comment_override + + return render_comments_for_node(node_id, can_post_comments=can_post_comments) + + +def render_comments_for_node(node_id: str, *, can_post_comments: bool): + """Render the list of comments for a node.""" + api = system_util.pillar_api() # Query for all children, i.e. comments on the node. comments = Node.all({ @@ -145,7 +155,8 @@ def comments_for_node(node_id): some_comment['_user'] = subquery.get_user_info(some_comment['user']) some_comment['_is_own'] = some_comment['user'] == current_user.objectid some_comment['_current_user_rating'] = None # tri-state boolean - some_comment['_rating'] = some_comment.properties.rating_positive - some_comment.properties.rating_negative + some_comment[ + '_rating'] = some_comment.properties.rating_positive - some_comment.properties.rating_negative if current_user.is_authenticated: for rating in some_comment.properties.ratings or (): @@ -163,10 +174,8 @@ def comments_for_node(node_id): enrich(comment) for reply in comment['_replies']['_items']: enrich(reply) - nr_of_comments = sum(1 + comment['_replies']['_meta']['total'] for comment in comments['_items']) - return render_template('nodes/custom/comment/list_embed.html', node_id=node_id, comments=comments, diff --git a/src/templates/nodes/custom/comment/list_embed.pug b/src/templates/nodes/custom/comment/list_embed.pug index a2c890a3..43a380c5 100644 --- a/src/templates/nodes/custom/comment/list_embed.pug +++ b/src/templates/nodes/custom/comment/list_embed.pug @@ -1,233 +1 @@ -| {% import 'nodes/custom/comment/_macros.html' as macros %} -#comments.comments-container - section#comments-list.comments-list - .comment-reply-container - | {% if can_post_comments %} - .comment-reply-avatar - img( - title="{{ _('Commenting as') }} {{ current_user.full_name }}", - src="{{ current_user.gravatar }}") - - .comment-reply-form - - .comment-reply-field - textarea( - id="comment_field", - data-parent-id="{{ node_id }}", - placeholder="{{ _('Join the conversation...') }}") - - .comment-reply-meta - - button.comment-action-submit( - id="comment_submit", - type="button", - title="Post Comment (Ctrl+Enter)") - span - i.pi-paper-plane - | {{ _('Send') }} - span.hotkey Ctrl + Enter - - .comment-reply-preview - .comment-reply-preview-md - .comment-reply-info - .comment-action-cancel( - type="button", - title="{{ _('cancel') }}") - span {{ _('cancel') }} - - a( - title="{{ _('Handy guide of Markdown syntax') }}", - target="_blank", - href="https://guides.github.com/features/mastering-markdown/") - span {{ _('markdown cheatsheet') }} - - | {% elif current_user.is_authenticated %} - - | {# * User is authenticated, but has no subscription or 'POST' permission #} - .comment-reply-form - .comment-reply-field.sign-in - | {% if current_user.has_cap('subscriber') %} - i.pi-lock - | Only project members can comment. - | {% elif current_user.has_cap('can-renew-subscription') %} - i.pi-heart - a(href='/renew', target='_blank') Renew your subscription to join the conversation! - | {% else %} - | Join the conversation! Subscribe to Blender Cloud now. - | {% endif %} - - | {% else %} - | {# * User is not autenticated #} - .comment-reply-form - .comment-reply-field.sign-in - a(href="{{ url_for('users.login') }}") {{ _('Log in to comment') }} - | {% endif %} - - | {% if show_comments and (nr_of_comments > 0) %} - section.comments-list-header - .comments-list-title - | {{ nr_of_comments }} {{ _('comment') }}{{ nr_of_comments|pluralize }} - .comments-list-items - | {% for comment in comments['_items'] %} - | {{ macros.render_comment(comment, False) }} - | {% endfor %} - | {% endif %} - -| {% block comment_scripts %} -script. - - {% if show_comments %} - $('body') - .off('pillar:comment-posted') - .on('pillar:comment-posted', function(e, comment_node_id) { - - var commentsUrl = "{{ url_for('nodes.comments_for_node', node_id=node_id) }}"; - - loadComments(commentsUrl) - .done(function() { - $('#' + comment_node_id).scrollHere(); - }); - }); - - // If there's a comment link in the URL, scroll there - function scrollToLinkedComment() { - var scrollToId = location.hash; - - // Check that it's a valid ObjectID before passing it to jQuery. - if (!/^[a-fA-F0-9]{24}$/.test(scrollToId)) return; - - $(scrollToId) - .addClass('comment-linked') - .scrollHere(); - } - $(scrollToLinkedComment); - - {% endif %} - - - {% if can_post_comments %} - - // If we can actually comment, load the tools to do it - - // Initialize Markdown to later convert comment as we type - var convert = new Markdown.getSanitizingConverter(); - Markdown.Extra.init(convert); - convert = convert.makeHtml; - - // Submit new comment - $(document) - .off('click','body .comment-action-submit') - .on( 'click','body .comment-action-submit', function(e){ - post_comment($(this)); - }); - - // Writing comment - // Markdown convert as we type in the textarea - $(document) - .off('keyup','body .comment-reply-field textarea') - .on( 'keyup','body .comment-reply-field textarea',function(e){ - var $textarea = $(this); - var $container = $(this).parent(); - var $preview = $container.parent().find('.comment-reply-preview-md'); - - // TODO: communicate with back-end to do the conversion, - // rather than relying on our JS-converted Markdown. - $preview.html(convert($textarea.val())); - - // While we are at it, style if empty - if ($textarea.val()) { - $container.addClass('filled'); - } else { - $container.removeClass('filled'); - } - - // Send on ctrl+enter - if ($textarea.is(":focus")) { - if ((e.keyCode == 10 || e.keyCode == 13) && e.ctrlKey){ - post_comment($container.find('.comment-action-submit')); - } - } - }); - - // Autoresize the textarea as we type - $('#comment_field').autoResize(); - - - // Edit comment - // Enter edit mode - $(document) - .off('click','body .comment-action-edit span.edit_mode') - .on( 'click','body .comment-action-edit span.edit_mode',function(){ - - comment_mode(this, 'edit'); - - var $parent_div = $(this).closest('.comment-container'); - var comment_id = $parent_div.data('node-id'); - - var comment_content = $parent_div.find('.comment-body span'); - var height = comment_content.height(); - - loadComment(comment_id, {'properties.content': 1}) - - .done(function(data) { - var comment_raw = data['properties']['content']; - comment_content.html($('