Merge pull request #127 from bornhack/develop

fix #123
This commit is contained in:
Stephan Telling 2017-05-23 22:09:27 +02:00 committed by GitHub
commit 49bfc58dda
9 changed files with 214 additions and 9 deletions

View file

@ -1,16 +1,10 @@
from allauth.account.views import ( from allauth.account.views import (
SignupView,
LoginView, LoginView,
LogoutView, LogoutView,
ConfirmEmailView,
EmailVerificationSentView,
PasswordResetView
) )
from django.conf import settings from django.conf import settings
from django.conf.urls import include, url from django.conf.urls import include, url
from django.contrib import admin from django.contrib import admin
from django.views.generic import TemplateView, RedirectView
from django.core.urlresolvers import reverse_lazy
from camps.views import * from camps.views import *
from info.views import * from info.views import *
from villages.views import * from villages.views import *
@ -291,6 +285,16 @@ urlpatterns = [
TeamListView.as_view(), TeamListView.as_view(),
name='team_list' name='team_list'
), ),
url(
r'^members/(?P<pk>[0-9]+)/remove/$',
TeamMemberRemoveView.as_view(),
name='teammember_remove',
),
url(
r'^members/(?P<pk>[0-9]+)/approve/$',
TeamMemberApproveView.as_view(),
name='teammember_approve',
),
url( url(
r'(?P<slug>[-_\w+]+)/join/$', r'(?P<slug>[-_\w+]+)/join/$',
TeamJoinView.as_view(), TeamJoinView.as_view(),

8
src/teams/forms.py Normal file
View file

@ -0,0 +1,8 @@
from django.forms import ModelForm
from .models import Team
class ManageTeamForm(ModelForm):
class Meta:
model = Team
fields = ['description', 'needs_members']

View file

@ -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),
),
]

View file

@ -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',
),
]

View file

@ -85,7 +85,7 @@ class Team(CampRelatedModel):
return self.area.responsible.all() return self.area.responsible.all()
class TeamMember(models.Model): class TeamMember(CampRelatedModel):
user = models.ForeignKey('auth.User') user = models.ForeignKey('auth.User')
team = models.ForeignKey('teams.Team') team = models.ForeignKey('teams.Team')
approved = models.BooleanField(default=False) approved = models.BooleanField(default=False)
@ -96,6 +96,10 @@ class TeamMember(models.Model):
self.user, '' if self.approved else 'an unapproved', self.team self.user, '' if self.approved else 'an unapproved', self.team
) )
@property
def camp(self):
return self.team.camp
@receiver(post_save, sender=TeamMember) @receiver(post_save, sender=TeamMember)
def add_responsible_email(sender, instance, created, **kwargs): def add_responsible_email(sender, instance, created, **kwargs):

View file

@ -1,6 +1,7 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load commonmark %} {% load commonmark %}
{% load teams_tags %} {% load teams_tags %}
{% load bootstrap3 %}
{% block title %} {% block title %}
Team: {{ team.name }} | {{ block.super }} Team: {{ team.name }} | {{ block.super }}
@ -33,4 +34,65 @@ Team: {{ team.name }} | {{ block.super }}
<li><b>{{ resp.get_full_name|default:"Unnamed" }}</b></li> <li><b>{{ resp.get_full_name|default:"Unnamed" }}</b></li>
{% endfor %} {% endfor %}
</ul> </ul>
<hr>
{% if request.user in team.responsible %}
<h3>Manage {{ team.name }} Team</h3>
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
<hr />
{% buttons %}
<button class="btn btn-primary pull-right" type="submit">Save</button>
{% endbuttons %}
</form>
<br />
<br />
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>
Profile
<th >
Name
<th>
Email
<th>
Description
<th>
Membership Status
<th>
Action
<tbody>
{% for membership in team.teammember_set.all %}
<tr>
<td>
{{ membership.user }}
<td>
{{ membership.user.profile.name }}
<td>
{{ membership.user.profile.email }}
<td>
{{ membership.user.profile.description }}
<td>
{% if membership.approved %}member{% else %}pending{% endif %}
<td>
{% if membership.approved %}
<a class="btn btn-danger" href="{% url 'teammember_remove' camp_slug=camp.slug pk=membership.id %}"><i class="fa fa-trash-o"></i> Remove</a>
{% else %}
<a class="btn btn-danger" href="{% url 'teammember_remove' camp_slug=camp.slug pk=membership.id %}"><i class="fa fa-trash-o"></i> Remove</a>
<a class="btn btn-success" href="{% url 'teammember_approve' camp_slug=camp.slug pk=membership.id %}"><i class="fa fa-check"></i> Approve</a>
{% endif %}
{% endfor %}
{% endif %}
{% endblock %} {% endblock %}

