A PageTemplate conversion of an older version of the IssueTracker page.

We are not using this at the moment because the DTML version is easier to develop (anyone can tweak the IssueTracker page) and can be installed either in the wiki or in the skin.


This code for a ZPT version of the IssueTracker should be correct now, but of course improvements are possible and appreciated.

Enjoy! :)

Nifty. I've installed here so you can try it with a bunch of issues. I tried making it anonymous editable but I don't think that's going to work. It needs to be called in the context of a zwiki page, so eg IssueTracker/issuetrackerzpt .

 <html>
   <head>
     <title tal:content="template/title">The title</title>
   </head>
   <body>
 <span tal:define="global Catalog python:getattr(here, 'Catalog')"></span>
 <!-- start of tracker search panel -->
 <a name="tracker">
 <span tal:define="
   global open python:len(Catalog(isIssue=1,status='open'));
   global pending python:len(Catalog(isIssue=1,status='pending'));
   global closed python:len(Catalog(isIssue=1,status='closed'));
   global tracked python:open+pending+closed
 ">
 </span>
 <form tal:attributes="action here/page_url" method="GET">
 <table border="0" cellspacing="1" cellpadding="0" width="100%"><tr>
 <td valign="top">
 <b><input type="submit" value="Search the tracker:" style="font-weight:bold"></b>
 <b><input type="text" name="textortitle" tal:attributes="value textortitle|nothing" size="40" maxlength="100" style="font-weight:bold"></b><br>
 <!-- Customize this description and reference link area -->
 This is the issue tracker. The last ten issues modified are shown by default.
 </td>
 <td valign="top">
 <table border="0" cellspacing="2" cellpadding="0">
 <span tal:repeat="status here/issue_statuses">
 <tr>
 <td align="right"><small><a tal:attributes="href python:here.page_url() + '?statuses:list=' + status">
 <span tal:replace="python:len(Catalog(isIssue=1,status=status))"> status number </span>
 </a></small></td>
 <td align="left" nowrap><small> <span tal:replace="status"> status name </span> </small></td>
 </tr>
 </span>
 </table>
 </td>
 <td valign="top">
 <table border="0" cellspacing="2" cellpadding="0">
 <span tal:repeat="category here/issue_categories">
 <tr>
 <td align="right"><small><a tal:attributes="href python:here.page_url()+'?categories:list='+ category"> 
 <span tal:replace="python:len(Catalog(isIssue=1,category=category))"> number </span>
 </a></small></td>
 <td align="left" nowrap><small tal:content="category"> Category name </small></td>
 </tr>
 </span>
 </table>
 </td>
 <td align=right valign="top">
 <big><big><big><big><b tal:content="python:str(open)+'/'+str(tracked)"> numbers of open/tracked issues </b></big></big></big></big><br>
 <small>open/total<br>issues</small>
 </td>
 </tr></table>
 </form>
 <!-- end of tracker search panel -->

 <!-- start of issue list -->
 <a name="issues">
 <span tal:define="
 global querystr request/QUERY_STRING;
 find python:modules['string'].find;
 global sortstart python:find(querystr,'sort_on');
 global sortend python:find(querystr,'&',sortstart);
 global sortend python:(sortend != -1) and (sortend+1) or len(querystr);
 global query python:(sortstart == -1) and querystr or (querystr[:sortstart]+querystr[sortend:]);
 global query  python:query and ('&'+query) or '';
 global order python:getattr(request,'sort_order','') and '&sort_order=' or '&sort_order=reverse'
 ">
 </span>
 <table border=0 width="100%">
 <tr>
 <td align=left valign=top>
 <a tal:attributes="href python:here.page_url()+'?sort_on=id'+query+'#tracker'">description</a>
 </td>
 <td align=left valign=top width="1%">
 <a tal:attributes="href python:here.page_url()+'?sort_on=category_index'+query+'#tracker'">category</a>
 </td>
 <td align=left valign=top width="1%">
 <a tal:attributes="href python:here.page_url()+'?sort_on=severity_index'+query+'#tracker'">severity</a>
 </td>
 <td align=left valign=top width="1%">
 <a tal:attributes="href python:here.page_url()+'?sort_on=status_index'+query+'#tracker'">status</a>
 </td>
 <td align=left valign=top width="1%">
 <a tal:attributes="href python:here.page_url()+'?sort_on=creation_time'+query+'#tracker'">age</a>
 </td>
 <td align=left valign=top width="1%">
 <a tal:attributes="href python:here.page_url()+'?sort_on=lastEditTime'+query+'#tracker'">modified</a>
 </td>
 </tr>

 <span tal:repeat="item python:getattr(request,'textortitle','')
  and
 (
 Catalog(isIssue=1,
         sort_on=getattr(request,'sort_on','id'),
         title=textortitle) +
 Catalog(isIssue=1,
         sort_on=getattr(request,'sort_on','id'),
         category=textortitle) +
 Catalog(isIssue=1,
         sort_on=getattr(request,'sort_on','id'),
         text=textortitle)
 )
 or
 (not getattr(request,'textortitle','') and querystr and
 Catalog(isIssue=1,
         sort_on=getattr(request,'sort_on','id'),
         text=getattr(request,'textsearch',''),
         title=getattr(request,'titlesearch',''),
         category=getattr(request,'categories',''),
         severity=getattr(request,'severities',''),
         status=getattr(request,'statuses',''))
 )
 or
 (not getattr(request,'textortitle','') and not querystr and
 Catalog(isIssue=1,
         sort_on='lastEditTime',
         sort_order='reverse')[:10]
 )
 ">

 <span tal:condition="python: item.id != 'IssuePrototype'">
 <tr tal:attributes="bgcolor python:(item.status=='open' and (
   item.severity=='critical' and '#ff2222' or
   item.severity=='serious' and '#ff6060' or
   item.severity=='normal' and '#ffbbbb' or
   item.severity=='minor' and '#ffdddd' or
   item.severity=='wishlist' and '#ffe0e0'
   ) or (
   item.status == 'pending' and '#ffcc77' or 
   item.status == 'closed' and '#e0f0e0'
 ))">

 <span tal:define="
   statbold_open python:(item.status in ['open','pending'] and '<b>' or '');
   statbold_clos python:(item.status in ['open','pending'] and '</b>' or '')
 ">
 <td align=left valign=top>
   <span tal:replace="structure statbold_open"></span>
   <a tal:attributes="href python: here.wiki_url()+'/'+item.id" tal:content="item/title_or_id"> Title or id goes here </a>
   <span tal:replace="structure statbold_clos"></span>
 </td>
 <td align=left valign=top nowrap tal:content="item/category"></td>
 <td align=left valign=top nowrap tal:content="item/severity"></td>
 <td align=left valign=top nowrap tal:content="structure python:statbold_open+item.status+statbold_clos"></td>
 </span>

 <td align=left valign=top nowrap>
 <span tal:define="
     creation_time python:getattr(item,'creation_time','');
     creation python:DateTime(getattr(item,'creation_time','') or 1007105000);
     current python:DateTime(here.ZopeTime().strftime('%Y/%m/%d %H:%M:%S'));
     elapsed python:current-creation;
     hourfactor python:0.041666666666666664;
     minutefactor python:0.00069444444444444447;
     secondsfactor python:1.1574074074074073e-05;
     days python:int(math.floor(elapsed));
     weeks python:(days / 7);
     months python:(days / 30);
     years python:(days / 365);
     hours python:int(math.floor((elapsed-days)/hourfactor));
     minutes  python:int(math.floor((elapsed-days-hourfactor*hours)/minutefactor));
     seconds python:int(round((elapsed-days-hourfactor*hours-minutefactor*minutes)/secondsfactor))
   ">
   <span tal:content="python:(
     years and str(years)+'year'+ (years>1 and 's' or'') or
     months and str(months)+'month'+ (months>1 and 's' or'') or
     days and str(days)+'day'+ (days>1 and 's' or'') or
     hours and str(hours)+'hour'+ (hours>1 and 's' or'') or
     minutes and str(minutes)+'minute'+ (minutes>1 and 's' or'') or
     seconds and str(seconds)+'second'+ (seconds>1 and 's' or'')
   )"></span>
 </span>
 </td>

 <td align=left valign=top nowrap>
 <!--start of age calculation-->
 <span tal:define="
     elapsed python:here.ZopeTime() - item.lastEditTime;
     hourfactor python:0.041666666666666664;
     minutefactor python:0.00069444444444444447;
     secondsfactor python:1.1574074074074073e-05;
     days python:int(math.floor(elapsed));
     weeks python:days / 7;
     months python:days / 30;
     years python:days / 365;
     hours python:int(math.floor((elapsed-days)/hourfactor));
     minutes python:int(math.floor((elapsed-days-hourfactor*hours)/minutefactor));
     seconds python:int(round((elapsed-days-hourfactor*hours-minutefactor*minutes)/secondsfactor))
   ">
   <span tal:content="python:(
     years and str(years)+'year'+ (years>1 and 's' or'') or
     months and str(months)+'month'+ (months>1 and 's' or'') or
     days and str(days)+'day'+ (days>1 and 's' or'') or
     hours and str(hours)+'hour'+ (hours>1 and 's' or'') or
     minutes and str(minutes)+'minute'+ (minutes>1 and 's' or'') or
     seconds and str(seconds)+'second'+ (seconds>1 and 's' or'')
   )"></span>
 </span>
 <!--end of age calculation-->
 </td>

 </tr>
 <tr><td colspan=6> <b tal:condition="repeat/item/end" tal:content="python:str(repeat['item'].length)+' issue'+(repeat['item'].length != 1 and 's' or '')+' listed'"></b> </td></tr>

 </span>                            <!--  cond. status != IssueProto ?  -->
 </span>
 <!-- end of issue list -->
 <p></p>
 <p></p>

 <!-- start of add issue form -->
 <a name="addissue">
 <b> Add an issue: </b> <br>

 <form tal:attributes="action here/page_url" method="POST">

 </form>
 <table border="0" cellspacing="0" cellpadding="5" width="60%">
 <tr bgcolor="#ffe0e0"><td nowrap>
 Description:
 <b><input type="text" name="newtitle" tal:attributes="value newtitle|nothing" size="60" maxlength="200" style="font-weight:bold"></b>
 <br>
 Category:
 <select name="newcategory">
   <span tal:repeat="category here/issue_categories">
     <option tal:content="category" tal:attributes="selected python:category == 'general' and 'SELECTED' or ''">> </option>
   </span>
 </select>
 <a href="TrackerSearchTips">Severity</a>:
 <select name="newseverity">
   <span tal:repeat="severity here/issue_severities">
     <option tal:content="severity" tal:attributes="selected python:severity == 'normal' and 'SELECTED' or ''">> </option>
   </span>
 </select>
 Status:
 <select name="newstatus">
   <span tal:repeat="status here/issue_statuses">
     <option tal:content="status" tal:attributes="selected python:status == 'open' and 'SELECTED' or ''">> </option>
   </span>
 </select>
 <br>
 Details:
 <br>
 <textarea name="newtext" wrap="virtual" rows=5 cols=60>
 </textarea>
 <input type="hidden" name="submitted" value="1">
 </td></tr>
 <tr>
 <td>
 <b><input name="submit" type="submit" value="Add issue" style="font-weight:bold"></b>
 <!-- Customize this mailto link for your own site, remove if no mail-in -->
 (or, mail your issue to <a href="mailto:tracker@zwiki.org">tracker@zwiki.org</a>)
 </td>
 </tr>
 </table>
 <!-- end of add issue form -->

 <!-- start of add issue form processing -->
 <span tal:condition="python:getattr(request,'submitted','') and getattr(request,'newtitle','')">
 <span tal:define="
     lastid python:Catalog(isIssue=1,sort_on='id')[-1].id;
     lastnumber python:int(lastid[7:11]);
     newnumber python:lastnumber+1;
     newid python:'IssueNo'+string.zfill(newnumber,4)
   ">
   <span tal:replace="python:request.set('newid',newid)" tal:on-error="python:request.set('newid','IssueNo0001')"> </span>
 </span>

 <span tal:define="
   newcategory python:getattr(request,'newcategory','zwiki: general');
   newseverity python:getattr(request,'newseverity','normal');
   newstatus python:getattr(request,'newstatus','open');
   newtext python:getattr(request,'newtext','');
   newtitle python:newid+' '+getattr(request,'newtitle','');
   newid python:canonicalIdFrom(newtitle)
 ">
 <span tal:replace="python:create(newtitle,text=newtext,request=request)"> </span>
 <span tal:replace="python:pageWithName(newtitle).changeProperties(
   REQUEST=None,
   title=newtitle,
   category=newcategory,
   severity=newseverity,
   status=newstatus
 )"> </span>
 <span tal:replace="python:createIssue(newtitle,newtext,newtitle,newcategory,newseverity,newstatus,request=request)"> </span>
 </span>                <!--  def: new...  -->

 <span tal:replace="python:request.RESPONSE.redirect(wiki_url() + '/' + 'IssueTracker')"> </span>
 <!-- end of add issue form processing -->
 </span>                <!--  cond: submitted  -->   


comments:

Close the anchors --Curtis Yanko, Mon, 20 Oct 2003 10:00:16 -0700 reply
In plone, if the three anchor tags aren't closed everything becomes underlined. I also pulled back one big up around the open/total issues display as they get clipped with 4 big tags around it and look good with just three.