]> git.parisson.com Git - teleforma.git/commitdiff
Uncommited changes by Yoan
authorGael Le Mignot <gael@pilotsystems.net>
Fri, 22 Jul 2022 10:28:00 +0000 (12:28 +0200)
committerGael Le Mignot <gael@pilotsystems.net>
Fri, 22 Jul 2022 10:28:00 +0000 (12:28 +0200)
teleforma/admin.py
teleforma/migrations/0006_seminarstep.py [new file with mode: 0644]
teleforma/migrations/0007_alter_seminarstep_quiz.py [new file with mode: 0644]
teleforma/models/pro.py
teleforma/templates/teleforma/inc/quiz_list.html
teleforma/templates/teleforma/seminar_detail.html
teleforma/templatetags/teleforma_tags.py
teleforma/views/pro.py

index e4633bc3f04c07a490ac99e07c47047e6fbc5fb6..c36d877c2fa981e9a0ded48c5805d86dc6417847 100644 (file)
@@ -210,9 +210,13 @@ class ConferenceAdmin(admin.ModelAdmin):
 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',
@@ -288,6 +292,9 @@ class SeminarAdmin(admin.ModelAdmin):
     class Media:
         css = { 'all': ('admin/extra.css',) }
 
+
+
+
 class MediaItemMarkerAdmin(admin.ModelAdmin):
     search_fields = ['title', 'description']
 
diff --git a/teleforma/migrations/0006_seminarstep.py b/teleforma/migrations/0006_seminarstep.py
new file mode 100644 (file)
index 0000000..2855b05
--- /dev/null
@@ -0,0 +1,27 @@
+# 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')),
+            ],
+        ),
+    ]
diff --git a/teleforma/migrations/0007_alter_seminarstep_quiz.py b/teleforma/migrations/0007_alter_seminarstep_quiz.py
new file mode 100644 (file)
index 0000000..482e8c9
--- /dev/null
@@ -0,0 +1,21 @@
+# 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,
+        ),
+    ]
index 5bbabbe2fc6003b903b99dc70fcc142af07e21af..fab61248bd9f28179a4773c04a340b1a890507b8 100644 (file)
@@ -61,6 +61,9 @@ class SeminarType(models.Model):
         verbose_name = _('Seminar type')
 
 
+
+
+
 class Seminar(ClonableMixin, Displayable, ProductCodeMixin, SuggestionsMixin):
 
     # title, description, keywords, dates and status are given by Displayable
@@ -181,6 +184,33 @@ class Seminar(ClonableMixin, Displayable, ProductCodeMixin, SuggestionsMixin):
     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 ?
@@ -243,6 +273,30 @@ class Seminar(ClonableMixin, Displayable, ProductCodeMixin, SuggestionsMixin):
         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):
 
index 552be97403cc2f3db9c1c4c127b7041423c1393a..592d6fa155dde3c9c911e91a4f3eae3c9f0940d4 100644 (file)
@@ -5,17 +5,17 @@
     <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' %}" />
index e05a5caaecff98769f652253850cdfa1951c620a..96aaf513b11789edce8884764a479baeb3666e8f 100644 (file)
     {% 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 %}
 
index 887a16d0643622d25e2fcf25df5710b956f82d25..895746ae06435c5d2ce1df03e24319f649bd1828 100644 (file)
@@ -237,11 +237,16 @@ def validated(question, user):
         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:
index 91d4b7af11d420f5652fadfb6d4b656b552388dd..8b2515e9414afd351d56c522c2e503a954d0d17f 100644 (file)
@@ -71,7 +71,7 @@ from quiz.views import QuizTake
 
 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
 
@@ -231,6 +231,9 @@ class SeminarView(SeminarAccessMixin, DetailView):
 
         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
@@ -939,31 +942,40 @@ class QuizQuestionView(SeminarAccessMixin, SeminarRevisionMixin, QuizTake):
 
     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,
@@ -989,11 +1001,11 @@ class QuizQuestionView(SeminarAccessMixin, SeminarRevisionMixin, QuizTake):
 
         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()