From 1c0927ca1c02b8ced3ab0f3f29ff4c34faa9af04 Mon Sep 17 00:00:00 2001 From: tkupek Date: Sun, 21 Feb 2016 22:41:24 +0100 Subject: [PATCH] styled site with bootstrap, did some minor ui improvements and fixes --- db.sqlite3 | Bin 99328 -> 106496 bytes tkupek_elearning/elearning/admin.py | 2 +- .../migrations/0018_auto_20160221_1705.py | 26 ++++++ .../migrations/0019_auto_20160221_1754.py | 30 +++++++ .../migrations/0020_setting_text_next.py | 20 +++++ tkupek_elearning/elearning/models.py | 21 +++-- .../elearning/static/css/style.css | 12 +-- .../elearning/static/js/elearning.js | 85 +++++++++++++----- .../elearning/templates/access_denied.html | 8 ++ .../elearning/templates/elearning.html | 39 ++++++-- .../elearning/templates/statistic.html | 17 +++- tkupek_elearning/elearning/views.py | 25 ++++-- 12 files changed, 233 insertions(+), 52 deletions(-) create mode 100644 tkupek_elearning/elearning/migrations/0018_auto_20160221_1705.py create mode 100644 tkupek_elearning/elearning/migrations/0019_auto_20160221_1754.py create mode 100644 tkupek_elearning/elearning/migrations/0020_setting_text_next.py diff --git a/db.sqlite3 b/db.sqlite3 index b4ff74396c219c82d33ced4d1889cc944af1af60..0cb670df613a1dbcd1acf957f0f39dd1362abb08 100644 GIT binary patch delta 5778 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 delta 2023 zcmYjReNa@_6~E`5_t2zn_ z-Tj^4@0@$@@0_TlQ4)v8b&JS5PCr-W(9M}cNc zo*EujooV=4%BD6l_sOEYWG>MkVDhi85A8+ z<0saGl~uW)=PT1kYfs>FwN2XQ&|y6q(MmPF;oBAlJ391OOzYGmVZAf=e_?GP+CLcX z)H}8I!&-MdK2YuP#CsD1dT*JYXqdYiOGLUtEqZh?5z~fK&5nfn^kZ5g(y8qUA2`t4 z-`8i9XTiHOnj%|(&c&pq(jDw07ap2VWOSLb0s(lbR*aloE;h_K#V7NsQ8@+nrp6EBwB|qEGl0!><_RMuowf|E@86`Uk$2$CmnjYz75vkYhPV+vhH zIUgHAynag)_x@OrP7RXb4wIfmGtR*sQv4c(apgr(Z(J2`|NMzHHAxcAG5QObBX$;( zbAJwcH9HG3yh$%jo%C<%ed!fx6WoRYC}nrq%dD3L&jeSSitGw&RzbY|uQhp!%cd|N zhb>`UYY7hw=#d}Hz1JP3o+&NXG&Z_c1>?1GXy9_Qg{bcwI+E9U}hzLb#a9jYa`=nBZJod9vOV07_7~@u7g{;8Vf%>8t%M@3Zq6hU z2^JT?Ms8|w63im4c@pZl>G`DueFXPT!Y*!#EFsuR;-iJoWlh`fAo#Qj^`R2umwAwB zY&0Oq(}EckCd-W96hO6__H??!j#JL}b0Eve*bQqyx#WTpXKLtdtcKwYJc`?;Z=|I3 zqTxITUQFF)+d0_4?cqWyMLjfp&Ct$mJp}|?s20IoOBuTEY|W|g>|XW;nu{(3+t?wdX4C%Dzv*b zPqxC^D7_&7Zf@SXnn-G);b@_&X9S>FHCL@tSd8=^yb0xC zo;fGWvvLD0AhcX+0@vhQFeNX#8#w}Xs>AJ9Sn4*9-lAb~RQV{E%B{Kp<#xv&FI6w) zutN_=N{qH)^6qEDu%2h^@uUdSUAaKr&nPHUSR)}A290NQmlC;?APqyM@n#>Gjk6IV z(!(W0q>Ln@-ICr@Opvy&4;dGK0{KSi6l~(@d)HCaLkEgYL9=SFb}KAFDUJQG9_&{S lfNZ7CPBZC4xB;(06Z@J?3x_-@HM@*&hG5(5KZn3-`46mH4DbK| diff --git a/tkupek_elearning/elearning/admin.py b/tkupek_elearning/elearning/admin.py index 8e41476..996a8b3 100644 --- a/tkupek_elearning/elearning/admin.py +++ b/tkupek_elearning/elearning/admin.py @@ -24,4 +24,4 @@ class UserAdmin(admin.ModelAdmin): admin.site.register(Question, QuestionAdmin) admin.site.register(Setting), -admin.site.register(User, UserAdmin) \ No newline at end of file +admin.site.register(User, UserAdmin) diff --git a/tkupek_elearning/elearning/migrations/0018_auto_20160221_1705.py b/tkupek_elearning/elearning/migrations/0018_auto_20160221_1705.py new file mode 100644 index 0000000..b1ab113 --- /dev/null +++ b/tkupek_elearning/elearning/migrations/0018_auto_20160221_1705.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-21 17:05 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('elearning', '0017_auto_20160214_1534'), + ] + + operations = [ + migrations.AddField( + model_name='useranswer', + name='correct', + field=models.NullBooleanField(), + ), + migrations.AlterField( + model_name='setting', + name='logo', + field=models.CharField(default='test', max_length=256), + preserve_default=False, + ), + ] diff --git a/tkupek_elearning/elearning/migrations/0019_auto_20160221_1754.py b/tkupek_elearning/elearning/migrations/0019_auto_20160221_1754.py new file mode 100644 index 0000000..10d8186 --- /dev/null +++ b/tkupek_elearning/elearning/migrations/0019_auto_20160221_1754.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-21 17:54 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('elearning', '0018_auto_20160221_1705'), + ] + + operations = [ + migrations.RenameField( + model_name='setting', + old_name='button_solution', + new_name='text_solution', + ), + migrations.AddField( + model_name='setting', + name='text_answer', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='option', + name='text', + field=models.CharField(max_length=256, null=True), + ), + ] diff --git a/tkupek_elearning/elearning/migrations/0020_setting_text_next.py b/tkupek_elearning/elearning/migrations/0020_setting_text_next.py new file mode 100644 index 0000000..666591e --- /dev/null +++ b/tkupek_elearning/elearning/migrations/0020_setting_text_next.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-02-21 20:50 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('elearning', '0019_auto_20160221_1754'), + ] + + operations = [ + migrations.AddField( + model_name='setting', + name='text_next', + field=models.CharField(max_length=100, null=True), + ), + ] diff --git a/tkupek_elearning/elearning/models.py b/tkupek_elearning/elearning/models.py index cca2f4f..4cc50b1 100644 --- a/tkupek_elearning/elearning/models.py +++ b/tkupek_elearning/elearning/models.py @@ -12,11 +12,13 @@ class Setting(models.Model): message_welcome_user = models.TextField(null=True) message_access_denied = models.TextField(null=True) message_already_answered = models.TextField(null=True) - button_solution = models.CharField(max_length=100, null=True) + text_answer = models.CharField(max_length=100, null=True) + text_solution = models.CharField(max_length=100, null=True) + text_next = models.CharField(max_length=100, null=True) logo = models.CharField(max_length=256, null=False) active = models.BooleanField(unique=True, default=False) - def __str__(self): + def __unicode__(self): return self.title @@ -26,16 +28,16 @@ class Question(models.Model): text = models.TextField(null=True) explanation = models.TextField(null=True) - def __str__(self): + def __unicode__(self): return self.title class Option(models.Model): - text = models.CharField(max_length=100, null=True) + text = models.CharField(max_length=256, null=True) correct = models.BooleanField(null=False, default=False) question = models.ForeignKey(Question, on_delete=models.CASCADE, null=False) - def __str__(self): + def __unicode__(self): return self.text @@ -49,7 +51,7 @@ class User(models.Model): name = models.CharField(max_length=100, null=False) last_seen = models.DateTimeField(null=True) - def __str__(self): + def __unicode__(self): return self.name @@ -58,8 +60,8 @@ class UserAnswer(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE, null=False) correct = models.NullBooleanField(null=True) - def __str__(self): - return str(self.user) + " - " + str(self.question) + def __unicode__(self): + return str(self.user) + " - " + str(self.question.id) class Meta: unique_together = (('user', 'question'),) @@ -71,3 +73,6 @@ class UserAnswerOptions(models.Model): class Meta: unique_together = (('user_answer', 'option'),) + + def __unicode__(self): + return str(self.user_answer) + " - " + str(self.option) diff --git a/tkupek_elearning/elearning/static/css/style.css b/tkupek_elearning/elearning/static/css/style.css index 538b0f9..a0df864 100644 --- a/tkupek_elearning/elearning/static/css/style.css +++ b/tkupek_elearning/elearning/static/css/style.css @@ -34,12 +34,8 @@ p[id^="explanation_"] { margin-top: 50px; } -.correct { - outline: 4px solid #00a353; -} - -.failed { - outline: 4px solid #a60000; +.margin75 { + margin-top: 75px; } .mainLogo { @@ -54,4 +50,8 @@ p[id^="explanation_"] { .table_headline { font-weight: bold; +} + +.footer { + color: #b3b3b3 } \ No newline at end of file diff --git a/tkupek_elearning/elearning/static/js/elearning.js b/tkupek_elearning/elearning/static/js/elearning.js index 02c9ad1..1d92732 100644 --- a/tkupek_elearning/elearning/static/js/elearning.js +++ b/tkupek_elearning/elearning/static/js/elearning.js @@ -59,8 +59,8 @@ function toggle_solution(id) function show_solution(id) { var element = document.getElementById("explanation_" + id); - if (element.className == "hide") { - element.className = "show"; + if (element.className.indexOf("hide") > -1) { + element.className = element.className.replace("hide", "show"); } } @@ -76,9 +76,10 @@ function get_answer(id) { if (answerRequest.readyState==4){ if (answerRequest.status==200 || window.location.href.indexOf("http")==-1){ parseResponse(id, answerRequest.responseText); + setButtonToNext(id); } else{ - alert("An error has occured making the request"); + alert("Sorry, sending your answer was not successful!"); } } } @@ -91,6 +92,35 @@ function get_answer(id) { answerRequest.send(null) } +function setButtonToNext(id) { + button = document.getElementById('showSolution_' + id); + button.className = button.className.replace("show", "hide"); + + if(getNextQuestion(id)) { + button = document.getElementById('next_' + id); + button.className = button.className.replace("hide", "show"); + } +} + +function scrollToNextQuestion(id) { + var nextQuestion = getNextQuestion(id); + + if(nextQuestion) { + location.href = "#" + nextQuestion.id; + } +} + +function getNextQuestion(id) { + var questions = document.getElementsByName("question"); + + for(var i = 0; i < questions.length; i++) { + if(questions[i].id == "question_" + id) { + return questions[i+1]; + } + } + return null; +} + function getCheckboxAnswers(id) { var answers = []; @@ -107,32 +137,45 @@ function getCheckboxAnswers(id) { function parseResponse(id, responseText) { - var correctOptions = JSON.parse(responseText); + var correctOptions = JSON.parse(responseText).options_id; + var progress = JSON.parse(responseText).progress; + setCorrectOptions(correctOptions, id) + setProgress(progress) +} + +function setCorrectOptions(correctOptions, id) { var elements = document.getElementsByName("checkbox_" + id); + var holders = document.getElementsByName("checkbox_div_" + id); - for(var i = 0; i < elements.length; i++) { - var element = elements[i]; - element.className=""; + for(var i = 0; i < elements.length; i++) { + var element = elements[i]; + var holder = holders[i]; - var correct = isCorrectOption(element.value); - if(correct) { - element.className="correct"; - } else { - if(element.checked) { - element.className="failed"; + var correct = isCorrectOption(element.value); + if(correct) { + holder.className = holder.className + " list-group-item-success"; + } else { + if(element.checked) { + holder.className = holder.className + " list-group-item-danger";; + } } - } - } + element.disabled = true; + } - function isCorrectOption(option) { - for(var i = 0; i < correctOptions.length; i++) { - if(correctOptions[i] == option) { - return true; + function isCorrectOption(option) { + for(var i = 0; i < correctOptions.length; i++) { + if(correctOptions[i] == option) { + return true; + } } + return false; } - return false; - } +} + +function setProgress(progress) { + progressbar = document.getElementById("progressbar"); + progressbar.style.width = progress + "%"; } function ajaxRequest() { diff --git a/tkupek_elearning/elearning/templates/access_denied.html b/tkupek_elearning/elearning/templates/access_denied.html index 9215ec8..a498d12 100644 --- a/tkupek_elearning/elearning/templates/access_denied.html +++ b/tkupek_elearning/elearning/templates/access_denied.html @@ -7,7 +7,15 @@ {% load staticfiles %} + + {{ settings.title }} + + + + + + diff --git a/tkupek_elearning/elearning/templates/elearning.html b/tkupek_elearning/elearning/templates/elearning.html index 09d3053..287e40e 100644 --- a/tkupek_elearning/elearning/templates/elearning.html +++ b/tkupek_elearning/elearning/templates/elearning.html @@ -7,19 +7,33 @@ {% load staticfiles %} + + {{ settings.title }} + + + + + +
+

{{ settings.title }}

{{ settings.message_welcome_user }}

+
+
+
+

{% for question, options in questions_options.items %} +

{{ question.id }}: {{ question.title }}

{{ question.text }}

@@ -27,19 +41,28 @@ {{ settings.message_already_answered }}

-
- {% for option in options %} - +
    + {% for option in options %} +
  • - {% endfor %} - -
  • + + {% endfor %} +
-

{{ question.explanation }}

-
+
+ + +
+ +
+

{{ settings.text_answer }}

+

{{ question.explanation }}

+
+
+
{% endfor %}
diff --git a/tkupek_elearning/elearning/templates/statistic.html b/tkupek_elearning/elearning/templates/statistic.html index 4efa1f9..0f884ae 100644 --- a/tkupek_elearning/elearning/templates/statistic.html +++ b/tkupek_elearning/elearning/templates/statistic.html @@ -7,7 +7,15 @@ {% load staticfiles %} + + {{ settings.title }} + + + + + + @@ -20,7 +28,7 @@

Users

- +
@@ -38,7 +46,7 @@

Questions

-
name questions answered
+
@@ -57,7 +65,10 @@

- {{ settings.footer }} + + diff --git a/tkupek_elearning/elearning/views.py b/tkupek_elearning/elearning/views.py index ce5580b..44a232f 100644 --- a/tkupek_elearning/elearning/views.py +++ b/tkupek_elearning/elearning/views.py @@ -1,8 +1,9 @@ -import datetime -import json +from __future__ import division from django.core.exceptions import ObjectDoesNotExist from django.http import HttpResponse from django.shortcuts import render_to_response +import datetime +import json from tkupek_elearning.elearning.models import Setting, Question, Option, UserAnswer, User, UserAnswerOptions @@ -10,6 +11,13 @@ from tkupek_elearning.elearning.models import Setting, Question, Option, UserAns import pdb +def get_progress(user): + progress_max = Question.objects.all().count() + progress_current = UserAnswer.objects.filter(user=user.id).count() + progress = str(int(progress_current / progress_max * 100)) + return progress + + def start(request): token = request.GET.get('token') @@ -42,7 +50,9 @@ def start(request): questions_options[question] = options questions_options[question] = options - return render_to_response('elearning.html', {'settings': settings, 'questions_options': questions_options}) + progress = get_progress(user) + + return render_to_response('elearning.html', {'settings': settings, 'questions_options': questions_options, 'progress': progress}) else: return render_to_response('access_denied.html', {'settings': settings}) @@ -95,7 +105,10 @@ def get_answer(request): user_answer_options.option = Option.objects.get(id=option) user_answer_options.save() - return HttpResponse(options_id) + holder = {'options_id': options_id, 'progress': get_progress(user)} + holder = json.dumps(holder) + + return HttpResponse(holder) def get_user_answer(question, user): @@ -124,6 +137,8 @@ def statistic(request): for question in questions: question.answers = UserAnswer.objects.filter(question=question.id).count() question.correct_answers = UserAnswer.objects.filter(question=question.id, correct=True).count() - question.correct_answers_percentage = question.correct_answers / question.answers + if question.answers: + question.correct_answers_percentage = str(int(question.correct_answers / question.answers * 100)) + question.correct_answers_percentage += str(' %') return render_to_response('statistic.html', {'settings': settings, 'users': users, 'questions': questions})
title answers