Mercurial > p > roundup > code
comparison doc/customizing.txt @ 1559:6bfb9c9de03c
added blockers customisation example to doc
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Wed, 26 Mar 2003 06:03:58 +0000 |
| parents | d20680d611a6 |
| children | 3f2e516b8de3 |
comparison
equal
deleted
inserted
replaced
| 1558:7914c286b68e | 1559:6bfb9c9de03c |
|---|---|
| 1 =================== | 1 =================== |
| 2 Customising Roundup | 2 Customising Roundup |
| 3 =================== | 3 =================== |
| 4 | 4 |
| 5 :Version: $Revision: 1.78 $ | 5 :Version: $Revision: 1.79 $ |
| 6 | 6 |
| 7 .. This document borrows from the ZopeBook section on ZPT. The original is at: | 7 .. This document borrows from the ZopeBook section on ZPT. The original is at: |
| 8 http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx | 8 http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx |
| 9 | 9 |
| 10 .. contents:: | 10 .. contents:: |
| 2893 </tal:block> | 2893 </tal:block> |
| 2894 </tal:block> | 2894 </tal:block> |
| 2895 </table> | 2895 </table> |
| 2896 | 2896 |
| 2897 | 2897 |
| 2898 Blocking issues that depend on other issues | |
| 2899 ------------------------------------------- | |
| 2900 | |
| 2901 We needed the ability to mark certain issues as "blockers" - that is, | |
| 2902 they can't be resolved until another issue (the blocker) they rely on | |
| 2903 is resolved. To achieve this: | |
| 2904 | |
| 2905 1. Create a new property on the issue Class, ``blockers=Multilink("issue")``. | |
| 2906 Edit your tracker's dbinit.py file. Where the "issue" class is defined, | |
| 2907 something like:: | |
| 2908 | |
| 2909 issue = IssueClass(db, "issue", | |
| 2910 assignedto=Link("user"), topic=Multilink("keyword"), | |
| 2911 priority=Link("priority"), status=Link("status")) | |
| 2912 | |
| 2913 add the blockers entry like so:: | |
| 2914 | |
| 2915 issue = IssueClass(db, "issue", | |
| 2916 blockers=Multilink("issue"), | |
| 2917 assignedto=Link("user"), topic=Multilink("keyword"), | |
| 2918 priority=Link("priority"), status=Link("status")) | |
| 2919 | |
| 2920 2. Add the new "blockers" property to the issue.item edit page, using | |
| 2921 something like: | |
| 2922 | |
| 2923 <th nowrap>Waiting On</th> | |
| 2924 <td> | |
| 2925 <span tal:replace="structure python:context.blockers.field(showid=1, | |
| 2926 size=20)" /> | |
| 2927 <span tal:replace="structure python:db.issue.classhelp('id,title')" /> | |
| 2928 <span tal:condition="context/blockers" tal:repeat="blk context/blockers"> | |
| 2929 <br>View: <a tal:attributes="href string:issue${blk/id}" | |
| 2930 tal:content="blk/id"></a> | |
| 2931 </span> | |
| 2932 | |
| 2933 You'll need to fiddle with your item page layout to find an appropriate | |
| 2934 place to put it - I'll leave that fun part up to you. Just make sure it | |
| 2935 appears in the first table, possibly somewhere near the "superseders" | |
| 2936 field. | |
| 2937 | |
| 2938 3. Create a new detector module (attached) which enforces the rules: | |
| 2939 | |
| 2940 - issues may not be resolved if they have blockers | |
| 2941 - when a blocker is resolved, it's removed from issues it blocks | |
| 2942 | |
| 2943 The contents of the detector should be something like this:: | |
| 2944 | |
| 2945 def blockresolution(db, cl, nodeid, newvalues): | |
| 2946 ''' If the issue has blockers, don't allow it to be resolved. | |
| 2947 ''' | |
| 2948 if nodeid is None: | |
| 2949 blockers = [] | |
| 2950 else: | |
| 2951 blockers = cl.get(nodeid, 'blockers') | |
| 2952 blockers = newvalues.get('blockers', blockers) | |
| 2953 | |
| 2954 # don't do anything if there's no blockers or the status hasn't changed | |
| 2955 if not blockers or not newvalues.has_key('status'): | |
| 2956 return | |
| 2957 | |
| 2958 # get the resolved state ID | |
| 2959 resolved_id = db.status.lookup('resolved') | |
| 2960 | |
| 2961 # format the info | |
| 2962 u = db.config.TRACKER_WEB | |
| 2963 s = ', '.join(['<a href="%sissue%s">%s</a>'%(u,id,id) for id in blockers]) | |
| 2964 if len(blockers) == 1: | |
| 2965 s = 'issue %s is'%s | |
| 2966 else: | |
| 2967 s = 'issues %s are'%s | |
| 2968 | |
| 2969 # ok, see if we're trying to resolve | |
| 2970 if newvalues['status'] == resolved_id: | |
| 2971 raise ValueError, "This issue can't be resolved until %s resolved."%s | |
| 2972 | |
| 2973 def resolveblockers(db, cl, nodeid, newvalues): | |
| 2974 ''' When we resolve an issue that's a blocker, remove it from the | |
| 2975 blockers list of the issue(s) it blocks. | |
| 2976 ''' | |
| 2977 if not newvalues.has_key('status'): | |
| 2978 return | |
| 2979 | |
| 2980 # get the resolved state ID | |
| 2981 resolved_id = db.status.lookup('resolved') | |
| 2982 | |
| 2983 # interesting? | |
| 2984 if newvalues['status'] != resolved_id: | |
| 2985 return | |
| 2986 | |
| 2987 # yes - find all the blocked issues, if any, and remove me from their | |
| 2988 # blockers list | |
| 2989 issues = cl.find(blockers=nodeid) | |
| 2990 for issueid in issues: | |
| 2991 blockers = cl.get(issueid, 'blockers') | |
| 2992 if nodeid in blockers: | |
| 2993 blockers.remove(nodeid) | |
| 2994 cl.set(issueid, blockers=blockers) | |
| 2995 | |
| 2996 | |
| 2997 def init(db): | |
| 2998 # might, in an obscure situation, happen in a create | |
| 2999 db.issue.audit('create', blockresolution) | |
| 3000 db.issue.audit('set', blockresolution) | |
| 3001 | |
| 3002 # can only happen on a set | |
| 3003 db.issue.react('set', resolveblockers) | |
| 3004 | |
| 3005 Put the above code in a file called "blockers.py" in your tracker's | |
| 3006 "detectors" directory. | |
| 3007 | |
| 3008 4. Finally, and this is an optional step, modify the tracker web page URLs | |
| 3009 so they filter out issues with any blockers. You do this by adding an | |
| 3010 additional filter on "blockers" for the value "-1". For example, the | |
| 3011 existing "Show All" link in the "page" template (in the tracker's | |
| 3012 "html" directory) looks like this:: | |
| 3013 | |
| 3014 <a href="issue?:sort=-activity&:group=priority&:filter=status&:columns=id,activity,title,creator,assignedto,status&status=-1,1,2,3,4,5,6,7">Show All</a><br> | |
| 3015 | |
| 3016 modify it to add the "blockers" info to the URL (note, both the | |
| 3017 ":filter" *and* "blockers" values must be specified):: | |
| 3018 | |
| 3019 <a href="issue?:sort=-activity&:group=priority&:filter=status,blockers@blockers=-1&:columns=id,activity,title,creator,assignedto,status&status=-1,1,2,3,4,5,6,7">Show All</a><br> | |
| 3020 | |
| 3021 That's it. You should now be able to se blockers on your issues. Note that | |
| 3022 if you want to know whether an issue has any other issues dependent on it | |
| 3023 (ie. it's in their blockers list) you can look at the journal history | |
| 3024 at the bottom of the issue page - look for a "link" event to another | |
| 3025 issue's "blockers" property. | |
| 3026 | |
| 3027 | |
| 2898 ------------------- | 3028 ------------------- |
| 2899 | 3029 |
| 2900 Back to `Table of Contents`_ | 3030 Back to `Table of Contents`_ |
| 2901 | 3031 |
| 2902 .. _`Table of Contents`: index.html | 3032 .. _`Table of Contents`: index.html |
