mirror of
https://github.com/Rushilwiz/launchx.git
synced 2025-04-05 04:30:19 -04:00
feat: added judges section
This commit is contained in:
parent
3a97b74639
commit
55fc02219f
|
@ -160,7 +160,7 @@ CRISPY_TEMPLATE_PACK = 'bootstrap4'
|
||||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||||
MEDIA_URL = '/media/'
|
MEDIA_URL = '/media/'
|
||||||
|
|
||||||
LOGIN_REDIRECT_URL = 'blog-home'
|
LOGIN_REDIRECT_URL = 'judges-portal'
|
||||||
LOGIN_URL = 'login'
|
LOGIN_URL = 'login'
|
||||||
|
|
||||||
# Email
|
# Email
|
||||||
|
|
|
@ -19,12 +19,13 @@ from django.contrib import admin
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from users import views as user_views
|
from users import views as user_views
|
||||||
from innovate.admin import admin_site as innovate_admin
|
from innovate.admin import admin_site as innovate_admin
|
||||||
|
from django.contrib.auth import views as auth_views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', include('launchx.urls')),
|
path('', include('launchx.urls')),
|
||||||
path('innovate/', include('innovate.urls'), name='innovate'),
|
path('innovate/', include('innovate.urls'), name='innovate'),
|
||||||
path('login/', user_views.login, name='login'),
|
path('login/', auth_views.LoginView.as_view(template_name='users/login.html'), name='login'),
|
||||||
path('logout/', user_views.login, name='logout'),
|
path('logout/', user_views.logout, name='logout'),
|
||||||
path('admin/', innovate_admin.urls),
|
path('admin/', innovate_admin.urls),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from .models import Team, Competitor
|
from .models import Team, Competitor, Judge, Score
|
||||||
from django.contrib.auth.models import User, Group
|
from django.contrib.auth.models import User, Group
|
||||||
|
|
||||||
# Register your models here.
|
# Register your models here.
|
||||||
|
@ -14,6 +14,9 @@ admin_site = LaunchXAdminSite(name='launchx-admin')
|
||||||
admin_site.register(User)
|
admin_site.register(User)
|
||||||
admin_site.register(Group)
|
admin_site.register(Group)
|
||||||
|
|
||||||
|
admin_site.register(Judge)
|
||||||
|
admin_site.register(Score)
|
||||||
|
|
||||||
admin_site.register(Competitor)
|
admin_site.register(Competitor)
|
||||||
|
|
||||||
class CompetitorInline(admin.TabularInline):
|
class CompetitorInline(admin.TabularInline):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.forms import modelformset_factory
|
from django.forms import modelformset_factory
|
||||||
|
|
||||||
from .models import Competitor, Team
|
from .models import Competitor, Team, Score
|
||||||
|
|
||||||
class CompetitorForm(forms.ModelForm):
|
class CompetitorForm(forms.ModelForm):
|
||||||
name = forms.CharField(label='Full Name', widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'John Doe'}))
|
name = forms.CharField(label='Full Name', widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'John Doe'}))
|
||||||
|
@ -24,7 +24,7 @@ CompetitorFormset = modelformset_factory(
|
||||||
min_num=2, max_num=4)
|
min_num=2, max_num=4)
|
||||||
|
|
||||||
class TeamForm(forms.ModelForm):
|
class TeamForm(forms.ModelForm):
|
||||||
name = forms.CharField(required=False, label="Team Name", widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'BusinessX'}))
|
name = forms.CharField(required=True, label="Team Name", widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'BusinessX'}))
|
||||||
reciept = forms.FileField(required=False)
|
reciept = forms.FileField(required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -41,3 +41,20 @@ class TeamForm(forms.ModelForm):
|
||||||
if commit:
|
if commit:
|
||||||
m.save()
|
m.save()
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
class ScoreForm(forms.ModelForm):
|
||||||
|
innovation = forms.IntegerField(min_value=0, max_value=30, widget=forms.NumberInput(attrs={'placeholder': '30'}))
|
||||||
|
need = forms.IntegerField(min_value=0, max_value=35, widget=forms.NumberInput(attrs={'placeholder': '35'}))
|
||||||
|
finances = forms.IntegerField(min_value=0, max_value=25, widget=forms.NumberInput(attrs={'placeholder': '25'}))
|
||||||
|
creativity = forms.IntegerField(min_value=0, max_value=10, widget=forms.NumberInput(attrs={'placeholder': '10'}))
|
||||||
|
|
||||||
|
qna = forms.IntegerField(min_value=0, max_value=25, widget=forms.NumberInput(attrs={'placeholder': '25'}))
|
||||||
|
speaking = forms.IntegerField(min_value=0, max_value=10, widget=forms.NumberInput(attrs={'placeholder': '10'}))
|
||||||
|
persuasiveness = forms.IntegerField(min_value=0, max_value=10, widget=forms.NumberInput(attrs={'placeholder': '10'}))
|
||||||
|
professionalism = forms.IntegerField(min_value=0, max_value=5, widget=forms.NumberInput(attrs={'placeholder': '5'}))
|
||||||
|
|
||||||
|
feedback = forms.CharField(required=False, widget=forms.Textarea(attrs={'placeholder': 'Enter feedback here (optional)', 'class': 'form-control'}))
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Score
|
||||||
|
fields = ['innovation', 'need', 'finances', 'creativity', 'qna', 'speaking', 'persuasiveness', 'professionalism']
|
27
innovate/migrations/0004_judge.py
Normal file
27
innovate/migrations/0004_judge.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# Generated by Django 3.1.6 on 2021-02-19 05:04
|
||||||
|
|
||||||
|
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),
|
||||||
|
('innovate', '0003_auto_20210211_0122'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Judge',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Judge',
|
||||||
|
'verbose_name_plural': 'Judges',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
19
innovate/migrations/0005_judge_iseven.py
Normal file
19
innovate/migrations/0005_judge_iseven.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# Generated by Django 3.1.6 on 2021-02-19 05:10
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('innovate', '0004_judge'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='judge',
|
||||||
|
name='isEven',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
36
innovate/migrations/0006_score.py
Normal file
36
innovate/migrations/0006_score.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# Generated by Django 3.1.6 on 2021-02-19 17:20
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import innovate.models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('innovate', '0005_judge_iseven'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Score',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('innovation', innovate.models.IntegerRangeField()),
|
||||||
|
('need', innovate.models.IntegerRangeField()),
|
||||||
|
('finances', innovate.models.IntegerRangeField()),
|
||||||
|
('creativity', innovate.models.IntegerRangeField()),
|
||||||
|
('qna', innovate.models.IntegerRangeField()),
|
||||||
|
('speaking', innovate.models.IntegerRangeField()),
|
||||||
|
('persuasiveness', innovate.models.IntegerRangeField()),
|
||||||
|
('professionalism', innovate.models.IntegerRangeField()),
|
||||||
|
('feedback', models.TextField(blank=True, null=True)),
|
||||||
|
('judge', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='innovate.judge')),
|
||||||
|
('team', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='innovate.team')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Feedback',
|
||||||
|
'verbose_name_plural': 'Feedback',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,7 +1,15 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.contrib.auth.models import User
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
# Create your models here.
|
class IntegerRangeField(models.IntegerField):
|
||||||
|
def __init__(self, verbose_name=None, name=None, min_value=None, max_value=None, **kwargs):
|
||||||
|
self.min_value, self.max_value = min_value, max_value
|
||||||
|
models.IntegerField.__init__(self, verbose_name, name, **kwargs)
|
||||||
|
def formfield(self, **kwargs):
|
||||||
|
defaults = {'min_value': self.min_value, 'max_value':self.max_value}
|
||||||
|
defaults.update(kwargs)
|
||||||
|
return super(IntegerRangeField, self).formfield(**defaults)
|
||||||
|
|
||||||
class Team(models.Model):
|
class Team(models.Model):
|
||||||
number = models.IntegerField()
|
number = models.IntegerField()
|
||||||
|
@ -43,3 +51,44 @@ class Competitor(models.Model):
|
||||||
|
|
||||||
# if Competitor.objects.filter(email=self.email).count() > 0:
|
# if Competitor.objects.filter(email=self.email).count() > 0:
|
||||||
# raise ValidationError({'email': 'Somebody with that email is already registered!'})
|
# raise ValidationError({'email': 'Somebody with that email is already registered!'})
|
||||||
|
|
||||||
|
class Judge(models.Model):
|
||||||
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
|
isEven = models.BooleanField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = "Judge"
|
||||||
|
verbose_name_plural = "Judges"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'Judge {self.user.last_name}'
|
||||||
|
|
||||||
|
class Score(models.Model):
|
||||||
|
judge = models.ForeignKey(Judge, on_delete=models.CASCADE)
|
||||||
|
team = models.ForeignKey(Team, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
# product scores
|
||||||
|
innovation = IntegerRangeField(min_value=0, max_value=30)
|
||||||
|
need = IntegerRangeField(min_value=0, max_value=35)
|
||||||
|
finances = IntegerRangeField(min_value=0, max_value=25)
|
||||||
|
creativity = IntegerRangeField(min_value=0, max_value=10)
|
||||||
|
|
||||||
|
# delivery scores
|
||||||
|
qna = IntegerRangeField(min_value=0, max_value=25)
|
||||||
|
speaking = IntegerRangeField(min_value=0, max_value=10)
|
||||||
|
persuasiveness = IntegerRangeField(min_value=0, max_value=10)
|
||||||
|
professionalism = IntegerRangeField(min_value=0, max_value=5)
|
||||||
|
fields = [innovation, need, finances, creativity, qna, speaking, persuasiveness, professionalism]
|
||||||
|
|
||||||
|
feedback = models.TextField(blank=True, null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = "Feedback"
|
||||||
|
verbose_name_plural = "Feedback"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'Team {self.team.number}\'s Feedback from {self.judge.user.get_full_name()}'
|
||||||
|
|
||||||
|
def get_total_score(self):
|
||||||
|
fields = [self.innovation, self.need, self.finances, self.creativity, self.qna, self.speaking, self.persuasiveness, self.professionalism]
|
||||||
|
return sum(fields)
|
6
innovate/static/innovate/portal.css
Normal file
6
innovate/static/innovate/portal.css
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
h3 small {
|
||||||
|
font-size: .66em;
|
||||||
|
}
|
||||||
|
.text-success {
|
||||||
|
color: rgb(25, 207, 34) !important
|
||||||
|
}
|
121
innovate/templates/innovate/feedback.html
Normal file
121
innovate/templates/innovate/feedback.html
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
{% extends 'launchx/base.html' %}
|
||||||
|
{% load launchx_extras %}
|
||||||
|
{% block content %}
|
||||||
|
<h1>Feedback for Team {{ team.number }}: {{ team.name }}</h1>
|
||||||
|
<div class="d-flex">
|
||||||
|
<form method="POST">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.non_field_errors }}
|
||||||
|
{{ form.errors }}
|
||||||
|
{% for hidden in form.hidden_fields %}
|
||||||
|
{{ hidden }}
|
||||||
|
{% endfor %}
|
||||||
|
<input type="hidden" id="team_number" name="team_number" value="{{ team.number }}">
|
||||||
|
<div class="container">
|
||||||
|
<h2><span class="border-bottom border-3">Product</span></h2>
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<h3>Innovation</h3>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<p>Does the product have a unique value proposition (15 pts) ? i.e. does it use novel, innovative technologies, or combine existing technologies in a unique way (10 pts) ? How does their solution fit under the theme of innovation (5 pts) ? </p>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
{{ form.innovation }}/30
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<h3>Marketability / Need</h3>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<p>Is there a need for this product (10 pts) ? Does the team know the intended market (5 pts) ? Do they complete a market analysis or examine their servicable avaible market (15 pts) ? Is the innovation practical (5 pts) ?</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
{{ form.need }}/35
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<h3>Finances</h3>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<p>Does the team have a business model (10 pts) ? Do they know who their intended customer is (5 pts) ? Does the team perform a competitive analysis of their market (explain the differentiators between their innovation and current products/services in the market) (10 pts)?</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
{{ form.finances }}/25
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<h3>Creativity / Professionalism </h3>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<p>Is their presentation creative AND professional (5 pts each) ?</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
{{ form.creativity }}/10
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container mt-md-3">
|
||||||
|
<h2><span class="border-bottom border-3">Delivery</span></h2>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<h3>Q&A Session</h3>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
{{ form.qna }}/25
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<h3>Speaking Quality </h3>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
{{ form.speaking }}/10
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<h3>Persuasiveness</h3>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
{{ form.persuasiveness }}/10
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<h3>Professionalism</h3>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
{{ form.professionalism }}/5
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container mt-md-3">
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<h2>Feedback</h2>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
{{ form.feedback }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group mt-md-3">
|
||||||
|
<button class="btn btn-light btn-block" type="submit">Submit Score</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
31
innovate/templates/innovate/portal.html
Normal file
31
innovate/templates/innovate/portal.html
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
{% extends 'launchx/base.html' %}
|
||||||
|
{% load launchx_extras %}
|
||||||
|
|
||||||
|
{% block styles %}
|
||||||
|
<link rel="stylesheet" href="{% static 'innovate/portal.css' %}">
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container mt-md-3 w-75">
|
||||||
|
<h1>Welcome Judge {{ request.user.last_name }},</h1>
|
||||||
|
<h5>Thanks for judging at InnovateTJ, now time to score!</h5>
|
||||||
|
<hr>
|
||||||
|
</div>
|
||||||
|
<div class="containter text-center">
|
||||||
|
<h4>{{ completed_teams_count }} out of {{ teams_count }} teams scored</h4>
|
||||||
|
</div>
|
||||||
|
<div class="container w-50">
|
||||||
|
{% for team in teams %}
|
||||||
|
<div class="border border-2 border-secondary rounded-3 mt-md-4 p-md-4">
|
||||||
|
<h3>Team {{ team.number }}: {{ team.name }} <small class="text-secondary">Unscored</small></h3>
|
||||||
|
<a href="{% url '/innovate/judges/feedback' %}?team={{ team.number | urlencode }}"><button class="btn btn-light w-100">Score Team {{ team.number }}</button></a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for team, score in completed_teams %}
|
||||||
|
<div class="border border-2 border-secondary rounded-3 mt-md-4 p-md-2">
|
||||||
|
<h3>Team {{ team.number }}: {{ team.name }} <small><span class="text-success">Scored</span> {{ score.get_total_score }}/150</small></h3>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -5,4 +5,6 @@ urlpatterns = [
|
||||||
path('', views.home, name='innovate-home'),
|
path('', views.home, name='innovate-home'),
|
||||||
path('signup/', views.signup, name='competitor-signup'),
|
path('signup/', views.signup, name='competitor-signup'),
|
||||||
path('signup/confirm/', views.confirm, name='competitor-signup-confirm'),
|
path('signup/confirm/', views.confirm, name='competitor-signup-confirm'),
|
||||||
|
path('judges/', views.portal, name='judges-portal'),
|
||||||
|
path('judges/feedback/', views.feedback, name='judges-feedback')
|
||||||
]
|
]
|
|
@ -1,13 +1,16 @@
|
||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import render, redirect
|
||||||
|
|
||||||
from .forms import CompetitorFormset, CompetitorForm, TeamForm
|
from .forms import CompetitorFormset, CompetitorForm, TeamForm, ScoreForm
|
||||||
from .models import Competitor
|
from .models import Competitor, Team, Judge, Score
|
||||||
|
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.utils.html import strip_tags
|
from django.utils.html import strip_tags
|
||||||
from config.settings import EMAIL_HOST_USER
|
|
||||||
from django.core.mail import EmailMultiAlternatives, send_mail
|
from django.core.mail import EmailMultiAlternatives, send_mail
|
||||||
|
|
||||||
|
from config.settings import EMAIL_HOST_USER
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
def home(request):
|
def home(request):
|
||||||
return render(request, 'innovate/index.html')
|
return render(request, 'innovate/index.html')
|
||||||
|
@ -66,3 +69,62 @@ def send_confirmation(request, team, members):
|
||||||
|
|
||||||
def confirm(request):
|
def confirm(request):
|
||||||
return render(request, 'innovate/confirm.html')
|
return render(request, 'innovate/confirm.html')
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def portal(request):
|
||||||
|
judge = Judge.objects.get(user=request.user)
|
||||||
|
team_numbers = [team.number for team in Team.objects.all() if ((team.number % 2 == 0 and judge.isEven) or (team.number % 2 != 0 and not judge.isEven))]
|
||||||
|
teams, completed_teams = [], []
|
||||||
|
for number in team_numbers:
|
||||||
|
if Score.objects.filter(team=Team.objects.get(number=number), judge=judge).count() == 0:
|
||||||
|
teams.append(Team.objects.get(number=number))
|
||||||
|
else:
|
||||||
|
completed_teams.append((Team.objects.get(number=number), Score.objects.get(team=Team.objects.get(number=number), judge=judge)))
|
||||||
|
|
||||||
|
context = {
|
||||||
|
'teams': teams,
|
||||||
|
'completed_teams': completed_teams,
|
||||||
|
'completed_teams_count': len(completed_teams),
|
||||||
|
'teams_count': len(team_numbers)
|
||||||
|
}
|
||||||
|
|
||||||
|
return render(request, 'innovate/portal.html', context=context)
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def feedback(request):
|
||||||
|
form = ScoreForm()
|
||||||
|
judge = Judge.objects.get(user=request.user)
|
||||||
|
if type(judge) != Judge:
|
||||||
|
print('no team or judge')
|
||||||
|
return redirect('judges-portal')
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = ScoreForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
team = Team.objects.get(number=request.POST['team_number'])
|
||||||
|
if ((team.number % 2 != 0 and judge.isEven) or (team.number % 2 == 0 and not judge.isEven)):
|
||||||
|
print('judge not approved')
|
||||||
|
return redirect('judges-portal')
|
||||||
|
score = form.save(commit=False)
|
||||||
|
score.judge = judge
|
||||||
|
score.team = team
|
||||||
|
score.feedback = form.cleaned_data['feedback']
|
||||||
|
score.save()
|
||||||
|
return redirect('judges-portal')
|
||||||
|
elif request.GET.get('team'):
|
||||||
|
team = Team.objects.get(number=request.GET['team'])
|
||||||
|
if team == None:
|
||||||
|
print('no team or judge')
|
||||||
|
elif ((team.number % 2 != 0 and judge.isEven) or (team.number % 2 == 0 and not judge.isEven)):
|
||||||
|
print('judge not approved')
|
||||||
|
elif Score.objects.filter(team=team, judge=judge).count() != 0:
|
||||||
|
print('feedback already exists')
|
||||||
|
else:
|
||||||
|
context = {
|
||||||
|
'team': team,
|
||||||
|
'judge': judge,
|
||||||
|
'form': form,
|
||||||
|
}
|
||||||
|
return render(request, 'innovate/feedback.html', context=context)
|
||||||
|
return redirect('judges-portal')
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,14 @@
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="navbarToggle">
|
<div class="collapse navbar-collapse" id="navbarToggle">
|
||||||
<div class="navbar-nav mr-auto">
|
<div class="navbar-nav me-auto mr-auto">
|
||||||
<a class="nav-item nav-link {% if request.resolver_match.url_name == 'landing' %}active{% endif %}" href="{% url '/' %}">Home</a>
|
<a class="nav-item nav-link {% if request.resolver_match.url_name == 'landing' %}active{% endif %}" href="{% url '/' %}">Home</a>
|
||||||
<a class="nav-item nav-link {% if request.resolver_match.url_name == 'innovate-home' %}active{% endif %}" href="{% url '/innovate' %}">InnovateTJ</a>
|
<a class="nav-item nav-link {% if request.resolver_match.url_name == 'innovate-home' %}active{% endif %}" href="{% url '/innovate' %}">InnovateTJ</a>
|
||||||
<a class="nav-item nav-link {% if request.resolver_match.url_name == 'calendar' %}active{% endif %}" href="{% url '/calendar' %}">Calendar</a>
|
<a class="nav-item nav-link {% if request.resolver_match.url_name == 'calendar' %}active{% endif %}" href="{% url '/calendar' %}">Calendar</a>
|
||||||
<a class="nav-item nav-link {% if request.resolver_match.url_name == 'officers' %}active{% endif %}" href="{% url '/officers' %}">Officers</a>
|
<a class="nav-item nav-link {% if request.resolver_match.url_name == 'officers' %}active{% endif %}" href="{% url '/officers' %}">Officers</a>
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
<a class="nav-item nav-link {% if request.resolver_match.url_name == 'judges-portal' %}active{% endif %}" href="{% url '/innovate/judges' %}">Judging Portal</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<!-- Navbar Right Side -->
|
<!-- Navbar Right Side -->
|
||||||
<div class="navbar-nav">
|
<div class="navbar-nav">
|
||||||
|
@ -57,3 +60,5 @@
|
||||||
{% block scripts %}{% endblock %}
|
{% block scripts %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
||||||
|
|
3
users/static/users/login.css
Normal file
3
users/static/users/login.css
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
form {
|
||||||
|
color: white
|
||||||
|
}
|
|
@ -1,4 +1,18 @@
|
||||||
{% extends 'users/base.html' %}
|
{% extends 'users/base.html' %}
|
||||||
{% block content %}
|
{% load crispy_forms_tags %}
|
||||||
<h1 style="color: white">Login page also in development</h1>
|
{% load launchx_extras %}
|
||||||
|
{% block styles %}
|
||||||
|
<link rel="stylesheet" type="text/css" href="{% static 'users/login.css' %}">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="d-flex flex-column min-vh-100 justify-content-center align-items-center">
|
||||||
|
<form method="POST">
|
||||||
|
{% csrf_token %}
|
||||||
|
<legend class="">Judges Log In</legend>
|
||||||
|
{{ form|crispy }}
|
||||||
|
<div class="form-group mt-3">
|
||||||
|
<button class="btn btn-light btn-block" type="submit">Login</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
6
users/templates/users/logout.html
Normal file
6
users/templates/users/logout.html
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{% extends 'launchx/base.html' %}
|
||||||
|
{% load launchx_extras %}
|
||||||
|
{% block content %}
|
||||||
|
<h1 style="color: white">You've logged out!</h1>
|
||||||
|
<a href="{% url '/' %}"><button class="btn btn-light">Back</button></a>
|
||||||
|
{% endblock %}
|
|
@ -1,5 +1,15 @@
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
from django.contrib.auth import login as auth_login
|
||||||
|
from django.contrib.auth import logout as auth_logout
|
||||||
|
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
def login(request):
|
def login(request):
|
||||||
return render(request, 'users/login.html')
|
return render(request, 'users/login.html')
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def logout(request):
|
||||||
|
auth_logout(request)
|
||||||
|
return render(request, 'users/logout.html')
|
Loading…
Reference in New Issue
Block a user