From d0bfa668ba90d845b9b6aefdbc7f0d18af61ca94 Mon Sep 17 00:00:00 2001 From: Klaas van Schelven Date: Wed, 5 Jun 2024 20:23:28 +0200 Subject: [PATCH] WIP teams & project-management (3) --- teams/models.py | 3 ++ teams/tasks.py | 4 +-- teams/templates/teams/team_list.html | 45 +++++++++++++++++++------ teams/templates/teams/team_members.html | 10 ++++++ teams/views.py | 26 ++++++++++---- users/tasks.py | 4 +-- 6 files changed, 70 insertions(+), 22 deletions(-) diff --git a/teams/models.py b/teams/models.py index 6cf5b53..d61e82e 100644 --- a/teams/models.py +++ b/teams/models.py @@ -41,3 +41,6 @@ class TeamMembership(models.Model): class Meta: unique_together = ("team", "user") + + def is_admin(self): + return self.role == TeamRole.ADMIN diff --git a/teams/tasks.py b/teams/tasks.py index 59e8cdd..2343db7 100644 --- a/teams/tasks.py +++ b/teams/tasks.py @@ -20,7 +20,7 @@ def send_team_invite_email_new_user(email, team_pk, token): "site_title": get_settings().SITE_TITLE, "base_url": get_settings().BASE_URL + "/", "team_name": team.name, - "url": reverse("team_members_accept_new_user", kwargs={ + "url": get_settings().BASE_URL + reverse("team_members_accept_new_user", kwargs={ "token": token, "team_pk": team_pk, }), @@ -40,7 +40,7 @@ def send_team_invite_email(email, team_pk): "site_title": get_settings().SITE_TITLE, "base_url": get_settings().BASE_URL + "/", "team_name": team.name, - "url": reverse("team_members_accept", kwargs={ + "url": get_settings().BASE_URL + reverse("team_members_accept", kwargs={ "team_pk": team_pk, }), }, diff --git a/teams/templates/teams/team_list.html b/teams/templates/teams/team_list.html index 35c9fb4..4a04a73 100644 --- a/teams/templates/teams/team_list.html +++ b/teams/templates/teams/team_list.html @@ -28,37 +28,43 @@ - {% for member in member_list %} + {% for team in team_list %} + + + {% empty %} + + {% endfor %} +
- {{ member.project_count }} projects | {{ member.member_count }} members + {{ team.project_count }} projects | {{ team.member_count }} members +
- {% if not member.accepted %} - Invitation pending - {% elif member.role == 1 %} {# NOTE: we intentionally hide admin-ness for non-accepted users; TODO better use of constants #} - Admin + {% if team.member %} + {% if not team.member.accepted %} + You're invited! + {% elif team.member.role == 1 %} {# NOTE: we intentionally hide admin-ness for non-accepted users; TODO better use of constants #} + Admin + {% endif %} {% endif %} + {% if team.member.is_admin %} + {% endif %} + {% if team.member.is_admin %} + {% endif %} -
- -
+ {% if team.member %} + {% if not team.member.accepted %} + + {% elif team.member.role == 1 %} {# NOTE: we intentionally hide admin-ness for non-accepted users; TODO better use of constants #} +
+ +
+ {% endif %} + {% endif %} +
+ No teams found.
diff --git a/teams/templates/teams/team_members.html b/teams/templates/teams/team_members.html index 58b1548..a7f018d 100644 --- a/teams/templates/teams/team_members.html +++ b/teams/templates/teams/team_members.html @@ -63,6 +63,16 @@ + {% empty %} + + +
+ {# Note: this is already somewhat exceptional, because the usually you'll at least see yourself here (unless you're a superuser and a team has become memberless) #} + No members yet. Invite someone. +
+ + + {% endfor %} diff --git a/teams/views.py b/teams/views.py index 4114037..bc605f8 100644 --- a/teams/views.py +++ b/teams/views.py @@ -28,22 +28,34 @@ def team_list(request, ownership_filter="mine"): TeamMembership.objects.filter(team=team_pk, user=request.user.id).delete() # messages.success("User removed from team") I think this will be obvious enough + my_memberships = TeamMembership.objects.filter(user=request.user) + if ownership_filter == "mine": - base_qs = TeamMembership.objects.filter(user=request.user) + base_qs = Team.objects.filter(teammembership__in=my_memberships) elif ownership_filter == "other": - base_qs = TeamMembership.objects.exclude(user=request.user).distinct("team") # TODO filter on minimal visibility + base_qs = Team.objects.exclude(teammembership__in=my_memberships).distinct() else: raise ValueError("Invalid ownership_filter") - # select member_list with associated counts (active i.e. accepted members) - member_list = base_qs.select_related('team').annotate( - project_count=models.Count('team__project', distinct=True), - member_count=models.Count('team__teammembership', distinct=True, filter=models.Q(team__teammembership__accepted=True)), + team_list = base_qs.annotate( + project_count=models.Count('project', distinct=True), + member_count=models.Count('teammembership', distinct=True, filter=models.Q(teammembership__accepted=True)), ) + if ownership_filter == "mine": + # Perhaps there's some Django-native way of doing this, but I can't figure it out soon enough, and this also + # works: + my_memberships_dict = {m.team_id: m for m in my_memberships} + + team_list_2 = [] + for team in team_list: + team.member = my_memberships_dict.get(team.id) + team_list_2.append(team) + team_list = team_list_2 + return render(request, 'teams/team_list.html', { 'ownership_filter': ownership_filter, - 'member_list': member_list, + 'team_list': team_list, }) diff --git a/users/tasks.py b/users/tasks.py index 90c7d23..b876048 100644 --- a/users/tasks.py +++ b/users/tasks.py @@ -15,7 +15,7 @@ def send_confirm_email(email, token): context={ "site_title": get_settings().SITE_TITLE, "base_url": get_settings().BASE_URL + "/", - "confirm_url": reverse("confirm_email", kwargs={"token": token}), + "confirm_url": get_settings().BASE_URL + reverse("confirm_email", kwargs={"token": token}), }, ) @@ -29,6 +29,6 @@ def send_reset_email(email, token): context={ "site_title": get_settings().SITE_TITLE, "base_url": get_settings().BASE_URL + "/", - "reset_url": reverse("reset_email", kwargs={"token": token}), + "reset_url": get_settings().BASE_URL + reverse("reset_password", kwargs={"token": token}), }, )