Reorganize views for better clarity. Add editing capabilities for Info Items.

This commit is contained in:
Víðir Valberg Guðmundsson 2018-05-05 00:19:24 +02:00
parent 735f17b1f1
commit b668ac0694
11 changed files with 249 additions and 88 deletions

View file

@ -1,4 +1,5 @@
from django.contrib import admin
from reversion.admin import VersionAdmin
from .models import (
InfoItem,
InfoCategory
@ -6,7 +7,7 @@ from .models import (
@admin.register(InfoItem)
class InfoItemAdmin(admin.ModelAdmin):
class InfoItemAdmin(VersionAdmin):
list_filter = ['category', 'category__camp',]
list_display = ['headline',]

View file

@ -37,6 +37,7 @@ class InfoCategory(CampRelatedModel):
blank=True,
help_text='The team responsible for this info category.',
on_delete=models.PROTECT,
related_name='info_categories'
)
def clean(self):

View file

@ -109,6 +109,9 @@ class Team(CampRelatedModel):
def __str__(self):
return '{} ({})'.format(self.name, self.camp)
def get_absolute_url(self):
return reverse_lazy('teams:detail', kwargs={'camp_slug': self.camp.slug, 'team_slug': self.slug})
def save(self, **kwargs):
# generate slug if needed
if not self.pk or not self.slug:

View file

@ -0,0 +1,35 @@
{% extends 'base.html' %}
{% load commonmark %}
{% load bootstrap3 %}
{% block title %}
{% if form.instance.id %}
Edit Info Item: {{ form.instance.headline }}
{% else %}
Create Info item
{% endif %}
for in {{ form.instance.category.headline }}
{% endblock %}
{% block content %}
<div class="panel panel-default">
<div class="panel-heading">
<h4>
{% if form.instance.id %}
Edit Info Item: {{ form.instance.name }}
{% else %}
Create Info Item
{% endif %}
for in {{ form.instance.category.headline }}
</h4>
</div>
<div class="panel-body">
<form method="POST">
{% csrf_token %}
{% bootstrap_form form %}
<button type="submit" class="btn btn-primary">{% if form.instance.id %}Save{% else %}Create{% endif %}</button>
</form>
</div>
<div class="panel-footer"><i>This info item belongs to the <a href="{% url 'teams:detail' team_slug=team.slug camp_slug=team.camp.slug %}">{{ team.name }} Team</a></i></div>
</div>
{% endblock %}

View file

@ -115,6 +115,41 @@ Team: {{ team.name }} | {{ block.super }}
{% if request.user in team.responsible_members.all %}
<a href="{% url 'teams:task_create' camp_slug=camp.slug team_slug=team.slug %}" class="btn btn-primary"><i class="fa fa-plus"></i> Create Task</a>
{% endif %}
{# Team info categories section - only visible for team responsible #}
{% if request.user in team.responsible_members.all %}
<hr />
<h4>Info categories</h4>
{% for info_category in team.info_categories.all %}
{{ info_category.headline }}
<table class="table table-hover">
<thead>
<tr>
<th>Item name</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for item in info_category.infoitems.all %}
<tr>
<td>{{ item.headline }}</td>
<td>
<a href="{% url 'teams:info_item_update' camp_slug=camp.slug team_slug=team.slug anchor=item.anchor %}"
class="btn btn-primary btn-sm">
<i class="fa fa-edit"></i> Edit Task
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
{% endif %}
</div>
</div>

View file

@ -1,6 +1,22 @@
from django.conf.urls import url, include
from .views import *
from teams.views.base import (
TeamListView,
TeamMemberRemoveView,
TeamMemberApproveView,
TeamDetailView,
TeamJoinView,
TeamLeaveView,
TeamManageView,
FixIrcAclView,
)
from teams.views.info import InfoItemUpdateView
from teams.views.tasks import (
TaskCreateView,
TaskDetailView,
TaskUpdateView,
)
app_name = 'teams'
@ -75,6 +91,24 @@ urlpatterns = [
]),
),
url(
r'^info_items/', include([
url(
r'^(?P<anchor>[-_\w+]+)/', include([
# url(
# r'^$',
# TaskDetailView.as_view(),
# name='task_detail',
# ),
url(
r'^update/$',
InfoItemUpdateView.as_view(),
name='info_item_update',
),
]),
),
])
)
]),
),
]

View file

View file

