Code

fixes to time tracking customisation
[roundup.git] / doc / customizing.txt
index 068e9076244f7e1096625e299bebd443f584b10c..eb6b8adceeed1c70a49388a0f576c9aea12d2d35 100644 (file)
@@ -2,7 +2,7 @@
 Customising Roundup
 ===================
 
-:Version: $Revision: 1.64 $
+:Version: $Revision: 1.72 $
 
 .. This document borrows from the ZopeBook section on ZPT. The original is at:
    http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx
@@ -107,13 +107,25 @@ The configuration variables available are:
  The email address that e-mail sent to roundup should go to. Think of it as the
  tracker's personal e-mail address.
 
-**TRACKER_WEB** - ``'http://your.tracker.url.example/'``
+**TRACKER_WEB** - ``'http://tracker.example/cgi-bin/roundup.cgi/bugs/'``
  The web address that the tracker is viewable at. This will be included in
- information sent to users of the tracker.
+ information sent to users of the tracker. The URL **must** include the
+ cgi-bin part or anything else that is required to get to the home page of
+ the tracker. You **must** include a trailing '/' in the URL.
 
 **ADMIN_EMAIL** - ``'roundup-admin@%s'%MAIL_DOMAIN``
  The email address that roundup will complain to if it runs into trouble.
 
+**EMAIL_FROM_TAG** - ``''``
+ Additional text to include in the "name" part of the ``From:`` address used
+ in nosy messages. If the sending user is "Foo Bar", the ``From:`` line is
+ usually::
+     "Foo Bar" <issue_tracker@tracker.example>
+
+ the EMAIL_FROM_TAG goes inside the "Foo Bar" quotes like so::
+
+    "Foo Bar EMAIL_FROM_TAG" <issue_tracker@tracker.example>
+
 **MESSAGES_TO_AUTHOR** - ``'yes'`` or``'no'``
  Send nosy messages to the author of the message.
 
@@ -170,12 +182,22 @@ tracker is attempted.::
     # The email address that mail to roundup should go to
     TRACKER_EMAIL = 'issue_tracker@%s'%MAIL_DOMAIN
 
-    # The web address that the tracker is viewable at
-    TRACKER_WEB = 'http://your.tracker.url.example/'
+    # The web address that the tracker is viewable at. This will be included in
+    # information sent to users of the tracker. The URL MUST include the cgi-bin
+    # part or anything else that is required to get to the home page of the
+    # tracker. You MUST include a trailing '/' in the URL.
+    TRACKER_WEB = 'http://tracker.example/cgi-bin/roundup.cgi/bugs/'
 
     # The email address that roundup will complain to if it runs into trouble
     ADMIN_EMAIL = 'roundup-admin@%s'%MAIL_DOMAIN
 
+    # Additional text to include in the "name" part of the From: address used
+    # in nosy messages. If the sending user is "Foo Bar", the From: line is
+    # usually: "Foo Bar" <issue_tracker@tracker.example>
+    # the EMAIL_FROM_TAG goes inside the "Foo Bar" quotes like so:
+    #    "Foo Bar EMAIL_FROM_TAG" <issue_tracker@tracker.example>
+    EMAIL_FROM_TAG = ""
+
     # Send nosy messages to the author of the message
     MESSAGES_TO_AUTHOR = 'no'           # either 'yes' or 'no'
 
@@ -206,6 +228,14 @@ tracker is attempted.::
     MAIL_DEFAULT_CLASS = 'issue'   # use "issue" class by default
     #MAIL_DEFAULT_CLASS = ''        # disable (or just comment the var out)
 
+    # 
+    # SECURITY DEFINITIONS
+    #
+    # define the Roles that a user gets when they register with the tracker
+    # these are a comma-separated string of role names (e.g. 'Admin,User')
+    NEW_WEB_USER_ROLES = 'User'
+    NEW_EMAIL_USER_ROLES = 'User'
+
 Tracker Schema
 ==============
 
@@ -731,6 +761,12 @@ triggered by using a ``:action`` CGI variable, where the value is one of:
   the :note if it's supplied.
  :required=property,property,...
   The named properties are required to be filled in the form.
