diff --git a/tin/apps/assignments/forms.py b/tin/apps/assignments/forms.py index 66a7ec62..3b91a946 100644 --- a/tin/apps/assignments/forms.py +++ b/tin/apps/assignments/forms.py @@ -69,6 +69,7 @@ class Meta: "submission_limit_cooldown", "is_quiz", "quiz_action", + "quiz_autocomplete_enabled", ] labels = { "markdown": "Use markdown?", @@ -82,6 +83,7 @@ class Meta: "submission_limit_interval": "Rate limit interval (minutes)", "submission_limit_cooldown": "Rate limit cooldown period (minutes)", "is_quiz": "Is this a quiz?", + "quiz_autocomplete_enabled": "Enable code autocompletion?", } sections = ( { @@ -112,6 +114,7 @@ class Meta: "fields": ( "is_quiz", "quiz_action", + "quiz_autocomplete_enabled", ), "collapsed": False, }, @@ -149,9 +152,13 @@ class Meta: "submission_limit_cooldown": 'This sets the length of the "cooldown" period after a ' "student exceeds the rate limit for submissions.", "folder": "If blank, assignment will show on the main classroom page.", - "is_quiz": "This forces students to submit through a page that monitors their actions.", + "is_quiz": "This forces students to submit through a page that monitors their actions. The below options " + "have no effect if this is unset.", "quiz_action": "Tin will take the selected action if a student clicks off of the " "quiz page.", + "quiz_autocomplete_enabled": "This gives students basic code completion in the quiz editor, including " + "variable names, built-in functions, and keywords. It's recommended for quizzes that focus on code logic " + "and not syntax.", } widgets = {"description": forms.Textarea(attrs={"cols": 30, "rows": 4})} diff --git a/tin/apps/assignments/migrations/0031_assignment_quiz_autocomplete_enabled.py b/tin/apps/assignments/migrations/0031_assignment_quiz_autocomplete_enabled.py new file mode 100644 index 00000000..57ecb257 --- /dev/null +++ b/tin/apps/assignments/migrations/0031_assignment_quiz_autocomplete_enabled.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.13 on 2024-05-27 21:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("assignments", "0030_quizlogmessage_assignment_is_quiz_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="assignment", + name="quiz_autocomplete_enabled", + field=models.BooleanField(default=False), + ), + ] diff --git a/tin/apps/assignments/models.py b/tin/apps/assignments/models.py index b7bacdb8..93a37d17 100644 --- a/tin/apps/assignments/models.py +++ b/tin/apps/assignments/models.py @@ -128,6 +128,7 @@ class Assignment(models.Model): is_quiz = models.BooleanField(default=False) QUIZ_ACTIONS = (("0", "Log only"), ("1", "Color Change"), ("2", "Lock")) quiz_action = models.CharField(max_length=1, choices=QUIZ_ACTIONS, default="2") + quiz_autocomplete_enabled = models.BooleanField(default=False) objects = AssignmentQuerySet.as_manager() diff --git a/tin/templates/assignments/quiz.html b/tin/templates/assignments/quiz.html index 51f615f4..cff74289 100644 --- a/tin/templates/assignments/quiz.html +++ b/tin/templates/assignments/quiz.html @@ -12,6 +12,9 @@ + {% if latest_submission %} {% endif %} @@ -32,6 +35,12 @@ var mode = modelist.getModeForPath(filename).mode; editor.session.setMode(mode); + {% if assignment.quiz_autocomplete_enabled %} + editor.setOptions({ + enableLiveAutocompletion: true + }); + {% endif %} + editor.getSession().setValue(textarea.val()); editor.getSession().on("change", function () { textarea.val(editor.getSession().getValue());