Mercurial > p > roundup > code
comparison doc/customizing.txt @ 659:e429649ed124
More documentation cleanups.
- renamed .stx to .txt so they're identifiable as readable files.
- fixed FAQ and announcement formatting
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Wed, 13 Mar 2002 23:00:48 +0000 |
| parents | |
| children | 604c84696461 54333751e98d |
comparison
equal
deleted
inserted
replaced
| 658:1409d4d55f92 | 659:e429649ed124 |
|---|---|
| 1 Customising Roundup | |
| 2 =================== | |
| 3 | |
| 4 Instances have the following structure: | |
| 5 | |
| 6 +-------------------+--------------------------------------------------------+ | |
| 7 |instance_config.py |Holds the basic instance_configuration | | |
| 8 +-------------------+--------------------------------------------------------+ | |
| 9 |dbinit.py |Holds the instance_schema | | |
| 10 +-------------------+--------------------------------------------------------+ | |
| 11 |interfaces.py |Defines the Web and E-Mail interfaces for the instance | | |
| 12 +-------------------+--------------------------------------------------------+ | |
| 13 |select_db.py |Selects the database back-end for the instance | | |
| 14 +-------------------+--------------------------------------------------------+ | |
| 15 |db/ |Holds the instance's database | | |
| 16 +-------------------+--------------------------------------------------------+ | |
| 17 |db/files/ |Holds the instance's upload files and messages | | |
| 18 +-------------------+--------------------------------------------------------+ | |
| 19 |detectors/ |Auditors and reactors for this instance | | |
| 20 +-------------------+--------------------------------------------------------+ | |
| 21 |html/ |Web interface templates, images and style sheets | | |
| 22 +-------------------+--------------------------------------------------------+ | |
| 23 | |
| 24 Instance Configuration | |
| 25 ---------------------- | |
| 26 | |
| 27 The instance_config.py located in your instance home contains the basic | |
| 28 configuration for the web and e-mail components of roundup's interfaces. This | |
| 29 file is a Python module. The default instance_config.py is given below - as you | |
| 30 can see, the MAIL_DOMAIN must be edited before any interaction with the | |
| 31 instance is attempted.:: | |
| 32 | |
| 33 MAIL_DOMAIN=MAILHOST=HTTP_HOST=None | |
| 34 HTTP_PORT=0 | |
| 35 | |
| 36 # roundup home is this package's directory | |
| 37 INSTANCE_HOME=os.path.split(__file__)[0] | |
| 38 | |
| 39 # The SMTP mail host that roundup will use to send mail | |
| 40 if not MAILHOST: | |
| 41 MAILHOST = 'localhost' | |
| 42 | |
| 43 # The domain name used for email addresses. | |
| 44 if not MAIL_DOMAIN: | |
| 45 MAIL_DOMAIN = 'fill.me.in.' | |
| 46 | |
| 47 # the next two are only used for the standalone HTTP server. | |
| 48 if not HTTP_HOST: | |
| 49 HTTP_HOST = '' | |
| 50 if not HTTP_PORT: | |
| 51 HTTP_PORT = 9080 | |
| 52 | |
| 53 # This is the directory that the database is going to be stored in | |
| 54 DATABASE = os.path.join(INSTANCE_HOME, 'db') | |
| 55 | |
| 56 # This is the directory that the HTML templates reside in | |
| 57 TEMPLATES = os.path.join(INSTANCE_HOME, 'html') | |
| 58 | |
| 59 # The email address that mail to roundup should go to | |
| 60 ISSUE_TRACKER_EMAIL = 'issue_tracker@%s'%MAIL_DOMAIN | |
| 61 | |
| 62 # The web address that the instance is viewable at | |
| 63 ISSUE_TRACKER_WEB = 'http://some.useful.url/' | |
| 64 | |
| 65 # The email address that roundup will complain to if it runs into trouble | |
| 66 ADMIN_EMAIL = 'roundup-admin@%s'%MAIL_DOMAIN | |
| 67 | |
| 68 # Somewhere for roundup to log stuff internally sent to stdout or stderr | |
| 69 LOG = os.path.join(INSTANCE_HOME, 'roundup.log') | |
| 70 | |
| 71 # Where to place the web filtering HTML on the index page | |
| 72 FILTER_POSITION = 'bottom' # one of 'top', 'bottom', 'top and bottom' | |
| 73 | |
| 74 # Deny or allow anonymous access to the web interface | |
| 75 ANONYMOUS_ACCESS = 'deny' | |
| 76 | |
| 77 # Deny or allow anonymous users to register through the web interface | |
| 78 ANONYMOUS_REGISTER = 'deny' | |
| 79 | |
| 80 # Send nosy messages to the author of the message | |
| 81 MESSAGES_TO_AUTHOR = 'no' # either 'yes' or 'no' | |
| 82 | |
| 83 | |
| 84 Instance Schema | |
| 85 --------------- | |
| 86 | |
| 87 Note: if you modify the schema, you'll most likely need to edit the | |
| 88 `web interface`_ HTML template files to reflect your changes. | |
| 89 | |
| 90 An instance schema defines what data is stored in the instance's database. The | |
| 91 two schemas shipped with Roundup turn it into a typical software bug tracker | |
| 92 (the extended schema allowing for support issues as well as bugs). Schemas are | |
| 93 defined using Python code. The "classic" schema looks like this:: | |
| 94 | |
| 95 pri = Class(db, "priority", name=String(), order=String()) | |
| 96 pri.setkey("name") | |
| 97 pri.create(name="critical", order="1") | |
| 98 pri.create(name="urgent", order="2") | |
| 99 pri.create(name="bug", order="3") | |
| 100 pri.create(name="feature", order="4") | |
| 101 pri.create(name="wish", order="5") | |
| 102 | |
| 103 stat = Class(db, "status", name=String(), order=String()) | |
| 104 stat.setkey("name") | |
| 105 stat.create(name="unread", order="1") | |
| 106 stat.create(name="deferred", order="2") | |
| 107 stat.create(name="chatting", order="3") | |
| 108 stat.create(name="need-eg", order="4") | |
| 109 stat.create(name="in-progress", order="5") | |
| 110 stat.create(name="testing", order="6") | |
| 111 stat.create(name="done-cbb", order="7") | |
| 112 stat.create(name="resolved", order="8") | |
| 113 | |
| 114 keyword = Class(db, "keyword", name=String()) | |
| 115 keyword.setkey("name") | |
| 116 | |
| 117 user = Class(db, "user", username=String(), password=String(), | |
| 118 address=String(), realname=String(), phone=String(), | |
| 119 organisation=String()) | |
| 120 user.setkey("username") | |
| 121 user.create(username="admin", password=adminpw, | |
| 122 address=instance_config.ADMIN_EMAIL) | |
| 123 | |
| 124 msg = FileClass(db, "msg", author=Link("user"), recipients=Multilink | |
| 125 ("user"), date=Date(), summary=String(), files=Multilink("file")) | |
| 126 | |
| 127 file = FileClass(db, "file", name=String(), type=String()) | |
| 128 | |
| 129 issue = IssueClass(db, "issue", assignedto=Link("user"), | |
| 130 topic=Multilink("keyword"), priority=Link("priority"), status=Link | |
| 131 ("status")) | |
| 132 issue.setkey('title') | |
| 133 | |
| 134 Classes and Properties - creating a new information store | |
| 135 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| 136 | |
| 137 In the instance above, we've defined 7 classes of information: | |
| 138 | |
| 139 priority | |
| 140 Defines the possible levels of urgency for issues. | |
| 141 | |
| 142 status | |
| 143 Defines the possible states of processing the issue may be in. | |
| 144 | |
| 145 keyword | |
| 146 Initially empty, will hold keywords useful for searching issues. | |
| 147 | |
| 148 user | |
| 149 Initially holding the "admin" user, will eventually have an entry for all | |
| 150 users using roundup. | |
| 151 | |
| 152 msg | |
| 153 Initially empty, will all e-mail messages sent to or generated by | |
| 154 roundup. | |
| 155 | |
| 156 file | |
| 157 Initially empty, will all files attached to issues. | |
| 158 | |
| 159 issue | |
| 160 Initially emtyp, this is where the issue information is stored. | |
| 161 | |
| 162 We define the "priority" and "status" classes to allow two things: reduction in | |
| 163 the amount of information stored on the issue and more powerful, accurate | |
| 164 searching of issues by priority and status. By only requiring a link on the | |
| 165 issue (which is stored as a single number) we reduce the chance that someone | |
| 166 mis-types a priority or status - or simply makes a new one up. | |
| 167 | |
| 168 Class and Nodes | |
| 169 ::::::::::::::: | |
| 170 | |
| 171 A Class defines a particular class (or type) of data that will be stored in the | |
| 172 database. A class comprises one or more properties, which given the information | |
| 173 about the class nodes. | |
| 174 The actual data entered into the database, using class.create() are called | |
| 175 nodes. They have a special immutable property called id. We sometimes refer to | |
| 176 this as the nodeid. | |
| 177 | |
| 178 Properties | |
| 179 :::::::::: | |
| 180 | |
| 181 A Class is comprised of one or more properties of the following types: | |
| 182 * String properties are for storing arbitrary-length strings. | |
| 183 * Password properties are for storing encoded arbitrary-length strings. The | |
| 184 default encoding is defined on the roundup.password.Password class. | |
| 185 * Date properties store date-and-time stamps. Their values are Timestamp | |
| 186 objects. | |
| 187 * A Link property refers to a single other node selected from a specified | |
| 188 class. The class is part of the property; the value is an integer, the id | |
| 189 of the chosen node. | |
| 190 * A Multilink property refers to possibly many nodes in a specified class. | |
| 191 The value is a list of integers. | |
| 192 | |
| 193 FileClass | |
| 194 ::::::::: | |
| 195 | |
| 196 FileClasses save their "content" attribute off in a separate file from the rest | |
| 197 of the database. This reduces the number of large entries in the database, | |
| 198 which generally makes databases more efficient, and also allows us to use | |
| 199 command-line tools to operate on the files. They are stored in the files sub- | |
| 200 directory of the db directory in your instance. | |
| 201 | |
| 202 IssueClass | |
| 203 :::::::::: | |
| 204 | |
| 205 IssueClasses automatically include the "messages", "files", "nosy", and | |
| 206 "superseder" properties. | |
| 207 The messages and files properties list the links to the messages and files | |
| 208 related to the issue. The nosy property is a list of links to users who wish to | |
| 209 be informed of changes to the issue - they get "CC'ed" e-mails when messages | |
| 210 are sent to or generated by the issue. The nosy reactor (in the detectors | |
| 211 directory) handles this action. The superceder link indicates an issue which | |
| 212 has superceded this one. | |
| 213 They also have the dynamically generated "creation", "activity" and "creator" | |
| 214 properties. | |
| 215 The value of the "creation" property is the date when a node was created, and | |
| 216 the value of the "activity" property is the date when any property on the node | |
| 217 was last edited (equivalently, these are the dates on the first and last | |
| 218 records in the node's journal). The "creator" property holds a link to the user | |
| 219 that created the issue. | |
| 220 | |
| 221 setkey(property) | |
| 222 :::::::::::::::: | |
| 223 | |
| 224 Select a String property of the class to be the key property. The key property | |
| 225 muse be unique, and allows references to the nodes in the class by the content | |
| 226 of the key property. That is, we can refer to users by their username, e.g. | |
| 227 let's say that there's an issue in roundup, issue 23. There's also a user, | |
| 228 richard who happens to be user 2. To assign an issue to him, we could do either | |
| 229 of:: | |
| 230 | |
| 231 roundup-admin set issue assignedto=2 | |
| 232 | |
| 233 or:: | |
| 234 | |
| 235 roundup-admin set issue assignedto=richard | |
| 236 | |
| 237 Note, the same thing can be done in the web and e-mail interfaces. | |
| 238 | |
| 239 create(information) | |
| 240 ::::::::::::::::::: | |
| 241 | |
| 242 Create a node in the database. This is generally used to create nodes in the | |
| 243 "definitional" classes like "priority" and "status". | |
| 244 | |
| 245 Web Interface | |
| 246 ------------- | |
| 247 | |
| 248 The web interface works behind the cgi-bin/roundup.cgi or roundup-server | |
| 249 scripts. In both cases, the scripts determine which instance is being accessed | |
| 250 (the first part of the URL path inside the scope of the CGI handler) and pass | |
| 251 control on to the instance interfaces.Client class which handles the rest of | |
| 252 the access through its main() method. This means that you can do pretty much | |
| 253 anything you want as a web interface to your instance. | |
| 254 Most customisation of the web view can be done by modifying the templates in | |
| 255 the instance html directory. These are divided into index, item and newitem | |
| 256 views. The newitem view is optional - the item view will be used if the newitem | |
| 257 view doesn't exist. | |
| 258 | |
| 259 Repurcussions of changing the instance schema | |
| 260 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| 261 | |
| 262 If you choose to change_the_instance_schema you will need to ensure the web | |
| 263 interface knows about it: | |
| 264 | |
| 265 1. Index, item and filter pages for the relevant classes may need to have | |
| 266 properties added or removed, | |
| 267 2. The default page header relies on the existence of, and some values of | |
| 268 the priority, status, assignedto and activity classes. If you change any | |
| 269 of these (specifically if you remove any of the classes or their default | |
| 270 values) you will need to implement your own pagehead() method in your | |
| 271 instance's interfaces.py module. | |
| 272 | |
| 273 Displaying Properties | |
| 274 ~~~~~~~~~~~~~~~~~~~~~ | |
| 275 | |
| 276 Properties appear in the user interface in three contexts: in indices, in | |
| 277 editors, and as filters. For each type of property, there are several display | |
| 278 possibilities. For example, in an index view, a string property may just be | |
| 279 printed as a plain string, but in an editor view, that property should be | |
| 280 displayed in an editable field. | |
| 281 | |
| 282 The display of a property is handled by functions in the htmltemplate module. | |
| 283 Displayer functions are triggered by <display> tags in templates. The call | |
| 284 attribute of the tag provides a Python expression for calling the displayer | |
| 285 function. The three standard arguments are inserted in front of the arguments | |
| 286 given. For example, the occurrence of:: | |
| 287 | |
| 288 <display call="plain('status')"> | |
| 289 | |
| 290 in a template triggers a call the "plain" function. The displayer functions can | |
| 291 accept extra arguments to further specify details about the widgets that should | |
| 292 be generated. By defining new displayer functions, the user interface can be | |
| 293 highly customized. | |
| 294 | |
| 295 +-----------------------------------------------------------------------------+ | |
| 296 |The displayer functions are | | |
| 297 +---------+-------------------------------------------------------------------+ | |
| 298 |plain |Display a String property directly. | | |
| 299 | |Display a Date property in a specified time zone with an option to | | |
| 300 | |omit the time from the date stamp. | | |
| 301 | |For a Link or Multilink property, display the key strings of the | | |
| 302 | |linked nodes (or the ids if the linked class has no key property). | | |
| 303 | |Options: | | |
| 304 | |escape (boolean) - HTML-escape the resulting text. | | |
| 305 +---------+-------------------------------------------------------------------+ | |
| 306 |field |Display a property like the plain displayer above, but in a form | | |
| 307 | |field to be edited. Strings, Dates and Intervals use TEXT fields, | | |
| 308 | |Links use SELECT fields and Multilinks use SELECT MULTIPLE fields. | | |
| 309 | |Options: | | |
| 310 | |size (number) - width of TEXT fields. | | |
| 311 | |height (number) - number of nows in SELECT MULTIPLE tags. | | |
| 312 | |showid (boolean) - true includes the id of linked nodes in the | | |
| 313 | |SELECT MULTIPLE fields. | | |
| 314 +---------+-------------------------------------------------------------------+ | |
| 315 |menu |For a Links and Multilinks, display the same field as would be | | |
| 316 | |generated using field. | | |
| 317 +---------+-------------------------------------------------------------------+ | |
| 318 |link |For a Link or Multilink property, display the names of the linked | | |
| 319 | |nodes, hyperlinked to the item views on those nodes. | | |
| 320 | |For other properties, link to this node with the property as the | | |
| 321 | |text. | | |
| 322 | |Options: | | |
| 323 | |property (property name) - the property to use in the second case. | | |
| 324 +---------+-------------------------------------------------------------------+ | |
| 325 |count |For a Multilink property, display a count of the number of links in| | |
| 326 | |the list. | | |
| 327 | |Arguments: | | |
| 328 | |property (property name) - the property to use. | | |
| 329 +---------+-------------------------------------------------------------------+ | |
| 330 |reldate |Display a Date property in terms of an interval relative to the | | |
| 331 | |current date (e.g. "+ 3w", "- 2d"). | | |
| 332 | |Arguments: | | |
| 333 | |property (property name) - the property to use. | | |
| 334 | |Options: | | |
| 335 | |pretty (boolean) - display the relative date in an English form. | | |
| 336 +---------+-------------------------------------------------------------------+ | |
| 337 |download |For a Link or Multilink property, display the names of the linked | | |
| 338 | |nodes, hyperlinked to the item views on those nodes. | | |
| 339 | |For other properties, link to this node with the property as the | | |
| 340 | |text. | | |
| 341 | |In all cases, append the name (key property) of the item to the | | |
| 342 | |path so it is the name of the file being downloaded. | | |
| 343 | |Arguments: | | |
| 344 | |property (property name) - the property to use. | | |
| 345 +---------+-------------------------------------------------------------------+ | |
| 346 |checklist|For a Link or Multilink property, display checkboxes for the | | |
| 347 | |available choices to permit filtering. | | |
| 348 | |Arguments: | | |
| 349 | |property (property name) - the property to use. | | |
| 350 +---------+-------------------------------------------------------------------+ | |
| 351 |note |Display the special notes field, which is a text area for entering | | |
| 352 | |a note to go along with a change. | | |
| 353 +---------+-------------------------------------------------------------------+ | |
| 354 |list |List the nodes specified by property using the standard index for | | |
| 355 | |the class. | | |
| 356 | |Arguments: | | |
| 357 | |property (property name) - the property to use. | | |
| 358 +---------+-------------------------------------------------------------------+ | |
| 359 |history |List the history of the item. | | |
| 360 +---------+-------------------------------------------------------------------+ | |
| 361 |submit |Add a submit button for the item. | | |
| 362 +---------+-------------------------------------------------------------------+ | |
| 363 | |
| 364 | |
| 365 Index Views | |
| 366 ~~~~~~~~~~~ | |
| 367 | |
| 368 An index view contains two sections: a filter section and an index section. The | |
| 369 filter section provides some widgets for selecting which items appear in the | |
| 370 index. The index section is a table of items. | |
| 371 | |
| 372 Index View Specifiers | |
| 373 ::::::::::::::::::::: | |
| 374 | |
| 375 An index view specifier (URL fragment) looks like this (whitespace has been | |
| 376 added for clarity):: | |
| 377 | |
| 378 /issue?status=unread,in-progress,resolved& | |
| 379 topic=security,ui& | |
| 380 :group=+priority& | |
| 381 :sort=-activity& | |
| 382 :filters=status,topic& | |
| 383 :columns=title,status,fixer | |
| 384 | |
| 385 The index view is determined by two parts of the specifier: the layout part and | |
| 386 the filter part. The layout part consists of the query parameters that begin | |
| 387 with colons, and it determines the way that the properties of selected nodes | |
| 388 are displayed. The filter part consists of all the other query parameters, and | |
| 389 it determines the criteria by which nodes are selected for display. | |
| 390 The filter part is interactively manipulated with the form widgets displayed in | |
| 391 the filter section. The layout part is interactively manipulated by clicking on | |
| 392 the column headings in the table. | |
| 393 | |
| 394 The filter part selects the union of the sets of items with values matching any | |
| 395 specified Link properties and the intersection of the sets of items with values | |
| 396 matching any specified Multilink properties. | |
| 397 | |
| 398 The example specifies an index of "issue" nodes. Only items with a "status" of | |
| 399 either "unread" or "in-progres" or "resolved" are displayed, and only items | |
| 400 with "topic" values including both "security" and "ui" are displayed. The items | |
| 401 are grouped by priority, arranged in ascending order; and within groups, sorted | |
| 402 by activity, arranged in descending order. The filter section shows filters for | |
| 403 the "status" and "topic" properties, and the table includes columns for the | |
| 404 "title", "status", and "fixer" properties. | |
| 405 | |
| 406 Associated with each item class is a default layout specifier. The layout | |
| 407 specifier in the above example is the default layout to be provided with the | |
| 408 default bug-tracker schema described above in section 4.4. | |
| 409 | |
| 410 Filter Section | |
| 411 :::::::::::::: | |
| 412 | |
| 413 The template for a filter section provides the filtering widgets at the top of | |
| 414 the index view. Fragments enclosed in <property>...</property> tags are | |
| 415 included or omitted depending on whether the view specifier requests a filter | |
| 416 for a particular property. | |
| 417 | |
| 418 A property must appear in the filter template for it to be available as a | |
| 419 filter. | |
| 420 | |
| 421 Here's a simple example of a filter template.:: | |
| 422 | |
| 423 <property name=status> | |
| 424 <display call="checklist('status')"> | |
| 425 </property> | |
| 426 <br> | |
| 427 <property name=priority> | |
| 428 <display call="checklist('priority')"> | |
| 429 </property> | |
| 430 <br> | |
| 431 <property name=fixer> | |
| 432 <display call="menu('fixer')"> | |
| 433 </property> | |
| 434 | |
| 435 The standard index generation code appends a section to the index pages which | |
| 436 allows selection of the filters - from those which are defined in the filter | |
| 437 template. | |
| 438 | |
| 439 Index Section | |
| 440 ::::::::::::: | |
| 441 | |
| 442 The template for an index section describes one row of the index table. | |
| 443 Fragments enclosed in <property>...</property> tags are included or omitted | |
| 444 depending on whether the view specifier requests a column for a particular | |
| 445 property. The table cells should contain <display> tags to display the values | |
| 446 of the item's properties. | |
| 447 | |
| 448 Here's a simple example of an index template.:: | |
| 449 | |
| 450 <tr> | |
| 451 <property name=title> | |
| 452 <td><display call="plain('title', max=50)"></td> | |
| 453 </property> | |
| 454 <property name=status> | |
| 455 <td><display call="plain('status')"></td> | |
| 456 </property> | |
| 457 <property name=fixer> | |
| 458 <td><display call="plain('fixer')"></td> | |
| 459 </property> | |
| 460 </tr> | |
| 461 | |
| 462 Sorting | |
| 463 ::::::: | |
| 464 | |
| 465 String and Date values are sorted in the natural way. Link properties are | |
| 466 sorted according to the value of the "order" property on the linked nodes if it | |
| 467 is present; or otherwise on the key string of the linked nodes; or finally on | |
| 468 the node ids. Multilink properties are sorted according to how many links are | |
| 469 present. | |
| 470 | |
| 471 Item Views | |
| 472 ~~~~~~~~~~ | |
| 473 | |
| 474 An item view contains an editor section and a spool section. At the top of an | |
| 475 item view, links to superseding and superseded items are always displayed. | |
| 476 | |
| 477 Editor Section | |
| 478 :::::::::::::: | |
| 479 | |
| 480 The editor section is generated from a template containing <display> tags to | |
| 481 insert the appropriate widgets for editing properties. | |
| 482 | |
| 483 Here's an example of a basic editor template.:: | |
| 484 | |
| 485 <table> | |
| 486 <tr> | |
| 487 <td colspan=2> | |
| 488 <display call="field('title', size=60)"> | |
| 489 </td> | |
| 490 </tr> | |
| 491 <tr> | |
| 492 <td> | |
| 493 <display call="field('fixer', size=30)"> | |
| 494 </td> | |
| 495 <td> | |
| 496 <display call="menu('status')> | |
| 497 </td> | |
| 498 </tr> | |
| 499 <tr> | |
| 500 <td> | |
| 501 <display call="field('nosy', size=30)"> | |
| 502 </td> | |
| 503 <td> | |
| 504 <display call="menu('priority')> | |
| 505 </td> | |
| 506 </tr> | |
| 507 <tr> | |
| 508 <td colspan=2> | |
| 509 <display call="note()"> | |
| 510 </td> | |
| 511 </tr> | |
| 512 </table> | |
| 513 | |
| 514 As shown in the example, the editor template can also request the display of a | |
| 515 "note" field, which is a text area for entering a note to go along with a | |
| 516 change. | |
| 517 | |
| 518 When a change is submitted, the system automatically generates a message | |
| 519 describing the changed properties. | |
| 520 | |
| 521 If a note is given in the "note" field, the note is appended to the | |
| 522 description. The message is then added to the item's message spool (thus | |
| 523 triggering the standard detector to react by sending out this message to the | |
| 524 nosy list). | |
| 525 | |
| 526 The message also displays all of the property values on the item and indicates | |
| 527 which ones have changed. An example of such a message might be this:: | |
| 528 | |
| 529 Polly's taken a turn for the worse - this is now really important! | |
| 530 ----- | |
| 531 title: Polly Parrot is dead | |
| 532 priority: critical | |
| 533 status: unread -> in-progress | |
| 534 fixer: terry | |
| 535 keywords: parrot,plumage,perch,nailed,dead | |
| 536 | |
| 537 Spool Section | |
| 538 ::::::::::::: | |
| 539 | |
| 540 The spool section lists messages in the item's "messages" property. The index | |
| 541 of messages displays the "date", "author", and "summary" properties on the | |
| 542 message nodes, and selecting a message takes you to its content. | |
| 543 | |
| 544 The <property> tag used in the index may also be used here - it checks to see | |
| 545 if the nominated Multilink property has any entries. This can be used to | |
| 546 eliminate sections of the spool section if the property has no entries.:: | |
| 547 | |
| 548 <property name="files"> | |
| 549 <tr class="strong-header"> | |
| 550 <td><b>Files</b></td> | |
| 551 </tr> | |
| 552 | |
| 553 <tr> | |
| 554 <td><display call="list('files')"></td> | |
| 555 </tr> | |
| 556 </property> | |
| 557 | |
| 558 |