View file

@ -0,0 +1,18 @@
{% extends 'base.html' %}
{% load commonmark %}
{% block title %}
Approve team member {{ teammember.user.profile.name }} for the {{ teammember.team.name }} team
{% endblock %}
{% block content %}
<h3>Approve member {{ teammember.user.profile.name }} for the {{ teammember.team.name }} team</h3>
<p class="lead">Really approve the user <b>{{ teammember.user.profile.name }}</b> for the {{ teammember.team.name }} team? The user will receive an email with a message.<p>
<form method="POST">
{% csrf_token %}
{{ form }}
<button class="btn btn-success" type="submit"><i class="fa fa-check"></i> Add teammember</button>
<a href="{% url 'team_detail' camp_slug=teammember.team.camp.slug slug=teammember.team.slug %}" class="btn btn-default" type="submit"><i class="fa fa-remove"></i> Cancel</a>
</form>
{% endblock %}

View file

@ -0,0 +1,18 @@
{% extends 'base.html' %}
{% load commonmark %}
{% block title %}
Remove member {{ teammember.user.profile.name }} from the {{ teammember.team.name }} team
{% endblock %}
{% block content %}
<h3>Remove member {{ teammember.user.profile.name }} from the {{ teammember.team.name }} team</h3>
<p class="lead">Really remove the user <b>{{ teammember.user.profile.name }}</b> from the {{ teammember.team.name }} team? The user will receive an email with a message.<p>
<form method="POST">
{% csrf_token %}
{{ form }}
<button class="btn btn-danger" type="submit"><i class="fa fa-trash-o"></i> Remove teammember</button>
<a href="{% url 'team_detail' camp_slug=teammember.team.camp.slug slug=teammember.team.slug %}" class="btn btn-default" type="submit"><i class="fa fa-remove"></i> Cancel</a>
</form>
{% endblock %}

View file

@ -1,10 +1,14 @@
from django.views.generic import ListView, DetailView from django.views.generic import ListView, DetailView
from django.views.generic.edit import UpdateView from django.views.generic.edit import UpdateView, FormView
from camps.mixins import CampViewMixin from camps.mixins import CampViewMixin
from .models import Team, TeamMember from .models import Team, TeamMember
from .forms import ManageTeamForm
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import redirect from django.shortcuts import redirect
from django.contrib import messages from django.contrib import messages
from django.http import Http404, HttpResponseRedirect
from django.views.generic.detail import SingleObjectMixin
from django.core.urlresolvers import reverse_lazy
class TeamListView(CampViewMixin, ListView): class TeamListView(CampViewMixin, ListView):
@ -13,9 +17,10 @@ class TeamListView(CampViewMixin, ListView):
context_object_name = 'teams' context_object_name = 'teams'
class TeamDetailView(CampViewMixin, DetailView): class TeamDetailView(CampViewMixin, DetailView, UpdateView, FormView):
template_name = "team_detail.html" template_name = "team_detail.html"
model = Team model = Team
form_class = ManageTeamForm
context_object_name = 'team' context_object_name = 'team'
@ -58,3 +63,38 @@ class TeamLeaveView(LoginRequiredMixin, CampViewMixin, UpdateView):
messages.success(self.request, "You are no longer a member of the team %s" % self.get_object().name) 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) return redirect('team_list', camp_slug=self.get_object().camp.slug)
class EnsureTeamResponsibleMixin(SingleObjectMixin):
model = TeamMember
def dispatch(self, request, *args, **kwargs):
if request.user not 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)
class TeamMemberApproveView(LoginRequiredMixin, EnsureTeamResponsibleMixin, UpdateView):
template_name = "teammember_approve.html"
model = TeamMember
fields = []
def form_valid(self, form):
form.instance.approved = True
form.instance.save()
messages.success(self.request, "Team member approved")
return redirect('team_detail', camp_slug=form.instance.team.camp.slug, slug=form.instance.team.slug)