256 lines
9.9 KiB
Python
256 lines
9.9 KiB
Python
from django.contrib import admin
|
|
from django.utils import timezone
|
|
from unfold.admin import ModelAdmin, TabularInline
|
|
|
|
from apps.events.models import Event
|
|
|
|
from .current import (
|
|
AboutAudience,
|
|
AboutContent,
|
|
AboutGalleryImage,
|
|
AboutItem,
|
|
AboutMember,
|
|
AboutMilestone,
|
|
AboutYear,
|
|
HomeContent,
|
|
ListingContent,
|
|
SiteContent,
|
|
)
|
|
|
|
|
|
class FixedContentAdmin(ModelAdmin):
|
|
"""The page records are installed by migration; editors only change them."""
|
|
|
|
list_per_page = 20
|
|
|
|
def has_add_permission(self, request):
|
|
return False
|
|
|
|
def has_delete_permission(self, request, obj=None):
|
|
return False
|
|
|
|
|
|
@admin.register(SiteContent)
|
|
class SiteContentAdmin(FixedContentAdmin):
|
|
fieldsets = (
|
|
("Association", {"fields": ("official_name", "short_name", "faculty_subline", "description", "logo", "logo_alt")}),
|
|
("Navigation labels", {"fields": ("nav_home", "nav_about", "nav_events", "nav_blog")}),
|
|
("Contact and footer", {"fields": ("email", "phone", "telegram_url", "instagram_url", "website_url", "address", "footer_copy")}),
|
|
("eNAMAD certificate", {"fields": ("enamad_image", "enamad_image_alt", "enamad_url"), "description": "The badge stays unlinked until you add its verification URL."}),
|
|
("SEO defaults", {"fields": ("seo_title", "seo_description", "seo_image", "seo_image_alt")}),
|
|
)
|
|
|
|
|
|
@admin.register(HomeContent)
|
|
class HomeContentAdmin(FixedContentAdmin):
|
|
fieldsets = (
|
|
("Page introduction", {"fields": ("title", "intro")}),
|
|
("Hero", {"fields": (
|
|
"hero_heading", "hero_body", "hero_image", "hero_image_alt",
|
|
"hero_action_label", "hero_action_url", "hero_secondary_action_label", "hero_secondary_action_url",
|
|
), "description": "Destinations accept an internal path such as /events or a secure https URL."}),
|
|
("Featured events", {"fields": (
|
|
"featured_events_heading", "featured_events_intro", "featured_events_link_label", "featured_events_url", "featured_event_action_label",
|
|
), "description": "Destinations accept an internal path such as /events or a secure https URL."}),
|
|
("Featured blog posts", {"fields": (
|
|
"featured_posts_heading", "featured_posts_intro", "featured_posts_link_label", "featured_posts_url", "featured_post_action_label",
|
|
), "description": "Destinations accept an internal path such as /blog or a secure https URL."}),
|
|
("Participation", {"fields": (
|
|
"participation_heading", "participation_body", "participation_image", "participation_image_alt",
|
|
"participation_action_label", "participation_action_url",
|
|
"participation_secondary_action_label", "participation_secondary_action_url",
|
|
), "description": "Destinations accept an internal path such as /auth or a secure https URL."}),
|
|
("SEO", {"fields": ("seo_title", "seo_description", "seo_image", "seo_image_alt")}),
|
|
)
|
|
|
|
|
|
class AboutItemInline(TabularInline):
|
|
model = AboutItem
|
|
extra = 0
|
|
fields = ("kind", "title", "text", "position")
|
|
|
|
def get_queryset(self, request):
|
|
return super().get_queryset(request).filter(kind="faq")
|
|
|
|
def formfield_for_choice_field(self, db_field, request, **kwargs):
|
|
field = super().formfield_for_choice_field(db_field, request, **kwargs)
|
|
if db_field.name == "kind":
|
|
field.choices = tuple(choice for choice in field.choices if choice[0] == "faq")
|
|
return field
|
|
|
|
def has_add_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
def has_delete_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
|
|
class AboutAudienceInline(TabularInline):
|
|
model = AboutAudience
|
|
extra = 0
|
|
fields = ("title", "text", "icon", "position")
|
|
ordering = ("position",)
|
|
|
|
def has_add_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
def has_delete_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
|
|
class AboutMilestoneInline(TabularInline):
|
|
model = AboutMilestone
|
|
extra = 0
|
|
fields = ("year_label", "title", "description", "position")
|
|
ordering = ("position",)
|
|
|
|
def has_add_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
def has_delete_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
|
|
class AboutMemberInline(TabularInline):
|
|
model = AboutMember
|
|
fk_name = "year_group"
|
|
extra = 0
|
|
fields = ("name", "role", "bio", "photo", "photo_alt", "position")
|
|
ordering = ("position",)
|
|
|
|
def has_add_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
def has_delete_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
|
|
class LegacyAboutMemberInline(TabularInline):
|
|
model = AboutMember
|
|
fk_name = "about"
|
|
extra = 0
|
|
fields = ("name", "role", "entry_year", "bio", "photo", "photo_alt", "position")
|
|
ordering = ("entry_year", "position")
|
|
|
|
def get_queryset(self, request):
|
|
return super().get_queryset(request).filter(year_group__isnull=True)
|
|
|
|
def has_add_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
def has_delete_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
|
|
class AboutGalleryInline(TabularInline):
|
|
model = AboutGalleryImage
|
|
extra = 0
|
|
fields = ("image", "image_alt", "caption", "position")
|
|
ordering = ("position",)
|
|
|
|
def has_add_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
def has_delete_permission(self, request, obj=None):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
|
|
@admin.register(AboutContent)
|
|
class AboutContentAdmin(FixedContentAdmin):
|
|
inlines = (
|
|
AboutItemInline,
|
|
AboutAudienceInline,
|
|
AboutMilestoneInline,
|
|
LegacyAboutMemberInline,
|
|
AboutGalleryInline,
|
|
)
|
|
fieldsets = (
|
|
("Page introduction", {"fields": ("title", "intro", "identity_heading", "identity_body")}),
|
|
("Mission, vision, and values", {"fields": (
|
|
"mission_heading", "mission_body", "vision_heading", "vision_body", "values_heading", "values_body",
|
|
)}),
|
|
("Activities", {"fields": ("activities_heading", "activities_body")}),
|
|
("Association history", {"fields": ("history_heading",)}),
|
|
("Who the association serves", {"fields": ("audience_heading",)}),
|
|
("Annual archive", {"fields": ("members_heading", "members_intro", "year_events_heading")}),
|
|
("Memories gallery", {"fields": ("gallery_heading", "gallery_intro")}),
|
|
("FAQ and call to action", {"fields": (
|
|
"faq_heading", "cta_heading", "cta_body", "cta_action_label", "cta_action_url",
|
|
), "description": "The CTA destination stays empty until you set an internal path or secure https URL."}),
|
|
("SEO", {"fields": ("seo_title", "seo_description", "seo_image", "seo_image_alt")}),
|
|
)
|
|
|
|
|
|
@admin.register(AboutYear)
|
|
class AboutYearAdmin(ModelAdmin):
|
|
list_display = ("year_label", "position")
|
|
list_editable = ("position",)
|
|
ordering = ("position", "pk")
|
|
search_fields = ("year_label",)
|
|
fieldsets = (
|
|
("Academic year", {"fields": ("year_label", "position", "events")}),
|
|
)
|
|
filter_horizontal = ("events",)
|
|
inlines = (AboutMemberInline,)
|
|
|
|
def has_module_permission(self, request):
|
|
return request.user.has_perm("content.change_aboutcontent")
|
|
|
|
def has_view_permission(self, request, obj=None):
|
|
return self.has_module_permission(request)
|
|
|
|
def has_add_permission(self, request):
|
|
return self.has_module_permission(request)
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
return self.has_module_permission(request)
|
|
|
|
def has_delete_permission(self, request, obj=None):
|
|
return self.has_module_permission(request)
|
|
|
|
def get_queryset(self, request):
|
|
return super().get_queryset(request).filter(about_id=1)
|
|
|
|
def save_model(self, request, obj, form, change):
|
|
if not obj.about_id:
|
|
obj.about = AboutContent.objects.get(pk=1)
|
|
super().save_model(request, obj, form, change)
|
|
|
|
def formfield_for_manytomany(self, db_field, request, **kwargs):
|
|
field = super().formfield_for_manytomany(db_field, request, **kwargs)
|
|
if db_field.name == "events":
|
|
field.queryset = Event.objects.filter(
|
|
is_deleted=False,
|
|
status__in=(Event.StatusChoices.PUBLISHED, Event.StatusChoices.COMPLETED),
|
|
start_time__lte=timezone.now(),
|
|
).order_by("-start_time", "title")
|
|
return field
|
|
|
|
|
|
@admin.register(ListingContent)
|
|
class ListingContentAdmin(FixedContentAdmin):
|
|
list_display = ("slug", "title")
|
|
readonly_fields = ("slug",)
|
|
fieldsets = (
|
|
("Content", {"fields": ("slug", "title", "intro")}),
|
|
("SEO", {"fields": ("seo_title", "seo_description", "seo_image", "seo_image_alt")}),
|
|
)
|