summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.txt36
-rw-r--r--README_production.rst30
-rw-r--r--online_test/__init__.py2
-rw-r--r--setup.py2
-rw-r--r--yaksh/migrations/0009_auto_20180113_1124.py149
-rw-r--r--yaksh/migrations/0010_auto_20180226_1324.py34
-rw-r--r--yaksh/migrations/0011_release_0_8_0.py68
7 files changed, 282 insertions, 39 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index d3364e0..01d80dd 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,8 +1,29 @@
-=== 0.8.0 ===
+=== 0.8.0 (23-03-2018) ===
+
+* Refactored the add_group command to allow creation of moderator group and add users to moderator group and renamed to create_moderator.
+* Deprecated multiple management commands: dump_user_data, load_exam, load_question_xml, results2csv.
+* Changed the unit of time_between_attempts field within Quiz model from days to hours.
+* Fixed assignment upload feature.
+* Error output is displayed using Ajax instead of reloading the entire page.
+* Added Mathjax to the repository.
+* Added Yaksh logo on the website.
+* Changed travis build distribution from precise (Ubuntu 12.04 LTS) to trusty (Ubuntu 14.04 LTS).
+* Fixed a bug that allowed creation of multiple answerpapers.
+* Added MCQ/MCC Shuffle testcases feature for question paper.
+* Added Arrange in Correct Order question type feature.
+* Added a feature to create a course with lessons, quizzes and exercises.
+* Fixed a bug where a oauth users' email is not verified.
+* Added a feature to show per student course completion status.
+* Fixed a bug where a moderator could change question paper of other moderator.
+* Fixed a bug where a teacher could not access question paper for a course.
+* Fixed a bug where a teacher could become the course creator while editing a course.
+* Updated clone course feature to create copy of course, lessons, quizzes and learning modules.
+* Changed Student dashboard to show the days remaining for a course to start.
+* Changed UI for student and moderator dashboard.
+* Updated documentation
+* Added a feature where a moderator can create exercises.
+* Added grading feature which allows a moderator to create a grading system and apply it for a course.
-* Added a management command to add users to moderator group
-* Renamed add_group management command to create_mod_group
-* Deprecated multiple management commands: dump_user_data, load_exam, load_question_xml, results2csv
=== 0.7.0 (15-11-2017) ===
@@ -24,8 +45,8 @@
* Added a Datetimepicker to edit course Page.
* Added invoke script for quickstart and docker deployment.
* Added the facility to send mails to all students enrolled in a course.
-* Fixed a bug that would cause issue during email activation key check
-* Added comprehensive tests for views.py
+* Fixed a bug that would cause issue during email activation key check.
+* Added comprehensive tests for views.py.
* Fixed a bug that allowed moderators to set cyclic quiz prerequisites in a course.
* Added a feature that redirects to edit profile page if user has no profile.
* Fixed a bug that would allow enrolled students to attempt quizzes for deactivated courses.
@@ -48,7 +69,7 @@
=== 0.6.0 (11-05-2017) ===
* Added a course code field that can be used to search a course.
-* Updated the documentation to describe the course code feature
+* Updated the documentation to describe the course code feature.
* Fixed a bug that prevented redirection based on 'next' parameter after login.
* Fixed a bug that littered residual system processes created by code evaluators.
* Added the facility to allow moderators to see and download uploaded assignments.
@@ -71,4 +92,3 @@
* Fixed a bug that displayed the elements of stdout testcase output as unicode.
* Fixed a bug that prevented users from logging in using Google OAuth.
* Added coverage reports to travis.yml.
-
diff --git a/README_production.rst b/README_production.rst
index a9bd55b..13fb8f9 100644
--- a/README_production.rst
+++ b/README_production.rst
@@ -222,33 +222,3 @@ Follow these steps to deploy and run the Django Server, MySQL instance and Code
invoke remove
12. You can use ``invoke --list`` to get a list of all the available commands
-
-
-.. _add-commands:
-
-######################################
-Additional commands available
-######################################
-
-We provide several convenient commands for you to use:
-
-- load\_exam : load questions and a quiz from a python file. See
- docs/sample\_questions.py
-
-- load\_questions\_xml : load questions from XML file, see
- docs/sample\_questions.xml use of this is deprecated in favor of
- load\_exam.
-
-- results2csv : Dump the quiz results into a CSV file for further
- processing.
-
-- dump\_user\_data : Dump out relevalt user data for either all users
- or specified users.
-
-For more information on these do this:
-
-::
-
- $ python manage.py help [command]
-
-where [command] is one of the above.
diff --git a/online_test/__init__.py b/online_test/__init__.py
index a71c5c7..32a90a3 100644
--- a/online_test/__init__.py
+++ b/online_test/__init__.py
@@ -1 +1 @@
-__version__ = '0.7.0'
+__version__ = '0.8.0'
diff --git a/setup.py b/setup.py
index 9fe5be5..83a5e42 100644
--- a/setup.py
+++ b/setup.py
@@ -6,6 +6,7 @@ README = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read()
# allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
+
def get_version():
import os
data = {}
@@ -24,6 +25,7 @@ install_requires = [
'invoke==0.21.0',
'six',
'requests',
+ 'markdown==2.6.9',
]
setup(
diff --git a/yaksh/migrations/0009_auto_20180113_1124.py b/yaksh/migrations/0009_auto_20180113_1124.py
new file mode 100644
index 0000000..dbbcb30
--- /dev/null
+++ b/yaksh/migrations/0009_auto_20180113_1124.py
@@ -0,0 +1,149 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.5 on 2018-01-13 11:24
+from __future__ import unicode_literals
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+import yaksh.models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('yaksh', '0008_release_0_7_0'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='CourseStatus',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('grade', models.CharField(blank=True, max_length=255, null=True)),
+ ('total_marks', models.FloatField(default=0.0)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='LearningModule',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=255)),
+ ('description', models.TextField(blank=True, default=None, null=True)),
+ ('order', models.IntegerField(default=0)),
+ ('check_prerequisite', models.BooleanField(default=True)),
+ ('html_data', models.TextField(blank=True, null=True)),
+ ('is_trial', models.BooleanField(default=False)),
+ ('creator', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='module_creator', to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='LearningUnit',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('order', models.IntegerField()),
+ ('type', models.CharField(max_length=16)),
+ ('check_prerequisite', models.BooleanField(default=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Lesson',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=255)),
+ ('description', models.TextField()),
+ ('html_data', models.TextField(blank=True, null=True)),
+ ('creator', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='LessonFile',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('file', models.FileField(upload_to=yaksh.models.get_file_dir)),
+ ('lesson', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lesson', to='yaksh.Lesson')),
+ ],
+ ),
+ migrations.RemoveField(
+ model_name='quiz',
+ name='course',
+ ),
+ migrations.RemoveField(
+ model_name='quiz',
+ name='language',
+ ),
+ migrations.RemoveField(
+ model_name='quiz',
+ name='prerequisite',
+ ),
+ migrations.AddField(
+ model_name='answerpaper',
+ name='course',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='yaksh.Course'),
+ ),
+ migrations.AddField(
+ model_name='question',
+ name='min_time',
+ field=models.IntegerField(default=0, verbose_name='time in minutes'),
+ ),
+ migrations.AddField(
+ model_name='question',
+ name='solution',
+ field=models.TextField(blank=True),
+ ),
+ migrations.AddField(
+ model_name='quiz',
+ name='creator',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AddField(
+ model_name='quiz',
+ name='is_exercise',
+ field=models.BooleanField(default=False),
+ ),
+ migrations.AddField(
+ model_name='quiz',
+ name='weightage',
+ field=models.FloatField(default=1.0),
+ ),
+ migrations.AddField(
+ model_name='learningunit',
+ name='lesson',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='yaksh.Lesson'),
+ ),
+ migrations.AddField(
+ model_name='learningunit',
+ name='quiz',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='yaksh.Quiz'),
+ ),
+ migrations.AddField(
+ model_name='learningmodule',
+ name='learning_unit',
+ field=models.ManyToManyField(related_name='learning_unit', to='yaksh.LearningUnit'),
+ ),
+ migrations.AddField(
+ model_name='coursestatus',
+ name='completed_units',
+ field=models.ManyToManyField(related_name='completed_units', to='yaksh.LearningUnit'),
+ ),
+ migrations.AddField(
+ model_name='coursestatus',
+ name='course',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='yaksh.Course'),
+ ),
+ migrations.AddField(
+ model_name='coursestatus',
+ name='current_unit',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='current_unit', to='yaksh.LearningUnit'),
+ ),
+ migrations.AddField(
+ model_name='coursestatus',
+ name='user',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AddField(
+ model_name='course',
+ name='learning_module',
+ field=models.ManyToManyField(related_name='learning_module', to='yaksh.LearningModule'),
+ ),
+ ]
diff --git a/yaksh/migrations/0010_auto_20180226_1324.py b/yaksh/migrations/0010_auto_20180226_1324.py
new file mode 100644
index 0000000..b400da7
--- /dev/null
+++ b/yaksh/migrations/0010_auto_20180226_1324.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.5 on 2018-02-26 13:24
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('yaksh', '0009_auto_20180113_1124'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='learningmodule',
+ name='active',
+ field=models.BooleanField(default=True),
+ ),
+ migrations.AddField(
+ model_name='lesson',
+ name='active',
+ field=models.BooleanField(default=True),
+ ),
+ migrations.AlterField(
+ model_name='quiz',
+ name='time_between_attempts',
+ field=models.FloatField(verbose_name='Time Between Quiz Attempts in hours'),
+ ),
+ migrations.AlterUniqueTogether(
+ name='answerpaper',
+ unique_together=set([('user', 'question_paper', 'attempt_number', 'course')]),
+ ),
+ ]
diff --git a/yaksh/migrations/0011_release_0_8_0.py b/yaksh/migrations/0011_release_0_8_0.py
new file mode 100644
index 0000000..41a2abd
--- /dev/null
+++ b/yaksh/migrations/0011_release_0_8_0.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.5 on 2018-03-23 10:46
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('grades', 'default_grading_system'),
+ ('yaksh', '0010_auto_20180226_1324'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='ArrangeTestCase',
+ fields=[
+ ('testcase_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='yaksh.TestCase')),
+ ('options', models.TextField(default=None)),
+ ],
+ bases=('yaksh.testcase',),
+ ),
+ migrations.CreateModel(
+ name='TestCaseOrder',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('order', models.TextField()),
+ ('answer_paper', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answer_paper', to='yaksh.AnswerPaper')),
+ ],
+ ),
+ migrations.RenameField(
+ model_name='coursestatus',
+ old_name='total_marks',
+ new_name='percentage',
+ ),
+ migrations.AddField(
+ model_name='course',
+ name='grading_system',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='grades.GradingSystem'),
+ ),
+ migrations.AddField(
+ model_name='questionpaper',
+ name='shuffle_testcases',
+ field=models.BooleanField(default=True, verbose_name='Shuffle testcase for each user'),
+ ),
+ migrations.AlterField(
+ model_name='question',
+ name='type',
+ field=models.CharField(choices=[('mcq', 'Single Correct Choice'), ('mcc', 'Multiple Correct Choices'), ('code', 'Code'), ('upload', 'Assignment Upload'), ('integer', 'Answer in Integer'), ('string', 'Answer in String'), ('float', 'Answer in Float'), ('arrange', 'Arrange in Correct Order')], max_length=24),
+ ),
+ migrations.AlterField(
+ model_name='quiz',
+ name='weightage',
+ field=models.FloatField(default=100, help_text='Will be considered as percentage'),
+ ),
+ migrations.AlterField(
+ model_name='testcase',
+ name='type',
+ field=models.CharField(choices=[('standardtestcase', 'Standard Testcase'), ('stdiobasedtestcase', 'StdIO Based Testcase'), ('mcqtestcase', 'MCQ Testcase'), ('hooktestcase', 'Hook Testcase'), ('integertestcase', 'Integer Testcase'), ('stringtestcase', 'String Testcase'), ('floattestcase', 'Float Testcase'), ('arrangetestcase', 'Arrange Testcase')], max_length=24, null=True),
+ ),
+ migrations.AddField(
+ model_name='testcaseorder',
+ name='question',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='yaksh.Question'),
+ ),
+ ]