export_xls.short_description = "Export vers XLS"
- def add_to_group(self, request, queryset):
- group_name = request.POST['group_name']
- group, c = StudentGroup.objects.get_or_create(name=group_name)
- for student in queryset:
- group.students.add(student)
- # self.message_user(request, ("Successfully added to group : %s") % (group_name,), messages.SUCCESS)
- add_to_group.short_description = "Ajouter au groupe"
+ def add_to_group(self, request, queryset):
+ group_name = request.POST['group_name']
+ group, c = StudentGroup.objects.get_or_create(name=group_name)
+ for student in queryset:
+ group.students.add(student)
+ # self.message_user(request, ("Successfully added to group : %s") % (group_name,), messages.SUCCESS)
+ add_to_group.short_description = "Ajouter au groupe"
class CorrectorAdmin(admin.ModelAdmin):
admin.site.register(Student, StudentAdmin)
# admin.site.register(Corrector, CorrectorAdmin)
admin.site.register(Professor, ProfessorAdmin)
-# admin.site.register(StudentGroup, StudentGroupAdmin)
+admin.site.register(StudentGroup, StudentGroupAdmin)
admin.site.register(GroupedMessage)
admin.site.register(Home, HomeAdmin)
admin.site.register(Parameters, ParametersAdmin)
--- /dev/null
+# Generated by Django 3.2.13 on 2023-05-22 09:36
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('teleforma', '0004_payment'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='studentgroup',
+ name='students',
+ ),
+ migrations.DeleteModel(
+ name='GroupedMessage',
+ ),
+ migrations.DeleteModel(
+ name='StudentGroup',
+ ),
+ ]
--- /dev/null
+# Generated by Django 3.2.13 on 2023-05-22 09:36
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('teleforma', '0005_auto_20230522_0936'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='StudentGroup',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=255, verbose_name='name')),
+ ('students', models.ManyToManyField(blank=True, related_name='groups', to='teleforma.Student', verbose_name='students')),
+ ],
+ options={
+ 'verbose_name': 'Student group',
+ 'db_table': 'teleforma_student_groups',
+ },
+ ),
+ migrations.CreateModel(
+ name='GroupedMessage',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('subject', models.CharField(max_length=119, verbose_name='subject')),
+ ('message', models.TextField(verbose_name='message')),
+ ('to_send', models.BooleanField(default=False, verbose_name='to send')),
+ ('sent', models.BooleanField(default=False, verbose_name='sent')),
+ ('date_sent', models.DateTimeField(blank=True, null=True, verbose_name='date sent')),
+ ('group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='grouped_messages', to='teleforma.studentgroup', verbose_name='group')),
+ ('sender', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='grouped_messages', to=settings.AUTH_USER_MODEL, verbose_name='sender')),
+ ],
+ options={
+ 'verbose_name': 'Grouped message',
+ 'db_table': 'teleforma_grouped_messages',
+ },
+ ),
+ ]
verbose_name_plural = _('AE students')
ordering = ['user__last_name']
+ def __str__(self):
+ return self.user.get_full_name()
+
def update_balance_signal(sender, instance, *args, **kwargs):
try:
if sender is Student or sender:
class WebclassAdmin(admin.ModelAdmin):
inlines = [WebclassSlotInline]
- list_filter = ('course', 'period', 'iej', 'bbb_server', 'status')
- list_display = ('course', 'period', 'bbb_server', 'status')
+ list_filter = ('course', 'period', 'iej', 'session', 'bbb_server', 'status')
+ list_display = ('course', 'period', 'session', 'bbb_server', 'status')
filter_horizontal = ('iej',)
search_fields = ['id', 'course__code', 'course__title']
class WebclassRecordAdmin(admin.ModelAdmin):
- list_filter = ('course', 'period')
- list_display = ('course', 'period', 'created')
+ list_filter = ('course', 'period', 'category')
+ list_display = ('course', 'period', 'category', 'created')
search_fields = ['id', 'course__code', 'course__title']
# def get_form(self, request, obj=None, **kwargs):
class WebclassRecordsForm(Form):
- # period = ModelChoiceField(label='Période',
- # queryset=Period.objects.filter(is_open=True))
-
- class Meta:
- pass
-
def __init__(self, *args, **kwargs):
+ # for each course, we create a field whcih includes a list of bbb course from the same course id and same period id
self.period_id = kwargs.pop('period_id')
self.period = Period.objects.get(pk=self.period_id)
super(WebclassRecordsForm, self).__init__(*args, **kwargs)
all_records = self.get_records_by_course()
for course in courses:
+ # get list of webclass
webclasses = course.webclass.filter(period=self.period).all()
if webclasses:
+ # build a rooms id list
rooms = []
for webclass in webclasses:
for slot in webclass.slots.all():
# for each bbb record for the current course, add an option to the field
for record in records:
+ if not record['slot']:
+ continue
webclass_slot = WebclassSlot.objects.get(
pk=record['slot'].id)
label = u"%s à %s - %s" % (record['start_date'].strftime(
label=course.title, choices=vocabulary, required=False)
def get_records_by_course(self):
+ """
+ Get all records, in a dict with course_id as key
+ """
records = get_records(period_id=self.period_id)
by_course = {}
for record in records:
- by_course.setdefault(record['course_id'], []).append(record)
+ if record.get('course_id'):
+ by_course.setdefault(record['course_id'], []).append(record)
return by_course
def save_records(self):
--- /dev/null
+# Generated by Django 3.2.13 on 2023-05-22 12:00
+
+from django.db import migrations, models
+import teleforma.fields
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('webclass', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='webclass',
+ name='allow_elearning',
+ field=models.BooleanField(default=True, verbose_name='Autoriser e-learning'),
+ ),
+ migrations.AddField(
+ model_name='webclass',
+ name='allow_presentiel',
+ field=models.BooleanField(default=True, verbose_name='Autoriser présentiel'),
+ ),
+ migrations.AddField(
+ model_name='webclass',
+ name='comment',
+ field=teleforma.fields.ShortTextField(blank=True, max_length=255, verbose_name='comment'),
+ ),
+ migrations.AddField(
+ model_name='webclass',
+ name='session',
+ field=models.CharField(choices=[('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8'), ('9', '9'), ('10', '10')], default='1', max_length=16, verbose_name='session'),
+ ),
+ migrations.AddField(
+ model_name='webclassrecord',
+ name='category',
+ field=models.CharField(choices=[('WC', 'Webclass'), ('CC', 'Correction de copie')], default='WC', max_length=2, verbose_name='Catégorie'),
+ ),
+ migrations.AddIndex(
+ model_name='webclass',
+ index=models.Index(fields=['status', 'period', 'course'], name='teleforma_w_status_03cc4b_idx'),
+ ),
+ ]
import calendar
import datetime
from datetime import date, timedelta
+from unidecode import unidecode
import django.db.models as models
from bigbluebutton_api_python import BigBlueButton
from django.utils import translation
from django.utils.translation import ugettext_lazy as _
from jxmlease import XMLDictNode, XMLListNode
-from teleforma.fields import DurationField
-from unidecode import unidecode
+from teleforma.fields import DurationField, ShortTextField
+from teleforma.models import session_choices
+
translation.activate('fr')
app_label = 'teleforma'
'end': end,
'end_date': datetime.datetime.fromtimestamp(end),
'url': url,
- 'preview': str(recording.get('playback', {}).get('format', {}).get('preview', {}).get('images', {}).get('image', [])[0]),
+ 'preview': str(recording.get('playback', {}).get('format', {}).get('preview', {}).get('images', {}).get('image', [])),
'state': str(recording['state']),
}
if recording['metadata'].get('periodid'):
pk=int(recording['metadata'].get('slotid', -1)))
except WebclassSlot.DoesNotExist:
# this happen if the slot is deleted in django admin
- continue
+ pass
data.update({
'period_id': int(recording['metadata'].get('periodid', -1)),
'course_id': int(recording['metadata'].get('courseid', -1)),
return "Serveur %d" % self.id
-class PublishedManager(models.Manager):
- def get_query_set(self):
- return super(PublishedManager, self).get_query_set().filter(status=3).exclude(end_date__lt=date.today())
-
+class WebclassPublishedManager(models.Manager):
+ def get_queryset(self):
+ return super(WebclassPublishedManager, self).get_queryset().filter(status=3).exclude(end_date__lt=date.today())
class Webclass(models.Model):
'teleforma.Course', related_name='webclass', verbose_name=_('course'), on_delete=models.CASCADE)
iej = models.ManyToManyField(
'teleforma.IEJ', related_name='webclass', verbose_name=_('iej'), blank=True)
+ allow_elearning = models.BooleanField('Autoriser e-learning', default=True)
+ allow_presentiel = models.BooleanField('Autoriser présentiel', default=True)
bbb_server = models.ForeignKey(
'BBBServer', related_name='webclass', verbose_name='Serveur BBB', on_delete=models.CASCADE)
duration = DurationField('Durée de la conférence', default="00:30:00")
max_participants = models.IntegerField(
'Nombre maxium de participants par créneau', blank=True, null=True, default=80)
end_date = models.DateField('date de fin', blank=True, null=True)
+ session = models.CharField(_('session'), choices=session_choices,
+ max_length=16, default="1")
status = models.IntegerField(
_('status'), choices=STATUS_CHOICES, default=2)
+ comment = ShortTextField(_('comment'), max_length=255, blank=True)
objects = models.Manager()
- published = PublishedManager()
+ published = WebclassPublishedManager()
class Meta(MetaCore):
db_table = app_label + '_' + 'webclass'
verbose_name = _('webclass')
verbose_name_plural = _('webclass')
+ indexes = [
+ models.Index(fields=['status', 'period', 'course', ]),
+ ]
def __str__(self):
return "Webclass %d : %s" % (self.id, self.course.title)
except WebclassSlot.DoesNotExist:
return None
+ def is_not_over(self):
+ """
+ Check if the webclass is not over yet
+ """
+ if self.end_date and self.end_date < datetime.date.today():
+ return False
+ return True
+
class SlotPublishedManager(models.Manager):
- def get_query_set(self):
- return super(SlotPublishedManager, self).get_query_set().filter(webclass__status=3).exclude(webclass__end_date__lt=date.today())
+ def get_queryset(self):
+ return super(SlotPublishedManager, self).get_queryset().filter(webclass__status=3).exclude(webclass__end_date__lt=date.today())
class WebclassSlot(models.Model):
def __str__(self):
return "Webclass slot : " + str(self.id)
+ @property
+ def date(self):
+ """
+ Compute the last date (from weekday) before the end of webclass.
+ This is the webclass date. Before, webclass were every "monday" for example.
+ Now there is only one date per webclass.
+ This is not ideal. We should have a "date" field on the webclass slot instead of "day".
+ But we're waiting to see how PB use webclasses in the future.
+ """
+ end_day = self.webclass.end_date
+ next_day = end_day + datetime.timedelta(days=7 - end_day.weekday() + self.day, weeks=-1)
+ if next_day > end_day:
+ next_day = next_day - datetime.timedelta(weeks=1)
+ return next_day
+
@property
def remaining_participant_slot(self):
"""
'slotid': self.id,
'professor': self.professor.user.username,
}
- print(params)
try:
result = self.bbb.create_meeting(
self.room_id, params=params, meta=meta)
'BBBServer', related_name='webclass_records', verbose_name='Serveur BBB', on_delete=models.CASCADE)
created = models.DateTimeField("Date de la conférence", auto_now_add=True)
+ WEBCLASS = 'WC'
+ CORRECTION = 'CC'
+ CATEGORY_CHOICES = [
+ (WEBCLASS, 'Webclass'),
+ (CORRECTION, 'Correction de copie'),
+ ]
+ category = models.CharField(
+ "Catégorie",
+ max_length=2,
+ choices=CATEGORY_CHOICES,
+ default=WEBCLASS,
+ )
+
class Meta(MetaCore):
db_table = app_label + '_' + 'webclass_record'
verbose_name = 'enregistrement'
@staticmethod
def get_records(period, course):
record_ids = set()
+ # id : category mapping
+ category_mapping = {}
for record in WebclassRecord.objects.filter(period=period, course=course):
record_ids.add(record.record_id)
+ category_mapping[record.record_id] = record.category
if not record_ids:
- return []
+ return {}
records = get_records_from_bbb(recording_id=','.join(record_ids))
- return records
+
+ # group records by category
+ categories = {}
+ for record in records:
+ category = category_mapping[record['id']]
+ if category not in categories:
+ categories[category] = []
+ categories[category].append(record)
+
+ return categories
<tr>
<th>Horaire</th>
<th>Professeur</th>
- <th>Places restantes</th>
+ {% comment %} <th>Places restantes</th> {% endcomment %}
<th>Inscription</th>
</tr>
</thead>
{% for slot in slots %}
<tr>
<td>
- <span class="booking_date"><strong>{{slot.get_day_display}}</strong> de <strong>{{slot.start_hour|date:"H\hi"}}</strong> à <strong>{{slot.end_hour|date:"H\hi"}}</strong></span>
+ <span class="booking_date">{{slot.get_day_display}} <strong>{{slot.date}}</strong> de <strong>{{slot.start_hour|date:"H\hi"}}</strong> à <strong>{{slot.end_hour|date:"H\hi"}}</strong></span>
</td>
<td>
{{slot.professor}}
</td>
- <td>
+ {% comment %} <td>
{{slot.remaining_participant_slot}}
- </td>
+ </td> {% endcomment %}
<td>
<form class="booking_form" method="POST">
- <span class="booking_date" style="display:none"><strong>{{slot.get_day_display}}</strong> de <strong>{{slot.start_hour|date:"H\hi"}}</strong> à <strong>{{slot.end_hour|date:"H\hi"}}</strong></span>
+ <span class="booking_date" style="display:none">{{slot.get_day_display}} <strong>{{slot.date}}</strong> de <strong>{{slot.start_hour|date:"H\hi"}}</strong> à <strong>{{slot.end_hour|date:"H\hi"}}</strong></span>
{% csrf_token %}
<input type="hidden" name="slot_id" value="{{slot.id}}" />
{% if slot.participant_slot_available %}
{% block content %}
<table class="webclass-appointment listing" width="100%">
<thead>
- <tr>
- <th>Horaire</th>
- <th>Période</th>
- <th>Cours</th>
- {% comment %} <th>IEJ</th> {% endcomment %}
- <th>Participants</th>
- <th>Salon</th>
- </tr>
+ <tr>
+ <th>Horaire</th>
+ <th>Période</th>
+ <th>Cours</th>
+ {% comment %} <th>IEJ</th> {% endcomment %}
+ <th>Participants</th>
+ <th>Salon</th>
+ {% if is_superuser %}
+ <th>Professeur</th>
+ {% endif %}
+ </tr>
</thead>
<tbody>
- {% for slot in slots %}
- <tr>
- <td>
- <span><strong>{{slot.get_day_display}}</strong> de <strong>{{slot.start_hour|date:"H\hi"}}</strong> à <strong>{{slot.end_hour|date:"H\hi"}}</strong></span>
- </td>
- <td>
- {{slot.webclass.period.name}}
- </td>
- <td>
- {{slot.webclass.course.title}}
- </td>
- {% comment %} <td>
- {% for iej in slot.webclass.iej.all %}
- {{iej.name}}
+ {% for slot in slots %}
+ <tr>
+ <td>
+ <span>{{slot.get_day_display}} <strong>{{slot.date}}</strong> de <strong>{{slot.start_hour|date:"H\hi"}}</strong> à
+ <strong>{{slot.end_hour|date:"H\hi"}}</strong></span>
+ </td>
+ <td>
+ {{slot.webclass.period.name}}
+ </td>
+ <td>
+ {{slot.webclass.course.title}}
+ </td>
+ {% comment %} <td>
+ {% for iej in slot.webclass.iej.all %}
+ {{iej.name}}
+ {% endfor %}
+ </td> {% endcomment %}
+ <td>
+ {{slot.participants.count}}
+ </td>
+ <td>
+ <a href="{% url 'teleforma-webclass-join' slot.id %}" target="_blank"
+ class="conference-big-button component_icon button icon_next">Rejoindre la conférence</a>
+ </td>
+ {% if is_superuser %}
+ <td>{{slot.professor}}</td>
+ {% endif %}
+ </tr>
+ {% empty %}
+ <tr>
+ <td colspan="5">Aucune webclasse programmée.</td>
+ </tr>
{% endfor %}
- </td> {% endcomment %}
- <td>
- {{slot.participants.count}}
- </td>
- <td>
- <a href="{% url 'teleforma-webclass-join' slot.id %}" target="_blank" class="conference-big-button component_icon button icon_next">Rejoindre la conférence</a>
- </td>
- </tr>
- {% empty %}
- <tr>
- <td colspan="5">Aucune webclasse programmée.</td>
- </tr>
- {% endfor %}
</tbody>
</table>
-{% endblock content %}
+{% endblock content %}
\ No newline at end of file
--- /dev/null
+{% load teleforma_tags webclass %}
+{% load i18n %}
+
+{% if webclass_corrections_records %}
+<div class="course_content content_video">
+ <table class="listing" width="100%">
+ <tbody>
+
+ {% for record in webclass_corrections_records %}
+ {% webclass_record record %}
+ {% endfor %}
+ </tbody>
+ </table>
+</div>
+{% else %}
+<div class="course_content">
+ <p>Aucun document</p>
+</div>
+{% endif %}
\ No newline at end of file
-{% load teleforma_tags %}
+{% load teleforma_tags webclass %}
{% load i18n %}
{% if webclass_slot or webclass_records %}
{% if webclass_slot %}
<tr>
<td colspan="2">
- <p>Vous êtes inscrit pour les webclasses du
- <strong>{{webclass_slot.get_day_display}} de
+ <p>Vous êtes inscrit pour la webclass du
+ <strong>{{webclass_slot.get_day_display}} {{webclass_slot.date}} de
{{webclass_slot.start_hour|date:"H\hi"}} à
{{webclass_slot.end_hour|date:"H\hi"}}</strong>
- avec le professeur <strong>{{webclass_slot.professor.user.last_name}}</strong>.</p>
+ avec le professeur <strong>{{webclass_slot.professor.user.last_name}}</strong>.
+ </p>
+ <p><a href="{% url 'teleforma-webclass-unregister' pk=webclass_slot.id %}" class="component_icon button icon_next">Se désinscrire</a> Vous pourrez ensuite vous inscrire sur un autre créneau.</p>
{% if webclass_slot.status == 'past' %}
<p>
</tr>
{% endif %}
{% for record in webclass_records %}
- <tr>
- <td {% if forloop.first %}class="border-top" {% endif %} style="width:200px">
- <a href="{% url 'teleforma-webclass-record' %}?url={{record.url}}" title="{% trans "View" %}">
- <img src="{{ record.preview }}" style="width:176px" alt="{% trans 'Click here' %}" />
- <div>Cliquez-ici</div>
- </a>
- </td>
- <td {% if forloop.first %}class="border-top" {% endif %} style="padding-left: 1em;">
- <div>
- <dl class="listing" style="font-size: 1.2em;">
- {% if record.slot %}
- <dt>{% trans "Professor" %}</dt>
- <dd>{{ record.slot.professor }}</dd>
- {% endif %}
- <dt>{% trans "Begin" %}</dt>
- <dd>{{ record.start_date }}</dd>
- </dl>
- </div>
- </td>
- <div style="padding-left: 1em;">
-
- </div>
- </tr>
+ {% webclass_record record %}
{% endfor %}
</tbody>
</table>
</div>
+{% else %}
+<div class="course_content">
+ <p>Aucun document</p>
+</div>
{% endif %}
\ No newline at end of file
--- /dev/null
+{% load i18n %}
+
+<tr>
+ <td {% if forloop.first %}class="border-top" {% endif %} style="width:200px">
+ <a href="{% url 'teleforma-webclass-record' %}?url={{record.url}}" title="{% trans "View" %}">
+ <img src="{{ record.preview }}" style="width:176px" alt="{% trans 'Click here' %}" />
+ <div>Cliquez-ici</div>
+ </a>
+ </td>
+ <td {% if forloop.first %}class="border-top" {% endif %} style="padding-left: 1em;">
+ <div>
+ <dl class="listing" style="font-size: 1.2em;">
+ {% if record.slot %}
+ <dt>{% trans "Professor" %}</dt>
+ <dd>{{ record.slot.professor }}</dd>
+ {% endif %}
+ <dt>{% trans "Begin" %}</dt>
+ <dd>{{ record.start_date }}</dd>
+ </dl>
+ </div>
+ </td>
+ <div style="padding-left: 1em;">
+
+ </div>
+</tr>
\ No newline at end of file
from ..webclass.views import (WebclassAppointment,
WebclassProfessorAppointments,
WebclassRecordsFormView, WebclassRecordView,
- join_webclass)
+ join_webclass, unregister)
urlpatterns = [
url(r'^desk/webclass_appointments/(?P<pk>.*)$', WebclassAppointment.as_view(),
name="teleforma-webclass-record"),
url(r'^webclass/periods/(?P<period_id>.*)/webclass_records_form/$',
WebclassRecordsFormView.as_view(), name="teleforma-webclass-records-form"),
+ url(r'^desk/webclass/(?P<pk>.*)/unregister/$',
+ unregister,
+ name="teleforma-webclass-unregister"),
url(r'^desk/webclass/(?P<pk>.*)/join/$',
join_webclass,
name="teleforma-webclass-join")
+
]
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.views.generic import FormView, TemplateView, View
-
-from teleforma.models.core import Professor
+from datetime import datetime
from ..decorators import access_required
from ..views.core import get_courses, get_periods
class WebclassProfessorAppointments(TemplateView):
template_name = 'webclass/appointments_professor.html'
- def dispatch(self, request, *args, **kwargs):
- user = self.request.user
- try:
- user.professor.get()
- except Professor.DoesNotExist:
- return HttpResponse('Unauthorized', status=401)
-
- return super().dispatch(request, *args, **kwargs)
-
-
def get_context_data(self, **kwargs):
""" """
context = super(WebclassProfessorAppointments,
self).get_context_data(**kwargs)
-
- context['slots'] = WebclassSlot.published.filter(
- professor=user.professor.get(), webclass__status=3).order_by('day', 'start_hour')
- print(context['slots'])
+
+ user = self.request.user
+ if not user.professor.all() and not user.is_superuser:
+ return HttpResponse('Unauthorized', status=401)
+ today = datetime.today()
+ query = {
+ 'webclass__status': 3,
+ 'webclass__end_date__gte': today
+ }
+ if user.professor.all():
+ query['professor'] = user.professor.get()
+ context['slots'] = WebclassSlot.published.filter(**query).order_by('day', 'start_hour')
+ context['is_superuser'] = user.is_superuser
return context
student = student[0]
# check period
period_id = webclass.period.id
- periods = [p for p in get_periods(user) if int(p.id) == period_id]
+ periods = [p for p in get_periods(self.request) if int(p.id) == period_id]
if not periods:
return HttpResponse('Unauthorized', status=401)
# check courses
# Student is in the right IEJ ?
if not student.iej in webclass.iej.all():
return HttpResponse('Unauthorized', status=401)
+ if student.platform_only and not webclass.allow_elearning:
+ return HttpResponse('Unauthorized', status=401)
+ if not student.platform_only and not webclass.allow_presentiel:
+ return HttpResponse('Unauthorized', status=401)
+
return
def render(self, request, webclass):
# Ensure user is logged in, a student, and has access to current period
user = request.user
student = user.student.all()[0]
-
- return render(request, self.template_name, {'slots': webclass.slots.order_by('day', 'start_hour'), 'webclass': webclass})
+ slots = webclass.slots.order_by('day', 'start_hour')
+ # only display unavaible slots or first slot of the day
+ filtered_slots = []
+ day = None
+ for slot in slots:
+ if slot.participant_slot_available:
+ if slot.day != day:
+ filtered_slots.append(slot)
+ day = slot.day
+ else:
+ filtered_slots.append(slot)
+
+ return render(request, self.template_name, {'slots': filtered_slots, 'webclass': webclass})
def check_slot_validity(self, user, slot):
"""
# return data
+
class WebclassRecordView(TemplateView):
template_name = 'webclass/record.html'
return redirect(webclass_slot.get_join_webclass_url(request, user))
else:
return HttpResponse('Unauthorized', status=401)
+
+
+@access_required
+def unregister(request, pk):
+ """
+ Unregister to a webclass
+ """
+ webclass_slot = WebclassSlot.objects.get(pk=int(pk))
+ user = request.user
+
+ if user in webclass_slot.participants.all():
+ webclass_slot.participants.remove(user)
+
+ messages.add_message(request, messages.INFO,
+ "Votre réservation a été annulé.")
+ # redirect to register form
+ return redirect(reverse("teleforma-webclass-appointments", kwargs={'pk':webclass_slot.webclass.id}))