Code

moving templates around
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Thu, 17 Apr 2003 03:38:00 +0000 (03:38 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Thu, 17 Apr 2003 03:38:00 +0000 (03:38 +0000)
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1663 57a73879-2fb5-44c3-a270-3262357dd7e2

110 files changed:
CHANGES.txt
MANIFEST.in
roundup/admin.py
roundup/cgi/templating.py
roundup/init.py
roundup/mailgw.py
roundup/templates/.cvsignore [deleted file]
roundup/templates/README.txt [deleted file]
roundup/templates/__init__.py [deleted file]
roundup/templates/builder.py [deleted file]
roundup/templates/classic/.cvsignore [deleted file]
roundup/templates/classic/__init__.py [deleted file]
roundup/templates/classic/config.py [deleted file]
roundup/templates/classic/dbinit.py [deleted file]
roundup/templates/classic/detectors/.cvsignore [deleted file]
roundup/templates/classic/detectors/__init__.py [deleted file]
roundup/templates/classic/detectors/messagesummary.py [deleted file]
roundup/templates/classic/detectors/nosyreaction.py [deleted file]
roundup/templates/classic/detectors/statusauditor.py [deleted file]
roundup/templates/classic/html/_generic.help [deleted file]
roundup/templates/classic/html/_generic.index [deleted file]
roundup/templates/classic/html/_generic.item [deleted file]
roundup/templates/classic/html/file.index [deleted file]
roundup/templates/classic/html/file.item [deleted file]
roundup/templates/classic/html/home [deleted file]
roundup/templates/classic/html/home.classlist [deleted file]
roundup/templates/classic/html/issue.index [deleted file]
roundup/templates/classic/html/issue.item [deleted file]
roundup/templates/classic/html/issue.search [deleted file]
roundup/templates/classic/html/keyword.item [deleted file]
roundup/templates/classic/html/msg.index [deleted file]
roundup/templates/classic/html/msg.item [deleted file]
roundup/templates/classic/html/page [deleted file]
roundup/templates/classic/html/query.item [deleted file]
roundup/templates/classic/html/style.css [deleted file]
roundup/templates/classic/html/user.forgotten [deleted file]
roundup/templates/classic/html/user.index [deleted file]
roundup/templates/classic/html/user.item [deleted file]
roundup/templates/classic/html/user.register [deleted file]
roundup/templates/classic/html/user.rego_progress [deleted file]
roundup/templates/classic/interfaces.py [deleted file]
roundup/templates/minimal/.cvsignore [deleted file]
roundup/templates/minimal/__init__.py [deleted file]
roundup/templates/minimal/config.py [deleted file]
roundup/templates/minimal/dbinit.py [deleted file]
roundup/templates/minimal/detectors/.cvsignore [deleted file]
roundup/templates/minimal/detectors/__init__.py [deleted file]
roundup/templates/minimal/html/_generic.help [deleted file]
roundup/templates/minimal/html/_generic.index [deleted file]
roundup/templates/minimal/html/_generic.item [deleted file]
roundup/templates/minimal/html/home [deleted file]
roundup/templates/minimal/html/home.classlist [deleted file]
roundup/templates/minimal/html/page [deleted file]
roundup/templates/minimal/html/style.css [deleted file]
roundup/templates/minimal/html/user.index [deleted file]
roundup/templates/minimal/html/user.item [deleted file]
roundup/templates/minimal/html/user.register [deleted file]
roundup/templates/minimal/interfaces.py [deleted file]
setup.py
templates/classic/.cvsignore [new file with mode: 0644]
templates/classic/TEMPLATE-INFO.txt [new file with mode: 0644]
templates/classic/__init__.py [new file with mode: 0644]
templates/classic/config.py [new file with mode: 0644]
templates/classic/dbinit.py [new file with mode: 0644]
templates/classic/detectors/.cvsignore [new file with mode: 0644]
templates/classic/detectors/__init__.py [new file with mode: 0644]
templates/classic/detectors/messagesummary.py [new file with mode: 0644]
templates/classic/detectors/nosyreaction.py [new file with mode: 0644]
templates/classic/detectors/statusauditor.py [new file with mode: 0644]
templates/classic/html/_generic.help.html [new file with mode: 0644]
templates/classic/html/_generic.index.html [new file with mode: 0644]
templates/classic/html/_generic.item.html [new file with mode: 0644]
templates/classic/html/file.index.html [new file with mode: 0644]
templates/classic/html/file.item.html [new file with mode: 0644]
templates/classic/html/home.classlist.html [new file with mode: 0644]
templates/classic/html/home.html [new file with mode: 0644]
templates/classic/html/issue.index.html [new file with mode: 0644]
templates/classic/html/issue.item.html [new file with mode: 0644]
templates/classic/html/issue.search.html [new file with mode: 0644]
templates/classic/html/keyword.item.html [new file with mode: 0644]
templates/classic/html/msg.index.html [new file with mode: 0644]
templates/classic/html/msg.item.html [new file with mode: 0644]
templates/classic/html/page.html [new file with mode: 0644]
templates/classic/html/query.item.html [new file with mode: 0644]
templates/classic/html/style.css [new file with mode: 0644]
templates/classic/html/user.forgotten.html [new file with mode: 0644]
templates/classic/html/user.index.html [new file with mode: 0644]
templates/classic/html/user.item.html [new file with mode: 0644]
templates/classic/html/user.register.html [new file with mode: 0644]
templates/classic/html/user.rego_progress.html [new file with mode: 0644]
templates/classic/htmlbase.py [new file with mode: 0644]
templates/classic/interfaces.py [new file with mode: 0644]
templates/minimal/.cvsignore [new file with mode: 0644]
templates/minimal/TEMPLATE-INFO.txt [new file with mode: 0644]
templates/minimal/__init__.py [new file with mode: 0644]
templates/minimal/config.py [new file with mode: 0644]
templates/minimal/dbinit.py [new file with mode: 0644]
templates/minimal/detectors/.cvsignore [new file with mode: 0644]
templates/minimal/detectors/__init__.py [new file with mode: 0644]
templates/minimal/html/_generic.help.html [new file with mode: 0644]
templates/minimal/html/_generic.index.html [new file with mode: 0644]
templates/minimal/html/_generic.item.html [new file with mode: 0644]
templates/minimal/html/home.classlist.html [new file with mode: 0644]
templates/minimal/html/home.html [new file with mode: 0644]
templates/minimal/html/page.html [new file with mode: 0644]
templates/minimal/html/style.css [new file with mode: 0644]
templates/minimal/html/user.index.html [new file with mode: 0644]
templates/minimal/html/user.item.html [new file with mode: 0644]
templates/minimal/html/user.register.html [new file with mode: 0644]
templates/minimal/interfaces.py [new file with mode: 0644]

index fc64ee6f619fbac1776204863a1aaa613bbbf917..900ea99880ef891b7041dd4255dcb9668b4d1dae 100644 (file)
@@ -59,6 +59,9 @@ Feature:
 - added command-line functionality for roundup-adming (sf feature 687664)
 - added nicer popup windows for topic, nosy, etc (has add/remove buttons)
   thanks Gus Gollings
+- HTML templating files now have a .html extension
+- Roundup templates are now distributed much more sanely, allowing for
+  3rd-party templates.
 
 
 Fixed:
index a0cbe8119d8eed5c57c99c1e11644204d610b968..26aa1a6cdf5c21f40b58006d210976ca5ade809b 100644 (file)
@@ -1,4 +1,4 @@
-recursive-include roundup *.* home* page*
+recursive-include roundup *.*
 recursive-include frontends *.*
 recursive-include scripts *.* *-*
 recursive-include tools *.*
@@ -6,8 +6,10 @@ recursive-include cgi-bin *.cgi
 recursive-include test *.py *.txt
 recursive-include doc *.html *.png *.txt *.css *.1
 recursive-include detectors *.py
+recursive-include templates *.* home* page*
 recursive-exclude roundup *.pyc *.pyo .cvsignore
 recursive-exclude frontends *.pyc *.pyo .cvsignore
+recursive-exclude templates *.pyc *.pyo .cvsignore
 include run_tests *.txt
 exclude BUILD.txt I18N_PROGRESS.txt TODO.txt
 exclude doc/security.txt doc/templating.txt
index 65bfa8c213535de51e3e8b39954a9bbb562fe78c..fda6e461e9639348cc729543d8cbace41f4c2be9 100644 (file)
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: admin.py,v 1.50 2003-03-27 05:23:39 richard Exp $
+# $Id: admin.py,v 1.51 2003-04-17 03:37:57 richard Exp $
 
 '''Administration commands for maintaining Roundup trackers.
 '''
 
-import sys, os, getpass, getopt, re, UserDict, shlex, shutil
+import sys, os, getpass, getopt, re, UserDict, shlex, shutil, rfc822
 try:
     import csv
 except ImportError:
@@ -278,10 +278,43 @@ Command help:
                     print line
         return 0
 
+    def listTemplates(self):
+        ''' List all the available templates.
+
+            Look in three places:
+                <prefix>/share/roundup/templates
+                <__file__>/../templates
+                current dir
+        '''
+        # OK, try <prefix>/share/roundup/templates
+        # -- this module (roundup.admin) will be installed in something
+        # _like_ /usr/lib/python2.2/site-packages/roundup/admin.py, and
+        # we're interested in where the "lib" directory is - ie. the /usr/
+        # part
+        path = __file__
+        for i in range(5):
+            path = os.path.dirname(path)
+        tdir = os.path.join(path, 'share', 'roundup', 'templates')
+        if os.path.isdir(tdir):
+            templates = listTemplates(tdir)
+        else:
+            templates = {}
+
+        # OK, now try as if we're in the roundup source distribution
+        # directory, so this module will be in .../roundup-*/roundup/admin.py
+        # and we're interested in the .../roundup-*/ part.
+        path = __file__
+        for i in range(2):
+            path = os.path.dirname(path)
+        tdir = os.path.join(path, 'templates')
+        if os.path.isdir(tdir):
+            templates.update(listTemplates(tdir))
+
+        return templates
+
     def help_initopts(self):
-        import roundup.templates
-        templates = roundup.templates.listTemplates()
-        print _('Templates:'), ', '.join(templates)
+        templates = self.listTemplates()
+        print _('Templates:'), ', '.join(templates.keys())
         import roundup.backends
         backends = roundup.backends.__all__
         print _('Back ends:'), ', '.join(backends)
@@ -312,12 +345,11 @@ Command help:
                 ' does not exist')%locals()
 
         # select template
-        import roundup.templates
-        templates = roundup.templates.listTemplates()
+        templates = self.listTemplates()
         template = len(args) > 1 and args[1] or ''
-        if template not in templates:
-            print _('Templates:'), ', '.join(templates)
-        while template not in templates:
+        if not templates.has_key(template):
+            print _('Templates:'), ', '.join(templates.keys())
+        while not templates.has_key(template):
             template = raw_input(_('Select template [classic]: ')).strip()
             if not template:
                 template = 'classic'
@@ -335,7 +367,7 @@ Command help:
         # XXX perform a unit test based on the user's selections
 
         # install!
