diff --git a/media/images/loading.gif b/media/images/loading.gif new file mode 100644 index 00000000..7eca54a3 Binary files /dev/null and b/media/images/loading.gif differ diff --git a/media/images/ui-icons_ffffff_256x240.png b/media/images/ui-icons_ffffff_256x240.png new file mode 100644 index 00000000..42f8f992 Binary files /dev/null and b/media/images/ui-icons_ffffff_256x240.png differ diff --git a/media/styles/style.css b/media/styles/style.css index 262a37e4..68286808 100755 --- a/media/styles/style.css +++ b/media/styles/style.css @@ -2,10 +2,57 @@ /* @group Global */ -/* @group Page Structure */ +/* @group Browser reset */ + +h1, h2, h3, h4, h5, h6 { + margin-bottom: 10px; +} + +h1{ + font-size: 20px; + margin-bottom: 20px; +} +h2{ + font-size: 16px; + margin-bottom: 16px; +} + +#help_icon { + float: right; +} +h3{ + font-size: 12px; +} + +p, ol, pre, input{ + margin-bottom: 10px; +} + +pre{ + left: -14px; + padding-left: 20px; +} + +ul li{ + list-style-type: disc; +} + +ol li{ + list-style-type: decimal; +} + +li { + padding-left: 20px; + margin-bottom: 10px; + list-style-position: inside; +} + +/* @end */ + +/* @group Page structure */ body { - background: #FFFFFF none repeat scroll 0 0; + background: #fff none repeat scroll 0 0; color: #333333; font-family: "Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif; font-size: 12px; @@ -17,7 +64,6 @@ body { position: relative; width: 100%; min-width: 760px; - padding: 0; } #content { @@ -25,8 +71,7 @@ body { margin-right: auto; margin-left: auto; margin-bottom: 10px; - padding-right: 20px; - padding-bottom: 20px; + padding: 20px; } #footer { @@ -45,44 +90,62 @@ body { width: 100%; } -#header a:link, #header a:visited { - color: white; +#sub_header { + background: #005094; + overflow: hidden; + width: 100%; + color: #eaeaea; + font-size: 11px; + padding-top: 3px; + padding-bottom: 4px; } -#header a:hover { - text-decoration: underline; +.inner { + width: 800px; + margin-right: auto; + margin-left: auto; + padding-left: 20px; + padding-right: 20px; } #title h1 { - padding: 0 10px; + font-size: 18px; - margin: 8px 0; font-weight: normal; color: white; + float: left; + margin-top: 8px; + margin-bottom: 8px; } -#title h2 { - padding: 0 10px; - font-size: 14px; - margin: -8px 0 8px 0; - font-weight: normal; - color: #ffc; +#user-tools { + float: right; + margin-top: 12px; } -#user-tools { - position: absolute; - top: 0; - right: 0; - padding: 1.2em 10px; - font-size: 11px; - text-align: right; +#header a:link, #header a:visited{ + color: white; + text-decoration: none; +} + +#sub_header a:link, #sub_header a:visited, #sub_header a{ + color: #eaeaea; + text-decoration: none; +} + +#sub_header a:hover{ + text-decoration: underline; +} + +#header a:hover{ + text-decoration: underline; } /* @end */ /* @group Forms */ -th { +form th { text-align: right; vertical-align: top; } @@ -96,6 +159,14 @@ label { font-size: 10pt; font-family: sans-serif; vertical-align: top; + float: left; + width: 8em; + display: block; +} + +form .help{ + margin-left: 9em; + color: #999999; } .errorlist { @@ -139,6 +210,11 @@ label { background-image: url(../images/ui-icons_c31818_256x240.png); } +.icon-white { + background-image: url(../images/ui-icons_ffffff_256x240.png); +} + + .icon-none { background-image: none !important; } @@ -160,20 +236,90 @@ label { /* @group Task */ +/* @group Task Detail */ + +#task_detail #submission_date { + float: right; +} + +/* @end */ + /* @group Task List */ -div.left { +#task_list div.left { + float: left; + width: 48%; + padding-right: 2%; +} + +#task_list div.right { + float: right; + width: 48%; + padding-left: 2%; +} + + + +/* @end */ + + + +/* @end */ + +/* @group Solution */ + +/* @group Solution Detail */ + +#solution_detail #commit_text { + display: inline; +} + +#solution_detail form { + display: inline; +} + + + +/* @end */ + +/* @group Solution Upload */ + +#soluion_upload div.left { float: left; width: 48%; padding-right: 2%; } -div.right { +#soluion_upload div.right { float: right; width: 48%; padding-left: 2%; } +#soluion_upload div.left a { + float: right; +} + +#soluion_upload .simple_overlay { + /* must be initially hidden */ + display:none; + + /* styling */ + color:#fff; + width: 30%; + min-height:200px; + padding:35px; + font-size: 20px; +} + +#soluion_upload img#spinner { + display: inline; + float: left; + position: relative; + top: 4px; + margin-right: 10px; +} + /* @end */ @@ -186,73 +332,77 @@ div.right { /* @group Attestation Edit */ -.activeFile { +#attestation_edit .activeFile { font-weight: bold; } -.ui-tabs .ui-tabs-hide, .hidden { - - +#attestation_edit .ui-tabs .ui-tabs-hide, .hidden { /* override display:none of hidden tab to instantiate bespin see http://jqueryui.com/demos/tabs/ */ position: absolute; left: -10000px; } -h3.result { +#attestation_edit h3.result { text-decoration: none; } -div.result span.icon { +#attestation_edit div.result span.icon { float: left; margin-right: .3em; width: 16px; height: 16px; } -.bespin { +#attestation_edit .bespin { margin: 0; margin-top: 10px; padding: 0; border: 0; height: 500px; - border: 10px - solid #ddd; + border: 10px solid #ddd; -moz-border-radius: 10px; -webkit-border-radius: 10px; } - - /* @end */ /* @group Attestation List */ -#comment { +#attestation_list #comment { color: #c0c0c0; width: 80%; float: right; } -div.attestation { +#attestation_list div.attestation { position: relative; left: 20px; } -#Solutions form { +#attestation_list #Solutions form { margin-top: 40px; } +#soluion_upload div.attestation { + margin-left: 15px; +} + /* @end */ /* @group Attestation View */ -div.changed { +#attestation_view div.changed { background-color: #c4ff6f; } +#attestation_view form .help { + display: inline; + margin-left: 60px; +} + /* @end */ diff --git a/src/praktomat/attestation/views.py b/src/praktomat/attestation/views.py index 3d49759a..967109ad 100755 --- a/src/praktomat/attestation/views.py +++ b/src/praktomat/attestation/views.py @@ -29,12 +29,15 @@ def attestation_list(request, task_id): # don't allow a new attestation if one already exists solution_list = map(lambda solution:(solution, not solution.attestations_by(requestuser)), solutions) # first published => all published - published = solutions[0].attestations_by(requestuser)[0].published - all_solutions_attested = not reduce(lambda x,y: x or y, [new_attest_possible for (solution, new_attest_possible) in solution_list]) + try: + published = solutions[0].attestations_by(requestuser)[0].published + except IndexError: + published = False + all_solutions_attested = not reduce(lambda x,y: x or y, [new_attest_possible for (solution, new_attest_possible) in solution_list], False) all_attestations_final = reduce(lambda x,y: x and y, map(lambda attestation: attestation.final , - sum([list(solution.attestations_by(requestuser)) for solution in solutions],[]))) - publishable = all_solutions_attested and all_attestations_final + sum([list(solution.attestations_by(requestuser)) for solution in solutions],[])), True) + publishable = all_solutions_attested and all_attestations_final and task.expired() if request.method == "POST" and publishable: for solution in solutions: for attestation in solution.attestations_by(requestuser): diff --git a/src/praktomat/checker/views.py b/src/praktomat/checker/views.py index 9a572db9..8b137891 100755 --- a/src/praktomat/checker/views.py +++ b/src/praktomat/checker/views.py @@ -1,16 +1 @@ -from django.contrib.auth.decorators import login_required -from django.http import HttpResponse, HttpResponseBadRequest -from django.views.decorators.cache import never_cache -from django.utils import simplejson -@login_required -@never_cache -def checker_progress(request): - """ Return JSON object with information about the progress of the checker run.""" - try: - checker_progress = request.session['checker_progress'] - except: - checker_progress = 0 - # return HttpResponseBadRequest('Server Error') - json = simplejson.dumps({'progress': checker_progress}) - return HttpResponse(json) diff --git a/src/praktomat/solutions/models.py b/src/praktomat/solutions/models.py index c2b42c2d..2c6660b4 100755 --- a/src/praktomat/solutions/models.py +++ b/src/praktomat/solutions/models.py @@ -35,11 +35,9 @@ def copySolutionFiles(self, toTempDir): for file in self.solutionfile_set.all(): file.copyTo(toTempDir) - def check(self, session, run_secret = 0): + def check(self, run_secret = 0): """Builds and tests this solution.""" - session['checker_progress'] = 0 - # Delete previous results if the checker have allready been run self.checkerresult_set.all().delete() # set up environment @@ -63,7 +61,7 @@ def check(self, session, run_secret = 0): os.makedirs(env.tmpdir(), TMP_DIR_MODE) os.chmod(env.tmpdir(), TMP_DIR_MODE) self.copySolutionFiles(env.tmpdir()) - self.run_checks(env, session, run_secret) + self.run_checks(env, run_secret) finally: # reset default temp dir location tempfile.tempdir = None @@ -76,7 +74,7 @@ def check(self, session, run_secret = 0): - def run_checks(self, env, session, run_all): # , task + def run_checks(self, env, run_all): # , task """ Check program. The case `Nothing submitted' is handled by the Saver. Also, this does not work when submitting archives, since at this point, archives are not unpacked yet, and hence, @@ -106,9 +104,6 @@ def run_checks(self, env, session, run_all): # , task task.dejagnusetup_set.all(), task.dejagnutester_set.all() ] - number_of_checkers_total = sum(map(lambda x:x.count(), checkersets)) - number_of_finished_checkers = 0 - for checkers in checkersets: for checker in checkers: @@ -145,11 +140,6 @@ def run_checks(self, env, session, run_all): # , task if result.passed: passed_checkers.append(checker) - - number_of_finished_checkers += 1 - session['checker_progress'] = int(100.0 * number_of_finished_checkers / number_of_checkers_total) - session.save() - self.save() def attestations_by(self, user): diff --git a/src/praktomat/solutions/views.py b/src/praktomat/solutions/views.py index 35751b54..95f8b567 100755 --- a/src/praktomat/solutions/views.py +++ b/src/praktomat/solutions/views.py @@ -1,4 +1,3 @@ -from datetime import datetime import zipfile import tempfile @@ -19,23 +18,16 @@ def solution_list(request, task_id): task = get_object_or_404(Task,pk=task_id) my_solutions = task.solution_set.filter(author = request.user) - submission_possible = task.submission_date > datetime.now() and not my_solutions.filter(final = True) + submission_possible = not task.expired() and not my_solutions.filter(final = True) if request.method == "POST": solution = Solution(task = task, author=request.user) formset = SolutionFormSet(request.POST, request.FILES, instance=solution) if formset.is_valid(): try: - request.session['checker_progress'] = 0 - request.session.save() solution.save() formset.save() - solution.check(request.session) - # the form's submit targets an iframe, this allaows webkit based browsers (and probably others) to make ajax calls while posting - # so we are returning an javascript which will redirect the parent window of the iframe - #import time - #time.sleep(600) - #return render_to_response("solutions/js_redirect.html", {"redirect_url": reverse('solution_detail', args=[solution.id])}, context_instance=RequestContext(request)) + solution.check() return HttpResponseRedirect(reverse('solution_detail', args=[solution.id])) except: solution.delete() # delete files diff --git a/src/praktomat/tasks/models.py b/src/praktomat/tasks/models.py index 6cdb58bf..bffb39e4 100755 --- a/src/praktomat/tasks/models.py +++ b/src/praktomat/tasks/models.py @@ -1,7 +1,7 @@ from django.db import models from django.db import transaction from django.core import serializers -from datetime import date, datetime +from datetime import date, datetime, timedelta import tempfile import zipfile @@ -23,9 +23,9 @@ def solutions(self,user): def checker(self): return self.AnonymityChecker_set.all() + self.LineCounter_set.all() - def expiered(self): + def expired(self): """docstring for expiered""" - return self.submission_date + datetime.timedelta(hour=1) > datetime.now() + return self.submission_date + timedelta(hours=1) < datetime.now() @classmethod def export_Tasks(cls, qureyset): diff --git a/src/praktomat/tasks/views.py b/src/praktomat/tasks/views.py index 84072157..60e73f12 100755 --- a/src/praktomat/tasks/views.py +++ b/src/praktomat/tasks/views.py @@ -23,7 +23,7 @@ def taskList(Request): return render_to_response('tasks/task_list.html',{'upcoming_tasks':upcoming_tasks, 'expired_tasks':expired_tasks, 'tutors':tutors}, context_instance=RequestContext(Request)) #return object_list(Request, Task.objects.all(), template_object_name='tasks') -#@login_required +@login_required def taskDetail(Request,task_id): my_solutions = Task.objects.get(pk=task_id).solution_set.filter(author = Request.user) return object_detail(Request, Task.objects.all(), task_id, extra_context={'solutions': my_solutions}, template_object_name='task') diff --git a/src/praktomat/templates/admin/tasks/task/model_solution.html b/src/praktomat/templates/admin/tasks/task/model_solution.html index 99d42379..139087aa 100755 --- a/src/praktomat/templates/admin/tasks/task/model_solution.html +++ b/src/praktomat/templates/admin/tasks/task/model_solution.html @@ -18,16 +18,20 @@ -
- | - - - | -
There are no solutions yet.
{%endfor%}