From 0a6380c0f3ef337b2de067de6a1852ab4d2119cf Mon Sep 17 00:00:00 2001 From: Anirudh Prabhakaran Date: Mon, 11 Dec 2023 19:08:20 +0530 Subject: [PATCH 1/2] Create team --- corpus/embedathon/admin.py | 4 + corpus/embedathon/forms.py | 7 ++ .../0002_team_invite_embedathonuser_team.py | 73 +++++++++++++++++++ corpus/embedathon/models.py | 23 ++++++ corpus/embedathon/urls.py | 1 + corpus/embedathon/views.py | 45 +++++++++++- corpus/templates/embedathon/index.html | 64 ++++++++++++++-- 7 files changed, 211 insertions(+), 6 deletions(-) create mode 100644 corpus/embedathon/migrations/0002_team_invite_embedathonuser_team.py diff --git a/corpus/embedathon/admin.py b/corpus/embedathon/admin.py index cd901423..2da48b39 100644 --- a/corpus/embedathon/admin.py +++ b/corpus/embedathon/admin.py @@ -1,6 +1,10 @@ from django.contrib import admin from embedathon.models import EmbedathonUser +from embedathon.models import Invite +from embedathon.models import Team # Register your models here. admin.site.register(EmbedathonUser) +admin.site.register(Team) +admin.site.register(Invite) diff --git a/corpus/embedathon/forms.py b/corpus/embedathon/forms.py index 0039dcd6..87a1b72e 100644 --- a/corpus/embedathon/forms.py +++ b/corpus/embedathon/forms.py @@ -1,4 +1,5 @@ from embedathon.models import EmbedathonUser +from embedathon.models import Team from corpus.forms import CorpusModelForm @@ -16,3 +17,9 @@ class Meta: "ieee_membership_no", "cass_member", ] + + +class TeamCreationForm(CorpusModelForm): + class Meta: + model = Team + fields = ["team_name"] diff --git a/corpus/embedathon/migrations/0002_team_invite_embedathonuser_team.py b/corpus/embedathon/migrations/0002_team_invite_embedathonuser_team.py new file mode 100644 index 00000000..72111d99 --- /dev/null +++ b/corpus/embedathon/migrations/0002_team_invite_embedathonuser_team.py @@ -0,0 +1,73 @@ +# Generated by Django 4.2.4 on 2023-12-11 13:19 +import django.db.models.deletion +from django.conf import settings +from django.db import migrations +from django.db import models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("embedathon", "0001_initial"), + ] + + operations = [ + migrations.CreateModel( + name="Team", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("team_name", models.CharField(max_length=200)), + ( + "team_leader", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="leader", + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + migrations.CreateModel( + name="Invite", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("invite_email", models.EmailField(max_length=254)), + ( + "inviting_team", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="invite_to_team", + to="embedathon.team", + ), + ), + ], + ), + migrations.AddField( + model_name="embedathonuser", + name="team", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="team", + to="embedathon.team", + ), + ), + ] diff --git a/corpus/embedathon/models.py b/corpus/embedathon/models.py index 26ae003d..7142f384 100644 --- a/corpus/embedathon/models.py +++ b/corpus/embedathon/models.py @@ -18,6 +18,29 @@ class EmbedathonUser(models.Model): ieee_member = models.BooleanField(default=False) ieee_membership_no = models.BigIntegerField(blank=True, null=True) cass_member = models.BooleanField(default=False) + team = models.ForeignKey( + "Team", on_delete=models.CASCADE, related_name="team", blank=True, null=True + ) def __str__(self): return self.user.__str__() + + +class Team(models.Model): + team_name = models.CharField(max_length=200, blank=False, null=False) + team_leader = models.ForeignKey( + User, on_delete=models.CASCADE, related_name="leader" + ) + + def __str__(self): + return self.team_name + + +class Invite(models.Model): + inviting_team = models.ForeignKey( + Team, on_delete=models.CASCADE, related_name="invite_to_team" + ) + invite_email = models.EmailField(blank=False, null=False) + + def __str__(self): + return self.invite_email diff --git a/corpus/embedathon/urls.py b/corpus/embedathon/urls.py index a331aa9a..01b69b49 100644 --- a/corpus/embedathon/urls.py +++ b/corpus/embedathon/urls.py @@ -4,4 +4,5 @@ urlpatterns = [ path("", views.index, name="embedathon_index"), path("register", views.register, name="embedathon_register"), + path("create_team", views.create_team, name="embedathon_create_team"), ] diff --git a/corpus/embedathon/views.py b/corpus/embedathon/views.py index 4d761043..52707906 100644 --- a/corpus/embedathon/views.py +++ b/corpus/embedathon/views.py @@ -7,7 +7,9 @@ from django.shortcuts import redirect from django.shortcuts import render from embedathon.forms import EmbedathonForm +from embedathon.forms import TeamCreationForm from embedathon.models import EmbedathonUser +from embedathon.models import Invite from corpus.decorators import module_enabled @@ -18,13 +20,33 @@ @login_required @module_enabled(module_name="embedathon") def index(request): + args = {} try: embedathon_user = EmbedathonUser.objects.get(user=request.user) + args["embedathon_user"] = embedathon_user except EmbedathonUser.DoesNotExist: messages.error(request, "Please register for Embedathon first!") return redirect("embedathon_register") - args = {"embedathon_user": embedathon_user} + # Check if user is part of a team. + if embedathon_user.team is not None: + args["in_team"] = True + + team = embedathon_user.team + members = EmbedathonUser.objects.filter(team=team) + invites = Invite.objects.filter(invite_email=embedathon_user.user.email) + + args["team"] = team + args["members"] = members + args["invites"] = invites + + if team.team_leader == embedathon_user: + args["is_leader"] = True + else: + args["is_leader"] = False + else: + args["in_team"] = False + args["team_creation_form"] = TeamCreationForm() return render(request, "embedathon/index.html", args) @@ -71,3 +93,24 @@ def register(request): args = {"form": form} return render(request, "embedathon/register.html", args) + + +@login_required +@module_enabled(module_name="embedathon") +def create_team(request): + if request.method == "POST": + form = TeamCreationForm(request.POST) + if form.is_valid(): + team = form.save(commit=False) + team.team_leader = request.user + team.save() + + embedathon_user = EmbedathonUser.objects.get(user=request.user) + embedathon_user.team = team + embedathon_user.save() + + messages.success(request, "Team created successfully!") + return redirect("embedathon_index") + else: + messages.error(request, "Illegal Request") + return redirect("embedathon_index") diff --git a/corpus/templates/embedathon/index.html b/corpus/templates/embedathon/index.html index 0c3342f5..c85b2f95 100644 --- a/corpus/templates/embedathon/index.html +++ b/corpus/templates/embedathon/index.html @@ -1,11 +1,65 @@ {% extends 'base.html' %} {% block title %} -Embedathon + Embedathon {% endblock %} {% block content %} -
-

