Skip to content

Commit

Permalink
Add teams functionality
Browse files Browse the repository at this point in the history
Also commit missed redo of the evaluator loop
  • Loading branch information
yuvipanda committed Jul 25, 2024
1 parent 6c970f2 commit 71575d0
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 12 deletions.
15 changes: 15 additions & 0 deletions comptest/web/management/commands/evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,28 @@ async def process_running_evaluation(self, evaluator: DockerEvaluator, evaluatio
async def ahandle(self):
evaluator = DockerEvaluator()
while True:
# Create evaluation objects when they do not exist
submissions_without_evaluations = Submission.objects.filter(
Q(status=Submission.Status.UPLOADED),
~Exists(
Evaluation.objects.filter(
submission=OuterRef("pk")
)
)
)
async for s in submissions_without_evaluations:
e = Evaluation(submission=s)
await e.asave()

# Start Evaluations when they have not been started yet
unstarted_evaluations = Evaluation.objects.select_related("submission").filter(
status=Evaluation.Status.NOT_STARTED
)

async for e in unstarted_evaluations:
await self.start_evaluation(evaluator, e)

# Check running evaluations
running_evaluations = Evaluation.objects.select_related("submission").filter(
status=Evaluation.Status.EVALUATING
)
Expand Down
13 changes: 12 additions & 1 deletion comptest/web/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,15 @@ class Status(models.TextChoices):


def __str__(self):
return f"({self.status}) {self.result} {self.submission.data_uri}"
return f"({self.status}) {self.result} {self.submission.data_uri}"



class Team(models.Model):
name = models.CharField(max_length=1024)
members = models.ManyToManyField(User, through='TeamMembership', related_name='teams')

class TeamMembership(models.Model):
is_admin = models.BooleanField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
team = models.ForeignKey(Team, on_delete=models.CASCADE)
14 changes: 14 additions & 0 deletions comptest/web/templates/teams/add-member.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% extends "page.html" %}


{% block body %}

<h1>Add someone to team {{team.name}}</h1>

<form class="form" action="{% url 'teams-add-member' team.id %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
<input class="form-control btn btn-primary mt-2" type="submit" value="Submit">
</form>

{% endblock %}
14 changes: 14 additions & 0 deletions comptest/web/templates/teams/create.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% extends "page.html" %}


{% block body %}

<h1>Create a team</h1>

<form class="form" action="{% url 'teams-create' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
<input class="form-control btn btn-primary mt-2" type="submit" value="Submit">
</form>

{% endblock %}
14 changes: 14 additions & 0 deletions comptest/web/templates/teams/list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% extends "page.html" %}

{% block body %}

<h2>List of Teams you are a part of</h2>
<a href="{% url 'teams-create' %}" class="btn btn-secondary">Create a new team</a>

<ul>
{% for t in teams %}
<li><a href="{% url 'teams-view' t.id %}">{{ t.name }}</a></li>
{% endfor %}
</ul>

{% endblock %}
16 changes: 16 additions & 0 deletions comptest/web/templates/teams/view.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{% extends "page.html" %}

{% block body %}

<h2>{{ team.name }}</h2>

<h3>Members</h3>
<a href="{% url 'teams-add-member' team.id %}" class="btn btn-secondary">Add users to this team</a>

<ul>
{% for u in team.members.all %}
<li>{{ u.username }}</li>
{% endfor %}
</ul>

{% endblock %}
12 changes: 8 additions & 4 deletions comptest/web/urls.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
from django.urls import path

from . import views
from .views import default, teams

urlpatterns = [
path("upload", views.upload, name="upload"),
path("results", views.results, name="results"),
path("", views.home, name="home")
path("upload", default.upload, name="upload"),
path("results", default.results, name="results"),
path("teams/list", teams.list, name="teams-list"),
path("teams/create", teams.create, name="teams-create"),
path("teams/<int:id>", teams.view, name="teams-view"),
path("teams/<int:id>/add-member", teams.add_member, name="teams-add-member"),
path("", default.home, name="home")
]
Empty file added comptest/web/views/__init__.py
Empty file.
9 changes: 2 additions & 7 deletions comptest/web/views.py → comptest/web/views/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect, JsonResponse
from django import forms
from django.contrib.auth.decorators import login_required
from .models import Submission, Evaluation
from ..models import Submission, Evaluation
from django.conf import settings


Expand All @@ -24,12 +24,7 @@ def upload(request: HttpRequest) -> HttpResponse:
status=Submission.Status.UPLOADED,
data_uri=f"file:///{filepath}"
)
# FIXME: Figure out transactions
s.save()
e = Evaluation(
submission=s,
)
e.save()
return HttpResponseRedirect("/")
else:
form = UploadForm()
Expand All @@ -53,4 +48,4 @@ def results(request: HttpRequest) -> HttpResponse:
})

def home(request: HttpRequest) -> HttpResponse:
return render(request, "results.html")
return render(request, "results.html")
81 changes: 81 additions & 0 deletions comptest/web/views/teams.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import os
import tempfile
from django.shortcuts import render
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect, Http404
from django.urls import reverse
from django import forms
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from ..models import Team, TeamMembership
from django.conf import settings

@login_required
def list(request: HttpRequest) -> HttpResponse:
teams = request.user.teams.all()

return render(request, 'teams/list.html', {
'teams': teams
})


class TeamForm(forms.Form):
name = forms.CharField(max_length=1024)


@login_required
def create(request: HttpRequest) -> HttpResponse:
if request.method == "POST":
form = TeamForm(request.POST)
if form.is_valid():
team = Team()
team.name = form.cleaned_data['name']
# FIXME: Transactions?
team.save()
membership = TeamMembership()
membership.user = request.user
membership.team = team
membership.is_admin = True
membership.save()
return HttpResponseRedirect(reverse('teams-view', args=(team.id, )))
else:
form = TeamForm()
return render(request, "teams/create.html", {"form": form})

# Intentionally not authenticated, as anyone should be able to view team membership
def view(request: HttpRequest, id: int) -> HttpResponse:
try:
team = Team.objects.filter(id=id).get()
except Team.DoesNotExist:
raise Http404("The requested team does not exist")

return render(request, "teams/view.html", {"team": team})



class AddMemberForm(forms.Form):
username = forms.CharField(max_length=1024)
is_admin = forms.BooleanField(required=False)

@login_required
def add_member(request: HttpRequest, id: int) -> HttpRequest:
try:
team = Team.objects.filter(id=id).get()
except Team.DoesNotExist:
raise Http404("The requested team does not exist")

# FIXME: Validate that we are admin on the team so we can add people
if request.method == "POST":
form = AddMemberForm(request.POST)
if form.is_valid():
# FIXME: Handle missing users
# FIXME: Handle an 'invitation acceptance' flow for users
user = User.objects.filter(username=form.cleaned_data['username']).get()
membership = TeamMembership()
membership.user = user
membership.team = team
membership.is_admin = form.cleaned_data['is_admin']
membership.save()
return HttpResponseRedirect(reverse('teams-view', args=(team.id, )))
else:
form = AddMemberForm()
return render(request, "teams/add-member.html", {"form": form, "team": team})

0 comments on commit 71575d0

Please sign in to comment.