Mercurial > p > roundup > code
comparison doc/customizing.txt @ 1100:f96deb4fb935
more docco
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Tue, 10 Sep 2002 12:42:46 +0000 |
| parents | c5819344714c |
| children | a95428868bf4 |
comparison
equal
deleted
inserted
replaced
| 1099:7362dc1f0226 | 1100:f96deb4fb935 |
|---|---|
| 1 =================== | 1 =================== |
| 2 Customising Roundup | 2 Customising Roundup |
| 3 =================== | 3 =================== |
| 4 | 4 |
| 5 :Version: $Revision: 1.26 $ | 5 :Version: $Revision: 1.27 $ |
| 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:: |
| 388 **newissuecopy.py** | 388 **newissuecopy.py** |
| 389 This detector sends an email to a team address whenever a new issue is | 389 This detector sends an email to a team address whenever a new issue is |
| 390 created. The address is hard-coded into the detector, so edit it before you | 390 created. The address is hard-coded into the detector, so edit it before you |
| 391 use it (look for the text 'team@team.host') or you'll get email errors! | 391 use it (look for the text 'team@team.host') or you'll get email errors! |
| 392 | 392 |
| 393 XXX give the example here. | 393 The detector code:: |
| 394 | |
| 395 from roundup import roundupdb | |
| 396 | |
| 397 def newissuecopy(db, cl, nodeid, oldvalues): | |
| 398 ''' Copy a message about new issues to a team address. | |
| 399 ''' | |
| 400 # so use all the messages in the create | |
| 401 change_note = cl.generateCreateNote(nodeid) | |
| 402 | |
| 403 # send a copy to the nosy list | |
| 404 for msgid in cl.get(nodeid, 'messages'): | |
| 405 try: | |
| 406 # note: last arg must be a list | |
| 407 cl.send_message(nodeid, msgid, change_note, ['team@team.host']) | |
| 408 except roundupdb.MessageSendError, message: | |
| 409 raise roundupdb.DetectorError, message | |
| 410 | |
| 411 def init(db): | |
| 412 db.issue.react('create', newissuecopy) | |
| 394 | 413 |
| 395 | 414 |
| 396 Database Content | 415 Database Content |
| 397 ================ | 416 ================ |
| 398 | 417 |
| 405 case though, so be careful to use the right one. | 424 case though, so be careful to use the right one. |
| 406 | 425 |
| 407 **Changing content before tracker initialisation** | 426 **Changing content before tracker initialisation** |
| 408 Edit the dbinit module in your tracker to alter the items created in using | 427 Edit the dbinit module in your tracker to alter the items created in using |
| 409 the create() methods. | 428 the create() methods. |
| 410 | |
| 411 | 429 |
| 412 **Changing content after tracker initialisation** | 430 **Changing content after tracker initialisation** |
| 413 Use the roundup-admin interface's create, set and retire methods to add, | 431 Use the roundup-admin interface's create, set and retire methods to add, |
| 414 alter or remove items from the classes in question. | 432 alter or remove items from the classes in question. |
| 415 | 433 |
| 604 | 622 |
| 605 Most customisation of the web view can be done by modifying the templates in | 623 Most customisation of the web view can be done by modifying the templates in |
| 606 the tracker **html** directory. There are several types of files in there: | 624 the tracker **html** directory. There are several types of files in there: |
| 607 | 625 |
| 608 page | 626 page |
| 609 defines the overall look of your tracker. When you | 627 This template defines the overall look of your tracker. When you |
| 610 view an issue, it appears inside this template. When you view an index, it | 628 view an issue, it appears inside this template. When you view an index, it |
| 611 also appears inside this template. | 629 also appears inside this template. It will have a ``tal:content`` or |
| 630 ``tal:replace`` command with the expression ``structure content`` which | |
| 631 will show the issue, list of issues or whatever. | |
| 612 home | 632 home |
| 613 the default page displayed when no other page is indicated by the user | 633 the default page displayed when no other page is indicated by the user |
| 614 home.classlist | 634 home.classlist |
| 615 a special version of the default page that lists the classes in the tracker | 635 a special version of the default page that lists the classes in the tracker |
| 616 *classname*.item | 636 *classname*.item |
| 625 used to display a "class help" page where there is no *classname*.help | 645 used to display a "class help" page where there is no *classname*.help |
| 626 user.register | 646 user.register |
| 627 a special page just for the user class that renders the registration page | 647 a special page just for the user class that renders the registration page |
| 628 style.css | 648 style.css |
| 629 a static file that is served up as-is | 649 a static file that is served up as-is |
| 630 | |
| 631 Overall Look - "page" template | |
| 632 ------------------------------ | |
| 633 | |
| 634 XXX | |
| 635 | 650 |
| 636 How the templates work | 651 How the templates work |
| 637 ---------------------- | 652 ---------------------- |
| 638 | 653 |
| 639 Roundup's templates consist of special attributes on your template tags. These | 654 Roundup's templates consist of special attributes on your template tags. These |
| 779 *tracker* | 794 *tracker* |
| 780 The current tracker | 795 The current tracker |
| 781 *db* | 796 *db* |
| 782 The current database, through which db.config may be reached. | 797 The current database, through which db.config may be reached. |
| 783 *nothing* | 798 *nothing* |
| 784 XXX a special variable | 799 This is a special variable - if an expression evaluates to this, then the |
| 800 tag (in the case of a tal:replace), its contents (in the case of | |
| 801 tal:content) or some attributes (in the case of tal:attributes) will not | |
| 802 appear in the the output. So for example:: | |
| 803 | |
| 804 <span tal:attributes="class nothing">Hello, World!</span> | |
| 805 | |
| 806 would result in:: | |
| 807 | |
| 808 <span>Hello, World!</span> | |
| 809 | |
| 785 *default* | 810 *default* |
| 786 XXX a special variable | 811 Also a special variable - if an expression evaluates to this, then the |
| 812 existing HTML in the template will not be replaced or removed, it will | |
| 813 remain. So:: | |
| 814 | |
| 815 <span tal:replace="default">Hello, World!</span> | |
| 816 | |
| 817 would result in:: | |
| 818 | |
| 819 <span>Hello, World!</span> | |
| 787 | 820 |
| 788 The context variable | 821 The context variable |
| 789 ~~~~~~~~~~~~~~~~~~~~ | 822 ~~~~~~~~~~~~~~~~~~~~ |
| 790 | 823 |
| 791 The *context* variable is one of three things based on the current context | 824 The *context* variable is one of three things based on the current context |
| 1078 4. add it to the appropriate xxxPermission methods on in your tracker | 1111 4. add it to the appropriate xxxPermission methods on in your tracker |
| 1079 interfaces module | 1112 interfaces module |
| 1080 | 1113 |
| 1081 | 1114 |
| 1082 | 1115 |
| 1083 An example of adding a new field to a roundup schema | 1116 Examples |
| 1084 ==================================================== | 1117 ======== |
| 1118 | |
| 1119 Adding a new field to a roundup schema | |
| 1120 -------------------------------------- | |
| 1121 | |
| 1122 This example shows how to add a new constrained property (ie. a selection of | |
| 1123 distinct values) to your tracker. | |
| 1085 | 1124 |
| 1086 Introduction | 1125 Introduction |
| 1087 ------------ | 1126 ~~~~~~~~~~~~ |
| 1088 | 1127 |
| 1089 To make the classic schema of roundup useful as a todo tracking system | 1128 To make the classic schema of roundup useful as a todo tracking system |
| 1090 for a group of systems administrators, it needed an extra data field | 1129 for a group of systems administrators, it needed an extra data field |
| 1091 per issue: a category. | 1130 per issue: a category. |
| 1092 | 1131 |
| 1094 area of interest without having to do complex queries, and without | 1133 area of interest without having to do complex queries, and without |
| 1095 relying on the spelling capabilities of other sysads (a losing | 1134 relying on the spelling capabilities of other sysads (a losing |
| 1096 proposition at best). | 1135 proposition at best). |
| 1097 | 1136 |
| 1098 Adding a field to the database | 1137 Adding a field to the database |
| 1099 ------------------------------ | 1138 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 1100 | 1139 |
| 1101 This is the easiest part of the change. The category would just be a plain | 1140 This is the easiest part of the change. The category would just be a plain |
| 1102 string, nothing fancy. To change what is in the database you need to add | 1141 string, nothing fancy. To change what is in the database you need to add |
| 1103 some lines to the ``open()`` function in ``dbinit.py``:: | 1142 some lines to the ``open()`` function in ``dbinit.py``:: |
| 1104 | 1143 |
| 1125 | 1164 |
| 1126 That is all you need to do to change the schema. The rest of the effort is | 1165 That is all you need to do to change the schema. The rest of the effort is |
| 1127 fiddling around so you can actually use the new category. | 1166 fiddling around so you can actually use the new category. |
| 1128 | 1167 |
| 1129 Setting up security on the new objects | 1168 Setting up security on the new objects |
| 1130 -------------------------------------- | 1169 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 1131 | 1170 |
| 1132 By default only the admin user can look at and change objects. This doesn't | 1171 By default only the admin user can look at and change objects. This doesn't |
| 1133 suit us, as we want any user to be able to create new categories as | 1172 suit us, as we want any user to be able to create new categories as |
| 1134 required, and obviously everyone needs to be able to view the categories of | 1173 required, and obviously everyone needs to be able to view the categories of |
| 1135 issues for it to be useful. | 1174 issues for it to be useful. |
| 1176 This is all the work that needs to be done for the database. It will store | 1215 This is all the work that needs to be done for the database. It will store |
| 1177 categories, and let users view and edit them. Now on to the interface | 1216 categories, and let users view and edit them. Now on to the interface |
| 1178 stuff. | 1217 stuff. |
| 1179 | 1218 |
| 1180 Changing the web left hand frame | 1219 Changing the web left hand frame |
| 1181 -------------------------------- | 1220 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 1182 | 1221 |
| 1183 We need to give the users the ability to create new categories, and the | 1222 We need to give the users the ability to create new categories, and the |
| 1184 place to put the link to this functionality is in the left hand function | 1223 place to put the link to this functionality is in the left hand function |
| 1185 bar, under the "Issues" area. The file that defines how this area looks is | 1224 bar, under the "Issues" area. The file that defines how this area looks is |
| 1186 ``html/page``, which is what we are going to be editing next. | 1225 ``html/page``, which is what we are going to be editing next. |
| 1215 that it is so I can add more links in this section later on. However to fix | 1254 that it is so I can add more links in this section later on. However to fix |
| 1216 the problem you could change the condition in the classblock statement, so | 1255 the problem you could change the condition in the classblock statement, so |
| 1217 that only users with "Edit" permission would see the "Categories" stuff. | 1256 that only users with "Edit" permission would see the "Categories" stuff. |
| 1218 | 1257 |
| 1219 Setting up a page to edit categories | 1258 Setting up a page to edit categories |
| 1220 ------------------------------------ | 1259 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 1221 | 1260 |
| 1222 We defined code in the previous section which let users with the | 1261 We defined code in the previous section which let users with the |
| 1223 appropriate permissions see a link to a page which would let them edit | 1262 appropriate permissions see a link to a page which would let them edit |
| 1224 conditions. Now we have to write that page. | 1263 conditions. Now we have to write that page. |
| 1225 | 1264 |
| 1307 there is a lot of setup for basically one line (the form line) to do | 1346 there is a lot of setup for basically one line (the form line) to do |
| 1308 its work. To add another field to "category" would involve one more line | 1347 its work. To add another field to "category" would involve one more line |
| 1309 (well maybe a few extra to get the formatting correct). | 1348 (well maybe a few extra to get the formatting correct). |
| 1310 | 1349 |
| 1311 Adding the category to the issue | 1350 Adding the category to the issue |
| 1312 -------------------------------- | 1351 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 1313 | 1352 |
| 1314 We now have the ability to create issues to our hearts content, but | 1353 We now have the ability to create issues to our hearts content, but |
| 1315 that is pointless unless we can assign categories to issues. Just like | 1354 that is pointless unless we can assign categories to issues. Just like |
| 1316 the ``html/category.item`` file was used to define how to add a new | 1355 the ``html/category.item`` file was used to define how to add a new |
| 1317 category, the ``html/issue.item`` is used to define how a new issue is | 1356 category, the ``html/issue.item`` is used to define how a new issue is |
| 1334 | 1373 |
| 1335 The classhelp lines generate a link (labelled "list") to a popup window | 1374 The classhelp lines generate a link (labelled "list") to a popup window |
| 1336 which contains the list of currently known categories. | 1375 which contains the list of currently known categories. |
| 1337 | 1376 |
| 1338 Searching on categories | 1377 Searching on categories |
| 1339 ----------------------- | 1378 ~~~~~~~~~~~~~~~~~~~~~~~ |
| 1340 | 1379 |
| 1341 We can add categories, and create issues with categories. The next obvious | 1380 We can add categories, and create issues with categories. The next obvious |
| 1342 thing that we would like to be would be to search issues based on their | 1381 thing that we would like to be would be to search issues based on their |
| 1343 category, so that any one working on the web server could look at all | 1382 category, so that any one working on the web server could look at all |
| 1344 issues in the category "Web" for example. | 1383 issues in the category "Web" for example. |
| 1382 name part of "s" again. For objects more complex than category, obviously | 1421 name part of "s" again. For objects more complex than category, obviously |
| 1383 you would put an id in the value, and the descriptive part in the content; | 1422 you would put an id in the value, and the descriptive part in the content; |
| 1384 but for category they are the same. | 1423 but for category they are the same. |
| 1385 | 1424 |
| 1386 Adding category to the default view | 1425 Adding category to the default view |
| 1387 ----------------------------------- | 1426 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 1388 | 1427 |
| 1389 We can now add categories, add issues with categories, and search issues | 1428 We can now add categories, add issues with categories, and search issues |
| 1390 based on categories. This is everything that we need to do, however there | 1429 based on categories. This is everything that we need to do, however there |
| 1391 is some more icing that we would like. I think the category of an issue is | 1430 is some more icing that we would like. I think the category of an issue is |
| 1392 important enough that it should be displayed by default when listing all | 1431 important enough that it should be displayed by default when listing all |
| 1421 lots of options. The option that we are interested in is the ``:columns=`` one | 1460 lots of options. The option that we are interested in is the ``:columns=`` one |
| 1422 which tells roundup which fields of the issue to display. Simply add | 1461 which tells roundup which fields of the issue to display. Simply add |
| 1423 "category" to that list and it all should work. | 1462 "category" to that list and it all should work. |
| 1424 | 1463 |
| 1425 | 1464 |
| 1465 Adding in state transition control | |
| 1466 ---------------------------------- | |
| 1467 | |
| 1468 Sometimes tracker admins want to control the states that users may move issues | |
| 1469 to. | |
| 1470 | |
| 1471 1. add a Multilink property to the status class:: | |
| 1472 | |
| 1473 stat = Class(db, "status", ... , transitions=Multilink('status'), ...) | |
| 1474 | |
| 1475 and then edit the statuses already created through the web using the | |
| 1476 generic class list / CSV editor. | |
| 1477 | |
| 1478 2. add an auditor module ``checktransition.py`` in your tracker's | |
| 1479 ``detectors`` directory:: | |
| 1480 | |
| 1481 def checktransition(db, cl, nodeid, newvalues): | |
| 1482 ''' Check that the desired transition is valid for the "status" | |
| 1483 property. | |
| 1484 ''' | |
| 1485 if not newvalues.has_key('status'): | |
| 1486 return | |
| 1487 current = cl.get(nodeid, 'status') | |
| 1488 new = newvalues['status'] | |
| 1489 if new == current: | |
| 1490 return | |
| 1491 ok = db.status.get(current, 'transitions') | |
| 1492 if new not in ok: | |
| 1493 raise ValueError, 'Status not allowed to move from "%s" to "%s"'%( | |
| 1494 db.status.get(current, 'name'), db.status.get(new, 'name')) | |
| 1495 | |
| 1496 def init(db): | |
| 1497 db.issue.audit('set', checktransition) | |
| 1498 | |
| 1499 3. in the ``issue.item`` template, change the status editing bit from:: | |
| 1500 | |
| 1501 <th nowrap>Status</th> | |
| 1502 <td tal:content="structure context/status/menu">status</td> | |
| 1503 | |
| 1504 to:: | |
| 1505 | |
| 1506 <th nowrap>Status</th> | |
| 1507 <td> | |
| 1508 <select tal:condition="context/id" name="status"> | |
| 1509 <tal:block tal:define="ok context/status/transitions" | |
| 1510 tal:repeat="state db/status/list"> | |
| 1511 <option tal:condition="python:state.id in ok" | |
| 1512 tal:attributes="value state/id; | |
| 1513 selected python:state.id == context.status.id" | |
| 1514 tal:content="state/name"></option> | |
| 1515 </tal:block> | |
| 1516 </select> | |
| 1517 <tal:block tal:condition="not:context/id" | |
| 1518 tal:replace="structure context/status/menu" /> | |
| 1519 </td> | |
| 1520 | |
| 1521 which displays only the allowed status to transition to. | |
| 1522 | |
| 1523 | |
| 1426 ------------------- | 1524 ------------------- |
| 1427 | 1525 |
| 1428 Back to `Table of Contents`_ | 1526 Back to `Table of Contents`_ |
| 1429 | 1527 |
| 1430 .. _`Table of Contents`: index.html | 1528 .. _`Table of Contents`: index.html |
