add teamtask support
This commit is contained in:
parent
d4265edaa0
commit
142afa5ead
|
@ -10,7 +10,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h2>Infodesk Backoffice</h2>
|
<h2>Infodesk Backoffice</h2>
|
||||||
<div class="lead">
|
<div class="lead">
|
||||||
Orders with one or more Products that are not handed out
|
Paid (and not later refunded) orders with at least one product that is not yet handed out
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -297,6 +297,7 @@ urlpatterns = [
|
||||||
VillageUpdateView.as_view(),
|
VillageUpdateView.as_view(),
|
||||||
name='village_update'
|
name='village_update'
|
||||||
),
|
),
|
||||||
|
# this has to be the last url in the list
|
||||||
url(
|
url(
|
||||||
r'(?P<slug>[-_\w+]+)/$',
|
r'(?P<slug>[-_\w+]+)/$',
|
||||||
VillageDetailView.as_view(),
|
VillageDetailView.as_view(),
|
||||||
|
@ -306,45 +307,11 @@ urlpatterns = [
|
||||||
),
|
),
|
||||||
|
|
||||||
url(
|
url(
|
||||||
r'^teams/', include([
|
r'^teams/',
|
||||||
url(
|
include('teams.urls', namespace='teams')
|
||||||
r'^$',
|
|
||||||
TeamListView.as_view(),
|
|
||||||
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(
|
|
||||||
r'(?P<slug>[-_\w+]+)/join/$',
|
|
||||||
TeamJoinView.as_view(),
|
|
||||||
name='team_join'
|
|
||||||
),
|
|
||||||
url(
|
|
||||||
r'(?P<slug>[-_\w+]+)/leave/$',
|
|
||||||
TeamLeaveView.as_view(),
|
|
||||||
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
|
|
||||||
url(
|
|
||||||
r'(?P<slug>[-_\w+]+)/$',
|
|
||||||
TeamDetailView.as_view(),
|
|
||||||
name='team_detail'
|
|
||||||
),
|
|
||||||
])
|
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-9 col-sm-9 text-container">
|
<div class="col-md-9 col-sm-9 text-container">
|
||||||
<div class="lead">
|
<div class="lead">
|
||||||
The BornHack team looks forward to organising another great event for the hacker community. We <a href="{% url 'team_list' camp_slug=camp.slug %}">still need volunteers</a>, so please let us know if you want to help!
|
The BornHack team looks forward to organising another great event for the hacker community. We <a href="{% url 'teams:list' camp_slug=camp.slug %}">still need volunteers</a>, so please let us know if you want to help!
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-9 col-sm-9 text-container">
|
<div class="col-md-9 col-sm-9 text-container">
|
||||||
<div class="lead">
|
<div class="lead">
|
||||||
The BornHack team looks forward to organising another great event for the hacker community. We <a href="{% url 'team_list' camp_slug=camp.slug %}">still need volunteers</a>, so please let us know if you want to help!
|
The BornHack team looks forward to organising another great event for the hacker community. We <a href="{% url 'teams:list' camp_slug=camp.slug %}">still need volunteers</a>, so please let us know if you want to help!
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-9 col-sm-9 text-container">
|
<div class="col-md-9 col-sm-9 text-container">
|
||||||
<div class="lead">
|
<div class="lead">
|
||||||
The BornHack team looks forward to organising another great event for the hacker community. We <a href="{% url 'team_list' camp_slug=camp.slug %}">still need volunteers</a>, so please let us know if you want to help!
|
The BornHack team looks forward to organising another great event for the hacker community. We <a href="{% url 'teams:list' camp_slug=camp.slug %}">still need volunteers</a>, so please let us know if you want to help!
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
|
|
|
@ -1,8 +1,18 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from .models import Team, TeamArea, TeamMember
|
from .models import Team, TeamArea, TeamMember, TeamTask
|
||||||
from .email import add_added_membership_email, add_removed_membership_email
|
from .email import add_added_membership_email, add_removed_membership_email
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(TeamTask)
|
||||||
|
class TeamTaskAdmin(admin.ModelAdmin):
|
||||||
|
list_display = [
|
||||||
|
'id',
|
||||||
|
'team',
|
||||||
|
'name',
|
||||||
|
'description',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Team)
|
@admin.register(Team)
|
||||||
class TeamAdmin(admin.ModelAdmin):
|
class TeamAdmin(admin.ModelAdmin):
|
||||||
def get_responsible(self, obj):
|
def get_responsible(self, obj):
|
||||||
|
|
35
src/teams/migrations/0017_auto_20171122_1928.py
Normal file
35
src/teams/migrations/0017_auto_20171122_1928.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2017-11-22 18:28
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('teams', '0016_auto_20170711_2247'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='TeamTask',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated', models.DateTimeField(auto_now=True)),
|
||||||
|
('name', models.CharField(help_text='Short name of this task', max_length=100)),
|
||||||
|
('slug', models.SlugField(blank=True, help_text='url slug, leave blank to autogenerate', max_length=255)),
|
||||||
|
('description', models.TextField(help_text='Description of the task. Markdown is supported.')),
|
||||||
|
('team', models.ForeignKey(help_text='The team this task belongs to', on_delete=django.db.models.deletion.CASCADE, to='teams.Team')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['name'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='teamtask',
|
||||||
|
unique_together=set([('slug', 'team'), ('name', 'team')]),
|
||||||
|
),
|
||||||
|
]
|
21
src/teams/migrations/0018_auto_20171122_2204.py
Normal file
21
src/teams/migrations/0018_auto_20171122_2204.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2017-11-22 21:04
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('teams', '0017_auto_20171122_1928'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='teamtask',
|
||||||
|
name='team',
|
||||||
|
field=models.ForeignKey(help_text='The team this task belongs to', on_delete=django.db.models.deletion.CASCADE, related_name='tasks', to='teams.Team'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -115,3 +115,38 @@ def add_responsible_email(sender, instance, created, **kwargs):
|
||||||
if created:
|
if created:
|
||||||
if not add_new_membership_email(instance):
|
if not add_new_membership_email(instance):
|
||||||
logger.error('Error adding email to outgoing queue')
|
logger.error('Error adding email to outgoing queue')
|
||||||
|
|
||||||
|
|
||||||
|
class TeamTask(CampRelatedModel):
|
||||||
|
team = models.ForeignKey(
|
||||||
|
'teams.Team',
|
||||||
|
related_name='tasks',
|
||||||
|
help_text='The team this task belongs to',
|
||||||
|
)
|
||||||
|
name = models.CharField(
|
||||||
|
max_length=100,
|
||||||
|
help_text='Short name of this task',
|
||||||
|
)
|
||||||
|
slug = models.SlugField(
|
||||||
|
max_length=255,
|
||||||
|
blank=True,
|
||||||
|
help_text='url slug, leave blank to autogenerate',
|
||||||
|
)
|
||||||
|
description = models.TextField(
|
||||||
|
help_text='Description of the task. Markdown is supported.'
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ['name']
|
||||||
|
unique_together = (('name', 'team'), ('slug', 'team'))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def camp(self):
|
||||||
|
return self.team.camp
|
||||||
|
|
||||||
|
def save(self, **kwargs):
|
||||||
|
if not self.slug:
|
||||||
|
slug = slugify(self.name)
|
||||||
|
self.slug = slug
|
||||||
|
super().save(**kwargs)
|
||||||
|
|
||||||
|
|
17
src/teams/templates/task_detail.html
Normal file
17
src/teams/templates/task_detail.html
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load commonmark %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{{ task.name }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading"><h4>Task: {{ task.name }}</h4></div>
|
||||||
|
<div class="panel-body">{{ task.description|commonmark }}</div>
|
||||||
|
<div class="panel-footer"><i>This task belongs to the <a href="{% url 'teams:detail' slug=task.team.slug camp_slug=task.team.camp.slug %}">{{ task.team.name }} Team</a></i></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -9,29 +9,18 @@ Team: {{ team.name }} | {{ block.super }}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h3>{{ team.name }} Team ({{ team.area.name }} area)</h3>
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading"><h4>{{ team.name }} Team</h4></div>
|
||||||
|
<div class="panel-body">
|
||||||
{{ team.description|unsafecommonmark }}
|
{{ team.description|unsafecommonmark }}
|
||||||
<p>Currently {{ team.approvedmembers.count }} people are members of this team{% if request.user in team.members.all %} (including you){% endif %}.</p>
|
|
||||||
|
|
||||||
{% if request.user in team.members.all %}
|
|
||||||
<p>Your team status: {% membershipstatus request.user team %}</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if request.user in team.members.all %}
|
|
||||||
<a href="{% url 'team_leave' camp_slug=camp.slug slug=team.slug %}" class="btn btn-danger">Leave Team</a>
|
|
||||||
{% else %}
|
|
||||||
{% if team.needs_members %}
|
|
||||||
<a href="{% url 'team_join' camp_slug=camp.slug slug=team.slug %}" class="btn btn-success">Join Team</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if request.user in team.responsible.all %}
|
{% 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>
|
<a href="{% url 'teams:manage' camp_slug=camp.slug slug=team.slug %}" class="btn btn-success">Manage Team</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<hr />
|
|
||||||
<h3>Team Members</h3>
|
<hr>
|
||||||
<p>The following people are members of the <b>{{ team.name }} team</b>:</p>
|
|
||||||
|
<h3>Members</h3>
|
||||||
|
<p>The following <b>{{ team.approvedmembers.count }}</b> people are members of the <b>{{ team.name }} team</b>:</p>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -45,20 +34,56 @@ Team: {{ team.name }} | {{ block.super }}
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for teammember in team.approvedmembers.all %}
|
{% for teammember in team.approvedmembers.all %}
|
||||||
{% if teammember.user.profile.approved_public_credit_name and teammember.approved or teammember.responsible %}
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
{% if teammember.user.profile.approved_public_credit_name %}
|
||||||
{{ teammember.user.profile.approved_public_credit_name }}
|
{{ teammember.user.profile.approved_public_credit_name }}
|
||||||
|
{% else %}
|
||||||
|
anonymous
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% if teammember.responsible %}Team Responsible{% else %}Team Member{% endif %}
|
{% if teammember.responsible %}Team Responsible{% else %}Team Member{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% if team.anoncount %}
|
|
||||||
<p>Plus <b>{{ team.anoncount }}</b> member(s) who prefer to remain anonymous.</p>
|
{% if request.user in team.members.all %}
|
||||||
|
<p>Your membership status: <b>{% membershipstatus request.user team %}</b></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if request.user in team.members.all %}
|
||||||
|
<a href="{% url 'teams:leave' camp_slug=camp.slug slug=team.slug %}" class="btn btn-danger">Leave Team</a>
|
||||||
|
{% else %}
|
||||||
|
{% if team.needs_members %}
|
||||||
|
<b>This team is looking for members!</b> <a href="{% url 'teams:join' camp_slug=camp.slug slug=team.slug %}" class="btn btn-xs btn-success">Join Team</a>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h3>Tasks</h3>
|
||||||
|
<p>This team is responsible for the following tasks</p>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for task in team.tasks.all %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url 'teams:task_detail' slug=task.slug camp_slug=camp.slug team_slug=team.slug %}">{{ task.name }}</a></td>
|
||||||
|
<td>{{ task.description }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -13,6 +13,6 @@ Join Team: {{ team.name }} | {{ block.super }}
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form }}
|
{{ form }}
|
||||||
<button class="btn btn-success" type="submit"><i class="fa fa-check"></i> Join {{ team.name }} Team</button>
|
<button class="btn btn-success" type="submit"><i class="fa fa-check"></i> Join {{ team.name }} Team</button>
|
||||||
<a href="{% url 'team_list' camp_slug=camp.slug %}" class="btn btn-default" type="submit"><i class="fa fa-remove"></i> Cancel</a>
|
<a href="{% url 'teams:list' camp_slug=camp.slug %}" class="btn btn-default" type="submit"><i class="fa fa-remove"></i> Cancel</a>
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -13,6 +13,6 @@ Leave Team: {{ team.name }} | {{ block.super }}
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form }}
|
{{ form }}
|
||||||
<button class="btn btn-success" type="submit"><i class="fa fa-check"></i> Leave {{ team.name }} Team</button>
|
<button class="btn btn-success" type="submit"><i class="fa fa-check"></i> Leave {{ team.name }} Team</button>
|
||||||
<a href="{% url 'team_list' camp_slug=camp.slug %}" class="btn btn-default" type="submit"><i class="fa fa-remove"></i> Cancel</a>
|
<a href="{% url 'teams:list' camp_slug=camp.slug %}" class="btn btn-default" type="submit"><i class="fa fa-remove"></i> Cancel</a>
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -22,6 +22,7 @@ Teams | {{ block.super }}
|
||||||
<th>Description</th>
|
<th>Description</th>
|
||||||
<th>Responsible</th>
|
<th>Responsible</th>
|
||||||
<th class="text-center">Members</th>
|
<th class="text-center">Members</th>
|
||||||
|
<th class="text-center">Tasks</th>
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<th>Member?</th>
|
<th>Member?</th>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
|
@ -32,7 +33,7 @@ Teams | {{ block.super }}
|
||||||
{% for team in teams %}
|
{% for team in teams %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url 'team_detail' camp_slug=camp.slug slug=team.slug %}">
|
<a href="{% url 'teams:detail' camp_slug=camp.slug slug=team.slug %}">
|
||||||
{{ team.name }} Team
|
{{ team.name }} Team
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
@ -51,6 +52,10 @@ Teams | {{ block.super }}
|
||||||
{% if team.needs_members %}(more needed){% endif %}
|
{% if team.needs_members %}(more needed){% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
<td class="text-center">
|
||||||
|
<span class="badge">{{ team.tasks.count }}</span><br>
|
||||||
|
</td>
|
||||||
|
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
{% membershipstatus request.user team as membership_status %}
|
{% membershipstatus request.user team as membership_status %}
|
||||||
|
@ -67,15 +72,15 @@ Teams | {{ block.super }}
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
{% if request.user in team.members.all %}
|
{% if request.user in team.members.all %}
|
||||||
<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 'teams: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</a>
|
<a href="{% url 'teams:join' camp_slug=camp.slug slug=team.slug %}" class="btn btn-success"><i class="fa fa-plus"></i> Join</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if request.user in team.responsible.all %}
|
{% 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>
|
<a href="{% url 'teams:manage' camp_slug=camp.slug slug=team.slug %}" class="btn btn-primary"><i class="fa fa-cog"></i> Manage</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -71,10 +71,10 @@ Manage Team: {{ team.name }} | {{ block.super }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% if membership.approved %}
|
{% 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>
|
<a class="btn btn-danger" href="{% url 'teams:teammember_remove' camp_slug=camp.slug pk=membership.id %}"><i class="fa fa-trash-o"></i> Remove</a>
|
||||||
{% else %}
|
{% 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-danger" href="{% url 'teams: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>
|
<a class="btn btn-success" href="{% url 'teams:teammember_approve' camp_slug=camp.slug pk=membership.id %}"><i class="fa fa-check"></i> Approve</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -13,6 +13,6 @@ Approve team member {{ teammember.user.profile.name }} for the {{ teammember.tea
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form }}
|
{{ form }}
|
||||||
<button class="btn btn-success" type="submit"><i class="fa fa-check"></i> Add teammember</button>
|
<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>
|
<a href="{% url 'teams: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>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -13,6 +13,6 @@ Remove member {{ teammember.user.profile.name }} from the {{ teammember.team.nam
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form }}
|
{{ form }}
|
||||||
<button class="btn btn-danger" type="submit"><i class="fa fa-trash-o"></i> Remove teammember</button>
|
<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>
|
<a href="{% url 'teams: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>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
47
src/teams/urls.py
Normal file
47
src/teams/urls.py
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
from django.conf.urls import url
|
||||||
|
from .views import *
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(
|
||||||
|
r'^$',
|
||||||
|
TeamListView.as_view(),
|
||||||
|
name='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(
|
||||||
|
r'(?P<team_slug>[-_\w+]+)/tasks/(?P<slug>[-_\w+]+)/$',
|
||||||
|
TaskDetailView.as_view(),
|
||||||
|
name='task_detail',
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
r'(?P<slug>[-_\w+]+)/join/$',
|
||||||
|
TeamJoinView.as_view(),
|
||||||
|
name='join'
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
r'(?P<slug>[-_\w+]+)/leave/$',
|
||||||
|
TeamLeaveView.as_view(),
|
||||||
|
name='leave'
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
r'(?P<slug>[-_\w+]+)/manage/$',
|
||||||
|
TeamManageView.as_view(),
|
||||||
|
name='manage'
|
||||||
|
),
|
||||||
|
# this has to be the last url in the list
|
||||||
|
url(
|
||||||
|
r'(?P<slug>[-_\w+]+)/$',
|
||||||
|
TeamDetailView.as_view(),
|
||||||
|
name='detail'
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from django.views.generic import ListView, DetailView
|
from django.views.generic import ListView, DetailView
|
||||||
from django.views.generic.edit import UpdateView, FormView
|
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, TeamTask
|
||||||
from .forms import ManageTeamForm
|
from .forms import ManageTeamForm
|
||||||
from .email import add_added_membership_email, add_removed_membership_email
|
from .email import add_added_membership_email, add_removed_membership_email
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
@ -62,22 +62,22 @@ class TeamJoinView(LoginRequiredMixin, CampViewMixin, UpdateView):
|
||||||
request,
|
request,
|
||||||
"Please fill the description in your profile before joining a team"
|
"Please fill the description in your profile before joining a team"
|
||||||
)
|
)
|
||||||
return redirect('team_list', camp_slug=self.camp.slug)
|
return redirect('teams:list', camp_slug=self.camp.slug)
|
||||||
|
|
||||||
if request.user in self.get_object().members.all():
|
if request.user in self.get_object().members.all():
|
||||||
messages.warning(request, "You are already a member of this team")
|
messages.warning(request, "You are already a member of this team")
|
||||||
return redirect('team_list', camp_slug=self.camp.slug)
|
return redirect('teams:list', camp_slug=self.camp.slug)
|
||||||
|
|
||||||
if not self.get_object().needs_members:
|
if not self.get_object().needs_members:
|
||||||
messages.warning(request, "This team does not need members right now")
|
messages.warning(request, "This team does not need members right now")
|
||||||
return redirect('team_list', camp_slug=self.get_object().camp.slug)
|
return redirect('teams:list', camp_slug=self.get_object().camp.slug)
|
||||||
|
|
||||||
return super().get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
TeamMember.objects.create(team=self.get_object(), user=self.request.user)
|
TeamMember.objects.create(team=self.get_object(), user=self.request.user)
|
||||||
messages.success(self.request, "You request to join the team %s has been registered, thank you." % self.get_object().name)
|
messages.success(self.request, "You request to join the team %s has been registered, thank you." % self.get_object().name)
|
||||||
return redirect('team_list', camp_slug=self.get_object().camp.slug)
|
return redirect('teams:list', camp_slug=self.get_object().camp.slug)
|
||||||
|
|
||||||
|
|
||||||
class TeamLeaveView(LoginRequiredMixin, CampViewMixin, UpdateView):
|
class TeamLeaveView(LoginRequiredMixin, CampViewMixin, UpdateView):
|
||||||
|
@ -88,14 +88,14 @@ class TeamLeaveView(LoginRequiredMixin, CampViewMixin, UpdateView):
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
if request.user not in self.get_object().members.all():
|
if request.user not in self.get_object().members.all():
|
||||||
messages.warning(request, "You are not a member of this team")
|
messages.warning(request, "You are not a member of this team")
|
||||||
return redirect('team_list', camp_slug=self.get_object().camp.slug)
|
return redirect('teams:list', camp_slug=self.get_object().camp.slug)
|
||||||
|
|
||||||
return super().get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
TeamMember.objects.filter(team=self.get_object(), user=self.request.user).delete()
|
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)
|
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('teams:list', camp_slug=self.get_object().camp.slug)
|
||||||
|
|
||||||
|
|
||||||
class EnsureTeamMemberResponsibleMixin(SingleObjectMixin):
|
class EnsureTeamMemberResponsibleMixin(SingleObjectMixin):
|
||||||
|
@ -145,3 +145,9 @@ class TeamMemberApproveView(LoginRequiredMixin, CampViewMixin, EnsureTeamMemberR
|
||||||
)
|
)
|
||||||
return redirect('team_detail', camp_slug=self.camp.slug, slug=form.instance.team.slug)
|
return redirect('team_detail', camp_slug=self.camp.slug, slug=form.instance.team.slug)
|
||||||
|
|
||||||
|
|
||||||
|
class TaskDetailView(CampViewMixin, DetailView):
|
||||||
|
template_name = "task_detail.html"
|
||||||
|
context_object_name = "task"
|
||||||
|
model = TeamTask
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@
|
||||||
<a class="btn {% menubuttonclass 'program' %}" href="{% url 'schedule_index' camp_slug=camp.slug %}">Program</a>
|
<a class="btn {% menubuttonclass 'program' %}" href="{% url 'schedule_index' camp_slug=camp.slug %}">Program</a>
|
||||||
<a class="btn {% menubuttonclass 'villages' %}" href="{% url 'village_list' camp_slug=camp.slug %}">Villages</a>
|
<a class="btn {% menubuttonclass 'villages' %}" href="{% url 'village_list' camp_slug=camp.slug %}">Villages</a>
|
||||||
<a class="btn {% menubuttonclass 'sponsors' %}" href="{% url 'sponsors' camp_slug=camp.slug %}">Sponsors</a>
|
<a class="btn {% menubuttonclass 'sponsors' %}" href="{% url 'sponsors' camp_slug=camp.slug %}">Sponsors</a>
|
||||||
<a class="btn {% menubuttonclass 'teams' %}" href="{% url 'team_list' camp_slug=camp.slug %}">Teams</a>
|
<a class="btn {% menubuttonclass 'teams' %}" href="{% url 'teams:list' camp_slug=camp.slug %}">Teams</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group-vertical visible-xs">
|
<div class="btn-group-vertical visible-xs">
|
||||||
<a class="btn {% menubuttonclass 'camps' %}" href="{% url 'camp_detail' camp_slug=camp.slug %}">{{ camp.title }}</a>
|
<a class="btn {% menubuttonclass 'camps' %}" href="{% url 'camp_detail' camp_slug=camp.slug %}">{{ camp.title }}</a>
|
||||||
|
@ -99,7 +99,7 @@
|
||||||
<a class="btn {% menubuttonclass 'program' %}" href="{% url 'schedule_index' camp_slug=camp.slug %}">Program</a>
|
<a class="btn {% menubuttonclass 'program' %}" href="{% url 'schedule_index' camp_slug=camp.slug %}">Program</a>
|
||||||
<a class="btn {% menubuttonclass 'villages' %}" href="{% url 'village_list' camp_slug=camp.slug %}">Villages</a>
|
<a class="btn {% menubuttonclass 'villages' %}" href="{% url 'village_list' camp_slug=camp.slug %}">Villages</a>
|
||||||
<a class="btn {% menubuttonclass 'sponsors' %}" href="{% url 'sponsors' camp_slug=camp.slug %}">Sponsors</a>
|
<a class="btn {% menubuttonclass 'sponsors' %}" href="{% url 'sponsors' camp_slug=camp.slug %}">Sponsors</a>
|
||||||
<a class="btn {% menubuttonclass 'teams' %}" href="{% url 'team_list' camp_slug=camp.slug %}">Teams</a>
|
<a class="btn {% menubuttonclass 'teams' %}" href="{% url 'teams:list' camp_slug=camp.slug %}">Teams</a>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue