diff --git a/opentech/apply/funds/admin.py b/opentech/apply/funds/admin.py index ccecd965741aab3cdcf1d0d7b13e3ebcfd26a080..3eef4a8b77776dafdf902b697ddcdc718fb0dce8 100644 --- a/opentech/apply/funds/admin.py +++ b/opentech/apply/funds/admin.py @@ -1,3 +1,4 @@ +from django.conf.urls import url from django.urls import reverse from django.utils.safestring import mark_safe from wagtail.contrib.modeladmin.helpers import PermissionHelper @@ -6,13 +7,16 @@ from wagtail.contrib.modeladmin.options import ModelAdmin, ModelAdminGroup from opentech.apply.funds.models import ReviewerRole, ScreeningStatus from opentech.apply.review.admin import ReviewFormAdmin from opentech.apply.utils.admin import ListRelatedMixin +from opentech.apply.categories.admin import CategoryAdmin, MetaTermAdmin + from .admin_helpers import ( ButtonsWithPreview, FormsFundRoundListFilter, RoundFundChooserView, + ApplicationFormButtonHelper, ) +from .admin_views import CopyApplicationFormViewClass from .models import ApplicationForm, FundType, LabType, RequestForPartners, Round, SealedRound -from opentech.apply.categories.admin import CategoryAdmin, MetaTermAdmin class BaseRoundAdmin(ModelAdmin): @@ -126,6 +130,7 @@ class ApplicationFormAdmin(ListRelatedMixin, ModelAdmin): list_display = ('name', 'used_by') list_filter = (FormsFundRoundListFilter,) permission_helper_class = NoDeletePermission + button_helper_class = ApplicationFormButtonHelper related_models = [ ('applicationbaseform', 'application'), @@ -133,6 +138,21 @@ class ApplicationFormAdmin(ListRelatedMixin, ModelAdmin): ('labbaseform', 'lab'), ] + def copy_form_view(self, request, instance_pk): + kwargs = {'model_admin': self, 'form_pk': instance_pk} + view_class = CopyApplicationFormViewClass + return view_class.as_view(**kwargs)(request) + + def get_admin_urls_for_registration(self): + """Add the url for creating form copy.""" + urls = super().get_admin_urls_for_registration() + copy_form_url = url( + self.url_helper.get_action_url_pattern('copy_form'), + self.copy_form_view, + name=self.url_helper.get_action_url_name('copy_form') + ) + return urls + (copy_form_url, ) + class ApplyAdminGroup(ModelAdminGroup): menu_label = 'Apply' diff --git a/opentech/apply/funds/admin_helpers.py b/opentech/apply/funds/admin_helpers.py index 75ce474fbf28c8f37df7de768e2654e78619aee8..79d4b8f313a43f1cd6aec1fc3cd0043a5383fa64 100644 --- a/opentech/apply/funds/admin_helpers.py +++ b/opentech/apply/funds/admin_helpers.py @@ -4,7 +4,7 @@ from django.urls import reverse from django.utils.translation import ugettext as _ from wagtail.contrib.modeladmin.forms import ParentChooserForm -from wagtail.contrib.modeladmin.helpers import PageButtonHelper +from wagtail.contrib.modeladmin.helpers import PageButtonHelper, ButtonHelper from wagtail.contrib.modeladmin.views import ChooseParentView from wagtail.core.models import Page @@ -53,7 +53,7 @@ class ButtonsWithPreview(PageButtonHelper): class FormsFundRoundListFilter(admin.SimpleListFilter): - title = 'useage' + title = 'usage' parameter_name = 'form-usage' def lookups(self, request, model_admin): @@ -69,3 +69,37 @@ class FormsFundRoundListFilter(admin.SimpleListFilter): query = {f'{value}form__isnull': False} return queryset.filter(**query).distinct() return queryset + + +class ApplicationFormButtonHelper(ButtonHelper): + def prepare_classnames(self, start=None, add=None, exclude=None): + """Parse classname sets into final css classess list.""" + classnames = start or [] + classnames.extend(add or []) + return self.finalise_classname(classnames, exclude or []) + + def copy_form_button(self, pk, form_name, **kwargs): + classnames = self.prepare_classnames( + start=self.edit_button_classnames, + add=kwargs.get('classnames_add'), + exclude=kwargs.get('classnames_exclude') + ) + return { + 'classname': classnames, + 'label': f'Copy', + 'title': f'Copy {form_name}', + 'url': self.url_helper.get_action_url('copy_form', admin.utils.quote(pk)), + } + + def get_buttons_for_obj(self, obj, exclude=None, *args, **kwargs): + """Override the getting of buttons, appending copy form button.""" + buttons = super().get_buttons_for_obj(obj, *args, **kwargs) + + copy_form_button = self.copy_form_button( + pk=getattr(obj, self.opts.pk.attname), + form_name=getattr(obj, 'name'), + **kwargs + ) + buttons.append(copy_form_button) + + return buttons diff --git a/opentech/apply/funds/admin_views.py b/opentech/apply/funds/admin_views.py index 79071813169b4a71e7436240840a0c0a5bb45fc6..dcb6eb55ef18c086e5910c6e4386c7f46cbcd9f6 100644 --- a/opentech/apply/funds/admin_views.py +++ b/opentech/apply/funds/admin_views.py @@ -1,12 +1,14 @@ from django.core.exceptions import PermissionDenied -from django.shortcuts import redirect +from django.shortcuts import redirect, get_object_or_404 from django.utils.translation import ugettext as _ +from django.contrib.admin.utils import unquote from wagtail.admin import messages from wagtail.admin.forms.pages import CopyForm from wagtail.admin.views.pages import get_valid_next_url_from_request from wagtail.core import hooks from wagtail.core.models import Page +from wagtail.contrib.modeladmin.views import CreateView def custom_admin_round_copy_view(request, page): @@ -77,3 +79,20 @@ def custom_admin_round_copy_view(request, page): if next_url: return redirect(next_url) return redirect('wagtailadmin_explore', parent_page.id) + + +class CopyApplicationFormViewClass(CreateView): + """View class that can take an additional URL param for parent id.""" + + form_pk = None + form_instance = None + + def __init__(self, model_admin, form_pk): + self.form_pk = unquote(form_pk) + object_qs = model_admin.model._default_manager.get_queryset() + object_qs = object_qs.filter(pk=self.form_pk) + self.form_instance = get_object_or_404(object_qs) + super().__init__(model_admin) + + def get_initial(self): + return {'name': f'[CHANGE] Copy of {self.form_instance.name}', 'form_fields': self.form_instance.form_fields}