Django Library PaTT
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

views.py 38KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. from .access import acc_task, acc_project, create_project_possible, create_task_possible
  2. from .context import context_adaption
  3. from django.contrib import messages
  4. from django.contrib.auth.decorators import login_required
  5. from django.contrib.auth.forms import User
  6. from django.shortcuts import render, redirect
  7. from django.urls.base import reverse
  8. from django.utils import timezone
  9. from django.utils.translation import gettext as _
  10. from .forms import TaskForm, TaskFormLimited, ProjectForm, CommentForm, TaskCommentForm, SearchForm, EasySearchForm, PattUserProfileForm
  11. from .help import help_pages
  12. from .models import Task, ModelList, Comment, TASKSTATE_CHOICES, PRIO_CHOICES, TASKS_IN_WORK
  13. from .models import Project, Search, get_pattuserprofile
  14. import patt
  15. from .search import load_index, search, mk_search_pattern, get_project_ids_from_search_pattern, common_searches
  16. from users.forms import UserProfileForm
  17. from users.models import get_userprofile
  18. from themes import Context
  19. class Like(object):
  20. DATA = []
  21. def __init__(self, request, obj):
  22. for key in self.DATA:
  23. if key in request.POST:
  24. setattr(self, key, request.POST.get(key))
  25. else:
  26. try:
  27. setattr(self, key, getattr(obj, key))
  28. except AttributeError:
  29. setattr(self, key, None)
  30. self.__init_additions__(request, obj)
  31. if self.creation_date is None:
  32. self.creation_date = timezone.now()
  33. if self.id is None:
  34. self.id = 'xxx'
  35. def __init_additions__(self, request, obj):
  36. pass
  37. class TaskLike(Like):
  38. DATA = ['id', 'state', 'priority', 'targetdate', 'progress', 'name', 'description', 'creation_date', 'comments']
  39. def __init_additions__(self, request, obj):
  40. if 'project' in request.POST:
  41. self.project = Project.objects.get(id=request.POST.get('project'))
  42. else:
  43. self.project = getattr(obj, 'project')
  44. if 'assigned_user' in request.POST:
  45. try:
  46. self.assigned_user = User.objects.get(id=request.POST.get('assigned_user'))
  47. except ValueError:
  48. self.assigned_user = None
  49. else:
  50. self.assigned_user = getattr(obj, 'assigned_user')
  51. #
  52. self.class_by_state = 'task-normal' if self.state == '0' else 'task-finished'
  53. #
  54. if obj is None:
  55. self.attachment_target_path = Task().attachment_target_path
  56. else:
  57. self.attachment_target_path = obj.attachment_target_path
  58. if self.assigned_user and self.id:
  59. self.taskname_prefix = '**#%d //(%s)//:** ' % (self.id, self.assigned_user.username)
  60. elif self.id:
  61. self.taskname_prefix = '**#%d:** ' % self.id
  62. elif self.assigned_user:
  63. self.taskname_prefix = '**//(%s)//:** ' % self.assigned_user.username
  64. else:
  65. self.taskname_prefix = ''
  66. class CommentLike(Like):
  67. DATA = ['id', 'type', 'creation_date', 'comment']
  68. def __init_additions__(self, request, obj):
  69. if 'user' in request.POST:
  70. self.user = User.objects.get(id=request.POST.get('user'))
  71. else:
  72. try:
  73. self.user = getattr(obj, 'user')
  74. except AttributeError:
  75. self.user = request.user
  76. #
  77. if obj is None:
  78. self.attachment_target_path = Comment().attachment_target_path
  79. else:
  80. self.attachment_target_path = obj.attachment_target_path
  81. class ProjectLike(Like):
  82. DATA = ['id', 'name', 'description', 'state', 'creation_date']
  83. def __init_additions__(self, request, obj):
  84. self.role_leader = [User.objects.get(id=user_id) for user_id in request.POST.getlist('role_leader', [])]
  85. self.role_member = [User.objects.get(id=user_id) for user_id in request.POST.getlist('role_member', [])]
  86. self.creation_date = '-'
  87. self.formatted_leaders = ', '.join([user.username for user in self.role_leader])
  88. self.formatted_members = ', '.join([user.username for user in self.role_member])
  89. #
  90. if obj is None:
  91. self.attachment_target_path = Project().attachment_target_path
  92. else:
  93. self.attachment_target_path = obj.attachment_target_path
  94. def permission_denied_msg_project(request, project_id):
  95. if project_id is None:
  96. messages.error(request, _('Permission denied to create a new Project.'))
  97. else:
  98. messages.error(request, _('Permission denied to Project #%(project_id)d') % {'project_id': project_id})
  99. def permission_denied_msg_task(request, task_id):
  100. if task_id is None:
  101. messages.error(request, _('Permission denied to create a new Task'))
  102. else:
  103. messages.error(request, _('Permission denied to Task #%(task_id)d') % {'task_id': task_id})
  104. def permission_denied_msg_comment(request, task_id):
  105. messages.error(request, _('Permission denied to add or edit a comment of Task #%(task_id)d') % {'task_id': task_id})
  106. def no_change_msg(request):
  107. messages.info(request, _("Nothing changed, no storage needed."))
  108. def does_not_exist_msg_task(request, task_id):
  109. messages.error(request, _('Task #%(id)d does not exist!') % {'id': task_id})
  110. def does_not_exist_msg_search(request, search_id):
  111. messages.error(request, _('Search #%(id)d does not exist!') % {'id': search_id})
  112. def get_next(request):
  113. if not request.POST:
  114. return request.GET.get('next', '/')
  115. else:
  116. return request.POST.get('next', '/')
  117. def profile_post_actions(request, context):
  118. if request.POST:
  119. form = context.get('form_userprofile')
  120. if form.is_valid():
  121. form.save()
  122. form = context.get('form_pattprofile')
  123. if form.is_valid():
  124. form.save()
  125. return redirect(request.GET.get('next') or '/')
  126. def profile_pre_actions(request, context, form_to_be_used=UserProfileForm):
  127. user_profile = get_userprofile(request.user)
  128. patt_user_profile = get_pattuserprofile(request.user)
  129. if request.POST:
  130. userprofile_form = UserProfileForm(request.POST, instance=user_profile)
  131. pattprofile_form = PattUserProfileForm(request.POST, instance=patt_user_profile)
  132. else:
  133. userprofile_form = UserProfileForm(instance=user_profile)
  134. pattprofile_form = PattUserProfileForm(instance=patt_user_profile)
  135. context['form_userprofile'] = userprofile_form
  136. context['form_pattprofile'] = pattprofile_form
  137. @login_required
  138. def patt_profile(request):
  139. context = Context(request) # needs to be executed first because of time mesurement
  140. profile_pre_actions(request, context)
  141. response = profile_post_actions(request, context)
  142. if response is not None:
  143. return response
  144. else:
  145. context_adaption(context, request, title=_('Profile for %(username)s') % {'username': request.user.username})
  146. return render(request, 'patt/profile.html', context=context)
  147. @login_required
  148. def patt_tasklist(request, user_filter_id=None, common_filter_id=None):
  149. context = Context(request) # needs to be executed first because of time mesurement
  150. is_printview = patt.is_printview(request)
  151. search_txt = patt.get_search_query(request)
  152. if user_filter_id is not None:
  153. try:
  154. s = Search.objects.get(id=user_filter_id)
  155. except Search.DoesNotExist:
  156. does_not_exist_msg_search(request, user_filter_id)
  157. return redirect(patt.url_tasklist(request))
  158. search_txt = s.search_txt
  159. title = s.name
  160. ix = load_index()
  161. sr = search(ix, search_txt)
  162. if sr is None:
  163. messages.error(request, _('Invalid search pattern: %s') % repr(search_txt))
  164. sr = []
  165. tasklist = ModelList(sr, acc_task, request.user)
  166. elif search_txt is not None:
  167. ix = load_index()
  168. sr = search(ix, search_txt)
  169. if sr is None:
  170. messages.error(request, _('Invalid search pattern: %s') % repr(search_txt))
  171. sr = []
  172. tasklist = ModelList(sr, acc_task, request.user)
  173. max_len = 25
  174. if len(search_txt) > max_len:
  175. title = _('Searchresults for %s') % repr(search_txt[:max_len - 3] + '...')
  176. else:
  177. title = _('Searchresults for %s') % repr(search_txt)
  178. elif common_filter_id is not None:
  179. try:
  180. title, search_txt = common_searches(request)[common_filter_id]
  181. except KeyError:
  182. messages.error(request, _('Invalid common search: %s') % repr(common_filter_id))
  183. sr = []
  184. title = _('Common Search Error')
  185. else:
  186. ix = load_index()
  187. sr = search(ix, search_txt)
  188. if sr is None:
  189. messages.error(request, _('Invalid search pattern: %s') % repr(search_txt))
  190. sr = []
  191. tasklist = ModelList(sr, acc_task, request.user)
  192. else:
  193. tasklist = ModelList(Task.objects.filter(state__in=TASKS_IN_WORK), acc_task, request.user)
  194. title = _("All Tasks in work")
  195. try:
  196. project_id = get_project_ids_from_search_pattern(search_txt)[0]
  197. except IndexError:
  198. project_id = None
  199. except TypeError:
  200. project_id = None
  201. tasklist.sort()
  202. context_adaption(
  203. context, # the base context
  204. request, # the request object to be used in context_adaption
  205. tasklist=tasklist, # the tasklist to be shown (template)
  206. printview=is_printview, # Show reduced view and functionality in printview
  207. target_head=None if is_printview else 'patt-taskview', # target-link for head (template)
  208. project_id=project_id, # as default Value for New Task entry
  209. title=title, # the title for the page (template)
  210. )
  211. if patt.is_printview(request):
  212. return render(request, 'patt/tasklist_print.html', context=context)
  213. else:
  214. return render(request, 'patt/tasklist.html', context=context)
  215. @login_required
  216. def patt_projectlist(request):
  217. context = Context(request) # needs to be executed first because of time mesurement
  218. projectlist = ModelList(Project.objects.all(), acc_project, request.user)
  219. projectlist.sort()
  220. context_adaption(
  221. context, # the base context
  222. request, # the request object to be used in context_adaption
  223. projectlist=projectlist, # the projectlist to be shown (template)
  224. target_head='patt-projectedit', # target-link for head (template)
  225. title=_("Projectlist"), # the title for the page (template)
  226. )
  227. return render(request, 'patt/projectlist.html', context=context)
  228. @login_required
  229. def patt_taskview(request, task_id):
  230. context = Context(request) # needs to be executed first because of time mesurement
  231. is_printview = patt.is_printview(request)
  232. try:
  233. task = Task.objects.get(id=task_id)
  234. except Task.DoesNotExist:
  235. does_not_exist_msg_task(request, task_id)
  236. else:
  237. acc = acc_task(task, request.user)
  238. if acc.read:
  239. context_adaption(
  240. context, # the base context
  241. request, # the request object to be used in context_adaption
  242. task=task, # the task to be shown (template)
  243. printview=is_printview, # Show reduced view and functionality in printview
  244. taskview=True, # deactivate collapse and expand buttons
  245. target_head=None if is_printview else 'patt-taskedit', # target-link for head (template)
  246. project_id=task.project.id, # as default Value for New Task entry
  247. title=_('Task #%d') % task.id # the title for the page (template)
  248. )
  249. if patt.is_printview(request):
  250. return render(request, 'patt/taskview_print.html', context=context)
  251. else:
  252. return render(request, 'patt/taskview.html', context=context)
  253. else:
  254. permission_denied_msg_task(request, task.id)
  255. return redirect(reverse('patt-tasklist'))
  256. @login_required
  257. def patt_tasknew(request):
  258. context = Context(request) # needs to be executed first because of time mesurement
  259. nxt = get_next(request)
  260. if create_task_possible(request.user):
  261. if not request.POST: # Initial Form...
  262. task = Task(project_id=request.GET.get('project_id'))
  263. form = TaskForm(instance=task, request=request)
  264. form_comment = TaskCommentForm()
  265. context_adaption(
  266. context, # the base context
  267. request, # the request object to be used in context_adaption
  268. form=form, # the form object to create the task form (template)
  269. form_comment=form_comment, # the form object to create the comment form (template)
  270. next=nxt, # the url for redirection
  271. title=_('New Task') # the title for the page (template)
  272. )
  273. return render(request, 'patt/task_form.html', context=context)
  274. else:
  275. task = Task()
  276. form = TaskForm(request.POST, instance=task, request=request)
  277. form_comment = TaskCommentForm(request.POST)
  278. context_adaption(
  279. context, # the base context
  280. request, # the request object to be used in context_adaption
  281. form=form, # the form object to create the task form (template)
  282. form_comment=form_comment, # the form object to create the comment form (template)
  283. next=nxt, # the url for redirection
  284. title=_('New Task') # the title for the page (template)
  285. )
  286. if request.POST.get('save'): # Save form content...
  287. if form.is_valid() and form_comment.is_valid():
  288. form.save()
  289. if request.POST.get('comment'):
  290. form_comment = TaskCommentForm(request.POST, instance=Comment(task_id=form.instance.id, user=request.user))
  291. form_comment.save()
  292. messages.success(request, _('Thanks for adding Task #%(task_id)d.') % {'task_id': form.instance.id})
  293. return redirect(nxt + '#task-%d' % form.instance.id)
  294. elif request.POST.get('preview'): # Create a preview
  295. context['comment_new'] = CommentLike(request, None) # the new comment to be used in the preview
  296. context['template'] = 'patt/task/task.html' # the template for preview (template)
  297. context['task'] = TaskLike(request, task) # the object to be used in the preview template
  298. context['printview'] = True # Show reduced view and functionality like in printview
  299. return render(request, 'patt/task_form.html', context=context)
  300. else:
  301. permission_denied_msg_task(request, None)
  302. return redirect(nxt)
  303. @login_required
  304. def patt_projectnew(request):
  305. context = Context(request) # needs to be executed first because of time mesurement
  306. nxt = get_next(request)
  307. if create_project_possible(request.user):
  308. project = Project()
  309. if not request.POST:
  310. form = ProjectForm(instance=project)
  311. context_adaption(
  312. context, # the base context
  313. request, # the request object to be used in context_adaption
  314. form=form, # the form object to create the form (template)
  315. next=nxt, # the url for redirection
  316. disable_delete=True, # disable delete button
  317. disable_search=True, # disable search button
  318. title=_('New Project') # the title for the page (template)
  319. )
  320. return render(request, 'patt/raw_single_form.html', context=context)
  321. else:
  322. form = ProjectForm(request.POST, instance=project)
  323. context_adaption(
  324. context, # the base context
  325. request, # the request object to be used in context_adaption
  326. form=form, # the form object to create the form (template)
  327. next=nxt, # the url for redirection
  328. disable_delete=True, # disable delete button
  329. disable_search=True, # disable search button
  330. title=_('New Project') # the title for the page (template)
  331. )
  332. #
  333. if request.POST.get('save'):
  334. if form.is_valid():
  335. form.save()
  336. messages.success(request, _('Thanks for adding Project #%(project_id)d.') % {'project_id': form.instance.id})
  337. return redirect(nxt + '#project-%d' % form.instance.id)
  338. elif request.POST.get('preview'):
  339. context['template'] = 'patt/project/project.html' # the template for preview (template)
  340. context['project'] = ProjectLike(request, None) # the object to be used in the preview template
  341. return render(request, 'patt/raw_single_form.html', context=context)
  342. else:
  343. permission_denied_msg_project(request, None)
  344. return redirect(nxt)
  345. @login_required
  346. def patt_taskedit(request, task_id, **kwargs):
  347. context = Context(request) # needs to be executed first because of time mesurement
  348. nxt = get_next(request)
  349. try:
  350. task = Task.objects.get(id=task_id)
  351. except Task.DoesNotExist:
  352. does_not_exist_msg_task(request, task_id)
  353. return redirect(nxt)
  354. else:
  355. acc = acc_task(task, request.user)
  356. if acc.modify or acc.modify_limited:
  357. if acc.modify:
  358. ThisForm = TaskForm
  359. else:
  360. ThisForm = TaskFormLimited
  361. if not request.POST:
  362. # get request parameters
  363. do = request.GET.get('do')
  364. state = request.GET.get('state')
  365. if state:
  366. state = int(state)
  367. priority = request.GET.get('priority')
  368. if priority:
  369. priority = int(priority)
  370. #
  371. if do == 'edit':
  372. form = ThisForm(instance=task, request=request)
  373. context_adaption(
  374. context, # the base context
  375. request, # the request object to be used in context_adaption
  376. form=form, # the form object to create the task form (template)
  377. form_comment=TaskCommentForm(), # the form object to create the comment form (template)
  378. next=nxt, # the url for redirection
  379. next_anchor='task-%d' % task.id, # the anchor for redirection
  380. title=_('Edit Task #%d') % task.id # the title for the page (template)
  381. )
  382. return render(request, 'patt/task_form.html', context=context)
  383. elif do == 'set_state':
  384. if state in acc.allowed_targetstates:
  385. task.state = state
  386. task.save()
  387. messages.success(request, _('State of Task #%(task_id)d set to %(name)s') % {'task_id': task.id, 'name': dict(TASKSTATE_CHOICES)[state]})
  388. else:
  389. permission_denied_msg_task(request, task_id)
  390. elif do == 'set_priority':
  391. if priority in acc.allowed_targetpriority:
  392. task.priority = priority
  393. task.save()
  394. messages.success(request, _('Priority of Task #%(task_id)d set to %(name)s') % {'task_id': task.id, 'name': dict(PRIO_CHOICES)[priority]})
  395. else:
  396. permission_denied_msg_task(request, task_id)
  397. else:
  398. messages.error(request, 'Edit with do="%s" not yet implemented!' % do)
  399. return redirect(nxt + '#task-%d' % task_id)
  400. else:
  401. comment = Comment(task_id=task_id, user=request.user)
  402. form = ThisForm(request.POST, instance=task, request=request)
  403. form_comment = TaskCommentForm(request.POST, instance=comment)
  404. context_adaption(
  405. context, # the base context
  406. request, # the request object to be used in context_adaption
  407. form=form, # the form object to create the task form (template)
  408. form_comment=form_comment, # the form object to create the comment form (template)
  409. next=nxt, # the url for redirection
  410. next_anchor='task-%d' % task.id, # the anchor for redirection
  411. title=_('Edit Task #%d') % task.id # the title for the page (template)
  412. )
  413. if request.POST.get('save'):
  414. if form.is_valid() and form_comment.is_valid(): # TODO: Validator depending on modify and modify_limited (to ensure content is okay for this user)!
  415. save_needed = form.save().save_needed
  416. if request.POST.get('comment'):
  417. save_needed |= form_comment.save().save_needed
  418. if save_needed:
  419. messages.success(request, _('Thanks for editing Task #%(task_id)d.') % {'task_id': task.id})
  420. else:
  421. no_change_msg(request)
  422. return redirect(nxt + '#task-%d' % task_id)
  423. elif request.POST.get('preview'):
  424. context['comment_new'] = CommentLike(request, comment) # the new comment to be used in the preview
  425. context['template'] = 'patt/task/task.html' # the template for preview (template)
  426. context['task'] = TaskLike(request, task) # the object to be used in the preview template
  427. context['printview'] = True # Show reduced view and functionality like in printview
  428. return render(request, 'patt/task_form.html', context=context)
  429. else:
  430. permission_denied_msg_task(request, task_id)
  431. return redirect(nxt + '#task-%d' % task_id)
  432. @login_required
  433. def patt_projectedit(request, project_id):
  434. context = Context(request) # needs to be executed first because of time mesurement
  435. nxt = get_next(request)
  436. try:
  437. project = Project.objects.get(id=project_id)
  438. except Task.DoesNotExist:
  439. messages.error(request, _('Project with id %(project_id)d does not exist!') % {'project_id': project_id})
  440. return redirect(nxt)
  441. else:
  442. acc = acc_project(project, request.user)
  443. if acc.modify:
  444. if not request.POST:
  445. form = ProjectForm(instance=project)
  446. context_adaption(
  447. context, # the base context
  448. request, # the request object to be used in context_adaption
  449. form=form, # the form object to create the form (template)
  450. next=nxt, # the url for redirection
  451. next_anchor='project-%d' % project_id, # the anchor for redirection
  452. item_id=project.id, # project.id for Preview, ... (template)
  453. disable_delete=True, # disable delete button
  454. disable_search=True, # disable search button
  455. title=_('Edit Project #%d') % project_id # the title for the page (template)
  456. )
  457. return render(request, 'patt/raw_single_form.html', context=context)
  458. else:
  459. form = ProjectForm(request.POST, instance=project)
  460. context_adaption(
  461. context, # the base context
  462. request, # the request object to be used in context_adaption
  463. form=form, # the form object to create the form (template)
  464. next=nxt, # the url for redirection
  465. next_anchor='project-%d' % project_id, # the anchor for redirection
  466. item_id=project.id, # project.id for Preview, ... (template)
  467. disable_delete=True, # disable delete button
  468. disable_search=True, # disable search button
  469. title=_('Edit Project #%d') % project_id # the title for the page (template)
  470. )
  471. #
  472. if request.POST.get('save'):
  473. if form.is_valid():
  474. form.save()
  475. messages.success(request, _('Thanks for editing Project #%(project_id)d.') % {'project_id': project.id})
  476. return redirect(nxt + '#project-%d' % project_id)
  477. elif request.POST.get('preview'):
  478. context['template'] = 'patt/project/project.html' # the template for preview (template)
  479. context['project'] = ProjectLike(request, project) # the object to be used in the preview template
  480. return render(request, 'patt/raw_single_form.html', context=context)
  481. else:
  482. permission_denied_msg_project(request, project_id)
  483. return redirect(nxt + '#project-%d' % project_id)
  484. @login_required
  485. def patt_commentnew(request, task_id):
  486. context = Context(request) # needs to be executed first because of time mesurement
  487. nxt = get_next(request)
  488. try:
  489. task = Task.objects.get(id=task_id)
  490. except Task.DoesNotExist:
  491. does_not_exist_msg_task(request, task_id)
  492. return redirect(nxt)
  493. else:
  494. acc = acc_task(task, request.user)
  495. if acc.add_comments:
  496. if not request.POST:
  497. form = CommentForm(instance=Comment(), acc=acc)
  498. context_adaption(
  499. context, # the base context
  500. request, # the request object to be used in context_adaption
  501. form=form, # the form object to create the form (template)
  502. next=nxt, # the url for redirection
  503. next_anchor='task-%d' % task_id, # the anchor for redirection
  504. disable_delete=True, # disable delete button
  505. disable_search=True, # disable search button
  506. title=_('Add a Comment (Task #%d)') % task_id # the title for the page (template)
  507. )
  508. return render(request, 'patt/raw_single_form.html', context=context)
  509. else:
  510. comment = Comment(task_id=task_id, user=request.user)
  511. #
  512. form = CommentForm(request.POST, instance=comment, acc=acc)
  513. context_adaption(
  514. context, # the base context
  515. request, # the request object to be used in context_adaption
  516. form=form, # the form object to create the form (template)
  517. next=nxt, # the url for redirection
  518. next_anchor='task-%d' % task_id, # the anchor for redirection
  519. disable_delete=True, # disable delete button
  520. disable_search=True, # disable search button
  521. title=_('Add Comment to Task #%d') % task_id # the title for the page (template)
  522. )
  523. if request.POST.get('save'):
  524. if form.is_valid():
  525. form.save()
  526. messages.success(request, _('Thanks for adding a comment to Task #%(task_id)d.') % {'task_id': task_id})
  527. return redirect(nxt + '#task-%d' % task_id)
  528. elif request.POST.get('preview'):
  529. context['template'] = 'patt/task/comment.html' # the template for preview (template)
  530. context['comment'] = CommentLike(request, comment) # the object to be used in the preview template
  531. return render(request, 'patt/raw_single_form.html', context=context)
  532. else:
  533. permission_denied_msg_comment(request, task_id)
  534. return redirect(nxt + '#task-%d' % task_id)
  535. @login_required
  536. def patt_commentedit(request, task_id, comment_id):
  537. context = Context(request) # needs to be executed first because of time mesurement
  538. nxt = get_next(request)
  539. comment = Comment.objects.get(id=comment_id)
  540. acc = acc_task(comment.task, request.user)
  541. if acc.modify_comment:
  542. if not request.POST:
  543. form = CommentForm(instance=comment, acc=acc)
  544. context_adaption(
  545. context, # the base context
  546. request, # the request object to be used in context_adaption
  547. form=form, # the form object to create the form (template)
  548. next=nxt, # the url for redirection
  549. next_anchor='task-%d' % task_id, # the anchor for redirection
  550. disable_delete=True, # disable delete button
  551. disable_search=True, # disable search button
  552. title=_('Edit Comment (Task #%d)') % task_id # the title for the page (template)
  553. )
  554. return render(request, 'patt/raw_single_form.html', context=context)
  555. else:
  556. form = CommentForm(request.POST, instance=comment, acc=acc)
  557. context_adaption(
  558. context, # the base context
  559. request, # the request object to be used in context_adaption
  560. form=form, # the form object to create the form (template)
  561. next=nxt, # the url for redirection
  562. next_anchor='task-%d' % task_id, # the anchor for redirection
  563. disable_delete=True, # disable delete button
  564. disable_search=True, # disable search button
  565. title=_('Edit Comment (Task #%d)') % task_id # the title for the page (template)
  566. )
  567. #
  568. if request.POST.get('save'):
  569. if form.is_valid():
  570. if form.save().save_needed:
  571. messages.success(request, _('Thanks for editing a comment of Task #%(task_id)d.') % {'task_id': task_id})
  572. else:
  573. no_change_msg(request)
  574. return redirect(nxt + '#task-%d' % task_id)
  575. elif request.POST.get('preview'):
  576. context['template'] = 'patt/task/comment.html' # the template for preview (template)
  577. context['comment'] = CommentLike(request, comment) # the object to be used in the preview template
  578. return render(request, 'patt/raw_single_form.html', context=context)
  579. else:
  580. permission_denied_msg_comment(request, task_id)
  581. return redirect(nxt + '#task-%d' % task_id)
  582. def patt_filteredit(request, search_id=None):
  583. def filter_does_not_exist_error(request, search_id):
  584. messages.error(request, _('Filter #%d does not exist.') % search_id)
  585. context = Context(request) # needs to be executed first because of time mesurement
  586. if not request.POST:
  587. if search_id is not None:
  588. try:
  589. form = SearchForm(instance=Search.objects.get(id=search_id))
  590. except Search.DoesNotExist:
  591. filter_does_not_exist_error(request, search_id)
  592. return redirect('/')
  593. else:
  594. if patt.get_search_query(request) is None:
  595. form = SearchForm(initial={'user': request.user})
  596. else:
  597. form = SearchForm(initial={'search_txt': patt.get_search_query(request), 'user': request.user})
  598. context_adaption(
  599. context, # the base context
  600. request, # the request object to be used in context_adaption
  601. form=form, # the form object to create the form (template)
  602. disable_preview=True, # disable the preview button
  603. disable_search=True, # disable search button
  604. title=_('Edit Filter') # the title for the page (template)
  605. )
  606. return render(request, 'patt/raw_single_form.html', context=context)
  607. else:
  608. if search_id is not None:
  609. try:
  610. s = Search.objects.get(id=search_id)
  611. except Search.DoesNotExist:
  612. filter_does_not_exist_error(request, search_id)
  613. return redirect('/')
  614. else:
  615. s = Search(user=request.user)
  616. if request.user == s.user:
  617. form = SearchForm(request.POST, instance=s)
  618. context_adaption(
  619. context, # the base context
  620. request, # the request object to be used in context_adaption
  621. form=form, # the form object to create the form (template)
  622. disable_preview=True, # disable the preview button
  623. disable_search=True, # disable search button
  624. title=_('Edit Filter') # the title for the page (template)
  625. )
  626. #
  627. if request.POST.get('save'):
  628. if form.is_valid():
  629. s.save()
  630. messages.success(request, _('Thanks for editing Filter #%(search_id)d.') % {'search_id': s.id})
  631. return redirect(patt.url_tasklist(request, user_filter_id=s.id))
  632. elif request.POST.get('delete'):
  633. messages.success(request, _('Filter #%(search_id)d delteted.') % {'search_id': s.id})
  634. s.delete()
  635. return redirect('/')
  636. return render(request, 'patt/raw_single_form.html', context=context)
  637. else:
  638. messages.error(request, _('Access to Filter (%s) denied.') % repr(search_id))
  639. return redirect('/')
  640. def patt_easysearch(request):
  641. context = Context(request) # needs to be executed first because of time mesurement
  642. if not request.POST:
  643. form = EasySearchForm()
  644. context_adaption(
  645. context, # the base context
  646. request, # the request object to be used in context_adaption
  647. form=form, # the form object to create the form (template)
  648. disable_preview=True, # disable the preview button
  649. disable_delete=True, # disable the delete button
  650. disable_save=True, # disable save button
  651. title=_('Edit Filter') # the title for the page (template)
  652. )
  653. return render(request, 'patt/raw_single_form.html', context=context)
  654. else:
  655. form = EasySearchForm(request.POST)
  656. form_data = dict(form.data)
  657. if 'states' not in form_data:
  658. form_data['states'] = []
  659. return redirect(patt.url_tasklist(request, search_txt=mk_search_pattern(**form_data)))
  660. def patt_helpview(request, page='main'):
  661. context = Context(request) # needs to be executed first because of time mesurement
  662. help_content = help_pages[page]
  663. context_adaption(
  664. context, # the base context
  665. request, # the request object to be used in context_adaption
  666. current_help_page=page, # the current help_page to identify which taskbar entry has to be highlighted
  667. help_content=help_content, # the help content itself (template)
  668. title=_('Help') # the title for the page (template)
  669. )
  670. return render(request, 'patt/help.html', context=context)