diff --git a/hypha/apply/funds/admin.py b/hypha/apply/funds/admin.py
index 30bdfa3706..c5c50da6e0 100644
--- a/hypha/apply/funds/admin.py
+++ b/hypha/apply/funds/admin.py
@@ -1,7 +1,13 @@
-from django.urls import re_path
+from django.urls import reverse
from django.utils.safestring import mark_safe
-from wagtail.contrib.modeladmin.helpers import PermissionHelper
-from wagtail.contrib.modeladmin.options import ModelAdmin, ModelAdminGroup
+from wagtail.admin.menu import MenuItem
+from wagtail.contrib.modeladmin.options import (
+ ModelAdmin,
+ ModelAdminGroup,
+ modeladmin_register,
+)
+from wagtail.snippets.models import register_snippet
+from wagtail.snippets.views.snippets import SnippetViewSet
from hypha.apply.categories.admin import CategoryAdmin, MetaTermAdmin
from hypha.apply.determinations.admin import (
@@ -11,33 +17,57 @@
)
from hypha.apply.funds.models import ReviewerRole, ReviewerSettings, ScreeningStatus
from hypha.apply.review.admin import ReviewFormAdmin
-from hypha.apply.utils.admin import AdminIcon, ListRelatedMixin, RelatedFormsMixin
+from hypha.apply.utils.admin import AdminIcon, RelatedFormsMixin
from hypha.core.wagtail.admin.options import SettingModelAdmin
from .admin_helpers import (
- ApplicationFormButtonHelper,
ButtonsWithPreview,
- FormsFundRoundListFilter,
RoundAdminURLHelper,
RoundFundChooserView,
RoundStateListFilter,
)
-from .admin_views import (
- CopyApplicationFormViewClass,
- CreateApplicationFormView,
- EditApplicationFormView,
-)
from .models import (
ApplicationForm,
ApplicationSettings,
- FundType,
- LabType,
RequestForPartners,
Round,
SealedRound,
)
+class ScreeningStatusAdmin(SnippetViewSet):
+ model = ScreeningStatus
+ icon = str(AdminIcon.SCREENING_STATUS)
+ list_display = ("title", "yes", "default")
+
+ def user_can_edit(self, user):
+ return user.is_superuser
+
+ def user_can_delete(self, user):
+ return user.is_superuser
+
+
+class ReviewerRoleAdmin(SnippetViewSet):
+ model = ReviewerRole
+ icon = str(AdminIcon.REVIEWER_ROLE)
+ menu_label = "Reviewer Roles"
+
+
+# having issues with Locale during save
+# class FundAdmin(SnippetViewSet, RelatedFormsMixin):
+# model = FundType
+# icon = str(AdminIcon.FUND)
+# menu_label = "Funds"
+# list_display = ("title", "application_forms", "get_review_forms", "get_determination_forms")
+#
+#
+# class LabAdmin(SnippetViewSet, RelatedFormsMixin):
+# model = LabType
+# icon = str(AdminIcon.LAB)
+# menu_label = "Labs"
+# list_display = ("title", "application_forms", "get_review_forms", "get_determination_forms")
+
+
class BaseRoundAdmin(ModelAdmin):
choose_parent_view_class = RoundFundChooserView
choose_parent_template_name = "funds/admin/parent_chooser.html"
@@ -67,30 +97,6 @@ def fund(self, obj):
return mark_safe(url_tag)
-class ScreeningStatusPermissionHelper(PermissionHelper):
- def user_can_edit_obj(self, user, obj):
- """
- Return a boolean to indicate whether `user` is permitted to 'change'
- a specific `self.model` instance.
- """
- return user.is_superuser
-
- def user_can_delete_obj(self, user, obj):
- """
- Return a boolean to indicate whether `user` is permitted to 'delete'
- a specific `self.model` instance.
- """
- return user.is_superuser
-
-
-class ScreeningStatusAdmin(ModelAdmin):
- model = ScreeningStatus
- menu_icon = str(AdminIcon.SCREENING_STATUS)
- list_display = ("title", "yes", "default")
- permission_helper_class = ScreeningStatusPermissionHelper
- list_display = ("title", "yes", "default")
-
-
class SealedRoundAdmin(BaseRoundAdmin):
model = SealedRound
menu_icon = str(AdminIcon.SEALED_ROUND)
@@ -98,75 +104,51 @@ class SealedRoundAdmin(BaseRoundAdmin):
list_display = ("title", "fund", "start_date", "end_date")
-class FundAdmin(ModelAdmin, RelatedFormsMixin):
- model = FundType
- menu_icon = str(AdminIcon.FUND)
- menu_label = "Funds"
- list_display = ("title", "application_forms", "review_forms", "determination_forms")
-
-
+# class FundAdmin(ModelAdmin, RelatedFormsMixin):
+# model = FundType
+# menu_icon = str(AdminIcon.FUND)
+# menu_label = "Funds"
+# list_display = ("title", "application_forms", "review_forms", "determination_forms")
+#
+#
class RFPAdmin(ModelAdmin):
model = RequestForPartners
menu_icon = str(AdminIcon.REQUEST_FOR_PARTNERS)
menu_label = "Request For Partners"
-class LabAdmin(ModelAdmin, RelatedFormsMixin):
- model = LabType
- menu_icon = str(AdminIcon.LAB)
- menu_label = "Labs"
- list_display = ("title", "application_forms", "review_forms", "determination_forms")
+#
+# class LabAdmin(ModelAdmin, RelatedFormsMixin):
+# model = LabType
+# menu_icon = str(AdminIcon.LAB)
+# menu_label = "Labs"
+# list_display = ("title", "application_forms", "review_forms", "determination_forms")
+#
-class ReviewerRoleAdmin(ModelAdmin):
- model = ReviewerRole
- menu_icon = str(AdminIcon.REVIEWER_ROLE)
- menu_label = "Reviewer Roles"
+class ApplicationFormAdmin(SnippetViewSet):
+ model = ApplicationForm
+ menu_icon = str(AdminIcon.APPLICATION_FORM)
+ list_display = ("name", "used_by")
+ def get_queryset(self, request):
+ # Explicitly define the queryset for this snippet
+ qs = self.model.objects.all()
-class DeletePermission(PermissionHelper, ListRelatedMixin):
- related_models = [
- ("applicationbaseform", "application"),
- ("roundbaseform", "round"),
- ("labbaseform", "lab"),
- ]
+ # Prefetch related fields for the 'used_by' logic
+ related = [
+ "applicationbaseform_set__application",
+ "roundbaseform_set__round",
+ "labbaseform_set__lab",
+ ]
+ return qs.prefetch_related(*related)
- def user_can_delete_obj(self, user, obj):
- if str(self.used_by(obj)):
- return False
- return True
-
-class ApplicationFormAdmin(ListRelatedMixin, ModelAdmin):
- model = ApplicationForm
- menu_icon = str(AdminIcon.APPLICATION_FORM)
- list_display = ("name", "used_by")
- list_filter = (FormsFundRoundListFilter,)
- permission_helper_class = DeletePermission
- button_helper_class = ApplicationFormButtonHelper
- create_view_class = CreateApplicationFormView
- edit_view_class = EditApplicationFormView
-
- related_models = [
- ("applicationbaseform", "application"),
- ("roundbaseform", "round"),
- ("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 = re_path(
- 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,)
+register_snippet(ApplicationFormAdmin)
+register_snippet(ScreeningStatusAdmin)
+register_snippet(ReviewerRoleAdmin)
+# register_snippet(FundAdmin)
+# register_snippet(LabAdmin)
class ApplicationSettingAdmin(SettingModelAdmin):
@@ -183,10 +165,7 @@ class ApplyAdminGroup(ModelAdminGroup):
items = (
RoundAdmin,
SealedRoundAdmin,
- FundAdmin,
- LabAdmin,
RFPAdmin,
- ApplicationFormAdmin,
ApplicationSettingAdmin,
ReviewFormAdmin,
ReviewerSettingAdmin,
@@ -194,7 +173,47 @@ class ApplyAdminGroup(ModelAdminGroup):
DeterminationMessageSettingsAdmin,
DeterminationFormSettingsAdmin,
CategoryAdmin,
- ScreeningStatusAdmin,
- ReviewerRoleAdmin,
MetaTermAdmin,
)
+
+ def get_submenu_items(self):
+ # Get existing items
+ submenu_items = super().get_submenu_items()
+
+ snippets = [
+ {
+ "model": ReviewerRole,
+ "menu_label": "Reviewer Roles",
+ "icon_name": str(AdminIcon.REVIEWER_ROLE),
+ },
+ # {"model": FundType, "menu_label": "Funds", "icon_name": str(AdminIcon.FUND)},
+ # {"model": LabType, "menu_label": "Labs", "icon_name": str(AdminIcon.LAB)},
+ # {"model": RequestForPartners, "menu_label": "Request For Partners", "icon_name": str(AdminIcon.REQUEST_FOR_PARTNERS)},
+ {
+ "model": ScreeningStatus,
+ "menu_label": "Screening Decisions",
+ "icon_name": str(AdminIcon.SCREENING_STATUS),
+ },
+ {
+ "model": ApplicationForm,
+ "menu_label": "Application Forms",
+ "icon_name": str(AdminIcon.APPLICATION_FORM),
+ },
+ ]
+
+ for snippet in snippets:
+ snippet_url = reverse(
+ f"wagtailsnippets_{snippet['model']._meta.app_label}_{snippet['model']._meta.model_name}:list",
+ )
+ submenu_items.append(
+ MenuItem(
+ snippet["menu_label"],
+ snippet_url,
+ icon_name=snippet["icon_name"],
+ )
+ )
+
+ return submenu_items
+
+
+modeladmin_register(ApplyAdminGroup)
diff --git a/hypha/apply/funds/edit_handlers.py b/hypha/apply/funds/edit_handlers.py
index 3b01944d8a..cb519aac4e 100644
--- a/hypha/apply/funds/edit_handlers.py
+++ b/hypha/apply/funds/edit_handlers.py
@@ -3,12 +3,20 @@
from django.urls import reverse
from wagtail.admin.panels import FieldPanel, Panel
from wagtail.models import Page
+from wagtail.snippets.models import get_snippet_models
def reverse_edit(obj):
if isinstance(obj, Page):
return reverse("wagtailadmin_pages:edit", args=(obj.id,))
+ snippet_models = get_snippet_models()
+ if obj.__class__ in snippet_models:
+ return reverse(
+ f"wagtailsnippets_{obj._meta.app_label}_{obj._meta.model_name}:edit",
+ args=(obj.id,),
+ )
+
url_name = f"{obj._meta.app_label}_{obj._meta.model_name}_modeladmin_edit"
return reverse(url_name, args=(obj.id,))
diff --git a/hypha/apply/funds/models/__init__.py b/hypha/apply/funds/models/__init__.py
index 09afb0d643..fdd128ef66 100644
--- a/hypha/apply/funds/models/__init__.py
+++ b/hypha/apply/funds/models/__init__.py
@@ -1,3 +1,4 @@
+from django.contrib.admin import display
from django.utils.translation import gettext_lazy as _
from .application_revisions import ApplicationRevision
@@ -35,6 +36,23 @@ class FundType(ApplicationBase):
class Meta:
verbose_name = _("Fund")
+ @property
+ def application_forms(self):
+ # Return related forms as a comma-separated list
+ return ", ".join(form.form.name for form in self.forms.all())
+
+ @property
+ @display(description=_("Review Forms"))
+ def get_review_forms(self):
+ # Return related forms as a comma-separated list
+ return ", ".join(form.form.name for form in self.review_forms.all())
+
+ @property
+ @display(description=_("Determination Forms"))
+ def get_determination_forms(self):
+ # Return related forms as a comma-separated list
+ return ", ".join(form.form.name for form in self.determination_forms.all())
+
class RequestForPartners(ApplicationBase):
subpage_types = ["funds.Round", "funds.SealedRound"]
@@ -58,3 +76,20 @@ def __init__(self, *args, **kwargs):
class LabType(LabBase):
class Meta:
verbose_name = _("Lab")
+
+ @property
+ def application_forms(self):
+ # Return related forms as a comma-separated list
+ return ", ".join(form.form.name for form in self.forms.all())
+
+ @property
+ @display(description=_("Review Forms"))
+ def get_review_forms(self):
+ # Return related forms as a comma-separated list
+ return ", ".join(form.form.name for form in self.review_forms.all())
+
+ @property
+ @display(description=_("Determination Forms"))
+ def get_determination_forms(self):
+ # Return related forms as a comma-separated list
+ return ", ".join(form.form.name for form in self.determination_forms.all())
diff --git a/hypha/apply/funds/models/forms.py b/hypha/apply/funds/models/forms.py
index a0d8c36b5b..0c77753ecb 100644
--- a/hypha/apply/funds/models/forms.py
+++ b/hypha/apply/funds/models/forms.py
@@ -1,4 +1,6 @@
from django.db import models
+from django.urls import reverse
+from django.utils.safestring import mark_safe
from modelcluster.fields import ParentalKey
from wagtail.admin.panels import FieldPanel
from wagtail.fields import StreamField
@@ -23,6 +25,33 @@ class ApplicationForm(models.Model):
def __str__(self):
return self.name
+ @property
+ def used_by(self):
+ rows = []
+ related_models = [
+ ("applicationbaseform", "application"),
+ ("roundbaseform", "round"),
+ ("labbaseform", "lab"),
+ ]
+
+ for form, field in related_models:
+ related_values = getattr(self, f"{form}_set").values(
+ f"{field}__title", f"{field}__id"
+ )
+ for value in related_values:
+ title = value.get(f"{field}__title")
+ obj_id = value.get(f"{field}__id")
+ if title and obj_id:
+ edit_url = reverse("wagtailadmin_pages:edit", args=(obj_id,))
+ rows.append(
+ f''
+ f' {title}'
+ )
+ elif title:
+ rows.append(f"{title}")
+ return mark_safe(", ".join(rows))
+
class AbstractRelatedForm(Orderable):
FIRST_STAGE = 1
diff --git a/hypha/apply/funds/wagtail_hooks.py b/hypha/apply/funds/wagtail_hooks.py
index 3dbbafdc6f..0516e22b06 100644
--- a/hypha/apply/funds/wagtail_hooks.py
+++ b/hypha/apply/funds/wagtail_hooks.py
@@ -1,13 +1,9 @@
from django.contrib.auth.models import Permission
from wagtail import hooks
-from wagtail.contrib.modeladmin.options import modeladmin_register
-from .admin import ApplyAdminGroup
from .admin_views import custom_admin_round_copy_view
from .models import RoundBase
-modeladmin_register(ApplyAdminGroup)
-
@hooks.register("before_create_page")
def before_create_page(request, parent_page, page_class):
diff --git a/hypha/apply/utils/admin.py b/hypha/apply/utils/admin.py
index 6f0d633f7b..ee034bdfff 100644
--- a/hypha/apply/utils/admin.py
+++ b/hypha/apply/utils/admin.py
@@ -118,7 +118,7 @@ def application_forms(self, obj):
def build_urls(application_forms):
for application_form in application_forms:
url = reverse(
- "funds_applicationform_modeladmin_edit",
+ "wagtailsnippets_funds_applicationform:edit",
args=[application_form.form.id],
)
yield f'{application_form}'