+ :remove:<propname>=id(s)
+  The ids will be removed from the multilink property. You may have multiple
+  :remove:<propname> form elements for a single <propname>.
+ :add:<propname>=id(s)
+  The ids will be added to the multilink property. You may have multiple
+  :add:<propname> form elements for a single <propname>.
 
 **new**
  Add a new item to the database. You may use the same special form elements
@@ -963,7 +999,7 @@ forms:
    in place if the "foo" form variable doesn't exist.
 
 **String Expressions** - eg. ``string:hello ${user/name}``
-   These expressions are simple string interpolations (though they can be just
+   These expressions are simple string interpolations though they can be just
    plain strings with no interpolation if you want. The expression in the
    ``${ ... }`` is just a path expression as above.
 
@@ -1211,30 +1247,58 @@ _value          the value of the property if any - this is the actual value
 
 There are several methods available on these wrapper objects:
 
-=========== =================================================================
-Method      Description
-=========== =================================================================
-plain       render a "plain" representation of the property
-field       render a form edit field for the property
-stext       only on String properties - render the value of the
-            property as StructuredText (requires the StructureText module
-            to be installed separately)
-multiline   only on String properties - render a multiline form edit
-            field for the property
-email       only on String properties - render the value of the 
-            property as an obscured email address
-confirm     only on Password properties - render a second form edit field for
-            the property, used for confirmation that the user typed the
-            password correctly. Generates a field with name "name:confirm".
-reldate     only on Date properties - render the interval between the
-            date and now
-pretty      only on Interval properties - render the interval in a
-            pretty format (eg. "yesterday")
-menu        only on Link and Multilink properties - render a form select
-            list for this property
-reverse     only on Multilink properties - produce a list of the linked
-            items in reverse order
-=========== =================================================================
+========= =====================================================================
+Method    Description
+========= =====================================================================
+plain     render a "plain" representation of the property. This method may
+          take two arguments:
+
+          escape
+           If true, escape the text so it is HTML safe (default: no). The
+           reason this defaults to off is that text is usually escaped
+           at a later stage by the TAL commands, unless the "structure"
+           option is used in the template. The following are all equivalent::
+
+            <p tal:content="structure python:msg.content.plain(escape=1)" />
+            <p tal:content="python:msg.content.plain()" />
+            <p tal:content="msg/content/plain" />
+            <p tal:content="msg/content" />
+
+           Usually you'll only want to use the escape option in a complex
+           expression.
+
+          hyperlink
+           If true, turn URLs, email addresses and hyperdb item designators
+           in the text into hyperlinks (default: no). Note that you'll need
+           to use the "structure" TAL option if you want to use this::
+
+            <p tal:content="structure python:msg.content.plain(hyperlink=1)" />
+
+           Note also that the text is automatically HTML-escape before the
+           hyperlinking transformation.
+
+field     render an appropriate form edit field for the property - for most
+          types this is a text entry box, but for Booleans it's a tri-state
+          yes/no/neither selection.
+stext     only on String properties - render the value of the
+          property as StructuredText (requires the StructureText module
+          to be installed separately)
+multiline only on String properties - render a multiline form edit
+          field for the property
+email     only on String properties - render the value of the 
+          property as an obscured email address
+confirm   only on Password properties - render a second form edit field for
+          the property, used for confirmation that the user typed the
+          password correctly. Generates a field with name "name:confirm".
+reldate   only on Date properties - render the interval between the
+          date and now
+pretty    only on Interval properties - render the interval in a
+          pretty format (eg. "yesterday")
+menu      only on Link and Multilink properties - render a form select
+          list for this property
+reverse   only on Multilink properties - produce a list of the linked
+          items in reverse order
+========= =====================================================================
 
 The request variable
 ~~~~~~~~~~~~~~~~~~~~
@@ -1487,7 +1551,7 @@ Searching Views
 ---------------
 
 Note: if you add a new column to the ``:columns`` form variable potentials
-      then you will need to add the column to the `index view`_
+      then you will need to add the column to the appropriate `index views`_
       template so it is actually displayed.
 
 This is one of the class context views. The template used is typically
@@ -2488,44 +2552,66 @@ able to give a summary of the total time spent on a particular issue.
 
    The code to do this is::
 
-    actions = client.Client.actions + (
-        ('edit_with_timelog', 'timelogEditAction'),
-    )
+    class Client(client.Client): 
+        ''' derives basic CGI implementation from the standard module, 
+            with any specific extensions 
+        ''' 
+        actions = client.Client.actions + (
+            ('edit_with_timelog', 'timelogEditAction'),
+        )
+
+        def timelogEditAction(self):
+            ''' Handle the creation of a new time log entry if necessary.
+
+                If we create a new entry, fake up a CGI form value for the
+                altered "times" property of the issue being edited.
+   
+                Punt to the regular edit action when we're done.
+            '''
+            # if there's a timelog value specified, create an entry
+            if self.form.has_key(':timelog') and \
+                    self.form[':timelog'].value.strip():
+                period = Interval(self.form[':timelog'].value)
+                # create it
+                newid = self.db.timelog.create(period=period)
+
+                # if we're editing an existing item, get the old timelog value
+                if self.nodeid:
+                    l = self.db.issue.get(self.nodeid, 'times')
+                    l.append(newid)
+                else:
+                    l = [newid]
 
-    def timelogEditAction(self):
-        ''' Handle the creation of a new time log entry if necessary.
+                # now make the fake CGI form values
+                for entry in l:
+                    self.form.list.append(MiniFieldStorage('times', entry))
 
-            If we create a new entry, fake up a CGI form value for the altered
-            "times" property of the issue being edited.
+            # punt to the normal edit action
+            return self.editItemAction()
+   
+   you add this code to your Client class in your tracker's ``interfaces.py``
+   file. Locate the section that looks like::
 
-            Punt to the regular edit action when we're done.
-        '''
-        # if there's a timelog value specified, create an entry
-        if self.form.has_key(':timelog') and \
-                self.form[':timelog'].value.strip():
-            period = Interval(self.form[':timelog'].value)
-            # create it
-            newid = self.db.timelog.create(period=period)
-
-            # if we're editing an existing item, get the old timelog value
-            if self.nodeid:
-                l = self.db.issue.get(self.nodeid, 'times')
-                l.append(newid)
-            else:
-                l = [newid]
-
-            # now make the fake CGI form values
-            for entry in l:
-                self.form.list.append(MiniFieldStorage('times', entry))
-
-        # punt to the normal edit action
-        return self.editItemAction()
+    class Client:
+        ''' derives basic CGI implementation from the standard module, 
+            with any specific extensions 
+        ''' 
+        pass
 
-   you add this code to your Client class in your tracker's ``interfaces.py``
-   file.
+   and insert this code in place of the ``pass`` statement.
 
 5. You'll also need to modify your ``issue.item`` form submit action so it
-   calls the time logging action we just created::
+   calls the time logging action we just created. The current template will
+   look like this::
+
+    <tr>
+     <td>&nbsp;</td>
+     <td colspan=3 tal:content="structure context/submit">
+      submit button will go here
+     </td>
+    </tr>
+
+   replace it with this::
 
     <tr>
      <td>&nbsp;</td>
@@ -2541,9 +2627,8 @@ able to give a summary of the total time spent on a particular issue.
      </td>
     </tr>
 
-   Note that the "context/submit" command usually handles all that for you -
-   isn't it handy? The important change is setting the action to
-   "edit_with_timelog" for edit operations (where the item exists)
+   The important change is setting the action to "edit_with_timelog" for
+   edit operations (where the item exists)
 
 6. We want to display a total of the time log times that have been accumulated
    for an issue. To do this, we'll need to actually write some Python code,
@@ -2551,7 +2636,6 @@ able to give a summary of the total time spent on a particular issue.
    We do this by adding a method to the TemplatingUtils class in our tracker
    ``interfaces.py`` module::
 
-
     class TemplatingUtils:
         ''' Methods implemented on this class will be available to HTML
             templates through the 'utils' variable.
@@ -2565,8 +2649,9 @@ able to give a summary of the total time spent on a particular issue.
                 total += time.period._value
             return total
 
+   Replace the ``pass`` line as we did in step 4 above with the Client class.
    As indicated in the docstrings, we will be able to access the
-   ``totalTimeSpent`` method via the ``utils`` variable in our templates. See
+   ``totalTimeSpent`` method via the ``utils`` variable in our templates.
 
 7. Display the time log for an issue::