mezzanine icon indicating copy to clipboard operation
mezzanine copied to clipboard

Add feature to allow users editing their owns comments

Open eayin2 opened this issue 8 years ago • 2 comments

{% editable comment.comment %} only allows staff to edit comments, please allow also users to edit their own comments.

References: mezzanine/js/editable.js mezzanine/core/includes/editable_form.html

  • Use editable_form.html as template for editable_user_form.html pointing to {% url "user_edit" %}

mezzanine.core.views.edit

  • Create user_edit view by replacing if not (is_editable(obj, request) and has_site_permission(request.user)): with if request.user != obj.user

I purposely didn't add a pull request, because I don't know how to integrate this with TinyMCE.

eayin2 avatar Nov 05 '17 16:11 eayin2

I didn't have to bother with TinyMCE. This worked for me:

  1. Add mezzanine.core.templatetags.mezzanine_tags.user_editable:
  • Here I only changed is_editable() to is_user_editable()

def user_editable(parsed, context, token):
    """
    Add the required HTML to the parsed content for in-line editing,
    such as the icon and edit form if the object is deemed to be
    editable - either it has an ``editable`` method which returns
    ``True``, or the logged in user has change permissions for the
    model.
    """
    def parse_field(field):
        field = field.split(".")
        obj = context.get(field.pop(0), None)
        attr = field.pop()
        while field:
            obj = getattr(obj, field.pop(0))
            if callable(obj):
                # Allows {% editable page.get_content_model.content %}
                obj = obj()
        return obj, attr

    fields = [parse_field(f) for f in token.split_contents()[1:]]
    if fields:
        fields = [f for f in fields if len(f) == 2 and f[0] is fields[0][0]]
    if not parsed.strip():
        try:
            parsed = "".join([str(getattr(*field)) for field in fields])
        except AttributeError:
            pass

    if settings.INLINE_EDITING_ENABLED and fields and "request" in context:
        obj = fields[0][0]
        if isinstance(obj, Model) and is_user_editable(obj, context["request"]):
            field_names = ",".join([f[1] for f in fields])
            context["editable_form"] = get_edit_form(obj, field_names)
            context["original"] = parsed
            t = get_template("includes/editable_form.html")
            return t.render(context.flatten())
    return parsed

  1. Add mezzanine.utils.views.is_user_editable
  • Here we only check for if request.user == obj.user and removed the permission and has_site_permission checks.
def is_user_editable(obj, request):
    """
    Returns ``True`` if the object is editable for the request. First
    check for a custom ``editable`` handler on the object, otherwise
    use the logged in user and check change permissions for the
    object's model.
    """
    if hasattr(obj, "is_editable"):
        return obj.is_editable(request)
    else:
        return (request.user == obj.user)
  1. Then we can use {% user_editable comment.comment %} instead of {% editable comment.comment %} in the templates

Is it okay to add it like this?

eayin2 avatar Nov 05 '17 17:11 eayin2

We should add this ability for users to edit their own comments. The approach you've taken isn't correct though - inline editing is definitely only intended for administrators.

The correct approach will need to modify the comments_for template tag, which currently adds 2 forms to the template - a reply form, and a new comment form. We could potentially use one of these, or add a third, that gets used to edit a comment, by adding the comment ID to the form. Some handling would also be needed server-side to ensure the user is the owner of the comment being edited.

stephenmcd avatar Nov 12 '17 23:11 stephenmcd