Attachment 'TaskPlanner-1.8.4.py'
Download 1 # -*- coding: utf-8 -*-
2 """
3 MoinMoin - TaskPlanner Action
4 Version 0.9
5
6 A task planner plugin for Moin.
7
8 General information:
9 * The task database file "task-db" is located in the wiki's data dir and is
10 a plain text file.
11 * The total number of tasks is currently restricted to 999.999 tasks. However
12 a plain text database doesn't scale very well. So try to keep the database
13 small and do remove task not needed anymore.
14 * Note: Removing a task from the database does also mean: deleting the task's wiki
15 homepage.
16 * Note: You have to be superuser to be able to remove tasks. Normal users can mark
17 a completed task with the label "remove me" so superuser get to know which tasks to
18 remove.
19
20 @copyright: 2007 by Oliver Siemoneit
21 @license: GNU GPL, see COPYING for details.
22
23 """
24
25 import os, time
26 from MoinMoin import config, wikiutil, user
27 from MoinMoin.Page import Page
28 from MoinMoin.util import timefuncs
29
30
31 def _make_unique_task_id(request):
32 """
33 Make unique task id
34
35 @param request: request object
36 @return: 6-digit id (string)
37 """
38 from random import randint
39 databaseFile = os.path.join(request.cfg.data_dir, "task-db")
40 if os.path.isfile(databaseFile):
41 existing_id = task_id = 0
42 while task_id == existing_id:
43 task_id = "%06d" % randint(1, 999999)
44 for line in open(databaseFile).readlines():
45 tmp = line.split("\t")
46 existing_id = tmp[0]
47 if existing_id == task_id:
48 break
49 else:
50 task_id = "%06d" % randint(1, 999999)
51
52 return task_id
53
54
55 def _make_local_timestamp(request):
56 """
57 Make a timestamp for creation/closing of task
58
59 @param request: request object
60 @return: timestamp (string)
61 """
62 now = time.time()
63 user = request.user
64
65 if user.valid and user.tz_offset:
66 tz = user.tz_offset
67 tz -= tz % 60
68 minutes = tz / 60
69 hours = minutes / 60
70 minutes -= hours * 60
71 now += tz
72
73 return time.strftime("%Y.%m.%dT%H:%M:%S", timefuncs.tmtuple(now))
74
75
76 def do_mainform(request, actname, msg=None):
77 """
78 Build the main form
79
80 @param request: request object
81 @param actname: actname object
82 @param msg: message to display
83 @return: html form (string)
84 """
85 _ = request.getText
86 ticket = wikiutil.createTicket(request)
87 querytext = _('TaskPlanner User Interface')
88 button1 = _('Add Task')
89 button2 = _('Edit Task')
90 button3 = _('Remove Task')
91 button4 = _('Close')
92
93 formhtml1 = '''
94 <form method="post" action="">
95 <strong>%s <br></strong>''' % querytext
96
97 if msg:
98 formhtml2 = "<br> %s <br>" % msg
99 else:
100 formhtml2 = ""
101
102 formhtml3 = '''
103 <br>
104 <input type="hidden" name="action" value="%(actname)s">
105 <input type="hidden" name="ticket" value="%(ticket)s">
106 <input class="buttons" type="submit" name="button_add" value="%(button1)s">
107 <input class="buttons" type="submit" name="button_edit" value="%(button2)s"> ''' % {
108 'actname' : actname,
109 'ticket' : ticket,
110 'button1' : button1,
111 'button2' : button2, }
112
113 if request.user.isSuperUser():
114 formhtml4 = '''
115 <input class="buttons" type="submit" name="button_remove" value="%(button3)s">''' % {
116 'button3' : button3, }
117
118 else:
119 formhtml4 = ""
120
121 formhtml5 = '''
122 <input class="buttons" type="submit" name="button_cancel" value="%(button4)s">
123 </form>''' % {
124 'button4' : button4, }
125
126 formhtml = formhtml1 + formhtml2 + formhtml3 + formhtml4 + formhtml5
127 return formhtml
128
129
130 def do_addform(request, actname, page, msg=None, assoc_page=None, assign=None):
131 """
132 Build the 'add task' form
133
134 @param request: request object
135 @param actname: actname object
136 @param page: page object
137 @param msg: message to display
138 @param assoc_page: preset page association (by TaskTable macro)
139 @param assign: preset assign (by TaskTable macro)
140 @return: html form (string)
141 """
142 _ = request.getText
143 ticket = wikiutil.createTicket(request)
144 task_id = _make_unique_task_id(request)
145 querytext = _('Add Task')
146 button1 = _('Add')
147 button2 = _('Cancel')
148 label1 = _('Task ID')
149 value1 = task_id
150 label2 = _('Created by')
151 value2 = request.user.name
152 label3 = _('Created on')
153 value3 = _make_local_timestamp(request)
154 label4 = _('Task name')
155 value4 = ""
156 label5 = _('Assigned to')
157 if assign:
158 value5 = assign.replace('%20', ' ')
159 else:
160 value5 = ""
161 label6 = _('Time-frame')
162 value6 = ""
163 label7 = _('Priority')
164 value7 = ""
165 label8 = _('Status')
166 value8 = _('to do')
167 label9 = _('Task description')
168 value9 = ""
169 label10 = _('Task\'s wiki homepage')
170 value10 = "Taskplanner/%s" % task_id
171 label11 = _('Task associated with page')
172 if assoc_page:
173 value11 = assoc_page.replace('%20', ' ')
174 else:
175 value11 = page.page_name
176
177 formhtml1 = '''
178 <form method="post" action="">
179 <div class="userpref">
180 <strong>%s <br></strong>''' % querytext
181
182 if msg:
183 formhtml2 = "%s" % msg
184 else:
185 formhtml2 = ""
186
187 formhtml3 = '''
188 <br>
189 <input type="hidden" name="action" value="%(actname)s">
190 <input type="hidden" name="ticket" value="%(ticket)s">
191 <input type="hidden" name="closed_by" value="unknown">
192 <input type="hidden" name="closed_at" value="unknown">
193 <table border="0">
194 <tr>
195 <td class="label"><label>%(label1)s</label></td>
196 <td class="content">
197 <input type="text" name="task_id" value="%(value1)s" size="6" readonly="readonly">
198 </td>
199 </tr>
200 <tr>
201 <td class="label"><label>%(label2)s</label></td>
202 <td class="content">
203 <input type="text" name="created_by" value="%(value2)s" size="36" readonly="readonly">
204 </td>
205 </tr>
206 <tr>
207 <td class="label"><label>%(label3)s</label></td>
208 <td class="content">
209 <input type="text" name="created_at" value="%(value3)s" size="36" readonly="readonly">
210 </td>
211 </tr>
212 <tr>
213 <td class="label"><label>%(label4)s</label></td>
214 <td class="content">
215 <input type="text" name="task_name" value="%(value4)s" size="36" maxlength="50">
216 </td>
217 </tr>
218 <tr>
219 <td class="label"><label>%(label5)s</label></td>
220 <td class="content">
221 <input type="text" name="assigned_to" value="%(value5)s" size="36" maxlength="100">
222 </td>
223 </tr>
224 <tr>
225 <td class="label"><label>%(label6)s</label></td>
226 <td class="content">
227 <input type="text" name="time_frame" value="%(value6)s" size="36" maxlength="20">
228 </td>
229 </tr>
230 <tr>
231 <td class="label"><label>%(label7)s</label></td>
232 <td class="content">
233 <select name="priority" size="1">
234 <option selected value=""> </option>
235 <option value="low">%(low)s</option>
236 <option value="medium">%(medium)s</option>
237 <option value="high">%(high)s</option>
238 <option value="critical">%(critical)s</option>
239 </select>
240 </td>
241 </tr>
242 <tr>
243 <td class="label"><label>%(label8)s</label></td>
244 <td class="content">
245 <select name="status" size="1">
246 <option selected value="to do">%(ToDo)s</option>
247 <option value="in progress">%(InProgress)s</option>
248 <option value="pending">%(Pending)s</option>
249 </select>
250 </td>
251 </tr>
252 <tr>
253 <td class="label"><label>%(label9)s</label></td>
254 <td class="content">
255 <input type="text" name="task_desc" value="%(value9)s" size="80" maxlength="100">
256 </td>
257 </tr>
258 <tr>
259 <td class="label"><label>%(label10)s</label></td>
260 <td class="content">
261 <input type="text" name="task_disc_page" value="%(value10)s" size="80" maxlength="100">
262 </td>
263 </tr>
264 <tr>
265 <td class="label"><label>%(label11)s</label></td>
266 <td class="content">
267 <input type="text" name="task_assoc" value="%(value11)s" size="80" maxlength="100">
268 </td>
269 </tr>
270 <tr>
271 <td> </td>
272 <td>
273 <input class="buttons" type="submit" name="button_add_a" value="%(button1)s">
274 <input class="buttons" type="submit" name="button_back" value="%(button2)s">
275 </td>
276 </tr>
277 </table>
278 </div>
279 </form>''' % {
280 'actname' : actname,
281 'ticket' : ticket,
282 'label1' : label1,
283 'value1' : value1,
284 'label2' : label2,
285 'value2' : value2,
286 'label3' : label3,
287 'value3' : value3,
288 'label4' : label4,
289 'value4' : value4,
290 'label5' : label5,
291 'value5' : value5,
292 'label6' : label6,
293 'value6' : value6,
294 'label7' : label7,
295 'low' : _('low'),
296 'medium' : _('medium'),
297 'high' : _('high'),
298 'critical' : _('critical'),
299 'label8' : label8,
300 'ToDo' : _('to do'),
301 'Pending' : _('pending'),
302 'InProgress' : _('in progress'),
303 'label9' : label9,
304 'value9' : value9,
305 'label10' : label10,
306 'value10' : value10,
307 'label11' : label11,
308 'value11' : value11,
309 'button1' : button1,
310 'button2' : button2
311 }
312 formhtml = formhtml1 + formhtml2 + formhtml3
313 return formhtml
314
315
316 def _check_form_input(request):
317 """
318 Check for valid input in 'add task' and 'edit task' form
319
320 @param request: request object
321 @result: result (string)
322 """
323 _ = request.getText
324 task_name = request.form.get('task_name', [""])[0]
325 task_name = task_name.strip(' ')
326 if task_name == "":
327 return (_('You have to specify a task name.'), "warning")
328
329 assigned_to = request.form.get('assigned_to', [""])[0]
330 assigned_to = assigned_to.strip(' ')
331 if assigned_to == "":
332 return (_('You have to assign the task to someone.'), "warning")
333
334 time_frame = request.form.get('time_frame', [""])[0]
335 time_frame = time_frame.strip(' ')
336 if time_frame != "":
337 from time import strptime
338 try:
339 time_struct = strptime(time_frame, "%d.%m.%y")
340 except ValueError:
341 try:
342 time_struct = strptime(time_frame, "%d.%m.%y %H:%M")
343 except ValueError:
344 return (_('Valid time-frame formats are either dd.mm.yy or dd.mm.yy hh:mm.'),"warning")
345 return ""
346
347
348 def _save_task(request):
349 """
350 Save task data to disc
351
352 @param request: request object
353 @return: result (string)
354 """
355 _ = request.getText
356 task_id = request.form.get('task_id', [""])[0]
357 created_by = request.form.get('created_by', [""])[0]
358 created_at = request.form.get('created_at', [""])[0]
359 closed_by = request.form.get('closed_by', [""])[0]
360 closed_at = request.form.get('closed_at', [""])[0]
361 task_name = request.form.get('task_name', [""])[0]
362 task_name = wikiutil.escape(task_name, 1)
363 task_name = wikiutil.clean_input(task_name)
364 assigned_to = request.form.get('assigned_to', [""])[0]
365 assigned_to = wikiutil.escape(assigned_to, 1)
366 assigned_to = wikiutil.clean_input(assigned_to)
367 time_frame = request.form.get('time_frame', [""])[0]
368 priority = request.form.get('priority', [""])[0]
369 status = request.form.get('status', [""])[0]
370 task_desc = request.form.get('task_desc', [""])[0]
371 if task_desc != "":
372 task_desc = wikiutil.escape(task_desc, 1)
373 task_desc = wikiutil.clean_input(task_desc)
374 task_disc_page = request.form.get('task_disc_page', [""])[0]
375 if task_disc_page != "":
376 task_disc_page = wikiutil.escape(task_disc_page, 1)
377 task_disc_page = wikiutil.clean_input(task_disc_page)
378 task_assoc = request.form.get('task_assoc', [""])[0]
379 if task_assoc != "":
380 task_assoc = wikiutil.escape(task_assoc, 1)
381 task_assoc = wikiutil.clean_input(task_assoc)
382
383 try:
384 databaseFile = os.path.join(request.cfg.data_dir, "task-db")
385 db = open(databaseFile,"a")
386 db.write("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" % (task_id,
387 created_by,
388 created_at,
389 closed_by,
390 closed_at,
391 task_name,
392 assigned_to,
393 time_frame,
394 priority,
395 status,
396 task_desc,
397 task_disc_page,
398 task_assoc))
399 db.close()
400 except IOError:
401 return (_('Error while trying to save task data.'), "error")
402 return (_('Task successfully saved.'), "ok")
403
404
405 def do_edit_search_form(request, actname, msg=None):
406 """
407 Build the 'search task for editing' form
408
409 @param request: request object
410 @param actname: actname object
411 @param msg: message to display
412 @return: html form (string)
413 """
414 _ = request.getText
415 ticket = wikiutil.createTicket(request)
416 querytext = _('Edit Task')
417 button1 = _('Edit')
418 button2 = _('Cancel')
419 label1 = _('Task ID')
420 value1 = ""
421
422 formhtml1 = '''
423 <form method="post" action="">
424 <div class="userpref">
425 <strong>%s <br></strong>''' % querytext
426
427 if msg:
428 formhtml2 = "%s" % msg
429 else:
430 formhtml2 = ""
431
432 formhtml3 = '''
433 <br>
434 <input type="hidden" name="action" value="%(actname)s">
435 <input type="hidden" name="ticket" value="%(ticket)s">
436 <table border="0">
437 <tr>
438 <td class="label"><label>%(label1)s</label></td>
439 <td class="content">
440 <input type="text" name="task_id" value="%(value1)s" size="6" maxlength="6">
441 </td>
442 </tr>
443 <tr>
444 <td> </td>
445 <td>
446 <input class="buttons" type="submit" name="button_search_id" value="%(button1)s">
447 <input class="buttons" type="submit" name="button_back" value="%(button2)s">
448 </td>
449 </tr>
450 </table>
451 </div>
452 </form>''' % {
453 'actname': actname,
454 'ticket' : ticket,
455 'label1' : label1,
456 'value1' : value1,
457 'button1': button1,
458 'button2': button2
459 }
460 formhtml = formhtml1 + formhtml2 + formhtml3
461 return formhtml
462
463
464 def do_editform(request, actname, page, task, msg=None):
465 """
466 Build the 'edit task' form
467
468 @param request: request object
469 @param actname: actname object
470 @param page: page object
471 @param task: task to edit
472 @param msg: message to display
473 @return: html form (string)
474 """
475 _ = request.getText
476 ticket = wikiutil.createTicket(request)
477 querytext = _('Edit Task')
478 button1 = _('Save')
479 button2 = _('Cancel')
480 label1 = _('Task ID')
481 value1 = task[0]
482 label2 = _('Created by')
483 value2 = task[1]
484 label3 = _('Created on')
485 value3 = task[2]
486 label4 = _('Closed by')
487 value4 = task[3]
488 label5 = _('Closed at')
489 value5 = task[4]
490 label6 = _('Task name')
491 value6 = task[5]
492 label7 = _('Assigned to')
493 value7 = task[6]
494 label8 = _('Time-frame')
495 value8 = task[7]
496 label9 = _('Priority')
497 value9 = task[8]
498 label10 = _('Status')
499 value10 = task[9]
500 label11 = _('Task description')
501 value11 = task[10]
502 label12 = _('Task\'s wiki homepage')
503 value12 = task[11]
504 label13 = _('Task associated with page')
505 value13 = task[12]
506
507 formhtml1 = '''
508 <form method="post" action="">
509 <div class="userpref">
510 <strong>%s <br></strong>''' % querytext
511
512 if msg:
513 formhtml2 = "%s" % msg
514 else:
515 formhtml2 = ""
516
517 formhtml3 = '''
518 <br>
519 <input type="hidden" name="action" value="%(actname)s">
520 <input type="hidden" name="ticket" value="%(ticket)s">
521 <table border="0">
522 <tr>
523 <td class="label"><label>%(label1)s</label></td>
524 <td class="content">
525 <input type="text" name="task_id" value="%(value1)s" size="6" readonly="readonly">
526 </td>
527 </tr>
528 <tr>
529 <td class="label"><label>%(label2)s</label></td>
530 <td class="content">
531 <input type="text" name="created_by" value="%(value2)s" size="36" readonly="readonly">
532 </td>
533 </tr>
534 <tr>
535 <td class="label"><label>%(label3)s</label></td>
536 <td class="content">
537 <input type="text" name="created_at" value="%(value3)s" size="36" readonly="readonly">
538 </td>
539 </tr> ''' % {
540 'actname': actname,
541 'ticket' : ticket,
542 'label1' : label1,
543 'value1' : value1,
544 'label2' : label2,
545 'value2' : value2,
546 'label3' : label3,
547 'value3' : value3
548 }
549
550 if value4 != "unknown":
551 formhtml4 = '''
552 <tr>
553 <td class="label"><label>%(label4)s</label></td>
554 <td class="content">
555 <input type="text" name="closed_by" value="%(value4)s" size="36" readonly="readonly">
556 </td>
557 </tr>
558 <tr>
559 <td class="label"><label>%(label5)s</label></td>
560 <td class="content">
561 <input type="text" name="closed_at" value="%(value5)s" size="36" readonly="readonly">
562 </td>
563 </tr> ''' % {
564 'label4' : label4,
565 'value4' : value4,
566 'label5' : label5,
567 'value5' : value5
568 }
569 else:
570 formhtml4 = '''
571 <input type="hidden" name="closed_by" value="%(value4)s">
572 <input type="hidden" name="closed_at" value="%(value5)s"> ''' % {
573 'value4' : value4,
574 'value5' : value5
575 }
576
577 formhtml5 = '''
578 <tr>
579 <td class="label"><label>%(label6)s</label></td>
580 <td class="content">
581 <input type="text" name="task_name" value="%(value6)s" size="36" maxlength="50">
582 </td>
583 </tr>
584 <tr>
585 <td class="label"><label>%(label7)s</label></td>
586 <td class="content">
587 <input type="text" name="assigned_to" value="%(value7)s" size="36" maxlength="100">
588 </td>
589 </tr>
590 <tr>
591 <td class="label"><label>%(label8)s</label></td>
592 <td class="content">
593 <input type="text" name="time_frame" value="%(value8)s" size="36" maxlength="20">
594 </td>
595 </tr>
596 <tr>
597 <td class="label"><label>%(label9)s</label></td>
598 <td class="content">
599 <select name="priority" size="1"> ''' % {
600 'label6' : label6,
601 'value6' : value6,
602 'label7' : label7,
603 'value7' : value7,
604 'label8' : label8,
605 'value8' : value8,
606 'label9' : label9
607 }
608 # ToDo: Make code more compact. Don't use if value9 = ..
609 if value9 == "":
610 formhtml6 = '''
611 <option selected value=""> </option>
612 <option value="low">%(low)s</option>
613 <option value="medium">%(medium)s</option>
614 <option value="high">%(high)s</option>
615 <option value="critical">%(critical)s</option>
616 </select>''' % { 'low' : _('low'),
617 'medium' : _('medium'),
618 'high' : _('high'),
619 'critical' : _('critical') }
620
621 if value9 == "low":
622 formhtml6 = '''
623 <option value=""> </option>
624 <option selected value="low">%(low)s</option>
625 <option value="medium">%(medium)s</option>
626 <option value="high">%(high)s</option>
627 <option value="critical">%(critical)s</option>
628 </select>''' % { 'low' : _('low'),
629 'medium' : _('medium'),
630 'high' : _('high'),
631 'critical' : _('critical') }
632
633 if value9 == "medium":
634 formhtml6 = '''
635 <option value=""> </option>
636 <option value="low">%(low)s</option>
637 <option selected value="medium">%(medium)s</option>
638 <option value="high">%(high)s</option>
639 <option value="critical">%(critical)s</option>
640 </select>''' % { 'low' : _('low'),
641 'medium' : _('medium'),
642 'high' : _('high'),
643 'critical' : _('critical') }
644
645 if value9 == "high":
646 formhtml6 = '''
647 <option value=""> </option>
648 <option value="low">%(low)s</option>
649 <option value="medium">%(medium)s</option>
650 <option selected value="high">%(high)s</option>
651 <option value="critical">%(critical)s</option>
652 </select>''' % { 'low' : _('low'),
653 'medium' : _('medium'),
654 'high' : _('high'),
655 'critical' : _('critical') }
656
657 if value9 == "critical":
658 formhtml6 = '''
659 <option value=""> </option>
660 <option value="low">%(low)s</option>
661 <option value="medium">%(medium)s</option>
662 <option value="high">%(high)s</option>
663 <option selected value="critical">%(critical)s</option>
664 </select>''' % { 'low' : _('low'),
665 'medium' : _('medium'),
666 'high' : _('high'),
667 'critical' : _('critical') }
668
669 formhtml7 = '''
670 </td>
671 </tr>
672 <tr>
673 <td class="label"><label>%(label10)s</label></td>
674 <td class="content">
675 <select name="status" size="1"> ''' % {
676 'label10' : label10 }
677
678 # ToDo: Make code more compact. Don't use if value10 = ..
679 if value10 == "to do":
680 formhtml8 = '''
681 <option selected value="to do">%(ToDo)s</option>
682 <option value="in progress">%(InProgress)s</option>
683 <option value="pending">%(Pending)s</option>
684 <option value="done">%(Done)s</option>
685 <option value="failed">%(Undone)s</option>
686 <option value="closed">%(Closed)s</option>
687 <option value="remove me">%(RemoveMe)s</option>''' % { 'ToDo' : _('to do'),
688 'InProgress' : _('in progress'),
689 'Pending' : _('pending'),
690 'Done' : _('done'),
691 'Undone' : _('failed'),
692 'Closed' : _('closed'),
693 'RemoveMe' : _('remove me') }
694
695 if value10 == "in progress":
696 formhtml8 = '''
697 <option value="to do">%(ToDo)s</option>
698 <option selected value="in progress">%(InProgress)s</option>
699 <option value="pending">%(Pending)s</option>
700 <option value="done">%(Done)s</option>
701 <option value="failed">%(Undone)s</option>
702 <option value="closed">%(Closed)s</option>
703 <option value="remove me">%(RemoveMe)s</option>''' % { 'ToDo' : _('to do'),
704 'InProgress' : _('in progress'),
705 'Pending' : _('pending'),
706 'Done' : _('done'),
707 'Undone' : _('failed'),
708 'Closed' : _('closed'),
709 'RemoveMe' : _('remove me') }
710
711 if value10 == "pending":
712 formhtml8 = '''
713 <option value="to do">%(ToDo)s</option>
714 <option value="in progress">%(InProgress)s</option>
715 <option selected value="pending">%(Pending)s</option>
716 <option value="done">%(Done)s</option>
717 <option value="failed">%(Undone)s</option>
718 <option value="closed">%(Closed)s</option>
719 <option value="remove me">%(RemoveMe)s</option>''' % { 'ToDo' : _('to do'),
720 'InProgress' : _('in progress'),
721 'Pending' : _('pending'),
722 'Done' : _('done'),
723 'Undone' : _('failed'),
724 'Closed' : _('closed'),
725 'RemoveMe' : _('remove me') }
726
727 if value10 == "done":
728 formhtml8 = '''
729 <option value="to do">%(ToDo)s</option>
730 <option value="in progress">%(InProgress)s</option>
731 <option value="pending">%(Pending)s</option>
732 <option selected value="done">%(Done)s</option>
733 <option value="failed">%(Undone)s</option>
734 <option value="closed">%(Closed)s</option>
735 <option value="remove me">%(RemoveMe)s</option>''' % { 'ToDo' : _('to do'),
736 'InProgress' : _('in progress'),
737 'Pending' : _('pending'),
738 'Done' : _('done'),
739 'Undone' : _('failed'),
740 'Closed' : _('closed'),
741 'RemoveMe' : _('remove me') }
742
743 if value10 == "failed":
744 formhtml8 = '''
745 <option value="to do">%(ToDo)s</option>
746 <option value="in progress">%(InProgress)s</option>
747 <option value="pending">%(Pending)s</option>
748 <option value="done">%(Done)s</option>
749 <option selected value="failed">%(Undone)s</option>
750 <option value="closed">%(Closed)s</option>
751 <option value="remove me">%(RemoveMe)s</option>''' % { 'ToDo' : _('to do'),
752 'InProgress' : _('in progress'),
753 'Pending' : _('pending'),
754 'Done' : _('done'),
755 'Undone' : _('failed'),
756 'Closed' : _('closed'),
757 'RemoveMe' : _('remove me') }
758
759 if value10 == "closed":
760 formhtml8 = '''
761 <option value="to do">%(ToDo)s</option>
762 <option value="in progress">%(InProgress)s</option>
763 <option value="pending">%(Pending)s</option>
764 <option value="done">%(Done)s</option>
765 <option value="failed">%(Undone)s</option>
766 <option selected value="closed">%(Closed)s</option>
767 <option value="remove me">%(RemoveMe)s</option>''' % { 'ToDo' : _('to do'),
768 'InProgress' : _('in progress'),
769 'Pending' : _('pending'),
770 'Done' : _('done'),
771 'Undone' : _('failed'),
772 'Closed' : _('closed'),
773 'RemoveMe' : _('remove me') }
774
775 if value10 == "remove me":
776 formhtml8 = '''
777 <option value="to do">%(ToDo)s</option>
778 <option value="in progress">%(InProgress)s</option>
779 <option value="pending">%(Pending)s</option>
780 <option value="done">%(Done)s</option>
781 <option value="failed">%(Undone)s</option>
782 <option value="closed">%(Closed)s</option>
783 <option selected value="remove me">%(RemoveMe)s</option>''' % { 'ToDo' : _('to do'),
784 'InProgress' : _('in progress'),
785 'Pending' : _('pending'),
786 'Done' : _('done'),
787 'Undone' : _('failed'),
788 'Closed' : _('closed'),
789 'RemoveMe' : _('remove me') }
790
791 formhtml9 = '''
792 </select>
793 </td>
794 </tr>
795 <tr>
796 <td class="label"><label>%(label11)s</label></td>
797 <td class="content">
798 <input type="text" name="task_desc" value="%(value11)s" size="80" maxlength="100">
799 </td>
800 </tr>
801 <tr>
802 <td class="label"><label>%(label12)s</label></td>
803 <td class="content">
804 <input type="text" name="task_disc_page" value="%(value12)s" size="80" maxlength="100">
805 </td>
806 </tr>
807 <tr>
808 <td class="label"><label>%(label13)s</label></td>
809 <td class="content">
810 <input type="text" name="task_assoc" value="%(value13)s" size="80" maxlength="100">
811 </td>
812 </tr>
813 <tr>
814 <td> </td>
815 <td>
816 <input class="buttons" type="submit" name="button_save_edit" value="%(button1)s">
817 <input class="buttons" type="submit" name="button_back_search" value="%(button2)s">
818 </td>
819 </tr>
820 </table>
821 </div>
822 </form>''' % {
823 'label11' : label11,
824 'value11' : value11,
825 'label12' : label12,
826 'value12' : value12,
827 'label13' : label13,
828 'value13' : value13,
829 'button1' : button1,
830 'button2' : button2
831 }
832 formhtml = formhtml1 + formhtml2 + formhtml3 + formhtml4 + formhtml5 + formhtml6 + formhtml7 + formhtml8 + formhtml9
833 return formhtml
834
835
836 def _save_changed_task(request, page):
837 """
838 Save changed task data to disc
839
840 @param request: request object
841 @param page: page object
842 @return: result (string)
843
844 """
845 _ = request.getText
846 task_id = request.form.get('task_id', [""])[0]
847 created_by = request.form.get('created_by', [""])[0]
848 created_at = request.form.get('created_at', [""])[0]
849 closed_by = request.form.get('closed_by', [""])[0]
850 closed_at = request.form.get('closed_at', [""])[0]
851 task_name = request.form.get('task_name', [""])[0]
852 task_name = wikiutil.escape(task_name, 1)
853 task_name = wikiutil.clean_input(task_name)
854 assigned_to = request.form.get('assigned_to', [""])[0]
855 assigned_to = wikiutil.escape(assigned_to, 1)
856 assigned_to = wikiutil.clean_input(assigned_to)
857 time_frame = request.form.get('time_frame', [""])[0]
858 priority = request.form.get('priority', [""])[0]
859 status = request.form.get('status', [""])[0]
860 task_desc = request.form.get('task_desc', [""])[0]
861 if task_desc != "":
862 task_desc = wikiutil.escape(task_desc, 1)
863 task_desc = wikiutil.clean_input(task_desc)
864 task_disc_page = request.form.get('task_disc_page', [""])[0]
865 if task_disc_page != "":
866 task_disc_page = wikiutil.escape(task_disc_page, 1)
867 task_disc_page = wikiutil.clean_input(task_disc_page)
868 task_assoc = request.form.get('task_assoc', [""])[0]
869 if task_assoc != "":
870 task_assoc = wikiutil.escape(task_assoc, 1)
871 task_assoc = wikiutil.clean_input(task_assoc)
872
873 databaseFile = os.path.join(request.cfg.data_dir, "task-db")
874 try:
875 db = open(databaseFile,"r")
876 taskdata = db.readlines()
877 db.close()
878 except IOError:
879 return (_('Error while trying to read task data.'), "error")
880
881 new_taskdata = []
882 for line in taskdata:
883 tmp = line.split("\t")
884 if tmp[0] == task_id:
885 # task closed
886 if (status == "closed" or status == "remove me") and (tmp[9] != "closed" or tmp[9] != "remove me"):
887 tmp[3] = request.user.name
888 tmp[4] = _make_local_timestamp(request)
889 # task reopend
890 if status in ["to do", "in progress", "pending", "done", "failed"] and (tmp[9] == "closed" or tmp[9] == "remove me"):
891 tmp[3] = "unknown"
892 tmp[4] = "unknown"
893 tmp[5] = task_name
894 tmp[6] = assigned_to
895 tmp[7] = time_frame
896 tmp[8] = priority
897 tmp[9] = status
898 tmp[10] = task_desc
899 tmp[11] = task_disc_page
900 tmp[12] = task_assoc
901 newline = "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" % (tmp[0],
902 tmp[1],
903 tmp[2],
904 tmp[3],
905 tmp[4],
906 tmp[5],
907 tmp[6],
908 tmp[7],
909 tmp[8],
910 tmp[9],
911 tmp[10],
912 tmp[11],
913 tmp[12])
914 new_taskdata += newline
915 else:
916 new_taskdata += line
917
918 try:
919 db = open(databaseFile,"w")
920 db.writelines(new_taskdata)
921 db.close()
922 except IOError:
923 return (_('Error while trying to save task data.'),"error")
924
925 return (_('Task successfully saved.'),"ok")
926
927
928 def do_removeform(request, actname, msg=None):
929 """
930 Build the 'remove task' form
931
932 @param request: request object
933 @param actname: actname object
934 @param msg: message to display
935 @return: html form (string)
936 """
937 _ = request.getText
938 ticket = wikiutil.createTicket(request)
939 querytext = _('Remove Task')
940 button1 = _('Remove')
941 button2 = _('Cancel')
942 label1 = _('Task ID')
943 value1 = ""
944
945 formhtml1 = '''
946 <form method="post" action="">
947 <div class="userpref">
948 <strong>%s <br></strong>''' % querytext
949
950 if msg:
951 formhtml2 = "%s" % msg
952 else:
953 formhtml2 = ""
954
955 formhtml3 = '''
956 <br>
957 <input type="hidden" name="action" value="%(actname)s">
958 <input type="hidden" name="ticket" value="%(ticket)s">
959 <table border="0">
960 <tr>
961 <td class="label"><label>%(label1)s</label></td>
962 <td class="content">
963 <input type="text" name="task_id" value="%(value1)s" size="6" maxlength="6">
964 </td>
965 </tr>
966 <tr>
967 <td> </td>
968 <td>
969 <input class="buttons" type="submit" name="button_remove_id" value="%(button1)s">
970 <input class="buttons" type="submit" name="button_back" value="%(button2)s">
971 </td>
972 </tr>
973 </table>
974 </div>
975 </form>''' % {
976 'actname': actname,
977 'ticket' : ticket,
978 'label1' : label1,
979 'value1' : value1,
980 'button1': button1,
981 'button2': button2
982 }
983 formhtml = formhtml1 + formhtml2 + formhtml3
984 return formhtml
985
986
987 def _remove_task(request, task_to_remove=None):
988 """
989 Remove task from database
990
991 @param request: request object
992 @param task_to_remove: id of task to remove
993 @return: tuple result, message (bool, string)
994 """
995 _ = request.getText
996 if task_to_remove == None:
997 task_id = request.form['task_id'][0]
998 else:
999 task_id = task_to_remove
1000 databaseFile = os.path.join(request.cfg.data_dir, "task-db")
1001 if os.path.isfile(databaseFile):
1002 try:
1003 db = open(databaseFile, "r")
1004 database = db.readlines()
1005 db.close()
1006 except:
1007 return (False, (_('Error while trying to remove task from database.'), "error"))
1008 found = False
1009 task_homepage = ""
1010 new_database = []
1011 for line in database:
1012 tmp = line.split("\t")
1013 if tmp[0] == task_id:
1014 found = True
1015 task_homepage = tmp[11]
1016 else:
1017 new_database += line
1018
1019 if found == True:
1020 try:
1021 db = open(databaseFile, "w")
1022 db.writelines(new_database)
1023 db.close()
1024 except:
1025 return (False, (_('Error while trying to remove task from database.'), "error"))
1026 if Page(request, task_homepage).exists():
1027 if request.user.may.delete(task_homepage):
1028 page = PageEditor(request, task_homepage, do_editor_backup=0)
1029 success, msg = page.deletePage()
1030 if success:
1031 return (True, (_("Task and task's wiki homepage successfully removed."),"ok"))
1032 else:
1033 return (True, (_("Task successfully removed from database. Error while trying to delete task's wiki homepage."),"warning"))
1034 else:
1035 return (True, (_("Task successfully removed from database. Error while trying to delete task's wiki homepage: You are not allowed to delete this page."),"warning"))
1036 return (True, (_('Task successfully removed.'),"ok"))
1037 else:
1038 return (False, (_('Task not found.'),"error"))
1039 else:
1040 return (False, (_('Database not found.'),"error"))
1041
1042
1043 def execute(pagename, request):
1044 _ = request.getText
1045 actname = __name__.split('.')[-1]
1046 page = Page(request, pagename)
1047
1048 # check whether user is logged in
1049 if request.user.valid == 0:
1050 # return page.send_page(msg=_('Please log in first.'))
1051 request.theme.add_msg(_('Please log in first.'),'error')
1052 return page.send_page()
1053
1054 # ckeck whether action is allowed
1055 if actname in request.cfg.actions_excluded:
1056 # return page.send_page(msg=_('You are not allowed to perform this action.'))
1057 request.theme.add_msg(_('You are not allowed to perform this action.'),"warning")
1058 return page.send_page()
1059
1060 # check whether page does really exist
1061 if not page.exists():
1062 # return page.send_page(msg=_('This page is already deleted or was never created!'))
1063 request.theme.add_msg(_('This page is already deleted or was never created!'),"error")
1064 return page.send_page()
1065
1066 #
1067 # 'add task' called from outside by the macro via "?action=TaskPlanner&add" (currently not used)
1068 #
1069 if request.form.has_key('action') and request.form.has_key('add'):
1070 # check whether this is a valid request (make outside
1071 # attacks harder by requiring two full HTTP transactions)
1072 if not request.form.has_key('ticket'):
1073 # return page.send_page(msg=_('Please use the interactive user interface for adding, editing and removing tasks.'))
1074 # msg=_('Please use the interactive user interface for adding, editing and removing tasks.')
1075 request.theme.add_msg(_('Please use the interactive user interface for adding, editing and removing tasks.'),"warning")
1076 return page.send_page()
1077
1078 if not wikiutil.checkTicket(request, request.form['ticket'][0]):
1079 # return page.send_page(msg=_('Please use the interactive user interface for adding, editing and removing tasks.'))
1080 request.theme.add_msg(_('Please use the interactive user interface for adding, editing and removing tasks.'),"warning")
1081 return page.send_page()
1082
1083 if request.form.has_key('button_back'):
1084 return page.send_page()
1085
1086 # check whether TaskTable macro has forwarded information on page and assign
1087 assoc_page = assign = None
1088 if request.form.has_key('page'):
1089 assoc_page = request.form.get('page', [None])[0]
1090 if request.form.has_key('assign'):
1091 assign = request.form.get('assign', [None])[0]
1092
1093 if request.form.has_key('button_add_a'):
1094 result = _check_form_input(request)
1095 if result =="":
1096 result = _save_task(request)
1097 # return page.send_page(msg=result)
1098 request.theme.add_msg(*result)
1099 return page.send_page()
1100 else:
1101 # return page.send_page(msg=do_addform(request, actname, page, msg=result, assoc_page=assoc_page, assign=assign))
1102 request.theme.add_msg(_(do_addform(request, actname, page, msg=result[0], assoc_page=assoc_page, assign=assign)),result[1])
1103 return page.send_page()
1104
1105 # return page.send_page(msg=do_addform(request, actname, page, assoc_page=assoc_page, assign=assign))
1106 request.theme.add_msg(_(do_addform(request, actname, page, assoc_page=assoc_page, assign=assign)))
1107 return page.send_page()
1108
1109 #
1110 # 'edit task' called from outside by the macro via "?action=TaskPlanner&edit=[task_id]"
1111 #
1112 elif request.form.has_key('action') and request.form.has_key('edit'):
1113 # check whether this is a valid request (make outside
1114 # attacks harder by requiring two full HTTP transactions)
1115 if not request.form.has_key('ticket'):
1116 # return page.send_page(msg=_('Please use the interactive user interface for adding, editing and removing tasks.'))
1117 request.theme.add_msg(_('Please use the interactive user interface for adding, editing and removing tasks.'),"warning")
1118 return page.send_page()
1119
1120 if not wikiutil.checkTicket(request, request.form['ticket'][0]):
1121 # return page.send_page(msg=_('Please use the interactive user interface for adding, editing and removing tasks.'))
1122 request.theme.add_msg(_('Please use the interactive user interface for adding, editing and removing tasks.'),"warning")
1123 return page.send_page()
1124
1125 if request.form.has_key('button_back_search'):
1126 return page.send_page()
1127
1128 task_id = request.form.get('edit', [""])[0]
1129 databaseFile = os.path.join(request.cfg.data_dir, "task-db")
1130 if os.path.isfile(databaseFile):
1131 existing_id = 0
1132 found = False
1133 for line in open(databaseFile).readlines():
1134 tmp = line.split("\t")
1135 existing_id = tmp[0]
1136 if existing_id == task_id:
1137 found = True
1138 break
1139 else:
1140 # return page.send_page(msg=_('/!\\ Database not found. '))
1141 request.theme.add_msg(_('Database not found. '),"error")
1142 return page.send_page()
1143
1144 if request.form.has_key('button_save_edit'):
1145 result = _check_form_input(request)
1146 if result =="":
1147 result = _save_changed_task(request, page)
1148 # return page.send_page(msg=result)
1149 request.theme.add_msg(*result)
1150 return page.send_page()
1151 else:
1152 # return page.send_page(msg=do_editform(request, actname, page, tmp, msg=result))
1153 request.theme.add_msg(do_editform(request, actname, page, tmp, msg=result[0]))
1154 return page.send_page()
1155
1156 if found == True:
1157 # return page.send_page(msg=do_editform(request, actname, page, tmp))
1158 request.theme.add_msg(_(do_editform(request, actname, page, tmp)))
1159 return page.send_page()
1160
1161 else:
1162 #return page.send_page(msg=_('/!\\ Task not found. '))
1163 request.theme.add_msg(_('Task not found. '),"error")
1164 return page.send_page()
1165
1166 #
1167 # 'remove task' called from outside by the macro via "?action=TaskPlanner&remove=[task_id]"
1168 #
1169 elif request.form.has_key('action') and request.form.has_key('remove'):
1170 # check whether this is a valid request (make outside
1171 # attacks harder by requiring two full HTTP transactions)
1172 if not request.form.has_key('ticket'):
1173 #return page.send_page(msg=_('Please use the interactive user interface for adding, editing and removing tasks.'))
1174 request.theme.add_msg(_('Please use the interactive user interface for adding, editing and removing tasks.'),"warning")
1175 return page.send_page()
1176
1177 if not wikiutil.checkTicket(request, request.form['ticket'][0]):
1178 #return page.send_page(msg=_('Please use the interactive user interface for adding, editing and removing tasks.'))
1179 request.theme.add_msg(_('Please use the interactive user interface for adding, editing and removing tasks.'),"warning")
1180 return page.send_page()
1181
1182 if not request.user.isSuperUser():
1183 # return page.send_page(msg=_('You have to be superuser to remove items from the task list database.'))
1184 request.theme.add_msg(_('You have to be superuser to remove items from the task list database.'),"warning")
1185 return page.send_page()
1186
1187 task_id = request.form.get('remove', [""])[0]
1188 success, msg = _remove_task(request, task_id)
1189 # return page.send_page(msg=msg)
1190 request.theme.add_msg(*msg)
1191 return page.send_page()
1192
1193 #
1194 # Event handling for TaskPlanner user interface
1195 #
1196 elif request.form.has_key('action') and request.form.has_key('ticket'):
1197 # check whether ticket is valid (make outside attacks harder
1198 # by requiring two full HTTP transactions)
1199 if not request.form.has_key('ticket'):
1200 #return page.send_page(msg=_('Please use the interactive user interface for adding, editing and removing tasks.'))
1201 request.theme.add_msg(_('Please use the interactive user interface for adding, editing and removing tasks.'),"warning")
1202 return page.send_page()
1203
1204 if not wikiutil.checkTicket(request, request.form['ticket'][0]):
1205 # return page.send_page(msg=_('Please use the interactive user interface for adding, editing and removing tasks.'))
1206 request.theme.add_msg(_('Please use the interactive user interface for adding, editing and removing tasks.'),"warning")
1207 return page.send_page()
1208 #
1209 # 'add task' stuff
1210 #
1211
1212 # check whether TaskTable macro has forwarded information on page and assign
1213 assoc_page = assign = None
1214 if request.form.has_key('page'):
1215 assoc_page = request.form.get('page', [None])[0]
1216 if request.form.has_key('assign'):
1217 assign = request.form.get('assign', [None])[0]
1218
1219 # display menu for adding tasks
1220 if request.form.has_key('button_add'):
1221 #return page.send_page(msg=do_addform(request, actname, page, assoc_page=assoc_page, assign=assign))
1222 request.theme.add_msg(do_addform(request, actname, page, assoc_page=assoc_page, assign=assign))
1223 return page.send_page()
1224
1225 # user pressed button 'add task'
1226 if request.form.has_key('button_add_a'):
1227 result = _check_form_input(request)
1228 if result != "":
1229 #return page.send_page(msg=do_addform(request, actname, page, msg=result, assoc_page=assoc_page, assign=assign))
1230 request.theme.add_msg(_(do_addform(request, actname, page, msg=result[0], assoc_page=assoc_page, assign=assign)),result[1])
1231 return page.send_page()
1232 else:
1233 result = _save_task(request)
1234 # return page.send_page(msg=do_mainform(request, actname, msg=result))
1235 request.theme.add_msg(_(do_mainform(request, actname, msg=result[0])),result[1])
1236 return page.send_page()
1237
1238 #
1239 # 'edit task' stuff
1240 #
1241
1242 # display menu for searching task to edit
1243 if request.form.has_key('button_edit'):
1244 # return page.send_page(msg=do_edit_search_form(request, actname))
1245 request.theme.add_msg(_(do_edit_search_form(request, actname)))
1246 return page.send_page()
1247
1248 # user pressed button 'edit task' in the search task form
1249 if request.form.has_key('button_search_id'):
1250 task_id = request.form['task_id'][0]
1251 databaseFile = os.path.join(request.cfg.data_dir, "task-db")
1252 if os.path.isfile(databaseFile):
1253 existing_id = 0
1254 found = False
1255 for line in open(databaseFile).readlines():
1256 tmp = line.split("\t")
1257 existing_id = tmp[0]
1258 if existing_id == task_id:
1259 found = True
1260 break
1261 else:
1262 # return page.send_page(msg=do_edit_search_form(request, actname, msg=_('/!\\ Database not found. ')))
1263 request.theme.add_msg(_('Database not found. '),"error")
1264 return page.send_page()
1265
1266 if found == True:
1267 # return page.send_page(msg=do_editform(request, actname, page, tmp))
1268 request.theme.add_msg(do_editform(request, actname, page, tmp))
1269 return page.send_page()
1270 else:
1271 # return page.send_page(msg=do_edit_search_form(request, actname, msg=_('/!\\ Task not found. ')))
1272 request.theme.add_msg(_('Task not found. '),"warning")
1273 return page.send_page()
1274
1275 # user pressed button 'save edited' task
1276 if request.form.has_key('button_save_edit'):
1277 result = _check_form_input(request)
1278 # if we have invalid input, reload task data and display edit form again
1279 if result != "":
1280 task_id = request.form['task_id'][0]
1281 databaseFile = os.path.join(request.cfg.data_dir, "task-db")
1282 if os.path.isfile(databaseFile):
1283 existing_id = 0
1284 found = False
1285 for line in open(databaseFile).readlines():
1286 tmp = line.split("\t")
1287 existing_id = tmp[0]
1288 if existing_id == task_id:
1289 found = True
1290 break
1291 else:
1292 #return page.send_page(msg=do_edit_search_form(request, actname, msg=_('/!\\ Database not found. ')))
1293 request.theme.add_msg(_('Database not found. '),"error")
1294 return page.send_page()
1295 # return page.send_page(msg=do_editform(request, actname, page, tmp, msg=result))
1296 request.theme.add_msg(do_editform(request, actname, page, tmp, msg=result[0]),result[1])
1297 return page.send_page()
1298
1299 else:
1300 result = _save_changed_task(request, page)
1301 # return page.send_page(msg=do_mainform(request, actname, msg=result))
1302 request.theme.add_msg(do_mainform(request, actname, msg=result[0]),result[1])
1303 return page.send_page()
1304
1305 # user pressed button cancel editing task
1306 if request.form.has_key('button_back_search'):
1307 # return page.send_page(msg=do_mainform(request, actname))
1308 request.theme.add_msg(do_mainform(request, actname))
1309 return page.send_page()
1310
1311 #
1312 # 'remove task' stuff
1313 #
1314
1315 # display menu for removing tasks
1316 if request.form.has_key('button_remove'):
1317 if not request.user.isSuperUser():
1318 # return page.send_page(msg=do_mainform(request, actname, msg=_('You have to be superuser to remove items from the task list database.')))
1319 request.theme.add_msg(do_mainform(request, actname, msg=_('You have to be superuser to remove items from the task list database.')),"warning")
1320 return page.send_page()
1321 # return page.send_page(msg=do_removeform(request, actname))
1322 request.theme.add_msg(do_removeform(request, actname))
1323 return page.send_page()
1324
1325
1326
1327 # user pressed button 'remove task'
1328 if request.form.has_key('button_remove_id'):
1329 if not request.user.isSuperUser():
1330 # return page.send_page(msg=do_mainform(request, actname, msg= _('You have to be superuser to remove items from the task list database.')))
1331 request.theme.add_msg(do_mainform(request, actname, msg= _('You have to be superuser to remove items from the task list database.')),"warning")
1332 return page.send_page()
1333
1334 success, msg = _remove_task(request)
1335 if success:
1336 # return page.send_page(msg=do_mainform(request, actname, msg=msg))
1337 request.theme.add_msg(do_mainform(request, actname, msg=msg[0]),msg[1])
1338 return page.send_page()
1339 else:
1340 #return page.send_page(msg=do_removeform(request, actname, msg=msg))
1341 request.theme.add_msg(do_removeform(request, actname, msg=msg[0]),msg[1])
1342 return page.send_page()
1343
1344 # user pressed button 'cancel' in the main form
1345 if request.form.has_key('button_cancel'):
1346 return page.send_page()
1347
1348 # either no button was pressed (i.e. just display TaskPlanner user interface after calling the action
1349 # or 'button_back' was pressed (then show main form again)
1350 # return page.send_page(msg=do_mainform(request, actname))
1351 request.theme.add_msg(do_mainform(request, actname))
1352 return page.send_page()
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.