Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
280c26d
Initial commit for S08-Judging
Sarosim Oct 17, 2020
2d5539b
Add highest_score field to HPScoreCategory model
Sarosim Oct 18, 2020
5edd8ca
In order to used the updated model, Merge branch 'S08-adjust-model' o…
Sarosim Oct 18, 2020
6df7c73
Set up basic urls - views - template for Judging landing page
Sarosim Oct 18, 2020
fd26d6b
prepare context for judging landing page
Sarosim Oct 18, 2020
b33fce1
add min_score field, rename max_score and test both
Sarosim Oct 18, 2020
fde4081
Add score button for judges to the event they can judge
Sarosim Oct 18, 2020
6e0b069
Pulling from upstream to update my dev branch
Sarosim Oct 19, 2020
70a6d33
Add verifications to judging view
Sarosim Oct 19, 2020
27b6db5
Pulling 20-Oct
Sarosim Oct 20, 2020
7c7f0f9
Build the base for the template
Sarosim Oct 20, 2020
4e150fb
Add custom tag for creating score dropdowns
Sarosim Oct 21, 2020
b816e10
Add my notes to .gitignore to avoid littering the repo
Sarosim Oct 25, 2020
ebad685
Fix merge conflicts after pulling from upstream
Sarosim Oct 25, 2020
b1863b6
Fix merge conflicts, delete sqlite and create a new, migrate
Sarosim Oct 25, 2020
b6f3a23
Finalise page layout for scoring
Sarosim Oct 25, 2020
b666642
Handle score submssion and save to model
Sarosim Oct 25, 2020
972e718
Refactor code and finalise for PR
Sarosim Oct 25, 2020
e86250b
Pull changes from upstream and update
Sarosim Oct 26, 2020
43fe928
Pull the latest PRs from upsteram and fix merge conflicts
Sarosim Oct 26, 2020
b95be71
Pull upstream 28/10 and fix merge conflicts
Sarosim Oct 28, 2020
005fa9b
Fix PR change requests, migrations not made...
Sarosim Oct 28, 2020
2b31055
Delete commented out code
Sarosim Oct 28, 2020
0b8fc80
Solve the remaining two minor change requests for PR
Sarosim Oct 28, 2020
eb09710
Fix merge conflicts and migrations for PR
Sarosim Oct 29, 2020
c4a3ccf
Remove the admin from profiles.json and add accounts back to seed
Sarosim Oct 29, 2020
98206df
Add blank line between 3rd party and local modules
Sarosim Oct 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ settings.json
.gitpod.yml
venv/
.idea/
MYNOTES.md
MYNOTES.md
6 changes: 6 additions & 0 deletions hackathon/lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@
('published', 'Published'),
('deleted', 'Deleted'),
)

JUDGING_STATUS_CHOICES = (
('not_yet_started', "Hasn't started"),
('open', "Open"),
('closed', "Closed"),
)
26 changes: 26 additions & 0 deletions hackathon/migrations/0017_auto_20201025_1211.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generated by Django 3.1.1 on 2020-10-25 12:11

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('hackathon', '0016_merge_20201024_1240'),
]

operations = [
migrations.AlterField(
model_name='hackproject',
name='created_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='hackproject', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='hackprojectscore',
name='created_by',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackprojectscores', to=settings.AUTH_USER_MODEL),
),
]
21 changes: 21 additions & 0 deletions hackathon/migrations/0018_auto_20201025_1933.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 3.1.1 on 2020-10-25 19:33

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('hackathon', '0017_auto_20201025_1211'),
]

operations = [
migrations.AlterField(
model_name='hackprojectscore',
name='judge',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]
14 changes: 14 additions & 0 deletions hackathon/migrations/0021_merge_20201029_1407.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 3.1.1 on 2020-10-29 14:07

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('hackathon', '0020_merge_20201026_2056'),
('hackathon', '0018_auto_20201025_1933'),
]

operations = [
]
18 changes: 18 additions & 0 deletions hackathon/migrations/0022_hackathon_judging_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.1.1 on 2020-10-29 14:20

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('hackathon', '0021_merge_20201029_1407'),
]

