kopia lustrzana https://github.com/wagtail/wagtail
Add structure of CommentPanel to initialize the comment app in the frontend, and add forms to validate comments on save. (Comments are not yet output or written to the db)
rodzic
9a48221d66
commit
1ca48eb31f
|
@ -13,6 +13,8 @@ from django.utils.translation import gettext_lazy
|
|||
from taggit.managers import TaggableManager
|
||||
|
||||
from wagtail.admin import compare, widgets
|
||||
from wagtail.admin.forms.comments import CommentForm, CommentReplyForm
|
||||
from wagtail.admin.templatetags.wagtailadmin_tags import user_display_name
|
||||
from wagtail.core.fields import RichTextField
|
||||
from wagtail.core.models import Page
|
||||
from wagtail.core.utils import camelcase_to_underscore, resolve_model_string
|
||||
|
@ -59,6 +61,7 @@ def get_form_for_model(
|
|||
}
|
||||
|
||||
metaclass = type(form_class)
|
||||
|
||||
return metaclass(class_name, (form_class,), form_class_attrs)
|
||||
|
||||
|
||||
|
@ -789,8 +792,65 @@ class PrivacyModalPanel(EditHandler):
|
|||
)
|
||||
|
||||
|
||||
class CommentPanel(EditHandler):
|
||||
def required_formsets(self):
|
||||
# add the comments formset
|
||||
# we need to pass in the current user for validation on the formset
|
||||
# this could alternatively be done on the page form itself if we added the
|
||||
# comments formset there, but we typically only add fields via edit handlers
|
||||
current_user = getattr(self.request, 'user', None)
|
||||
|
||||
class CommentReplyFormWithRequest(CommentReplyForm):
|
||||
user = current_user
|
||||
|
||||
class CommentFormWithRequest(CommentForm):
|
||||
user = current_user
|
||||
|
||||
class Meta:
|
||||
formsets = {
|
||||
'replies': {
|
||||
'form': CommentReplyFormWithRequest
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
'comments': {
|
||||
'form': CommentFormWithRequest,
|
||||
'fields': ['text', 'contentpath'],
|
||||
}
|
||||
}
|
||||
|
||||
template = "wagtailadmin/edit_handlers/comments/comment_panel.html"
|
||||
js_template = "wagtailadmin/edit_handlers/comments/comment_panel.js"
|
||||
declarations_template = "wagtailadmin/edit_handlers/comments/comment_declarations.html"
|
||||
|
||||
def html_declarations(self):
|
||||
return render_to_string(self.declarations_template)
|
||||
|
||||
def render(self):
|
||||
user = getattr(self.request, 'user', None)
|
||||
comments_author = {
|
||||
'id': user.pk,
|
||||
'name': user_display_name(user)
|
||||
} if user else None
|
||||
|
||||
panel = render_to_string(self.template, {
|
||||
'self': self,
|
||||
'comments_author': comments_author
|
||||
})
|
||||
js = self.render_js_init()
|
||||
return widget_with_script(panel, js)
|
||||
|
||||
def render_js_init(self):
|
||||
return mark_safe(render_to_string(self.js_template, {
|
||||
'self': self,
|
||||
}))
|
||||
|
||||
|
||||
# Now that we've defined EditHandlers, we can set up wagtailcore.Page to have some.
|
||||
|
||||
Page.content_panels = [
|
||||
CommentPanel(),
|
||||
FieldPanel('title', classname="full title"),
|
||||
]
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
from django.forms import ValidationError
|
||||
from django.forms.formsets import DELETION_FIELD_NAME
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from .models import WagtailAdminModelForm
|
||||
|
||||
|
||||
class CommentReplyForm(WagtailAdminModelForm):
|
||||
user = None
|
||||
|
||||
class Meta:
|
||||
fields = ('text',)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
user = self.user
|
||||
if self.instance.pk and self.instance.user != user:
|
||||
# trying to edit someone else's comment reply
|
||||
if any(field for field in self.changed_data):
|
||||
# includes DELETION_FIELD_NAME, as users cannot delete each other's individual comment replies
|
||||
# if deleting a whole thread, this should be done by deleting the parent Comment instead
|
||||
self.add_error(None, error=ValidationError(_("You cannot edit another user's comment")))
|
||||
return cleaned_data
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.instance.pk:
|
||||
self.instance.user = self.user
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class CommentForm(WagtailAdminModelForm):
|
||||
"""
|
||||
This is designed to be subclassed and have the user overidden to enable user-based validation within the edit handler system
|
||||
"""
|
||||
user = None
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
user = self.user
|
||||
|
||||
if self.instance.pk and self.instance.user != user:
|
||||
# trying to edit someone else's comment
|
||||
if any(field for field in self.changed_data if field != DELETION_FIELD_NAME):
|
||||
# users can delete each other's base comments, as this is just the "resolve" action
|
||||
self.add_error(None, error=ValidationError(_("You cannot edit another user's comment")))
|
||||
|
||||
return cleaned_data
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.instance.pk:
|
||||
self.instance.user = self.user
|
||||
return super().save(*args, **kwargs)
|
|
@ -114,7 +114,6 @@ class WagtailAdminPageForm(WagtailAdminModelForm):
|
|||
self.parent_page = parent_page
|
||||
|
||||
def clean(self):
|
||||
|
||||
cleaned_data = super().clean()
|
||||
if 'slug' in self.cleaned_data:
|
||||
if not Page._slug_is_available(
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
{% load wagtailadmin_tags %}
|
||||
<button type="button" id="comment-icon" data-annotation class="button button-secondary button-small u-hidden">{% icon name='comment' class_name='initial' %}</button>
|
|
@ -0,0 +1,6 @@
|
|||
{% load wagtailadmin_tags %}
|
||||
<div>
|
||||
<div id="comments"></div>
|
||||
</div>
|
||||
{{ comments_author|json_script:"comments-author" }}
|
||||
<script src="{% versioned_static 'wagtailadmin/js/comments.js' %}"></script>
|
|
@ -0,0 +1 @@
|
|||
window.comments.initComments([]);
|
|
@ -27,6 +27,4 @@
|
|||
<script src="{% versioned_static 'wagtailadmin/js/workflow-status.js' %}"></script>
|
||||
<script src="{% versioned_static 'wagtailadmin/js/lock-unlock-action.js' %}"></script>
|
||||
<script src="{% versioned_static 'wagtailadmin/js/vendor/bootstrap-tooltip.js' %}"></script>
|
||||
<script src="{% versioned_static 'wagtailadmin/js/comments.js' %}"></script>
|
||||
|
||||
{% hook_output 'insert_editor_js' %}
|
||||
|
|
|
@ -116,8 +116,6 @@
|
|||
Additional HTML code that edit handlers define through 'html_declarations'. (Technically this isn't JavaScript, but it will generally be data that exists for JavaScript to work with...)
|
||||
{% endcomment %}
|
||||
{{ edit_handler.html_declarations }}
|
||||
{{ comments_author|json_script:"comments-author" }}
|
||||
<button type="button" id="comment-icon" data-annotation class="button button-secondary button-small u-hidden">{% icon name='comment' class_name='initial' %}</button>
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
|
@ -179,7 +177,4 @@
|
|||
LockUnlockAction('{{ csrf_token|escapejs }}', '{% url 'wagtailadmin_pages:edit' page.id %}');
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
window.comments.initComments([]);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -14,7 +14,6 @@ from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
|
|||
|
||||
from wagtail.admin import messages
|
||||
from wagtail.admin.action_menu import PageActionMenu
|
||||
from wagtail.admin.templatetags.wagtailadmin_tags import user_display_name
|
||||
from wagtail.admin.views.generic import HookResponseMixin
|
||||
from wagtail.admin.views.pages.utils import get_valid_next_url_from_request
|
||||
from wagtail.core.exceptions import PageClassNotFoundError
|
||||
|
@ -533,10 +532,6 @@ class EditView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
'publishing_will_cancel_workflow': self.workflow_tasks and getattr(settings, 'WAGTAIL_WORKFLOW_CANCEL_ON_PUBLISH', True),
|
||||
'locale': None,
|
||||
'translations': [],
|
||||
'comments_author': {
|
||||
'id': self.request.user.pk, # TODO: move into the comments widget/edit handler when created
|
||||
'name': user_display_name(self.request.user)
|
||||
},
|
||||
})
|
||||
|
||||
if getattr(settings, 'WAGTAIL_I18N_ENABLED', False):
|
||||
|
|
Ładowanie…
Reference in New Issue