diff options
-rw-r--r-- | yaksh/forms.py | 13 | ||||
-rw-r--r-- | yaksh/models.py | 4 | ||||
-rw-r--r-- | yaksh/static/yaksh/css/question_paper_creation.css | 12 | ||||
-rw-r--r-- | yaksh/static/yaksh/js/question_paper_creation.js | 218 | ||||
-rw-r--r-- | yaksh/templates/manage.html | 6 | ||||
-rw-r--r-- | yaksh/templates/yaksh/add_quiz.html | 2 | ||||
-rw-r--r-- | yaksh/templates/yaksh/ajax_questions.html | 31 | ||||
-rw-r--r-- | yaksh/templates/yaksh/courses.html | 25 | ||||
-rw-r--r-- | yaksh/templates/yaksh/design_questionpaper.html | 178 | ||||
-rw-r--r-- | yaksh/test_views.py | 4 | ||||
-rw-r--r-- | yaksh/urls.py | 8 | ||||
-rw-r--r-- | yaksh/views.py | 174 |
12 files changed, 260 insertions, 415 deletions
diff --git a/yaksh/forms.py b/yaksh/forms.py index a12ce9a..bc9b4c0 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -1,6 +1,6 @@ from django import forms -from yaksh.models import get_model_class, Profile, Quiz, Question, TestCase, Course, StandardTestCase, StdioBasedTestCase - +from yaksh.models import get_model_class, Profile, Quiz, Question, TestCase, Course,\ + QuestionPaper, StandardTestCase, StdioBasedTestCase from django.contrib.auth import authenticate from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType @@ -199,7 +199,7 @@ class QuestionFilterForm(forms.Form): super(QuestionFilterForm, self).__init__(*args, **kwargs) questions = Question.objects.filter(user_id=user.id) points_list = questions.values_list('points', flat=True).distinct() - points_options = [('select', 'Select Marks')] + points_options = [(None, 'Select Marks')] points_options.extend([(point, point) for point in points_list]) self.fields['marks'] = forms.FloatField(widget=forms.Select\ (choices=points_options)) @@ -215,6 +215,7 @@ class CourseForm(forms.ModelForm): model = Course fields = ['name', 'active', 'enrollment'] + class ProfileForm(forms.ModelForm): """ profile form for students and moderators """ @@ -236,3 +237,9 @@ class ProfileForm(forms.ModelForm): class UploadFileForm(forms.Form): file = forms.FileField() + + +class QuestionPaperForm(forms.ModelForm): + class Meta: + model = QuestionPaper + fields = ['shuffle_questions'] diff --git a/yaksh/models.py b/yaksh/models.py index 444df4a..f098cd2 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -604,10 +604,10 @@ class QuestionPaper(models.Model): random_questions = models.ManyToManyField("QuestionSet") # Option to shuffle questions, each time a new question paper is created. - shuffle_questions = models.BooleanField(default=False) + shuffle_questions = models.BooleanField(default=False, blank=False) # Total marks for the question paper. - total_marks = models.FloatField() + total_marks = models.FloatField(default=0.0, blank=True) objects = QuestionPaperManager() diff --git a/yaksh/static/yaksh/css/question_paper_creation.css b/yaksh/static/yaksh/css/question_paper_creation.css index c915320..588b65c 100644 --- a/yaksh/static/yaksh/css/question_paper_creation.css +++ b/yaksh/static/yaksh/css/question_paper_creation.css @@ -5,9 +5,6 @@ body { line-height: 18px; color: #404040; } -.clearfix { - clear: both; -} .tabs li { text-align: center; width: 33%; @@ -48,7 +45,7 @@ body { padding: 7px 0; border: 2px solid #f5f5f5; } -#selectors .span4 { +#selectors .col-md-6 { margin-left: 0; } #id_question_type { @@ -57,8 +54,8 @@ body { #id_marks { width: 100%; } -#fixed-questions .span7 > div, -#random-questions .span7 > div{ +#fixed-questions .col-md-6 > div, +#random-questions .col-md-6 > div{ background: #f5f5f5; height: 200px; border: 1px solid #333333; @@ -111,9 +108,6 @@ body { .red-alert { border: 2px solid red; } -#myModal .qcard .remove{ - display: none; -} .well{ padding: 5px; } diff --git a/yaksh/static/yaksh/js/question_paper_creation.js b/yaksh/static/yaksh/js/question_paper_creation.js index a144540..898e491 100644 --- a/yaksh/static/yaksh/js/question_paper_creation.js +++ b/yaksh/static/yaksh/js/question_paper_creation.js @@ -1,204 +1,33 @@ $(document).ready(function(){ - /* selectors for the 3 step tabs*/ - $fixed_tab = $("#fixed-tab"); - $random_tab = $("#random-tab"); - $finish_tab = $("#finish-tab"); - - $question_type = $("#id_question_type"); - $marks = $("#id_marks"); - - $total_marks = $("#total_marks"); + $question_type = $('#id_question_type'); + $qpaper_id = $('#qpaper_id'); + $marks = $('#id_marks'); + $show = $('#show'); /* ajax requsts on selectors change */ $question_type.change(function() { - $.ajax({ - url: "/exam/ajax/questionpaper/marks/", - type: "POST", - data: { - question_type: $question_type.val() - }, - dataType: "html", - success: function(output) { - $marks.html(output); - } - }); + this.form.submit(); }); $marks.change(function() { - var fixed_question_list = []; - var fixed_inputs = $("input[name=fixed]"); - var random_question_list = []; - var random_inputs = $("input[name=random]"); - for(var i = 0; i < fixed_inputs.length; i++){ - fixed_question_list.push($(fixed_inputs[i]).val()); - } - for(var i = 0; i < random_inputs.length; i++){ - random_question_list.push($(random_inputs[i]).val()); - } - $.ajax({ - url: "/exam/ajax/questionpaper/questions/", - type: "POST", - data: { - question_type: $question_type.val(), - marks: $marks.val(), - fixed_list: fixed_question_list, - random_list: random_question_list - }, - dataType: "html", - success: function(output) { - if($fixed_tab.hasClass("active")) { - var questions = $(output).filter("#questions").html(); - $("#fixed-available").html(questions); - } else if($random_tab.hasClass("active")) { - var questions = $(output).filter("#questions").html(); - var numbers = $(output).filter("#num").html(); - $("#random-available").html(questions); - $("#number-wrapper").html(numbers); - } - } - }); - }); - - /* adding fixed questions */ - $("#add-fixed").click(function(e) { - var count = 0; - var selected = []; - var html = ""; - var $element; - var total_marks = parseFloat($total_marks.text()); - var marks_per = parseFloat($marks.val()) - $("#fixed-available input:checkbox").each(function(index, element) { - if($(this).attr("checked")) { - qid = $(this).attr("data-qid"); - if(!$(this).hasClass("ignore")) { - selected.push(qid); - $element = $("<div class='qcard'></div>"); - html += "<li>" + $(this).next().html() + "</li>"; - count++; - } - } - }); - html = "<ul>" + html + "</ul>"; - selected = selected.join(","); - var $input = $("<input type='hidden'>"); - $input.attr({ - value: selected, - name: "fixed" - }); - $remove = $("<a href='#' class='remove' data-num="+count+" data-marks = "+marks_per +">×</div>"); - $element.html(count + " question(s) added").append(html).append($input).append($remove); - $("#fixed-added").prepend($element); - total_marks = total_marks + count * marks_per; - $total_marks.text(total_marks) - e.preventDefault(); - }); - - /* adding random questions */ - $("#add-random").click(function(e) { - $numbers = $("#numbers"); - random_number = $numbers.val() - if($numbers.val()) { - $numbers.removeClass("red-alert"); - var count = 0; - var selected = []; - var html = ""; - var $element; - var total_marks = parseFloat($total_marks.text()); - var marks_per = parseFloat($marks.val()) - $("#random-available input:checkbox").each(function(index, element) { - if($(this).attr("checked")) { - qid = $(this).attr("data-qid"); - if(!$(this).hasClass("ignore")) { - selected.push(qid); - $element = $("<div class='qcard'></div>"); - html += "<li>" + $(this).next().html() + "</li>"; - count++; - } - } - }); - html = "<ul>" + html + "</ul>"; - selected = selected.join(","); - var $input_random = $("<input type='hidden'>"); - $input_random.attr({ - value: selected, - name: "random" - }); - var $input_number = $("<input type='hidden'>"); - $input_number.attr({ - value: $numbers.val(), - name: "number" - }); - $remove = $("<a href='#' class='remove' data-num="+random_number+" data-marks = "+marks_per +">×</div>"); - $element.html(random_number + " question(s) will be selected from " + count + " question(s)").append(html).append($input_random).append($input_number).append($remove); - $("#random-added").prepend($element); - total_marks = total_marks + random_number * marks_per; - $total_marks.text(total_marks) - } else { - $numbers.addClass("red-alert"); - } - e.preventDefault(); - }); - - /* removing added questions */ - $(".qcard .remove").live("click", function(e) { - var marks_per = $(this).attr('data-marks'); - var num_question = $(this).attr('data-num'); - var sub_marks = marks_per*num_question; - var total_marks = parseFloat($total_marks.text()); - total_marks = total_marks - sub_marks; - $total_marks.text(total_marks); - - $(this).parent().slideUp("normal", function(){ $(this).remove(); }); - e.preventDefault(); + this.form.submit(); }); /* showing/hiding selectors on tab click */ $(".tabs li").click(function() { if($(this).attr("id") == "finish-tab") { $("#selectors").hide(); + $('#is_active').val("finish"); } else { - $question_type.val('select'); - $marks.val('select') - $("#selectors").show(); - } - }); - /* check all questions on checked*/ - $("#checkall").live("click", function(){ - if($(this).attr("checked")) { - if($("#fixed-tab").hasClass("active")) { - $("#fixed-available input:checkbox").each(function(index, element) { - $(this).attr('checked','checked'); - }); + if($(this).attr("id") == "fixed-tab") { + $('#is_active').val("fixed"); } - else { - $("#random-available input:checkbox").each(function(index, element) { - $(this).attr('checked','checked'); - }); + if($(this).attr("id") == "random-tab") { + $('#is_active').val("random"); } - } - else { - if($("#fixed-tab").hasClass("active")) { - $("#fixed-available input:checkbox").each(function(index, element) { - $(this).removeAttr('checked'); - }); - } - else { - $("#random-available input:checkbox").each(function(index, element) { - $(this).removeAttr('checked'); - }); - } - } - }); - - /* show preview on preview click */ - $("#preview").click(function(){ - questions = getQuestions() - if(questions.trim() == ""){ - $('#modal_body').html("No questions selected"); + $question_type.val('select'); + $marks.val('select') + $("#selectors").show(); } - else { - $('#modal_body').html(questions); - } - $("#myModal").modal('show'); }); /* tab change on next or previous button click */ @@ -217,21 +46,4 @@ $(document).ready(function(){ $("#random").click(); }); - /* Check at least one question is present before saving */ - $('#save').click(function(){ - questions = getQuestions(); - if(questions.trim() == ""){ - $("#modalSave").modal("show"); - } - else { - document.forms["frm"].submit(); - } - }); - - /* Fetch selected questions */ - function getQuestions(){ - var fixed_div = $("#fixed-added").html(); - var random_div = $("#random-added").html(); - return fixed_div+random_div; - } -}); //document +});//document diff --git a/yaksh/templates/manage.html b/yaksh/templates/manage.html index 63c0ea7..f4c524e 100644 --- a/yaksh/templates/manage.html +++ b/yaksh/templates/manage.html @@ -46,6 +46,12 @@ <div class="page-header"> <h3><center>{% block subtitle %}Welcome {{ user.first_name.title }} {{user.last_name.title}} !{% endblock %}</center></h3><br> </div> + <div class="row"> + <div class="col-md-12"> + {% block new_manage %} + {% endblock %} + </div> + </div> <div class=row> <div class=span14> {% block manage %} diff --git a/yaksh/templates/yaksh/add_quiz.html b/yaksh/templates/yaksh/add_quiz.html index 5a0bee4..1c73e12 100644 --- a/yaksh/templates/yaksh/add_quiz.html +++ b/yaksh/templates/yaksh/add_quiz.html @@ -20,7 +20,7 @@ </table> </center> - <center><button class="btn" type="submit" id="submit" name="questionpaper">Design Question Paper</button> + <center><button class="btn" type="submit" id="submit" name="questionpaper"> Save </button> <button class="btn" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/courses/");'>Cancel</button> </center> diff --git a/yaksh/templates/yaksh/ajax_questions.html b/yaksh/templates/yaksh/ajax_questions.html deleted file mode 100644 index e343f9b..0000000 --- a/yaksh/templates/yaksh/ajax_questions.html +++ /dev/null @@ -1,31 +0,0 @@ -<div id="questions"> - {% if questions %} - <input type="checkbox" id="checkall" class="ignore"> - <span><b> <font size="3"> Select All </font></b></span> - {% endif %} - <ul class="inputs-list"> - - {% for question in questions %} - <li> - <label> - <input type="checkbox" name="questions" data-qid="{{question.id}}"> - <span> {{ question.summary }} </span> - </label> - </li> - {% endfor %} - </ul> -</div> - -<div id="num"> - <select id="numbers"> - <option value="">Number of questions to be picked from the pool</option> - {% for q in questions %} - {% if forloop.counter0 != 0 %} - <option value={{forloop.counter0}}>{{ forloop.counter0}}</option> - {% endif %} - {% if questions|length == 1%} - <option value=1>1</option> - {% endif %} - {% endfor %} - </select> -</div> diff --git a/yaksh/templates/yaksh/courses.html b/yaksh/templates/yaksh/courses.html index 43f323b..dcf9af5 100644 --- a/yaksh/templates/yaksh/courses.html +++ b/yaksh/templates/yaksh/courses.html @@ -18,11 +18,10 @@ {% if user != course.creator %} <h4> {{course.creator.get_full_name}} added you to this course</h4> {% endif %} - <div class="row show-grid"> <div class="span14"> <div class="row"> - <div class="span6"> + <div class="span4"> <p> <b><u>Course</u></b> {% if course.active %} @@ -35,7 +34,7 @@ </br></br> {% if user == course.creator %} <div class="row"> - <div class="span6 wrap"> + <div class="span3 wrap"> <center><b><u>Teacher(s) Added to {{ course }}</u></b></center> {% if course.get_teachers %} <div align="left"> @@ -65,12 +64,23 @@ <p><b><a href="{{URL_ROOT}}/exam/manage/searchteacher/{{course.id}}/">Add Teacher</a></b></p> </div> {% endif %} - <div class="span6"> - <p><b><u>Quiz(zes)</u></b></p> + <div class="span4" style="text-align:left"> {% if course.get_quizzes %} - {% for quiz in course.get_quizzes %} + <p><b><u>Quiz(zes)</u></b></p> + {% for quiz in course.get_quizzes %} <a href="{{URL_ROOT}}/exam/manage/addquiz/{{course.id}}/{{quiz.id}}/">{{ quiz.description }}</a><br> - + {% endfor %} + </div> + <div class="span4" style="text-align:left"> + <p><b><u>Question Paper(s)</u></b></p> + {% for quiz in course.get_quizzes %} + {% if quiz.questionpaper_set.get %} + <a href="{{URL_ROOT}}/exam/manage/designquestionpaper/{{ quiz.id }}/{{quiz.questionpaper_set.get.id}}/">Question Paper for {{ quiz.description }}</a><br> + {% else %} + <p><b>No Question Paper </b> + <button class="btn small primary" type="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/quiz/designquestionpaper/{{ quiz.id }}/");'>Add</button> + </p> + {% endif %} {% endfor %} {% else %} <p><b>No quiz </b></p> @@ -79,7 +89,6 @@ </div> <br/> <button class="btn primary"type="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/addquiz/{{course.id}}/");'>Add New Quiz</button> - </div> </div> <br><br> diff --git a/yaksh/templates/yaksh/design_questionpaper.html b/yaksh/templates/yaksh/design_questionpaper.html index 2aa169b..435de83 100644 --- a/yaksh/templates/yaksh/design_questionpaper.html +++ b/yaksh/templates/yaksh/design_questionpaper.html @@ -1,12 +1,12 @@ {% extends "manage.html" %} -{% block subtitle %}Design Question Paper{% endblock %} +{% block title %} Design Question Paper {% endblock title %} + +{% block subtitle %} Design Question Paper {% endblock %} {% block css %} -<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/base.css" type="text/css" /> -<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/question_quiz.css" type="text/css" /> -<link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/autotaggit.css" /> -<link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/question_paper_creation.css" /> + <link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/bootstrap.css" /> + <link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/question_paper_creation.css" /> <style> select { @@ -14,17 +14,19 @@ select } </style> {% endblock %} -{% block script %} -<script src="{{ URL_ROOT }}/static/yaksh/js/jquery-1.4.2.min.js" type="text/javascript"></script> -<script src="{{ URL_ROOT }}/static/yaksh/js/bootstrap-tabs.js"></script> -<script src="{{ URL_ROOT }}/static/yaksh/js/add_questionpaper.js"></script> -<script src="{{ URL_ROOT }}/static/yaksh/js/question_paper_creation.js"></script> -<script src="{{ URL_ROOT }}/static/yaksh/js/bootstrap-modal.js"></script> +{% block script %} + <script src="{{ URL_ROOT }}/static/yaksh/js/jquery-1.9.1.min.js"></script> + <script src="{{ URL_ROOT }}/static/yaksh/js/bootstrap.js"></script> + <script src="{{ URL_ROOT }}/static/yaksh/js/bootstrap-tabs.js"></script> + <script src="{{ URL_ROOT }}/static/yaksh/js/question_paper_creation.js"></script> {% endblock %} -{% block manage %} -<input type=hidden id="url_root" value={{ URL_ROOT }}> +{% block new_manage %} +<form action="{{ URL_ROOT }}/exam/manage/designquestionpaper/{{ qpaper.quiz.id }}/{{ qpaper.id }}/" method="POST"> +<input class ="btn primary small" type="submit" name="back" id="back" value="Cancel"> + {% csrf_token %} + <input type=hidden name="is_active" id="is_active" value="{{ state }}"> <center><b>Manual mode to design the {{lang}} Question Paper</center><br> <ul class="tabs" data-tabs="tabs"> <li class="active" id="fixed-tab"> @@ -46,42 +48,62 @@ select </a></li> </ul> -<form action="{{URL_ROOT}}/exam/manage/designquestionpaper/" method="post" name=frm > {% csrf_token %} <div> - <h3>Total Marks: <span id="total_marks" class="well">0</span></h3> + <h3>Total Marks: <span id="total_marks" class="well"> {{ qpaper.total_marks }} </span></h3> </div> <div class="tab-content"> <!-- common to fixed and random questions --> <div class="row" id="selectors"> <h5 style="padding-left: 20px;">Please select Question type and Marks</h5> - <div class="span4"> - {{ form.question_type }} - </div> <!-- /.span4 --> - <div class="span4"> - {{ form.marks }} - </div> <!-- /.span4 --> - <div class="span4"> - <div class="pull-left" id="number-wrapper"></div> - </div> <!-- /.span4 --> + <div class="col-md-6"> + {{ filter_form.question_type }} + </div> + <div class="col-md-6"> + {{ filter_form.marks }} + </div> </div> <!-- /.row --> <br><br> - <div class="tab-pane active" id="fixed-questions"> <div class="row"> - <div class="span7"> + <div class="col-md-6"> <div id="fixed-available-wrapper"> <p><u>Select questions to add:</u></p> <div id="fixed-available"> + {% if state == "fixed" or state == "None" %} + <ul class="inputs-list"> + {% for question in questions %} + <li> + <label> + <input type="checkbox" name="questions" data-qid="{{question.id}}" value={{question.id}}> + <span> {{ question.summary }} </span> <span> {{ question.points }} </span> + </label> + </li> + {% endfor %} + </ul> + {% endif %} </div> - <a id="add-fixed" class="btn small primary pull-right" href="#">Add to paper</a> + <br /><br /> + <button id="add-fixed" name="add-fixed" class="btn small primary pull-right" type="submit">Add to paper</button> </div> </div> - <div class="span7"> + <div class="col-md-6"> <div id="fixed-added-wrapper"> <p><u>Fixed questions currently in paper:</u></p> <div id="fixed-added"> + <ul class="inputs-list"> + {% for question in fixed_questions %} + <li> + <label> + <input type="checkbox" name="added-questions" data-qid="{{question.id}}" value={{question.id}}> + <span> {{ question.summary }} </span> <span> {{ question.points }} </span> + </label> + </li> + {% endfor %} + </ul> </div> + <br /> + <button id="remove-fixed" name="remove-fixed" class="btn small primary pull-right" type="submit"> Remove from paper</button> </div> </div> </div> <!-- /.row --> @@ -89,25 +111,66 @@ select <div class="pull-right"> <a class="btn" id="fixed-next">Next ></a> </div> - </div> <!-- /#fixed-questions --> - <div class="tab-pane" id="random-questions"> <div class="row"> - <div class="span7"> + <div class="col-md-6"> <div id="random-available-wrapper"> <p><u>Select questions to add to the pool:</u></p> <div id="random-available"> + {% if state == "random" %} + <select id="num_of_questions" name="num_of_questions"> + <option value="1">Number of questions to be picked from the pool</option> + {% for q in questions %} + {% if forloop.counter0 != 0 %} + <option value={{forloop.counter0}}>{{ forloop.counter0}}</option> + {% endif %} + {% if questions|length == 1%} + <option value=1>1</option> + {% endif %} + {% endfor %} + </select> + <ul class="inputs-list"> + {% for question in questions %} + <li> + <label> + <input type="checkbox" name="random_questions" data-qid="{{question.id}}" value={{question.id}}> + <span> {{ question.summary }} </span> <span> {{ question.points }} </span> + </label> + </li> + {% endfor %} + </ul> + {% endif %} </div> - <a id="add-random" class="btn small primary pull-right" href="#">Add to paper</a> + <br /><br /> + <button id="add-random" name="add-random" class="btn small primary pull-right" type="submit">Add to paper</button> </div> </div> - <div class="span7"> + <div class="col-md-6"> <div id="random-added-wrapper"> <p><u>Pool of questions currently in paper:</u></p> <div id="random-added"> + <ul class="inputs-list"> + {% for random_set in random_sets %} + <li> + <label> + <input type="checkbox" name="random_sets" data-qid="{{random_set.id}}" value={{random_set.id}}> + <span> Random Set {{ forloop.counter }} (will take {{ random_set.num_questions }} randomly out of {{ random_set.questions.count }})</span> + </label> + </li> + {% for question in random_set.questions.all %} + <li> + <label> + <span> {{ question.summary }} </span> <span> {{ question.points }} </span> + </label> + </li> + {% endfor %} + {% endfor %} + </ul> </div> + <br /> + <button id="remove-random" name="remove-random" class="btn small primary pull-right" type="submit"> Remove from paper</button> </div> </div> </div> <!-- /.row --> @@ -124,11 +187,10 @@ select <center> <h5>Almost finished creating your question paper</h5> <label style="float: none;"> - {{ form.shuffle_questions }} + {{ qpaper_form.shuffle_questions }} <span>Auto shuffle.</span> </label> <br><br> - <input class ="btn primary large" type="button" id="preview" value="Preview question paper"> - <input class ="btn primary large" type="button" id="save" value="Save question paper"> + <input class ="btn primary large" type="submit" name="save" id="save" value="Save question paper"> <br> <div class="pull-left"> <a class="btn" id="finish-prev">< Previous</a> @@ -139,44 +201,18 @@ select <!-- /.tab-content --> </form> <br> -<div class="clearfix"></div> - -<!-- Modal --> -<div class="modal fade " id="myModal" > - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <h4 class="modal-title" id="myModalLabel">Question Paper Preview</h4> - </div> - <div id = "modal_body"class="modal-body"> - </div> - <div class="modal-footer"> - <button type="button" class="btn primary close" data-dismiss="modal">OK</button> - </div> - </div> - </div> -</div> - -<div class="modal fade " id="modalSave" > - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <h4 class="modal-title" id="myModalLabel">Cannot Save</h4> - </div> - <div class="modal-body"> - Please select questions for your paper - </div> - <div class="modal-footer"> - <button type="button" class="btn primary close" data-dismiss="modal">OK</button> - </div> - </div> - </div> -</div> -</div> - <script> $(function () { $('.tabs').tabs() + {% if state == "fixed" %} + $('#fixed').tab('show'); + {% elif state == "random" %} + $("#random").tab('show'); + {% elif state == "finish" %} + $('#finished').tab('show'); + {% endif %} }) </script> {% endblock %} +{% block manage %} +{% endblock %} diff --git a/yaksh/test_views.py b/yaksh/test_views.py index cf547b5..1d1c3f3 100644 --- a/yaksh/test_views.py +++ b/yaksh/test_views.py @@ -294,7 +294,7 @@ class TestAddQuiz(TestCase): self.assertEqual(updated_quiz.course, self.course) self.assertEqual(response.status_code, 302) - self.assertRedirects(response, '/exam/manage/') + self.assertRedirects(response, '/exam/manage/courses/') def test_add_quiz_post_new_quiz(self): """ @@ -340,7 +340,7 @@ class TestAddQuiz(TestCase): self.assertEqual(new_quiz.course, self.course) self.assertEqual(response.status_code, 302) - self.assertRedirects(response, '/exam/manage/designquestionpaper/') + self.assertRedirects(response, '/exam/manage/courses/') class TestAddTeacher(TestCase): def setUp(self): diff --git a/yaksh/urls.py b/yaksh/urls.py index c4619b6..bb8cf2e 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -68,9 +68,10 @@ urlpatterns += [ url(r'^manage/user_data/(?P<user_id>\d+)/(?P<questionpaper_id>\d+)/$', views.user_data), url(r'^manage/user_data/(?P<user_id>\d+)/$', views.user_data), - url(r'^manage/designquestionpaper/$', views.design_questionpaper, name='design_questionpaper'), - url(r'^manage/designquestionpaper/(?P<questionpaper_id>\d+)/$',\ - views.design_questionpaper), + url(r'^manage/quiz/designquestionpaper/(?P<quiz_id>\d+)/$', views.design_questionpaper, + name='design_questionpaper'), + url(r'^manage/designquestionpaper/(?P<quiz_id>\d+)/(?P<questionpaper_id>\d+)/$', + views.design_questionpaper, name='designquestionpaper'), url(r'^manage/statistics/question/(?P<questionpaper_id>\d+)/$', views.show_statistics), url(r'^manage/statistics/question/(?P<questionpaper_id>\d+)/(?P<attempt_number>\d+)/$', @@ -87,7 +88,6 @@ urlpatterns += [ url(r'manage/enrolled/reject/(?P<course_id>\d+)/(?P<user_id>\d+)/$', views.reject, {'was_enrolled': True}), url(r'manage/toggle_status/(?P<course_id>\d+)/$', views.toggle_course_status), - url(r'^ajax/questionpaper/(?P<query>.+)/$', views.ajax_questionpaper), url(r'^ajax/questions/filter/$', views.ajax_questions_filter), url(r'^editprofile/$', views.edit_profile, name='edit_profile'), url(r'^viewprofile/$', views.view_profile, name='view_profile'), diff --git a/yaksh/views.py b/yaksh/views.py index 0ed5f5a..049788a 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -29,7 +29,7 @@ from yaksh.models import Profile, Answer, AnswerPaper, User, TestCase, FileUploa from yaksh.forms import UserRegisterForm, UserLoginForm, QuizForm,\ QuestionForm, RandomQuestionForm,\ QuestionFilterForm, CourseForm, ProfileForm, UploadFileForm,\ - get_object_form, FileForm + get_object_form, FileForm, QuestionPaperForm from .settings import URL_ROOT from yaksh.models import AssignmentUpload from .file_utils import extract_files @@ -246,7 +246,7 @@ def add_quiz(request, course_id, quiz_id=None): form = QuizForm(request.POST, user=user, course=course_id) if form.is_valid(): form.save() - return my_redirect(reverse('yaksh:design_questionpaper')) + return my_redirect("/exam/manage/courses/") else: context["form"] = form return my_render_to_response('yaksh/add_quiz.html', @@ -259,7 +259,7 @@ def add_quiz(request, course_id, quiz_id=None): if form.is_valid(): form.save() context["quiz_id"] = quiz_id - return my_redirect("/exam/manage/") + return my_redirect("/exam/manage/courses/") else: if quiz_id is None: form = QuizForm(course=course_id, user=user) @@ -631,7 +631,6 @@ def courses(request): raise Http404('You are not allowed to view this page') courses = Course.objects.filter(creator=user, is_trial=False) allotted_courses = Course.objects.filter(teachers=user, is_trial=False) - context = {'courses': courses, "allotted_courses": allotted_courses} return my_render_to_response('yaksh/courses.html', context, context_instance=ci) @@ -813,6 +812,95 @@ def ajax_questions_filter(request): {'questions': questions}) +def _get_questions(user, question_type, marks): + if question_type is None and marks is None: + return None + if question_type: + questions = Question.objects.filter(type=question_type, user=user) + if marks: + questions = questions.filter(points=marks) + return questions + + +def _remove_already_present(questionpaper_id, questions): + if questionpaper_id is None: + return questions + questionpaper = QuestionPaper.objects.get(pk=questionpaper_id) + questions = questions.exclude( + id__in=questionpaper.fixed_questions.values_list('id', flat=True)) + for random_set in questionpaper.random_questions.all(): + questions = questions.exclude( + id__in=random_set.questions.values_list('id', flat=True)) + return questions + + +@login_required +def design_questionpaper(request, quiz_id, questionpaper_id=None): + user = request.user + + if not is_moderator(user): + raise Http404('You are not allowed to view this page!') + + filter_form = QuestionFilterForm(user=user) + questions = None + marks = None + state = None + if questionpaper_id is None: + question_paper = QuestionPaper.objects.get_or_create(quiz_id=quiz_id)[0] + else: + question_paper = get_object_or_404(QuestionPaper, id=questionpaper_id) + qpaper_form = QuestionPaperForm(instance=question_paper) + + if request.method == 'POST': + + filter_form = QuestionFilterForm(request.POST, user=user) + qpaper_form = QuestionPaperForm(request.POST, instance=question_paper) + question_type = request.POST.get('question_type', None) + marks = request.POST.get('marks', None) + state = request.POST.get('is_active', None) + + if 'add-fixed' in request.POST: + question_ids = request.POST.getlist('questions', None) + for question in Question.objects.filter(id__in=question_ids): + question_paper.fixed_questions.add(question) + + if 'remove-fixed' in request.POST: + question_ids = request.POST.getlist('added-questions', None) + question_paper.fixed_questions.remove(*question_ids) + + if 'add-random' in request.POST: + question_ids = request.POST.getlist('random_questions', None) + num_of_questions = request.POST.get('num_of_questions', 1) + if question_ids and marks: + random_set = QuestionSet(marks=marks, num_questions=num_of_questions) + random_set.save() + for question in Question.objects.filter(id__in=question_ids): + random_set.questions.add(question) + question_paper.random_questions.add(random_set) + + if 'remove-random' in request.POST: + random_set_ids = request.POST.getlist('random_sets', None) + question_paper.random_questions.remove(*random_set_ids) + + if 'save' in request.POST or 'back' in request.POST: + qpaper_form.save() + return my_redirect('/exam/manage/courses/') + + if marks: + questions = _get_questions(user, question_type, marks) + questions = _remove_already_present(questionpaper_id, questions) + + question_paper.update_total_marks() + question_paper.save() + random_sets = question_paper.random_questions.all() + fixed_questions = question_paper.fixed_questions.all() + context = {'qpaper_form': qpaper_form, 'filter_form': filter_form, 'qpaper': + question_paper, 'questions': questions, 'fixed_questions': fixed_questions, + 'state': state, 'random_sets': random_sets} + return my_render_to_response('yaksh/design_questionpaper.html', context, + context_instance=RequestContext(request)) + + @login_required def show_all_questions(request): """Show a list of all the questions currently in the database.""" @@ -999,80 +1087,6 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None): ) -@csrf_exempt -def ajax_questionpaper(request, query): - """ - During question paper creation, ajax call made to get question details. - """ - - user = request.user - if query == 'marks': - question_type = request.POST.get('question_type') - questions = Question.objects.filter(type=question_type, user=user) - marks = questions.values_list('points').distinct() - return my_render_to_response('yaksh/ajax_marks.html', {'marks': marks}) - elif query == 'questions': - question_type = request.POST['question_type'] - marks_selected = request.POST['marks'] - fixed_questions = request.POST.getlist('fixed_list[]') - fixed_question_list = ",".join(fixed_questions).split(',') - random_questions = request.POST.getlist('random_list[]') - random_question_list = ",".join(random_questions).split(',') - question_list = fixed_question_list + random_question_list - questions = list(Question.objects.filter(type=question_type, - points=marks_selected, user=user)) - questions = [question for question in questions \ - if not str(question.id) in question_list] - return my_render_to_response('yaksh/ajax_questions.html', - {'questions': questions}) - - -@login_required -def design_questionpaper(request): - user = request.user - ci = RequestContext(request) - - if not is_moderator(user): - raise Http404('You are not allowed to view this page!') - - if request.method == 'POST': - fixed_questions = request.POST.getlist('fixed') - random_questions = request.POST.getlist('random') - random_number = request.POST.getlist('number') - is_shuffle = request.POST.get('shuffle_questions', False) - if is_shuffle == 'on': - is_shuffle = True - - question_paper = QuestionPaper(shuffle_questions=is_shuffle) - quiz = Quiz.objects.order_by("-id")[0] - tot_marks = 0 - question_paper.quiz = quiz - question_paper.total_marks = tot_marks - question_paper.save() - if fixed_questions: - fixed_questions_ids = ",".join(fixed_questions) - fixed_questions_ids_list = fixed_questions_ids.split(',') - for question_id in fixed_questions_ids_list: - question_paper.fixed_questions.add(question_id) - if random_questions: - for random_question, num in zip(random_questions, random_number): - qid = random_question.split(',')[0] - question = Question.objects.get(id=int(qid)) - marks = question.points - question_set = QuestionSet(marks=marks, num_questions=num) - question_set.save() - for question_id in random_question.split(','): - question_set.questions.add(question_id) - question_paper.random_questions.add(question_set) - question_paper.update_total_marks() - question_paper.save() - return my_redirect('/exam/manage/courses') - else: - form = RandomQuestionForm() - context = {'form': form, 'questionpaper':True} - return my_render_to_response('yaksh/design_questionpaper.html', - context, context_instance=ci) - @login_required def view_profile(request): """ view moderators and users profile """ @@ -1151,7 +1165,6 @@ def search_teacher(request, course_id): Q(id=course.creator.id)) context['success'] = True context['teachers'] = teachers - return my_render_to_response('yaksh/addteacher.html', context, context_instance=ci) @@ -1180,7 +1193,6 @@ def add_teacher(request, course_id): course.add_teachers(*teachers) context['status'] = True context['teachers_added'] = teachers - return my_render_to_response('yaksh/addteacher.html', context, context_instance=ci) @@ -1188,7 +1200,7 @@ def add_teacher(request, course_id): @login_required def remove_teachers(request, course_id): """ remove user from a course """ - + user = request.user course = get_object_or_404(Course, pk=course_id) if not is_moderator(user) and (user != course.creator and user not in course.teachers.all()): |