-        init.install(tracker_home, template)
+        init.install(tracker_home, templates[template]['path'])
         init.write_select_db(tracker_home, backend)
 
         print _('''
@@ -1377,6 +1409,28 @@ Date format is "YYYY-MM-DD" eg:
             if self.db:
                 self.db.close()
 
+
+def listTemplates(dir):
+    ''' List all the Roundup template directories in a given directory.
+
+        Find all the dirs that contain a TEMPLATE-INFO.txt and parse it.
+
+        Return a list of dicts of info about the templates.
+    '''
+    ret = {}
+    for idir in os.listdir(dir):
+        idir = os.path.join(dir, idir)
+        ti = os.path.join(idir, 'TEMPLATE-INFO.txt')
+        if os.path.isfile(ti):
+            m = rfc822.Message(open(ti))
+            ti = {}
+            ti['name'] = m['name']
+            ti['description'] = m['description']
+            ti['intended-for'] = m['intended-for']
+            ti['path'] = idir
+            ret[m['name']] = ti
+    return ret
+
 if __name__ == '__main__':
     tool = AdminTool()
     sys.exit(tool.main())
index e2d2b6c52c260be8309db61875730f420d6b74ce..4eacc8cc258846563f534b4a455cc4345ff074fe 100644 (file)
@@ -38,9 +38,9 @@ class Templates:
             if os.path.isdir(filename): continue
             if '.' in filename:
                 name, extension = filename.split('.')
-                self.getTemplate(name, extension)
+                self.get(name, extension)
             else:
-                self.getTemplate(filename, None)
+                self.get(filename, None)
 
     def get(self, name, extension=None):
         ''' Interface to get a template, possibly loading a compiled template.
@@ -66,27 +66,31 @@ class Templates:
             filename = name
 
         src = os.path.join(self.dir, filename)
+        if not os.path.exists(src):
+            filename = filename + '.html'
+            src = os.path.join(self.dir, filename)
+            if not os.path.exists(src):
+                if not extension:
+                    raise NoTemplate, 'Template file "%s" doesn\'t exist'%name
+
+                # try for a generic template
+                generic = '_generic.%s'%extension
+                src = os.path.join(self.dir, generic)
+                if not os.path.exists(src):
+                    generic = '_generic.%s.html'%extension
+                    src = os.path.join(self.dir, generic)
+                    if not os.path.exists(src):
+                        raise NoTemplate, 'No template file exists for '\
+                            'templating "%s" with template "%s" (neither '\
+                            '"%s" nor "%s")'%(name, extension, filename,
+                            generic)
+                filename = generic
+
         try:
             stime = os.stat(src)[os.path.stat.ST_MTIME]
         except os.error, error:
             if error.errno != errno.ENOENT:
                 raise
-            if not extension:
-                raise NoTemplate, 'Template file "%s" doesn\'t exist'%name
-
-            # try for a generic template
-            generic = '_generic.%s'%extension
-            src = os.path.join(self.dir, generic)
-            try:
-                stime = os.stat(src)[os.path.stat.ST_MTIME]
-            except os.error, error:
-                if error.errno != errno.ENOENT:
-                    raise
-                # nicer error
-                raise NoTemplate, 'No template file exists for templating '\
-                    '"%s" with template "%s" (neither "%s" nor "%s")'%(name,
-                    extension, filename, generic)
-            filename = generic
 
         if self.templates.has_key(src) and \
                 stime < self.templates[src].mtime:
index 9a7ffc51241d5c8bb94459809671d1963bee99fe..fd7124c79460d28de6509dd723440826a4b8a684 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: init.py,v 1.25 2003-02-25 10:19:31 richard Exp $
+# $Id: init.py,v 1.26 2003-04-17 03:37:58 richard Exp $
 
 __doc__ = """
 Init (create) a roundup instance.
@@ -58,8 +58,8 @@ def install(instance_home, template):
     '''Install an instance using the named template and backend.
 
     instance_home - the directory to place the instance data in
-    template - the template to use in creating the instance data
-    backend - the database to use to store the instance data
+    template      - the directory holding the template to use in creating
+                    the instance data
 
     The instance_home directory will be created using the files found in
     the named template (roundup.templates.<name>). A standard instance_home
@@ -82,20 +82,10 @@ def install(instance_home, template):
         . detectors/
           - the auditor and reactor modules for this instance
 
-    The html directory is typically extracted from the htmlbase module in
-    the template.
     '''
-    # first, copy the template dir over
-    from roundup.templates import builder
-
-    # copy the roundup.templates.<template> package contents to the instance dir
-    template_dir = os.path.split(__file__)[0]
-    template_name = template
-    template = os.path.join(template_dir, 'templates', template)
+    # At the moment, it's just a copy
     copytree(template, instance_home)
 
-    builder.installHtmlBase(template_name, instance_home)
-
 
 def write_select_db(instance_home, backend):
     ''' Write the file that selects the backend for the tracker
index 468a3b7f2f25cfbd2add7fdf6d4325da176da930..1a5332bb99027c4fed6a2378da084d617b205e0e 100644 (file)
@@ -73,7 +73,7 @@ are calling the create() method to create a new node). If an auditor raises
 an exception, the original message is bounced back to the sender with the
 explanatory message given in the exception. 
 
-$Id: mailgw.py,v 1.114 2003-04-10 05:12:41 richard Exp $
+$Id: mailgw.py,v 1.115 2003-04-17 03:37:59 richard Exp $
 '''
 
 import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri
@@ -806,6 +806,7 @@ not find a text/plain part to use.
         # parse the body of the message, stripping out bits as appropriate
         summary, content = parseContent(content, keep_citations, 
             keep_body)
+        content = content.strip()
 
         # 
         # handle the attachments
diff --git a/roundup/templates/.cvsignore b/roundup/templates/.cvsignore
deleted file mode 100644 (file)
index 8d65e41..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-*.pyc
-*.pyo
-*.cover
-*_htmlbase.py
-*_htmlbase.pyc
diff --git a/roundup/templates/README.txt b/roundup/templates/README.txt
deleted file mode 100644 (file)
index 11a9223..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-This directory contains "templates" for installations of roundup. 
-
-Choose a template that matches your needs most closely, then run
-roundup-admin init <templatename>, then customise the new instance's 
-templates.
-
-The currently available templates are:
-
-  classic  -- The schema is as described in the Roundup spec.
-
-  extended -- The classic schema with some extra fields useful for support
-              calls: product identification, customer name, source of call,
-              log of time spent on call.
-
diff --git a/roundup/templates/__init__.py b/roundup/templates/__init__.py
deleted file mode 100644 (file)
index 2abf9ce..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
-# This module is free software, and you may redistribute it and/or modify
-# under the same terms as Python, so long as this copyright message and
-# disclaimer are retained in their original form.
-#
-# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
-# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
-# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-# $Id: __init__.py,v 1.5 2002-09-10 01:07:06 richard Exp $
-
-import os
-
-def listTemplates():
-    t_dir = os.path.split(__file__)[0]
-    l = []
-    for entry in os.listdir(t_dir):
-        # this isn't strictly necessary - the CVS dir won't be distributed
-        if entry == 'CVS': continue
-        if os.path.isdir(os.path.join(t_dir, entry)):
-            l.append(entry)
-    return l
-
-# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/templates/builder.py b/roundup/templates/builder.py
deleted file mode 100644 (file)
index eeb93cf..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-#
-# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
-# This module is free software, and you may redistribute it and/or modify
-# under the same terms as Python, so long as this copyright message and
-# disclaimer are retained in their original form.
-#
-# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
-# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
-# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-# $Id: builder.py,v 1.4 2002-09-13 04:39:12 richard Exp $
-import os, sys, glob, errno, re
-
-__doc__ = """
-Collect template parts and create instance template files.
-"""
-
-preamble = """ 
-# Do Not Edit (Unless You Want To)
-# This file automagically generated by roundup.templatebuilder.makeHtmlBase
-# 
-"""
-
-def makeHtmlBase(templateDir):
-    ''' make a <template>_htmlbase.py file in rondup.tempaltes, from the
-        contents of templateDir/html
-    '''
-    print "packing up templates in", templateDir
-
-    filelist = glob.glob(os.path.join(templateDir, 'html', '*'))
-    filelist = filter(os.path.isfile, filelist) # only want files
-    filelist.sort()
-
-    # ok, figure the template name and templates dir
-    dir, name = os.path.split(templateDir)
-
-    fd = open(os.path.join(dir, '%s_htmlbase.py'%name), 'w')
-    fd.write(preamble)
-    for file in filelist:
-        # skip the backup files created by richard's vim
-        if file[-1] == '~': continue
-        mangled_name = os.path.basename(file).replace('.','DOT')
-        fd.write('%s = """'%mangled_name)
-        fd.write(re.sub(r'\$((Id|File|Log).*?)\$', r'dollar\1dollar',
-            open(file).read(), re.I))
-        fd.write('"""\n\n')
-    fd.close()
-
-def installHtmlBase(template, installDir):
-    ''' passed a template name and an installDir, unpacks the html files into
-        the installdir
-    '''
-    tmod = '%s_htmlbase'%template
-    tdir = __import__('roundup.templates.'+tmod).templates
-    if hasattr(tdir, tmod):
-        htmlbase = getattr(tdir, tmod)
-    else:
-        raise "TemplateError", \
-            "couldn't find roundup.templates.%s_htmlbase"%template
-    installDir = os.path.join(installDir, 'html')
-    try:
-        os.makedirs(installDir)
-    except OSError, error:
-        if error.errno != errno.EEXIST: raise
-
-#    print "installing from", htmlbase.__file__, "into", installDir
-    modulecontents = dir(htmlbase)
-    for mangledfile in modulecontents:
-        if mangledfile.startswith('__') and mangledfile.endswith('__'):
-            continue
-        filename = re.sub('DOT', '.', mangledfile)
-        outfile = os.path.join(installDir, filename)
-        outfd = open(outfile, 'w')
-        data = getattr(htmlbase, mangledfile)
-        outfd.write(data)
-    
-if __name__ == "__main__":
-    if len(sys.argv) == 2:
-        makeHtmlBase(sys.argv[1])
-    elif len(sys.argv) == 3:
-        installHtmlBase(sys.argv[1], sys.argv[2])
-    else:
-        print "Usage: %s <template directory>"%sys.argv[0]
-
-# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/templates/classic/.cvsignore b/roundup/templates/classic/.cvsignore
deleted file mode 100644 (file)
index d90d51d..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-*.pyc
-*.pyo
-htmlbase.py
-*.cover
diff --git a/roundup/templates/classic/__init__.py b/roundup/templates/classic/__init__.py
deleted file mode 100644 (file)
index a64f168..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
-# This module is free software, and you may redistribute it and/or modify
-# under the same terms as Python, so long as this copyright message and
-# disclaimer are retained in their original form.
-#
-# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
-# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
-# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-# $Id: __init__.py,v 1.7 2002-09-09 23:55:19 richard Exp $
-
-import config
-from dbinit import open, init
-from interfaces import Client, MailGW
-
-# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/templates/classic/config.py b/roundup/templates/classic/config.py
deleted file mode 100644 (file)
index ceb6235..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-#
-# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
-# This module is free software, and you may redistribute it and/or modify
-# under the same terms as Python, so long as this copyright message and
-# disclaimer are retained in their original form.
-#
-# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
-# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
-# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-# $Id: config.py,v 1.7 2003-01-12 00:41:27 richard Exp $
-
-import os
-
-# roundup home is this package's directory
-TRACKER_HOME=os.path.split(__file__)[0]
-
-# The SMTP mail host that roundup will use to send mail
-MAILHOST = 'localhost'
-
-# The domain name used for email addresses.
-MAIL_DOMAIN = 'your.tracker.email.domain.example'
-
-# This is the directory that the database is going to be stored in
-DATABASE = os.path.join(TRACKER_HOME, 'db')
-
-# This is the directory that the HTML templates reside in
-TEMPLATES = os.path.join(TRACKER_HOME, 'html')
-
-# A descriptive name for your roundup instance
-TRACKER_NAME = 'Roundup issue tracker'
-
-# 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. 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'
-
-# Does the author of a message get placed on the nosy list automatically?
-# If 'new' is used, then the author will only be added when a message
-# creates a new issue. If 'yes', then the author will be added on followups
-# too. If 'no', they're never added to the nosy.
-ADD_AUTHOR_TO_NOSY = 'new'          # one of 'yes', 'no', 'new'
-
-# Do the recipients (To:, Cc:) of a message get placed on the nosy list?
-# If 'new' is used, then the recipients will only be added when a message
-# creates a new issue. If 'yes', then the recipients will be added on followups
-# too. If 'no', they're never added to the nosy.
-ADD_RECIPIENTS_TO_NOSY = 'new'      # either 'yes', 'no', 'new'
-
-# Where to place the email signature
-EMAIL_SIGNATURE_POSITION = 'bottom' # one of 'top', 'bottom', 'none'
-
-# Keep email citations when accepting messages. Setting this to "no" strips
-# out "quoted" text from the message. Signatures are also stripped.
-EMAIL_KEEP_QUOTED_TEXT = 'yes'      # either 'yes' or 'no'
-
-# Preserve the email body as is - that is, keep the citations _and_
-# signatures.
-EMAIL_LEAVE_BODY_UNCHANGED = 'no'   # either 'yes' or 'no'
-
-# Default class to use in the mailgw if one isn't supplied in email
-# subjects. To disable, comment out the variable below or leave it blank.
-# Examples:
-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'
-
-# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/templates/classic/dbinit.py b/roundup/templates/classic/dbinit.py
deleted file mode 100644 (file)
index 0bd0bf3..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-#
-# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
-# This module is free software, and you may redistribute it and/or modify
-# under the same terms as Python, so long as this copyright message and
-# disclaimer are retained in their original form.
-#
-# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
-# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
-# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-# $Id: dbinit.py,v 1.34 2003-04-10 05:12:42 richard Exp $
-
-import os
-
-import config
-from select_db import Database, Class, FileClass, IssueClass
-
-def open(name=None):
-    ''' as from the roundupdb method openDB 
-    ''' 
-    from roundup.hyperdb import String, Password, Date, Link, Multilink
-    from roundup.hyperdb import Interval, Boolean, Number
-
-    # open the database
-    db = Database(config, name)
-
-    #
-    # Now initialise the schema. Must do this each time the database is
-    # opened.
-    #
-
-    # Class automatically gets these properties:
-    #   creation = Date()
-    #   activity = Date()
-    #   creator = Link('user')
-    pri = Class(db, "priority", 
-                    name=String(), order=String())
-    pri.setkey("name")
-
-    stat = Class(db, "status", 
-                    name=String(), order=String())
-    stat.setkey("name")
-
-    keyword = Class(db, "keyword", 
-                    name=String())
-    keyword.setkey("name")
-    
-    query = Class(db, "query",
-                    klass=String(),     name=String(),
-                    url=String())
-    query.setkey("name")
-
-    # add any additional database schema configuration here
-    
-    # Note: roles is a comma-separated string of Role names
-    user = Class(db, "user", 
-                    username=String(),   password=Password(),
-                    address=String(),    realname=String(), 
-                    phone=String(),      organisation=String(),
-                    alternate_addresses=String(),
-                    queries=Multilink('query'), roles=String(),
-                    timezone=String())
-    user.setkey("username")
-
-    # FileClass automatically gets these properties:
-    #   content = String()    [saved to disk in <tracker home>/db/files/]
-    #   (it also gets the Class properties creation, activity and creator)
-    msg = FileClass(db, "msg", 
-                    author=Link("user", do_journal='no'),
-                    recipients=Multilink("user", do_journal='no'), 
-                    date=Date(),         summary=String(), 
-                    files=Multilink("file"),
-                    messageid=String(),  inreplyto=String())
-
-    file = FileClass(db, "file", 
-                    name=String(),       type=String())
-
-    # IssueClass automatically gets these properties:
-    #   title = String()
-    #   messages = Multilink("msg")
-    #   files = Multilink("file")
-    #   nosy = Multilink("user")
-    #   superseder = Multilink("issue")
-    #   (it also gets the Class properties creation, activity and creator)
-    issue = IssueClass(db, "issue", 
-                    assignedto=Link("user"), topic=Multilink("keyword"),
-                    priority=Link("priority"), status=Link("status"))
-
-    #
-    # SECURITY SETTINGS
-    #
-    # See the configuration and customisation document for information
-    # about security setup.
-    # Add new Permissions for this schema
-    for cl in 'issue', 'file', 'msg', 'user', 'query', 'keyword':
-        db.security.addPermission(name="Edit", klass=cl,
-            description="User is allowed to edit "+cl)
-        db.security.addPermission(name="View", klass=cl,
-            description="User is allowed to access "+cl)
-
-    # Assign the access and edit Permissions for issue, file and message
-    # to regular users now
-    for cl in 'issue', 'file', 'msg', 'query', 'keyword':
-        p = db.security.getPermission('View', cl)
-        db.security.addPermissionToRole('User', p)
-        p = db.security.getPermission('Edit', cl)
-        db.security.addPermissionToRole('User', p)
-
-    # and give the regular users access to the web and email interface
-    p = db.security.getPermission('Web Access')
-    db.security.addPermissionToRole('User', p)
-    p = db.security.getPermission('Email Access')
-    db.security.addPermissionToRole('User', p)
-
-    # May users view other user information? Comment these lines out
-    # if you don't want them to
-    p = db.security.getPermission('View', 'user')
-    db.security.addPermissionToRole('User', p)
-
-    # Assign the appropriate permissions to the anonymous user's Anonymous
-    # Role. Choices here are:
-    # - Allow anonymous users to register through the web
-    p = db.security.getPermission('Web Registration')
-    db.security.addPermissionToRole('Anonymous', p)
-    # - Allow anonymous (new) users to register through the email gateway
-    p = db.security.getPermission('Email Registration')
-    db.security.addPermissionToRole('Anonymous', p)
-    # - Allow anonymous users access to the "issue" class of data
-    #   Note: this also grants access to related information like files,
-    #         messages, statuses etc that are linked to issues
-    p = db.security.getPermission('View', 'issue')
-    db.security.addPermissionToRole('Anonymous', p)
-    # - Allow anonymous users access to edit the "issue" class of data
-    #   Note: this also grants access to create related information like
-    #         files and messages etc that are linked to issues
-    #p = db.security.getPermission('Edit', 'issue')
-    #db.security.addPermissionToRole('Anonymous', p)
-
-    # oh, g'wan, let anonymous access the web interface too
-    p = db.security.getPermission('Web Access')
-    db.security.addPermissionToRole('Anonymous', p)
-
-    import detectors
-    detectors.init(db)
-
-    # schema is set up - run any post-initialisation
-    db.post_init()
-    return db
-def init(adminpw): 
-    ''' as from the roundupdb method initDB 
-    Open the new database, and add new nodes - used for initialisation. You
-    can edit this before running the "roundup-admin initialise" command to
-    change the initial database entries.
-    ''' 
-    dbdir = os.path.join(config.DATABASE, 'files')
-    if not os.path.isdir(dbdir):
-        os.makedirs(dbdir)
-
-    db = open("admin")
-    db.clear()
-
-    #
-    # INITIAL PRIORITY AND STATUS VALUES
-    #
-    pri = db.getclass('priority')
-    pri.create(name="critical", order="1")
-    pri.create(name="urgent", order="2")
-    pri.create(name="bug", order="3")
-    pri.create(name="feature", order="4")
-    pri.create(name="wish", order="5")
-
-    stat = db.getclass('status')
-    stat.create(name="unread", order="1")
-    stat.create(name="deferred", order="2")
-    stat.create(name="chatting", order="3")
-    stat.create(name="need-eg", order="4")
-    stat.create(name="in-progress", order="5")
-    stat.create(name="testing", order="6")
-    stat.create(name="done-cbb", order="7")
-    stat.create(name="resolved", order="8")
-
-    # create the two default users
-    user = db.getclass('user')
-    user.create(username="admin", password=adminpw,
-        address=config.ADMIN_EMAIL, roles='Admin')
-    user.create(username="anonymous", roles='Anonymous')
-
-    # add any additional database create steps here - but only if you
-    # haven't initialised the database with the admin "initialise" command
-
-    db.commit()
-
-# vim: set filetype=python ts=4 sw=4 et si
-
diff --git a/roundup/templates/classic/detectors/.cvsignore b/roundup/templates/classic/detectors/.cvsignore
deleted file mode 100644 (file)
index 4162d5e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-*.pyc
-*.pyo
-*.cover
diff --git a/roundup/templates/classic/detectors/__init__.py b/roundup/templates/classic/detectors/__init__.py
deleted file mode 100644 (file)
index 96bb081..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
-# This module is free software, and you may redistribute it and/or modify
-# under the same terms as Python, so long as this copyright message and
-# disclaimer are retained in their original form.
-#
-# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
-# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
-# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-#$Id: __init__.py,v 1.8 2003-02-24 04:12:15 richard Exp $
-
-import sys, os, imp
-
-def init(db):
-    ''' execute the init functions of all the modules in this directory
-    '''
-    this_dir = os.path.split(__file__)[0]
-    for file in os.listdir(this_dir):
-        path = os.path.join(this_dir, file)
-        name, ext = os.path.splitext(file)
-        if name == '__init__':
-            continue
-        if ext == '.py':
-            module = imp.load_module(name, open(path), file,
-                ('.py', 'r', imp.PY_SOURCE))
-            module.init(db)
-
-# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/templates/classic/detectors/messagesummary.py b/roundup/templates/classic/detectors/messagesummary.py
deleted file mode 100644 (file)
index 2b23475..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#$Id: messagesummary.py,v 1.1 2003-02-13 21:14:27 richard Exp $
-
-from roundup.mailgw import parseContent
-
-def summarygenerator(db, cl, nodeid, newvalues):
-    ''' If the message doesn't have a summary, make one for it.
-    '''
-    if newvalues.has_key('summary') or not newvalues.has_key('content'):
-        return
-
-    summary, content = parseContent(newvalues['content'], 1, 1)
-    newvalues['summary'] = summary
-
-
-def init(db):
-    # fire before changes are made
-    db.msg.audit('create', summarygenerator)
-
-# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/templates/classic/detectors/nosyreaction.py b/roundup/templates/classic/detectors/nosyreaction.py
deleted file mode 100644 (file)
index 0aba92a..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-#
-# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
-# This module is free software, and you may redistribute it and/or modify
-# under the same terms as Python, so long as this copyright message and
-# disclaimer are retained in their original form.
-#
-# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
-# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
-# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-#$Id: nosyreaction.py,v 1.14 2002-09-10 01:07:06 richard Exp $
-
-from roundup import roundupdb, hyperdb
-
-def nosyreaction(db, cl, nodeid, oldvalues):
-    ''' A standard detector is provided that watches for additions to the
-        "messages" property.
-        
-        When a new message is added, the detector sends it to all the users on
-        the "nosy" list for the issue that are not already on the "recipients"
-        list of the message.
-        
-        Those users are then appended to the "recipients" property on the
-        message, so multiple copies of a message are never sent to the same
-        user.
-        
-        The journal recorded by the hyperdatabase on the "recipients" property
-        then provides a log of when the message was sent to whom. 
-    '''
-    # send a copy of all new messages to the nosy list
-    for msgid in determineNewMessages(cl, nodeid, oldvalues):
-        try:
-            cl.nosymessage(nodeid, msgid, oldvalues)
-        except roundupdb.MessageSendError, message:
-            raise roundupdb.DetectorError, message
-
-def determineNewMessages(cl, nodeid, oldvalues):
-    ''' Figure a list of the messages that are being added to the given
-        node in this transaction.
-    '''
-    messages = []
-    if oldvalues is None:
-        # the action was a create, so use all the messages in the create
-        messages = cl.get(nodeid, 'messages')
-    elif oldvalues.has_key('messages'):
-        # the action was a set (so adding new messages to an existing issue)
-        m = {}
-        for msgid in oldvalues['messages']:
-            m[msgid] = 1
-        messages = []
-        # figure which of the messages now on the issue weren't there before
-        for msgid in cl.get(nodeid, 'messages'):
-            if not m.has_key(msgid):
-                messages.append(msgid)
-    return messages
-
-def updatenosy(db, cl, nodeid, newvalues):
-    '''Update the nosy list for changes to the assignedto
-    '''
-    # nodeid will be None if this is a new node
-    current = {}
-    if nodeid is None:
-        ok = ('new', 'yes')
-    else:
-        ok = ('yes',)
-        # old node, get the current values from the node if they haven't
-        # changed
-        if not newvalues.has_key('nosy'):
-            nosy = cl.get(nodeid, 'nosy')
-            for value in nosy:
-                if not current.has_key(value):
-                    current[value] = 1
-
-    # if the nosy list changed in this transaction, init from the new value
-    if newvalues.has_key('nosy'):
-        nosy = newvalues.get('nosy', [])
-        for value in nosy:
-            if not db.hasnode('user', value):
-                continue
-            if not current.has_key(value):
-                current[value] = 1
-
-    # add assignedto(s) to the nosy list
-    if newvalues.has_key('assignedto') and newvalues['assignedto'] is not None:
-        propdef = cl.getprops()
-        if isinstance(propdef['assignedto'], hyperdb.Link):
-            assignedto_ids = [newvalues['assignedto']]
-        elif isinstance(propdef['assignedto'], hyperdb.Multilink):
-            assignedto_ids = newvalues['assignedto']
-        for assignedto_id in assignedto_ids:
-            if not current.has_key(assignedto_id):
-                current[assignedto_id] = 1
-
-    # see if there's any new messages - if so, possibly add the author and
-    # recipient to the nosy
-    if newvalues.has_key('messages'):
-        if nodeid is None:
-            ok = ('new', 'yes')
-            messages = newvalues['messages']
-        else:
-            ok = ('yes',)
-            # figure which of the messages now on the issue weren't
-            # there before - make sure we don't get a cached version!
-            oldmessages = cl.get(nodeid, 'messages', cache=0)
-            messages = []
-            for msgid in newvalues['messages']:
-                if msgid not in oldmessages:
-                    messages.append(msgid)
-
-        # configs for nosy modifications
-        add_author = getattr(db.config, 'ADD_AUTHOR_TO_NOSY', 'new')
-        add_recips = getattr(db.config, 'ADD_RECIPIENTS_TO_NOSY', 'new')
-
-        # now for each new message:
-        msg = db.msg
-        for msgid in messages:
-            if add_author in ok:
-                authid = msg.get(msgid, 'author')
-                current[authid] = 1
-
-            # add on the recipients of the message
-            if add_recips in ok:
-                for recipient in msg.get(msgid, 'recipients'):
-                    current[recipient] = 1
-
-    # that's it, save off the new nosy list
-    newvalues['nosy'] = current.keys()
-
-def init(db):
-    db.issue.react('create', nosyreaction)
-    db.issue.react('set', nosyreaction)
-    db.issue.audit('create', updatenosy)
-    db.issue.audit('set', updatenosy)
-
-# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/templates/classic/detectors/statusauditor.py b/roundup/templates/classic/detectors/statusauditor.py
deleted file mode 100644 (file)
index 7b4a526..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright (c) 2002 ekit.com Inc (http://www.ekit-inc.com/)
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-#   The above copyright notice and this permission notice shall be included in
-#   all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
-#$Id: statusauditor.py,v 1.3 2002-10-11 01:26:05 richard Exp $
-
-def chatty(db, cl, nodeid, newvalues):
-    ''' If the issue is currently 'unread', 'resolved' or 'done-cbb', then set
-        it to 'chatting'
-    '''
-    # don't fire if there's no new message (ie. chat)
-    if not newvalues.has_key('messages'):
-        return
-    if newvalues['messages'] == cl.get(nodeid, 'messages', cache=0):
-        return
-
-    # get the chatting state ID
-    try:
-        chatting_id = db.status.lookup('chatting')
-    except KeyError:
-        # no chatting state, ignore all this stuff
-        return
-
-    # get the current value
-    current_status = cl.get(nodeid, 'status')
-
-    # see if there's an explicit change in this transaction
-    if newvalues.has_key('status') and newvalues['status'] != current_status:
-        # yep, skip
-        return
-
-    # determine the id of 'unread', 'resolved' and 'chatting'
-    fromstates = []
-    for state in 'unread resolved done-cbb'.split():
-        try:
-            fromstates.append(db.status.lookup(state))
-        except KeyError:
-            pass
-
-    # ok, there's no explicit change, so check if we are in a state that
-    # should be changed
-    if current_status in fromstates:
-        # yep, we're now chatting
-        newvalues['status'] = chatting_id
-
-
-def presetunread(db, cl, nodeid, newvalues):
-    ''' Make sure the status is set on new issues
-    '''
-    if newvalues.has_key('status') and newvalues['status']:
-        return
-
-    # ok, do it
-    newvalues['status'] = db.status.lookup('unread')
-
-
-def init(db):
-    # fire before changes are made
-    db.issue.audit('set', chatty)
-    db.issue.audit('create', presetunread)
-
-# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/templates/classic/html/_generic.help b/roundup/templates/classic/html/_generic.help
deleted file mode 100644 (file)
index 0749525..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-<html>
-<head>
-<link rel="stylesheet" type="text/css" href="_file/style.css">
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8;">
-<script language="JavaScript" 
-        tal:condition="python:request.form.has_key('property')"
-        tal:content="structure string:
-
-// this is the name of the field in the original form that we're working on
-field = '${request/form/property/value}';
-
-function listClose() {
-  window.close();
-}
-        
-function listClear() {
-  window.opener.document.itemSynopsis[field].value = '';
-}
-        
-function pick(opt) {
-  if (window.opener && !window.opener.closed) {
-    window.opener.document.itemSynopsis[field].value = opt;
-  }
-}
-        
-// add a value to the form field
-function add(opt) {
-  val = window.opener.document.itemSynopsis[field].value;
-  if (/^\s*$$/.test(val)) {
-    newval = opt;   // existing is all whitespace, so just replace
-  } else {
-    newval = val + ', ' + opt;
-  }
-  pick(newval);
-}
-        
-// remove a value from the form field
-function remove(opt) {
-  // ((opt(,\s*)?)|(,\s*opt))
-  replaceStr = new String('(('+opt+'(,\\s*)?)|(,\\s*'+opt+'))');
-  re = new RegExp(replaceStr);
-
-  str = window.opener.document.itemSynopsis[field].value;
-
-  // replace occurences with empty string
-  newstr = str.replace(re, '');
-  pick(newstr);
-}
-">
-</script>
-</head>
-
-<body class="body" marginwidth="0" marginheight="0">
-<form>
-<div style="padding:10px;text-align:center;">
- <script language="javascript">
-  // put up a 'reset' button if the field has values when we pop up this window
-
-  // this is the name of the field in the original form that we're working on
-  orig = window.opener.document.itemSynopsis[field].value;
-  if (/[^\s]/.test(orig)) {
-    reset = '<input type="button" onclick="pick(orig);" ' +
-      'value="Reset to original values" /> | ';
-    document.write(reset);
-  }
- </script>
- <input type="button"
-        tal:attributes="value string:Clear all ${request/form/property/value} values"
-        onclick="listClear();" /> | 
- <input type="button" onclick="listClose();" value="Close this window" />
-</div>
-
-<table class="classhelp"
-       tal:define="props python:request.form['properties'].value.split(',')">
-<tr>
- <th tal:condition="python:request.form.has_key('property')">add/remove</th>
- <th tal:repeat="prop props" tal:content="prop"></th>
-</tr>
-<tr tal:repeat="item context/list">
- <td tal:condition="python:request.form.has_key('property')">
- <input type="button" tal:define="opt python: item[props[0]]" 
-         tal:attributes="onclick string:add('${opt}')" value=" + ">
- <input type="button" tal:define="opt python: item[props[0]]" 
-         tal:attributes="onclick string:remove('${opt}')" value=" - " />
- </td>
- <td tal:repeat="prop props" tal:content="structure python:item[prop]"></td>
-</tr>
-</table>
-</form>
-</body>
-</html>
diff --git a/roundup/templates/classic/html/_generic.index b/roundup/templates/classic/html/_generic.index
deleted file mode 100644 (file)
index f21b5d2..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-<!-- dollarId: issue.index,v 1.2 2001/07/29 04:07:37 richard Exp dollar-->
-
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title"
-       tal:content="python:context._classname.capitalize()+' editing'"></title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2 tal:content="python:context._classname.capitalize()+' editing'"></h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
-You are not allowed to view this page.
-</span>
-
-<tal:block tal:condition="context/is_edit_ok">
-<p class="form-help">
- You may edit the contents of the <span tal:replace="request/classname" />
- class using this form. Commas, newlines and double quotes (") must be
- handled delicately. You may include commas and newlines by enclosing the
- values in double-quotes ("). Double quotes themselves must be quoted by
- doubling ("").
-</p>
-
-<p class="form-help">
- Multilink properties have their multiple values colon (":") separated 
- (... ,"one:two:three", ...)
-</p>
-
-<p class="form-help">
- Remove entries by deleting their line. Add new entries by appending
- them to the table - put an X in the id column.
-</p>
-
-<form onSubmit="return submit_once()" method="POST">
-<textarea rows="15" cols="60" name="rows" tal:content="context/csv"></textarea>
-<br>
-<input type="hidden" name=":action" value="editCSV">
-<input type="submit" value="Edit Items">
-</form>
-</tal:block>
-
-<tal:block tal:condition="context/is_only_view_ok">
-view ok
-</tal:block>
-
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/_generic.item b/roundup/templates/classic/html/_generic.item
deleted file mode 100644 (file)
index a9d2e85..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title"
-       tal:content="python:context._classname.capitalize()+' editing'"></title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2 tal:content="python:context._classname.capitalize()+' editing'"></h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
-You are not allowed to view this page.
-</span>
-
-<form method="POST" onSubmit="return submit_once()"
-      enctype="multipart/form-data" tal:condition="context/is_edit_ok">
-
-<input type="hidden" name=":template" value="item">
-<input type="hidden" name=":required" value="title">
-
-<table class="form">
-
-<tr tal:repeat="prop python:db[context._classname].properties()">
- <tal:block tal:condition="python:prop._name not in ('id', 'creator',
-                                  'creation', 'activity')">
-  <th tal:content="prop/_name"></th>
-  <td tal:content="structure python:context[prop._name].field()"></td>
- </tal:block>
-</tr>
-<tr>
- <td>&nbsp;</td>
- <td colspan=3 tal:content="structure context/submit">
-  submit button will go here
- </td>
-</tr>
-</table>
-
-</form>
-
-<table class="form" tal:condition="context/is_only_view_ok">
-
-<tr tal:repeat="prop python:db[context._classname].properties()">
- <tal:block tal:condition="python:prop._name not in ('id', 'creator',
-                                  'creation', 'activity')">
-  <th tal:content="prop/_name"></th>
-  <td tal:content="structure python:context[prop._name].field()"></td>
- </tal:block>
-</tr>
-</table>
-
-
-<tal:block tal:condition="python:context.id and context.is_view_ok()">
- <tal:block tal:replace="structure context/history" />
-</tal:block>
-
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/file.index b/roundup/templates/classic/html/file.index
deleted file mode 100644 (file)
index 34dd0cf..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<!-- dollarId: file.index,v 1.4 2002/01/23 05:10:27 richard Exp dollar-->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title"> 
- <span tal:replace="config/TRACKER_NAME" />: List of files
-</title> 
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>List of files</h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<table class="otherinfo">
-<tr><th style="padding-right: 10">Download</th>
-    <th style="padding-right: 10">Content Type</th>
-    <th style="padding-right: 10">Uploaded By</th>
-    <th style="padding-right: 10">Date</th>
-</tr>
-<tr tal:repeat="file context/list">
- <td>
-  <a tal:attributes="href string:file${file/id}/${file/name}"
-     tal:content="file/name">dld link</a>
- </td>
- <td tal:content="file/type">content type</td>
- <td tal:content="file/creator">creator's name</td>
- <td tal:content="file/creation">creation date</td>
-</tr>
-</table>
-
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/file.item b/roundup/templates/classic/html/file.item
deleted file mode 100644 (file)
index ca9f6bd..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title">File display</title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>File display</h2>
-</td>
-
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
-You are not allowed to view this page.
-</span>
-
-<form method="POST" onSubmit="return submit_once()"
-      enctype="multipart/form-data" tal:condition="context/is_edit_ok">
-
-<input type="hidden" name=":template" value="item">
-<input type="hidden" name=":required" value="name,type">
-
-<input type="hidden" name=":multilink"
-       tal:condition="python:request.form.has_key(':multilink')"
-       tal:attributes="value request/form/:multilink/value">
-
-<table class="form">
- <tr>
-  <th>Name</th>
-  <td tal:content="structure context/name/field"></td>
- </tr>
- <tr>
-  <th>Content Type</th>
-  <td tal:content="structure context/type/field"></td>
- </tr>
-
- <tr>
-  <td>&nbsp;</td>
-  <td tal:content="structure context/submit">submit button here</td>
- </tr>
-</table>
-</form>
-
-<a tal:condition="python:context.id and context.is_view_ok()"
-   tal:attributes="href string:file${context/id}/${context/name}">download</a>
-
-<table class="form" tal:condition="context/is_only_view_ok">
- <tr>
-  <th>Name</th>
-  <td tal:content="context/name"></td>
- </tr>
- <tr>
-  <th>Content Type</th>
-  <td tal:content="context/type"></td>
- </tr>
-</table>
-
-<tal:block tal:condition="python:context.id and context.is_view_ok()"
-           tal:replace="structure context/history" />
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/home b/roundup/templates/classic/html/home
deleted file mode 100644 (file)
index fafdb2e..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<!--
- This is the default body that is displayed when people visit the
- tracker. The tag below lists the currently open issues. You may
- replace it with a greeting message, or a different list of issues or
- whatever. It's a good idea to have the issues on the front page though
--->
-<span tal:replace="structure python:db.issue.renderWith('index',
-    sort=('-', 'activity'), group=('+', 'priority'), filter=['status'],
-    columns=['id','activity','title','creator','assignedto', 'status'],
-    filterspec={'status':['-1','1','2','3','4','5','6','7']})" />
diff --git a/roundup/templates/classic/html/home.classlist b/roundup/templates/classic/html/home.classlist
deleted file mode 100644 (file)
index 0b5a244..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title">List of classes</title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>List of classes</h2>
-</td>
-<td class="content" metal:fill-slot="content">
-<table class="classlist">
-
-<tal:block tal:repeat="cl db/classes">
- <tr>
-  <th class="header" colspan="2" align="left">
-   <a tal:attributes="href string:${cl/classname}"
-      tal:content="python:cl.classname.capitalize()">classname</a>
-  </th>
- </tr>
- <tr tal:repeat="prop cl/properties">
-  <th tal:content="prop/_name">name</th>
-  <td tal:content="prop/_prop">type</td>
- </tr>
-</tal:block>
-
-</table>
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/issue.index b/roundup/templates/classic/html/issue.index
deleted file mode 100644 (file)
index e830c44..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-<!-- dollarId: issue.index,v 1.2 2001/07/29 04:07:37 richard Exp dollar-->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title"> 
- <span tal:replace="config/TRACKER_NAME" />: List of issues
-</title> 
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>List of issues</h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<tal:block tal:condition="not:context/is_view_ok">
-You are not allowed to view this page.
-</tal:block>
-
-<tal:block tal:define="batch request/batch" tal:condition="context/is_view_ok">
- <table class="list">
-  <tr>
-   <th tal:condition="request/show/priority">Priority</th>
-   <th tal:condition="request/show/id">ID</th>
-   <th tal:condition="request/show/creation">Creation</th>
-   <th tal:condition="request/show/activity">Activity</th>
-   <th tal:condition="request/show/topic">Topic</th>
-   <th tal:condition="request/show/title">Title</th>
-   <th tal:condition="request/show/status">Status</th>
-   <th tal:condition="request/show/creator">Created&nbsp;By</th>
-   <th tal:condition="request/show/assignedto">Assigned&nbsp;To</th>
-  </tr>
- <tal:block tal:repeat="i batch">
-  <tr tal:condition="python:request.group[1] and
-                            batch.propchanged(request.group[1])">
-   <th tal:attributes="colspan python:len(request.columns)"
-       tal:content="python:i[request.group[1]]" class="group">
-   </th>
-  </tr>
-  <tr tal:attributes="class python:['normal', 'alt'][repeat['i'].index%6/3]">
-   <td tal:condition="request/show/priority" tal:content="i/priority"></td>
-   <td tal:condition="request/show/id" tal:content="i/id"></td>
-   <td nowrap tal:condition="request/show/creation"
-       tal:content="i/creation/reldate"></td>
-   <td nowrap tal:condition="request/show/activity"
-       tal:content="i/activity/reldate"></td>
-   <td tal:condition="request/show/topic" tal:content="i/topic"></td>
-   <td tal:condition="request/show/title">
-    <a tal:attributes="href string:issue${i/id}"
-               tal:content="python:str(i.title.plain(hyperlink=0)) or '[no title]'">title</a>
-   </td>
-   <td tal:condition="request/show/status" tal:content="i/status"></td>
-   <td tal:condition="request/show/creator" tal:content="i/creator"></td>
-   <td tal:condition="request/show/assignedto" tal:content="i/assignedto"></td>
-  </tr>
- </tal:block>
- <tr class="navigation" tal:define="colspan python:len(request.columns)">
-  <th tal:attributes="colspan python:colspan/2">
-   <a tal:define="prev batch/previous" tal:condition="prev"
-      tal:attributes="href python:request.indexargs_url(request.classname,
-      {':startwith':prev.first, ':pagesize':prev.size})">&lt;&lt; previous</a>
-   &nbsp;
-  </th>
-  <th tal:attributes="colspan python:colspan/2 + colspan%2">
-   <a tal:define="next batch/next" tal:condition="next"
-      tal:attributes="href python:request.indexargs_url(request.classname,
-      {':startwith':next.first, ':pagesize':next.size})">next &gt;&gt;</a>
-   &nbsp;
-  </th>
- </tr>
-</table>
-
-<form method="GET" tal:attributes="action request/classname">
- <tal:block tal:replace="structure python:request.indexargs_form(sort=0, group=0)" />
- <table class="form">
-  <tr tal:condition="batch">
-   <th>Sort on:</th>
-   <td>
-    <select name=":sort">
-     <option value="">- nothing -</option>
-     <option tal:repeat="col context/properties"
-             tal:attributes="value col/_name;
-                             selected python:col._name == request.sort[1]"
-             tal:content="col/_name">column</option>
-    </select>
-   </td>
-   <th>Descending:</th>
-   <td><input type="checkbox" name=":sortdir"
-              tal:attributes="checked python:request.sort[0] == '-'"> 
-   </td>
-  </tr>
-  <tr>
-   <th>Group on:</th>
-   <td>
-    <select name=":group">
-     <option value="">- nothing -</option>
-     <option tal:repeat="col context/properties"
-             tal:attributes="value col/_name;
-                             selected python:col._name == request.group[1]"
-             tal:content="col/_name">column</option>
-    </select>
-   </td>
-   <th>Descending:</th>
-   <td><input type="checkbox" name=":groupdir"
-              tal:attributes="checked python:request.group[0] == '-'"> 
-   </td>
-  </tr>
-  <tr><td colspan="4"><input type="submit" value="Redisplay"></td></tr>
- </table>
-</form>
-
-</tal:block>
-
-</td>
-</tal:block>
-
diff --git a/roundup/templates/classic/html/issue.item b/roundup/templates/classic/html/issue.item
deleted file mode 100644 (file)
index 8db909b..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-<!-- dollarId: issue.item,v 1.4 2001/08/03 01:19:43 richard Exp dollar-->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title"> 
-<span tal:replace="config/TRACKER_NAME" />: 
-<span tal:condition="context/id"
-       tal:replace="string:Issue ${context/id}: ${context/title}" />
-<tal:x tal:condition="not:context/id">New Issue</tal:x> 
-</title> 
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>
-  Issue<span tal:replace="context/id" />
-   <tal:x tal:condition="context/is_edit_ok">Editing</tal:x>
- </h2>
-</td>
-
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
-You are not allowed to view this page.
-</span>
-
-<form method="POST" name="itemSynopsis" onSubmit="return submit_once()"
-      enctype="multipart/form-data" tal:condition="context/is_edit_ok">
-
-<input type="hidden" name=":template" value="item">
-<input type="hidden" name=":required" value="title,priority">
-
-<table class="form">
-<tr>
- <th class="required" nowrap>Title</th>
- <td colspan=3 tal:content="structure python:context.title.field(size=60)">title</td>
-</tr>
-
-<tr>
- <th class="required" nowrap>Priority</th>
- <td tal:content="structure context/priority/menu">priority</td>
- <th nowrap>Status</th>
- <td tal:content="structure context/status/menu">status</td>
-</tr>
-
-<tr>
- <th nowrap>Superseder</th>
- <td>
-  <span tal:replace="structure python:context.superseder.field(showid=1, size=20)" />
-  <span tal:replace="structure python:db.issue.classhelp('id,title', property='superseder')" />
-  <span tal:condition="context/superseder" tal:repeat="sup context/superseder">
-   <br>View: <a tal:attributes="href string:issue${sup/id}"
-                tal:content="sup/id"></a>
-  </span>
- </td>
- <th nowrap>Nosy List</th>
- <td>
-  <span tal:replace="structure context/nosy/field" />
-  <span tal:replace="structure
-python:db.user.classhelp('username,realname,address', property='nosy', width='600')" /><br>
- </td>
-</tr>
-
-<tr>
- <th nowrap>Assigned To</th>
- <td tal:content="structure context/assignedto/menu">assignedto menu</td>
- <th nowrap>Topics</th>
- <td>
-  <span tal:replace="structure context/topic/field" />
-  <span tal:replace="structure python:db.keyword.classhelp(property='topic')" />
- </td>
-</tr>
-
-<tr>
- <th nowrap>Change Note</th>
- <td colspan=3>
-  <textarea tal:content="request/form/:note/value | default"
-            name=":note" wrap="hard" rows="5" cols="80"></textarea>
- </td>
-</tr>
-
-<tr>
- <th nowrap>File</th>
- <td colspan=3><input type="file" name=":file" size="40"></td>
-</tr>
-
-<tr>
- <td>&nbsp;</td>
- <td colspan=3 tal:content="structure context/submit">
-  submit button will go here
- </td>
-</tr>
-</table>
-</form>
-
-<table class="form" tal:condition="not:context/id">
-<tr>
- <td>Note:&nbsp;</td>
- <th class="required">highlighted</th>
- <td>&nbsp;fields are required.</td>
-</tr>
-</table>
-
-<table class="form" tal:condition="context/is_only_view_ok">
-<tr>
- <th nowrap>Title</th><td colspan=3 tal:content="context/title">title</td>
-</tr>
-
-<tr>
- <th nowrap>Priority</th><td tal:content="context/priority">priority</td>
- <th nowrap>Status</th><td tal:content="context/status">status</td>
-</tr>
-
-<tr>
- <th nowrap>Superseder</th>
- <td>
-  <span tal:condition="context/superseder" tal:repeat="sup context/superseder">
-   <br>View: <a tal:attributes="href string:issue${sup/id}"
-                tal:content="sup/id"></a>
-  </span>
- </td>
- <th nowrap>Nosy List</th><td><span tal:replace="context/nosy" /></td>
-</tr>
-
-<tr>
- <th nowrap>Assigned To</th><td tal:content="context/assignedto"></td>
- <th nowrap>Topics</th><td tal:content="structure context/topic"></td>
-</tr>
-</table>
-
-<tal:block tal:condition="python:context.id and context.is_view_ok()">
-
- <p tal:content="structure string:Created on
-  <b>${context/creation}</b> by <b>${context/creator}</b>, last
-  changed <b>${context/activity}</b>.">activity info
- </p>
-
- <table class="messages" tal:condition="context/messages">
-  <tr><th colspan="4" class="header">Messages</th></tr>
-  <tal:block tal:repeat="msg context/messages/reverse">
-   <tr>
-    <th><a tal:attributes="href string:msg${msg/id}"
-           tal:content="string:msg${msg/id}"></a></th>
-    <th tal:content="string:Author: ${msg/author}">author</th>
-    <th tal:content="string:Date: ${msg/date}">date</th>
-    <th>
-     <a tal:attributes="href string:?:remove:messages=${msg/id}&:action=edit">remove</a>
-    </th>
-   </tr>
-   <tr>
-    <td colspan="4" class="content">
-     <pre tal:content="msg/content">content</pre>
-    </td>
-   </tr>
-  </tal:block>
- </table>
-
- <table class="files" tal:condition="context/files">
-  <tr><th colspan="2" class="header">Files</th></tr>
-  <tr><th>File name</th><th>Uploaded</th></tr>
-  <tr tal:repeat="file context/files">
-   <td>
-    <a tal:attributes="href string:file${file/id}/${file/name}"
-       tal:content="file/name">dld link</a>
-   </td>
-   <td>
-    <span tal:content="file/creator">creator's name</span>,
-    <span tal:content="file/creation">creation date</span>
-   </td>
-  </tr>
- </table>
-
- <tal:block tal:replace="structure context/history" />
-
-</tal:block>
-
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/issue.search b/roundup/templates/classic/html/issue.search
deleted file mode 100644 (file)
index 4f9112d..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title">Issue searching</title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>Issue searching</h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<form method="GET" tal:attributes="action request/classname">
-<input type="hidden" name=":action" value="search">
-
-<table class="form" tal:define="
-   cols python:'id activity priority title status assignedto'.split();
-   defsort python:['activity'];
-   defgroup python:['priority'];
-   defdisp python:'id activity title status assignedto'.split()">
-
-<tr>
- <th class="header">&nbsp;</th>
- <th class="header">Filter on</th>
- <th class="header">Display</th>
- <th class="header">Sort on</th>
- <th class="header">Group on</th>
-</tr>
-
-<tr>
- <th>All text*:</th>
- <td><input name=":search_text"
-            tal:attributes="value request/form/:search_text/value | nothing">
- </td>
- <td>&nbsp;</td>
- <td>&nbsp;</td>
- <td>&nbsp;</td>
-</tr>
-
-<tr>
- <th>Title:</th>
- <td><input name="title"></td>
- <td><input type="checkbox" name=":columns" value="title" checked></td>
- <td><input type="radio" name=":sort" value="title"></td>
- <td>&nbsp;</td>
-</tr>
-
-<tr>
- <th>Topic:</th>
- <td>
-  <select name="topic">
-   <option value="">don't care</option>
-   <option value="">------------</option>
-   <option tal:repeat="s db/keyword/list" tal:attributes="value s/name"
-           tal:content="s/name">topic to filter on</option>
-  </select>
- </td>
- <td><input type="checkbox" name=":columns" value="topic" checked></td>
- <td><input type="radio" name=":sort" value="topic"></td>
- <td><input type="radio" name=":group" value="topic"></td>
-</tr>
-
-<tr>
- <th>ID:</th>
- <td><input name="id"></td>
- <td><input type="checkbox" name=":columns" value="id" checked></td>
- <td><input type="radio" name=":sort" value="id"></td>
- <td>&nbsp;</td>
-</tr>
-
-<tr>
- <th>Creation date:</th>
- <td><input name="creation"></td>
- <td><input type="checkbox" name=":columns" value="creation"></td>
- <td><input type="radio" name=":sort" value="creation"></td>
- <td><input type="radio" name=":group" value="creation"></td>
-</tr>
-
-<tr>
- <th>Creator:</th>
- <td>
-  <select name="creator">
-   <option value="">don't care</option>
-   <option tal:attributes="value request/user/id">created by me</option>
-   <option value="-1">------------</option>
-   <option tal:repeat="s db/user/list" tal:attributes="value s/id"
-     tal:content="s/username">user to filter on</option>
-  </select>
- </td>
- <td><input type="checkbox" name=":columns" value="creator" checked></td>
- <td><input type="radio" name=":sort" value="creator"></td>
- <td><input type="radio" name=":group" value="creator"></td>
-</tr>
-
-<tr>
- <th>Activity:</th>
- <td><input name="activity"></td>
- <td><input type="checkbox" name=":columns" value="activity" checked></td>
- <td><input type="radio" name=":sort" value="activity"></td>
- <td>&nbsp;</td>
-</tr>
-
-<tr>
- <th>Priority:</th>
- <td>
-  <select name="priority">
-   <option value="">don't care</option>
-   <option value="-1">not selected</option>
-   <option value="">------------</option>
-   <option tal:repeat="s db/priority/list" tal:attributes="value s/id"
-     tal:content="s/name">priority to filter on</option>
-  </select>
- </td>
- <td><input type="checkbox" name=":columns" value="priority"></td>
- <td><input type="radio" name=":sort" value="priority"></td>
- <td><input type="radio" name=":group" value="priority"></td>
-</tr>
-
-<tr>
- <th>Status:</th>
- <td>
-  <select name="status">
-   <option value="">don't care</option>
-   <option value="-1,1,2,3,4,5,6,7">not resolved</option>
-   <option value="-1">not selected</option>
-   <option value="">------------</option>
-   <option tal:repeat="s db/status/list" tal:attributes="value s/id"
-           tal:content="s/name">status to filter on</option>
-  </select>
- </td>
- <td><input type="checkbox" name=":columns" value="status" checked></td>
- <td><input type="radio" name=":sort" value="status"></td>
- <td><input type="radio" name=":group" value="status"></td>
-</tr>
-
-<tr>
- <th>Assigned To:</th>
- <td>
-  <select name="assignedto">
-   <option value="">don't care</option>
-   <option tal:attributes="value request/user/id">assigned to me</option>
-   <option value="-1">unassigned</option>
-   <option value="">------------</option>
-   <option tal:repeat="s db/user/list" tal:attributes="value s/id"
-     tal:content="s/username">user to filter on</option>
-  </select>
- </td>
- <td><input type="checkbox" name=":columns" value="assignedto" checked></td>
- <td><input type="radio" name=":sort" value="assignedto"></td>
- <td><input type="radio" name=":group" value="assignedto"></td>
-</tr>
-
-<tr>
-<th>Pagesize:</th>
-<td><input type="text" name=":pagesize" size="3" value="50"></td>
-</tr>
-
-<tr>
-<th>Start With:</th>
-<td><input type="text" name=":startwith" size="3" value="0"></td>
-</tr>
-
-<tr>
-<th>Sort Descending:</th>
-<td><input type="checkbox" name=":sortdir" checked>
-</td>
-
-<tr>
-<th>Group Descending:</th>
-<td><input type="checkbox" name=":groupdir">
-</td>
-</tr>
-
-<tr>
-<th>Query name**:</th>
-<td><input name=":queryname"
-            tal:attributes="value request/form/:queryname/value | nothing">
-</td>
-</tr>
-
-<tr><td>&nbsp;</td>
-<td><input type="submit" value="Search"></td>
-</tr>
-
-<tr><td>&nbsp;</td>
- <td colspan="4" class="help">
-   *: The "all text" field will look in message bodies and issue titles<br>
-   **: If you supply a name, the query will be saved off and available as a
-       link in the sidebar
- </td>
-</tr>
-</table>
-
-</form>
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/keyword.item b/roundup/templates/classic/html/keyword.item
deleted file mode 100644 (file)
index 4572370..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-<!-- dollarId: keyword.item,v 1.3 2002/05/22 00:32:34 richard Exp dollar-->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title">Keyword editing</title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>Keyword editing</h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<table class="otherinfo" tal:define="keywords db/keyword/list"
-       tal:condition="keywords">
- <tr><th colspan="4" class="header">Existing Keywords</th></tr>
- <tr tal:repeat="start python:range(0, len(keywords), 4)">
-  <td width="25%" tal:define="batch python:utils.Batch(keywords, 4, start)"
-      tal:repeat="keyword batch">
-    <a tal:attributes="href string:keyword${keyword/id}"
-       tal:content="keyword/name">keyword here</a>
-  </td>
- </tr>
- <tr>
-  <td colspan="4" style="border-top: 1px solid gray">
-   To edit an existing keyword (for spelling or typing errors),
-   click on its entry above.
-  </td>
- </tr>
-</table>
-
-<p class="help" tal:condition="not:context/id">
- To create a new keyword, enter it below and click "Submit New Entry".
-</p>
-
-<form method="POST" onSubmit="return submit_once()"
-      enctype="multipart/form-data">
-
- <input type="hidden" name=":required" value="name">
- <input type="hidden" name=":template" value="item">
-
- <table class="form">
-  <tr>
-   <th nowrap>Keyword</th>
-   <td tal:content="structure context/name/field">name</td>
-  </tr>
-
-  <tr>
-   <td>&nbsp;</td>
-   <td colspan=3 tal:content="structure context/submit">
-    submit button will go here
-   </td>
-  </tr>
- </table>
-</form>
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/msg.index b/roundup/templates/classic/html/msg.index
deleted file mode 100644 (file)
index 666344b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title"> 
- <span tal:replace="config/TRACKER_NAME" />: List of messages
-</title> 
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>Message listing</h2>
-</td>
-<td class="content" metal:fill-slot="content">
-<table class="messages" tal:condition="request/filter">
- <tr><th colspan=2 class="header">Messages</th></tr>
- <tal:block tal:repeat="msg context/list">
-  <tr>
-   <th tal:content="string:Author: ${msg/author}">author</th>
-   <th tal:content="string:Date: ${msg/date}">date</th>
-  </tr>
-  <tr>
-   <td colspan="2"><pre tal:content="msg/content">content</pre></td>
-  </tr>
- </tal:block>
-</table>
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/msg.item b/roundup/templates/classic/html/msg.item
deleted file mode 100644 (file)
index 49e203a..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-<!-- dollarId: msg.item,v 1.3 2002/05/22 00:32:34 richard Exp dollar-->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title"> 
-<span tal:replace="config/TRACKER_NAME" />: 
-<span tal:condition="context/id" tal:replace="string:Message ${context/id}" />
-<tal:x tal:condition="not:context/id">New Message</tal:x> 
-</title> 
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>
-  Message<span tal:replace="context/id" />
-   <tal:x tal:condition="context/is_edit_ok">Editing</tal:x>
- </h2>
-</td>
-<td class="content" metal:fill-slot="content">
-<table class="form">
-
-<tr>
- <th nowrap>Author</th>
- <td tal:content="context/author"></td>
-</tr>
-
-<tr>
- <th nowrap>Recipients</th>
- <td tal:content="context/recipients"></td>
-</tr>
-
-<tr>
- <th nowrap>Date</th>
- <td tal:content="context/date"></td>
-</tr>
-</table>
-
-<table class="messages">
- <tr><th colspan=2 class="header">Content</th></tr>
- <tr>
-  <td class="content" colspan=2><pre tal:content="context/content"></pre></td>
- </tr>
-</table>
-
-<table class="files" tal:condition="context/files">
- <tr><th colspan="2" class="header">Files</th></tr>
- <tr><th>File name</th><th>Uploaded</th></tr>
- <tr tal:repeat="file context/files">
-  <td>
-   <a tal:attributes="href string:file${file/id}/${file/name}"
-      tal:content="file/name">dld link</a>
-  </td>
-  <td>
-   <span tal:content="file/creator">creator's name</span>,
-   <span tal:content="file/creation">creation date</span>
-  </td>
- </tr>
-</table>
-
-<tal:block tal:replace="structure context/history" />
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/page b/roundup/templates/classic/html/page
deleted file mode 100644 (file)
index cd2e98f..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-<html metal:define-macro="icing">
-<head>
-<title metal:define-slot="head_title">title goes here</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8;">
-
-<link rel="stylesheet" type="text/css" href="_file/style.css">
-
-<script tal:replace="structure request/base_javascript">
-</script>
-
-</head>
-<body class="body" marginwidth="0" marginheight="0">
-
-<table class="body">
-
-<tr>
- <td class="page-header-left">&nbsp;</td>
- <td class="page-header-top" metal:define-slot="body_title"><h2>name</h2></td>
-</tr>
-
-<tr>
- <td rowspan="2" valign="top" nowrap class="sidebar">
-  <p class="classblock" tal:condition="request/user/queries">
-   <b>Your Queries</b><br>
-   <tal:block tal:repeat="qs request/user/queries">
-    <a tal:attributes="href string:${qs/klass}${qs/url}"
-       tal:content="qs/name">link</a><br>
-   </tal:block>
-  </p>
-
-  <form method="POST">
-   <p class="classblock"
-       tal:condition="python:request.user.hasPermission('View', 'issue')">
-    <b>Issues</b><br>
-    <a tal:condition="python:request.user.hasPermission('Edit', 'issue')"
-      href="issue?:template=item">Create New<br></a>
-    <a href="issue?:sort=-activity&:group=priority&:filter=status,assignedto&:columns=id,activity,title,creator,status&status=-1,1,2,3,4,5,6,7&assignedto=-1">Show Unassigned</a><br>
-    <a href="issue?:sort=-activity&:group=priority&:filter=status&:columns=id,activity,title,creator,assignedto,status&status=-1,1,2,3,4,5,6,7">Show All</a><br>
-    <a href="issue?:template=search">Search</a><br>
-    <input type="submit" value="Show issue no."><input size="4" type="text" name=":number">
-    <input type="hidden" name=":type" value="issue">
-    <input type="hidden" name=":action" value="show">
-   </p>
-  </form>
-
-  <p class="classblock"
-     tal:condition="python:request.user.hasPermission('View', 'keyword')">
-   <b>Keywords</b><br>
-   <a tal:condition="python:request.user.hasPermission('Edit', 'keyword')"
-      href="keyword?:template=item">Create New<br></a>
-   <a tal:condition="python:request.user.hasPermission('Edit', 'keyword') and
-                            len(db.keyword.list())"
-      href="keyword?:template=item">Edit Existing<br></a>
-  </p>
-
-  <p class="classblock"
-       tal:condition="python:request.user.username != 'anonymous'">
-   <b>Administration</b><br>
-   <a tal:condition="python:request.user.hasPermission('Edit', None)"
-      href="home?:template=classlist">Class List</a><br>
-   <a tal:condition="python:request.user.hasPermission('View', 'user')
-                            or request.user.hasPermission('Edit', 'user')"
-      href="user" >User List</a><br>
-   <a tal:condition="python:request.user.hasPermission('Edit', 'user')"
-      href="user?:template=item">Add User</a>
-  </p>
-
-  <form method="POST" action="">
-   <p class="userblock" tal:condition="python:request.user.username=='anonymous'">
-    <input size="10" name="__login_name"><br>
-    <input size="10" type="password" name="__login_password"><br>
-    <input type="submit" name=":action" value="login">
-    <span tal:replace="structure request/indexargs_form" />
-    <a href="user?:template=register">Register</a><br>
-    <a href="user?:template=forgotten">Forgotten your password?</a><br>
-   </p>
-  </form>
-   
-  <p class="userblock" tal:condition="python:request.user.username != 'anonymous'">
-   <b>Hello,</b><br><b tal:content="request/user/username">username</b><br>
-   <a tal:attributes="href string:issue?:sort=-activity&:group=priority&:filter=status,assignedto&:columns=id,activity,title,creator,status&status=-1,1,2,3,4,5,6,7&assignedto=${request/user/id}">My Issues</a><br>
-   <a tal:attributes="href string:user${request/user/id}">My Details</a><br>
-   <a tal:attributes="href python:request.indexargs_href('',
-       {':action':'logout'})">Logout</a>
-  </p>
- </td>
- <td>
-  <p tal:condition="options/error_message | nothing" class="error-message"
-     tal:repeat="m options/error_message" tal:content="structure m">error</p>
-  <p tal:condition="options/ok_message | nothing" class="ok-message"
-     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
- </td>
-</tr>
-<tr>
- <td class="content" metal:define-slot="content">Page content goes here</td>
-</tr>
-
-</table>
-
-<pre tal:condition="request/form/debug | nothing" tal:content="request">
-</pre>
-
-</body>
-</html>
diff --git a/roundup/templates/classic/html/query.item b/roundup/templates/classic/html/query.item
deleted file mode 100755 (executable)
index 5e969d3..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<!-- query.item -->
-<span tal:content="structure context/renderQueryForm" />
-
diff --git a/roundup/templates/classic/html/style.css b/roundup/templates/classic/html/style.css
deleted file mode 100644 (file)
index da5c4c6..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-/* main page styles */
-body.body {
-  font-family: sans-serif, Arial, Helvetica;
-  color: #333333;
-}
-a[href]:hover { color:blue; text-decoration: underline; }
-a[href]:link { color:blue; text-decoration: none; }
-a[href] { color:blue; text-decoration: none; }
-
-table.body {
-  border: 0;
-  padding: 0;
-  border-spacing: 0px;
-  border-collapse: separate;
-}
-
-td.page-header-left {
-  padding: 5px;
-  border-bottom: 1px solid #444444;
-}
-
-td.page-header-top {
-  padding: 5px;
-  border-bottom: 1px solid #444444;
-}
-
-td.sidebar {
-  padding: 1 0 0 1;
-}
-
-td.sidebar p.classblock {
-  padding: 0 5 0 5;
-  margin: 1 1 1 1;
-  border: 1px solid #444444;
-  background-color: #eeeeee;
-}
-
-td.sidebar p.userblock {
-  padding: 0 5 0 5;
-  margin: 1 1 1 1;
-  border: 1px solid #444444;
-  background-color: #eeeeff;
-}
-
-td.content {
-  padding: 1 5 1 5;
-  vertical-align: top;
-  width: 100%;
-}
-
-p.ok-message {
-  background-color: #22bb22;
-  padding: 5 5 5 5;
-  color: white;
-  font-weight: bold;
-}
-p.error-message {
-  background-color: #bb2222;
-  padding: 5 5 5 5;
-  color: white;
-  font-weight: bold;
-}
-
-
-/* style for forms */
-table.form {
-  padding: 2;
-  border-spacing: 0px;
-  border-collapse: separate;
-}
-
-table.form th {
-  color: #333388;
-  text-align: right;
-  vertical-align: top;
-  font-weight: normal;
-}
-
-table.form th.header {
-  font-weight: bold;
-  background-color: #eeeeff;
-  text-align: left;
-}
-
-table.form th.required {
-  font-weight: bold;
-}
-
-table.form td {
-  color: #333333;
-  empty-cells: show;
-  vertical-align: top;
-}
-
-table.form td.optional {
-  font-weight: bold;
-  font-style: italic;
-}
-
-table.form td.html {
-  color: #777777;
-}
-
-/* style for lists */
-table.list {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.list th {
-  padding: 0 4 0 4;
-  color: #404070;
-  background-color: #eeeeff;
-  border: 1px solid white;
-  vertical-align: top;
-  empty-cells: show;
-}
-table.list th a[href]:hover { color: #404070 }
-table.list th a[href]:link { color: #404070 }
-table.list th a[href] { color: #404070 }
-table.list th.group {
-  background-color: #f4f4ff;
-  text-align: center;
-}
-
-table.list td {
-  padding: 0 4 0 4;
-  border: 1px solid white;
-  color: #404070;
-  background-color: white;
-  vertical-align: top;
-  empty-cells: show;
-}
-
-table.list tr.normal td {
-  background-color: #efefef;
-}
-
-table.list tr.alt td {
-  background-color: #efefef;
-}
-
-table.list tr.navigation th {
-  text-align: right;
-}
-table.list tr.navigation th:first-child {
-  text-align: left;
-}
-
-
-/* style for message displays */
-table.messages {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.messages th.header{
-  padding-top: 10px;
-  border-bottom: 1px solid gray;
-  font-weight: bold;
-  background-color: white;
-  color: #707040;
-}
-
-table.messages th {
-  font-weight: bold;
-  color: black;
-  text-align: left;
-  border-bottom: 1px solid #afafaf;
-}
-
-table.messages td {
-  font-family: monospace;
-  background-color: #efefef;
-  border-bottom: 1px solid #afafaf;
-  color: black;
-  empty-cells: show;
-  border-right: 1px solid #afafaf;
-  vertical-align: top;
-  padding: 2 5 2 5;
-}
-
-table.messages td:first-child {
-  border-left: 1px solid #afafaf;
-  border-right: 1px solid #afafaf;
-}
-
-/* style for file displays */
-table.files {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.files th.header{
-  padding-top: 10px;
-  border-bottom: 1px solid gray;
-  font-weight: bold;
-  background-color: white;
-  color: #707040;
-}
-
-table.files th {
-  border-bottom: 1px solid #afafaf;
-  font-weight: bold;
-  text-align: left;
-}
-
-table.files td {
-  font-family: monospace;
-  empty-cells: show;
-}
-
-/* style for history displays */
-table.history {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.history th.header{
-  padding-top: 10px;
-  border-bottom: 1px solid gray;
-  font-weight: bold;
-  background-color: white;
-  color: #707040;
-  font-size: 100%;
-}
-
-table.history th {
-  border-bottom: 1px solid #afafaf;
-  font-weight: bold;
-  text-align: left;
-  font-size: 90%;
-}
-
-table.history td {
-  font-size: 90%;
-  vertical-align: top;
-  empty-cells: show;
-}
-
-
-/* style for class list */
-table.classlist {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.classlist th.header{
-  padding-top: 10px;
-  border-bottom: 1px solid gray;
-  font-weight: bold;
-  background-color: white;
-  color: #707040;
-}
-
-table.classlist th {
-  font-weight: bold;
-  text-align: left;
-}
-
-
-/* style for class help display */
-table.classhelp {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.classhelp th {
-  font-weight: bold;
-  text-align: left;
-  color: #707040;
-}
-
-table.classhelp td {
-  padding: 2 2 2 2;
-  border: 1px solid black;
-  text-align: left;
-  vertical-align: top;
-  empty-cells: show;
-}
-
-
-/* style for "other" displays */
-table.otherinfo {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.otherinfo th.header{
-  padding-top: 10px;
-  border-bottom: 1px solid gray;
-  font-weight: bold;
-  background-color: white;
-  color: #707040;
-}
-
-table.otherinfo th {
-  border-bottom: 1px solid #afafaf;
-  font-weight: bold;
-  text-align: left;
-}
diff --git a/roundup/templates/classic/html/user.forgotten b/roundup/templates/classic/html/user.forgotten
deleted file mode 100644 (file)
index 1df6918..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title">Password reset request</title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>Password reset request</h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<p>You have two options if you have forgotten your password. If you 
-know the email address you registered with, enter it below.</p>
-
-<form method="POST" onSubmit="return submit_once()">
-<input type="hidden" name="@action" value="passrst">
-<input type="hidden" name="@template" value="forgotten">
-<table class="form">
- <tr><th>Email Address:</th> <td><input name="address"></td> </tr>
- <tr><td></td><td><input type="submit" value="Request password reset"></td></tr>
-</table>
-
-<p>Or, if you know your username, then enter it below.</p>
-
-<table class="form">
- <tr><th>Username:</th> <td><input name="username"></td> </tr>
- <tr><td></td><td><input type="submit" value="Request password reset"></td></tr>
-</table>
-</form>
-
-<p>A confirmation email will be sent to you - please follow the
-instructions
-within it to complete the reset process.</p>
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/user.index b/roundup/templates/classic/html/user.index
deleted file mode 100644 (file)
index 7c70042..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<!-- dollarId: user.index,v 1.3 2002/07/09 05:29:51 richard Exp dollar-->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title">User listing</title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>User listing</h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="not:context/is_view_ok">
-You are not allowed to view this page.
-</span>
-
-<table width="100%" tal:condition="context/is_view_ok" class="list">
-<tr>
- <th>Username</th>
- <th>Real name</th>
- <th>Organisation</th>
- <th>Email address</th>
- <th>Phone number</th>
- <th tal:condition="context/is_edit_ok">Retire</th>
-</tr>
-<tr tal:repeat="user context/list"
-    tal:attributes="class python:['normal', 'alt'][repeat['user'].index%6/3]">
- <td>
-  <a tal:attributes="href string:user${user/id}"
-     tal:content="user/username">username</a>
- </td>
- <td tal:content="user/realname">realname</td>
- <td tal:content="user/organisation">organisation</td>
- <td tal:content="python:user.address.email()">address</td>
- <td tal:content="user/phone">phone</td>
- <td tal:condition="context/is_edit_ok">
-  <a tal:attributes="href string:user${user/id}?:action=retire&:template=index">
-   retire</a>
- </td>
-</tr>
-</table>
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/user.item b/roundup/templates/classic/html/user.item
deleted file mode 100644 (file)
index 422d933..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title"> 
-<span tal:replace="config/TRACKER_NAME" />: 
-<span tal:condition="context/id"
-      tal:replace="string:User ${context/id}: ${context/username}" />
-<tal:x tal:condition="not:context/id">New User</tal:x> 
-</title> 
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>
-  User<span tal:replace="context/id" />
-   <tal:x tal:condition="context/is_edit_ok">Editing</tal:x>
- </h2>
-</td>
-
-<td class="content" metal:fill-slot="content">
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
-You are not allowed to view this page.
-</span>
-
-<form method="POST" onSubmit="return submit_once()"
-      enctype="multipart/form-data" tal:condition="context/is_edit_ok">
-
-<input type="hidden" name=":required" value="username,address">
-
-<table class="form">
- <tr>
-  <th>Name</th>
-  <td tal:content="structure context/realname/field">realname</td>
- </tr>
- <tr>
-  <th>Login Name</th>
-  <td tal:content="structure context/username/field">username</td>
- </tr>
- <tr>
-  <th>Login Password</th>
-  <td tal:content="structure context/password/field">password</td>
- </tr>
- <tr>
-  <th>Confirm Password</th>
-  <td tal:content="structure context/password/confirm">password</td>
- </tr>
- <tr tal:condition="python:request.user.hasPermission('Web Roles')">
-  <th>Roles</th>
-  <td tal:condition="context/id"
-      tal:content="structure context/roles/field">roles</td>
-  <td tal:condition="not:context/id">
-   <input name="roles" tal:attributes="value db/config/NEW_WEB_USER_ROLES">
-   (to give the user more than one role, enter a comma,separated,list)
-  </td>
- </tr>
- <tr>
-  <th>Phone</th>
-  <td tal:content="structure context/phone/field">phone</td>
- </tr>
- <tr>
-  <th>Organisation</th>
-  <td tal:content="structure context/organisation/field">organisation</td>
- </tr>
- <tr>
-  <th>Timezone</th>
-  <td tal:content="structure context/timezone/field">timezone</td>
- </tr>
- <tr>
-  <th>E-mail address</th>
-  <td tal:content="structure context/address/field">address</td>
- </tr>
- <tr>
-  <th>Alternate E-mail addresses<br>One address per line</th>
-  <td tal:content="structure context/alternate_addresses/multiline">alternate_addresses</td>
- </tr>
-
- <tr>
-  <td>&nbsp;</td>
-  <td tal:content="structure context/submit">submit button here</td>
- </tr>
-</table>
-</form>
-
-<table class="otherinfo" tal:condition="context/queries">
- <tr><th colspan="3" class="header">Queries</th></tr>
- <tr><th>Name</th><th colspan="2">Actions</th></tr>
- <tr tal:repeat="query context/queries">
-  <td><a tal:attributes="href string:query${query/id}"
-         tal:content="query/name"></a></td>
-  <td>
-   <a tal:attributes="href python:'%s%s'%(query['klass'], query['url'])">display</a>
-  </td>
-  <td>
-   <a tal:attributes="href string:?:remove:queries=${query/id}&:action=edit">remove</a>
-  </td>
- </tr>
-</table>
-
-<table class="form" tal:condition="context/is_only_view_ok">
- <tr>
-  <th colspan=2 class="header" tal:content="context/realname">realname</th>
- </tr>
- <tr>
-  <th>Login Name</th>
-  <td tal:content="context/username">username</td>
- </tr>
- <tr>
-  <th>Phone</th>
-  <td tal:content="context/phone">phone</td>
- </tr>
- <tr>
-  <th>Organisation</th>
-  <td tal:content="context/organisation">organisation</td>
- </tr>
- <tr>
-  <th>Timezone</th>
-  <td tal:content="context/timezone">timezone</td>
- </tr>
- <tr>
-  <th>E-mail address</th>
-  <td tal:content="context/address/email">address</td>
- </tr>
-</table>
-
-<tal:block tal:condition="python:context.id and context.is_view_ok()"
-           tal:replace="structure context/history" />
-
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/user.register b/roundup/templates/classic/html/user.register
deleted file mode 100644 (file)
index a226413..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title"
-       tal:content="string:Registering with ${db/config/TRACKER_NAME}"></title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2 tal:content="string:Registering with ${db/config/TRACKER_NAME}"></h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<tal:block tal:define=" editok python:request.user.username=='anonymous' and
-           request.user.hasPermission('Web Registration')">
-
-<span tal:condition="python:not editok">
-You are not allowed to view this page.
-</span>
-
-<tal:block tal:condition="editok">
-<form method="POST" onSubmit="return submit_once()" enctype="multipart/form-data">
-<input type="hidden" name=":template" value="register">
-<input type="hidden" name=":required" value="username">
-<input type="hidden" name=":required" value="password">
-<input type="hidden" name=":required" value="address">
-
-<table class="form">
- <tr>
-  <th>Name</th>
-  <td tal:content="structure context/realname/field">realname</td>
- </tr>
- <tr>
-  <th>Login Name</th>
-  <td tal:content="structure context/username/field">username</td>
- </tr>
- <tr>
-  <th>Login Password</th>
-  <td tal:content="structure context/password/field">password</td>
- </tr>
- <tr>
-  <th>Confirm Password</th>
-  <td tal:content="structure context/password/confirm">password</td>
- </tr>
- <tr tal:condition="python:request.user.hasPermission('Web Roles')">
-  <th>Roles</th>
-  <td tal:condition="exists:item"
-      tal:content="structure context/roles/field">roles</td>
-  <td tal:condition="not:exists:item">
-   <input name="roles" tal:attributes="value db/config/NEW_WEB_USER_ROLES">
-  </td>
- </tr>
- <tr>
-  <th>Phone</th>
-  <td tal:content="structure context/phone/field">phone</td>
- </tr>
- <tr>
-  <th>Organisation</th>
-  <td tal:content="structure context/organisation/field">organisation</td>
- </tr>
- <tr>
-  <th>E-mail address</th>
-  <td tal:content="structure context/address/field">address</td>
- </tr>
- <tr>
-  <th>Alternate E-mail addresses<br>One address per line</th>
-  <td tal:content="structure context/alternate_addresses/multiline">alternate_addresses</td>
- </tr>
-
- <tr>
-  <td>&nbsp;</td>
-  <td>
-   <input type="hidden" name=":action" value="register">
-   <input type="submit" name="submit" value="Register">
-  </td>
- </tr>
-</table>
-</form>
-
-</tal:block>
-
-</tal:block>
-
-</td>
-
-</tal:block>
diff --git a/roundup/templates/classic/html/user.rego_progress b/roundup/templates/classic/html/user.rego_progress
deleted file mode 100644 (file)
index 95b1412..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- dollarId: issue.index,v 1.2 2001/07/29 04:07:37 richard Exp dollar-->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title">List of issues</title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h1>Registration in progress...</h1>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<p>You will shortly receive an email to confirm your registration. To
-complete the registration process, visit the link indicated in the
-email.
-</p>
-
-</td>
-</tal:block>
-
diff --git a/roundup/templates/classic/interfaces.py b/roundup/templates/classic/interfaces.py
deleted file mode 100644 (file)
index 82fd85f..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
-# This module is free software, and you may redistribute it and/or modify
-# under the same terms as Python, so long as this copyright message and
-# disclaimer are retained in their original form.
-#
-# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
-# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
-# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-# $Id: interfaces.py,v 1.16 2002-10-11 01:26:43 richard Exp $
-
-from roundup import mailgw 
-from roundup.cgi import client
-
-class Client(client.Client): 
-    ''' derives basic CGI implementation from the standard module, 
-        with any specific extensions 
-    ''' 
-    pass
-
-class TemplatingUtils:
-    ''' Methods implemented on this class will be available to HTML templates
-        through the 'utils' variable.
-    '''
-    pass
-
-class MailGW(mailgw.MailGW): 
-    ''' derives basic mail gateway implementation from the standard module, 
-        with any specific extensions 
-    ''' 
-    pass
-
-# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/templates/minimal/.cvsignore b/roundup/templates/minimal/.cvsignore
deleted file mode 100644 (file)
index d90d51d..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-*.pyc
-*.pyo
-htmlbase.py
-*.cover
diff --git a/roundup/templates/minimal/__init__.py b/roundup/templates/minimal/__init__.py
deleted file mode 100644 (file)
index 28e7663..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
-# This module is free software, and you may redistribute it and/or modify
-# under the same terms as Python, so long as this copyright message and
-# disclaimer are retained in their original form.
-#
-# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
-# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
-# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-# $Id: __init__.py,v 1.1 2002-09-26 04:15:07 richard Exp $
-
-import config
-from dbinit import open, init
-from interfaces import Client, MailGW
-
-# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/templates/minimal/config.py b/roundup/templates/minimal/config.py
deleted file mode 100644 (file)
index f047fa1..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#
-# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
-# This module is free software, and you may redistribute it and/or modify
-# under the same terms as Python, so long as this copyright message and
-# disclaimer are retained in their original form.
-#
-# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
-# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
-# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-# $Id: config.py,v 1.5 2003-01-12 00:41:27 richard Exp $
-
-import os
-
-# roundup home is this package's directory
-TRACKER_HOME=os.path.split(__file__)[0]
-
-# The SMTP mail host that roundup will use to send mail
-MAILHOST = 'localhost'
-
-# The domain name used for email addresses.
-MAIL_DOMAIN = 'your.tracker.email.domain.example'
-
-# This is the directory that the database is going to be stored in
-DATABASE = os.path.join(TRACKER_HOME, 'db')
-
-# This is the directory that the HTML templates reside in
-TEMPLATES = os.path.join(TRACKER_HOME, 'html')
-
-# A descriptive name for your roundup instance
-TRACKER_NAME = 'Roundup issue tracker'
-
-# 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. 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 = ""
-
-# 
-# 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'
-
-# Send nosy messages to the author of the message
-MESSAGES_TO_AUTHOR = 'no'           # either 'yes' or 'no'
-
-# Does the author of a message get placed on the nosy list automatically?
-# If 'new' is used, then the author will only be added when a message
-# creates a new issue. If 'yes', then the author will be added on followups
-# too. If 'no', they're never added to the nosy.
-ADD_AUTHOR_TO_NOSY = 'new'          # one of 'yes', 'no', 'new'
-
-# Do the recipients (To:, Cc:) of a message get placed on the nosy list?
-# If 'new' is used, then the recipients will only be added when a message
-# creates a new issue. If 'yes', then the recipients will be added on followups
-# too. If 'no', they're never added to the nosy.
-ADD_RECIPIENTS_TO_NOSY = 'new'      # either 'yes', 'no', 'new'
-
-# Where to place the email signature
-EMAIL_SIGNATURE_POSITION = 'bottom' # one of 'top', 'bottom', 'none'
-
-# Keep email citations when accepting messages. Setting this to "no" strips
-# out "quoted" text from the message. Signatures are also stripped.
-EMAIL_KEEP_QUOTED_TEXT = 'yes'      # either 'yes' or 'no'
-
-# Preserve the email body as is - that is, keep the citations _and_
-# signatures.
-EMAIL_LEAVE_BODY_UNCHANGED = 'no'   # either 'yes' or 'no'
-
-# Default class to use in the mailgw if one isn't supplied in email
-# subjects. To disable, comment out the variable below or leave it blank.
-# Examples:
-MAIL_DEFAULT_CLASS = 'issue'   # use "issue" class by default
-#MAIL_DEFAULT_CLASS = ''        # disable (or just comment the var out)
-
-# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/templates/minimal/dbinit.py b/roundup/templates/minimal/dbinit.py
deleted file mode 100644 (file)
index 4801f85..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-#
-# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
-# This module is free software, and you may redistribute it and/or modify
-# under the same terms as Python, so long as this copyright message and
-# disclaimer are retained in their original form.
-#
-# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
-# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
-# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-# $Id: dbinit.py,v 1.3 2002-10-10 07:17:39 richard Exp $
-
-import os
-
-import config
-from select_db import Database, Class, FileClass, IssueClass
-
-def open(name=None):
-    ''' as from the roundupdb method openDB 
-    ''' 
-    from roundup.hyperdb import String, Password, Date, Link, Multilink
-    from roundup.hyperdb import Interval, Boolean, Number
-
-    # open the database
-    db = Database(config, name)
-
-    #
-    # Now initialise the schema. Must do this each time the database is
-    # opened.
-    #
-
-    # The "Minimal" template gets only one class, the required "user"
-    # class. That's it. And even that has the bare minimum of properties.
-
-    # Note: roles is a comma-separated string of Role names
-    user = Class(db, "user", username=String(), password=Password(),
-        address=String(), alternate_addresses=String(), roles=String())
-    user.setkey("username")
-
-    # add any additional database schema configuration here
-
-    #
-    # SECURITY SETTINGS
-    #
-    # new permissions for this schema
-    for cl in ('user', ):
-        db.security.addPermission(name="Edit", klass=cl,
-            description="User is allowed to edit "+cl)
-        db.security.addPermission(name="View", klass=cl,
-            description="User is allowed to access "+cl)
-
-    # and give the regular users access to the web and email interface
-    p = db.security.getPermission('Web Access')
-    db.security.addPermissionToRole('User', p)
-    p = db.security.getPermission('Email Access')
-    db.security.addPermissionToRole('User', p)
-
-    # May users view other user information? Comment these lines out
-    # if you don't want them to
-    p = db.security.getPermission('View', 'user')
-    db.security.addPermissionToRole('User', p)
-
-    # Assign the appropriate permissions to the anonymous user's Anonymous
-    # Role. Choices here are:
-    # - Allow anonymous users to register through the web
-    p = db.security.getPermission('Web Registration')
-    db.security.addPermissionToRole('Anonymous', p)
-    # - Allow anonymous (new) users to register through the email gateway
-    p = db.security.getPermission('Email Registration')
-    db.security.addPermissionToRole('Anonymous', p)
-
-    import detectors
-    detectors.init(db)
-
-    # schema is set up - run any post-initialisation
-    db.post_init()
-    return db
-def init(adminpw): 
-    ''' as from the roundupdb method initDB 
-    Open the new database, and add new nodes - used for initialisation. You
-    can edit this before running the "roundup-admin initialise" command to
-    change the initial database entries.
-    ''' 
-    dbdir = os.path.join(config.DATABASE, 'files')
-    if not os.path.isdir(dbdir):
-        os.makedirs(dbdir)
-
-    db = open("admin")
-    db.clear()
-
-    # create the two default users
-    user = db.getclass('user')
-    user.create(username="admin", password=adminpw,
-        address=config.ADMIN_EMAIL, roles='Admin')
-    user.create(username="anonymous", roles='Anonymous')
-
-    # add any additional database create steps here - but only if you
-    # haven't initialised the database with the admin "initialise" command
-
-    db.commit()
-
-# vim: set filetype=python ts=4 sw=4 et si
-
diff --git a/roundup/templates/minimal/detectors/.cvsignore b/roundup/templates/minimal/detectors/.cvsignore
deleted file mode 100644 (file)
index 4162d5e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-*.pyc
-*.pyo
-*.cover
diff --git a/roundup/templates/minimal/detectors/__init__.py b/roundup/templates/minimal/detectors/__init__.py
deleted file mode 100644 (file)
index 9ae5e06..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
-# This module is free software, and you may redistribute it and/or modify
-# under the same terms as Python, so long as this copyright message and
-# disclaimer are retained in their original form.
-#
-# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
-# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
-# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-#$Id: __init__.py,v 1.2 2003-02-20 07:04:55 richard Exp $
-
-import sys, os, imp
-
-def init(db):
-    ''' execute the init functions of all the modules in this directory
-    '''
-    this_dir = os.path.split(__file__)[0]
-    for file in os.listdir(this_dir):
-        path = os.path.join(this_dir, file)
-        name, ext = os.path.splitext(file)
-        if name == '__init__':
-            continue
-        if ext == '.py':
-            module = imp.load_module(name, open(path), file,
-                ('.py', 'r', imp.PY_SOURCE))
-            print (name, open(path), file, module)
-            module.init(db)
-
-# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/templates/minimal/html/_generic.help b/roundup/templates/minimal/html/_generic.help
deleted file mode 100644 (file)
index ff4c7a3..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8;">
-<link rel="stylesheet" type="text/css" href="_file/style.css">
-</head>
-<body class="body" marginwidth="0" marginheight="0">
-
-<table class="classhelp"
-       tal:define="props python:request.form['properties'].value.split(',')">
-<tr><th tal:repeat="prop props" tal:content="prop"></th></tr>
-<tr tal:repeat="item context/list">
- <td tal:repeat="prop props" tal:content="python:item[prop]"></td>
-</tr>
-</table>
-
-</body>
diff --git a/roundup/templates/minimal/html/_generic.index b/roundup/templates/minimal/html/_generic.index
deleted file mode 100644 (file)
index f21b5d2..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-<!-- dollarId: issue.index,v 1.2 2001/07/29 04:07:37 richard Exp dollar-->
-
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title"
-       tal:content="python:context._classname.capitalize()+' editing'"></title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2 tal:content="python:context._classname.capitalize()+' editing'"></h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
-You are not allowed to view this page.
-</span>
-
-<tal:block tal:condition="context/is_edit_ok">
-<p class="form-help">
- You may edit the contents of the <span tal:replace="request/classname" />
- class using this form. Commas, newlines and double quotes (") must be
- handled delicately. You may include commas and newlines by enclosing the
- values in double-quotes ("). Double quotes themselves must be quoted by
- doubling ("").
-</p>
-
-<p class="form-help">
- Multilink properties have their multiple values colon (":") separated 
- (... ,"one:two:three", ...)
-</p>
-
-<p class="form-help">
- Remove entries by deleting their line. Add new entries by appending
- them to the table - put an X in the id column.
-</p>
-
-<form onSubmit="return submit_once()" method="POST">
-<textarea rows="15" cols="60" name="rows" tal:content="context/csv"></textarea>
-<br>
-<input type="hidden" name=":action" value="editCSV">
-<input type="submit" value="Edit Items">
-</form>
-</tal:block>
-
-<tal:block tal:condition="context/is_only_view_ok">
-view ok
-</tal:block>
-
-</td>
-
-</tal:block>
diff --git a/roundup/templates/minimal/html/_generic.item b/roundup/templates/minimal/html/_generic.item
deleted file mode 100644 (file)
index a9d2e85..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title"
-       tal:content="python:context._classname.capitalize()+' editing'"></title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2 tal:content="python:context._classname.capitalize()+' editing'"></h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
-You are not allowed to view this page.
-</span>
-
-<form method="POST" onSubmit="return submit_once()"
-      enctype="multipart/form-data" tal:condition="context/is_edit_ok">
-
-<input type="hidden" name=":template" value="item">
-<input type="hidden" name=":required" value="title">
-
-<table class="form">
-
-<tr tal:repeat="prop python:db[context._classname].properties()">
- <tal:block tal:condition="python:prop._name not in ('id', 'creator',
-                                  'creation', 'activity')">
-  <th tal:content="prop/_name"></th>
-  <td tal:content="structure python:context[prop._name].field()"></td>
- </tal:block>
-</tr>
-<tr>
- <td>&nbsp;</td>
- <td colspan=3 tal:content="structure context/submit">
-  submit button will go here
- </td>
-</tr>
-</table>
-
-</form>
-
-<table class="form" tal:condition="context/is_only_view_ok">
-
-<tr tal:repeat="prop python:db[context._classname].properties()">
- <tal:block tal:condition="python:prop._name not in ('id', 'creator',
-                                  'creation', 'activity')">
-  <th tal:content="prop/_name"></th>
-  <td tal:content="structure python:context[prop._name].field()"></td>
- </tal:block>
-</tr>
-</table>
-
-
-<tal:block tal:condition="python:context.id and context.is_view_ok()">
- <tal:block tal:replace="structure context/history" />
-</tal:block>
-
-</td>
-
-</tal:block>
diff --git a/roundup/templates/minimal/html/home b/roundup/templates/minimal/html/home
deleted file mode 100644 (file)
index acf6023..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title">Tracker home</title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>Tracker home</h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<!--
- This is the default body that is displayed when people visit the
- tracker. The tag below lists the currently open issues. You may
- replace it with a greeting message, or a different list of issues or
- whatever. It's a good idea to have the issues on the front page though
--->
-
-<tal:block tal:define="anon python:request.user.username == 'anonymous'">
-<p tal:condition="not:anon" class="help">
-Please select from one of the menu options on the right.
-</p>
-<p tal:condition="anon" class="help">
-Please log in or register.
-</p>
-</tal:block>
-
-</td>
-</tal:block>
diff --git a/roundup/templates/minimal/html/home.classlist b/roundup/templates/minimal/html/home.classlist
deleted file mode 100644 (file)
index 0b5a244..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title">List of classes</title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>List of classes</h2>
-</td>
-<td class="content" metal:fill-slot="content">
-<table class="classlist">
-
-<tal:block tal:repeat="cl db/classes">
- <tr>
-  <th class="header" colspan="2" align="left">
-   <a tal:attributes="href string:${cl/classname}"
-      tal:content="python:cl.classname.capitalize()">classname</a>
-  </th>
- </tr>
- <tr tal:repeat="prop cl/properties">
-  <th tal:content="prop/_name">name</th>
-  <td tal:content="prop/_prop">type</td>
- </tr>
-</tal:block>
-
-</table>
-</td>
-
-</tal:block>
diff --git a/roundup/templates/minimal/html/page b/roundup/templates/minimal/html/page
deleted file mode 100644 (file)
index 219a52a..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-<html metal:define-macro="icing">
-<head>
-<title metal:define-slot="head_title">title goes here</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8;">
-
-<link rel="stylesheet" type="text/css" href="_file/style.css">
-
-<script tal:replace="structure request/base_javascript">
-</script>
-
-</head>
-<body class="body" marginwidth="0" marginheight="0">
-
-<table class="body">
-
-<tr>
- <td class="page-header-left">&nbsp;</td>
- <td class="page-header-top" metal:define-slot="body_title"><h2>name</h2></td>
-</tr>
-
-<tr>
- <td rowspan="2" valign="top" nowrap class="sidebar">
-  <p class="userblock" tal:condition="python:request.user.username=='anonymous'">
-   <form method="POST" action="">
-    <input size="10" name="__login_name"><br>
-    <input size="10" type="password" name="__login_password"><br>
-    <input type="submit" name=":action" value="login">
-    <span tal:replace="structure request/indexargs_form" />
-   </form>
-   <a href="user?:template=register">Register</a>
-  </p>
-
-  <p class="userblock" tal:condition="python:request.user.username != 'anonymous'">
-   <b>Hello,</b><br><b tal:content="request/user/username">username</b><br>
-   <a tal:attributes="href string:user${request/user/id}">My Details</a><br>
-   <a tal:attributes="href python:request.indexargs_href('',
-       {':action':'logout'})">Logout</a>
-  </p>
-
-  <p class="classblock"
-       tal:condition="python:request.user.username != 'anonymous'">
-   <b>Administration</b><br>
-   <a tal:condition="python:request.user.hasPermission('Edit', None)"
-      href="home?:template=classlist">Class List</a><br>
-   <a tal:condition="python:request.user.hasPermission('View', 'user')
-                            or request.user.hasPermission('Edit', 'user')"
-      href="user" >User List</a><br>
-   <a tal:condition="python:request.user.hasPermission('Edit', 'user')"
-      href="user?:template=item">Add User</a>
-  </p>
- </td>
- <td>
-  <p tal:condition="options/error_message | nothing" class="error-message"
-     tal:repeat="m options/error_message" tal:content="structure m">error</p>
-  <p tal:condition="options/ok_message | nothing" class="ok-message"
-     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
- </td>
-</tr>
-<tr>
- <td class="content" metal:define-slot="content">Page content goes here</td>
-</tr>
-
-</table>
-
-<pre tal:condition="request/form/debug | nothing" tal:content="request">
-</pre>
-
-</body>
-</html>
diff --git a/roundup/templates/minimal/html/style.css b/roundup/templates/minimal/html/style.css
deleted file mode 100644 (file)
index 8aad458..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-/* main page styles */
-body.body {
-  font-family: sans-serif, Arial, Helvetica;
-  color: #333333;
-}
-a[href]:hover { color:blue; text-decoration: underline; }
-a[href]:link { color:blue; text-decoration: none; }
-a[href] { color:blue; text-decoration: none; }
-
-table.body {
-  border: 0;
-  padding: 0;
-  border-spacing: 0px;
-  border-collapse: separate;
-}
-
-td.page-header-left {
-  padding: 5px;
-  border-bottom: 1px solid #444444;
-}
-
-td.page-header-top {
-  padding: 5px;
-  border-bottom: 1px solid #444444;
-}
-
-td.sidebar {
-  padding: 1 0 0 1;
-}
-
-td.sidebar p.classblock {
-  padding: 0 5 0 5;
-  margin: 1 1 1 1;
-  border: 1px solid #444444;
-  background-color: #eeeeee;
-}
-
-td.sidebar p.userblock {
-  padding: 0 5 0 5;
-  margin: 1 1 1 1;
-  border: 1px solid #444444;
-  background-color: #eeeeff;
-}
-
-td.content {
-  padding: 1 5 1 5;
-  vertical-align: top;
-  width: 100%;
-}
-
-p.ok-message {
-  background-color: #22bb22;
-  padding: 5 5 5 5;
-  color: white;
-  font-weight: bold;
-}
-p.error-message {
-  background-color: #bb2222;
-  padding: 5 5 5 5;
-  color: white;
-  font-weight: bold;
-}
-
-
-/* style for forms */
-table.form {
-  padding: 2;
-  border-spacing: 0px;
-  border-collapse: separate;
-}
-
-table.form th {
-  font-weight: bold;
-  color: #333388;
-  text-align: right;
-  vertical-align: top;
-}
-
-table.form th.header {
-  font-weight: bold;
-  color: #333388;
-  background-color: #eeeeff;
-  text-align: left;
-}
-
-table.form td {
-  color: #333333;
-  empty-cells: show;
-  vertical-align: top;
-}
-
-table.form td.optional {
-  font-weight: bold;
-  font-style: italic;
-}
-
-table.form td.html {
-  color: #777777;
-}
-
-/* style for lists */
-table.list {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.list th {
-  padding: 0 4 0 4;
-  color: #404070;
-  background-color: #eeeeff;
-  border-right: 1px solid #404070;
-  border-top: 1px solid #404070;
-  border-bottom: 1px solid #404070;
-  vertical-align: top;
-  empty-cells: show;
-}
-table.list th a[href]:hover { color: #404070 }
-table.list th a[href]:link { color: #404070 }
-table.list th a[href] { color: #404070 }
-table.list th.group {
-  background-color: #f4f4ff;
-  text-align: center;
-}
-
-table.list td {
-  padding: 0 4 0 4;
-  border: 0 2 0 2;
-  border-right: 1px solid #404070;
-  color: #404070;
-  background-color: white;
-  vertical-align: top;
-  empty-cells: show;
-}
-
-table.list tr.normal td {
-  background-color: white;
-}
-
-table.list tr.alt td {
-  background-color: #efefef;
-}
-
-table.list td:first-child {
-  border-left: 1px solid #404070;
-  border-right: 1px solid #404070;
-}
-
-table.list th:first-child {
-  border-left: 1px solid #404070;
-  border-right: 1px solid #404070;
-}
-
-table.list tr.navigation th {
-  text-align: right;
-}
-table.list tr.navigation th:first-child {
-  border-right: none;
-  text-align: left;
-}
-
-
-/* style for message displays */
-table.messages {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.messages th.header{
-  padding-top: 10px;
-  border-bottom: 1px solid gray;
-  font-weight: bold;
-  background-color: white;
-  color: #707040;
-}
-
-table.messages th {
-  font-weight: bold;
-  color: black;
-  text-align: left;
-  border-bottom: 1px solid #afafaf;
-}
-
-table.messages td {
-  font-family: monospace;
-  background-color: #efefef;
-  border-bottom: 1px solid #afafaf;
-  color: black;
-  empty-cells: show;
-  border-right: 1px solid #afafaf;
-  vertical-align: top;
-  padding: 2 5 2 5;
-}
-
-table.messages td:first-child {
-  border-left: 1px solid #afafaf;
-  border-right: 1px solid #afafaf;
-}
-
-/* style for file displays */
-table.files {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.files th.header{
-  padding-top: 10px;
-  border-bottom: 1px solid gray;
-  font-weight: bold;
-  background-color: white;
-  color: #707040;
-}
-
-table.files th {
-  border-bottom: 1px solid #afafaf;
-  font-weight: bold;
-  text-align: left;
-}
-
-table.files td {
-  font-family: monospace;
-  empty-cells: show;
-}
-
-/* style for history displays */
-table.history {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.history th.header{
-  padding-top: 10px;
-  border-bottom: 1px solid gray;
-  font-weight: bold;
-  background-color: white;
-  color: #707040;
-  font-size: 100%;
-}
-
-table.history th {
-  border-bottom: 1px solid #afafaf;
-  font-weight: bold;
-  text-align: left;
-  font-size: 90%;
-}
-
-table.history td {
-  font-size: 90%;
-  vertical-align: top;
-  empty-cells: show;
-}
-
-
-/* style for class list */
-table.classlist {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.classlist th.header{
-  padding-top: 10px;
-  border-bottom: 1px solid gray;
-  font-weight: bold;
-  background-color: white;
-  color: #707040;
-}
-
-table.classlist th {
-  font-weight: bold;
-  text-align: left;
-}
-
-
-/* style for class help display */
-table.classhelp {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.classhelp th {
-  font-weight: bold;
-  text-align: left;
-  color: #707040;
-}
-
-table.classhelp td {
-  padding: 2 2 2 2;
-  border: 1px solid black;
-  text-align: left;
-  vertical-align: top;
-  empty-cells: show;
-}
-
-
-/* style for "other" displays */
-table.otherinfo {
-  border-spacing: 0px;
-  border-collapse: separate;
-  width: 100%;
-}
-
-table.otherinfo th.header{
-  padding-top: 10px;
-  border-bottom: 1px solid gray;
-  font-weight: bold;
-  background-color: white;
-  color: #707040;
-}
-
-table.otherinfo th {
-  border-bottom: 1px solid #afafaf;
-  font-weight: bold;
-  text-align: left;
-}
diff --git a/roundup/templates/minimal/html/user.index b/roundup/templates/minimal/html/user.index
deleted file mode 100644 (file)
index 30312c2..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<!-- dollarId: user.index,v 1.3 2002/07/09 05:29:51 richard Exp dollar-->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title">User listing</title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>User listing</h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="not:context/is_view_ok">
-You are not allowed to view this page.
-</span>
-
-<table width="100%" tal:condition="context/is_view_ok" class="list">
-<tr>
- <th>Username</th>
- <th>Email address</th>
-</tr>
-<tr tal:repeat="user context/list"
-    tal:attributes="class python:['normal', 'alt'][repeat['user'].index%6/3]">
- <td>
-  <a tal:attributes="href string:user${user/id}"
-     tal:content="user/username">username</a>
- </td>
- <td tal:content="python:user.address.email()">address</td>
-</tr>
-</table>
-</td>
-
-</tal:block>
diff --git a/roundup/templates/minimal/html/user.item b/roundup/templates/minimal/html/user.item
deleted file mode 100644 (file)
index 642b776..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title">User editing</title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2>User editing</h2>
-</td>
-<td class="content" metal:fill-slot="content">
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
-You are not allowed to view this page.
-</span>
-
-<form method="POST" onSubmit="return submit_once()"
-      enctype="multipart/form-data" tal:condition="context/is_edit_ok">
-
-<input type="hidden" name=":required" value="username,address">
-
-<table class="form">
- <tr>
-  <th>Login Name</th>
-  <td tal:content="structure context/username/field">username</td>
- </tr>
- <tr>
-  <th>Login Password</th>
-  <td tal:content="structure context/password/field">password</td>
- </tr>
- <tr>
-  <th>Confirm Password</th>
-  <td tal:content="structure context/password/confirm">password</td>
- </tr>
- <tr tal:condition="python:request.user.hasPermission('Web Roles')">
-  <th>Roles</th>
-  <td tal:condition="context/id"
-      tal:content="structure context/roles/field">roles</td>
-  <td tal:condition="not:context/id">
-   <input name="roles" tal:attributes="value db/config/NEW_WEB_USER_ROLES">
-  </td>
- </tr>
- <tr>
-  <th>E-mail address</th>
-  <td tal:content="structure context/address/field">address</td>
- </tr>
- <tr>
-  <th>Alternate E-mail addresses<br>One address per line</th>
-  <td tal:content="structure context/alternate_addresses/multiline">alternate_addresses</td>
- </tr>
-
- <tr>
-  <td>&nbsp;</td>
-  <td tal:content="structure context/submit">submit button here</td>
- </tr>
-</table>
-</form>
-
-<table class="form" tal:condition="context/is_only_view_ok">
- <tr>
-  <th>Login Name</th>
-  <td tal:content="context/username">username</td>
- </tr>
- <tr>
-  <th>E-mail address</th>
-  <td tal:content="context/address/email">address</td>
- </tr>
-</table>
-
-<tal:block tal:condition="python:context.id and context.is_view_ok()"
-           tal:replace="structure context/history" />
-
-</td>
-
-</tal:block>
diff --git a/roundup/templates/minimal/html/user.register b/roundup/templates/minimal/html/user.register
deleted file mode 100644 (file)
index a226413..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title"
-       tal:content="string:Registering with ${db/config/TRACKER_NAME}"></title>
-<td class="page-header-top" metal:fill-slot="body_title">
- <h2 tal:content="string:Registering with ${db/config/TRACKER_NAME}"></h2>
-</td>
-<td class="content" metal:fill-slot="content">
-
-<tal:block tal:define=" editok python:request.user.username=='anonymous' and
-           request.user.hasPermission('Web Registration')">
-
-<span tal:condition="python:not editok">
-You are not allowed to view this page.
-</span>
-
-<tal:block tal:condition="editok">
-<form method="POST" onSubmit="return submit_once()" enctype="multipart/form-data">
-<input type="hidden" name=":template" value="register">
-<input type="hidden" name=":required" value="username">
-<input type="hidden" name=":required" value="password">
-<input type="hidden" name=":required" value="address">
-
-<table class="form">
- <tr>
-  <th>Name</th>
-  <td tal:content="structure context/realname/field">realname</td>
- </tr>
- <tr>
-  <th>Login Name</th>
-  <td tal:content="structure context/username/field">username</td>
- </tr>
- <tr>
-  <th>Login Password</th>
-  <td tal:content="structure context/password/field">password</td>
- </tr>
- <tr>
-  <th>Confirm Password</th>
-  <td tal:content="structure context/password/confirm">password</td>
- </tr>
- <tr tal:condition="python:request.user.hasPermission('Web Roles')">
-  <th>Roles</th>
-  <td tal:condition="exists:item"
-      tal:content="structure context/roles/field">roles</td>
-  <td tal:condition="not:exists:item">
-   <input name="roles" tal:attributes="value db/config/NEW_WEB_USER_ROLES">
-  </td>
- </tr>
- <tr>
-  <th>Phone</th>
-  <td tal:content="structure context/phone/field">phone</td>
- </tr>
- <tr>
-  <th>Organisation</th>
-  <td tal:content="structure context/organisation/field">organisation</td>
- </tr>
- <tr>
-  <th>E-mail address</th>
-  <td tal:content="structure context/address/field">address</td>
- </tr>
- <tr>
-  <th>Alternate E-mail addresses<br>One address per line</th>
-  <td tal:content="structure context/alternate_addresses/multiline">alternate_addresses</td>
- </tr>
-
- <tr>
-  <td>&nbsp;</td>
-  <td>
-   <input type="hidden" name=":action" value="register">
-   <input type="submit" name="submit" value="Register">
-  </td>
- </tr>
-</table>
-</form>
-
-</tal:block>
-
-</tal:block>
-
-</td>
-
-</tal:block>
diff --git a/roundup/templates/minimal/interfaces.py b/roundup/templates/minimal/interfaces.py
deleted file mode 100644 (file)
index 489699a..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
-# This module is free software, and you may redistribute it and/or modify
-# under the same terms as Python, so long as this copyright message and
-# disclaimer are retained in their original form.
-#
-# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
-# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
-# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
-# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-# $Id: interfaces.py,v 1.2 2002-10-11 01:26:43 richard Exp $
-
-from roundup import mailgw 
-from roundup.cgi import client
-
-class Client(client.Client): 
-    ''' derives basic CGI implementation from the standard module, 
-        with any specific extensions 
-    ''' 
-    pass
-
-class TemplatingUtils:
-    ''' Methods implemented on this class will be available to HTML templates
-        through the 'utils' variable.
-    '''
-    pass
-
-class MailGW(mailgw.MailGW): 
-    ''' derives basic mail gateway implementation from the standard module, 
-        with any specific extensions 
-    ''' 
-    pass
-
-# vim: set filetype=python ts=4 sw=4 et si
index 08bfe4407288dfb82e94ee563a6e4dc1cbcff83e..bb1d8a3c7cd99eab0da95e587528b6ac13ad270b 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -16,7 +16,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: setup.py,v 1.47 2003-04-17 01:14:10 richard Exp $
+# $Id: setup.py,v 1.48 2003-04-17 03:37:57 richard Exp $
 
 from distutils.core import setup, Extension
 from distutils.util import get_platform
@@ -31,8 +31,6 @@ if sys.version < '2.2.3':
     DistributionMetadata.classifiers = None
     DistributionMetadata.download_url = None
 
-from roundup.templates.builder import makeHtmlBase
-
 
 #############################################################################
 ### Build script files
@@ -124,26 +122,11 @@ def scriptname(path):
 ### Main setup stuff
 #############################################################################
 
-def isTemplateDir(dir):
-    return dir[0] != '.' and dir != 'CVS' and os.path.isdir(dir) \
-        and os.path.isfile(os.path.join(dir, '__init__.py'))
-
-# use that function to list all the templates
-templates = map(os.path.basename, filter(isTemplateDir,
-    glob(os.path.join('roundup', 'templates', '*'))))
-
-def buildTemplates():
-    for template in templates:
-        tdir = os.path.join('roundup', 'templates', template)
-        makeHtmlBase(tdir)
-
 def main():
     # build list of scripts from their implementation modules
     roundup_scripts = map(scriptname, glob('roundup/scripts/[!_]*.py'))
 
     # template munching
-    templates = map(os.path.basename, filter(isTemplateDir,
-        glob(os.path.join('roundup', 'templates', '*'))))
     packagelist = [
         'roundup',
         'roundup.cgi',
@@ -151,8 +134,7 @@ def main():
         'roundup.cgi.TAL',
         'roundup.cgi.ZTUtils',
         'roundup.backends',
-        'roundup.scripts',
-        'roundup.templates'
+        'roundup.scripts'
     ]
     installdatafiles = [
         ('share/roundup/cgi-bin', ['cgi-bin/roundup.cgi']),
@@ -163,23 +145,23 @@ def main():
         installdatafiles.append(('man/man1', ['doc/roundup-admin.1',
             'doc/roundup-mailgw.1', 'doc/roundup-server.1']))
 
-    # munge the template HTML into the htmlbase module
-    buildTemplates()
-
-    # add the templates to the setup packages and data files lists
-    for template in templates:
-        tdir = os.path.join('roundup', 'templates', template)
-
-        # add the template package and subpackage
-        packagelist.append('roundup.templates.%s' % template)
-        packagelist.append('roundup.templates.%s.detectors' % template)
-
+    # add the templates to the data files lists
+    from roundup.admin import listTemplates
+    templates = [t['path'] for t in listTemplates('.').values()]
+    for tdir in templates:
         # scan for data files
-        tfiles = glob(os.path.join(tdir, 'html', '*'))
-        tfiles = filter(os.path.isfile, tfiles)
-        installdatafiles.append(
-            ('share/roundup/templates/%s/html' % template, tfiles)
-        )
+        for idir in '. detectors html'.split():
+            idir = os.path.join(tdir, idir)
+            tfiles = []
+            for f in os.listdir(idir):
+                if f.startswith('.'):
+                    continue
+                ifile = os.path.join(idir, f)
+                if os.path.isfile(ifile):
+                    tfiles.append(ifile)
+            installdatafiles.append(
+                (os.path.join('share', 'roundup', idir), tfiles)
+            )
 
     # perform the setup action
     from roundup import __version__
@@ -233,7 +215,7 @@ def install_demo():
         if error.errno != errno.ENOENT:
             raise
     from roundup import init, instance, password
-    init.install(home, 'classic')
+    init.install(home, os.path.join('templates', 'classic'))
     # don't have email flying around
     os.remove(os.path.join(home, 'detectors', 'nosyreaction.py'))
     init.write_select_db(home, 'anydbm')
diff --git a/templates/classic/.cvsignore b/templates/classic/.cvsignore
new file mode 100644 (file)
index 0000000..d90d51d
--- /dev/null
@@ -0,0 +1,4 @@
+*.pyc
+*.pyo
+htmlbase.py
+*.cover
diff --git a/templates/classic/TEMPLATE-INFO.txt b/templates/classic/TEMPLATE-INFO.txt
new file mode 100644 (file)
index 0000000..1c20d54
--- /dev/null
@@ -0,0 +1,7 @@
+Name: classic
+Description: This is a generic issue tracker that may be used to track bugs,
+             feature requests, project issues or any number of other types
+             of issues. Most users of Roundup will find that this template
+             suits them, with perhaps a few customisations.
+Intended-For: All first-time Roundup users
+
diff --git a/templates/classic/__init__.py b/templates/classic/__init__.py
new file mode 100644 (file)
index 0000000..e566b54
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
+# This module is free software, and you may redistribute it and/or modify
+# under the same terms as Python, so long as this copyright message and
+# disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
+# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# 
+# $Id: __init__.py,v 1.1 2003-04-17 03:26:03 richard Exp $
+
+import config
+from dbinit import open, init
+from interfaces import Client, MailGW
+
+# vim: set filetype=python ts=4 sw=4 et si
diff --git a/templates/classic/config.py b/templates/classic/config.py
new file mode 100644 (file)
index 0000000..3c3df21
--- /dev/null
@@ -0,0 +1,100 @@
+#
+# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
+# This module is free software, and you may redistribute it and/or modify
+# under the same terms as Python, so long as this copyright message and
+# disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
+# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# 
+# $Id: config.py,v 1.1 2003-04-17 03:26:03 richard Exp $
+
+import os
+
+# roundup home is this package's directory
+TRACKER_HOME=os.path.split(__file__)[0]
+
+# The SMTP mail host that roundup will use to send mail
+MAILHOST = 'localhost'
+
+# The domain name used for email addresses.
+MAIL_DOMAIN = 'your.tracker.email.domain.example'
+
+# This is the directory that the database is going to be stored in
+DATABASE = os.path.join(TRACKER_HOME, 'db')
+
+# This is the directory that the HTML templates reside in
+TEMPLATES = os.path.join(TRACKER_HOME, 'html')
+
+# A descriptive name for your roundup instance
+TRACKER_NAME = 'Roundup issue tracker'
+
+# 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. 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'
+
+# Does the author of a message get placed on the nosy list automatically?
+# If 'new' is used, then the author will only be added when a message
+# creates a new issue. If 'yes', then the author will be added on followups
+# too. If 'no', they're never added to the nosy.
+ADD_AUTHOR_TO_NOSY = 'new'          # one of 'yes', 'no', 'new'
+
+# Do the recipients (To:, Cc:) of a message get placed on the nosy list?
+# If 'new' is used, then the recipients will only be added when a message
+# creates a new issue. If 'yes', then the recipients will be added on followups
+# too. If 'no', they're never added to the nosy.
+ADD_RECIPIENTS_TO_NOSY = 'new'      # either 'yes', 'no', 'new'
+
+# Where to place the email signature
+EMAIL_SIGNATURE_POSITION = 'bottom' # one of 'top', 'bottom', 'none'
+
+# Keep email citations when accepting messages. Setting this to "no" strips
+# out "quoted" text from the message. Signatures are also stripped.
+EMAIL_KEEP_QUOTED_TEXT = 'yes'      # either 'yes' or 'no'
+
+# Preserve the email body as is - that is, keep the citations _and_
+# signatures.
+EMAIL_LEAVE_BODY_UNCHANGED = 'no'   # either 'yes' or 'no'
+
+# Default class to use in the mailgw if one isn't supplied in email
+# subjects. To disable, comment out the variable below or leave it blank.
+# Examples:
+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'
+
+# vim: set filetype=python ts=4 sw=4 et si
diff --git a/templates/classic/dbinit.py b/templates/classic/dbinit.py
new file mode 100644 (file)
index 0000000..f7849ce
--- /dev/null
@@ -0,0 +1,203 @@
+#
+# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
+# This module is free software, and you may redistribute it and/or modify
+# under the same terms as Python, so long as this copyright message and
+# disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
+# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# 
+# $Id: dbinit.py,v 1.1 2003-04-17 03:26:03 richard Exp $
+
+import os
+
+import config
+from select_db import Database, Class, FileClass, IssueClass
+
+def open(name=None):
+    ''' as from the roundupdb method openDB 
+    ''' 
+    from roundup.hyperdb import String, Password, Date, Link, Multilink
+    from roundup.hyperdb import Interval, Boolean, Number
+
+    # open the database
+    db = Database(config, name)
+
+    #
+    # Now initialise the schema. Must do this each time the database is
+    # opened.
+    #
+
+    # Class automatically gets these properties:
+    #   creation = Date()
+    #   activity = Date()
+    #   creator = Link('user')
+    pri = Class(db, "priority", 
+                    name=String(), order=String())
+    pri.setkey("name")
+
+    stat = Class(db, "status", 
+                    name=String(), order=String())
+    stat.setkey("name")
+
+    keyword = Class(db, "keyword", 
+                    name=String())
+    keyword.setkey("name")
+    
+    query = Class(db, "query",
+                    klass=String(),     name=String(),
+                    url=String())
+    query.setkey("name")
+
+    # add any additional database schema configuration here
+    
+    # Note: roles is a comma-separated string of Role names
+    user = Class(db, "user", 
+                    username=String(),   password=Password(),
+                    address=String(),    realname=String(), 
+                    phone=String(),      organisation=String(),
+                    alternate_addresses=String(),
+                    queries=Multilink('query'), roles=String(),
+                    timezone=String())
+    user.setkey("username")
+
+    # FileClass automatically gets these properties:
+    #   content = String()    [saved to disk in <tracker home>/db/files/]
+    #   (it also gets the Class properties creation, activity and creator)
+    msg = FileClass(db, "msg", 
+                    author=Link("user", do_journal='no'),
+                    recipients=Multilink("user", do_journal='no'), 
+                    date=Date(),         summary=String(), 
+                    files=Multilink("file"),
+                    messageid=String(),  inreplyto=String())
+
+    file = FileClass(db, "file", 
+                    name=String(),       type=String())
+
+    # IssueClass automatically gets these properties:
+    #   title = String()
+    #   messages = Multilink("msg")
+    #   files = Multilink("file")
+    #   nosy = Multilink("user")
+    #   superseder = Multilink("issue")
+    #   (it also gets the Class properties creation, activity and creator)
+    issue = IssueClass(db, "issue", 
+                    assignedto=Link("user"), topic=Multilink("keyword"),
+                    priority=Link("priority"), status=Link("status"))
+
+    #
+    # SECURITY SETTINGS
+    #
+    # See the configuration and customisation document for information
+    # about security setup.
+    # Add new Permissions for this schema
+    for cl in 'issue', 'file', 'msg', 'user', 'query', 'keyword':
+        db.security.addPermission(name="Edit", klass=cl,
+            description="User is allowed to edit "+cl)
+        db.security.addPermission(name="View", klass=cl,
+            description="User is allowed to access "+cl)
+
+    # Assign the access and edit Permissions for issue, file and message
+    # to regular users now
+    for cl in 'issue', 'file', 'msg', 'query', 'keyword':
+        p = db.security.getPermission('View', cl)
+        db.security.addPermissionToRole('User', p)
+        p = db.security.getPermission('Edit', cl)
+        db.security.addPermissionToRole('User', p)
+
+    # and give the regular users access to the web and email interface
+    p = db.security.getPermission('Web Access')
+    db.security.addPermissionToRole('User', p)
+    p = db.security.getPermission('Email Access')
+    db.security.addPermissionToRole('User', p)
+
+    # May users view other user information? Comment these lines out
+    # if you don't want them to
+    p = db.security.getPermission('View', 'user')
+    db.security.addPermissionToRole('User', p)
+
+    # Assign the appropriate permissions to the anonymous user's Anonymous
+    # Role. Choices here are:
+    # - Allow anonymous users to register through the web
+    p = db.security.getPermission('Web Registration')
+    db.security.addPermissionToRole('Anonymous', p)
+    # - Allow anonymous (new) users to register through the email gateway
+    p = db.security.getPermission('Email Registration')
+    db.security.addPermissionToRole('Anonymous', p)
+    # - Allow anonymous users access to the "issue" class of data
+    #   Note: this also grants access to related information like files,
+    #         messages, statuses etc that are linked to issues
+    p = db.security.getPermission('View', 'issue')
+    db.security.addPermissionToRole('Anonymous', p)
+    # - Allow anonymous users access to edit the "issue" class of data
+    #   Note: this also grants access to create related information like
+    #         files and messages etc that are linked to issues
+    #p = db.security.getPermission('Edit', 'issue')
+    #db.security.addPermissionToRole('Anonymous', p)
+
+    # oh, g'wan, let anonymous access the web interface too
+    p = db.security.getPermission('Web Access')
+    db.security.addPermissionToRole('Anonymous', p)
+
+    import detectors
+    detectors.init(db)
+
+    # schema is set up - run any post-initialisation
+    db.post_init()
+    return db
+def init(adminpw): 
+    ''' as from the roundupdb method initDB 
+    Open the new database, and add new nodes - used for initialisation. You
+    can edit this before running the "roundup-admin initialise" command to
+    change the initial database entries.
+    ''' 
+    dbdir = os.path.join(config.DATABASE, 'files')
+    if not os.path.isdir(dbdir):
+        os.makedirs(dbdir)
+
+    db = open("admin")
+    db.clear()
+
+    #
+    # INITIAL PRIORITY AND STATUS VALUES
+    #
+    pri = db.getclass('priority')
+    pri.create(name="critical", order="1")
+    pri.create(name="urgent", order="2")
+    pri.create(name="bug", order="3")
+    pri.create(name="feature", order="4")
+    pri.create(name="wish", order="5")
+
+    stat = db.getclass('status')
+    stat.create(name="unread", order="1")
+    stat.create(name="deferred", order="2")
+    stat.create(name="chatting", order="3")
+    stat.create(name="need-eg", order="4")
+    stat.create(name="in-progress", order="5")
+    stat.create(name="testing", order="6")
+    stat.create(name="done-cbb", order="7")
+    stat.create(name="resolved", order="8")
+
+    # create the two default users
+    user = db.getclass('user')
+    user.create(username="admin", password=adminpw,
+        address=config.ADMIN_EMAIL, roles='Admin')
+    user.create(username="anonymous", roles='Anonymous')
+
+    # add any additional database create steps here - but only if you
+    # haven't initialised the database with the admin "initialise" command
+
+    db.commit()
+
+# vim: set filetype=python ts=4 sw=4 et si
+
diff --git a/templates/classic/detectors/.cvsignore b/templates/classic/detectors/.cvsignore
new file mode 100644 (file)
index 0000000..4162d5e
--- /dev/null
@@ -0,0 +1,3 @@
+*.pyc
+*.pyo
+*.cover
diff --git a/templates/classic/detectors/__init__.py b/templates/classic/detectors/__init__.py
new file mode 100644 (file)
index 0000000..ead90bb
--- /dev/null
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
+# This module is free software, and you may redistribute it and/or modify
+# under the same terms as Python, so long as this copyright message and
+# disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
+# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# 
+#$Id: __init__.py,v 1.1 2003-04-17 03:26:38 richard Exp $
+
+import sys, os, imp
+
+def init(db):
+    ''' execute the init functions of all the modules in this directory
+    '''
+    this_dir = os.path.split(__file__)[0]
+    for file in os.listdir(this_dir):
+        path = os.path.join(this_dir, file)
+        name, ext = os.path.splitext(file)
+        if name == '__init__':
+            continue
+        if ext == '.py':
+            module = imp.load_module(name, open(path), file,
+                ('.py', 'r', imp.PY_SOURCE))
+            module.init(db)
+
+# vim: set filetype=python ts=4 sw=4 et si
diff --git a/templates/classic/detectors/messagesummary.py b/templates/classic/detectors/messagesummary.py
new file mode 100644 (file)
index 0000000..2558213
--- /dev/null
@@ -0,0 +1,19 @@
+#$Id: messagesummary.py,v 1.1 2003-04-17 03:26:38 richard Exp $
+
+from roundup.mailgw import parseContent
+
+def summarygenerator(db, cl, nodeid, newvalues):
+    ''' If the message doesn't have a summary, make one for it.
+    '''
+    if newvalues.has_key('summary') or not newvalues.has_key('content'):
+        return
+
+    summary, content = parseContent(newvalues['content'], 1, 1)
+    newvalues['summary'] = summary
+
+
+def init(db):
+    # fire before changes are made
+    db.msg.audit('create', summarygenerator)
+
+# vim: set filetype=python ts=4 sw=4 et si
diff --git a/templates/classic/detectors/nosyreaction.py b/templates/classic/detectors/nosyreaction.py
new file mode 100644 (file)
index 0000000..2c29204
--- /dev/null
@@ -0,0 +1,142 @@
+#
+# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
+# This module is free software, and you may redistribute it and/or modify
+# under the same terms as Python, so long as this copyright message and
+# disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
+# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# 
+#$Id: nosyreaction.py,v 1.1 2003-04-17 03:26:38 richard Exp $
+
+from roundup import roundupdb, hyperdb
+
+def nosyreaction(db, cl, nodeid, oldvalues):
+    ''' A standard detector is provided that watches for additions to the
+        "messages" property.
+        
+        When a new message is added, the detector sends it to all the users on
+        the "nosy" list for the issue that are not already on the "recipients"
+        list of the message.
+        
+        Those users are then appended to the "recipients" property on the
+        message, so multiple copies of a message are never sent to the same
+        user.
+        
+        The journal recorded by the hyperdatabase on the "recipients" property
+        then provides a log of when the message was sent to whom. 
+    '''
+    # send a copy of all new messages to the nosy list
+    for msgid in determineNewMessages(cl, nodeid, oldvalues):
+        try:
+            cl.nosymessage(nodeid, msgid, oldvalues)
+        except roundupdb.MessageSendError, message:
+            raise roundupdb.DetectorError, message
+
+def determineNewMessages(cl, nodeid, oldvalues):
+    ''' Figure a list of the messages that are being added to the given
+        node in this transaction.
+    '''
+    messages = []
+    if oldvalues is None:
+        # the action was a create, so use all the messages in the create
+        messages = cl.get(nodeid, 'messages')
+    elif oldvalues.has_key('messages'):
+        # the action was a set (so adding new messages to an existing issue)
+        m = {}
+        for msgid in oldvalues['messages']:
+            m[msgid] = 1
+        messages = []
+        # figure which of the messages now on the issue weren't there before
+        for msgid in cl.get(nodeid, 'messages'):
+            if not m.has_key(msgid):
+                messages.append(msgid)
+    return messages
+
+def updatenosy(db, cl, nodeid, newvalues):
+    '''Update the nosy list for changes to the assignedto
+    '''
+    # nodeid will be None if this is a new node
+    current = {}
+    if nodeid is None:
+        ok = ('new', 'yes')
+    else:
+        ok = ('yes',)
+        # old node, get the current values from the node if they haven't
+        # changed
+        if not newvalues.has_key('nosy'):
+            nosy = cl.get(nodeid, 'nosy')
+            for value in nosy:
+                if not current.has_key(value):
+                    current[value] = 1
+
+    # if the nosy list changed in this transaction, init from the new value
+    if newvalues.has_key('nosy'):
+        nosy = newvalues.get('nosy', [])
+        for value in nosy:
+            if not db.hasnode('user', value):
+                continue
+            if not current.has_key(value):
+                current[value] = 1
+
+    # add assignedto(s) to the nosy list
+    if newvalues.has_key('assignedto') and newvalues['assignedto'] is not None:
+        propdef = cl.getprops()
+        if isinstance(propdef['assignedto'], hyperdb.Link):
+            assignedto_ids = [newvalues['assignedto']]
+        elif isinstance(propdef['assignedto'], hyperdb.Multilink):
+            assignedto_ids = newvalues['assignedto']
+        for assignedto_id in assignedto_ids:
+            if not current.has_key(assignedto_id):
+                current[assignedto_id] = 1
+
+    # see if there's any new messages - if so, possibly add the author and
+    # recipient to the nosy
+    if newvalues.has_key('messages'):
+        if nodeid is None:
+            ok = ('new', 'yes')
+            messages = newvalues['messages']
+        else:
+            ok = ('yes',)
+            # figure which of the messages now on the issue weren't
+            # there before - make sure we don't get a cached version!
+            oldmessages = cl.get(nodeid, 'messages', cache=0)
+            messages = []
+            for msgid in newvalues['messages']:
+                if msgid not in oldmessages:
+                    messages.append(msgid)
+
+        # configs for nosy modifications
+        add_author = getattr(db.config, 'ADD_AUTHOR_TO_NOSY', 'new')
+        add_recips = getattr(db.config, 'ADD_RECIPIENTS_TO_NOSY', 'new')
+
+        # now for each new message:
+        msg = db.msg
+        for msgid in messages:
+            if add_author in ok:
+                authid = msg.get(msgid, 'author')
+                current[authid] = 1
+
+            # add on the recipients of the message
+            if add_recips in ok:
+                for recipient in msg.get(msgid, 'recipients'):
+                    current[recipient] = 1
+
+    # that's it, save off the new nosy list
+    newvalues['nosy'] = current.keys()
+
+def init(db):
+    db.issue.react('create', nosyreaction)
+    db.issue.react('set', nosyreaction)
+    db.issue.audit('create', updatenosy)
+    db.issue.audit('set', updatenosy)
+
+# vim: set filetype=python ts=4 sw=4 et si
diff --git a/templates/classic/detectors/statusauditor.py b/templates/classic/detectors/statusauditor.py
new file mode 100644 (file)
index 0000000..05f1710
--- /dev/null
@@ -0,0 +1,78 @@
+# Copyright (c) 2002 ekit.com Inc (http://www.ekit-inc.com/)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+#   The above copyright notice and this permission notice shall be included in
+#   all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+#$Id: statusauditor.py,v 1.1 2003-04-17 03:26:38 richard Exp $
+
+def chatty(db, cl, nodeid, newvalues):
+    ''' If the issue is currently 'unread', 'resolved' or 'done-cbb', then set
+        it to 'chatting'
+    '''
+    # don't fire if there's no new message (ie. chat)
+    if not newvalues.has_key('messages'):
+        return
+    if newvalues['messages'] == cl.get(nodeid, 'messages', cache=0):
+        return
+
+    # get the chatting state ID
+    try:
+        chatting_id = db.status.lookup('chatting')
+    except KeyError:
+        # no chatting state, ignore all this stuff
+        return
+
+    # get the current value
+    current_status = cl.get(nodeid, 'status')
+
+    # see if there's an explicit change in this transaction
+    if newvalues.has_key('status') and newvalues['status'] != current_status:
+        # yep, skip
+        return
+
+    # determine the id of 'unread', 'resolved' and 'chatting'
+    fromstates = []
+    for state in 'unread resolved done-cbb'.split():
+        try:
+            fromstates.append(db.status.lookup(state))
+        except KeyError:
+            pass
+
+    # ok, there's no explicit change, so check if we are in a state that
+    # should be changed
+    if current_status in fromstates:
+        # yep, we're now chatting
+        newvalues['status'] = chatting_id
+
+
+def presetunread(db, cl, nodeid, newvalues):
+    ''' Make sure the status is set on new issues
+    '''
+    if newvalues.has_key('status') and newvalues['status']:
+        return
+
+    # ok, do it
+    newvalues['status'] = db.status.lookup('unread')
+
+
+def init(db):
+    # fire before changes are made
+    db.issue.audit('set', chatty)
+    db.issue.audit('create', presetunread)
+
+# vim: set filetype=python ts=4 sw=4 et si
diff --git a/templates/classic/html/_generic.help.html b/templates/classic/html/_generic.help.html
new file mode 100644 (file)
index 0000000..0749525
--- /dev/null
@@ -0,0 +1,91 @@
+<html>
+<head>
+<link rel="stylesheet" type="text/css" href="_file/style.css">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8;">
+<script language="JavaScript" 
+        tal:condition="python:request.form.has_key('property')"
+        tal:content="structure string:
+
+// this is the name of the field in the original form that we're working on
+field = '${request/form/property/value}';
+
+function listClose() {
+  window.close();
+}
+        
+function listClear() {
+  window.opener.document.itemSynopsis[field].value = '';
+}
+        
+function pick(opt) {
+  if (window.opener && !window.opener.closed) {
+    window.opener.document.itemSynopsis[field].value = opt;
+  }
+}
+        
+// add a value to the form field
+function add(opt) {
+  val = window.opener.document.itemSynopsis[field].value;
+  if (/^\s*$$/.test(val)) {
+    newval = opt;   // existing is all whitespace, so just replace
+  } else {
+    newval = val + ', ' + opt;
+  }
+  pick(newval);
+}
+        
+// remove a value from the form field
+function remove(opt) {
+  // ((opt(,\s*)?)|(,\s*opt))
+  replaceStr = new String('(('+opt+'(,\\s*)?)|(,\\s*'+opt+'))');
+  re = new RegExp(replaceStr);
+
+  str = window.opener.document.itemSynopsis[field].value;
+
+  // replace occurences with empty string
+  newstr = str.replace(re, '');
+  pick(newstr);
+}
+">
+</script>
+</head>
+
+<body class="body" marginwidth="0" marginheight="0">
+<form>
+<div style="padding:10px;text-align:center;">
+ <script language="javascript">
+  // put up a 'reset' button if the field has values when we pop up this window
+
+  // this is the name of the field in the original form that we're working on
+  orig = window.opener.document.itemSynopsis[field].value;
+  if (/[^\s]/.test(orig)) {
+    reset = '<input type="button" onclick="pick(orig);" ' +
+      'value="Reset to original values" /> | ';
+    document.write(reset);
+  }
+ </script>
+ <input type="button"
+        tal:attributes="value string:Clear all ${request/form/property/value} values"
+        onclick="listClear();" /> | 
+ <input type="button" onclick="listClose();" value="Close this window" />
+</div>
+
+<table class="classhelp"
+       tal:define="props python:request.form['properties'].value.split(',')">
+<tr>
+ <th tal:condition="python:request.form.has_key('property')">add/remove</th>
+ <th tal:repeat="prop props" tal:content="prop"></th>
+</tr>
+<tr tal:repeat="item context/list">
+ <td tal:condition="python:request.form.has_key('property')">
+ <input type="button" tal:define="opt python: item[props[0]]" 
+         tal:attributes="onclick string:add('${opt}')" value=" + ">
+ <input type="button" tal:define="opt python: item[props[0]]" 
+         tal:attributes="onclick string:remove('${opt}')" value=" - " />
+ </td>
+ <td tal:repeat="prop props" tal:content="structure python:item[prop]"></td>
+</tr>
+</table>
+</form>
+</body>
+</html>
diff --git a/templates/classic/html/_generic.index.html b/templates/classic/html/_generic.index.html
new file mode 100644 (file)
index 0000000..f21b5d2
--- /dev/null
@@ -0,0 +1,48 @@
+<!-- dollarId: issue.index,v 1.2 2001/07/29 04:07:37 richard Exp dollar-->
+
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title"
+       tal:content="python:context._classname.capitalize()+' editing'"></title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2 tal:content="python:context._classname.capitalize()+' editing'"></h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
+You are not allowed to view this page.
+</span>
+
+<tal:block tal:condition="context/is_edit_ok">
+<p class="form-help">
+ You may edit the contents of the <span tal:replace="request/classname" />
+ class using this form. Commas, newlines and double quotes (") must be
+ handled delicately. You may include commas and newlines by enclosing the
+ values in double-quotes ("). Double quotes themselves must be quoted by
+ doubling ("").
+</p>
+
+<p class="form-help">
+ Multilink properties have their multiple values colon (":") separated 
+ (... ,"one:two:three", ...)
+</p>
+
+<p class="form-help">
+ Remove entries by deleting their line. Add new entries by appending
+ them to the table - put an X in the id column.
+</p>
+
+<form onSubmit="return submit_once()" method="POST">
+<textarea rows="15" cols="60" name="rows" tal:content="context/csv"></textarea>
+<br>
+<input type="hidden" name=":action" value="editCSV">
+<input type="submit" value="Edit Items">
+</form>
+</tal:block>
+
+<tal:block tal:condition="context/is_only_view_ok">
+view ok
+</tal:block>
+
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/_generic.item.html b/templates/classic/html/_generic.item.html
new file mode 100644 (file)
index 0000000..a9d2e85
--- /dev/null
@@ -0,0 +1,56 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title"
+       tal:content="python:context._classname.capitalize()+' editing'"></title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2 tal:content="python:context._classname.capitalize()+' editing'"></h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
+You are not allowed to view this page.
+</span>
+
+<form method="POST" onSubmit="return submit_once()"
+      enctype="multipart/form-data" tal:condition="context/is_edit_ok">
+
+<input type="hidden" name=":template" value="item">
+<input type="hidden" name=":required" value="title">
+
+<table class="form">
+
+<tr tal:repeat="prop python:db[context._classname].properties()">
+ <tal:block tal:condition="python:prop._name not in ('id', 'creator',
+                                  'creation', 'activity')">
+  <th tal:content="prop/_name"></th>
+  <td tal:content="structure python:context[prop._name].field()"></td>
+ </tal:block>
+</tr>
+<tr>
+ <td>&nbsp;</td>
+ <td colspan=3 tal:content="structure context/submit">
+  submit button will go here
+ </td>
+</tr>
+</table>
+
+</form>
+
+<table class="form" tal:condition="context/is_only_view_ok">
+
+<tr tal:repeat="prop python:db[context._classname].properties()">
+ <tal:block tal:condition="python:prop._name not in ('id', 'creator',
+                                  'creation', 'activity')">
+  <th tal:content="prop/_name"></th>
+  <td tal:content="structure python:context[prop._name].field()"></td>
+ </tal:block>
+</tr>
+</table>
+
+
+<tal:block tal:condition="python:context.id and context.is_view_ok()">
+ <tal:block tal:replace="structure context/history" />
+</tal:block>
+
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/file.index.html b/templates/classic/html/file.index.html
new file mode 100644 (file)
index 0000000..34dd0cf
--- /dev/null
@@ -0,0 +1,30 @@
+<!-- dollarId: file.index,v 1.4 2002/01/23 05:10:27 richard Exp dollar-->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title"> 
+ <span tal:replace="config/TRACKER_NAME" />: List of files
+</title> 
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>List of files</h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<table class="otherinfo">
+<tr><th style="padding-right: 10">Download</th>
+    <th style="padding-right: 10">Content Type</th>
+    <th style="padding-right: 10">Uploaded By</th>
+    <th style="padding-right: 10">Date</th>
+</tr>
+<tr tal:repeat="file context/list">
+ <td>
+  <a tal:attributes="href string:file${file/id}/${file/name}"
+     tal:content="file/name">dld link</a>
+ </td>
+ <td tal:content="file/type">content type</td>
+ <td tal:content="file/creator">creator's name</td>
+ <td tal:content="file/creation">creation date</td>
+</tr>
+</table>
+
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/file.item.html b/templates/classic/html/file.item.html
new file mode 100644 (file)
index 0000000..ca9f6bd
--- /dev/null
@@ -0,0 +1,58 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title">File display</title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>File display</h2>
+</td>
+
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
+You are not allowed to view this page.
+</span>
+
+<form method="POST" onSubmit="return submit_once()"
+      enctype="multipart/form-data" tal:condition="context/is_edit_ok">
+
+<input type="hidden" name=":template" value="item">
+<input type="hidden" name=":required" value="name,type">
+
+<input type="hidden" name=":multilink"
+       tal:condition="python:request.form.has_key(':multilink')"
+       tal:attributes="value request/form/:multilink/value">
+
+<table class="form">
+ <tr>
+  <th>Name</th>
+  <td tal:content="structure context/name/field"></td>
+ </tr>
+ <tr>
+  <th>Content Type</th>
+  <td tal:content="structure context/type/field"></td>
+ </tr>
+
+ <tr>
+  <td>&nbsp;</td>
+  <td tal:content="structure context/submit">submit button here</td>
+ </tr>
+</table>
+</form>
+
+<a tal:condition="python:context.id and context.is_view_ok()"
+   tal:attributes="href string:file${context/id}/${context/name}">download</a>
+
+<table class="form" tal:condition="context/is_only_view_ok">
+ <tr>
+  <th>Name</th>
+  <td tal:content="context/name"></td>
+ </tr>
+ <tr>
+  <th>Content Type</th>
+  <td tal:content="context/type"></td>
+ </tr>
+</table>
+
+<tal:block tal:condition="python:context.id and context.is_view_ok()"
+           tal:replace="structure context/history" />
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/home.classlist.html b/templates/classic/html/home.classlist.html
new file mode 100644 (file)
index 0000000..0b5a244
--- /dev/null
@@ -0,0 +1,25 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title">List of classes</title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>List of classes</h2>
+</td>
+<td class="content" metal:fill-slot="content">
+<table class="classlist">
+
+<tal:block tal:repeat="cl db/classes">
+ <tr>
+  <th class="header" colspan="2" align="left">
+   <a tal:attributes="href string:${cl/classname}"
+      tal:content="python:cl.classname.capitalize()">classname</a>
+  </th>
+ </tr>
+ <tr tal:repeat="prop cl/properties">
+  <th tal:content="prop/_name">name</th>
+  <td tal:content="prop/_prop">type</td>
+ </tr>
+</tal:block>
+
+</table>
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/home.html b/templates/classic/html/home.html
new file mode 100644 (file)
index 0000000..fafdb2e
--- /dev/null
@@ -0,0 +1,10 @@
+<!--
+ This is the default body that is displayed when people visit the
+ tracker. The tag below lists the currently open issues. You may
+ replace it with a greeting message, or a different list of issues or
+ whatever. It's a good idea to have the issues on the front page though
+-->
+<span tal:replace="structure python:db.issue.renderWith('index',
+    sort=('-', 'activity'), group=('+', 'priority'), filter=['status'],
+    columns=['id','activity','title','creator','assignedto', 'status'],
+    filterspec={'status':['-1','1','2','3','4','5','6','7']})" />
diff --git a/templates/classic/html/issue.index.html b/templates/classic/html/issue.index.html
new file mode 100644 (file)
index 0000000..e830c44
--- /dev/null
@@ -0,0 +1,111 @@
+<!-- dollarId: issue.index,v 1.2 2001/07/29 04:07:37 richard Exp dollar-->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title"> 
+ <span tal:replace="config/TRACKER_NAME" />: List of issues
+</title> 
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>List of issues</h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<tal:block tal:condition="not:context/is_view_ok">
+You are not allowed to view this page.
+</tal:block>
+
+<tal:block tal:define="batch request/batch" tal:condition="context/is_view_ok">
+ <table class="list">
+  <tr>
+   <th tal:condition="request/show/priority">Priority</th>
+   <th tal:condition="request/show/id">ID</th>
+   <th tal:condition="request/show/creation">Creation</th>
+   <th tal:condition="request/show/activity">Activity</th>
+   <th tal:condition="request/show/topic">Topic</th>
+   <th tal:condition="request/show/title">Title</th>
+   <th tal:condition="request/show/status">Status</th>
+   <th tal:condition="request/show/creator">Created&nbsp;By</th>
+   <th tal:condition="request/show/assignedto">Assigned&nbsp;To</th>
+  </tr>
+ <tal:block tal:repeat="i batch">
+  <tr tal:condition="python:request.group[1] and
+                            batch.propchanged(request.group[1])">
+   <th tal:attributes="colspan python:len(request.columns)"
+       tal:content="python:i[request.group[1]]" class="group">
+   </th>
+  </tr>
+  <tr tal:attributes="class python:['normal', 'alt'][repeat['i'].index%6/3]">
+   <td tal:condition="request/show/priority" tal:content="i/priority"></td>
+   <td tal:condition="request/show/id" tal:content="i/id"></td>
+   <td nowrap tal:condition="request/show/creation"
+       tal:content="i/creation/reldate"></td>
+   <td nowrap tal:condition="request/show/activity"
+       tal:content="i/activity/reldate"></td>
+   <td tal:condition="request/show/topic" tal:content="i/topic"></td>
+   <td tal:condition="request/show/title">
+    <a tal:attributes="href string:issue${i/id}"
+               tal:content="python:str(i.title.plain(hyperlink=0)) or '[no title]'">title</a>
+   </td>
+   <td tal:condition="request/show/status" tal:content="i/status"></td>
+   <td tal:condition="request/show/creator" tal:content="i/creator"></td>
+   <td tal:condition="request/show/assignedto" tal:content="i/assignedto"></td>
+  </tr>
+ </tal:block>
+ <tr class="navigation" tal:define="colspan python:len(request.columns)">
+  <th tal:attributes="colspan python:colspan/2">
+   <a tal:define="prev batch/previous" tal:condition="prev"
+      tal:attributes="href python:request.indexargs_url(request.classname,
+      {':startwith':prev.first, ':pagesize':prev.size})">&lt;&lt; previous</a>
+   &nbsp;
+  </th>
+  <th tal:attributes="colspan python:colspan/2 + colspan%2">
+   <a tal:define="next batch/next" tal:condition="next"
+      tal:attributes="href python:request.indexargs_url(request.classname,
+      {':startwith':next.first, ':pagesize':next.size})">next &gt;&gt;</a>
+   &nbsp;
+  </th>
+ </tr>
+</table>
+
+<form method="GET" tal:attributes="action request/classname">
+ <tal:block tal:replace="structure python:request.indexargs_form(sort=0, group=0)" />
+ <table class="form">
+  <tr tal:condition="batch">
+   <th>Sort on:</th>
+   <td>
+    <select name=":sort">
+     <option value="">- nothing -</option>
+     <option tal:repeat="col context/properties"
+             tal:attributes="value col/_name;
+                             selected python:col._name == request.sort[1]"
+             tal:content="col/_name">column</option>
+    </select>
+   </td>
+   <th>Descending:</th>
+   <td><input type="checkbox" name=":sortdir"
+              tal:attributes="checked python:request.sort[0] == '-'"> 
+   </td>
+  </tr>
+  <tr>
+   <th>Group on:</th>
+   <td>
+    <select name=":group">
+     <option value="">- nothing -</option>
+     <option tal:repeat="col context/properties"
+             tal:attributes="value col/_name;
+                             selected python:col._name == request.group[1]"
+             tal:content="col/_name">column</option>
+    </select>
+   </td>
+   <th>Descending:</th>
+   <td><input type="checkbox" name=":groupdir"
+              tal:attributes="checked python:request.group[0] == '-'"> 
+   </td>
+  </tr>
+  <tr><td colspan="4"><input type="submit" value="Redisplay"></td></tr>
+ </table>
+</form>
+
+</tal:block>
+
+</td>
+</tal:block>
+
diff --git a/templates/classic/html/issue.item.html b/templates/classic/html/issue.item.html
new file mode 100644 (file)
index 0000000..8db909b
--- /dev/null
@@ -0,0 +1,174 @@
+<!-- dollarId: issue.item,v 1.4 2001/08/03 01:19:43 richard Exp dollar-->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title"> 
+<span tal:replace="config/TRACKER_NAME" />: 
+<span tal:condition="context/id"
+       tal:replace="string:Issue ${context/id}: ${context/title}" />
+<tal:x tal:condition="not:context/id">New Issue</tal:x> 
+</title> 
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>
+  Issue<span tal:replace="context/id" />
+   <tal:x tal:condition="context/is_edit_ok">Editing</tal:x>
+ </h2>
+</td>
+
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
+You are not allowed to view this page.
+</span>
+
+<form method="POST" name="itemSynopsis" onSubmit="return submit_once()"
+      enctype="multipart/form-data" tal:condition="context/is_edit_ok">
+
+<input type="hidden" name=":template" value="item">
+<input type="hidden" name=":required" value="title,priority">
+
+<table class="form">
+<tr>
+ <th class="required" nowrap>Title</th>
+ <td colspan=3 tal:content="structure python:context.title.field(size=60)">title</td>
+</tr>
+
+<tr>
+ <th class="required" nowrap>Priority</th>
+ <td tal:content="structure context/priority/menu">priority</td>
+ <th nowrap>Status</th>
+ <td tal:content="structure context/status/menu">status</td>
+</tr>
+
+<tr>
+ <th nowrap>Superseder</th>
+ <td>
+  <span tal:replace="structure python:context.superseder.field(showid=1, size=20)" />
+  <span tal:replace="structure python:db.issue.classhelp('id,title', property='superseder')" />
+  <span tal:condition="context/superseder" tal:repeat="sup context/superseder">
+   <br>View: <a tal:attributes="href string:issue${sup/id}"
+                tal:content="sup/id"></a>
+  </span>
+ </td>
+ <th nowrap>Nosy List</th>
+ <td>
+  <span tal:replace="structure context/nosy/field" />
+  <span tal:replace="structure
+python:db.user.classhelp('username,realname,address', property='nosy', width='600')" /><br>
+ </td>
+</tr>
+
+<tr>
+ <th nowrap>Assigned To</th>
+ <td tal:content="structure context/assignedto/menu">assignedto menu</td>
+ <th nowrap>Topics</th>
+ <td>
+  <span tal:replace="structure context/topic/field" />
+  <span tal:replace="structure python:db.keyword.classhelp(property='topic')" />
+ </td>
+</tr>
+
+<tr>
+ <th nowrap>Change Note</th>
+ <td colspan=3>
+  <textarea tal:content="request/form/:note/value | default"
+            name=":note" wrap="hard" rows="5" cols="80"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <th nowrap>File</th>
+ <td colspan=3><input type="file" name=":file" size="40"></td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td colspan=3 tal:content="structure context/submit">
+  submit button will go here
+ </td>
+</tr>
+</table>
+</form>
+
+<table class="form" tal:condition="not:context/id">
+<tr>
+ <td>Note:&nbsp;</td>
+ <th class="required">highlighted</th>
+ <td>&nbsp;fields are required.</td>
+</tr>
+</table>
+
+<table class="form" tal:condition="context/is_only_view_ok">
+<tr>
+ <th nowrap>Title</th><td colspan=3 tal:content="context/title">title</td>
+</tr>
+
+<tr>
+ <th nowrap>Priority</th><td tal:content="context/priority">priority</td>
+ <th nowrap>Status</th><td tal:content="context/status">status</td>
+</tr>
+
+<tr>
+ <th nowrap>Superseder</th>
+ <td>
+  <span tal:condition="context/superseder" tal:repeat="sup context/superseder">
+   <br>View: <a tal:attributes="href string:issue${sup/id}"
+                tal:content="sup/id"></a>
+  </span>
+ </td>
+ <th nowrap>Nosy List</th><td><span tal:replace="context/nosy" /></td>
+</tr>
+
+<tr>
+ <th nowrap>Assigned To</th><td tal:content="context/assignedto"></td>
+ <th nowrap>Topics</th><td tal:content="structure context/topic"></td>
+</tr>
+</table>
+
+<tal:block tal:condition="python:context.id and context.is_view_ok()">
+
+ <p tal:content="structure string:Created on
+  <b>${context/creation}</b> by <b>${context/creator}</b>, last
+  changed <b>${context/activity}</b>.">activity info
+ </p>
+
+ <table class="messages" tal:condition="context/messages">
+  <tr><th colspan="4" class="header">Messages</th></tr>
+  <tal:block tal:repeat="msg context/messages/reverse">
+   <tr>
+    <th><a tal:attributes="href string:msg${msg/id}"
+           tal:content="string:msg${msg/id}"></a></th>
+    <th tal:content="string:Author: ${msg/author}">author</th>
+    <th tal:content="string:Date: ${msg/date}">date</th>
+    <th>
+     <a tal:attributes="href string:?:remove:messages=${msg/id}&:action=edit">remove</a>
+    </th>
+   </tr>
+   <tr>
+    <td colspan="4" class="content">
+     <pre tal:content="msg/content">content</pre>
+    </td>
+   </tr>
+  </tal:block>
+ </table>
+
+ <table class="files" tal:condition="context/files">
+  <tr><th colspan="2" class="header">Files</th></tr>
+  <tr><th>File name</th><th>Uploaded</th></tr>
+  <tr tal:repeat="file context/files">
+   <td>
+    <a tal:attributes="href string:file${file/id}/${file/name}"
+       tal:content="file/name">dld link</a>
+   </td>
+   <td>
+    <span tal:content="file/creator">creator's name</span>,
+    <span tal:content="file/creation">creation date</span>
+   </td>
+  </tr>
+ </table>
+
+ <tal:block tal:replace="structure context/history" />
+
+</tal:block>
+
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/issue.search.html b/templates/classic/html/issue.search.html
new file mode 100644 (file)
index 0000000..4f9112d
--- /dev/null
@@ -0,0 +1,192 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title">Issue searching</title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>Issue searching</h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<form method="GET" tal:attributes="action request/classname">
+<input type="hidden" name=":action" value="search">
+
+<table class="form" tal:define="
+   cols python:'id activity priority title status assignedto'.split();
+   defsort python:['activity'];
+   defgroup python:['priority'];
+   defdisp python:'id activity title status assignedto'.split()">
+
+<tr>
+ <th class="header">&nbsp;</th>
+ <th class="header">Filter on</th>
+ <th class="header">Display</th>
+ <th class="header">Sort on</th>
+ <th class="header">Group on</th>
+</tr>
+
+<tr>
+ <th>All text*:</th>
+ <td><input name=":search_text"
+            tal:attributes="value request/form/:search_text/value | nothing">
+ </td>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+</tr>
+
+<tr>
+ <th>Title:</th>
+ <td><input name="title"></td>
+ <td><input type="checkbox" name=":columns" value="title" checked></td>
+ <td><input type="radio" name=":sort" value="title"></td>
+ <td>&nbsp;</td>
+</tr>
+
+<tr>
+ <th>Topic:</th>
+ <td>
+  <select name="topic">
+   <option value="">don't care</option>
+   <option value="">------------</option>
+   <option tal:repeat="s db/keyword/list" tal:attributes="value s/name"
+           tal:content="s/name">topic to filter on</option>
+  </select>
+ </td>
+ <td><input type="checkbox" name=":columns" value="topic" checked></td>
+ <td><input type="radio" name=":sort" value="topic"></td>
+ <td><input type="radio" name=":group" value="topic"></td>
+</tr>
+
+<tr>
+ <th>ID:</th>
+ <td><input name="id"></td>
+ <td><input type="checkbox" name=":columns" value="id" checked></td>
+ <td><input type="radio" name=":sort" value="id"></td>
+ <td>&nbsp;</td>
+</tr>
+
+<tr>
+ <th>Creation date:</th>
+ <td><input name="creation"></td>
+ <td><input type="checkbox" name=":columns" value="creation"></td>
+ <td><input type="radio" name=":sort" value="creation"></td>
+ <td><input type="radio" name=":group" value="creation"></td>
+</tr>
+
+<tr>
+ <th>Creator:</th>
+ <td>
+  <select name="creator">
+   <option value="">don't care</option>
+   <option tal:attributes="value request/user/id">created by me</option>
+   <option value="-1">------------</option>
+   <option tal:repeat="s db/user/list" tal:attributes="value s/id"
+     tal:content="s/username">user to filter on</option>
+  </select>
+ </td>
+ <td><input type="checkbox" name=":columns" value="creator" checked></td>
+ <td><input type="radio" name=":sort" value="creator"></td>
+ <td><input type="radio" name=":group" value="creator"></td>
+</tr>
+
+<tr>
+ <th>Activity:</th>
+ <td><input name="activity"></td>
+ <td><input type="checkbox" name=":columns" value="activity" checked></td>
+ <td><input type="radio" name=":sort" value="activity"></td>
+ <td>&nbsp;</td>
+</tr>
+
+<tr>
+ <th>Priority:</th>
+ <td>
+  <select name="priority">
+   <option value="">don't care</option>
+   <option value="-1">not selected</option>
+   <option value="">------------</option>
+   <option tal:repeat="s db/priority/list" tal:attributes="value s/id"
+     tal:content="s/name">priority to filter on</option>
+  </select>
+ </td>
+ <td><input type="checkbox" name=":columns" value="priority"></td>
+ <td><input type="radio" name=":sort" value="priority"></td>
+ <td><input type="radio" name=":group" value="priority"></td>
+</tr>
+
+<tr>
+ <th>Status:</th>
+ <td>
+  <select name="status">
+   <option value="">don't care</option>
+   <option value="-1,1,2,3,4,5,6,7">not resolved</option>
+   <option value="-1">not selected</option>
+   <option value="">------------</option>
+   <option tal:repeat="s db/status/list" tal:attributes="value s/id"
+           tal:content="s/name">status to filter on</option>
+  </select>
+ </td>
+ <td><input type="checkbox" name=":columns" value="status" checked></td>
+ <td><input type="radio" name=":sort" value="status"></td>
+ <td><input type="radio" name=":group" value="status"></td>
+</tr>
+
+<tr>
+ <th>Assigned To:</th>
+ <td>
+  <select name="assignedto">
+   <option value="">don't care</option>
+   <option tal:attributes="value request/user/id">assigned to me</option>
+   <option value="-1">unassigned</option>
+   <option value="">------------</option>
+   <option tal:repeat="s db/user/list" tal:attributes="value s/id"
+     tal:content="s/username">user to filter on</option>
+  </select>
+ </td>
+ <td><input type="checkbox" name=":columns" value="assignedto" checked></td>
+ <td><input type="radio" name=":sort" value="assignedto"></td>
+ <td><input type="radio" name=":group" value="assignedto"></td>
+</tr>
+
+<tr>
+<th>Pagesize:</th>
+<td><input type="text" name=":pagesize" size="3" value="50"></td>
+</tr>
+
+<tr>
+<th>Start With:</th>
+<td><input type="text" name=":startwith" size="3" value="0"></td>
+</tr>
+
+<tr>
+<th>Sort Descending:</th>
+<td><input type="checkbox" name=":sortdir" checked>
+</td>
+
+<tr>
+<th>Group Descending:</th>
+<td><input type="checkbox" name=":groupdir">
+</td>
+</tr>
+
+<tr>
+<th>Query name**:</th>
+<td><input name=":queryname"
+            tal:attributes="value request/form/:queryname/value | nothing">
+</td>
+</tr>
+
+<tr><td>&nbsp;</td>
+<td><input type="submit" value="Search"></td>
+</tr>
+
+<tr><td>&nbsp;</td>
+ <td colspan="4" class="help">
+   *: The "all text" field will look in message bodies and issue titles<br>
+   **: If you supply a name, the query will be saved off and available as a
+       link in the sidebar
+ </td>
+</tr>
+</table>
+
+</form>
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/keyword.item.html b/templates/classic/html/keyword.item.html
new file mode 100644 (file)
index 0000000..4572370
--- /dev/null
@@ -0,0 +1,53 @@
+<!-- dollarId: keyword.item,v 1.3 2002/05/22 00:32:34 richard Exp dollar-->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title">Keyword editing</title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>Keyword editing</h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<table class="otherinfo" tal:define="keywords db/keyword/list"
+       tal:condition="keywords">
+ <tr><th colspan="4" class="header">Existing Keywords</th></tr>
+ <tr tal:repeat="start python:range(0, len(keywords), 4)">
+  <td width="25%" tal:define="batch python:utils.Batch(keywords, 4, start)"
+      tal:repeat="keyword batch">
+    <a tal:attributes="href string:keyword${keyword/id}"
+       tal:content="keyword/name">keyword here</a>
+  </td>
+ </tr>
+ <tr>
+  <td colspan="4" style="border-top: 1px solid gray">
+   To edit an existing keyword (for spelling or typing errors),
+   click on its entry above.
+  </td>
+ </tr>
+</table>
+
+<p class="help" tal:condition="not:context/id">
+ To create a new keyword, enter it below and click "Submit New Entry".
+</p>
+
+<form method="POST" onSubmit="return submit_once()"
+      enctype="multipart/form-data">
+
+ <input type="hidden" name=":required" value="name">
+ <input type="hidden" name=":template" value="item">
+
+ <table class="form">
+  <tr>
+   <th nowrap>Keyword</th>
+   <td tal:content="structure context/name/field">name</td>
+  </tr>
+
+  <tr>
+   <td>&nbsp;</td>
+   <td colspan=3 tal:content="structure context/submit">
+    submit button will go here
+   </td>
+  </tr>
+ </table>
+</form>
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/msg.index.html b/templates/classic/html/msg.index.html
new file mode 100644 (file)
index 0000000..666344b
--- /dev/null
@@ -0,0 +1,23 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title"> 
+ <span tal:replace="config/TRACKER_NAME" />: List of messages
+</title> 
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>Message listing</h2>
+</td>
+<td class="content" metal:fill-slot="content">
+<table class="messages" tal:condition="request/filter">
+ <tr><th colspan=2 class="header">Messages</th></tr>
+ <tal:block tal:repeat="msg context/list">
+  <tr>
+   <th tal:content="string:Author: ${msg/author}">author</th>
+   <th tal:content="string:Date: ${msg/date}">date</th>
+  </tr>
+  <tr>
+   <td colspan="2"><pre tal:content="msg/content">content</pre></td>
+  </tr>
+ </tal:block>
+</table>
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/msg.item.html b/templates/classic/html/msg.item.html
new file mode 100644 (file)
index 0000000..49e203a
--- /dev/null
@@ -0,0 +1,58 @@
+<!-- dollarId: msg.item,v 1.3 2002/05/22 00:32:34 richard Exp dollar-->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title"> 
+<span tal:replace="config/TRACKER_NAME" />: 
+<span tal:condition="context/id" tal:replace="string:Message ${context/id}" />
+<tal:x tal:condition="not:context/id">New Message</tal:x> 
+</title> 
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>
+  Message<span tal:replace="context/id" />
+   <tal:x tal:condition="context/is_edit_ok">Editing</tal:x>
+ </h2>
+</td>
+<td class="content" metal:fill-slot="content">
+<table class="form">
+
+<tr>
+ <th nowrap>Author</th>
+ <td tal:content="context/author"></td>
+</tr>
+
+<tr>
+ <th nowrap>Recipients</th>
+ <td tal:content="context/recipients"></td>
+</tr>
+
+<tr>
+ <th nowrap>Date</th>
+ <td tal:content="context/date"></td>
+</tr>
+</table>
+
+<table class="messages">
+ <tr><th colspan=2 class="header">Content</th></tr>
+ <tr>
+  <td class="content" colspan=2><pre tal:content="context/content"></pre></td>
+ </tr>
+</table>
+
+<table class="files" tal:condition="context/files">
+ <tr><th colspan="2" class="header">Files</th></tr>
+ <tr><th>File name</th><th>Uploaded</th></tr>
+ <tr tal:repeat="file context/files">
+  <td>
+   <a tal:attributes="href string:file${file/id}/${file/name}"
+      tal:content="file/name">dld link</a>
+  </td>
+  <td>
+   <span tal:content="file/creator">creator's name</span>,
+   <span tal:content="file/creation">creation date</span>
+  </td>
+ </tr>
+</table>
+
+<tal:block tal:replace="structure context/history" />
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/page.html b/templates/classic/html/page.html
new file mode 100644 (file)
index 0000000..cd2e98f
--- /dev/null
@@ -0,0 +1,104 @@
+<html metal:define-macro="icing">
+<head>
+<title metal:define-slot="head_title">title goes here</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8;">
+
+<link rel="stylesheet" type="text/css" href="_file/style.css">
+
+<script tal:replace="structure request/base_javascript">
+</script>
+
+</head>
+<body class="body" marginwidth="0" marginheight="0">
+
+<table class="body">
+
+<tr>
+ <td class="page-header-left">&nbsp;</td>
+ <td class="page-header-top" metal:define-slot="body_title"><h2>name</h2></td>
+</tr>
+
+<tr>
+ <td rowspan="2" valign="top" nowrap class="sidebar">
+  <p class="classblock" tal:condition="request/user/queries">
+   <b>Your Queries</b><br>
+   <tal:block tal:repeat="qs request/user/queries">
+    <a tal:attributes="href string:${qs/klass}${qs/url}"
+       tal:content="qs/name">link</a><br>
+   </tal:block>
+  </p>
+
+  <form method="POST">
+   <p class="classblock"
+       tal:condition="python:request.user.hasPermission('View', 'issue')">
+    <b>Issues</b><br>
+    <a tal:condition="python:request.user.hasPermission('Edit', 'issue')"
+      href="issue?:template=item">Create New<br></a>
+    <a href="issue?:sort=-activity&:group=priority&:filter=status,assignedto&:columns=id,activity,title,creator,status&status=-1,1,2,3,4,5,6,7&assignedto=-1">Show Unassigned</a><br>
+    <a href="issue?:sort=-activity&:group=priority&:filter=status&:columns=id,activity,title,creator,assignedto,status&status=-1,1,2,3,4,5,6,7">Show All</a><br>
+    <a href="issue?:template=search">Search</a><br>
+    <input type="submit" value="Show issue no."><input size="4" type="text" name=":number">
+    <input type="hidden" name=":type" value="issue">
+    <input type="hidden" name=":action" value="show">
+   </p>
+  </form>
+
+  <p class="classblock"
+     tal:condition="python:request.user.hasPermission('View', 'keyword')">
+   <b>Keywords</b><br>
+   <a tal:condition="python:request.user.hasPermission('Edit', 'keyword')"
+      href="keyword?:template=item">Create New<br></a>
+   <a tal:condition="python:request.user.hasPermission('Edit', 'keyword') and
+                            len(db.keyword.list())"
+      href="keyword?:template=item">Edit Existing<br></a>
+  </p>
+
+  <p class="classblock"
+       tal:condition="python:request.user.username != 'anonymous'">
+   <b>Administration</b><br>
+   <a tal:condition="python:request.user.hasPermission('Edit', None)"
+      href="home?:template=classlist">Class List</a><br>
+   <a tal:condition="python:request.user.hasPermission('View', 'user')
+                            or request.user.hasPermission('Edit', 'user')"
+      href="user" >User List</a><br>
+   <a tal:condition="python:request.user.hasPermission('Edit', 'user')"
+      href="user?:template=item">Add User</a>
+  </p>
+
+  <form method="POST" action="">
+   <p class="userblock" tal:condition="python:request.user.username=='anonymous'">
+    <input size="10" name="__login_name"><br>
+    <input size="10" type="password" name="__login_password"><br>
+    <input type="submit" name=":action" value="login">
+    <span tal:replace="structure request/indexargs_form" />
+    <a href="user?:template=register">Register</a><br>
+    <a href="user?:template=forgotten">Forgotten your password?</a><br>
+   </p>
+  </form>
+   
+  <p class="userblock" tal:condition="python:request.user.username != 'anonymous'">
+   <b>Hello,</b><br><b tal:content="request/user/username">username</b><br>
+   <a tal:attributes="href string:issue?:sort=-activity&:group=priority&:filter=status,assignedto&:columns=id,activity,title,creator,status&status=-1,1,2,3,4,5,6,7&assignedto=${request/user/id}">My Issues</a><br>
+   <a tal:attributes="href string:user${request/user/id}">My Details</a><br>
+   <a tal:attributes="href python:request.indexargs_href('',
+       {':action':'logout'})">Logout</a>
+  </p>
+ </td>
+ <td>
+  <p tal:condition="options/error_message | nothing" class="error-message"
+     tal:repeat="m options/error_message" tal:content="structure m">error</p>
+  <p tal:condition="options/ok_message | nothing" class="ok-message"
+     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
+ </td>
+</tr>
+<tr>
+ <td class="content" metal:define-slot="content">Page content goes here</td>
+</tr>
+
+</table>
+
+<pre tal:condition="request/form/debug | nothing" tal:content="request">
+</pre>
+
+</body>
+</html>
diff --git a/templates/classic/html/query.item.html b/templates/classic/html/query.item.html
new file mode 100644 (file)
index 0000000..5e969d3
--- /dev/null
@@ -0,0 +1,3 @@
+<!-- query.item -->
+<span tal:content="structure context/renderQueryForm" />
+
diff --git a/templates/classic/html/style.css b/templates/classic/html/style.css
new file mode 100644 (file)
index 0000000..da5c4c6
--- /dev/null
@@ -0,0 +1,308 @@
+/* main page styles */
+body.body {
+  font-family: sans-serif, Arial, Helvetica;
+  color: #333333;
+}
+a[href]:hover { color:blue; text-decoration: underline; }
+a[href]:link { color:blue; text-decoration: none; }
+a[href] { color:blue; text-decoration: none; }
+
+table.body {
+  border: 0;
+  padding: 0;
+  border-spacing: 0px;
+  border-collapse: separate;
+}
+
+td.page-header-left {
+  padding: 5px;
+  border-bottom: 1px solid #444444;
+}
+
+td.page-header-top {
+  padding: 5px;
+  border-bottom: 1px solid #444444;
+}
+
+td.sidebar {
+  padding: 1 0 0 1;
+}
+
+td.sidebar p.classblock {
+  padding: 0 5 0 5;
+  margin: 1 1 1 1;
+  border: 1px solid #444444;
+  background-color: #eeeeee;
+}
+
+td.sidebar p.userblock {
+  padding: 0 5 0 5;
+  margin: 1 1 1 1;
+  border: 1px solid #444444;
+  background-color: #eeeeff;
+}
+
+td.content {
+  padding: 1 5 1 5;
+  vertical-align: top;
+  width: 100%;
+}
+
+p.ok-message {
+  background-color: #22bb22;
+  padding: 5 5 5 5;
+  color: white;
+  font-weight: bold;
+}
+p.error-message {
+  background-color: #bb2222;
+  padding: 5 5 5 5;
+  color: white;
+  font-weight: bold;
+}
+
+
+/* style for forms */
+table.form {
+  padding: 2;
+  border-spacing: 0px;
+  border-collapse: separate;
+}
+
+table.form th {
+  color: #333388;
+  text-align: right;
+  vertical-align: top;
+  font-weight: normal;
+}
+
+table.form th.header {
+  font-weight: bold;
+  background-color: #eeeeff;
+  text-align: left;
+}
+
+table.form th.required {
+  font-weight: bold;
+}
+
+table.form td {
+  color: #333333;
+  empty-cells: show;
+  vertical-align: top;
+}
+
+table.form td.optional {
+  font-weight: bold;
+  font-style: italic;
+}
+
+table.form td.html {
+  color: #777777;
+}
+
+/* style for lists */
+table.list {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.list th {
+  padding: 0 4 0 4;
+  color: #404070;
+  background-color: #eeeeff;
+  border: 1px solid white;
+  vertical-align: top;
+  empty-cells: show;
+}
+table.list th a[href]:hover { color: #404070 }
+table.list th a[href]:link { color: #404070 }
+table.list th a[href] { color: #404070 }
+table.list th.group {
+  background-color: #f4f4ff;
+  text-align: center;
+}
+
+table.list td {
+  padding: 0 4 0 4;
+  border: 1px solid white;
+  color: #404070;
+  background-color: white;
+  vertical-align: top;
+  empty-cells: show;
+}
+
+table.list tr.normal td {
+  background-color: #efefef;
+}
+
+table.list tr.alt td {
+  background-color: #efefef;
+}
+
+table.list tr.navigation th {
+  text-align: right;
+}
+table.list tr.navigation th:first-child {
+  text-align: left;
+}
+
+
+/* style for message displays */
+table.messages {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.messages th.header{
+  padding-top: 10px;
+  border-bottom: 1px solid gray;
+  font-weight: bold;
+  background-color: white;
+  color: #707040;
+}
+
+table.messages th {
+  font-weight: bold;
+  color: black;
+  text-align: left;
+  border-bottom: 1px solid #afafaf;
+}
+
+table.messages td {
+  font-family: monospace;
+  background-color: #efefef;
+  border-bottom: 1px solid #afafaf;
+  color: black;
+  empty-cells: show;
+  border-right: 1px solid #afafaf;
+  vertical-align: top;
+  padding: 2 5 2 5;
+}
+
+table.messages td:first-child {
+  border-left: 1px solid #afafaf;
+  border-right: 1px solid #afafaf;
+}
+
+/* style for file displays */
+table.files {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.files th.header{
+  padding-top: 10px;
+  border-bottom: 1px solid gray;
+  font-weight: bold;
+  background-color: white;
+  color: #707040;
+}
+
+table.files th {
+  border-bottom: 1px solid #afafaf;
+  font-weight: bold;
+  text-align: left;
+}
+
+table.files td {
+  font-family: monospace;
+  empty-cells: show;
+}
+
+/* style for history displays */
+table.history {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.history th.header{
+  padding-top: 10px;
+  border-bottom: 1px solid gray;
+  font-weight: bold;
+  background-color: white;
+  color: #707040;
+  font-size: 100%;
+}
+
+table.history th {
+  border-bottom: 1px solid #afafaf;
+  font-weight: bold;
+  text-align: left;
+  font-size: 90%;
+}
+
+table.history td {
+  font-size: 90%;
+  vertical-align: top;
+  empty-cells: show;
+}
+
+
+/* style for class list */
+table.classlist {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.classlist th.header{
+  padding-top: 10px;
+  border-bottom: 1px solid gray;
+  font-weight: bold;
+  background-color: white;
+  color: #707040;
+}
+
+table.classlist th {
+  font-weight: bold;
+  text-align: left;
+}
+
+
+/* style for class help display */
+table.classhelp {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.classhelp th {
+  font-weight: bold;
+  text-align: left;
+  color: #707040;
+}
+
+table.classhelp td {
+  padding: 2 2 2 2;
+  border: 1px solid black;
+  text-align: left;
+  vertical-align: top;
+  empty-cells: show;
+}
+
+
+/* style for "other" displays */
+table.otherinfo {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.otherinfo th.header{
+  padding-top: 10px;
+  border-bottom: 1px solid gray;
+  font-weight: bold;
+  background-color: white;
+  color: #707040;
+}
+
+table.otherinfo th {
+  border-bottom: 1px solid #afafaf;
+  font-weight: bold;
+  text-align: left;
+}
diff --git a/templates/classic/html/user.forgotten.html b/templates/classic/html/user.forgotten.html
new file mode 100644 (file)
index 0000000..1df6918
--- /dev/null
@@ -0,0 +1,33 @@
+<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title">Password reset request</title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>Password reset request</h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<p>You have two options if you have forgotten your password. If you 
+know the email address you registered with, enter it below.</p>
+
+<form method="POST" onSubmit="return submit_once()">
+<input type="hidden" name="@action" value="passrst">
+<input type="hidden" name="@template" value="forgotten">
+<table class="form">
+ <tr><th>Email Address:</th> <td><input name="address"></td> </tr>
+ <tr><td></td><td><input type="submit" value="Request password reset"></td></tr>
+</table>
+
+<p>Or, if you know your username, then enter it below.</p>
+
+<table class="form">
+ <tr><th>Username:</th> <td><input name="username"></td> </tr>
+ <tr><td></td><td><input type="submit" value="Request password reset"></td></tr>
+</table>
+</form>
+
+<p>A confirmation email will be sent to you - please follow the
+instructions
+within it to complete the reset process.</p>
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/user.index.html b/templates/classic/html/user.index.html
new file mode 100644 (file)
index 0000000..7c70042
--- /dev/null
@@ -0,0 +1,40 @@
+<!-- dollarId: user.index,v 1.3 2002/07/09 05:29:51 richard Exp dollar-->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title">User listing</title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>User listing</h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="not:context/is_view_ok">
+You are not allowed to view this page.
+</span>
+
+<table width="100%" tal:condition="context/is_view_ok" class="list">
+<tr>
+ <th>Username</th>
+ <th>Real name</th>
+ <th>Organisation</th>
+ <th>Email address</th>
+ <th>Phone number</th>
+ <th tal:condition="context/is_edit_ok">Retire</th>
+</tr>
+<tr tal:repeat="user context/list"
+    tal:attributes="class python:['normal', 'alt'][repeat['user'].index%6/3]">
+ <td>
+  <a tal:attributes="href string:user${user/id}"
+     tal:content="user/username">username</a>
+ </td>
+ <td tal:content="user/realname">realname</td>
+ <td tal:content="user/organisation">organisation</td>
+ <td tal:content="python:user.address.email()">address</td>
+ <td tal:content="user/phone">phone</td>
+ <td tal:condition="context/is_edit_ok">
+  <a tal:attributes="href string:user${user/id}?:action=retire&:template=index">
+   retire</a>
+ </td>
+</tr>
+</table>
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/user.item.html b/templates/classic/html/user.item.html
new file mode 100644 (file)
index 0000000..422d933
--- /dev/null
@@ -0,0 +1,126 @@
+<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title"> 
+<span tal:replace="config/TRACKER_NAME" />: 
+<span tal:condition="context/id"
+      tal:replace="string:User ${context/id}: ${context/username}" />
+<tal:x tal:condition="not:context/id">New User</tal:x> 
+</title> 
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>
+  User<span tal:replace="context/id" />
+   <tal:x tal:condition="context/is_edit_ok">Editing</tal:x>
+ </h2>
+</td>
+
+<td class="content" metal:fill-slot="content">
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
+You are not allowed to view this page.
+</span>
+
+<form method="POST" onSubmit="return submit_once()"
+      enctype="multipart/form-data" tal:condition="context/is_edit_ok">
+
+<input type="hidden" name=":required" value="username,address">
+
+<table class="form">
+ <tr>
+  <th>Name</th>
+  <td tal:content="structure context/realname/field">realname</td>
+ </tr>
+ <tr>
+  <th>Login Name</th>
+  <td tal:content="structure context/username/field">username</td>
+ </tr>
+ <tr>
+  <th>Login Password</th>
+  <td tal:content="structure context/password/field">password</td>
+ </tr>
+ <tr>
+  <th>Confirm Password</th>
+  <td tal:content="structure context/password/confirm">password</td>
+ </tr>
+ <tr tal:condition="python:request.user.hasPermission('Web Roles')">
+  <th>Roles</th>
+  <td tal:condition="context/id"
+      tal:content="structure context/roles/field">roles</td>
+  <td tal:condition="not:context/id">
+   <input name="roles" tal:attributes="value db/config/NEW_WEB_USER_ROLES">
+   (to give the user more than one role, enter a comma,separated,list)
+  </td>
+ </tr>
+ <tr>
+  <th>Phone</th>
+  <td tal:content="structure context/phone/field">phone</td>
+ </tr>
+ <tr>
+  <th>Organisation</th>
+  <td tal:content="structure context/organisation/field">organisation</td>
+ </tr>
+ <tr>
+  <th>Timezone</th>
+  <td tal:content="structure context/timezone/field">timezone</td>
+ </tr>
+ <tr>
+  <th>E-mail address</th>
+  <td tal:content="structure context/address/field">address</td>
+ </tr>
+ <tr>
+  <th>Alternate E-mail addresses<br>One address per line</th>
+  <td tal:content="structure context/alternate_addresses/multiline">alternate_addresses</td>
+ </tr>
+
+ <tr>
+  <td>&nbsp;</td>
+  <td tal:content="structure context/submit">submit button here</td>
+ </tr>
+</table>
+</form>
+
+<table class="otherinfo" tal:condition="context/queries">
+ <tr><th colspan="3" class="header">Queries</th></tr>
+ <tr><th>Name</th><th colspan="2">Actions</th></tr>
+ <tr tal:repeat="query context/queries">
+  <td><a tal:attributes="href string:query${query/id}"
+         tal:content="query/name"></a></td>
+  <td>
+   <a tal:attributes="href python:'%s%s'%(query['klass'], query['url'])">display</a>
+  </td>
+  <td>
+   <a tal:attributes="href string:?:remove:queries=${query/id}&:action=edit">remove</a>
+  </td>
+ </tr>
+</table>
+
+<table class="form" tal:condition="context/is_only_view_ok">
+ <tr>
+  <th colspan=2 class="header" tal:content="context/realname">realname</th>
+ </tr>
+ <tr>
+  <th>Login Name</th>
+  <td tal:content="context/username">username</td>
+ </tr>
+ <tr>
+  <th>Phone</th>
+  <td tal:content="context/phone">phone</td>
+ </tr>
+ <tr>
+  <th>Organisation</th>
+  <td tal:content="context/organisation">organisation</td>
+ </tr>
+ <tr>
+  <th>Timezone</th>
+  <td tal:content="context/timezone">timezone</td>
+ </tr>
+ <tr>
+  <th>E-mail address</th>
+  <td tal:content="context/address/email">address</td>
+ </tr>
+</table>
+
+<tal:block tal:condition="python:context.id and context.is_view_ok()"
+           tal:replace="structure context/history" />
+
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/user.register.html b/templates/classic/html/user.register.html
new file mode 100644 (file)
index 0000000..a226413
--- /dev/null
@@ -0,0 +1,82 @@
+<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title"
+       tal:content="string:Registering with ${db/config/TRACKER_NAME}"></title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2 tal:content="string:Registering with ${db/config/TRACKER_NAME}"></h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<tal:block tal:define=" editok python:request.user.username=='anonymous' and
+           request.user.hasPermission('Web Registration')">
+
+<span tal:condition="python:not editok">
+You are not allowed to view this page.
+</span>
+
+<tal:block tal:condition="editok">
+<form method="POST" onSubmit="return submit_once()" enctype="multipart/form-data">
+<input type="hidden" name=":template" value="register">
+<input type="hidden" name=":required" value="username">
+<input type="hidden" name=":required" value="password">
+<input type="hidden" name=":required" value="address">
+
+<table class="form">
+ <tr>
+  <th>Name</th>
+  <td tal:content="structure context/realname/field">realname</td>
+ </tr>
+ <tr>
+  <th>Login Name</th>
+  <td tal:content="structure context/username/field">username</td>
+ </tr>
+ <tr>
+  <th>Login Password</th>
+  <td tal:content="structure context/password/field">password</td>
+ </tr>
+ <tr>
+  <th>Confirm Password</th>
+  <td tal:content="structure context/password/confirm">password</td>
+ </tr>
+ <tr tal:condition="python:request.user.hasPermission('Web Roles')">
+  <th>Roles</th>
+  <td tal:condition="exists:item"
+      tal:content="structure context/roles/field">roles</td>
+  <td tal:condition="not:exists:item">
+   <input name="roles" tal:attributes="value db/config/NEW_WEB_USER_ROLES">
+  </td>
+ </tr>
+ <tr>
+  <th>Phone</th>
+  <td tal:content="structure context/phone/field">phone</td>
+ </tr>
+ <tr>
+  <th>Organisation</th>
+  <td tal:content="structure context/organisation/field">organisation</td>
+ </tr>
+ <tr>
+  <th>E-mail address</th>
+  <td tal:content="structure context/address/field">address</td>
+ </tr>
+ <tr>
+  <th>Alternate E-mail addresses<br>One address per line</th>
+  <td tal:content="structure context/alternate_addresses/multiline">alternate_addresses</td>
+ </tr>
+
+ <tr>
+  <td>&nbsp;</td>
+  <td>
+   <input type="hidden" name=":action" value="register">
+   <input type="submit" name="submit" value="Register">
+  </td>
+ </tr>
+</table>
+</form>
+
+</tal:block>
+
+</tal:block>
+
+</td>
+
+</tal:block>
diff --git a/templates/classic/html/user.rego_progress.html b/templates/classic/html/user.rego_progress.html
new file mode 100644 (file)
index 0000000..95b1412
--- /dev/null
@@ -0,0 +1,16 @@
+<!-- dollarId: issue.index,v 1.2 2001/07/29 04:07:37 richard Exp dollar-->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title">List of issues</title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h1>Registration in progress...</h1>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<p>You will shortly receive an email to confirm your registration. To
+complete the registration process, visit the link indicated in the
+email.
+</p>
+
+</td>
+</tal:block>
+
diff --git a/templates/classic/htmlbase.py b/templates/classic/htmlbase.py
new file mode 100644 (file)
index 0000000..0b40ae7
--- /dev/null
@@ -0,0 +1,529 @@
+# Do Not Edit (Unless You Want To)
+# This file automagically generated by roundup.templatebuilder.makeHtmlBase
+# 
+fileDOTindex = """<!-- dollarId: file.index,v 1.4 2002/01/23 05:10:27 richard Exp dollar-->
+<tr>
+    <property name="name">
+        <td><display call="download('name')"></td>
+    </property>
+    <property name="type">
+        <td><display call="plain('type')"></td>
+    </property>
+    <property name="creator">
+        <td><display call="plain('creator')"></td>
+    </property>
+    <property name="creation">
+        <td><display call="plain('creation')"></td>
+    </property>
+</tr>
+"""
+
+fileDOTnewitem = """<!-- dollarId: file.newitem,v 1.1 2001/07/30 08:12:17 richard Exp dollar-->
+<table border=0 cellspacing=0 cellpadding=2>
+
+<tr class="strong-header">
+  <td colspan=2>File upload details</td>
+</td>
+
+<tr bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">File:</span></td>
+    <td class="form-text"><input type="file" name="content" size="40"></td>
+</tr>
+
+<tr bgcolor="ffffea">
+    <td>&nbsp;</td>
+    <td class="form-text"><display call="submit()"></td>
+</tr>
+
+</table>
+"""
+
+issueDOTfilter = """<!-- dollarId: issue.filter,v 1.2 2001/07/29 04:07:37 richard Exp dollar-->
+<property name="title">
+ <tr><th width="1%" align="right" class="location-bar">Title</th>
+ <td><display call="field('title')"></td></tr>
+</property>
+<property name="status">
+ <tr><th width="1%" align="right" class="location-bar">Status</th>
+ <td><display call="checklist('status')"></td></tr>
+</property>
+<property name="priority">
+ <tr><th width="1%" align="right" class="location-bar">Priority</th>
+ <td><display call="checklist('priority')"></td></tr>
+</property>
+<property name="assignedto">
+ <tr><th width="1%" align="right" class="location-bar">Assignedto</th>
+ <td><display call="field('assignedto')"></td></tr>
+</property>
+"""
+
+issueDOTindex = """<!-- dollarId: issue.index,v 1.2 2001/07/29 04:07:37 richard Exp dollar-->
+<tr class="row-<display call="plain('status')">">
+    <property name="id">
+        <td valign="top"><display call="plain('id')"></td>
+    </property>
+    <property name="activity">
+        <td valign="top"><display call="reldate('activity', pretty=1)"></td>
+    </property>
+    <property name="priority">
+        <td valign="top"><display call="plain('priority')"></td>
+    </property>
+    <property name="title">
+        <td valign="top"><display call="link('title')"></td>
+    </property>
+    <property name="status">
+        <td valign="top"><display call="plain('status')"></td>
+    </property>
+    <property name="assignedto">
+        <td valign="top"><display call="link('assignedto')"></td>
+    </property>
+</tr>
+"""
+
+issueDOTitem = """<!-- dollarId: issue.item,v 1.4 2001/08/03 01:19:43 richard Exp dollar-->
+<table border=0 cellspacing=0 cellpadding=2>
+
+<tr  bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Title</span></td>
+    <td colspan=3 class="form-text"><display call="field('title', size=80)"></td>
+</tr>
+
+<tr bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Created</span></td>
+    <td class="form-text"><display call="reldate('creation', pretty=1)">
+        (<display call="plain('creator')">)</td>
+    <td width=1% nowrap align=right><span class="form-label">Last activity</span></td>
+    <td class="form-text"><display call="reldate('activity', pretty=1)"></td>
+</tr>
+
+<tr bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Priority</span></td>
+    <td class="form-text"><display call="menu('priority')"></td>
+    <td width=1% nowrap align=right><span class="form-label">Status</span></td>
+    <td class="form-text"><display call="menu('status')"></td>
+</tr>
+
+<tr bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Superseder</span></td>
+    <td class="form-text"><display call="field('superseder', size=40, showid=1)"></td>
+    <td width=1% nowrap align=right><span class="form-label">Nosy List</span></td>
+    <td class="form-text"><display call="field('nosy')"></td>
+</tr>
+
+<tr bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Assigned To</span></td>
+    <td class="form-text"><display call="menu('assignedto')"></td>
+    <td>&nbsp;</td>
+    <td>&nbsp;</td>
+</tr>
+
+<tr bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Change Note</span></td>
+    <td colspan=3 class="form-text"><display call="note()"></td>
+</tr>
+
+<tr bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">File</span></td>
+    <td colspan=3 class="form-text"><input type="file" name="__file" size="80"></td>
+</tr>
+
+<tr bgcolor="ffffea">
+    <td>&nbsp;</td>
+    <td colspan=3 class="form-text"><display call="submit()"></td>
+</tr>
+
+<tr class="msg-header">
+    <td colspan=4><b>Messages</b></td>
+</tr>
+<property name="messages">
+<tr>
+    <td colspan=4><display call="list('messages')"></td>
+</tr>
+</property>
+
+<tr class="file-header">
+  <td colspan=4><b>Files</b></td>
+</tr>
+<tr class="form-help">
+ <td colspan=4>
+   <a href="newfile?:multilink=issue<display
+call="plain('id')">:files">Attach a file to this issue</a>
+ </td>
+</tr>
+<property name="files">
+ <tr>
+     <td colspan=4><display call="list('files')"></td>
+ </tr>
+</property>
+
+<tr class="history-header">
+    <td colspan=4><b>History</b></td>
+</tr>
+<tr>
+    <td colspan=4><display call="history()"></td>
+</tr>
+
+</table>
+
+"""
+
+msgDOTindex = """<!-- dollarId: msg.index,v 1.2 2001/07/29 04:07:37 richard Exp dollar-->
+<tr>
+    <property name="date">
+        <td><display call="link('date')"></td>
+    </property>
+    <property name="author">
+        <td><display call="plain('author')"></td>
+    </property>
+    <property name="summary">
+        <td><display call="plain('summary')"></td>
+    </property>
+</tr>
+"""
+
+msgDOTitem = """<!-- dollarId: msg.item,v 1.2 2001/07/29 04:07:37 richard Exp dollar-->
+<table border=0 cellspacing=0 cellpadding=2>
+
+<tr class="strong-header">
+  <td colspan=2>Message Information</td>
+</td>
+
+<tr bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Author</span></td>
+    <td class="form-text"><display call="plain('author')"></td>
+</tr>
+
+<tr bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Recipients</span></td>
+    <td class="form-text"><display call="plain('recipients')"></td>
+</tr>
+
+<tr bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Date</span></td>
+    <td class="form-text"><display call="plain('date')"></td>
+</tr>
+
+<tr bgcolor="ffeaff">
+ <td colspan=2 class="form-text">
+  <pre><display call="plain('content')"></pre>
+ </td>
+</tr>
+
+<property name="files">
+<tr class="strong-header"><td colspan=2><b>Files</b></td></tr>
+<tr><td colspan=2><display call="list('files')"></td></tr>
+</property>
+
+<tr class="strong-header"><td colspan=2><b>History</b></td><tr>
+<tr><td colspan=2><display call="history()"></td></tr>
+
+</table>
+"""
+
+styleDOTcss = """h1 {
+  font-family: Verdana, Helvetica, sans-serif; 
+  font-size: 18pt; 
+  font-weight: bold; 
+}
+
+h2 {
+  font-family: Verdana, Helvetica, sans-serif; 
+  font-size: 16pt; 
+  font-weight: bold; 
+}
+
+h3 {
+  font-family: Verdana, Helvetica, sans-serif; 
+  font-size: 12pt; 
+  font-weight: bold; 
+}
+
+a:hover {  
+  font-family: Verdana, Helvetica, sans-serif; 
+  text-decoration: underline;
+  color: #333333; 
+}
+
+a:link {
+  font-family: Verdana, Helvetica, sans-serif; 
+  text-decoration: none;
+  color: #000099;
+}
+
+a {
+  font-family: Verdana, Helvetica, sans-serif; 
+  text-decoration: none;
+  color: #000099;
+}
+
+p {
+  font-family: Verdana, Helvetica, sans-serif;
+  font-size: 10pt;
+  color: #333333;
+}
+
+th {
+  font-family: Verdana, Helvetica, sans-serif; 
+  font-weight: bold;
+  font-size: 10pt; 
+  color: #333333;
+}
+
+.form-help {
+  font-family: Verdana, Helvetica, sans-serif;
+  font-size: 10pt;
+  color: #333333;
+}
+
+.std-text {
+  font-family: Verdana, Helvetica, sans-serif;
+  font-size: 10pt;
+  color: #333333;
+}
+
+.tab-small {
+  font-family: Verdana, Helvetica, sans-serif; 
+  font-size: 8pt; 
+  color: #333333;
+}
+
+.location-bar {
+  background-color: #44bb66;
+  color: #ffffff;
+  border: none;
+}
+
+.strong-header {
+  font-family: Verdana, Helvetica, sans-serif;
+  font-size: 12pt;
+  font-weight: bold;
+  background-color: #000000;
+  color: #ffffff;
+}
+
+.msg-header {
+  font-family: Verdana, Helvetica, sans-serif;
+  font-size: 12pt;
+  font-weight: bold;
+  background-color: #EE71AC;
+  color: #ffffff;
+}
+
+.file-header {
+  font-family: Verdana, Helvetica, sans-serif;
+  font-size: 12pt;
+  font-weight: bold;
+  background-color: #41BE62;
+  color: #ffffff;
+}   
+
+.history-header {
+  font-family: Verdana, Helvetica, sans-serif;
+  font-size: 12pt;
+  font-weight: bold;
+  background-color: #739DEE;
+  color: #ffffff;
+}
+
+.list-header {
+  background-color: #aaccff;
+  color: #000000;
+  border: none;
+}
+
+.list-item {
+  font-family: Verdana, Helvetica, sans-serif; 
+  font-size: 10pt; 
+}
+
+.list-nav {
+  font-family: Verdana, Helvetica, sans-serif; 
+  font-size: 10pt; 
+  font-weight: bold;
+}
+
+.row-normal {
+  background-color: #ffffff;
+  border: none;
+
+}
+
+.row-hilite {
+  background-color: #efefef;
+  border: none;
+}
+
+.row-unread {
+  background-color: #ffddd9;
+  border: none;
+}
+
+.row-in-progress {
+  background-color: #3ccc50;
+  border: none;
+}
+
+.row-resolved {
+  background-color: #aaccff;
+  border: none;
+}
+
+.row-done-cbb {
+  background-color: #aaccff;
+  border: none;
+}
+
+.row-testing {
+  background-color: #c6ddff;
+  border: none;
+}
+
+.row-need-eg {
+  background-color: #ffc7c0;
+  border: none;
+}
+
+.row-chatting {
+  background-color: #ffe3c0;
+  border: none;
+}
+
+.row-deferred {
+  background-color: #cccccc;
+  border: none;
+}
+
+.section-bar {
+  background-color: #707070;
+  color: #ffffff;
+  border: 1px solid #404040;
+}
+
+.system-msg {
+  font-family: Verdana, Helvetica, sans-serif; 
+  font-size: 10pt; 
+  background-color: #ffffff;
+  border:  1px solid #000000;
+  margin-bottom: 6px;
+  margin-top: 6px;
+  padding: 4px;
+  width: 100%;
+  color: #660033;
+}
+
+.form-title {
+  font-family: Verdana, Helvetica, sans-serif; 
+  font-weight: bold;
+  font-size: 12pt; 
+  color: #333333;
+}
+
+.form-label {
+  font-family: Verdana, Helvetica, sans-serif; 
+  font-weight: bold;
+  font-size: 10pt; 
+  color: #333333;
+}
+
+.form-optional {
+  font-family: Verdana, Helvetica, sans-serif; 
+  font-weight: bold;
+  font-style: italic;
+  font-size: 10pt; 
+  color: #333333;
+}
+
+.form-element {
+  font-family: Verdana, Helvetica, aans-serif;
+  font-size: 10pt;
+  color: #000000;
+}
+
+.form-text {
+  font-family: Verdana, Helvetica, sans-serif;
+  font-size: 10pt;
+  color: #333333;
+}
+
+.form-mono {
+  font-family: monospace;
+  font-size: 12px;
+  text-decoration: none;
+}
+"""
+
+userDOTindex = """<!-- dollarId: user.index,v 1.2 2001/07/29 04:07:37 richard Exp dollar-->
+<tr>
+    <property name="username">
+        <td><display call="link('username')"></td>
+    </property>
+    <property name="realname">
+        <td><display call="plain('realname')"></td>
+    </property>
+    <property name="organisation">
+        <td><display call="plain('organisation')"></td>
+    </property>
+    <property name="address">
+        <td><display call="plain('address')"></td>
+    </property>
+    <property name="phone">
+        <td><display call="plain('phone')"></td>
+    </property>
+</tr>
+"""
+
+userDOTitem = """<!-- dollarId: user.item,v 1.3 2002/02/15 07:08:44 richard Exp dollar-->
+<table border=0 cellspacing=0 cellpadding=2>
+
+<tr class="strong-header">
+  <td colspan=2>Your Details</td>
+</td>
+
+<tr  bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Name</span></td>
+    <td class="form-text"><display call="field('realname', size=40)"></td>
+</tr>
+<tr  bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Login Name</span></td>
+    <td class="form-text"><display call="field('username', size=40)"></td>
+</tr>
+<tr  bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Login Password</span></td>
+    <td class="form-text"><display call="field('password', size=10)"></td>
+</tr>
+<tr  bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Phone</span></td>
+    <td class="form-text"><display call="field('phone', size=40)"></td>
+</tr>
+<tr  bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Organisation</span></td>
+    <td class="form-text"><display call="field('organisation', size=40)"></td>
+</tr>
+<tr  bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">E-mail address</span></td>
+    <td class="form-text"><display call="field('address', size=40)"></td>
+</tr>
+<tr bgcolor="ffffea">
+    <td width=1% nowrap align=right><span class="form-label">Alternate
+    E-mail addresses</span><br>
+     <span class="form-help">One address per line</span></td>
+    <td class="form-text"><display call="multiline('alternate_addresses')"></td>
+</tr>
+
+<tr bgcolor="ffffea">
+    <td>&nbsp;</td>
+    <td class="form-text"><display call="submit()"></td>
+</tr>
+
+<tr class="strong-header">
+    <td colspan=2><b>History</b></td>
+</tr>
+<tr>
+    <td colspan=2><display call="history()"></td>
+</tr>
+
+</table>
+
+"""
+
diff --git a/templates/classic/interfaces.py b/templates/classic/interfaces.py
new file mode 100644 (file)
index 0000000..69f4048
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
+# This module is free software, and you may redistribute it and/or modify
+# under the same terms as Python, so long as this copyright message and
+# disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
+# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# 
+# $Id: interfaces.py,v 1.1 2003-04-17 03:26:03 richard Exp $
+
+from roundup import mailgw 
+from roundup.cgi import client
+
+class Client(client.Client): 
+    ''' derives basic CGI implementation from the standard module, 
+        with any specific extensions 
+    ''' 
+    pass
+
+class TemplatingUtils:
+    ''' Methods implemented on this class will be available to HTML templates
+        through the 'utils' variable.
+    '''
+    pass
+
+class MailGW(mailgw.MailGW): 
+    ''' derives basic mail gateway implementation from the standard module, 
+        with any specific extensions 
+    ''' 
+    pass
+
+# vim: set filetype=python ts=4 sw=4 et si
diff --git a/templates/minimal/.cvsignore b/templates/minimal/.cvsignore
new file mode 100644 (file)
index 0000000..d90d51d
--- /dev/null
@@ -0,0 +1,4 @@
+*.pyc
+*.pyo
+htmlbase.py
+*.cover
diff --git a/templates/minimal/TEMPLATE-INFO.txt b/templates/minimal/TEMPLATE-INFO.txt
new file mode 100644 (file)
index 0000000..0cb35b5
--- /dev/null
@@ -0,0 +1,8 @@
+Name: minimal
+Description: This is an empty tracker - it must be customised for it to be
+             useful! It only defines the bare minimum of information - the
+             user database and the two default users (admin and anonymous).
+             The rest is entirely up to you! Not recommended for first-time
+             Roundup users (it's easier to tweak the Classic tracker).
+Intended-For: Roundup experts who need a clean slate to start with.
+
diff --git a/templates/minimal/__init__.py b/templates/minimal/__init__.py
new file mode 100644 (file)
index 0000000..fdc93c3
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
+# This module is free software, and you may redistribute it and/or modify
+# under the same terms as Python, so long as this copyright message and
+# disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
+# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# 
+# $Id: __init__.py,v 1.1 2003-04-17 03:27:27 richard Exp $
+
+import config
+from dbinit import open, init
+from interfaces import Client, MailGW
+
+# vim: set filetype=python ts=4 sw=4 et si
diff --git a/templates/minimal/config.py b/templates/minimal/config.py
new file mode 100644 (file)
index 0000000..e5e40f2
--- /dev/null
@@ -0,0 +1,99 @@
+#
+# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
+# This module is free software, and you may redistribute it and/or modify
+# under the same terms as Python, so long as this copyright message and
+# disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
+# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# 
+# $Id: config.py,v 1.1 2003-04-17 03:27:27 richard Exp $
+
+import os
+
+# roundup home is this package's directory
+TRACKER_HOME=os.path.split(__file__)[0]
+
+# The SMTP mail host that roundup will use to send mail
+MAILHOST = 'localhost'
+
+# The domain name used for email addresses.
+MAIL_DOMAIN = 'your.tracker.email.domain.example'
+
+# This is the directory that the database is going to be stored in
+DATABASE = os.path.join(TRACKER_HOME, 'db')
+
+# This is the directory that the HTML templates reside in
+TEMPLATES = os.path.join(TRACKER_HOME, 'html')
+
+# A descriptive name for your roundup instance
+TRACKER_NAME = 'Roundup issue tracker'
+
+# 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. 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 = ""
+
+# 
+# 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'
+
+# Send nosy messages to the author of the message
+MESSAGES_TO_AUTHOR = 'no'           # either 'yes' or 'no'
+
+# Does the author of a message get placed on the nosy list automatically?
+# If 'new' is used, then the author will only be added when a message
+# creates a new issue. If 'yes', then the author will be added on followups
+# too. If 'no', they're never added to the nosy.
+ADD_AUTHOR_TO_NOSY = 'new'          # one of 'yes', 'no', 'new'
+
+# Do the recipients (To:, Cc:) of a message get placed on the nosy list?
+# If 'new' is used, then the recipients will only be added when a message
+# creates a new issue. If 'yes', then the recipients will be added on followups
+# too. If 'no', they're never added to the nosy.
+ADD_RECIPIENTS_TO_NOSY = 'new'      # either 'yes', 'no', 'new'
+
+# Where to place the email signature
+EMAIL_SIGNATURE_POSITION = 'bottom' # one of 'top', 'bottom', 'none'
+
+# Keep email citations when accepting messages. Setting this to "no" strips
+# out "quoted" text from the message. Signatures are also stripped.
+EMAIL_KEEP_QUOTED_TEXT = 'yes'      # either 'yes' or 'no'
+
+# Preserve the email body as is - that is, keep the citations _and_
+# signatures.
+EMAIL_LEAVE_BODY_UNCHANGED = 'no'   # either 'yes' or 'no'
+
+# Default class to use in the mailgw if one isn't supplied in email
+# subjects. To disable, comment out the variable below or leave it blank.
+# Examples:
+MAIL_DEFAULT_CLASS = 'issue'   # use "issue" class by default
+#MAIL_DEFAULT_CLASS = ''        # disable (or just comment the var out)
+
+# vim: set filetype=python ts=4 sw=4 et si
diff --git a/templates/minimal/dbinit.py b/templates/minimal/dbinit.py
new file mode 100644 (file)
index 0000000..b1fb6a4
--- /dev/null
@@ -0,0 +1,112 @@
+#
+# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
+# This module is free software, and you may redistribute it and/or modify
+# under the same terms as Python, so long as this copyright message and
+# disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
+# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# 
+# $Id: dbinit.py,v 1.1 2003-04-17 03:27:27 richard Exp $
+
+import os
+
+import config
+from select_db import Database, Class, FileClass, IssueClass
+
+def open(name=None):
+    ''' as from the roundupdb method openDB 
+    ''' 
+    from roundup.hyperdb import String, Password, Date, Link, Multilink
+    from roundup.hyperdb import Interval, Boolean, Number
+
+    # open the database
+    db = Database(config, name)
+
+    #
+    # Now initialise the schema. Must do this each time the database is
+    # opened.
+    #
+
+    # The "Minimal" template gets only one class, the required "user"
+    # class. That's it. And even that has the bare minimum of properties.
+
+    # Note: roles is a comma-separated string of Role names
+    user = Class(db, "user", username=String(), password=Password(),
+        address=String(), alternate_addresses=String(), roles=String())
+    user.setkey("username")
+
+    # add any additional database schema configuration here
+
+    #
+    # SECURITY SETTINGS
+    #
+    # new permissions for this schema
+    for cl in ('user', ):
+        db.security.addPermission(name="Edit", klass=cl,
+            description="User is allowed to edit "+cl)
+        db.security.addPermission(name="View", klass=cl,
+            description="User is allowed to access "+cl)
+
+    # and give the regular users access to the web and email interface
+    p = db.security.getPermission('Web Access')
+    db.security.addPermissionToRole('User', p)
+    p = db.security.getPermission('Email Access')
+    db.security.addPermissionToRole('User', p)
+
+    # May users view other user information? Comment these lines out
+    # if you don't want them to
+    p = db.security.getPermission('View', 'user')
+    db.security.addPermissionToRole('User', p)
+
+    # Assign the appropriate permissions to the anonymous user's Anonymous
+    # Role. Choices here are:
+    # - Allow anonymous users to register through the web
+    p = db.security.getPermission('Web Registration')
+    db.security.addPermissionToRole('Anonymous', p)
+    # - Allow anonymous (new) users to register through the email gateway
+    p = db.security.getPermission('Email Registration')
+    db.security.addPermissionToRole('Anonymous', p)
+
+    import detectors
+    detectors.init(db)
+
+    # schema is set up - run any post-initialisation
+    db.post_init()
+    return db
+def init(adminpw): 
+    ''' as from the roundupdb method initDB 
+    Open the new database, and add new nodes - used for initialisation. You
+    can edit this before running the "roundup-admin initialise" command to
+    change the initial database entries.
+    ''' 
+    dbdir = os.path.join(config.DATABASE, 'files')
+    if not os.path.isdir(dbdir):
+        os.makedirs(dbdir)
+
+    db = open("admin")
+    db.clear()
+
+    # create the two default users
+    user = db.getclass('user')
+    user.create(username="admin", password=adminpw,
+        address=config.ADMIN_EMAIL, roles='Admin')
+    user.create(username="anonymous", roles='Anonymous')
+
+    # add any additional database create steps here - but only if you
+    # haven't initialised the database with the admin "initialise" command
+
+    db.commit()
+
+# vim: set filetype=python ts=4 sw=4 et si
+
diff --git a/templates/minimal/detectors/.cvsignore b/templates/minimal/detectors/.cvsignore
new file mode 100644 (file)
index 0000000..4162d5e
--- /dev/null
@@ -0,0 +1,3 @@
+*.pyc
+*.pyo
+*.cover
diff --git a/templates/minimal/detectors/__init__.py b/templates/minimal/detectors/__init__.py
new file mode 100644 (file)
index 0000000..e96d262
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
+# This module is free software, and you may redistribute it and/or modify
+# under the same terms as Python, so long as this copyright message and
+# disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
+# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# 
+#$Id: __init__.py,v 1.1 2003-04-17 03:27:56 richard Exp $
+
+import sys, os, imp
+
+def init(db):
+    ''' execute the init functions of all the modules in this directory
+    '''
+    this_dir = os.path.split(__file__)[0]
+    for file in os.listdir(this_dir):
+        path = os.path.join(this_dir, file)
+        name, ext = os.path.splitext(file)
+        if name == '__init__':
+            continue
+        if ext == '.py':
+            module = imp.load_module(name, open(path), file,
+                ('.py', 'r', imp.PY_SOURCE))
+            print (name, open(path), file, module)
+            module.init(db)
+
+# vim: set filetype=python ts=4 sw=4 et si
diff --git a/templates/minimal/html/_generic.help.html b/templates/minimal/html/_generic.help.html
new file mode 100644 (file)
index 0000000..ff4c7a3
--- /dev/null
@@ -0,0 +1,16 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8;">
+<link rel="stylesheet" type="text/css" href="_file/style.css">
+</head>
+<body class="body" marginwidth="0" marginheight="0">
+
+<table class="classhelp"
+       tal:define="props python:request.form['properties'].value.split(',')">
+<tr><th tal:repeat="prop props" tal:content="prop"></th></tr>
+<tr tal:repeat="item context/list">
+ <td tal:repeat="prop props" tal:content="python:item[prop]"></td>
+</tr>
+</table>
+
+</body>
diff --git a/templates/minimal/html/_generic.index.html b/templates/minimal/html/_generic.index.html
new file mode 100644 (file)
index 0000000..f21b5d2
--- /dev/null
@@ -0,0 +1,48 @@
+<!-- dollarId: issue.index,v 1.2 2001/07/29 04:07:37 richard Exp dollar-->
+
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title"
+       tal:content="python:context._classname.capitalize()+' editing'"></title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2 tal:content="python:context._classname.capitalize()+' editing'"></h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
+You are not allowed to view this page.
+</span>
+
+<tal:block tal:condition="context/is_edit_ok">
+<p class="form-help">
+ You may edit the contents of the <span tal:replace="request/classname" />
+ class using this form. Commas, newlines and double quotes (") must be
+ handled delicately. You may include commas and newlines by enclosing the
+ values in double-quotes ("). Double quotes themselves must be quoted by
+ doubling ("").
+</p>
+
+<p class="form-help">
+ Multilink properties have their multiple values colon (":") separated 
+ (... ,"one:two:three", ...)
+</p>
+
+<p class="form-help">
+ Remove entries by deleting their line. Add new entries by appending
+ them to the table - put an X in the id column.
+</p>
+
+<form onSubmit="return submit_once()" method="POST">
+<textarea rows="15" cols="60" name="rows" tal:content="context/csv"></textarea>
+<br>
+<input type="hidden" name=":action" value="editCSV">
+<input type="submit" value="Edit Items">
+</form>
+</tal:block>
+
+<tal:block tal:condition="context/is_only_view_ok">
+view ok
+</tal:block>
+
+</td>
+
+</tal:block>
diff --git a/templates/minimal/html/_generic.item.html b/templates/minimal/html/_generic.item.html
new file mode 100644 (file)
index 0000000..a9d2e85
--- /dev/null
@@ -0,0 +1,56 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title"
+       tal:content="python:context._classname.capitalize()+' editing'"></title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2 tal:content="python:context._classname.capitalize()+' editing'"></h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
+You are not allowed to view this page.
+</span>
+
+<form method="POST" onSubmit="return submit_once()"
+      enctype="multipart/form-data" tal:condition="context/is_edit_ok">
+
+<input type="hidden" name=":template" value="item">
+<input type="hidden" name=":required" value="title">
+
+<table class="form">
+
+<tr tal:repeat="prop python:db[context._classname].properties()">
+ <tal:block tal:condition="python:prop._name not in ('id', 'creator',
+                                  'creation', 'activity')">
+  <th tal:content="prop/_name"></th>
+  <td tal:content="structure python:context[prop._name].field()"></td>
+ </tal:block>
+</tr>
+<tr>
+ <td>&nbsp;</td>
+ <td colspan=3 tal:content="structure context/submit">
+  submit button will go here
+ </td>
+</tr>
+</table>
+
+</form>
+
+<table class="form" tal:condition="context/is_only_view_ok">
+
+<tr tal:repeat="prop python:db[context._classname].properties()">
+ <tal:block tal:condition="python:prop._name not in ('id', 'creator',
+                                  'creation', 'activity')">
+  <th tal:content="prop/_name"></th>
+  <td tal:content="structure python:context[prop._name].field()"></td>
+ </tal:block>
+</tr>
+</table>
+
+
+<tal:block tal:condition="python:context.id and context.is_view_ok()">
+ <tal:block tal:replace="structure context/history" />
+</tal:block>
+
+</td>
+
+</tal:block>
diff --git a/templates/minimal/html/home.classlist.html b/templates/minimal/html/home.classlist.html
new file mode 100644 (file)
index 0000000..0b5a244
--- /dev/null
@@ -0,0 +1,25 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title">List of classes</title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>List of classes</h2>
+</td>
+<td class="content" metal:fill-slot="content">
+<table class="classlist">
+
+<tal:block tal:repeat="cl db/classes">
+ <tr>
+  <th class="header" colspan="2" align="left">
+   <a tal:attributes="href string:${cl/classname}"
+      tal:content="python:cl.classname.capitalize()">classname</a>
+  </th>
+ </tr>
+ <tr tal:repeat="prop cl/properties">
+  <th tal:content="prop/_name">name</th>
+  <td tal:content="prop/_prop">type</td>
+ </tr>
+</tal:block>
+
+</table>
+</td>
+
+</tal:block>
diff --git a/templates/minimal/html/home.html b/templates/minimal/html/home.html
new file mode 100644 (file)
index 0000000..acf6023
--- /dev/null
@@ -0,0 +1,25 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title">Tracker home</title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>Tracker home</h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<!--
+ This is the default body that is displayed when people visit the
+ tracker. The tag below lists the currently open issues. You may
+ replace it with a greeting message, or a different list of issues or
+ whatever. It's a good idea to have the issues on the front page though
+-->
+
+<tal:block tal:define="anon python:request.user.username == 'anonymous'">
+<p tal:condition="not:anon" class="help">
+Please select from one of the menu options on the right.
+</p>
+<p tal:condition="anon" class="help">
+Please log in or register.
+</p>
+</tal:block>
+
+</td>
+</tal:block>
diff --git a/templates/minimal/html/page.html b/templates/minimal/html/page.html
new file mode 100644 (file)
index 0000000..219a52a
--- /dev/null
@@ -0,0 +1,69 @@
+<html metal:define-macro="icing">
+<head>
+<title metal:define-slot="head_title">title goes here</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8;">
+
+<link rel="stylesheet" type="text/css" href="_file/style.css">
+
+<script tal:replace="structure request/base_javascript">
+</script>
+
+</head>
+<body class="body" marginwidth="0" marginheight="0">
+
+<table class="body">
+
+<tr>
+ <td class="page-header-left">&nbsp;</td>
+ <td class="page-header-top" metal:define-slot="body_title"><h2>name</h2></td>
+</tr>
+
+<tr>
+ <td rowspan="2" valign="top" nowrap class="sidebar">
+  <p class="userblock" tal:condition="python:request.user.username=='anonymous'">
+   <form method="POST" action="">
+    <input size="10" name="__login_name"><br>
+    <input size="10" type="password" name="__login_password"><br>
+    <input type="submit" name=":action" value="login">
+    <span tal:replace="structure request/indexargs_form" />
+   </form>
+   <a href="user?:template=register">Register</a>
+  </p>
+
+  <p class="userblock" tal:condition="python:request.user.username != 'anonymous'">
+   <b>Hello,</b><br><b tal:content="request/user/username">username</b><br>
+   <a tal:attributes="href string:user${request/user/id}">My Details</a><br>
+   <a tal:attributes="href python:request.indexargs_href('',
+       {':action':'logout'})">Logout</a>
+  </p>
+
+  <p class="classblock"
+       tal:condition="python:request.user.username != 'anonymous'">
+   <b>Administration</b><br>
+   <a tal:condition="python:request.user.hasPermission('Edit', None)"
+      href="home?:template=classlist">Class List</a><br>
+   <a tal:condition="python:request.user.hasPermission('View', 'user')
+                            or request.user.hasPermission('Edit', 'user')"
+      href="user" >User List</a><br>
+   <a tal:condition="python:request.user.hasPermission('Edit', 'user')"
+      href="user?:template=item">Add User</a>
+  </p>
+ </td>
+ <td>
+  <p tal:condition="options/error_message | nothing" class="error-message"
+     tal:repeat="m options/error_message" tal:content="structure m">error</p>
+  <p tal:condition="options/ok_message | nothing" class="ok-message"
+     tal:repeat="m options/ok_message" tal:content="structure m">error</p>
+ </td>
+</tr>
+<tr>
+ <td class="content" metal:define-slot="content">Page content goes here</td>
+</tr>
+
+</table>
+
+<pre tal:condition="request/form/debug | nothing" tal:content="request">
+</pre>
+
+</body>
+</html>
diff --git a/templates/minimal/html/style.css b/templates/minimal/html/style.css
new file mode 100644 (file)
index 0000000..8aad458
--- /dev/null
@@ -0,0 +1,319 @@
+/* main page styles */
+body.body {
+  font-family: sans-serif, Arial, Helvetica;
+  color: #333333;
+}
+a[href]:hover { color:blue; text-decoration: underline; }
+a[href]:link { color:blue; text-decoration: none; }
+a[href] { color:blue; text-decoration: none; }
+
+table.body {
+  border: 0;
+  padding: 0;
+  border-spacing: 0px;
+  border-collapse: separate;
+}
+
+td.page-header-left {
+  padding: 5px;
+  border-bottom: 1px solid #444444;
+}
+
+td.page-header-top {
+  padding: 5px;
+  border-bottom: 1px solid #444444;
+}
+
+td.sidebar {
+  padding: 1 0 0 1;
+}
+
+td.sidebar p.classblock {
+  padding: 0 5 0 5;
+  margin: 1 1 1 1;
+  border: 1px solid #444444;
+  background-color: #eeeeee;
+}
+
+td.sidebar p.userblock {
+  padding: 0 5 0 5;
+  margin: 1 1 1 1;
+  border: 1px solid #444444;
+  background-color: #eeeeff;
+}
+
+td.content {
+  padding: 1 5 1 5;
+  vertical-align: top;
+  width: 100%;
+}
+
+p.ok-message {
+  background-color: #22bb22;
+  padding: 5 5 5 5;
+  color: white;
+  font-weight: bold;
+}
+p.error-message {
+  background-color: #bb2222;
+  padding: 5 5 5 5;
+  color: white;
+  font-weight: bold;
+}
+
+
+/* style for forms */
+table.form {
+  padding: 2;
+  border-spacing: 0px;
+  border-collapse: separate;
+}
+
+table.form th {
+  font-weight: bold;
+  color: #333388;
+  text-align: right;
+  vertical-align: top;
+}
+
+table.form th.header {
+  font-weight: bold;
+  color: #333388;
+  background-color: #eeeeff;
+  text-align: left;
+}
+
+table.form td {
+  color: #333333;
+  empty-cells: show;
+  vertical-align: top;
+}
+
+table.form td.optional {
+  font-weight: bold;
+  font-style: italic;
+}
+
+table.form td.html {
+  color: #777777;
+}
+
+/* style for lists */
+table.list {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.list th {
+  padding: 0 4 0 4;
+  color: #404070;
+  background-color: #eeeeff;
+  border-right: 1px solid #404070;
+  border-top: 1px solid #404070;
+  border-bottom: 1px solid #404070;
+  vertical-align: top;
+  empty-cells: show;
+}
+table.list th a[href]:hover { color: #404070 }
+table.list th a[href]:link { color: #404070 }
+table.list th a[href] { color: #404070 }
+table.list th.group {
+  background-color: #f4f4ff;
+  text-align: center;
+}
+
+table.list td {
+  padding: 0 4 0 4;
+  border: 0 2 0 2;
+  border-right: 1px solid #404070;
+  color: #404070;
+  background-color: white;
+  vertical-align: top;
+  empty-cells: show;
+}
+
+table.list tr.normal td {
+  background-color: white;
+}
+
+table.list tr.alt td {
+  background-color: #efefef;
+}
+
+table.list td:first-child {
+  border-left: 1px solid #404070;
+  border-right: 1px solid #404070;
+}
+
+table.list th:first-child {
+  border-left: 1px solid #404070;
+  border-right: 1px solid #404070;
+}
+
+table.list tr.navigation th {
+  text-align: right;
+}
+table.list tr.navigation th:first-child {
+  border-right: none;
+  text-align: left;
+}
+
+
+/* style for message displays */
+table.messages {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.messages th.header{
+  padding-top: 10px;
+  border-bottom: 1px solid gray;
+  font-weight: bold;
+  background-color: white;
+  color: #707040;
+}
+
+table.messages th {
+  font-weight: bold;
+  color: black;
+  text-align: left;
+  border-bottom: 1px solid #afafaf;
+}
+
+table.messages td {
+  font-family: monospace;
+  background-color: #efefef;
+  border-bottom: 1px solid #afafaf;
+  color: black;
+  empty-cells: show;
+  border-right: 1px solid #afafaf;
+  vertical-align: top;
+  padding: 2 5 2 5;
+}
+
+table.messages td:first-child {
+  border-left: 1px solid #afafaf;
+  border-right: 1px solid #afafaf;
+}
+
+/* style for file displays */
+table.files {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.files th.header{
+  padding-top: 10px;
+  border-bottom: 1px solid gray;
+  font-weight: bold;
+  background-color: white;
+  color: #707040;
+}
+
+table.files th {
+  border-bottom: 1px solid #afafaf;
+  font-weight: bold;
+  text-align: left;
+}
+
+table.files td {
+  font-family: monospace;
+  empty-cells: show;
+}
+
+/* style for history displays */
+table.history {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.history th.header{
+  padding-top: 10px;
+  border-bottom: 1px solid gray;
+  font-weight: bold;
+  background-color: white;
+  color: #707040;
+  font-size: 100%;
+}
+
+table.history th {
+  border-bottom: 1px solid #afafaf;
+  font-weight: bold;
+  text-align: left;
+  font-size: 90%;
+}
+
+table.history td {
+  font-size: 90%;
+  vertical-align: top;
+  empty-cells: show;
+}
+
+
+/* style for class list */
+table.classlist {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.classlist th.header{
+  padding-top: 10px;
+  border-bottom: 1px solid gray;
+  font-weight: bold;
+  background-color: white;
+  color: #707040;
+}
+
+table.classlist th {
+  font-weight: bold;
+  text-align: left;
+}
+
+
+/* style for class help display */
+table.classhelp {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.classhelp th {
+  font-weight: bold;
+  text-align: left;
+  color: #707040;
+}
+
+table.classhelp td {
+  padding: 2 2 2 2;
+  border: 1px solid black;
+  text-align: left;
+  vertical-align: top;
+  empty-cells: show;
+}
+
+
+/* style for "other" displays */
+table.otherinfo {
+  border-spacing: 0px;
+  border-collapse: separate;
+  width: 100%;
+}
+
+table.otherinfo th.header{
+  padding-top: 10px;
+  border-bottom: 1px solid gray;
+  font-weight: bold;
+  background-color: white;
+  color: #707040;
+}
+
+table.otherinfo th {
+  border-bottom: 1px solid #afafaf;
+  font-weight: bold;
+  text-align: left;
+}
diff --git a/templates/minimal/html/user.index.html b/templates/minimal/html/user.index.html
new file mode 100644 (file)
index 0000000..30312c2
--- /dev/null
@@ -0,0 +1,29 @@
+<!-- dollarId: user.index,v 1.3 2002/07/09 05:29:51 richard Exp dollar-->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title">User listing</title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>User listing</h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="not:context/is_view_ok">
+You are not allowed to view this page.
+</span>
+
+<table width="100%" tal:condition="context/is_view_ok" class="list">
+<tr>
+ <th>Username</th>
+ <th>Email address</th>
+</tr>
+<tr tal:repeat="user context/list"
+    tal:attributes="class python:['normal', 'alt'][repeat['user'].index%6/3]">
+ <td>
+  <a tal:attributes="href string:user${user/id}"
+     tal:content="user/username">username</a>
+ </td>
+ <td tal:content="python:user.address.email()">address</td>
+</tr>
+</table>
+</td>
+
+</tal:block>
diff --git a/templates/minimal/html/user.item.html b/templates/minimal/html/user.item.html
new file mode 100644 (file)
index 0000000..642b776
--- /dev/null
@@ -0,0 +1,70 @@
+<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title">User editing</title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2>User editing</h2>
+</td>
+<td class="content" metal:fill-slot="content">
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())">
+You are not allowed to view this page.
+</span>
+
+<form method="POST" onSubmit="return submit_once()"
+      enctype="multipart/form-data" tal:condition="context/is_edit_ok">
+
+<input type="hidden" name=":required" value="username,address">
+
+<table class="form">
+ <tr>
+  <th>Login Name</th>
+  <td tal:content="structure context/username/field">username</td>
+ </tr>
+ <tr>
+  <th>Login Password</th>
+  <td tal:content="structure context/password/field">password</td>
+ </tr>
+ <tr>
+  <th>Confirm Password</th>
+  <td tal:content="structure context/password/confirm">password</td>
+ </tr>
+ <tr tal:condition="python:request.user.hasPermission('Web Roles')">
+  <th>Roles</th>
+  <td tal:condition="context/id"
+      tal:content="structure context/roles/field">roles</td>
+  <td tal:condition="not:context/id">
+   <input name="roles" tal:attributes="value db/config/NEW_WEB_USER_ROLES">
+  </td>
+ </tr>
+ <tr>
+  <th>E-mail address</th>
+  <td tal:content="structure context/address/field">address</td>
+ </tr>
+ <tr>
+  <th>Alternate E-mail addresses<br>One address per line</th>
+  <td tal:content="structure context/alternate_addresses/multiline">alternate_addresses</td>
+ </tr>
+
+ <tr>
+  <td>&nbsp;</td>
+  <td tal:content="structure context/submit">submit button here</td>
+ </tr>
+</table>
+</form>
+
+<table class="form" tal:condition="context/is_only_view_ok">
+ <tr>
+  <th>Login Name</th>
+  <td tal:content="context/username">username</td>
+ </tr>
+ <tr>
+  <th>E-mail address</th>
+  <td tal:content="context/address/email">address</td>
+ </tr>
+</table>
+
+<tal:block tal:condition="python:context.id and context.is_view_ok()"
+           tal:replace="structure context/history" />
+
+</td>
+
+</tal:block>
diff --git a/templates/minimal/html/user.register.html b/templates/minimal/html/user.register.html
new file mode 100644 (file)
index 0000000..a226413
--- /dev/null
@@ -0,0 +1,82 @@
+<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title"
+       tal:content="string:Registering with ${db/config/TRACKER_NAME}"></title>
+<td class="page-header-top" metal:fill-slot="body_title">
+ <h2 tal:content="string:Registering with ${db/config/TRACKER_NAME}"></h2>
+</td>
+<td class="content" metal:fill-slot="content">
+
+<tal:block tal:define=" editok python:request.user.username=='anonymous' and
+           request.user.hasPermission('Web Registration')">
+
+<span tal:condition="python:not editok">
+You are not allowed to view this page.
+</span>
+
+<tal:block tal:condition="editok">
+<form method="POST" onSubmit="return submit_once()" enctype="multipart/form-data">
+<input type="hidden" name=":template" value="register">
+<input type="hidden" name=":required" value="username">
+<input type="hidden" name=":required" value="password">
+<input type="hidden" name=":required" value="address">
+
+<table class="form">
+ <tr>
+  <th>Name</th>
+  <td tal:content="structure context/realname/field">realname</td>
+ </tr>
+ <tr>
+  <th>Login Name</th>
+  <td tal:content="structure context/username/field">username</td>
+ </tr>
+ <tr>
+  <th>Login Password</th>
+  <td tal:content="structure context/password/field">password</td>
+ </tr>
+ <tr>
+  <th>Confirm Password</th>
+  <td tal:content="structure context/password/confirm">password</td>
+ </tr>
+ <tr tal:condition="python:request.user.hasPermission('Web Roles')">
+  <th>Roles</th>
+  <td tal:condition="exists:item"
+      tal:content="structure context/roles/field">roles</td>
+  <td tal:condition="not:exists:item">
+   <input name="roles" tal:attributes="value db/config/NEW_WEB_USER_ROLES">
+  </td>
+ </tr>
+ <tr>
+  <th>Phone</th>
+  <td tal:content="structure context/phone/field">phone</td>
+ </tr>
+ <tr>
+  <th>Organisation</th>
+  <td tal:content="structure context/organisation/field">organisation</td>
+ </tr>
+ <tr>
+  <th>E-mail address</th>
+  <td tal:content="structure context/address/field">address</td>
+ </tr>
+ <tr>
+  <th>Alternate E-mail addresses<br>One address per line</th>
+  <td tal:content="structure context/alternate_addresses/multiline">alternate_addresses</td>
+ </tr>
+
+ <tr>
+  <td>&nbsp;</td>
+  <td>
+   <input type="hidden" name=":action" value="register">
+   <input type="submit" name="submit" value="Register">
+  </td>
+ </tr>
+</table>
+</form>
+
+</tal:block>
+
+</tal:block>
+
+</td>
+
+</tal:block>
diff --git a/templates/minimal/interfaces.py b/templates/minimal/interfaces.py
new file mode 100644 (file)
index 0000000..e74ce46
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
+# This module is free software, and you may redistribute it and/or modify
+# under the same terms as Python, so long as this copyright message and
+# disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
+# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# 
+# $Id: interfaces.py,v 1.1 2003-04-17 03:27:27 richard Exp $
+
+from roundup import mailgw 
+from roundup.cgi import client
+
+class Client(client.Client): 
+    ''' derives basic CGI implementation from the standard module, 
+        with any specific extensions 
+    ''' 
+    pass
+
+class TemplatingUtils:
+    ''' Methods implemented on this class will be available to HTML templates
+        through the 'utils' variable.
+    '''
+    pass
+
+class MailGW(mailgw.MailGW): 
+    ''' derives basic mail gateway implementation from the standard module, 
+        with any specific extensions 
+    ''' 
+    pass
+
+# vim: set filetype=python ts=4 sw=4 et si