Comments on tasks.
This commit is contained in:
parent
3d5645a10e
commit
d9b7668ea8
29
src/teams/migrations/0047_taskcomment.py
Normal file
29
src/teams/migrations/0047_taskcomment.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# Generated by Django 2.1 on 2018-08-14 17:42
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('teams', '0046_auto_20180808_2154'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='TaskComment',
|
||||||
|
fields=[
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated', models.DateTimeField(auto_now=True)),
|
||||||
|
('content', models.TextField()),
|
||||||
|
('author', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='teams.TeamMember')),
|
||||||
|
('task', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='comments', to='teams.TeamTask')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
18
src/teams/migrations/0048_auto_20180814_1950.py
Normal file
18
src/teams/migrations/0048_auto_20180814_1950.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 2.1 on 2018-08-14 17:50
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('teams', '0047_taskcomment'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='taskcomment',
|
||||||
|
old_name='content',
|
||||||
|
new_name='comment',
|
||||||
|
),
|
||||||
|
]
|
|
@ -9,7 +9,7 @@ from django.urls import reverse_lazy
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.postgres.fields import DateTimeRangeField
|
from django.contrib.postgres.fields import DateTimeRangeField
|
||||||
|
|
||||||
from utils.models import CampRelatedModel
|
from utils.models import CampRelatedModel, CreatedUpdatedModel, UUIDModel
|
||||||
|
|
||||||
logger = logging.getLogger("bornhack.%s" % __name__)
|
logger = logging.getLogger("bornhack.%s" % __name__)
|
||||||
|
|
||||||
|
@ -320,6 +320,12 @@ class TeamTask(CampRelatedModel):
|
||||||
super().save(**kwargs)
|
super().save(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class TaskComment(UUIDModel, CreatedUpdatedModel):
|
||||||
|
task = models.ForeignKey('teams.TeamTask', on_delete=models.PROTECT, related_name="comments")
|
||||||
|
author = models.ForeignKey('teams.TeamMember', on_delete=models.PROTECT)
|
||||||
|
comment = models.TextField()
|
||||||
|
|
||||||
|
|
||||||
class TeamShift(CampRelatedModel):
|
class TeamShift(CampRelatedModel):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% extends 'team_base.html' %}
|
{% extends 'team_base.html' %}
|
||||||
{% load commonmark %}
|
{% load commonmark %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ task.name }}
|
{{ task.name }}
|
||||||
|
@ -16,7 +17,31 @@
|
||||||
<li>Finish: {{ task.when.upper|default:"N/A" }}<br>
|
<li>Finish: {{ task.when.upper|default:"N/A" }}<br>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-footer"><i>This task belongs to the <a href="{% url 'teams:general' team_slug=task.team.slug camp_slug=task.team.camp.slug %}">{{ task.team.name }} Team</a></i></div>
|
{% if user in task.team.members.all %}
|
||||||
|
<div class="panel-footer panel-heading">
|
||||||
|
<h4>Comments</h4>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<ul class="list-group">
|
||||||
|
{% for comment in task.comments.all %}
|
||||||
|
<li class="list-group-item">
|
||||||
|
<strong>{{ comment.author.user.username }}</strong>: {{ comment.comment }}
|
||||||
|
</li>
|
||||||
|
{% empty %}
|
||||||
|
<li class="list-group-item">
|
||||||
|
No comments
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
<hr />
|
||||||
|
<form method="POST">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% bootstrap_form comment_form %}
|
||||||
|
<button type="submit" class="btn btn-primary pull-right">Comment</button>
|
||||||
|
<span class="clearfix"></span>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
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, HttpResponseNotAllowed
|
||||||
from django.views.generic import DetailView, CreateView, UpdateView
|
from django.views.generic import DetailView, CreateView, UpdateView
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.views.generic.edit import ProcessFormView
|
||||||
|
|
||||||
from camps.mixins import CampViewMixin
|
from camps.mixins import CampViewMixin
|
||||||
from ..models import Team, TeamTask
|
from ..models import Team, TeamTask, TaskComment, TeamMember
|
||||||
from .mixins import EnsureTeamResponsibleMixin, TeamViewMixin
|
from .mixins import EnsureTeamResponsibleMixin, TeamViewMixin
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,12 +18,39 @@ class TeamTasksView(CampViewMixin, DetailView):
|
||||||
active_menu = 'tasks'
|
active_menu = 'tasks'
|
||||||
|
|
||||||
|
|
||||||
|
class TaskCommentForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = TaskComment
|
||||||
|
fields = ['comment']
|
||||||
|
|
||||||
|
|
||||||
class TaskDetailView(CampViewMixin, TeamViewMixin, DetailView):
|
class TaskDetailView(CampViewMixin, TeamViewMixin, DetailView):
|
||||||
template_name = "task_detail.html"
|
template_name = "task_detail.html"
|
||||||
context_object_name = "task"
|
context_object_name = "task"
|
||||||
model = TeamTask
|
model = TeamTask
|
||||||
active_menu = 'tasks'
|
active_menu = 'tasks'
|
||||||
|
|
||||||
|
def get_context_data(self, *args, **kwargs):
|
||||||
|
context = super().get_context_data(*args, **kwargs)
|
||||||
|
context['comment_form'] = TaskCommentForm()
|
||||||
|
return context
|
||||||
|
|
||||||
|
def post(self, request, **kwargs):
|
||||||
|
task = self.get_object()
|
||||||
|
if request.user not in task.team.members.all():
|
||||||
|
return HttpResponseNotAllowed('Nope')
|
||||||
|
|
||||||
|
form = TaskCommentForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
comment = form.save(commit=False)
|
||||||
|
comment.author = TeamMember.objects.get(user=request.user, team=task.team)
|
||||||
|
comment.task = task
|
||||||
|
comment.save()
|
||||||
|
else:
|
||||||
|
messages.error(request, "Something went wrong.")
|
||||||
|
|
||||||
|
return HttpResponseRedirect(task.get_absolute_url())
|
||||||
|
|
||||||
|
|
||||||
class TaskForm(forms.ModelForm):
|
class TaskForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
Loading…
Reference in a new issue