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.
168 lines
5.8 KiB
168 lines
5.8 KiB
from django.contrib import admin
|
|
from django import forms
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from unfold.admin import ModelAdmin, StackedInline
|
|
from unfold.contrib.filters.admin import (
|
|
ChoicesDropdownFilter,
|
|
MultipleRelatedDropdownFilter,
|
|
RangeDateFilter,
|
|
)
|
|
|
|
from utils.admin import project_admin_site
|
|
from apps.course.models import (
|
|
CourseLiveSession,
|
|
LiveSessionRecording,
|
|
LiveSessionUser,
|
|
USER_ROLE_CHOICES,
|
|
RECORDING_TYPE_CHOICES,
|
|
)
|
|
from django.contrib.auth import get_user_model
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
# --- WIDTH ENFORCEMENT & PLACEHOLDER TEXT FOR DROPDOWNS ---
|
|
class MinWidthInlineForm(forms.ModelForm):
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
# Target the dropdown fields to ensure they don't collapse
|
|
target_dropdown_fields = ['user', 'role', 'recording_type']
|
|
|
|
for field_name, field in self.fields.items():
|
|
if field_name in target_dropdown_fields:
|
|
if hasattr(field.widget, 'attrs'):
|
|
existing_class = field.widget.attrs.get('class', '')
|
|
field.widget.attrs['class'] = f"{existing_class} min-w-[250px] w-full"
|
|
|
|
existing_style = field.widget.attrs.get('style', '')
|
|
field.widget.attrs['style'] = f"{existing_style} min-width: 250px; width: 250px;"
|
|
|
|
# 🔔 Add the custom placeholder text
|
|
if hasattr(field, 'empty_label'):
|
|
field.empty_label = _("Select a value")
|
|
|
|
|
|
class LiveSessionUserInline(StackedInline):
|
|
model = LiveSessionUser
|
|
form = MinWidthInlineForm
|
|
extra = 1
|
|
tab = True
|
|
|
|
fieldsets = (
|
|
(None, {
|
|
'fields': (('user', 'role', 'is_online'),) # Grouped horizontally
|
|
}),
|
|
(_("Timing"), {
|
|
'fields': (('entered_at', 'exited_at'),) # Grouped horizontally
|
|
}),
|
|
)
|
|
|
|
show_change_link = True
|
|
verbose_name = _("Session User")
|
|
verbose_name_plural = _("Session Users")
|
|
|
|
# 🔔 FILTER THE USER DROPDOWN TO ONLY SHOW ACTIVE & NON-GUEST USERS
|
|
def formfield_for_foreignkey(self, db_field, request, **kwargs):
|
|
if db_field.name == "user":
|
|
kwargs["queryset"] = User.objects.filter(is_active=True, email__isnull=False)
|
|
return super().formfield_for_foreignkey(db_field, request, **kwargs)
|
|
|
|
|
|
class LiveSessionRecordingInline(StackedInline):
|
|
model = LiveSessionRecording
|
|
form = MinWidthInlineForm
|
|
extra = 1
|
|
tab = True
|
|
|
|
fieldsets = (
|
|
(None, {
|
|
'fields': (('title', 'recording_type', 'is_active'),) # Grouped horizontally
|
|
}),
|
|
(_("Media"), {
|
|
'fields': ('file',)
|
|
}),
|
|
)
|
|
|
|
show_change_link = True
|
|
verbose_name = _("Session Recording")
|
|
verbose_name_plural = _("Session Recordings")
|
|
|
|
|
|
class CourseLiveSessionAdmin(ModelAdmin):
|
|
list_display = ("subject", "course", "started_at", "ended_at", "created_at")
|
|
list_filter = (
|
|
("course", MultipleRelatedDropdownFilter),
|
|
("started_at", RangeDateFilter),
|
|
)
|
|
search_fields = ("subject", "course__title")
|
|
ordering = ("-started_at",)
|
|
autocomplete_fields = ("course",)
|
|
readonly_fields = ("created_at", "updated_at")
|
|
|
|
# Add the custom tabs here
|
|
inlines = [LiveSessionUserInline, LiveSessionRecordingInline]
|
|
|
|
fieldsets = (
|
|
(None, {"fields": ("course", "subject", "started_at", "ended_at")}),
|
|
(_("Timestamps"), {"fields": ("created_at", "updated_at")}),
|
|
)
|
|
|
|
|
|
class LiveSessionUserAdmin(ModelAdmin):
|
|
list_display = ("user", "session", "role", "is_online", "entered_at", "exited_at")
|
|
list_filter = (
|
|
("session", MultipleRelatedDropdownFilter),
|
|
("user", MultipleRelatedDropdownFilter),
|
|
("role", ChoicesDropdownFilter),
|
|
("entered_at", RangeDateFilter),
|
|
("is_online", admin.BooleanFieldListFilter),
|
|
)
|
|
search_fields = (
|
|
"user__email",
|
|
"user__fullname",
|
|
"session__subject",
|
|
)
|
|
autocomplete_fields = ("user", "session")
|
|
readonly_fields = ("created_at", "updated_at")
|
|
fieldsets = (
|
|
(None, {"fields": ("session", "user", "role")}),
|
|
(_("Session Timing"), {"fields": ("entered_at", "exited_at", "is_online")}),
|
|
(_("Timestamps"), {"fields": ("created_at", "updated_at")}),
|
|
)
|
|
|
|
def get_role_choices(self, request):
|
|
return USER_ROLE_CHOICES
|
|
|
|
# 🔔 FILTER THE STANDALONE ADMIN FORM AS WELL JUST IN CASE
|
|
def formfield_for_foreignkey(self, db_field, request, **kwargs):
|
|
if db_field.name == "user":
|
|
kwargs["queryset"] = User.objects.filter(is_active=True, email__isnull=False)
|
|
return super().formfield_for_foreignkey(db_field, request, **kwargs)
|
|
|
|
|
|
class LiveSessionRecordingAdmin(ModelAdmin):
|
|
list_display = ("title", "session", "recording_type", "is_active", "created_at")
|
|
list_filter = (
|
|
("session", MultipleRelatedDropdownFilter),
|
|
("recording_type", ChoicesDropdownFilter),
|
|
("created_at", RangeDateFilter),
|
|
("is_active", admin.BooleanFieldListFilter),
|
|
)
|
|
search_fields = ("title", "session__subject", "session__course__title")
|
|
autocomplete_fields = ("session",)
|
|
readonly_fields = ("created_at", "updated_at")
|
|
fieldsets = (
|
|
(None, {"fields": ("session", "title", "recording_type")}),
|
|
(_("Files"), {"fields": ("file", "file_time", "thumbnail")}),
|
|
(_("Status"), {"fields": ("is_active",)}),
|
|
(_("Timestamps"), {"fields": ("created_at", "updated_at")}),
|
|
)
|
|
|
|
def get_recording_type_choices(self, request):
|
|
return RECORDING_TYPE_CHOICES
|
|
|
|
|
|
project_admin_site.register(CourseLiveSession, CourseLiveSessionAdmin)
|
|
project_admin_site.register(LiveSessionUser, LiveSessionUserAdmin)
|
|
project_admin_site.register(LiveSessionRecording, LiveSessionRecordingAdmin)
|