Skip to content

Commit 472670b

Browse files
author
Richard Jones
committed
added blockers customisation example to doc
1 parent d06a287 commit 472670b

File tree

1 file changed

+131
-1
lines changed

1 file changed

+131
-1
lines changed

doc/customizing.txt

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Customising Roundup
33
===================
44

5-
:Version: $Revision: 1.78 $
5+
:Version: $Revision: 1.79 $
66

77
.. This document borrows from the ZopeBook section on ZPT. The original is at:
88
http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx
@@ -2895,6 +2895,136 @@ achieve this::
28952895
</table>
28962896

28972897

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+
28983028
-------------------
28993029

29003030
Back to `Table of Contents`_

0 commit comments

Comments
 (0)