""" Административная панель для видеоконференций. """ from django.contrib import admin from django.utils.html import format_html from django.urls import reverse from .models import VideoRoom, VideoParticipant, VideoCallLog, ScreenRecording @admin.register(VideoRoom) class VideoRoomAdmin(admin.ModelAdmin): """Админ интерфейс для видеокомнат.""" list_display = [ 'room_id', 'lesson_title', 'mentor_link', 'client_link', 'status_badge', 'duration_display', 'is_recording', 'created_at' ] list_filter = [ 'status', 'is_recording', 'created_at', 'started_at' ] search_fields = [ 'room_id', 'lesson__title', 'mentor__email', 'mentor__first_name', 'mentor__last_name', 'client__email', 'client__first_name', 'client__last_name' ] readonly_fields = [ 'room_id', 'created_at', 'updated_at', 'started_at', 'ended_at', 'duration', 'mentor_joined_at', 'client_joined_at' ] fieldsets = ( ('Основная информация', { 'fields': ( 'room_id', 'lesson', 'mentor', 'client', 'status' ) }), ('Время', { 'fields': ( 'created_at', 'started_at', 'ended_at', 'duration', 'mentor_joined_at', 'client_joined_at' ) }), ('Запись', { 'fields': ( 'is_recording', 'recording_url' ) }), ('Техническая информация', { 'fields': ( 'router_id', 'max_participants' ) }), ('Качество', { 'fields': ( 'quality_rating', 'quality_issues' ) }) ) def lesson_title(self, obj): """Название занятия.""" return obj.lesson.title lesson_title.short_description = 'Занятие' def mentor_link(self, obj): """Ссылка на ментора.""" url = reverse('admin:users_user_change', args=[obj.mentor.id]) return format_html('{}', url, obj.mentor.get_full_name()) mentor_link.short_description = 'Ментор' def client_link(self, obj): """Ссылка на клиента.""" url = reverse('admin:users_user_change', args=[obj.client.id]) return format_html('{}', url, obj.client.get_full_name()) client_link.short_description = 'Клиент' def status_badge(self, obj): """Бейдж статуса.""" colors = { 'waiting': '#ffc107', 'active': '#28a745', 'ended': '#6c757d' } return format_html( '{}', colors.get(obj.status, '#000'), obj.get_status_display() ) status_badge.short_description = 'Статус' def duration_display(self, obj): """Отображение длительности.""" duration = obj.actual_duration if duration: hours = duration // 3600 minutes = (duration % 3600) // 60 seconds = duration % 60 return f"{hours:02d}:{minutes:02d}:{seconds:02d}" return '-' duration_display.short_description = 'Длительность' @admin.register(VideoParticipant) class VideoParticipantAdmin(admin.ModelAdmin): """Админ интерфейс для участников видео.""" list_display = [ 'user_name', 'room_id', 'is_connected', 'is_audio_enabled', 'is_video_enabled', 'is_screen_sharing', 'joined_at', 'left_at', 'duration_display' ] list_filter = [ 'is_connected', 'is_audio_enabled', 'is_video_enabled', 'is_screen_sharing', 'joined_at' ] search_fields = [ 'user__email', 'user__first_name', 'user__last_name', 'room__room_id' ] readonly_fields = [ 'joined_at', 'left_at', 'total_duration', 'reconnection_count' ] def user_name(self, obj): """Имя пользователя.""" return obj.user.get_full_name() user_name.short_description = 'Пользователь' def room_id(self, obj): """ID комнаты.""" return str(obj.room.room_id)[:8] room_id.short_description = 'Комната' def duration_display(self, obj): """Отображение длительности.""" if obj.total_duration: hours = obj.total_duration // 3600 minutes = (obj.total_duration % 3600) // 60 seconds = obj.total_duration % 60 return f"{hours:02d}:{minutes:02d}:{seconds:02d}" return '-' duration_display.short_description = 'Время в звонке' @admin.register(VideoCallLog) class VideoCallLogAdmin(admin.ModelAdmin): """Админ интерфейс для логов видеозвонков.""" list_display = [ 'room_id', 'total_participants', 'duration_display', 'average_bitrate', 'packet_loss_rate', 'connection_issues', 'created_at' ] list_filter = [ 'created_at', 'connection_issues', 'audio_issues', 'video_issues' ] search_fields = [ 'room__room_id', 'room__lesson__title' ] readonly_fields = [ 'room', 'total_participants', 'total_duration', 'average_bitrate', 'packet_loss_rate', 'average_jitter', 'connection_issues', 'audio_issues', 'video_issues', 'metadata', 'created_at' ] def room_id(self, obj): """ID комнаты.""" return str(obj.room.room_id)[:8] room_id.short_description = 'Комната' def duration_display(self, obj): """Отображение длительности.""" if obj.total_duration: hours = obj.total_duration // 3600 minutes = (obj.total_duration % 3600) // 60 seconds = obj.total_duration % 60 return f"{hours:02d}:{minutes:02d}:{seconds:02d}" return '-' duration_display.short_description = 'Длительность' @admin.register(ScreenRecording) class ScreenRecordingAdmin(admin.ModelAdmin): """Админ интерфейс для записей видео.""" list_display = [ 'room_id', 'status_badge', 'file_size_display', 'duration_display', 'is_public', 'expires_at', 'created_at' ] list_filter = [ 'status', 'is_public', 'created_at', 'processed_at' ] search_fields = [ 'room__room_id', 'room__lesson__title', 'file_path' ] readonly_fields = [ 'room', 'file_size', 'duration', 'status', 'processing_error', 'created_at', 'processed_at' ] actions = ['mark_as_public', 'mark_as_private'] def room_id(self, obj): """ID комнаты.""" return str(obj.room.room_id)[:8] room_id.short_description = 'Комната' def status_badge(self, obj): """Бейдж статуса.""" colors = { 'processing': '#ffc107', 'ready': '#28a745', 'failed': '#dc3545' } return format_html( '{}', colors.get(obj.status, '#000'), obj.get_status_display() ) status_badge.short_description = 'Статус' def file_size_display(self, obj): """Отображение размера файла.""" if obj.file_size: size_mb = obj.file_size / (1024 * 1024) if size_mb > 1024: return f"{size_mb / 1024:.2f} GB" return f"{size_mb:.2f} MB" return '-' file_size_display.short_description = 'Размер' def duration_display(self, obj): """Отображение длительности.""" if obj.duration: hours = obj.duration // 3600 minutes = (obj.duration % 3600) // 60 seconds = obj.duration % 60 return f"{hours:02d}:{minutes:02d}:{seconds:02d}" return '-' duration_display.short_description = 'Длительность' @admin.action(description='Сделать публичными') def mark_as_public(self, request, queryset): """Сделать записи публичными.""" queryset.update(is_public=True) @admin.action(description='Сделать приватными') def mark_as_private(self, request, queryset): """Сделать записи приватными.""" queryset.update(is_public=False)