comparison doc/customizing.txt @ 3904:91008ec8f9a0

retire "topic" usage "Topic" still appears in the locale files. I'm sure we need to support that for existing trackers. I *think* they don't care about any of the other changes that have been made. I also left Ka-Ping Yee's original design document unchanged. This takes care of sf feature request [SF#953161]
author Justus Pendleton <jpend@users.sourceforge.net>
date Sun, 16 Sep 2007 02:45:11 +0000
parents e7050411a774
children 586679a314f7
comparison
equal deleted inserted replaced
3903:a90fa2e08a0a 3904:91008ec8f9a0
1 =================== 1 ===================
2 Customising Roundup 2 Customising Roundup
3 =================== 3 ===================
4 4
5 :Version: $Revision: 1.220 $ 5 :Version: $Revision: 1.221 $
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::
443 date=Date(), recipients=Multilink("user"), 443 date=Date(), recipients=Multilink("user"),
444 files=Multilink("file"), messageid=String(), inreplyto=String()) 444 files=Multilink("file"), messageid=String(), inreplyto=String())
445 445
446 file = FileClass(db, "file", name=String()) 446 file = FileClass(db, "file", name=String())
447 447
448 issue = IssueClass(db, "issue", topic=Multilink("keyword"), 448 issue = IssueClass(db, "issue", keyword=Multilink("keyword"),
449 status=Link("status"), assignedto=Link("user"), 449 status=Link("status"), assignedto=Link("user"),
450 priority=Link("priority")) 450 priority=Link("priority"))
451 issue.setkey('title') 451 issue.setkey('title')
452 452
453 453
2479 2479
2480 An index view specifier (URL fragment) looks like this (whitespace has 2480 An index view specifier (URL fragment) looks like this (whitespace has
2481 been added for clarity):: 2481 been added for clarity)::
2482 2482
2483 /issue?status=unread,in-progress,resolved& 2483 /issue?status=unread,in-progress,resolved&
2484 topic=security,ui& 2484 keyword=security,ui&
2485 @group=priority,-status& 2485 @group=priority,-status&
2486 @sort=-activity& 2486 @sort=-activity&
2487 @filters=status,topic& 2487 @filters=status,keyword&
2488 @columns=title,status,fixer 2488 @columns=title,status,fixer
2489 2489
2490 The index view is determined by two parts of the specifier: the layout 2490 The index view is determined by two parts of the specifier: the layout
2491 part and the filter part. The layout part consists of the query 2491 part and the filter part. The layout part consists of the query
2492 parameters that begin with colons, and it determines the way that the 2492 parameters that begin with colons, and it determines the way that the
2501 matching any specified Link properties and the intersection of the sets 2501 matching any specified Link properties and the intersection of the sets
2502 of items with values matching any specified Multilink properties. 2502 of items with values matching any specified Multilink properties.
2503 2503
2504 The example specifies an index of "issue" items. Only items with a 2504 The example specifies an index of "issue" items. Only items with a
2505 "status" of either "unread" or "in-progress" or "resolved" are 2505 "status" of either "unread" or "in-progress" or "resolved" are
2506 displayed, and only items with "topic" values including both "security" 2506 displayed, and only items with "keyword" values including both "security"
2507 and "ui" are displayed. The items are grouped by priority arranged in 2507 and "ui" are displayed. The items are grouped by priority arranged in
2508 ascending order and in descending order by status; and within 2508 ascending order and in descending order by status; and within
2509 groups, sorted by activity, arranged in descending order. The filter 2509 groups, sorted by activity, arranged in descending order. The filter
2510 section shows filters for the "status" and "topic" properties, and the 2510 section shows filters for the "status" and "keyword" properties, and the
2511 table includes columns for the "title", "status", and "fixer" 2511 table includes columns for the "title", "status", and "fixer"
2512 properties. 2512 properties.
2513 2513
2514 ============ ============================================================= 2514 ============ =============================================================
2515 Argument Description 2515 Argument Description
2902 caches the schema). 2902 caches the schema).
2903 2903
2904 1. Modify the ``schema.py``:: 2904 1. Modify the ``schema.py``::
2905 2905
2906 issue = IssueClass(db, "issue", 2906 issue = IssueClass(db, "issue",
2907 assignedto=Link("user"), topic=Multilink("keyword"), 2907 assignedto=Link("user"), keyword=Multilink("keyword"),
2908 priority=Link("priority"), status=Link("status"), 2908 priority=Link("priority"), status=Link("status"),
2909 due_date=Date()) 2909 due_date=Date())
2910 2910
2911 2. Add an edit field to the ``issue.item.html`` template:: 2911 2. Add an edit field to the ``issue.item.html`` template::
2912 2912
3396 3396
3397 2. Link to the new class from your issue class (again, in 3397 2. Link to the new class from your issue class (again, in
3398 ``schema.py``):: 3398 ``schema.py``)::
3399 3399
3400 issue = IssueClass(db, "issue", 3400 issue = IssueClass(db, "issue",
3401 assignedto=Link("user"), topic=Multilink("keyword"), 3401 assignedto=Link("user"), keyword=Multilink("keyword"),
3402 priority=Link("priority"), status=Link("status"), 3402 priority=Link("priority"), status=Link("status"),
3403 times=Multilink("timelog")) 3403 times=Multilink("timelog"))
3404 3404
3405 the "times" property is the new link to the "timelog" class. 3405 the "times" property is the new link to the "timelog" class.
3406 3406
3569 system = Class(db, "system", name=String(), order=Number()) 3569 system = Class(db, "system", name=String(), order=Number())
3570 system.setkey("name") 3570 system.setkey("name")
3571 3571
3572 # store issues related to those systems 3572 # store issues related to those systems
3573 support = IssueClass(db, "support", 3573 support = IssueClass(db, "support",
3574 assignedto=Link("user"), topic=Multilink("keyword"), 3574 assignedto=Link("user"), keyword=Multilink("keyword"),
3575 status=Link("status"), deadline=Date(), 3575 status=Link("status"), deadline=Date(),
3576 affects=Multilink("system")) 3576 affects=Multilink("system"))
3577 3577
3578 3. Copy the existing ``issue.*`` (item, search and index) templates in the 3578 3. Copy the existing ``issue.*`` (item, search and index) templates in the
3579 tracker's ``html`` to ``support.*``. Edit them so they use the properties 3579 tracker's ``html`` to ``support.*``. Edit them so they use the properties
4053 1. Create a new property on the ``issue`` class: 4053 1. Create a new property on the ``issue`` class:
4054 ``blockers=Multilink("issue")``. To do this, edit the definition of 4054 ``blockers=Multilink("issue")``. To do this, edit the definition of
4055 this class in your tracker's ``schema.py`` file. Change this:: 4055 this class in your tracker's ``schema.py`` file. Change this::
4056 4056
4057 issue = IssueClass(db, "issue", 4057 issue = IssueClass(db, "issue",
4058 assignedto=Link("user"), topic=Multilink("keyword"), 4058 assignedto=Link("user"), keyword=Multilink("keyword"),
4059 priority=Link("priority"), status=Link("status")) 4059 priority=Link("priority"), status=Link("status"))
4060 4060
4061 to this, adding the blockers entry:: 4061 to this, adding the blockers entry::
4062 4062
4063 issue = IssueClass(db, "issue", 4063 issue = IssueClass(db, "issue",
4064 blockers=Multilink("issue"), 4064 blockers=Multilink("issue"),
4065 assignedto=Link("user"), topic=Multilink("keyword"), 4065 assignedto=Link("user"), keyword=Multilink("keyword"),
4066 priority=Link("priority"), status=Link("status")) 4066 priority=Link("priority"), status=Link("status"))
4067 4067
4068 2. Add the new ``blockers`` property to the ``issue.item.html`` edit 4068 2. Add the new ``blockers`` property to the ``issue.item.html`` edit
4069 page, using something like:: 4069 page, using something like::
4070 4070
4202 that if you want to know whether an issue has any other issues dependent 4202 that if you want to know whether an issue has any other issues dependent
4203 on it (i.e. it's in their blockers list) you can look at the journal 4203 on it (i.e. it's in their blockers list) you can look at the journal
4204 history at the bottom of the issue page - look for a "link" event to 4204 history at the bottom of the issue page - look for a "link" event to
4205 another issue's "blockers" property. 4205 another issue's "blockers" property.
4206 4206
4207 Add users to the nosy list based on the topic 4207 Add users to the nosy list based on the keyword
4208 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4208 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4209 4209
4210 Let's say we need the ability to automatically add users to the nosy 4210 Let's say we need the ability to automatically add users to the nosy
4211 list based 4211 list based
4212 on the occurance of a topic. Every user should be allowed to edit their 4212 on the occurance of a keyword. Every user should be allowed to edit their
4213 own list of topics for which they want to be added to the nosy list. 4213 own list of keywords for which they want to be added to the nosy list.
4214 4214
4215 Below, we'll show that this change can be done with minimal 4215 Below, we'll show that this change can be done with minimal
4216 understanding of the Roundup system, using only copy and paste. 4216 understanding of the Roundup system, using only copy and paste.
4217 4217
4218 This requires three changes to the tracker: a change in the database to 4218 This requires three changes to the tracker: a change in the database to
4219 allow per-user recording of the lists of topics for which he wants to 4219 allow per-user recording of the lists of keywords for which he wants to
4220 be put on the nosy list, a change in the user view allowing them to edit 4220 be put on the nosy list, a change in the user view allowing them to edit
4221 this list of topics, and addition of an auditor which updates the nosy 4221 this list of keywords, and addition of an auditor which updates the nosy
4222 list when a topic is set. 4222 list when a keyword is set.
4223 4223
4224 Adding the nosy topic list 4224 Adding the nosy keyword list
4225 :::::::::::::::::::::::::: 4225 ::::::::::::::::::::::::::::
4226 4226
4227 The change to make in the database, is that for any user there should be 4227 The change to make in the database, is that for any user there should be a list
4228 a list of topics for which he wants to be put on the nosy list. Adding 4228 of keywords for which he wants to be put on the nosy list. Adding a
4229 a ``Multilink`` of ``keyword`` seems to fullfill this (note that within 4229 ``Multilink`` of ``keyword`` seems to fullfill this. As such, all that has to
4230 the code, topics are called ``keywords``.) As such, all that has to be 4230 be done is to add a new field to the definition of ``user`` within the file
4231 done is to add a new field to the definition of ``user`` within the 4231 ``schema.py``. We will call this new field ``nosy_keywords``, and the updated
4232 file ``schema.py``. We will call this new field ``nosy_keywords``, and 4232 definition of user will be::
4233 the updated definition of user will be::
4234 4233
4235 user = Class(db, "user", 4234 user = Class(db, "user",
4236 username=String(), password=Password(), 4235 username=String(), password=Password(),
4237 address=String(), realname=String(), 4236 address=String(), realname=String(),
4238 phone=String(), organisation=String(), 4237 phone=String(), organisation=String(),
4239 alternate_addresses=String(), 4238 alternate_addresses=String(),
4240 queries=Multilink('query'), roles=String(), 4239 queries=Multilink('query'), roles=String(),
4241 timezone=String(), 4240 timezone=String(),
4242 nosy_keywords=Multilink('keyword')) 4241 nosy_keywords=Multilink('keyword'))
4243 4242
4244 Changing the user view to allow changing the nosy topic list 4243 Changing the user view to allow changing the nosy keyword list
4245 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 4244 ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
4246 4245
4247 We want any user to be able to change the list of topics for which 4246 We want any user to be able to change the list of keywords for which
4248 he will by default be added to the nosy list. We choose to add this 4247 he will by default be added to the nosy list. We choose to add this
4249 to the user view, as is generated by the file ``html/user.item.html``. 4248 to the user view, as is generated by the file ``html/user.item.html``.
4250 We can easily 4249 We can easily
4251 see that the topic field in the issue view has very similar editing 4250 see that the keyword field in the issue view has very similar editing
4252 requirements as our nosy topics, both being lists of topics. As 4251 requirements as our nosy keywords, both being lists of keywords. As
4253 such, we look for Topics in ``issue.item.html``, and extract the 4252 such, we look for Keywords in ``issue.item.html``, and extract the
4254 associated parts from there. We add this to ``user.item.html`` at the 4253 associated parts from there. We add this to ``user.item.html`` at the
4255 bottom of the list of viewed items (i.e. just below the 'Alternate 4254 bottom of the list of viewed items (i.e. just below the 'Alternate
4256 E-mail addresses' in the classic template):: 4255 E-mail addresses' in the classic template)::
4257 4256
4258 <tr> 4257 <tr>
4259 <th>Nosy Topics</th> 4258 <th>Nosy Keywords</th>
4260 <td> 4259 <td>
4261 <span tal:replace="structure context/nosy_keywords/field" /> 4260 <span tal:replace="structure context/nosy_keywords/field" />
4262 <span tal:replace="structure python:db.keyword.classhelp(property='nosy_keywords')" /> 4261 <span tal:replace="structure python:db.keyword.classhelp(property='nosy_keywords')" />
4263 </td> 4262 </td>
4264 </tr> 4263 </tr>
4267 Addition of an auditor to update the nosy list 4266 Addition of an auditor to update the nosy list
4268 :::::::::::::::::::::::::::::::::::::::::::::: 4267 ::::::::::::::::::::::::::::::::::::::::::::::
4269 4268
4270 The more difficult part is the logic to add 4269 The more difficult part is the logic to add
4271 the users to the nosy list when required. 4270 the users to the nosy list when required.
4272 We choose to perform this action whenever the topics on an 4271 We choose to perform this action whenever the keywords on an
4273 item are set (this includes the creation of items). 4272 item are set (this includes the creation of items).
4274 Here we choose to start out with a copy of the 4273 Here we choose to start out with a copy of the
4275 ``detectors/nosyreaction.py`` detector, which we copy to the file 4274 ``detectors/nosyreaction.py`` detector, which we copy to the file
4276 ``detectors/nosy_keyword_reaction.py``. 4275 ``detectors/nosy_keyword_reaction.py``.
4277 This looks like a good start as it also adds users 4276 This looks like a good start as it also adds users
4288 ``current`` to a combination of the old and new nosy lists. This 4287 ``current`` to a combination of the old and new nosy lists. This
4289 functionality is left in the new auditor. The following block of 4288 functionality is left in the new auditor. The following block of
4290 code, which handled adding the assignedto user(s) to the nosy list in 4289 code, which handled adding the assignedto user(s) to the nosy list in
4291 ``updatenosy``, should be replaced by a block of code to add the 4290 ``updatenosy``, should be replaced by a block of code to add the
4292 interested users to the nosy list. We choose here to loop over all 4291 interested users to the nosy list. We choose here to loop over all
4293 new topics, than looping over all users, 4292 new keywords, than looping over all users,
4294 and assign the user to the nosy list when the topic occurs in the user's 4293 and assign the user to the nosy list when the keyword occurs in the user's
4295 ``nosy_keywords``. The next part in ``updatenosy`` -- adding the author 4294 ``nosy_keywords``. The next part in ``updatenosy`` -- adding the author
4296 and/or recipients of a message to the nosy list -- is obviously not 4295 and/or recipients of a message to the nosy list -- is obviously not
4297 relevant here and is thus deleted from the new auditor. The last 4296 relevant here and is thus deleted from the new auditor. The last
4298 part, copying the new nosy list to ``newvalues``, can stay as is. 4297 part, copying the new nosy list to ``newvalues``, can stay as is.
4299 This results in the following function:: 4298 This results in the following function::
4300 4299
4301 def update_kw_nosy(db, cl, nodeid, newvalues): 4300 def update_kw_nosy(db, cl, nodeid, newvalues):
4302 '''Update the nosy list for changes to the topics 4301 '''Update the nosy list for changes to the keywords
4303 ''' 4302 '''
4304 # nodeid will be None if this is a new node 4303 # nodeid will be None if this is a new node
4305 current = {} 4304 current = {}
4306 if nodeid is None: 4305 if nodeid is None:
4307 ok = ('new', 'yes') 4306 ok = ('new', 'yes')
4322 if not db.hasnode('user', value): 4321 if not db.hasnode('user', value):
4323 continue 4322 continue
4324 if not current.has_key(value): 4323 if not current.has_key(value):
4325 current[value] = 1 4324 current[value] = 1
4326 4325
4327 # add users with topic in nosy_keywords to the nosy list 4326 # add users with keyword in nosy_keywords to the nosy list
4328 if newvalues.has_key('topic') and newvalues['topic'] is not None: 4327 if newvalues.has_key('keyword') and newvalues['keyword'] is not None:
4329 topic_ids = newvalues['topic'] 4328 keyword_ids = newvalues['keyword']
4330 for topic in topic_ids: 4329 for keyword in keyword_ids:
4331 # loop over all users, 4330 # loop over all users,
4332 # and assign user to nosy when topic in nosy_keywords 4331 # and assign user to nosy when keyword in nosy_keywords
4333 for user_id in db.user.list(): 4332 for user_id in db.user.list():
4334 nosy_kw = db.user.get(user_id, "nosy_keywords") 4333 nosy_kw = db.user.get(user_id, "nosy_keywords")
4335 found = 0 4334 found = 0
4336 for kw in nosy_kw: 4335 for kw in nosy_kw:
4337 if kw == topic: 4336 if kw == keyword:
4338 found = 1 4337 found = 1
4339 if found: 4338 if found:
4340 current[user_id] = 1 4339 current[user_id] = 1
4341 4340
4342 # that's it, save off the new nosy list 4341 # that's it, save off the new nosy list
4352 A few problems with the design here can be noted: 4351 A few problems with the design here can be noted:
4353 4352
4354 Multiple additions 4353 Multiple additions
4355 When a user, after automatic selection, is manually removed 4354 When a user, after automatic selection, is manually removed
4356 from the nosy list, he is added to the nosy list again when the 4355 from the nosy list, he is added to the nosy list again when the
4357 topic list of the issue is updated. A better design might be 4356 keyword list of the issue is updated. A better design might be
4358 to only check which topics are new compared to the old list 4357 to only check which keywords are new compared to the old list
4359 of topics, and only add users when they have indicated 4358 of keywords, and only add users when they have indicated
4360 interest on a new topic. 4359 interest on a new keyword.
4361 4360
4362 The code could also be changed to only trigger on the ``create()`` 4361 The code could also be changed to only trigger on the ``create()``
4363 event, rather than also on the ``set()`` event, thus only setting 4362 event, rather than also on the ``set()`` event, thus only setting
4364 the nosy list when the issue is created. 4363 the nosy list when the issue is created.
4365 4364
4366 Scalability 4365 Scalability
4367 In the auditor, there is a loop over all users. For a site with 4366 In the auditor, there is a loop over all users. For a site with
4368 only few users this will pose no serious problem; however, with 4367 only few users this will pose no serious problem; however, with
4369 many users this will be a serious performance bottleneck. 4368 many users this will be a serious performance bottleneck.
4370 A way out would be to link from the topics to the users who 4369 A way out would be to link from the keywords to the users who
4371 selected these topics as nosy topics. This will eliminate the 4370 selected these keywords as nosy keywords. This will eliminate the
4372 loop over all users. 4371 loop over all users.
4373 4372
4374 Changes to Security and Permissions 4373 Changes to Security and Permissions
4375 ----------------------------------- 4374 -----------------------------------
4376 4375

Roundup Issue Tracker: http://roundup-tracker.org/