@ -1,52 +1,22 @@
from django.views.generic import ListView, DetailView
from django.views.generic.edit import CreateView, UpdateView
from django.views.generic.edit import UpdateView
from camps.mixins import CampViewMixin
from .models import Team, TeamMember, TeamTask
from .email import add_added_membership_email, add_removed_membership_email
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import redirect
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.views.generic.detail import SingleObjectMixin
from django.urls import reverse_lazy
from django.conf import settings
from profiles.models import Profile
from .mixins import EnsureTeamResponsibleMixin, EnsureTeamMemberResponsibleMixin
from ..models import Team, TeamMember
from ..email import add_added_membership_email, add_removed_membership_email
import logging
logger = logging.getLogger("bornhack.%s" % __name__)
class EnsureTeamResponsibleMixin(object):
"""
Use to make sure request.user is responsible for the team specified by kwargs['team_slug']
"""
def dispatch(self, request, *args, **kwargs):
self.team = Team.objects.get(slug=kwargs['team_slug'], camp=self.camp)
if request.user not in self.team.responsible_members.all():
messages.error(request, 'No thanks')
return redirect('teams:detail', camp_slug=self.camp.slug, team_slug=self.team.slug)
return super().dispatch(
request, *args, **kwargs
)
class EnsureTeamMemberResponsibleMixin(SingleObjectMixin):
"""
Use to make sure request.user is responsible for the team which TeamMember belongs to
"""
model = TeamMember
def dispatch(self, request, *args, **kwargs):
if request.user not in self.get_object().team.responsible_members.all():
messages.error(request, 'No thanks')
return redirect('teams:detail', camp_slug=self.get_object().team.camp.slug, team_slug=self.get_object().team.slug)
return super().dispatch(
request, *args, **kwargs
)
class TeamListView(CampViewMixin, ListView):
template_name = "team_list.html"
model = Team
@ -165,56 +135,6 @@ class TeamMemberApproveView(LoginRequiredMixin, CampViewMixin, EnsureTeamMemberR
return redirect('teams:detail', camp_slug=self.camp.slug, team_slug=form.instance.team.slug)
class TaskDetailView(CampViewMixin, DetailView):
template_name = "task_detail.html"
context_object_name = "task"
model = TeamTask
class TaskCreateView(LoginRequiredMixin, CampViewMixin, EnsureTeamResponsibleMixin, CreateView):
model = TeamTask
template_name = "task_form.html"
fields = ['name', 'description']
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
context['team'] = self.team
return context
def form_valid(self, form):
task = form.save(commit=False)
task.team = self.team
if not task.name:
task.name = "noname"
task.save()
return HttpResponseRedirect(task.get_absolute_url())
def get_success_url(self):
return self.get_object().get_absolute_url()
class TaskUpdateView(LoginRequiredMixin, CampViewMixin, EnsureTeamResponsibleMixin, UpdateView):
model = TeamTask
template_name = "task_form.html"
fields = ['name', 'description']
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
context['team'] = self.team
return context
def form_valid(self, form):
task = form.save(commit=False)
task.team = self.team
if not task.name:
task.name = "noname"
task.save()
return HttpResponseRedirect(task.get_absolute_url())
def get_success_url(self):
return self.get_object().get_absolute_url()
class FixIrcAclView(LoginRequiredMixin, CampViewMixin, UpdateView):
template_name = "fix_irc_acl.html"
model = Team

39
src/teams/views/info.py Normal file
View file

@ -0,0 +1,39 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView, UpdateView
from reversion.views import RevisionMixin
from camps.mixins import CampViewMixin
from info.models import InfoItem
from teams.views.mixins import EnsureTeamResponsibleMixin
class InfoItemCreateView(LoginRequiredMixin, CampViewMixin, EnsureTeamResponsibleMixin, CreateView):
model = InfoItem
template_name = "info_item_form.html"
fields = ['headline', 'body', 'anchor', 'weight']
slug_field = 'anchor'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
context['team'] = self.object.category.team
return context
def get_success_url(self):
return self.object.category.team.get_absolute_url()
class InfoItemUpdateView(LoginRequiredMixin, CampViewMixin, EnsureTeamResponsibleMixin, RevisionMixin, UpdateView):
model = InfoItem
template_name = "info_item_form.html"
fields = ['headline', 'body', 'anchor', 'weight']
slug_field = 'anchor'
slug_url_kwarg = 'anchor'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
context['team'] = self.object.category.team
return context
def get_success_url(self):
return self.object.category.team.get_absolute_url()

36
src/teams/views/mixins.py Normal file
View file

@ -0,0 +1,36 @@
from django.contrib import messages
from django.shortcuts import redirect
from django.views.generic.detail import SingleObjectMixin
from teams.models import Team, TeamMember
class EnsureTeamResponsibleMixin(object):
"""
Use to make sure request.user is responsible for the team specified by kwargs['team_slug']
"""
def dispatch(self, request, *args, **kwargs):
self.team = Team.objects.get(slug=kwargs['team_slug'], camp=self.camp)
if request.user not in self.team.responsible_members.all():
messages.error(request, 'No thanks')
return redirect('teams:detail', camp_slug=self.camp.slug, team_slug=self.team.slug)
return super().dispatch(
request, *args, **kwargs
)
class EnsureTeamMemberResponsibleMixin(SingleObjectMixin):
"""
Use to make sure request.user is responsible for the team which TeamMember belongs to
"""
model = TeamMember
def dispatch(self, request, *args, **kwargs):
if request.user not in self.get_object().team.responsible_members.all():
messages.error(request, 'No thanks')
return redirect('teams:detail', camp_slug=self.get_object().team.camp.slug, team_slug=self.get_object().team.slug)
return super().dispatch(
request, *args, **kwargs
)

57
src/teams/views/tasks.py Normal file
View file

@ -0,0 +1,57 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseRedirect
from django.views.generic import DetailView, CreateView, UpdateView
from camps.mixins import CampViewMixin
from ..models import TeamTask
from .mixins import EnsureTeamResponsibleMixin
class TaskDetailView(CampViewMixin, DetailView):
template_name = "task_detail.html"
context_object_name = "task"
model = TeamTask
class TaskCreateView(LoginRequiredMixin, CampViewMixin, EnsureTeamResponsibleMixin, CreateView):
model = TeamTask
template_name = "task_form.html"
fields = ['name', 'description']
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
context['team'] = self.team
return context
def form_valid(self, form):
task = form.save(commit=False)
task.team = self.team
if not task.name:
task.name = "noname"
task.save()
return HttpResponseRedirect(task.get_absolute_url())
def get_success_url(self):
return self.get_object().get_absolute_url()
class TaskUpdateView(LoginRequiredMixin, CampViewMixin, EnsureTeamResponsibleMixin, UpdateView):
model = TeamTask
template_name = "task_form.html"
fields = ['name', 'description']
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
context['team'] = self.team
return context
def form_valid(self, form):
task = form.save(commit=False)
task.team = self.team
if not task.name:
task.name = "noname"
task.save()
return HttpResponseRedirect(task.get_absolute_url())
def get_success_url(self):
return self.get_object().get_absolute_url()