operations = [
migrations.AddField(
model_name='hackathon',
name='judging_status',
field=models.CharField(choices=[('not_yet_started', "Hasn't started"), ('open', 'Open'), ('closed', 'Closed')], default='not_yet_started', max_length=16),
),
]
13 changes: 10 additions & 3 deletions hackathon/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from accounts.models import CustomUser as User
from accounts.models import Organisation
from .lists import STATUS_TYPES_CHOICES
from .lists import STATUS_TYPES_CHOICES, JUDGING_STATUS_CHOICES

# Optional fields are ony set to deal with object deletion issues.
# If this isn't a problem, they can all be changed to required fields.
Expand Down Expand Up @@ -55,6 +55,13 @@ class Hackathon(models.Model):
default='draft',
choices=STATUS_TYPES_CHOICES
)
judging_status = models.CharField(
max_length=16,
blank=False,
default='not_yet_started',
choices=JUDGING_STATUS_CHOICES
)


def __str__(self):
return self.display_name
Expand Down Expand Up @@ -161,8 +168,8 @@ class HackProjectScore(models.Model):
created_by = models.ForeignKey(User,
on_delete=models.CASCADE,
related_name="hackprojectscores")
# One Judge can give one score - One to One
judge = models.OneToOneField(User, on_delete=models.CASCADE)
# One Judge scores several scorecategories - One to Many
judge = models.ForeignKey(User, on_delete=models.CASCADE)
# One score is for one project, a project has numerous scores: One to Many
project = models.ForeignKey(HackProject,
on_delete=models.CASCADE,
Expand Down
20 changes: 20 additions & 0 deletions hackathon/static/hackathon/css/hackathon.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.hack-score-form {
width: 100%;
margin-right: 0px;
margin-left: 0px;
}

.hack-score-cat-name {
min-height: 60px;
margin-bottom: 0;
}

@media screen and (max-width: 720px) {
.hack-score-cat-name {
min-height: 30px;
}
/* .hack-score-cat-name, h5 {
font-size: 1rem;
} */

}
74 changes: 74 additions & 0 deletions hackathon/templates/hackathon/judging.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{% extends 'base.html' %}

{% load my_tags %}<!-- for the usage of custom get_range tag -->
{% load static %}
{% block css %}
<link rel="stylesheet" href="{% static 'hackathon/css/hackathon.css' %}" type="text/css">
{% endblock %}

{% block content %}
<div class="container text-center">
<section>
<h2>Judging Team {{ team }}</h2>
<div class="d-flex flex-wrap justify-content-around my-2 my-md-4">
<div>
<a href="{{ project.github_url }}" class="btn btn-outline-info mb-3 mb-md-0" target="_blank">View Project Repo</a>
</div>
<div>
<a href="{{ project.deployed_url }}" class="btn btn-outline-info mb-3 mb-md-0" target="_blank">View Deployed Site</a>
</div>
</div>
</section>

<section class="container">
<!-- judging form -->
<form class="hack-score-form tex-center" action="{% url 'hackathon:judging' hackathon.id team.id %}" method="post">
{% csrf_token %}
<div class=" row justify-content-around" >
{% for category in score_categories %}
<div class="col-12 col-md-6 mb-3 mb-md-4 p-0 p-md-2">
<div class="shadow p-3 bg-white rounded mx-3">
<div class="row">
<div class="col-32 order-12 col-md-3 order-md-1 mt-2 input-group">
<select required class="custom-select" name="score_{{ category.id }}">
<option selected disabled value="">Score</option>
<!-- using custom get_range tag -->
{% for i in category.max_score|get_range:category.min_score %}

<option value="{{ i }}">{{ i }}</option>
{% endfor %}

</select>
</div>
<div class="col-12 order-1 col-md-9 order-md-12 text-left">
<h5 class="hack-score-cat-name"><strong>{{ category }}</strong></h5>
</div>
</div>
<div class="row">
<div class="col-12 my-2 text-left">
<p class="mb-0">some description here... probably something one liner or max two</p>
<p class="mb-0">
<em><small> descr. field needed in ScoreCat model</small></em>
</p>
</div>
</div>



</div>
</div>
{% endfor %}
</div>
<div class="row d-flex justify-content-center">
<div class="mt-1 mb-5">
<button class="btn-lg btn-ci mt-1" type="submit" value="Submit">Submit scores</button>
</div>
</div>

</form>

</section>


</div>
{% endblock %}
Empty file.
27 changes: 27 additions & 0 deletions hackathon/templatetags/my_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

# range snippet from: https://www.djangosnippets.org/snippets/1357/
# adjusted to current project needs based on https://docs.djangoproject.com/en/3.1/howto/custom-template-tags/
from django.template import Library

register = Library()

@register.filter
def get_range(value, start):
"""
Filter - returns a list containing range made from given value
Usage (in template):

<ul>{% for i in 3|get_range %}
<li>{{ i }}. Do something</li>
{% endfor %}</ul>

Results with the HTML:
<ul>
<li>0. Do something</li>
<li>1. Do something</li>
<li>2. Do something</li>
</ul>

Instead of 3 one may use the variable set in the views
"""
return range(start, value+1, 1)
7 changes: 4 additions & 3 deletions hackathon/urls.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from django.urls import path

from .views import (
HackathonListView, create_hackathon, update_hackathon, delete_hackathon
HackathonListView, create_hackathon, update_hackathon, delete_hackathon, judging
)

urlpatterns = [
path('', HackathonListView.as_view(), name='hackathon-list'),
path('', HackathonListView.as_view(), name="hackathon-list"),
path("<int:hack_id>/team/<int:team_id>/judging/", judging, name="judging"),
path("create_hackathon", create_hackathon, name='create_hackathon'),
path("<int:hackathon_id>/update_hackathon", update_hackathon, name="update_hackathon"),
path("<int:hackathon_id>/delete_hackathon", delete_hackathon, name="delete_hackathon"),
]

64 changes: 62 additions & 2 deletions hackathon/views.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from datetime import datetime

from django.views.generic import ListView
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.utils import timezone

from .models import Hackathon
from .models import Hackathon, HackTeam, HackProject, HackProjectScore, HackProjectScoreCategory
from .forms import HackathonForm

# Create your views here.

class HackathonListView(ListView):
"""Renders a page with a list of Hackathons."""
Expand All @@ -30,6 +31,65 @@ def get_context_data(self, **kwargs):


@login_required
def judging(request, hack_id, team_id):
"""Displays the judging page for the judge to save their scores
for the selected project - determined by hackathon id and team id"""

# HackProjectScoreCategories:
score_categories = HackProjectScoreCategory.objects.all()

hackathon = get_object_or_404(Hackathon, pk=hack_id)
team = get_object_or_404(HackTeam, pk=team_id)

# verify whether user is judge for the hackathon
if hackathon not in Hackathon.objects.filter(judges=request.user):
messages.error(request, "You are not a judge for that event!")
return render(request, 'home/index.html')

# verify if hackathon is ready to be judged (judging_status == 'open')
if hackathon.judging_status != 'open':
messages.error(request, f"Judging is not open! {hackathon.judging_status}!")
return render(request, 'home/index.html')

# verify that the selected team belongs to the selected hackathon
if team.hackathon != hackathon:
messages.error(request, f"Nice try! That team is not part of the event...")
return render(request, 'home/index.html')

# check if the judge has already scored the requested team's Project
project = get_object_or_404(HackTeam, pk=team_id).project
if not project:
messages.error(request, f"The team doesn't have a project yet, check back later...")
return render(request, 'home/index.html')
judge_has_scored_this = False
if HackProjectScore.objects.filter(judge=request.user, project=project):
messages.error(request, f"Oooops, sorry! Something went wrong, you have already scored that team...")
return render(request, 'home/index.html')

if request.method == 'POST':
# judge score submitted for a team
for score_category in score_categories:
score_cat_id = f"score_{score_category.id}"
team_score = HackProjectScore(
created_by = request.user,
judge = request.user,
project = get_object_or_404(HackTeam, pk=team_id).project,
score = request.POST.get(score_cat_id),
hack_project_score_category = score_category,
)
team_score.save()

return redirect("hackathon:hackathon-list")

context = {
'hackathon': hackathon,
'score_categories': score_categories,
'team': team,
'project': project,
}
return render(request, 'hackathon/judging.html', context)


def create_hackathon(request):
""" Allow users to create hackathon event """

Expand Down