From 916dba52c1b9f90fbd3029b522a56332e90bc3fb Mon Sep 17 00:00:00 2001 From: Thomas Steen Rasmussen Date: Tue, 23 May 2017 21:21:47 +0200 Subject: [PATCH] add member remove button --- src/bornhack/urls.py | 5 +++ .../migrations/0013_auto_20170523_2046.py | 32 +++++++++++++++++++ .../0014_remove_teammember_deleted.py | 19 +++++++++++ src/teams/models.py | 6 +++- src/teams/templates/team_detail.html | 22 +++++++------ src/teams/templates/teammember_remove.html | 18 +++++++++++ src/teams/views.py | 27 ++++++++++++++++ 7 files changed, 119 insertions(+), 10 deletions(-) create mode 100644 src/teams/migrations/0013_auto_20170523_2046.py create mode 100644 src/teams/migrations/0014_remove_teammember_deleted.py create mode 100644 src/teams/templates/teammember_remove.html diff --git a/src/bornhack/urls.py b/src/bornhack/urls.py index 7d666749..fad2ef47 100644 --- a/src/bornhack/urls.py +++ b/src/bornhack/urls.py @@ -285,6 +285,11 @@ urlpatterns = [ TeamListView.as_view(), name='team_list' ), + url( + r'^members/(?P[0-9]+)/remove/$', + TeamMemberRemoveView.as_view(), + name='teammember_remove', + ), url( r'(?P[-_\w+]+)/join/$', TeamJoinView.as_view(), diff --git a/src/teams/migrations/0013_auto_20170523_2046.py b/src/teams/migrations/0013_auto_20170523_2046.py new file mode 100644 index 00000000..fb536ace --- /dev/null +++ b/src/teams/migrations/0013_auto_20170523_2046.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-05-23 18:46 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('teams', '0012_teammember_responsible'), + ] + + operations = [ + migrations.AddField( + model_name='teammember', + name='created', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='teammember', + name='deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='teammember', + name='updated', + field=models.DateTimeField(auto_now=True), + ), + ] diff --git a/src/teams/migrations/0014_remove_teammember_deleted.py b/src/teams/migrations/0014_remove_teammember_deleted.py new file mode 100644 index 00000000..759afe2e --- /dev/null +++ b/src/teams/migrations/0014_remove_teammember_deleted.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-05-23 19:13 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('teams', '0013_auto_20170523_2046'), + ] + + operations = [ + migrations.RemoveField( + model_name='teammember', + name='deleted', + ), + ] diff --git a/src/teams/models.py b/src/teams/models.py index fd8aced4..cdf11569 100644 --- a/src/teams/models.py +++ b/src/teams/models.py @@ -83,7 +83,7 @@ class Team(CampRelatedModel): return self.area.responsible.all() -class TeamMember(models.Model): +class TeamMember(CampRelatedModel): user = models.ForeignKey('auth.User') team = models.ForeignKey('teams.Team') approved = models.BooleanField(default=False) @@ -94,6 +94,10 @@ class TeamMember(models.Model): self.user, '' if self.approved else 'an unapproved', self.team ) + @property + def camp(self): + return self.team.camp + @receiver(post_save, sender=TeamMember) def send_responsible_email(sender, instance, created, **kwargs): diff --git a/src/teams/templates/team_detail.html b/src/teams/templates/team_detail.html index 31a1feed..c16443a6 100644 --- a/src/teams/templates/team_detail.html +++ b/src/teams/templates/team_detail.html @@ -35,6 +35,8 @@ Team: {{ team.name }} | {{ block.super }} {% endfor %} +
+ {% if request.user in team.responsible %}

Manage {{ team.name }} Team

@@ -60,30 +62,32 @@ Team: {{ team.name }} | {{ block.super }} Profile Name - - Status Email Description + + Membership Status Action - {% for member in team.teammember_set.all %} + {% for membership in team.teammember_set.all %} - {{ member.user }} + {{ membership.user }} - {{ member.user.profile.name }} + {{ membership.user.profile.name }} - {{ member.approved }} + {{ membership.user.profile.email }} - {{ member.user.profile.email }} + {{ membership.user.profile.description }} - {{ member.user.profile.description }} + {% if membership.approved %}member{% else %}pending{% endif %} - TBD + {% if membership.approved %} + Remove + {% endif %} {% endfor %} {% endif %} diff --git a/src/teams/templates/teammember_remove.html b/src/teams/templates/teammember_remove.html new file mode 100644 index 00000000..673c7d51 --- /dev/null +++ b/src/teams/templates/teammember_remove.html @@ -0,0 +1,18 @@ +{% extends 'base.html' %} +{% load commonmark %} + +{% block title %} +Remove member {{ teammember.user.profile.name }} from team {{ teammember.team.name }} +{% endblock %} + +{% block content %} + +

Remove member {{ teammember.user.profile.name }} from the {{ teammember.team.name }} team

+

Really remove the user {{ teammember.user.profile.name }} from the {{ teammember.team.name }} team? The user will receive an email with a message.

+

+{% csrf_token %} +{{ form }} + + Cancel +
+{% endblock %} diff --git a/src/teams/views.py b/src/teams/views.py index c80eff19..a74f72f5 100644 --- a/src/teams/views.py +++ b/src/teams/views.py @@ -7,6 +7,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin from django.shortcuts import redirect from django.contrib import messages from django.http import Http404 +from django.views.generic.detail import SingleObjectMixin class TeamListView(CampViewMixin, ListView): @@ -60,3 +61,29 @@ class TeamLeaveView(LoginRequiredMixin, CampViewMixin, UpdateView): TeamMember.objects.filter(team=self.get_object(), user=self.request.user).delete() messages.success(self.request, "You are no longer a member of the team %s" % self.get_object().name) return redirect('team_list', camp_slug=self.get_object().camp.slug) + + +class EnsureTeamResponsibleMixin(SingleObjectMixin): + model = TeamMember + + def dispatch(self, request, *args, **kwargs): + if not request.user in self.get_object().team.responsible.all(): + messages.error(request, 'No thanks') + return HttpResponseRedirect(reverse_lazy('team_detail', slug=self.get_object().team.slug)) + + return super().dispatch( + request, *args, **kwargs + ) + + +class TeamMemberRemoveView(LoginRequiredMixin, EnsureTeamResponsibleMixin, UpdateView): + template_name = "teammember_remove.html" + model = TeamMember + fields = [] + + def form_valid(self, form): + form.instance.delete() + messages.success(self.request, "Team member removed") + return redirect('team_detail', camp_slug=form.instance.team.camp.slug, slug=form.instance.team.slug) + +