summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.txt11
-rw-r--r--grades/templates/add_grades.html5
-rw-r--r--grades/templates/grading_systems.html5
-rw-r--r--online_test/__init__.py2
-rw-r--r--requirements/requirements-common.txt1
-rw-r--r--yaksh/admin.py32
-rw-r--r--yaksh/error_messages.py3
-rw-r--r--yaksh/forms.py108
-rw-r--r--yaksh/java_stdio_evaluator.py3
-rw-r--r--yaksh/live_server_tests/selenium_test.py3
-rw-r--r--yaksh/migrations/0016_release_0_12_0.py20
-rw-r--r--yaksh/models.py7
-rw-r--r--yaksh/python_stdio_evaluator.py3
-rw-r--r--yaksh/r_code_evaluator.py96
-rw-r--r--yaksh/settings.py4
-rw-r--r--yaksh/static/yaksh/css/custom.css105
-rw-r--r--yaksh/static/yaksh/css/design_course.css17
-rw-r--r--yaksh/static/yaksh/css/question_paper_creation.css15
-rw-r--r--yaksh/static/yaksh/js/add_quiz.js4
-rw-r--r--yaksh/static/yaksh/js/course.js141
-rw-r--r--yaksh/static/yaksh/js/lesson.js24
-rw-r--r--yaksh/templates/base.html2
-rw-r--r--yaksh/templates/exam.html174
-rw-r--r--yaksh/templates/manage.html57
-rw-r--r--yaksh/templates/user.html95
-rw-r--r--yaksh/templates/yaksh/add_course.html7
-rw-r--r--yaksh/templates/yaksh/add_exercise.html127
-rw-r--r--yaksh/templates/yaksh/add_lesson.html206
-rw-r--r--yaksh/templates/yaksh/add_module.html153
-rw-r--r--yaksh/templates/yaksh/add_question.html12
-rw-r--r--yaksh/templates/yaksh/add_quiz.html152
-rw-r--r--yaksh/templates/yaksh/addteacher.html138
-rw-r--r--yaksh/templates/yaksh/complete.html27
-rw-r--r--yaksh/templates/yaksh/course_added_modules.html49
-rw-r--r--yaksh/templates/yaksh/course_detail.html435
-rw-r--r--yaksh/templates/yaksh/course_detail_options.html47
-rw-r--r--yaksh/templates/yaksh/course_modules.html321
-rw-r--r--yaksh/templates/yaksh/course_progress.html70
-rw-r--r--yaksh/templates/yaksh/course_send_mail.html63
-rw-r--r--yaksh/templates/yaksh/course_students.html245
-rw-r--r--yaksh/templates/yaksh/course_teachers.html29
-rw-r--r--yaksh/templates/yaksh/courses.html195
-rw-r--r--yaksh/templates/yaksh/design_course_session.html37
-rw-r--r--yaksh/templates/yaksh/design_questionpaper.html398
-rw-r--r--yaksh/templates/yaksh/error_template.html19
-rw-r--r--yaksh/templates/yaksh/grade_user.html827
-rw-r--r--yaksh/templates/yaksh/intro.html91
-rw-r--r--yaksh/templates/yaksh/lessons.html86
-rw-r--r--yaksh/templates/yaksh/login.html6
-rw-r--r--yaksh/templates/yaksh/moderator_dashboard.html19
-rw-r--r--yaksh/templates/yaksh/modules.html114
-rw-r--r--yaksh/templates/yaksh/monitor.html361
-rw-r--r--yaksh/templates/yaksh/preview_questionpaper.html30
-rw-r--r--yaksh/templates/yaksh/question.html498
-rw-r--r--yaksh/templates/yaksh/quit.html22
-rw-r--r--yaksh/templates/yaksh/quizzes.html122
-rw-r--r--yaksh/templates/yaksh/quizzes_user.html299
-rw-r--r--yaksh/templates/yaksh/show_video.html278
-rw-r--r--yaksh/templates/yaksh/showquestions.html38
-rw-r--r--yaksh/templates/yaksh/statistics_question.html41
-rw-r--r--yaksh/templates/yaksh/user_data.html595
-rw-r--r--yaksh/templates/yaksh/view_answerpaper.html576
-rw-r--r--yaksh/templatetags/custom_filters.py26
-rw-r--r--yaksh/templatetags/test_custom_filters.py11
-rw-r--r--yaksh/test_views.py226
-rw-r--r--yaksh/urls.py40
-rw-r--r--yaksh/views.py527
67 files changed, 5039 insertions, 3461 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index dc80135..4145e07 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,3 +1,14 @@
+=== 0.12.0 (04-02-2020) ===
+
+* Added syntax highlighting to the code answers in answerpaper
+* Added feature to allow adding newlines to Standard IO testcases
+* Added an evaluator to support R language
+* Fixed bug to only allow self created grading systems to show up in the course
+form
+* Fixed bug to hide deleted questions from search results
+* Fixed bug to check if residual files exist before teardown operations in
+JavaStdIOEvaluator
+
=== 0.11.0 (27-09-2019) ===
* Upgraded python-social-auth 0.2.19 to social-auth-app-django 3.1.0
diff --git a/grades/templates/add_grades.html b/grades/templates/add_grades.html
index 6a9dec9..59a344d 100644
--- a/grades/templates/add_grades.html
+++ b/grades/templates/add_grades.html
@@ -13,11 +13,6 @@
</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="{% url 'yaksh:allotted_courses' %}">
- Allotted Courses
- </a>
- </li>
- <li class="nav-item">
<a class="nav-link" href="{% url 'yaksh:add_course' %}">
Add New Course
</a>
diff --git a/grades/templates/grading_systems.html b/grades/templates/grading_systems.html
index 0b26e8e..8102230 100644
--- a/grades/templates/grading_systems.html
+++ b/grades/templates/grading_systems.html
@@ -12,11 +12,6 @@
</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="{% url 'yaksh:allotted_courses' %}">
- Allotted Courses
- </a>
- </li>
- <li class="nav-item">
<a class="nav-link" href="{% url 'yaksh:add_course' %}">
Add New Course
</a>
diff --git a/online_test/__init__.py b/online_test/__init__.py
index f323a57..2c7bffb 100644
--- a/online_test/__init__.py
+++ b/online_test/__init__.py
@@ -1 +1 @@
-__version__ = '0.11.0'
+__version__ = '0.12.0'
diff --git a/requirements/requirements-common.txt b/requirements/requirements-common.txt
index 913ef1f..54e4c84 100644
--- a/requirements/requirements-common.txt
+++ b/requirements/requirements-common.txt
@@ -9,3 +9,4 @@ selenium==2.53.6
coverage
ruamel.yaml==0.15.23
markdown==2.6.9
+pygments==2.2.0
diff --git a/yaksh/admin.py b/yaksh/admin.py
index 7ea8ed6..495b48d 100644
--- a/yaksh/admin.py
+++ b/yaksh/admin.py
@@ -1,6 +1,8 @@
from yaksh.models import Question, Quiz, QuestionPaper, Profile
from yaksh.models import (TestCase, StandardTestCase, StdIOBasedTestCase,
- Course, AnswerPaper)
+ Course, AnswerPaper, CourseStatus, LearningModule,
+ Lesson
+ )
from django.contrib import admin
@@ -14,12 +16,36 @@ class ProfileAdmin(admin.ModelAdmin):
"roll_number", "institute", "department"]
+class CourseStatusAdmin(admin.ModelAdmin):
+ search_fields = ['user__first_name', 'user__last_name', 'user__username']
+ list_filter = ['course__is_trial']
+
+
+class CourseAdmin(admin.ModelAdmin):
+ list_filter = ['active', 'is_trial']
+
+
+class LearningModuleAdmin(admin.ModelAdmin):
+ list_filter = ['active', 'is_trial']
+
+
+class LessonAdmin(admin.ModelAdmin):
+ list_filter = ['active']
+
+
+class QuizAdmin(admin.ModelAdmin):
+ list_filter = ['active', 'is_trial']
+
+
admin.site.register(Profile, ProfileAdmin)
admin.site.register(Question)
admin.site.register(TestCase)
admin.site.register(StandardTestCase)
admin.site.register(StdIOBasedTestCase)
-admin.site.register(Course)
-admin.site.register(Quiz)
+admin.site.register(Course, CourseAdmin)
+admin.site.register(Quiz, QuizAdmin)
admin.site.register(QuestionPaper)
admin.site.register(AnswerPaper, AnswerPaperAdmin)
+admin.site.register(CourseStatus, CourseStatusAdmin)
+admin.site.register(Lesson, LessonAdmin)
+admin.site.register(LearningModule, LearningModuleAdmin)
diff --git a/yaksh/error_messages.py b/yaksh/error_messages.py
index f34bf28..2d27417 100644
--- a/yaksh/error_messages.py
+++ b/yaksh/error_messages.py
@@ -34,8 +34,7 @@ def _get_incorrect_user_lines(exp_lines, user_lines):
err_line_numbers = []
for line_no, (expected_line, user_line) in \
enumerate(zip_longest(exp_lines, user_lines)):
- if (not user_line or not expected_line or
- user_line.strip() != expected_line.strip()):
+ if user_line != expected_line:
err_line_numbers.append(line_no)
return err_line_numbers
diff --git a/yaksh/forms.py b/yaksh/forms.py
index def9c32..73d4b54 100644
--- a/yaksh/forms.py
+++ b/yaksh/forms.py
@@ -3,6 +3,7 @@ from yaksh.models import (
get_model_class, Profile, Quiz, Question, Course, QuestionPaper, Lesson,
LearningModule
)
+from grades.models import GradingSystem
from django.contrib.auth import authenticate
from django.contrib.auth.models import User
from django.conf import settings
@@ -216,6 +217,13 @@ class UserLoginForm(forms.Form):
class ExerciseForm(forms.ModelForm):
+
+ def __init__(self, *args, **kwargs):
+ super(ExerciseForm, self).__init__(*args, **kwargs)
+ self.fields['description'].widget.attrs.update(
+ {'class': form_input_class, 'placeholder': "Exercise Description"}
+ )
+
class Meta:
model = Quiz
fields = ['description', 'view_answerpaper', 'active']
@@ -228,6 +236,34 @@ class QuizForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(QuizForm, self).__init__(*args, **kwargs)
+ self.fields['start_date_time'].widget.attrs.update(
+ {'class': form_input_class}
+ )
+ self.fields['end_date_time'].widget.attrs.update(
+ {'class': form_input_class}
+ )
+ self.fields['duration'].widget.attrs.update(
+ {'class': form_input_class}
+ )
+ self.fields['description'].widget.attrs.update(
+ {'class': form_input_class}
+ )
+ self.fields['attempts_allowed'].widget.attrs.update(
+ {'class': 'custom-select'}
+ )
+ self.fields['time_between_attempts'].widget.attrs.update(
+ {'class': form_input_class}
+ )
+ self.fields['instructions'].widget.attrs.update(
+ {'class': form_input_class}
+ )
+ self.fields['weightage'].widget.attrs.update(
+ {'class': form_input_class}
+ )
+ self.fields['pass_criteria'].widget.attrs.update(
+ {'class': form_input_class}
+ )
+
self.fields["instructions"].initial = dedent("""\
<p>
This examination system has been developed with the intention of
@@ -341,8 +377,26 @@ class QuestionFilterForm(forms.Form):
class CourseForm(forms.ModelForm):
""" course form for moderators """
+ class Meta:
+ model = Course
+ fields = [
+ 'name', 'enrollment', 'active', 'code', 'instructions',
+ 'start_enroll_time', 'end_enroll_time', 'grading_system',
+ 'view_grade'
+ ]
- def __init__(self, *args, **kwargs):
+ def save(self, commit=True, *args, **kwargs):
+ instance = super(CourseForm, self).save(commit=False)
+ if instance.code:
+ instance.hidden = True
+ else:
+ instance.hidden = False
+
+ if commit:
+ instance.save()
+ return instance
+
+ def __init__(self, user, *args, **kwargs):
super(CourseForm, self).__init__(*args, **kwargs)
self.fields['name'].widget.attrs.update(
{'class': form_input_class, 'placeholder': 'Course Name'}
@@ -365,25 +419,14 @@ class CourseForm(forms.ModelForm):
self.fields['grading_system'].widget.attrs.update(
{'class': 'custom-select'}
)
-
- def save(self, commit=True, *args, **kwargs):
- instance = super(CourseForm, self).save(commit=False)
- if instance.code:
- instance.hidden = True
+ if (self.instance.id and
+ self.instance.teachers.filter(id=user.id).exists()):
+ self.fields['grading_system'].widget.attrs['disabled'] = True
else:
- instance.hidden = False
-
- if commit:
- instance.save()
- return instance
-
- class Meta:
- model = Course
- fields = [
- 'name', 'enrollment', 'active', 'code', 'instructions',
- 'start_enroll_time', 'end_enroll_time', 'grading_system',
- 'view_grade'
- ]
+ grading_choices = GradingSystem.objects.filter(
+ creator=user
+ )
+ self.fields['grading_system'].queryset = grading_choices
class ProfileForm(forms.ModelForm):
@@ -446,9 +489,15 @@ class LessonForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(LessonForm, self).__init__(*args, **kwargs)
des_msg = "Enter Lesson Description as Markdown text"
- name_msg = "Enter Lesson Name"
- self.fields['description'].widget.attrs['placeholder'] = des_msg
- self.fields['name'].widget.attrs['placeholder'] = name_msg
+ self.fields['name'].widget.attrs.update(
+ {'class': form_input_class, 'placeholder': 'Lesson Name'}
+ )
+ self.fields['description'].widget.attrs.update(
+ {'class': form_input_class, 'placeholder': des_msg}
+ )
+ self.fields['video_file'].widget.attrs.update(
+ {'class': "custom-file-input"}
+ )
class Meta:
model = Lesson
@@ -468,17 +517,22 @@ class LessonForm(forms.ModelForm):
class LessonFileForm(forms.Form):
- Lesson_files = forms.FileField(widget=forms.ClearableFileInput(
- attrs={'multiple': True}),
- required=False)
+ Lesson_files = forms.FileField(
+ widget=forms.ClearableFileInput(
+ attrs={'multiple': True, 'class': "custom-file-input"}),
+ required=False)
class LearningModuleForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(LearningModuleForm, self).__init__(*args, **kwargs)
- name_msg = "Enter Learning Module Name"
- self.fields['name'].widget.attrs['placeholder'] = name_msg
self.fields['name'].widget.attrs['size'] = 30
+ self.fields['name'].widget.attrs.update(
+ {'class': form_input_class, 'placeholder': 'Module Name'}
+ )
+ self.fields['description'].widget.attrs.update(
+ {'class': form_input_class, 'placeholder': 'Module Description'}
+ )
class Meta:
model = LearningModule
diff --git a/yaksh/java_stdio_evaluator.py b/yaksh/java_stdio_evaluator.py
index 89f9fc4..0d7e480 100644
--- a/yaksh/java_stdio_evaluator.py
+++ b/yaksh/java_stdio_evaluator.py
@@ -26,7 +26,8 @@ class JavaStdIOEvaluator(StdIOEvaluator):
self.weight = test_case_data.get('weight')
def teardown(self):
- os.remove(self.submit_code_path)
+ if os.path.exists(self.submit_code_path):
+ os.remove(self.submit_code_path)
if self.files:
delete_files(self.files)
diff --git a/yaksh/live_server_tests/selenium_test.py b/yaksh/live_server_tests/selenium_test.py
index 41a0fad..6d9117d 100644
--- a/yaksh/live_server_tests/selenium_test.py
+++ b/yaksh/live_server_tests/selenium_test.py
@@ -74,6 +74,7 @@ class SeleniumTest():
submit_answer_elem.click()
WebDriverWait(self.driver, 90).until(ElementDisplay(
(By.XPATH, "//*[@id='ontop']")))
+ self.driver.execute_script("scrollBy(0,-1000);")
def test_c_question(self, question_label):
# Incorrect Answer
@@ -127,7 +128,7 @@ class SeleniumTest():
# open module link
self.driver.find_elements_by_partial_link_text(
'START')[0].click()
- self.driver.find_element_by_link_text('Start').click()
+ self.driver.find_element_by_link_text('START').click()
# open quiz link
self.driver.find_element_by_link_text(self.quiz_name).click()
diff --git a/yaksh/migrations/0016_release_0_12_0.py b/yaksh/migrations/0016_release_0_12_0.py
new file mode 100644
index 0000000..74edaa5
--- /dev/null
+++ b/yaksh/migrations/0016_release_0_12_0.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.21 on 2020-02-05 05:38
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('yaksh', '0015_release_0_10_0'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='question',
+ name='language',
+ field=models.CharField(choices=[('python', 'Python'), ('bash', 'Bash'), ('c', 'C Language'), ('cpp', 'C++ Language'), ('java', 'Java Language'), ('scilab', 'Scilab'), ('r', 'R')], max_length=24),
+ ),
+ ]
diff --git a/yaksh/models.py b/yaksh/models.py
index 6881b4f..efd4fd7 100644
--- a/yaksh/models.py
+++ b/yaksh/models.py
@@ -46,6 +46,7 @@ languages = (
("cpp", "C++ Language"),
("java", "Java Language"),
("scilab", "Scilab"),
+ ("r", "R"),
)
question_types = (
@@ -879,6 +880,7 @@ class Course(models.Model):
copy_module_name = "Copy of {0}".format(module.name)
new_module = module._create_module_copy(user, copy_module_name)
new_course.learning_module.add(new_module)
+ return new_course
def request(self, *users):
self.requests.add(*users)
@@ -1160,6 +1162,11 @@ class CourseStatus(models.Model):
self.current_unit = unit
self.save()
+ def __str__(self):
+ return "{0} status for {1}".format(
+ self.course.name, self.user.username
+ )
+
###############################################################################
class ConcurrentUser(models.Model):
diff --git a/yaksh/python_stdio_evaluator.py b/yaksh/python_stdio_evaluator.py
index 64a2809..a1e8f72 100644
--- a/yaksh/python_stdio_evaluator.py
+++ b/yaksh/python_stdio_evaluator.py
@@ -46,6 +46,7 @@ class PythonStdIOEvaluator(BaseEvaluator):
if self.file_paths:
self.files = copy_files(self.file_paths)
submitted = compile(self.user_answer, '<string>', mode='exec')
+ self.expected_output = self.expected_output.replace('\r', '')
if self.expected_input:
self.expected_input = self.expected_input.replace('\r', '')
input_buffer = StringIO()
@@ -55,7 +56,7 @@ class PythonStdIOEvaluator(BaseEvaluator):
with redirect_stdout() as output_buffer:
exec_scope = {}
exec(submitted, exec_scope)
- self.output_value = output_buffer.getvalue().rstrip("\n")
+ self.output_value = output_buffer.getvalue()
return self.output_value
def check_code(self):
diff --git a/yaksh/r_code_evaluator.py b/yaksh/r_code_evaluator.py
new file mode 100644
index 0000000..ca4c94a
--- /dev/null
+++ b/yaksh/r_code_evaluator.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+from __future__ import unicode_literals
+import os
+import subprocess
+import re
+
+# Local imports
+from .base_evaluator import BaseEvaluator
+from .file_utils import copy_files, delete_files
+
+
+class RCodeEvaluator(BaseEvaluator):
+ """Tests the R code obtained from Code Server"""
+ def __init__(self, metadata, test_case_data):
+ self.files = []
+ self.submit_code_path = ""
+ self.test_code_path = ""
+ # Set metadata values
+ self.user_answer = metadata.get('user_answer')
+ self.file_paths = metadata.get('file_paths')
+ self.partial_grading = metadata.get('partial_grading')
+
+ # Set test case data values
+ self.test_case = test_case_data.get('test_case')
+ self.weight = test_case_data.get('weight')
+
+ def teardown(self):
+ # Delete the created file.
+ if os.path.exists(self.submit_code_path):
+ os.remove(self.submit_code_path)
+ if os.path.exists(self.test_code_path):
+ os.remove(self.test_code_path)
+ if self.files:
+ delete_files(self.files)
+
+ def check_code(self):
+ self.submit_code_path = self.create_submit_code_file('function.r')
+ self.test_code_path = self.create_submit_code_file('main.r')
+ if self.file_paths:
+ self.files = copy_files(self.file_paths)
+ clean_ref_path = self.test_code_path
+ self.user_answer, terminate_commands = \
+ self._remove_r_quit(self.user_answer.lstrip())
+
+ success = False
+ mark_fraction = 0.0
+ self.write_to_submit_code_file(self.submit_code_path, self.user_answer)
+ self.write_to_submit_code_file(self.test_code_path, self.test_case)
+ # Throw message if there are commmands that terminates scilab
+ add_err = ""
+ if terminate_commands:
+ add_err = "Please do not use quit() in your\
+ code.\n Otherwise your code will not be evaluated\
+ correctly.\n"
+
+ cmd = 'Rscript main.r'
+ ret = self._run_command(cmd, shell=True, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE
+ )
+ proc, stdout, stderr = ret
+
+ if stderr is '':
+ # Clean output
+ stdout = self._strip_output(stdout)
+ if proc.returncode == 31:
+ success, err = True, None
+ mark_fraction = 1.0 if self.partial_grading else 0.0
+ else:
+ err = add_err + stdout
+ else:
+ err = add_err + stderr
+
+ return success, err, mark_fraction
+
+ def _remove_r_quit(self, string):
+ """
+ Removes quit from the R code
+ """
+ new_string = ""
+ terminate_commands = False
+ for line in string.splitlines():
+ new_line = re.sub(r"quit.*$", "", line)
+ if line != new_line:
+ terminate_commands = True
+ new_string = new_string + '\n' + new_line
+ return new_string, terminate_commands
+
+ def _strip_output(self, out):
+ """
+ Cleans whitespace from the output
+ """
+ strip_out = "Message"
+ for l in out.split('\n'):
+ if l.strip():
+ strip_out = strip_out+"\n"+l.strip()
+ return strip_out + out
diff --git a/yaksh/settings.py b/yaksh/settings.py
index 9e9597d..7b42298 100644
--- a/yaksh/settings.py
+++ b/yaksh/settings.py
@@ -55,4 +55,8 @@ code_evaluators = {
"standardtestcase": "yaksh.scilab_code_evaluator.ScilabCodeEvaluator",
"hooktestcase": "yaksh.hook_evaluator.HookEvaluator"
},
+ "r": {
+ "standardtestcase": "yaksh.r_code_evaluator.RCodeEvaluator",
+ "hooktestcase": "yaksh.hook_evaluator.HookEvaluator"
+ },
}
diff --git a/yaksh/static/yaksh/css/custom.css b/yaksh/static/yaksh/css/custom.css
index 55d5d6d..63ee455 100644
--- a/yaksh/static/yaksh/css/custom.css
+++ b/yaksh/static/yaksh/css/custom.css
@@ -1,25 +1,3 @@
-.yakshfooter {
- background-color: #142624;
- padding-top: 1%;
- padding-left: 10%;
- padding-right: 10%;
- padding-bottom: 1%;
- color: white;
- bottom: 0;
- width: 100%;
- position: absolute;
- text-align: center;
-}
-
-.yakshfooter .nav-pills>li>a, .yakshfooter .nav-pills .nav-link,.yakshnav .nav-pills>li>a {
- color: white;
-}
-
-.yakshfooter .nav-pills>li>a:hover, .yakshnav .nav-pills>li>a:hover {
- color: black;
- background-color: white;
-}
-
body, .dropdown-menu {
font-size: 1.25rem;
}
@@ -36,3 +14,86 @@ body, .dropdown-menu {
.dropdown {
display: flex;
}
+
+.course-detail, #result-table {
+ table-layout: fixed;
+ width: 100%;
+}
+
+.course-detail, #result-table > th, td {
+ word-wrap: break-word;
+}
+
+#rendered_text{
+ width: 550px;
+}
+
+.navbar {
+ padding: 15px 10px;
+ background: #fff;
+ border: none;
+ border-radius: 0;
+ margin-bottom: 40px;
+ box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);
+}
+
+.navbar-btn {
+ box-shadow: none;
+ outline: none !important;
+ border: none;
+}
+
+.line {
+ width: 100%;
+ height: 1px;
+ border-bottom: 1px dashed #ddd;
+ margin: 40px 0;
+}
+
+/* ---------------------------------------------------
+ SIDEBAR STYLE
+----------------------------------------------------- */
+
+.wrapper {
+ display: flex;
+ width: 100%;
+ align-items: stretch;
+}
+
+#sidebar {
+ min-width: 350px;
+ max-width: 350px;
+ background: #fff;
+ transition: all 0.3s;
+}
+
+#sidebar.active {
+ margin-left: -350px;
+}
+
+#sidebar .sidebar-header {
+ padding: 20px;
+ background: #158CBA;
+}
+
+#sidebar ul.components {
+ padding: 20px 0;
+ border-bottom: 1px solid #fff;
+}
+
+#sidebar ul li a {
+ padding: 10px;
+ font-size: 1.1em;
+ display: block;
+}
+
+/* ---------------------------------------------------
+ CONTENT STYLE
+----------------------------------------------------- */
+
+#content {
+ width: 100%;
+ padding: 20px;
+ min-height: 100vh;
+ transition: all 0.3s;
+}
diff --git a/yaksh/static/yaksh/css/design_course.css b/yaksh/static/yaksh/css/design_course.css
index d1bf4bd..a0dcd10 100644
--- a/yaksh/static/yaksh/css/design_course.css
+++ b/yaksh/static/yaksh/css/design_course.css
@@ -1,17 +1,6 @@
-body {
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 13px;
- font-weight: normal;
- line-height: 18px;
- color: #404040;
-}
-
-#available-lesson-quiz .col-md-8 > div{
+#available-lesson-quiz .col-md-12 > div{
background: #f5f5f5;
border: 1px solid #333333;
overflow-y: scroll;
- height: 300px;
-}
-#available-lesson-quiz .available-list > div{
- height: 300px;
-}
+ height: 400px;
+} \ No newline at end of file
diff --git a/yaksh/static/yaksh/css/question_paper_creation.css b/yaksh/static/yaksh/css/question_paper_creation.css
index ff4bf32..bc8feeb 100644
--- a/yaksh/static/yaksh/css/question_paper_creation.css
+++ b/yaksh/static/yaksh/css/question_paper_creation.css
@@ -1,10 +1,3 @@
-body {
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 13px;
- font-weight: normal;
- line-height: 18px;
- color: #404040;
-}
.nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus {
background-color: #FFFFFF;
border-color: #DDDDDD #DDDDDD rgba(0, 0, 0, 0);
@@ -63,20 +56,20 @@ body {
#fixed-questions .col-md-6 > div,
#random-questions .col-md-6 > div{
background: #f5f5f5;
- height: 200px;
+ height: 300px;
border: 1px solid #333333;
padding: 5px;
}
#fixed-available,
#random-available {
- height: 125px;
- min-height: 125px;
+ height: 220px;
+ min-height: 200px;
overflow-y: scroll;
margin-bottom: 15px;
}
#fixed-added,
#random-added {
- height: 160px;
+ height: 220px;
overflow-y: scroll;
}
#fixed-added hr,
diff --git a/yaksh/static/yaksh/js/add_quiz.js b/yaksh/static/yaksh/js/add_quiz.js
index 57993ef..dab5a3d 100644
--- a/yaksh/static/yaksh/js/add_quiz.js
+++ b/yaksh/static/yaksh/js/add_quiz.js
@@ -1,8 +1,8 @@
function test()
{
- document.getElementById('id_duration').setAttribute('class','mini-text');
- document.getElementById('id_pass_criteria').setAttribute('class','mini-text');
+ document.getElementById('id_duration').setAttribute('class','mini-text form-control');
+ document.getElementById('id_pass_criteria').setAttribute('class','mini-text form-control');
if (document.getElementById("id_description").value != "")
{
document.getElementById("submit").innerHTML = "Save";
diff --git a/yaksh/static/yaksh/js/course.js b/yaksh/static/yaksh/js/course.js
index bd197a8..a4b5579 100644
--- a/yaksh/static/yaksh/js/course.js
+++ b/yaksh/static/yaksh/js/course.js
@@ -1,5 +1,5 @@
$(document).ready(function(){
-$(".checkall").change( function(){
+ $(".checkall").change( function(){
if($(this).prop("checked")) {
$("#enroll-all input:checkbox").each(function(index, element) {
$(this).prop('checked', true);
@@ -11,7 +11,7 @@ $(".checkall").change( function(){
});
}
});
-$(".enroll").change( function(){
+ $(".enroll").change( function(){
if($(this).prop("checked")) {
$("#enroll input:checkbox").each(function(index, element) {
$(this).prop('checked', true);
@@ -23,7 +23,7 @@ $(".enroll").change( function(){
});
}
});
-$(".reject").change( function(){
+ $(".reject").change( function(){
if($(this).prop("checked")) {
$("#reject input:checkbox").each(function(index, element) {
$(this).prop('checked', true);
@@ -36,68 +36,95 @@ $(".reject").change( function(){
}
});
-$(function() {
- tinymce.init({
- selector: 'textarea#email_body',
- max_height: 200,
- height: 200
+ $(".send_check").change( function(){
+ if($(this).prop("checked")) {
+ $("#sender_list input:checkbox").each(function(index, element) {
+ $(this).prop('checked', true);
+ });
+ }
+ else {
+ $("#sender_list input:checkbox").each(function(index, element) {
+ $(this).prop('checked', false);
+ });
+ }
});
-});
-$("#send_mail").click(function(){
- var subject = $("#subject").val();
- var body = tinymce.get("email_body").getContent();
- var status = false;
- var selected = [];
- $('#reject input:checked').each(function() {
- selected.push($(this).attr('value'));
+ $(function() {
+ tinymce.init({
+ selector: 'textarea#email_body',
+ max_height: 200,
+ height: 200
+ });
});
- if (subject == '' || body == ''){
- $("#error_msg").html("Please enter mail details");
- $("#dialog").dialog();
- }
- else if (selected.length == 0){
- $("#error_msg").html("Please select atleast one user");
- $("#dialog").dialog();
- }
- else {
- status = true;
- }
- return status;
-});
+ $("#send_mail").click(function(){
+ var subject = $("#subject").val();
+ var body = tinymce.get("email_body").getContent();
+ var status = false;
+ var selected = [];
+ $('#sender_list input:checked').each(function() {
+ selected.push($(this).attr('value'));
+ });
+ if (subject == '' || body == ''){
+ $("#error_msg").html("Please enter mail details");
+ $("#dialog").dialog();
+ }
+ else if (selected.length == 0){
+ $("#error_msg").html("Please select atleast one user");
+ $("#dialog").dialog();
+ }
+ else {
+ status = true;
+ }
+ return status;
+ });
-// Table sorter for course details
-$("table").tablesorter({});
-// Get user course completion status
-$('.user_data').click(function() {
- var data = $(this).data('item-id');
- course_id = data.split("+")[0];
- student_id = data.split("+")[1];
- var status_div = $("#show_status_"+course_id+"_"+student_id);
- if(!status_div.is(":visible")){
- var get_url = window.location.protocol + "//" + window.location.host +
- "/exam/manage/get_user_status/" + course_id + "/" + student_id;
- $.ajax({
- url: get_url,
- timeout: 8000,
- type: "GET",
- dataType: "json",
- contentType: 'application/json; charset=utf-8',
- success: function(data) {
+ // Table sorter for course details
+ $("table").tablesorter({});
+
+ // Get user course completion status
+ $('.user_data').click(function() {
+ var data = $(this).data('item-id');
+ course_id = data.split("+")[0];
+ student_id = data.split("+")[1];
+ var status_div = $("#show_status_"+course_id+"_"+student_id);
+ if(!status_div.is(":visible")){
+ var get_url = $("#url-"+student_id).attr("data-url");
+ $.ajax({
+ url: get_url,
+ timeout: 8000,
+ type: "GET",
+ dataType: "json",
+ contentType: 'application/json; charset=utf-8',
+ success: function(data) {
status_div.toggle();
status_div.html(data.user_data);
- },
- error: function(jqXHR, textStatus) {
- alert("Unable to get user data. Please Try again later.");
- }
- });
- } else {
- status_div.toggle();
- }
-});
+ },
+ error: function(jqXHR, textStatus) {
+ alert("Unable to get user data. Please Try again later.");
+ }
+ });
+ } else {
+ status_div.toggle();
+ }
+ });
-$('[data-toggle="tooltip"]').tooltip();
+ $('[data-toggle="tooltip"]').tooltip();
+ $('#upload').on('change',function(){
+ //get the file name
+ var files = [];
+ for (var i = 0; i < $(this)[0].files.length; i++) {
+ files.push($(this)[0].files[i].name);
+ }
+ $(this).next('.custom-file-label').html(files.join(', '));
+ });
+
+ $('[data-toggle="tab"]').tooltip({
+ trigger: 'hover',
+ placement: 'top',
+ animate: false,
+ container: 'body'
+ });
}); // end document ready
diff --git a/yaksh/static/yaksh/js/lesson.js b/yaksh/static/yaksh/js/lesson.js
index 6f873b9..55d4846 100644
--- a/yaksh/static/yaksh/js/lesson.js
+++ b/yaksh/static/yaksh/js/lesson.js
@@ -44,9 +44,9 @@ $(document).ready(function(){
$("#embed").click(function() {
$("#dialog_iframe").toggle();
$("#dialog_iframe").dialog({
- resizable: false,
- height: '300',
- width: '450'
+ resizable: true,
+ height: '450',
+ width: '640'
});
});
@@ -75,4 +75,22 @@ $(document).ready(function(){
alert("Unable to copy. Press Ctrl+C or Cmd+C to copy")
}
});
+
+ $('#id_video_file').on('change',function(){
+ //get the file name
+ var files = [];
+ for (var i = 0; i < $(this)[0].files.length; i++) {
+ files.push($(this)[0].files[i].name);
+ }
+ $(this).next('.custom-file-label').html(files.join(', '));
+ });
+
+ $('#id_Lesson_files').on('change',function(){
+ //get the file name
+ var files = [];
+ for (var i = 0; i < $(this)[0].files.length; i++) {
+ files.push($(this)[0].files[i].name);
+ }
+ $(this).next('.custom-file-label').html(files.join(', '));
+ });
});
diff --git a/yaksh/templates/base.html b/yaksh/templates/base.html
index 0cfe8a3..c70c265 100644
--- a/yaksh/templates/base.html
+++ b/yaksh/templates/base.html
@@ -49,7 +49,7 @@
<div id="ontop">
<div id="state">
- Checking...<img src="{{ URL_ROOT }}/static/yaksh/images/check_answer.gif"/>
+ Checking...<img src="{% static 'yaksh/images/check_answer.gif' %}"/>
</div></div>
diff --git a/yaksh/templates/exam.html b/yaksh/templates/exam.html
index d439c64..a773076 100644
--- a/yaksh/templates/exam.html
+++ b/yaksh/templates/exam.html
@@ -1,83 +1,94 @@
{% extends "base.html" %}
{% load custom_filters %}
+{% load static %}
+
+{% block title %}{{ paper.question_paper.quiz.description }}{% endblock %}
+
{% block nav %}
-<div class="container-fluid yakshnav">
- <nav class="navbar fixed-top navbar-expand-lg yakshheading yakshnav">
- <div class="container">
- <button class="navbar-toggler navbar-dark" type="button" data-toggle="collapse" data-target="#myNavbar" aria-controls="myNavbar" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon" style="color: white"></span>
- </button>
- <a class="navbar-brand">
- <img src="{{ URL_ROOT }}/static/yaksh/images/yaksh_banner.png" alt="YAKSH">
- </img>
- </a>
- <div class="collapse navbar-collapse col-md-6" id="myNavbar">
- <div class="nav nav-pills nav-fill ml-auto">
- <span class="time-div nav-item" id="time_left" ></span>
- <form id="logout" action="{{URL_ROOT}}/exam/quit/{{ paper.attempt_number }}/{{module.id}}/{{ paper.question_paper.id }}/{{course.id}}/" method="post" class="ml-auto">
- {% csrf_token %}
- <span class="nav-item"><button class="nav-link btn-danger" type="submit" name="quit">
- {% if paper.questions_unanswered.all %}
- Quit {{ quiz_type }}
- {% else %}
- Finish {{ quiz_type }}
- {% endif %}
- <span class="fa fa-power-off"></span></button></span>
- </form>
- </div>
- </div><!-- /.navbar -->
- </div><!-- /.container -->
- </nav><!-- /.navbar -->
+<div class="container-fluid">
+ <nav class="navbar navbar-expand-sm navbar-dark bg-primary fixed-top">
+ <img src="{% static 'yaksh/images/yaksh_banner.png' %}" alt="YAKSH">
+ <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
+ <span class="navbar-toggler-icon"></span>
+ </button>
+
+ <div class="collapse navbar-collapse" id="navbarColor01">
+ <div class="row ml-auto">
+ <div class="col-md-4">
+ <span class="time-div nav-item" id="time_left"></span>
+ </div>
+ <div class="col-md-7">
+ <form id="logout" action="{% url 'yaksh:quit_quiz' paper.attempt_number module.id paper.question_paper.id course.id %}" method="post" class="ml-auto">
+ {% csrf_token %}
+ <span class="nav-item"><button class="btn btn-danger btn-lg" type="submit" name="quit">
+ {% if paper.questions_unanswered.all %}
+ Quit {{quiz_type}}
+ {% else %}
+ Finish {{quiz_type}}
+ {% endif %}
+ <i class="fa fa-power-off"></i></button></span>
+ </form>
+ </div>
+ </div>
+ </div>
+ </nav>
</div>
{% endblock %}
{% block content %}
<div class="container-fluid">
<div class="row">
- <!-- Side bar -->
- <div class="col-md-3 yakshlabel collapse" id="sidebar">
- <center>
- <b class="yakshheading">{{course.name}}</b><br>
- {{ paper.question_paper.quiz.description }}</h4>
- <hr>
- </center>
- <div class="yakshwell">
- <p class="text-center">Question Navigator</p>
- <div>
- {% for qid in paper.get_all_ordered_questions %}
- {%if paper.question_paper.quiz.allow_skip %}
- {% if qid in paper.get_questions_unanswered %}
- {% if qid.id == question.id %}
- <a class="active btn btn-outline-success " href="#"data-toggle="tooltip"
- title="{{ qid.description|striptags }}"
- onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ qid.id }}/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')">{{ forloop.counter }}</a>
- {% else %}
- <a class=" btn btn-outline-success " href="#" data-toggle="tooltip" title="{{ qid.description|striptags }}"
- onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ qid.id }}/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')">{{ forloop.counter }}</a>
- {% endif %}
- {% endif %}
- {% if qid in paper.get_questions_answered %}
- <a class="btn btn-outline-light question-nav-bg" href="#" data-toggle="tooltip"
- onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ qid.id }}/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')"
- title="{{ qid.description }}">{{ forloop.counter }}</a>
- {% endif %}
- {% else %}
- {% if qid.id == question.id %}
- <a class="active btn btn-outline-success" data-toggle="tooltip" title="{{ qid.description|striptags }}">{{ forloop.counter }}</a>
- {% elif qid in paper.get_questions_answered %}
- <a class="btn btn-outline-success question-nav-bg" href="#" data-toggle="tooltip"
- onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ qid.id }}/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')"
- title="{{ qid.description }}">{{ forloop.counter }}</a>
- {% else %}
- <a class="disabled btn btn-outline-success " data-toggle="tooltip" title="{{ qid.description|striptags }}">{{ forloop.counter }}</a>
- {% endif %}
- {% endif %}
- {% endfor %}
- </div>
- <br>
- <p class="text-center">Question(s) left: <b>{{ paper.questions_left }}</b></p>
- </div>
- <br>
- <table class = "legend_table table-bordered table-sm">
+ <!-- Side Component -->
+ <div class="col-md-3 bg-secondary" style="overflow-x: scroll;">
+ <br>
+ <center>
+ <b>{{course.name}}</b><br>
+ {{ paper.question_paper.quiz.description }}</h4>
+ </center>
+ <hr>
+ <center><p><b><u>Question Navigator</b></u></p></center>
+ <br>
+ <div class="justify-content-center">
+ {% for qid in paper.get_all_ordered_questions %}
+ {% if paper.question_paper.quiz.allow_skip %}
+ {% if qid in paper.get_questions_unanswered %}
+ {% if qid.id == question.id %}
+ <a class="active btn btn-outline-primary " href="#"data-toggle="tooltip"
+ title="{{ qid.description|striptags|truncatechars:100 }}" style="width: 50px"
+ onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ qid.id }}/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')">{{ forloop.counter }}</a>
+ {% else %}
+ <a class=" btn btn-outline-primary " href="#" data-toggle="tooltip" title="{{ qid.description|striptags|truncatechars:100 }}" style="width: 50px"
+ onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ qid.id }}/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')">{{ forloop.counter }}</a>
+ {% endif %}
+ {% endif %}
+ {% if qid in paper.get_questions_answered %}
+ <a class="btn btn-success" href="#" data-toggle="tooltip" style="width: 50px"
+ onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ qid.id }}/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')"
+ title="{{ qid.description|striptags|truncatechars:100 }}">{{ forloop.counter }}</a>
+ {% endif %}
+ {% else %}
+ {% if qid.id == question.id %}
+ <a class="active btn btn-outline-primary" data-toggle="tooltip" title="{{ qid.description|striptags|truncatechars:100 }}" style="width: 50px">{{ forloop.counter }}</a>
+ {% elif qid in paper.get_questions_answered %}
+ <a class="btn btn-success" href="#" data-toggle="tooltip" style="width: 50px"
+ onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ qid.id }}/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')"
+ title="{{ qid.description|striptags|truncatechars:100 }}">{{ forloop.counter }}</a>
+ {% else %}
+ <a class="btn btn-outline-primary" style="width: 50px" data-toggle="tooltip" title="{{ qid.description|striptags|truncatechars:100 }}">{{ forloop.counter }}</a>
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+ </div>
+ <br>
+ <p><span class="btn btn-success"></span> Attempted question(s)</p>
+ <p><span class="btn btn-primary"></span> Current question</p>
+ <p><span class="btn btn-outline-primary"></span> Unattempted question(s)</p>
+ <br>
+ <div>
+ <p class="text-center">Question(s) left: <b>{{ paper.questions_left }}</b></p>
+ </div>
+ <br>
+ <div>
+ <table class="table table-bordered table-responsive-sm">
<thead>
<tr>
<th>Category</th>
@@ -97,16 +108,15 @@
{% endfor %}
</tbody>
</table>
- </div> <!--end of sidebar -->
- <a href="#sidebar" data-toggle="collapse" id="sidebaricon"><i class="fa fa-navicon fa-lg"></i></a>
-
- <main class="col" id="sidebarbody">
- <div class="container-fluid yakshwell">
-
- {% block main %}
- {% endblock %}
- </div>
- </main>
+ <br>
+ </div>
+ </div>
+ <!-- Main Component -->
+ <div class="col-md-9">
+ <br>
+ {% block main %}
+ {% endblock %}
+ </div>
</div>
</div>
diff --git a/yaksh/templates/manage.html b/yaksh/templates/manage.html
index 9557582..8e74494 100644
--- a/yaksh/templates/manage.html
+++ b/yaksh/templates/manage.html
@@ -46,38 +46,35 @@
</div>
</nav>
+<!-- iframe div for video embed -->
+<div id="iframe_div" style="display: none;">
+ <iframe class="embed-responsive-item" id="video_frame" width="640" height="480" allowfullscreen>
+ </iframe>
+</div>
+<!-- end iframe div -->
-
- <!-- iframe div for video embed -->
- <div id="iframe_div" style="display: none;">
- <div class="embed-responsive embed-responsive-16by9" style=" position: relative;">
- <iframe class="embed-responsive-item" id="video_frame" width="800" height="500" allowfullscreen>
- </iframe>
- <div style="width: 80px; height: 80px; position: absolute; opacity: 0; right: 0px; top: 0px;">&nbsp;
- </div>
- </div>
- </div>
- <!-- end iframe div -->
-
- <!-- Dialog to video embed -->
- <div id="dialog_iframe" title="Embed Video URL" style="display: none;">
- <label>Enter embed url:</label>
- <input id="url" name="url" type="text" required="true">
- <input type="button" id="submit_info" name="submit_info" class="btn" value="Submit" />
- <div id="error_div" style="display: none;">
- <b> Please enter URL</b>
- </div>
- <div id="copy_div">
- <br>
- <label>Paste HTML to embed in website:</label>
- <textarea rows="5" cols="35" id="html_text"></textarea>
- <br>
- <a class="btn btn-default" id="copy" data-toggle="tooltip" title="Copy to Clipboard">
- <i class="fa fa-clipboard" aria-hidden="true"></i>
- </a>
- </div>
+<!-- Dialog to video embed -->
+<div id="dialog_iframe" title="Embed Video URL" style="display: none;">
+ <div class="input-group mb-3">
+ <input id="url" name="url" type="text" required="true" class="form-control" placeholder="Enter video link">
+ <div class="input-group-append">
+ <input type="button" id="submit_info" name="submit_info" class="btn btn-primary" value="Submit" />
</div>
- <!-- end dialog -->
+ </div>
+ <div id="error_div" style="display: none;">
+ <b> Please enter URL</b>
+ </div>
+ <div id="copy_div">
+ <br>
+ <label>Paste HTML to embed in website:</label>
+ <textarea id="html_text" class="form-control" rows="5" cols="100"></textarea>
+ <br>
+ <a class="btn btn-secondary" id="copy" data-toggle="tooltip" title="Copy to Clipboard">
+ <i class="fa fa-clipboard" aria-hidden="true"></i>
+ </a>
+ </div>
+</div>
+<!-- end dialog -->
{% endblock %}
{% block content %}
diff --git a/yaksh/templates/user.html b/yaksh/templates/user.html
index 4ded0a3..4e3974b 100644
--- a/yaksh/templates/user.html
+++ b/yaksh/templates/user.html
@@ -1,39 +1,46 @@
{% extends "base.html" %}
-
+{% load static %}
{% block nav %}
-<div class="container-fluid yakshnav">
-<nav class="navbar fixed-top navbar-expand-lg yakshheading yakshnav">
- <div class="container">
- <button class="navbar-toggler navbar-dark" type="button" data-toggle="collapse" data-target="#myNavbar" aria-controls="myNavbar" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon" style="color: white"></span>
- </button>
- <a class="navbar-brand" href="{{ URL_ROOT }}/exam/">
- <img src="{{ URL_ROOT }}/static/yaksh/images/yaksh_banner.png" alt="YAKSH" style="margin-top: -3px; margin-left:-15px">
- </img>
- </a>
- <div class="collapse navbar-collapse" id="myNavbar">
- <ul class="nav nav-pills ml-auto">
- <li class="nav-item"><a class="nav-link" href="{{ URL_ROOT }}/exam/"><i class="fa fa-home" style="size: 18px"></i></a></li>
- <li class="nav-item dropdown">
- <a class="dropdown-toggle nav-link" id="user_dropdown" data-toggle="dropdown" href="#"> {{user.get_full_name|title}}</a>
- <div class="dropdown-menu">
- <a class="dropdown-item" href="{{ URL_ROOT }}/exam/viewprofile/"><i class="fa fa-user"></i> My Profile</a>
- <div class="dropdown-divider"></div>
- {% if user.profile.is_moderator %}
- <a class="dropdown-item" href="{{URL_ROOT}}/exam/toggle_moderator/"><i class="fa fa-exchange"></i>
- Switch To Moderator
- </a>
- <div class="dropdown-divider"></div>
- {% endif %}
- <a class="dropdown-item" href="{{ URL_ROOT }}/exam/reset/changepassword/"><i class="fa fa-key"></i> Change Password</a>
- <div class="dropdown-divider"></div>
- <a id="user_logout" class="dropdown-item" href="{{URL_ROOT}}/exam/logout/"><i class="fa fa-sign-out"></i> Logout</a>
- </div>
- </li>
+<div class="container-fluid">
+ <nav class="navbar navbar-expand-sm navbar-dark bg-primary fixed-top">
+ <a class="navbar-brand" href="{% url 'yaksh:index' %}">
+ <img src="{% static 'yaksh/images/yaksh_banner.png' %}" alt="YAKSH">
+ </a>
+ <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
+ <span class="navbar-toggler-icon"></span>
+ </button>
+
+ <div class="collapse navbar-collapse" id="navbarColor01">
+ <ul class="navbar-nav mr-auto">
+ <li class="nav-item"><a class="nav-link" href="{% url 'yaksh:index' %}"><i class="fa fa-home" style="size: 18px"></i>&nbsp;Home</a></li>
</ul>
- </div>
- </div>
-</nav>
+ <ul class="navbar-nav ml-auto">
+ <li class="nav-item dropdown my-lg-0" style="font-size: 1.2rem">
+ <a class="dropdown-toggle nav-link" id="user_dropdown" data-toggle="dropdown" href="#">{{user.get_full_name|title}}
+ </a>
+ <div class="dropdown-menu dropdown-menu-right">
+ <a class="dropdown-item" href="{% url 'yaksh:edit_profile' %}">
+ <i class="fa fa-user"></i> My Profile
+ </a>
+ <div class="dropdown-divider"></div>
+ {% if user.profile.is_moderator %}
+ <a class="dropdown-item" href="{% url 'yaksh:toggle_moderator' %}"><i class="fa fa-exchange"></i>
+ Switch To Moderator
+ </a>
+ <div class="dropdown-divider"></div>
+ {% endif %}
+ <a class="dropdown-item" href="{% url 'password_change' %}">
+ <i class="fa fa-key"></i> Change Password
+ </a>
+ <div class="dropdown-divider"></div>
+ <a class="dropdown-item" id="user_logout" href="{% url 'yaksh:logout' %}">
+ <i class="fa fa-sign-out"></i> Logout
+ </a>
+ </div>
+ </li>
+ </ul>
+ </div>
+ </nav>
</div>
{% endblock %}
@@ -44,25 +51,3 @@
{% endblock %}
{% endblock %}
{% endblock %}
-
-{% block footer %}
- <!--footer-->
- <footer class="container-fluid yakshfooter text-center ">
- <div class="row justify-content-center">
- <div class="col-sm-5 ">
- {% if user %}
- {% block info %}
- <b>{{user.get_full_name|title}}</b> with Roll no. <b>{{user.profile.roll_number}}</b> is logged in as <b>{{user.username}}</b>
- {% endblock %}
- {% endif %}
- </div>
- <div class="col-sm-2">
- |
- </div>
- <div class="col-sm-4 text-left">
- <b>Any Queries?</b> Email : info@fossee.in
- </div>
- </div>
- </footer>
- <!--footer end-->
-{% endblock %} \ No newline at end of file
diff --git a/yaksh/templates/yaksh/add_course.html b/yaksh/templates/yaksh/add_course.html
index 6276425..72403ce 100644
--- a/yaksh/templates/yaksh/add_course.html
+++ b/yaksh/templates/yaksh/add_course.html
@@ -22,11 +22,6 @@
</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="{% url 'yaksh:allotted_courses' %}">
- Allotted Courses
- </a>
- </li>
- <li class="nav-item">
<a class="nav-link active" href="{% url 'yaksh:add_course' %}">
Add New Course
</a>
@@ -67,7 +62,7 @@
<center>
<button class="btn btn-success btn-lg" type="submit" id="submit" name="course">
- Save
+ <i class="fa fa-save"></i>&nbsp;Save
</button>
<a class="btn btn-danger btn-lg" name="button" href="{% url 'yaksh:courses' %}">
Cancel
diff --git a/yaksh/templates/yaksh/add_exercise.html b/yaksh/templates/yaksh/add_exercise.html
index 21ef6cc..d3d9068 100644
--- a/yaksh/templates/yaksh/add_exercise.html
+++ b/yaksh/templates/yaksh/add_exercise.html
@@ -1,54 +1,101 @@
{% extends "manage.html" %}
+{% load static %}
-
+{% block title %}Add Exercise{% endblock %}
{% block subtitle %}Add Exercise{% endblock %}
{% block css %}
{% endblock %}
{% block script %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery-3.3.1.min.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/add_quiz.js"></script>
+<script src="{% static 'yaksh/js/jquery-3.3.1.min.js' %}"></script>
+<script src="{% static 'yaksh/js/add_quiz.js' %}"></script>
{% endblock %}
{% block onload %} window.onload="javascript:test();" {% endblock %}
{% block content %}
-<div class="yakshwell container">
-<form name=frm id=frm action="" method="post" >
- {% csrf_token %}
- <center>
- <table class="span1 table table-responsive-sm">
- {{ form.as_table }}
- </table>
- <br/><br/>
- </center>
- <center><button class="btn btn-success" type="submit" id="submit" name="save_exercise"> Save
- </button>
-
- <button class="btn btn-danger" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/courses/");'>Cancel</button> </center>
-</form>
-{% if exercise and course_id %}
- {% if exercise.questionpaper_set.get.id %}
- <center>
- <h4>You can check the quiz by attempting it in the following modes:</h4>
- <a href="{{URL_ROOT}}/exam/manage/designquestionpaper/{{ exercise.id }}/{{exercise.questionpaper_set.get.id}}/{{course_id}}" class="btn btn-primary">View Question Paper</a>
- <button class="btn" type="button" name="button" onClick='usermode("{{URL_ROOT}}/exam/manage/usermode/{{exercise.id}}/{{course_id}}/");'>User Mode</button>
+<div class="container">
+ {% if messages %}
+ {% for message in messages %}
+ <div class="alert alert-dismissible alert-{{ message.tags }}">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ message }}</strong>
+ </div>
+ {% endfor %}
+ {% endif %}
+ {% if course_id %}
+ <a class="btn btn-primary" href="{% url 'yaksh:get_course_modules' course_id %}">
+ <i class="fa fa-arrow-left"></i>
+ Back
+ </a>
+ {% else %}
+ <a class="btn btn-primary" href="{% url 'yaksh:show_all_quizzes' %}">
+ <i class="fa fa-arrow-left"></i>
+ Back
+ </a>
+ {% endif %}
+ <br><br>
+ <form name=frm id=frm action="" method="post" >
+ {% csrf_token %}
+ <center>
+ <table class="span1 table table-responsive-sm">
+ {{ form.as_table }}
+ </table>
+ <br/><br/>
+ </center>
+ <center>
+ <button class="btn btn-success btn-lg" type="submit" id="submit" name="save_exercise">
+ <i class="fa fa-save"></i>&nbsp;Save
+ </button>
+ </center>
+ </form>
+ <br>
+ {% if exercise and course_id %}
+ {% if exercise.questionpaper_set.get.id %}
+ <center>
+ <a href="{% url 'yaksh:designquestionpaper' exercise.id exercise.questionpaper_set.get.id course_id %}" class="btn btn-primary">
+ <i class="fa fa-edit"></i> Edit Question Paper
+ </a>
+ <a href="{% url 'yaksh:preview_questionpaper' exercise.questionpaper_set.get.id %}" class="btn btn-info" target="_blank">
+ <i class="fa fa-eye"></i> Preview Question Paper
+ </a>
+ <br>
+ <br>
+ <h4>You can check the quiz by attempting it in the following modes:</h4>
+ <a class="btn btn-outline-info" name="button" href="{% url 'yaksh:test_quiz' 'usermode' exercise.id course_id %}" target="blank">
+ User Mode
+ </a>
- <button class="btn" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/godmode/{{exercise.id}}/{{course_id}}/");'>
- God Mode</button>
- <a data-toggle="collapse" data-target="#help">
- <span class="glyphicon glyphicon-info-sign">Help</span></a>
- <div id="help" class="collapse">
- <br/>
- <ul>
- <li><b>User Mode:</b> Attempt quiz the way normal users will attempt i.e. -
- <ul>
- <li><i>Quiz will have the same duration as that of the original quiz.</li>
- <li>Quiz won't start if the course is inactive or the quiz time has expired.</li>
- <li>You will be notified about quiz prerequisites.(You can still attempt the quiz though)</i></li>
- </ul>
- </p>
- <li> <b>God Mode:</b> Attempt quiz without any time or eligibilty constraints.</p>
- </div>
+ <a class="btn btn-outline-info" name="button" href="{% url 'yaksh:test_quiz' 'godmode' exercise.id course_id %}" target="blank">
+ God Mode
+ </a>
+ <a data-toggle="modal" data-target="#help">
+ <span class="text-info"><i class="fa fa-info-circle"></i> Help</span></a>
+ </center>
+ {% endif %}
{% endif %}
-{% endif %}
+</div>
+<div class="modal" id="help">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h5 class="modal-title">Quiz Test Modes</h5>
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true"><i class="fa fa-close"></i></span>
+ </button>
+ </div>
+ <div class="modal-body">
+ <p>
+ <b>User Mode:</b> Attempt quiz the way normal users will attempt i.e. -
+ <ul class="list-group list-group-flush">
+ <li class="list-group-item">Quiz will have the same duration as that of the original quiz.</li>
+ <li class="list-group-item">Quiz won't start if the course is inactive or the quiz time has expired.</li>
+ <li class="list-group-item">You will be notified about quiz prerequisites.(You can still attempt the quiz though)</li>
+ </ul>
+ <b>God Mode:</b> Attempt quiz without any time or eligibilty constraints.
+ </p>
+ </div>
+ </div>
+ </div>
</div>
{% endblock %}
diff --git a/yaksh/templates/yaksh/add_lesson.html b/yaksh/templates/yaksh/add_lesson.html
index 87fb8d0..99fc31a 100644
--- a/yaksh/templates/yaksh/add_lesson.html
+++ b/yaksh/templates/yaksh/add_lesson.html
@@ -1,85 +1,161 @@
{% extends "manage.html" %}
{% load custom_filters %}
+{% load static %}
{% block title %}Create/Edit Lesson{% endblock %}
{% block script %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/lesson.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery-ui-1.12.1.js"></script>
+<script type="text/javascript" src="{% static 'yaksh/js/lesson.js' %}">
+</script>
+<script type="text/javascript" src="{% static 'yaksh/js/jquery-ui.js' %}">
+</script>
{% endblock %}
{% block css %}
-<link rel="stylesheet" href="{{URL_ROOT}}/static/yaksh/css/jquery-ui/jquery-ui-1.12.1.css">
-<link rel="stylesheet" href="{{URL_ROOT}}/static/yaksh/css/lesson.css">
+<link rel="stylesheet" href="{% static 'yaksh/css/lesson.css' %}" type="text/css" />
+<link rel="stylesheet" href="{% static 'yaksh/css/jquery-ui/jquery-ui.css' %}" type="text/css" />
{% endblock %}
{% block content %}
-<div class="yakshwell container">
+<div class="container">
{% if error %}
<div class="alert alert-danger">
{{error}}
</div>
{% endif %}
-<form name=frm id=frm action="" method="post" enctype="multipart/form-data">
- {% csrf_token %}
- <center>
- <table class="table table-bordered table-responsive-sm">
- {{ lesson_form.as_table }}
- {{ lesson_file_form.as_table }}
- </table>
- </center>
- <br><br>
- {% if lesson_files %}
- <center>
- <div class="alert alert-success col-md-8 animated flash">
- <h4>Files added to this lesson</h4>
- </div>
- </center>
- {% for f in lesson_files %}
- <li class="list-group-item">
- <h4>
- <input type="checkbox" name="delete_files" value="{{f.id}}">
- </input>
- <a href="{{f.file.url}}">{{ f.file.name|file_title }}</a>
- </h4>
- </li>
- {% endfor %}
- {% else %}
-
- <center>
- <div class="alert alert-warning col-md-8 animated flash">
- <h4 class="alert-warning">No Files added to this lesson</h4>
- </div>
- </center>
- {% endif %}
- <br><br>
- <center>
- <button class="btn btn-success" type="submit" id="submit" name="Save"> Save
- </button>
- {% if lesson_files %}
- <button class="btn btn-danger" type="submit" id="submit" name="Delete"> Delete Files
- </button>
- {% endif %}
- {% if course_id %}
- <button class="btn btn-danger" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/courses/");'>Cancel</button>
- {% else %}
- <button class="btn btn-danger" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/courses/all_lessons/");'>Cancel</button>
- {% endif %}
- </form>
- <button class="btn btn-outline-primary" type="button" name="button" id="preview">Preview Lesson Description
- </button>
- <button class="btn btn-outline-primary" type="button" name="button" id="embed">
- Embed Video link
- </button>
- </center>
- <hr>
- <div class="card" id="preview_text_div" style="display: none;">
- <div class="card-heading">
- <center>
- <h3>Description Preview</h3>
- </center>
- </div>
- <div class="card-body" id="description_body">
+<div class="container">
+ <div class="row justify-content-center form-group">
+ <div class="col-md-9 col-md-offset-4">
+ {% if course_id %}
+ <a class="btn btn-primary" href="{% url 'yaksh:get_course_modules' course_id %}">
+ <i class="fa fa-arrow-left"></i>
+ Back
+ </a>
+ {% else %}
+ <a class="btn btn-primary" href="{% url 'yaksh:show_all_lessons' %}">
+ <i class="fa fa-arrow-left"></i>
+ Back
+ </a>
+ {% endif %}
+ <br>
+ {% if messages %}
+ <br>
+ {% for message in messages %}
+ <div class="alert alert-dismissible alert-{{ message.tags }}">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ message }}</strong>
+ </div>
+ {% endfor %}
+ {% endif %}
+ <br>
+ <form name=frm id=frm action="" method="post" enctype="multipart/form-data">
+ <fieldset>
+ {% csrf_token %}
+ {% if lesson_form.errors %}
+ {% for field in lesson_form %}
+ {% for error in field.errors %}
+ <div class="alert alert-dismissible alert-danger">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ error|escape }}</strong>
+ </div>
+ {% endfor %}
+ {% endfor %}
+ {% for error in lesson_form.non_field_errors %}
+ <div class="alert alert-dismissible alert-danger">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ error|escape }}</strong>
+ </div>
+ {% endfor %}
+ {% endif %}
+ {{lesson_form.name}}
+ <br>
+ {{lesson_form.description}}
+ <br>
+ Active:&nbsp;{{lesson_form.active}}
+ <br><br>
+ Video File:
+ <span class="badge badge-info">
+ {{lesson_form.video_file.help_text}}
+ </span>
+ <div class="input-group mb-3">
+ <div class="custom-file">
+ {{lesson_form.video_file}}
+ <label class="custom-file-label" for="id_video_file">
+ Choose file
+ </label>
+ </div>
+ </div>
+ <br>
+ Lesson Files:
+ <div class="input-group mb-3">
+ <div class="custom-file">
+ {{lesson_file_form.Lesson_files}}
+ <label class="custom-file-label" for="id_video_file">
+ Choose file
+ </label>
+ </div>
+ </div>
+ <br>
+ {% if lesson_files %}
+ <center>
+ <div class="alert alert-info">
+ <h4>Files added to this lesson</h4>
+ </div>
+ </center>
+ {% for f in lesson_files %}
+ <li class="list-group-item">
+ <h4>
+ <input type="checkbox" name="delete_files" value="{{f.id}}">
+ </input>
+ <a href="{{f.file.url}}">{{ f.file.name|file_title }}</a>
+ </h4>
+ </li>
+ {% endfor %}
+ <br>
+ {% else %}
+ <center>
+ <div class="alert alert-warning">
+ <h4 class="alert-warning">No Files added to this lesson</h4>
+ </div>
+ </center>
+ {% endif %}
+ <center>
+ <button class="btn btn-success btn-lg" type="submit" id="submit" name="Save">
+ <i class="fa fa-save"></i>
+ Save
+ </button>
+ {% if lesson_files %}
+ <button class="btn btn-danger btn-lg" type="submit" id="submit" name="Delete"> <i class="fa fa-trash"></i>&nbsp;Delete Files
+ </button>
+ {% endif %}
+ <button class="btn btn-outline-primary btn-lg" type="button" name="button" id="preview">
+ <i class="fa fa-eye"></i>
+ Preview Description
+ </button>
+ <button class="btn btn-outline-primary btn-lg" type="button" name="button" id="embed">
+ <i class="fa fa-angle-left"></i>&nbsp;<i class="fa fa-angle-right"></i>
+ Embed Video link
+ </button>
+ </center>
+ </form>
+ <hr>
+ <div class="card" id="preview_text_div" style="display: none;">
+ <div class="card-heading">
+ <center>
+ <h3>Description Preview</h3>
+ </center>
+ </div>
+ <div class="card-body" id="description_body">
+ </div>
+ </div>
+ </fieldset>
+ </form>
</div>
</div>
</div>
diff --git a/yaksh/templates/yaksh/add_module.html b/yaksh/templates/yaksh/add_module.html
index 6b2214b..edbfaa2 100644
--- a/yaksh/templates/yaksh/add_module.html
+++ b/yaksh/templates/yaksh/add_module.html
@@ -1,70 +1,125 @@
{% extends "manage.html" %}
+{% load static %}
{% block title %}Create/Edit Learning Module{% endblock %}
-{% block pagetitle %}<h4>Design Learning Module</h4>{% endblock %}
-
{% block script %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery-3.3.1.min.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/design_course.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/lesson.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery-ui.js"></script>
+<script type="text/javascript" src="{% static 'yaksh/js/jquery-3.3.1.min.js' %}">
+</script>
+<script type="text/javascript" src="{% static 'yaksh/js/design_course.js' %}">
+</script>
+<script type="text/javascript" src="{% static 'yaksh/js/lesson.js' %}">
+</script>
+<script type="text/javascript" src="{% static 'yaksh/js/jquery-ui.js' %}">
+</script>
{% endblock %}
{% block css %}
-<link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/design_course.css" />
-<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/jquery-ui/jquery-ui.css">
+<link rel="stylesheet" href="{% static 'yaksh/css/design_course.css' %}" type="text/css" />
+<link rel="stylesheet" href="{% static 'yaksh/css/jquery-ui/jquery-ui.css' %}" type="text/css" />
{% endblock %}
{% block content %}
-<div class="yaskhwell container">
+<div class="container">
+{% if messages %}
+ {% for message in messages %}
+ <div class="alert alert-dismissible alert-{{ message.tags }}">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ message }}</strong>
+ </div>
+ {% endfor %}
+{% endif %}
{% if course_id %}
- <a href="{{URL_ROOT}}/exam/manage/courses/" class="btn btn-primary">
- Back to Courses</a>
+ <a class="btn btn-primary" href="{% url 'yaksh:get_course_modules' course_id %}">
+ <i class="fa fa-arrow-left"></i>
+ Back
+ </a>
{% else %}
- <a href="{{URL_ROOT}}/exam/manage/courses/all_learning_module" class="btn btn-primary">
- Back to Learning Modules</a>
+ <a class="btn btn-primary" href="{% url 'yaksh:show_all_modules' %}">
+ <i class="fa fa-arrow-left"></i>
+ Back
+ </a>
{% endif %}
+</div>
+<br>
{% if status == "add" %}
-<form name=frm id=frm action="" method="post">
- {% csrf_token %}
- <br>
- <center>
- <table class="table table-bordered table-responsive-sm">
- {{ module_form.as_table }}
- </table>
- </center>
- <br><br>
- <center>
- <button class="btn btn-success" type="submit" id="submit" name="Save">
- Save
- </button>
- <button class="btn btn-outline-primary" type="button" name="button" id="preview">
- Preview Module Description
- </button>
- <button class="btn btn-outline-primary" type="button" name="button" id="embed">
- Embed Video link
- </button>
- </center>
-</form>
-<hr>
-<div class="card" id="preview_text_div" style="display: none;">
- <div class="card-heading">
- <center>
- <h3>Description Preview</h3>
- </center>
- </div>
- <div class="card-body" id="description_body">
+<div class="container">
+ <div class="row justify-content-center form-group">
+ <div class="col-md-9 col-md-offset-4">
+ <form name=frm id=frm action="" method="post">
+ <fieldset>
+ {% csrf_token %}
+ {% if module_form.errors %}
+ {% for field in module_form %}
+ {% for error in field.errors %}
+ <div class="alert alert-dismissible alert-danger">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ error|escape }}</strong>
+ </div>
+ {% endfor %}
+ {% endfor %}
+ {% for error in form.non_field_errors %}
+ <div class="alert alert-dismissible alert-danger">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ error|escape }}</strong>
+ </div>
+ {% endfor %}
+ {% endif %}
+ {{module_form.name}}
+ <br>
+ {{module_form.description}}
+ <br>
+ Active:&nbsp;{{module_form.active}}
+ <br>
+ <center>
+ <button class="btn btn-success btn-lg" type="submit" id="submit" name="Save">
+ <i class="fa fa-save"></i>
+ Save
+ </button>
+ <button class="btn btn-outline-primary btn-lg" type="button" name="button" id="preview">
+ <i class="fa fa-eye"></i>
+ Preview Description
+ </button>
+ <button class="btn btn-outline-primary btn-lg" type="button" name="button" id="embed">
+ <i class="fa fa-angle-left"></i>&nbsp;<i class="fa fa-angle-right"></i>
+ Embed Video link
+ </button>
+ </center>
+ </form>
+ <hr>
+ <div class="card" id="preview_text_div" style="display: none;">
+ <div class="card-heading">
+ <center>
+ <h3>Description Preview</h3>
+ </center>
+ </div>
+ <div class="card-body" id="description_body">
+ </div>
+ </div>
+ </fieldset>
+ </form>
+ </div>
</div>
</div>
{% endif %}
<!-- Add learning Units -->
{% if status == "design" %}
+<div class="container">
<center><h3><u>Add/Edit Learning Units</h3></u></center>
-<form action="{{URL_ROOT}}/exam/manage/courses/designmodule/{{module_id}}/" method="POST" id="design_course_form">
+{% if course_id %}
+<form action="{% url 'yaksh:design_module' module_id course_id %}" method="POST" id="design_course_form">
+{% else %}
+<form action="{% url 'yaksh:design_module' module_id %}" method="POST" id="design_course_form">
+{% endif %}
{% csrf_token %}
<div class="tab-pane active" id="available-lesson-quiz">
<div class="row">
- <div class="col-md-8 available-list col-md-offset-2">
+ <div class="col-md-12 available-list">
<div id="fixed-available-wrapper">
<p><u><b>Available Lessons and quizzes: (Add Lessons and Quizzes)</b></u></p>
<div id="fixed-available">
@@ -87,13 +142,13 @@
</div>
<br>
<center>
- <button class="btn btn-success" type="submit" id="submit" name="Add">
- Add to Module
+ <button class="btn btn-success" type="submit" id="submit" name="Add"><i class="fa fa-plus-square"></i>
+ &nbsp;Add to Module
</button>
</center>
<br><br>
</div>
- <div class="col-md-8 col-md-offset-2">
+ <div class="col-md-12 col-md-offset-2">
<div id="fixed-added-wrapper">
<p><u><b>Chosen Lessons and quizzes:</b></u>
</p>
@@ -152,8 +207,8 @@
</div>
<br>
<center>
- <button id="Remove" name="Remove" class="btn btn-danger" type="submit">Remove from Module</button>
- <button id="Change" name="Change" class="btn btn-info" type="submit"> Change Order</button>
+ <button id="Remove" name="Remove" class="btn btn-danger" type="submit"> <i class="fa fa-minus-square"></i>&nbsp;Remove from Module</button>
+ <button id="Change" name="Change" class="btn btn-info" type="submit"><i class="fa fa-reorder"></i>&nbsp;Change Order</button>
<button id="Change" name="Change_prerequisite" class="btn btn-primary" type="submit"> Change Prerequisite</button>
</center>
</div>
diff --git a/yaksh/templates/yaksh/add_question.html b/yaksh/templates/yaksh/add_question.html
index 665e86a..a400e35 100644
--- a/yaksh/templates/yaksh/add_question.html
+++ b/yaksh/templates/yaksh/add_question.html
@@ -62,11 +62,13 @@
<div class="form-group">
{{ formset.management_form }}
- {% for form in formset %}
- <div class="link-formset well">
- {{ form.as_p }}
- </div>
- {% endfor %}
+ {% for form in formset %}
+ <div class="link-formset well">
+ {% autoescape off %}
+ {{ form.as_p }}
+ {% endautoescape %}
+ </div>
+ {% endfor %}
</div>
{% endfor %}
diff --git a/yaksh/templates/yaksh/add_quiz.html b/yaksh/templates/yaksh/add_quiz.html
index 48d64ce..57b4d77 100644
--- a/yaksh/templates/yaksh/add_quiz.html
+++ b/yaksh/templates/yaksh/add_quiz.html
@@ -1,73 +1,109 @@
{% extends "manage.html" %}
+{% load static %}
+{% block title %}Add/Edit Quiz{% endblock %}
-{% block subtitle %}Add Quiz{% endblock %}
+{% block subtitle %}Add/Edit Quiz{% endblock %}
{% block css %}
-<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/jquery.datetimepicker.css" type="text/css" />
+
+<link rel="stylesheet" href="{% static 'yaksh/css/jquery.datetimepicker.css' %}" type="text/css" />
{% endblock %}
{% block script %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery-3.3.1.min.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/add_quiz.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery.datetimepicker.full.min.js"></script>
+
+<script src="{% static 'yaksh/js/jquery-3.3.1.min.js' %}"></script>
+<script src="{% static 'yaksh/js/add_quiz.js' %}"></script>
+<script src="{% static 'yaksh/js/jquery.datetimepicker.full.min.js' %}"></script>
+
{% endblock %}
{% block onload %} onload="javascript:test();" {% endblock %}
{% block content %}
-<div class="yakshwell container">
-<form name=frm id=frm action="" method="post" >
- {% csrf_token %}
- <center>
- <table class="span1 table table-responsive-sm">
- {{ form.as_table }}
- </table>
- <script type="text/javascript">
- $("#id_start_date_time").datetimepicker({format: 'Y-m-d H:i:s'});
- $("#id_end_date_time").datetimepicker({format: 'Y-m-d H:i:s'});
- </script>
- <br/><br/>
- </center>
-
- <center><button class="btn btn-success" type="submit" id="submit" name="questionpaper"> Save
- </button>
-
- <button class="btn btn-danger" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/courses/");'>Cancel</button> </center>
-
-</form>
-<br>
-{% if quiz and course_id %}
- {% if quiz.questionpaper_set.get.id %}
- <center>
- <a href="{{URL_ROOT}}/exam/manage/designquestionpaper/{{ quiz.id }}/{{quiz.questionpaper_set.get.id}}/{{course_id}}" class="btn btn-primary">Edit Question Paper</a>
- <a href="{{URL_ROOT}}/exam/manage/preview_questionpaper/{{quiz.questionpaper_set.get.id}}" class="btn btn-primary" target="_blank">
- Preview Question Paper
+<div class="container">
+ {% if messages %}
+ {% for message in messages %}
+ <div class="alert alert-dismissible alert-{{ message.tags }}">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ message }}</strong>
+ </div>
+ {% endfor %}
+ {% endif %}
+ {% if course_id %}
+ <a class="btn btn-primary" href="{% url 'yaksh:get_course_modules' course_id %}">
+ <i class="fa fa-arrow-left"></i>
+ Back
+ </a>
+ {% else %}
+ <a class="btn btn-primary" href="{% url 'yaksh:show_all_quizzes' %}">
+ <i class="fa fa-arrow-left"></i>
+ Back
</a>
- <br>
- <br>
- <h4>You can check the quiz by attempting it in the following modes:</h4>
- <button class="btn btn-outline-info" type="button" name="button" onClick='usermode("{{URL_ROOT}}/exam/manage/usermode/{{quiz.id}}/{{course_id}}/");'>User Mode</button>
+ {% endif %}
+ <br><br>
+ <form name=frm id=frm action="" method="post" >
+ {% csrf_token %}
+ <center>
+ <table class="table">
+ {{ form.as_table }}
+ </table>
+ <script type="text/javascript">
+ $("#id_start_date_time").datetimepicker({format: 'Y-m-d H:i:s'});
+ $("#id_end_date_time").datetimepicker({format: 'Y-m-d H:i:s'});
+ </script>
+ <br/>
+ <button class="btn btn-success btn-lg" id="submit" name="questionpaper">
+ <i class="fa fa-save">&nbsp;Save</i>
+ </button>
+ </center>
+ </form>
+ <br>
+ {% if quiz and course_id %}
+ {% if quiz.questionpaper_set.get.id %}
+ <center>
+ <a href="{% url 'yaksh:designquestionpaper' quiz.id quiz.questionpaper_set.get.id course_id %}" class="btn btn-primary">
+ <i class="fa fa-edit"></i> Edit Question Paper
+ </a>
+ <a href="{% url 'yaksh:preview_questionpaper' quiz.questionpaper_set.get.id %}" class="btn btn-info" target="_blank">
+ <i class="fa fa-eye"></i> Preview Question Paper
+ </a>
+ <br>
+ <br>
+ <h4>You can check the quiz by attempting it in the following modes:</h4>
+ <a class="btn btn-outline-info" name="button" href="{% url 'yaksh:test_quiz' 'usermode' quiz.id course_id %}" target="blank">
+ User Mode
+ </a>
- <button class="btn btn-outline-info" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/godmode/{{quiz.id}}/{{course_id}}/");'>
- God Mode</button>
- <a data-toggle="collapse" data-target="#help">
- <span class=" text-info"><i class="fa fa-info-circle"></i> Help</span></a>
- <div id="help" class="collapse">
- <br/>
- <ul>
- <li><b>User Mode:</b> Attempt quiz the way normal users will attempt i.e. -
- <ul>
- <li><i>Quiz will have the same duration as that of the original quiz.</li>
- <li>Quiz won't start if the course is inactive or the quiz time has expired.</li>
- <li>You will be notified about quiz prerequisites.(You can still attempt the quiz though)</i></li>
- </ul>
- </p>
- <li> <b>God Mode:</b> Attempt quiz without any time or eligibilty constraints.</p>
+ <a class="btn btn-outline-info" name="button" href="{% url 'yaksh:test_quiz' 'godmode' quiz.id course_id %}" target="blank">
+ God Mode
+ </a>
+ <a data-toggle="modal" data-target="#help">
+ <span class="text-info"><i class="fa fa-info-circle"></i> Help</span></a>
+ </center>
+ {% endif %}
+ {% endif %}
+</div>
+<div class="modal" id="help">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h5 class="modal-title">Quiz Test Modes</h5>
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true"><i class="fa fa-close"></i></span>
+ </button>
+ </div>
+ <div class="modal-body">
+ <p>
+ <b>User Mode:</b> Attempt quiz the way normal users will attempt i.e. -
+ <ul class="list-group list-group-flush">
+ <li class="list-group-item">Quiz will have the same duration as that of the original quiz.</li>
+ <li class="list-group-item">Quiz won't start if the course is inactive or the quiz time has expired.</li>
+ <li class="list-group-item">You will be notified about quiz prerequisites.(You can still attempt the quiz though)</li>
+ </ul>
+ <b>God Mode:</b> Attempt quiz without any time or eligibilty constraints.
+ </p>
+ </div>
</div>
- {% endif %}
-{% endif %}
-<style type="text/css">
- #rendered_text{
- width: 550px;
- }
-</style>
+ </div>
</div>
{% endblock %}
diff --git a/yaksh/templates/yaksh/addteacher.html b/yaksh/templates/yaksh/addteacher.html
index fa322f3..58f48d9 100644
--- a/yaksh/templates/yaksh/addteacher.html
+++ b/yaksh/templates/yaksh/addteacher.html
@@ -1,76 +1,86 @@
-{% extends "manage.html" %}
-
-{% block title %} Add teacher {% endblock title %}
-{% block subtitle %} {{ course.name }} {% endblock %}
-
-{% block content %}
-<div class="yakshwell container">
-<center><h3>Add Teachers for this course</h3><br></center>
-<center><h3>Search teacher with username, firstname, lastname, email</h3><br></center>
-<div align="center">
- <form action="{{ URL_ROOT }}/exam/manage/searchteacher/{{ course.id }}/" method="post">
- {% csrf_token %}
- Search Teacher: <input type="text" name="uname" style="height: 25px; padding: 0px"><br><br>
- <center><button class="btn btn-info" type="submit">Search</button>
- <button class="btn btn-danger" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/courses");'>Cancel</button> </center></form>
-</div>
+<div class="container">
+<center><h3>Add Teachers/TAs</h3><br></center>
+<form action="{% url 'yaksh:search_teacher' course.id %}" method="post">
+ {% csrf_token %}
+ <div class="form-group">
+ <input class="form-control form-control-lg" type="text" name="uname" id="inputLarge" placeholder="Search teachers with username, firstname, lastname, email" required>
+ </div>
+ <center>
+ <button class="btn btn-info btn-lg" type="submit">
+ <i class="fa fa-search"></i>
+ Search
+ </button>
+ </center>
+</form>
<br><br>
-<form action="{{ URL_ROOT }}/exam/manage/addteacher/{{ course.id }}/" method="post">
-{% csrf_token %}
-{% if success == True %}
- {% if teachers|length == 0 %}
- <center><h3>No results found</h3></center>
- {% else %}
- <center><b><u>Search Results</u></b></center><br>
- <center><b>Search results does not include teachers already added</b></center><br>
- <table class="table table-striped table-responsive-sm">
+{% if success %}
+ {% if teachers|length == 0 %}
+ <center><h3 class="badge badge-warning">No results found</h3></center>
+ {% else %}
+ <center><b><u>Search Results</u></b></center><br>
+ <center>
+ <p class="alert alert-info">
+ Search results does not include teachers already added
+ </p>
+ </center>
+ <br>
+ <form action="{% url 'yaksh:add_teacher' course.id %}" method="post">
+ {% csrf_token %}
+ <table class="table table-striped table-responsive-sm course-detail">
<th></th>
<th>Username</th>
- <th>First Name</th>
- <th>Last Name</th>
- <th>Email</th>
- <th>Institute</th>
- <th>Department</th>
+ <th>First Name</th>
+ <th>Last Name</th>
+ <th>Email</th>
+ <th>Institute</th>
+ <th>Department</th>
<th>Position</th>
- {% for teacher in teachers %}
- {% if teacher not in course.get_teachers %}
- <tr class="yakshgreen">
- <td><input type="checkbox" name="check" value="{{ teacher.id }}"></td>
- <td>{{ teacher.username }}</td>
- <td>{{ teacher.first_name }}</td>
- <td>{{ teacher.last_name }}</td>
- <td>{{ teacher.email }}</td>
- <td>{{ teacher.profile.institute }}</td>
- <td>{{ teacher.profile.department }}</td>
- <td>{{ teacher.profile.position }}</td>
- </tr>
- {% endif %}
- {% endfor %}
- </table>
- </br>
- <button class="btn btn-success" type="submit">Add Selected</button>
- {% endif %}
+ {% for teacher in teachers %}
+ {% if teacher not in course.get_teachers %}
+ <tr class="yakshgreen">
+ <td><input type="checkbox" name="check" value="{{ teacher.id }}"></td>
+ <td>{{ teacher.username }}</td>
+ <td>{{ teacher.first_name }}</td>
+ <td>{{ teacher.last_name }}</td>
+ <td>{{ teacher.email }}</td>
+ <td>{{ teacher.profile.institute }}</td>
+ <td>{{ teacher.profile.department }}</td>
+ <td>{{ teacher.profile.position }}</td>
+ </tr>
+ {% endif %}
+ {% endfor %}
+ </table>
+ </br>
+ <button class="btn btn-success btn-lg" type="submit">
+ <i class="fa fa-plus-circle"></i>
+ Add Selected
+ </button>
+ </form>
+ {% endif %}
{% endif %}
-</form>
-{% if status == True %}
-<div class="row">
- <div class="span6 offset4 wrap">
+
+
+{% if status %}
+<div class="container">
+ <center><b><u>Teacher(s) added</u></b></center>
+ <br>
{% if teachers_added %}
- {% for teacher in teachers_added %}
- <div class="well">
- <div class="row">
- <div class="span3" style="width: auto;">
- <h5>{{ teacher.get_full_name }}</h5>
- </div>
- </div>
- </div>
- {% endfor %}
+ <table class="table table-responsive-sm">
+ <tr>
+ <th>Sr No.</th>
+ <th>Name</th>
+ </tr>
+ {% for teacher in teachers_added %}
+ <tr>
+ <td>{{forloop.counter}}</td>
+ <td>{{ teacher.get_full_name }}</td>
+ </tr>
+ {% endfor %}
+ <table>
{% else %}
- <center><b>No Teacher(s) Added</b></center>
+ <center><b class="badge badge-info">No Teacher(s)TA(s) Added</b></center>
{% endif %}
- </div>
</div>
{% endif %}
</div>
-{% endblock %}
diff --git a/yaksh/templates/yaksh/complete.html b/yaksh/templates/yaksh/complete.html
index 8c8073e..df76e13 100644
--- a/yaksh/templates/yaksh/complete.html
+++ b/yaksh/templates/yaksh/complete.html
@@ -1,18 +1,21 @@
{% extends "base.html" %}
+{% load static %}
+
+{% block title %} Complete Quiz {% endblock %}
{% block nav %}
<nav class="navbar navbar-expand-lg navbar-dark bg-primary fixed-top">
- <a class="navbar-brand" href="{{ URL_ROOT }}/exam/">
- <img src="{{ URL_ROOT }}/static/yaksh/images/yaksh_banner.png" alt="YAKSH">
- </a>
+ <a class="navbar-brand" href="{% url 'yaksh:index' %}">
+ <img src="{% static 'yaksh/images/yaksh_banner.png' %}" alt="YAKSH">
+ </a>
</nav>
{% endblock %}
{% block content %}
<br>
-{% if module_id and not paper.question_paper.quiz.is_trial %}
+{% if module_id and not paper.course.is_trial %}
<center>
- <div class="alert alert-info col-md-8 animated flash">
+ <div class="alert alert-info col-md-8">
Note:- Please Click on the Next button to submit the quiz. Please do not close the browser without clicking Next.
</div>
</center>
@@ -20,11 +23,11 @@
{% csrf_token %}
{% if paper.questions_answered.all or paper.questions_unanswered.all %}
<center>
- <div class="col-md-8 yakshwell">
+ <div class="col-md-8">
<h3>Submission Status</h3>
<table class="table table-bordered table-responsive-sm" >
<thead>
- <tr class="yakshred text-center">
+ <tr class="text-center">
<th> Question</th>
<th> Status </th>
</tr>
@@ -37,7 +40,7 @@
<td> {{ question.summary }} </td>
<td> Attempted </td>
{% else %}
- <tr class="table-danger">
+ <tr class="table-warning">
<td> {{ question }} </td>
<td> Not completed </td>
{% endif %}
@@ -56,20 +59,20 @@
</center>
<center>
<br>
- {% if module_id and not paper.question_paper.quiz.is_trial %}
+ {% if module_id and not paper.course.is_trial %}
{% if first_unit %}
- <a href="{{URL_ROOT}}/exam/next_unit/{{course_id}}/{{module_id}}/{{learning_unit.id}}/1" class="btn btn-info" id="Next"> Next
+ <a href="{% url 'yaksh:next_unit' course_id module_id learning_unit.id '1' %}" class="btn btn-info btn-lg" id="Next"> Next
<span class="fa fa-step-forward">
</span>
</a>
{% else %}
- <a href="{{URL_ROOT}}/exam/next_unit/{{course_id}}/{{module_id}}/{{learning_unit.id}}" class="btn btn-info" id="Next"> Next
+ <a href="{% url 'yaksh:next_unit' course_id module_id learning_unit.id %}" class="btn btn-info btn-lg" id="Next"> Next
<span class="fa fa-step-forward">
</span>
</a>
{% endif %}
{% else %}
- <a href="{{URL_ROOT}}/exam/" id="home" class="btn btn-primary btn-lg"> Home </a>
+ <a href="{% url 'yaksh:index' %}" id="home" class="btn btn-primary btn-lg"> Home </a>
{% endif %}
</center>
{% endblock content %}
diff --git a/yaksh/templates/yaksh/course_added_modules.html b/yaksh/templates/yaksh/course_added_modules.html
new file mode 100644
index 0000000..c70eb7a
--- /dev/null
+++ b/yaksh/templates/yaksh/course_added_modules.html
@@ -0,0 +1,49 @@
+{% if is_modules %}
+ {% block pagetitle %} <center> <h3>Course Modules</h3> </center> {% endblock %}
+ {% if modules %}
+ <table class="table table-responsive">
+ <tr>
+ <th>Module</th>
+ <th>Module Design</th>
+ <th>Lessons/Quizzes</th>
+ </tr>
+ {% for module in modules %}
+ <tr>
+ <td>
+ <a href="{% url 'yaksh:edit_module' module.id course.id %}">
+ {{module.name}}</a>
+ </td>
+ <td>
+ <a href="{% url 'yaksh:design_module' module.id course.id %}">
+ Add Quizzes/Lessons for {{module.name}}
+ </a>
+ </td>
+ <td>
+ {% for unit in module.get_learning_units %}
+ <ul class="inputs-list">
+ <li>
+ {% if unit.type == "quiz" %}
+ {% if unit.quiz.is_exercise %}
+ <a href="{% url 'yaksh:edit_exercise' unit.quiz.id course.id %}">
+ {{unit.quiz.description}}</a>
+ {% else %}
+ <a href="{% url 'yaksh:edit_quiz' unit.quiz.id course.id %}">
+ {{unit.quiz.description}}</a>
+ {% endif %}
+ {% else %}
+ <a href="{% url 'yaksh:edit_lesson' unit.lesson.id course.id %}">
+ {{unit.lesson.name}}</a>
+ {% endif %}
+ </li>
+ </ul>
+ {% endfor %}
+ </td>
+ </tr>
+ {% endfor %} <!-- end for modules -->
+ </table>
+ {% else %}
+ <center>
+ <span class="badge badge-warning"><big>No learning modules</big></span>
+ </center>
+ {% endif %}
+{% endif %} \ No newline at end of file
diff --git a/yaksh/templates/yaksh/course_detail.html b/yaksh/templates/yaksh/course_detail.html
index f75e362..654f373 100644
--- a/yaksh/templates/yaksh/course_detail.html
+++ b/yaksh/templates/yaksh/course_detail.html
@@ -1,383 +1,94 @@
{% extends "manage.html" %}
+{% load static %}
{% load custom_filters %}
{% block title %} Course Details {% endblock title %}
-<div class="text-center col-md-offset-2">
-{% block pagetitle %} Course Details for {{ course.name|title }} {% endblock %}
-</div>
-
{% block script %}
-<script language="JavaScript" type="text/javascript" src="{{ URL_ROOT }}/static/yaksh/js/course.js"></script>
-<script type="text/javascript" src="{{ URL_ROOT }}/static/yaksh/js/tinymce/js/tinymce/tinymce.min.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery-ui.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery.tablesorter.min.js"></script>
+<script type="text/javascript" src="{% static 'yaksh/js/course.js' %}"></script>
+<script type="text/javascript" src="{% static 'yaksh/js/tinymce/js/tinymce/tinymce.min.js' %}"></script>
+<script type="text/javascript" src="{% static 'yaksh/js/jquery-ui.js' %}"></script>
+<script type="text/javascript" src="{% static 'yaksh/js/jquery.tablesorter.min.js' %}">
+</script>
{% endblock %}
{% block css %}
-<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/jquery-ui/jquery-ui.css">
-<style>
- .user_data + .tooltip.top > .tooltip-inner {
- padding: 12px;
- font-size: 10px;
- }
-</style>
+<link rel="stylesheet" href="{% static 'yaksh/css/jquery-ui/jquery-ui.css' %}">
{% endblock %}
+
+<div class="text-center">
+{% block pagetitle %} <h1>{{ course.name|title }}</h1> {% endblock %}
+</div>
+
{% block content %}
-<div class="row">
- <!-- Side bar -->
- <div class="col-md-3 yakshlabel collapse" id="sidebar">
- <div class="list-group">
- {% if state == 'mail' or state == 'course_status' %}
- <a href="{{URL_ROOT}}/exam/manage/course_detail/{{course.id}}/" class="list-group-item" data-parent="#sidebar"><i class="fa fa-caret-left"></i> Go to Course Details </a>
- {% else %}
- <a href="#student-requests" id="request" class="list-group-item" data-parent="#sidebar"> Requested Students </a>
- <a href="#enrolled-students" id="enroll-students" class="list-group-item" data-parent="#sidebar"> Enrolled Students</a>
- <a href="#rejected-students" id="reject-students" class="list-group-item" data-parent="#sidebar"> Rejected Students </a>
- {% endif %}
- <a href="{{URL_ROOT}}/exam/manage/send_mail/{{ course.id }}/" class="list-group-item" data-parent="#sidebar"> Send Mail </a>
- <a href="{{URL_ROOT}}/exam/manage/course_status/{{ course.id }}/" class="list-group-item" data-parent="#sidebar"> View Course Status </a>
+<hr>
+<div id="dialog" title="Alert">
+ <p id="error_msg"></p>
+</div>
+<div class="container-fluid">
+ <div class="row">
+ <div class="col-sm-3">
+ {% include "yaksh/course_detail_options.html" %}
</div>
- </div>
- <a href="#sidebar" data-toggle="collapse" id="sidebaricon"><i class="fa fa-navicon fa-lg"></i></a>
- <!-- End of sidebar -->
- <main class="col" id="sidebarbody">
- <div class="container-fluid yakshwell">
-
- <form id="upload_users" action="{{ URL_ROOT }}/exam/manage/upload_users/{{course.id}}/"
- method="POST" enctype="multipart/form-data" class="yakshwell">
- {% csrf_token %}
- <input type="file" name="csv_file" />
- <button class="btn btn-outline-primary" type=submit> Upload Users <span class="glyphicon glyphicon-open"/></button>
- </form>
- <div class="card" role="alert">
- <div class="card-body">
- <p>
- - The uploaded csv should have headers exactly same as mentioned below:<br />
- <b>firstname, lastname, email, username, password, institute, roll_no, department,
- remove</b><br />
- - Mandatory fields are <b> firstname, lastname and email. </b><br />
- - Other fields are optional. <br />
- - If username and password are not provided then
- <b>Users created will have username and password same as their email</b>
- </p>
- <p>
- <b> Click <a class="btn btn-success" href="{{ URL_ROOT }}/exam/manage/download_sample_csv/
- ">here</a> to download a sample CSV, edit and upload it</b>
- </p>
- </div>
- </div>
- <div class="yakshwell">
- {% if message %}
- <center>
- <div class="alert alert-warning animated flash col-md-8" role="alert">
- <strong> {{ message }} </strong>
- </div>
- </center>
- {% endif %}
- {% if upload_details %}
- <div class="alert alert-info" role="info">
- {% for detail in upload_details %}
- <strong> {{ detail }} </strong><br>
- {% endfor %}
+ <div class="col-md-9">
+ <div class="tab-content">
+ {% if messages %}
+ {% for message in messages %}
+ <div class="alert alert-dismissible alert-{{ message.tags }}">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ message }}</strong>
</div>
+ {% endfor %}
{% endif %}
-
- {% if state == 'mail' %}
- <div id="enrolled-students" >
- <center ><div class="yakshlabel"><h5>Send Mails to Students</h5></div></center><br>
- {% if course.get_enrolled %}
- <input type="checkbox" class="reject"/>&nbsp;<font class="text-info">Select all</font>
- <div id="reject" class="yakshwell">
- <form action="{{URL_ROOT}}/exam/manage/send_mail/{{ course.id }}/" method="post" id="send_mail_form">
- {% csrf_token %}
- <table id="mail_table" class="tablesorter table table-striped table-responsive-sm" data-sortlist="[1,0]">
- <thead>
- <th></th>
- <th></th>
- <th>Full Name</th>
- <th>Email</th>
- <th>Roll Number</th>
- <th>Institute</th>
- <th>Department</th>
- </thead>
- <tbody>
- {% for enrolled in course.get_enrolled %}
- <tr>
- <td><input type="checkbox" name="check" value="{{ enrolled.id }}"></td>
- <td>{{ forloop.counter }}.</td>
- <td> {{ enrolled.get_full_name|title }} </td>
- <td> {{enrolled.email}}</td>
- <td> {{enrolled.profile.roll_number}}</td>
- <td> {{enrolled.profile.institute}}</td>
- <td> {{enrolled.profile.department}}</td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- <br>
- <div class="card">
- <textarea name="subject" id="subject" placeholder="Email Subject" cols="50"></textarea>
- <br><br>
- <textarea name="body" id="email_body"></textarea><br>
- <span class="yakshwell"> Attachments: <input type="file" name="email_attach" multiple=""></span>
- <br>
- </div>
- <div class="text-center yakshwell">
- <button class="btn btn-success" type="submit" name='send_mail' value='send_mail' id="send_mail">
- Send Mail to Selected Students</button>
- </div>
- </form>
- </div>
- {% endif %}
- </div>
- {% elif state == "course_status" %}
- <div class="course_data">
-
- <center>
- <div class="row">
- <div class="col">
- <h5>Course Status</h5>
- </div>
- <div class="col-md-8">
- Number Of Students: {{ student_details | length }}
- </div>
- <div class="col">
- <input type="hidden" id="course_name" value="{{course.name}}">
- <a href="#" class="btn btn-outline-success" id="export">Export to CSV</a>
- </div>
- </div>
- </center>
- <div class="yakshwell">
- <table class="tablesorter table table-bordered table-responsive-sm" id="course_table" data-sortlist="[0,0]">
- <thead>
- <tr class="yakshlight">
- <th>Roll No.</th>
- <th>Name</th>
- <th>Current Unit</th>
- <th>Course Completion Percentage</th>
- <th>Grade</th>
- </tr>
- </thead>
- <tbody>
- {% for student, grade, percent, unit in student_details %}
- <tr>
- <td>
- {{ student.profile.roll_number}}
- </td>
- <td width="50%">
- <a class="user_data" data-item-id="{{course.id}}+{{student.id}}" data-toggle="tooltip" title="Click to view Overall Course progress" data-placement="top">
- {{ student.get_full_name|title}}
- <i class="fa fa-caret-down"></i>
- </a>
- <div id="show_status_{{course.id}}_{{student.id}}" style="display: None;">
- </div>
- </td>
- <td>
- {% if unit %}
- {% if unit.type == 'quiz' %}
- {{unit.quiz.description}}
- {% else %}
- {{unit.lesson.name}}
- {% endif %}
- {% else %}
- NA
- {% endif%}
- </td>
- <td>
- {{ percent }} %
- </td>
- <td>
- {{ grade }}
- </td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- </div>
- </div>
+ {% if is_students %}
+ {% include "yaksh/course_students.html" %}
+ {% elif is_mail %}
+ {% include "yaksh/course_send_mail.html" %}
+ {% elif is_progress %}
+ {% include "yaksh/course_progress.html" %}
+ {% elif is_modules %}
+ {% include "yaksh/course_added_modules.html" %}
+ {% elif is_design_course %}
+ {% include "yaksh/design_course_session.html" %}
+ {% elif is_add_teacher %}
+ {% include "yaksh/addteacher.html" %}
+ {% elif is_teachers %}
+ {% include "yaksh/course_teachers.html" %}
{% else %}
- <div id="students_enrollment">
- <div id="student-requests" class="card">
- <center><div class="yakshlabel card-heading">Requests</div></center><br>
- <div class="card-body">
- {% if course.get_requests %}
- <input type="checkbox" class="checkall"/>&nbsp;<font size="2">Select all</font>
- <div id="enroll-all">
- <form action="{{URL_ROOT}}/exam/manage/enroll/{{ course.id }}/" method="post">
- {% csrf_token %}
- <table id="requested_table" class="tablesorter table table-striped table-responsive-sm" data-sortlist="[1,0]">
- <thead>
- <th></th>
- <th></th>
- <th>Full Name</th>
- <th>Email</th>
- <th>Roll Number</th>
- <th>Institute</th>
- <th>Department</th>
- <th>Enroll/Reject</th>
- </thead>
- <tbody>
- {% for request in course.get_requests %}
- <tr>
- <td><input type="checkbox" name="check" value="{{ request.id }}"></td>
- <td>{{ forloop.counter }}.</td>
- <td>{{request.get_full_name}}</td>
- <td> {{request.email}}</td>
- <td> {{request.profile.roll_number}}</td>
- <td> {{request.profile.institute}}</td>
- <td> {{request.profile.department}}</td>
- <td>
- <a class="btn btn-success"
- href="{{URL_ROOT}}/exam/manage/enroll/{{ course.id }}/{{ request.id }}/">
- Enroll </a>
- <a class="btn btn-danger"
- href="{{URL_ROOT}}/exam/manage/reject/{{ course.id }}/{{ request.id }}/">
- Reject </a>
- </td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- <button class="btn btn-success pull-right" type="submit" name='enroll' value='enroll'>Enroll Selected</button> <br>
- </form>
- </div>
- {% else %}
- <center>
- <span class="badge badge-warning"><big> No requests yet</big></span>
- </center>
- {% endif %}
- </div>
- </div>
- <br>
- <div id="enrolled-students" class="card">
- <center><div class="yakshlabel card-heading">Enrolled</div></center><br>
- <div class="card-body">
- {% if course.get_enrolled %}
- <input type="checkbox" class="reject"/>&nbsp;<font size="2">Select all</font>
- <div id="reject">
- <form action="{{URL_ROOT}}/exam/manage/enrolled/reject/{{ course.id }}/" method="post" id="reject-form">
- {% csrf_token %}
- <table id="enrolled_table" class="tablesorter table table-striped table-responsive-sm" data-sortlist="[1,0]">
- <thead>
- <th></th>
- <th></th>
- <th>Full Name</th>
- <th>Email</th>
- <th>Roll Number</th>
- <th>Institute</th>
- <th>Department</th>
- <th>Reject</th>
- </thead>
- <tbody>
- {% for enrolled in course.get_enrolled %}
- <tr>
- <td><input type="checkbox" name="check" value="{{ enrolled.id }}"></td>
- <td>{{ forloop.counter }}.</td>
- <td> {{ enrolled.get_full_name|title }} </td>
- <td> {{enrolled.email}}</td>
- <td> {{enrolled.profile.roll_number}}</td>
- <td> {{enrolled.profile.institute}}</td>
- <td> {{enrolled.profile.department}}</td>
- <td><a class="btn btn-danger"
- href="{{URL_ROOT}}/exam/manage/enrolled/reject/{{ course.id }}/{{ enrolled.id }}/">
- Reject </a>
- </td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- <button class="btn btn-danger pull-right" type="submit" name='reject' value='reject'>
- Reject Selected</button> <br>
- </form>
- </div>
- {% else %}
- <center>
- <span class="badge badge-warning"><big> No enrolled students yet</big></span>
- </center>
- {% endif %}
- </div>
- </div>
- <br>
- <div id="rejected-students" class="card">
- <center><div class="yakshlabel card-heading">Rejected</div></center><br>
- <div class="card-body">
- {% if course.get_rejected %}
- <input type="checkbox" class="enroll"/>&nbsp;<font size="2">Select all</font>
- <div id="enroll">
- <form action="{{URL_ROOT}}/exam/manage/enroll/rejected/{{ course.id }}/" method="post">
- {% csrf_token %}
- <table id="rejected_table" class="tablesorter table table-striped table-responsive-sm" data-sortlist="[1,0]">
- <thead>
- <th></th>
- <th></th>
- <th>Full Name</th>
- <th>Email</th>
- <th>Roll Number</th>
- <th>Institute</th>
- <th>Department</th>
- <th>Enroll</th>
- </thead>
- <tbody>
- {% for rejected in course.get_rejected %}
- <tr>
- <td><input type="checkbox" name="check" value="{{ rejected.id }}"></td>
- <td>{{ forloop.counter }}.</td>
- <td>{{rejected.get_full_name|title}}</td>
- <td> {{rejected.email}}</td>
- <td> {{rejected.profile.roll_number}}</td>
- <td> {{rejected.profile.institute}}</td>
- <td> {{rejected.profile.department}}</td>
- <td>
- <a class="btn btn-success"
- href="{{URL_ROOT}}/exam/manage/enroll/rejected/{{ course.id }}/{{ rejected.id }}/">
- Enroll </a>
- </td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- <br>
- <button class="btn btn-success pull-right" type="submit" name='enroll' value='enroll'>
- Enroll Selected</button> <br>
- </form>
- </div>
- {% else %}
- <center>
- <span class="badge badge-warning"><big> No rejected students yet</big></span>
- </center>
- {% endif %}
- </div>
- </div>
+ <div class="jumbotron">
+ <h1 class="display-4">Manage Course</h1>
+ <hr class="my-4">
+ <p>
+ <ul>
+ <li>
+ Students enrollments
+ </li>
+ <li>
+ Add and View Modules, Lessons and Quizzes
+ </li>
+ <li>
+ Send mail to the students
+ </li>
+ <li>
+ View Students course progress
+ </li>
+ <li>
+ Add and View Teachers/TAs
+ </li>
+ </ul>
+ </p>
+ <p class="lead">
+ <a class="btn btn-primary btn-lg" href="https://yaksh.readthedocs.io/en/latest/moderator_docs/creating_course.html" role="button" target="blank">
+ <i class="fa fa-info-circle"></i>
+ Learn more
+ </a>
+ </p>
</div>
{% endif %}
</div>
- <!-- Dialog to display error message -->
- <div id="dialog" title="Alert">
- <p id="error_msg"></p>
- </div>
</div>
- </main>
+ </div>
</div>
{% endblock %}
-{% block footer %}
- <!--footer-->
- <footer class="container-fluid yakshsidebarfooter text-center">
- <div class="row justify-content-center">
- <div class="col-sm-5 ">
- {% if user %}
- {% block info %}
- <b>{{user.get_full_name|title}}</b> with Roll no. <b>{{user.profile.roll_number}}</b> is logged in as <b>{{user.username}}</b>
- {% endblock %}
- {% endif %}
- </div>
- <div class="col-sm-2">
- |
- </div>
- <div class="col-sm-4 text-left">
- <b>Any Queries?</b> Email : info@fossee.in
- </div>
- </div>
- </footer>
- <!--footer end-->
-{% endblock %}
diff --git a/yaksh/templates/yaksh/course_detail_options.html b/yaksh/templates/yaksh/course_detail_options.html
new file mode 100644
index 0000000..43422ed
--- /dev/null
+++ b/yaksh/templates/yaksh/course_detail_options.html
@@ -0,0 +1,47 @@
+<ul class="nav nav-pills list-group">
+ <li class="nav-item">
+ <a href="{% url 'yaksh:courses' %}" class="nav-link list-group-item" title="View all the courses" data-placement="top" data-toggle="tooltip">
+ Back to Courses
+ </a>
+ </li>
+ <li class="nav-item">
+ <a href="{% url 'yaksh:course_students' course.id %}" id="enroll-students" class="nav-link list-group-item {% if is_students %} active {% endif %}" title="View the course requested, rejected and added students" data-placement="top" data-toggle="tooltip">
+ Enroll Students
+ </a>
+ </li>
+ <li class="nav-item">
+ <a href="{% url 'yaksh:send_mail' course.id %}" class="nav-link list-group-item {% if is_mail %} active {% endif %}" title="Send mail to course students" data-placement="top" data-toggle="tooltip">
+ Send Mail
+ </a>
+ </li>
+ <li class="nav-item">
+ <a href="{% url 'yaksh:course_status' course.id %}" class="nav-link list-group-item {% if is_progress %} active {% endif %}" title="View Students course progress" data-placement="top" data-toggle="tooltip">
+ Course Progress
+ </a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link list-group-item" href="{% url 'yaksh:duplicate_course' course.id %}" data-toggle="tooltip" title="Creates copy of this course and all its contents" data-placement="top">
+ Clone Course
+ </a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link list-group-item {% if is_design_course %} active {% endif %}" href="{% url 'yaksh:design_course' course.id %}" title="Add modules to this course" data-placement="top" data-toggle="tooltip">
+ Design Course
+ </a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link list-group-item {% if is_modules %} active {% endif %}" href="{% url 'yaksh:get_course_modules' course.id %}" title="View modules added to the course" data-placement="top" data-toggle="tooltip">
+ Course Modules
+ </a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link list-group-item {% if is_add_teacher %} active {% endif %}" href="{% url 'yaksh:search_teacher' course.id %}" data-toggle="tooltip" title="Add Teachers/TAs to this course" data-placement="top">
+ Add Teachers/TAs
+ </a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link list-group-item {% if is_teachers %} active {% endif %}" href="{% url 'yaksh:course_teachers' course.id %}" data-toggle="tooltip" title="View all the Teachers/TAs for this course" data-placement="top">
+ Current Teachers/TAs
+ </a>
+ </li>
+</ul> \ No newline at end of file
diff --git a/yaksh/templates/yaksh/course_modules.html b/yaksh/templates/yaksh/course_modules.html
index 8440d51..214f8c7 100644
--- a/yaksh/templates/yaksh/course_modules.html
+++ b/yaksh/templates/yaksh/course_modules.html
@@ -1,186 +1,175 @@
{% extends "user.html" %}
{% load custom_filters %}
{% block title %} Course Modules {% endblock %}
-{% block script %}
-<script>
- function view_unit(unit){
- $("#"+unit+"_down").toggle();
- $("#"+unit+"_up").toggle();
- }
-
-</script>
-{% endblock %}
{% block main %}
-
<div class="container">
-<div class="row justify-content-md-center yakshwell">
- <div class="col-md-10 bg-light card" id="card">
- <div class="row align-items-center">
- <div class="col h4"> {{ course.name }} </div>
- <div class = "col">
- {% if course.has_lessons %}
- <a href="{% url 'yaksh:download_course' course.id %}" data-toggle="tooltip" title="Download course content" class="btn btn-primary pull-right">
- Download Course
- </a>
- {% endif %}
- </div>
- </div>
- </div>
-</div>
-
-<center>
- {% if course.view_grade %}
- <div class=" col-md-8">
- <b>Grade: {% if grade %} {{ grade }} {% else %} Will be available once the course is complete {% endif %}</b>
+ <div class="card">
+ <div class="card-header">
+ {{ course.name }}
</div>
- {% endif %}
-
- {% if msg %}
- <div class="col-md-8 alert alert-warning animated flash" role="alert">
- {{ msg }}
- </div>
- {% endif %}
-</center>
-
-<div class="row justify-content-md-center ">
-{% if modules %}
- <div class="col-md-10 yakshwell">
-
- <strong>Overall Course Progress</strong>
- <div class="progress">
- {% if course_percentage <= 50 %}
- <div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="40"
- aria-valuemin="0" aria-valuemax="100" style="width:{{course_percentage}}%">
- {% elif course_percentage <= 75 %}
- <div class="progress-bar progress-bar-warning" role="progressbar" aria-valuenow="40"
- aria-valuemin="0" aria-valuemax="100" style="width:{{course_percentage}}%">
- {% else %}
- <div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="40"
- aria-valuemin="0" aria-valuemax="100" style="width:{{course_percentage}}%">
- {% endif %}
- <b style="color: black;">{{course_percentage}}% Completed</b>
- </div>
- </div>
-
- {% for module, percent in modules %}
- <div class="yakshwell">
- <div class="row yakshlabel align-items-center">
- <div class="col-md-4">
- {{module.name|title}}
+ <div class="card-body">
+ {% if course.view_grade %}
+ <center>
+ <b>Grade:</b> {% if grade %} {{ grade }} {% else %} Will be available once the course is complete {% endif %}
+ </center>
+ {% endif %}
+ {% if msg %}
+ <div class="alert alert-dismissible alert-warning">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ msg }}</strong>
</div>
-
- <div class="col-md-1">
- <a data-toggle="collapse" data-target="#learning_units{{module.id}}{{course.id}}" onclick="view_unit('learning_units{{module.id}}{{course.id}}');">
- <div class="btn yakshred">
- <span class="fa fa-caret-down fa-2x" id="learning_units{{module.id}}{{course.id}}_down" >
- </span>
- <span class="fa fa-caret-right fa-2x" id="learning_units{{module.id}}{{course.id}}_up" style="display: none; ">
- </span>
+ {% endif %}
+ {% if modules %}
+ <strong>Overall Course Progress:</strong>
+ <div class="progress">
+ {% if course_percentage %}
+ {% if course_percentage <= 50 %}
+ <div class="progress-bar bg-danger" role="progressbar" aria-valuenow="{{course_percentage}}"
+ aria-valuemin="0" aria-valuemax="100" style="width:{{course_percentage}}%">
+ {% elif course_percentage <= 75 %}
+ <div class="progress-bar bg-warning" role="progressbar" aria-valuenow="{{course_percentage}}"
+ aria-valuemin="0" aria-valuemax="100" style="width:{{course_percentage}}%">
+ {% else %}
+ <div class="progress-bar bg-success" role="progressbar" aria-valuenow="{{course_percentage}}"
+ aria-valuemin="0" aria-valuemax="100" style="width:{{course_percentage}}%">
+ {% endif %}
+ <b style="color: white;">{{course_percentage}}% Completed</b>
</div>
- </a>
-
+ {% else %}
+ <b style="color: black;">0% Completed</b>
+ {% endif %}
+ </div>
+ {% else %}
+ <div class="alert alert-danger">
+ <strong>No lectures found</strong>
</div>
- <div class="col-md-5 ml-auto">
- <div class="row align-items-center justify-content-md-end">
- <div class="col-md-3">
- <a href="{{URL_ROOT}}/exam/quizzes/view_module/{{module.id}}/{{course.id}}">
- {% get_module_status user module course as module_status %}
- {% if module_status == "completed" %}
- <div class="btn btn-success ">
- View
- </div>
- {% elif module_status == "inprogress" %}
- <div class="btn btn-info">
- Continue
- </div>
- {% else %}
- <div class="btn btn-danger ">
- Start
+ {% endif %}
+ <br>
+ {% for module, percent in modules %}
+ <div class="accordian-{{module.id}}">
+ <div class="card">
+ <div class="card-header">
+ <div class="row">
+ <div class="col-md-4">
+ {{ module.name|title }}
+ </div>
+ <div class="col-md-3">
+ <a class="card-link btn btn-outline-info" data-toggle="collapse" href="#collapse-{{module.id}}">
+ Details&nbsp;<i class="fa fa-toggle-down"></i>
+ </a>
+ </div>
+ <div class="col-md-2">
+ <a href="{% url 'yaksh:view_module' module.id course.id %}">
+ {% get_module_status user module course as module_status %}
+ {% if module_status == "completed" %}
+ <div class="btn btn-info ">
+ View
+ </div>
+ {% elif module_status == "inprogress" %}
+ <div class="btn btn-primary">
+ Continue
+ </div>
+ {% else %}
+ <div class="btn btn-success ">
+ Start
+ </div>
+ {% endif %}
+ </a>
+ </div>
+ <div class="col-md-3">
+ <div class="progress bg-white">
+ {% if percent %}
+ {% get_module_status user module course as module_status %}
+ {% if module_status == "completed" %}
+ <div class="progress-bar bg-success" role="progressbar" aria-valuenow="{{percent}}"
+ aria-valuemin="0" aria-valuemax="100" style="width:{{percent}}%">
+ {% elif module_status == "inprogress" %}
+ <div class="progress-bar bg-warning" role="progressbar"
+ aria-valuemin="0" aria-valuemax="100" style="width:{{percent}}%">
+ {% endif %}
+ <b style="color: white;">{{percent}}% Completed</b>
+ </div>
+ {% else %}
+ <b style="color: black;">0% Completed</b>
+ {% endif %}
+ </div>
+ </div>
</div>
- {% endif %}
- </a>
</div>
- <div class="col-md-6">
- {% get_module_status user module course as module_status %}
- {% if module_status == "completed" %}
- <div class="progress">
- <div class="progress-bar bg-success" role="progressbar" style="width: 100%; color: black;" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100">{{ percent }} % completed</div>
- </div>
- {% elif module_status == "inprogress" %}
- <div class="progress">
- <div class="progress-bar bg-warning " role="progressbar" style="width: 50%; color: black;" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100">{{ percent }} % completed</div>
+ <div id="collapse-{{module.id}}" class="collapse hide" data-parent="#accordion-{{module.id}}">
+ <div class="card-body">
+ <table class="table yakshwell">
+ {% for unit in module.get_learning_units %}
+ <tr>
+ <td>
+ {% if unit.type == "quiz" %}
+ {% if unit.quiz.is_exercise %}
+ <span class="fa fa-pencil"></span>
+ {% else %}
+ <span class="fa fa-puzzle-piece"></span>
+ {% endif %}
+ {% else %}
+ <span class="fa fa-book"></span>
+ {% endif %}
+ </td>
+ <td>
+ {% if unit.type == "quiz" %}
+ {{unit.quiz.description}}
+ {% else %}
+ {{unit.lesson.name}}
+ {% endif %}
+ </td>
+ <td>
+ {% if unit.type == "lesson" %}
+ <a href="{% url 'yaksh:show_lesson' unit.lesson.id module.id course.id %}" class="btn btn-outline-info">
+ View
+ </a>
+ {% else %}
+ <a href="{% url 'yaksh:start_quiz' unit.quiz.questionpaper_set.get.id module.id course.id %}" class="btn btn-outline-info">
+ View
+ </a>
+ {% endif %}
+ </td>
+ <td>
+ {% get_unit_status course module unit user as status %}
+ {% if status == "completed" %}
+ <span class="badge badge-success">{{status|title}}
+ </span>
+ {% elif status == "inprogress" %}
+ <span class="badge badge-info">{{status|title}}
+ </span>
+ {% else %}
+ <span class="badge badge-warning">{{status|title}}
+ </span>
+ {% endif %}
+ </td>
+ <td>
+ {% if unit.type == "quiz" %}
+ {% if unit.quiz.view_answerpaper %}
+ <a href="{% url 'yaksh:view_answerpaper' unit.quiz.questionpaper_set.get.id course.id %}" >
+ <i class="fa fa-eye"></i>&nbsp;Answer paper</a>
+ {% else %}
+ <a >
+ <i class="fa fa-eye-slash" aria-hidden="true">
+ </i>Answer paper</a>
+ {% endif %}
+ {% else %}
+ ------
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
</div>
- {% else %}
- <div class="progress">
- <div class="progress-bar bg-danger" role="progressbar" style="width: 1%; color: black;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">{{ percent }} % completed</div>
- </div>
- {% endif %}
- </div>
</div>
</div>
</div>
- <div id="learning_units{{module.id}}{{course.id}}" class="collapse">
- <table class="table yakshwell">
-
- {% for unit in module.get_learning_units %}
- <tr>
- <td>
- {% if unit.type == "quiz" %}
- {% if unit.quiz.is_exercise %}
- <span class="fa fa-pencil"></span>
- {% else %}
- <span class="fa fa-puzzle-piece"></span>
- {% endif %}
- {% else %}
- <span class="fa fa-book"></span>
- {% endif %}
- </td>
- <td>
- {% if unit.type == "quiz" %}
- {{unit.quiz.description}}
- {% else %}
- {{unit.lesson.name}}
- {% endif %}
- </td>
-
- <td>
- {% get_unit_status course module unit user as status %}
- {% if status == "completed" %}
- <span class="badge badge-success">{{status|title}}
- </span>
- {% elif status == "inprogress" %}
- <span class="badge badge-info">{{status|title}}
- </span>
- {% else %}
- <span class="badge badge-warning">{{status|title}}
- </span>
- {% endif %}
- </td>
- <td>
- {% if unit.type == "quiz" %}
- {% if unit.quiz.view_answerpaper %}
- <a href="{{ URL_ROOT }}/exam/view_answerpaper/{{ unit.quiz.questionpaper_set.get.id }}/{{course.id}}" >
- <i class="fa fa-eye" aria-hidden="true"></i>Answer paper</a>
- {% else %}
- <a >
- <i class="fa fa-eye-slash" aria-hidden="true">
- </i>Answer paper</a>
- {% endif %}
- {% else %}
- ------
- {% endif %}
- </td>
- </tr>
- {% endfor %}
- </table>
- </div>
+ <br>
+ {% endfor %}
</div>
- {% endfor %}
</div>
-{% else %}
- <h3 class="alert-danger"> No lectures found </h3>
-{% endif %}
-</div>
</div>
{% endblock %}
diff --git a/yaksh/templates/yaksh/course_progress.html b/yaksh/templates/yaksh/course_progress.html
new file mode 100644
index 0000000..a833c92
--- /dev/null
+++ b/yaksh/templates/yaksh/course_progress.html
@@ -0,0 +1,70 @@
+<!-- Course Status -->
+{% if is_progress %}
+<div class="course_data">
+ {% if student_details %}
+ <div class="text-center">
+ <h3>Course Progress</h3>
+ <div class="col">
+ Number Of Students: {{ students_no }}
+ </div>
+ </div>
+ {% include "yaksh/paginator.html" %}
+ <table class="tablesorter table table-bordered table-responsive-sm" id="course_table" data-sortlist="[0,0]">
+ <thead>
+ <tr>
+ <th>Sr. No</th>
+ <th>Roll No.</th>
+ <th>Name</th>
+ <th>Current Unit</th>
+ <th>Completion Percentage</th>
+ <th>Grade</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for student, grade, percent, unit in student_details %}
+ <tr>
+ <td>{{forloop.counter}}</td>
+ <td>
+ {{ student.profile.roll_number}}
+ </td>
+ <td width="50%">
+ <input type="hidden" id="url-{{student.id}}" data-url="{% url 'yaksh:get_user_data' course.id student.id %}">
+ <a class="user_data" data-item-id="{{course.id}}+{{student.id}}" data-toggle="tooltip" title="Click to view Overall Course progress" data-placement="top">
+ {{ student.get_full_name|title}}
+ <i class="fa fa-caret-down"></i>
+ </a>
+ <div id="show_status_{{course.id}}_{{student.id}}" style="display: None;">
+ </div>
+ </td>
+ <td>
+ {% if unit %}
+ {% if unit.type == 'quiz' %}
+ {{unit.quiz.description}}
+ {% else %}
+ {{unit.lesson.name}}
+ {% endif %}
+ {% else %}
+ NA
+ {% endif%}
+ </td>
+ <td>
+ {{ percent }} %
+ </td>
+ <td>
+ {{ grade }}
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% include "yaksh/paginator.html" %}
+ {% else %}
+ <center>
+ <span class="badge badge-warning">
+ <big>No course data found</big>
+ </span>
+ </center>
+ {% endif %}
+</div>
+<!-- End Course Status -->
+{% endif %} \ No newline at end of file
diff --git a/yaksh/templates/yaksh/course_send_mail.html b/yaksh/templates/yaksh/course_send_mail.html
new file mode 100644
index 0000000..57442a6
--- /dev/null
+++ b/yaksh/templates/yaksh/course_send_mail.html
@@ -0,0 +1,63 @@
+<!-- Send Mail -->
+{% if is_mail %}
+<div id="send-mail">
+ {% if enrolled %}
+ <form action="{% url 'yaksh:send_mail' course.id %}" method="post" id="send_mail_form" enctype="multipart/form-data">
+ {% csrf_token %}
+ <div class="card">
+ <div class="card-body">
+ <textarea name="subject" class="form-control" id="subject" placeholder="Email Subject"></textarea>
+ <br><br>
+ <textarea name="body" id="email_body"></textarea><br>
+ Attachments:
+ <div class="input-group mb-3">
+ <div class="custom-file">
+ <input type="file" class="custom-file-input" name="email_attach" id="upload" multiple="">
+ <label class="custom-file-label" for="upload">Choose file</label>
+ </div>
+ </div>
+ <br>
+ </div>
+ </div>
+ <br>
+ <input type="checkbox" class="send_check"/>&nbsp;
+ <font size="5">Select all</font>
+ <div id="sender_list">
+ <table id="mail_table" class="tablesorter table table-striped table-responsive-sm course-detail" data-sortlist="[1,0]">
+ <thead>
+ <th></th>
+ <th>Full Name&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Email&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Roll Number&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Institute&nbsp;<i class="fa fa-sort"></i></th>
+ </thead>
+ <tbody>
+ {% for enroll in enrolled %}
+ <tr>
+ <td>
+ {{ forloop.counter }}.
+ <input type="checkbox" name="check" value="{{ enroll.id }}">
+ </td>
+ <td> {{ enroll.get_full_name|title }} </td>
+ <td> {{enroll.email}}</td>
+ {% with enroll.profile as user_profile %}
+ <td> {{user_profile.roll_number}}</td>
+ <td> {{user_profile.institute}}</td>
+ {% endwith %}
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ <button class="btn btn-success btn-lg" type="submit" name='send_mail' value='send_mail' id="send_mail">
+ Send Mail
+ </button>
+ </div>
+ </form>
+ {% else %}
+ <center>
+ <span class="badge badge-warning"><big> No enrolled students yet</big></span>
+ </center>
+ {% endif %}
+</div>
+<!-- End send mail -->
+{% endif %} \ No newline at end of file
diff --git a/yaksh/templates/yaksh/course_students.html b/yaksh/templates/yaksh/course_students.html
new file mode 100644
index 0000000..03c57b8
--- /dev/null
+++ b/yaksh/templates/yaksh/course_students.html
@@ -0,0 +1,245 @@
+{% if is_students %} <!-- Start if course students -->
+<!-- Upload Users -->
+<div id="accordian-upload" class="card">
+ <div class="card-header">
+ <a class="card-link" data-toggle="collapse" href="#upload_users_csv">
+ Upload Users&nbsp;<i class="fa fa-angle-down"></i>
+ </a>
+ </div>
+</div>
+<div id="upload_users_csv" class="collapse hide" data-parent="#accordion-upload">
+ <div class="card-body">
+ <form id="upload_users" action="{% url 'yaksh:upload_users' course.id %}" method="POST" enctype="multipart/form-data">
+ {% csrf_token %}
+ <div class="input-group mb-3">
+ <div class="custom-file">
+ <input type="file" class="custom-file-input" name="csv_file" id="upload"/>
+ <label class="custom-file-label" for="upload">Choose file</label>
+ </div>
+ <div class="input-group-append">
+ <button class="btn btn-outline-primary" type="submit">
+ <i class="fa fa-upload"></i>
+ Upload
+ </button>
+ </div>
+ </div>
+ </form>
+ <hr>
+ <p>
+ - The uploaded csv should have headers exactly same as mentioned below:<br />
+ <b>firstname, lastname, email, username, password, institute, roll_no, department,
+ remove</b><br />
+ - Mandatory fields are <b> firstname, lastname and email. </b><br />
+ - Other fields are optional. <br />
+ - If username and password are not provided then
+ <b>Users created will have username and password same as their email</b>
+ </p>
+ <p>
+ <b> Click
+ <a class="btn btn-success" href="{% url 'yaksh:download_sample_csv' %}">
+ here
+ </a> to download a sample CSV, edit and upload it</b>
+ </p>
+ </div>
+</div>
+<!-- End Upload users -->
+<br>
+<!-- Enrolled Students -->
+<div id="accordian-enrolled" class="card">
+ <div class="card-header">
+ <a class="card-link" data-toggle="collapse" href="#enrolled">
+ Enrolled Students&nbsp;<i class="fa fa-angle-down"></i>
+ </a>
+ </div>
+</div>
+<div id="enrolled" class="collapse hide" data-parent="#accordion-enrolled">
+ {% if enrolled %}
+ <br>
+ <input type="checkbox" class="reject"/>&nbsp;
+ <font size="5">Select all</font>
+ <div id="reject">
+ <form action="{% url 'yaksh:reject_users' course.id %}" method="post" id="reject-form">
+ {% csrf_token %}
+ <table id="enrolled_table" class="tablesorter table table-striped table-responsive-sm course-detail" data-sortlist="[1,0]" style="width: 100%">
+ <thead>
+ <th></th>
+ <th>Full Name&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Email&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Roll Number&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Institute&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Department&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Reject</th>
+ </thead>
+ <tbody>
+ {% for enroll in enrolled %}
+ <tr>
+ <td>
+ {{ forloop.counter }}.
+ <input type="checkbox" name="check" value="{{ enroll.id }}">
+ </td>
+ <td> {{ enroll.get_full_name|title }} </td>
+ <td> {{enroll.email}}</td>
+ {% with enroll.profile as enroll_profile %}
+ <td> {{enroll_profile.roll_number}}</td>
+ <td> {{enroll_profile.institute}}</td>
+ <td> {{enroll_profile.department}}</td>
+ {% endwith %}
+ <td>
+ <a class="btn btn-danger"
+ href="{% url 'yaksh:reject_user' course.id enroll.id %}">
+ <i class="fa fa-minus-square"></i>
+ Reject
+ </a>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ <button class="btn btn-danger btn-lg" type="submit" name='reject' value='reject'>
+ <i class="fa fa-minus-square"></i>
+ Reject Selected
+ </button> <br>
+ </form>
+ </div>
+ {% else %}
+ <center>
+ <span class="badge badge-warning"><big> No enrolled students yet</big></span>
+ </center>
+ {% endif %}
+</div>
+<!-- End Enrolled Students -->
+
+<br>
+<!-- Requested Students -->
+<div id="accordian-request" class="card">
+ <div class="card-header">
+ <a class="card-link" data-toggle="collapse" href="#requested">
+ Requested Students&nbsp;<i class="fa fa-angle-down"></i>
+ </a>
+ </div>
+</div>
+<div id="requested" class="collapse hide" data-parent="#accordion-request">
+ {% if requested %}
+ <br>
+ <input type="checkbox" class="checkall"/>&nbsp;
+ <font size="5">Select all</font>
+ <div id="enroll-all">
+ <form action="{% url 'yaksh:enroll_users' course.id %}" method="post">
+ {% csrf_token %}
+ <table id="requested_table" class="tablesorter table table-striped table-responsive-sm course-detail" data-sortlist="[1,0]">
+ <thead>
+ <th></th>
+ <th>Full Name&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Email&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Roll Number&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Institute&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Department&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Enroll/Reject</th>
+ </thead>
+ <tbody>
+ {% for request in requested %}
+ <tr>
+ <td>
+ {{ forloop.counter }}.
+ <input type="checkbox" name="check" value="{{ request.id }}">
+ </td>
+ <td>{{request.get_full_name}}</td>
+ <td> {{request.email}}</td>
+ {% with request.profile as request_profile %}
+ <td> {{request_profile.roll_number}}</td>
+ <td> {{request_profile.institute}}</td>
+ <td> {{request_profile.department}}</td>
+ {% endwith %}
+ <td>
+ <a class="btn btn-success"
+ href="{% url 'yaksh:enroll_user' course.id request.id %}">
+ <i class="fa fa-plus-square"></i>
+ Enroll </a>
+ <a class="btn btn-danger"
+ href="{% url 'yaksh:reject_user' course.id request.id %}">
+ <i class="fa fa-minus-square"></i>
+ Reject </a>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ <button class="btn btn-success btn-lg" type="submit" name='enroll' value='enroll'>
+ <i class="fa fa-plus-square"></i>
+ Enroll Selected
+ </button> <br>
+ </form>
+ </div>
+ {% else %}
+ <center>
+ <span class="badge badge-warning"><big> No requests yet</big></span>
+ </center>
+ {% endif %}
+</div>
+<!-- End Requested Students -->
+<br>
+<!-- Rejected Students -->
+<div id="accordian-rejected" class="card">
+ <div class="card-header">
+ <a class="card-link" data-toggle="collapse" href="#rejected">
+ Rejected Students&nbsp;<i class="fa fa-angle-down"></i>
+ </a>
+ </div>
+</div>
+<div id="rejected" class="collapse hide" data-parent="#accordion-rejected">
+ {% if rejected %}
+ <br>
+ <input type="checkbox" class="enroll"/>&nbsp;
+ <font size="5">Select all</font>
+ <div id="enroll">
+ <form action="{% url 'yaksh:enroll_rejected' course.id %}" method="post">
+ {% csrf_token %}
+ <table id="rejected_table" class="tablesorter table table-striped table-responsive-sm course-detail" data-sortlist="[1,0]">
+ <thead>
+ <th>Full Name&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Email&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Roll Number&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Institute&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Department&nbsp;<i class="fa fa-sort"></i></th>
+ <th>Enroll</th>
+ </thead>
+ <tbody>
+ {% for reject in rejected %}
+ <tr>
+ <td>
+ {{ forloop.counter }}.
+ <input type="checkbox" name="check" value="{{ reject.id }}">
+ </td>
+ <td>{{reject.get_full_name|title}}</td>
+ <td> {{reject.email}}</td>
+ {% with reject.profile as reject_profile %}
+ <td> {{reject_profile.roll_number}}</td>
+ <td> {{reject_profile.institute}}</td>
+ <td> {{reject_profile.department}}</td>
+ {% endwith %}
+ <td>
+ <a class="btn btn-success"
+ href="{% url 'yaksh:enroll_rejected' course.id reject.id %}">
+ <i class="fa fa-plus-square"></i>
+ Enroll </a>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ <br>
+ <button class="btn btn-success btn-lg" type="submit" name='enroll' value='enroll'>
+ <i class="fa fa-plus-square"></i>
+ Enroll Selected
+ </button>
+ <br>
+ </form>
+ </div>
+ {% else %}
+ <center>
+ <span class="badge badge-warning"><big> No rejected students yet</big></span>
+ </center>
+ {% endif %}
+</div>
+<!-- End Rejected Students -->
+{% endif %} \ No newline at end of file
diff --git a/yaksh/templates/yaksh/course_teachers.html b/yaksh/templates/yaksh/course_teachers.html
new file mode 100644
index 0000000..1b1af87
--- /dev/null
+++ b/yaksh/templates/yaksh/course_teachers.html
@@ -0,0 +1,29 @@
+<center><h3>Teacher(s)/TA(s)</h3></center>
+<br>
+
+{% if teachers %}
+ <form action="{% url 'yaksh:remove_teacher' course.id %}" method="post">
+ {% csrf_token %}
+ <div class="container">
+ <table class="table table-responsive-sm course-detail">
+ <tr>
+ <th>Select</th>
+ <th>Name</th>
+ </tr>
+ {% for teacher in teachers %}
+ <tr>
+ <td><input type="checkbox" name="remove" value="{{ teacher.id }}"></td>
+ <td>{{ teacher.get_full_name }}</td>
+ </tr>
+ {% endfor %}
+ <table>
+ </div>
+ <br>
+ <button class="btn btn-danger" type="submit" data-toggle="tooltip" title="Remove Selected Teachers from this course">
+ <i class="fa fa-minus-square"></i>
+ Remove Teachers
+ </button>
+ </form>
+{% else %}
+ <center><b class="badge badge-warning">No Teacher(s) added</b></center>
+{% endif %} \ No newline at end of file
diff --git a/yaksh/templates/yaksh/courses.html b/yaksh/templates/yaksh/courses.html
index e5f3936..5d2c913 100644
--- a/yaksh/templates/yaksh/courses.html
+++ b/yaksh/templates/yaksh/courses.html
@@ -22,11 +22,6 @@
</a>
</li>
<li class="nav-item">
- <a class="nav-link {% if allotted %}active{% endif %}" href="{% url 'yaksh:allotted_courses' %}">
- Allotted Courses
- </a>
- </li>
- <li class="nav-item">
<a class="nav-link" href="{% url 'yaksh:add_course' %}">
Add New Course
</a>
@@ -35,16 +30,16 @@
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="true">More</a>
<div class="dropdown-menu hide" x-placement="bottom-start" style="position: absolute; transform: translate3d(0px, 37px, 0px); top: 0px; left: 0px; will-change: transform;">
<a class="dropdown-item" href="{% url 'yaksh:show_all_quizzes' %}">
- View Quizzes
+ Add/View Quizzes
</a>
<a class="dropdown-item" href="{% url 'yaksh:show_all_lessons' %}">
- View Lessons
+ Add/View Lessons
</a>
<a class="dropdown-item" href="{% url 'yaksh:show_all_modules' %}">
- View Modules
+ Add/View Modules
</a>
<a href="{% url 'grades:grading_systems'%}" class="dropdown-item" >
- View Grading Systems
+ Add/View Grading Systems
</a>
</div>
</li>
@@ -52,20 +47,17 @@
</div>
</div>
</div>
- {% if not objects %}
- <center>
- <h2> No Courses Found </h2>
- <br>
- <a href="{% url 'yaksh:add_course' %}" class="btn btn-success btn-lg">
- <span class=" fa fa-plus-circle"></span>&nbsp;Add Course
- </a>
- </center>
- {% else %}
- <div class="container">
+ <div class="container">
+ {% if not objects %}
+ <br><br>
+ <div class="alert alert-info">
+ <center> <h3> No Courses Found </h3> </center>
+ </div>
+ {% else %}
<hr>
{% if messages %}
{% for message in messages %}
- <div class="alert alert-dismissible alert-info">
+ <div class="alert alert-dismissible alert-{{ message.tags }}">
<button type="button" class="close" data-dismiss="alert">
<i class="fa fa-close"></i>
</button>
@@ -74,28 +66,121 @@
{% endfor %}
{% endif %}
{% with objects as courses %}
- {% include "yaksh/paginator.html" %}
<div class="row">
- <br>
- {% for course in courses %}
- <div class="col-md-6">
- <div class="card border-primary">
- <div class="card-header" style="height: 150px">
- {{course.name}}
- </div>
- <div class="card-body">
- <div class="row">
- <div class="col">
- <strong>Starts On:</strong>
- {{course.start_enroll_time}}
- <br>
- <strong>Ends On:</strong>
- {{course.end_enroll_time}}
+ <div class="col-md-4">
+ {% include "yaksh/paginator.html" %}
+ </div>
+ <div class="ml-auto">
+ <div class="nav nav-pills" role="tablist" aria-orientation="vertical">
+ <a href="#listview" id="listbtn" class="nav-link" data-toggle="pill" role="tab" aria-controls="show" aria-selected="true"> <i class="fa fa-list"></i></a>
+ <a href="#gridview" id="gridbtn" class="nav-link active" data-toggle="pill" role="tab" aria-controls="updown" aria-selected="false" > <i class="fa fa-columns"></i></a>
+ </div>
+ </div>
+ </div>
+
+ <div class="tab-content">
+ <div class="tab-pane active" id="gridview" role="tabpanel" aria-labelledby="gridbtn">
+ <!-- GridView -->
+ <br>
+ <div class="row">
+ <br>
+ {% for course in courses %}
+ <div class="col-md-6">
+ <div class="card border-primary">
+ <div class="card-header" style="height: 150px">
+ {{course.name}}
+ </div>
+ <div class="card-body">
+ <div class="row">
+ <div class="col">
+ <strong>Starts On:</strong>
+ {{course.start_enroll_time}}
+ <br>
+ <strong>Ends On:</strong>
+ {{course.end_enroll_time}}
+ </div>
+ </div>
+ <hr>
+ <div class="row">
+ <div class="col-md-5">
+ <span class="badge badge-pill badge-info">
+ {% if user.id != course.creator.id %}
+ Allotted Course
+ {% else %}
+ Created Course
+ {% endif %}
+ </span>
+ </div>
+ <div class="col-md-3">
+ {% if course.active %}
+ <span class="badge badge-pill badge-success">
+ Active
+ </span>
+ {% else %}
+ <span class="badge badge-pill badge-danger">
+ Inactive
+ </span>
+ {% endif %}
+ </div>
+ <div class="col-md-4">
+ <a href="{% url 'yaksh:toggle_course_status' course.id %}">
+ {% if course.active %}
+ <i class="fa fa-toggle-on fa-2x"></i>
+ {% else %}
+ <i class="fa fa-toggle-off fa-2x"></i>
+ {% endif %}
+ </a>
+ </div>
+ </div>
+ <hr>
+ <div class="row">
+ <div class="col-md-4">
+ <a href="{% url 'yaksh:edit_course' course.id %}" class="btn btn-info">
+ <i class="fa fa-edit"></i>
+ Edit Course
+ </a>
+ </div>
+ <div class="col-md-4">
+ <a href="{% url 'yaksh:course_detail' course.id %}" class="btn btn-primary">
+ <i class="fa fa-tasks"></i>
+ Manage Course
+ </a>
+ </div>
+ <div class="col-md-4">
+ <a href="{% url 'yaksh:download_course_csv' course.id %}" class="btn btn-secondary">
+ <i class="fa fa-download"></i>
+ Download CSV
+ </a>
+ </div>
+ </div>
</div>
</div>
- <hr>
+ <br>
+ </div>
+ {% endfor %}
+ <br>
+ </div>
+ </div>
+ <div class="tab-pane" id="listview" role="tabpanel" aria-labelledby="gridbtn">
+ <!-- ListView -->
+ <br>
+ {% for course in courses %}
+ <div class="card">
+ <div class="card-header">
<div class="row">
- <div class="col-md-6">
+ <div class="col-md-5">
+ {{course.name}}
+ </div>
+ <div class="col-md-3">
+ <span class="badge badge-pill badge-info">
+ {% if user.id != course.creator.id %}
+ Allotted Course
+ {% else %}
+ Created Course
+ {% endif %}
+ </span>
+ </div>
+ <div class="col-md-2">
{% if course.active %}
<span class="badge badge-pill badge-success">
Active
@@ -106,8 +191,8 @@
</span>
{% endif %}
</div>
- <div class="col-md-6">
- <a href="{{URL_ROOT}}/exam/manage/toggle_status/{{ course.id }}/">
+ <div class="col-md-2">
+ <a href="{% url 'yaksh:toggle_course_status' course.id %}">
{% if course.active %}
<i class="fa fa-toggle-on fa-2x"></i>
{% else %}
@@ -116,20 +201,34 @@
</a>
</div>
</div>
+ </div>
+ <div class="card-body">
+ <div class="row">
+ <div class="col">
+ <strong>Starts On:</strong>
+ {{course.start_enroll_time}}
+ <br>
+ <strong>Ends On:</strong>
+ {{course.end_enroll_time}}
+ </div>
+ </div>
<hr>
<div class="row">
<div class="col-md-4">
- <a href="{{URL_ROOT}}/exam/manage/edit_course/{{course.id}}" class="btn btn-primary">
+ <a href="{% url 'yaksh:edit_course' course.id %}" class="btn btn-info">
+ <i class="fa fa-edit"></i>
Edit Course
</a>
</div>
<div class="col-md-4">
- <a href="{% url 'yaksh:course_detail' course.id %}" class="btn btn-info">
+ <a href="{% url 'yaksh:course_detail' course.id %}" class="btn btn-primary">
+ <i class="fa fa-tasks"></i>
Manage Course
</a>
</div>
<div class="col-md-4">
- <a href="{{URL_ROOT}}/exam/manage/courses/download_course_csv/{{course.id}}" class="btn btn-secondary">
+ <a href="{% url 'yaksh:download_course_csv' course.id %}" class="btn btn-secondary">
+ <i class="fa fa-download"></i>
Download CSV
</a>
</div>
@@ -137,13 +236,13 @@
</div>
</div>
<br>
- </div>
- {% endfor %}
- <br>
+ {% endfor %}
+ <br>
+ </div>
</div>
{% include "yaksh/paginator.html" %}
{% endwith %}
- </div>
- {% endif %}
+ {% endif %}
+ </div>
</div>
{% endblock %} \ No newline at end of file
diff --git a/yaksh/templates/yaksh/design_course_session.html b/yaksh/templates/yaksh/design_course_session.html
index a2d9b08..a15f4b1 100644
--- a/yaksh/templates/yaksh/design_course_session.html
+++ b/yaksh/templates/yaksh/design_course_session.html
@@ -1,30 +1,20 @@
-{% extends "manage.html" %}
-{% load custom_filters %}
-{% block title %}Design Course Session{% endblock %}
+{% load static %}
-{% block pagetitle %}Design Course Session{% endblock %}
+{% block title %} <center> <h3> Design Course Session </h3> </center>{% endblock %}
{% block script %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery-3.3.1.min.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/design_course.js"></script>
+<script language="JavaScript" type="text/javascript" src="{% static 'yaksh/js/design_course.js' %}"></script>
{% endblock %}
{% block css %}
-<link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/design_course.css" />
+<link rel="stylesheet" href="{% static 'yaksh/css/design_course.css' %}">
{% endblock %}
-{% block main %}
-<div class="yakshwell container">
-<a href="{{URL_ROOT}}/exam/manage/courses/" class="btn btn-primary">
- Back to Courses
-</a>
-<br/>
-<br/>
-<form action="{{URL_ROOT}}/exam/manage/courses/designcourse/{{course_id}}/" method="POST" id="design_course_form">
+<form action="{% url 'yaksh:design_course' course.id %}" method="POST" id="design_course_form">
{% csrf_token %}
- <div class="tab-pane active" id="available-lesson-quiz">
+ <div id="available-lesson-quiz">
<div class="row">
- <div class="col-md-8 col-md-offset-2 available-list">
+ <div class="col-md-12 available-list">
<div id="fixed-available-wrapper">
<p><u><b>Available Modules:</b></u></p>
<div id="fixed-available">
@@ -61,11 +51,12 @@
</div>
<br>
<center>
- <button id="Add" name="Add" class="btn btn-success" type="submit">Add to course</button>
+ <button id="Add" name="Add" class="btn btn-success" type="submit">
+ <i class="fa fa-plus-square"></i>&nbsp;Add to course</button>
</center>
<br><br>
</div>
- <div class="col-md-8 col-md-offset-2">
+ <div class="col-md-12">
<div id="fixed-added-wrapper">
<p><u><b>Chosen Modules:</b></u></p>
<div id="fixed-added">
@@ -136,8 +127,8 @@
</div>
<br>
<center>
- <button id="Remove" name="Remove" class="btn btn-danger" type="submit">Remove from course</button>
- <button id="Change" name="Change" class="btn btn-info" type="submit"> Change Order</button>
+ <button id="Remove" name="Remove" class="btn btn-danger" type="submit"><i class="fa fa-minus-square"></i>&nbsp;Remove from course</button>
+ <button id="Change" name="Change" class="btn btn-info" type="submit"><i class="fa fa-reorder"></i>&nbsp;Change Order</button>
<button id="Change" name="change_prerequisite_completion" class="btn btn-primary" type="submit"> Change Prerequisite Completion</button>
<button id="Change_prereq_passing" name="change_prerequisite_passing" class="btn btn-primary" type="submit"> Change Prerequisite Passing</button>
@@ -145,6 +136,4 @@
</div>
</div> <!-- /.row -->
</div>
-</form>
-</div>
-{% endblock %} \ No newline at end of file
+</form> \ No newline at end of file
diff --git a/yaksh/templates/yaksh/design_questionpaper.html b/yaksh/templates/yaksh/design_questionpaper.html
index 0ab7cc0..6e916a3 100644
--- a/yaksh/templates/yaksh/design_questionpaper.html
+++ b/yaksh/templates/yaksh/design_questionpaper.html
@@ -1,39 +1,36 @@
{% extends "manage.html" %}
+{% load static %}
{% block title %} Design Question Paper {% endblock title %}
{% block subtitle %} Design Question Paper {% endblock %}
{% block css %}
- <link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/question_paper_creation.css" />
-<style>
-select
-{
- width:auto;
-}
-</style>
+ <link rel="stylesheet" media="all" type="text/css" href="{% static 'yaksh/css/question_paper_creation.css' %}" />
{% endblock %}
{% block script %}
- <script src="{{ URL_ROOT }}/static/yaksh/js/jquery-3.3.1.min.js"></script>
- <script src="{{ URL_ROOT }}/static/yaksh/js/jquery-ui.js"></script>
- <script src="{{ URL_ROOT }}/static/yaksh/js/bootstrap.min.js"></script>
- <script src="{{ URL_ROOT }}/static/yaksh/js/question_paper_creation.js"></script>
+ <script src="{% static 'yaksh/js/jquery-ui.js' %}"></script>
+ <script src="{% static 'yaksh/js/question_paper_creation.js' %}"></script>
{% endblock %}
{% block content %}
-<div class="yakshwell container">
+<div class="container">
<input type=hidden id="url_root" value={{ URL_ROOT }}>
{% if course_id %}
- <form action="{{ URL_ROOT }}/exam/manage/designquestionpaper/{{ qpaper.quiz.id }}/{{ qpaper.id }}/{{course_id}}/" method="POST" id="design_q">
- <a href="{{URL_ROOT}}/exam/manage/courses" class="btn btn-danger">Cancel</a>
+ <form action="{% url 'yaksh:designquestionpaper' qpaper.quiz.id qpaper.id course_id %}" method="POST" id="design_q">
+ <a href="{% url 'yaksh:get_course_modules' course_id %}" class="btn btn-primary">
+ <i class="fa fa-arrow-left"></i>&nbsp;Back
+ </a>
{% else %}
- <form action="{{ URL_ROOT }}/exam/manage/designquestionpaper/{{ qpaper.quiz.id }}/{{ qpaper.id }}/" method="POST" id="design_q">
- <a href="{{URL_ROOT}}/exam/manage/courses/all_quizzes" class="btn btn-danger">Cancel</a>
+ <form action="{% url 'yaksh:designquestionpaper' qpaper.quiz.id qpaper.id %}" method="POST" id="design_q">
+ <a href="{% url 'yaksh:show_all_quizzes' %}" class="btn btn-primary">
+ <i class="fa fa-arrow-left"></i>&nbsp;Back
+ </a>
{% endif %}
{% 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>
+ <center><b>Manual mode to design the {{lang}} Question Paper</center><br>
<div class = "tab-base">
<ul class="nav nav-pills tabs">
<li id="fixed-tab">
@@ -55,86 +52,105 @@ select
</a></li>
</ul>
</div>
+ <br>
<div>
- <h3>Total Marks: <span id="total_marks" class="well"> {{ qpaper.total_marks }} </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">
- <div class = "col-md-8">
- <h5>Please select Question type and Marks</h5>
+ <br>
+ {% if messages %}
+ {% for message in messages %}
+ <div class="alert alert-dismissible alert-{{ message.tags }}">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ message }}</strong>
</div>
- <div class="col-md-6">
- {{ filter_form.question_type }}
- </div>
- <div class="col-md-6">
- {{ filter_form.marks }}
- </div>
- </div> <!-- /.row -->
- <br><br>
- {% csrf_token %}
- <div class="tab-pane active" id="fixed-questions">
- <h4>Or</h4>
- <!-- Search questions using tags -->
- <h4>Search using Tags: </h4>
- <span class="input-group-addon" id="basic-addon1">Search Questions: </span>
- <div class="col-md-14">
- <div class="input-group">
- <input type="text" id="question_tags" name="question_tags" class="form-control"
- placeholder="Search using comma separated Tags">
- <span class="input-group-btn">
- <button class="btn btn-default" type="submit">Search</button>
- </span>
+ {% endfor %}
+ {% endif %}
+ <div class="tab-content">
+ <!-- common to fixed and random questions -->
+ <div class="row" id="selectors">
+ <div class = "col-md-8">
+ <h5>Please select Question type and Marks</h5>
+ </div>
<div class="col-md-6">
- <select class="form-control" id="sel1" onchange="append_tag(this);">
- {% if all_tags %}
- <option value="" disabled selected>Available Tags</option>
- {% for tag in all_tags %}
- <option>
- {{tag}}
- </option>
- {% endfor %}
- {% else %}
- <option value="" disabled selected>No Available Tags</option>
- {% endif %}
- </select>
+ {{ filter_form.question_type }}
</div>
- </div>
- </div>
- <br><br>
- <div class="row">
<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>
- {% if user == question.user %}
- <a href="{{URL_ROOT}}/exam/manage/addquestion/{{ question.id }}" target="_blank">{{ question.summary }}</a>
- {% else %}
- {{question.summary}}
- {% endif %}
- </span>
- <span> {{ question.points }}</span>
- </label>
- </li>
- {% endfor %}
- </ul>
- {% endif %}
- </div>
- <br /><br />
- <button id="add-fixed" name="add-fixed" class="btn small btn-primary pull-right" type="submit">Add to paper</button>
+ {{ filter_form.marks }}
+ </div>
+ </div> <!-- /.row -->
+ <br>
+ {% csrf_token %}
+ <div class="tab-pane active" id="fixed-questions">
+ <h4>Or</h4>
+ <!-- Search questions using tags -->
+ <h4>Search using Tags: </h4>
+ <span class="input-group-addon" id="basic-addon1">Search Questions: </span>
+ <div class="col-md-14">
+ <div class="input-group">
+ <input type="text" id="question_tags" name="question_tags" class="form-control"
+ placeholder="Search using comma separated Tags">
+ <span class="input-group-btn">
+ <button class="btn btn-outline-primary" type="submit">
+ <i class="fa fa-search"></i>&nbsp;Search
+ </button>
+ </span>
+ <div class="col-md-6">
+ <select class="form-control" id="sel1" onchange="append_tag(this);">
+ {% if all_tags %}
+ <option value="" disabled selected>Available Tags</option>
+ {% for tag in all_tags %}
+ <option>
+ {{tag}}
+ </option>
+ {% endfor %}
+ {% else %}
+ <option value="" disabled selected>No Available Tags</option>
+ {% endif %}
+ </select>
</div>
</div>
- <div class="col-md-6">
- <div id="fixed-added-wrapper">
- <p><u>Fixed questions currently in paper:</u></p>
- <div id="fixed-added">
+ </div>
+ <br><br>
+ <br>
+ <div class="row">
+ <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>
+ {% if user == question.user %}
+ <a href="{% url 'yaksh:add_question' question.id %}" target="_blank">{{ question.summary }}</a>
+ {% else %}
+ {{question.summary}}
+ {% endif %}
+ </span>
+ <span> {{ question.points }}</span>
+ </label>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ </div>
+ </div>
+ <br />
+ <button id="add-fixed" name="add-fixed" class="btn btn-success pull-right" type="submit">
+ <i class="fa fa-plus-square"></i>&nbsp;Add to paper
+ </button>
+ </div>
+ <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>
@@ -143,7 +159,7 @@ select
data-qid="{{question.id}}" value={{question.id}}>
<span>
{% if user == question.user %}
- <a href="{{URL_ROOT}}/exam/manage/addquestion/{{ question.id }}" target="_blank">{{ question.summary }}</a>
+ <a href="{% url 'yaksh:add_question' question.id %}" target="_blank">{{ question.summary }}</a>
{% else %}
{{question.summary}}
{% endif %}
@@ -153,119 +169,125 @@ select
</li>
{% endfor %}
</ul>
+ </div>
</div>
- <br />
- <button id="remove-fixed" name="remove-fixed" class="btn btn-danger pull-right" type="submit"> Remove from paper</button>
+ <br />
+ <button id="remove-fixed" name="remove-fixed" class="btn btn-danger pull-right" type="submit">
+ <i class="fa fa-minus-square"></i>&nbsp;Remove from paper
+ </button>
</div>
+ </div> <!-- /.row -->
+ <br>
+ <div class="pull-right">
+ <a class="btn btn-info" id="fixed-next">Next &gt;</a>
</div>
- </div> <!-- /.row -->
- <br>
- <div class="pull-right">
- <a class="btn btn-info" id="fixed-next">Next &gt;</a>
- </div>
- </div> <!-- /#fixed-questions -->
+ </div> <!-- /#fixed-questions -->
- <div class="tab-pane" id="random-questions">
- <div class="row">
- <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>
+ <div class="tab-pane" id="random-questions">
+ <div class="row">
+ <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 %}
- {% 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>
+ {% if user == question.user %}
+ <a href="{% url 'yaksh:add_question' question.id %}" target="_blank">{{ question.summary }}</a>
+ {% else %}
+ {{question.summary}}
+ {% endif %}</span>
+ <span> {{ question.points }} </span>
+ </label>
+ </li>
{% 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>
- {% if user == question.user %}
- <a href="{{URL_ROOT}}/exam/manage/addquestion/{{ question.id }}" target="_blank">{{ question.summary }}</a>
- {% else %}
- {{question.summary}}
- {% endif %}</span>
- <span> {{ question.points }} </span>
- </label>
- </li>
- {% endfor %}
- </ul>
- {% endif %}
+ </ul>
+ {% endif %}
+ </div>
</div>
- <br /><br />
- <button id="add-random" name="add-random" class="btn btn-primary pull-right" type="submit">Add to paper</button>
+ <br>
+ <button id="add-random" name="add-random" class="btn btn-success pull-right" type="submit">
+ <i class="fa fa-plus-square"></i>&nbsp;Add to paper
+ </button>
</div>
- </div>
- <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>
- {% if user == question.user %}
- <a href="{{URL_ROOT}}/exam/manage/addquestion/{{ question.id }}" target="_blank">{{ question.summary }}</a>
- {% else %}
- {{question.summary}}
- {% endif %}</span>
- <span> {{ question.points }} </span>
- </label>
- </li>
+ <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>
+ {% if user == question.user %}
+ <a href="{% url 'yaksh:add_question' question.id %}" target="_blank">{{ question.summary }}</a>
+ {% else %}
+ {{question.summary}}
+ {% endif %}</span>
+ <span> {{ question.points }} </span>
+ </label>
+ </li>
+ {% endfor %}
{% endfor %}
- {% endfor %}
- </ul>
+ </ul>
+ </div>
</div>
<br />
- <button id="remove-random" name="remove-random" class="btn btn-danger pull-right" type="submit"> Remove from paper</button>
+ <button id="remove-random" name="remove-random" class="btn btn-danger pull-right" type="submit">
+ <i class="fa fa-minus-square"></i>&nbsp;Remove from paper
+ </button>
</div>
- </div>
- </div> <!-- /.row -->
- <br>
- <div class="pull-left">
- <a class="btn btn-info" id="random-prev">&lt; Previous</a>
- </div>
- <div class="pull-right">
- <a class="btn btn-info" id="random-next">Next &gt;</a>
- </div>
- </div> <!-- /#random-questions -->
-
- <div class="tab-pane" id="finish">
- <center>
- <h5><u>Almost finished creating your question paper</u></h5>
- <label style="float: none;">
- {{ qpaper_form.shuffle_questions }}
- <span>Shuffle questions' order for each student</span>
- </label> <br><br>
- <label style="float: none;">
- {{ qpaper_form.shuffle_testcases }}
- <span>Shuffle MCQ/MCC options for each student</span>
- </label> <br><br>
- <input class ="btn btn-success" type="submit" name="save" id="save" value="Save question paper">
+ </div> <!-- /.row -->
<br>
<div class="pull-left">
- <a class="btn btn-info" id="finish-prev">&lt; Previous</a>
+ <a class="btn btn-info" id="random-prev">&lt; Previous</a>
</div>
- </center>
- </div> <!-- /#finish -->
-</div>
+ <div class="pull-right">
+ <a class="btn btn-info" id="random-next">Next &gt;</a>
+ </div>
+ </div> <!-- /#random-questions -->
+
+ <div class="tab-pane" id="finish">
+ <center>
+ <h5><u>Almost finished creating your question paper</u></h5>
+ <label style="float: none;">
+ {{ qpaper_form.shuffle_questions }}
+ <span>Shuffle questions' order for each student</span>
+ </label> <br><br>
+ <label style="float: none;">
+ {{ qpaper_form.shuffle_testcases }}
+ <span>Shuffle MCQ/MCC options for each student</span>
+ </label> <br><br>
+ <input class="btn btn-success btn-lg" type="submit" name="save" id="save" value="Save">
+ <br>
+ <div class="pull-left">
+ <a class="btn btn-info" id="finish-prev">&lt; Previous</a>
+ </div>
+ </center>
+ </div> <!-- /#finish -->
+ </div>
<!-- /.tab-content -->
</form>
<br>
diff --git a/yaksh/templates/yaksh/error_template.html b/yaksh/templates/yaksh/error_template.html
index 5530844..9cfeac1 100644
--- a/yaksh/templates/yaksh/error_template.html
+++ b/yaksh/templates/yaksh/error_template.html
@@ -1,12 +1,17 @@
+{% load static %}
+{% block css%}
+ <link rel="stylesheet" href="{% static 'yaksh/css/dashboard.css' %}" type="text/css" />
+{% endblock %}
+{% block script %}
+ <script src="{% static 'yaksh/js/jquery-ui.js' %}"></script>
+{% endblock %}
{% load custom_filters %}
{% if error_message %}
-<div class="container-fluid row justify-content-center">
{% for error in error_message %}
-<div class="col-md-10 yakshwell">
<div class="card ">
<div class="card-header alert-danger">Error No. {{ forloop.counter }}</div>
- <div class="card-body ">
+ <div class="card-body ">
<div class="">
{% if not error.type %}
<pre><code> {{error|safe}} </code></pre>
@@ -64,8 +69,8 @@
</tr>
{% for expected,user in error.expected_output|zip:error.user_output %}
<td> {{forloop.counter}} </td>
- <td>{{expected|default:""}} </td>
- <td>{{user|default:""}}</td>
+ <td>{{expected|default:""|highlight_spaces|safe}} </td>
+ <td>{{user|default:""|highlight_spaces|safe}}</td>
{% if forloop.counter0 in error.error_line_numbers or not expected or not user %}
<td><span class ="fa fa-times text-warning"/></td>
{% else %}
@@ -85,7 +90,7 @@
</div>
</div>
</div>
+ <br>
</div>
- {% endfor %}
-</div>
+ {% endfor %}
{% endif %} \ No newline at end of file
diff --git a/yaksh/templates/yaksh/grade_user.html b/yaksh/templates/yaksh/grade_user.html
index a76f2c7..e3888b8 100644
--- a/yaksh/templates/yaksh/grade_user.html
+++ b/yaksh/templates/yaksh/grade_user.html
@@ -1,15 +1,15 @@
{% extends "manage.html" %}
{% load custom_filters %}
+{% load static %}
{% block title %} Grade User {% endblock %}
{% block pagetitle %} Grade User {% endblock pagetitle %}
-{% block content %}
-<div class="yakshwell container">
{% block script %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery.tablesorter.min.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/mathjax/MathJax.js?config=TeX-MML-AM_CHTML"></script>
+<script type="text/javascript" src="{% static 'yaksh/js/jquery.tablesorter.min.js' %}">
+</script>
+<script type="text/javascript" src="{% static 'yaksh/js/mathjax/MathJax.js' %}?config=TeX-MML-AM_CHTML"></script>
<script type="text/javascript">
$(document).ready(function()
{
@@ -19,371 +19,486 @@ $(document).ready(function()
</script>
{% endblock script %}
-{% if course_details %}
-<div class="table-wrapper-2">
- <table id="course-details" class="table table-bordered table-responsive-sm">
- <tr class="yakshlabel yakshred text-center">
- <th><i class="fa fa-book"></i> Courses</th>
- <th><i class="fa fa-puzzle-piece"></i> Quizzes </th>
- </tr>
-
- {% for course in course_details %}
- <tr>
- <td><ul class="list-group">{{course.name}} </td>
-
- {% if course.get_quizzes %}
- <td>
- {% for quiz in course.get_quizzes %}
- <li class="list-group-item"><a href = "{{URL_ROOT}}/exam/manage/gradeuser/{{quiz.id}}/{{course.id}}/">
- {{quiz.description}}
- </a></li>
- {% endfor %}
- </td>
- {% else %}
- <td> No quiz</td>
- {% endif %}
- </ul></tr>
- {% endfor %}
- </table>
- </div>
-{% endif %}
-
-<div class="row">
-{% if not course_details %}
-{% if users %}
- <div id = "student" class="col-md-2">
- {% for user in users %}
- <p><a href = "{{URL_ROOT}}/exam/manage/gradeuser/{{quiz_id}}/{{user.user__id}}/{{course_id}}/" class="btn btn-primary">
- {{user.user__first_name}} {{user.user__last_name}}</a></p>
- {% endfor %}
+{% block content %}
+<div class="container">
+{% if objects %}
+ {% include "yaksh/paginator.html" %}
+ <div id="accordion">
+ {% for course in objects %}
+ <div class="card">
+ <div class="card-header">
+ <div class="row">
+ <div class="col-md-9">
+ <h5 data-toggle="tooltip" title="{{course.name}}">
+ {{ course.name }}
+ </h5>
+ </div>
+ <div class="col-md">
+ <a class="card-link btn btn-info" data-toggle="collapse" href="#collapse{{course.id}}">
+ Details
+ <i class="fa fa-toggle-down" id="toggle_course_{{course.id}}"></i>
+ </a>
+ </div>
+ </div>
+ </div>
+ <div id="collapse{{course.id}}" class="collapse hide" data-parent="#accordion">
+ <div class="card-body">
+ {% with course.get_quizzes as quizzes %}
+ {% if quizzes %}
+ <ul class="list-group">
+ {% for quiz in quizzes %}
+ <li class="list-group-item">
+ <div class="row">
+ <div class="col-md-8">
+ {{quiz.description}}
+ </div>
+ <div class="col-md-2">
+ <a href="{% url 'yaksh:grade_user' quiz.id course.id%}" class="btn btn-primary">
+ Grade
+ </a>
+ </div>
+ </div>
+ </li>
+ {% endfor %}
+ </ul>
+ {% else %}
+ <center>
+ <p class="badge badge-danger badge-pill">
+ No Quizzes
+ </p>
+ </center>
+ {% endif %}
+ {% endwith %}
+ </div>
+ </div>
+ </div>
+ <br>
+ {% endfor %}
</div>
-{% else %}
-<center>
- <div class="alert-warning alert animated flash">
-<h4>No Users Found for {{ quiz.description }}</h4>
-</center>
-{% endif %}
-{% endif %}
-
-{% if has_quiz_assignments %}
-
-<a href="{{URL_ROOT}}/exam/manage/download/quiz_assignments/{{quiz_id}}/{{course_id}}" class="btn btn-outline-info">
- Download All Assignments</a>
-{% endif %}
-
-<div id = "paper" class="col-md-10">
-{% if data %}
-
-
-<p> <h3> <center> Showing paper for {{data.user.get_full_name.title}} </center></h3>
-<p><b>Name:</b> {{ data.user.get_full_name.title }}
-{% if data.profile %}
-
-<p><b> Roll number:</b> {{ data.profile.roll_number }}
-<p><b>Position: </b> {{ data.profile.position }}
-<p><b>Department: </b>{{ data.profile.department }}
-<p><b>Institute: </b>{{ data.profile.institute }}
-{% endif %}
-
-{% if data.papers %}
-
-{% for paper in data.papers %}
-<hr>
-{{ paper.total_marks }}
-
-<h4> Course: {{ paper.question_paper.quiz.course.name }}</h4>
-<h4> Quiz: {{ paper.question_paper.quiz.description }} </h4>
-
-<p>
-Attempt Number: <b>{{paper.attempt_number}} </b>
-<select id = "attempt" onchange="window.location.href=this.value">
-<option selected="">Select attempt number</option>
-{%for attempt in attempts %}
-<option value = "{{URL_ROOT}}/exam/manage/gradeuser/{{quiz_id}}/{{user_id}}/{{attempt.attempt_number}}/{{course_id}}/">
-{{attempt.attempt_number}}
-</option>
-{% endfor %}
-</select>
-<br/>Questions correctly answered: {{ paper.get_answered_str }} <br/>
-Total attempts at questions: {{ paper.answers.count }} <br/>
-Marks obtained: {{ paper.marks_obtained }} <br/>
-Start time: {{ paper.start_time }} <br/>
-End time: {{ paper.end_time }} <br/>
-{%if paper.percent%}
-Percentage obtained: {{paper.percent}}% <br/>
-{% endif %}
-{% if paper.passed %}
-Status : <b style="color: green;"> Passed </b><br/>
-{% else %}
-Status : <b style="color: red;"> Failed </b><br/>
+ {% include "yaksh/paginator.html" %}
+{% elif msg == 'grade' and not objects %}
+ <br>
+ <div class="alert alert-info">
+ <center><h3>No courses found to grade</h3></center>
+ </div>
{% endif %}
-</p>
-{% if paper.answers.count %}
-
-<h4> Report </h4><br>
-<table class="tablesorter table table-striped table-bordered table-responsive-sm" id ='marks_table'>
- <thead>
- <tr class="yakshlabel text-center yakshred">
- <th>Question Id</th>
- <th>Questions</th>
- <th>Marks Obtained</th>
- </tr>
- </thead>
- <tbody>
- {% for question, answers in paper.get_question_answers.items %}
- {% with answers|last as answer %}
- <tr>
- <td>{{question.id}}</td>
- <td><a href="#question_{{question.id}}">{{ question.summary }}</a></td>
- <td>{{ answer.answer.marks }}</td>
- </tr>
- {% endwith %}
- {% endfor %}
- </tbody>
-</table>
-
-<div class="table-wrapper-2">
-<h3> Answers </h3><br>
-<form name=frm id="q{{ paper.quiz.id }}_form"
- action="{{URL_ROOT}}/exam/manage/gradeuser/{{quiz_id}}/{{user_id}}/{{paper.attempt_number}}/{{course_id}}/"
- method="post">
-{% csrf_token %}
-
-{% for question, answers in paper.get_question_answers.items %}
-<div class = "yakshlabel">
-<div class="card">
- <div class="card-heading alert-info" id="question_{{question.id}}">
- <strong> Details: {{forloop.counter}}. {{ question.summary }}
- <span class="marks pull-right"> Mark(s): {{ question.points }} </span>
- </strong>
- </div>
- <div class="card-body">
- <h5><u>Question:</u></h5> <strong>{{ question.description|safe }}</strong>
- {% if question.type == "mcq" or question.type == "mcc" %}
- <h5> <u>Choices:</u></h5>
- {% for testcase in question.get_test_cases %}
- {% if testcase.correct %}
- <br/>
- <strong>{{ forloop.counter }}. {{ testcase.options }}</strong>
- <span class="alert alert-success"> Correct </span>
- {% else %}
- <br/><strong>
- {{ forloop.counter }}. {{ testcase.options }}</strong>
- {% endif %}
- {% endfor %}
-
- {% elif question.type == "integer" or question.type == "string" or question.type == "float" %}
- <h5> <u>Correct Answer:</u></h5>
- {% for testcase in question.get_test_cases %}
- <strong>{{ testcase.correct }}</strong>
- {% if testcase.error_margin %}
- <strong>{{ testcase.error_margin }}</strong>
- {% endif %}
- {% endfor %}
- {% elif question.type == "arrange" %}
- <h5> <u>Correct Order:</u></h5>
- <div class="list-group" >
- {% for testcase in question.get_test_cases %}
- <li class="list-group-item"><strong>{{ testcase.options }}</strong></li>
- {% endfor %}
- </div>
-
- {% else %}
- <h5> <u>Test cases: </u></h5>
- {% for testcase in question.get_test_cases %}
- <br/><strong>{{ forloop.counter }}. {{ testcase }}</strong>
- {% endfor %}
- {%endif%}
+</div>
+<div class="container-fluid">
+ <div class="row">
+ {% if status == "grade" %}
+ {% if users %}
+ <div id="student" class="col-md-3">
+ <ul class="nav nav-pills list-group">
+ {% for user in users %}
+ <li class="nav-item">
+ <a href="{% url 'yaksh:grade_user' quiz_id user.user__id course_id %}" class="list-group-item{% if user.user__id == data.user.id %} active {% endif %}">
+ {{user.user__first_name}} {{user.user__last_name}}
+ </a>
+ </li>
+ {% endfor %}
+ </ul>
</div>
- </div>
- <h5>Student answer: </h5>
- {% if question.type == "upload" %}
- {% if has_user_assignments %}
- <a href="{{URL_ROOT}}/exam/manage/download/user_assignment/{{question.id}}/{{data.user.id}}/{{paper.question_paper.quiz.id}}/{{course_id}}">
- <div class="btn btn-outline-info text-center">
- Assignment File for {{ data.user.get_full_name.title }}
+ {% else %}
+ <div class="col-md-1"></div>
+ <div class="col-md-10">
+ <div class="alert alert-warning">
+ <center>
+ <h4>No Users Found for {{ quiz.description }}</h4>
+ </center>
+ </div>
</div>
- </a>
- {% with answers|last as answer%}
- {% if answer.answer.correct %}
- <div class="card ">
- <div class="card-heading alert-success">Correct answer</div></div>
- {% else %}
- <div class="card ">
- <div class="card-heading alert-danger">Incorrect Answer</div></div>
- {% endif %}
- {% endwith %}
- {% else %}
- <center>
- <div class="alert alert-warning animated flash">
- <h5>No Assignment submitted by {{ data.user.get_full_name.title }}</h5>
- </div>
- </center>
+ {% endif %}
{% endif %}
- {% else %}
- {% for ans in answers %}
- {% if ans.answer.correct %}
- <div class="card ">
- <div class="card-heading alert-success">Correct answer:
- {% else %}
- <div class="card ">
- <div class="card-heading-heading alert-danger">Error:
- {% endif %}
- {% with ans.error_list as err %}
- {% for error in err %}
- {% if error.type == 'stdio' %}
- <div class = "card">
- <div class="card-body">
- {% if error.given_input %}
- <table class="table table-bordered table-responsive-sm">
- <col width="30%">
- <tr class = "table-active">
- <td> For given Input value(s):</td>
- <td>{{error.given_input}}</td>
- </tr>
- </table>
- {% endif %}
- <table class="table table-bordered table-responsive-sm" width="100%" id="output" style="table-layout: fixed">
- <col width="10%">
- <col width="40%">
- <col width="40%">
- <col width="10%">
- <tr>
- <th><center>Line No.</center></th>
- <th><center>Expected Output</center></th>
- <th><center>User output</center></th>
- <th><center>Status</center></th>
- </tr>
- {% for expected,user in error.expected_output|zip:error.user_output %}
- <td> {{forloop.counter}} </td>
- <td>{{expected|default:""}} </td>
- <td>{{user|default:""}}</td>
- {% if forloop.counter0 in error.error_line_numbers or not expected or not user %}
- <td><span class ="fa fa-times text-warning"/></td>
- {% else %}
- <td><span class ="fa fa-check text-success"/></td>
- {% endif %}
- </tr>
- {% endfor %}
- </table>
- <table width="100%" class="table table-bordered table-responsive-sm">
- <col width="10">
- <tr>
- <td><b>Error:</b></td>
- <td>{{error.error_msg}}</td>
- </tr>
- </table>
- </div>
- </div>
- {% elif error.type == 'assertion' %}
- {% if error.test_case %}
- <strong> We tried you code with the following test case:</strong><br/></br>
- <pre><code><strong style="color:#d9534f">{{error.test_case}}</strong></code></pre>
- {% endif %}
- <p> <b>The following error took place: </b></p>
- <div class="card">
- <div class="card-body">
- <table class="table table-bordered table-responsive-sm" width="100%" style="table-layout: fixed">
- <col width="30%">
- <tr class = "active">
- <td><b>Exception Name: </b></td>
- <td><span style="color: #d9534f">{{error.exception}}</span></td>
- </tr>
- <tr>
- <td><b>Exception Message: </b></td><td>{{error.message}}</td>
- </tr>
- <tr>
- {% if error.traceback %}
- <td><b>Full Traceback: </b></td>
- <td><pre>{{error.traceback}}</pre></td>
- {% endif %}
- </tr>
- </table>
- </div>
- </div> <!-- Closes card -->
- {% else %}
- <pre><code> {{error}} </code></pre>
- {% endif %}
- {% endfor %}
- {% endwith %}
- </div>
-
- <div class="card-body">
- {% if question.type == "code" %}
- <pre><code>{{ ans.answer.answer.strip }}</code></pre>
- {% elif question.type == "mcc"%}
- <div class="card">
- <div class="card-body">
- {% for testcases in question.get_test_cases %}
- {%if testcases.id|stringformat:"i" in ans.answer.answer.strip %}
- <li>{{ testcases.options.strip }}</li>
- {% endif %}
- {% endfor %}
+ <div id="paper" class="col-md-9">
+ {% if has_quiz_assignments %}
+ <a href="{% url 'yaksh:download_quiz_assignment' quiz_id course_id %}" class="btn btn-outline-info">
+ <i class="fa fa-download"></i>&nbsp;Download All Assignments
+ </a>
+ <br><br>
+ {% endif %}
+
+ {% if messages %}
+ {% for message in messages %}
+ <div class="alert alert-dismissible alert-{{ message.tags }}">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ message }}</strong>
</div>
- </div>
- {% elif question.type == "mcq"%}
- <div class="card">
- <div class="card-body">
- {% for testcases in question.get_test_cases %}
- {%if testcases.id|stringformat:"i" == ans.answer.answer.strip %}
- <li>{{ testcases.options.strip }}</li>
- {% endif %}
{% endfor %}
- </div>
- </div>
+ {% endif %}
- {% elif question.type == "arrange"%}
+ {% if data %}
<div class="card">
+ <div class="card-header">
+ Student Details
+ </div>
<div class="card-body">
- {% get_answer_for_arrange_options ans.answer.answer question as tc_list %}
- {% for testcases in tc_list %}
- <li>{{ testcases.options.strip }}</li>
- {% endfor %}
- </div>
- </div>
-
- {% else %}
- <div class="card">
- <div class="card-body">
- {{ ans.answer.answer.strip }}
+ <p><b>Name:</b> {{ data.user.get_full_name.title }}</p>
+ {% with data.profile as profile %}
+ {% if profile %}
+ <div class="row">
+ <div class="col-md-4">
+ <p><b> Roll number:</b> {{ profile.roll_number }}</p>
+ <p><b>Position: </b> {{ profile.position }}</p>
+ </div>
+ <div class="col-md-7">
+ <p><b>Department: </b>{{ profile.department }}</p>
+ <p><b>Institute: </b>{{ profile.institute }}</p>
+ </div>
+ </div>
+ {% endif %}
+ {% endwith %}
</div>
</div>
- {% endif %}
- </div>
- </div>
- {% endfor %}
- {% endif %}
- {% with answers|last as answer %}
- Marks: <input id="q{{ question.id }}" type="text"
- name="q{{ question.id }}_marks" size="4"
- value="{{ answer.answer.marks }}"><br><br>
- {% endwith %}
- <hr/>
- </div>
-
- {% endfor %} {# for question, answers ... #}
- </div>
-<div class="form-group">
-<h3>Teacher comments: </h3>
-<textarea id="comments_{{paper.question_paper.id}}" class="form-control"
- name="comments_{{ paper.question_paper.id }}">{{ paper.comments }}</textarea>
-</div>
-<br><button class="btn btn-primary" type="submit" name="submit_{{paper.quiz.id}}">Save Marks</button>
-
-</form>
-</div>
-
-{% endif %} {# if paper.answers.count #}
-
-
-{% endfor %} {# for paper in data.papers #}
-
-{% endif %} {# if data.papers #}
-{% else %}
+ <hr>
+ {% if data.papers %}
+ {% with data.papers.0 as paper %}
+ <div class="card">
+ <div class="card-header">
+ Course Details
+ </div>
+ <div class="card-body">
+ <div class="row">
+ <div class="col-md-6">
+ <p><b>Course:</b> {{ paper.course.name }}</p>
+ <p><b>Quiz:</b> {{ paper.question_paper.quiz.description }}</p>
+ </div>
+ <div class="col-md-6">
+ <p><b>Start time:</b> {{ paper.start_time }}</p>
+ <p><b>End time:</b> {{ paper.end_time }}</p>
+ </div>
+ </div>
+ </div>
+ </div>
+ {% endwith %}
+ {% for paper in data.papers %}
+ <hr>
+ <div class="card">
+ <div class="card-header">
+ Scorecard
+ </div>
+ <div class="card-body">
+ <div class="row">
+ <div class="col-md-4">
+ <p><b>Status:</b>
+ {% if paper.passed %}
+ <span class="badge badge-pill badge-success"> Passed </span>
+ {% else %}
+ <span class="badge badge-pill badge-danger"> Failed </span>
+ {% endif %}
+ </p>
+ <p><b>Total Marks:</b> {{ paper.question_paper.total_marks }}</p>
+ <p><b>Marks obtained:</b> {{ paper.marks_obtained }}</p>
+ </div>
+ <div class="col-md-4">
+ {% if paper.percent %}
+ <p><b>Percentage obtained:</b> {{paper.percent}}%</p>
+ {% endif %}
+ <p><b>Total attempts at questions:</b> {{ paper.answers.count }}</p>
+ <p>
+ <b>Attempt Number:</b>&nbsp;
+ <span class="badge badge-pill badge-info">
+ {{paper.attempt_number}}
+ </span>
+ <select id="attempt" onchange="window.location.href=this.value" class="custom-select">
+ <option selected="">Select attempt number</option>
+ {% for attempt in attempts %}
+ <option value="{% url 'yaksh:grade_user' quiz_id user_id attempt.attempt_number course_id %}">
+ {{attempt.attempt_number}}
+ </option>
+ {% endfor %}
+ </select>
+ </p>
+ </div>
+ </div>
+ </div>
+ </div>
+ <hr>
+ {% if paper.answers.count %}
+ <div class="card">
+ <div class="card-header">
+ Submission Details
+ </div>
+ <div class="card-body">
+ <table class="tablesorter table table-striped table-bordered table-responsive-sm" id='marks_table'>
+ <thead>
+ <tr>
+ <th>Questions</th>
+ <th>Type</th>
+ <th>Marks Obtained</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for question, answers in paper.get_question_answers.items %}
+ {% with answers|last as answer %}
+ <tr>
+ <td>
+ <a href="#question_{{question.id}}">
+ {{ question.summary }}
+ </a>
+ </td>
+ <td>{{ question.type }}</td>
+ <td>{{ answer.answer.marks }}</td>
+ </tr>
+ {% endwith %}
+ {% endfor %}
+ </tbody>
+ </table>
+ <form name=frm id="q{{ paper.quiz.id }}_form"
+ action="{% url 'yaksh:grade_user' quiz_id user_id paper.attempt_number course_id %}"
+ method="post">
+ {% csrf_token %}
+ {% for question, answers in paper.get_question_answers.items %}
+ <div class="card" id="question_{{question.id}}">
+ <div class="card-header text-white bg-info">
+ <strong>
+ Details: {{forloop.counter}}. {{ question.summary }}
+ <span class="marks pull-right"> Mark(s): {{ question.points }} </span>
+ </strong>
+ </div>
+ <div class="card-body">
+ <h5>
+ <span class="badge badge-pill badge-primary">Question:</span>
+ </h5>
+ <strong>{{ question.description }}</strong>
+ <br><br>
+ {% if question.type == "mcq" or question.type == "mcc" %}
+ <h5>
+ <span class="badge badge-pill badge-primary">Choices:</span>
+ </h5>
+ {% for testcase in question.get_test_cases %}
+ {% if testcase.correct %}
+ <strong>
+ <span class="badge badge-pill badge-success">
+ {{ forloop.counter }}.
+ </span>
+ {{ testcase.options|safe }}
+ </strong>
+ {% else %}
+ <strong>
+ <span class="badge badge-pill badge-secondary">
+ {{ forloop.counter }}.
+ </span>
+ {{ testcase.options|safe }}
+ </strong>
+ {% endif %}
+ <br>
+ {% endfor %}
+ {% elif question.type == "integer" or question.type == "string" or question.type == "float" %}
+ <h5>
+ <span class="badge badge-pill badge-primary">
+ Correct Answer:
+ </span>
+ </h5>
+ {% for testcase in question.get_test_cases %}
+ <strong>{{ testcase.correct }}</strong>
+ {% if testcase.error_margin %}
+ <strong>{{ testcase.error_margin }}</strong>
+ {% endif %}
+ {% endfor %}
+ {% elif question.type == "arrange" %}
+ <h5>
+ <span class="badge badge-pill badge-primary">
+ Correct Order:</span>
+ </h5>
+ <div class="list-group" >
+ {% for testcase in question.get_test_cases %}
+ <li class="list-group-item">
+ <strong>{{ testcase.options }}</strong>
+ </li>
+ {% endfor %}
+ </div>
+ {% else %}
+ <h5>
+ <span class="badge badge-pill badge-primary">Test cases:
+ </span>
+ </h5>
+ {% for testcase in question.get_test_cases %}
+ <strong>
+ {{ forloop.counter }}. {{ testcase }}
+ </strong>
+ <br>
+ {% endfor %}
+ {% endif %}
+ <br>
+ <h5>
+ <span class="badge badge-pill badge-primary">Student answer(s):
+ </span>
+ </h5>
+ {% if question.type == "upload" %}
+ {% if has_user_assignments %}
+ <a href="{% url 'yaksh:download_user_assignment' question.id data.user.id paper.question_paper.quiz.id course_id %}">
+ <div class="btn btn-outline-info text-center">
+ Assignment File for {{ data.user.get_full_name.title }}
+ </div>
+ </a>
+ {% else %}
+ <center>
+ <div class="alert alert-warning">
+ <h5>
+ Assignment not submitted by {{ data.user.get_full_name.title }}
+ </h5>
+ </div>
+ </center>
+ {% endif %} <!-- End has_user_assignments -->
+ {% else %}
+ {% for ans in answers %}
+ <strong>
+ Attempt Number: {{forloop.counter}}
+ </strong>
+ <div id="accordian">
+ <div class="card">
+ {% if ans.answer.correct %}
+ <div class="card-header">
+ <span class="badge badge-success">
+ Correct answer:
+ </span>
+ <a class="card-link" data-toggle="collapse" href="#submitted_{{ans.answer.id}}">
+ <span class="pull-right">
+ Details&nbsp;<i class="fa fa-toggle-down"></i>
+ </span>
+ </a>
+ </div>
+ {% else %}
+ <div class="card-header">
+ <span class="badge badge-danger">
+ Error:
+ </span>
+ <a class="card-link" data-toggle="collapse" href="#submitted_{{ans.answer.id}}">
+ <span class="pull-right">
+ Details&nbsp;<i class="fa fa-toggle-down"></i>
+ </span>
+ </a>
+ </div>
+ {% endif %}
+ <div class="collapse hide" id="submitted_{{ans.answer.id}}" data-parent="#accordion">
+ <div class="card-body">
+ {% with ans.error_list as err %}
+ {% for error in err %}
+ {% if error.type == 'stdio' %}
+ {% if error.given_input %}
+ <table class="table table-bordered table-responsive-sm">
+ <tr class="table-active">
+ <td> For given Input value(s):</td>
+ <td>{{error.given_input}}</td>
+ </tr>
+ </table>
+ {% endif %}
+ <table id="course-detail" class="table table-bordered table-responsive-sm" width="100%" id="output">
+ <tr>
+ <th><center>Line No.</center></th>
+ <th><center>Expected Output</center></th>
+ <th><center>User output</center></th>
+ <th><center>Status</center></th>
+ </tr>
+ {% for expected,user in error.expected_output|zip:error.user_output %}
+ <td> {{forloop.counter}} </td>
+ <td>{{expected|default:""}} </td>
+ <td>{{user|default:""}}</td>
+ {% if forloop.counter0 in error.error_line_numbers or not expected or not user %}
+ <td><span class ="fa fa-times text-warning"/></td>
+ {% else %}
+ <td><span class ="fa fa-check text-success"/></td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </table>
+ <table width="100%" class="table table-bordered table-responsive-sm">
+ <col width="10">
+ <tr>
+ <td>Error:</td>
+ <td>{{error.error_msg}}</td>
+ </tr>
+ </table>
+ {% elif error.type == 'assertion' %}
+ {% if error.test_case %}
+ <strong>
+ We tried you code with the following test case:
+ </strong><br><br>
+ <pre><code>
+ <strong>{{error.test_case}}</strong>
+ </code></pre>
+ {% endif %}
+ <p><b>The following error took place: </b></p>
+ <table id="course-detail" class="table table-bordered table-responsive-sm" width="100%">
+ <tr class = "active">
+ <td><b>Exception Name: </b></td>
+ <td><span>{{error.exception}}</span></td>
+ </tr>
+ <tr>
+ <td><b>Exception Message: </b></td><td>{{error.message}}</td>
+ </tr>
+ <tr>
+ {% if error.traceback %}
+ <td><b>Full Traceback: </b></td>
+ <td><pre>{{error.traceback}}</pre></td>
+ {% endif %}
+ </tr>
+ </table>
+ {% else %}
+ <pre><code> {{error}} </code></pre>
+ {% endif %}
+ {% endfor %}
+ {% endwith %}
+ {% if question.type == "code" %}
+ {% pygmentise_user_answer question.language ans.answer.answer.strip as user_answer %}
+ <style type="text/css">{{user_answer.1}}</style>
+ <pre><code>{{user_answer.0|safe}}</code></pre>
+ {% elif question.type == "mcc" or question.type == "mcq" %}
+ {% for testcases in question.get_test_cases %}
+ {% if testcases.id|stringformat:"i" in ans.answer.answer.strip %}
+ <li>{{ testcases.options.strip|safe }}</li>
+ {% endif %}
+ {% endfor %}
+ {% elif question.type == "arrange"%}
+ {% get_answer_for_arrange_options ans.answer.answer question as tc_list %}
+ {% for testcases in tc_list %}
+ <li>{{ testcases.options.strip }}</li>
+ {% endfor %}
+ {% else %}
+ {{ ans.answer.answer.strip }}
+ {% endif %}
+ </div>
+ </div>
+ </div>
+ </div>
+ <br>
+ {% endfor %} <!-- End for ans in answers -->
+ </div>
+ </div>
+ {% endif %}
+ <br>
+ <div class="form-group">
+ <div class="col-md-2">
+ <label class="col-form-label" for="q{{ question.id }}">Marks:</label>
+ {% with answers|last as answer %}
+ <input id="q{{ question.id }}" type="text" name="q{{ question.id }}_marks" size="4" class="form-control" value="{{ answer.answer.marks }}"><br><br>
+ {% endwith %}
+ </div>
+ </div>
+ <hr/>
+ {% endfor %} {# for question, answers ... #}
+ <div class="form-group">
+ <h3>Teacher comments: </h3>
+ <textarea id="comments_{{paper.question_paper.id}}" class="form-control"
+ name="comments_{{ paper.question_paper.id }}">{{ paper.comments }}</textarea>
+ <br>
+ <button class="btn btn-success btn-lg" type="submit" name="submit_{{paper.quiz.id}}">
+ <i class="fa fa-save"></i>&nbsp;Save
+ </button>
+ </div>
+ </form>
+ </div>
+ </div>
+ {% endif %} {# if paper.answers.count #}
+ {% endfor %} {# for paper in data.papers #}
+ {% endif %} {# if data.papers #}
+ {% else %}
+ <!-- No Data -->
+ {% endif %} {#if data#}
</div>
-{% endif %} {#if data#}
-
-</div>
+ </div>
</div>
{% endblock%}
diff --git a/yaksh/templates/yaksh/intro.html b/yaksh/templates/yaksh/intro.html
index 567282a..7657a65 100644
--- a/yaksh/templates/yaksh/intro.html
+++ b/yaksh/templates/yaksh/intro.html
@@ -1,61 +1,54 @@
{% extends "base.html" %}
-{% block pagetitle %} OnlineTest Instructions and Rules {% endblock pagetitle %}
+{% block title %} {{questionpaper.quiz.description}} {% endblock %}
+{% block pagetitle %} Quiz Instructions and Rules {% endblock pagetitle %}
{% block content %}
-<div class="container-fluid card col-md-10">
- <center class="yakshwell">
- {% if questionpaper.quiz.is_expired %}
- <div class="alert col-md-8 alert-error animated flash">
+<div class="container">
+ <div class="card">
+ <div class="card-header">
+ {{questionpaper.quiz.description}}
+ </div>
+ <div class="card-body">
+ {% if questionpaper.quiz.is_expired %}
+ <div class="alert alert-error">
This Quiz has expired. You can no longer attempt this Quiz.
- <br/>
</div>
- {% else %}
- <div class="alert alert-success col-md-8 animated flash">
- {% load tz %}
- {% get_current_timezone as TIME_ZONE %}
- You can attempt this Quiz at any time between {{ questionpaper.quiz.start_date_time }} {{ TIME_ZONE }} and {{ questionpaper.quiz.end_date_time }} {{ TIME_ZONE }}
- <br/>
- You are not allowed to attempt the Quiz before or after this duration
- <br/>
+ {% else %}
+ <div class="alert alert-info">
+ You can attempt this Quiz at any time between <b>{{ questionpaper.quiz.start_date_time }}</b> and <b>{{ questionpaper.quiz.end_date_time }}</b>
</div>
- {% endif %}
- </center>
- <div class="yakshwell">
+ {% endif %}
<p> Welcome <strong>{{user.get_full_name|title}}</strong>, to the programming quiz! </p>
{{ questionpaper.quiz.instructions|safe }}
- <div class="row yakshwell">
- <div class="col-md-6">
- <center>
- {% if status != "moderator" %}
- <a href="{{URL_ROOT}}/exam/quizzes/view_module/{{module.id}}/{{course.id}}" class="btn btn-primary" name="home">
- <i class="fa fa-step-backward">
- </i>
- Go Back</a>
- {% else %}
- <a href="{{URL_ROOT}}/exam" class="btn btn-primary" name="home">
- <i class="fa fa-step-backward">
- </i>
- Go Back</a>
- {% endif %}
- </center>
- </div>
- <div class="col-md-6">
- {% if not questionpaper.quiz.is_expired %}
- <form action="{{URL_ROOT}}/exam/start/{{ attempt_num }}/{{module.id}}/{{ questionpaper.id }}/{{course.id}}/" method="post" align="center">
- {% csrf_token %}
- <center><button class="btn btn-success" type="submit" name="start"> Start Exam <i class="fa fa-play"></i></button></center>
- </form>
- {% endif %}
- </div>
+ <div class="row">
+ <div class="col-md-6">
+ <center>
+ {% if status != "moderator" %}
+ <a href="{% url 'yaksh:view_module' module.id course.id %}" class="btn btn-primary btn-lg" name="home">
+ <i class="fa fa-step-backward"></i>
+ Go Back
+ </a>
+ {% else %}
+ <a href="{% url 'yaksh:index' %}" class="btn btn-primary btn-lg" name="home">
+ <i class="fa fa-step-backward"></i>
+ Go Back
+ </a>
+ {% endif %}
+ </center>
+ </div>
+ <div class="col-md-6">
+ {% if not questionpaper.quiz.is_expired %}
+ <form action="{% url 'yaksh:start_quiz' attempt_num module.id questionpaper.id course.id %}" method="post" align="center">
+ {% csrf_token %}
+ <button class="btn btn-success btn-lg" type="submit" name="start">
+ Start <i class="fa fa-play"></i>
+ </button>
+ </form>
+ {% endif %}
+ </div>
</div>
</div>
- </div>
+ </div>
+</div>
{% endblock content %}
-
-{% if user %}
- {% block info %}
- <h5>{{user.get_full_name|title}}({{user.profile.roll_number}}) Logged in as {{user.username}}</h5>
- {% endblock %}
-{% endif %}
-
diff --git a/yaksh/templates/yaksh/lessons.html b/yaksh/templates/yaksh/lessons.html
new file mode 100644
index 0000000..0146a6b
--- /dev/null
+++ b/yaksh/templates/yaksh/lessons.html
@@ -0,0 +1,86 @@
+{% extends "manage.html" %}
+{% load static %}
+{% block title %} My Lessons {% endblock %}
+{% block content %}
+<div class="container">
+ <div class="row">
+ <div class="col-md-8">
+ <ul class="nav nav-pills" id="course_tabs">
+ <li class="nav-item">
+ <a class="nav-link {% if created %}active{% endif %}" href="{% url 'yaksh:courses' %}">
+ My Courses
+ </a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="{% url 'yaksh:add_course' %}">
+ Add New Course
+ </a>
+ </li>
+ <li class="nav-item dropdown hide">
+ <a class="nav-link dropdown-toggle active" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="true">More</a>
+ <div class="dropdown-menu hide" x-placement="bottom-start" style="position: absolute; transform: translate3d(0px, 37px, 0px); top: 0px; left: 0px; will-change: transform;">
+ <a class="dropdown-item" href="{% url 'yaksh:show_all_quizzes' %}">
+ Add/View Quizzes
+ </a>
+ <a class="dropdown-item active" href="{% url 'yaksh:show_all_lessons' %}">
+ Add/View Lessons
+ </a>
+ <a class="dropdown-item" href="{% url 'yaksh:show_all_modules' %}">
+ Add/View Modules
+ </a>
+ <a href="{% url 'grades:grading_systems'%}" class="dropdown-item" >
+ Add/View Grading Systems
+ </a>
+ </div>
+ </li>
+ </ul>
+ </div>
+ </div>
+</div>
+<div class="container">
+ <hr>
+ <a href="{% url 'yaksh:edit_lesson' %}" class="btn btn-primary btn-lg">
+ <i class="fa fa-plus-circle"></i>&nbsp;Add new Lesson
+ </a>
+ {% if not lessons %}
+ <br><br>
+ <div class="alert alert-info">
+ <center><h3> No new Lessons added</h3></center>
+ </div>
+ {% else %}
+ <center><h3> Lessons </h3></center>
+ <table id="course-details" class="table table-bordered table-responsive-sm">
+ <tr>
+ <th>Sr.No</th>
+ <th>Lesson</th>
+ </tr>
+
+ {% for lesson in lessons %}
+ <tr>
+ <td width="2%">{{forloop.counter}}</td>
+ <td width="30%">
+ <div class="row">
+ <div class="col-md-8">
+ <a href="{% url 'yaksh:edit_lesson' lesson.id %}">
+ {{ lesson.name }}
+ </a>
+ </div>
+ <div class="col-md-4">
+ {% if lesson.active %}
+ <span class="badge badge-success badge-pill">
+ Active
+ </span>
+ {% else %}
+ <span class="badge badge-danger badge-pill">
+ Closed
+ </span>
+ {% endif %}
+ </div>
+ </div>
+ </td>
+ {% endfor %} <!-- end for lessons -->
+ </tr>
+ </table>
+ {% endif %}
+</div>
+{% endblock %} \ No newline at end of file
diff --git a/yaksh/templates/yaksh/login.html b/yaksh/templates/yaksh/login.html
index e2adca7..63a2ef2 100644
--- a/yaksh/templates/yaksh/login.html
+++ b/yaksh/templates/yaksh/login.html
@@ -52,9 +52,11 @@
</table>
</center>
<div class="row justify-content-center">
- <button class="btn btn-lg btn-success btn-block" type="submit" id="login-btn">Login</button>
+ <button class="btn btn-lg btn-success btn-block" type="submit" id="login-btn">
+ <i class="fa fa-sign-in"></i>&nbsp;Login
+ </button>
<a href="{% url 'yaksh:register' %}" class="btn btn-lg btn-primary btn-block" id="signup-btn">
- NEW USER? SIGN UP
+ <i class="fa fa-user-plus"></i>&nbsp;NEW USER? SIGN UP
</a>
<a class="btn btn-lg btn-primary btn-block" href="{% url 'password_reset' %}" id="forgot-btn">
Forgot Password?
diff --git a/yaksh/templates/yaksh/moderator_dashboard.html b/yaksh/templates/yaksh/moderator_dashboard.html
index db37983..b2d38b0 100644
--- a/yaksh/templates/yaksh/moderator_dashboard.html
+++ b/yaksh/templates/yaksh/moderator_dashboard.html
@@ -19,22 +19,22 @@
<a href="{% url 'yaksh:create_demo_course' %}" class="btn btn-primary btn-lg">
Create Demo Course
</a>
- <br>
- {% if msg %}
- <div class="container">
- <div class="alert alert-dismissible alert-info">
+ <br><br>
+ {% if messages %}
+ {% for message in messages %}
+ <div class="alert alert-dismissible alert-{{ message.tags }}">
<button type="button" class="close" data-dismiss="alert">
<i class="fa fa-close"></i>
</button>
- <strong>{{ msg }}</strong>
+ <strong>{{ message }}</strong>
</div>
- </div>
+ {% endfor %}
{% endif %}
</center>
{% with objects as courses %}
<br>
{% if not courses %}
- <div class="alert alert-secondary">
+ <div class="alert alert-info">
No Courses found. Add a new course or Create demo course
</div>
{% else %}
@@ -62,12 +62,13 @@
{% endif %}
</div>
<div class="col-md-3">
- <a href="{% url 'yaksh:course_detail' course.id %}" class="btn btn-primary btn-lg">
+ <a href="{% url 'yaksh:course_detail' course.id %}" class="btn btn-primary">
+ <i class="fa fa-tasks"></i>
Manage Course
</a>
</div>
<div class="col-md">
- <a class="card-link btn btn-info btn-lg" data-toggle="collapse" href="#collapse{{course.id}}">
+ <a class="card-link btn btn-info" data-toggle="collapse" href="#collapse{{course.id}}">
Details
<i class="fa fa-toggle-down" id="toggle_course_{{course.id}}"></i>
</a>
diff --git a/yaksh/templates/yaksh/modules.html b/yaksh/templates/yaksh/modules.html
new file mode 100644
index 0000000..4fafbf1
--- /dev/null
+++ b/yaksh/templates/yaksh/modules.html
@@ -0,0 +1,114 @@
+{% extends "manage.html" %}
+{% load static %}
+
+{% block title %} My Modules {% endblock %}
+{% block content %}
+<div class="container">
+ <div class="row">
+ <div class="col-md-8">
+ <ul class="nav nav-pills" id="course_tabs">
+ <li class="nav-item">
+ <a class="nav-link {% if created %}active{% endif %}" href="{% url 'yaksh:courses' %}">
+ My Courses
+ </a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="{% url 'yaksh:add_course' %}">
+ Add New Course
+ </a>
+ </li>
+ <li class="nav-item dropdown hide">
+ <a class="nav-link dropdown-toggle active" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="true">More</a>
+ <div class="dropdown-menu hide" x-placement="bottom-start" style="position: absolute; transform: translate3d(0px, 37px, 0px); top: 0px; left: 0px; will-change: transform;">
+ <a class="dropdown-item" href="{% url 'yaksh:show_all_quizzes' %}">
+ Add/View Quizzes
+ </a>
+ <a class="dropdown-item" href="{% url 'yaksh:show_all_lessons' %}">
+ Add/View Lessons
+ </a>
+ <a class="dropdown-item active" href="{% url 'yaksh:show_all_modules' %}">
+ Add/View Modules
+ </a>
+ <a href="{% url 'grades:grading_systems'%}" class="dropdown-item" >
+ Add/View Grading Systems
+ </a>
+ </div>
+ </li>
+ </ul>
+ </div>
+ </div>
+</div>
+<div class="container">
+ <hr>
+ <a href="{% url 'yaksh:add_module' %}" class="btn btn-primary btn-lg">
+ <i class="fa fa-plus-circle"></i>&nbsp;Add new Module
+ </a>
+ {% if not modules %}
+ <br><br>
+ <div class="alert alert-info">
+ <center><h3> No new learning modules added</h3></center>
+ </div>
+ {% else %}
+ <center><h3> Learning Modules </h3></center>
+ <table class="table table-bordered table-responsive-sm">
+ <tr>
+ <th>Sr.No</th>
+ <th>Learning Modules</th>
+ <th>Design Module</th>
+ <th>Lessons/Quizzes</th>
+ </tr>
+ {% for module in modules %}
+ <tr>
+ <td width="2%">{{forloop.counter}}</td>
+ <td width="30%">
+ <div class="row">
+ <div class="col-md-7">
+ <a href="{% url 'yaksh:edit_module' module.id %}">
+ {{ module.name }}
+ </a>
+ </div>
+ <div class="col-md-4">
+ {% if module.active %}
+ <span class="badge badge-success badge-pill">
+ Active
+ </span>
+ {% else %}
+ <span class="badge badge-danger badge-pill">
+ Closed
+ </span>
+ {% endif %}
+ </div>
+ </div>
+ </td>
+ <td width="40%">
+ <a href="{% url 'yaksh:design_module' module.id %}">
+ Add Quizzes/Lessons for {{module.name}}
+ </a>
+ </td>
+ <td width="30%">
+ {% with module.get_learning_units as units %}
+ {% if units %}
+ <ul class="list-group">
+ {% for unit in units %}
+ <li class="list-group-item">
+ {% if unit.type == 'quiz' %}
+ {{unit.quiz.description}}
+ {% else %}
+ {{unit.lesson.name}}
+ {% endif %}
+ </li>
+ {% endfor %} <!-- end for learning units -->
+ </ul>
+ {% else %}
+ <span class="badge badge-danger badge-pill">
+ No Learning units
+ </span>
+ {% endif %}
+ {% endwith %}
+ </td>
+ {% endfor %} <!-- end for modules -->
+ </tr>
+ </table>
+ {% endif %}
+</div>
+{% endblock %} \ No newline at end of file
diff --git a/yaksh/templates/yaksh/monitor.html b/yaksh/templates/yaksh/monitor.html
index a9f8328..cf6888c 100644
--- a/yaksh/templates/yaksh/monitor.html
+++ b/yaksh/templates/yaksh/monitor.html
@@ -1,14 +1,15 @@
{% extends "manage.html" %}
{% load custom_filters %}
+{% load static %}
{% block title %} Monitor {% endblock %}
-{% block pagetitle %} {{ msg }} {% endblock pagetitle %}
+{% block pagetitle %} Monitor {% endblock pagetitle %}
{% block meta %} <meta http-equiv="refresh" content="30"/> {% endblock meta %}
-
{% block script %}
{% if papers %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery.tablesorter.min.js"></script>
+<script type="text/javascript" src="{% static 'yaksh/js/jquery.tablesorter.min.js' %}">
+</script>
<script type="text/javascript">
$(document).ready(function()
{
@@ -29,166 +30,210 @@ $(document).ready(function()
{% block content %}
<div class="container">
- <div class="yakshwell">
- {# ############################################################### #}
- {# This is rendered when we are just viewing exam/monitor #}
-
- {% if course_details %}
- <div class="table-wrapper-2">
- <table id="course-details" class="table table-bordered table-responsive-sm">
- <tr class="table-info">
- <th>Courses</th>
- <th> Quizzes </th>
- </tr>
-
- {% for course in course_details %}
- <tr>
- <td><ul class="list-group">{{course.name}} </td>
-
- {% if course.get_quizzes %}
- <td>
- {% for quiz in course.get_quizzes %}
- <li class="list-group-item"><a href = "{{URL_ROOT}}/exam/manage/monitor/{{quiz.id}}/{{course.id}}/">
- {{quiz.description}}
- </a></li>
- {% endfor %}
- </td>
- {% else %}
- <td> No quiz</td>
- {% endif %}
- </ul></tr>
- {% endfor %}
- </table>
- </div>
- {% endif %}
+ {# ############################################################### #}
+ {# This is rendered when we are just viewing exam/monitor #}
+ {% if objects %}
+ {% include "yaksh/paginator.html" %}
+ <div id="accordion">
+ {% for course in objects %}
+ <div class="card">
+ <div class="card-header">
+ <div class="row">
+ <div class="col-md-9">
+ <h5 data-toggle="tooltip" title="{{course.name}}">
+ {{ course.name }}
+ </h5>
+ </div>
+ <div class="col-md">
+ <a class="card-link btn btn-info" data-toggle="collapse" href="#collapse{{course.id}}">
+ Details
+ <i class="fa fa-toggle-down" id="toggle_course_{{course.id}}"></i>
+ </a>
+ </div>
+ </div>
+ </div>
+ <div id="collapse{{course.id}}" class="collapse hide" data-parent="#accordion">
+ <div class="card-body">
+ {% with course.get_quizzes as quizzes %}
+ {% if quizzes %}
+ <ul class="list-group">
+ {% for quiz in quizzes %}
+ <li class="list-group-item">
+ <div class="row">
+ <div class="col-md-8">
+ {{quiz.description}}
+ </div>
+ <div class="col-md-2">
+ <a href="{% url 'yaksh:monitor' quiz.id course.id%}" class="btn btn-primary">
+ Monitor
+ </a>
+ </div>
+ </div>
+ </li>
+ {% endfor %}
+ </ul>
+ {% else %}
+ <center>
+ <p class="badge badge-danger badge-pill">
+ No Quizzes
+ </p>
+ </center>
+ {% endif %}
+ {% endwith %}
+ </div>
+ </div>
+ </div>
+ <br>
+ {% endfor %}
+ </div>
+ {% include "yaksh/paginator.html" %}
- {# ############################################################### #}
- {# This is rendered when we are just viewing exam/monitor/quiz_num #}
- {% if msg != "Monitor" %}
- {% if quiz %}
+ {% elif msg == 'Monitor' and not objects %}
+ <br>
+ <div class="alert alert-info">
+ <center><h3>No courses to monitor</h3></center>
+ </div>
+ {% endif %}
+ {# ############################################################### #}
+ {# This is rendered when we are just viewing exam/monitor/quiz_num #}
+ {% if msg != "Monitor" %}
+ {% if quiz %}
{% if papers %}
- <div class="row">
- <div class="card col-md-10">
- <div class = "table-responsive"">
- <table class = "table">
- <tr>
- <td><b>Course Name:&nbsp</b></td>
- <td>{{course.name}}</td>
- </tr>
- <tr>
- <td><b>Quiz Name:&nbsp</b></td>
- <td>{{quiz.description}}</td>
- </tr>
- <tr>
- <td><b>Number of papers: &nbsp</b></td>
- <td>{{papers|length}}</td>
- </tr>
- <tr>
- <td><b>Papers Completed: &nbsp</b></td>
- <td>
- {% completed papers as completed_papers %}
- <b class = "yakshgreen">{{completed_papers}}</b>
- </td>
- </tr>
- <tr>
- <td><b>Papers in progress: &nbsp</b></td>
- <td>
- {% inprogress papers as inprogress_papers %}
- <b class="yakshred"> {{ inprogress_papers }} </b>
- </td>
- </tr>
- </table>
+ <div class="card">
+ <div class="table-responsive">
+ <table id="course-detail" class="table">
+ <tr>
+ <td><b>Course Name:&nbsp</b></td>
+ <td>{{course.name}}</td>
+ </tr>
+ <tr>
+ <td><b>Quiz Name:&nbsp</b></td>
+ <td>{{quiz.description}}</td>
+ </tr>
+ <tr>
+ <td><b>Number of papers: &nbsp</b></td>
+ <td>{{papers|length}}</td>
+ </tr>
+ <tr>
+ <td><b>Papers Completed: &nbsp</b></td>
+ <td>
+ {% completed papers as completed_papers %}
+ <b>{{completed_papers}}</b>
+ </td>
+ </tr>
+ <tr>
+ <td><b>Papers in progress: &nbsp</b></td>
+ <td>
+ {% inprogress papers as inprogress_papers %}
+ <b>{{ inprogress_papers }}</b>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ <br>
+ <div class="row">
+ <div class="col-md-4">
+ <a href="{% url 'yaksh:show_statistics' papers.0.question_paper.id course.id %}" class="btn btn-primary">
+ <i class="fa fa-line-chart"></i>&nbsp;Question Statistics
+ </a>
</div>
- </div>
- <div class = "row">
- <div class="col-md-2">
- <p><a href="{{URL_ROOT}}/exam/manage/statistics/question/{{papers.0.question_paper.id}}/{{course.id}}" class="btn btn-primary">Question Statisitics</a></p>
- <p>
- <button type="button" class="btn btn-info" data-toggle="modal" data-target="#csvModal">
- Download CSV <span class="fa fa-download"></span>
- </button>
- </p>
+ <div class="col-md-4">
+ <button type="button" class="btn btn-info" data-toggle="modal" data-target="#csvModal">
+ <i class="fa fa-download"></i>&nbsp;Download CSV
+ </button>
</div>
- </div>
- <div class="table-wrapper-2">
- <table id="result-table" class="tablesorter table table-striped table-responsive-sm">
- <thead>
- <tr class="table-info">
- <th> Name </th>
- <th> Username </th>
- <th> Roll number </th>
- <th> Institute </th>
- <th> Questions answered </th>
- <th> Marks obtained </th>
- <th> Attempts </th>
- <th> Time Remaining </th>
- <th> Status </th>
- </tr>
- </thead>
- <tbody>
- {% for paper in latest_attempts %}
- <tr>
- <td> <a href="{{URL_ROOT}}/exam/manage/user_data/{{paper.user.id}}/{{paper.question_paper.id}}/{{course.id}}"><i class="fa fa-circle fa-sm"></i> {{ paper.user.get_full_name.title }}</a> </td>
- <td> {{ paper.user.username }} </td>
- <td> {{ paper.user.profile.roll_number }} </td>
- <td> {{ paper.user.profile.institute }} </td>
- <td> {{ paper.get_answered_str }} </td>
- <td> {{ paper.marks_obtained }} </td>
- <td> {{ paper.answers.count }} </td>
- <td id="time_left{{forloop.counter0}}"> {{ paper.time_left }} </td>
- <td>{{ paper.status }}</td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- </div>
- {% else %}
- <p> No answer papers found for {{ quiz.description }}</p>
- {% endif %} {# if papers #}
- {% else %}
- <h4>No Quiz Found</h4>
- {% endif %}
- {% endif %}
- </div>
- <!-- CSV Modal -->
- <div class="modal fade" id="csvModal" role="dialog">
- <div class="modal-dialog">
+ </div>
+ <br>
+ <table id="result-table" class="tablesorter table table-striped table-responsive-sm">
+ <thead>
+ <tr>
+ <th> Name&nbsp;<i class="fa fa-sort"></i> </th>
+ <th> Username&nbsp;<i class="fa fa-sort"></i> </th>
+ <th> Roll No&nbsp;<i class="fa fa-sort"></i> </th>
+ <th> Institute&nbsp;<i class="fa fa-sort"></i> </th>
+ <th> Marks&nbsp;<i class="fa fa-sort"></i> </th>
+ <th> Attempts&nbsp;<i class="fa fa-sort"></i> </th>
+ <th> Time&nbsp;<i class="fa fa-sort"></i> </th>
+ <th> Status&nbsp;<i class="fa fa-sort"></i> </th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for paper in latest_attempts %}
+ <tr>
+ <td> <a href="{% url 'yaksh:user_data' paper.user.id paper.question_paper.id course.id %}">
+ {{ paper.user.get_full_name.title }}</a> </td>
+ <td> {{ paper.user.username }} </td>
+ <td> {{ paper.user.profile.roll_number }} </td>
+ <td> {{ paper.user.profile.institute }} </td>
+ <td> {{ paper.marks_obtained }} </td>
+ <td> {{ paper.answers.count }} </td>
+ <td id="time_left{{forloop.counter0}}"> {{ paper.time_left }} </td>
+ <td>{{ paper.status }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ <!-- CSV Modal -->
+ <div class="modal fade" id="csvModal" role="dialog">
+ <div class="modal-dialog">
- <!-- Modal content-->
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal">&times;</button>
- <h3 class="modal-title">Uncheck unwanted columns</h3>
- </div>
- <form action="{{URL_ROOT}}/exam/manage/download_quiz_csv/{{ course.id }}/{{ quiz.id }}/" method="post">
- {% csrf_token %}
- <div class="modal-body">
- {% for field in csv_fields %}
- <div class="form-check form-check-inline">
- <label class="form-check-label">
- <input class="form-check-input" name="csv_fields" type="checkbox" value="{{ field }}" checked> {{ field }}
- </label>
- </div>
- {% endfor %}
- <b>Select Attempt Number: Default latest attempt</b>
- <select class="form-control" name = "attempt_number">
- {%for attempt_number in attempt_numbers %}
- {% if forloop.last %}
- <option value="{{ attempt_number }}" selected>{{ attempt_number }} (Latest)</option>
- {% else %}
- <option value = "{{ attempt_number }}"> {{ attempt_number }}</option>
- {% endif %}
- {% endfor %}
- </select>
- </div>
- <div class="modal-footer">
- <button type="submit" class="btn btn-primary"> Download <span class="glyphicon glyphicon-save"></span></button>
- <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ <!-- Modal content-->
+ <div class="modal-content">
+ <div class="modal-header">
+ <h3 class="modal-title">Download CSV for {{quiz.description}} </h3>
+ <button type="button" class="close" data-dismiss="modal">
+ <i class="fa fa-close"></i>
+ </button>
+ </div>
+ <form action="{% url 'yaksh:download_quiz_csv' course.id quiz.id %}" method="post">
+ {% csrf_token %}
+ <div class="modal-body">
+ <b>Uncheck unwanted columns</b>
+ <br>
+ {% for field in csv_fields %}
+ <div class="form-check form-check-inline">
+ <label class="form-check-label">
+ <input class="form-check-input" name="csv_fields" type="checkbox" value="{{ field }}" checked> {{ field }}
+ </label>
+ </div>
+ <br>
+ {% endfor %}
+ <b>Select Attempt Number: Default latest attempt</b>
+ <select class="form-control" name = "attempt_number">
+ {%for attempt_number in attempt_numbers %}
+ {% if forloop.last %}
+ <option value="{{ attempt_number }}" selected>{{ attempt_number }} (Latest)</option>
+ {% else %}
+ <option value = "{{ attempt_number }}"> {{ attempt_number }}</option>
+ {% endif %}
+ {% endfor %}
+ </select>
+ </div>
+ <div class="modal-footer">
+ <button type="submit" class="btn btn-success">
+ <span class="fa fa-save"></span>&nbsp;Download
+ </button>
+ <button type="button" class="btn btn-secondary" data-dismiss="modal">
+ Close
+ </button>
+ </div>
+ </form>
+ </div>
+ </div>
+ </div>
+ {% else %}
+ <div class="col-md-12">
+ <div class="alert alert-warning">
+ <center>
+ <h4>No Users Found for {{ quiz.description }}</h4>
+ </center>
</div>
- </form>
- </div>
- </div>
- </div>
- </div>
+ </div>
+ {% endif %} {# if papers #}
+ {% else %}
+ <h4>No Quiz Found</h4>
+ {% endif %}
+ {% endif %}
</div>
{% endblock %}
diff --git a/yaksh/templates/yaksh/preview_questionpaper.html b/yaksh/templates/yaksh/preview_questionpaper.html
index d6391e1..72355ea 100644
--- a/yaksh/templates/yaksh/preview_questionpaper.html
+++ b/yaksh/templates/yaksh/preview_questionpaper.html
@@ -1,24 +1,33 @@
{% extends "base.html" %}
+{% block title %} Preview Question paper {% endblock title %}
{% block pagetitle %} Quiz: {{ paper.quiz.description }} {% endblock pagetitle %}
{% block content %}
-<div class="yakshwell container">
+<div class="container">
<div class="card">
- <div class="col-md-12 card-body">
- <div class="col-md-6">Maximum Mark(s): {{ paper.total_marks }}</div>
- <div class="col-md-6"><span class="pull-right">Total Time: {{ paper.quiz.duration }} minutes</span></div>
- </div>
+ <div class="card-body">
+ <div class="row">
+ <div class="col-md-6">Maximum Mark(s): {{ paper.total_marks }}</div>
+ <div class="col-md-6">
+ <span class="pull-right">
+ Total Time: {{ paper.quiz.duration }} minutes
+ </span>
+ </div>
+ </div>
+ </div>
</div>
+<br>
<div class="card">
- <div class="card-heading">Instructions</div>
- <div class="card-body" id="instructions">
- {{ paper.quiz.instructions|safe }}
- </div>
+ <div class="card-header">Instructions</div>
+ <div class="card-body" id="instructions">
+ {{ paper.quiz.instructions|safe }}
+ </div>
</div>
+<br>
{% for question in questions %}
<div class="card">
- <div class="card-heading yakshlabel">
+ <div class="card-header">
<strong> {{forloop.counter}}. {{ question.summary }}
<span class="marks pull-right"> Mark(s): {{ question.points }} </span>
</strong>
@@ -39,6 +48,7 @@
</div>
</div>
+ <br>
{% endfor %}
</div>
{% endblock %}
diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html
index f13de1a..74343f8 100644
--- a/yaksh/templates/yaksh/question.html
+++ b/yaksh/templates/yaksh/question.html
@@ -1,11 +1,12 @@
{% extends "exam.html" %}
{% load custom_filters %}
-
+{% load static %}
{% block css %}
-<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/question.css" type="text/css" />
-<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/codemirror/lib/codemirror.css" type="text/css" />
-<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/exam.css" type="text/css" />
+
+<link rel="stylesheet" href="{% static 'yaksh/css/question.css' %}" type="text/css" />
+<link rel="stylesheet" href="{% static 'yaksh/css/codemirror/lib/codemirror.css' %}" type="text/css" />
+<link rel="stylesheet" href="{% static 'yaksh/css/exam.css' %}" type="text/css" />
<style>
.CodeMirror{
border-style: groove;
@@ -18,13 +19,15 @@
{% endblock %}
{% block script %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/requesthandler.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/codemirror/lib/codemirror.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/codemirror/mode/python/python.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/codemirror/mode/clike/clike.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/codemirror/mode/shell/shell.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/mathjax/MathJax.js?config=TeX-MML-AM_CHTML"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery-sortable.js"></script>
+
+
+<script src="{% static 'yaksh/js/requesthandler.js' %}"></script>
+<script src="{% static 'yaksh/js/codemirror/lib/codemirror.js' %}"></script>
+<script src="{% static 'yaksh/js/codemirror/mode/python/python.js' %}"></script>
+<script src="{% static 'yaksh/js/codemirror/mode/clike/clike.js' %}"></script>
+<script src="{% static 'yaksh/js/codemirror/mode/shell/shell.js' %}"></script>
+<script type="text/javascript" src="{% static 'yaksh/js/mathjax/MathJax.js' %}?config=TeX-MML-AM_CHTML"></script>
+<script src="{% static 'yaksh/js/jquery-sortable.js' %}"></script>
<script>
init_val = '{{ last_attempt|escape_quotes|safe }}';
lang = "{{ question.language }}"
@@ -34,9 +37,9 @@ is_exercise = "{{ quiz.is_exercise }}"
can_skip = "{{ can_skip }}"
delay_time = new Number("{{ delay_time }}")
-var time_left = {{ paper.time_left }}
+var time_left = "{{ paper.time_left }}"
{% if quiz.is_exercise %}
- time_left = {{ delay_time }}
+ time_left = "{{ delay_time }}"
{% endif %}
function getTimeRemaining(endtime){
@@ -115,252 +118,275 @@ question_type = "{{ question.type }}"
{% block main %}
- <form id="code" action="{{URL_ROOT}}/exam/{{ question.id }}/check/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/" method="post" enctype="multipart/form-data">
- {% csrf_token %}
- <input type=hidden name="question_id" id="question_id" value={{ question.id }}></input>
- <div class="yakshwell">
- <div class="card ">
- <div class="col-md-12 bg-light">
- <div class="row align-items-center ">
- <div class="col-md-6 yakshheading"> {{ question.summary }} </div>
- <div class="col-md-3 ml-auto yakshwell text-center">
- {% if question.type == "mcq" %}
- SINGLE CORRECT CHOICE
- {% elif question.type == "mcc" %}
- MULTIPLE CORRECT CHOICES
- {% elif question.type == "code" %}
- PROGRAMMING
- {% elif question.type == "upload" %}
- ASSIGNMENT UPLOAD
- {% elif question.type == "integer" %}
- FILL IN THE BLANKS WITH INTEGER ANSWER
- {% elif question.type == "string" %}
- FILL IN THE BLANKS WITH STRING ANSWER
- {% if testcase.string_check == "lower" %}
- <br>(CASE INSENSITIVE)
- {% else %}
- <br>(CASE SENSITIVE)
- {% endif %}
- {% elif question.type == "float" %}
- FILL IN THE BLANKS WITH FLOAT ANSWER
- {% elif question.type == "arrange" %}
- ARRANGE THE OPTIONS IN CORRECT ORDER
- {% endif %}
- </div>
- <div class="col-md-2 ml-auto text-center">
- <div class="row">
- <div class="col-md-6">
- <h5>
- <span class="badge badge-warning">
- {{ question.points }} Marks
- </span>
- </h5>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="yakshwell">
- <font size=3 face=arial> {{ question.description|safe }} </font>
- {% if files %}
- <div class="yakshwell col-md-5">
- <div class="card yakshwell">
- <span> Files to download for this question </span> <hr>
- {% for f_name in files %}
- <div class="yakshwell">
- <a href="{{f_name.file.url}}" class="btn btn-outline-secondary btn-sm " target="_blank">{{f_name.get_filename}}</a>
- <br>
- </div>
- {% endfor %}
- </div>
- </div>
- {% endif %}
- </div>
- </div>
- <br/>
- <center>
- {% if notification %}
- {% if question.type == "code" %}
- <div id="notification" class="alert alert-success col-md-8 animated flash" role="alert">
- <strong>Note:</strong> {{ notification }}
+ <div>
+ <center>
+ {% if notification %}
+ {% if question.type == "code" %}
+ <div id="notification" class="alert alert-info col-md-8" role="alert">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>Note:</strong> {{ notification }}
+ </div>
+ {% else %}
+ <div id="notification" class="alert alert-info col-md-8" role="alert">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>Note:</strong> {{ notification }}
+ </div>
+ {% endif %}
+ {% else %}
+ <div id="notification" role="alert">
+ </div>
+ {% endif %}
+ </center>
+ </div>
+ <form id="code" action="{% url 'yaksh:check' question.id paper.attempt_number module.id paper.question_paper.id course.id %}" method="post" enctype="multipart/form-data">
+ {% csrf_token %}
+ <input type=hidden name="question_id" id="question_id" value="{{ question.id }}"></input>
+ <div class="card">
+ <div class="card-header">
+ <div class="row">
+ <div class="col-md-6">
+ {{ question.summary }}
</div>
- {% else %}
- <div id="notification" class="alert alert-warning col-md-8 animated flash" role="alert">
- <strong>Note:</strong> {{ notification }}
+ <div class="col-md-4">
+ {% if question.type == "mcq" %}
+ SINGLE CORRECT CHOICE
+ {% elif question.type == "mcc" %}
+ MULTIPLE CORRECT CHOICES
+ {% elif question.type == "code" %}
+ PROGRAMMING
+ {% elif question.type == "upload" %}
+ ASSIGNMENT UPLOAD
+ {% elif question.type == "integer" %}
+ FILL IN THE BLANKS WITH INTEGER ANSWER
+ {% elif question.type == "string" %}
+ FILL IN THE BLANKS WITH STRING ANSWER
+ {% if testcase.string_check == "lower" %}
+ <br>(CASE INSENSITIVE)
+ {% else %}
+ <br>(CASE SENSITIVE)
+ {% endif %}
+ {% elif question.type == "float" %}
+ FILL IN THE BLANKS WITH FLOAT ANSWER
+ {% elif question.type == "arrange" %}
+ ARRANGE THE OPTIONS IN CORRECT ORDER
+ {% endif %}
</div>
- {% endif %}
- {% else %}
- <div id="notification" role="alert">
+ <div class="col-md-2">
+ <span class="badge badge-info">
+ {{ question.points }} Marks
+ </span>
+ </div>
+ </div>
+ </div>
+ <div class="card-body">
+ <div>
+ {{ question.description|safe }}
+ </div>
+ {% if files %}
+ <div class="col-md-5">
+ <div class="card">
+ <div class="card-header">
+ <span> Files to download for this question </span>
+ </div>
+ <div class="card-body">
+ {% for f_name in files %}
+ <a href="{{f_name.file.url}}" class="list-group-item" target="_blank">{{f_name.get_filename}}
+ </a>
+ {% endfor %}
+ </div>
+ </div>
</div>
{% endif %}
- </center>
- {% if quiz.is_exercise %}
- {% if can_skip %}
- <div class = "card col-md-8" id="solution">
- {% else %}
- <div id="solution" style="display:none">
- {% endif %}
- {% if question.solution %}
- <h4><u> Solution by teacher</u></h4>
- {% endif%}
- <font size=3 face=arial> {{ question.solution|safe }} </font>
- </div>
- {% endif %}
- <div class="card">
- <div class="yakshwell">
- {% if question.type == "mcq" %}
- {% for test_case in test_cases %}
- {% if last_attempt and last_attempt|safe == test_case.id|safe %}
- <input name="answer" type="radio" value="{{ test_case.id }}" checked />
- {{ test_case.options|safe }} <br/>
- {% else %}
- <input name="answer" type="radio" value="{{ test_case.id }}" />
- {{ test_case.options|safe }} <br/>
- {% endif %}
- {% endfor %}
- {% endif %}
- {% if question.type == "integer" %}
- Enter Integer:<br/>
- <input autofocus name="answer" type="number" id="integer" value="{{ last_attempt|safe }}" />
- <br/><br/>
- {% endif %}
+ {% if quiz.is_exercise %}
+ <div>
+ {% if can_skip %}
+ <div id="solution">
+ {% else %}
+ <div id="solution" style="display:none">
+ {% endif %}
+ {% if question.solution %}
+ <br>
+ <h4><u> Solution by teacher</u></h4>
+ {% endif %}
+ <font size=3 face=arial> {{ question.solution|safe }} </font>
+ </div>
+ </div>
+ {% endif %}
+ <br>
+ <div>
+ <!-- MCQ type question -->
+ {% if question.type == "mcq" %}
+ {% for test_case in test_cases %}
+ {% if last_attempt and last_attempt|safe == test_case.id|safe %}
+ <input name="answer" type="radio" value="{{ test_case.id }}" checked />
+ {{ test_case.options|safe }} <br/>
+ {% else %}
+ <input name="answer" type="radio" value="{{ test_case.id }}" />
+ {{ test_case.options|safe }} <br/>
+ {% endif %}
+ {% endfor %}
+ {% endif %}
- {% if question.type == "string" %}
- Enter Text:<br/>
- <textarea autofocus name="answer" id="string">{{ last_attempt|safe }}</textarea>
- <br/><br/>
- {% endif %}
+ <!-- Integer type question -->
+ {% if question.type == "integer" %}
+ Enter Integer:<br/>
+ <input autofocus class="form-control" name="answer" type="number" id="integer" value="{{ last_attempt|safe }}" />
+ <br><br>
+ {% endif %}
- {% if question.type == "float" %}
- Enter Decimal Value :<br/>
- <input autofocus name="answer" type="number" step="any" id="float" value="{{ last_attempt|safe }}" />
- <br/><br/>
- {% endif %}
+ <!-- String type question -->
+ {% if question.type == "string" %}
+ Enter Text:<br/>
+ <textarea autofocus name="answer" id="string" class="form-control" style="width: 100%">{{ last_attempt|safe }}</textarea>
+ <br/><br/>
+ {% endif %}
- {% if question.type == "mcc" %}
- {% for test_case in test_cases %}
- {% if last_attempt and test_case.id|safe in last_attempt|safe %}
- <input name="answer" type="checkbox" value="{{ test_case.id }}" checked/> {{ test_case.options| safe }}
- <br>
- {% else %}
- <input name="answer" type="checkbox" value="{{ test_case.id }}">
- {{ test_case.options| safe }}
- <br/>
- {% endif %}
- {% endfor %}
- {% endif %}
- {% if question.type == "upload" %}
- <p>Upload assignment file for the said question<p>
- <input type=file id="assignment" name="assignment" multiple="">
- {% endif %}
+ <!-- Float type question -->
+ {% if question.type == "float" %}
+ Enter Decimal Value :<br/>
+ <input autofocus class="form-control" name="answer" type="number" step="any" id="float" value="{{ last_attempt|safe }}" />
+ <br/><br/>
+ {% endif %}
- {% if question.type == "arrange" %}
- {% if last_attempt %}
- {% get_answer_for_arrange_options last_attempt question as test_cases %}
- {% endif %}
- <input name="answer" type="hidden" id='arrange_order'/>
- <div class="list-group">
- <ol class="arrange ">
- {% for test_case in test_cases %}
- <li class="list-group-item yakshlight" id={{test_case.id}}>{{test_case.options| safe }}</li> {% endfor %}
- </ol>
- </div>
- <script type="text/javascript">
- var arrange = $("ol.arrange");
- var order_array = $(arrange).sortable(['serialize']);
- </script>
- {% endif %}
+ <!-- MCC type question -->
+ {% if question.type == "mcc" %}
+ {% for test_case in test_cases %}
+ {% if last_attempt and test_case.id|safe in last_attempt|safe %}
+ <input name="answer" type="checkbox" value="{{ test_case.id }}" checked/>
+ {{ test_case.options| safe }}
+ <br>
+ {% else %}
+ <input name="answer" type="checkbox" value="{{ test_case.id }}">
+ {{ test_case.options| safe }}
+ <br>
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+ <!-- Upload type question -->
+ {% if question.type == "upload" %}
+ <p>Upload assignment file for the said question<p>
+ <input type=file id="assignment" name="assignment" multiple="">
+ {% endif %}
- {% if question.type == "code" %}
- <div class="row align-items-center">
- <div class="col-md-9">
- <h5>Write your program below:</h5>
- </div>
- <div class="col-md-3 ml-auto">
- <a href="#answer" class=" btn btn-outline-primary" onclick="confirm()" name="reset" id="reset">Undo Changes&nbsp;<span class="glyphicon glyphicon-refresh"></span></a>
- </div>
- </div>
- <div class="yakshwell">
- <textarea autofocus name="answer" id="answer"></textarea>
- </div>
- {% endif %}
- </div>
- </div>
- <div class="text-center yakshwell">
+ <!-- Arrange type question -->
+ {% if question.type == "arrange" %}
+ {% if last_attempt %}
+ {% get_answer_for_arrange_options last_attempt question as test_cases %}
+ {% endif %}
+ <input name="answer" type="hidden" id='arrange_order'/>
+ <div class="list-group">
+ <ol class="arrange">
+ {% for test_case in test_cases %}
+ <li class="list-group-item yakshlight" id={{test_case.id}}>
+ {{test_case.options| safe }}</li> {% endfor %}
+ </ol>
+ </div>
+ <script type="text/javascript">
+ var arrange = $("ol.arrange");
+ var order_array = $(arrange).sortable(['serialize']);
+ </script>
+ {% endif %}
- {% if question.type == "mcq" or question.type == "mcc" or question.type == "integer" or question.type == "float" or question.type == "string" %}
- <br><button class="btn btn-success" type="submit" name="check" id="check">Submit Answer</button>&nbsp;&nbsp;
- {% elif question.type == "upload" %}
- <br><button class="btn btn-success" type="submit" name="check" id="check" onClick="return validate();">Upload</button>&nbsp;&nbsp;
- {% elif question.type == "arrange" %}
- <br><button class="btn btn-success" type="submit" name="check" id="check" onClick="return user_arranged_options();">Submit Answer</button>&nbsp;&nbsp;
+ <!-- Code type question -->
+ {% if question.type == "code" %}
+ <div class="row align-items-center">
+ <div class="col-md-9">
+ <h4>Write your program below:</h4>
+ </div>
+ <div class="col-md-3 ml-auto">
+ <a href="#answer" class=" btn btn-outline-primary" onclick="confirm()" name="reset" id="reset">Undo Changes&nbsp;<span class="fa fa-refresh"></span></a>
+ </div>
+ </div>
+ <br>
+ <div>
+ <textarea autofocus name="answer" id="answer"></textarea>
+ </div>
+ {% endif %}
+ <!-- Submit Buttons -->
+ <br>
+ <div>
+ {% if question.type == "mcq" or question.type == "mcc" or question.type == "integer" or question.type == "float" or question.type == "string" %}
+ <br><button class="btn btn-success" type="submit" name="check" id="check">Submit Answer</button>
+ {% elif question.type == "upload" %}
+ <br><button class="btn btn-success" type="submit" name="check" id="check" onClick="return validate();">Upload</button>
+ {% elif question.type == "arrange" %}
+ <br><button class="btn btn-success" type="submit" name="check" id="check" onClick="return user_arranged_options();">Submit Answer</button>
+ {% else %}
+ {% if question in paper.get_questions_unanswered or quiz.is_exercise %}
+ <button class="btn btn-success" type="submit" name="check" id="check" >
+ Check Answer
+ </button>
+ {% endif %}
+ {% endif %}
+ {% if quiz.is_exercise %}
+ {% if can_skip %}
+ <button id="skip_ex" class="btn btn-primary" onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')" name="skip"> Next <span class="fa fa-step-forward"></span></button>
+ {% else %}
+ <button id="skip_ex" class="btn btn-primary" onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')" name="skip" style="visibility:hidden"> Next <span class="fa fa-step-forward"></span>
+ </button>
+ {% endif %}
+ {% endif %}
- {% else %}
- {% if question in paper.get_questions_unanswered or quiz.is_exercise %}
- <button class="btn btn-success" type="submit" name="check" id="check" >Check Answer <span class="glyphicon glyphicon-cog"></span></button>&nbsp;&nbsp;
- {% endif %}
- {% endif %}
- {% if quiz.is_exercise %}
- {% if can_skip %}
- <button id="skip_ex" class="btn btn-primary" onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')" name="skip"> Next <span class="glyphicon glyphicon-arrow-right"></span></button>
- {% else %}
- <button id="skip_ex" class="btn btn-primary" onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')" name="skip" style="visibility:hidden"> Next <span class="fa fa-step-forward"></span></button>
- {% endif %}
- {% endif %}
+ {% if paper.question_paper.quiz.allow_skip and not paper.get_questions_unanswered|length_is:"1" %}
+ {% if question in paper.get_questions_unanswered %}
+ <button class="btn btn-primary" onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')" name="skip" id="skip">
+ Attempt Later <span class="fa fa-step-forward"></span>
+ </button>
+ {% endif %}
+ {% endif %}
+ </div>
+ </div>
+ </div>
+ </div>
+ </form>
- {% if paper.question_paper.quiz.allow_skip and not paper.get_questions_unanswered|length_is:"1" %}
- {% if question in paper.get_questions_unanswered %}
- <button class="btn btn-primary" onclick="call_skip('{{ URL_ROOT }}/exam/{{ question.id }}/skip/{{ paper.attempt_number }}/{{ module.id }}/{{ paper.question_paper.id }}/{{course.id}}/')" name="skip" id="skip">Attempt Later <span class="fa fa-step-forward"></span></button>
- {% endif %}
- {% endif %}
- </div>
- </form>
-
- </div>
- </div>
- <br/>
- <p id="status"></p>
+ <!-- Errors for code questions -->
+ <p id="status"></p>
{% if question.type == 'code' or question.type == 'upload' %}
- <div class="row" id="error_panel"></div>
+ <div id="error_panel"></div>
{% endif %}
- <!-- Modal -->
- <div class="modal" id="upload_alert" >
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <h4 class="modal-title" id="myModalLabel">File not selected</h4>
- </div>
- <div id = "modal_body"class="modal-body">
- <font color="brown"><b>Kindly attach a file and then click upload.</b></font>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
- </div>
+ <!-- Modal -->
+ <div class="modal" id="upload_alert" >
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h4 class="modal-title" id="myModalLabel">File not selected</h4>
+ </div>
+ <div id = "modal_body"class="modal-body">
+ <font color="brown"><b>Kindly attach a file and then click upload.</b></font>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
</div>
</div>
- </div>
+ </div>
+ </div>
- <!-- UNDO CHANGES Modal -->
- <div class="modal" id="undo_changes" >
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <h4 class="modal-title" id="myModalLabel">Are you Sure?</h4>
- </div>
- <div id = "modal_body"class="modal-body">
- <font color="brown"><b>Your code will be reset.</b></font>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-warning" onclick="reset_editor()">OK</button>
- <button type="button" class="btn btn-primary" data-dismiss="modal">Cancel</button>
- </div>
+ <!-- UNDO CHANGES Modal -->
+ <div class="modal" id="undo_changes" >
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h4 class="modal-title" id="myModalLabel">Are you Sure?</h4>
+ </div>
+ <div id = "modal_body"class="modal-body">
+ <font color="brown"><b>Your code will be reset.</b></font>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-warning" onclick="reset_editor()">OK</button>
+ <button type="button" class="btn btn-primary" data-dismiss="modal">Cancel</button>
</div>
</div>
- </div>
+ </div>
+ </div>
{% endblock main %}
diff --git a/yaksh/templates/yaksh/quit.html b/yaksh/templates/yaksh/quit.html
index dd06ff9..ccb0893 100644
--- a/yaksh/templates/yaksh/quit.html
+++ b/yaksh/templates/yaksh/quit.html
@@ -1,13 +1,15 @@
{% extends "base.html" %}
+{% load static %}
+
+{% block title %} Quit Quiz {% endblock %}
{% block nav %}
<div class="container-fluid yakshnav">
<nav class="navbar fixed-top navbar-expand-lg yakshheading yakshnav">
<div class="container">
- <a class="navbar-brand">
- <img src="{{ URL_ROOT }}/static/yaksh/images/yaksh_banner.png" alt="YAKSH">
- </img>
- </a>
+ <a class="navbar-brand" href="{% url 'yaksh:index' %}">
+ <img src="{% static 'yaksh/images/yaksh_banner.png' %}" alt="YAKSH">
+ </a>
</div><!-- /.container -->
</nav><!-- /.navbar -->
</div>
@@ -15,11 +17,11 @@
{% block content %}
<center>
-<div class="col-md-8 yakshwell">
+<div class="col-md-8">
<h3>Submission Status</h3>
<table class="table table-bordered table-responsive-sm" >
<thead>
- <tr class="yakshred text-center">
+ <tr class="text-center">
<th> Question</th>
<th> Status </th>
</tr>
@@ -32,7 +34,7 @@
<td> {{ question.summary }} </td>
<td> Attempted </td>
{% else %}
- <tr class="table-danger">
+ <tr class="table-warning">
<td> {{ question }} </td>
<td> Not completed </td>
{% endif %}
@@ -50,11 +52,11 @@
<center><h4> Are you sure you wish to quit the exam?</h4></center>
<center><h4> Be sure, as you won't be able to restart this exam.</h4></center>
{% endif %}
- <form action="{{URL_ROOT}}/exam/complete/{{ paper.attempt_number }}/{{module_id}}/{{ paper.question_paper.id }}/{{course_id}}/" method="post">
+ <form action="{% url 'yaksh:complete' paper.attempt_number module_id paper.question_paper.id course_id %}" method="post">
{% csrf_token %}
<center>
- <button class="btn btn-outline-success" type="submit" name="yes">Yes!</button>&nbsp;
- <button class="btn btn-outline-danger" type="button" name="no" onClick="window.location='{{ URL_ROOT }}/exam/start/{{ paper.attempt_number }}/{{module_id}}/{{ paper.question_paper.id }}/{{course_id}}'">No!</button>
+ <button class="btn btn-outline-success btn-lg" type="submit" name="yes">Yes</button>
+ <a class="btn btn-outline-danger btn-lg" name="no" href="{% url 'yaksh:start_quiz' paper.attempt_number module_id paper.question_paper.id course_id %}">No</a>
</center>
</form>
{% endblock content %}
diff --git a/yaksh/templates/yaksh/quizzes.html b/yaksh/templates/yaksh/quizzes.html
new file mode 100644
index 0000000..7e53d31
--- /dev/null
+++ b/yaksh/templates/yaksh/quizzes.html
@@ -0,0 +1,122 @@
+{% extends "manage.html" %}
+{% load static %}
+
+{% block title %} My Quizzes {% endblock %}
+{% block content %}
+<div class="container">
+ <div class="row">
+ <div class="col-md-8">
+ <ul class="nav nav-pills" id="course_tabs">
+ <li class="nav-item">
+ <a class="nav-link {% if created %}active{% endif %}" href="{% url 'yaksh:courses' %}">
+ My Courses
+ </a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="{% url 'yaksh:add_course' %}">
+ Add New Course
+ </a>
+ </li>
+ <li class="nav-item dropdown hide">
+ <a class="nav-link dropdown-toggle active" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="true">More</a>
+ <div class="dropdown-menu hide" x-placement="bottom-start" style="position: absolute; transform: translate3d(0px, 37px, 0px); top: 0px; left: 0px; will-change: transform;">
+ <a class="dropdown-item active" href="{% url 'yaksh:show_all_quizzes' %}">
+ Add/View Quizzes
+ </a>
+ <a class="dropdown-item" href="{% url 'yaksh:show_all_lessons' %}">
+ Add/View Lessons
+ </a>
+ <a class="dropdown-item" href="{% url 'yaksh:show_all_modules' %}">
+ Add/View Modules
+ </a>
+ <a href="{% url 'grades:grading_systems'%}" class="dropdown-item" >
+ Add/View Grading Systems
+ </a>
+ </div>
+ </li>
+ </ul>
+ </div>
+ </div>
+</div>
+<div class="container">
+ <hr>
+ <a href="{% url 'yaksh:add_quiz' %}" class="btn btn-primary btn-lg">
+ <i class="fa fa-plus-circle"></i>&nbsp;Add New Quiz
+ </a>
+ <a href="{% url 'yaksh:add_exercise' %}" class="btn btn-info btn-lg">
+ <i class="fa fa-plus-circle"></i>&nbsp;Add New Exercise
+ </a>
+ {% if not quizzes %}
+ <br><br>
+ <div class="alert alert-info">
+ <center><h3> No new Quiz added</h3></center>
+ </div>
+ {% else %}
+ <center><h3> Quizzes </h3></center>
+ <table class="table table-bordered table-responsive-sm">
+ <tr>
+ <th>Sr.No</th>
+ <th>Quiz/Exercise</th>
+ <th>QuestionPaper</th>
+ </tr>
+ {% for quiz in quizzes %}
+ <tr>
+ <td>{{forloop.counter}}</td>
+ <td width="30%">
+ <div class="row">
+ <div class="col-md-7">
+ {% if quiz.is_exercise %}
+ <a href="{% url 'yaksh:edit_exercise' quiz.id %}">
+ {{ quiz.description }}
+ </a>
+ {% else %}
+ <a href="{% url 'yaksh:edit_quiz' quiz.id %}">
+ {{ quiz.description }}
+ </a>
+ {% endif %}
+ </div>
+ <div class="col-md-5">
+ {% if quiz.active %}
+ <span class="badge badge-success badge-pill">
+ Active
+ </span>
+ {% else %}
+ <span class="badge badge-danger badge-pill">
+ Closed
+ </span>
+ {% endif %}
+ </div>
+ </div>
+ </td>
+ <td>
+ {% if quiz.questionpaper_set.get %}
+ <div class="row">
+ <div class="col-md-7">
+ <a href="{% url 'yaksh:designquestionpaper' quiz.id quiz.questionpaper_set.get.id %}">
+ Question Paper for {{ quiz.description }}</a>
+ </div>
+ <div class="col-md-5">
+ <a href="{% url 'yaksh:preview_questionpaper' quiz.questionpaper_set.get.id %}" class="btn btn-primary active btn-xs" target="_blank">
+ <i class="fa fa-eye"></i>&nbsp;Preview
+ </a>
+ </div>
+ </div>
+ {% else %}
+ <div class="row">
+ <div class="col-md-7">
+ <p>No Question Paper</p>
+ </div>
+ <div class="col-md-5">
+ <a href="{% url 'yaksh:designquestionpaper' quiz.id %}" class="btn btn-success">
+ <i class="fa fa-plus-circle"></i>&nbsp;Add
+ </a>
+ </div>
+ </div>
+ {% endif %}
+ </td>
+ {% endfor %} <!-- end for quizzes -->
+ </tr>
+ </table>
+ {% endif %}
+</div>
+{% endblock %} \ No newline at end of file
diff --git a/yaksh/templates/yaksh/quizzes_user.html b/yaksh/templates/yaksh/quizzes_user.html
index eb3705e..7771954 100644
--- a/yaksh/templates/yaksh/quizzes_user.html
+++ b/yaksh/templates/yaksh/quizzes_user.html
@@ -7,186 +7,161 @@
{% block main %}
<div class="container">
- {% if msg %}
- <center><div class="col-md-8 alert alert-warning animated flash" role="alert">
- {{ msg }}
- </div></center>
- {% endif %}
-
- {% block navtab %}
- {% if 'Enrolled Courses' not in title%}
- <div class="container">
- <div class="nav nav-tabs yakshnavtab">
- <li class="nav-item" >
- <a class="active nav-link bg-light" href="{{ URL_ROOT }}/exam/quizzes/" id="yakshactive">ALL COURSES</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="{{ URL_ROOT }}/exam/quizzes/enrolled/">ENROLLED COURSES</a>
- </li>
- </div>
- </div>
- <div class="row justify-content-center yakshwell">
- <div class="col-md-6">
- <div class="yakshwell">
- <form action="{{ URL_ROOT }}/exam/quizzes/" method="post" id="custom-search-form" >
- {% csrf_token %}
- <div class="col-md-12">
- <div class="input-group">
- <div class="input-group-prepend">
- <span class="input-group-text" id="basic-addon1">Search Course</span>
- </div>
- <input type="text" name="course_code" class="form-control" type="search" placeholder="Enter Course-Code">
- <span class="input-group-append">
- <button class="btn btn-outline-secondary" type="submit"><i class="fa fa-search yakshred"></i></button>
- <button class="btn btn-outline-secondary" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/quizzes/");'>Go Back</button>
- </span>
- </div>
- </div>
- </form>
- </div>
- </div>
- </div>
- {% else %}
- <div class="container">
- <div class="nav nav-tabs yakshnavtab">
- <li class="nav-item" >
- <a class="nav-link" href="{{ URL_ROOT }}/exam/quizzes/">ALL COURSES</a>
- </li>
- <li class="nav-item">
- <a class="active nav-link bg-light" href="{{ URL_ROOT }}/exam/quizzes/enrolled/" id="yakshactive">ENROLLED COURSES</a>
- </li>
+ <center>
+ <h2>All Courses</h2>
+ </center>
+ <hr>
+ <div class="row justify-content-center">
+ <div class="col-md-8">
+ <form action="{% url 'yaksh:quizlist_user' %}" method="post" id="custom-search-form" >
+ {% csrf_token %}
+ <div class="col-md-12">
+ <div class="input-group">
+ <input type="text" name="course_code" class="form-control" type="search" placeholder="Enter course code to search" required="">
+ <span class="input-group-append">
+ <button class="btn btn-outline-info" type="submit"><i class="fa fa-search"></i>&nbsp;Search</button>
+ </span>
+ </div>
</div>
- </div>
+ </form>
+ </div>
+ {% if title == "Search" %}
+ <div class="col-md-4">
+ <a href="{% url 'yaksh:quizlist_user' %}" class="btn btn-primary">
+ <i class="fa fa-times"></i>&nbsp;Clear search
+ </a>
+ </div>
{% endif %}
- {% endblock %}
+ </div>
+ <br>
+ {% if messages %}
+ {% for message in messages %}
+ <div class="alert alert-dismissible alert-{{ message.tags }}">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ message }}</strong>
+ </div>
+ <br>
+ {% endfor %}
+ {% endif %}
{% if not courses %}
- <center><div class="col-md-8 alert alert-warning animated flash" role="alert">
+ <center><div class="col-md-8 alert alert-warning" role="alert">
No Courses to display
</div></center>
{% endif %}
-
<div class="row justify-content-md-center align-items-center" >
- <div class="col col-sm-10 yakshwell">
- {% for course in courses %}
- <div class="yakshwell">
- <div class="row yakshlabel align-items-center">
- <div class="col">
- <a data-toggle="collapse" href="#collapsedetails{{course.data.id}}" role="button" aria-expanded="false" aria-controls="#collapsedetails{{course.data.id}}">
- <h4><b>
- {{ course.data.name }} by {{ course.data.creator.get_full_name }}
- </b></h4>
- </a>
- {% if course.data.is_active_enrollment %}
- <div class="text-left">
- <span class="yakshgreen">{{course.data.start_enroll_time}}</span>&nbsp;&nbsp; to &nbsp;&nbsp;<span class="yakshgreen">{{course.data.end_enroll_time}}</span>
- </div>
- {% endif %}
- </div>
- <div class="col-sm-auto">
- {% if course.data.days_before_start != 0 %}
- <span class="label label-info" style="font-size: 15px">
- {{course.data.days_before_start}} day(s) to start
- </span>
- {% endif %}
-
- </div>
- <div class="container-fluid">
- <a class="btn btn-primary" data-toggle="collapse" href="#collapsedetails{{course.data.id}}" role="button" aria-expanded="false" aria-controls="#collapsedetails{{course.data.id}}">DETAILS</a>
- {% if user in course.data.requests.all %} <span class="badge badge-warning">Request Pending </span>
- {% elif user in course.data.rejected.all %}<span class="badge badge-danger">Request Rejected</span>
- {% elif user in course.data.students.all %}
- {% if course.data.has_lessons %}
- <a href="{% url 'yaksh:download_course' course.data.id %}" data-toggle="tooltip" title="Download course content" class="btn btn-primary">
- Download Course
- </a>
- {% endif %}
- <a class="btn btn-success" href="{{URL_ROOT}}/exam/course_modules/{{course.data.id}}" >
- {% if course.completion_percentage > 0 %}
- CONTINUE
- {% else %}
- START
- {% endif %}
- </a>
- {% else %}
- {% if course.data.active %}
- {% if course.data.is_active_enrollment %}
- {% if course.data.is_self_enroll %}
- <a class="btn btn-success" href="{{ URL_ROOT }}/exam/self_enroll/{{ course.data.id }}">ENROLL</a>
+ <div class="col-md-12">
+ <div id="accordian">
+ {% for course in courses %}
+ <div class="card">
+ <div class="card-header">
+ <div class="row">
+ <div class="col-md-7">{{course.data.name}}</div>
+ <div class="col-md-2">
+ <a class="card-link btn btn-info" data-toggle="collapse" href="#collapse{{course.data.id}}">
+ Details&nbsp;<i class="fa fa-toggle-down" id="toggle_course_{{course.id}}"></i>
+ </a>
+ </div>
+ <div class="col-md-2">
+ {% if user in course.data.requests.all %}
+ <span class="badge badge-warning badge-pill">
+ Request Pending
+ </span>
+ {% elif user in course.data.rejected.all %}
+ <span class="badge badge-danger badge-pill">
+ Request Rejected
+ </span>
+ {% elif user in course.data.students.all %}
+ {% if course.completion_percentage > 0 %}
+ <a class="btn btn-primary" href="{% url 'yaksh:course_modules' course.data.id %}" >
+ Continue
+ </a>
+ {% else %}
+ <a class="btn btn-success" href="{% url 'yaksh:course_modules' course.data.id %}">
+ Start
+ </a>
+ {% endif %}
{% else %}
- <a class="btn btn-success" href="{{ URL_ROOT }}/exam/enroll_request/{{ course.data.id }}">ENROLL</a>
+ {% if course.data.active %}
+ {% if course.data.is_active_enrollment %}
+ {% if course.data.is_self_enroll %}
+ <a class="btn btn-primary" href="{% url 'yaksh:self_enroll' course.data.id %}">Enroll</a>
+ {% else %}
+ <a class="btn btn-primary" href="{% url 'yaksh:enroll_request' course.data.id %}">Enroll</a>
+ {% endif %}
+ {% else %}
+ <span class="badge badge-danger badge-pill">
+ Enrollment Closed
+ </span>
+ {% endif %}
+ {% else %}
+ <span class="badge badge-danger">
+ Inactive Course
+ </span>
+ {% endif %}
{% endif %}
- {% else %}
- <span class="btn btn-danger disabled" style="font-size: 15px">
- Enrollment Closed
- </span>
- {% endif %}
- {% else %}
- <span class="badge badge-danger" style="font-size: 15px">
- Inactive Course
- </span>
- {% endif %}
- {% endif %}
- </div>
- <!-- About course-->
- <div class="collapse container-fluid" id="collapsedetails{{course.data.id}}">
- <div class="card card-body ">
- <h4>{{ course.data.name }} by {{ course.data.creator.get_full_name }}</h4><hr>
- <div class="row">
- <div class="col-md-7">
- {% if course.data.description %}
- <p> <span class="yakshred yakshheading">About the course</span><br>
- {{ course.data.description }}
- </p>
- {% endif %}
- {% if course.data.get_learning_modules %}
- <p> <span class="yakshred yakshheading">What you'll learn</span>
- <ul>
- {% for module in course.data.get_learning_modules %}
- <li>{{module.name|title}}</li>
- {% endfor %}
- </ul>
- </p>
- {% endif %}
- <p> <span class="yakshred yakshheading">Instructor</span><br>
- {{ course.data.creator.get_full_name }}
- </p>
- {% if course.data.instructions %}
- <p> <span class="yakshred yakshheading">Instructions</span><br>
- {{ course.data.instructions|safe }}
- </p>
- {% endif %}
- </div>
- <div class="col-md-4">
- <div class="row my-3">
- <div class="col-md-5">
- STARTS ON
- </div>
- <div class="col-md-7">
- {{course.data.start_enroll_time}}
</div>
</div>
- <div class="row my-3">
- <div class="col-md-5">
- ENDS ON
- </div>
- <div class="col-md-7">
- {{course.data.end_enroll_time}}
+ </div>
+ <div id="collapse{{course.data.id}}" class="collapse hide" data-parent="#accordion">
+ <div class="card-body">
+ <div class="row">
+ <div class="col-md-8">
+ <p><b>Instructor:</b> {{course.data.creator.get_full_name|title}}</p>
+ {% with course.data.get_learning_modules as modules %}
+ {% if modules %}
+ <p> <span class="badge badge-pill badge-primary">
+ Course Content</span>
+ <ul>
+ {% for module in modules %}
+ <li>{{module.name|title}}</li>
+ {% endfor %}
+ </ul>
+ </p>
+ {% endif %}
+ {% endwith %}
+ {% if course.data.instructions %}
+ <p> <span class="badge badge-pill badge-primary">
+ Instructions</span><br>
+ {{ course.data.instructions|safe }}
+ </p>
+ {% endif %}
+ </div>
+ <div class="col-md-4">
+ <p><b>Starts On:</b> {{course.data.start_enroll_time}}</p>
+ <p><b>Ends On:</b> {{course.data.end_enroll_time}}</p>
+ {% with course.completion_percentage as percent %}
+ <p><b>Course Progress:</b></p>
+ <div class="progress">
+ {% if percent %}
+ {% if percent <= 50 %}
+ <div class="progress-bar bg-danger" role="progressbar" aria-valuenow="{{percent}}"
+ aria-valuemin="0" aria-valuemax="100" style="width:{{percent}}%">
+ {% elif percent <= 75 %}
+ <div class="progress-bar bg-warning" role="progressbar" aria-valuenow="{{percent}}"
+ aria-valuemin="0" aria-valuemax="100" style="width:{{percent}}%">
+ {% else %}
+ <div class="progress-bar bg-success" role="progressbar" aria-valuenow="{{percent}}"
+ aria-valuemin="0" aria-valuemax="100" style="width:{{percent}}%">
+ {% endif %}
+ <b style="color: white;">{{percent}}% completed</b>
+ </div>
+ {% else %}
+ <b style="color: black;">0% completed</b>
+ {% endif %}
+ </div>
+ {% endwith %}
+ </div>
</div>
</div>
- <div class="row my-3">
- <div class="progress-bar bg-success" role="progressbar" style="width:{{course.completion_percentage}}%"; color: black;" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100">{{course.completion_percentage}} % completed
- </div>
- </div>
</div>
</div>
- </div>
- </div>
- <!-- End of About course-->
+ <br>
+ {% endfor %}
</div>
</div>
- {% endfor %}
- </div>
</div>
</div>
diff --git a/yaksh/templates/yaksh/show_video.html b/yaksh/templates/yaksh/show_video.html
index 9d24b44..a2edbe0 100644
--- a/yaksh/templates/yaksh/show_video.html
+++ b/yaksh/templates/yaksh/show_video.html
@@ -2,168 +2,162 @@
{% load custom_filters %}
{% block title %} {{ learning_module.name }} {% endblock %}
-
-
{% block main %}
-
-<div class="row">
-
- <!-- Side bar -->
- <div class="col-md-3 yakshlabel collapse" id="sidebar">
- <center><h4><a class="text-dark" href="{{ URL_ROOT }}/exam/course_modules/{{course.id}}"><i class="fa fa-caret-left"></i> {{course.name}}</h4></center>
- {% for module in all_modules %}
- <div class="list-group">
-
- <a href="{{URL_ROOT}}/exam/quizzes/view_module/{{module.id}}/{{course.id}}" id="menu1" class="list-group-item bg-light" data-parent="#sidebar">
- {% if module.id == learning_module.id %}
- <i class="fa fa-toggle-on yakshred" data-toggle="tooltip" title="Currently on">
- </i>
- {% else %}
- <i class="fa fa-toggle-off" data-toggle="tooltip" title="Currently off"></i>
- {% endif %}
- {{module}}
+<div class="wrapper">
+ <!-- Sidebar -->
+ <nav id="sidebar">
+ <div class="sidebar-header">
+ <a class="text-light" href="{% url 'yaksh:course_modules' course.id %}">
+ {{course.name}}
</a>
- {% for unit in module.get_learning_units %}
- {% get_unit_status course module unit user as status %}
- <span id="menudrop">
- {% if unit.type == "quiz" %}
- <a href="{{ URL_ROOT }}/exam/start/{{unit.quiz.questionpaper_set.get.id}}/{{module.id}}/{{course.id}}" class="list-group-item" data-parent="#menu1">
- {% if status == "completed" %}
- <i class="fa fa-check-square yakshgreen"></i>
- {% else %}
- <i class="fa fa-square-o"></i>
- {% endif %}
- {{ unit.quiz.description }}
- {% if unit.id == current_unit.id %}
- <i class="fa fa-thumb-tack yakshred" data-toggle="tooltip" title="Currently on">
- </i>
- {% endif %}
- </a>
+ </div>
+ {% for module in all_modules %}
+ <div id="accordian">
+ <div class="card">
+ <div class="card-header">
+ <div class="row">
+ <div class="col-md-10">
+ <a href="{% url 'yaksh:view_module' module.id course.id %}">
+ {{module.name}}
+ {% if learning_module.id == module.id %}
+ <i class="fa fa-edit"></i>
+ {% endif %}
+ </a>
+ </div>
+ <div class="col-md-2">
+ <a class="card-link" data-toggle="collapse" href="#collapse{{module.id}}">
+ <i class="fa fa-angle-down"></i>
+ </a>
+ </div>
+ </div>
+ </div>
+ {% if learning_module.id == module.id %}
+ <div id="collapse{{module.id}}" class="collapse show" data-parent="#accordion">
{% else %}
- <a href="{{ URL_ROOT }}/exam/show_lesson/{{unit.lesson.id}}/{{module.id}}/{{course.id}}" class="list-group-item" data-parent="#menu1">
- {% if status == "completed" %}
- <i class="fa fa-check-square yakshgreen"></i>
- {% else %}
- <i class="fa fa-square-o"></i>
- {% endif %}
- {{ unit.lesson.name }}
- {% if unit.id == current_unit.id %}
- <i class="fa fa-thumb-tack yakshred" data-toggle="tooltip" title="Currently on">
- </i>
- {% endif %}
- </a>
+ <div id="collapse{{module.id}}" class="collapse hide" data-parent="#accordion">
{% endif %}
- </span>
- {% endfor %}
-
- </div>
+ <div class="card-body">
+ {% for unit in module.get_learning_units %}
+ {% get_unit_status course module unit user as status %}
+ {% if unit.type == "quiz" %}
+ <a href="{% url 'yaksh:start_quiz' unit.quiz.questionpaper_set.get.id module.id course.id %}" class="list-group-item">
+ {% if status == "completed" %}
+ <i class="fa fa-check-square"></i>
+ {% else %}
+ <i class="fa fa-square-o"></i>
+ {% endif %}
+ {{ unit.quiz.description }}
+ </a>
+ {% else %}
+ <a href="{% url 'yaksh:show_lesson' unit.lesson.id module.id course.id %}" class="list-group-item">
+ {% if status == "completed" %}
+ <i class="fa fa-check-square"></i>
+ {% else %}
+ <i class="fa fa-square-o"></i>
+ {% endif %}
+ {{ unit.lesson.name }}
+ {% if unit.id == current_unit.id %}
+ <i class="fa fa-play-circle" data-toggle="tooltip" title="Currently on">
+ </i>
+ {% endif %}
+ </a>
+ {% endif %}
+ {% endfor %}
+ </div>
+ </div>
+ </div>
+ </div>
{% endfor %}
- </div>
- <a href="#sidebar" data-toggle="collapse" id="sidebaricon"><i class="fa fa-navicon fa-lg"></i></a>
- <!-- End of sidebar-->
+ </nav>
- <main class="col" id="sidebarbody">
+ <!-- Page Content -->
+ <div id="content">
- <div class="container-fluid yakshwell">
- <div class="yakshwell bg-light">
- <div class="row align-items-center ">
- <div class="col h3 text-center">
- {{ learning_module.name }}
- {% if state == "lesson" %}
- : {{lesson.name}}
- {% endif %}
- </div>
- </div>
- </div>
-
-
- {% if msg %}
+ <button type="button" id="sidebarCollapse" class="btn btn-outline-info">
+ <i class="fa fa-navicon fa-lg"></i>
+ </button>
+
+ <br><br>
+ <ol class="breadcrumb">
+ <li class="breadcrumb-item">
+ {{course.name}}
+ </li>
+ <li class="breadcrumb-item">
+ {{ learning_module.name }}
+ </li>
+ {% if state == "lesson" %}
+ <li class="breadcrumb-item active">{{lesson.name}}</li>
+ {% endif %}
+ </ol>
+ <br>
+
+ {% if msg %}
<center>
- <div class="col-md-8 yakshwell">
- <div class="alert alert-warning animated flash">{{msg}}</div>
+ <div class="alert alert-dismissible alert-warning">
+ <button type="button" class="close" data-dismiss="alert">
+ <i class="fa fa-close"></i>
+ </button>
+ <strong>{{ msg }}</strong>
</div>
</center>
- {% endif %}
+ {% endif %}
+
- <div class="col-md-12 main">
{% if state == "module" %} <!-- Module instructions body -->
- <div class="row yakshwell">
- <div class="col-md-8 ">
- {{learning_module.html_data|safe}}
- {% if learning_module.html_data%}
- {% endif %}
- </div>
- </div>
- <div class="yakshwell text-center">
- {% if first_unit %}
- <a href="{{ URL_ROOT }}/exam/next_unit/{{course.id}}/{{learning_module.id}}/{{first_unit.id}}/1" class="btn btn-success">Start
- <i class="fa fa-play">
- </i>
- </a>
- {% else %}
- <a href="{{ URL_ROOT }}/exam/next_unit/{{course.id}}/{{learning_module.id}}" class="btn btn-success">Next
- <i class="fa fa-step-forward">
- </i>
- </a>
- {% endif %}
- </div>
- </div>
+ {% if learning_module.html_data %}
+ {{learning_module.html_data|safe}}
+ {% else %}
+ No Module information
+ {% endif %}
+ <br>
+ {% if first_unit %}
+ <a href="{% url 'yaksh:next_unit' course.id learning_module.id first_unit.id '1' %}" class="btn btn-success btn-lg">Start
+ <i class="fa fa-play">
+ </i>
+ </a>
+ {% else %}
+ <a href="{% url 'yaksh:next_unit' course.id learning_module.id %}" class="btn btn-success btn-lg">Next
+ <i class="fa fa-step-forward">
+ </i>
+ </a>
+ {% endif %}
{% else %} <!-- Lesson body -->
-
- <div class="yakshwell">
- <div class="yakshwell text-center ">
- {{lesson.html_data|safe}}
- </div>
- {% if lesson.get_files %}
- <div class="yakshwell col-md-5">
- <div class="card yakshwell">
- <span class="h4"> Files for this lesson </span> <hr>
- <span class="col-md-2">
- {% for f in lesson.get_files %}
- <div class="yakshwell">
- <a href="{{f.file.url}}" class="btn btn-outline-secondary"><b>{{forloop.counter}}.</b> {{ f.file.name|file_title }}</a>
- <br>
- </div>
- {% endfor %}
- </span>
+ <div class="col-md-6" style="width: 100%">
+ {{lesson.html_data|safe}}
+ <br>
+ <a href="{% url 'yaksh:next_unit' course.id learning_module.id current_unit.id %}" class="btn btn-info btn-lg" >
+ Next&nbsp;<i class="fa fa-step-forward"></i>
+ </a>
+ </div>
+ <br>
+ <div class="col-md-7">
+ {% with lesson.get_files as lesson_files %}
+ {% if lesson_files %}
+ <div class="card">
+ <div class="card-header">
+ Files for this lesson
+ </div>
+ <div class="card-body">
+ {% for f in lesson_files %}
+ <a href="{{f.file.url}}" class="list-group-item">
+ {{forloop.counter}}.{{ f.file.name|file_title }}
+ </a>
+ {% endfor %}
</div>
</div>
{% endif %}
- </div>
- <div class="yakshwell text-center">
- <a href="{{ URL_ROOT }}/exam/next_unit/{{course.id}}/{{learning_module.id}}/{{current_unit.id}}" class="btn btn-info" >Next
- <i class="fa fa-step-forward">
- </i>
- </a>
+ {% endwith %}
</div>
{% endif %}
- </div>
</div>
- </main>
</div>
-{% endblock %}
-
-
-{% block footer %}
- <!--footer-->
- <footer class="container-fluid yakshsidebarfooter text-center">
- <div class="row justify-content-center">
- <div class="col-sm-5 ">
- {% if user %}
- {% block info %}
- <b>{{user.get_full_name|title}}</b> with Roll no. <b>{{user.profile.roll_number}}</b> is logged in as <b>{{user.username}}</b>
- {% endblock %}
- {% endif %}
- </div>
- <div class="col-sm-2">
- |
- </div>
- <div class="col-sm-4 text-left">
- <b>Any Queries?</b> Email : info@fossee.in
- </div>
- </div>
- </footer>
- <!--footer end-->
+<script type="text/javascript">
+ $(document).ready(function () {
+ $('#sidebarCollapse').on('click', function () {
+ $('#sidebar').toggleClass('active');
+ });
+ });
+</script>
{% endblock %}
diff --git a/yaksh/templates/yaksh/showquestions.html b/yaksh/templates/yaksh/showquestions.html
index 4216d94..895c345 100644
--- a/yaksh/templates/yaksh/showquestions.html
+++ b/yaksh/templates/yaksh/showquestions.html
@@ -14,9 +14,9 @@
{% block content %}
<div class="container">
<!-- Side bar -->
- <div class="nav nav-pills" id="sidebar" role="tablist" aria-orientation="vertical">
+ <div class="nav nav-pills" role="tablist" aria-orientation="vertical">
<a href="#show" id="showbar" class="nav-link active" data-toggle="pill" role="tab" aria-controls="show" aria-selected="true"> Show all Questions</a>
- <a href="#updown" id="updownbar" class="nav-link" data-toggle="pill" role="tab" aria-controls="updown" aria-selected="false" > Upload and Download Questions</a>
+ <a href="#updown" id="updownbar" class="nav-link" data-toggle="pill" role="tab" aria-controls="updown" aria-selected="false" > Upload Questions</a>
</div>
<!-- End of side bar -->
<div class="tab-content">
@@ -49,7 +49,7 @@
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group col-md-6">
- <a class="btn btn-lg btn-primary" href="{% url 'yaksh:download_yaml_template' %}">
+ <a class="btn btn-info" href="{% url 'yaksh:download_yaml_template' %}">
<i class="fa fa-download"></i>&nbsp;Download Template</a>
<br><br>
<h4> Or </h4>
@@ -61,8 +61,10 @@
Choose file
</label>
</div>
+ <div class="input-group-append">
+ <button class="btn btn-outline-primary" type="submit" name="upload" value="upload"><i class="fa fa-upload"></i>&nbsp;Upload File</button>
+ </div>
</div>
- <button class="btn btn-lg btn-success" type="submit" name="upload" value="upload"><i class="fa fa-upload"></i>&nbsp;Upload File</button>
</div>
<script>
$('#id_file').on('change',function(){
@@ -138,11 +140,14 @@
{% endif %}
</select>
</div>
+ <br><br>
+ <div class="col-md-6">
+ <a class="btn btn-primary" href="{% url 'yaksh:show_questions' %}">
+ Clear Filters
+ </a>
+ </div>
</div>
</div>
- <br/>
- <a class="btn btn-lg btn-primary" href="{% url 'yaksh:show_questions' %}">
- Clear Filters</a>
</div>
</div>
<div id="filtered-questions">
@@ -160,13 +165,13 @@
<thead>
<tr class="yakshred">
<th> Select </th>
- <th> Summary </th>
- <th> Language </th>
- <th> Type </th>
- <th> Marks </th>
+ <th> Summary&nbsp;<i class="fa fa-sort"></i> </th>
+ <th> Language&nbsp;<i class="fa fa-sort"></i> </th>
+ <th> Type&nbsp;<i class="fa fa-sort"></i> </th>
+ <th> Marks&nbsp;<i class="fa fa-sort"></i> </th>
</tr>
</thead>
- <tbody>
+ <tbody>
{% for question in questions %}
<tr>
<td>
@@ -183,6 +188,11 @@
</div>
</div>
{% include "yaksh/paginator.html" %}
+ {% else %}
+ <br><br>
+ <div class="alert alert-info">
+ <center><h3>No Questions created</h3></center>
+ </div>
{% endif %}
</div>
<br>
@@ -190,9 +200,9 @@
{% if questions %}
<button class="btn btn-lg btn-primary" type="submit" name='download' value='download'><i class="fa fa-download"></i>&nbsp;Download Selected</button>
<button class="btn btn-lg btn-primary" type="submit" name="test" value="test">Test Selected</button>
+ <button class="btn btn-lg btn-danger" type="submit" onClick="return confirm_delete(frm);" name='delete' value='delete'>
+ <i class="fa fa-trash"></i>&nbsp;Delete Selected</button>
{% endif %}
- <button class="btn btn-lg btn-danger" type="submit" onClick="return confirm_delete(frm);" name='delete' value='delete'>
- <i class="fa fa-trash"></i>&nbsp;Delete Selected</button>
</center>
</form>
</div>
diff --git a/yaksh/templates/yaksh/statistics_question.html b/yaksh/templates/yaksh/statistics_question.html
index 4d737eb..58fd8db 100644
--- a/yaksh/templates/yaksh/statistics_question.html
+++ b/yaksh/templates/yaksh/statistics_question.html
@@ -3,24 +3,29 @@
{% block pagetitle %} Statistics for {{ quiz.description }}{% endblock pagetitle %}
{% block content %}
-<div class="yakshwell container">
-<div class="row">
- <div class="col-md-2">
-{% for attempt in attempts %}
- <p><a href="{{URL_ROOT}}/exam/manage/statistics/question/{{questionpaper_id}}/{{attempt}}/{{course_id}}">Attempt {{ attempt }}</a></p>
- {% endfor %}
-</div>
-<div class="col-md-9">
-{% if question_stats %}
- <p><b>Total number of participants: {{ total }}</b></p>
- <table class="table table-bordered table-responsive-sm">
- <tr class="bg-light yakshred"><th>Question</th><th>Type</th><th>Total</th><th>Answered</th></tr>
- {% for question, value in question_stats.items %}
- <tr><td>{{ question.summary }}</td><td>{{ question.type }}</td><td>{{value.1}}</td><td>{{ value.0 }} ({% widthratio value.0 value.1 100 %}%)</td></tr>
- {% endfor %}
- </table>
- {% endif %}
+<div class="container">
+ <div class="row">
+ <div class="col-md-2">
+ <ul class="list-group">
+ {% for attempt in attempts %}
+ <li class="list-group-item">
+ <a href="{% url 'yaksh:show_statistics' questionpaper_id attempt course_id %}">Attempt {{ attempt }}
+ </a>
+ </li>
+ {% endfor %}
+ </ul>
+ </div>
+ <div class="col-md-9">
+ {% if question_stats %}
+ <p><b>Total number of participants: {{ total }}</b></p>
+ <table class="table table-bordered table-responsive-sm">
+ <tr class="bg-light yakshred"><th>Question</th><th>Type</th><th>Total</th><th>Answered</th></tr>
+ {% for question, value in question_stats.items %}
+ <tr><td>{{ question.summary }}</td><td>{{ question.type }}</td><td>{{value.1}}</td><td>{{ value.0 }} ({% widthratio value.0 value.1 100 %}%)</td></tr>
+ {% endfor %}
+ </table>
+ {% endif %}
+ </div>
</div>
</div>
-</div>
{% endblock %}
diff --git a/yaksh/templates/yaksh/user_data.html b/yaksh/templates/yaksh/user_data.html
index 317cb15..6547851 100644
--- a/yaksh/templates/yaksh/user_data.html
+++ b/yaksh/templates/yaksh/user_data.html
@@ -1,299 +1,354 @@
{% extends "manage.html" %}
{% load custom_filters %}
+{% load static %}
+{% block title %} User Data {% endblock %}
{% block pagetitle %} Data for user {{ data.user.get_full_name.title }} {% endblock pagetitle %}
-{% block content %}
+
{% block script %}
-<script src= "{{ URL_ROOT }}/static/yaksh/js/edit_question.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/mathjax/MathJax.js?config=TeX-MML-AM_CHTML"></script>
+<script type="text/javascript" src="{% static 'yaksh/js/jquery.tablesorter.min.js' %}">
+</script>
+<script type="text/javascript" src="{% static 'yaksh/js/mathjax/MathJax.js' %}?config=TeX-MML-AM_CHTML"></script>
{% endblock %}
-<div class="yakshwell container">
- <div class="card col-md-4">
- <p class="card-body">
- Name: {{ data.user.get_full_name.title }} <br/>
- Username: {{ data.user.username }} <br/>
- {% if data.profile %}
- Roll number: {{ data.profile.roll_number }} <br/>
- Position: {{ data.profile.position }} <br/>
- Department: {{ data.profile.department }} <br/>
- Institute: {{ data.profile.institute }} <br/>
- {% endif %}
- Email: {{ data.user.email }} <br/>
- Date joined: {{ data.user.date_joined }} <br/>
- Last login: {{ data.user.last_login }}
- </p>
- </div>
- {% if data.papers %}
- <p class="text-center"><a href="{{URL_ROOT}}/exam/manage/gradeuser/{{data.papers.0.question_paper.quiz.id}}/{{ data.user.id }}/{{course_id}}/" class="btn btn-info ">
- Grade/correct paper</a>
- </p>
- {% for paper in data.papers %}
- {% if forloop.counter == 2 and data.questionpaperid %}
- <hr>
- <u>
- <h2> Previous attempts </h2>
- </u>
- {% endif %}
- <h2> Quiz: {{ paper.question_paper.quiz.description }} </h2>
- <p>
- Attempt Number: {{ paper.attempt_number }}<br/>
- Questions correctly answered: {{ paper.get_answered_str }} <br/>
- Total attempts at questions: {{ paper.answers.count }} <br/>
- Marks obtained: {{ paper.marks_obtained }} <br/>
- Start time: {{ paper.start_time }} <br/>
- User IP address: {{ paper.user_ip }}
- </p>
- {% if paper.answers.count %}
- <div class="table-wrapper-2">
- <h3> Answers </h3>
- <br>
- {% for question, answers in paper.get_question_answers.items %}
- <div class = "yakshlabel">
- <div class="card">
- <div class="card-heading alert-info" id="question_{{question.id}}">
- <strong> Details: {{forloop.counter}}. {{ question.summary }}
- <a href="" onClick="grade_data('show_question{{question.id}}{{paper.attempt_number}}'); return false;"> Show Question </a>
- <span class="marks pull-right"> Mark(s): {{ question.points }} </span>
+{% block content %}
+<div class="container">
+ {% if data.papers %}
+ <p class="text-center">
+ {% with data.papers.0 as paper %}
+ <div class="card">
+ <div class="card-header">
+ Course Details
+ </div>
+ <div class="card-body">
+ <div class="row">
+ <div class="col-md-6">
+ <p><b>Course:</b> {{ paper.course.name }}</p>
+ <p><b>Quiz:</b> {{ paper.question_paper.quiz.description }}</p>
+ </div>
+ <div class="col-md-6">
+ <p><b>Start time:</b> {{ paper.start_time }}</p>
+ <p><b>End time:</b> {{ paper.end_time }}</p>
+ <p><b>User IP:</b> {{paper.user_ip}} </p>
+ </div>
+ </div>
+ </div>
+ </div>
+ {% endwith %}
+ <br>
+ <a href="{% url 'yaksh:grade_user' data.papers.0.question_paper.quiz.id data.user.id course_id %}" class="btn btn-info">
+ Grade User
+ </a>
+ <br>
+ {% for paper in data.papers %}
+ <br>
+ <h3><b><u>Attempt Number:</u></b>&nbsp;<span class="badge badge-pill badge-info">
+ {{paper.attempt_number}}
+ </span></h3>
+ <div class="card">
+ <div class="card-header">
+ Scorecard
+ </div>
+ <div class="card-body">
+ <p><b>Status:</b>
+ {% if paper.passed %}
+ <span class="badge badge-pill badge-success"> Passed </span>
+ {% else %}
+ <span class="badge badge-pill badge-danger"> Failed </span>
+ {% endif %}
+ </p>
+ <p><b>Total Marks:</b> {{ paper.question_paper.total_marks }}</p>
+ <p><b>Marks obtained:</b> {{ paper.marks_obtained }}</p>
+ {% if paper.percent %}
+ <p><b>Percentage obtained:</b> {{paper.percent}}%</p>
+ {% endif %}
+ <p><b>Total attempts at questions:</b> {{ paper.answers.count }}</p>
+ </div>
+ </div>
+ <br>
+ {% if paper.answers.count %}
+ <div class="card">
+ <div class="card-header">
+ Submission Details
+ </div>
+ <div class="card-body">
+ <table class="tablesorter table table-striped table-bordered table-responsive-sm" id='marks_table'>
+ <thead>
+ <tr>
+ <th>Questions</th>
+ <th>Type</th>
+ <th>Marks Obtained</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for question, answers in paper.get_question_answers.items %}
+ {% with answers|last as answer %}
+ <tr>
+ <td>
+ <a href="#question_{{question.id}}">
+ {{ question.summary }}
+ </a>
+ </td>
+ <td>{{ question.type }}</td>
+ <td>{{ answer.answer.marks }}</td>
+ </tr>
+ {% endwith %}
+ {% endfor %}
+ </tbody>
+ </table>
+ {% for question, answers in paper.get_question_answers.items %}
+ <div class="card" id="question_{{question.id}}">
+ <div class="card-header text-white bg-info">
+ <strong>
+ Details: {{forloop.counter}}. {{ question.summary }}
+ <span class="marks pull-right"> Mark(s): {{ question.points }} </span>
</strong>
- </div>
- <div class="card-body" id="show_question{{question.id}}{{paper.attempt_number}}" style="display: none;">
- <h5><u>Question:</u></h5>
+ </div>
+ <div class="card-body">
+ <h5>
+ <span class="badge badge-pill badge-primary">Question:</span>
+ </h5>
<strong>{{ question.description|safe }}</strong>
+ <br><br>
{% if question.type == "mcq" or question.type == "mcc" %}
- <h5> <u>Choices:</u></h5>
- {% for testcase in question.get_test_cases %}
- {% if testcase.correct %}
- <br/>
- <strong>{{ forloop.counter }}. {{ testcase.options|safe }}</strong>
- <span class="badge badge-success">Correct </span>
- {% else %}
- <br/><strong>
- {{ forloop.counter }}. {{ testcase.options|safe }}</strong>
- {% endif %}
- {% endfor %}
+ <h5>
+ <span class="badge badge-pill badge-primary">Choices:</span>
+ </h5>
+ {% for testcase in question.get_test_cases %}
+ {% if testcase.correct %}
+ <strong>
+ <span class="badge badge-pill badge-success">
+ {{ forloop.counter }}.
+ </span>
+ {{ testcase.options|safe }}
+ </strong>
+ {% else %}
+ <strong>
+ <span class="badge badge-pill badge-secondary">
+ {{ forloop.counter }}.
+ </span>
+ {{ testcase.options|safe }}
+ </strong>
+ {% endif %}
+ <br>
+ {% endfor %}
{% elif question.type == "integer" or question.type == "string" or question.type == "float" %}
- <h5> <u>Correct Answer:</u></h5>
- {% for testcase in question.get_test_cases %}
- <strong>{{ testcase.correct|safe }}</strong>
- {% if testcase.error_margin %}
- <strong>{{ testcase.error_margin|safe }}</strong>
- {% endif %}
- {% endfor %}
+ <h5>
+ <span class="badge badge-pill badge-primary">
+ Correct Answer:
+ </span>
+ </h5>
+ {% for testcase in question.get_test_cases %}
+ <strong>{{ testcase.correct }}</strong>
+ {% if testcase.error_margin %}
+ <strong>{{ testcase.error_margin }}</strong>
+ {% endif %}
+ {% endfor %}
{% elif question.type == "arrange" %}
- <h5> <u>Correct Order:</u></h5>
- <div class="list-group" >
- {% for testcase in question.get_test_cases %}
- <li class="list-group-item"><strong>{{ testcase.options|safe }}</strong></li>
- {% endfor %}
- </div>
+ <h5>
+ <span class="badge badge-pill badge-primary">
+ Correct Order:</span>
+ </h5>
+ <div class="list-group" >
+ {% for testcase in question.get_test_cases %}
+ <li class="list-group-item">
+ <strong>{{ testcase.options }}</strong>
+ </li>
+ {% endfor %}
+ </div>
{% else %}
- <h5> <u>Test cases: </u></h5>
- {% for testcase in question.get_test_cases %}
- <br/><strong>{{ forloop.counter }}. {{ testcase }}</strong>
- {% endfor %}
- {%endif%}
- </div>
- </div>
- <h5>Student answer: </h5>
- {% if question.type == "upload" %}
- {% if has_user_assignments %}
- <a href="{{URL_ROOT}}/exam/manage/download/user_assignment/{{question.id}}/{{data.user.id}}/{{paper.question_paper.quiz.id}}/{{course_id}}">
- <div class="btn btn-outline-info text-center">
- Assignment File for {{ data.user.get_full_name.title }}
- </div>
- </a>
- {% with answers|last as answer%}
- {% if answer.answer.correct %}
- <div class="card ">
- <div class="card-heading alert-success">Correct answer</div>
- </div>
- {% else %}
- <div class="card ">
- <div class="card-heading alert-danger">Incorrect Answer</div>
- </div>
- {% endif %}
- {% endwith %}
- {% else %}
- <center>
- <div class="alert alert-warning animated flash">
- <h5>No Assignment submitted by {{ data.user.get_full_name.title }}</h5>
- </div>
- </center>
- {% endif %}
- {% else %}
- {% for ans in answers %}
- {% if ans.answer.correct %}
- <div class="card ">
- <div class="card-heading alert-success">
- Correct answer:
+ <h5>
+ <span class="badge badge-pill badge-primary">Test cases:
+ </span>
+ </h5>
+ {% for testcase in question.get_test_cases %}
+ <strong>
+ {{ forloop.counter }}. {{ testcase }}
+ </strong>
+ <br>
+ {% endfor %}
+ {% endif %}
+ <br>
+ <h5>
+ <span class="badge badge-pill badge-primary">Student answer(s):
+ </span>
+ </h5>
+ {% if question.type == "upload" %}
+ {% if has_user_assignments %}
+ <a href="{% url 'yaksh:download_user_assignment' question.id data.user.id paper.question_paper.quiz.id course_id %}">
+ <div class="btn btn-outline-info text-center">
+ Assignment File for {{ data.user.get_full_name.title }}
+ </div>
+ </a>
+ {% else %}
+ <center>
+ <div class="alert alert-warning">
+ <h5>
+ Assignment not submitted by {{ data.user.get_full_name.title }}
+ </h5>
+ </div>
+ </center>
+ {% endif %} <!-- End has_user_assignments -->
{% else %}
- <div class="card ">
- <div class="card-heading-heading alert-danger">
- Error:
+ {% for ans in answers %}
+ <strong>
+ Attempt Number: {{forloop.counter}}
+ </strong>
+ <div id="accordian">
+ <div class="card">
+ {% if ans.answer.correct %}
+ <div class="card-header">
+ <span class="badge badge-success">
+ Correct answer:
+ </span>
+ <a class="card-link" data-toggle="collapse" href="#submitted_{{ans.answer.id}}">
+ <span class="pull-right">
+ Details&nbsp;<i class="fa fa-toggle-down"></i>
+ </span>
+ </a>
+ </div>
+ {% else %}
+ <div class="card-header">
+ <span class="badge badge-danger">
+ Error:
+ </span>
+ <a class="card-link" data-toggle="collapse" href="#submitted_{{ans.answer.id}}">
+ <span class="pull-right">
+ Details&nbsp;<i class="fa fa-toggle-down"></i>
+ </span>
+ </a>
+ </div>
{% endif %}
- {% with ans.error_list as err %}
- {% for error in err %}
- {% if error.type == 'stdio' %}
- <div class = "card">
- <div class="card-body">
- {% if error.given_input %}
- <table class="table table-bordered table-responsive-sm">
- <col width="30%">
- <tr class = "table-active">
- <td> For given Input value(s):</td>
- <td>{{error.given_input}}</td>
- </tr>
- </table>
- {% endif %}
- <table class="table table-bordered table-responsive-sm" width="100%" id="output" style="table-layout: fixed">
- <col width="10%">
- <col width="40%">
- <col width="40%">
- <col width="10%">
- <tr>
- <th>
- <center>Line No.</center>
- </th>
- <th>
- <center>Expected Output</center>
- </th>
- <th>
- <center>User output</center>
- </th>
- <th>
- <center>Status</center>
- </th>
- </tr>
- {% for expected,user in error.expected_output|zip:error.user_output %}
- <tr>
+ <div class="collapse hide" id="submitted_{{ans.answer.id}}" data-parent="#accordion">
+ <div class="card-body">
+ {% with ans.error_list as err %}
+ {% for error in err %}
+ {% if error.type == 'stdio' %}
+ {% if error.given_input %}
+ <table class="table table-bordered table-responsive-sm">
+ <tr class="table-active">
+ <td> For given Input value(s):</td>
+ <td>{{error.given_input}}</td>
+ </tr>
+ </table>
+ {% endif %}
+ <table id="course-detail" class="table table-bordered table-responsive-sm" width="100%" id="output">
+ <tr>
+ <th><center>Line No.</center></th>
+ <th><center>Expected Output</center></th>
+ <th><center>User output</center></th>
+ <th><center>Status</center></th>
+ </tr>
+ {% for expected,user in error.expected_output|zip:error.user_output %}
<td> {{forloop.counter}} </td>
<td>{{expected|default:""}} </td>
<td>{{user|default:""}}</td>
{% if forloop.counter0 in error.error_line_numbers or not expected or not user %}
- <td><span class ="fa fa-times text-warning"></span></td>
+ <td><span class ="fa fa-times text-warning"/></td>
{% else %}
- <td><span class ="fa fa-check text-success"></span></td>
+ <td><span class ="fa fa-check text-success"/></td>
{% endif %}
- </tr>
- {% endfor %}
- </table>
- <table width="100%" class="table table-bordered table-responsive-sm">
- <col width="10">
- <tr>
- <td><b>Error:</b></td>
- <td>{{error.error_msg}}</td>
- </tr>
- </table>
- </div>
- </div>
- {% elif error.type == 'assertion' %}
- {% if error.test_case %}
- <strong> We tried you code with the following test case:</strong><br/></br>
- <pre><code><strong style="color:#d9534f">{{error.test_case}}</strong></code></pre>
- {% endif %}
- <p> <b>The following error took place: </b></p>
- <div class="card">
- <div class="card-body">
- <table class="table table-bordered table-responsive-sm" width="100%" style="table-layout: fixed">
- <col width="30%">
- <tr class = "active">
- <td><b>Exception Name: </b></td>
- <td><span style="color: #d9534f">{{error.exception}}</span></td>
- </tr>
- <tr>
- <td><b>Exception Message: </b></td>
- <td>{{error.message}}</td>
- </tr>
- <tr>
- {% if error.traceback %}
- <td><b>Full Traceback: </b></td>
- <td>
- <pre>{{error.traceback}}</pre>
- </td>
- {% endif %}
- </tr>
- </table>
- </div>
- </div>
- <!-- Closes card -->
- {% else %}
- <pre><code> {{error|safe}} </code></pre>
- {% endif %}
- {% endfor %}
- {% endwith %}
- </div>
- <div class="card-body">
- {% if question.type == "code" %}
- <pre><code>{{ ans.answer.answer.strip|safe }}</code></pre>
- {% elif question.type == "mcc"%}
- <div class="card">
- <div class="card-body">
- {% for testcases in question.get_test_cases %}
- {%if testcases.id|stringformat:"i" in ans.answer.answer.strip|safe %}
- <li>{{ testcases.options.strip|safe }}</li>
- {% endif %}
+ </tr>
+ {% endfor %}
+ </table>
+ <table width="100%" class="table table-bordered table-responsive-sm">
+ <col width="10">
+ <tr>
+ <td>Error:</td>
+ <td>{{error.error_msg}}</td>
+ </tr>
+ </table>
+ {% elif error.type == 'assertion' %}
+ {% if error.test_case %}
+ <strong>
+ We tried you code with the following test case:
+ </strong><br><br>
+ <pre><code>
+ <strong>{{error.test_case}}</strong>
+ </code></pre>
+ {% endif %}
+ <p><b>The following error took place: </b></p>
+ <table id="course-detail" class="table table-bordered table-responsive-sm" width="100%">
+ <tr class = "active">
+ <td><b>Exception Name: </b></td>
+ <td><span>{{error.exception}}</span></td>
+ </tr>
+ <tr>
+ <td><b>Exception Message: </b></td><td>{{error.message}}</td>
+ </tr>
+ <tr>
+ {% if error.traceback %}
+ <td><b>Full Traceback: </b></td>
+ <td><pre>{{error.traceback}}</pre></td>
+ {% endif %}
+ </tr>
+ </table>
+ {% else %}
+ <pre><code> {{error}} </code></pre>
+ {% endif %}
{% endfor %}
- </div>
- </div>
- {% elif question.type == "mcq"%}
- <div class="card">
- <div class="card-body">
+ {% endwith %}
+ {% if question.type == "code" %}
+ {% pygmentise_user_answer question.language ans.answer.answer.strip as user_answer %}
+ <style type="text/css">{{user_answer.1}}</style>
+ <pre><code>{{user_answer.0|safe}}</code></pre>
+ {% elif question.type == "mcc" or question.type == "mcq" %}
{% for testcases in question.get_test_cases %}
- {%if testcases.id|stringformat:"i" == ans.answer.answer.strip|safe %}
- <li>{{ testcases.options.strip|safe }}</li>
- {% endif %}
+ {% if testcases.id|stringformat:"i" in ans.answer.answer.strip %}
+ <li>{{ testcases.options.strip|safe }}</li>
+ {% endif %}
{% endfor %}
- </div>
- </div>
- {% elif question.type == "arrange"%}
- <div class="card">
- <div class="card-body">
+ {% elif question.type == "arrange"%}
{% get_answer_for_arrange_options ans.answer.answer question as tc_list %}
{% for testcases in tc_list %}
- <li>{{ testcases.options.strip|safe }}</li>
+ <li>{{ testcases.options.strip }}</li>
{% endfor %}
- </div>
- </div>
- {% else %}
- <div class="card">
- <div class="card-body">
- {{ ans.answer.answer.strip|safe }}
- </div>
+ {% else %}
+ {{ ans.answer.answer.strip }}
+ {% endif %}
+ </div>
</div>
- {% endif %}
- </div>
- </div>
- {% endfor %}
- {% endif %}
+ </div>
+ </div>
+ <br>
+ {% endfor %} <!-- End for ans in answers -->
+ </div>
+ </div>
+ {% endif %}
+ <br>
+ <div class="form-group">
+ <div class="col-md-2">
+ <label class="col-form-label" for="q{{ question.id }}">Marks:</label>
{% with answers|last as answer %}
- Marks: <input id="q{{ question.id }}" type="text"
- name="q{{ question.id }}_marks" size="4"
- value="{{ answer.answer.marks }}"><br><br>
+ <input id="q{{ question.id }}" type="text" name="q{{ question.id }}_marks" size="4" class="form-control" value="{{ answer.answer.marks }}" readonly=""><br><br>
{% endwith %}
- <hr/>
- </div>
-
- {% endfor %} {# for question, answers ... #}
- </div>
-
-
-<h3>Teacher comments: </h3>
-{{ paper.comments|default:"None" }}
-{% endif %} {# if paper.answers.count #}
-{% endfor %} {# for paper in data.papers #}
-{% endif %} {# if data.papers #}
+ </div>
+ </div>
+ <hr/>
+ {% endfor %} {# for question, answers ... #}
+ <div class="form-group">
+ <h3>Teacher comments: </h3>
+ <textarea id="comments_{{paper.question_paper.id}}" class="form-control"
+ name="comments_{{ paper.question_paper.id }}" readonly="">{{ paper.comments }}</textarea>
+ </div>
+ </div>
+ </div>
+ {% else %}
+ <div class="alert alert-warning">
+ No submissions found
+ </div>
+ {% endif %} {# if paper.answers.count #}
+ <hr>
+ {% endfor %} {# for paper in data.papers #}
+ {% else %}
+ <br>
+ <center>
+ <div class="alert alert-warning">
+ {% if quiz.is_exercise %}
+ You have not attempted the Exercise {{ quiz.description }}
+ {% else %}
+ You have not attempted the quiz {{ quiz.description }}
+ {% endif %}
+ </div>
+ </center>
+ {% endif %} {# if data.papers #}
</div>
-
-<br />
-<hr />
-{% with data.papers.0 as paper %}
-<a href="{{URL_ROOT}}/exam/manage/gradeuser/{{paper.question_paper.quiz.id}}/{{ data.user.id }}/{{course_id}}/">Grade/correct paper</a>
-{% endwith %}
-<br />
-{% if data.papers.count > 1 %}
-<a href="{{URL_ROOT}}/exam/manage/monitor/">Monitor quiz</a>
-{% else %}
-{% with data.papers.0 as paper %}
-<a href="{{URL_ROOT}}/exam/manage/monitor/{{paper.question_paper.id}}/">Monitor quiz</a>
-{% endwith %}
-{% endif %}
-{% endblock %} \ No newline at end of file
+{% endblock %}
diff --git a/yaksh/templates/yaksh/view_answerpaper.html b/yaksh/templates/yaksh/view_answerpaper.html
index b87c818..c1f13d1 100644
--- a/yaksh/templates/yaksh/view_answerpaper.html
+++ b/yaksh/templates/yaksh/view_answerpaper.html
@@ -1,264 +1,354 @@
{% extends "user.html" %}
{% load custom_filters %}
+{% load static %}
+{% block title %} View Answer paper {% endblock %}
{% block pagetitle %} Answer Paper for {{ quiz.description }}{% endblock pagetitle %}
{% block script %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/mathjax/MathJax.js?config=TeX-MML-AM_CHTML"></script>
-
-{% endblock script %}
-
-{% block main %}
-<div class="yakshwell container">
-{% if not data.papers %}
- {% if quiz.is_exercise %}
- <p><b> You have not attempted the Exercise {{ quiz.description }} </b></p>
- {% else %}
- <p><b> You have not attempted the quiz {{ quiz.description }} </b></p>
- {% endif %}
-{% else %}
- {% for paper in data.papers %}
- {% if forloop.counter == 2 and data.questionpaperid %}
- <U><h2> Previous attempts </h2></U>
- {% endif %}
- {% if quiz.is_exercise %}
- <h2> Exercise: {{ paper.question_paper.quiz.description }} </h2>
- {% else %}
- <h2> Quiz: {{ paper.question_paper.quiz.description }} </h2>
- {% endif %}
-
- <div class="card">
- <div class="card-body">
- Attempt Number: {{ paper.attempt_number }}<br/>
- Questions correctly answered: {{ paper.get_answered_str }} <br/>
- Marks obtained: {{ paper.marks_obtained }} <br/>
- Start time: {{ paper.start_time }} <br/>
- End time : {{ paper.end_time }} <br/>
- Percentage obtained: {{ paper.percent }}% <br/>
- {% if paper.passed %}
- Status : <b style="color: green;"> Passed </b><br/>
- {% else %}
- Status : <b style="color: red;"> Failed </b><br/>
- {% endif %}
- </div>
- </div>
-
- {% if paper.answers.count %}
- <h3> Answerpaper: </h3>
- {% for question, answers in paper.get_question_answers.items %}
-
- <div class="card">
- <div class="card-heading yakshlabel">
- <strong> Details: {{forloop.counter}}. {{ question.summary }}
- <span class="marks pull-right"> Mark(s): {{ question.points }} </span>
- </strong>
+<script type="text/javascript" src="{% static 'yaksh/js/jquery.tablesorter.min.js' %}">
+</script>
+<script type="text/javascript" src="{% static 'yaksh/js/mathjax/MathJax.js' %}?config=TeX-MML-AM_CHTML"></script>
+{% endblock %}
+{% block content %}
+<div class="container">
+ <a class="btn btn-primary" href="{% url 'yaksh:course_modules' course_id %}">
+ <i class="fa fa-arrow-left"></i>
+ Back
+ </a>
+ <br><br>
+ {% if data.papers %}
+ <p class="text-center">
+ {% with data.papers.0 as paper %}
+ <div class="card">
+ <div class="card-header">
+ Course Details
</div>
<div class="card-body">
- <h5><u>Question:</u></h5> <strong>{{ question.description }}</strong>
- {% if question.type == "mcq" or question.type == "mcc" %}
- <h5> <u>Choices:</u></h5>
- {% get_ordered_testcases question paper as testcases %}
- {% for testcase in testcases %}
- {% if testcase.correct %}
- <br/>
- <strong>{{ forloop.counter }}. {{ testcase.options }}</strong>
- <span class="alert alert-success"> Correct</span>
- {% else %}
- <br/><strong>
- {{ forloop.counter }}. {{ testcase.options }}</strong>
- {% endif %}
- {% endfor %}
-
- {% elif question.type == "integer" or question.type == "string" or question.type == "float" %}
- <h5> <u>Correct Answer:</u></h5>
- {% for testcase in question.get_test_cases %}
- <strong>{{ testcase.correct }}</strong>
- {% endfor %}
-
- {% elif question.type == "arrange" %}
- <h5> <u>Correct Order:</u></h5>
- <div class="list-group">
- {% for testcase in question.get_test_cases %}
- <li class="list-group-item"><strong>{{ testcase.options }}</strong></li>
- {% endfor %}
- </div>
-
- {% else %}
- <h5> <u>Test cases: </u></h5>
- {% for testcase in question.get_test_cases %}
- <br/><strong>{{ forloop.counter }}. {{ testcase }}</strong>
- {% endfor %}
- {% endif %}
-
- </div>
- </div>
- {% if question.type != "code" %}
- {% if "Correct answer" in answers.0.error_list %}
- <div class="card alert-success">
- {% else %}
- <div class="card card-danger">
- {% endif %}
- <div class="card-heading">
- <strong>{{ answers.0.error_list.0 }}</strong>
+ <div class="row">
+ <div class="col-md-6">
+ <p><b>Course:</b> {{ paper.course.name }}</p>
+ <p><b>Quiz:</b> {{ paper.question_paper.quiz.description }}</p>
</div>
- <div class="card-body">
- {% if question.type == "mcc"%}
- <div class="card">
- <div class="card-body">
- {% for testcases in question.get_test_cases %}
- {%if testcases.id|stringformat:"i" in answers.0.answer %}
- <li>{{ testcases.options.strip }}</li>
- {% endif %}
- {% endfor %}
+ <div class="col-md-6">
+ <p><b>Start time:</b> {{ paper.start_time }}</p>
+ <p><b>End time:</b> {{ paper.end_time }}</p>
+ </div>
+ </div>
</div>
</div>
- {% elif question.type == "mcq"%}
- <div class="card">
- <div class="card-body">
- {% for testcases in question.get_test_cases %}
- {%if testcases.id|stringformat:"i" == answers.0.answer %}
- <li>{{ testcases.options.strip }}</li>
- {% endif %}
- {% endfor %}
+ {% endwith %}
+ {% for paper in data.papers %}
+ <br>
+ <h3><b><u>Attempt Number:</u></b>&nbsp;<span class="badge badge-pill badge-info">
+ {{paper.attempt_number}}
+ </span></h3>
+ <div class="card">
+ <div class="card-header">
+ Scorecard
+ </div>
+ <div class="card-body">
+ <p><b>Status:</b>
+ {% if paper.passed %}
+ <span class="badge badge-pill badge-success"> Passed </span>
+ {% else %}
+ <span class="badge badge-pill badge-danger"> Failed </span>
+ {% endif %}
+ </p>
+ <p><b>Total Marks:</b> {{ paper.question_paper.total_marks }}</p>
+ <p><b>Marks obtained:</b> {{ paper.marks_obtained }}</p>
+ {% if paper.percent %}
+ <p><b>Percentage obtained:</b> {{paper.percent}}%</p>
+ {% endif %}
+ <p><b>Total attempts at questions:</b> {{ paper.answers.count }}</p>
</div>
</div>
- {% elif question.type == "arrange"%}
+ <br>
+ {% if paper.answers.count %}
<div class="card">
+ <div class="card-header">
+ Submission Details
+ </div>
<div class="card-body">
- {% get_answer_for_arrange_options answers.0.answer question as tc_list %}
- {% for testcases in tc_list %}
- <li>{{ testcases.options.strip }}</li>
- {% endfor %}
- </div>
- </div>
- {% elif question.type == "upload" and has_user_assignment %}
- <a href="{{URL_ROOT}}/exam/download/user_assignment/{{question.id}}/{{data.user.id}}/{{paper.question_paper.quiz.id}}">
- <div class="card">
+ <table class="tablesorter table table-striped table-bordered table-responsive-sm" id='marks_table'>
+ <thead>
+ <tr>
+ <th>Questions</th>
+ <th>Type</th>
+ <th>Marks Obtained</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for question, answers in paper.get_question_answers.items %}
+ {% with answers|last as answer %}
+ <tr>
+ <td>
+ <a href="#question_{{question.id}}">
+ {{ question.summary }}
+ </a>
+ </td>
+ <td>{{ question.type }}</td>
+ <td>{{ answer.answer.marks }}</td>
+ </tr>
+ {% endwith %}
+ {% endfor %}
+ </tbody>
+ </table>
+ {% for question, answers in paper.get_question_answers.items %}
+ <div class="card" id="question_{{question.id}}">
+ <div class="card-header text-white bg-info">
+ <strong>
+ Details: {{forloop.counter}}. {{ question.summary }}
+ <span class="marks pull-right"> Mark(s): {{ question.points }} </span>
+ </strong>
+ </div>
<div class="card-body">
- Assignment File for {{ data.user.get_full_name.title }}
- </div></a>
+ <h5>
+ <span class="badge badge-pill badge-primary">Question:</span>
+ </h5>
+ <strong>{{ question.description|safe }}</strong>
+ <br><br>
+ {% if question.type == "mcq" or question.type == "mcc" %}
+ <h5>
+ <span class="badge badge-pill badge-primary">Choices:</span>
+ </h5>
+ {% for testcase in question.get_test_cases %}
+ {% if testcase.correct %}
+ <strong>
+ <span class="badge badge-pill badge-success">
+ {{ forloop.counter }}.
+ </span>
+ {{ testcase.options|safe }}
+ </strong>
+ {% else %}
+ <strong>
+ <span class="badge badge-pill badge-secondary">
+ {{ forloop.counter }}.
+ </span>
+ {{ testcase.options|safe }}
+ </strong>
+ {% endif %}
+ <br>
+ {% endfor %}
+ {% elif question.type == "integer" or question.type == "string" or question.type == "float" %}
+ <h5>
+ <span class="badge badge-pill badge-primary">
+ Correct Answer:
+ </span>
+ </h5>
+ {% for testcase in question.get_test_cases %}
+ <strong>{{ testcase.correct }}</strong>
+ {% if testcase.error_margin %}
+ <strong>{{ testcase.error_margin }}</strong>
+ {% endif %}
+ {% endfor %}
+ {% elif question.type == "arrange" %}
+ <h5>
+ <span class="badge badge-pill badge-primary">
+ Correct Order:</span>
+ </h5>
+ <div class="list-group" >
+ {% for testcase in question.get_test_cases %}
+ <li class="list-group-item">
+ <strong>{{ testcase.options }}</strong>
+ </li>
+ {% endfor %}
+ </div>
+ {% else %}
+ <h5>
+ <span class="badge badge-pill badge-primary">Test cases:
+ </span>
+ </h5>
+ {% for testcase in question.get_test_cases %}
+ <strong>
+ {{ forloop.counter }}. {{ testcase }}
+ </strong>
+ <br>
+ {% endfor %}
+ {% endif %}
+ <br>
+ <h5>
+ <span class="badge badge-pill badge-primary">Student answer(s):
+ </span>
+ </h5>
+ {% if question.type == "upload" %}
+ {% if has_user_assignments %}
+ <a href="{% url 'yaksh:download_user_assignment' question.id data.user.id paper.question_paper.quiz.id course_id %}">
+ <div class="btn btn-outline-info text-center">
+ Assignment File for {{ data.user.get_full_name.title }}
+ </div>
+ </a>
+ {% else %}
+ <center>
+ <div class="alert alert-warning">
+ <h5>
+ Assignment not submitted by {{ data.user.get_full_name.title }}
+ </h5>
+ </div>
+ </center>
+ {% endif %} <!-- End has_user_assignments -->
+ {% else %}
+ {% for ans in answers %}
+ <strong>
+ Attempt Number: {{forloop.counter}}
+ </strong>
+ <div id="accordian">
+ <div class="card">
+ {% if ans.answer.correct %}
+ <div class="card-header">
+ <span class="badge badge-success">
+ Correct answer:
+ </span>
+ <a class="card-link" data-toggle="collapse" href="#submitted_{{ans.answer.id}}">
+ <span class="pull-right">
+ Details&nbsp;<i class="fa fa-toggle-down"></i>
+ </span>
+ </a>
+ </div>
+ {% else %}
+ <div class="card-header">
+ <span class="badge badge-danger">
+ Error:
+ </span>
+ <a class="card-link" data-toggle="collapse" href="#submitted_{{ans.answer.id}}">
+ <span class="pull-right">
+ Details&nbsp;<i class="fa fa-toggle-down"></i>
+ </span>
+ </a>
+ </div>
+ {% endif %}
+ <div class="collapse hide" id="submitted_{{ans.answer.id}}" data-parent="#accordion">
+ <div class="card-body">
+ {% with ans.error_list as err %}
+ {% for error in err %}
+ {% if error.type == 'stdio' %}
+ {% if error.given_input %}
+ <table class="table table-bordered table-responsive-sm">
+ <tr class="table-active">
+ <td> For given Input value(s):</td>
+ <td>{{error.given_input}}</td>
+ </tr>
+ </table>
+ {% endif %}
+ <table id="course-detail" class="table table-bordered table-responsive-sm" width="100%" id="output">
+ <tr>
+ <th><center>Line No.</center></th>
+ <th><center>Expected Output</center></th>
+ <th><center>User output</center></th>
+ <th><center>Status</center></th>
+ </tr>
+ {% for expected,user in error.expected_output|zip:error.user_output %}
+ <td> {{forloop.counter}} </td>
+ <td>{{expected|default:""}} </td>
+ <td>{{user|default:""}}</td>
+ {% if forloop.counter0 in error.error_line_numbers or not expected or not user %}
+ <td><span class ="fa fa-times text-warning"/></td>
+ {% else %}
+ <td><span class ="fa fa-check text-success"/></td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </table>
+ <table width="100%" class="table table-bordered table-responsive-sm">
+ <col width="10">
+ <tr>
+ <td>Error:</td>
+ <td>{{error.error_msg}}</td>
+ </tr>
+ </table>
+ {% elif error.type == 'assertion' %}
+ {% if error.test_case %}
+ <strong>
+ We tried you code with the following test case:
+ </strong><br><br>
+ <pre><code>
+ <strong>{{error.test_case}}</strong>
+ </code></pre>
+ {% endif %}
+ <p><b>The following error took place: </b></p>
+ <table id="course-detail" class="table table-bordered table-responsive-sm" width="100%">
+ <tr class = "active">
+ <td><b>Exception Name: </b></td>
+ <td><span>{{error.exception}}</span></td>
+ </tr>
+ <tr>
+ <td><b>Exception Message: </b></td><td>{{error.message}}</td>
+ </tr>
+ <tr>
+ {% if error.traceback %}
+ <td><b>Full Traceback: </b></td>
+ <td><pre>{{error.traceback}}</pre></td>
+ {% endif %}
+ </tr>
+ </table>
+ {% else %}
+ <pre><code> {{error}} </code></pre>
+ {% endif %}
+ {% endfor %}
+ {% endwith %}
+ {% if question.type == "code" %}
+ {% pygmentise_user_answer question.language ans.answer.answer.strip as user_answer %}
+ <style type="text/css">{{user_answer.1}}</style>
+ <pre><code>{{user_answer.0|safe}}</code></pre>
+ {% elif question.type == "mcc" or question.type == "mcq" %}
+ {% for testcases in question.get_test_cases %}
+ {% if testcases.id|stringformat:"i" in ans.answer.answer.strip %}
+ <li>{{ testcases.options.strip|safe }}</li>
+ {% endif %}
+ {% endfor %}
+ {% elif question.type == "arrange"%}
+ {% get_answer_for_arrange_options ans.answer.answer question as tc_list %}
+ {% for testcases in tc_list %}
+ <li>{{ testcases.options.strip }}</li>
+ {% endfor %}
+ {% else %}
+ {{ ans.answer.answer.strip }}
+ {% endif %}
+ </div>
+ </div>
+ </div>
+ </div>
+ <br>
+ {% endfor %} <!-- End for ans in answers -->
</div>
- {% else %}
- <h5><u>Student answer:</u></h5>
- <div class="card">
- <div class="card-body">
- {{ answers.0.answer }}
- </div>
- </div>
- {% endif %}
- </div>
- </div>
- {% else %}
- <h5>Student answer: </h5>
- {% for answer in answers %}
- {% if not answer.skipped %}
- {% if answer.answer.correct %}
- <div class="card">
- <div class="card-heading alert-success">
- <strong>Correct Answer</strong>
- </div>
- {% else %}
- <div class="card ">
- <div class="card-heading alert-danger">
- <strong>Incorrect Answer</strong>
- </div>
- {% endif %}
-
- {% with answer.error_list as err %}
- {% for error in err %}
-
- {% if error.type == 'stdio' %}
- <div class = "card">
- <div class="card-body">
- {% if error.given_input %}
- <table class="table table-bordered table-responsive-sm">
- <col width="30%">
- <tr class = "table-active">
- <td> For given Input value(s):</td>
- <td>{{error.given_input}}</td>
- </tr>
- </table>
- {% endif %}
- <table class="table table-bordered table-responsive-sm" width="100%" id="output" style="table-layout: fixed">
- <col width="10%">
- <col width="40%">
- <col width="40%">
- <col width="10%">
- <tr class="info">
- <th><center>Line No.</center></th>
- <th><center>Expected Output</center></th>
- <th><center>User output</center></th>
- <th><center>Status</center></th>
- </tr>
- {% for expected,user in error.expected_output|zip:error.user_output %}
- <td> {{forloop.counter}} </td>
- <td>{{expected|default:""}} </td>
- <td>{{user|default:""}}</td>
- {% if forloop.counter0 in error.error_line_numbers or not expected or not user %}
- <td><span class ="fa fa-times text-warning"/></td>
- {% else %}
- <td><span class ="fa fa-check text-success"/></td>
- {% endif %}
- </tr>
- {% endfor %}
- </table>
- <table width="100%" class="table table-bordered table-responsive-sm">
- <col width="10">
- <tr class = "table-danger">
- <td><b>Error:</b></td>
- <td>{{error.error_msg}}</td>
- </tr>
- </table>
+ </div>
+ {% endif %}
+ <br>
+ <div class="form-group">
+ <div class="col-md-2">
+ <label class="col-form-label" for="q{{ question.id }}">Marks:</label>
+ {% with answers|last as answer %}
+ <input id="q{{ question.id }}" type="text" name="q{{ question.id }}_marks" size="4" class="form-control" value="{{ answer.answer.marks }}" readonly=""><br><br>
+ {% endwith %}
+ </div>
+ </div>
+ <hr/>
+ {% endfor %} {# for question, answers ... #}
+ <div class="form-group">
+ <h3>Teacher comments: </h3>
+ <textarea id="comments_{{paper.question_paper.id}}" class="form-control"
+ name="comments_{{ paper.question_paper.id }}" readonly="">{{ paper.comments }}</textarea>
+ </div>
+ </div>
</div>
- </div>
- {% elif error.type == 'assertion' %}
- {% if error.test_case %}
- <strong> We tried you code with the following test case:</strong><br/></br>
- <pre><code><strong style="color:#d9534f">{{error.test_case}}</strong></code></pre>
- {% endif %}
- <p> <b>The following error took place: </b></p>
- <div class="well well-sm">
- <table class="table table-bordered table-responsive-sm" width="100%" style="table-layout: fixed">
- <col width="30%">
- <tr class = "active">
- <td><b>Exception Name: </b></td>
- <td><span style="color: #d9534f">{{error.exception}}</span></td>
- </tr>
- <tr>
- <td><b>Exception Message: </b></td><td>{{error.message}}</td>
- </tr>
- <tr>
- {% if error.traceback %}
- <td><b>Full Traceback: </b></td>
- <td><pre>{{error.traceback}}</pre></td>
- {% endif %}
- </tr>
- </table>
- </div> <!-- Closes well -->
- {% else %}
- <pre><code> {{error}} </code></pre>
- {% endif %}
- {% endfor %}
- {% endwith %}
- <div class="panel-body">
- <pre><code>{{ answer.answer.answer.strip }}</code></pre>
- </div>
- </div>
- {% endif %}
- {% endfor %}
- {% endif %}
- {% with answers|last as answer %}
- <p><em><mark>Obtained Marks: {{answer.answer.marks}}</mark></em> </p>
- {% endwith %}
- <hr>
- {% endfor %} {# for question, answers ... #}
- <h3>Teacher comments: </h3>
- {{ paper.comments|default:"None" }}
- <hr><hr>
- {% endif %} {# if paper.answers.count #}
-
+ {% else %}
+ <div class="alert alert-warning">
+ No submissions found
+ </div>
+ {% endif %} {# if paper.answers.count #}
+ <hr>
{% endfor %} {# for paper in data.papers #}
-
-{% endif %} {# if not data.papers #}
+ {% else %}
+ <br>
+ <center>
+ <div class="alert alert-warning">
+ {% if quiz.is_exercise %}
+ You have not attempted the Exercise {{ quiz.description }}
+ {% else %}
+ You have not attempted the quiz {{ quiz.description }}
+ {% endif %}
+ </div>
+ </center>
+ {% endif %} {# if data.papers #}
</div>
{% endblock %}
diff --git a/yaksh/templatetags/custom_filters.py b/yaksh/templatetags/custom_filters.py
index 1cd3ca2..a78440d 100644
--- a/yaksh/templatetags/custom_filters.py
+++ b/yaksh/templatetags/custom_filters.py
@@ -7,6 +7,9 @@ try:
from itertools import zip_longest
except ImportError:
from itertools import izip_longest as zip_longest
+from pygments import highlight
+from pygments.lexers import get_lexer_by_name
+from pygments.formatters import HtmlFormatter
register = template.Library()
@@ -93,3 +96,26 @@ def course_grade(course, user):
@register.filter(name='is_checkbox')
def is_checkbox(value):
return isinstance(value, CheckboxInput)
+
+
+@register.simple_tag
+def pygmentise_user_answer(language, answer):
+ lexer = get_lexer_by_name(language, stripall=True)
+ formatter = HtmlFormatter(linenos="inline",
+ cssclass="highlight",
+ style="colorful")
+ style = formatter.get_style_defs('.highlight')
+ result = highlight(answer, lexer, formatter)
+ return result, style
+
+
+@register.simple_tag
+def course_grade(course, user):
+ return course.get_grade(user)
+
+
+@register.filter(name='highlight_spaces')
+def highlight_spaces(text):
+ return text.replace(
+ " ", '<span style="background-color:#ffb6db">&nbsp</span>'
+ )
diff --git a/yaksh/templatetags/test_custom_filters.py b/yaksh/templatetags/test_custom_filters.py
index eb1f0fb..9d7f246 100644
--- a/yaksh/templatetags/test_custom_filters.py
+++ b/yaksh/templatetags/test_custom_filters.py
@@ -11,7 +11,8 @@ from yaksh.models import (User, Profile, Question, Quiz, QuestionPaper,
from yaksh.templatetags.custom_filters import (completed, inprogress,
get_ordered_testcases,
- get_answer_for_arrange_options
+ get_answer_for_arrange_options,
+ highlight_spaces
)
@@ -57,6 +58,7 @@ def tearDownModule():
User.objects.get(username="teacher2000").delete()
Group.objects.all().delete()
+
class CustomFiltersTestCases(unittest.TestCase):
@classmethod
@@ -148,3 +150,10 @@ class CustomFiltersTestCases(unittest.TestCase):
self.assertSequenceEqual(testcases, ordered_testcases)
new_answerpaper.delete()
+
+ def test_highlight_spaces(self):
+ expected_output = "A "
+ highlighted_output = highlight_spaces(expected_output)
+ self.assertEqual(highlighted_output,
+ 'A<span style="background-color:#ffb6db">&nbsp</span>'
+ )
diff --git a/yaksh/test_views.py b/yaksh/test_views.py
index 714fc67..569b468 100644
--- a/yaksh/test_views.py
+++ b/yaksh/test_views.py
@@ -20,6 +20,7 @@ from django.core import mail
from django.conf import settings
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.files import File
+from django.contrib.messages import get_messages
from yaksh.models import (
@@ -429,29 +430,6 @@ class TestStudentDashboard(TestCase):
self.assertEqual(response.context['title'], 'All Courses')
self.assertEqual(response.context['courses'][0], courses_in_context)
- def test_student_dashboard_enrolled_courses_get(self):
- """
- Check student dashboard for all courses in which student is
- enrolled
- """
- self.client.login(
- username=self.student.username,
- password=self.student_plaintext_pass
- )
- self.course.students.add(self.student)
- response = self.client.get(reverse('yaksh:quizlist_user',
- kwargs={'enrolled': "enrolled"}),
- follow=True
- )
- courses_in_context = {
- 'data': self.course,
- 'completion_percentage': 0,
- }
- self.assertEqual(response.status_code, 200)
- self.assertTemplateUsed(response, "yaksh/quizzes_user.html")
- self.assertEqual(response.context['title'], 'Enrolled Courses')
- self.assertEqual(response.context['courses'][0], courses_in_context)
-
def test_student_dashboard_hidden_courses_post(self):
"""
Get courses for student based on the course code
@@ -610,7 +588,7 @@ class TestMonitor(TestCase):
)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "yaksh/monitor.html")
- self.assertEqual(response.context['course_details'][0], self.course)
+ self.assertEqual(response.context['objects'][0], self.course)
self.assertEqual(response.context['msg'], "Monitor")
def test_monitor_display_quiz_results(self):
@@ -796,7 +774,7 @@ class TestGradeUser(TestCase):
)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "yaksh/grade_user.html")
- self.assertEqual(response.context['course_details'][0], self.course)
+ self.assertEqual(response.context['objects'][0], self.course)
def test_grade_user_get_quiz_users(self):
"""
@@ -1209,9 +1187,6 @@ class TestAddQuiz(TestCase):
self.assertEqual(updated_quiz.description, 'updated demo quiz')
self.assertEqual(updated_quiz.pass_criteria, 40)
- self.assertEqual(response.status_code, 302)
- self.assertRedirects(response, '/exam/manage/courses/all_quizzes/')
-
def test_add_quiz_post_new_quiz(self):
"""
POST request to add quiz should add new quiz if no quiz exists
@@ -1254,9 +1229,6 @@ class TestAddQuiz(TestCase):
self.assertEqual(new_quiz.description, 'new demo quiz')
self.assertEqual(new_quiz.pass_criteria, 50)
- self.assertEqual(response.status_code, 302)
- self.assertRedirects(response, '/exam/manage/courses/all_quizzes/')
-
def test_add_exercise_denies_anonymous(self):
"""
If not logged in redirect to login page
@@ -1319,8 +1291,6 @@ class TestAddQuiz(TestCase):
self.assertEqual(updated_exercise.description, 'updated demo exercise')
self.assertEqual(updated_exercise.pass_criteria, 0)
self.assertTrue(updated_exercise.is_exercise)
- self.assertEqual(response.status_code, 302)
- self.assertRedirects(response, '/exam/manage/courses/all_quizzes/')
def test_add_exercise_post_new_exercise(self):
"""
@@ -1346,8 +1316,6 @@ class TestAddQuiz(TestCase):
self.assertEqual(new_exercise.description, 'Demo Exercise')
self.assertEqual(new_exercise.pass_criteria, 0)
self.assertTrue(new_exercise.is_exercise)
- self.assertEqual(response.status_code, 302)
- self.assertRedirects(response, '/exam/manage/courses/all_quizzes/')
def test_show_all_quizzes(self):
self.client.login(
@@ -1359,9 +1327,8 @@ class TestAddQuiz(TestCase):
follow=True
)
self.assertEqual(response.status_code, 200)
- self.assertEqual(response.context['type'], "quiz")
self.assertEqual(response.context['quizzes'][0], self.quiz)
- self.assertTemplateUsed(response, "yaksh/courses.html")
+ self.assertTemplateUsed(response, "yaksh/quizzes.html")
class TestAddAsModerator(TestCase):
@@ -1720,7 +1687,8 @@ class TestRemoveTeacher(TestCase):
institute='IIT',
department='Chemical',
position='Moderator',
- timezone='UTC'
+ timezone='UTC',
+ is_moderator=True
)
# Create Student
@@ -1836,16 +1804,10 @@ class TestRemoveTeacher(TestCase):
),
data={'remove': teacher_id_list}
)
-
- self.assertEqual(response.status_code, 302)
- redirect_destination = '/exam/manage/courses'
- self.assertRedirects(
- response, redirect_destination, status_code=302,
- target_status_code=301
+ self.assertEqual(response.status_code, 200)
+ self.assertFalse(
+ self.course.teachers.filter(id__in=teacher_id_list).exists()
)
- for t_id in teacher_id_list:
- teacher = User.objects.get(id=t_id)
- self.assertNotIn(teacher, self.course.teachers.all())
class TestCourses(TestCase):
@@ -2092,7 +2054,8 @@ class TestCourses(TestCase):
)
# Student is not allowed if not enrolled in the course
err_msg = "You are not enrolled for this course!"
- self.assertEqual(response.context['msg'], err_msg)
+ messages = [m.message for m in get_messages(response.wsgi_request)]
+ self.assertEqual(messages[0], err_msg)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "yaksh/quizzes_user.html")
@@ -2108,7 +2071,8 @@ class TestCourses(TestCase):
)
err_msg = "{0} is either expired or not active".format(
self.user1_course.name)
- self.assertEqual(response.context['msg'], err_msg)
+ messages = [m.message for m in get_messages(response.wsgi_request)]
+ self.assertEqual(messages[0], err_msg)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "yaksh/quizzes_user.html")
@@ -2157,9 +2121,9 @@ class TestCourses(TestCase):
follow=True
)
err_msg = "You do not have permissions"
- self.assertEqual(response.status_code, 200)
- self.assertTemplateUsed(response, "yaksh/complete.html")
- self.assertIn(err_msg, response.context['message'])
+ self.assertEqual(response.status_code, 404)
+ messages = [m.message for m in get_messages(response.wsgi_request)]
+ self.assertIn(err_msg, messages[0])
# Test clone/duplicate courses and create copies of modules and units
@@ -2577,10 +2541,10 @@ class TestCourseDetail(TestCase):
# Then
uploaded_user = User.objects.filter(email="abc@xyz.com")
self.assertEqual(uploaded_user.count(), 1)
- self.assertEqual(response.status_code, 200)
- self.assertIn('upload_details', response.context)
+ self.assertEqual(response.status_code, 302)
+ messages = [m.message for m in get_messages(response.wsgi_request)]
+ self.assertIn("abc@xyz.com", messages[0])
self.assertIn(uploaded_user.first(), self.user1_course.students.all())
- self.assertTemplateUsed(response, 'yaksh/course_detail.html')
def test_upload_existing_user(self):
# Given
@@ -2598,9 +2562,9 @@ class TestCourseDetail(TestCase):
data={'csv_file': upload_file})
# Then
- self.assertEqual(response.status_code, 200)
- self.assertIn('upload_details', response.context)
- self.assertTemplateUsed(response, 'yaksh/course_detail.html')
+ self.assertEqual(response.status_code, 302)
+ messages = [m.message for m in get_messages(response.wsgi_request)]
+ self.assertIn("demo_user2", messages[0])
self.assertIn(self.user2, self.user1_course.students.all())
def test_upload_same_user_multiple_course(self):
@@ -2627,15 +2591,21 @@ class TestCourseDetail(TestCase):
# Then
uploaded_users = User.objects.filter(email='abc@xyz.com')
- self.assertEqual(response1.status_code, 200)
- self.assertIn('upload_details', response1.context)
- self.assertTemplateUsed(response1, 'yaksh/course_detail.html')
- self.assertEqual(response2.status_code, 200)
- self.assertIn('upload_details', response2.context)
- self.assertTemplateUsed(response2, 'yaksh/course_detail.html')
- self.assertIn(uploaded_users.first(), self.user1_course.students.all())
- self.assertIn(uploaded_users.first(),
- self.user1_othercourse.students.all())
+ self.assertEqual(response1.status_code, 302)
+ messages1 = [m.message for m in get_messages(response1.wsgi_request)]
+ self.assertIn('abc@xyz.com', messages1[0])
+ self.assertEqual(response2.status_code, 302)
+ messages2 = [m.message for m in get_messages(response2.wsgi_request)]
+ self.assertIn('abc@xyz.com', messages2[0])
+ self.assertIn('abc@xyz.com', messages2[1])
+ self.assertTrue(
+ self.user1_course.students.filter(
+ id=uploaded_users.first().id).exists()
+ )
+ self.assertTrue(
+ self.user1_othercourse.students.filter(
+ id=uploaded_users.first().id).exists()
+ )
def test_upload_users_add_update_reject(self):
# Given
@@ -2661,9 +2631,10 @@ class TestCourseDetail(TestCase):
self.assertEqual(uploaded_user.count(), 1)
self.assertEqual(user.first_name, "test2")
self.assertIn(user, self.user1_course.get_rejected())
- self.assertEqual(response.status_code, 200)
- self.assertIn('upload_details', response.context)
- self.assertTemplateUsed(response, 'yaksh/course_detail.html')
+ self.assertEqual(response.status_code, 302)
+ messages = [m.message for m in get_messages(response.wsgi_request)]
+ self.assertIn('test2', messages[2])
+ self.assertIn('User rejected', messages[2])
def test_upload_users_with_wrong_csv(self):
# Given
@@ -2684,11 +2655,9 @@ class TestCourseDetail(TestCase):
csv_file.close()
# Then
- self.assertEqual(response.status_code, 200)
- self.assertNotIn('upload_details', response.context)
- self.assertIn('message', response.context)
- self.assertEqual(response.context['message'], message)
- self.assertTemplateUsed(response, 'yaksh/course_detail.html')
+ self.assertEqual(response.status_code, 302)
+ messages = [m.message for m in get_messages(response.wsgi_request)]
+ self.assertEqual('The file uploaded is not a CSV file.', messages[0])
def test_upload_users_csv_with_missing_headers(self):
# Given
@@ -2710,11 +2679,11 @@ class TestCourseDetail(TestCase):
csv_file.close()
# Then
- self.assertEqual(response.status_code, 200)
- self.assertNotIn('upload_details', response.context)
- self.assertIn('message', response.context)
- self.assertEqual(response.context['message'], message)
- self.assertTemplateUsed(response, 'yaksh/course_detail.html')
+ self.assertEqual(response.status_code, 302)
+ messages = [m.message for m in get_messages(response.wsgi_request)]
+ self.assertIn(
+ 'The CSV file does not contain the required headers', messages[0]
+ )
def test_upload_users_csv_with_no_values(self):
# Given
@@ -2735,12 +2704,9 @@ class TestCourseDetail(TestCase):
csv_file.close()
# Then
- self.assertEqual(response.status_code, 200)
- self.assertIn('upload_details', response.context)
- self.assertNotIn('message', response.context)
- self.assertIn("No rows in the CSV file",
- response.context['upload_details'])
- self.assertTemplateUsed(response, 'yaksh/course_detail.html')
+ self.assertEqual(response.status_code, 302)
+ messages = [m.message for m in get_messages(response.wsgi_request)]
+ self.assertIn("No rows in the CSV file", messages[0])
def test_upload_users_csv_with_missing_values(self):
'''
@@ -2776,10 +2742,9 @@ class TestCourseDetail(TestCase):
# Then
uploaded_user = User.objects.filter(email="dummy@xyz.com")
self.assertEqual(uploaded_user.count(), 1)
- self.assertEqual(response.status_code, 200)
- self.assertIn('upload_details', response.context)
- self.assertNotIn('message', response.context)
- self.assertTemplateUsed(response, 'yaksh/course_detail.html')
+ self.assertEqual(response.status_code, 302)
+ messages = [m.message for m in get_messages(response.wsgi_request)]
+ self.assertIn("Missing Values", messages[0])
def test_course_detail_denies_anonymous(self):
"""
@@ -2862,7 +2827,7 @@ class TestCourseDetail(TestCase):
'user_id': self.student.id})
)
enrolled_student = self.user1_course.students.all()
- self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.status_code, 302)
self.assertSequenceEqual([self.student], enrolled_student)
def test_student_course_enroll_post(self):
@@ -2879,7 +2844,7 @@ class TestCourseDetail(TestCase):
data={'check': self.student1.id}
)
enrolled_student = self.user1_course.students.all()
- self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.status_code, 302)
self.assertSequenceEqual([self.student1], enrolled_student)
def test_student_course_reject_get(self):
@@ -2896,7 +2861,7 @@ class TestCourseDetail(TestCase):
'user_id': self.student.id})
)
enrolled_student = self.user1_course.rejected.all()
- self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.status_code, 302)
self.assertSequenceEqual([self.student], enrolled_student)
def test_student_course_reject_post(self):
@@ -2913,7 +2878,7 @@ class TestCourseDetail(TestCase):
data={'check': self.student1.id}
)
enrolled_student = self.user1_course.rejected.all()
- self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.status_code, 302)
self.assertSequenceEqual([self.student1], enrolled_student)
def test_toggle_course_status_get(self):
@@ -2991,7 +2956,7 @@ class TestCourseDetail(TestCase):
)
self.assertEqual(get_response.status_code, 200)
self.assertEqual(get_response.context['course'], self.user1_course)
- self.assertEqual(get_response.context['state'], 'mail')
+ self.assertTrue(get_response.context['is_mail'])
def test_download_users_template(self):
""" Test to check download users template """
@@ -3037,7 +3002,7 @@ class TestCourseDetail(TestCase):
response = self.client.get(reverse('yaksh:course_status',
kwargs={'course_id': self.user1_course.id}))
self.assertEqual(response.status_code, 200)
- self.assertEqual(response.context['state'], "course_status")
+ self.assertTrue(response.context['is_progress'])
self.assertEqual(response.context['course'], self.user1_course)
student_details = response.context['student_details'][0]
student, grade, percent, current_unit = student_details
@@ -3052,7 +3017,7 @@ class TestCourseDetail(TestCase):
response = self.client.get(reverse('yaksh:course_status',
kwargs={'course_id': self.user1_course.id}))
self.assertEqual(response.status_code, 200)
- self.assertEqual(response.context['state'], "course_status")
+ self.assertTrue(response.context['is_progress'])
self.assertEqual(response.context['course'], self.user1_course)
student_details = response.context['student_details'][0]
student, grade, percent, current_unit = student_details
@@ -4000,37 +3965,8 @@ class TestModeratorDashboard(TestCase):
response = self.client.get(reverse('yaksh:manage'), follow=True)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "yaksh/moderator_dashboard.html")
- self.assertEqual(response.context['trial_paper'][0],
- self.trial_answerpaper)
self.assertEqual(response.context['courses'][0], self.course)
- def test_moderator_dashboard_delete_trial_papers(self):
- """
- Check moderator dashboard to delete trial papers
- """
- self.client.login(
- username=self.user.username,
- password=self.user_plaintext_pass
- )
- self.course.is_trial = True
- self.course.save()
- response = self.client.post(
- reverse('yaksh:manage'),
- data={'delete_paper': [self.trial_answerpaper.id]}
- )
-
- self.assertEqual(response.status_code, 200)
- self.assertTemplateUsed(response, "yaksh/moderator_dashboard.html")
- updated_answerpaper = AnswerPaper.objects.filter(user=self.user)
- updated_quiz = Quiz.objects.filter(
- description=self.trial_question_paper.quiz.description
- )
- updated_course = Course.objects.filter(
- name=self.trial_course.name)
- self.assertSequenceEqual(updated_answerpaper, [])
- self.assertSequenceEqual(updated_quiz, [])
- self.assertSequenceEqual(updated_course, [])
-
class TestUserLogin(TestCase):
def setUp(self):
@@ -4448,7 +4384,9 @@ class TestShowQuestions(TestCase):
)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'yaksh/showquestions.html')
- self.assertIn("download", response.context['msg'])
+ messages = [m.message for m in get_messages(response.wsgi_request)]
+ err_msg = "Please select atleast one question to download"
+ self.assertIn(err_msg, messages[0])
def test_upload_zip_questions(self):
"""
@@ -4490,7 +4428,8 @@ class TestShowQuestions(TestCase):
)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'yaksh/showquestions.html')
- self.assertIn("ZIP file", response.context['message'])
+ messages = [m.message for m in get_messages(response.wsgi_request)]
+ self.assertIn("Please Upload a ZIP file", messages[0])
def test_upload_yaml_questions(self):
"""
@@ -5392,7 +5331,7 @@ class TestQuestionPaper(TestCase):
# Design question paper for a quiz
response = self.client.post(
- reverse('yaksh:design_questionpaper',
+ reverse('yaksh:designquestionpaper',
kwargs={"quiz_id": self.quiz_without_qp.id}),
data={"marks": "1.0", "question_type": "code"})
self.assertEqual(response.status_code, 200)
@@ -5710,8 +5649,7 @@ class TestLearningModule(TestCase):
"description": "my test1",
"Save": "Save"})
- self.assertEqual(response.status_code, 302)
- self.assertRedirects(response, self.expected_url)
+ self.assertEqual(response.status_code, 200)
learning_module = LearningModule.objects.get(name="test module1")
self.assertEqual(learning_module.description, "my test1")
self.assertEqual(learning_module.creator, self.user)
@@ -5734,8 +5672,7 @@ class TestLearningModule(TestCase):
"description": "my test2",
"Save": "Save"})
- self.assertEqual(response.status_code, 302)
- self.assertRedirects(response, self.expected_url)
+ self.assertEqual(response.status_code, 200)
learning_module = LearningModule.objects.get(name="test module2")
self.assertEqual(learning_module.description, "my test2")
self.assertEqual(learning_module.creator, self.user)
@@ -5751,9 +5688,7 @@ class TestLearningModule(TestCase):
)
response = self.client.get(reverse('yaksh:show_all_modules'))
self.assertEqual(response.status_code, 200)
- self.assertTemplateUsed(response, 'yaksh/courses.html')
- self.assertEqual(response.context['type'], "learning_module")
- self.assertEqual(response.context['learning_modules'][0],
+ self.assertEqual(response.context['modules'][0],
self.learning_module)
def test_teacher_can_edit_module(self):
@@ -5770,8 +5705,7 @@ class TestLearningModule(TestCase):
"description": "teacher module 2",
"Save": "Save"})
- self.assertEqual(response.status_code, 302)
- self.assertRedirects(response, "/exam/manage/courses/")
+ self.assertEqual(response.status_code, 200)
learning_module = LearningModule.objects.get(name="teacher module 2")
self.assertEqual(learning_module.description, "teacher module 2")
self.assertEqual(learning_module.creator, self.user)
@@ -6054,8 +5988,6 @@ class TestLessons(TestCase):
self.learning_module.id, self.learning_module2.id])
self.course.teachers.add(self.teacher.id)
- self.expected_url = "/exam/manage/courses/"
-
def tearDown(self):
self.user.delete()
self.student.delete()
@@ -6103,18 +6035,16 @@ class TestLessons(TestCase):
)
# Teacher edits existing lesson and adds file
- self.assertEqual(response.status_code, 302)
- self.assertRedirects(response, self.expected_url)
+ self.assertEqual(response.status_code, 200)
updated_lesson = Lesson.objects.get(name="updated lesson")
self.assertEqual(updated_lesson.description, "updated description")
self.assertEqual(updated_lesson.creator, self.user)
self.assertEqual(updated_lesson.html_data,
Markdown().convert("updated description"))
- self.assertEqual(os.path.basename(updated_lesson.video_file.name),
- "test.mp4")
+ self.assertIn("test", os.path.basename(updated_lesson.video_file.name))
lesson_files = LessonFile.objects.filter(
lesson=self.lesson).first()
- self.assertIn("test.txt", lesson_files.file.name)
+ self.assertIn("test", lesson_files.file.name)
lesson_file_path = lesson_files.file.path
# Teacher removes the lesson file
response = self.client.post(
@@ -6124,8 +6054,7 @@ class TestLessons(TestCase):
data={"delete_files": [str(lesson_files.id)],
"Delete": "Delete"}
)
- self.assertEqual(response.status_code, 302)
- self.assertRedirects(response, self.expected_url)
+ self.assertEqual(response.status_code, 200)
lesson_file_exists = LessonFile.objects.filter(
lesson=self.lesson).exists()
self.assertFalse(lesson_file_exists)
@@ -6200,8 +6129,7 @@ class TestLessons(TestCase):
)
response = self.client.get(reverse('yaksh:show_all_lessons'))
self.assertEqual(response.status_code, 200)
- self.assertTemplateUsed(response, "yaksh/courses.html")
- self.assertEqual(response.context["type"], "lesson")
+ self.assertTemplateUsed(response, "yaksh/lessons.html")
self.assertEqual(response.context["lessons"][0], self.lesson)
def test_preview_lesson_description(self):
diff --git a/yaksh/urls.py b/yaksh/urls.py
index 3397fb1..49c3d4f 100644
--- a/yaksh/urls.py
+++ b/yaksh/urls.py
@@ -11,18 +11,19 @@ urlpatterns = [
url(r'^toggle_moderator/$', views.toggle_moderator_role,
name='toggle_moderator'),
url(r'^quizzes/$', views.quizlist_user, name='quizlist_user'),
- url(r'^quizzes/(?P<enrolled>\w+)/$', views.quizlist_user,
- name='quizlist_user'),
url(r'^results/$', views.results_user),
url(r'^start/(?P<questionpaper_id>\d+)/(?P<module_id>\d+)/'
- '(?P<course_id>\d+)/$', views.start),
+ '(?P<course_id>\d+)/$', views.start, name="start_quiz"),
url(r'^start/(?P<attempt_num>\d+)/(?P<module_id>\d+)/'
- '(?P<questionpaper_id>\d+)/(?P<course_id>\d+)/$', views.start),
+ '(?P<questionpaper_id>\d+)/(?P<course_id>\d+)/$', views.start,
+ name="start_quiz"),
url(r'^quit/(?P<attempt_num>\d+)/(?P<module_id>\d+)/'
- '(?P<questionpaper_id>\d+)/(?P<course_id>\d+)/$', views.quit),
- url(r'^complete/$', views.complete),
+ '(?P<questionpaper_id>\d+)/(?P<course_id>\d+)/$', views.quit,
+ name="quit_quiz"),
+ url(r'^complete/$', views.complete, name="complete"),
url(r'^complete/(?P<attempt_num>\d+)/(?P<module_id>\d+)/'
- '(?P<questionpaper_id>\d+)/(?P<course_id>\d+)/$', views.complete),
+ '(?P<questionpaper_id>\d+)/(?P<course_id>\d+)/$', views.complete,
+ name="complete"),
url(r'^register/$', views.user_register, name="register"),
url(r'^(?P<q_id>\d+)/check/$', views.check, name="check"),
url(r'^get_result/(?P<uid>\d+)/(?P<course_id>\d+)/(?P<module_id>\d+)/$',
@@ -32,10 +33,10 @@ urlpatterns = [
views.check, name="check"),
url(r'^(?P<q_id>\d+)/skip/(?P<attempt_num>\d+)/(?P<module_id>\d+)/'
'(?P<questionpaper_id>\d+)/(?P<course_id>\d+)/$',
- views.skip),
+ views.skip, name="skip_question"),
url(r'^(?P<q_id>\d+)/skip/(?P<next_q>\d+)/(?P<attempt_num>\d+)/'
'(?P<module_id>\d+)/(?P<questionpaper_id>\d+)/(?P<course_id>\d+)/$',
- views.skip),
+ views.skip, name="skip_question"),
url(r'^enroll_request/(?P<course_id>\d+)/$', views.enroll_request,
name='enroll_request'),
url(r'^self_enroll/(?P<course_id>\d+)/$', views.self_enroll,
@@ -91,7 +92,7 @@ urlpatterns = [
views.user_data, name="user_data"),
url(r'^manage/user_data/(?P<user_id>\d+)/$', views.user_data),
url(r'^manage/quiz/designquestionpaper/(?P<quiz_id>\d+)/$',
- views.design_questionpaper, name='design_questionpaper'),
+ views.design_questionpaper, name='designquestionpaper'),
url(r'^manage/designquestionpaper/(?P<quiz_id>\d+)/'
'(?P<questionpaper_id>\d+)/$',
views.design_questionpaper, name='designquestionpaper'),
@@ -109,8 +110,6 @@ urlpatterns = [
url(r'^manage/duplicate_course/(?P<course_id>\d+)/$',
views.duplicate_course, name='duplicate_course'),
url(r'manage/courses/$', views.courses, name='courses'),
- url(r'manage/allotted/courses/$', views.allotted_courses,
- name='allotted_courses'),
url(r'manage/add_course/$', views.add_course, name='add_course'),
url(r'manage/edit_course/(?P<course_id>\d+)$', views.add_course,
name='edit_course'),
@@ -119,7 +118,7 @@ urlpatterns = [
url(r'manage/enroll/(?P<course_id>\d+)/(?P<user_id>\d+)/$', views.enroll,
name="enroll_user"),
url(r'manage/enroll/rejected/(?P<course_id>\d+)/(?P<user_id>\d+)/$',
- views.enroll, {'was_rejected': True}),
+ views.enroll, {'was_rejected': True}, name="enroll_rejected"),
url(r'manage/upload_users/(?P<course_id>\d+)/$', views.upload_users,
name="upload_users"),
url(r'manage/send_mail/(?P<course_id>\d+)/$', views.send_mail,
@@ -137,10 +136,11 @@ urlpatterns = [
url(r'^manage/enroll/(?P<course_id>\d+)/$', views.enroll,
name="enroll_users"),
url(r'manage/enroll/rejected/(?P<course_id>\d+)/$',
- views.enroll, {'was_rejected': True}),
+ views.enroll, {'was_rejected': True}, name="enroll_rejected"),
url(r'manage/enrolled/reject/(?P<course_id>\d+)/$',
views.reject, {'was_enrolled': True}, name="reject_users"),
- url(r'^manage/searchteacher/(?P<course_id>\d+)/$', views.search_teacher),
+ url(r'^manage/searchteacher/(?P<course_id>\d+)/$', views.search_teacher,
+ name="search_teacher"),
url(r'^manage/addteacher/(?P<course_id>\d+)/$', views.add_teacher,
name='add_teacher'),
url(r'^manage/remove_teachers/(?P<course_id>\d+)/$', views.remove_teachers,
@@ -161,7 +161,7 @@ urlpatterns = [
url(r'^manage/regrade/paper/(?P<course_id>\d+)/(?P<answerpaper_id>\d+)/$',
views.regrade, name='regrade'),
url(r'^manage/(?P<mode>godmode|usermode)/(?P<quiz_id>\d+)/'
- '(?P<course_id>\d+)/$', views.test_quiz),
+ '(?P<course_id>\d+)/$', views.test_quiz, name="test_quiz"),
url(r'^manage/create_demo_course/$', views.create_demo_course,
name="create_demo_course"),
url(r'^manage/courses/download_course_csv/(?P<course_id>\d+)/$',
@@ -202,8 +202,6 @@ urlpatterns = [
views.add_module, name="edit_module"),
url(r'^manage/courses/designcourse/(?P<course_id>\d+)/$',
views.design_course, name="design_course"),
- url(r'^manage/courses/designcourse/(?P<course_id>\d+)/$',
- views.design_course, name="design_course"),
url(r'^manage/course_status/(?P<course_id>\d+)/$',
views.course_status, name="course_status"),
url(r'^manage/preview_questionpaper/(?P<questionpaper_id>\d+)/$',
@@ -214,4 +212,10 @@ urlpatterns = [
views.download_course, name="download_course"),
url(r'^download_course/(?P<course_id>\d+)/$',
views.download_course, name="download_course"),
+ url(r'^manage/course/enrollments/(?P<course_id>\d+)',
+ views.course_students, name="course_students"),
+ url(r'^manage/course/all/modules/(?P<course_id>\d+)',
+ views.get_course_modules, name="get_course_modules"),
+ url(r'^manage/course/teachers/(?P<course_id>\d+)',
+ views.course_teachers, name="course_teachers"),
]
diff --git a/yaksh/views.py b/yaksh/views.py
index 98fde00..d1e8b7b 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -6,10 +6,12 @@ from django.shortcuts import render, get_object_or_404, redirect
from django.template import Context, Template
from django.http import Http404
from django.db.models import Max, Q, F
+from django.db import models
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group
from django.forms.models import inlineformset_factory
+from django.forms import fields
from django.utils import timezone
from django.core.exceptions import (
MultipleObjectsReturned, ObjectDoesNotExist
@@ -17,6 +19,7 @@ from django.core.exceptions import (
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib import messages
from taggit.models import Tag
+from django.urls import reverse
import json
import six
from textwrap import dedent
@@ -99,6 +102,13 @@ def get_html_text(md_text):
return Markdown().convert(md_text)
+def formfield_callback(field):
+ if (isinstance(field, models.TextField) and field.name == 'expected_output'
+ or field.name == 'expected_input'):
+ return fields.CharField(strip=False)
+ return field.formfield()
+
+
@email_verified
def index(request, next_url=None):
"""The start page.
@@ -165,20 +175,20 @@ def quizlist_user(request, enrolled=None, msg=None):
hidden_courses = Course.objects.get_hidden_courses(code=course_code)
courses = hidden_courses
title = 'Search'
-
- elif enrolled is not None:
- courses = user.students.filter(is_trial=False).order_by('-id')
- title = 'Enrolled Courses'
else:
- courses = Course.objects.filter(
- active=True, is_trial=False
+ courses = list(Course.objects.filter(
+ active=True, is_trial=False,
).exclude(
~Q(requests=user), ~Q(rejected=user), hidden=True
- ).order_by('-id')
+ ).order_by('-id'))
+ enrolled_course = list(
+ user.students.filter(is_trial=False).order_by('-id')
+ )
+ courses.extend(enrolled_course)
title = 'All Courses'
for course in courses:
- if user in course.students.all():
+ if course.students.filter(id=user.id).exists():
_percent = course.get_completion_percent(user)
else:
_percent = None
@@ -189,9 +199,10 @@ def quizlist_user(request, enrolled=None, msg=None):
}
)
+ messages.info(request, msg)
context = {
'user': user, 'courses': courses_data,
- 'title': title, 'msg': msg
+ 'title': title
}
return my_render_to_response(request, "yaksh/quizzes_user.html", context)
@@ -245,8 +256,12 @@ def add_question(request, question_id=None):
file.toggle_hide_status()
formsets = []
for testcase in TestCase.__subclasses__():
- formset = inlineformset_factory(Question, testcase, extra=0,
- fields='__all__')
+
+ formset = inlineformset_factory(
+ Question, testcase, extra=0,
+ fields='__all__',
+ formfield_callback=formfield_callback
+ )
formsets.append(formset(
request.POST, request.FILES, instance=question
)
@@ -323,15 +338,11 @@ def add_quiz(request, quiz_id=None, course_id=None):
if quiz is None:
form.instance.creator = user
form.save()
- if not course_id:
- return my_redirect("/exam/manage/courses/all_quizzes/")
- else:
- return my_redirect("/exam/manage/courses/")
-
+ messages.success(request, "Quiz saved successfully")
else:
form = QuizForm(instance=quiz)
- context["course_id"] = course_id
- context["quiz"] = quiz
+ context["course_id"] = course_id
+ context["quiz"] = quiz
context["form"] = form
return my_render_to_response(request, 'yaksh/add_quiz.html', context)
@@ -368,12 +379,9 @@ def add_exercise(request, quiz_id=None, course_id=None):
quiz.duration = 1000
quiz.pass_criteria = 0
quiz.save()
-
- if not course_id:
- return my_redirect("/exam/manage/courses/all_quizzes/")
- else:
- return my_redirect("/exam/manage/courses/")
-
+ messages.success(
+ request, "{0} saved successfully".format(quiz.description)
+ )
else:
form = ExerciseForm(instance=quiz)
context["exercise"] = quiz
@@ -395,8 +403,8 @@ def prof_manage(request, msg=None):
return my_redirect('/exam/')
courses = Course.objects.get_queryset().filter(
Q(creator=user) | Q(teachers=user),
- is_trial=False).distinct().order_by("-id")
- paginator = Paginator(courses, 10)
+ is_trial=False).distinct().order_by("-active")
+ paginator = Paginator(courses, 30)
page = request.GET.get('page')
try:
courses = paginator.page(page)
@@ -406,28 +414,8 @@ def prof_manage(request, msg=None):
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
courses = paginator.page(paginator.num_pages)
- trial_paper = AnswerPaper.objects.filter(
- user=user, question_paper__quiz__is_trial=True,
- course__is_trial=True
- )
- if request.method == "POST":
- delete_paper = request.POST.getlist('delete_paper')
- for answerpaper_id in delete_paper:
- answerpaper = AnswerPaper.objects.get(id=answerpaper_id)
- qpaper = answerpaper.question_paper
- answerpaper.course.remove_trial_modules()
- answerpaper.course.delete()
- if qpaper.quiz.is_trial:
- qpaper.quiz.delete()
- else:
- if qpaper.answerpaper_set.count() == 1:
- qpaper.quiz.delete()
- else:
- answerpaper.delete()
-
- context = {'user': user, 'objects': courses,
- 'trial_paper': trial_paper, 'msg': msg
- }
+ messages.info(request, msg)
+ context = {'user': user, 'objects': courses}
return my_render_to_response(
request, 'yaksh/moderator_dashboard.html', context
)
@@ -509,14 +497,14 @@ def start(request, questionpaper_id=None, attempt_num=None, course_id=None,
# is user enrolled in the course
if not course.is_enrolled(user):
msg = 'You are not enrolled in {0} course'.format(course.name)
- if is_moderator(user):
+ if is_moderator(user) and course.is_trial:
return prof_manage(request, msg=msg)
return quizlist_user(request, msg=msg)
# if course is active and is not expired
if not course.active or not course.is_active_enrollment():
msg = "{0} is either expired or not active".format(course.name)
- if is_moderator(user):
+ if is_moderator(user) and course.is_trial:
return prof_manage(request, msg=msg)
return quizlist_user(request, msg=msg)
@@ -524,7 +512,7 @@ def start(request, questionpaper_id=None, attempt_num=None, course_id=None,
if quest_paper.quiz.is_expired() or not quest_paper.quiz.active:
msg = "{0} is either expired or not active".format(
quest_paper.quiz.description)
- if is_moderator(user):
+ if is_moderator(user) and course.is_trial:
return prof_manage(request, msg=msg)
return view_module(request, module_id=module_id, course_id=course_id,
msg=msg)
@@ -534,7 +522,7 @@ def start(request, questionpaper_id=None, attempt_num=None, course_id=None,
if not learning_unit.is_prerequisite_complete(
user, learning_module, course):
msg = "You have not completed the previous Lesson/Quiz/Exercise"
- if is_moderator(user):
+ if is_moderator(user) and course.is_trial:
return prof_manage(request, msg=msg)
return view_module(request, module_id=module_id,
course_id=course_id, msg=msg)
@@ -938,10 +926,9 @@ def complete(request, reason=None, attempt_num=None, questionpaper_id=None,
"""Show a page to inform user that the quiz has been completed."""
user = request.user
if questionpaper_id is None:
- message = (
- reason or "An Unexpected Error occurred."
- " Please contact your instructor/administrator."
- )
+ message = reason or ("An Unexpected Error occurred. Please "
+ "contact your instructor/administrator."
+ )
context = {'message': message}
return my_render_to_response(request, 'yaksh/complete.html', context)
else:
@@ -979,19 +966,22 @@ def add_course(request, course_id=None):
if not is_moderator(user):
raise Http404('You are not allowed to view this page')
if request.method == 'POST':
- form = CourseForm(request.POST, instance=course)
+ form = CourseForm(user, request.POST, instance=course)
if form.is_valid():
new_course = form.save(commit=False)
if course_id is None:
new_course.creator = user
new_course.save()
+ messages.success(
+ request, "Saved {0} successfully".format(new_course.name)
+ )
return my_redirect('/exam/manage/courses')
else:
return my_render_to_response(
request, 'yaksh/add_course.html', {'form': form}
)
else:
- form = CourseForm(instance=course)
+ form = CourseForm(user, instance=course)
return my_render_to_response(
request, 'yaksh/add_course.html', {'form': form}
)
@@ -1007,9 +997,15 @@ def enroll_request(request, course_id):
'Unable to add enrollments for this course, please contact your '
'instructor/administrator.'
)
- return complete(request, msg, attempt_num=None, questionpaper_id=None)
-
- course.request(user)
+ messages.warning(request, msg)
+ else:
+ course.request(user)
+ messages.success(
+ request,
+ "Enrollment request sent for {0} by {1}".format(
+ course.name, course.creator.get_full_name()
+ )
+ )
if is_moderator(user):
return my_redirect('/exam/manage/courses')
else:
@@ -1024,6 +1020,12 @@ def self_enroll(request, course_id):
if course.is_self_enroll():
was_rejected = False
course.enroll(was_rejected, user)
+ messages.success(
+ request,
+ "Enrolled in {0} by {1}".format(
+ course.name, course.creator.get_full_name()
+ )
+ )
if is_moderator(user):
return my_redirect('/exam/manage/')
else:
@@ -1037,8 +1039,9 @@ def courses(request):
if not is_moderator(user):
raise Http404('You are not allowed to view this page')
courses = Course.objects.filter(
- creator=user, is_trial=False).order_by('-id')
- paginator = Paginator(courses, 20)
+ Q(creator=user) | Q(teachers=user),
+ is_trial=False).order_by('-active').distinct()
+ paginator = Paginator(courses, 30)
page = request.GET.get('page')
try:
courses = paginator.page(page)
@@ -1054,28 +1057,6 @@ def courses(request):
@login_required
@email_verified
-def allotted_courses(request):
- user = request.user
- if not is_moderator(user):
- raise Http404('You are not allowed to view this page')
- allotted_courses = Course.objects.filter(
- teachers=user, is_trial=False).order_by('-id')
- paginator = Paginator(allotted_courses, 20)
- page = request.GET.get('page')
- try:
- allotted_courses = paginator.page(page)
- except PageNotAnInteger:
- # If page is not an integer, deliver first page.
- allotted_courses = paginator.page(1)
- except EmptyPage:
- # If page is out of range (e.g. 9999), deliver last page of results.
- allotted_courses = paginator.page(paginator.num_pages)
- context = {'allotted': True, "objects": allotted_courses}
- return my_render_to_response(request, 'yaksh/courses.html', context)
-
-
-@login_required
-@email_verified
def course_detail(request, course_id):
user = request.user
@@ -1105,7 +1086,8 @@ def enroll(request, course_id, user_id=None, was_rejected=False):
' please contact your '
'instructor/administrator.'
)
- return complete(request, msg, attempt_num=None, questionpaper_id=None)
+ messages.warning(request, msg)
+ return my_redirect(reverse('yaksh:course_students', args=[course_id]))
if not course.is_creator(user) and not course.is_teacher(user):
raise Http404('This course does not belong to you')
@@ -1115,12 +1097,13 @@ def enroll(request, course_id, user_id=None, was_rejected=False):
else:
enroll_ids = [user_id]
if not enroll_ids:
- return my_render_to_response(
- request, 'yaksh/course_detail.html', {'course': course}
- )
+ messages.warning(request, "Please select atleast one student")
+ return my_redirect(reverse('yaksh:course_students', args=[course_id]))
+
users = User.objects.filter(id__in=enroll_ids)
course.enroll(was_rejected, *users)
- return course_detail(request, course_id)
+ messages.success(request, "Enrolled student(s) successfully")
+ return my_redirect(reverse('yaksh:course_students', args=[course_id]))
@login_required
@@ -1146,9 +1129,10 @@ def send_mail(request, course_id, user_id=None):
message = send_bulk_mail(
subject, email_body, recipients, attachments
)
+ messages.info(request, message)
context = {
'course': course, 'message': message,
- 'state': 'mail'
+ 'enrolled': course.get_enrolled(), 'is_mail': True
}
return my_render_to_response(request, 'yaksh/course_detail.html', context)
@@ -1169,14 +1153,13 @@ def reject(request, course_id, user_id=None, was_enrolled=False):
else:
reject_ids = [user_id]
if not reject_ids:
- message = "Please select atleast one User"
- return my_render_to_response(
- request, 'yaksh/course_detail.html',
- {'course': course, 'message': message},
- )
+ messages.warning(request, "Please select atleast one student")
+ return my_redirect(reverse('yaksh:course_students', args=[course_id]))
+
users = User.objects.filter(id__in=reject_ids)
course.reject(was_enrolled, *users)
- return course_detail(request, course_id)
+ messages.success(request, "Rejected students successfully")
+ return my_redirect(reverse('yaksh:course_students', args=[course_id]))
@login_required
@@ -1242,17 +1225,24 @@ def monitor(request, quiz_id=None, course_id=None):
"""Monitor the progress of the papers taken so far."""
user = request.user
- if not user.is_authenticated() or not is_moderator(user):
+ if not is_moderator(user):
raise Http404('You are not allowed to view this page!')
if quiz_id is None:
- course_details = Course.objects.filter(
+ courses = Course.objects.filter(
Q(creator=user) | Q(teachers=user),
is_trial=False
- ).distinct()
+ ).order_by("-id").distinct()
+ paginator = Paginator(courses, 30)
+ page = request.GET.get('page')
+ try:
+ courses = paginator.page(page)
+ except PageNotAnInteger:
+ courses = paginator.page(1)
+ except EmptyPage:
+ courses = paginator.page(paginator.num_pages)
context = {
- "papers": [], "course_details": course_details,
- "msg": "Monitor"
+ "papers": [], "objects": courses, "msg": "Monitor"
}
return my_render_to_response(request, 'yaksh/monitor.html', context)
# quiz_id is not None.
@@ -1364,12 +1354,12 @@ def _remove_already_present(questionpaper_id, questions):
return questions
-def _get_questions_from_tags(question_tags, user):
+def _get_questions_from_tags(question_tags, user, active=True):
search_tags = []
for tags in question_tags:
search_tags.extend(re.split('[; |, |\*|\n]', tags))
return Question.objects.filter(tags__name__in=search_tags,
- user=user).distinct()
+ user=user, active=active).distinct()
@login_required
@@ -1427,19 +1417,27 @@ def design_questionpaper(request, quiz_id, questionpaper_id=None,
question_paper.fixed_question_order = questions_order
question_paper.save()
question_paper.fixed_questions.add(*questions)
+ messages.success(request, "Questions added successfully")
+ else:
+ messages.warning(request, "Please select atleast one question")
if 'remove-fixed' in request.POST:
question_ids = request.POST.getlist('added-questions', None)
- if question_paper.fixed_question_order:
- que_order = question_paper.fixed_question_order.split(",")
- for qid in question_ids:
- que_order.remove(qid)
- if que_order:
- question_paper.fixed_question_order = ",".join(que_order)
- else:
- question_paper.fixed_question_order = ""
- question_paper.save()
- question_paper.fixed_questions.remove(*question_ids)
+ if question_ids:
+ if question_paper.fixed_question_order:
+ que_order = question_paper.fixed_question_order.split(",")
+ for qid in question_ids:
+ que_order.remove(qid)
+ if que_order:
+ question_paper.fixed_question_order = ",".join(
+ que_order)
+ else:
+ question_paper.fixed_question_order = ""
+ question_paper.save()
+ question_paper.fixed_questions.remove(*question_ids)
+ messages.success(request, "Questions removed successfully")
+ else:
+ messages.warning(request, "Please select atleast one question")
if 'add-random' in request.POST:
question_ids = request.POST.getlist('random_questions', None)
@@ -1451,14 +1449,21 @@ def design_questionpaper(request, quiz_id, questionpaper_id=None,
random_ques = Question.objects.filter(id__in=question_ids)
random_set.questions.add(*random_ques)
question_paper.random_questions.add(random_set)
+ messages.success(request, "Questions removed successfully")
+ else:
+ messages.warning(request, "Please select atleast one question")
if 'remove-random' in request.POST:
random_set_ids = request.POST.getlist('random_sets', None)
- question_paper.random_questions.remove(*random_set_ids)
+ if random_set_ids:
+ question_paper.random_questions.remove(*random_set_ids)
+ messages.success(request, "Questions removed successfully")
+ else:
+ messages.warning(request, "Please select question set")
if 'save' in request.POST or 'back' in request.POST:
qpaper_form.save()
- return my_redirect('/exam/manage/courses/all_quizzes/')
+ messages.success(request, "Question Paper saved successfully")
if marks:
questions = _get_questions(user, question_type, marks)
@@ -1506,7 +1511,7 @@ def show_all_questions(request):
user_tags = questions.values_list('tags', flat=True).distinct()
all_tags = Tag.objects.filter(id__in=user_tags)
upload_form = UploadFileForm()
- paginator = Paginator(questions, 10)
+ paginator = Paginator(questions, 30)
page = request.GET.get('page')
try:
questions = paginator.page(page)
@@ -1590,7 +1595,7 @@ def show_all_questions(request):
def user_data(request, user_id, questionpaper_id=None, course_id=None):
"""Render user data."""
current_user = request.user
- if not current_user.is_authenticated() or not is_moderator(current_user):
+ if not is_moderator(current_user):
raise Http404('You are not allowed to view this page!')
user = User.objects.get(id=user_id)
data = AnswerPaper.objects.get_user_data(user, questionpaper_id, course_id)
@@ -1693,12 +1698,22 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None,
and update all their marks and also give comments for each paper.
"""
current_user = request.user
- if not current_user.is_authenticated() or not is_moderator(current_user):
+ if not is_moderator(current_user):
raise Http404('You are not allowed to view this page!')
- course_details = Course.objects.filter(Q(creator=current_user) |
- Q(teachers=current_user),
- is_trial=False).distinct()
- context = {"course_details": course_details}
+ if not course_id:
+ courses = Course.objects.filter(
+ Q(creator=current_user) | Q(teachers=current_user), is_trial=False
+ ).order_by("-id").distinct()
+ paginator = Paginator(courses, 30)
+ page = request.GET.get('page')
+ try:
+ courses = paginator.page(page)
+ except PageNotAnInteger:
+ courses = paginator.page(1)
+ except EmptyPage:
+ courses = paginator.page(paginator.num_pages)
+ context = {"objects": courses, "msg": "grade"}
+
if quiz_id is not None:
questionpaper_id = QuestionPaper.objects.filter(
quiz_id=quiz_id
@@ -1720,7 +1735,8 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None,
"quiz_id": quiz_id,
"quiz": quiz,
"has_quiz_assignments": has_quiz_assignments,
- "course_id": course_id
+ "course_id": course_id,
+ "status": "grade"
}
if user_id is not None:
attempts = AnswerPaper.objects.get_user_all_attempts(
@@ -1747,7 +1763,8 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None,
"user_id": user_id,
"has_user_assignments": has_user_assignments,
"has_quiz_assignments": has_quiz_assignments,
- "course_id": course_id
+ "course_id": course_id,
+ "status": "grade"
}
if request.method == "POST":
papers = data['papers']
@@ -1762,6 +1779,7 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None,
paper.comments = request.POST.get(
'comments_%d' % paper.question_paper.id, 'No comments')
paper.save()
+ messages.success(request, "Student data saved successfully")
course_status = CourseStatus.objects.filter(course=course, user=user)
if course_status.exists():
@@ -1854,7 +1872,8 @@ def search_teacher(request, course_id):
)
context['success'] = True
context['teachers'] = teachers
- return my_render_to_response(request, 'yaksh/addteacher.html', context)
+ context['is_add_teacher'] = True
+ return my_render_to_response(request, 'yaksh/course_detail.html', context)
@login_required
@@ -1904,7 +1923,9 @@ def add_teacher(request, course_id):
course.add_teachers(*teachers)
context['status'] = True
context['teachers_added'] = teachers
- return my_render_to_response(request, 'yaksh/addteacher.html', context)
+ messages.success(request, "Added teachers successfully")
+ context['is_add_teacher'] = True
+ return my_render_to_response(request, 'yaksh/course_detail.html', context)
@login_required
@@ -1920,9 +1941,13 @@ def remove_teachers(request, course_id):
if request.method == "POST":
teacher_ids = request.POST.getlist('remove')
- teachers = User.objects.filter(id__in=teacher_ids)
- course.remove_teachers(*teachers)
- return my_redirect('/exam/manage/courses')
+ if teacher_ids:
+ teachers = User.objects.filter(id__in=teacher_ids)
+ course.remove_teachers(*teachers)
+ messages.success(request, "Removed teachers successfully")
+ else:
+ messages.warning(request, "Please select atleast one teacher")
+ return course_teachers(request, course_id)
def test_mode(user, godmode=False, questions_list=None, quiz_id=None,
@@ -1963,6 +1988,10 @@ def test_quiz(request, mode, quiz_id, course_id=None):
current_user = request.user
quiz = Quiz.objects.get(id=quiz_id)
if (quiz.is_expired() or not quiz.active) and not godmode:
+ messages.warning(
+ request,
+ "{0} is either expired or inactive".format(quiz.description)
+ )
return my_redirect('/exam/manage')
trial_questionpaper, trial_course, trial_module = test_mode(
@@ -2233,66 +2262,60 @@ def upload_users(request, course_id):
context = {'course': course}
if not (course.is_teacher(user) or course.is_creator(user)):
- msg = 'You do not have permissions to this course.'
- return complete(request, reason=msg)
+ raise Http404('You are not allowed to view this page!')
if request.method == 'POST':
if 'csv_file' not in request.FILES:
- context['message'] = "Please upload a CSV file."
- return my_render_to_response(
- request, 'yaksh/course_detail.html', context
- )
+ messages.warning(request, "Please upload a CSV file.")
+ return my_redirect(reverse('yaksh:course_students',
+ args=[course_id]))
csv_file = request.FILES['csv_file']
is_csv_file, dialect = is_csv(csv_file)
if not is_csv_file:
- context['message'] = "The file uploaded is not a CSV file."
- return my_render_to_response(
- request, 'yaksh/course_detail.html', context
- )
+ messages.warning(request, "The file uploaded is not a CSV file.")
+ return my_redirect(reverse('yaksh:course_students',
+ args=[course_id]))
required_fields = ['firstname', 'lastname', 'email']
try:
reader = csv.DictReader(
csv_file.read().decode('utf-8').splitlines(),
dialect=dialect)
except TypeError:
- context['message'] = "Bad CSV file"
- return my_render_to_response(
- request, 'yaksh/course_detail.html', context
- )
+ messages.warning(request, "Bad CSV file")
+ return my_redirect(reverse('yaksh:course_students',
+ args=[course_id]))
stripped_fieldnames = [
field.strip().lower() for field in reader.fieldnames]
for field in required_fields:
if field not in stripped_fieldnames:
- context['message'] = "The CSV file does not contain the"\
- " required headers"
- return my_render_to_response(
- request, 'yaksh/course_detail.html', context
- )
+ msg = "The CSV file does not contain the required headers"
+ messages.warning(request, msg)
+ return my_redirect(reverse('yaksh:course_students',
+ args=[course_id]))
reader.fieldnames = stripped_fieldnames
- context['upload_details'] = _read_user_csv(reader, course)
- return my_render_to_response(request, 'yaksh/course_detail.html', context)
+ _read_user_csv(request, reader, course)
+ return my_redirect(reverse('yaksh:course_students', args=[course_id]))
-def _read_user_csv(reader, course):
+def _read_user_csv(request, reader, course):
fields = reader.fieldnames
- upload_details = ["Upload Summary:"]
counter = 0
for row in reader:
counter += 1
(username, email, first_name, last_name, password, roll_no, institute,
department, remove) = _get_csv_values(row, fields)
if not email or not first_name or not last_name:
- upload_details.append("{0} -- Missing Values".format(counter))
+ messages.info(request, "{0} -- Missing Values".format(counter))
continue
users = User.objects.filter(username=username)
if users.exists():
user = users[0]
if remove.strip().lower() == 'true':
_remove_from_course(user, course)
- upload_details.append("{0} -- {1} -- User rejected".format(
- counter, user.username))
+ messages.info(request, "{0} -- {1} -- User rejected".format(
+ counter, user.username))
else:
_add_to_course(user, course)
- upload_details.append(
+ messages.info(request,
"{0} -- {1} -- User Added Successfully".format(
counter, user.username))
continue
@@ -2309,11 +2332,10 @@ def _read_user_csv(reader, course):
course.students.add(user)
else:
state = "Updated"
- upload_details.append("{0} -- {1} -- User {2} Successfully".format(
- counter, user.username, state))
+ messages.info(request, "{0} -- {1} -- User {2} Successfully".format(
+ counter, user.username, state))
if counter == 0:
- upload_details.append("No rows in the CSV file")
- return upload_details
+ messages.warning(request, "No rows in the CSV file")
def _get_csv_values(row, fields):
@@ -2395,15 +2417,21 @@ def duplicate_course(request, course_id):
if course.is_teacher(user) or course.is_creator(user):
# Create new entries of modules, lessons/quizzes
# from current course to copied course
- course.create_duplicate_course(user)
+ duplicate_course = course.create_duplicate_course(user)
+ msg = dedent(
+ '''\
+ Course duplication successful with the name {0} , please check
+ the courses page.'''.format(duplicate_course.name)
+ )
+ messages.success(request, msg)
else:
msg = dedent(
'''\
You do not have permissions to clone {0} course, please contact
your instructor/administrator.'''.format(course.name)
)
- return complete(request, msg, attempt_num=None, questionpaper_id=None)
- return my_redirect('/exam/manage/courses/')
+ messages.warning(request, msg)
+ return my_redirect(reverse('yaksh:course_detail', args=[course_id]))
@login_required
@@ -2440,9 +2468,9 @@ def edit_lesson(request, lesson_id=None, course_id=None):
course = get_object_or_404(Course, id=course_id)
if not course.is_creator(user) and not course.is_teacher(user):
raise Http404('This Lesson does not belong to you')
- redirect_url = "/exam/manage/courses/"
+ redirect_url = reverse("yaksh:get_course_modules", args=[course_id])
else:
- redirect_url = "/exam/manage/courses/all_lessons/"
+ redirect_url = reverse("yaksh:show_all_lessons")
context = {}
if request.method == "POST":
if "Save" in request.POST:
@@ -2467,7 +2495,9 @@ def edit_lesson(request, lesson_id=None, course_id=None):
LessonFile.objects.get_or_create(
lesson=lesson, file=les_file
)
- return my_redirect(redirect_url)
+ messages.success(
+ request, "Saved {0} successfully".format(lesson.name)
+ )
else:
context['lesson_form'] = lesson_form
context['error'] = lesson_form["video_file"].errors
@@ -2479,7 +2509,13 @@ def edit_lesson(request, lesson_id=None, course_id=None):
files = LessonFile.objects.filter(id__in=remove_files_id)
for file in files:
file.remove()
- return my_redirect(redirect_url)
+ messages.success(
+ request, "Deleted files successfully"
+ )
+ else:
+ messages.warning(
+ request, "Please select atleast one file to delete"
+ )
lesson_files = LessonFile.objects.filter(lesson=lesson)
lesson_files_form = LessonFileForm()
@@ -2553,9 +2589,10 @@ def design_module(request, module_id, course_id=None):
learning_module = LearningModule.objects.get(id=module_id)
if request.method == "POST":
if "Add" in request.POST:
- add_values = request.POST.get("chosen_list").split(',')
+ add_values = request.POST.get("chosen_list")
to_add_list = []
if add_values:
+ add_values = add_values.split(',')
ordered_units = learning_module.get_learning_units()
if ordered_units.exists():
start_val = ordered_units.last().order + 1
@@ -2573,29 +2610,56 @@ def design_module(request, module_id, course_id=None):
type=type)
to_add_list.append(learning_unit)
learning_module.learning_unit.add(*to_add_list)
+ messages.success(request, "Lesson/Quiz added successfully")
+ else:
+ messages.warning(request, "Please select a lesson/quiz to add")
if "Change" in request.POST:
- order_list = request.POST.get("ordered_list").split(",")
- for order in order_list:
- learning_unit, learning_order = order.split(":")
- if learning_order:
- learning_unit = learning_module.learning_unit.get(
- id=learning_unit)
- learning_unit.order = learning_order
- learning_unit.save()
+ order_list = request.POST.get("ordered_list")
+ print(order_list)
+ if order_list:
+ order_list = order_list.split(",")
+ for order in order_list:
+ learning_unit, learning_order = order.split(":")
+ if learning_order:
+ learning_unit = learning_module.learning_unit.get(
+ id=learning_unit)
+ learning_unit.order = learning_order
+ learning_unit.save()
+ messages.success(request, "Order changed successfully")
+ else:
+ messages.warning(
+ request, "Please select a lesson/quiz to change"
+ )
if "Remove" in request.POST:
remove_values = request.POST.getlist("delete_list")
if remove_values:
learning_module.learning_unit.remove(*remove_values)
LearningUnit.objects.filter(id__in=remove_values).delete()
+ messages.success(
+ request, "Lessons/quizzes deleted successfully"
+ )
+ else:
+ messages.warning(
+ request, "Please select a lesson/quiz to remove"
+ )
if "Change_prerequisite" in request.POST:
unit_list = request.POST.getlist("check_prereq")
- for unit in unit_list:
- learning_unit = learning_module.learning_unit.get(id=unit)
- learning_unit.toggle_check_prerequisite()
- learning_unit.save()
+ if unit_list:
+ for unit in unit_list:
+ learning_unit = learning_module.learning_unit.get(id=unit)
+ learning_unit.toggle_check_prerequisite()
+ learning_unit.save()
+ messages.success(
+ request, "Changed prerequisite status successfully"
+ )
+ else:
+ messages.warning(
+ request,
+ "Please select a lesson/quiz to change prerequisite"
+ )
added_quiz_lesson = learning_module.get_added_quiz_lesson()
quizzes = [("quiz", quiz) for quiz in Quiz.objects.filter(
@@ -2617,12 +2681,12 @@ def add_module(request, module_id=None, course_id=None):
user = request.user
if not is_moderator(user):
raise Http404('You are not allowed to view this page!')
- redirect_url = "/exam/manage/courses/all_learning_module/"
+ redirect_url = reverse("yaksh:show_all_modules")
if course_id:
course = Course.objects.get(id=course_id)
if not course.is_creator(user) and not course.is_teacher(user):
raise Http404('This course does not belong to you')
- redirect_url = "/exam/manage/courses/"
+ redirect_url = reverse("yaksh:get_course_modules", args=[course_id])
if module_id:
module = LearningModule.objects.get(id=module_id)
if not module.creator == user and not course_id:
@@ -2639,7 +2703,10 @@ def add_module(request, module_id=None, course_id=None):
module = module_form.save()
module.html_data = get_html_text(module.description)
module.save()
- return my_redirect(redirect_url)
+ messages.success(
+ request,
+ "Saved {0} successfully".format(module.name)
+ )
else:
context['module_form'] = module_form
@@ -2657,8 +2724,8 @@ def show_all_quizzes(request):
if not is_moderator(user):
raise Http404('You are not allowed to view this page!')
quizzes = Quiz.objects.filter(creator=user, is_trial=False)
- context = {"quizzes": quizzes, "type": "quiz"}
- return my_render_to_response(request, 'yaksh/courses.html', context)
+ context = {"quizzes": quizzes}
+ return my_render_to_response(request, 'yaksh/quizzes.html', context)
@login_required
@@ -2668,8 +2735,8 @@ def show_all_lessons(request):
if not is_moderator(user):
raise Http404('You are not allowed to view this page!')
lessons = Lesson.objects.filter(creator=user)
- context = {"lessons": lessons, "type": "lesson"}
- return my_render_to_response(request, 'yaksh/courses.html', context)
+ context = {"lessons": lessons}
+ return my_render_to_response(request, 'yaksh/lessons.html', context)
@login_required
@@ -2680,8 +2747,10 @@ def show_all_modules(request):
raise Http404('You are not allowed to view this page!')
learning_modules = LearningModule.objects.filter(
creator=user, is_trial=False)
- context = {"learning_modules": learning_modules, "type": "learning_module"}
- return my_render_to_response(request, 'yaksh/courses.html', context)
+ context = {"modules": learning_modules}
+ return my_render_to_response(
+ request, 'yaksh/modules.html', context
+ )
@login_required
@@ -2704,7 +2773,7 @@ def get_next_unit(request, course_id, module_id, current_unit_id=None,
user = request.user
course = Course.objects.prefetch_related("learning_module").get(
id=course_id)
- if user not in course.students.all():
+ if not course.students.filter(id=user.id).exists():
raise Http404('You are not enrolled for this course!')
learning_module = course.learning_module.prefetch_related(
"learning_unit").get(id=module_id)
@@ -2812,9 +2881,10 @@ def design_course(request, course_id):
learning_modules = set(all_learning_modules) - set(added_learning_modules)
context['added_learning_modules'] = added_learning_modules
context['learning_modules'] = learning_modules
- context['course_id'] = course_id
+ context['course'] = course
+ context['is_design_course'] = True
return my_render_to_response(
- request, 'yaksh/design_course_session.html', context
+ request, 'yaksh/course_detail.html', context
)
@@ -2898,13 +2968,26 @@ def course_status(request, course_id):
course = get_object_or_404(Course, pk=course_id)
if not course.is_creator(user) and not course.is_teacher(user):
raise Http404('This course does not belong to you')
- students = course.get_only_students()
+ students = course.students.order_by("-id")
+ students_no = students.count()
+ paginator = Paginator(students, 100)
+ page = request.GET.get('page')
+ try:
+ students = paginator.page(page)
+ except PageNotAnInteger:
+ # If page is not an integer, deliver first page.
+ students = paginator.page(1)
+ except EmptyPage:
+ # If page is out of range (e.g. 9999), deliver last page of results.
+ students = paginator.page(paginator.num_pages)
+
stud_details = [(student, course.get_grade(student),
course.get_completion_percent(student),
- course.get_current_unit(student)) for student in students]
+ course.get_current_unit(student))
+ for student in students.object_list]
context = {
- 'course': course, 'student_details': stud_details,
- 'state': 'course_status'
+ 'course': course, 'objects': students, 'is_progress': True,
+ 'student_details': stud_details, 'students_no': students_no
}
return my_render_to_response(request, 'yaksh/course_detail.html', context)
@@ -2991,6 +3074,8 @@ def get_user_data(request, course_id, student_id):
@email_verified
def download_course(request, course_id):
user = request.user
+ if not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
course = get_object_or_404(Course, pk=course_id)
if (not course.is_creator(user) and not course.is_teacher(user) and not
course.is_student(user)):
@@ -3017,3 +3102,51 @@ def download_course(request, course_id):
)
response.write(zip_file.read())
return response
+
+
+@login_required
+@email_verified
+def course_students(request, course_id):
+ user = request.user
+ if not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+ course = get_object_or_404(Course, pk=course_id)
+ if not course.is_creator(user) and not course.is_teacher(user):
+ raise Http404("You are not allowed to view {0}".format(
+ course.name))
+ enrolled = course.get_enrolled()
+ requested = course.get_requests()
+ rejected = course.get_rejected()
+ context = {"enrolled": enrolled, "requested": requested, "course": course,
+ "rejected": rejected, "is_students": True}
+ return my_render_to_response(request, 'yaksh/course_detail.html', context)
+
+
+@login_required
+@email_verified
+def course_teachers(request, course_id):
+ user = request.user
+ if not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+ course = get_object_or_404(Course, pk=course_id)
+ if not course.is_creator(user) and not course.is_teacher(user):
+ raise Http404("You are not allowed to view {0}".format(
+ course.name))
+ teachers = course.get_teachers()
+ context = {"teachers": teachers, "is_teachers": True, "course": course}
+ return my_render_to_response(request, 'yaksh/course_detail.html', context)
+
+
+@login_required
+@email_verified
+def get_course_modules(request, course_id):
+ user = request.user
+ if not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+ course = get_object_or_404(Course, pk=course_id)
+ if not course.is_creator(user) and not course.is_teacher(user):
+ raise Http404("You are not allowed to view {0}".format(
+ course.name))
+ modules = course.get_learning_modules()
+ context = {"modules": modules, "is_modules": True, "course": course}
+ return my_render_to_response(request, 'yaksh/course_detail.html', context)