|
@@ -1,383 +0,0 @@
|
|
|
-from django.contrib.admin import SimpleListFilter
|
|
|
-from django.contrib.admin.utils import quote
|
|
|
-from django.shortcuts import redirect
|
|
|
-from django.urls import path, reverse
|
|
|
-from django.utils.translation import gettext_lazy as _
|
|
|
-from wagtail.contrib.modeladmin.helpers import (
|
|
|
- PermissionHelper,
|
|
|
- PagePermissionHelper,
|
|
|
- PageAdminURLHelper,
|
|
|
- AdminURLHelper,
|
|
|
- ButtonHelper,
|
|
|
-)
|
|
|
-from wagtail.contrib.modeladmin.options import ModelAdmin
|
|
|
-from wagtail.contrib.modeladmin.views import IndexView, InstanceSpecificView
|
|
|
-from wagtail.admin import messages
|
|
|
-from wagtail import hooks
|
|
|
-from wagtail.models import Page
|
|
|
-from wagtail.contrib.forms.utils import get_forms_for_user
|
|
|
-
|
|
|
-from .models import SessionFormSubmission
|
|
|
-
|
|
|
-
|
|
|
-class FormIndexView(IndexView):
|
|
|
- page_title = _("Forms")
|
|
|
-
|
|
|
-
|
|
|
-class FormPermissionHelper(PagePermissionHelper):
|
|
|
- def user_can_list(self, user):
|
|
|
- return get_forms_for_user(user).exists()
|
|
|
-
|
|
|
- def user_can_create(self, user):
|
|
|
- return False
|
|
|
-
|
|
|
- def user_can_edit_obj(self, user, obj):
|
|
|
- return False
|
|
|
-
|
|
|
- def user_can_delete_obj(self, user, obj):
|
|
|
- return False
|
|
|
-
|
|
|
- def user_can_publish_obj(self, user, obj):
|
|
|
- return False
|
|
|
-
|
|
|
- def user_can_unpublish_obj(self, user, obj):
|
|
|
- return False
|
|
|
-
|
|
|
- def user_can_copy_obj(self, user, obj):
|
|
|
- return False
|
|
|
-
|
|
|
- def user_can_inspect_obj(self, user, obj):
|
|
|
- return False
|
|
|
-
|
|
|
-
|
|
|
-class FormURLHelper(PageAdminURLHelper):
|
|
|
- def _get_action_url_pattern(self, action):
|
|
|
- if action == "index":
|
|
|
- return r"^stream_forms/$"
|
|
|
- return r"^stream_forms/%s/$" % action
|
|
|
-
|
|
|
-
|
|
|
-class FormAdmin(ModelAdmin):
|
|
|
- model = Page
|
|
|
- menu_label = _("Forms")
|
|
|
- menu_icon = "form"
|
|
|
- list_display = (
|
|
|
- "title",
|
|
|
- "unprocessed_submissions_link",
|
|
|
- "all_submissions_link",
|
|
|
- "edit_link",
|
|
|
- )
|
|
|
- index_view_class = FormIndexView
|
|
|
- permission_helper_class = FormPermissionHelper
|
|
|
- url_helper_class = FormURLHelper
|
|
|
-
|
|
|
- def get_queryset(self, request):
|
|
|
- return get_forms_for_user(request.user)
|
|
|
-
|
|
|
- def all_submissions_link(
|
|
|
- self, obj, label=_("See all submissions"), url_suffix=""
|
|
|
- ):
|
|
|
- return '<a href="%s?page_id=%s%s">%s</a>' % (
|
|
|
- reverse(SubmissionAdmin().url_helper.get_action_url_name("index")),
|
|
|
- obj.pk,
|
|
|
- url_suffix,
|
|
|
- label,
|
|
|
- )
|
|
|
-
|
|
|
- all_submissions_link.short_description = ""
|
|
|
- all_submissions_link.allow_tags = True
|
|
|
-
|
|
|
- def unprocessed_submissions_link(self, obj):
|
|
|
- return self.all_submissions_link(
|
|
|
- obj,
|
|
|
- _("See unprocessed submissions"),
|
|
|
- "&status=%s" % SubmissionStatusFilter.unprocessed_status,
|
|
|
- )
|
|
|
-
|
|
|
- unprocessed_submissions_link.short_description = ""
|
|
|
- unprocessed_submissions_link.allow_tags = True
|
|
|
-
|
|
|
- def edit_link(self, obj):
|
|
|
- return '<a href="%s">%s</a>' % (
|
|
|
- reverse("wagtailadmin_pages:edit", args=(obj.pk,)),
|
|
|
- _("Edit this form page"),
|
|
|
- )
|
|
|
-
|
|
|
- edit_link.short_description = ""
|
|
|
- edit_link.allow_tags = True
|
|
|
-
|
|
|
-
|
|
|
-class SubmissionStatusFilter(SimpleListFilter):
|
|
|
- title = _("status")
|
|
|
- parameter_name = "status"
|
|
|
- unprocessed_status = ",".join(
|
|
|
- (SessionFormSubmission.COMPLETE, SessionFormSubmission.REVIEWED)
|
|
|
- )
|
|
|
-
|
|
|
- def lookups(self, request, model_admin):
|
|
|
- yield (self.unprocessed_status, _("Complete or reviewed"))
|
|
|
- for status, verbose_status in SessionFormSubmission.STATUSES:
|
|
|
- if status != SessionFormSubmission.INCOMPLETE:
|
|
|
- yield status, verbose_status
|
|
|
-
|
|
|
- def queryset(self, request, queryset):
|
|
|
- status = self.value()
|
|
|
- if not status:
|
|
|
- return queryset
|
|
|
- if "," in status:
|
|
|
- return queryset.filter(status__in=status.split(","))
|
|
|
- return queryset.filter(status=status)
|
|
|
-
|
|
|
-
|
|
|
-class SubmissionPermissionHelper(PermissionHelper):
|
|
|
- def user_can_list(self, user):
|
|
|
- return get_forms_for_user(user).exists()
|
|
|
-
|
|
|
- def user_can_create(self, user):
|
|
|
- return False
|
|
|
-
|
|
|
- def user_can_edit_obj(self, user, obj):
|
|
|
- return False
|
|
|
-
|
|
|
- def user_can_inspect_obj(self, user, obj):
|
|
|
- return False
|
|
|
-
|
|
|
- def user_can_set_status_obj(self, user, obj):
|
|
|
- return user.can_set_status()
|
|
|
-
|
|
|
-
|
|
|
-class SubmissionURLHelper(AdminURLHelper):
|
|
|
- def _get_action_url_pattern(self, action):
|
|
|
- if action == "index":
|
|
|
- return r"^%s/%s/$" % (self.opts.app_label, "submissions")
|
|
|
- return r"^%s/%s/%s/$" % (self.opts.app_label, "submissions", action)
|
|
|
-
|
|
|
- def _get_object_specific_action_url_pattern(self, action):
|
|
|
- return r"^%s/%s/%s/(?P<instance_pk>[-\w]+)/$" % (
|
|
|
- self.opts.app_label,
|
|
|
- "submissions",
|
|
|
- action,
|
|
|
- )
|
|
|
-
|
|
|
-
|
|
|
-class SubmissionButtonHelper(ButtonHelper):
|
|
|
- def set_status_button(
|
|
|
- self,
|
|
|
- pk,
|
|
|
- status,
|
|
|
- label,
|
|
|
- title,
|
|
|
- classnames_add=None,
|
|
|
- classnames_exclude=None,
|
|
|
- ):
|
|
|
- if classnames_add is None:
|
|
|
- classnames_add = []
|
|
|
- if classnames_exclude is None:
|
|
|
- classnames_exclude = []
|
|
|
- classnames = self.finalise_classname(classnames_add, classnames_exclude)
|
|
|
- url = self.url_helper.get_action_url("set_status", quote(pk))
|
|
|
- url += "?status=" + status
|
|
|
- return {
|
|
|
- "url": url,
|
|
|
- "label": label,
|
|
|
- "classname": classnames,
|
|
|
- "title": title,
|
|
|
- }
|
|
|
-
|
|
|
- def reviewed_button(self, pk, classnames_add=None, classnames_exclude=None):
|
|
|
- if classnames_add is None:
|
|
|
- classnames_add = []
|
|
|
- return self.set_status_button(
|
|
|
- pk,
|
|
|
- self.model.REVIEWED,
|
|
|
- _("mark as reviewed"),
|
|
|
- _("Mark this submission as reviewed"),
|
|
|
- classnames_add=classnames_add,
|
|
|
- classnames_exclude=classnames_exclude,
|
|
|
- )
|
|
|
-
|
|
|
- def approve_button(self, pk, classnames_add=None, classnames_exclude=None):
|
|
|
- if classnames_add is None:
|
|
|
- classnames_add = []
|
|
|
- if "button-secondary" in classnames_add:
|
|
|
- classnames_add.remove("button-secondary")
|
|
|
- classnames_add = ["yes"] + classnames_add
|
|
|
- return self.set_status_button(
|
|
|
- pk,
|
|
|
- self.model.APPROVED,
|
|
|
- _("approve"),
|
|
|
- _("Approve this submission"),
|
|
|
- classnames_add=classnames_add,
|
|
|
- classnames_exclude=classnames_exclude,
|
|
|
- )
|
|
|
-
|
|
|
- def reject_button(self, pk, classnames_add=None, classnames_exclude=None):
|
|
|
- if classnames_add is None:
|
|
|
- classnames_add = []
|
|
|
- if "button-secondary" in classnames_add:
|
|
|
- classnames_add.remove("button-secondary")
|
|
|
- classnames_add = ["no"] + classnames_add
|
|
|
- return self.set_status_button(
|
|
|
- pk,
|
|
|
- self.model.REJECTED,
|
|
|
- _("reject"),
|
|
|
- _("Reject this submission"),
|
|
|
- classnames_add=classnames_add,
|
|
|
- classnames_exclude=classnames_exclude,
|
|
|
- )
|
|
|
-
|
|
|
- def get_buttons_for_obj(
|
|
|
- self, obj, exclude=None, classnames_add=None, classnames_exclude=None
|
|
|
- ):
|
|
|
- buttons = super().get_buttons_for_obj(
|
|
|
- obj,
|
|
|
- exclude=exclude,
|
|
|
- classnames_add=classnames_add,
|
|
|
- classnames_exclude=classnames_exclude,
|
|
|
- )
|
|
|
- pk = getattr(obj, self.opts.pk.attname)
|
|
|
- status_buttons = []
|
|
|
- if obj.status != obj.REVIEWED:
|
|
|
- status_buttons.append(
|
|
|
- self.reviewed_button(
|
|
|
- pk,
|
|
|
- classnames_add=classnames_add,
|
|
|
- classnames_exclude=classnames_exclude,
|
|
|
- )
|
|
|
- )
|
|
|
- if obj.status != obj.APPROVED:
|
|
|
- status_buttons.append(
|
|
|
- self.approve_button(
|
|
|
- pk,
|
|
|
- classnames_add=classnames_add,
|
|
|
- classnames_exclude=classnames_exclude,
|
|
|
- )
|
|
|
- )
|
|
|
- if obj.status != obj.REJECTED:
|
|
|
- status_buttons.append(
|
|
|
- self.reject_button(
|
|
|
- pk,
|
|
|
- classnames_add=classnames_add,
|
|
|
- classnames_exclude=classnames_exclude,
|
|
|
- )
|
|
|
- )
|
|
|
- return status_buttons + buttons
|
|
|
-
|
|
|
-
|
|
|
-class SetStatusView(InstanceSpecificView):
|
|
|
- def check_action_permitted(self, user):
|
|
|
- return self.permission_helper.user_can_set_status_obj(
|
|
|
- user, self.instance
|
|
|
- )
|
|
|
-
|
|
|
- def get(self, request, *args, **kwargs):
|
|
|
- status = request.GET.get("status")
|
|
|
- if status in dict(self.model.STATUSES):
|
|
|
- previous_status = self.instance.status
|
|
|
- self.instance.status = status
|
|
|
- self.instance.save()
|
|
|
- verbose_label = self.instance.get_status_display()
|
|
|
- if "revert" in request.GET:
|
|
|
- messages.success(
|
|
|
- request, "Reverted to the “%s” status." % verbose_label
|
|
|
- )
|
|
|
- else:
|
|
|
- revert_url = (
|
|
|
- self.url_helper.get_action_url(
|
|
|
- "set_status", self.instance_pk
|
|
|
- )
|
|
|
- + "?revert&status="
|
|
|
- + previous_status
|
|
|
- )
|
|
|
- messages.success(
|
|
|
- request,
|
|
|
- "Successfully changed the status to “%s”." % verbose_label,
|
|
|
- buttons=[messages.button(revert_url, _("Revert"))],
|
|
|
- )
|
|
|
- url = request.META.get("HTTP_REFERER")
|
|
|
- if url is None:
|
|
|
- url = (
|
|
|
- self.url_helper.get_action_url("index")
|
|
|
- + "?page_id=%s" % self.instance.page_id
|
|
|
- )
|
|
|
- return redirect(url)
|
|
|
-
|
|
|
-
|
|
|
-class SubmissionAdmin(ModelAdmin):
|
|
|
- model = SessionFormSubmission
|
|
|
- menu_icon = "form"
|
|
|
- permission_helper_class = SubmissionPermissionHelper
|
|
|
- url_helper_class = SubmissionURLHelper
|
|
|
- button_helper_class = SubmissionButtonHelper
|
|
|
- set_status_view_class = SetStatusView
|
|
|
- list_display = ("status", "user", "submit_time", "last_modification")
|
|
|
- list_filter = (SubmissionStatusFilter, "submit_time", "last_modification")
|
|
|
- search_fields = ("user__first_name", "user__last_name")
|
|
|
-
|
|
|
- def register_with_wagtail(self):
|
|
|
- @hooks.register("register_permissions")
|
|
|
- def register_permissions():
|
|
|
- return self.get_permissions_for_registration()
|
|
|
-
|
|
|
- @hooks.register("register_admin_urls")
|
|
|
- def register_admin_urls():
|
|
|
- return self.get_admin_urls_for_registration()
|
|
|
-
|
|
|
- def get_queryset(self, request):
|
|
|
- qs = super().get_queryset(request)
|
|
|
- form_pages = get_forms_for_user(request.user)
|
|
|
- return qs.filter(page__in=form_pages).exclude(
|
|
|
- status=self.model.INCOMPLETE
|
|
|
- )
|
|
|
-
|
|
|
- def get_form_page(self, request):
|
|
|
- form_pages = get_forms_for_user(request.user)
|
|
|
- try:
|
|
|
- return form_pages.get(pk=int(request.GET["page_id"])).specific
|
|
|
- except (KeyError, TypeError, ValueError, Page.DoesNotExist):
|
|
|
- pass
|
|
|
-
|
|
|
- # TODO: Find a cleaner way to display data from dynamic fields.
|
|
|
- def add_data_bridge(self, name, label):
|
|
|
- def data_bridge(obj):
|
|
|
- return obj.get_data().get(name)
|
|
|
-
|
|
|
- data_bridge.short_description = label
|
|
|
- setattr(self, name, data_bridge)
|
|
|
-
|
|
|
- def get_list_display(self, request):
|
|
|
- form_page = self.get_form_page(request)
|
|
|
- if form_page is None:
|
|
|
- return self.list_display
|
|
|
- fields = []
|
|
|
- for name, label in form_page.get_data_fields():
|
|
|
- fields.append(name)
|
|
|
- self.add_data_bridge(name, label)
|
|
|
- return fields
|
|
|
-
|
|
|
- def set_status_view(self, request, instance_pk):
|
|
|
- kwargs = {"model_admin": self, "instance_pk": instance_pk}
|
|
|
- view_class = self.set_status_view_class
|
|
|
- return view_class.as_view(**kwargs)(request)
|
|
|
-
|
|
|
- def get_admin_urls_for_registration(self):
|
|
|
- urls = super().get_admin_urls_for_registration()
|
|
|
- urls += (
|
|
|
- path(
|
|
|
- self.url_helper.get_action_url_pattern("set_status"),
|
|
|
- self.set_status_view,
|
|
|
- name=self.url_helper.get_action_url_name("set_status"),
|
|
|
- ),
|
|
|
- )
|
|
|
- return urls
|
|
|
-
|
|
|
-
|
|
|
-# @hooks.register('construct_main_menu')
|
|
|
-# def hide_old_forms_module(request, menu_items):
|
|
|
-# from wagtail.contrib.forms.wagtail_hooks import FormsMenuItem
|
|
|
-# for menu_item in menu_items:
|
|
|
-# if isinstance(menu_item, FormsMenuItem):
|
|
|
-# menu_items.remove(menu_item)
|
|
|
-
|
|
|
-# modeladmin_register(FormAdmin)
|
|
|
-# modeladmin_register(SubmissionAdmin)
|