class SeminarQuestionInline(admin.StackedInline):
model = Question
+class SeminarStepInline(admin.StackedInline):
+ model = SeminarStep
+ autocomplete_fields = [ 'docs_1', 'medias', 'docs_2', 'docs_correct', 'quiz']
+
class SeminarAdmin(admin.ModelAdmin):
exclude = ['keywords']
- inlines = [SeminarQuestionInline,]
+ inlines = [SeminarQuestionInline, SeminarStepInline]
filter_horizontal = ['professor',]
# filter_vertical = ['docs_description', 'docs_1',
# 'docs_2', 'docs_correct', 'medias',
class Media:
css = { 'all': ('admin/extra.css',) }
+
+
+
class MediaItemMarkerAdmin(admin.ModelAdmin):
search_fields = ['title', 'description']
--- /dev/null
+# Generated by Django 3.2.3 on 2022-07-13 10:32
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('quiz', '__first__'),
+ ('teleforma', '0005_auto_20220117_1756'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='SeminarStep',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('docs_1', models.ManyToManyField(blank=True, related_name='seminarstep_docs1', to='teleforma.Document', verbose_name='documents 1')),
+ ('docs_2', models.ManyToManyField(blank=True, related_name='seminarstep_docs2', to='teleforma.Document', verbose_name='documents 2')),
+ ('docs_correct', models.ManyToManyField(blank=True, related_name='seminarstep_docs_correct', to='teleforma.Document', verbose_name='corrected documents')),
+ ('medias', models.ManyToManyField(blank=True, related_name='seminarstep', to='teleforma.Media', verbose_name='media')),
+ ('quiz', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='seminarstep', to='quiz.quiz', verbose_name='quiz')),
+ ('seminar', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='steps', to='teleforma.seminar', verbose_name='seminar')),
+ ],
+ ),
+ ]
--- /dev/null
+# Generated by Django 3.2.3 on 2022-07-13 10:49
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('quiz', '__first__'),
+ ('teleforma', '0006_seminarstep'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='seminarstep',
+ name='quiz',
+ field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.PROTECT, related_name='seminarstep', to='quiz.quiz', verbose_name='quiz'),
+ preserve_default=False,
+ ),
+ ]
verbose_name = _('Seminar type')
+
+
+
class Seminar(ClonableMixin, Displayable, ProductCodeMixin, SuggestionsMixin):
# title, description, keywords, dates and status are given by Displayable
def suggestions(self):
return (list(self.suggested_seminars.all())+list(self.suggested_conferences.all()))[:3]
+ @property
+ def is_multistep(self):
+ return self.steps.count()
+
+ @property
+ def number_of_steps(self):
+ """ number of top steps """
+ return self.steps.count() or 1
+
+ def get_steps(self, user):
+ """ get steps info """
+ steps = []
+ last_accessible = None
+ for i, step in enumerate(self.steps.order_by('id')):
+ validated = step.is_validated(user)
+ accessible = validated
+ if not validated and not last_accessible:
+ accessible = True
+ last_accessible = True
+ steps.append({
+ 'index': i + 1,
+ 'object': step,
+ 'validated': validated,
+ 'accessible': accessible
+ })
+ return steps
+
def use_webclass(self, user):
"""
Should we show the webclass or the media ?
verbose_name = _('Seminar')
ordering = ['rank']
+class SeminarStep(models.Model):
+ seminar = models.ForeignKey(Seminar, related_name='steps', verbose_name=_('seminar'), on_delete=models.CASCADE)
+ docs_1 = models.ManyToManyField(Document, related_name="seminarstep_docs1",
+ verbose_name=_('documents 1'),
+ blank=True)
+ medias = models.ManyToManyField(Media, related_name="seminarstep",
+ verbose_name=_('media'),
+ blank=True)
+ docs_2 = models.ManyToManyField(Document, related_name="seminarstep_docs2",
+ verbose_name=_('documents 2'),
+ blank=True)
+ docs_correct = models.ManyToManyField(Document, related_name="seminarstep_docs_correct",
+ verbose_name=_('corrected documents'),
+ blank=True)
+ quiz = models.ForeignKey(Quiz, related_name="seminarstep",
+ verbose_name=_('quiz'),
+ on_delete=models.PROTECT)
+
+
+ def is_validated(self, user):
+ validations = QuizValidation.objects.filter(quiz=self.quiz, user=user, validated=True, date_validated__range=[self.seminar.date_added, self.seminar.expiry_date])
+ if validations:
+ return True
+ return False
class Question(ClonableMixin, models.Model):
<tbody>
<tr>
<td class="border-top" width="35%">
- {% if seminar.quiz %}
- <a href="{% url 'teleforma-quiz' seminar.id seminar.quiz.url %}">{{ seminar.quiz.title }}</a>
+ {% if quiz %}
+ <a href="{% url 'teleforma-quiz' seminar.id quiz.url %}">{{ quiz.title }}</a>
{% endif %}
</td>
<td class="border-top"width="60%">
- {% if seminar|quiz_validated:user %}
- {% trans "validé le" %} {{ seminar|quiz_validated:user }}
+ {% if quiz|one_more:user|quiz_validated:seminar %}
+ {% trans "validé le" %} {{ quiz|one_more:user|quiz_validated:seminar }}
{% endif %}
</td>
<td class="border-top" width="5%" align="center">
- {% if seminar|quiz_validated:user %}
+ {% if quiz|one_more:user|quiz_validated:seminar %}
<img src="{{ STATIC_URL }}teleforma/images/ok.png" style="vertical-align:middle" alt="" title="{% trans "Validated" %}" />
{% else %}
<img src="{{ STATIC_URL }}teleforma/images/delete.png" style="vertical-align:middle" alt="" title="{% trans ' not viewed yet' %}" />
{% endif %}
</div>
- {% with seminar.docs_1 as docs %}
- <div class="course_content">
- <div class="course_subtitle">
- <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 1 :
- {% if docs.all.count > 1 %}{% trans "read these documents" %}{% else %}{% trans "read this document" %}{% endif %}
- </h3>
- </div>
- {% include "teleforma/inc/document_simple_list.html" %}
- </div>
- {% endwith %}
-
- {% if show_webclass %}
- {% with seminar.conference as webclass %}
- <div class="course_content">
- <div class="course_subtitle">
- <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 2 :
- {% trans "view this conference" %}</h3>
+ {% if seminar.is_multistep %}
+ {% for step in steps %}
+ {{ step.index }}
+ {% endfor %}
+
+
+ {% for step in steps %}
+ <h2>Step {{ step.index }} - {{ step.validated }} {{ step.accessible }}</h2>
+
+ {% with step.object.docs_1 as docs %}
+ <div class="course_content">
+ <div class="course_subtitle">
+ <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 1 :
+ {% if docs.all.count > 1 %}{% trans "read these documents" %}{% else %}{% trans "read this document" %}{% endif %}
+ </h3>
+ </div>
+ {% include "teleforma/inc/document_simple_list.html" %}
</div>
- {% include "teleforma/inc/webclass.html" %}
- </div>
- {% endwith %}
+ {% endwith %}
+
+ {% with step.object.medias as medias %}
+ <div class="course_content">
+ <div class="course_subtitle">
+ <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 2 :
+ {% if medias.all.count > 1 %}{% trans "view these conferences" %}{% else %}{% trans "view this conference" %}{% endif %}
+ </h3>
+ </div>
+ {% include "teleforma/inc/media_package_list.html" %}
+ </div>
+ {% endwith %}
+
+ {% with step.object.quiz as quiz %}
+ <div class="course_content">
+ <div class="course_subtitle">
+ <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 2bis :
+ {% trans "Quiz" %}</h3>
+ </div>
+ {% include "teleforma/inc/quiz_list.html" %}
+ </div>
+ {% endwith %}
+
+ {% endfor %}
+
{% else %}
- {% with seminar.medias as medias %}
+ {% with seminar.docs_1 as docs %}
<div class="course_content">
<div class="course_subtitle">
- <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 2 :
- {% if medias.all.count > 1 %}{% trans "view these conferences" %}{% else %}{% trans "view this conference" %}{% endif %}
+ <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 1 :
+ {% if docs.all.count > 1 %}{% trans "read these documents" %}{% else %}{% trans "read this document" %}{% endif %}
</h3>
</div>
- {% include "teleforma/inc/media_package_list.html" %}
+ {% include "teleforma/inc/document_simple_list.html" %}
</div>
{% endwith %}
- {% endif %}
+ {% if show_webclass %}
+ {% with seminar.conference as webclass %}
+ <div class="course_content">
+ <div class="course_subtitle">
+ <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 2 :
+ {% trans "view this conference" %}</h3>
+ </div>
+ {% include "teleforma/inc/webclass.html" %}
+ </div>
+ {% endwith %}
+ {% else %}
+ {% with seminar.medias as medias %}
+ <div class="course_content">
+ <div class="course_subtitle">
+ <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 2 :
+ {% if medias.all.count > 1 %}{% trans "view these conferences" %}{% else %}{% trans "view this conference" %}{% endif %}
+ </h3>
+ </div>
+ {% include "teleforma/inc/media_package_list.html" %}
+ </div>
+ {% endwith %}
+ {% endif %}
- {% if seminar.quiz %}
- <div class="course_content">
- <div class="course_subtitle">
- <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 2bis :
- {% trans "Quiz" %}</h3>
- </div>
- {% include "teleforma/inc/quiz_list.html" %}
- </div>
- {% endif %}
- {% with seminar.docs_2 as docs %}
- <div class="course_content">
- <div class="course_subtitle">
- <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 3 :
- {% if docs.all.count > 1 %}{% trans "read these documents" %}{% else %}{% trans "read this document" %}{% endif %}
- </h3>
+ {% if seminar.quiz %}
+ {% with seminar.quiz as quiz %}
+ <div class="course_content">
+ <div class="course_subtitle">
+ <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 2bis :
+ {% trans "Quiz" %}</h3>
+ </div>
+ {% include "teleforma/inc/quiz_list.html" %}
+ </div>
+ {% endwith %}
+ {% endif %}
+
+ {% with seminar.docs_2 as docs %}
+ <div class="course_content">
+ <div class="course_subtitle">
+ <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 3 :
+ {% if docs.all.count > 1 %}{% trans "read these documents" %}{% else %}{% trans "read this document" %}{% endif %}
+ </h3>
+ </div>
+ {% include "teleforma/inc/document_simple_list.html" %}
</div>
- {% include "teleforma/inc/document_simple_list.html" %}
- </div>
- {% endwith %}
+ {% endwith %}
- {% with seminar.question as questions %}
- <div class="course_content">
- <div class="course_subtitle">
- <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 4 :
- {% if questions.all.count > 1 %}{% trans "answer to these questions" %}{% else %}{% trans "answer to this question" %}{% endif %}
- </h3>
+ {% with seminar.question as questions %}
+ <div class="course_content">
+ <div class="course_subtitle">
+ <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 4 :
+ {% if questions.all.count > 1 %}{% trans "answer to these questions" %}{% else %}{% trans "answer to this question" %}{% endif %}
+ </h3>
+ </div>
+ {% include "teleforma/inc/question_list.html" %}
</div>
- {% include "teleforma/inc/question_list.html" %}
- </div>
- {% endwith %}
-
- {% with seminar.docs_correct as docs %}
- <div class="course_content">
- <div class="course_subtitle">
- <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 5 :
- {% if docs.all.count > 1 %}{% trans "read these corrected documents" %}{% else %}{% trans "read this corrected document" %}{% endif %}
- </h3>
+ {% endwith %}
+
+ {% with seminar.docs_correct as docs %}
+ <div class="course_content">
+ <div class="course_subtitle">
+ <h3><img src="{{ STATIC_URL }}/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Step" %} 5 :
+ {% if docs.all.count > 1 %}{% trans "read these corrected documents" %}{% else %}{% trans "read this corrected document" %}{% endif %}
+ </h3>
+ </div>
+ {% include "teleforma/inc/document_simple_list.html" %}
</div>
- {% include "teleforma/inc/document_simple_list.html" %}
- </div>
- {% endwith %}
+ {% endwith %}
+ {% endif %}
{% if seminar_progress == 100 %}
return ''
@register.filter
-def quiz_validated(seminar, user):
- quiz = seminar.quiz
+def one_more(_1, _2):
+ # to pass more than one argument to filter
+ return _1, _2
+
+@register.filter
+def quiz_validated(quiz_and_user, seminar):
+ quiz, user = quiz_and_user
startdate = seminar.date_added
enddate = seminar.expiry_date
- validations = QuizValidation.objects.filter(quiz=quiz, user=user, validated=True,date_validated__range=[startdate, enddate])
+ validations = QuizValidation.objects.filter(quiz=quiz, user=user, validated=True, date_validated__range=[startdate, enddate])
if validations:
return validations[0].date_validated
else:
from teleforma.context_processors import all_conferences, all_seminars, seminar_progress, seminar_validated
from teleforma.models.core import Conference
-from teleforma.models.pro import Answer, Question, QuizValidation, Seminar, SeminarRevision, Testimonial
+from teleforma.models.pro import Answer, Question, QuizValidation, Seminar, SeminarRevision, SeminarStep, Testimonial
from teleforma.forms import AnswerForm
from teleforma.views.core import DocumentDownloadView, DocumentReadView, MediaView
user = self.request.user
context['show_webclass'] = seminar.use_webclass(user)
+ context['steps'] = seminar.get_steps(user)
+
+
validated = seminar_validated(user, seminar)
if validated:
# check if testimonial exists and create it
template_name = 'quiz/question.html'
+ def _init(self):
+ self.seminar = Seminar.objects.get(pk=self.kwargs['pk'])
+ try:
+ self.step = self.quiz.seminarstep.get(seminar__pk=self.kwargs['pk'])
+ except SeminarStep.DoesNotExist:
+ self.step = self.seminar
+
def get_user(self):
user_id = self.request.user.id
return User.objects.get(id=user_id)
def can_access(self):
user = self.get_user()
- for items in [self.seminar.docs_1, self.seminar.medias]:
+ for items in [self.step.docs_1, self.step.medias]:
for item in items.all():
if item.weight:
if user not in item.readers.all():
return False
return True
+
def get_context_data(self, **kwargs):
context = super(QuizQuestionView, self).get_context_data(**kwargs)
+ self._init()
user = self.get_user()
- self.seminar = Seminar.objects.get(pk=self.kwargs['pk'])
+
context['can_access'] = self.can_access()
context['seminar'] = self.seminar
context['seminar_progress'] = seminar_progress(user, self.seminar)
return context
def final_result_user(self):
+ self._init()
user = self.get_user()
- self.seminar = Seminar.objects.get(pk=self.kwargs['pk'])
results = {
'quiz': self.quiz,
if self.sitting.get_percent_correct >= self.quiz.pass_mark:
validation = QuizValidation(
- user=user, quiz=self.seminar.quiz, validated=True)
+ user=user, quiz=self.step.quiz, validated=True)
validation.save()
else:
# revert step 1 validation
- for doc in self.seminar.docs_1.all():
+ for doc in self.step.docs_1.all():
doc.readers.remove(user)
doc.save()