Django Library PaTT
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

views.py 36KB

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