.
[gnutodo.git] / gtd
blob7576674fdabdb05da4f688568fccdff24bf067cf
1 #! /bin/zsh
2 function usage {
3 cat << EOF
4 --- $0 --- GNU Todo
5 Properties:
6 -s status
7 -i importance
8 -t timestamp
9 -p project
10 -c context
11 -l label
12 Options:
13 -T todo file
14 Actions:
15 -a add
16 -e edit (index)
17 -d done (index)
18 -r remove (index)
19 -C cleanup todo
20 -h help
21 EOF
22 exit
25 TS0=`date +%m%S%N`
26 function TS { echo $(( (`date +%m%S%N`-$TS0)/1000000 )) $@ ; } #date +%H:%m:%S.%N; }
28 BASEDIR=~/doc/org/gtd/own/
29 TODO=$BASEDIR/todo.txt
30 TMPFILE=/tmp/gtd.tmp.`cat /dev/urandom | tr -cd a-z0-9 | head -c 5`
31 STATES=""; PROJECTS=""; CONTEXTS=""; KEYS="";
32 TIMESTAMP_DEFAULT=99999999 #9999
33 TIMESTAMP_NOW=`date +%Y%m%d` #%H%m`
35 #SHELL_DEBUG=1
38 #-------
39 #ASCII <-> CGI encoded
40 #---
41 [[ $SHELL_DEBUG == 1 ]] && TS ascii - cgi
42 function STR2CGI {
43 sed '
44 s/ä/%E4/g;
45 s/Ä/%C4/g;
46 s/ö/%F6/g;
47 s/Ö/%D6/g;
48 s/ü/%FC/g;
49 s/Ü/%DC/g;
50 s/ß/%DF/g;
51 s/?/%3F/g;
52 s/&/%26/g;
53 s/+/%2B/g;
54 s/ /+/g;
55 s/"/%22/g;
56 s/=/%3D/g;
57 s/!/%21/g;
58 s/#/%23/g;
59 s/,/%2C/g;
60 s/:/%3A/g;
61 s/;/%3B/g;
62 s/@/%40/g;
63 s/\\/%5C/g;
64 s/\//%2F/g;
65 s/§/%A7/g;
66 s/\&/%26/g;
70 function CGI2STR {
71 sed '
72 s/%E4/ä/g;
73 s/%C4/Ä/g;
74 s/%F6/ö/g;
75 s/%D6/Ö/g;
76 s/%FC/ü/g;
77 s/%DC/Ü/g;
78 s/%DF/ß/g;
79 s/%3F/?/g;
80 s/%26/&/g;
81 s/+/ /g;
82 s/%22/"/g;
83 s/%3D/=/g;
84 s/%2B/+/g;
85 s/%21/!/g;
86 s/%23/#/g;
87 s/%2C/,/g;
88 s/%3A/:/g;
89 s/%3B/;/g;
90 s/%40/@/g;
91 s/%5C/\\/g;
92 s/%2F/\//g;
93 s/%A7/§/g;
94 s/%26/\&/g;
99 #-------
100 #Todo File Handling
101 #---
102 [[ $SHELL_DEBUG == 1 ]] && TS todo file handling
103 function MK_IDX { awk '{printf("I:%.3d ",NR);print$0;}'; }
104 function RM_IDX { sed 's/I:[0-9]* //g'; }
105 function CK_IDX { echo $1 | awk '{printf("%.3d",$1)}'; }
106 function SHOWENTRY { cat $TODO | MK_IDX | grep "^I:$1" | RM_IDX ; }
107 function RM_ENTRY { cat $TODO | MK_IDX | grep -v "^I:$1" | RM_IDX ; }
109 function COMPLETE_TIMESTAMP {
110 awk '
111 length($0)==4{print"'`date +%Y`'"$0;exit;}
112 length($0)==2{print"'`date +%Y%m`'"$0;exit;}
113 length($0)==7{yearmonth=$0;day=$0;gsub(".$","",yearmonth);gsub("^......","",day);print yearmonth"0"day}
114 length($0)==8{print;exit;}
115 ' ;
118 function getval {
119 TAG=$1;
120 shift;
121 if [[ $TAG == INDEX ]]; then
122 echo "$@" | sed 's/&/ /g;s/%/_percent_/g' | awk '{for(i=1;i<=NF;i++){if($i~/'$TAG'/){gsub("'$TAG'=","",$i);printf $i" "}}}' | sed 's/ $//;s/_percent_/%/g;'
123 elif [[ $TAG == projects ]]; then
124 echo "$@" | sed 's/&/ /g;s/%/_percent_/g' | awk '{for(i=1;i<=NF;i++){if($i~/'$TAG'/){gsub("'$TAG'=","",$i);printf $i" "}}}' | sed 's/ $//;s/_percent_/%/g;'
125 elif [[ $TAG == contexts ]]; then
126 echo "$@" | sed 's/&/ /g;s/%/_percent_/g' | awk '{for(i=1;i<=NF;i++){if($i~/'$TAG'/){gsub("'$TAG'=","",$i);printf $i" "}}}' | sed 's/ $//;s/_percent_/%/g;'
127 else
128 echo "$@" | grep "$TAG" | sed 's/\&/ /g' | grep "$TAG" | sed -r -e 's/\&/ /g;s/.*'$TAG'=([^ ]*).*/\1/';
133 #-------
134 #General GTD Operations
135 #---
136 [[ $SHELL_DEBUG == 1 ]] && TS general gtd operations
137 function SHOW {
138 [[ -z $STATES ]] && local STATES=aw
139 [[ -z $IMPORTANCE ]] && local IMPORTANCE=0
140 [[ -z $TIMESTAMP ]] && local TIMESTAMP=$TIMESTAMP_DEFAULT
141 REGEX_PROJ="`echo "($PROJECTS)" | sed 's/ /|/g;s/|)/)/;'`";
142 REGEX_CONT="`echo "($CONTEXTS)" | sed 's/ /|/g;s/|)/)/;'`";
144 cat $TODO | MK_IDX | egrep "$REGEX_PROJ" | egrep "$REGEX_CONT" | awk -v timestamp=$TIMESTAMP -v states=$STATES -v importance=$IMPORTANCE '
145 /status=[states]/ {
146 flag=0;
147 entry=$0;
148 for(i=1;i<=NF;i++) {
149 if ($i ~ /timestamp/) { gsub("timestamp=","",$i); if ($i > timestamp) { flag=1; } }
150 else if ($i ~ /importance/) { gsub("importance=","",$i); if ($i<importance) { flag=1; } }
152 if (flag == 0) { print entry; }
153 }' | sort -k 4.11,4.19 -k 3.12r # FIXME: Magic Numerz!
154 [[ $SHELL_DEBUG == 1 ]] && TS show >&2
157 function ADD {
158 ( [[ -z $STATES ]] || [[ ${#STATES} -gt 1 ]] ) && STATES=a
159 [[ -z $IMPORTANCE ]] && local IMPORTANCE=0
160 [[ -z $TIMESTAMP ]] && local TIMESTAMP=$TIMESTAMP_DEFAULT
161 [[ -z $LABEL ]] && [[ -n $ARGS ]] && LABEL="`echo $ARGS | STR2CGI`"
162 local ITEM="status=$STATES importance=$IMPORTANCE timestamp=$TIMESTAMP project=$PROJECTS context=$CONTEXTS label=$LABEL"
163 echo "Adding: $ITEM"
164 echo "$ITEM" >> $TODO
167 function EDIT {
168 local INDEX=$1; shift;
169 local ENTRY="`SHOWENTRY $INDEX`"
170 echo "Editing $INDEX: $ENTRY"
171 ( [[ -z $STATES ]] || [[ ${#STATES} -gt 1 ]] ) && local STATES="`getval status $ENTRY`"
172 [[ -z $IMPORTANCE ]] && local IMPORTANCE="`getval importance $ENTRY`"
173 [[ -z $TIMESTAMP ]] && local TIMESTAMP="`getval timestamp $ENTRY`"
174 [[ -z $PROJECTS ]] && local PROJECTS="`getval project $ENTRY`"
175 [[ -z $CONTEXTS ]] && local CONTEXTS="`getval context $ENTRY`"
176 [[ -z $LABEL ]] && local LABEL="`getval label $ENTRY`"
177 local ITEM="status=$STATES importance=$IMPORTANCE timestamp=$TIMESTAMP project=$PROJECTS context=$CONTEXTS label=$LABEL"
178 RM_ENTRY $INDEX > $TMPFILE
179 echo "$ITEM" >> $TMPFILE
180 mv $TMPFILE $TODO
181 echo " Now: $ITEM"
184 function DONE {
185 local INDEX=$1; shift;
186 local ENTRY="`SHOWENTRY $INDEX`"
187 local ITEM="`echo "$ENTRY" | sed 's/status=[aw]/status=d/g'`"
188 RM_ENTRY $INDEX > $TMPFILE
189 echo "$ITEM" >> $TMPFILE
190 mv $TMPFILE $TODO
191 echo "Done $INDEX: $ENTRY"
194 function REMOVE {
195 local INDEX=$1; shift;
196 local ENTRY="`SHOWENTRY $INDEX`"
197 echo "Remove $INDEX: $ENTRY"
198 RM_ENTRY $INDEX > $TMPFILE
199 mv $TMPFILE $TODO
202 function LIST_PROJ { cat $TODO | sed -r -e 's/\&/ /g;s/.*project=([^ ]*).*/\1/' | awk '! a[$0]++&&!/^$/' | sed -e :a -e '$!N;s/\n/ /;ta' ; }
203 function LIST_CONT { cat $TODO | sed -r -e 's/\&/ /g;s/.*context=([^ ]*).*/\1/' | awk '! a[$0]++&&!/^$/' | sed -e :a -e '$!N;s/\n/ /;ta' ; }
206 #-------
207 #Archiving
208 #---
209 [[ $SHELL_DEBUG == 1 ]] && TS archiving
210 function CLEANUP_TODO {
211 echo "Cleaning up $TODO"
212 cat $TODO | awk '/status=d/' > $TMPFILE.done
213 cat $TODO | awk '!/status=d/' > $TMPFILE.clean
214 cat $TMPFILE.done | gzip > $BASEDIR/todo.$TIMESTAMP_NOW.gz && rm $TMPFILE.done && echo "Created: todo.$TIMESTAMP_NOW.gz"
215 mv $TMPFILE.clean $TODO && echo "Created clean $TODO"
219 #-------
220 #Shell Functionality
221 #---
222 [[ $SHELL_DEBUG == 1 ]] && TS shell functionality
223 function SHELL_PARSE {
224 while getopts "s:i:t:p:c:l:ae:d:r:CT:h" opt; do
225 case $opt in
226 s) STATES=$STATES$OPTARG; ;;
227 i) IMPORTANCE=$OPTARG; ;;
228 t) TIMESTAMP="`echo $OPTARG | COMPLETE_TIMESTAMP`"; ;;
229 p) PROJECTS=${PROJECTS}"`echo $OPTARG | STR2CGI` "; ;;
230 c) CONTEXTS=${CONTEXTS}"`echo $OPTARG | STR2CGI` "; ;;
231 l) LABEL="`echo $OPTARG | STR2CGI`"; ;;
233 a) ACTION="ADD"; ;;
234 e) ACTION="EDIT"; INDEX=$INDEX"`CK_IDX $OPTARG` "; ;;
235 d) ACTION="DONE"; INDEX=$INDEX"`CK_IDX $OPTARG` "; ;;
236 r) ACTION="REMOVE"; INDEX=$INDEX"`CK_IDX $OPTARG` "; ;;
237 C) ACTION="CLEANUP_TODO"; ;;
239 T) TODO="$OPTARG"; ;;
241 h) usage ;;
242 *) usage ;;
243 esac
244 done
245 shift $(( $OPTIND - 1 ))
246 ARGS="$@"
250 function SHELL_OUTPUT {
251 local fg_blue="\033[0;34m"
252 local fg_green_lt="\033[1;32m"
253 local fg_cyan="\033[36m"
254 local fg_purple="\033[0;35m"
255 local fg_black="\033[30m"
256 local fg_white="\033[37m"
257 local fg_gray="\033[1;30m"
258 local bg_red="\033[41m"
259 local bg_yellow="\033[43m"
260 local bg_green="\033[42m"
261 local bg_white="\033[47m"
262 local bg_black="\033[40m"
263 local none="\033[0m"
265 local TS_RED=0
266 local TS_YELLOW=1
267 local TS_GREEN=3
269 echo "${fg_green_lt} .:| GNU-ToDo |:. ${none}"
270 echo "${fg_purple} Contexts: ${fg_cyan}`LIST_CONT | CGI2STR`${none}"
271 echo "${fg_blue} Projects: ${fg_cyan}`LIST_PROJ | CGI2STR`${none}"
273 SHOW | awk -v timestamp_ref=$TIMESTAMP -v timestamp_def=$TIMESTAMP_DEFAULT -v columns=$COLUMNS \
274 -v fg_gray=$fg_gray -v none=$none '
276 for (i=1;i<=NF;i++) {
277 if ($i ~ /I\:/) {
278 gsub("I:","",$i);
279 ind="'${fg_cyan}'"$i"'${none}'";
280 } else if ($i ~ /status/) {
281 gsub("status=","",$i)i;
282 if ($i == "a") { status=">"; }
283 else if ($i == "w") { status="<"; }
284 } else if ($i ~ /importance/) {
285 gsub("importance=","",$i);
286 if ($i == 0) { importance="."; }
287 else if ($i == 1) { importance="o"; }
288 else if ($i >= 1) { importance="O"; }
289 } else if ($i ~ /timestamp/) {
290 gsub("timestamp=","",$i);
291 if ($i == timestamp_def) { timestamp="'${fg_white}${bg_black}'-'${none}'"; }
292 else if ($i-timestamp_ref < 0) { timestamp="'${bg_red}${fg_black}'"$i"'${none}'"; }
293 else if ($i-timestamp_ref < '${TS_YELLOW}') { timestamp="'${bg_yellow}${fg_black}'"$i"'${none}'"; }
294 else if ($i-timestamp_ref < '${TS_GREEN}') { timestamp="'${bg_green}${fg_black}'"$i"'${none}'"; }
295 else if ($i-timestamp_ref >= '${TS_GREEN}') { timestamp="'${bg_white}${fg_black}'"$i"'${none}'"; }
296 } else if ($i ~ /project/) {
297 gsub("project=","",$i);
298 project="'${fg_blue}'"$i"'${none}'";
299 } else if ($i ~ /context/) {
300 gsub("context=","",$i);
301 context="'${fg_purple}'"$i"'${none}'";
302 } else if ($i ~ /label/) {
303 gsub("label=","",$i);
304 label=$i;
307 wdth=columns-16-10-10-10
308 printf (fg_gray"%1s%1s %s"fg_gray"%.1s"none" % -"wdth"s %.20s %.20s\n",
309 importance, timestamp, ind, status, label, project, context);
310 }' | CGI2STR
311 [[ $SHELL_DEBUG == 1 ]] && TS eof
315 #-------
316 #Webinterface
317 #---
318 [[ $SHELL_DEBUG == 1 ]] && TS webinterface
319 if [[ -z ${QUERY_STRING} ]]; then
320 SHELL_PARSE "$@"
321 [[ -z $ACTION ]] && ACTION="SHOW"
322 if [[ -n $INDEX ]]; then
323 for i in `echo $INDEX | sed 's/ /\n/g' | sort -nr`; do $ACTION $i; done
324 exit
326 if [[ $ACTION == "SHOW" ]]; then SHELL_OUTPUT;
327 else $ACTION; fi;
328 exit
332 function HTML_HEADER {
333 cat << __EOF__
334 Content-type: text/html
337 <html>
339 <head>
340 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
341 <base target="_top">
342 <style>
343 BODY {
344 background-color: #f0f0f0;
345 COLOR: #404040;
346 WIDTH: 99%;
347 font-size: 14px;
348 font-family: Verdana;
351 A:link { TEXT-DECORATION: none }
352 A:visited { COLOR: #606060; TEXT-DECORATION: none }
353 A:active { COLOR: #888888; TEXT-DECORATION: none; }
354 A:hover { BACKGROUND-COLOR: #ffffff; COLOR: #ff0000; TEXT-DECORATION: none }
356 td { font-family: Verdana; font-size: 11px; text-decoration: none }
357 tr { font-family: Verdana; font-size: 11px; text-decoration: none }
359 h1 { font-family: Times; font-size: 38px; font-weight: normal; padding:2px; background: #999; }
360 h2 { font-family: Times; font-size: 30px; font-weight: normal; padding:2px; background: #999}
361 h3 { font-family: Times; font-size: 22px; font-weight: normal; padding:2px;}
363 .red { background: #f00; padding: 1px; }
364 .amber { background: #ff6600; padding: 1px; }
365 .yellow { background: #FFD700; padding: 1px; }
366 .orange { background: #FFA500; padding: 1px; }
367 .green { background: #33cc00; padding: 1px; }
368 .grey { background: #e0e0e0; padding: 1px; }
369 .button { color: #202020; background: #b0b0b0; padding: 1px; }
370 .project { color: #404040; background: #D0D0D0; padding: 1px; margin-botton: 20px; }
371 .context { color: #404040; background: #D0D0D0; padding: 1px; }
372 .selected { color: #fff; background: #FFA500; padding: 1px; }
373 .date { color: #404040; }
374 .inputfield { color: #404040; background: #D0D0D0; padding: 1px; }
375 .active { }
376 .waiting { background: #e0e0e0; padding: 1px; }
377 .done { background: #e0e0e0; padding: 1px; }
378 .action { background: #ff6600; padding: 1px; }
380 </style>
382 <SCRIPT LANGUAGE="JavaScript">
383 // Checker
384 function checkAll(field) {
385 for (i = 0; i < field.length; i++)
386 field[i].checked = true ;
389 function uncheckAll(field) {
390 for (i = 0; i < field.length; i++)
391 field[i].checked = false ;
394 // Timestamp
395 function set_timestamp (ts) {
396 document.gtd.timestamp.value=ts;
399 // Key Processing
400 var inNav = navigator.appVersion.indexOf("MSIE") < 0;
401 function print_key (event, what) {
402 var key = (inNav==1) ? event.which : event.keyCode;
403 document.data.keyspressed.value = what + ":" + key + "=" + String.fromCharCode(key) + "\n" + document.data.keyspressed.value;
404 alert(String.fromCharCode(key));
407 function eval_key (event) {
408 key=String.fromCharCode((inNav==1) ? event.which : event.keyCode);
409 if (event.keyCode == 13) {
410 document.gtd.submit();
411 } else if (event.keyCode == 27) {
412 document.gtd.reset();
416 function fkt_chk(val) {
417 n_checked = 0;
418 for (i = 0; i < document.gtd.INDEX.length; i++)
419 if (document.gtd.INDEX[i].checked == true)
420 n_checked++;
421 if (n_checked == 0) {
422 } else if (n_checked == 1) {
423 } else {
427 // Hiding
428 function switchdiv(id){
429 if (document.getElementById) { // DOM3 = IE5, NS6
430 if (document.getElementById(id).style.display == 'none') {
431 showdiv(id);
432 } else { hidediv(id); }
433 } else if (document.layers) { // Netscape 4
434 if (document.id.display == 'none') {
435 showdiv(id);
436 } else { hidediv(id); }
437 } else {
438 if (document.all.id.style.display == 'none') {
439 showdiv(id);
440 } else { hidediv(id); }
444 function hidediv(id) {
445 //safe function to hide an element with a specified id
446 if (document.getElementById) { // DOM3 = IE5, NS6
447 document.getElementById(id).style.display = 'none';
448 } else {
449 if (document.layers) { // Netscape 4
450 document.id.display = 'none';
451 } else { // IE 4
452 document.all.id.style.display = 'none';
457 function showdiv(id) {
458 //safe function to show an element with a specified id
459 if (document.getElementById) { // DOM3 = IE5, NS6
460 document.getElementById(id).style.display = 'block';
461 } else {
462 if (document.layers) { // Netscape 4
463 document.id.display = 'block';
464 } else { // IE 4
465 document.all.id.style.display = 'block';
469 </script>
470 </head>
472 <body onkeypress="eval_key(event)">
473 __EOF__
476 function HTML_PARSE {
477 CONTEXTS="`getval contexts ${QUERY_STRING} | awk 'NF>0{print $NF}'`"
478 PROJECTS="`getval projects ${QUERY_STRING} | awk 'NF>0{print $NF}'`"
479 TIMESTAMP="`getval timestamp ${QUERY_STRING} | awk 'NF>0{print $NF}'`"
480 IMPORTANCE="`getval importance ${QUERY_STRING} | awk 'NF>0{print $NF}'`"
481 STATES="`getval states ${QUERY_STRING}`"
482 ACTION="`getval ACTION ${QUERY_STRING} | awk 'NF>0{print $NF}'`"
483 INDEX="`getval INDEX ${QUERY_STRING}`"
484 LABEL="`getval LABEL ${QUERY_STRING}`"
486 if [[ -z $ACTION ]]; then
487 if [[ -z $INDEX ]]; then
488 [[ -n $LABEL ]] && ACTION="ADD"
489 else
490 if ( [[ -n $LABEL ]] || [[ -n $PROJECTS ]] || [[ -n $CONTEXTS ]] || [[ -n $TIMESTAMP ]] || [[ -n $IMPORTANCE ]] ); then
491 ACTION="EDIT"
492 else
493 ACTION="DONE"
496 ACTION="SHOW"
497 elif [[ $ACTION != SHOW ]]; then
498 echo "<span id='ACTION' class='action'>"
499 DELAY=5000
500 if [[ $ACTION == ADD ]]; then
501 $ACTION
502 elif [[ $ACTION != SHOW ]]; then
503 for i in `echo $INDEX | sed 's/ /\n/g' | sort -nr`; do
504 $ACTION $i
505 done
507 LABEL=""
508 IMPORTANCE=""
509 STATUS=""
510 TIMESTAMP=$TIMESTAMP_DEFAULT
511 INDEX=""
512 sync; sync; sync;
513 echo "</span>"
516 [[ -z $TIMESTAMP ]] && TIMESTAMP=$TIMESTAMP_DEFAULT
520 function NICE_DATE {
521 echo "<pre>"
522 local YEAR="`date +%Y`"
523 local MONTH="`date +%m`"
524 local NEXTMONTH=`echo $(( $MONTH+1 )) | awk '{printf("%.2d",$1)}'`
525 [[ $1 == "CURRENT" ]] && cal -m | sed -r -e 's/\n//g;s/([^ ]*) '$YEAR'/ \1/;s/[0-9]*/<a href=\"javascript:set_timestamp('$YEAR$MONTH'&)\" class=\"date\">&<\/a>/g'
526 [[ $1 == "NEXT" ]] && cal -m -3 | sed -r -e 's/^.{44}//g;s/\n//g;s/([^ ]*) '$YEAR'/ \1/;s/[0-9]*/<a href=\"javascript:set_timestamp('$YEAR$NEXTMONTH'&)\" class=\"date\">&<\/a>/g'
527 echo "</pre>"
530 function SHOW_CONTEXTS {
531 cat << __EOF__
532 <SCRIPT LANGUAGE="JavaScript">window.setTimeout("hidediv('ACTION')",$DELAY)</script>
534 <table width="100%">
535 <colgroup>
536 <col width="85%">
537 <col width="15%">
538 </colgroup>
539 <tr>
540 <td style="border-bottom:1px solid;">
541 <table width="100%">
542 <tr>
543 <td>
544 __EOF__
546 LIST_CONT | awk '
548 for (i=1;i<=NF;i++){
549 print "<a href=\"'${BASE_URL}'&contexts="$i"&projects='${PROJECTS}'\" class=\"context\">"$i"</a>&nbsp;&nbsp;&nbsp;"
551 }' | CGI2STR
553 cat << __EOF__
554 </td>
555 <td align="right">
556 <a href="${BASE_URL}&contexts=&projects=${PROJECTS}" class="context">All</a>&nbsp;
557 </td>
558 </tr>
559 </table>
560 </td>
561 <td style="border-bottom:1px solid; border-left:1px solid">
562 <a href="${BASE_URL}&projects=&contexts=" class="context project">All</a>&nbsp;&nbsp;
563 <a href="#">Today</a>&nbsp;&nbsp;
564 <a href="#">Statistics</a>&nbsp;&nbsp;
565 </td>
566 </tr>
567 <tr>
568 <td valign=top>
569 <table>
570 <form name="gtd" ACTION="${FULL_URL}" method=get>
571 __EOF__
574 function SHOW_PROJECTS {
575 cat << __EOF__
576 </table>
577 </td>
578 <td valign=top style="border-left:1px solid; line-height: 2;">
579 <a href="${BASE_URL}&projects=&contexts=${CONTEXTS}" class="project">All</a><br class="project"><br class="project">
580 __EOF__
582 LIST_PROJ | awk '
584 for (i=1;i<=NF;i++){
585 print "<a href=\"'${BASE_URL}'&projects="$i"&contexts='${CONTEXTS}'\" class=\"project\">"$i"</a><br class=\"project\">"
587 }' | CGI2STR
589 cat << __EOF__
590 </td>
591 </tr>
592 </table>
593 __EOF__
596 function SHOW_ACTIONS {
597 SHOW | awk -v timestamp_ref=`date +%Y%m%d` '
599 print "<tr>"
600 for (i=1;i<=NF;i++) {
601 if ($i ~ /I\:/) {
602 gsub("I:","",$i);
603 ind="<td><input onclick=\"fkt_chk("$i")\" type=\"checkbox\" name=\"INDEX\" value=\""$i"\"></td>";
604 } else if ($i ~ /status/) {
605 gsub("status=","",$i);
606 if ($i ~ /a/) { status="<td><span class=active>></span></td>"; }
607 else if ($i == "w") { status="<td><span class=waiting><</span></td>"; }
608 else { status="<td></td>"; }
609 } else if ($i ~ /importance/) {
610 gsub("importance=","",$i);
611 } else if ($i ~ /timestamp/) {
612 gsub("timestamp=","",$i);
613 if ($i == $TIMESTAMP_DEFAULT) { timestamp="<td></td>"; class="grey"; }
614 else if ($i-timestamp_ref < 0) { timestamp="<td><span class=red>"$i"</span></td>"; class="red"; }
615 else if ($i-timestamp_ref < 1) { timestamp="<td><span class=yellow>"$i"</span></td>"; class="yellow"; }
616 else if ($i-timestamp_ref < 3) { timestamp="<td><span class=green>"$i"</span></td>"; class="green"; }
617 else if ($i-timestamp_ref >= 3) { timestamp="<td><span class=gray>"$i"</span></td>"; class="grey"; }
618 } else if ($i ~ /label/) {
619 gsub("label=","",$i);
620 label="<td><span class=\""class"\">"$i"</span></td>";
623 print ind"\n"status"\n"timestamp"\n"label"\n</tr>"
625 ' | CGI2STR
628 function SHOW_INPUT {
629 cat << __EOF__
630 <hr>
631 <table style="border:2px solid">
632 <tr>
633 <td align="center" class="inputfield">
634 <a href="javascript:checkAll(document.gtd.INDEX)" class=button>Check All</a>&nbsp;&nbsp;&nbsp;
635 <a href="javascript:uncheckAll(document.gtd.INDEX)" class=button>Uncheck All</a>
636 </td>
637 <td>Selection</td>
638 </tr>
639 <tr>
640 <td class="inputfield"><input type="text" size="50" name="LABEL" value="`echo ${LABEL} | CGI2STR | sed 's/^ //'`"></td>
641 <td>Label</td>
642 </tr>
643 <tr>
644 <td class="inputfield">
645 <input type="text" size="20" name="projects" value="`echo ${PROJECTS} | CGI2STR | sed 's/^ //'`">
646 <select name="projects">
647 <option selected></option>
648 __EOF__
650 LIST_PROJ | awk '
652 for (i=1;i<=NF;i++){
653 # if ($i ~ /'${PROJECTS}'/) { printf "<option selected>"; }
654 printf "<option>";
655 print $i"</option>"}
656 }' | CGI2STR
658 cat << __EOF__
659 </select>
660 </td>
661 <td>Project</td>
662 </tr>
663 <tr>
664 <td class="inputfield">
665 <input type="text" size="20" name="contexts" value="`echo ${CONTEXTS} | CGI2STR | sed 's/^ //'`">
666 <select name="contexts">
667 <option></option>
668 __EOF__
670 LIST_CONT | awk '
672 for (i=1;i<=NF;i++){
673 printf "<option>";
674 print $i"</option>"}
675 }' | CGI2STR
677 cat << __EOF__
678 </select>
679 </td>
680 <td>Context</td>
681 </tr>
682 <tr>
683 <td class="inputfield">
684 <table width="100%">
685 <tr>
686 <td>
687 __EOF__
689 NICE_DATE CURRENT
690 echo "</td><td>"
691 NICE_DATE NEXT
693 cat << __EOF__
694 </td>
695 </tr>
696 <tr>
697 <td colspan="2" align="center">
698 <input type="text" size="20" name="timestamp" value="">
699 </td>
700 </tr>
701 </table>
702 </td>
703 <td>Date</td>
704 </tr>
705 <tr>
706 <td>
707 <table width="100%">
708 <tr>
709 <td class="inputfield">
710 <select name="importance">
711 <option selected></option>
712 <option>0</option>
713 <option>1</option>
714 <option>3</option>
715 </select>
716 </td>
717 <td>Importance</td>
718 <td class="inputfield">
719 <select name="status">
720 <option selected></option>
721 <option>a</option>
722 <option>w</option>
723 <option>d</option>
724 </select>
725 </td>
726 <td>Status</td>
727 </tr>
728 </table>
729 </td>
730 </tr>
731 <tr>
732 <td align="center" class="inputfield">
733 <input type="hidden" name="ACTION" />
734 <a href="javascript:document.gtd.ACTION.value='ADD';document.gtd.submit();" class=button>Add</a>&nbsp;&nbsp;&nbsp;
735 <a href="javascript:document.gtd.ACTION.value='DONE';document.gtd.submit();" class=button>Done</a>&nbsp;&nbsp;&nbsp;
736 <a href="javascript:document.gtd.ACTION.value='EDIT';document.gtd.submit();" class=button>Edit</a>&nbsp;&nbsp;&nbsp;
737 <a href="javascript:document.gtd.ACTION.value='REMOVE';document.gtd.submit();" class=button>Remove</a>&nbsp;&nbsp;&nbsp;
738 <a href="javascript:document.gtd.reset();" class=button>Reset</a>
739 </td>
740 <td>Action</td>
741 </tr>
742 </table>
743 </form>
744 <script language="JavaScript">document.gtd.LABEL.focus();</script>
745 __EOF__
748 function HTML_TRAILER {
749 cat << __EOF__
750 </body>
752 </html>
753 __EOF__
757 HTML_HEADER
758 HTML_PARSE
760 BASE_URL="`basename $0`?"
761 FULL_URL="`basename $0`?contexts=`echo $CONTEXTS | STR2CGI`&projects=`echo $PROJECTS | STR2CGI`"
763 SHOW_CONTEXTS
764 SHOW_ACTIONS
765 SHOW_PROJECTS
766 SHOW_INPUT
768 HTML_TRAILER
773 [[ $SHELL_DEBUG == 1 ]] && TS eof