Add shortcut to users teams. Add a overview of users shifts, and prevent user from taking a shift which overlaps with one already assigned to the user.
This commit is contained in:
parent
a3bfd85604
commit
da639ff4cd
|
@ -7,13 +7,47 @@ Teams | {{ block.super }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h3>{{ camp.title }} Teams</h3>
|
<h3>{{ camp.title }} Teams</h3>
|
||||||
<p>This is a list of the teams for {{ camp.title }}. To join a team just press the Join button, but please put some info in your <a href="{% url 'profiles:detail' %}">profile</a> first, so the team responsible has some idea who you are.</p>
|
|
||||||
<p>You can also leave a team of course, but please let the team responsible know why :)</p>
|
<div class="row">
|
||||||
<p>Team memberships need to be approved by a team responsible. You will receive a message when your membership has been approved.</p>
|
<div class="col-md-{% if user.is_authenticated %}6{% else %}12{% endif %}">
|
||||||
<p>At {{ camp.title }} all organisers and volunteers buy full tickets like everyone else. At future events our budget may allow for discounts or free tickets for volunteers, but currently it does not.</p>
|
<h4>About teams</h4>
|
||||||
<p>We currently have {{ teams.count }} teams for {{ camp.title }}:</p>
|
<p>This is a list of the teams for {{ camp.title }}. To join a team just press the Join button, but please put some info in your <a href="{% url 'profiles:detail' %}">profile</a> first, so the team responsible has some idea who you are.</p>
|
||||||
|
<p>You can also leave a team of course, but please let the team responsible know why :)</p>
|
||||||
|
<p>Team memberships neesdf be approved by a team responsible. You will receive a message when your membership has been approved.</p>
|
||||||
|
<p>At {{ camp.title }} all organisers and volunteers buy full tickets like everyone else. At future events our budget may allow for discounts or free tickets for volunteers, but currently it does not.</p>
|
||||||
|
<p>We currently have {{ teams.count }} teams for {{ camp.title }}.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div>
|
||||||
|
<h4>Your teams</h4>
|
||||||
|
</div>
|
||||||
|
{% if user_teams %}
|
||||||
|
<ul>
|
||||||
|
{% for team_member in user_teams %}
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'teams:general' camp_slug=camp.slug team_slug=team_member.team.slug %}">
|
||||||
|
{{ team_member.team.name }}
|
||||||
|
{% if team_member.responsible %}
|
||||||
|
(Responsible)
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
<a href="{% url 'teams:user_shifts' camp_slug=camp.slug %}" class="btn btn-primary">
|
||||||
|
Manage shifts
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
You are not on any teams.
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if teams %}
|
{% if teams %}
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
|
|
44
src/teams/templates/team_user_shifts.html
Normal file
44
src/teams/templates/team_user_shifts.html
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h3>Your shifts</h3>
|
||||||
|
|
||||||
|
<table class="table table-condensed">
|
||||||
|
<tbody>
|
||||||
|
{% for shift in user_shifts %}
|
||||||
|
{% ifchanged shift.shift_range.lower|date:'d' %}
|
||||||
|
<tr>
|
||||||
|
<td colspan=4>
|
||||||
|
<h4>
|
||||||
|
{{ shift.shift_range.lower|date:'Y-m-d l' }}
|
||||||
|
</h4>
|
||||||
|
<tr>
|
||||||
|
<th>Team</th>
|
||||||
|
<th>Start</th>
|
||||||
|
<th>End</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
{% endifchanged %}
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{{ shift.team.name }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ shift.shift_range.lower|date:'H:i' }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ shift.shift_range.upper|date:'H:i' }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a class="btn btn-danger"
|
||||||
|
href="{% url 'teams:shift_member_drop' camp_slug=camp.slug team_slug=shift.team.slug pk=shift.pk %}">
|
||||||
|
<i class="fas fa-thumbs-down"></i> Unassign me
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -37,6 +37,7 @@ from teams.views.shifts import (
|
||||||
ShiftDeleteView,
|
ShiftDeleteView,
|
||||||
MemberTakesShift,
|
MemberTakesShift,
|
||||||
MemberDropsShift,
|
MemberDropsShift,
|
||||||
|
UserShifts,
|
||||||
)
|
)
|
||||||
|
|
||||||
app_name = 'teams'
|
app_name = 'teams'
|
||||||
|
@ -47,6 +48,11 @@ urlpatterns = [
|
||||||
TeamListView.as_view(),
|
TeamListView.as_view(),
|
||||||
name='list'
|
name='list'
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
'shifts',
|
||||||
|
UserShifts.as_view(),
|
||||||
|
name='user_shifts'
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
'<slug:team_slug>/', include([
|
'<slug:team_slug>/', include([
|
||||||
path(
|
path(
|
||||||
|
|
|
@ -19,6 +19,12 @@ class TeamListView(CampViewMixin, ListView):
|
||||||
model = Team
|
model = Team
|
||||||
context_object_name = 'teams'
|
context_object_name = 'teams'
|
||||||
|
|
||||||
|
def get_context_data(self, *, object_list=None, **kwargs):
|
||||||
|
context = super().get_context_data(object_list=object_list, **kwargs)
|
||||||
|
if self.request.user.is_authenticated:
|
||||||
|
context['user_teams'] = self.request.user.teammember_set.filter(team__camp=self.camp)
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class TeamGeneralView(CampViewMixin, DetailView):
|
class TeamGeneralView(CampViewMixin, DetailView):
|
||||||
template_name = "team_general.html"
|
template_name = "team_general.html"
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
from django.contrib import messages
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.template import Template, Context
|
||||||
from django.views.generic import (
|
from django.views.generic import (
|
||||||
View,
|
View,
|
||||||
CreateView,
|
CreateView,
|
||||||
|
@ -7,9 +9,9 @@ from django.views.generic import (
|
||||||
ListView,
|
ListView,
|
||||||
FormView,
|
FormView,
|
||||||
DeleteView,
|
DeleteView,
|
||||||
|
TemplateView
|
||||||
)
|
)
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.postgres.forms.ranges import RangeWidget
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
|
@ -299,6 +301,24 @@ class MemberTakesShift(LoginRequiredMixin, CampViewMixin, View):
|
||||||
|
|
||||||
team_member = TeamMember.objects.get(team=team, user=request.user)
|
team_member = TeamMember.objects.get(team=team, user=request.user)
|
||||||
|
|
||||||
|
overlapping_shifts = TeamShift.objects.filter(
|
||||||
|
team__camp=self.camp,
|
||||||
|
team_members__user=request.user,
|
||||||
|
shift_range__overlap=shift.shift_range
|
||||||
|
)
|
||||||
|
|
||||||
|
if overlapping_shifts.exists():
|
||||||
|
template = Template("""You have shifts overlapping with the one you are trying to assign:<br/> <ul>
|
||||||
|
{% for shift in shifts %}
|
||||||
|
<li>{{ shift }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
""")
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
template.render(Context({"shifts": overlapping_shifts}))
|
||||||
|
)
|
||||||
|
else:
|
||||||
shift.team_members.add(team_member)
|
shift.team_members.add(team_member)
|
||||||
|
|
||||||
kwargs.pop('pk')
|
kwargs.pop('pk')
|
||||||
|
@ -334,3 +354,16 @@ class MemberDropsShift(LoginRequiredMixin, CampViewMixin, View):
|
||||||
kwargs=kwargs
|
kwargs=kwargs
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class UserShifts(CampViewMixin, TemplateView):
|
||||||
|
template_name = 'team_user_shifts.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context['user_teams'] = self.request.user.teammember_set.filter(team__camp=self.camp)
|
||||||
|
context['user_shifts'] = TeamShift.objects.filter(
|
||||||
|
team__camp=self.camp,
|
||||||
|
team_members__user=self.request.user
|
||||||
|
)
|
||||||
|
return context
|
Loading…
Reference in a new issue