views.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. from datetime import datetime
  2. from django.contrib.auth import logout, login, update_session_auth_hash
  3. from django.contrib.auth.decorators import login_required
  4. from django.contrib.auth.forms import PasswordChangeForm
  5. from django.contrib.auth.models import User
  6. from django.core.paginator import Paginator
  7. from django.http.response import HttpResponse
  8. from django.shortcuts import render, get_object_or_404, redirect
  9. from notifications.signals import notify
  10. from main.forms import StoryForm, EpicForm, RegisterForm, ProfileForm, \
  11. CommentForm, SprintForm
  12. from main.models import Story, Epic, Sprint, Comment, Project
  13. @login_required
  14. def index(request):
  15. epics = Epic.objects.filter(closed=False)
  16. return render(request, 'index.html', {'current_sprint': Sprint.current(), 'epics': epics})
  17. def register(request):
  18. if request.method == 'POST':
  19. form = RegisterForm(request.POST)
  20. if form.is_valid():
  21. user = form.save()
  22. login(request, user)
  23. return redirect("index")
  24. else:
  25. form = RegisterForm()
  26. return render(request, 'registration/register.html', {'form': form})
  27. @login_required
  28. def profile_update(request):
  29. if request.method == 'POST':
  30. user = get_object_or_404(User, username=request.user)
  31. form = ProfileForm(request.POST, instance=user)
  32. if form.is_valid():
  33. user = form.save()
  34. login(request, user)
  35. return redirect("index")
  36. else:
  37. user = get_object_or_404(User, username=request.user)
  38. form = ProfileForm(instance=user)
  39. return render(request, 'registration/register.html', {'form': form})
  40. @login_required
  41. def change_password(request):
  42. if request.method == 'POST':
  43. form = PasswordChangeForm(request.user, request.POST)
  44. if form.is_valid():
  45. user = form.save()
  46. update_session_auth_hash(request, user) # Important!
  47. return redirect('index')
  48. else:
  49. form = PasswordChangeForm(request.user)
  50. return render(request, 'registration/change_password.html', {'form': form})
  51. @login_required
  52. def logout(request):
  53. logout(request)
  54. return redirect("index")
  55. @login_required
  56. def backlog_editor(request):
  57. epics = Epic.objects.filter(closed=False)
  58. closed = Epic.objects.filter(closed=True)
  59. return render(request, 'backlog_editor.html', {'epics': epics, 'closed': closed})
  60. def sprint_end(request):
  61. current_sprint = Sprint.current()
  62. next_sprint = Sprint.next()
  63. if request.method == 'POST':
  64. current_sprint.retro = request.POST["retro"]
  65. current_sprint.closed = True
  66. current_sprint.save()
  67. return redirect("index")
  68. form = SprintForm(instance=current_sprint)
  69. return render(request, 'sprint_end.html', {'sprint': current_sprint, 'next_sprint': next_sprint, 'form': form})
  70. @login_required
  71. def story_index(request):
  72. sprints = Sprint.objects.all()
  73. users = User.objects.all()
  74. stories = Story.objects
  75. filters = request.GET
  76. if 'state' in filters and filters['state']:
  77. stories = stories.filter(closed=(filters['state'] == 'closed'))
  78. if 'sprint' in filters and filters['sprint']:
  79. if filters['sprint'] == "None":
  80. stories = stories.filter(sprints=None)
  81. else:
  82. stories = stories.filter(sprints__id=filters['sprint'])
  83. if 'author' in filters and filters['author']:
  84. stories = stories.filter(author_id=filters['author'])
  85. if 'assignee' in filters and filters['assignee']:
  86. stories = stories.filter(assignees__id=filters['assignee'])
  87. paginator = Paginator(stories.all(), 20)
  88. page = request.GET.get('page')
  89. stories = paginator.get_page(page)
  90. return render(request, 'story_index.html', {'stories': stories, 'sprints': sprints, 'users': users, 'pages': range(1, paginator.num_pages + 1)})
  91. @login_required
  92. def story_details(request, story_id):
  93. story = get_object_or_404(Story, id=story_id)
  94. return render(request, 'story_details.html', {'story': story, 'com_pack': com_pack(story)})
  95. @login_required
  96. def story_create(request, epic_id=None):
  97. if request.method == 'POST':
  98. form = StoryForm(request.POST)
  99. if form.is_valid():
  100. story = form.save()
  101. return redirect("story_details", story.id)
  102. else:
  103. story = Story()
  104. if epic_id is not None:
  105. story.epic = get_object_or_404(Epic, id=epic_id)
  106. story.author = User.objects.get(username=request.user)
  107. form = StoryForm(instance=story)
  108. return render(request, 'story_form.html', {'form': form, 'current_sprint_id': Sprint.current().id})
  109. @login_required
  110. def story_edit(request, story_id):
  111. if request.method == 'POST':
  112. story = get_object_or_404(Story, id=story_id)
  113. form = StoryForm(request.POST, instance=story)
  114. if form.is_valid():
  115. form.save()
  116. return redirect("story_details", story.id)
  117. else:
  118. story = get_object_or_404(Story, id=story_id)
  119. form = StoryForm(instance=story)
  120. return render(request, 'story_form.html', {'form': form, 'current_sprint_id': Sprint.current().id})
  121. @login_required
  122. def story_delete(request, story_id):
  123. if request.method == 'POST':
  124. story = get_object_or_404(Story, id=story_id)
  125. story.delete()
  126. return redirect("index")
  127. else:
  128. story = get_object_or_404(Story, id=story_id)
  129. return render(request, 'deletion.html', {'object': story})
  130. def _story_close(request, story_id):
  131. story = get_object_or_404(Story, id=story_id)
  132. story.closed = True
  133. story.save()
  134. # for u in story.assignees.all():
  135. # for u in story.assignees.filter(id != request.user.id):
  136. # notify.send(request.user,
  137. # recipient=u,
  138. # verb="Story clôturée",
  139. # action_object=story,
  140. # description="La story #{} a été clôturée".format(story.id))
  141. return story
  142. @login_required
  143. def story_close(request, story_id):
  144. story = _story_close(request, story_id)
  145. return redirect('epic_details', story.epic.id)
  146. def story_close_ajax(request, story_id):
  147. story = _story_close(request, story_id)
  148. return HttpResponse(story.to_json())
  149. @login_required
  150. def story_close_from_sprintend(_, story_id):
  151. story = get_object_or_404(Story, id=story_id)
  152. story.closed = True
  153. story.save()
  154. return redirect("sprint_end")
  155. @login_required
  156. def story_reaffect_ajax(_, story_id):
  157. story = get_object_or_404(Story, id=story_id)
  158. next_sprint = Sprint.next()
  159. story.sprints.add(next_sprint)
  160. story.save()
  161. return HttpResponse(story.to_json())
  162. @login_required
  163. def story_reopen(_, story_id):
  164. story = get_object_or_404(Story, id=story_id)
  165. story.closed = False
  166. story.save()
  167. return redirect('story_details', story_id)
  168. @login_required
  169. def epic_details(request, epic_id):
  170. epic = get_object_or_404(Epic, id=epic_id)
  171. return render(request, 'epic_details.html', {'epic': epic, 'com_pack': com_pack(epic)})
  172. @login_required
  173. def epic_create(request):
  174. if request.method == 'POST':
  175. form = EpicForm(request.POST)
  176. if form.is_valid():
  177. epic = form.save(commit=False)
  178. epic.author = User.objects.get(username=request.user)
  179. epic.save()
  180. return redirect("backlog_editor")
  181. else:
  182. form = EpicForm()
  183. return render(request, 'epic_form.html', {'form': form})
  184. @login_required
  185. def epic_edit(request, epic_id, from_=""):
  186. if request.method == 'POST':
  187. epic = get_object_or_404(Epic, id=epic_id)
  188. form = EpicForm(request.POST, instance=epic)
  189. if form.is_valid():
  190. form.save()
  191. if from_:
  192. return redirect(from_)
  193. else:
  194. return redirect("epic_details", epic.id)
  195. else:
  196. epic = get_object_or_404(Epic, id=epic_id)
  197. form = EpicForm(instance=epic)
  198. return render(request, 'epic_form.html', {'form': form})
  199. @login_required
  200. def epic_delete(request, epic_id):
  201. if request.method == 'POST':
  202. epic = get_object_or_404(Epic, id=epic_id)
  203. epic.delete()
  204. return redirect("index")
  205. else:
  206. epic = get_object_or_404(Epic, id=epic_id)
  207. return render(request, 'deletion.html', {'object': epic})
  208. @login_required
  209. def epic_value_update(request, epic_id):
  210. if request.method == 'POST':
  211. epic = get_object_or_404(Epic, id=epic_id)
  212. epic.value = request.POST["value"]
  213. epic.save()
  214. return redirect("backlog_editor")
  215. @login_required
  216. def epic_close(_, epic_id):
  217. epic = get_object_or_404(Epic, id=epic_id)
  218. epic.closed = True
  219. epic.save()
  220. return redirect("backlog_editor")
  221. @login_required
  222. def epic_reopen(_, epic_id):
  223. epic = get_object_or_404(Epic, id=epic_id)
  224. epic.closed = False
  225. epic.save()
  226. return redirect("backlog_editor")
  227. @login_required
  228. def reports(request):
  229. return render(request, 'reports/report_index.html')
  230. @login_required
  231. def report_sprints(request):
  232. sprints = Sprint.objects.all()
  233. return render(request, 'reports/report_sprints.html', {'sprints': sprints})
  234. @login_required
  235. def report_projects(request):
  236. epics = Epic.objects.filter(closed=False)
  237. return render(request, 'reports/report_projects.html', {'epics': epics})
  238. def report_activity(request):
  239. projects_activity = {}
  240. for project in Project.objects.all():
  241. projects_activity[project] = {}
  242. projects_activity[project]["current"] = 0
  243. projects_activity[project]["sixmonths"] = 0
  244. epics_activity = {}
  245. for epic in Epic.objects.all():
  246. epics_activity[epic] = {}
  247. epics_activity[epic]["current"] = 0
  248. epics_activity[epic]["sixmonths"] = 0
  249. current = True
  250. for sprint in Sprint.objects.filter(date_end__lt = datetime.today()).order_by('-date_start')[:12]:
  251. for story in sprint.stories.all():
  252. if not story.epic:
  253. continue
  254. if current:
  255. projects_activity[story.epic.project]["current"] += story.weight
  256. epics_activity[story.epic]["current"] += story.weight
  257. projects_activity[story.epic.project]["sixmonths"] += story.weight
  258. epics_activity[story.epic]["sixmonths"] += story.weight
  259. current = False
  260. epics_activity_cleaned = {epic: act for epic, act in epics_activity.items() if act["sixmonths"] > 0 }
  261. return render(request, 'reports/report_activity.html', {'projects_activity': projects_activity, 'epics_activity': epics_activity_cleaned})
  262. def com_pack(obj):
  263. pack = {}
  264. pack['obj'] = obj
  265. pack['comments'] = {c: CommentForm(instance=c, prefix="{}".format(c.id)) for c in obj.comments()}
  266. pack['empty_form'] = CommentForm(prefix="new")
  267. return pack
  268. @login_required
  269. def comment_post(request, obj_uuid):
  270. comment = Comment()
  271. comment.obj_uuid = obj_uuid
  272. comment.author = get_object_or_404(User, username=request.user)
  273. comment.content = request.POST["new-content"]
  274. comment.save()
  275. return redirect(request.META['HTTP_REFERER'].split("#")[0] + "#a-comment-{}".format(comment.id))
  276. @login_required
  277. def comment_edit(request, comment_id):
  278. comment = get_object_or_404(Comment, id=comment_id)
  279. comment.content = request.POST["{}-content".format(comment_id)]
  280. comment.save()
  281. return redirect(request.META['HTTP_REFERER'].split("#")[0] + "#a-comment-{}".format(comment.id))
  282. @login_required
  283. def comment_del(request, comment_id):
  284. comment = get_object_or_404(Comment, id=comment_id)
  285. comment.delete()
  286. return redirect(request.META['HTTP_REFERER'].split("#")[0] + "#a-comment-section")
  287. @login_required
  288. def search(request):
  289. qstr = request.GET["q"]
  290. results = []
  291. results += Epic.objects.filter(name__icontains=qstr)
  292. results += Story.objects.filter(name__icontains=qstr)
  293. results += Epic.objects.filter(description__icontains=qstr)
  294. results += Story.objects.filter(description__icontains=qstr)
  295. if len(results) == 1:
  296. r = results[0]
  297. if isinstance(r, Epic):
  298. return redirect("epic_details", r.id)
  299. else:
  300. return redirect("story_details", r.id)
  301. else:
  302. paginator = Paginator(results, 10)
  303. page = request.GET.get('page')
  304. results = paginator.get_page(page)
  305. return render(request, 'search_results.html', {'results': results, 'pages': range(1, paginator.num_pages + 1)})