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, is_published=True, 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")}), )