You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
5.3 KiB
141 lines
5.3 KiB
from django.contrib import admin
|
|
from django.utils.translation import gettext_lazy as _
|
|
from unfold.admin import ModelAdmin, TabularInline, StackedInline
|
|
from unfold.decorators import display, action
|
|
|
|
from apps.profiles.models.institution import (
|
|
Institution,
|
|
InstitutionMember,
|
|
InstitutionTimeline,
|
|
InstitutionMedia,
|
|
InstitutionFollower,
|
|
)
|
|
from utils.admin import project_admin_site
|
|
|
|
|
|
class InstitutionMemberInline(TabularInline):
|
|
model = InstitutionMember
|
|
extra = 0
|
|
fields = ('user', 'role', 'title', 'joined_at')
|
|
readonly_fields = ('joined_at',)
|
|
|
|
|
|
class InstitutionTimelineInline(StackedInline):
|
|
model = InstitutionTimeline
|
|
extra = 0
|
|
fields = ('year', 'title', 'description', 'order')
|
|
|
|
|
|
class InstitutionMediaInline(TabularInline):
|
|
model = InstitutionMedia
|
|
extra = 0
|
|
fields = ('file', 'media_type', 'title', 'uploaded_at')
|
|
readonly_fields = ('uploaded_at',)
|
|
|
|
|
|
@admin.register(Institution, site=project_admin_site)
|
|
class InstitutionAdmin(ModelAdmin):
|
|
list_display = (
|
|
'name',
|
|
'type_badge',
|
|
'city',
|
|
'country',
|
|
'verification_badge',
|
|
'follower_count',
|
|
'is_featured',
|
|
'is_active',
|
|
'created_at',
|
|
)
|
|
list_filter = ('type', 'verification_status', 'is_featured', 'is_active', 'country')
|
|
search_fields = ('name', 'city', 'country', 'description', 'email', 'phone')
|
|
prepopulated_fields = {'slug': ('name',)}
|
|
readonly_fields = ('follower_count', 'created_at', 'updated_at')
|
|
inlines = [InstitutionMemberInline, InstitutionTimelineInline, InstitutionMediaInline]
|
|
actions = ['approve_institutions', 'reject_institutions', 'toggle_featured']
|
|
|
|
fieldsets = (
|
|
(_('Identity & Classification'), {
|
|
'fields': ('name', 'slug', 'type', 'is_featured', 'is_active', 'created_by')
|
|
}),
|
|
(_('Location & Geo-Coordinates'), {
|
|
'fields': ('country', 'city', 'address', 'latitude', 'longitude')
|
|
}),
|
|
(_('Contact & Official Channels'), {
|
|
'fields': ('email', 'phone', 'website', 'established_year')
|
|
}),
|
|
(_('Media & Branding'), {
|
|
'fields': ('avatar', 'cover_image')
|
|
}),
|
|
(_('Structured JSON Metadata'), {
|
|
'fields': ('description', 'social_media', 'working_hours', 'tags')
|
|
}),
|
|
(_('Verification & Statistics'), {
|
|
'fields': ('verification_status', 'follower_count', 'created_at', 'updated_at')
|
|
}),
|
|
)
|
|
|
|
@display(description=_('Type'))
|
|
def type_badge(self, obj):
|
|
return obj.get_type_display()
|
|
|
|
@display(description=_('Verification'), label={
|
|
Institution.VerificationStatus.APPROVED: "success",
|
|
Institution.VerificationStatus.PENDING: "warning",
|
|
Institution.VerificationStatus.REJECTED: "danger",
|
|
})
|
|
def verification_badge(self, obj):
|
|
return obj.get_verification_status_display()
|
|
|
|
@action(description=_('Approve and verify selected institutions'))
|
|
def approve_institutions(self, request, queryset):
|
|
count = queryset.update(verification_status=Institution.VerificationStatus.APPROVED)
|
|
self.message_user(request, _(f"{count} institution(s) approved and verified."))
|
|
|
|
@action(description=_('Reject selected institutions'))
|
|
def reject_institutions(self, request, queryset):
|
|
count = queryset.update(verification_status=Institution.VerificationStatus.REJECTED)
|
|
self.message_user(request, _(f"{count} institution(s) marked as rejected."))
|
|
|
|
@action(description=_('Toggle featured status for selected institutions'))
|
|
def toggle_featured(self, request, queryset):
|
|
for item in queryset:
|
|
item.is_featured = not item.is_featured
|
|
item.save(update_fields=['is_featured'])
|
|
self.message_user(request, _("Featured status updated for selected institutions."))
|
|
|
|
|
|
@admin.register(InstitutionMember, site=project_admin_site)
|
|
class InstitutionMemberAdmin(ModelAdmin):
|
|
list_display = ('user', 'institution', 'role_badge', 'title', 'joined_at')
|
|
list_filter = ('role', 'joined_at')
|
|
search_fields = ('user__email', 'user__fullname', 'institution__name', 'title')
|
|
readonly_fields = ('joined_at',)
|
|
|
|
@display(description=_('Role'), label={
|
|
InstitutionMember.MemberRole.ADMIN: "danger",
|
|
InstitutionMember.MemberRole.EDITOR: "warning",
|
|
InstitutionMember.MemberRole.VIEWER: "info",
|
|
})
|
|
def role_badge(self, obj):
|
|
return obj.get_role_display()
|
|
|
|
|
|
@admin.register(InstitutionTimeline, site=project_admin_site)
|
|
class InstitutionTimelineAdmin(ModelAdmin):
|
|
list_display = ('institution', 'year', 'title', 'order', 'created_at')
|
|
search_fields = ('institution__name', 'title', 'description', 'year')
|
|
list_filter = ('created_at',)
|
|
|
|
|
|
@admin.register(InstitutionMedia, site=project_admin_site)
|
|
class InstitutionMediaAdmin(ModelAdmin):
|
|
list_display = ('institution', 'title', 'media_type', 'uploaded_at')
|
|
list_filter = ('media_type', 'uploaded_at')
|
|
search_fields = ('institution__name', 'title', 'caption')
|
|
|
|
|
|
@admin.register(InstitutionFollower, site=project_admin_site)
|
|
class InstitutionFollowerAdmin(ModelAdmin):
|
|
list_display = ('user', 'institution', 'created_at')
|
|
search_fields = ('user__email', 'user__fullname', 'institution__name')
|
|
readonly_fields = ('created_at',)
|