From 61bff0638c1eba23b9bee153eafa1d9c05749be5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Tue, 5 Nov 2013 13:12:32 +0100 Subject: [PATCH 01/16] Some additional info while generating keys --- wtem/management/commands/wtem_generate_keys.py | 1 + 1 file changed, 1 insertion(+) diff --git a/wtem/management/commands/wtem_generate_keys.py b/wtem/management/commands/wtem_generate_keys.py index 239fe6b..75847ae 100644 --- a/wtem/management/commands/wtem_generate_keys.py +++ b/wtem/management/commands/wtem_generate_keys.py @@ -21,6 +21,7 @@ class Command(BaseCommand): Submission.create(**args) new += 1 else: + self.stdout.write('skipping ' + student['email'] + ': already exists.') skipped += 1 self.stdout.write('New: ' + str(new) + ', skipped: ' + str(skipped)) -- 2.20.1 From 53907d17526cecf92207417e051527c00bcd2426 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Tue, 5 Nov 2013 13:13:18 +0100 Subject: [PATCH 02/16] Sending keys wip: up to point of actually sending an email --- wtem/management/commands/wtem_send_keys.py | 59 +++++++++++++++++++ ...002_auto__add_field_submission_key_sent.py | 52 ++++++++++++++++ wtem/models.py | 1 + 3 files changed, 112 insertions(+) create mode 100644 wtem/management/commands/wtem_send_keys.py create mode 100644 wtem/migrations/0002_auto__add_field_submission_key_sent.py diff --git a/wtem/management/commands/wtem_send_keys.py b/wtem/management/commands/wtem_send_keys.py new file mode 100644 index 0000000..82e7469 --- /dev/null +++ b/wtem/management/commands/wtem_send_keys.py @@ -0,0 +1,59 @@ +from optparse import make_option + +from django.core.management.base import BaseCommand, CommandError +from django.conf import settings + +from wtem.models import Submission, DEBUG_KEY + + +class Command(BaseCommand): + help = 'Sends personalized links to WTEM contestants' + args = ', , ...' + + option_list = BaseCommand.option_list + ( + make_option('--all', + action='store_true', + dest='all', + default=False, + help='Use all available submissions'), + make_option('--force', + action='store_true', + dest='force', + default=False, + help='Force sending key even if one was already sent') + ) + + def handle(self, *args, **options): + if len(args) or options['all']: + return self.send_keys(*args, **options) + self.stdout.write('No submissions selected') + + def send_keys(self, *args, **options): + sent = 0 + skipped = 0 + failed = 0 + + query = Submission.objects.all() + if not options['force']: + query = query.filter(key_sent = False) + if len(args): + query = query.filter(email__in = args) + + for submission in query.all(): + assert len(submission.key) == 30 or (settings.DEBUG and submission.key == DEBUG_KEY) + + try: + self.send_key(submission) + except: + failed += 1 + self.stdout.write('failed sending to: ' + submission.email) + else: + submission.key_sent = True + submission.save() + sent += 1 + self.stdout.write('key sent to: ' + submission.email) + + self.stdout.write('sent: ' + str(sent)) + + def send_key(self, submission): + self.stdout.write('>>> sending to ' + submission.email) \ No newline at end of file diff --git a/wtem/migrations/0002_auto__add_field_submission_key_sent.py b/wtem/migrations/0002_auto__add_field_submission_key_sent.py new file mode 100644 index 0000000..825da07 --- /dev/null +++ b/wtem/migrations/0002_auto__add_field_submission_key_sent.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'Submission.key_sent' + db.add_column(u'wtem_submission', 'key_sent', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Submission.key_sent' + db.delete_column(u'wtem_submission', 'key_sent') + + + models = { + u'contact.contact': { + 'Meta': {'ordering': "('-created_at',)", 'object_name': 'Contact'}, + 'body': ('jsonfield.fields.JSONField', [], {'default': '{}'}), + 'contact': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'form_tag': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}) + }, + u'wtem.attachment': { + 'Meta': {'object_name': 'Attachment'}, + 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'submission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['wtem.Submission']"}) + }, + u'wtem.submission': { + 'Meta': {'object_name': 'Submission'}, + 'answers': ('django.db.models.fields.CharField', [], {'max_length': '65536', 'null': 'True', 'blank': 'True'}), + 'contact': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contact.Contact']", 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '100'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'key_sent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + } + } + + complete_apps = ['wtem'] \ No newline at end of file diff --git a/wtem/models.py b/wtem/models.py index 30539b2..75fa0ba 100644 --- a/wtem/models.py +++ b/wtem/models.py @@ -15,6 +15,7 @@ class Submission(models.Model): last_name = models.CharField(max_length = 100) email = models.EmailField(max_length = 100, unique = True) answers = models.CharField(max_length = 65536, null = True, blank = True) + key_sent = models.BooleanField(default = False) @classmethod def generate_key(cls): -- 2.20.1 From a2990772dfc18c810d16561ce4abbcaabc9f3637 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Tue, 5 Nov 2013 14:23:53 +0100 Subject: [PATCH 03/16] Sending emails with contest keys --- wtem/management/commands/wtem_send_keys.py | 18 +++++++++++++++--- wtem/templates/wtem/email_key.txt | 3 +++ 2 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 wtem/templates/wtem/email_key.txt diff --git a/wtem/management/commands/wtem_send_keys.py b/wtem/management/commands/wtem_send_keys.py index 82e7469..cff7bf3 100644 --- a/wtem/management/commands/wtem_send_keys.py +++ b/wtem/management/commands/wtem_send_keys.py @@ -1,7 +1,12 @@ +# -*- coding: utf-8 -*- + +import sys from optparse import make_option from django.core.management.base import BaseCommand, CommandError from django.conf import settings +from django.core.mail import send_mail +from django.template.loader import render_to_string from wtem.models import Submission, DEBUG_KEY @@ -44,9 +49,9 @@ class Command(BaseCommand): try: self.send_key(submission) - except: + except Exception as e: failed += 1 - self.stdout.write('failed sending to: ' + submission.email) + self.stdout.write('failed sending to: ' + submission.email + ' - ' + str(e)) else: submission.key_sent = True submission.save() @@ -56,4 +61,11 @@ class Command(BaseCommand): self.stdout.write('sent: ' + str(sent)) def send_key(self, submission): - self.stdout.write('>>> sending to ' + submission.email) \ No newline at end of file + self.stdout.write('>>> sending to ' + submission.email) + send_mail( + "WTEM - Twój link do zadań", + render_to_string('wtem/email_key.txt', dict(submission = submission)), + getattr(settings, 'WTEM_CONTACT_EMAIL', 'no-reply@edukacjamedialna.edu.pl'), + [submission.email], + fail_silently=False + ) \ No newline at end of file diff --git a/wtem/templates/wtem/email_key.txt b/wtem/templates/wtem/email_key.txt new file mode 100644 index 0000000..865b0be --- /dev/null +++ b/wtem/templates/wtem/email_key.txt @@ -0,0 +1,3 @@ +Poniżej znajduje się wygenerowany specjalnie dla Ciebie link, pod którym będziesz mógł/mogła rozwiązać zadania pierwszego etapu Wielkiego Turnieju Edukacji Medialnej: + +http://edukacjamedialna.edu.pl{% url 'wtem_form' key=submission.key %} \ No newline at end of file -- 2.20.1 From 720b406bad055e68e416812153ef45b471457107 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Wed, 6 Nov 2013 10:19:40 +0100 Subject: [PATCH 04/16] Assign exercises to a user via admin --- wtem/admin.py | 4 + wtem/migrations/0003_auto__add_assignment.py | 97 ++++++++++++++++++++ wtem/models.py | 18 +++- 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 wtem/admin.py create mode 100644 wtem/migrations/0003_auto__add_assignment.py diff --git a/wtem/admin.py b/wtem/admin.py new file mode 100644 index 0000000..0d7cd14 --- /dev/null +++ b/wtem/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin +from .models import Assignment + +admin.site.register(Assignment) \ No newline at end of file diff --git a/wtem/migrations/0003_auto__add_assignment.py b/wtem/migrations/0003_auto__add_assignment.py new file mode 100644 index 0000000..94e6509 --- /dev/null +++ b/wtem/migrations/0003_auto__add_assignment.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'Assignment' + db.create_table(u'wtem_assignment', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('exercises', self.gf('jsonfield.fields.JSONField')(default={})), + )) + db.send_create_signal(u'wtem', ['Assignment']) + + + def backwards(self, orm): + # Deleting model 'Assignment' + db.delete_table(u'wtem_assignment') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contact.contact': { + 'Meta': {'ordering': "('-created_at',)", 'object_name': 'Contact'}, + 'body': ('jsonfield.fields.JSONField', [], {'default': '{}'}), + 'contact': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'form_tag': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'wtem.assignment': { + 'Meta': {'object_name': 'Assignment'}, + 'exercises': ('jsonfield.fields.JSONField', [], {'default': '{}'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + u'wtem.attachment': { + 'Meta': {'object_name': 'Attachment'}, + 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'submission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['wtem.Submission']"}) + }, + u'wtem.submission': { + 'Meta': {'object_name': 'Submission'}, + 'answers': ('django.db.models.fields.CharField', [], {'max_length': '65536', 'null': 'True', 'blank': 'True'}), + 'contact': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contact.Contact']", 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '100'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'key_sent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + } + } + + complete_apps = ['wtem'] \ No newline at end of file diff --git a/wtem/models.py b/wtem/models.py index 75fa0ba..90492bf 100644 --- a/wtem/models.py +++ b/wtem/models.py @@ -2,6 +2,10 @@ import random import string from django.db import models +from django.contrib.auth.models import User +from django.core.exceptions import ValidationError +from django.utils.translation import ugettext as _ +from jsonfield import JSONField from contact.models import Contact @@ -41,4 +45,16 @@ class Submission(models.Model): class Attachment(models.Model): submission = models.ForeignKey(Submission) name = models.CharField(max_length=100) - file = models.FileField(upload_to = 'wtem/attachment') \ No newline at end of file + file = models.FileField(upload_to = 'wtem/attachment') + + +class Assignment(models.Model): + user = models.ForeignKey(User) + exercises = JSONField() + + def clean(self): + if not isinstance(self.exercises, list): + raise ValidationError(_('Assigned exercises must be declared in a list format')) + for exercise in self.exercises: + if not isinstance(exercise, int) or exercise < 1: + raise ValidationError(_('Invalid exercise id: %s' % exercise)) -- 2.20.1 From 3fd04fa811ccc4be2c8f949d06faef9b0325a393 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Wed, 6 Nov 2013 10:53:32 +0100 Subject: [PATCH 05/16] Sending exercise ids when submitting the contest form --- wtem/static/wtem/wtem.js | 10 +++++++--- wtem/templates/wtem/exercises/edumed_prawdafalsz.html | 2 +- .../templates/wtem/exercises/edumed_przyporzadkuj.html | 2 +- wtem/templates/wtem/exercises/edumed_uporzadkuj.html | 2 +- wtem/templates/wtem/exercises/edumed_wybor.html | 2 +- wtem/templates/wtem/exercises/file_upload.html | 2 +- wtem/templates/wtem/exercises/open.html | 2 +- 7 files changed, 13 insertions(+), 9 deletions(-) diff --git a/wtem/static/wtem/wtem.js b/wtem/static/wtem/wtem.js index 3f9bfad..5056b73 100644 --- a/wtem/static/wtem/wtem.js +++ b/wtem/static/wtem/wtem.js @@ -4,7 +4,7 @@ $(function() { $('#submit_answers').click(function(e) { //e.preventDefault(); - to_submit = []; + to_submit = {}; $('.exercise-wtem').each(function() { var el = $(this); @@ -21,16 +21,20 @@ $(function() { $('input[name=answers]').val(JSON.stringify(to_submit)); }); + var push_answer = function(el, answer) { + to_submit[el.attr('data-id')] = answer + }; + var handlers = { edumed: function(el) { var exercise = el.data('exercise'); if(exercise.get_answers) { - to_submit.push(exercise.get_answers()[0]); + push_answer(el, exercise.get_answers()[0]); } }, open: function(el) { - to_submit.push(el.find('textarea').val()); + push_answer(el, el.find('textarea').val()); } } diff --git a/wtem/templates/wtem/exercises/edumed_prawdafalsz.html b/wtem/templates/wtem/exercises/edumed_prawdafalsz.html index b5b7c3f..9ea5a5a 100644 --- a/wtem/templates/wtem/exercises/edumed_prawdafalsz.html +++ b/wtem/templates/wtem/exercises/edumed_prawdafalsz.html @@ -1,4 +1,4 @@ -
+

Zadanie {{no}}

diff --git a/wtem/templates/wtem/exercises/edumed_przyporzadkuj.html b/wtem/templates/wtem/exercises/edumed_przyporzadkuj.html index b5a1a3d..3fb9517 100644 --- a/wtem/templates/wtem/exercises/edumed_przyporzadkuj.html +++ b/wtem/templates/wtem/exercises/edumed_przyporzadkuj.html @@ -1,4 +1,4 @@ -
+

Zadanie {{no}}

diff --git a/wtem/templates/wtem/exercises/edumed_uporzadkuj.html b/wtem/templates/wtem/exercises/edumed_uporzadkuj.html index 082ae49..5da6053 100644 --- a/wtem/templates/wtem/exercises/edumed_uporzadkuj.html +++ b/wtem/templates/wtem/exercises/edumed_uporzadkuj.html @@ -1,4 +1,4 @@ -
+

Zadanie {{no}}

diff --git a/wtem/templates/wtem/exercises/edumed_wybor.html b/wtem/templates/wtem/exercises/edumed_wybor.html index 3fdb80a..031c718 100644 --- a/wtem/templates/wtem/exercises/edumed_wybor.html +++ b/wtem/templates/wtem/exercises/edumed_wybor.html @@ -1,4 +1,4 @@ -
+

Zadanie {{no}}

diff --git a/wtem/templates/wtem/exercises/file_upload.html b/wtem/templates/wtem/exercises/file_upload.html index df6f64b..e74e373 100644 --- a/wtem/templates/wtem/exercises/file_upload.html +++ b/wtem/templates/wtem/exercises/file_upload.html @@ -1,4 +1,4 @@ -
+

Zadanie {{no}}

diff --git a/wtem/templates/wtem/exercises/open.html b/wtem/templates/wtem/exercises/open.html index dbb3f53..4d2c782 100644 --- a/wtem/templates/wtem/exercises/open.html +++ b/wtem/templates/wtem/exercises/open.html @@ -1,4 +1,4 @@ -
+

Zadanie {{no}}

-- 2.20.1 From a5255a7dad7389d26a90a72072e8c39cfe5e469e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Wed, 6 Nov 2013 10:59:17 +0100 Subject: [PATCH 06/16] Only one assignment record per user --- .../0004_auto__add_unique_assignment_user.py | 92 +++++++++++++++++++ wtem/models.py | 2 +- 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 wtem/migrations/0004_auto__add_unique_assignment_user.py diff --git a/wtem/migrations/0004_auto__add_unique_assignment_user.py b/wtem/migrations/0004_auto__add_unique_assignment_user.py new file mode 100644 index 0000000..7730b9d --- /dev/null +++ b/wtem/migrations/0004_auto__add_unique_assignment_user.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding unique constraint on 'Assignment', fields ['user'] + db.create_unique(u'wtem_assignment', ['user_id']) + + + def backwards(self, orm): + # Removing unique constraint on 'Assignment', fields ['user'] + db.delete_unique(u'wtem_assignment', ['user_id']) + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contact.contact': { + 'Meta': {'ordering': "('-created_at',)", 'object_name': 'Contact'}, + 'body': ('jsonfield.fields.JSONField', [], {'default': '{}'}), + 'contact': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'form_tag': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'wtem.assignment': { + 'Meta': {'object_name': 'Assignment'}, + 'exercises': ('jsonfield.fields.JSONField', [], {'default': '{}'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + }, + u'wtem.attachment': { + 'Meta': {'object_name': 'Attachment'}, + 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'submission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['wtem.Submission']"}) + }, + u'wtem.submission': { + 'Meta': {'object_name': 'Submission'}, + 'answers': ('django.db.models.fields.CharField', [], {'max_length': '65536', 'null': 'True', 'blank': 'True'}), + 'contact': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contact.Contact']", 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '100'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'key_sent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + } + } + + complete_apps = ['wtem'] \ No newline at end of file diff --git a/wtem/models.py b/wtem/models.py index 90492bf..9e67ad8 100644 --- a/wtem/models.py +++ b/wtem/models.py @@ -49,7 +49,7 @@ class Attachment(models.Model): class Assignment(models.Model): - user = models.ForeignKey(User) + user = models.ForeignKey(User, unique = True) exercises = JSONField() def clean(self): -- 2.20.1 From 3998079d64b706303237dd7ededaab02ab42708c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Wed, 6 Nov 2013 10:59:58 +0100 Subject: [PATCH 07/16] Assignment string representation for admin --- wtem/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wtem/models.py b/wtem/models.py index 9e67ad8..877190b 100644 --- a/wtem/models.py +++ b/wtem/models.py @@ -58,3 +58,6 @@ class Assignment(models.Model): for exercise in self.exercises: if not isinstance(exercise, int) or exercise < 1: raise ValidationError(_('Invalid exercise id: %s' % exercise)) + + def __unicode__(self): + return self.user.username + ': ' + ','.join(map(str,self.exercises)) \ No newline at end of file -- 2.20.1 From ca5ba2a8976e5401291150a0c3fbc9b1a3fb5f95 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Wed, 6 Nov 2013 12:36:13 +0100 Subject: [PATCH 08/16] Submission string representation in admin --- wtem/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wtem/models.py b/wtem/models.py index 877190b..1e3eb4d 100644 --- a/wtem/models.py +++ b/wtem/models.py @@ -20,6 +20,8 @@ class Submission(models.Model): email = models.EmailField(max_length = 100, unique = True) answers = models.CharField(max_length = 65536, null = True, blank = True) key_sent = models.BooleanField(default = False) + def __unicode__(self): + return ', '.join((self.last_name, self.first_name, self.email)) @classmethod def generate_key(cls): -- 2.20.1 From 068d95bd6f8b28031a9e5236dbec460aad44ae7a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Wed, 6 Nov 2013 12:37:12 +0100 Subject: [PATCH 09/16] Mark field for Submission, setting marks api on Submission object --- .../0005_auto__add_field_submission_marks.py | 95 +++++++++++++++++++ wtem/models.py | 20 ++++ 2 files changed, 115 insertions(+) create mode 100644 wtem/migrations/0005_auto__add_field_submission_marks.py diff --git a/wtem/migrations/0005_auto__add_field_submission_marks.py b/wtem/migrations/0005_auto__add_field_submission_marks.py new file mode 100644 index 0000000..bbade28 --- /dev/null +++ b/wtem/migrations/0005_auto__add_field_submission_marks.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'Submission.marks' + db.add_column(u'wtem_submission', 'marks', + self.gf('jsonfield.fields.JSONField')(default={}), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Submission.marks' + db.delete_column(u'wtem_submission', 'marks') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contact.contact': { + 'Meta': {'ordering': "('-created_at',)", 'object_name': 'Contact'}, + 'body': ('jsonfield.fields.JSONField', [], {'default': '{}'}), + 'contact': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'form_tag': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'wtem.assignment': { + 'Meta': {'object_name': 'Assignment'}, + 'exercises': ('jsonfield.fields.JSONField', [], {'default': '{}'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + }, + u'wtem.attachment': { + 'Meta': {'object_name': 'Attachment'}, + 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'submission': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['wtem.Submission']"}) + }, + u'wtem.submission': { + 'Meta': {'object_name': 'Submission'}, + 'answers': ('django.db.models.fields.CharField', [], {'max_length': '65536', 'null': 'True', 'blank': 'True'}), + 'contact': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contact.Contact']", 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '100'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'key_sent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'marks': ('jsonfield.fields.JSONField', [], {'default': '{}'}) + } + } + + complete_apps = ['wtem'] \ No newline at end of file diff --git a/wtem/models.py b/wtem/models.py index 1e3eb4d..4c91392 100644 --- a/wtem/models.py +++ b/wtem/models.py @@ -20,6 +20,8 @@ class Submission(models.Model): email = models.EmailField(max_length = 100, unique = True) answers = models.CharField(max_length = 65536, null = True, blank = True) key_sent = models.BooleanField(default = False) + marks = JSONField() + def __unicode__(self): return ', '.join((self.last_name, self.first_name, self.email)) @@ -43,6 +45,24 @@ class Submission(models.Model): submission.save() return submission + def get_mark(self, user_id, exercise_id): + mark = None + user_id = str(user_id) + exercise_id = str(exercise_id) + if self.marks and user_id in self.marks: + mark = self.marks[user_id].get(exercise_id, None) + return mark + + def set_mark(self, user_id, exercise_id, mark): + user_id = str(user_id) + exercise_id = str(exercise_id) + if not self.marks: + self.marks = dict() + + self.marks.setdefault(user_id, {})[exercise_id] = mark + if mark == 'None': + del self.marks[user_id][exercise_id] + class Attachment(models.Model): submission = models.ForeignKey(Submission) -- 2.20.1 From cc7808417c18e06b6d8c7b68f2b045632103fa08 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Wed, 6 Nov 2013 12:38:41 +0100 Subject: [PATCH 10/16] Marking open questions via admin form --- wtem/admin.py | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/wtem/admin.py b/wtem/admin.py index 0d7cd14..f4ad1b0 100644 --- a/wtem/admin.py +++ b/wtem/admin.py @@ -1,4 +1,72 @@ +# -*- coding: utf-8 -*- + +import os + from django.contrib import admin -from .models import Assignment +from django import forms +from django.utils import simplejson + +from .models import Submission, Assignment + + +f = file(os.path.dirname(__file__) + '/fixtures/exercises.json') +exercises = simplejson.loads(f.read()) +f.close() + +def get_user_exercises(user): + assignment = Assignment.objects.get(user = user) + return [e for e in exercises if e['id'] in assignment.exercises] + + +readonly_fields = ('contact', 'first_name', 'last_name', 'email', 'key', 'key_sent') + + +class SubmissionFormBase(forms.ModelForm): + class Meta: + model = Submission + exclude = ('answers', 'marks') + readonly_fields + + +def get_form(request, submission): + fields = dict() + if submission.answers: + answers = simplejson.loads(submission.answers) + user_exercises = get_user_exercises(request.user) + for exercise in exercises: + if exercise not in user_exercises: + continue + if exercise['type'] == 'open': + answer_field_name = 'exercise_%s' % exercise['id'] + mark_field_name = 'markof_%s_by_%s' % (exercise['id'], request.user.id) + fields[answer_field_name] = forms.CharField( + widget = forms.Textarea(attrs={'readonly':True}), + initial = answers[str(exercise['id'])], + label = 'Rozwiązanie zadania %s' % exercise['id'] + ) + + fields[mark_field_name] = forms.ChoiceField( + choices = [(None, '-')] + [(i,i) for i in range(exercise['max_points']+1)], + initial = submission.get_mark(user_id = request.user.id, exercise_id = exercise['id']), + label = u'Twoja ocena zadania %s' % exercise['id'] + ) + return type('SubmissionForm', (SubmissionFormBase,), fields) + + +class SubmissionAdmin(admin.ModelAdmin): + readonly_fields = readonly_fields + + def get_form(self, request, obj, **kwargs): + return get_form(request, obj) + + def save_model(self, request, submission, form, change): + for name, value in form.cleaned_data.items(): + if name.startswith('markof_'): + parts = name.split('_') + exercise_id = parts[1] + user_id = parts[3] + submission.set_mark(user_id = user_id, exercise_id = exercise_id, mark = value) + submission.save() + +admin.site.register(Submission, SubmissionAdmin) admin.site.register(Assignment) \ No newline at end of file -- 2.20.1 From 60b7cd6ee28fed9a51e5e58d7962fc5c8c4ced7f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Wed, 6 Nov 2013 12:56:20 +0100 Subject: [PATCH 11/16] Link to contact form from submission edit view --- wtem/admin.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/wtem/admin.py b/wtem/admin.py index f4ad1b0..672666b 100644 --- a/wtem/admin.py +++ b/wtem/admin.py @@ -5,6 +5,7 @@ import os from django.contrib import admin from django import forms from django.utils import simplejson +from django.core.urlresolvers import reverse from .models import Submission, Assignment @@ -18,13 +19,13 @@ def get_user_exercises(user): return [e for e in exercises if e['id'] in assignment.exercises] -readonly_fields = ('contact', 'first_name', 'last_name', 'email', 'key', 'key_sent') +readonly_fields = ('submitted_by', 'first_name', 'last_name', 'email', 'key', 'key_sent') class SubmissionFormBase(forms.ModelForm): class Meta: model = Submission - exclude = ('answers', 'marks') + readonly_fields + exclude = ('answers', 'marks', 'contact') + readonly_fields def get_form(request, submission): @@ -58,6 +59,16 @@ class SubmissionAdmin(admin.ModelAdmin): def get_form(self, request, obj, **kwargs): return get_form(request, obj) + def submitted_by(self, instance): + if instance.contact: + return '%s' % ( + reverse('admin:contact_contact_change', args = [instance.contact.id]), + instance.contact.contact + ) + return '-' + submitted_by.allow_tags = True + submitted_by.short_description = "Zgłoszony/a przez" + def save_model(self, request, submission, form, change): for name, value in form.cleaned_data.items(): if name.startswith('markof_'): -- 2.20.1 From b6b567337c2dcdf8fb959b36fbb589d8ac9ff9eb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Wed, 6 Nov 2013 17:01:33 +0100 Subject: [PATCH 12/16] Showing exercices left to mark in admin list view of Submissions --- edumed/settings.d/40-middleware.py | 3 ++- wtem/admin.py | 8 ++++++++ wtem/middleware.py | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 wtem/middleware.py diff --git a/edumed/settings.d/40-middleware.py b/edumed/settings.d/40-middleware.py index 998b707..4dcd91d 100644 --- a/edumed/settings.d/40-middleware.py +++ b/edumed/settings.d/40-middleware.py @@ -24,5 +24,6 @@ MIDDLEWARE_CLASSES = tuple(x for x in ( 'django.middleware.cache.FetchFromCacheMiddleware', 'fnpdjango.middleware.SetRemoteAddrFromXRealIP', 'pybb.middleware.PybbMiddleware', - 'forum.middleware.ForumMiddleware' + 'forum.middleware.ForumMiddleware', + 'wtem.middleware.ThreadLocalMiddleware' ) if x is not None) diff --git a/wtem/admin.py b/wtem/admin.py index 672666b..037ed37 100644 --- a/wtem/admin.py +++ b/wtem/admin.py @@ -8,6 +8,7 @@ from django.utils import simplejson from django.core.urlresolvers import reverse from .models import Submission, Assignment +from .middleware import get_current_request f = file(os.path.dirname(__file__) + '/fixtures/exercises.json') @@ -54,6 +55,7 @@ def get_form(request, submission): class SubmissionAdmin(admin.ModelAdmin): + list_display = ('__unicode__', 'todo',) readonly_fields = readonly_fields def get_form(self, request, obj, **kwargs): @@ -69,6 +71,12 @@ class SubmissionAdmin(admin.ModelAdmin): submitted_by.allow_tags = True submitted_by.short_description = "Zgłoszony/a przez" + def todo(self, submission): + user = get_current_request().user + user_exercises = get_user_exercises(user) + user_marks = submission.marks.get(str(user.id), {}) + return ','.join([str(e['id']) for e in user_exercises if str(e['id']) not in user_marks.keys()]) + def save_model(self, request, submission, form, change): for name, value in form.cleaned_data.items(): if name.startswith('markof_'): diff --git a/wtem/middleware.py b/wtem/middleware.py new file mode 100644 index 0000000..d9bd308 --- /dev/null +++ b/wtem/middleware.py @@ -0,0 +1,15 @@ +try: + from threading import local +except ImportError: + from django.utils._threading_local import local + + +_thread_locals = local() + +def get_current_request(): + return getattr(_thread_locals, 'request', None) + + +class ThreadLocalMiddleware: + def process_request(self, request): + _thread_locals.request = request \ No newline at end of file -- 2.20.1 From 8180beca104f60812210f1ff96db8aa425224d65 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksander=20=C5=81ukasz?= Date: Thu, 7 Nov 2013 11:05:05 +0100 Subject: [PATCH 13/16] Support open part in questions of type 'wybor' --- wtem/admin.py | 26 +++++++++++++++++-- wtem/static/wtem/wtem.js | 12 +++++++-- .../wtem/exercises/edumed_wybor.html | 13 ++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/wtem/admin.py b/wtem/admin.py index 037ed37..99877fd 100644 --- a/wtem/admin.py +++ b/wtem/admin.py @@ -29,6 +29,28 @@ class SubmissionFormBase(forms.ModelForm): exclude = ('answers', 'marks', 'contact') + readonly_fields +def get_open_answer(answers, exercise): + def get_option(options, id): + for option in options: + if option['id'] == int(id): + return option + + exercise_id = str(exercise['id']) + answer = answers[exercise_id] + if exercise['type'] == 'open': + toret = answer + if exercise['type'] == 'edumed_wybor': + ok = set(map(str, exercise['answer'])) == set(map(str,answer['closed_part'])) + toret = u'Czesc testowa [%s]:\n' % ('poprawna' if ok else 'niepoprawna') + for selected in answer['closed_part']: + option = get_option(exercise['options'], selected) + toret += '%s: %s\n' % (selected, option['text']) + toret += u'\nCzesc otwarta (%s):\n\n' % ' '.join(exercise['open_part']) + toret += answer['open_part'] + + return toret + + def get_form(request, submission): fields = dict() if submission.answers: @@ -37,12 +59,12 @@ def get_form(request, submission): for exercise in exercises: if exercise not in user_exercises: continue - if exercise['type'] == 'open': + if exercise['type'] == 'open' or exercise.get('open_part', None): answer_field_name = 'exercise_%s' % exercise['id'] mark_field_name = 'markof_%s_by_%s' % (exercise['id'], request.user.id) fields[answer_field_name] = forms.CharField( widget = forms.Textarea(attrs={'readonly':True}), - initial = answers[str(exercise['id'])], + initial = get_open_answer(answers, exercise), label = 'Rozwiązanie zadania %s' % exercise['id'] ) diff --git a/wtem/static/wtem/wtem.js b/wtem/static/wtem/wtem.js index 5056b73..5253e03 100644 --- a/wtem/static/wtem/wtem.js +++ b/wtem/static/wtem/wtem.js @@ -27,10 +27,18 @@ $(function() { var handlers = { edumed: function(el) { - var exercise = el.data('exercise'); + var exercise = el.data('exercise'), + to_push = {}, + open_part; if(exercise.get_answers) { - push_answer(el, exercise.get_answers()[0]); + to_push.closed_part = exercise.get_answers()[0]; } + open_part = el.find('.open_part') + if(open_part.length) { + to_push.open_part = open_part.find('textarea').val(); + } + + push_answer(el, to_push); }, open: function(el) { diff --git a/wtem/templates/wtem/exercises/edumed_wybor.html b/wtem/templates/wtem/exercises/edumed_wybor.html index 031c718..d94995d 100644 --- a/wtem/templates/wtem/exercises/edumed_wybor.html +++ b/wtem/templates/wtem/exercises/edumed_wybor.html @@ -21,4 +21,17 @@
+ {% if exercise.open_part %} +
+
+ {% for para in exercise.open_part %} +

+ {{para}} +

+ {% endfor %} +
+ +
+ {% endif %} +
\ No newline at end of file -- 2.20.1