add live class
This commit is contained in:
parent
91858c53d5
commit
668d2596e7
Binary file not shown.
Binary file not shown.
57
core/templates/core/live_classroom.html
Normal file
57
core/templates/core/live_classroom.html
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n static %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "Live Classroom" %} - {{ subject.name_en }}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container-fluid p-0" style="height: calc(100vh - 76px); margin-top: 76px;">
|
||||||
|
|
||||||
|
<div id="meet" style="width: 100%; height: 100%;"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src='https://meet.jit.si/external_api.js'></script>
|
||||||
|
<script>
|
||||||
|
const domain = 'meet.jit.si';
|
||||||
|
const options = {
|
||||||
|
roomName: '{{ room_name }}',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
parentNode: document.querySelector('#meet'),
|
||||||
|
userInfo: {
|
||||||
|
displayName: '{{ user_display_name }}'
|
||||||
|
},
|
||||||
|
configOverwrite: {
|
||||||
|
startWithAudioMuted: true,
|
||||||
|
startWithVideoMuted: true,
|
||||||
|
{% if not is_teacher %}
|
||||||
|
// Hide some controls for students
|
||||||
|
disableRemoteMute: true,
|
||||||
|
{% endif %}
|
||||||
|
prejoinPageEnabled: false
|
||||||
|
},
|
||||||
|
interfaceConfigOverwrite: {
|
||||||
|
// Customize toolbar if needed
|
||||||
|
SHOW_JITSI_WATERMARK: false,
|
||||||
|
DEFAULT_BACKGROUND: 'white',
|
||||||
|
DEFAULT_LOCAL_DISPLAY_NAME: '{{ user_display_name }}',
|
||||||
|
TOOLBAR_BUTTONS: [
|
||||||
|
'microphone', 'camera', 'closedcaptions', 'desktop', 'fullscreen',
|
||||||
|
'fodeviceselection', 'hangup', 'profile', 'chat', 'recording',
|
||||||
|
'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
|
||||||
|
'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
|
||||||
|
'tileview', 'videobackgroundblur', 'download', 'help', 'mute-everyone',
|
||||||
|
'security'
|
||||||
|
],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const api = new JitsiMeetExternalAPI(domain, options);
|
||||||
|
|
||||||
|
// Redirect when hanging up
|
||||||
|
api.addEventListeners({
|
||||||
|
videoConferenceLeft: function () {
|
||||||
|
window.location.href = "{% url 'profile' %}";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
@ -126,11 +126,18 @@
|
|||||||
<span class="badge bg-primary bg-opacity-10 text-primary">
|
<span class="badge bg-primary bg-opacity-10 text-primary">
|
||||||
{{ subject.teacher.user.get_full_name|default:"No Teacher" }}
|
{{ subject.teacher.user.get_full_name|default:"No Teacher" }}
|
||||||
</span>
|
</span>
|
||||||
|
<div>
|
||||||
|
<a href="{% url 'live_classroom' subject.id %}" class="btn btn-sm btn-danger rounded-pill me-1" title="{% trans 'Join Live Class' %}">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-camera-video-fill" viewBox="0 0 16 16">
|
||||||
|
<path fill-rule="evenodd" d="M0 5a2 2 0 0 1 2-2h7.5a2 2 0 0 1 1.983 1.738l3.11-1.382A1 1 0 0 1 16 4.269v7.461a1 1 0 0 1-1.406.913l-3.111-1.382A2 2 0 0 1 9.5 13H2a2 2 0 0 1-2-2V5z"/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
<a href="{% url 'subject_detail' subject.id %}" class="btn btn-sm btn-primary rounded-pill">{% trans "Go to Class" %}</a>
|
<a href="{% url 'subject_detail' subject.id %}" class="btn btn-sm btn-primary rounded-pill">{% trans "Go to Class" %}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|||||||
@ -107,8 +107,14 @@
|
|||||||
{{ subject.subscribers.count }} {% trans "Students" %}
|
{{ subject.subscribers.count }} {% trans "Students" %}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3">
|
<div class="mt-3 d-grid gap-2">
|
||||||
<a href="{% url 'subject_detail' subject.id %}" class="btn btn-sm btn-primary w-100 rounded-pill">{% trans "Manage Class" %}</a>
|
<a href="{% url 'live_classroom' subject.id %}" class="btn btn-sm btn-danger rounded-pill">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-camera-video-fill me-2" viewBox="0 0 16 16">
|
||||||
|
<path fill-rule="evenodd" d="M0 5a2 2 0 0 1 2-2h7.5a2 2 0 0 1 1.983 1.738l3.11-1.382A1 1 0 0 1 16 4.269v7.461a1 1 0 0 1-1.406.913l-3.111-1.382A2 2 0 0 1 9.5 13H2a2 2 0 0 1-2-2V5z"/>
|
||||||
|
</svg>
|
||||||
|
{% trans "Start Live Class" %}
|
||||||
|
</a>
|
||||||
|
<a href="{% url 'subject_detail' subject.id %}" class="btn btn-sm btn-primary rounded-pill">{% trans "Manage Class" %}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -17,4 +17,5 @@ urlpatterns = [
|
|||||||
path('subscribe/<int:subject_id>/', views.subscribe_subject, name='subscribe_subject'),
|
path('subscribe/<int:subject_id>/', views.subscribe_subject, name='subscribe_subject'),
|
||||||
path('payment/success/', views.payment_success, name='payment_success'),
|
path('payment/success/', views.payment_success, name='payment_success'),
|
||||||
path('payment/cancel/', views.payment_cancel, name='payment_cancel'),
|
path('payment/cancel/', views.payment_cancel, name='payment_cancel'),
|
||||||
|
path('classroom/<int:subject_id>/', views.live_classroom, name='live_classroom'),
|
||||||
]
|
]
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.shortcuts import render, redirect, get_object_or_404
|
from django.shortcuts import render, redirect, get_object_or_404
|
||||||
from django.utils import translation
|
from django.utils import translation
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -244,3 +245,30 @@ def payment_success(request):
|
|||||||
@login_required
|
@login_required
|
||||||
def payment_cancel(request):
|
def payment_cancel(request):
|
||||||
return redirect('profile')
|
return redirect('profile')
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def live_classroom(request, subject_id):
|
||||||
|
subject = get_object_or_404(Subject, pk=subject_id)
|
||||||
|
|
||||||
|
is_teacher = False
|
||||||
|
is_student = False
|
||||||
|
|
||||||
|
if hasattr(request.user, 'teacher_profile') and subject.teacher and subject.teacher.user == request.user:
|
||||||
|
is_teacher = True
|
||||||
|
|
||||||
|
if hasattr(request.user, 'student_profile') and request.user.student_profile.subscribed_subjects.filter(pk=subject_id).exists():
|
||||||
|
is_student = True
|
||||||
|
|
||||||
|
if not (is_teacher or is_student):
|
||||||
|
raise PermissionDenied("You are not authorized to join this class.")
|
||||||
|
|
||||||
|
# Generate Room Name
|
||||||
|
# We use a consistent room name based on Subject ID
|
||||||
|
room_name = f"EduPlatform_Live_Subject_{subject.id}"
|
||||||
|
|
||||||
|
return render(request, 'core/live_classroom.html', {
|
||||||
|
'subject': subject,
|
||||||
|
'room_name': room_name,
|
||||||
|
'user_display_name': request.user.get_full_name() or request.user.username,
|
||||||
|
'is_teacher': is_teacher
|
||||||
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user