Welcome to Embedathon!

-
-{% endblock %} +
+

Welcome to Embedathon!

+
+
+
+
+ {% if in_team %} +

You are already in a team.

+ {% else %} +
+

Current Invites

+ {% if invites %} + + {% else %} +

You have no invites.

+ {% endif %} +
+
+
OR
+
+
+

Create a team

+
+ {% csrf_token %} + +
+ + {{ team_creation_form.team_name }} + {% if team_creation_form.team_name.errors %} +
+ +
+ {% endif %} +
+ +
+ +
+
+
+ {% endif %} +
+
+
+
+
+
+{% endblock %} From 36ae3d8a5612460acafd55d4a5b2f6d82d03d832 Mon Sep 17 00:00:00 2001 From: Anirudh Prabhakaran Date: Fri, 15 Dec 2023 18:28:17 +0530 Subject: [PATCH 2/2] Added invite system --- corpus/embedathon/forms.py | 7 ++ .../0002_team_invite_embedathonuser_team.py | 6 +- corpus/embedathon/models.py | 2 +- corpus/embedathon/urls.py | 7 ++ corpus/embedathon/views.py | 73 ++++++++++++- corpus/templates/embedathon/index.html | 100 ++++++++++++++++-- 6 files changed, 175 insertions(+), 20 deletions(-) diff --git a/corpus/embedathon/forms.py b/corpus/embedathon/forms.py index 87a1b72e..a1acf45a 100644 --- a/corpus/embedathon/forms.py +++ b/corpus/embedathon/forms.py @@ -1,4 +1,5 @@ from embedathon.models import EmbedathonUser +from embedathon.models import Invite from embedathon.models import Team from corpus.forms import CorpusModelForm @@ -23,3 +24,9 @@ class TeamCreationForm(CorpusModelForm): class Meta: model = Team fields = ["team_name"] + + +class InviteForm(CorpusModelForm): + class Meta: + model = Invite + fields = ["invite_email"] diff --git a/corpus/embedathon/migrations/0002_team_invite_embedathonuser_team.py b/corpus/embedathon/migrations/0002_team_invite_embedathonuser_team.py index 72111d99..cd2fde89 100644 --- a/corpus/embedathon/migrations/0002_team_invite_embedathonuser_team.py +++ b/corpus/embedathon/migrations/0002_team_invite_embedathonuser_team.py @@ -1,6 +1,5 @@ -# Generated by Django 4.2.4 on 2023-12-11 13:19 +# Generated by Django 4.2.4 on 2023-12-11 13:50 import django.db.models.deletion -from django.conf import settings from django.db import migrations from django.db import models @@ -8,7 +7,6 @@ class Migration(migrations.Migration): dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ("embedathon", "0001_initial"), ] @@ -31,7 +29,7 @@ class Migration(migrations.Migration): models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name="leader", - to=settings.AUTH_USER_MODEL, + to="embedathon.embedathonuser", ), ), ], diff --git a/corpus/embedathon/models.py b/corpus/embedathon/models.py index 7142f384..1fb694d8 100644 --- a/corpus/embedathon/models.py +++ b/corpus/embedathon/models.py @@ -29,7 +29,7 @@ def __str__(self): class Team(models.Model): team_name = models.CharField(max_length=200, blank=False, null=False) team_leader = models.ForeignKey( - User, on_delete=models.CASCADE, related_name="leader" + EmbedathonUser, on_delete=models.CASCADE, related_name="leader" ) def __str__(self): diff --git a/corpus/embedathon/urls.py b/corpus/embedathon/urls.py index 01b69b49..9d600180 100644 --- a/corpus/embedathon/urls.py +++ b/corpus/embedathon/urls.py @@ -5,4 +5,11 @@ path("", views.index, name="embedathon_index"), path("register", views.register, name="embedathon_register"), path("create_team", views.create_team, name="embedathon_create_team"), + path("create_invite", views.create_invite, name="embedathon_create_invite"), + path( + "accept_invite/", views.accept_invite, name="embedathon_accept_invite" + ), + path( + "delete_invite/", views.delete_invite, name="embedathon_delete_invite" + ), ] diff --git a/corpus/embedathon/views.py b/corpus/embedathon/views.py index 52707906..0d9634cf 100644 --- a/corpus/embedathon/views.py +++ b/corpus/embedathon/views.py @@ -7,6 +7,7 @@ from django.shortcuts import redirect from django.shortcuts import render from embedathon.forms import EmbedathonForm +from embedathon.forms import InviteForm from embedathon.forms import TeamCreationForm from embedathon.models import EmbedathonUser from embedathon.models import Invite @@ -34,19 +35,23 @@ def index(request): team = embedathon_user.team members = EmbedathonUser.objects.filter(team=team) - invites = Invite.objects.filter(invite_email=embedathon_user.user.email) args["team"] = team args["members"] = members - args["invites"] = invites if team.team_leader == embedathon_user: args["is_leader"] = True + invites = Invite.objects.filter(inviting_team=team) + args["invites_from_team"] = invites + args["invite_form"] = InviteForm() else: args["is_leader"] = False else: args["in_team"] = False + args["is_leader"] = False args["team_creation_form"] = TeamCreationForm() + invites = Invite.objects.filter(invite_email=embedathon_user.user.email) + args["invites_for_user"] = invites return render(request, "embedathon/index.html", args) @@ -102,10 +107,10 @@ def create_team(request): form = TeamCreationForm(request.POST) if form.is_valid(): team = form.save(commit=False) - team.team_leader = request.user + embedathon_user = EmbedathonUser.objects.get(user=request.user) + team.team_leader = embedathon_user team.save() - embedathon_user = EmbedathonUser.objects.get(user=request.user) embedathon_user.team = team embedathon_user.save() @@ -114,3 +119,63 @@ def create_team(request): else: messages.error(request, "Illegal Request") return redirect("embedathon_index") + + +@login_required +@module_enabled(module_name="embedathon") +def create_invite(request): + embedathon_user = EmbedathonUser.objects.get(user=request.user) + if request.method == "POST": + form = InviteForm(request.POST) + if form.is_valid(): + if request.user.email == form.cleaned_data["invite_email"]: + messages.error(request, "You cannot invite yourself!") + return redirect("embedathon_index") + + try: + invite = Invite.objects.get( + inviting_team=embedathon_user.team, + invite_email=form.cleaned_data["invite_email"], + ) + messages.error(request, "Invite has already been sent!") + return redirect("embedathon_index") + except Invite.DoesNotExist: + pass + + invite = form.save(commit=False) + inviting_team = embedathon_user.team + invite.inviting_team = inviting_team + invite.save() + + messages.success(request, "Invite sent!") + return redirect("embedathon_index") + messages.error(request, "Illegal Request") + return redirect("embedathon_index") + + +@login_required +@module_enabled(module_name="embedathon") +def accept_invite(request, pk): + invite = Invite.objects.get(pk=pk) + if request.user.email != invite.invite_email: + messages.error(request, "Illegal request") + return redirect("embedathon_index") + + embedathon_user = EmbedathonUser.objects.get(user=request.user) + embedathon_user.team = invite.inviting_team + embedathon_user.save() + + Invite.objects.filter(invite_email=request.user.email).delete() + + messages.success(request, "Invite accepted!") + return redirect("embedathon_index") + + +@login_required +@module_enabled(module_name="embedathon") +def delete_invite(request, pk): + invite = Invite.objects.get(pk=pk) + invite.delete() + + messages.success(request, "Invite deleted!") + return redirect("embedathon_index") diff --git a/corpus/templates/embedathon/index.html b/corpus/templates/embedathon/index.html index c85b2f95..c5f5b977 100644 --- a/corpus/templates/embedathon/index.html +++ b/corpus/templates/embedathon/index.html @@ -12,20 +12,98 @@

