|
@@ -8,12 +8,12 @@ from django.core.paginator import Paginator
|
|
|
from django.http.response import HttpResponse
|
|
from django.http.response import HttpResponse
|
|
|
from django.shortcuts import render, get_object_or_404, redirect
|
|
from django.shortcuts import render, get_object_or_404, redirect
|
|
|
from django.urls.base import reverse
|
|
from django.urls.base import reverse
|
|
|
|
|
+from notifications.models import Notification
|
|
|
from notifications.signals import notify
|
|
from notifications.signals import notify
|
|
|
|
|
|
|
|
from main.forms import StoryForm, EpicForm, RegisterForm, ProfileForm, \
|
|
from main.forms import StoryForm, EpicForm, RegisterForm, ProfileForm, \
|
|
|
CommentForm, SprintForm
|
|
CommentForm, SprintForm
|
|
|
from main.models import Story, Epic, Sprint, Comment, Project
|
|
from main.models import Story, Epic, Sprint, Comment, Project
|
|
|
-from notifications.models import Notification
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def register(request):
|
|
def register(request):
|
|
@@ -80,6 +80,7 @@ def sprint_end(request):
|
|
|
current_sprint.retro = request.POST["retro"]
|
|
current_sprint.retro = request.POST["retro"]
|
|
|
current_sprint.closed = True
|
|
current_sprint.closed = True
|
|
|
current_sprint.save()
|
|
current_sprint.save()
|
|
|
|
|
+ notify_sprint_end(current_sprint, next_sprint, request.user)
|
|
|
return redirect("index")
|
|
return redirect("index")
|
|
|
|
|
|
|
|
form = SprintForm(instance=current_sprint)
|
|
form = SprintForm(instance=current_sprint)
|
|
@@ -124,6 +125,10 @@ def story_create(request, epic_id=None):
|
|
|
form = StoryForm(request.POST)
|
|
form = StoryForm(request.POST)
|
|
|
if form.is_valid():
|
|
if form.is_valid():
|
|
|
story = form.save()
|
|
story = form.save()
|
|
|
|
|
+
|
|
|
|
|
+ for assignee in story.assignees.filter(id != request.user.id):
|
|
|
|
|
+ notify_story_assigned(story, request.user, assignee)
|
|
|
|
|
+
|
|
|
return redirect("story_details", story.id)
|
|
return redirect("story_details", story.id)
|
|
|
|
|
|
|
|
else:
|
|
else:
|
|
@@ -139,9 +144,16 @@ def story_create(request, epic_id=None):
|
|
|
def story_edit(request, story_id):
|
|
def story_edit(request, story_id):
|
|
|
if request.method == 'POST':
|
|
if request.method == 'POST':
|
|
|
story = get_object_or_404(Story, id=story_id)
|
|
story = get_object_or_404(Story, id=story_id)
|
|
|
|
|
+ former_assignees = list(story.assignees.all())
|
|
|
|
|
+
|
|
|
form = StoryForm(request.POST, instance=story)
|
|
form = StoryForm(request.POST, instance=story)
|
|
|
if form.is_valid():
|
|
if form.is_valid():
|
|
|
form.save()
|
|
form.save()
|
|
|
|
|
+
|
|
|
|
|
+ for assignee in form.instance.assignees.all():
|
|
|
|
|
+ if not assignee in former_assignees and assignee.id != request.user.id:
|
|
|
|
|
+ notify_story_assigned(story, request.user, assignee)
|
|
|
|
|
+
|
|
|
return redirect("story_details", story.id)
|
|
return redirect("story_details", story.id)
|
|
|
|
|
|
|
|
else:
|
|
else:
|
|
@@ -164,6 +176,7 @@ def story_delete(request, story_id):
|
|
|
def story_close(request, story_id):
|
|
def story_close(request, story_id):
|
|
|
story = get_object_or_404(Story, id=story_id)
|
|
story = get_object_or_404(Story, id=story_id)
|
|
|
story.close()
|
|
story.close()
|
|
|
|
|
+ notify_story_closed(story, request.user)
|
|
|
if request.is_ajax():
|
|
if request.is_ajax():
|
|
|
return HttpResponse(story.to_json())
|
|
return HttpResponse(story.to_json())
|
|
|
else:
|
|
else:
|
|
@@ -181,9 +194,10 @@ def story_reaffect(request, story_id):
|
|
|
return redirect('story_details', story.id)
|
|
return redirect('story_details', story.id)
|
|
|
|
|
|
|
|
@login_required
|
|
@login_required
|
|
|
-def story_reopen(_, story_id):
|
|
|
|
|
|
|
+def story_reopen(request, story_id):
|
|
|
story = get_object_or_404(Story, id=story_id)
|
|
story = get_object_or_404(Story, id=story_id)
|
|
|
story.reopen()
|
|
story.reopen()
|
|
|
|
|
+ notify_story_reopened(story, request.user)
|
|
|
return redirect('story_details', story_id)
|
|
return redirect('story_details', story_id)
|
|
|
|
|
|
|
|
@login_required
|
|
@login_required
|
|
@@ -244,16 +258,18 @@ def epic_value_update(request, epic_id):
|
|
|
return redirect("backlog_editor")
|
|
return redirect("backlog_editor")
|
|
|
|
|
|
|
|
@login_required
|
|
@login_required
|
|
|
-def epic_close(_, epic_id):
|
|
|
|
|
|
|
+def epic_close(request, epic_id):
|
|
|
epic = get_object_or_404(Epic, id=epic_id)
|
|
epic = get_object_or_404(Epic, id=epic_id)
|
|
|
epic.close()
|
|
epic.close()
|
|
|
epic.save()
|
|
epic.save()
|
|
|
|
|
+ notify_epic_closed(epic, request.user)
|
|
|
return redirect("backlog_editor")
|
|
return redirect("backlog_editor")
|
|
|
|
|
|
|
|
@login_required
|
|
@login_required
|
|
|
-def epic_reopen(_, epic_id):
|
|
|
|
|
|
|
+def epic_reopen(request, epic_id):
|
|
|
epic = get_object_or_404(Epic, id=epic_id)
|
|
epic = get_object_or_404(Epic, id=epic_id)
|
|
|
epic.reopen()
|
|
epic.reopen()
|
|
|
|
|
+ notify_epic_reopened(epic, request.user)
|
|
|
return redirect("backlog_editor")
|
|
return redirect("backlog_editor")
|
|
|
|
|
|
|
|
@login_required
|
|
@login_required
|
|
@@ -301,6 +317,9 @@ def report_activity(request):
|
|
|
|
|
|
|
|
return render(request, 'reports/report_activity.html', {'projects_activity': projects_activity, 'epics_activity': epics_activity_cleaned})
|
|
return render(request, 'reports/report_activity.html', {'projects_activity': projects_activity, 'epics_activity': epics_activity_cleaned})
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+# comments
|
|
|
|
|
+
|
|
|
@login_required
|
|
@login_required
|
|
|
def comment_post(request):
|
|
def comment_post(request):
|
|
|
form = CommentForm(request.POST)
|
|
form = CommentForm(request.POST)
|
|
@@ -309,15 +328,7 @@ def comment_post(request):
|
|
|
comment.author = request.user
|
|
comment.author = request.user
|
|
|
comment.save()
|
|
comment.save()
|
|
|
|
|
|
|
|
- obj = comment.content_object
|
|
|
|
|
- notify.send(request.user,
|
|
|
|
|
- recipient=obj.contributors(),
|
|
|
|
|
- action_object = obj,
|
|
|
|
|
- verb="{} a commenté <a href='{}#a-comment-{}'>{} #{}</a>".format(request.user.username,
|
|
|
|
|
- reverse('{}_details'.format(obj.model_name().lower()), args=(obj.id,)),
|
|
|
|
|
- comment.id,
|
|
|
|
|
- obj.model_name(),
|
|
|
|
|
- obj.id))
|
|
|
|
|
|
|
+ notify_comment(comment)
|
|
|
|
|
|
|
|
return redirect(request.META['HTTP_REFERER'].split("#")[0] + "#a-comment-{}".format(comment.id))
|
|
return redirect(request.META['HTTP_REFERER'].split("#")[0] + "#a-comment-{}".format(comment.id))
|
|
|
else:
|
|
else:
|
|
@@ -364,8 +375,11 @@ def search(request):
|
|
|
|
|
|
|
|
return render(request, 'search_results.html', {'results': results, 'pages': range(1, paginator.num_pages + 1)})
|
|
return render(request, 'search_results.html', {'results': results, 'pages': range(1, paginator.num_pages + 1)})
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+# notifications
|
|
|
|
|
+
|
|
|
@login_required
|
|
@login_required
|
|
|
-def notif_seen(request, notif_id):
|
|
|
|
|
|
|
+def notif_seen(_, notif_id):
|
|
|
notif = get_object_or_404(Notification, id=notif_id)
|
|
notif = get_object_or_404(Notification, id=notif_id)
|
|
|
notif.mark_as_read()
|
|
notif.mark_as_read()
|
|
|
return HttpResponse('{}')
|
|
return HttpResponse('{}')
|
|
@@ -376,4 +390,46 @@ def notif_all_seen(request):
|
|
|
notif.mark_as_read()
|
|
notif.mark_as_read()
|
|
|
return HttpResponse('{}')
|
|
return HttpResponse('{}')
|
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
+def notify_comment(comment):
|
|
|
|
|
+ obj = comment.content_object
|
|
|
|
|
+ target_url = reverse(f"{obj.model_name().lower()}_details", args=(obj.id,))
|
|
|
|
|
+ notif_content= f"{comment.author.username} a commenté <a href='{target_url}#a-comment-{comment.id}' title='{obj.name}'>{obj.model_name()} #{obj.id}</a>"
|
|
|
|
|
+
|
|
|
|
|
+ for user in obj.contributors():
|
|
|
|
|
+ if user.id != comment.author.id:
|
|
|
|
|
+ notify.send(comment.author, recipient=user, action_object = obj, verb=notif_content)
|
|
|
|
|
+
|
|
|
|
|
+def notify_story_closed(story, closed_by):
|
|
|
|
|
+ target_url = reverse(f"story_details", args=(story.id,))
|
|
|
|
|
+ notif_content= f"La <a href='{target_url}' title='{story.name}'>story #{story.id}</a> a été <b>clôturée</b> par {closed_by}"
|
|
|
|
|
+
|
|
|
|
|
+ notify.send(closed_by, recipient=story.contributors(), action_object = story, verb=notif_content)
|
|
|
|
|
+
|
|
|
|
|
+def notify_story_reopened(story, opened_by):
|
|
|
|
|
+ target_url = reverse(f"story_details", args=(story.id,))
|
|
|
|
|
+ notif_content= f"La <a href='{target_url}' title='{story.name}'>story #{story.id}</a> a été <b>réouverte</b> par {opened_by}"
|
|
|
|
|
+
|
|
|
|
|
+ notify.send(opened_by, recipient=story.contributors(), action_object = story, verb=notif_content)
|
|
|
|
|
+
|
|
|
|
|
+def notify_epic_closed(epic, closed_by):
|
|
|
|
|
+ target_url = reverse(f"epic_details", args=(epic.id,))
|
|
|
|
|
+ notif_content= f"La <a href='{target_url}' title='{epic.name}'>story #{epic.id}</a> a été <b>clôturée</b> par {closed_by}"
|
|
|
|
|
+
|
|
|
|
|
+ notify.send(closed_by, recipient=User.objects.all(), action_object = epic, verb=notif_content)
|
|
|
|
|
+
|
|
|
|
|
+def notify_epic_reopened(epic, opened_by):
|
|
|
|
|
+ target_url = reverse(f"epic_details", args=(epic.id,))
|
|
|
|
|
+ notif_content= f"L'<a href='{target_url}' title='{epic.name}'>epic #{epic.id}</a> a été <b>réouverte</b> par {opened_by}"
|
|
|
|
|
+
|
|
|
|
|
+ notify.send(opened_by, recipient=User.objects.all(), action_object = epic, verb=notif_content)
|
|
|
|
|
+
|
|
|
|
|
+def notify_story_assigned(story, assigned_by, assigned_to):
|
|
|
|
|
+ target_url = reverse(f"story_details", args=(story.id,))
|
|
|
|
|
+ notif_content= f"La <a href='{target_url}' title='{story.name}'>story #{story.id}</a> vous a été assignée par {assigned_by}"
|
|
|
|
|
+
|
|
|
|
|
+ notify.send(assigned_by, recipient=assigned_to, action_object = story, verb=notif_content)
|
|
|
|
|
+
|
|
|
|
|
+def notify_sprint_end(sprint, next_sprint, ended_by):
|
|
|
|
|
+ target_url = reverse(f"report_sprints")
|
|
|
|
|
+ notify.send(ended_by, recipient=User.objects.all(), action_object = sprint, verb=f"Fin du <a href='{target_url}'>{sprint}</a>")
|
|
|
|
|
+ notify.send(ended_by, recipient=User.objects.all(), action_object = sprint, verb=f"Démarrage du <a href='{target_url}'>{next_sprint}</a>")
|