From 3918842683580a7265e4420febb13aadf7604e35 Mon Sep 17 00:00:00 2001 From: prathamesh Date: Thu, 3 Jul 2014 17:31:19 +0530 Subject: Interface to create question paper --- testapp/exam/forms.py | 12 +- testapp/exam/urls.py | 1 + testapp/exam/views.py | 101 ++++++- testapp/static/exam/css/base.css | 315 ++++++++++++++++++++- .../static/exam/css/question_paper_creation.css | 119 ++++++++ testapp/static/exam/js/bootstrap-modal.js | 260 +++++++++++++++++ testapp/static/exam/js/bootstrap-tabs.js | 80 ++++++ testapp/static/exam/js/question_paper_creation.js | 237 ++++++++++++++++ testapp/templates/exam/ajax_marks.html | 4 + testapp/templates/exam/ajax_questions.html | 31 ++ testapp/templates/exam/design_questionpaper.html | 184 ++++++++++++ testapp/templates/exam/monitor.html | 4 +- 12 files changed, 1327 insertions(+), 21 deletions(-) create mode 100644 testapp/static/exam/css/question_paper_creation.css create mode 100644 testapp/static/exam/js/bootstrap-modal.js create mode 100644 testapp/static/exam/js/bootstrap-tabs.js create mode 100644 testapp/static/exam/js/question_paper_creation.js create mode 100644 testapp/templates/exam/ajax_marks.html create mode 100644 testapp/templates/exam/ajax_questions.html create mode 100644 testapp/templates/exam/design_questionpaper.html diff --git a/testapp/exam/forms.py b/testapp/exam/forms.py index d0b0b74..9bfedbe 100644 --- a/testapp/exam/forms.py +++ b/testapp/exam/forms.py @@ -13,7 +13,7 @@ from string import letters, punctuation, digits import datetime languages = ( - ("select", "Select"), + ("select", "Select Language"), ("python", "Python"), ("bash", "Bash"), ("C", "C Language"), @@ -23,7 +23,7 @@ languages = ( ) question_types = ( - ("select", "Select"), + ("select", "Select Question Type"), ("mcq", "Multiple Choice"), ("mcc", "Multiple Correct Choices"), ("code", "Code"), @@ -207,3 +207,11 @@ class QuestionForm(forms.Form): new_question.active = active new_question.snippet = snippet new_question.save() + + +class RandomQuestionForm(forms.Form): + question_type = forms.CharField(max_length=8, widget=forms.Select\ + (choices=question_types)) + marks = forms.CharField(max_length=8, widget=forms.Select\ + (choices=(('select', 'Select Marks'),))) + shuffle_questions = forms.BooleanField(required=False) diff --git a/testapp/exam/urls.py b/testapp/exam/urls.py index 33b2edf..3950a43 100644 --- a/testapp/exam/urls.py +++ b/testapp/exam/urls.py @@ -43,4 +43,5 @@ urlpatterns = patterns('exam.views', url(r'^manage/designquestionpaper/manual$','manual_questionpaper'), url(r'^manage/designquestionpaper/manual/(?P\d+)/$',\ 'manual_questionpaper'), + url(r'^ajax/questionpaper/(?P.+)/$', 'ajax_questionpaper'), ) diff --git a/testapp/exam/views.py b/testapp/exam/views.py index 6c29107..2eb6dd4 100644 --- a/testapp/exam/views.py +++ b/testapp/exam/views.py @@ -11,12 +11,14 @@ from django.shortcuts import render_to_response, get_object_or_404, redirect from django.template import RequestContext from django.http import Http404 from django.db.models import Sum +from django.views.decorators.csrf import csrf_exempt from taggit.models import Tag from itertools import chain # Local imports. -from exam.models import Quiz, Question, QuestionPaper +from exam.models import Quiz, Question, QuestionPaper, QuestionSet from exam.models import Profile, Answer, AnswerPaper, User -from exam.forms import UserRegisterForm, UserLoginForm, QuizForm, QuestionForm +from exam.forms import UserRegisterForm, UserLoginForm, QuizForm,\ + QuestionForm, RandomQuestionForm from exam.xmlrpc_clients import code_server from settings import URL_ROOT @@ -197,11 +199,11 @@ def results_user(request): papers = AnswerPaper.objects.filter(user=user) quiz_marks = [] for paper in papers: - marks_obtained = paper.update_marks_obtained() + marks_obtained = paper.marks_obtained max_marks = paper.question_paper.total_marks percentage = round((marks_obtained/max_marks)*100, 2) temp = paper.question_paper.quiz.description, marks_obtained,\ - max_marks, percentage + max_marks, percetage quiz_marks.append(temp) context = {'papers': quiz_marks} return my_render_to_response("exam/results_user.html", context) @@ -249,6 +251,7 @@ def edit_question(request): options = request.POST.getlist('options') type = request.POST.getlist('type') active = request.POST.getlist('active') + language = request.POST.getlist('language') snippet = request.POST.getlist('snippet') for j, question_id in enumerate(question_list): question = Question.objects.get(id=question_id) @@ -258,6 +261,7 @@ def edit_question(request): question.test = test[j] question.options = options[j] question.active = active[j] + question.language = language[j] question.snippet = snippet[j] question.type = type[j] question.save() @@ -292,6 +296,7 @@ def add_question(request, question_id=None): d.options = form['options'].data d.type = form['type'].data d.active = form['active'].data + d.language = form['language'].data d.snippet = form['snippet'].data d.save() question = Question.objects.get(id=question_id) @@ -322,6 +327,7 @@ def add_question(request, question_id=None): form.initial['options'] = d.options form.initial['type'] = d.type form.initial['active'] = d.active + form.initial['language'] = d.language form.initial['snippet'] = d.snippet form_tags = d.tags.all() form_tags_split = form_tags.values('name') @@ -389,15 +395,6 @@ def add_quiz(request, quiz_id=None): context_instance=ci) -def design_questionpaper(request, questionpaper_id=None): - user = request.user - ci = RequestContext(request) - if not user.is_authenticated() or not is_moderator(user): - raise Http404('You are not allowed to view this page!') - return my_render_to_response('exam/add_questionpaper.html', {}, - context_instance=ci) - - def show_all_questionpapers(request, questionpaper_id=None): user = request.user ci = RequestContext(request) @@ -842,7 +839,11 @@ def complete(request, reason=None, questionpaper_id=None): else: q_paper = QuestionPaper.objects.get(id=questionpaper_id) paper = AnswerPaper.objects.get(user=user, question_paper=q_paper) - obt_marks = paper.update_marks_obtained() + paper.update_marks_obtained() + paper.update_percent() + paper.update_passed() + paper.save() + obt_marks = paper.marks_obtained tot_marks = paper.question_paper.total_marks if obt_marks == paper.question_paper.total_marks: context = {'message': "Hurray ! You did an excellent job.\ @@ -1029,6 +1030,7 @@ def show_all_questions(request): form.initial['options'] = d.options form.initial['type'] = d.type form.initial['active'] = d.active + form.initial['language'] = d.language form.initial['snippet'] = d.snippet form_tags = d.tags.all() form_tags_split = form_tags.values('name') @@ -1094,3 +1096,74 @@ def grade_user(request, username): context = {'data': data} return my_render_to_response('exam/grade_user.html', context, context_instance=ci) + + +@csrf_exempt +def ajax_questionpaper(request, query): + """ + During question paper creation, ajax call made to get question details. + """ + if query == 'marks': + question_type = request.POST.get('question_type') + questions = Question.objects.filter(type=question_type) + marks = questions.values_list('points').distinct() + return my_render_to_response('exam/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)) + questions = [ question for question in questions \ + if not str(question.id) in question_list ] + return my_render_to_response('exam/ajax_questions.html', + {'questions': questions}) + + +def design_questionpaper(request): + user = request.user + ci = RequestContext(request) + + if not user.is_authenticated() or 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): + question = Question.objects.get(id=random_question[0]) + 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/showquiz') + else: + form = RandomQuestionForm() + context = {'form': form} + return my_render_to_response('exam/design_questionpaper.html', + context, context_instance=ci) diff --git a/testapp/static/exam/css/base.css b/testapp/static/exam/css/base.css index c822f4d..d3a0a0a 100644 --- a/testapp/static/exam/css/base.css +++ b/testapp/static/exam/css/base.css @@ -295,7 +295,7 @@ a:hover { width: 160px; } .span4 { - min-height : 500px; +/* min-height : 500px; */ width: 220px; } .span5 { @@ -1898,7 +1898,7 @@ button.btn::-moz-focus-inner, input[type=submit].btn::-moz-focus-inner { padding: 0; border: 0; } -.close { +/*.close { float: right; color: #000000; font-size: 20px; @@ -1917,7 +1917,7 @@ button.btn::-moz-focus-inner, input[type=submit].btn::-moz-focus-inner { -khtml-opacity: 0.4; -moz-opacity: 0.4; opacity: 0.4; -} +}*/ .alert-message { position: relative; padding: 7px 15px; @@ -2045,4 +2045,313 @@ button.btn::-moz-focus-inner, input[type=submit].btn::-moz-focus-inner { .label.notice { background-color: #62cffc; } +.well { + background-color: #f5f5f5; + margin-bottom: 20px; + padding: 19px; + min-height: 20px; + border: 1px solid #eee; + border: 1px solid rgba(0, 0, 0, 0.05); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.modal-backdrop { + background-color: #000000; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 10000; +} +.modal-backdrop.fade { + opacity: 0; +} +.modal-backdrop, .modal-backdrop.fade.in { + filter: alpha(opacity=80); + -khtml-opacity: 0.8; + -moz-opacity: 0.8; + opacity: 0.8; +} +/* +.modal { + position: fixed; + top: 50%; + left: 50%; + z-index: 11000; + width: 560px; + margin: -250px 0 0 -280px; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.modal .close { + margin-top: 7px; +} +.modal.fade { + -webkit-transform-style: preserve-3d; + -webkit-transition: opacity .3s linear, top .3s ease-out; + -moz-transition: opacity .3s linear, top .3s ease-out; + -ms-transition: opacity .3s linear, top .3s ease-out; + -o-transition: opacity .3s linear, top .3s ease-out; + transition: opacity .3s linear, top .3s ease-out; + top: -25%; +} +.modal.fade.in { + top: 50%; +} +.modal-header { + border-bottom: 1px solid #eee; + padding: 5px 15px; +} +.modal-body { + padding: 15px; +} +.modal-body form { + margin-bottom: 0; +} +.modal-footer { + background-color: #f5f5f5; + padding: 14px 15px 15px; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; + zoom: 1; + margin-bottom: 0; +} +.modal-footer:before, .modal-footer:after { + display: table; + content: ""; + zoom: 1; +} +.modal-footer:after { + clear: both; +} +.modal-footer .btn { + float: right; + margin-left: 5px; +} +.modal .popover, .modal .twipsy { + z-index: 12000; +} +*/ +.modal { + position: fixed; + top: 10%; + left: 50%; + z-index: 1050; + width: 560px; + margin-left: -280px; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + outline: none; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.modal.fade { + top: -25%; + -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; + -moz-transition: opacity 0.3s linear, top 0.3s ease-out; + -o-transition: opacity 0.3s linear, top 0.3s ease-out; + transition: opacity 0.3s linear, top 0.3s ease-out; +} + +.modal.fade.in { + top: 10%; +} + +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee; +} + +.modal-header .close { + margin-top: 2px; +} + +.modal-header h3 { + margin: 0; + line-height: 30px; +} + +.modal-body { + position: relative; + max-height: 400px; + padding: 15px; + overflow-y: auto; +} + +.modal-form { + margin-bottom: 0; +} + +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} + +.modal-footer:before, +.modal-footer:after { + display: table; + line-height: 0; + content: ""; +} + +.modal-footer:after { + clear: both; +} +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} + +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} + +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.tabs, .pills { + margin: 0 0 18px; + padding: 0; + list-style: none; + zoom: 1; +} +.tabs:before, +.pills:before, +.tabs:after, +.pills:after { + display: table; + content: ""; + zoom: 1; +} +.tabs:after, .pills:after { + clear: both; +} +.tabs > li, .pills > li { + float: left; +} +.tabs > li > a, .pills > li > a { + display: block; +} +.tabs { + border-color: #ddd; + border-style: solid; + border-width: 0 0 1px; +} +.tabs > li { + position: relative; + margin-bottom: -1px; +} +.tabs > li > a { + padding: 0 15px; + margin-right: 2px; + line-height: 23px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +.tabs > li > a:hover { + text-decoration: none; + background-color: #eee; + border-color: #eee #eee #ddd; +} +.tabs .active > a, .tabs .active > a:hover { + color: #808080; + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: transparent; + cursor: default; +} +.tabs .menu-dropdown, .tabs .dropdown-menu { + top: 35px; + border-width: 1px; + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px; +} +.tabs a.menu:after, .tabs .dropdown-toggle:after { + border-top-color: #999; + margin-top: 15px; + margin-left: 5px; +} +.tabs li.open.menu .menu, .tabs .open.dropdown .dropdown-toggle { + border-color: #999; +} +.tabs li.open a.menu:after, .tabs .dropdown.open .dropdown-toggle:after { + border-top-color: #555; +} +.pills a { + margin: 5px 3px 5px 0; + padding: 0 15px; + line-height: 30px; + text-shadow: 0 1px 1px #ffffff; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} +.pills a:hover { + color: #ffffff; + text-decoration: none; + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); + background-color: #00438a; +} +.pills .active a { + color: #ffffff; + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); + background-color: #0069d6; +} +.pills-vertical > li { + float: none; +} +.tab-content > .tab-pane, .pill-content > .pill-pane { + display: none; +} +.tab-content > .active, .pill-content > .active { + display: block; +} diff --git a/testapp/static/exam/css/question_paper_creation.css b/testapp/static/exam/css/question_paper_creation.css new file mode 100644 index 0000000..c915320 --- /dev/null +++ b/testapp/static/exam/css/question_paper_creation.css @@ -0,0 +1,119 @@ +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 18px; + color: #404040; +} +.clearfix { + clear: both; +} +.tabs li { + text-align: center; + width: 33%; +} +.tabs li:last-child { + width: 34%; +} +.tabs > .active > a { + border: 0; + background: lightgreen; +} +.tabs > .active > a:hover { + border: 0; + background: green; + color: #ffffff; +} +.tabs li a { + border-radius: 0; + margin-right: 0; +} +.tabs { + border: 1px solid #ddd; +} +#progress { + background: red; +} +#content-left{ + text-align: center; + background: grey; +} +#content-right{ + text-align: center; + background: grey; +} +#selectors { + margin-left: 0; + background: #fafafa; + padding: 7px 0; + border: 2px solid #f5f5f5; +} +#selectors .span4 { + margin-left: 0; +} +#id_question_type { + width: 100%; +} +#id_marks { + width: 100%; +} +#fixed-questions .span7 > div, +#random-questions .span7 > div{ + background: #f5f5f5; + height: 200px; + border: 1px solid #333333; + padding: 5px; +} +#fixed-available, +#random-available { + height: 125px; + min-height: 125px; + overflow-y: scroll; + margin-bottom: 15px; +} +#fixed-added, +#random-added { + height: 160px; + overflow-y: scroll; +} +#fixed-added hr, +#random-added hr { + margin: 5px 0 4px; +} +.qcard { + position: relative; + background: #ffffff; + padding: 5px; + margin: 5px 5px; + box-shadow: 1px 1px 5px #cccccc; + -webkit-box-shadow: 1px 1px 5px #cccccc; + -moz-box-shadow: 1px 1px 5px #cccccc; + -o-box-shadow: 1px 1px 5px #cccccc; +} +.qcard ul { + margin-bottom: 5px; +} +.qcard .remove { + position: absolute; + + top: 3px; + right: 3px; + padding: 1px 3px; + text-decoration: none; + color: #ffffff; + background: #ff4136; + border-radius: 3px; + font-weight: bold; +} +.qcard .remove:hover { + background: #333333; +} +.red-alert { + border: 2px solid red; +} +#myModal .qcard .remove{ + display: none; +} +.well{ + padding: 5px; +} diff --git a/testapp/static/exam/js/bootstrap-modal.js b/testapp/static/exam/js/bootstrap-modal.js new file mode 100644 index 0000000..b328217 --- /dev/null +++ b/testapp/static/exam/js/bootstrap-modal.js @@ -0,0 +1,260 @@ +/* ========================================================= + * bootstrap-modal.js v1.4.0 + * http://twitter.github.com/bootstrap/javascript.html#modal + * ========================================================= + * Copyright 2011 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================= */ + + +!function( $ ){ + + "use strict" + + /* CSS TRANSITION SUPPORT (https://gist.github.com/373874) + * ======================================================= */ + + var transitionEnd + + $(document).ready(function () { + + $.support.transition = (function () { + var thisBody = document.body || document.documentElement + , thisStyle = thisBody.style + , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined + return support + })() + + // set CSS transition event type + if ( $.support.transition ) { + transitionEnd = "TransitionEnd" + if ( $.browser.webkit ) { + transitionEnd = "webkitTransitionEnd" + } else if ( $.browser.mozilla ) { + transitionEnd = "transitionend" + } else if ( $.browser.opera ) { + transitionEnd = "oTransitionEnd" + } + } + + }) + + + /* MODAL PUBLIC CLASS DEFINITION + * ============================= */ + + var Modal = function ( content, options ) { + this.settings = $.extend({}, $.fn.modal.defaults, options) + this.$element = $(content) + .delegate('.close', 'click.modal', $.proxy(this.hide, this)) + + if ( this.settings.show ) { + this.show() + } + + return this + } + + Modal.prototype = { + + toggle: function () { + return this[!this.isShown ? 'show' : 'hide']() + } + + , show: function () { + var that = this + this.isShown = true + this.$element.trigger('show') + + escape.call(this) + backdrop.call(this, function () { + var transition = $.support.transition && that.$element.hasClass('fade') + + that.$element + .appendTo(document.body) + .show() + + if (transition) { + that.$element[0].offsetWidth // force reflow + } + + that.$element.addClass('in') + + transition ? + that.$element.one(transitionEnd, function () { that.$element.trigger('shown') }) : + that.$element.trigger('shown') + + }) + + return this + } + + , hide: function (e) { + e && e.preventDefault() + + if ( !this.isShown ) { + return this + } + + var that = this + this.isShown = false + + escape.call(this) + + this.$element + .trigger('hide') + .removeClass('in') + + $.support.transition && this.$element.hasClass('fade') ? + hideWithTransition.call(this) : + hideModal.call(this) + + return this + } + + } + + + /* MODAL PRIVATE METHODS + * ===================== */ + + function hideWithTransition() { + // firefox drops transitionEnd events :{o + var that = this + , timeout = setTimeout(function () { + that.$element.unbind(transitionEnd) + hideModal.call(that) + }, 500) + + this.$element.one(transitionEnd, function () { + clearTimeout(timeout) + hideModal.call(that) + }) + } + + function hideModal (that) { + this.$element + .hide() + .trigger('hidden') + + backdrop.call(this) + } + + function backdrop ( callback ) { + var that = this + , animate = this.$element.hasClass('fade') ? 'fade' : '' + if ( this.isShown && this.settings.backdrop ) { + var doAnimate = $.support.transition && animate + + this.$backdrop = $('"); + $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 = $("
"); + html += "
  • " + $(this).next().html() + "
  • "; + count++; + } + } + }); + html = "
      " + html + "
    "; + selected = selected.join(","); + var $input_random = $(""); + $input_random.attr({ + value: selected, + name: "random" + }); + var $input_number = $(""); + $input_number.attr({ + value: $numbers.val(), + name: "number" + }); + $remove = $("
    ×"); + $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(); + }); + + /* showing/hiding selectors on tab click */ + $(".tabs li").click(function() { + if($(this).attr("id") == "finish-tab") { + $("#selectors").hide(); + } 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'); + }); + } + else { + $("#random-available input:checkbox").each(function(index, element) { + $(this).attr('checked','checked'); + }); + } + } + 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"); + } + else { + $('#modal_body').html(questions); + } + $("#myModal").modal('show'); + }); + + /* tab change on next or previous button click */ + $("#fixed-next").click(function(){ + $("#random").click(); + }); + $("#random-next").click(function(){ + $("#finished").click(); + }); + + $("#random-prev").click(function(){ + $("#fixed").click(); + }); + + $("#finish-prev").click(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 diff --git a/testapp/templates/exam/ajax_marks.html b/testapp/templates/exam/ajax_marks.html new file mode 100644 index 0000000..716bb88 --- /dev/null +++ b/testapp/templates/exam/ajax_marks.html @@ -0,0 +1,4 @@ + +{% for mark in marks %} + +{% endfor %} diff --git a/testapp/templates/exam/ajax_questions.html b/testapp/templates/exam/ajax_questions.html new file mode 100644 index 0000000..e343f9b --- /dev/null +++ b/testapp/templates/exam/ajax_questions.html @@ -0,0 +1,31 @@ +
    + {% if questions %} + + Select All + {% endif %} +
      + + {% for question in questions %} +
    • + +
    • + {% endfor %} +
    +
    + +
    + +
    diff --git a/testapp/templates/exam/design_questionpaper.html b/testapp/templates/exam/design_questionpaper.html new file mode 100644 index 0000000..8994148 --- /dev/null +++ b/testapp/templates/exam/design_questionpaper.html @@ -0,0 +1,184 @@ +{% extends "manage.html" %} + +{% block subtitle %}Design Question Paper{% endblock %} + +{% block css %} + + + + + +{% endblock %} +{% block script %} + + + + + + + + +{% endblock %} + +{% block manage %} + +
    Manual mode to design the {{lang}} Question Paper

    +
    + +
    {% csrf_token %} +
    +

    Total Marks: 0

    +
    +
    + +
    +
    Please select Question type and Marks
    +
    + {{ form.question_type }} +
    +
    + {{ form.marks }} +
    +
    +
    +
    +
    +

    + + +
    +
    +
    +
    +

    Select questions to add:

    +
    +
    + Add to paper +
    +
    +
    +
    +

    Fixed questions currently in paper:

    +
    +
    +
    +
    +
    +
    +
    + Next > +
    + +
    + + +
    +
    +
    +
    +

    Select questions to add to the pool:

    +
    +
    + Add to paper +
    +
    +
    +
    +

    Pool of questions currently in paper:

    +
    +
    +
    +
    +
    +
    + +
    + Next > +
    +
    + +
    +
    +
    Almost finished creating your question paper
    +

    + + +
    + +
    +
    +
    + +
    +
    +
    + + + + + + + + +{% endblock %} diff --git a/testapp/templates/exam/monitor.html b/testapp/templates/exam/monitor.html index aa8b678..ecdb852 100644 --- a/testapp/templates/exam/monitor.html +++ b/testapp/templates/exam/monitor.html @@ -47,7 +47,7 @@ Roll number Institute Questions answered - Total marks + Marks obtained Attempts {% for paper in papers %} @@ -57,7 +57,7 @@ {{ paper.profile.roll_number }} {{ paper.profile.institute }} {{ paper.get_answered_str }} - {{ paper.get_total_marks }} + {{ paper.marks_obtained }} {{ paper.answers.count }} {% endfor %} -- cgit From aa80f512fbea42a1b78255254132fccf618030cf Mon Sep 17 00:00:00 2001 From: prathamesh Date: Thu, 3 Jul 2014 17:35:01 +0530 Subject: Whitespaces stripped --- testapp/exam/urls.py | 10 +++++----- testapp/exam/views.py | 38 +++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/testapp/exam/urls.py b/testapp/exam/urls.py index 3950a43..b659cf6 100644 --- a/testapp/exam/urls.py +++ b/testapp/exam/urls.py @@ -9,7 +9,7 @@ urlpatterns = patterns('exam.views', url(r'^start/(?P\d+)/$','start'), url(r'^quit/(?P\d+)/$', 'quit'), url(r'^intro/(?P\d+)/$','intro'), - url(r'^complete/$', 'complete'), + url(r'^complete/$', 'complete'), url(r'^complete/(?P\d+)/$', 'complete'), url(r'^register/$', 'user_register'), url(r'^(?P\d+)/$', 'question'), @@ -19,7 +19,7 @@ urlpatterns = patterns('exam.views', url(r'^manage/$', 'prof_manage'), url(r'^manage/addquestion/$', 'add_question'), - url(r'^manage/addquestion/(?P\d+)/$', 'add_question'), + url(r'^manage/addquestion/(?P\d+)/$', 'add_question'), url(r'^manage/addquiz/$', 'add_quiz'), url(r'^manage/editquiz/$', 'edit_quiz'), url(r'^manage/editquestion/$', 'edit_question'), @@ -27,12 +27,12 @@ urlpatterns = patterns('exam.views', url(r'^manage/gradeuser/$', 'show_all_users'), url(r'^manage/gradeuser/(?P[a-zA-Z0-9_.]+)/$', 'grade_user'), url(r'^manage/questions/$', 'show_all_questions'), - url(r'^manage/showquiz/$','show_all_quiz'), + url(r'^manage/showquiz/$','show_all_quiz'), url(r'^manage/monitor/$', 'monitor'), - url(r'^manage/showquestionpapers/$','show_all_questionpapers'), + url(r'^manage/showquestionpapers/$','show_all_questionpapers'), url(r'^manage/showquestionpapers/(?P\d+)/$',\ 'show_all_questionpapers'), - url(r'^manage/monitor/(?P\d+)/$', 'monitor'), + url(r'^manage/monitor/(?P\d+)/$', 'monitor'), url(r'^manage/user_data/(?P[a-zA-Z0-9_.]+)/$','user_data'), url(r'^manage/designquestionpaper/$','design_questionpaper'), url(r'^manage/designquestionpaper/(?P\d+)/$',\ diff --git a/testapp/exam/views.py b/testapp/exam/views.py index 2eb6dd4..bee617d 100644 --- a/testapp/exam/views.py +++ b/testapp/exam/views.py @@ -133,32 +133,32 @@ def user_register(request): context_instance=ci) -def quizlist_user(request): - """Show All Quizzes that is available to logged-in user.""" - user = request.user - avail_quizzes = list(QuestionPaper.objects.filter(quiz__active=True)) - user_answerpapers = AnswerPaper.objects.filter(user=user) - quizzes_taken = [] +def quizlist_user(request): + """Show All Quizzes that is available to logged-in user.""" + user = request.user + avail_quizzes = list(QuestionPaper.objects.filter(quiz__active=True)) + user_answerpapers = AnswerPaper.objects.filter(user=user) + quizzes_taken = [] pre_requisites = [] - context = {} - + context = {} + if 'cannot_attempt' in request.GET: context['cannot_attempt'] = True - - if user_answerpapers.count() == 0: + + if user_answerpapers.count() == 0: context['quizzes'] = avail_quizzes - context['user'] = user + context['user'] = user context['quizzes_taken'] = None - return my_render_to_response("exam/quizzes_user.html", context) - - for answer_paper in user_answerpapers: - for quiz in avail_quizzes: + return my_render_to_response("exam/quizzes_user.html", context) + + for answer_paper in user_answerpapers: + for quiz in avail_quizzes: if answer_paper.question_paper.id == quiz.id and \ - answer_paper.end_time != answer_paper.start_time: + answer_paper.end_time != answer_paper.start_time: avail_quizzes.remove(quiz) - quizzes_taken.append(answer_paper) - + quizzes_taken.append(answer_paper) + context['quizzes'] = avail_quizzes context['user'] = user context['quizzes_taken'] = quizzes_taken @@ -183,7 +183,7 @@ def intro(request, questionpaper_id): else: context = {'user': user, 'cannot_attempt':True} return my_redirect("/exam/quizzes/?cannot_attempt=True") - + except: context = {'user': user, 'cannot_attempt':True} return my_redirect("/exam/quizzes/?cannot_attempt=True") -- cgit From e3b7611e7c6cbbe105b8c709c42ef9b4ae27e18b Mon Sep 17 00:00:00 2001 From: prathamesh Date: Thu, 3 Jul 2014 17:45:50 +0530 Subject: minor change --- testapp/exam/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testapp/exam/views.py b/testapp/exam/views.py index bee617d..38beb0d 100644 --- a/testapp/exam/views.py +++ b/testapp/exam/views.py @@ -203,7 +203,7 @@ def results_user(request): max_marks = paper.question_paper.total_marks percentage = round((marks_obtained/max_marks)*100, 2) temp = paper.question_paper.quiz.description, marks_obtained,\ - max_marks, percetage + max_marks, percentage quiz_marks.append(temp) context = {'papers': quiz_marks} return my_render_to_response("exam/results_user.html", context) -- cgit From 2d04f8cce5c5cf610b401ed37f796bd2034c07e9 Mon Sep 17 00:00:00 2001 From: prathamesh Date: Thu, 3 Jul 2014 17:53:18 +0530 Subject: Removed comments from base css --- testapp/static/exam/css/base.css | 98 ---------------------------------------- 1 file changed, 98 deletions(-) diff --git a/testapp/static/exam/css/base.css b/testapp/static/exam/css/base.css index d3a0a0a..051ba22 100644 --- a/testapp/static/exam/css/base.css +++ b/testapp/static/exam/css/base.css @@ -295,7 +295,6 @@ a:hover { width: 160px; } .span4 { -/* min-height : 500px; */ width: 220px; } .span5 { @@ -1898,26 +1897,6 @@ button.btn::-moz-focus-inner, input[type=submit].btn::-moz-focus-inner { padding: 0; border: 0; } -/*.close { - float: right; - color: #000000; - font-size: 20px; - font-weight: bold; - line-height: 13.5px; - text-shadow: 0 1px 0 #ffffff; - filter: alpha(opacity=25); - -khtml-opacity: 0.25; - -moz-opacity: 0.25; - opacity: 0.25; -} -.close:hover { - color: #000000; - text-decoration: none; - filter: alpha(opacity=40); - -khtml-opacity: 0.4; - -moz-opacity: 0.4; - opacity: 0.4; -}*/ .alert-message { position: relative; padding: 7px 15px; @@ -2081,83 +2060,6 @@ button.btn::-moz-focus-inner, input[type=submit].btn::-moz-focus-inner { -moz-opacity: 0.8; opacity: 0.8; } -/* -.modal { - position: fixed; - top: 50%; - left: 50%; - z-index: 11000; - width: 560px; - margin: -250px 0 0 -280px; - background-color: #ffffff; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, 0.3); - *border: 1px solid #999; - - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; -} -.modal .close { - margin-top: 7px; -} -.modal.fade { - -webkit-transform-style: preserve-3d; - -webkit-transition: opacity .3s linear, top .3s ease-out; - -moz-transition: opacity .3s linear, top .3s ease-out; - -ms-transition: opacity .3s linear, top .3s ease-out; - -o-transition: opacity .3s linear, top .3s ease-out; - transition: opacity .3s linear, top .3s ease-out; - top: -25%; -} -.modal.fade.in { - top: 50%; -} -.modal-header { - border-bottom: 1px solid #eee; - padding: 5px 15px; -} -.modal-body { - padding: 15px; -} -.modal-body form { - margin-bottom: 0; -} -.modal-footer { - background-color: #f5f5f5; - padding: 14px 15px 15px; - border-top: 1px solid #ddd; - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; - -webkit-box-shadow: inset 0 1px 0 #ffffff; - -moz-box-shadow: inset 0 1px 0 #ffffff; - box-shadow: inset 0 1px 0 #ffffff; - zoom: 1; - margin-bottom: 0; -} -.modal-footer:before, .modal-footer:after { - display: table; - content: ""; - zoom: 1; -} -.modal-footer:after { - clear: both; -} -.modal-footer .btn { - float: right; - margin-left: 5px; -} -.modal .popover, .modal .twipsy { - z-index: 12000; -} -*/ .modal { position: fixed; top: 10%; -- cgit