feat: add configurable people maps
Add independent map profiles, offline city lookup, bundled world artwork and collision-free portrait placement with optional person details. Deploy with updated requirements, migrations 0029-0031 and collectstatic.
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
from django.contrib import admin
|
||||
from django.http import FileResponse, Http404, HttpResponseRedirect
|
||||
from django.urls import path, reverse
|
||||
from django.templatetags.static import static
|
||||
from django.utils.html import format_html_join
|
||||
from django.utils.html import format_html
|
||||
|
||||
from apps.core.admin_video import video_admin_preview
|
||||
from apps.core.video import VIDEO_ADMIN_FIELDSET
|
||||
|
||||
from .forms import MapMembershipAdminForm
|
||||
from .models import (
|
||||
AboutSection,
|
||||
AboutSectionItem,
|
||||
@@ -20,6 +23,10 @@ from .models import (
|
||||
HomepageSection,
|
||||
HomepageSectionItem,
|
||||
PageVideo,
|
||||
PeopleMap,
|
||||
MapPerson,
|
||||
MapMembership,
|
||||
MapPlacement,
|
||||
)
|
||||
|
||||
|
||||
@@ -319,3 +326,49 @@ class PageVideoAdmin(admin.ModelAdmin):
|
||||
@admin.display(description="Preview")
|
||||
def video_preview(self, obj):
|
||||
return video_admin_preview(obj)
|
||||
|
||||
|
||||
class MapMembershipInline(admin.StackedInline):
|
||||
model = MapMembership
|
||||
form = MapMembershipAdminForm
|
||||
extra = 0
|
||||
autocomplete_fields = ['person']
|
||||
|
||||
|
||||
class MapPlacementInline(admin.TabularInline):
|
||||
model = MapPlacement
|
||||
extra = 0
|
||||
|
||||
|
||||
@admin.register(PeopleMap)
|
||||
class PeopleMapAdmin(admin.ModelAdmin):
|
||||
list_display = ['title', 'style', 'background_style', 'is_active']
|
||||
list_filter = ['style', 'background_style', 'is_active']
|
||||
search_fields = ['title']
|
||||
inlines = [MapMembershipInline, MapPlacementInline]
|
||||
readonly_fields = ['background_gallery']
|
||||
fields = ['title', 'description', 'style', 'background_style', 'background_gallery', 'background_image', 'show_people_details', 'is_active']
|
||||
|
||||
@admin.display(description="Included world maps")
|
||||
def background_gallery(self, obj):
|
||||
return format_html_join('',
|
||||
'<figure style="display:inline-block;width:240px;margin:8px;vertical-align:top">'
|
||||
'<img src="{}" alt="{}" style="width:240px;height:120px;object-fit:contain;background:#0c182a;border-radius:8px" />'
|
||||
'<figcaption style="margin-top:8px">{}</figcaption></figure>',
|
||||
((static(PeopleMap(background_style=key).background_static_path), label, label)
|
||||
for key, label in PeopleMap.BACKGROUND_CHOICES))
|
||||
|
||||
|
||||
|
||||
@admin.register(MapPerson)
|
||||
class MapPersonAdmin(admin.ModelAdmin):
|
||||
list_display = ['name', 'role', 'institution']
|
||||
search_fields = ['name', 'institution', 'role']
|
||||
|
||||
|
||||
@admin.register(MapPlacement)
|
||||
class MapPlacementAdmin(admin.ModelAdmin):
|
||||
list_display = ['people_map', 'page_path', 'position', 'order', 'is_active']
|
||||
search_fields = ['page_path', 'people_map__title']
|
||||
autocomplete_fields = ['people_map']
|
||||
list_filter = ['position', 'is_active']
|
||||
|
||||
Reference in New Issue
Block a user