Mercurial > p > roundup > code
comparison doc/customizing.txt @ 1808:3ac35c8e1782
new example and some more installation docs
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Fri, 12 Sep 2003 04:29:35 +0000 |
| parents | a3b1b1dcf639 |
| children | 61a23c293147 |
comparison
equal
deleted
inserted
replaced
| 1807:ea43cb3c157f | 1808:3ac35c8e1782 |
|---|---|
| 1 =================== | 1 =================== |
| 2 Customising Roundup | 2 Customising Roundup |
| 3 =================== | 3 =================== |
| 4 | 4 |
| 5 :Version: $Revision: 1.97 $ | 5 :Version: $Revision: 1.98 $ |
| 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:: |
| 3347 that if you want to know whether an issue has any other issues dependent | 3347 that if you want to know whether an issue has any other issues dependent |
| 3348 on it (i.e. it's in their blockers list) you can look at the journal | 3348 on it (i.e. it's in their blockers list) you can look at the journal |
| 3349 history at the bottom of the issue page - look for a "link" event to | 3349 history at the bottom of the issue page - look for a "link" event to |
| 3350 another issue's "blockers" property. | 3350 another issue's "blockers" property. |
| 3351 | 3351 |
| 3352 Add users to the nosy list based on the topic | |
| 3353 --------------------------------------------- | |
| 3354 | |
| 3355 We need the ability to automatically add users to the nosy list based | |
| 3356 on the occurence of a topic. Every user should be allowed to edit his | |
| 3357 own list of topics for which he wants to be added to the nosy list. | |
| 3358 | |
| 3359 Below will be showed that such a change can be performed with only | |
| 3360 minimal understanding of the roundup system, but with clever use | |
| 3361 of Copy and Paste. | |
| 3362 | |
| 3363 This requires three changes to the tracker: a change in the database to | |
| 3364 allow per-user recording of the lists of topics for which he wants to | |
| 3365 be put on the nosy list, a change in the user view allowing to edit | |
| 3366 this list of topics, and addition of an auditor which updates the nosy | |
| 3367 list when a topic is set. | |
| 3368 | |
| 3369 Adding the nosy topic list | |
| 3370 ~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| 3371 | |
| 3372 The change in the database to make is that for any user there should be | |
| 3373 a list of topics for which he wants to be put on the nosy list. Adding | |
| 3374 a ``Multilink`` of ``keyword`` seem to fullfill this (note that within | |
| 3375 the code topics are called ``keywords``.) As such, all what has to be | |
| 3376 done is to add a new field to the definition of ``user`` within the | |
| 3377 file ``dbinit.py``. We will call this new field ``nosy_keywords``, and | |
| 3378 the updated definition of user will be:: | |
| 3379 | |
| 3380 user = Class(db, "user", | |
| 3381 username=String(), password=Password(), | |
| 3382 address=String(), realname=String(), | |
| 3383 phone=String(), organisation=String(), | |
| 3384 alternate_addresses=String(), | |
| 3385 queries=Multilink('query'), roles=String(), | |
| 3386 timezone=String(), | |
| 3387 nosy_keywords=Multilink('keyword')) | |
| 3388 | |
| 3389 Changing the user view to allow changing the nosy topic list | |
| 3390 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| 3391 | |
| 3392 We want any user to be able to change the list of topics for which | |
| 3393 he will by default be added to the nosy list. We choose to add this | |
| 3394 to the user view, as is generated by the file ``html/user.item.html``. | |
| 3395 We easily can | |
| 3396 see that the topic field in the issue view has very similar editting | |
| 3397 requirements as our nosy topics, both being a list of topics. As | |
| 3398 such, we search for Topics in ``issue.item.html``, and extract the | |
| 3399 associated parts from there. We add this to ``user.item.html`` at the | |
| 3400 bottom of the list of viewed items (i.e. just below the 'Alternate | |
| 3401 E-mail addresses' in the classic template):: | |
| 3402 | |
| 3403 <tr> | |
| 3404 <th>Nosy Topics</th> | |
| 3405 <td> | |
| 3406 <span tal:replace="structure context/nosy_keywords/field" /> | |
| 3407 <span tal:replace="structure python:db.keyword.classhelp(property='nosy_keywords')" /> | |
| 3408 </td> | |
| 3409 </tr> | |
| 3410 | |
| 3411 | |
| 3412 Addition of an auditor to update the nosy list | |
| 3413 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| 3414 | |
| 3415 The more difficult part is the addition of the logic to actually | |
| 3416 at the users to the nosy list when it is required. | |
| 3417 The choice is made to perform this action when the topics on an | |
| 3418 item are set, including when an item is created. | |
| 3419 Here we choose to start out with a copy of the | |
| 3420 ``detectors/nosyreaction.py`` detector, which we copy to the file | |
| 3421 ``detectors/nosy_keyword_reaction.py``. | |
| 3422 This looks like a good start as it also adds users | |
| 3423 to the nosy list. A look through the code reveals that the | |
| 3424 ``nosyreaction`` function actually is sending the e-mail, which | |
| 3425 we do not need. As such, we can change the init function to:: | |
| 3426 | |
| 3427 def init(db): | |
| 3428 db.issue.audit('create', update_kw_nosy) | |
| 3429 db.issue.audit('set', update_kw_nosy) | |
| 3430 | |
| 3431 After that we rename the ``updatenosy`` function to ``update_kw_nosy``. | |
| 3432 The first two blocks of code in that function relate to settings | |
| 3433 ``current`` to a combination of the old and new nosy lists. This | |
| 3434 functionality is left in the new auditor. The following block of | |
| 3435 code, which in ``updatenosy`` handled adding the assignedto user(s) | |
| 3436 to the nosy list, should be replaced by a block of code to add the | |
| 3437 interested users to the nosy list. We choose here to loop over all | |
| 3438 new topics, than loop over all users, | |
| 3439 and assign the user to the nosy list when the topic in the user's | |
| 3440 nosy_keywords. The next part in ``updatenosy``, adding the author | |
| 3441 and/or recipients of a message to the nosy list, obviously is not | |
| 3442 relevant here and thus is deleted from the new auditor. The last | |
| 3443 part, copying the new nosy list to newvalues, does not have to be changed. | |
| 3444 This brings the following function:: | |
| 3445 | |
| 3446 def update_kw_nosy(db, cl, nodeid, newvalues): | |
| 3447 '''Update the nosy list for changes to the topics | |
| 3448 ''' | |
| 3449 # nodeid will be None if this is a new node | |
| 3450 current = {} | |
| 3451 if nodeid is None: | |
| 3452 ok = ('new', 'yes') | |
| 3453 else: | |
| 3454 ok = ('yes',) | |
| 3455 # old node, get the current values from the node if they haven't | |
| 3456 # changed | |
| 3457 if not newvalues.has_key('nosy'): | |
| 3458 nosy = cl.get(nodeid, 'nosy') | |
| 3459 for value in nosy: | |
| 3460 if not current.has_key(value): | |
| 3461 current[value] = 1 | |
| 3462 | |
| 3463 # if the nosy list changed in this transaction, init from the new value | |
| 3464 if newvalues.has_key('nosy'): | |
| 3465 nosy = newvalues.get('nosy', []) | |
| 3466 for value in nosy: | |
| 3467 if not db.hasnode('user', value): | |
| 3468 continue | |
| 3469 if not current.has_key(value): | |
| 3470 current[value] = 1 | |
| 3471 | |
| 3472 # add users with topic in nosy_keywords to the nosy list | |
| 3473 if newvalues.has_key('topic') and newvalues['topic'] is not None: | |
| 3474 topic_ids = newvalues['topic'] | |
| 3475 for topic in topic_ids: | |
| 3476 # loop over all users, | |
| 3477 # and assign user to nosy when topic in nosy_keywords | |
| 3478 for user_id in db.user.list(): | |
| 3479 nosy_kw = db.user.get(user_id, "nosy_keywords") | |
| 3480 found = 0 | |
| 3481 for kw in nosy_kw: | |
| 3482 if kw == topic: | |
| 3483 found = 1 | |
| 3484 if found: | |
| 3485 current[user_id] = 1 | |
| 3486 | |
| 3487 # that's it, save off the new nosy list | |
| 3488 newvalues['nosy'] = current.keys() | |
| 3489 | |
| 3490 and these two function are the only ones needed in the file. | |
| 3491 | |
| 3492 TODO: update this example to use the find() Class method. | |
| 3493 | |
| 3494 Caveats | |
| 3495 ~~~~~~~ | |
| 3496 | |
| 3497 A few problems with the design here can be noted: | |
| 3498 | |
| 3499 Multiple additions | |
| 3500 When a user, after automatic selection, is manually removed | |
| 3501 from the nosy list, he again is added to the nosy list when the | |
| 3502 topic list of the issue is updated. A better design might be | |
| 3503 to only check which topics are new compared to the old list | |
| 3504 of topics, and only add users when they have indicated | |
| 3505 interest on a new topic. | |
| 3506 | |
| 3507 The code could also be changed to only trigger on the create() event, | |
| 3508 rather than also on the set() event, thus only setting the nosy list | |
| 3509 when the issue is created. | |
| 3510 | |
| 3511 Scalability | |
| 3512 In the auditor there is a loop over all users. For a site with | |
| 3513 only few users this will pose no serious problem, however, with | |
| 3514 many users this will be a serious performance bottleneck. | |
| 3515 A way out will be to link from the topics to the users which | |
| 3516 selected these topics a nosy topics. This will eliminate the | |
| 3517 loop over all users. | |
| 3352 | 3518 |
| 3353 ------------------- | 3519 ------------------- |
| 3354 | 3520 |
| 3355 Back to `Table of Contents`_ | 3521 Back to `Table of Contents`_ |
| 3356 | 3522 |
