Mercurial > p > roundup > code
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 |