Welcome to Embedathon!

{% if in_team %} -

You are already in a team.

+

Team: {{ team.team_name }}

+
+

Team Members

+
    + {% for member in members %} +
  • + {{ member.user }} +
  • + {% endfor %} +
+
+ {% if is_leader %} +
+
OR
+
+
+

Active Invites

+ {% if invites_from_team %} + + + + + + + + + + {% for invite in invites_from_team %} + + + + + + {% endfor %} + +
Email AddressActions
{{ forloop.counter }}{{ invite.invite_email }} + Revoke +
+ {% else %} +

You have no active invites.

+ {% endif %} +

Send Invite

+
+ {% csrf_token %} +
+ + {{ invite_form.invite_email }} +

Please enter the email that your teammate will + be registering with on Corpus.

+ {% if invite_form.invite_email.errors %} +
+ +
+ {% endif %} +
+
+ +
+
+
+ {% endif %} {% else %}
-

Current Invites

- {% if invites %} -
    - {% for invite in invites %} -
  • - - {{ invite.team.name }} - -
  • +

    Current Invites

    + {% if invites_for_user %} + + + + + + + + + + + {% for invite in invites_for_user %} + + + + {% endfor %} - + +
    Team NameInvited ByActions
    {{ forloop.counter }}{{ invite.inviting_team.team_name }}{{ invite.inviting_team.team_leader }} + Accept + Reject +
    {% else %}

    You have no invites.

    {% endif %}