split team management into seperate page, fix a few small things
This commit is contained in:
parent
f2ad740ca2
commit
0007e5424c
|
@ -305,6 +305,11 @@ urlpatterns = [
|
||||||
TeamLeaveView.as_view(),
|
TeamLeaveView.as_view(),
|
||||||
name='team_leave'
|
name='team_leave'
|
||||||
),
|
),
|
||||||
|
url(
|
||||||
|
r'(?P<slug>[-_\w+]+)/manage/$',
|
||||||
|
TeamManageView.as_view(),
|
||||||
|
name='team_manage'
|
||||||
|
),
|
||||||
# this has to be the last url in the list
|
# this has to be the last url in the list
|
||||||
url(
|
url(
|
||||||
r'(?P<slug>[-_\w+]+)/$',
|
r'(?P<slug>[-_\w+]+)/$',
|
||||||
|
|
|
@ -3,12 +3,24 @@ from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
|
|
||||||
class CampViewMixin(object):
|
class CampViewMixin(object):
|
||||||
|
"""
|
||||||
|
This mixin makes sure self.camp is available (taken from url kwarg camp_slug)
|
||||||
|
It also filters out objects that belong to other camps when the queryset has
|
||||||
|
a direct relation to the Camp model.
|
||||||
|
"""
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
self.camp = get_object_or_404(Camp, slug=self.kwargs['camp_slug'])
|
self.camp = get_object_or_404(Camp, slug=self.kwargs['camp_slug'])
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
queryset = super(CampViewMixin, self).get_queryset()
|
queryset = super(CampViewMixin, self).get_queryset()
|
||||||
|
if queryset:
|
||||||
|
# check if we have a foreignkey to Camp, filter if so
|
||||||
|
for field in queryset.model._meta.fields:
|
||||||
|
if field.name=="camp" and field.related_model._meta.label == "camps.Camp":
|
||||||
return queryset.filter(camp=self.camp)
|
return queryset.filter(camp=self.camp)
|
||||||
|
|
||||||
|
# Camp relation not found, or queryset is empty, return it unaltered
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ Team: {{ team.name }} | {{ block.super }}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h3>{{ team.name }} Team</h3>
|
<h3>{{ team.name }} Team ({{ team.area.name }} area)</h3>
|
||||||
|
|
||||||
{{ team.description|unsafecommonmark }}
|
{{ team.description|unsafecommonmark }}
|
||||||
<p>Currently {{ team.members.count }} people are members of this team{% if request.user in team.members.all %} (including you){% endif %}.</p>
|
<p>Currently {{ team.members.count }} people are members of this team{% if request.user in team.members.all %} (including you){% endif %}.</p>
|
||||||
|
@ -26,73 +26,16 @@ Team: {{ team.name }} | {{ block.super }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if request.user in team.responsible.all %}
|
||||||
|
<a href="{% url 'team_manage' camp_slug=camp.slug slug=team.slug %}" class="btn btn-success">Manage Team</a>
|
||||||
|
{% endif %}
|
||||||
<hr />
|
<hr />
|
||||||
<h3>{{ team.area.name }} Area:</h3>
|
<h3>Team Responsible</h3>
|
||||||
<p>This team is under the <b>{{ team.area.name }} area</b>. The following people are responsible for the <b>{{ team.name }} team</b>:</p>
|
<p>The following people are responsible for the <b>{{ team.name }} team</b>:</p>
|
||||||
<ul>
|
<ul>
|
||||||
{% for resp in team.responsible.all %}
|
{% for resp in team.responsible.all %}
|
||||||
<li><b>{{ resp.profile.name }}</b></li>
|
<li><b>{{ resp.profile.name }}</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 %}
|
||||||
|
|
|
@ -63,11 +63,15 @@ Teams | {{ block.super }}
|
||||||
<a href="{% url 'team_leave' camp_slug=camp.slug slug=team.slug %}" class="btn btn-danger"><i class="fa fa-minus"></i> Leave</a>
|
<a href="{% url 'team_leave' camp_slug=camp.slug slug=team.slug %}" class="btn btn-danger"><i class="fa fa-minus"></i> Leave</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if team.needs_members %}
|
{% if team.needs_members %}
|
||||||
<a href="{% url 'team_join' camp_slug=camp.slug slug=team.slug %}" class="btn btn-success"><i class="fa fa-plus"></i> Join</button>
|
<a href="{% url 'team_join' camp_slug=camp.slug slug=team.slug %}" class="btn btn-success"><i class="fa fa-plus"></i> Join</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i>Team does not need members</i>
|
<i>Team does not need members</i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if request.user in team.responsible.all %}
|
||||||
|
<a href="{% url 'team_manage' camp_slug=camp.slug slug=team.slug %}" class="btn btn-primary"><i class="fa fa-cog"></i> Manage</a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
{% else %}
|
{% else %}
|
||||||
<td>Login to join!</td>
|
<td>Login to join!</td>
|
||||||
|
|
61
src/teams/templates/team_manage.html
Normal file
61
src/teams/templates/team_manage.html
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load commonmark %}
|
||||||
|
{% load teams_tags %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Manage Team: {{ team.name }} | {{ block.super }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3>Manage {{ team.name }} Team</h3>
|
||||||
|
<form method="post" class="form-horizontal">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
|
||||||
|
|
||||||
|
{% buttons %}
|
||||||
|
<button class="btn btn-primary pull-right" type="submit">Save</button>
|
||||||
|
{% endbuttons %}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h3>{{ team.name }} Team Members</h3>
|
||||||
|
<table class="table table-bordered table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Profile
|
||||||
|
<th>
|
||||||
|
Name
|
||||||
|
<th>
|
||||||
|
Email
|
||||||
|
<th>
|
||||||
|
Description
|
||||||
|
<th>
|
||||||
|
Membership
|
||||||
|
<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 %}
|
||||||
|
{% endblock %}
|
|
@ -14,17 +14,38 @@ import logging
|
||||||
logger = logging.getLogger("bornhack.%s" % __name__)
|
logger = logging.getLogger("bornhack.%s" % __name__)
|
||||||
|
|
||||||
|
|
||||||
|
class EnsureTeamResponsibleMixin(SingleObjectMixin):
|
||||||
|
model = Team
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
if request.user not in self.get_object().responsible.all():
|
||||||
|
messages.error(request, 'No thanks')
|
||||||
|
return redirect('team_detail', camp_slug=self.camp.slug, slug=self.get_object().slug)
|
||||||
|
|
||||||
|
return super().dispatch(
|
||||||
|
request, *args, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TeamListView(CampViewMixin, ListView):
|
class TeamListView(CampViewMixin, ListView):
|
||||||
template_name = "team_list.html"
|
template_name = "team_list.html"
|
||||||
model = Team
|
model = Team
|
||||||
context_object_name = 'teams'
|
context_object_name = 'teams'
|
||||||
|
|
||||||
|
|
||||||
class TeamDetailView(CampViewMixin, DetailView, UpdateView, FormView):
|
class TeamDetailView(CampViewMixin, DetailView):
|
||||||
template_name = "team_detail.html"
|
template_name = "team_detail.html"
|
||||||
model = Team
|
|
||||||
form_class = ManageTeamForm
|
|
||||||
context_object_name = 'team'
|
context_object_name = 'team'
|
||||||
|
model = Team
|
||||||
|
|
||||||
|
|
||||||
|
class TeamManageView(CampViewMixin, EnsureTeamResponsibleMixin, UpdateView):
|
||||||
|
model = Team
|
||||||
|
template_name = "team_manage.html"
|
||||||
|
fields = ['description', 'needs_members']
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return reverse_lazy('team_detail', kwargs={'camp_slug': self.camp.slug, 'slug': self.get_object().slug})
|
||||||
|
|
||||||
|
|
||||||
class TeamJoinView(LoginRequiredMixin, CampViewMixin, UpdateView):
|
class TeamJoinView(LoginRequiredMixin, CampViewMixin, UpdateView):
|
||||||
|
@ -67,20 +88,20 @@ class TeamLeaveView(LoginRequiredMixin, CampViewMixin, UpdateView):
|
||||||
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):
|
class EnsureTeamMemberResponsibleMixin(SingleObjectMixin):
|
||||||
model = TeamMember
|
model = TeamMember
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
if request.user not in self.get_object().team.responsible.all():
|
if request.user not in self.get_object().team.responsible.all():
|
||||||
messages.error(request, 'No thanks')
|
messages.error(request, 'No thanks')
|
||||||
return HttpResponseRedirect(reverse_lazy('team_detail', slug=self.get_object().team.slug))
|
return redirect('team_detail', camp_slug=self.get_object().team.camp.slug, slug=self.get_object().team.slug)
|
||||||
|
|
||||||
return super().dispatch(
|
return super().dispatch(
|
||||||
request, *args, **kwargs
|
request, *args, **kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TeamMemberRemoveView(LoginRequiredMixin, EnsureTeamResponsibleMixin, UpdateView):
|
class TeamMemberRemoveView(LoginRequiredMixin, CampViewMixin, EnsureTeamMemberResponsibleMixin, UpdateView):
|
||||||
template_name = "teammember_remove.html"
|
template_name = "teammember_remove.html"
|
||||||
model = TeamMember
|
model = TeamMember
|
||||||
fields = []
|
fields = []
|
||||||
|
@ -94,10 +115,10 @@ class TeamMemberRemoveView(LoginRequiredMixin, EnsureTeamResponsibleMixin, Updat
|
||||||
logger.error(
|
logger.error(
|
||||||
'Unable to add removed email to outgoing queue for teammember: {}'.format(form.instance)
|
'Unable to add removed email to outgoing queue for teammember: {}'.format(form.instance)
|
||||||
)
|
)
|
||||||
return redirect('team_detail', camp_slug=form.instance.team.camp.slug, slug=form.instance.team.slug)
|
return redirect('team_detail', camp_slug=self.camp.slug, slug=form.instance.team.slug)
|
||||||
|
|
||||||
|
|
||||||
class TeamMemberApproveView(LoginRequiredMixin, EnsureTeamResponsibleMixin, UpdateView):
|
class TeamMemberApproveView(LoginRequiredMixin, CampViewMixin, EnsureTeamMemberResponsibleMixin, UpdateView):
|
||||||
template_name = "teammember_approve.html"
|
template_name = "teammember_approve.html"
|
||||||
model = TeamMember
|
model = TeamMember
|
||||||
fields = []
|
fields = []
|
||||||
|
@ -112,4 +133,5 @@ class TeamMemberApproveView(LoginRequiredMixin, EnsureTeamResponsibleMixin, Upda
|
||||||
logger.error(
|
logger.error(
|
||||||
'Unable to add approved email to outgoing queue for teammember: {}'.format(form.instance)
|
'Unable to add approved email to outgoing queue for teammember: {}'.format(form.instance)
|
||||||
)
|
)
|
||||||
return redirect('team_detail', camp_slug=form.instance.team.camp.slug, slug=form.instance.team.slug)
|
return redirect('team_detail', camp_slug=self.camp.slug, slug=form.instance.team.slug)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue